Allow to rebind GL texture if AHB content has changed
Add an output function argument updateProc to MakeBackendTexture.
updateProc needs to be invoked, when AHB buffer content has
changed. OES_EGL_image_external spec requires to bind the
texture, when buffer content has changed.
glEGLImageTargetTexture2DOES is invoked too (spec is not clear,
but MTK devices require it).
Test: Built and ran android
Bug: b/138674291
Change-Id: If7cf3051bc513c037440ab3331e0a0fdfcba5c2b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231482
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrAHardwareBufferUtils.cpp b/src/gpu/GrAHardwareBufferUtils.cpp
index 294f999..67d3459 100644
--- a/src/gpu/GrAHardwareBufferUtils.cpp
+++ b/src/gpu/GrAHardwareBufferUtils.cpp
@@ -157,33 +157,59 @@
return GrBackendFormat();
}
-class GLCleanupHelper {
+class GLTextureHelper {
public:
- GLCleanupHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display)
+ GLTextureHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display, GrGLuint texTarget)
: fTexID(texID)
, fImage(image)
- , fDisplay(display) { }
- ~GLCleanupHelper() {
+ , fDisplay(display)
+ , fTexTarget(texTarget) { }
+ ~GLTextureHelper() {
glDeleteTextures(1, &fTexID);
// eglDestroyImageKHR will remove a ref from the AHardwareBuffer
eglDestroyImageKHR(fDisplay, fImage);
}
+ void rebind(GrContext* grContext);
+
private:
GrGLuint fTexID;
EGLImageKHR fImage;
EGLDisplay fDisplay;
+ GrGLuint fTexTarget;
};
+void GLTextureHelper::rebind(GrContext* grContext) {
+ glBindTexture(fTexTarget, fTexID);
+ GLenum status = GL_NO_ERROR;
+ if ((status = glGetError()) != GL_NO_ERROR) {
+ SkDebugf("glBindTexture(%#x, %d) failed (%#x)", (int) fTexTarget,
+ (int) fTexID, (int) status);
+ return;
+ }
+ glEGLImageTargetTexture2DOES(fTexTarget, fImage);
+ if ((status = glGetError()) != GL_NO_ERROR) {
+ SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
+ return;
+ }
+ grContext->resetContext(kTextureBinding_GrGLBackendState);
+}
+
void delete_gl_texture(void* context) {
- GLCleanupHelper* cleanupHelper = static_cast<GLCleanupHelper*>(context);
+ GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
delete cleanupHelper;
}
+void update_gl_texture(void* context, GrContext* grContext) {
+ GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
+ cleanupHelper->rebind(grContext);
+}
+
static GrBackendTexture make_gl_backend_texture(
GrContext* context, AHardwareBuffer* hardwareBuffer,
int width, int height,
DeleteImageProc* deleteProc,
- DeleteImageCtx* deleteCtx,
+ UpdateImageProc* updateProc,
+ TexImageCtx* imageCtx,
bool isProtectedContent,
const GrBackendFormat& backendFormat,
bool isRenderable) {
@@ -236,7 +262,8 @@
textureInfo.fFormat = *backendFormat.getGLFormat();
*deleteProc = delete_gl_texture;
- *deleteCtx = new GLCleanupHelper(texID, image, display);
+ *updateProc = update_gl_texture;
+ *imageCtx = new GLTextureHelper(texID, image, display, target);
return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo);
}
@@ -267,11 +294,16 @@
delete cleanupHelper;
}
+void update_vk_image(void* context, GrContext* grContext) {
+ // no op
+}
+
static GrBackendTexture make_vk_backend_texture(
GrContext* context, AHardwareBuffer* hardwareBuffer,
int width, int height,
DeleteImageProc* deleteProc,
- DeleteImageCtx* deleteCtx,
+ UpdateImageProc* updateProc,
+ TexImageCtx* imageCtx,
bool isProtectedContent,
const GrBackendFormat& backendFormat,
bool isRenderable) {
@@ -456,7 +488,8 @@
imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
*deleteProc = delete_vk_image;
- *deleteCtx = new VulkanCleanupHelper(gpu, image, memory);
+ *updateProc = update_vk_image;
+ *imageCtx = new VulkanCleanupHelper(gpu, image, memory);
return GrBackendTexture(width, height, imageInfo);
}
@@ -489,7 +522,8 @@
GrBackendTexture MakeBackendTexture(GrContext* context, AHardwareBuffer* hardwareBuffer,
int width, int height,
DeleteImageProc* deleteProc,
- DeleteImageCtx* deleteCtx,
+ UpdateImageProc* updateProc,
+ TexImageCtx* imageCtx,
bool isProtectedContent,
const GrBackendFormat& backendFormat,
bool isRenderable) {
@@ -500,7 +534,7 @@
if (GrBackendApi::kOpenGL == context->backend()) {
return make_gl_backend_texture(context, hardwareBuffer, width, height, deleteProc,
- deleteCtx, createProtectedImage, backendFormat,
+ updateProc, imageCtx, createProtectedImage, backendFormat,
isRenderable);
} else {
SkASSERT(GrBackendApi::kVulkan == context->backend());
@@ -508,7 +542,7 @@
// Currently we don't support protected images on vulkan
SkASSERT(!createProtectedImage);
return make_vk_backend_texture(context, hardwareBuffer, width, height, deleteProc,
- deleteCtx, createProtectedImage, backendFormat,
+ updateProc, imageCtx, createProtectedImage, backendFormat,
isRenderable);
#else
return GrBackendTexture();
@@ -516,6 +550,18 @@
}
}
+GrBackendTexture MakeBackendTexture(GrContext* context, AHardwareBuffer* hardwareBuffer,
+ int width, int height,
+ DeleteImageProc* deleteProc,
+ TexImageCtx* imageCtx,
+ bool isProtectedContent,
+ const GrBackendFormat& backendFormat,
+ bool isRenderable) {
+ UpdateImageProc updateProc;
+ return MakeBackendTexture(context, hardwareBuffer, width, height, deleteProc, &updateProc,
+ imageCtx, isProtectedContent, backendFormat, isRenderable);
+}
+
} // GrAHardwareBufferUtils
#endif