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