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