10#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
11#define GL_GLEXT_PROTOTYPES
12#define EGL_EGLEXT_PROTOTYPES
24#include <EGL/eglext.h>
26#include <GLES/glext.h>
28#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
29#define EGL_PROTECTED_CONTENT_EXT 0x32C0
31namespace GrAHardwareBufferUtils {
34 uint32_t bufferFormat,
bool requireKnownFormat) {
39 switch (bufferFormat) {
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:
57 if (requireKnownFormat) {
66class GLTextureHelper {
72 , fTexTarget(texTarget) { }
74 glDeleteTextures(1, &fTexID);
76 eglDestroyImageKHR(fDisplay, fImage);
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);
95 glEGLImageTargetTexture2DOES(fTexTarget, fImage);
96 if ((status = glGetError()) != GL_NO_ERROR) {
97 SkDebugf(
"glEGLImageTargetTexture2DOES failed (%#x)", (
int) status);
103void delete_gl_texture(
void* context) {
104 GLTextureHelper* cleanupHelper =
static_cast<GLTextureHelper*
>(context);
105 delete cleanupHelper;
109 GLTextureHelper* cleanupHelper =
static_cast<GLTextureHelper*
>(context);
110 cleanupHelper->rebind(dContext);
117 DeleteImageProc* deleteProc,
118 UpdateImageProc* updateProc,
119 TexImageCtx* imageCtx,
120 bool isProtectedContent,
123 while (GL_NO_ERROR != glGetError()) {}
125 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
126 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
128 isProtectedContent ? EGL_TRUE : EGL_NONE,
130 EGLDisplay display = eglGetCurrentDisplay();
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() );
140 glGenTextures(1, &texID);
142 eglDestroyImageKHR(display,
image);
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);
157 if ((status = glGetError()) != GL_NO_ERROR) {
158 SkDebugf(
"glEGLImageTargetTexture2DOES failed (%#x)", (
int) status);
159 glDeleteTextures(1, &texID);
160 eglDestroyImageKHR(display,
image);
166 textureInfo.
fID = texID;
172 *deleteProc = delete_gl_texture;
173 *updateProc = update_gl_texture;
174 *imageCtx =
new GLTextureHelper(texID,
image, display,
target);
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;
197 static bool hasIt = can_import_protected_content_eglimpl();
204 DeleteImageProc* deleteProc,
205 UpdateImageProc* updateProc,
206 TexImageCtx* imageCtx,
207 bool isProtectedContent,
211 if (!dContext || dContext->
abandoned()) {
219 if (isProtectedContent && !can_import_protected_content(dContext)) {
223 return make_gl_backend_texture(dContext, hardwareBuffer,
width,
height, deleteProc,
224 updateProc, imageCtx, isProtectedContent, backendFormat,
#define EGL_PROTECTED_CONTENT_EXT
struct AHardwareBuffer AHardwareBuffer
#define GR_GL_TEXTURE_EXTERNAL
@ kTextureBinding_GrGLBackendState
static bool equal(const SkBitmap &a, const SkBitmap &b)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SK_API GrBackendApi backend() const
void resetContext(uint32_t state=kAll_GrBackendState)
bool abandoned() override
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
sk_sp< const SkImage > image
skgpu::Protected fProtected