• 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 "ColorBuffer.h"
17 
18 #include "DispatchTables.h"
19 #include "glestranslator/include/GLcommon/GLutils.h"
20 #include "RenderThreadInfo.h"
21 #include "TextureDraw.h"
22 #include "TextureResize.h"
23 #include "YUVConverter.h"
24 #include "vulkan/VulkanDispatch.h"
25 #include "vulkan/VkCommonOperations.h"
26 
27 #include "OpenGLESDispatch/DispatchTables.h"
28 #include "OpenGLESDispatch/EGLDispatch.h"
29 
30 #include "host-common/misc.h"
31 
32 #include <GLES2/gl2ext.h>
33 
34 #include <stdio.h>
35 #include <string.h>
36 
37 #define DEBUG_CB_FBO 0
38 
39 namespace {
40 
41 // Lazily create and bind a framebuffer object to the current host context.
42 // |fbo| is the address of the framebuffer object name.
43 // |tex| is the name of a texture that is attached to the framebuffer object
44 // on creation only. I.e. all rendering operations will target it.
45 // returns true in case of success, false on failure.
bindFbo(GLuint * fbo,GLuint tex)46 bool bindFbo(GLuint* fbo, GLuint tex) {
47     if (*fbo) {
48         // fbo already exist - just bind
49         s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
50         return true;
51     }
52 
53     s_gles2.glGenFramebuffers(1, fbo);
54     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
55     s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES,
56                                    GL_TEXTURE_2D, tex, 0);
57 #if DEBUG_CB_FBO
58     GLenum status = s_gles2.glCheckFramebufferStatus(GL_FRAMEBUFFER);
59     if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
60         ERR("ColorBuffer::bindFbo: FBO not complete: %#x\n", status);
61         s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
62         s_gles2.glDeleteFramebuffers(1, fbo);
63         *fbo = 0;
64         return false;
65     }
66 #endif
67 
68     return true;
69 }
70 
unbindFbo()71 void unbindFbo() {
72     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
73 }
74 
75 }
76 
77 ColorBuffer::Helper::~Helper() = default;
78 
sGetUnsizedColorBufferFormat(GLenum format)79 static GLenum sGetUnsizedColorBufferFormat(GLenum format) {
80     switch (format) {
81         case GL_R8:
82             return GL_RED;
83         case GL_RG8:
84             return GL_RG;
85         case GL_RGB8:
86         case GL_RGB565:
87         case GL_RGB16F:
88             return GL_RGB;
89         case GL_RGBA8:
90         case GL_RGB5_A1_OES:
91         case GL_RGBA4_OES:
92         case GL_UNSIGNED_INT_10_10_10_2_OES:
93         case GL_RGB10_A2:
94         case GL_RGBA16F:
95             return GL_RGBA;
96         case GL_BGRA8_EXT:
97         case GL_BGR10_A2_ANGLEX:
98             return GL_BGRA_EXT;
99         default: // already unsized
100             return format;
101     }
102 }
103 
sGetFormatParameters(GLint * internalFormat,GLenum * texFormat,GLenum * pixelType,int * bytesPerPixel,GLint * sizedInternalFormat,bool * isBlob)104 static bool sGetFormatParameters(GLint* internalFormat,
105                                  GLenum* texFormat,
106                                  GLenum* pixelType,
107                                  int* bytesPerPixel,
108                                  GLint* sizedInternalFormat,
109                                  bool* isBlob) {
110     if (!internalFormat) {
111         fprintf(stderr, "%s: error: internal format not provided\n", __func__);
112         return false;
113     }
114 
115     *isBlob = false;
116 
117     switch (*internalFormat) {
118         case GL_RGB:
119         case GL_RGB8:
120             *texFormat = GL_RGB;
121             *pixelType = GL_UNSIGNED_BYTE;
122             *bytesPerPixel = 3;
123             *sizedInternalFormat = GL_RGB8;
124             return true;
125         case GL_RGB565_OES:
126             *texFormat = GL_RGB;
127             *pixelType = GL_UNSIGNED_SHORT_5_6_5;
128             *bytesPerPixel = 2;
129             *sizedInternalFormat = GL_RGB565;
130             return true;
131         case GL_RGBA:
132         case GL_RGBA8:
133         case GL_RGB5_A1_OES:
134         case GL_RGBA4_OES:
135             *texFormat = GL_RGBA;
136             *pixelType = GL_UNSIGNED_BYTE;
137             *bytesPerPixel = 4;
138             *sizedInternalFormat = GL_RGBA8;
139             return true;
140         case GL_UNSIGNED_INT_10_10_10_2_OES:
141             *texFormat = GL_RGBA;
142             *pixelType = GL_UNSIGNED_SHORT;
143             *bytesPerPixel = 4;
144             *sizedInternalFormat = GL_UNSIGNED_INT_10_10_10_2_OES;
145             return true;
146         case GL_RGB10_A2:
147             *texFormat = GL_RGBA;
148             *pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
149             *bytesPerPixel = 4;
150             *sizedInternalFormat = GL_RGB10_A2;
151             return true;
152         case GL_RGB16F:
153             *texFormat = GL_RGB;
154             *pixelType = GL_HALF_FLOAT;
155             *bytesPerPixel = 6;
156             *sizedInternalFormat = GL_RGB16F;
157             return true;
158         case GL_RGBA16F:
159             *texFormat = GL_RGBA;
160             *pixelType = GL_HALF_FLOAT;
161             *bytesPerPixel = 8;
162             *sizedInternalFormat = GL_RGBA16F;
163             return true;
164         case GL_LUMINANCE:
165             *texFormat = GL_LUMINANCE;
166             *pixelType = GL_UNSIGNED_SHORT;
167             *bytesPerPixel = 2;
168             *sizedInternalFormat = GL_R8;
169             *isBlob = true;
170             return true;
171         case GL_BGRA_EXT:
172             *texFormat = GL_BGRA_EXT;
173             *pixelType = GL_UNSIGNED_BYTE;
174             *bytesPerPixel = 4;
175             *sizedInternalFormat = GL_BGRA8_EXT;
176             return true;
177         case GL_BGR10_A2_ANGLEX:
178             *texFormat = GL_RGBA;
179             *pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
180             *bytesPerPixel = 4;
181             *internalFormat = GL_RGB10_A2_EXT;
182             // GL_BGR10_A2_ANGLEX is actually not a valid GL format. We should
183             // replace it with a normal GL internal format instead.
184             *sizedInternalFormat = GL_BGR10_A2_ANGLEX;
185             return true;
186         case GL_R8:
187         case GL_RED:
188             *texFormat = GL_RED;
189             *pixelType = GL_UNSIGNED_BYTE;
190             *bytesPerPixel = 1;
191             *sizedInternalFormat = GL_R8;
192             return true;
193         case GL_RG8:
194         case GL_RG:
195             *texFormat = GL_RG;
196             *pixelType = GL_UNSIGNED_BYTE;
197             *bytesPerPixel = 2;
198             *sizedInternalFormat = GL_RG8;
199             return true;
200         default:
201             fprintf(stderr, "%s: Unknown format 0x%x\n", __func__,
202                     *internalFormat);
203             return false;
204     }
205 }
206 
207 // static
create(EGLDisplay p_display,int p_width,int p_height,GLint p_internalFormat,FrameworkFormat p_frameworkFormat,HandleType hndl,Helper * helper,bool fastBlitSupported)208 ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
209                                  int p_width,
210                                  int p_height,
211                                  GLint p_internalFormat,
212                                  FrameworkFormat p_frameworkFormat,
213                                  HandleType hndl,
214                                  Helper* helper,
215                                  bool fastBlitSupported) {
216     GLenum texFormat = 0;
217     GLenum pixelType = GL_UNSIGNED_BYTE;
218     int bytesPerPixel = 4;
219     GLint p_sizedInternalFormat = GL_RGBA8;
220     bool isBlob = false;;
221 
222     if (!sGetFormatParameters(&p_internalFormat, &texFormat, &pixelType,
223                               &bytesPerPixel, &p_sizedInternalFormat,
224                               &isBlob)) {
225         fprintf(stderr, "ColorBuffer::create invalid format 0x%x\n",
226                 p_internalFormat);
227         return NULL;
228     }
229 
230     const unsigned long bufsize = ((unsigned long)bytesPerPixel) * p_width
231             * p_height;
232 
233     RecursiveScopedHelperContext context(helper);
234     if (!context.isOk()) {
235         return NULL;
236     }
237 
238     ColorBuffer* cb = new ColorBuffer(p_display, hndl, helper);
239 
240     GLint prevUnpackAlignment;
241     s_gles2.glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlignment);
242     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
243 
244     s_gles2.glGenTextures(1, &cb->m_tex);
245     s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_tex);
246 
247     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, p_internalFormat, p_width, p_height,
248                          0, texFormat, pixelType, nullptr);
249 
250     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
251     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
252     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
253     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
254     // Swizzle B/R channel for BGR10_A2 images.
255     if (p_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
256         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
257         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
258         cb->m_BRSwizzle = true;
259     }
260 
261     //
262     // create another texture for that colorbuffer for blit
263     //
264     s_gles2.glGenTextures(1, &cb->m_blitTex);
265     s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
266     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, p_internalFormat, p_width, p_height,
267                          0, texFormat, pixelType, NULL);
268 
269     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
270     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
271     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
272     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
273     // Swizzle B/R channel for BGR10_A2 images.
274     if (p_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
275         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
276         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
277         cb->m_BRSwizzle = true;
278     }
279 
280     cb->m_width = p_width;
281     cb->m_height = p_height;
282     cb->m_internalFormat = p_internalFormat;
283     cb->m_sizedInternalFormat = p_sizedInternalFormat;
284     cb->m_format = texFormat;
285     cb->m_type = pixelType;
286 
287     cb->m_eglImage = s_egl.eglCreateImageKHR(
288             p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
289             (EGLClientBuffer)SafePointerFromUInt(cb->m_tex), NULL);
290 
291     cb->m_blitEGLImage = s_egl.eglCreateImageKHR(
292             p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
293             (EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex), NULL);
294 
295     cb->m_resizer = new TextureResize(p_width, p_height);
296 
297     cb->m_frameworkFormat = p_frameworkFormat;
298     switch (cb->m_frameworkFormat) {
299         case FRAMEWORK_FORMAT_GL_COMPATIBLE:
300             break;
301         default: // Any YUV format
302             cb->m_yuv_converter.reset(
303                     new YUVConverter(p_width, p_height, cb->m_frameworkFormat));
304             break;
305     }
306 
307     cb->m_fastBlitSupported = fastBlitSupported;
308 
309     // desktop GL only: use GL_UNSIGNED_INT_8_8_8_8_REV for faster readback.
310     if (emugl::getRenderer() == SELECTED_RENDERER_HOST) {
311 #define GL_UNSIGNED_INT_8_8_8_8           0x8035
312 #define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367
313         cb->m_asyncReadbackType = GL_UNSIGNED_INT_8_8_8_8_REV;
314     }
315 
316     cb->m_numBytes = (size_t)bufsize;
317 
318     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlignment);
319 
320     s_gles2.glFinish();
321     return cb;
322 }
323 
ColorBuffer(EGLDisplay display,HandleType hndl,Helper * helper)324 ColorBuffer::ColorBuffer(EGLDisplay display, HandleType hndl, Helper* helper)
325     : m_display(display), m_helper(helper), mHndl(hndl) {}
326 
~ColorBuffer()327 ColorBuffer::~ColorBuffer() {
328     RecursiveScopedHelperContext context(m_helper);
329 
330     if (m_blitEGLImage) {
331         s_egl.eglDestroyImageKHR(m_display, m_blitEGLImage);
332     }
333     if (m_eglImage) {
334         s_egl.eglDestroyImageKHR(m_display, m_eglImage);
335     }
336 
337     if (m_fbo) {
338         s_gles2.glDeleteFramebuffers(1, &m_fbo);
339     }
340 
341     if (m_yuv_conversion_fbo) {
342         s_gles2.glDeleteFramebuffers(1, &m_yuv_conversion_fbo);
343     }
344 
345     if (m_scaleRotationFbo) {
346         s_gles2.glDeleteFramebuffers(1, &m_scaleRotationFbo);
347     }
348 
349     m_yuv_converter.reset();
350 
351     GLuint tex[2] = {m_tex, m_blitTex};
352     s_gles2.glDeleteTextures(2, tex);
353 
354     if (m_memoryObject) {
355         s_gles2.glDeleteMemoryObjectsEXT(1, &m_memoryObject);
356     }
357 
358     delete m_resizer;
359 }
360 
readPixels(int x,int y,int width,int height,GLenum p_format,GLenum p_type,void * pixels)361 void ColorBuffer::readPixels(int x,
362                              int y,
363                              int width,
364                              int height,
365                              GLenum p_format,
366                              GLenum p_type,
367                              void* pixels) {
368     RecursiveScopedHelperContext context(m_helper);
369     if (!context.isOk()) {
370         return;
371     }
372     p_format = sGetUnsizedColorBufferFormat(p_format);
373     touch();
374 
375     if (bindFbo(&m_fbo, m_tex)) {
376         GLint prevAlignment = 0;
377         s_gles2.glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);
378         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, 1);
379         s_gles2.glReadPixels(x, y, width, height, p_format, p_type, pixels);
380         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);
381         unbindFbo();
382     }
383 }
384 
readPixelsScaled(int width,int height,GLenum p_format,GLenum p_type,int rotation,void * pixels)385 void ColorBuffer::readPixelsScaled(int width,
386                                    int height,
387                                    GLenum p_format,
388                                    GLenum p_type,
389                                    int rotation,
390                                    void* pixels) {
391     RecursiveScopedHelperContext context(m_helper);
392     if (!context.isOk()) {
393         return;
394     }
395     p_format = sGetUnsizedColorBufferFormat(p_format);
396     touch();
397     GLuint tex = m_resizer->update(m_tex, width, height, rotation);
398     if (bindFbo(&m_scaleRotationFbo, tex)) {
399         GLint prevAlignment = 0;
400         s_gles2.glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);
401         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, 1);
402         s_gles2.glReadPixels(0, 0, width, height, p_format, p_type, pixels);
403         s_gles2.glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);
404         unbindFbo();
405     }
406 }
407 
readPixelsYUVCached(int x,int y,int width,int height,void * pixels,uint32_t pixels_size)408 void ColorBuffer::readPixelsYUVCached(int x,
409                                       int y,
410                                       int width,
411                                       int height,
412                                       void* pixels,
413                                       uint32_t pixels_size) {
414     RecursiveScopedHelperContext context(m_helper);
415     if (!context.isOk()) {
416         return;
417     }
418 
419     touch();
420 
421 #if DEBUG_CB_FBO
422     fprintf(stderr, "%s %d request width %d height %d\n", __func__, __LINE__,
423             width, height);
424     memset(pixels, 0x00, pixels_size);
425     assert(m_yuv_converter.get());
426 #endif
427 
428     m_yuv_converter->readPixels((uint8_t*)pixels, pixels_size);
429 
430     return;
431 }
432 
reformat(GLint internalformat,GLenum type)433 void ColorBuffer::reformat(GLint internalformat, GLenum type) {
434     GLenum texFormat = internalformat;
435     GLenum pixelType = GL_UNSIGNED_BYTE;
436     GLint sizedInternalFormat = GL_RGBA8;
437     int bpp = 4;
438     bool isBlob = false;
439     if (!sGetFormatParameters(&internalformat, &texFormat, &pixelType, &bpp,
440                               &sizedInternalFormat, &isBlob)) {
441         fprintf(stderr, "%s: WARNING: reformat failed. internal format: 0x%x\n",
442                 __func__, internalformat);
443     }
444 
445     // BUG: 143607546
446     //
447     // During reformatting, sGetFormatParameters can be too
448     // opinionated and override the guest's intended choice for the
449     // pixel type.  If the guest wanted GL_UNSIGNED_SHORT_5_6_5 as
450     // the pixel type, and the incoming internal format is not
451     // explicitly sized, sGetFormatParameters will pick a default of
452     // GL_UNSIGNED BYTE, which goes against guest expectations.
453     //
454     // This happens only on older API levels where gralloc.cpp in
455     // goldfish-opengl communicated HAL_PIXEL_FORMAT_RGB_565 as GL
456     // format GL_RGB, pixel type GL_UNSIGNED_SHORT_5_6_5.  Newer
457     // system images communicate HAL_PIXEL_FORMAT_RGB_565 as GL
458     // format GL_RGB565, which allows sGetFormatParameters to work
459     // correctly.
460     if (pixelType != type) {
461         pixelType = type;
462     }
463 
464     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
465     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, m_height,
466                          0, texFormat, pixelType, nullptr);
467 
468     s_gles2.glBindTexture(GL_TEXTURE_2D, m_blitTex);
469     s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, m_height,
470                          0, texFormat, pixelType, nullptr);
471 
472     // EGL images need to be recreated because the EGL_KHR_image_base spec
473     // states that respecifying an image (i.e. glTexImage2D) will generally
474     // result in orphaning of the EGL image.
475     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
476     m_eglImage = s_egl.eglCreateImageKHR(
477             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
478             (EGLClientBuffer)SafePointerFromUInt(m_tex), NULL);
479 
480     s_egl.eglDestroyImageKHR(m_display, m_blitEGLImage);
481     m_blitEGLImage = s_egl.eglCreateImageKHR(
482             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
483             (EGLClientBuffer)SafePointerFromUInt(m_blitTex), NULL);
484 
485     s_gles2.glBindTexture(GL_TEXTURE_2D, 0);
486 
487     m_internalFormat = internalformat;
488     m_format = texFormat;
489     m_type = pixelType;
490     m_sizedInternalFormat = sizedInternalFormat;
491 
492     m_numBytes = bpp * m_width * m_height;
493 }
494 
swapYUVTextures(uint32_t type,uint32_t * textures)495 void ColorBuffer::swapYUVTextures(uint32_t type, uint32_t* textures) {
496     if (type == FRAMEWORK_FORMAT_NV12) {
497         m_yuv_converter->swapTextures(type, textures);
498     } else {
499         fprintf(stderr,
500                 "%s: ERROR: format other than NV12 is not supported: 0x%x\n",
501                 __func__, type);
502     }
503 }
504 
subUpdate(int x,int y,int width,int height,GLenum p_format,GLenum p_type,void * pixels)505 void ColorBuffer::subUpdate(int x,
506                             int y,
507                             int width,
508                             int height,
509                             GLenum p_format,
510                             GLenum p_type,
511                             void* pixels) {
512     const GLenum p_unsizedFormat = sGetUnsizedColorBufferFormat(p_format);
513     RecursiveScopedHelperContext context(m_helper);
514 
515     if (!context.isOk()) {
516         return;
517     }
518 
519     touch();
520 
521     if (m_needFormatCheck) {
522         if (p_type != m_type || p_format != m_format) {
523             reformat((GLint)p_format, p_type);
524         }
525         m_needFormatCheck = false;
526     }
527 
528     if (m_frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE) {
529         assert(m_yuv_converter.get());
530 
531         // This FBO will convert the YUV frame to RGB
532         // and render it to |m_tex|.
533         bindFbo(&m_yuv_conversion_fbo, m_tex);
534         m_yuv_converter->drawConvert(x, y, width, height, (char*)pixels);
535         unbindFbo();
536 
537         // |m_tex| still needs to be bound afterwards
538         s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
539 
540     } else {
541         s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
542         s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
543 
544         s_gles2.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, p_unsizedFormat,
545                                 p_type, pixels);
546     }
547 
548     if (m_fastBlitSupported) {
549         s_gles2.glFlush();
550         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
551     }
552 }
553 
replaceContents(const void * newContents,size_t numBytes)554 bool ColorBuffer::replaceContents(const void* newContents, size_t numBytes) {
555     RecursiveScopedHelperContext context(m_helper);
556     if (!context.isOk()) {
557         fprintf(stderr, "%s: Failed: Could not get current context\n", __func__);
558         return false;
559     }
560 
561     if (m_numBytes != numBytes) {
562         fprintf(stderr,
563             "%s: Error: Tried to replace contents of ColorBuffer with "
564             "%zu bytes (expected %zu; GL format info: 0x%x 0x%x 0x%x); ",
565             __func__,
566             numBytes,
567             m_numBytes,
568             m_internalFormat,
569             m_format,
570             m_type);
571         return false;
572     }
573 
574     touch();
575 
576     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
577     s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
578     s_gles2.glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, m_format,
579                             m_type, newContents);
580 
581     if (m_fastBlitSupported) {
582         s_gles2.glFlush();
583         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
584     }
585 
586     return true;
587 }
588 
readContents(size_t * numBytes,void * pixels)589 bool ColorBuffer::readContents(size_t* numBytes, void* pixels) {
590     if (m_yuv_converter) {
591         *numBytes = m_yuv_converter->getDataSize();
592         if (pixels) {
593             readPixelsYUVCached(0, 0, 0, 0, pixels, *numBytes);
594         }
595         return true;
596     } else {
597         RecursiveScopedHelperContext context(m_helper);
598         *numBytes = m_numBytes;
599 
600         if (!pixels) return true;
601 
602         readPixels(0, 0, m_width, m_height, m_format, m_type, pixels);
603 
604         return true;
605     }
606 }
607 
blitFromCurrentReadBuffer()608 bool ColorBuffer::blitFromCurrentReadBuffer() {
609     RenderThreadInfo* tInfo = RenderThreadInfo::get();
610     if (!tInfo->currContext.get()) {
611         // no Current context
612         return false;
613     }
614 
615     touch();
616 
617     if (m_fastBlitSupported) {
618         s_egl.eglBlitFromCurrentReadBufferANDROID(m_display, m_eglImage);
619         m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
620     } else {
621         // Copy the content of the current read surface into m_blitEGLImage.
622         // This is done by creating a temporary texture, bind it to the EGLImage
623         // then call glCopyTexSubImage2D().
624         GLuint tmpTex;
625         GLint currTexBind;
626         if (tInfo->currContext->clientVersion() > GLESApi_CM) {
627             s_gles2.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
628             s_gles2.glGenTextures(1, &tmpTex);
629             s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
630             s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
631 
632             const bool isGles3 = tInfo->currContext->clientVersion() > GLESApi_2;
633 
634             GLint prev_read_fbo = 0;
635             if (isGles3) {
636                 // Make sure that we unbind any existing GL_READ_FRAMEBUFFER
637                 // before calling glCopyTexSubImage2D, otherwise we may blit
638                 // from the guest's current read framebuffer instead of the EGL
639                 // read buffer.
640                 s_gles2.glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo);
641                 if (prev_read_fbo != 0) {
642                     s_gles2.glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
643                 }
644             } else {
645                 // On GLES 2, there are not separate read/draw framebuffers,
646                 // only GL_FRAMEBUFFER.  Per the EGL 1.4 spec section 3.9.3,
647                 // the draw surface must be bound to the calling thread's
648                 // current context, so GL_FRAMEBUFFER should be 0.  However, the
649                 // error case is not strongly defined and generating a new error
650                 // may break existing apps.
651                 //
652                 // Instead of the obviously wrong behavior of posting whatever
653                 // GL_FRAMEBUFFER is currently bound to, fix up the
654                 // GL_FRAMEBUFFER if it is non-zero.
655                 s_gles2.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_read_fbo);
656                 if (prev_read_fbo != 0) {
657                     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
658                 }
659             }
660 
661             // If the read buffer is multisampled, we need to resolve.
662             GLint samples;
663             s_gles2.glGetIntegerv(GL_SAMPLE_BUFFERS, &samples);
664             if (isGles3 && samples > 0) {
665                 s_gles2.glBindTexture(GL_TEXTURE_2D, 0);
666 
667                 GLuint resolve_fbo;
668                 GLint prev_draw_fbo;
669                 s_gles2.glGenFramebuffers(1, &resolve_fbo);
670                 s_gles2.glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo);
671 
672                 s_gles2.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
673                 s_gles2.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
674                         GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
675                         tmpTex, 0);
676                 s_gles2.glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width,
677                         m_height, GL_COLOR_BUFFER_BIT,
678                         GL_NEAREST);
679                 s_gles2.glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
680                         (GLuint)prev_draw_fbo);
681 
682                 s_gles2.glDeleteFramebuffers(1, &resolve_fbo);
683                 s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
684             } else {
685                 // If the buffer is not multisampled, perform a normal texture copy.
686                 s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
687                         m_height);
688             }
689 
690             if (prev_read_fbo != 0) {
691                 if (isGles3) {
692                     s_gles2.glBindFramebuffer(GL_READ_FRAMEBUFFER,
693                                               (GLuint)prev_read_fbo);
694                 } else {
695                     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER,
696                                               (GLuint)prev_read_fbo);
697                 }
698             }
699 
700             s_gles2.glDeleteTextures(1, &tmpTex);
701             s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind);
702 
703             // clear GL errors, because its possible that the fbo format does not
704             // match
705             // the format of the read buffer, in the case of OpenGL ES 3.1 and
706             // integer
707             // RGBA formats.
708             s_gles2.glGetError();
709             // This is currently for dEQP purposes only; if we actually want these
710             // integer FBO formats to actually serve to display something for human
711             // consumption,
712             // we need to change the egl image to be of the same format,
713             // or we get some really psychedelic patterns.
714         } else {
715             // Like in the GLES 2 path above, correct the case where
716             // GL_FRAMEBUFFER_OES is not bound to zero so that we don't blit
717             // from arbitrary framebuffers.
718             // Use GLES 2 because it internally has the same value as the GLES 1
719             // API and it doesn't require GL_OES_framebuffer_object.
720             GLint prev_fbo = 0;
721             s_gles2.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
722             if (prev_fbo != 0) {
723                 s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
724             }
725 
726             s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
727             s_gles1.glGenTextures(1, &tmpTex);
728             s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex);
729             s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
730             s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
731                     m_height);
732             s_gles1.glDeleteTextures(1, &tmpTex);
733             s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind);
734 
735             if (prev_fbo != 0) {
736                 s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)prev_fbo);
737             }
738         }
739 
740         RecursiveScopedHelperContext context(m_helper);
741         if (!context.isOk()) {
742             return false;
743         }
744 
745         if (!bindFbo(&m_fbo, m_tex)) {
746             return false;
747         }
748 
749         // Save current viewport and match it to the current colorbuffer size.
750         GLint vport[4] = {
751             0,
752         };
753         s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
754         s_gles2.glViewport(0, 0, m_width, m_height);
755 
756         // render m_blitTex
757         m_helper->getTextureDraw()->draw(m_blitTex, 0., 0, 0);
758 
759         // Restore previous viewport.
760         s_gles2.glViewport(vport[0], vport[1], vport[2], vport[3]);
761         unbindFbo();
762     }
763 
764     return true;
765 }
766 
bindToTexture()767 bool ColorBuffer::bindToTexture() {
768     if (!m_eglImage) {
769         return false;
770     }
771 
772     RenderThreadInfo* tInfo = RenderThreadInfo::get();
773     if (!tInfo->currContext.get()) {
774         return false;
775     }
776     touch();
777 
778     if (tInfo->currContext->clientVersion() > GLESApi_CM) {
779         s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
780     } else {
781         s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
782     }
783     return true;
784 }
785 
bindToTexture2()786 bool ColorBuffer::bindToTexture2() {
787     if (!m_eglImage) {
788         return false;
789     }
790 
791     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
792     return true;
793 }
794 
bindToRenderbuffer()795 bool ColorBuffer::bindToRenderbuffer() {
796     if (!m_eglImage) {
797         return false;
798     }
799     RenderThreadInfo* tInfo = RenderThreadInfo::get();
800     if (!tInfo->currContext.get()) {
801         return false;
802     }
803     touch();
804     if (tInfo->currContext->clientVersion() > GLESApi_CM) {
805         s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
806                                                        m_eglImage);
807     } else {
808         s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
809                                                        m_eglImage);
810     }
811     return true;
812 }
813 
scale()814 GLuint ColorBuffer::scale() {
815     return m_resizer->update(m_tex);
816 }
817 
setSync(bool debug)818 void ColorBuffer::setSync(bool debug) {
819     m_sync = (GLsync)s_egl.eglSetImageFenceANDROID(m_display, m_eglImage);
820     if (debug) fprintf(stderr, "%s: %u to %p\n", __func__, getHndl(), m_sync);
821 }
822 
waitSync(bool debug)823 void ColorBuffer::waitSync(bool debug) {
824     if (debug) fprintf(stderr, "%s: %u sync %p\n", __func__, getHndl(), m_sync);
825     if (m_sync) {
826         s_egl.eglWaitImageFenceANDROID(m_display, m_sync);
827     }
828 }
829 
post(GLuint tex,float rotation,float dx,float dy)830 bool ColorBuffer::post(GLuint tex, float rotation, float dx, float dy) {
831     // NOTE: Do not call m_helper->setupContext() here!
832     waitSync();
833     return m_helper->getTextureDraw()->draw(tex, rotation, dx, dy);
834 }
835 
postWithOverlay(GLuint tex,float rotation,float dx,float dy)836 bool ColorBuffer::postWithOverlay(GLuint tex, float rotation, float dx, float dy) {
837     // NOTE: Do not call m_helper->setupContext() here!
838     waitSync();
839     return m_helper->getTextureDraw()->drawWithOverlay(tex, rotation, dx, dy);
840 }
841 
readback(unsigned char * img,bool readbackBgra)842 void ColorBuffer::readback(unsigned char* img, bool readbackBgra) {
843     RecursiveScopedHelperContext context(m_helper);
844     if (!context.isOk()) {
845         return;
846     }
847     touch();
848     waitSync();
849 
850     if (bindFbo(&m_fbo, m_tex)) {
851         // Flip the readback format if RED/BLUE components are swizzled.
852         bool shouldReadbackBgra = m_BRSwizzle ? !readbackBgra : readbackBgra;
853         GLenum format = shouldReadbackBgra ? GL_BGRA_EXT : GL_RGBA;
854 
855         s_gles2.glReadPixels(0, 0, m_width, m_height, format, GL_UNSIGNED_BYTE, img);
856         unbindFbo();
857     }
858 }
859 
readbackAsync(GLuint buffer,bool readbackBgra)860 void ColorBuffer::readbackAsync(GLuint buffer, bool readbackBgra) {
861     RecursiveScopedHelperContext context(m_helper);
862     if (!context.isOk()) {
863         return;
864     }
865     touch();
866     waitSync();
867 
868     if (bindFbo(&m_fbo, m_tex)) {
869         s_gles2.glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
870         bool shouldReadbackBgra = m_BRSwizzle ? !readbackBgra : readbackBgra;
871         GLenum format = shouldReadbackBgra ? GL_BGRA_EXT : GL_RGBA;
872         s_gles2.glReadPixels(0, 0, m_width, m_height, format, m_asyncReadbackType, 0);
873         s_gles2.glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
874         unbindFbo();
875     }
876 }
877 
getHndl() const878 HandleType ColorBuffer::getHndl() const {
879     return mHndl;
880 }
881 
onSave(android::base::Stream * stream)882 void ColorBuffer::onSave(android::base::Stream* stream) {
883     stream->putBe32(getHndl());
884     stream->putBe32(static_cast<uint32_t>(m_width));
885     stream->putBe32(static_cast<uint32_t>(m_height));
886     stream->putBe32(static_cast<uint32_t>(m_internalFormat));
887     stream->putBe32(static_cast<uint32_t>(m_frameworkFormat));
888     // for debug
889     assert(m_eglImage && m_blitEGLImage);
890     stream->putBe32(reinterpret_cast<uintptr_t>(m_eglImage));
891     stream->putBe32(reinterpret_cast<uintptr_t>(m_blitEGLImage));
892     stream->putBe32(m_needFormatCheck);
893 }
894 
onLoad(android::base::Stream * stream,EGLDisplay p_display,Helper * helper,bool fastBlitSupported)895 ColorBuffer* ColorBuffer::onLoad(android::base::Stream* stream,
896                                  EGLDisplay p_display,
897                                  Helper* helper,
898                                  bool fastBlitSupported) {
899     HandleType hndl = static_cast<HandleType>(stream->getBe32());
900     GLuint width = static_cast<GLuint>(stream->getBe32());
901     GLuint height = static_cast<GLuint>(stream->getBe32());
902     GLenum internalFormat = static_cast<GLenum>(stream->getBe32());
903     FrameworkFormat frameworkFormat =
904             static_cast<FrameworkFormat>(stream->getBe32());
905     EGLImageKHR eglImage = reinterpret_cast<EGLImageKHR>(stream->getBe32());
906     EGLImageKHR blitEGLImage = reinterpret_cast<EGLImageKHR>(stream->getBe32());
907     uint32_t needFormatCheck = stream->getBe32();
908 
909     if (!eglImage) {
910         return create(p_display, width, height, internalFormat, frameworkFormat,
911                       hndl, helper, fastBlitSupported);
912     }
913     ColorBuffer* cb = new ColorBuffer(p_display, hndl, helper);
914     cb->mNeedRestore = true;
915     cb->m_eglImage = eglImage;
916     cb->m_blitEGLImage = blitEGLImage;
917     assert(eglImage && blitEGLImage);
918     cb->m_width = width;
919     cb->m_height = height;
920     cb->m_internalFormat = internalFormat;
921     cb->m_frameworkFormat = frameworkFormat;
922     cb->m_fastBlitSupported = fastBlitSupported;
923     cb->m_needFormatCheck = needFormatCheck;
924     return cb;
925 }
926 
restore()927 void ColorBuffer::restore() {
928     RecursiveScopedHelperContext context(m_helper);
929     s_gles2.glGenTextures(1, &m_tex);
930     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
931     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
932 
933     s_gles2.glGenTextures(1, &m_blitTex);
934     s_gles2.glBindTexture(GL_TEXTURE_2D, m_blitTex);
935     s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
936 
937     m_resizer = new TextureResize(m_width, m_height);
938     switch (m_frameworkFormat) {
939         case FRAMEWORK_FORMAT_GL_COMPATIBLE:
940             break;
941         case FRAMEWORK_FORMAT_YV12:
942         case FRAMEWORK_FORMAT_YUV_420_888:
943             m_yuv_converter.reset(
944                     new YUVConverter(m_width, m_height, m_frameworkFormat));
945             break;
946         default:
947             break;
948     }
949 }
950 
951 
getTexture()952 GLuint ColorBuffer::getTexture() {
953     touch();
954     return m_tex;
955 }
956 
postLayer(ComposeLayer * l,int frameWidth,int frameHeight)957 void ColorBuffer::postLayer(ComposeLayer* l, int frameWidth, int frameHeight) {
958     if (m_inUse) fprintf(stderr, "%s: cb in use\n", __func__);
959     waitSync();
960     m_helper->getTextureDraw()->drawLayer(l, frameWidth, frameHeight, m_width, m_height, m_tex);
961 }
962 
importMemory(void * handle,uint64_t size,bool dedicated,bool linearTiling,bool vulkanOnly,std::shared_ptr<DisplayVk::DisplayBufferInfo> displayBufferVk)963 bool ColorBuffer::importMemory(
964 #ifdef _WIN32
965     void* handle,
966 #else
967     int handle,
968 #endif
969     uint64_t size, bool dedicated, bool linearTiling, bool vulkanOnly,
970     std::shared_ptr<DisplayVk::DisplayBufferInfo> displayBufferVk) {
971     RecursiveScopedHelperContext context(m_helper);
972     m_displayBufferVk = std::move(displayBufferVk);
973     s_gles2.glCreateMemoryObjectsEXT(1, &m_memoryObject);
974     if (dedicated) {
975         static const GLint DEDICATED_FLAG = GL_TRUE;
976         s_gles2.glMemoryObjectParameterivEXT(m_memoryObject,
977                                              GL_DEDICATED_MEMORY_OBJECT_EXT,
978                                              &DEDICATED_FLAG);
979     }
980 
981 #ifdef _WIN32
982     s_gles2.glImportMemoryWin32HandleEXT(m_memoryObject, size, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, handle);
983 #else
984     s_gles2.glImportMemoryFdEXT(m_memoryObject, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, handle);
985 #endif
986 
987     GLuint glTiling = linearTiling ? GL_LINEAR_TILING_EXT : GL_OPTIMAL_TILING_EXT;
988 
989     std::vector<uint8_t> prevContents;
990 
991     if (!vulkanOnly) {
992         size_t bytes;
993         readContents(&bytes, nullptr);
994         prevContents.resize(bytes, 0);
995         readContents(&bytes, prevContents.data());
996     }
997 
998     s_gles2.glDeleteTextures(1, &m_tex);
999     s_gles2.glGenTextures(1, &m_tex);
1000     s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
1001 
1002     // HOST needed because we do not expose this to guest
1003     s_gles2.glTexParameteriHOST(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, glTiling);
1004 
1005     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1006     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1007     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1008     s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1009 
1010     if (m_sizedInternalFormat == GL_BGRA8_EXT ||
1011         m_sizedInternalFormat == GL_BGR10_A2_ANGLEX) {
1012         GLint internalFormat = m_sizedInternalFormat == GL_BGRA8_EXT
1013                                        ? GL_RGBA8
1014                                        : GL_RGB10_A2_EXT;
1015         s_gles2.glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, internalFormat, m_width,
1016                                      m_height, m_memoryObject, 0);
1017         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
1018         s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
1019         m_BRSwizzle = true;
1020     } else {
1021         s_gles2.glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, m_sizedInternalFormat, m_width, m_height, m_memoryObject, 0);
1022         m_BRSwizzle = false;
1023     }
1024 
1025     s_egl.eglDestroyImageKHR(m_display, m_eglImage);
1026     m_eglImage = s_egl.eglCreateImageKHR(
1027             m_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
1028             (EGLClientBuffer)SafePointerFromUInt(m_tex), NULL);
1029 
1030     if (!vulkanOnly) {
1031         replaceContents(prevContents.data(), m_numBytes);
1032     }
1033 
1034     return true;
1035 }
1036 
setInUse(bool inUse)1037 void ColorBuffer::setInUse(bool inUse) {
1038     m_inUse = inUse;
1039 }
1040