| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gl/gl_image_io_surface.h" | 5 #include "ui/gl/gl_image_io_surface.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" |
| 9 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/mac/bind_objc_block.h" |
| 10 #include "base/mac/foundation_util.h" | 12 #include "base/mac/foundation_util.h" |
| 11 #include "base/strings/stringize_macros.h" | 13 #include "base/strings/stringize_macros.h" |
| 12 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 13 #include "base/trace_event/memory_allocator_dump.h" | 15 #include "base/trace_event/memory_allocator_dump.h" |
| 14 #include "base/trace_event/memory_dump_manager.h" | 16 #include "base/trace_event/memory_dump_manager.h" |
| 15 #include "base/trace_event/process_memory_dump.h" | 17 #include "base/trace_event/process_memory_dump.h" |
| 16 #include "ui/gl/gl_bindings.h" | 18 #include "ui/gl/gl_bindings.h" |
| 17 #include "ui/gl/gl_context.h" | 19 #include "ui/gl/gl_context.h" |
| 18 #include "ui/gl/gl_helper.h" | 20 #include "ui/gl/gl_helper.h" |
| 19 #include "ui/gl/scoped_binders.h" | 21 #include "ui/gl/scoped_binders.h" |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } | 225 } |
| 224 | 226 |
| 225 void GLImageIOSurface::Destroy(bool have_context) { | 227 void GLImageIOSurface::Destroy(bool have_context) { |
| 226 DCHECK(thread_checker_.CalledOnValidThread()); | 228 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 if (have_context && framebuffer_) { | 229 if (have_context && framebuffer_) { |
| 228 glDeleteProgram(program_); | 230 glDeleteProgram(program_); |
| 229 glDeleteShader(vertex_shader_); | 231 glDeleteShader(vertex_shader_); |
| 230 glDeleteShader(fragment_shader_); | 232 glDeleteShader(fragment_shader_); |
| 231 glDeleteBuffersARB(1, &vertex_buffer_); | 233 glDeleteBuffersARB(1, &vertex_buffer_); |
| 232 glDeleteFramebuffersEXT(1, &framebuffer_); | 234 glDeleteFramebuffersEXT(1, &framebuffer_); |
| 233 glDeleteTextures(2, yuv_textures_); | |
| 234 } | 235 } |
| 235 io_surface_.reset(); | 236 io_surface_.reset(); |
| 236 } | 237 } |
| 237 | 238 |
| 238 gfx::Size GLImageIOSurface::GetSize() { | 239 gfx::Size GLImageIOSurface::GetSize() { |
| 239 return size_; | 240 return size_; |
| 240 } | 241 } |
| 241 | 242 |
| 242 unsigned GLImageIOSurface::GetInternalFormat() { | 243 unsigned GLImageIOSurface::GetInternalFormat() { |
| 243 return internalformat_; | 244 return internalformat_; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 bool GLImageIOSurface::CopyTexImage(unsigned target) { | 279 bool GLImageIOSurface::CopyTexImage(unsigned target) { |
| 279 DCHECK(thread_checker_.CalledOnValidThread()); | 280 DCHECK(thread_checker_.CalledOnValidThread()); |
| 280 | 281 |
| 281 if (format_ != BufferFormat::YUV_420_BIPLANAR) | 282 if (format_ != BufferFormat::YUV_420_BIPLANAR) |
| 282 return false; | 283 return false; |
| 283 if (target != GL_TEXTURE_RECTANGLE_ARB) { | 284 if (target != GL_TEXTURE_RECTANGLE_ARB) { |
| 284 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; | 285 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; |
| 285 return false; | 286 return false; |
| 286 } | 287 } |
| 287 | 288 |
| 289 // Ensure that all textures bound to IOSurfaces be destroyed before the |
| 290 // function exits. If they are not destroyed they may cause deadlocks between |
| 291 // VTDecompressionSession at CGLContextDestroy. |
| 292 // https://crbug.com/598388 |
| 293 unsigned y_texture = 0; |
| 294 glGenTextures(1, &y_texture); |
| 295 unsigned uv_texture = 0; |
| 296 glGenTextures(1, &uv_texture); |
| 297 base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{ |
| 298 glDeleteTextures(1, &y_texture); |
| 299 glDeleteTextures(1, &uv_texture); |
| 300 })); |
| 301 |
| 288 if (!framebuffer_) { | 302 if (!framebuffer_) { |
| 289 glGenFramebuffersEXT(1, &framebuffer_); | 303 glGenFramebuffersEXT(1, &framebuffer_); |
| 290 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); | 304 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); |
| 291 vertex_shader_ = gfx::GLHelper::LoadShader( | 305 vertex_shader_ = gfx::GLHelper::LoadShader( |
| 292 GL_VERTEX_SHADER, | 306 GL_VERTEX_SHADER, |
| 293 base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str()); | 307 base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str()); |
| 294 fragment_shader_ = gfx::GLHelper::LoadShader( | 308 fragment_shader_ = gfx::GLHelper::LoadShader( |
| 295 GL_FRAGMENT_SHADER, | 309 GL_FRAGMENT_SHADER, |
| 296 base::StringPrintf("%s\n%s\n%s", kGLSLVersion, | 310 base::StringPrintf("%s\n%s\n%s", kGLSLVersion, |
| 297 kTextureRectangleRequired, kFragmentShader) | 311 kTextureRectangleRequired, kFragmentShader) |
| 298 .c_str()); | 312 .c_str()); |
| 299 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); | 313 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); |
| 300 gfx::ScopedUseProgram use_program(program_); | 314 gfx::ScopedUseProgram use_program(program_); |
| 301 | 315 |
| 302 size_location_ = glGetUniformLocation(program_, "a_texScale"); | 316 size_location_ = glGetUniformLocation(program_, "a_texScale"); |
| 303 DCHECK_NE(-1, size_location_); | 317 DCHECK_NE(-1, size_location_); |
| 304 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture"); | 318 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture"); |
| 305 DCHECK_NE(-1, y_sampler_location); | 319 DCHECK_NE(-1, y_sampler_location); |
| 306 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture"); | 320 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture"); |
| 307 DCHECK_NE(-1, uv_sampler_location); | 321 DCHECK_NE(-1, uv_sampler_location); |
| 308 | 322 |
| 309 glUniform1i(y_sampler_location, 0); | 323 glUniform1i(y_sampler_location, 0); |
| 310 glUniform1i(uv_sampler_location, 1); | 324 glUniform1i(uv_sampler_location, 1); |
| 311 | |
| 312 glGenTextures(2, yuv_textures_); | |
| 313 DCHECK(yuv_textures_[0]); | |
| 314 DCHECK(yuv_textures_[1]); | |
| 315 } | 325 } |
| 316 | 326 |
| 317 CGLContextObj cgl_context = | 327 CGLContextObj cgl_context = |
| 318 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); | 328 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); |
| 319 | 329 |
| 320 GLint target_texture = 0; | 330 GLint target_texture = 0; |
| 321 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); | 331 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); |
| 322 DCHECK(target_texture); | 332 DCHECK(target_texture); |
| 323 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size_.width(), | 333 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size_.width(), |
| 324 size_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); | 334 size_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); |
| 325 | 335 |
| 326 CGLError cgl_error = kCGLNoError; | 336 CGLError cgl_error = kCGLNoError; |
| 327 { | 337 { |
| 328 DCHECK(io_surface_); | 338 DCHECK(io_surface_); |
| 329 | 339 |
| 330 gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0); | 340 gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0); |
| 331 gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB, | 341 gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB, |
| 332 yuv_textures_[0]); | 342 y_texture); |
| 333 cgl_error = CGLTexImageIOSurface2D( | 343 cgl_error = CGLTexImageIOSurface2D( |
| 334 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), | 344 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), |
| 335 size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); | 345 size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); |
| 336 if (cgl_error != kCGLNoError) { | 346 if (cgl_error != kCGLNoError) { |
| 337 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. " | 347 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. " |
| 338 << cgl_error; | 348 << cgl_error; |
| 339 return false; | 349 return false; |
| 340 } | 350 } |
| 341 { | 351 { |
| 342 gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1); | 352 gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1); |
| 343 gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB, | 353 gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB, |
| 344 yuv_textures_[1]); | 354 uv_texture); |
| 345 cgl_error = CGLTexImageIOSurface2D( | 355 cgl_error = CGLTexImageIOSurface2D( |
| 346 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, | 356 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, |
| 347 size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); | 357 size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); |
| 348 if (cgl_error != kCGLNoError) { | 358 if (cgl_error != kCGLNoError) { |
| 349 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " | 359 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " |
| 350 << cgl_error; | 360 << cgl_error; |
| 351 return false; | 361 return false; |
| 352 } | 362 } |
| 353 | 363 |
| 354 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); | 364 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 g_widget_to_layer_map.Pointer()->erase(widget); | 428 g_widget_to_layer_map.Pointer()->erase(widget); |
| 419 } | 429 } |
| 420 | 430 |
| 421 // static | 431 // static |
| 422 unsigned GLImageIOSurface::GetInternalFormatForTesting( | 432 unsigned GLImageIOSurface::GetInternalFormatForTesting( |
| 423 gfx::BufferFormat format) { | 433 gfx::BufferFormat format) { |
| 424 DCHECK(ValidFormat(format)); | 434 DCHECK(ValidFormat(format)); |
| 425 return TextureFormat(format); | 435 return TextureFormat(format); |
| 426 } | 436 } |
| 427 } // namespace gl | 437 } // namespace gl |
| OLD | NEW |