Flutter Engine
The Flutter Engine
AHardwareBufferGL.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
10#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
11#define GL_GLEXT_PROTOTYPES
12#define EGL_EGLEXT_PROTOTYPES
13
21
23#include <EGL/egl.h>
24#include <EGL/eglext.h>
25#include <GLES/gl.h>
26#include <GLES/glext.h>
27
28#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
29#define EGL_PROTECTED_CONTENT_EXT 0x32C0
30
31namespace GrAHardwareBufferUtils {
32
33GrBackendFormat GetGLBackendFormat(GrDirectContext* dContext,
34 uint32_t bufferFormat, bool requireKnownFormat) {
35 GrBackendApi backend = dContext->backend();
37 return GrBackendFormat();
38 }
39 switch (bufferFormat) {
40 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
41 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
42 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
44 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
46 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
48 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
50 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
52#if __ANDROID_API__ >= 33
53 case AHARDWAREBUFFER_FORMAT_R8_UNORM:
55#endif
56 default:
57 if (requireKnownFormat) {
58 return GrBackendFormat();
59 } else {
61 }
62 }
64}
65
66class GLTextureHelper {
67public:
68 GLTextureHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display, GrGLuint texTarget)
69 : fTexID(texID)
70 , fImage(image)
71 , fDisplay(display)
72 , fTexTarget(texTarget) { }
73 ~GLTextureHelper() {
74 glDeleteTextures(1, &fTexID);
75 // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
76 eglDestroyImageKHR(fDisplay, fImage);
77 }
78 void rebind(GrDirectContext*);
79
80private:
81 GrGLuint fTexID;
82 EGLImageKHR fImage;
83 EGLDisplay fDisplay;
84 GrGLuint fTexTarget;
85};
86
87void GLTextureHelper::rebind(GrDirectContext* dContext) {
88 glBindTexture(fTexTarget, fTexID);
89 GLenum status = GL_NO_ERROR;
90 if ((status = glGetError()) != GL_NO_ERROR) {
91 SkDebugf("glBindTexture(%#x, %d) failed (%#x)", (int) fTexTarget,
92 (int) fTexID, (int) status);
93 return;
94 }
95 glEGLImageTargetTexture2DOES(fTexTarget, fImage);
96 if ((status = glGetError()) != GL_NO_ERROR) {
97 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
98 return;
99 }
101}
102
103void delete_gl_texture(void* context) {
104 GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
105 delete cleanupHelper;
106}
107
108void update_gl_texture(void* context, GrDirectContext* dContext) {
109 GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
110 cleanupHelper->rebind(dContext);
111}
112
113static GrBackendTexture make_gl_backend_texture(
114 GrDirectContext* dContext,
115 AHardwareBuffer* hardwareBuffer,
116 int width, int height,
117 DeleteImageProc* deleteProc,
118 UpdateImageProc* updateProc,
119 TexImageCtx* imageCtx,
120 bool isProtectedContent,
121 const GrBackendFormat& backendFormat,
122 bool isRenderable) {
123 while (GL_NO_ERROR != glGetError()) {} //clear GL errors
124
125 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
126 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
127 isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
128 isProtectedContent ? EGL_TRUE : EGL_NONE,
129 EGL_NONE };
130 EGLDisplay display = eglGetCurrentDisplay();
131 // eglCreateImageKHR will add a ref to the AHardwareBuffer
132 EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
133 clientBuffer, attribs);
134 if (EGL_NO_IMAGE_KHR == image) {
135 SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
136 return GrBackendTexture();
137 }
138
139 GrGLuint texID;
140 glGenTextures(1, &texID);
141 if (!texID) {
142 eglDestroyImageKHR(display, image);
143 return GrBackendTexture();
144 }
145
147
148 glBindTexture(target, texID);
149 GLenum status = GL_NO_ERROR;
150 if ((status = glGetError()) != GL_NO_ERROR) {
151 SkDebugf("glBindTexture failed (%#x)", (int) status);
152 glDeleteTextures(1, &texID);
153 eglDestroyImageKHR(display, image);
154 return GrBackendTexture();
155 }
156 glEGLImageTargetTexture2DOES(target, image);
157 if ((status = glGetError()) != GL_NO_ERROR) {
158 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
159 glDeleteTextures(1, &texID);
160 eglDestroyImageKHR(display, image);
161 return GrBackendTexture();
162 }
164
165 GrGLTextureInfo textureInfo;
166 textureInfo.fID = texID;
167 SkASSERT(backendFormat.isValid());
168 textureInfo.fTarget = target;
169 textureInfo.fFormat = GrBackendFormats::AsGLFormatEnum(backendFormat);
170 textureInfo.fProtected = skgpu::Protected(isProtectedContent);
171
172 *deleteProc = delete_gl_texture;
173 *updateProc = update_gl_texture;
174 *imageCtx = new GLTextureHelper(texID, image, display, target);
175
177}
178
179static bool can_import_protected_content_eglimpl() {
180 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
181 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
182 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
183 size_t extsLen = strlen(exts);
184 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
185 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
186 bool atEnd = (cropExtLen+1) < extsLen
187 && !strcmp(" " PROT_CONTENT_EXT_STR,
188 exts + extsLen - (cropExtLen+1));
189 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
190 return equal || atStart || atEnd || inMiddle;
191}
192
193static bool can_import_protected_content(GrDirectContext* dContext) {
194 SkASSERT(GrBackendApi::kOpenGL == dContext->backend());
195 // Only compute whether the extension is present once the first time this
196 // function is called.
197 static bool hasIt = can_import_protected_content_eglimpl();
198 return hasIt;
199}
200
201GrBackendTexture MakeGLBackendTexture(GrDirectContext* dContext,
202 AHardwareBuffer* hardwareBuffer,
203 int width, int height,
204 DeleteImageProc* deleteProc,
205 UpdateImageProc* updateProc,
206 TexImageCtx* imageCtx,
207 bool isProtectedContent,
208 const GrBackendFormat& backendFormat,
209 bool isRenderable) {
210 SkASSERT(dContext);
211 if (!dContext || dContext->abandoned()) {
212 return GrBackendTexture();
213 }
214
215 if (GrBackendApi::kOpenGL != dContext->backend()) {
216 return GrBackendTexture();
217 }
218
219 if (isProtectedContent && !can_import_protected_content(dContext)) {
220 return GrBackendTexture();
221 }
222
223 return make_gl_backend_texture(dContext, hardwareBuffer, width, height, deleteProc,
224 updateProc, imageCtx, isProtectedContent, backendFormat,
225 isRenderable);
226}
227
228} // namespace GrAHardwareBufferUtils
229
230#endif
const char * backend
#define EGL_PROTECTED_CONTENT_EXT
struct AHardwareBuffer AHardwareBuffer
#define GR_GL_RGB8
Definition: GrGLDefines.h:509
#define GR_GL_RGB10_A2
Definition: GrGLDefines.h:525
#define GR_GL_RGBA8
Definition: GrGLDefines.h:524
#define GR_GL_R8
Definition: GrGLDefines.h:459
#define GR_GL_TEXTURE_2D
Definition: GrGLDefines.h:152
#define GR_GL_RGBA16F
Definition: GrGLDefines.h:527
#define GR_GL_RGB565
Definition: GrGLDefines.h:508
#define GR_GL_TEXTURE_EXTERNAL
Definition: GrGLDefines.h:1052
unsigned int GrGLuint
Definition: GrGLTypes.h:113
GrBackendApi
Definition: GrTypes.h:95
@ kTextureBinding_GrGLBackendState
Definition: GrTypes.h:159
static bool equal(const SkBitmap &a, const SkBitmap &b)
Definition: ImageTest.cpp:1395
#define SkUNREACHABLE
Definition: SkAssert.h:135
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
bool isValid() const
SK_API GrBackendApi backend() const
void resetContext(uint32_t state=kAll_GrBackendState)
bool abandoned() override
uint32_t * target
SK_API GrGLenum AsGLFormatEnum(const GrBackendFormat &)
SK_API GrBackendFormat MakeGL(GrGLenum format, GrGLenum target)
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
sk_sp< const SkImage > image
Definition: SkRecords.h:269
Protected
Definition: GpuTypes.h:61
int32_t height
int32_t width
skgpu::Protected fProtected
Definition: GrGLTypes.h:184
GrGLuint fID
Definition: GrGLTypes.h:182
GrGLenum fFormat
Definition: GrGLTypes.h:183
GrGLenum fTarget
Definition: GrGLTypes.h:181