1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "ColorBufferGl.h"
17 
18 #include <GLES2/gl2ext.h>
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "BorrowedImageGl.h"
23 #include "DebugGl.h"
24 #include "OpenGLESDispatch/DispatchTables.h"
25 #include "OpenGLESDispatch/EGLDispatch.h"
26 #include "RenderThreadInfoGl.h"
27 #include "TextureDraw.h"
28 #include "TextureResize.h"
29 #include "gl/YUVConverter.h"
30 #include "glestranslator/include/GLcommon/GLutils.h"
31 #include "host-common/GfxstreamFatalError.h"
32 #include "host-common/opengl/misc.h"
33 
34 #define DEBUG_CB_FBO 0
35 
36 using android::base::ManagedDescriptor;
37 using emugl::ABORT_REASON_OTHER;
38 using emugl::FatalError;
39 
40 namespace gfxstream {
41 namespace gl {
42 namespace {
43 
44 // Lazily create and bind a framebuffer object to the current host context.
45 // |fbo| is the address of the framebuffer object name.
46 // |tex| is the name of a texture that is attached to the framebuffer object
47 // on creation only. I.e. all rendering operations will target it.
48 // returns true in case of success, false on failure.
bindFbo(GLuint * fbo,GLuint tex,bool ensureTextureAttached)49 bool bindFbo(GLuint* fbo, GLuint tex, bool ensureTextureAttached) {
50     if (*fbo) {
51         // fbo already exist - just bind
52         s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
53         if (ensureTextureAttached) {
54             s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES,
55                                            GL_TEXTURE_2D, tex, 0);
56         }
57         return true;
58     }
59 
60     s_gles2.glGenFramebuffers(1, fbo);
61     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
62     s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES,
63                                    GL_TEXTURE_2D, tex, 0);
64 
65 #if DEBUG_CB_FBO
66     GLenum status = s_gles2.glCheckFramebufferStatus(GL_FRAMEBUFFER);
67     if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
68         ERR("ColorBufferGl::bindFbo: FBO not complete: %#x\n", status);
69         s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
70         s_gles2.glDeleteFramebuffers(1, fbo);
71         *fbo = 0;
72         return false;
73     }
74 #endif
75 
76     return true;
77 }
78 
unbindFbo()79 void unbindFbo() {
80     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
81 }
82 
83 }
84 
sGetUnsizedColorBufferFormat(GLenum format)85 static GLenum sGetUnsizedColorBufferFormat(GLenum format) {
86     switch (format) {
87         case GL_R8:
88             return GL_RED;
89         case GL_RG8:
90             return GL_RG;
91         case GL_RGB8:
92         case GL_RGB565:
93         case GL_RGB16F:
94             return GL_RGB;
95         case GL_RGBA8:
96         case GL_RGB5_A1_OES:
97         case GL_RGBA4_OES:
98         case GL_UNSIGNED_INT_10_10_10_2_OES:
99         case GL_RGB10_A2:
100         case GL_RGBA16F:
101             return GL_RGBA;
102         case GL_BGRA8_EXT:
103         case GL_BGR10_A2_ANGLEX:
104             return GL_BGRA_EXT;
105         default: // already unsized
106             return format;
107     }
108 }
109 
sGetFormatParameters(GLint * internalFormat,GLenum * texFormat,GLenum * pixelType,int * bytesPerPixel,GLint * sizedInternalFormat,bool * isBlob)110 static bool sGetFormatParameters(GLint* internalFormat,
111                                  GLenum* texFormat,
112                                  GLenum* pixelType,
113                                  int* bytesPerPixel,
114                                  GLint* sizedInternalFormat,
115                                  bool* isBlob) {
116     if (!internalFormat) {
117         fprintf(stderr, "%s: error: internal format not provided\n", __func__);
118         return false;
119     }
120 
121     *isBlob = false;
122 
123     switch (*internalFormat) {
124         case GL_RGB:
125         case GL_RGB8:
126             *texFormat = GL_RGB;
127             *pixelType = GL_UNSIGNED_BYTE;
128             *bytesPerPixel = 3;
129             *sizedInternalFormat = GL_RGB8;
130             return true;
131         case GL_RGB565_OES:
132             *texFormat = GL_RGB;
133             *pixelType = GL_UNSIGNED_SHORT_5_6_5;
134             *bytesPerPixel = 2;
135             *sizedInternalFormat = GL_RGB565;
136             return true;
137         case GL_RGBA:
138         case GL_RGBA8:
139         case GL_RGB5_A1_OES:
140         case GL_RGBA4_OES:
141             *texFormat = GL_RGBA;
142             *pixelType = GL_UNSIGNED_BYTE;
143             *bytesPerPixel = 4;
144             *sizedInternalFormat = GL_RGBA8;
145             return true;
146         case GL_UNSIGNED_INT_10_10_10_2_OES:
147             *texFormat = GL_RGBA;
148             *pixelType = GL_UNSIGNED_SHORT;
149             *bytesPerPixel = 4;
150             *sizedInternalFormat = GL_UNSIGNED_INT_10_10_10_2_OES;
151             return true;
152         case GL_RGB10_A2:
153             *texFormat = GL_RGBA;
154             *pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
155             *bytesPerPixel = 4;
156             *sizedInternalFormat = GL_RGB10_A2;
157             return true;
158         case GL_RGB16F:
159             *texFormat = GL_RGB;
160             *pixelType = GL_HALF_FLOAT;
161             *bytesPerPixel = 6;
162             *sizedInternalFormat = GL_RGB16F;
163             return true;
164         case GL_RGBA16F:
165             *texFormat = GL_RGBA;
166             *pixelType = GL_HALF_FLOAT;
167             *bytesPerPixel = 8;
168             *sizedInternalFormat = GL_RGBA16F;
169             return true;
170         case GL_LUMINANCE:
171             *texFormat = GL_LUMINANCE;
172             *pixelType = GL_UNSIGNED_BYTE;
173             *bytesPerPixel = 1;
174             *sizedInternalFormat = GL_R8;
175             *isBlob = true;
176             return true;
177         case GL_BGRA_EXT:
178             *texFormat = GL_BGRA_EXT;
179             *pixelType = GL_UNSIGNED_BYTE;
180             *bytesPerPixel = 4;
181             *sizedInternalFormat = GL_BGRA8_EXT;
182             return true;
183         case GL_BGR10_A2_ANGLEX:
184             *texFormat = GL_RGBA;
185             *pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
186             *bytesPerPixel = 4;
187             *internalFormat = GL_RGB10_A2_EXT;
188             // GL_BGR10_A2_ANGLEX is actually not a valid GL format. We should
189             // replace it with a normal GL internal format instead.
190             *sizedInternalFormat = GL_BGR10_A2_ANGLEX;
191             return true;
192         case GL_R8:
193         case GL_RED:
194             *texFormat = GL_RED;
195             *pixelType = GL_UNSIGNED_BYTE;
196             *bytesPerPixel = 1;
197             *sizedInternalFormat = GL_R8;
198             return true;
199         case GL_RG8:
200         case GL_RG:
201             *texFormat = GL_RG;
202             *pixelType = GL_UNSIGNED_BYTE;
203             *bytesPerPixel = 2;
204             *sizedInternalFormat = GL_RG8;
205             return true;
206         default:
207             fprintf(stderr, "%s: Unknown format 0x%x\n", __func__,
208                     *internalFormat);
209             return false;
210     }
211 }
212 
213 // static
create(EGLDisplay p_display,int p_width,int p_height,GLint p_internalFormat,FrameworkFormat p_frameworkFormat,HandleType hndl,ContextHelper * helper,TextureDraw * textureDraw,bool fastBlitSupported,const gfxstream::host::FeatureSet & features)214 std::unique_ptr<ColorBufferGl> ColorBufferGl::create(EGLDisplay p_display, int p_width,
215                                                      int p_height, GLint p_internalFormat,
216                                                      FrameworkFormat p_frameworkFormat,
217                                                      HandleType hndl, ContextHelper* helper,
218                                                      TextureDraw* textureDraw,
219                                                      bool fastBlitSupported,
220                                                      const gfxstream::host::FeatureSet& features) {
221     GLenum texFormat = 0;
222     GLenum pixelType = GL_UNSIGNED_BYTE;
223     int bytesPerPixel = 4;
224     GLint p_sizedInternalFormat = GL_RGBA8;
225     bool isBlob = false;;
226 
227     if (!sGetFormatParameters(&p_internalFormat, &texFormat, &pixelType,
228                               &bytesPerPixel, &p_sizedInternalFormat,
229                               &isBlob)) {
230         ERR("ColorBufferGl::create invalid format 0x%x", p_internalFormat);
231         return nullptr;
232     }
233     const unsigned long bufsize = ((unsigned long)bytesPerPixel) * p_width
234             * p_height;
235 
236     // This constructor is private, so std::make_unique can't be used.
237     std::unique_ptr<ColorBufferGl> cb{
238         new ColorBufferGl(p_display, hndl, p_width, p_height, helper, textureDraw)};
239     cb->m_internalFormat = p_internalFormat;
240     cb->m_sizedInternalFormat = p_sizedInternalFormat;
241     cb->m_format = texFormat;
242     cb->m_type = pixelType;
243     cb->m_frameworkFormat = p_frameworkFormat;
244     cb->m_yuv420888ToNv21 = features.Yuv420888ToNv21.enabled;
245     cb->m_fastBlitSupported = fastBlitSupported;
246     cb->m_numBytes = (size_t)bufsize;
247 
248     RecursiveScopedContextBind context(helper);
249     if (!context.isOk()) {
250         return nullptr;
251     }
252 
253     GL_SCOPED_DEBUG_GROUP("ColorBufferGl::create(handle:%d)", hndl);
254 
255     GLint prevUnpackAlignment;
256     s_gles2.glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlignment);
257     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
258 
259     s_gles2.glGenTextures(1, &cb->m_tex);
260     s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_tex);
261 
262     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, p_internalFormat, p_width, p_height,
263                          0, texFormat, pixelType, nullptr);
264 
265     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
266     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
267     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
268     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
269     // Swizzle B/R channel for BGR10_A2 images.
270     if (p_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
271         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
272         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
273         cb->m_BRSwizzle = true;
274     }
275 
276     //
277     // create another texture for that colorbuffer for blit
278     //
279     s_gles2.glGenTextures(1, &cb->m_blitTex);
280     s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
281     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, p_internalFormat, p_width, p_height,
282                          0, texFormat, pixelType, NULL);
283 
284     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
286     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
287     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
288     // Swizzle B/R channel for BGR10_A2 images.
289     if (p_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
290         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
291         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
292         cb->m_BRSwizzle = true;
293     }
294 
295     cb->m_eglImage = s_egl.eglCreateImageKHR(
296             p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
297             (EGLClientBuffer)SafePointerFromUInt(cb->m_tex), NULL);
298 
299     cb->m_blitEGLImage = s_egl.eglCreateImageKHR(
300             p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
301             (EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex), NULL);
302 
303     cb->m_resizer = new TextureResize(p_width, p_height);
304 
305     switch (cb->m_frameworkFormat) {
306         case FRAMEWORK_FORMAT_GL_COMPATIBLE:
307             break;
308         default: // Any YUV format
309             cb->m_yuv_converter.reset(
310                     new YUVConverter(p_width, p_height, cb->m_frameworkFormat, cb->m_yuv420888ToNv21));
311             break;
312     }
313 
314     // desktop GL only: use GL_UNSIGNED_INT_8_8_8_8_REV for faster readback.
315     if (emugl::getRenderer() == SELECTED_RENDERER_HOST) {
316 #define GL_UNSIGNED_INT_8_8_8_8           0x8035
317 #define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367
318         cb->m_asyncReadbackType = GL_UNSIGNED_INT_8_8_8_8_REV;
319     }
320 
321     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlignment);
322 
323     s_gles2.glFinish();
324     return cb;
325 }
326 
ColorBufferGl(EGLDisplay display,HandleType hndl,GLuint width,GLuint height,ContextHelper * helper,TextureDraw * textureDraw)327 ColorBufferGl::ColorBufferGl(EGLDisplay display, HandleType hndl, GLuint width, GLuint height,
328                              ContextHelper* helper, TextureDraw* textureDraw)
329     : m_width(width),
330       m_height(height),
331       m_display(display),
332       m_helper(helper),
333       m_textureDraw(textureDraw),
334       mHndl(hndl) {}
335 
~ColorBufferGl()336 ColorBufferGl::~ColorBufferGl() {
337     RecursiveScopedContextBind context(m_helper);
338 
339     // b/284523053
340     // Swiftshader logspam on exit. But it doesn't happen with SwANGLE.
341     if (!context.isOk()) {
342         GL_LOG("Failed to bind context when releasing color buffers\n");
343         return;
344     }
345 
346     if (m_blitEGLImage) {
347         s_egl.eglDestroyImageKHR(m_display, m_blitEGLImage);
348     }
349     if (m_eglImage) {
350         s_egl.eglDestroyImageKHR(m_display, m_eglImage);
351     }
352 
353     if (m_fbo) {
354         s_gles2.glDeleteFramebuffers(1, &m_fbo);
355     }
356 
357     if (m_yuv_conversion_fbo) {
358         s_gles2.glDeleteFramebuffers(1, &m_yuv_conversion_fbo);
359     }
360 
361     if (m_scaleRotationFbo) {
362         s_gles2.glDeleteFramebuffers(1, &m_scaleRotationFbo);
363     }
364 
365     m_yuv_converter.reset();
366 
367     GLuint tex[2] = {m_tex, m_blitTex};
368     s_gles2.glDeleteTextures(2, tex);
369 
370     if (m_memoryObject) {
371         s_gles2.glDeleteMemoryObjectsEXT(1, &m_memoryObject);
372     }
373 
374     delete m_resizer;
375 }
376 
convertRgbaToRgbPixels(void * dst,const void * src,uint32_t w,uint32_t h)377 static void convertRgbaToRgbPixels(void* dst, const void* src, uint32_t w, uint32_t h) {
378     const size_t pixelCount = w * h;
379     const uint32_t* srcPixels = reinterpret_cast<const uint32_t*>(src);
380     uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dst);
381     for (size_t i = 0; i < pixelCount; ++i) {
382         const uint32_t pixel = *(srcPixels++);
383         *(dstBytes++) = (pixel & 0xff);
384         *(dstBytes++) = ((pixel >> 8) & 0xff);
385         *(dstBytes++) = ((pixel >> 16) & 0xff);
386     }
387 }
388 
readPixels(int x,int y,int width,int height,GLenum p_format,GLenum p_type,void * pixels)389 bool ColorBufferGl::readPixels(int x, int y, int width, int height, GLenum p_format, GLenum p_type,
390                                void* pixels) {
391     RecursiveScopedContextBind context(m_helper);
392     if (!context.isOk()) {
393         return false;
394     }
395 
396     GL_SCOPED_DEBUG_GROUP("ColorBufferGl::readPixels(handle:%d fbo:%d tex:%d)", mHndl, m_fbo,
397                           m_tex);
398 
399     p_format = sGetUnsizedColorBufferFormat(p_format);
400 
401     waitSync();
402 
403     if (bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
404         m_needFboReattach = false;
405         GLint prevAlignment = 0;
406         s_gles2.glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);
407         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, 1);
408         if ((p_format == GL_RGB || p_format == GL_RGB8) && p_type == GL_UNSIGNED_BYTE) {
409             // GL_RGB reads fail with SwiftShader.
410             uint8_t* tmpPixels = new uint8_t[width * height * 4];
411             s_gles2.glReadPixels(x, y, width, height, GL_RGBA, p_type, tmpPixels);
412             convertRgbaToRgbPixels(pixels, tmpPixels, width, height);
413         } else {
414             s_gles2.glReadPixels(x, y, width, height, p_format, p_type, pixels);
415         }
416         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);
417         unbindFbo();
418         return true;
419     }
420 
421     return false;
422 }
423 
readPixelsScaled(int width,int height,GLenum p_format,GLenum p_type,int rotation,Rect rect,void * pixels)424 bool ColorBufferGl::readPixelsScaled(int width, int height, GLenum p_format, GLenum p_type,
425                                      int rotation, Rect rect, void* pixels) {
426     RecursiveScopedContextBind context(m_helper);
427     if (!context.isOk()) {
428         return false;
429     }
430     bool useSnipping = rect.size.w != 0 && rect.size.h != 0;
431     // Boundary check
432     if (useSnipping &&
433         (rect.pos.x < 0 || rect.pos.y < 0 || rect.pos.x + rect.size.w > width ||
434          rect.pos.y + rect.size.h > height)) {
435         ERR("readPixelsScaled failed. Out-of-bound rectangle: (%d, %d) [%d x %d]"
436             " with screen [%d x %d]",
437             rect.pos.x, rect.pos.y, rect.size.w, rect.size.h);
438         return false;
439     }
440     p_format = sGetUnsizedColorBufferFormat(p_format);
441 
442     waitSync();
443     GLuint tex = m_resizer->update(m_tex, width, height, rotation);
444     if (bindFbo(&m_scaleRotationFbo, tex, m_needFboReattach)) {
445         m_needFboReattach = false;
446         GLint prevAlignment = 0;
447         s_gles2.glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);
448         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, 1);
449         // SwANGLE does not suppot glReadPixels with 3 channels.
450         // In fact, the spec only require RGBA8888 format support. Supports for
451         // other formats are optional.
452         bool needConvert4To3Channel =
453                 p_format == GL_RGB && p_type == GL_UNSIGNED_BYTE &&
454                 (emugl::getRenderer() == SELECTED_RENDERER_SWIFTSHADER_INDIRECT ||
455                     emugl::getRenderer() == SELECTED_RENDERER_ANGLE_INDIRECT);
456         std::vector<uint8_t> tmpPixels;
457         void* readPixelsDst = pixels;
458         if (needConvert4To3Channel) {
459             tmpPixels.resize(width * height * 4);
460             p_format = GL_RGBA;
461             readPixelsDst = tmpPixels.data();
462         }
463         if (useSnipping) {
464             s_gles2.glReadPixels(rect.pos.x, rect.pos.y, rect.size.w,
465                                  rect.size.h, p_format, p_type, readPixelsDst);
466             width = rect.size.w;
467             height = rect.size.h;
468         } else {
469             s_gles2.glReadPixels(0, 0, width, height, p_format, p_type,
470                                  readPixelsDst);
471         }
472         if (needConvert4To3Channel) {
473             uint8_t* src = tmpPixels.data();
474             uint8_t* dst = static_cast<uint8_t*>(pixels);
475             for (int h = 0; h < height; h++) {
476                 for (int w = 0; w < width; w++) {
477                     memcpy(dst, src, 3);
478                     dst += 3;
479                     src += 4;
480                 }
481             }
482         }
483         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);
484         unbindFbo();
485         return true;
486     }
487 
488     return false;
489 }
490 
readPixelsYUVCached(int x,int y,int width,int height,void * pixels,uint32_t pixels_size)491 bool ColorBufferGl::readPixelsYUVCached(int x, int y, int width, int height, void* pixels,
492                                         uint32_t pixels_size) {
493     RecursiveScopedContextBind context(m_helper);
494     if (!context.isOk()) {
495         return false;
496     }
497 
498     waitSync();
499 
500 #if DEBUG_CB_FBO
501     fprintf(stderr, "%s %d request width %d height %d\n", __func__, __LINE__,
502             width, height);
503     memset(pixels, 0x00, pixels_size);
504     assert(m_yuv_converter.get());
505 #endif
506 
507     m_yuv_converter->readPixels((uint8_t*)pixels, pixels_size);
508 
509     return true;
510 }
511 
reformat(GLint internalformat,GLenum type)512 void ColorBufferGl::reformat(GLint internalformat, GLenum type) {
513     GLenum texFormat = internalformat;
514     GLenum pixelType = GL_UNSIGNED_BYTE;
515     GLint sizedInternalFormat = GL_RGBA8;
516     int bpp = 4;
517     bool isBlob = false;
518     if (!sGetFormatParameters(&internalformat, &texFormat, &pixelType, &bpp,
519                               &sizedInternalFormat, &isBlob)) {
520         fprintf(stderr, "%s: WARNING: reformat failed. internal format: 0x%x\n",
521                 __func__, internalformat);
522     }
523 
524     // BUG: 143607546
525     //
526     // During reformatting, sGetFormatParameters can be too
527     // opinionated and override the guest's intended choice for the
528     // pixel type.  If the guest wanted GL_UNSIGNED_SHORT_5_6_5 as
529     // the pixel type, and the incoming internal format is not
530     // explicitly sized, sGetFormatParameters will pick a default of
531     // GL_UNSIGNED BYTE, which goes against guest expectations.
532     //
533     // This happens only on older API levels where gralloc.cpp in
534     // goldfish-opengl communicated HAL_PIXEL_FORMAT_RGB_565 as GL
535     // format GL_RGB, pixel type GL_UNSIGNED_SHORT_5_6_5.  Newer
536     // system images communicate HAL_PIXEL_FORMAT_RGB_565 as GL
537     // format GL_RGB565, which allows sGetFormatParameters to work
538     // correctly.
539     if (pixelType != type) {
540         pixelType = type;
541     }
542 
543     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
544     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, m_height,
545                          0, texFormat, pixelType, nullptr);
546 
547     s_gles2.glBindTexture(GL_TEXTURE_2D, m_blitTex);
548     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, m_height,
549                          0, texFormat, pixelType, nullptr);
550 
551     // EGL images need to be recreated because the EGL_KHR_image_base spec
552     // states that respecifying an image (i.e. glTexImage2D) will generally
553     // result in orphaning of the EGL image.
554     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
555     m_eglImage = s_egl.eglCreateImageKHR(
556             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
557             (EGLClientBuffer)SafePointerFromUInt(m_tex), NULL);
558 
559     s_egl.eglDestroyImageKHR(m_display, m_blitEGLImage);
560     m_blitEGLImage = s_egl.eglCreateImageKHR(
561             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
562             (EGLClientBuffer)SafePointerFromUInt(m_blitTex), NULL);
563 
564     s_gles2.glBindTexture(GL_TEXTURE_2D, 0);
565 
566     m_internalFormat = internalformat;
567     m_format = texFormat;
568     m_type = pixelType;
569     m_sizedInternalFormat = sizedInternalFormat;
570 
571     m_numBytes = bpp * m_width * m_height;
572 }
573 
swapYUVTextures(FrameworkFormat type,uint32_t * textures,void * metadata)574 void ColorBufferGl::swapYUVTextures(FrameworkFormat type, uint32_t* textures, void* metadata) {
575     if (type == FrameworkFormat::FRAMEWORK_FORMAT_NV12) {
576         m_yuv_converter->swapTextures(type, textures, metadata);
577     } else {
578         fprintf(stderr,
579                 "%s: ERROR: format other than NV12 is not supported: 0x%x\n",
580                 __func__, type);
581     }
582 }
583 
subUpdate(int x,int y,int width,int height,GLenum p_format,GLenum p_type,const void * pixels,void * metadata)584 bool ColorBufferGl::subUpdate(int x, int y, int width, int height, GLenum p_format, GLenum p_type,
585                               const void* pixels, void* metadata) {
586     return subUpdateFromFrameworkFormat(x, y, width, height, m_frameworkFormat, p_format, p_type,
587                                         pixels, metadata);
588 }
589 
subUpdateFromFrameworkFormat(int x,int y,int width,int height,FrameworkFormat fwkFormat,GLenum p_format,GLenum p_type,const void * pixels,void * metadata)590 bool ColorBufferGl::subUpdateFromFrameworkFormat(int x, int y, int width, int height,
591                                                  FrameworkFormat fwkFormat, GLenum p_format,
592                                                  GLenum p_type, const void* pixels,
593                                                  void* metadata) {
594     const GLenum p_unsizedFormat = sGetUnsizedColorBufferFormat(p_format);
595     RecursiveScopedContextBind context(m_helper);
596     if (!context.isOk()) {
597         return false;
598     }
599 
600     GL_SCOPED_DEBUG_GROUP("ColorBufferGl::subUpdate(handle:%d fbo:%d tex:%d)", mHndl, m_fbo, m_tex);
601 
602     if (m_needFormatCheck) {
603         if (p_type != m_type || p_format != m_format) {
604             reformat((GLint)p_format, p_type);
605         }
606         m_needFormatCheck = false;
607     }
608 
609     if (m_frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE || fwkFormat != m_frameworkFormat) {
610         assert(m_yuv_converter.get());
611 
612         // This FBO will convert the YUV frame to RGB
613         // and render it to |m_tex|.
614         bindFbo(&m_yuv_conversion_fbo, m_tex, m_needFboReattach);
615         m_yuv_converter->drawConvertFromFormat(fwkFormat, x, y, width, height, (char*)pixels,
616                                                metadata);
617         unbindFbo();
618 
619         // |m_tex| still needs to be bound afterwards
620         s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
621 
622     } else {
623         s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
624         s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
625 
626         s_gles2.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, p_unsizedFormat,
627                                 p_type, pixels);
628     }
629 
630     if (m_fastBlitSupported) {
631         s_gles2.glFlush();
632         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
633     }
634 
635     return true;
636 }
637 
replaceContents(const void * newContents,size_t numBytes)638 bool ColorBufferGl::replaceContents(const void* newContents, size_t numBytes) {
639     return subUpdate(0, 0, m_width, m_height, m_format, m_type, newContents);
640 }
641 
readContents(size_t * numBytes,void * pixels)642 bool ColorBufferGl::readContents(size_t* numBytes, void* pixels) {
643     if (m_yuv_converter) {
644         // common code path for vk & gles
645         *numBytes = m_yuv_converter->getDataSize();
646         if (!pixels) {
647             return true;
648         }
649         return readPixelsYUVCached(0, 0, 0, 0, pixels, *numBytes);
650     } else {
651         *numBytes = m_numBytes;
652         if (!pixels) {
653             return true;
654         }
655         return readPixels(0, 0, m_width, m_height, m_format, m_type, pixels);
656     }
657 }
658 
blitFromCurrentReadBuffer()659 bool ColorBufferGl::blitFromCurrentReadBuffer() {
660     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
661     if (!tInfo) {
662         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
663             << "Render thread GL not available.";
664     }
665 
666     if (!tInfo->currContext.get()) {
667         // no Current context
668         return false;
669     }
670 
671     if (m_fastBlitSupported) {
672         s_egl.eglBlitFromCurrentReadBufferANDROID(m_display, m_eglImage);
673         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
674     } else {
675         // Copy the content of the current read surface into m_blitEGLImage.
676         // This is done by creating a temporary texture, bind it to the EGLImage
677         // then call glCopyTexSubImage2D().
678         GLuint tmpTex;
679         GLint currTexBind;
680         if (tInfo->currContext->clientVersion() > GLESApi_CM) {
681             s_gles2.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
682             s_gles2.glGenTextures(1, &tmpTex);
683             s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
684             s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
685 
686             const bool isGles3 = tInfo->currContext->clientVersion() > GLESApi_2;
687 
688             GLint prev_read_fbo = 0;
689             if (isGles3) {
690                 // Make sure that we unbind any existing GL_READ_FRAMEBUFFER
691                 // before calling glCopyTexSubImage2D, otherwise we may blit
692                 // from the guest's current read framebuffer instead of the EGL
693                 // read buffer.
694                 s_gles2.glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo);
695                 if (prev_read_fbo != 0) {
696                     s_gles2.glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
697                 }
698             } else {
699                 // On GLES 2, there are not separate read/draw framebuffers,
700                 // only GL_FRAMEBUFFER.  Per the EGL 1.4 spec section 3.9.3,
701                 // the draw surface must be bound to the calling thread's
702                 // current context, so GL_FRAMEBUFFER should be 0.  However, the
703                 // error case is not strongly defined and generating a new error
704                 // may break existing apps.
705                 //
706                 // Instead of the obviously wrong behavior of posting whatever
707                 // GL_FRAMEBUFFER is currently bound to, fix up the
708                 // GL_FRAMEBUFFER if it is non-zero.
709                 s_gles2.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_read_fbo);
710                 if (prev_read_fbo != 0) {
711                     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
712                 }
713             }
714 
715             // If the read buffer is multisampled, we need to resolve.
716             GLint samples;
717             s_gles2.glGetIntegerv(GL_SAMPLE_BUFFERS, &samples);
718             if (isGles3 && samples > 0) {
719                 s_gles2.glBindTexture(GL_TEXTURE_2D, 0);
720 
721                 GLuint resolve_fbo;
722                 GLint prev_draw_fbo;
723                 s_gles2.glGenFramebuffers(1, &resolve_fbo);
724                 s_gles2.glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo);
725 
726                 s_gles2.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
727                 s_gles2.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
728                         GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
729                         tmpTex, 0);
730                 s_gles2.glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width,
731                         m_height, GL_COLOR_BUFFER_BIT,
732                         GL_NEAREST);
733                 s_gles2.glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
734                         (GLuint)prev_draw_fbo);
735 
736                 s_gles2.glDeleteFramebuffers(1, &resolve_fbo);
737                 s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
738             } else {
739                 // If the buffer is not multisampled, perform a normal texture copy.
740                 s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
741                         m_height);
742             }
743 
744             if (prev_read_fbo != 0) {
745                 if (isGles3) {
746                     s_gles2.glBindFramebuffer(GL_READ_FRAMEBUFFER,
747                                               (GLuint)prev_read_fbo);
748                 } else {
749                     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER,
750                                               (GLuint)prev_read_fbo);
751                 }
752             }
753 
754             s_gles2.glDeleteTextures(1, &tmpTex);
755             s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind);
756 
757             // clear GL errors, because its possible that the fbo format does not
758             // match
759             // the format of the read buffer, in the case of OpenGL ES 3.1 and
760             // integer
761             // RGBA formats.
762             s_gles2.glGetError();
763             // This is currently for dEQP purposes only; if we actually want these
764             // integer FBO formats to actually serve to display something for human
765             // consumption,
766             // we need to change the egl image to be of the same format,
767             // or we get some really psychedelic patterns.
768         } else {
769             // Like in the GLES 2 path above, correct the case where
770             // GL_FRAMEBUFFER_OES is not bound to zero so that we don't blit
771             // from arbitrary framebuffers.
772             // Use GLES 2 because it internally has the same value as the GLES 1
773             // API and it doesn't require GL_OES_framebuffer_object.
774             GLint prev_fbo = 0;
775             s_gles2.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
776             if (prev_fbo != 0) {
777                 s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
778             }
779 
780             s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
781             s_gles1.glGenTextures(1, &tmpTex);
782             s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex);
783             s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
784             s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
785                     m_height);
786             s_gles1.glDeleteTextures(1, &tmpTex);
787             s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind);
788 
789             if (prev_fbo != 0) {
790                 s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)prev_fbo);
791             }
792         }
793 
794         RecursiveScopedContextBind context(m_helper);
795         if (!context.isOk()) {
796             return false;
797         }
798 
799         if (!bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
800             return false;
801         }
802 
803         // Save current viewport and match it to the current colorbuffer size.
804         GLint vport[4] = {
805             0,
806         };
807         s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
808         s_gles2.glViewport(0, 0, m_width, m_height);
809 
810         // render m_blitTex
811         m_textureDraw->draw(m_blitTex, 0., 0, 0);
812 
813         // Restore previous viewport.
814         s_gles2.glViewport(vport[0], vport[1], vport[2], vport[3]);
815         unbindFbo();
816     }
817 
818     return true;
819 }
820 
bindToTexture()821 bool ColorBufferGl::bindToTexture() {
822     if (!m_eglImage) {
823         return false;
824     }
825 
826     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
827     if (!tInfo) {
828         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
829             << "Render thread GL not available.";
830     }
831 
832     if (!tInfo->currContext.get()) {
833         return false;
834     }
835 
836     if (tInfo->currContext->clientVersion() > GLESApi_CM) {
837         s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
838     } else {
839         s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
840     }
841     return true;
842 }
843 
bindToTexture2()844 bool ColorBufferGl::bindToTexture2() {
845     if (!m_eglImage) {
846         return false;
847     }
848 
849     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
850     return true;
851 }
852 
bindToRenderbuffer()853 bool ColorBufferGl::bindToRenderbuffer() {
854     if (!m_eglImage) {
855         return false;
856     }
857 
858     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
859     if (!tInfo) {
860         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
861             << "Render thread GL not available.";
862     }
863 
864     if (!tInfo->currContext.get()) {
865         return false;
866     }
867 
868     if (tInfo->currContext->clientVersion() > GLESApi_CM) {
869         s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
870                                                        m_eglImage);
871     } else {
872         s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
873                                                        m_eglImage);
874     }
875     return true;
876 }
877 
getViewportScaledTexture()878 GLuint ColorBufferGl::getViewportScaledTexture() { return m_resizer->update(m_tex); }
879 
setSync(bool debug)880 void ColorBufferGl::setSync(bool debug) {
881     m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
882     if (debug) fprintf(stderr, "%s: %u to %p\n", __func__, getHndl(), m_sync);
883 }
884 
waitSync(bool debug)885 void ColorBufferGl::waitSync(bool debug) {
886     if (debug) fprintf(stderr, "%s: %u sync %p\n", __func__, getHndl(), m_sync);
887     if (m_sync) {
888         s_egl.eglWaitImageFenceANDROID(m_display, m_sync);
889     }
890 }
891 
post(GLuint tex,float rotation,float dx,float dy)892 bool ColorBufferGl::post(GLuint tex, float rotation, float dx, float dy) {
893     // NOTE: Do not call m_helper->setupContext() here!
894     waitSync();
895     return m_textureDraw->draw(tex, rotation, dx, dy);
896 }
897 
postViewportScaledWithOverlay(float rotation,float dx,float dy)898 bool ColorBufferGl::postViewportScaledWithOverlay(float rotation, float dx, float dy) {
899     // NOTE: Do not call m_helper->setupContext() here!
900     waitSync();
901     return m_textureDraw->drawWithOverlay(getViewportScaledTexture(), rotation, dx, dy);
902 }
903 
readback(unsigned char * img,bool readbackBgra)904 void ColorBufferGl::readback(unsigned char* img, bool readbackBgra) {
905     RecursiveScopedContextBind context(m_helper);
906     if (!context.isOk()) {
907         return;
908     }
909 
910     waitSync();
911 
912     if (bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
913         m_needFboReattach = false;
914         // Flip the readback format if RED/BLUE components are swizzled.
915         bool shouldReadbackBgra = m_BRSwizzle ? !readbackBgra : readbackBgra;
916         GLenum format = shouldReadbackBgra ? GL_BGRA_EXT : GL_RGBA;
917 
918         s_gles2.glReadPixels(0, 0, m_width, m_height, format, GL_UNSIGNED_BYTE, img);
919         unbindFbo();
920     }
921 }
922 
readbackAsync(GLuint buffer,bool readbackBgra)923 void ColorBufferGl::readbackAsync(GLuint buffer, bool readbackBgra) {
924     RecursiveScopedContextBind context(m_helper);
925     if (!context.isOk()) {
926         return;
927     }
928 
929     waitSync();
930 
931     if (bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
932         m_needFboReattach = false;
933         s_gles2.glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
934         bool shouldReadbackBgra = m_BRSwizzle ? !readbackBgra : readbackBgra;
935         GLenum format = shouldReadbackBgra ? GL_BGRA_EXT : GL_RGBA;
936         s_gles2.glReadPixels(0, 0, m_width, m_height, format, m_asyncReadbackType, 0);
937         s_gles2.glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
938         unbindFbo();
939     }
940 }
941 
getHndl() const942 HandleType ColorBufferGl::getHndl() const { return mHndl; }
943 
onSave(android::base::Stream * stream)944 void ColorBufferGl::onSave(android::base::Stream* stream) {
945     stream->putBe32(getHndl());
946     stream->putBe32(static_cast<uint32_t>(m_width));
947     stream->putBe32(static_cast<uint32_t>(m_height));
948     stream->putBe32(static_cast<uint32_t>(m_internalFormat));
949     stream->putBe32(static_cast<uint32_t>(m_frameworkFormat));
950     // for debug
951     assert(m_eglImage && m_blitEGLImage);
952     stream->putBe32(reinterpret_cast<uintptr_t>(m_eglImage));
953     stream->putBe32(reinterpret_cast<uintptr_t>(m_blitEGLImage));
954     stream->putBe32(m_needFormatCheck);
955 }
956 
onLoad(android::base::Stream * stream,EGLDisplay p_display,ContextHelper * helper,TextureDraw * textureDraw,bool fastBlitSupported,const gfxstream::host::FeatureSet & features)957 std::unique_ptr<ColorBufferGl> ColorBufferGl::onLoad(android::base::Stream* stream,
958                                                      EGLDisplay p_display, ContextHelper* helper,
959                                                      TextureDraw* textureDraw,
960                                                      bool fastBlitSupported,
961                                                      const gfxstream::host::FeatureSet& features) {
962     HandleType hndl = static_cast<HandleType>(stream->getBe32());
963     GLuint width = static_cast<GLuint>(stream->getBe32());
964     GLuint height = static_cast<GLuint>(stream->getBe32());
965     GLenum internalFormat = static_cast<GLenum>(stream->getBe32());
966     FrameworkFormat frameworkFormat =
967             static_cast<FrameworkFormat>(stream->getBe32());
968     EGLImageKHR eglImage = reinterpret_cast<EGLImageKHR>(stream->getBe32());
969     EGLImageKHR blitEGLImage = reinterpret_cast<EGLImageKHR>(stream->getBe32());
970     uint32_t needFormatCheck = stream->getBe32();
971 
972     if (!eglImage) {
973         return create(p_display, width, height, internalFormat, frameworkFormat,
974                       hndl, helper, textureDraw, fastBlitSupported, features);
975     }
976     std::unique_ptr<ColorBufferGl> cb(
977         new ColorBufferGl(p_display, hndl, width, height, helper, textureDraw));
978     cb->m_eglImage = eglImage;
979     cb->m_blitEGLImage = blitEGLImage;
980     assert(eglImage && blitEGLImage);
981     cb->m_internalFormat = internalFormat;
982     cb->m_frameworkFormat = frameworkFormat;
983     cb->m_fastBlitSupported = fastBlitSupported;
984     cb->m_needFormatCheck = needFormatCheck;
985 
986     GLenum texFormat;
987     GLenum pixelType;
988     int bytesPerPixel = 1;
989     GLint sizedInternalFormat;
990     bool isBlob;
991     sGetFormatParameters(&cb->m_internalFormat, &texFormat, &pixelType, &bytesPerPixel,
992                          &sizedInternalFormat, &isBlob);
993     cb->m_type = pixelType;
994     cb->m_format = texFormat;
995     cb->m_sizedInternalFormat = sizedInternalFormat;
996     // TODO: set m_BRSwizzle properly
997     cb->m_numBytes = ((unsigned long)bytesPerPixel) * width * height;
998     return cb;
999 }
1000 
restore()1001 void ColorBufferGl::restore() {
1002     RecursiveScopedContextBind context(m_helper);
1003     s_gles2.glGenTextures(1, &m_tex);
1004     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
1005     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
1006 
1007     s_gles2.glGenTextures(1, &m_blitTex);
1008     s_gles2.glBindTexture(GL_TEXTURE_2D, m_blitTex);
1009     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
1010 
1011     m_resizer = new TextureResize(m_width, m_height);
1012     switch (m_frameworkFormat) {
1013         case FRAMEWORK_FORMAT_GL_COMPATIBLE:
1014             break;
1015         default: // any YUV format
1016             m_yuv_converter.reset(
1017                     new YUVConverter(m_width, m_height, m_frameworkFormat, m_yuv420888ToNv21));
1018             break;
1019     }
1020 }
1021 
getTexture()1022 GLuint ColorBufferGl::getTexture() { return m_tex; }
1023 
postLayer(const ComposeLayer & l,int frameWidth,int frameHeight)1024 void ColorBufferGl::postLayer(const ComposeLayer& l, int frameWidth, int frameHeight) {
1025     waitSync();
1026     m_textureDraw->drawLayer(l, frameWidth, frameHeight, m_width, m_height,
1027                              getViewportScaledTexture());
1028 }
1029 
importMemory(ManagedDescriptor externalDescriptor,uint64_t size,bool dedicated,bool linearTiling)1030 bool ColorBufferGl::importMemory(ManagedDescriptor externalDescriptor, uint64_t size,
1031                                  bool dedicated, bool linearTiling) {
1032     RecursiveScopedContextBind context(m_helper);
1033     s_gles2.glCreateMemoryObjectsEXT(1, &m_memoryObject);
1034     if (dedicated) {
1035         static const GLint DEDICATED_FLAG = GL_TRUE;
1036         s_gles2.glMemoryObjectParameterivEXT(m_memoryObject,
1037                                              GL_DEDICATED_MEMORY_OBJECT_EXT,
1038                                              &DEDICATED_FLAG);
1039     }
1040     std::optional<ManagedDescriptor::DescriptorType> maybeRawDescriptor = externalDescriptor.get();
1041     if (!maybeRawDescriptor.has_value()) {
1042         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Uninitialized external descriptor.";
1043     }
1044     ManagedDescriptor::DescriptorType rawDescriptor = *maybeRawDescriptor;
1045 
1046 #ifdef _WIN32
1047     s_gles2.glImportMemoryWin32HandleEXT(m_memoryObject, size, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT,
1048                                          rawDescriptor);
1049 #else
1050     s_gles2.glImportMemoryFdEXT(m_memoryObject, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, rawDescriptor);
1051 #endif
1052     GLenum error = s_gles2.glGetError();
1053     if (error == GL_NO_ERROR) {
1054 #ifdef _WIN32
1055         // Let the external descriptor close when going out of scope. From the
1056         // EXT_external_objects_win32 spec: importing a Windows handle does not transfer ownership
1057         // of the handle to the GL implementation.  For handle types defined as NT handles, the
1058         // application must release the handle using an appropriate system call when it is no longer
1059         // needed.
1060 #else
1061         // Inform ManagedDescriptor not to close the fd, since the owner of the fd is transferred to
1062         // the GL driver. From the EXT_external_objects_fd spec: a successful import operation
1063         // transfers ownership of <fd> to the GL implementation, and performing any operation on
1064         // <fd> in the application after an import results in undefined behavior.
1065         externalDescriptor.release();
1066 #endif
1067     } else {
1068         ERR("Failed to import external memory object with error: %d", static_cast<int>(error));
1069         return false;
1070     }
1071 
1072     GLuint glTiling = linearTiling ? GL_LINEAR_TILING_EXT : GL_OPTIMAL_TILING_EXT;
1073 
1074     std::vector<uint8_t> prevContents;
1075 
1076     size_t bytes;
1077     readContents(&bytes, nullptr);
1078     prevContents.resize(bytes, 0);
1079     readContents(&bytes, prevContents.data());
1080 
1081     s_gles2.glDeleteTextures(1, &m_tex);
1082     s_gles2.glDeleteFramebuffers(1, &m_fbo);
1083     m_fbo = 0;
1084     s_gles2.glDeleteFramebuffers(1, &m_scaleRotationFbo);
1085     m_scaleRotationFbo = 0;
1086     s_gles2.glDeleteFramebuffers(1, &m_yuv_conversion_fbo);
1087     m_yuv_conversion_fbo = 0;
1088     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
1089 
1090     s_gles2.glGenTextures(1, &m_tex);
1091     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
1092 
1093     // HOST needed because we do not expose this to guest
1094     s_gles2.glTexParameteriHOST(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, glTiling);
1095 
1096     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1097     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1098     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1099     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1100 
1101     if (m_sizedInternalFormat == GL_BGRA8_EXT ||
1102         m_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
1103         GLint internalFormat = m_sizedInternalFormat == GL_BGRA8_EXT
1104                                        ? GL_RGBA8
1105                                        : GL_RGB10_A2_EXT;
1106         s_gles2.glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, internalFormat, m_width,
1107                                      m_height, m_memoryObject, 0);
1108         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
1109         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
1110         m_BRSwizzle = true;
1111     } else {
1112         s_gles2.glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, m_sizedInternalFormat, m_width, m_height, m_memoryObject, 0);
1113         m_BRSwizzle = false;
1114     }
1115 
1116     m_eglImage = s_egl.eglCreateImageKHR(
1117             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
1118             (EGLClientBuffer)SafePointerFromUInt(m_tex), NULL);
1119 
1120     replaceContents(prevContents.data(), m_numBytes);
1121 
1122     return true;
1123 }
1124 
importEglNativePixmap(void * pixmap,bool preserveContent)1125 bool ColorBufferGl::importEglNativePixmap(void* pixmap, bool preserveContent) {
1126     EGLImageKHR image = s_egl.eglCreateImageKHR(m_display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, pixmap, nullptr);
1127 
1128     if (image == EGL_NO_IMAGE_KHR) {
1129         fprintf(stderr, "%s: error: failed to import pixmap\n", __func__);
1130         return false;
1131     }
1132 
1133     // Assume pixmap is compatible with ColorBufferGl's current dimensions and internal format.
1134     EGLBoolean setInfoRes = s_egl.eglSetImageInfoANDROID(m_display, image, m_width, m_height, m_internalFormat);
1135 
1136     if (EGL_TRUE != setInfoRes) {
1137         fprintf(stderr, "%s: error: failed to set image info\n", __func__);
1138         s_egl.eglDestroyImageKHR(m_display, image);
1139         return false;
1140     }
1141 
1142     rebindEglImage(image, preserveContent);
1143     return true;
1144 }
1145 
importEglImage(void * nativeEglImage,bool preserveContent)1146 bool ColorBufferGl::importEglImage(void* nativeEglImage, bool preserveContent) {
1147     EGLImageKHR image = s_egl.eglImportImageANDROID(m_display, (EGLImage)nativeEglImage);
1148 
1149     if (image == EGL_NO_IMAGE_KHR) return false;
1150 
1151     // Assume nativeEglImage is compatible with ColorBufferGl's current dimensions and internal
1152     // format.
1153     EGLBoolean setInfoRes = s_egl.eglSetImageInfoANDROID(m_display, image, m_width, m_height, m_internalFormat);
1154 
1155     if (EGL_TRUE != setInfoRes) {
1156         s_egl.eglDestroyImageKHR(m_display, image);
1157         return false;
1158     }
1159 
1160     rebindEglImage(image, preserveContent);
1161     return true;
1162 }
1163 
getContents()1164 std::vector<uint8_t> ColorBufferGl::getContents() {
1165     // Assume there is a current context.
1166     size_t bytes;
1167     readContents(&bytes, nullptr);
1168     std::vector<uint8_t> contents(bytes);
1169     readContents(&bytes, contents.data());
1170     return contents;
1171 }
1172 
clearStorage()1173 void ColorBufferGl::clearStorage() {
1174     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)NULL);
1175     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
1176     m_eglImage = (EGLImageKHR)0;
1177 }
1178 
restoreEglImage(EGLImageKHR image)1179 void ColorBufferGl::restoreEglImage(EGLImageKHR image) {
1180     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
1181 
1182     m_eglImage = image;
1183     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)m_eglImage);
1184 }
1185 
rebindEglImage(EGLImageKHR image,bool preserveContent)1186 void ColorBufferGl::rebindEglImage(EGLImageKHR image, bool preserveContent) {
1187     RecursiveScopedContextBind context(m_helper);
1188 
1189     std::vector<uint8_t> contents;
1190     if (preserveContent) {
1191         contents = getContents();
1192     }
1193     clearStorage();
1194     restoreEglImage(image);
1195 
1196     if (preserveContent) {
1197         replaceContents(contents.data(), m_numBytes);
1198     }
1199 }
1200 
getBorrowedImageInfo()1201 std::unique_ptr<BorrowedImageInfo> ColorBufferGl::getBorrowedImageInfo() {
1202     auto info = std::make_unique<BorrowedImageInfoGl>();
1203     info->id = mHndl;
1204     info->width = m_width;
1205     info->height = m_height;
1206     info->texture = m_tex;
1207     info->onCommandsIssued = [this]() { setSync(); };
1208     return info;
1209 }
1210 
1211 }  // namespace gl
1212 }  // namespace gfxstream
1213