Index: ui/gl/gl_image_io_surface.mm |
diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm |
index 8a89afd579f1453d4f152d0b424494e9ecb825ff..e8d9592a74f115ab5411cab8db10a1bb967803e9 100644 |
--- a/ui/gl/gl_image_io_surface.mm |
+++ b/ui/gl/gl_image_io_surface.mm |
@@ -301,6 +301,23 @@ bool GLImageIOSurface::CopyTexImage(unsigned target) { |
return false; |
} |
+ GLint target_texture = 0; |
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); |
+ DCHECK(target_texture); |
+ |
+ // Manually re-set the state in the scoped closure runner, to avoid bugs |
+ // in using gfx::ScopedActiveTexture and gfx::ScopedTextureBinder together. |
+ // https://crbug.com/601729 |
+ GLint old_active_texture = -1; |
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &old_active_texture); |
+ GLint old_texture0_binding = -1; |
+ glActiveTexture(GL_TEXTURE0); |
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture0_binding); |
+ GLint old_texture1_binding = -1; |
+ glActiveTexture(GL_TEXTURE1); |
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture1_binding); |
+ glActiveTexture(old_active_texture); |
+ |
// Ensure that all textures bound to IOSurfaces be destroyed before the |
// function exits. If they are not destroyed they may cause deadlocks between |
// VTDecompressionSession at CGLContextDestroy. |
@@ -309,10 +326,17 @@ bool GLImageIOSurface::CopyTexImage(unsigned target) { |
glGenTextures(1, &y_texture); |
unsigned uv_texture = 0; |
glGenTextures(1, &uv_texture); |
- base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{ |
- glDeleteTextures(1, &y_texture); |
- glDeleteTextures(1, &uv_texture); |
- })); |
+ base::ScopedClosureRunner restore_bindings_and_destroy_resources( |
+ base::BindBlock(^{ |
+ glActiveTexture(GL_TEXTURE0); |
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, old_texture0_binding); |
+ glActiveTexture(GL_TEXTURE1); |
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, old_texture1_binding); |
+ glActiveTexture(old_active_texture); |
+ |
+ glDeleteTextures(1, &y_texture); |
+ glDeleteTextures(1, &uv_texture); |
+ })); |
if (!framebuffer_) { |
glGenFramebuffersEXT(1, &framebuffer_); |
@@ -342,19 +366,14 @@ bool GLImageIOSurface::CopyTexImage(unsigned target) { |
CGLContextObj cgl_context = |
static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); |
- GLint target_texture = 0; |
- glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); |
- DCHECK(target_texture); |
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size_.width(), |
size_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); |
CGLError cgl_error = kCGLNoError; |
- { |
DCHECK(io_surface_); |
- gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0); |
- gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB, |
- y_texture); |
+ glActiveTexture(GL_TEXTURE0); |
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, y_texture); |
cgl_error = CGLTexImageIOSurface2D( |
cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), |
size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); |
@@ -363,36 +382,33 @@ bool GLImageIOSurface::CopyTexImage(unsigned target) { |
<< cgl_error; |
return false; |
} |
- { |
- gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1); |
- gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB, |
- uv_texture); |
- cgl_error = CGLTexImageIOSurface2D( |
- cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, |
- size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); |
- if (cgl_error != kCGLNoError) { |
- LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " |
- << cgl_error; |
- return false; |
- } |
- |
- gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); |
- gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height()); |
- glViewport(0, 0, size_.width(), size_.height()); |
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
- GL_TEXTURE_RECTANGLE_ARB, target_texture, 0); |
- DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), |
- glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); |
- |
- gfx::ScopedUseProgram use_program(program_); |
- glUniform2f(size_location_, size_.width(), size_.height()); |
- |
- gfx::GLHelper::DrawQuad(vertex_buffer_); |
- // Detach the output texture from the fbo. |
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
- GL_TEXTURE_RECTANGLE_ARB, 0, 0); |
- } |
+ |
+ glActiveTexture(GL_TEXTURE1); |
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, uv_texture); |
+ cgl_error = CGLTexImageIOSurface2D( |
+ cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, |
+ size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); |
+ if (cgl_error != kCGLNoError) { |
+ LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " |
+ << cgl_error; |
+ return false; |
} |
+ |
+ gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); |
+ gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height()); |
+ glViewport(0, 0, size_.width(), size_.height()); |
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
+ GL_TEXTURE_RECTANGLE_ARB, target_texture, 0); |
+ DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), |
+ glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); |
+ |
+ gfx::ScopedUseProgram use_program(program_); |
+ glUniform2f(size_location_, size_.width(), size_.height()); |
+ |
+ gfx::GLHelper::DrawQuad(vertex_buffer_); |
+ // Detach the output texture from the fbo. |
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
+ GL_TEXTURE_RECTANGLE_ARB, 0, 0); |
return true; |
} |