• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)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     GLenum texFormat = 0;
221     GLenum pixelType = GL_UNSIGNED_BYTE;
222     int bytesPerPixel = 4;
223     GLint p_sizedInternalFormat = GL_RGBA8;
224     bool isBlob = false;;
225 
226     if (!sGetFormatParameters(&p_internalFormat, &texFormat, &pixelType,
227                               &bytesPerPixel, &p_sizedInternalFormat,
228                               &isBlob)) {
229         fprintf(stderr, "ColorBufferGl::create invalid format 0x%x\n", p_internalFormat);
230         return nullptr;
231     }
232     const unsigned long bufsize = ((unsigned long)bytesPerPixel) * p_width
233             * p_height;
234 
235     // This constructor is private, so std::make_unique can't be used.
236     std::unique_ptr<ColorBufferGl> cb{
237         new ColorBufferGl(p_display, hndl, p_width, p_height, helper, textureDraw)};
238     cb->m_internalFormat = p_internalFormat;
239     cb->m_sizedInternalFormat = p_sizedInternalFormat;
240     cb->m_format = texFormat;
241     cb->m_type = pixelType;
242     cb->m_frameworkFormat = p_frameworkFormat;
243     cb->m_fastBlitSupported = fastBlitSupported;
244     cb->m_numBytes = (size_t)bufsize;
245 
246     RecursiveScopedContextBind context(helper);
247     if (!context.isOk()) {
248         return nullptr;
249     }
250 
251     GL_SCOPED_DEBUG_GROUP("ColorBufferGl::create(handle:%d)", hndl);
252 
253     GLint prevUnpackAlignment;
254     s_gles2.glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlignment);
255     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
256 
257     s_gles2.glGenTextures(1, &cb->m_tex);
258     s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_tex);
259 
260     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, p_internalFormat, p_width, p_height,
261                          0, texFormat, pixelType, nullptr);
262 
263     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
264     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
265     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
266     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
267     // Swizzle B/R channel for BGR10_A2 images.
268     if (p_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
269         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
270         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
271         cb->m_BRSwizzle = true;
272     }
273 
274     //
275     // create another texture for that colorbuffer for blit
276     //
277     s_gles2.glGenTextures(1, &cb->m_blitTex);
278     s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
279     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, p_internalFormat, p_width, p_height,
280                          0, texFormat, pixelType, NULL);
281 
282     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
283     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
284     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
285     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
286     // Swizzle B/R channel for BGR10_A2 images.
287     if (p_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
288         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
289         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
290         cb->m_BRSwizzle = true;
291     }
292 
293     cb->m_eglImage = s_egl.eglCreateImageKHR(
294             p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
295             (EGLClientBuffer)SafePointerFromUInt(cb->m_tex), NULL);
296 
297     cb->m_blitEGLImage = s_egl.eglCreateImageKHR(
298             p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
299             (EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex), NULL);
300 
301     cb->m_resizer = new TextureResize(p_width, p_height);
302 
303     switch (cb->m_frameworkFormat) {
304         case FRAMEWORK_FORMAT_GL_COMPATIBLE:
305             break;
306         default: // Any YUV format
307             cb->m_yuv_converter.reset(
308                     new YUVConverter(p_width, p_height, cb->m_frameworkFormat));
309             break;
310     }
311 
312     // desktop GL only: use GL_UNSIGNED_INT_8_8_8_8_REV for faster readback.
313     if (emugl::getRenderer() == SELECTED_RENDERER_HOST) {
314 #define GL_UNSIGNED_INT_8_8_8_8           0x8035
315 #define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367
316         cb->m_asyncReadbackType = GL_UNSIGNED_INT_8_8_8_8_REV;
317     }
318 
319     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlignment);
320 
321     s_gles2.glFinish();
322     return cb;
323 }
324 
ColorBufferGl(EGLDisplay display,HandleType hndl,GLuint width,GLuint height,ContextHelper * helper,TextureDraw * textureDraw)325 ColorBufferGl::ColorBufferGl(EGLDisplay display, HandleType hndl, GLuint width, GLuint height,
326                              ContextHelper* helper, TextureDraw* textureDraw)
327     : m_width(width),
328       m_height(height),
329       m_display(display),
330       m_helper(helper),
331       m_textureDraw(textureDraw),
332       mHndl(hndl) {}
333 
~ColorBufferGl()334 ColorBufferGl::~ColorBufferGl() {
335     RecursiveScopedContextBind context(m_helper);
336 
337     if (m_blitEGLImage) {
338         s_egl.eglDestroyImageKHR(m_display, m_blitEGLImage);
339     }
340     if (m_eglImage) {
341         s_egl.eglDestroyImageKHR(m_display, m_eglImage);
342     }
343 
344     if (m_fbo) {
345         s_gles2.glDeleteFramebuffers(1, &m_fbo);
346     }
347 
348     if (m_yuv_conversion_fbo) {
349         s_gles2.glDeleteFramebuffers(1, &m_yuv_conversion_fbo);
350     }
351 
352     if (m_scaleRotationFbo) {
353         s_gles2.glDeleteFramebuffers(1, &m_scaleRotationFbo);
354     }
355 
356     m_yuv_converter.reset();
357 
358     GLuint tex[2] = {m_tex, m_blitTex};
359     s_gles2.glDeleteTextures(2, tex);
360 
361     if (m_memoryObject) {
362         s_gles2.glDeleteMemoryObjectsEXT(1, &m_memoryObject);
363     }
364 
365     delete m_resizer;
366 }
367 
readPixels(int x,int y,int width,int height,GLenum p_format,GLenum p_type,void * pixels)368 void ColorBufferGl::readPixels(int x, int y, int width, int height, GLenum p_format, GLenum p_type,
369                                void* pixels) {
370     RecursiveScopedContextBind context(m_helper);
371     if (!context.isOk()) {
372         return;
373     }
374 
375     GL_SCOPED_DEBUG_GROUP("ColorBufferGl::readPixels(handle:%d fbo:%d tex:%d)", mHndl, m_fbo,
376                           m_tex);
377 
378     p_format = sGetUnsizedColorBufferFormat(p_format);
379 
380     waitSync();
381 
382     if (bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
383         m_needFboReattach = false;
384         GLint prevAlignment = 0;
385         s_gles2.glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);
386         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, 1);
387         s_gles2.glReadPixels(x, y, width, height, p_format, p_type, pixels);
388         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);
389         unbindFbo();
390     }
391 }
392 
readPixelsScaled(int width,int height,GLenum p_format,GLenum p_type,int rotation,Rect rect,void * pixels)393 void ColorBufferGl::readPixelsScaled(int width, int height, GLenum p_format, GLenum p_type,
394                                      int rotation, Rect rect, void* pixels) {
395     RecursiveScopedContextBind context(m_helper);
396     if (!context.isOk()) {
397         return;
398     }
399     bool useSnipping = rect.size.w != 0 && rect.size.h != 0;
400     // Boundary check
401     if (useSnipping &&
402         (rect.pos.x < 0 || rect.pos.y < 0 || rect.pos.x + rect.size.w > width ||
403          rect.pos.y + rect.size.h > height)) {
404         ERR("readPixelsScaled failed. Out-of-bound rectangle: (%d, %d) [%d x %d]"
405             " with screen [%d x %d]",
406             rect.pos.x, rect.pos.y, rect.size.w, rect.size.h);
407         return;
408     }
409     p_format = sGetUnsizedColorBufferFormat(p_format);
410 
411     waitSync();
412     GLuint tex = m_resizer->update(m_tex, width, height, rotation);
413     if (bindFbo(&m_scaleRotationFbo, tex, m_needFboReattach)) {
414         m_needFboReattach = false;
415         GLint prevAlignment = 0;
416         s_gles2.glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);
417         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, 1);
418         // SwANGLE does not suppot glReadPixels with 3 channels.
419         // In fact, the spec only require RGBA8888 format support. Supports for
420         // other formats are optional.
421         bool needConvert4To3Channel =
422                 p_format == GL_RGB && p_type == GL_UNSIGNED_BYTE &&
423                 (emugl::getRenderer() == SELECTED_RENDERER_SWIFTSHADER_INDIRECT ||
424                     emugl::getRenderer() == SELECTED_RENDERER_ANGLE_INDIRECT);
425         std::vector<uint8_t> tmpPixels;
426         void* readPixelsDst = pixels;
427         if (needConvert4To3Channel) {
428             tmpPixels.resize(width * height * 4);
429             p_format = GL_RGBA;
430             readPixelsDst = tmpPixels.data();
431         }
432         if (useSnipping) {
433             s_gles2.glReadPixels(rect.pos.x, rect.pos.y, rect.size.w,
434                                  rect.size.h, p_format, p_type, readPixelsDst);
435             width = rect.size.w;
436             height = rect.size.h;
437         } else {
438             s_gles2.glReadPixels(0, 0, width, height, p_format, p_type,
439                                  readPixelsDst);
440         }
441         if (needConvert4To3Channel) {
442             uint8_t* src = tmpPixels.data();
443             uint8_t* dst = static_cast<uint8_t*>(pixels);
444             for (int h = 0; h < height; h++) {
445                 for (int w = 0; w < width; w++) {
446                     memcpy(dst, src, 3);
447                     dst += 3;
448                     src += 4;
449                 }
450             }
451         }
452         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);
453         unbindFbo();
454     }
455 }
456 
readPixelsYUVCached(int x,int y,int width,int height,void * pixels,uint32_t pixels_size)457 void ColorBufferGl::readPixelsYUVCached(int x, int y, int width, int height, void* pixels,
458                                         uint32_t pixels_size) {
459     RecursiveScopedContextBind context(m_helper);
460     if (!context.isOk()) {
461         return;
462     }
463 
464     waitSync();
465 
466 #if DEBUG_CB_FBO
467     fprintf(stderr, "%s %d request width %d height %d\n", __func__, __LINE__,
468             width, height);
469     memset(pixels, 0x00, pixels_size);
470     assert(m_yuv_converter.get());
471 #endif
472 
473     m_yuv_converter->readPixels((uint8_t*)pixels, pixels_size);
474 
475     return;
476 }
477 
reformat(GLint internalformat,GLenum type)478 void ColorBufferGl::reformat(GLint internalformat, GLenum type) {
479     GLenum texFormat = internalformat;
480     GLenum pixelType = GL_UNSIGNED_BYTE;
481     GLint sizedInternalFormat = GL_RGBA8;
482     int bpp = 4;
483     bool isBlob = false;
484     if (!sGetFormatParameters(&internalformat, &texFormat, &pixelType, &bpp,
485                               &sizedInternalFormat, &isBlob)) {
486         fprintf(stderr, "%s: WARNING: reformat failed. internal format: 0x%x\n",
487                 __func__, internalformat);
488     }
489 
490     // BUG: 143607546
491     //
492     // During reformatting, sGetFormatParameters can be too
493     // opinionated and override the guest's intended choice for the
494     // pixel type.  If the guest wanted GL_UNSIGNED_SHORT_5_6_5 as
495     // the pixel type, and the incoming internal format is not
496     // explicitly sized, sGetFormatParameters will pick a default of
497     // GL_UNSIGNED BYTE, which goes against guest expectations.
498     //
499     // This happens only on older API levels where gralloc.cpp in
500     // goldfish-opengl communicated HAL_PIXEL_FORMAT_RGB_565 as GL
501     // format GL_RGB, pixel type GL_UNSIGNED_SHORT_5_6_5.  Newer
502     // system images communicate HAL_PIXEL_FORMAT_RGB_565 as GL
503     // format GL_RGB565, which allows sGetFormatParameters to work
504     // correctly.
505     if (pixelType != type) {
506         pixelType = type;
507     }
508 
509     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
510     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, m_height,
511                          0, texFormat, pixelType, nullptr);
512 
513     s_gles2.glBindTexture(GL_TEXTURE_2D, m_blitTex);
514     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, m_height,
515                          0, texFormat, pixelType, nullptr);
516 
517     // EGL images need to be recreated because the EGL_KHR_image_base spec
518     // states that respecifying an image (i.e. glTexImage2D) will generally
519     // result in orphaning of the EGL image.
520     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
521     m_eglImage = s_egl.eglCreateImageKHR(
522             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
523             (EGLClientBuffer)SafePointerFromUInt(m_tex), NULL);
524 
525     s_egl.eglDestroyImageKHR(m_display, m_blitEGLImage);
526     m_blitEGLImage = s_egl.eglCreateImageKHR(
527             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
528             (EGLClientBuffer)SafePointerFromUInt(m_blitTex), NULL);
529 
530     s_gles2.glBindTexture(GL_TEXTURE_2D, 0);
531 
532     m_internalFormat = internalformat;
533     m_format = texFormat;
534     m_type = pixelType;
535     m_sizedInternalFormat = sizedInternalFormat;
536 
537     m_numBytes = bpp * m_width * m_height;
538 }
539 
swapYUVTextures(FrameworkFormat type,uint32_t * textures)540 void ColorBufferGl::swapYUVTextures(FrameworkFormat type, uint32_t* textures) {
541     if (type == FrameworkFormat::FRAMEWORK_FORMAT_NV12) {
542         m_yuv_converter->swapTextures(type, textures);
543     } else {
544         fprintf(stderr,
545                 "%s: ERROR: format other than NV12 is not supported: 0x%x\n",
546                 __func__, type);
547     }
548 }
549 
subUpdate(int x,int y,int width,int height,GLenum p_format,GLenum p_type,const void * pixels)550 bool ColorBufferGl::subUpdate(int x, int y, int width, int height, GLenum p_format, GLenum p_type,
551                               const void* pixels) {
552     return subUpdateFromFrameworkFormat(x, y, width, height, m_frameworkFormat, p_format, p_type,
553                                         pixels);
554 }
555 
subUpdateFromFrameworkFormat(int x,int y,int width,int height,FrameworkFormat fwkFormat,GLenum p_format,GLenum p_type,const void * pixels)556 bool ColorBufferGl::subUpdateFromFrameworkFormat(int x, int y, int width, int height,
557                                                  FrameworkFormat fwkFormat, GLenum p_format,
558                                                  GLenum p_type, const void* pixels) {
559     const GLenum p_unsizedFormat = sGetUnsizedColorBufferFormat(p_format);
560     RecursiveScopedContextBind context(m_helper);
561     if (!context.isOk()) {
562         return false;
563     }
564 
565     GL_SCOPED_DEBUG_GROUP("ColorBufferGl::subUpdate(handle:%d fbo:%d tex:%d)", mHndl, m_fbo, m_tex);
566 
567     if (m_needFormatCheck) {
568         if (p_type != m_type || p_format != m_format) {
569             reformat((GLint)p_format, p_type);
570         }
571         m_needFormatCheck = false;
572     }
573 
574     if (m_frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE || fwkFormat != m_frameworkFormat) {
575         assert(m_yuv_converter.get());
576 
577         // This FBO will convert the YUV frame to RGB
578         // and render it to |m_tex|.
579         bindFbo(&m_yuv_conversion_fbo, m_tex, m_needFboReattach);
580         m_yuv_converter->drawConvertFromFormat(fwkFormat, x, y, width, height, (char*)pixels);
581         unbindFbo();
582 
583         // |m_tex| still needs to be bound afterwards
584         s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
585 
586     } else {
587         s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
588         s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
589 
590         s_gles2.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, p_unsizedFormat,
591                                 p_type, pixels);
592     }
593 
594     if (m_fastBlitSupported) {
595         s_gles2.glFlush();
596         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
597     }
598 
599     return true;
600 }
601 
replaceContents(const void * newContents,size_t numBytes)602 bool ColorBufferGl::replaceContents(const void* newContents, size_t numBytes) {
603     return subUpdate(0, 0, m_width, m_height, m_format, m_type, newContents);
604 }
605 
readContents(size_t * numBytes,void * pixels)606 bool ColorBufferGl::readContents(size_t* numBytes, void* pixels) {
607     if (m_yuv_converter) {
608         // common code path for vk & gles
609         *numBytes = m_yuv_converter->getDataSize();
610         if (pixels) {
611             readPixelsYUVCached(0, 0, 0, 0, pixels, *numBytes);
612         }
613         return true;
614     } else {
615         *numBytes = m_numBytes;
616 
617         if (!pixels) return true;
618         RecursiveScopedContextBind context(m_helper);
619 
620         readPixels(0, 0, m_width, m_height, m_format, m_type, pixels);
621 
622         return true;
623     }
624 }
625 
blitFromCurrentReadBuffer()626 bool ColorBufferGl::blitFromCurrentReadBuffer() {
627     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
628     if (!tInfo) {
629         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
630             << "Render thread GL not available.";
631     }
632 
633     if (!tInfo->currContext.get()) {
634         // no Current context
635         return false;
636     }
637 
638     if (m_fastBlitSupported) {
639         s_egl.eglBlitFromCurrentReadBufferANDROID(m_display, m_eglImage);
640         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
641     } else {
642         // Copy the content of the current read surface into m_blitEGLImage.
643         // This is done by creating a temporary texture, bind it to the EGLImage
644         // then call glCopyTexSubImage2D().
645         GLuint tmpTex;
646         GLint currTexBind;
647         if (tInfo->currContext->clientVersion() > GLESApi_CM) {
648             s_gles2.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
649             s_gles2.glGenTextures(1, &tmpTex);
650             s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
651             s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
652 
653             const bool isGles3 = tInfo->currContext->clientVersion() > GLESApi_2;
654 
655             GLint prev_read_fbo = 0;
656             if (isGles3) {
657                 // Make sure that we unbind any existing GL_READ_FRAMEBUFFER
658                 // before calling glCopyTexSubImage2D, otherwise we may blit
659                 // from the guest's current read framebuffer instead of the EGL
660                 // read buffer.
661                 s_gles2.glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo);
662                 if (prev_read_fbo != 0) {
663                     s_gles2.glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
664                 }
665             } else {
666                 // On GLES 2, there are not separate read/draw framebuffers,
667                 // only GL_FRAMEBUFFER.  Per the EGL 1.4 spec section 3.9.3,
668                 // the draw surface must be bound to the calling thread's
669                 // current context, so GL_FRAMEBUFFER should be 0.  However, the
670                 // error case is not strongly defined and generating a new error
671                 // may break existing apps.
672                 //
673                 // Instead of the obviously wrong behavior of posting whatever
674                 // GL_FRAMEBUFFER is currently bound to, fix up the
675                 // GL_FRAMEBUFFER if it is non-zero.
676                 s_gles2.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_read_fbo);
677                 if (prev_read_fbo != 0) {
678                     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
679                 }
680             }
681 
682             // If the read buffer is multisampled, we need to resolve.
683             GLint samples;
684             s_gles2.glGetIntegerv(GL_SAMPLE_BUFFERS, &samples);
685             if (isGles3 && samples > 0) {
686                 s_gles2.glBindTexture(GL_TEXTURE_2D, 0);
687 
688                 GLuint resolve_fbo;
689                 GLint prev_draw_fbo;
690                 s_gles2.glGenFramebuffers(1, &resolve_fbo);
691                 s_gles2.glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo);
692 
693                 s_gles2.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
694                 s_gles2.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
695                         GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
696                         tmpTex, 0);
697                 s_gles2.glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width,
698                         m_height, GL_COLOR_BUFFER_BIT,
699                         GL_NEAREST);
700                 s_gles2.glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
701                         (GLuint)prev_draw_fbo);
702 
703                 s_gles2.glDeleteFramebuffers(1, &resolve_fbo);
704                 s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
705             } else {
706                 // If the buffer is not multisampled, perform a normal texture copy.
707                 s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
708                         m_height);
709             }
710 
711             if (prev_read_fbo != 0) {
712                 if (isGles3) {
713                     s_gles2.glBindFramebuffer(GL_READ_FRAMEBUFFER,
714                                               (GLuint)prev_read_fbo);
715                 } else {
716                     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER,
717                                               (GLuint)prev_read_fbo);
718                 }
719             }
720 
721             s_gles2.glDeleteTextures(1, &tmpTex);
722             s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind);
723 
724             // clear GL errors, because its possible that the fbo format does not
725             // match
726             // the format of the read buffer, in the case of OpenGL ES 3.1 and
727             // integer
728             // RGBA formats.
729             s_gles2.glGetError();
730             // This is currently for dEQP purposes only; if we actually want these
731             // integer FBO formats to actually serve to display something for human
732             // consumption,
733             // we need to change the egl image to be of the same format,
734             // or we get some really psychedelic patterns.
735         } else {
736             // Like in the GLES 2 path above, correct the case where
737             // GL_FRAMEBUFFER_OES is not bound to zero so that we don't blit
738             // from arbitrary framebuffers.
739             // Use GLES 2 because it internally has the same value as the GLES 1
740             // API and it doesn't require GL_OES_framebuffer_object.
741             GLint prev_fbo = 0;
742             s_gles2.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
743             if (prev_fbo != 0) {
744                 s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
745             }
746 
747             s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
748             s_gles1.glGenTextures(1, &tmpTex);
749             s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex);
750             s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
751             s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
752                     m_height);
753             s_gles1.glDeleteTextures(1, &tmpTex);
754             s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind);
755 
756             if (prev_fbo != 0) {
757                 s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)prev_fbo);
758             }
759         }
760 
761         RecursiveScopedContextBind context(m_helper);
762         if (!context.isOk()) {
763             return false;
764         }
765 
766         if (!bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
767             return false;
768         }
769 
770         // Save current viewport and match it to the current colorbuffer size.
771         GLint vport[4] = {
772             0,
773         };
774         s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
775         s_gles2.glViewport(0, 0, m_width, m_height);
776 
777         // render m_blitTex
778         m_textureDraw->draw(m_blitTex, 0., 0, 0);
779 
780         // Restore previous viewport.
781         s_gles2.glViewport(vport[0], vport[1], vport[2], vport[3]);
782         unbindFbo();
783     }
784 
785     return true;
786 }
787 
bindToTexture()788 bool ColorBufferGl::bindToTexture() {
789     if (!m_eglImage) {
790         return false;
791     }
792 
793     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
794     if (!tInfo) {
795         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
796             << "Render thread GL not available.";
797     }
798 
799     if (!tInfo->currContext.get()) {
800         return false;
801     }
802 
803     if (tInfo->currContext->clientVersion() > GLESApi_CM) {
804         s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
805     } else {
806         s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
807     }
808     return true;
809 }
810 
bindToTexture2()811 bool ColorBufferGl::bindToTexture2() {
812     if (!m_eglImage) {
813         return false;
814     }
815 
816     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
817     return true;
818 }
819 
bindToRenderbuffer()820 bool ColorBufferGl::bindToRenderbuffer() {
821     if (!m_eglImage) {
822         return false;
823     }
824 
825     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
826     if (!tInfo) {
827         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
828             << "Render thread GL not available.";
829     }
830 
831     if (!tInfo->currContext.get()) {
832         return false;
833     }
834 
835     if (tInfo->currContext->clientVersion() > GLESApi_CM) {
836         s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
837                                                        m_eglImage);
838     } else {
839         s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
840                                                        m_eglImage);
841     }
842     return true;
843 }
844 
getViewportScaledTexture()845 GLuint ColorBufferGl::getViewportScaledTexture() { return m_resizer->update(m_tex); }
846 
setSync(bool debug)847 void ColorBufferGl::setSync(bool debug) {
848     m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
849     if (debug) fprintf(stderr, "%s: %u to %p\n", __func__, getHndl(), m_sync);
850 }
851 
waitSync(bool debug)852 void ColorBufferGl::waitSync(bool debug) {
853     if (debug) fprintf(stderr, "%s: %u sync %p\n", __func__, getHndl(), m_sync);
854     if (m_sync) {
855         s_egl.eglWaitImageFenceANDROID(m_display, m_sync);
856     }
857 }
858 
post(GLuint tex,float rotation,float dx,float dy)859 bool ColorBufferGl::post(GLuint tex, float rotation, float dx, float dy) {
860     // NOTE: Do not call m_helper->setupContext() here!
861     waitSync();
862     return m_textureDraw->draw(tex, rotation, dx, dy);
863 }
864 
postViewportScaledWithOverlay(float rotation,float dx,float dy)865 bool ColorBufferGl::postViewportScaledWithOverlay(float rotation, float dx, float dy) {
866     // NOTE: Do not call m_helper->setupContext() here!
867     waitSync();
868     return m_textureDraw->drawWithOverlay(getViewportScaledTexture(), rotation, dx, dy);
869 }
870 
readback(unsigned char * img,bool readbackBgra)871 void ColorBufferGl::readback(unsigned char* img, bool readbackBgra) {
872     RecursiveScopedContextBind context(m_helper);
873     if (!context.isOk()) {
874         return;
875     }
876 
877     waitSync();
878 
879     if (bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
880         m_needFboReattach = false;
881         // Flip the readback format if RED/BLUE components are swizzled.
882         bool shouldReadbackBgra = m_BRSwizzle ? !readbackBgra : readbackBgra;
883         GLenum format = shouldReadbackBgra ? GL_BGRA_EXT : GL_RGBA;
884 
885         s_gles2.glReadPixels(0, 0, m_width, m_height, format, GL_UNSIGNED_BYTE, img);
886         unbindFbo();
887     }
888 }
889 
readbackAsync(GLuint buffer,bool readbackBgra)890 void ColorBufferGl::readbackAsync(GLuint buffer, bool readbackBgra) {
891     RecursiveScopedContextBind context(m_helper);
892     if (!context.isOk()) {
893         return;
894     }
895 
896     waitSync();
897 
898     if (bindFbo(&m_fbo, m_tex, m_needFboReattach)) {
899         m_needFboReattach = false;
900         s_gles2.glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
901         bool shouldReadbackBgra = m_BRSwizzle ? !readbackBgra : readbackBgra;
902         GLenum format = shouldReadbackBgra ? GL_BGRA_EXT : GL_RGBA;
903         s_gles2.glReadPixels(0, 0, m_width, m_height, format, m_asyncReadbackType, 0);
904         s_gles2.glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
905         unbindFbo();
906     }
907 }
908 
getHndl() const909 HandleType ColorBufferGl::getHndl() const { return mHndl; }
910 
onSave(android::base::Stream * stream)911 void ColorBufferGl::onSave(android::base::Stream* stream) {
912     stream->putBe32(getHndl());
913     stream->putBe32(static_cast<uint32_t>(m_width));
914     stream->putBe32(static_cast<uint32_t>(m_height));
915     stream->putBe32(static_cast<uint32_t>(m_internalFormat));
916     stream->putBe32(static_cast<uint32_t>(m_frameworkFormat));
917     // for debug
918     assert(m_eglImage && m_blitEGLImage);
919     stream->putBe32(reinterpret_cast<uintptr_t>(m_eglImage));
920     stream->putBe32(reinterpret_cast<uintptr_t>(m_blitEGLImage));
921     stream->putBe32(m_needFormatCheck);
922 }
923 
onLoad(android::base::Stream * stream,EGLDisplay p_display,ContextHelper * helper,TextureDraw * textureDraw,bool fastBlitSupported)924 std::unique_ptr<ColorBufferGl> ColorBufferGl::onLoad(android::base::Stream* stream,
925                                                      EGLDisplay p_display, ContextHelper* helper,
926                                                      TextureDraw* textureDraw,
927                                                      bool fastBlitSupported) {
928     HandleType hndl = static_cast<HandleType>(stream->getBe32());
929     GLuint width = static_cast<GLuint>(stream->getBe32());
930     GLuint height = static_cast<GLuint>(stream->getBe32());
931     GLenum internalFormat = static_cast<GLenum>(stream->getBe32());
932     FrameworkFormat frameworkFormat =
933             static_cast<FrameworkFormat>(stream->getBe32());
934     EGLImageKHR eglImage = reinterpret_cast<EGLImageKHR>(stream->getBe32());
935     EGLImageKHR blitEGLImage = reinterpret_cast<EGLImageKHR>(stream->getBe32());
936     uint32_t needFormatCheck = stream->getBe32();
937 
938     if (!eglImage) {
939         return create(p_display, width, height, internalFormat, frameworkFormat,
940                       hndl, helper, textureDraw, fastBlitSupported);
941     }
942     std::unique_ptr<ColorBufferGl> cb(
943         new ColorBufferGl(p_display, hndl, width, height, helper, textureDraw));
944     cb->m_eglImage = eglImage;
945     cb->m_blitEGLImage = blitEGLImage;
946     assert(eglImage && blitEGLImage);
947     cb->m_internalFormat = internalFormat;
948     cb->m_frameworkFormat = frameworkFormat;
949     cb->m_fastBlitSupported = fastBlitSupported;
950     cb->m_needFormatCheck = needFormatCheck;
951     return cb;
952 }
953 
restore()954 void ColorBufferGl::restore() {
955     RecursiveScopedContextBind context(m_helper);
956     s_gles2.glGenTextures(1, &m_tex);
957     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
958     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
959 
960     s_gles2.glGenTextures(1, &m_blitTex);
961     s_gles2.glBindTexture(GL_TEXTURE_2D, m_blitTex);
962     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
963 
964     m_resizer = new TextureResize(m_width, m_height);
965     switch (m_frameworkFormat) {
966         case FRAMEWORK_FORMAT_GL_COMPATIBLE:
967             break;
968         default: // any YUV format
969             m_yuv_converter.reset(
970                     new YUVConverter(m_width, m_height, m_frameworkFormat));
971             break;
972     }
973 }
974 
getTexture()975 GLuint ColorBufferGl::getTexture() { return m_tex; }
976 
postLayer(const ComposeLayer & l,int frameWidth,int frameHeight)977 void ColorBufferGl::postLayer(const ComposeLayer& l, int frameWidth, int frameHeight) {
978     waitSync();
979     m_textureDraw->drawLayer(l, frameWidth, frameHeight, m_width, m_height,
980                              getViewportScaledTexture());
981 }
982 
importMemory(ManagedDescriptor externalDescriptor,uint64_t size,bool dedicated,bool linearTiling)983 bool ColorBufferGl::importMemory(ManagedDescriptor externalDescriptor, uint64_t size,
984                                  bool dedicated, bool linearTiling) {
985     RecursiveScopedContextBind context(m_helper);
986     s_gles2.glCreateMemoryObjectsEXT(1, &m_memoryObject);
987     if (dedicated) {
988         static const GLint DEDICATED_FLAG = GL_TRUE;
989         s_gles2.glMemoryObjectParameterivEXT(m_memoryObject,
990                                              GL_DEDICATED_MEMORY_OBJECT_EXT,
991                                              &DEDICATED_FLAG);
992     }
993     std::optional<ManagedDescriptor::DescriptorType> maybeRawDescriptor = externalDescriptor.get();
994     if (!maybeRawDescriptor.has_value()) {
995         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Uninitialized external descriptor.";
996     }
997     ManagedDescriptor::DescriptorType rawDescriptor = *maybeRawDescriptor;
998 
999 #ifdef _WIN32
1000     s_gles2.glImportMemoryWin32HandleEXT(m_memoryObject, size, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT,
1001                                          rawDescriptor);
1002 #else
1003     s_gles2.glImportMemoryFdEXT(m_memoryObject, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, rawDescriptor);
1004 #endif
1005     GLenum error = s_gles2.glGetError();
1006     if (error == GL_NO_ERROR) {
1007 #ifdef _WIN32
1008         // Let the external descriptor close when going out of scope. From the
1009         // EXT_external_objects_win32 spec: importing a Windows handle does not transfer ownership
1010         // of the handle to the GL implementation.  For handle types defined as NT handles, the
1011         // application must release the handle using an appropriate system call when it is no longer
1012         // needed.
1013 #else
1014         // Inform ManagedDescriptor not to close the fd, since the owner of the fd is transferred to
1015         // the GL driver. From the EXT_external_objects_fd spec: a successful import operation
1016         // transfers ownership of <fd> to the GL implementation, and performing any operation on
1017         // <fd> in the application after an import results in undefined behavior.
1018         externalDescriptor.release();
1019 #endif
1020     } else {
1021         ERR("Failed to import external memory object with error: %d", static_cast<int>(error));
1022         return false;
1023     }
1024 
1025     GLuint glTiling = linearTiling ? GL_LINEAR_TILING_EXT : GL_OPTIMAL_TILING_EXT;
1026 
1027     std::vector<uint8_t> prevContents;
1028 
1029     size_t bytes;
1030     readContents(&bytes, nullptr);
1031     prevContents.resize(bytes, 0);
1032     readContents(&bytes, prevContents.data());
1033 
1034     s_gles2.glDeleteTextures(1, &m_tex);
1035     s_gles2.glDeleteFramebuffers(1, &m_fbo);
1036     m_fbo = 0;
1037     s_gles2.glDeleteFramebuffers(1, &m_scaleRotationFbo);
1038     m_scaleRotationFbo = 0;
1039     s_gles2.glDeleteFramebuffers(1, &m_yuv_conversion_fbo);
1040     m_yuv_conversion_fbo = 0;
1041     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
1042 
1043     s_gles2.glGenTextures(1, &m_tex);
1044     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
1045 
1046     // HOST needed because we do not expose this to guest
1047     s_gles2.glTexParameteriHOST(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, glTiling);
1048 
1049     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1050     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1051     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1052     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1053 
1054     if (m_sizedInternalFormat == GL_BGRA8_EXT ||
1055         m_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
1056         GLint internalFormat = m_sizedInternalFormat == GL_BGRA8_EXT
1057                                        ? GL_RGBA8
1058                                        : GL_RGB10_A2_EXT;
1059         s_gles2.glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, internalFormat, m_width,
1060                                      m_height, m_memoryObject, 0);
1061         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
1062         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
1063         m_BRSwizzle = true;
1064     } else {
1065         s_gles2.glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, m_sizedInternalFormat, m_width, m_height, m_memoryObject, 0);
1066         m_BRSwizzle = false;
1067     }
1068 
1069     m_eglImage = s_egl.eglCreateImageKHR(
1070             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
1071             (EGLClientBuffer)SafePointerFromUInt(m_tex), NULL);
1072 
1073     replaceContents(prevContents.data(), m_numBytes);
1074 
1075     return true;
1076 }
1077 
importEglNativePixmap(void * pixmap,bool preserveContent)1078 bool ColorBufferGl::importEglNativePixmap(void* pixmap, bool preserveContent) {
1079     EGLImageKHR image = s_egl.eglCreateImageKHR(m_display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, pixmap, nullptr);
1080 
1081     if (image == EGL_NO_IMAGE_KHR) {
1082         fprintf(stderr, "%s: error: failed to import pixmap\n", __func__);
1083         return false;
1084     }
1085 
1086     // Assume pixmap is compatible with ColorBufferGl's current dimensions and internal format.
1087     EGLBoolean setInfoRes = s_egl.eglSetImageInfoANDROID(m_display, image, m_width, m_height, m_internalFormat);
1088 
1089     if (EGL_TRUE != setInfoRes) {
1090         fprintf(stderr, "%s: error: failed to set image info\n", __func__);
1091         s_egl.eglDestroyImageKHR(m_display, image);
1092         return false;
1093     }
1094 
1095     rebindEglImage(image, preserveContent);
1096     return true;
1097 }
1098 
importEglImage(void * nativeEglImage,bool preserveContent)1099 bool ColorBufferGl::importEglImage(void* nativeEglImage, bool preserveContent) {
1100     EGLImageKHR image = s_egl.eglImportImageANDROID(m_display, (EGLImage)nativeEglImage);
1101 
1102     if (image == EGL_NO_IMAGE_KHR) return false;
1103 
1104     // Assume nativeEglImage is compatible with ColorBufferGl's current dimensions and internal
1105     // format.
1106     EGLBoolean setInfoRes = s_egl.eglSetImageInfoANDROID(m_display, image, m_width, m_height, m_internalFormat);
1107 
1108     if (EGL_TRUE != setInfoRes) {
1109         s_egl.eglDestroyImageKHR(m_display, image);
1110         return false;
1111     }
1112 
1113     rebindEglImage(image, preserveContent);
1114     return true;
1115 }
1116 
getContents()1117 std::vector<uint8_t> ColorBufferGl::getContents() {
1118     // Assume there is a current context.
1119     size_t bytes;
1120     readContents(&bytes, nullptr);
1121     std::vector<uint8_t> contents(bytes);
1122     readContents(&bytes, contents.data());
1123     return contents;
1124 }
1125 
clearStorage()1126 void ColorBufferGl::clearStorage() {
1127     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)NULL);
1128     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
1129     m_eglImage = (EGLImageKHR)0;
1130 }
1131 
restoreEglImage(EGLImageKHR image)1132 void ColorBufferGl::restoreEglImage(EGLImageKHR image) {
1133     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
1134 
1135     m_eglImage = image;
1136     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)m_eglImage);
1137 }
1138 
rebindEglImage(EGLImageKHR image,bool preserveContent)1139 void ColorBufferGl::rebindEglImage(EGLImageKHR image, bool preserveContent) {
1140     RecursiveScopedContextBind context(m_helper);
1141 
1142     std::vector<uint8_t> contents;
1143     if (preserveContent) {
1144         contents = getContents();
1145     }
1146     clearStorage();
1147     restoreEglImage(image);
1148 
1149     if (preserveContent) {
1150         replaceContents(contents.data(), m_numBytes);
1151     }
1152 }
1153 
getBorrowedImageInfo()1154 std::unique_ptr<BorrowedImageInfo> ColorBufferGl::getBorrowedImageInfo() {
1155     auto info = std::make_unique<BorrowedImageInfoGl>();
1156     info->id = mHndl;
1157     info->width = m_width;
1158     info->height = m_height;
1159     info->texture = m_tex;
1160     info->onCommandsIssued = [this]() { setSync(); };
1161     return info;
1162 }
1163 
1164 }  // namespace gl
1165 }  // namespace gfxstream
1166