| 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" |
| 10 #include "base/mac/foundation_util.h" | 11 #include "base/mac/foundation_util.h" |
| 11 #include "base/strings/stringize_macros.h" | 12 #include "base/strings/stringize_macros.h" |
| 12 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 13 #include "base/trace_event/memory_allocator_dump.h" | 14 #include "base/trace_event/memory_allocator_dump.h" |
| 14 #include "base/trace_event/memory_dump_manager.h" | 15 #include "base/trace_event/memory_dump_manager.h" |
| 15 #include "base/trace_event/process_memory_dump.h" | 16 #include "base/trace_event/process_memory_dump.h" |
| 16 #include "ui/gl/gl_bindings.h" | 17 #include "ui/gl/gl_bindings.h" |
| 17 #include "ui/gl/gl_context.h" | 18 #include "ui/gl/gl_context.h" |
| 18 #include "ui/gl/gl_helper.h" | 19 #include "ui/gl/gl_helper.h" |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 } | 241 } |
| 241 | 242 |
| 242 void GLImageIOSurface::Destroy(bool have_context) { | 243 void GLImageIOSurface::Destroy(bool have_context) { |
| 243 DCHECK(thread_checker_.CalledOnValidThread()); | 244 DCHECK(thread_checker_.CalledOnValidThread()); |
| 244 if (have_context && framebuffer_) { | 245 if (have_context && framebuffer_) { |
| 245 glDeleteProgram(program_); | 246 glDeleteProgram(program_); |
| 246 glDeleteShader(vertex_shader_); | 247 glDeleteShader(vertex_shader_); |
| 247 glDeleteShader(fragment_shader_); | 248 glDeleteShader(fragment_shader_); |
| 248 glDeleteBuffersARB(1, &vertex_buffer_); | 249 glDeleteBuffersARB(1, &vertex_buffer_); |
| 249 glDeleteFramebuffersEXT(1, &framebuffer_); | 250 glDeleteFramebuffersEXT(1, &framebuffer_); |
| 250 glDeleteTextures(2, yuv_textures_); | |
| 251 } | 251 } |
| 252 io_surface_.reset(); | 252 io_surface_.reset(); |
| 253 cv_pixel_buffer_.reset(); | 253 cv_pixel_buffer_.reset(); |
| 254 } | 254 } |
| 255 | 255 |
| 256 gfx::Size GLImageIOSurface::GetSize() { | 256 gfx::Size GLImageIOSurface::GetSize() { |
| 257 return size_; | 257 return size_; |
| 258 } | 258 } |
| 259 | 259 |
| 260 unsigned GLImageIOSurface::GetInternalFormat() { | 260 unsigned GLImageIOSurface::GetInternalFormat() { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 bool GLImageIOSurface::CopyTexImage(unsigned target) { | 296 bool GLImageIOSurface::CopyTexImage(unsigned target) { |
| 297 DCHECK(thread_checker_.CalledOnValidThread()); | 297 DCHECK(thread_checker_.CalledOnValidThread()); |
| 298 | 298 |
| 299 if (format_ != BufferFormat::YUV_420_BIPLANAR) | 299 if (format_ != BufferFormat::YUV_420_BIPLANAR) |
| 300 return false; | 300 return false; |
| 301 if (target != GL_TEXTURE_RECTANGLE_ARB) { | 301 if (target != GL_TEXTURE_RECTANGLE_ARB) { |
| 302 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; | 302 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; |
| 303 return false; | 303 return false; |
| 304 } | 304 } |
| 305 | 305 |
| 306 // Ensure that all textures bound to IOSurfaces be destroyed before the |
| 307 // function exits. If they are not destroyed they may cause deadlocks between |
| 308 // VTDecompressionSession at CGLContextDestroy. |
| 309 // https://crbug.com/598388 |
| 310 unsigned y_texture = 0; |
| 311 glGenTextures(1, &y_texture); |
| 312 unsigned uv_texture = 0; |
| 313 glGenTextures(1, &uv_texture); |
| 314 base::ScopedClosureRunner destroy_resources_runner(base::Bind( |
| 315 +[](unsigned y_texture, unsigned uv_texture) { |
| 316 glDeleteTextures(1, &y_texture); |
| 317 glDeleteTextures(1, &uv_texture); |
| 318 }, |
| 319 y_texture, uv_texture)); |
| 320 |
| 306 if (!framebuffer_) { | 321 if (!framebuffer_) { |
| 307 glGenFramebuffersEXT(1, &framebuffer_); | 322 glGenFramebuffersEXT(1, &framebuffer_); |
| 308 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); | 323 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); |
| 309 vertex_shader_ = gfx::GLHelper::LoadShader( | 324 vertex_shader_ = gfx::GLHelper::LoadShader( |
| 310 GL_VERTEX_SHADER, | 325 GL_VERTEX_SHADER, |
| 311 base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str()); | 326 base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str()); |
| 312 fragment_shader_ = gfx::GLHelper::LoadShader( | 327 fragment_shader_ = gfx::GLHelper::LoadShader( |
| 313 GL_FRAGMENT_SHADER, | 328 GL_FRAGMENT_SHADER, |
| 314 base::StringPrintf("%s\n%s\n%s", kGLSLVersion, | 329 base::StringPrintf("%s\n%s\n%s", kGLSLVersion, |
| 315 kTextureRectangleRequired, kFragmentShader) | 330 kTextureRectangleRequired, kFragmentShader) |
| 316 .c_str()); | 331 .c_str()); |
| 317 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); | 332 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); |
| 318 gfx::ScopedUseProgram use_program(program_); | 333 gfx::ScopedUseProgram use_program(program_); |
| 319 | 334 |
| 320 size_location_ = glGetUniformLocation(program_, "a_texScale"); | 335 size_location_ = glGetUniformLocation(program_, "a_texScale"); |
| 321 DCHECK_NE(-1, size_location_); | 336 DCHECK_NE(-1, size_location_); |
| 322 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture"); | 337 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture"); |
| 323 DCHECK_NE(-1, y_sampler_location); | 338 DCHECK_NE(-1, y_sampler_location); |
| 324 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture"); | 339 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture"); |
| 325 DCHECK_NE(-1, uv_sampler_location); | 340 DCHECK_NE(-1, uv_sampler_location); |
| 326 | 341 |
| 327 glUniform1i(y_sampler_location, 0); | 342 glUniform1i(y_sampler_location, 0); |
| 328 glUniform1i(uv_sampler_location, 1); | 343 glUniform1i(uv_sampler_location, 1); |
| 329 | |
| 330 glGenTextures(2, yuv_textures_); | |
| 331 DCHECK(yuv_textures_[0]); | |
| 332 DCHECK(yuv_textures_[1]); | |
| 333 } | 344 } |
| 334 | 345 |
| 335 CGLContextObj cgl_context = | 346 CGLContextObj cgl_context = |
| 336 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); | 347 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); |
| 337 | 348 |
| 338 GLint target_texture = 0; | 349 GLint target_texture = 0; |
| 339 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); | 350 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); |
| 340 DCHECK(target_texture); | 351 DCHECK(target_texture); |
| 341 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size_.width(), | 352 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size_.width(), |
| 342 size_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); | 353 size_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); |
| 343 | 354 |
| 344 CGLError cgl_error = kCGLNoError; | 355 CGLError cgl_error = kCGLNoError; |
| 345 { | 356 { |
| 346 DCHECK(io_surface_); | 357 DCHECK(io_surface_); |
| 347 | 358 |
| 348 gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0); | 359 gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0); |
| 349 gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB, | 360 gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB, |
| 350 yuv_textures_[0]); | 361 y_texture); |
| 351 cgl_error = CGLTexImageIOSurface2D( | 362 cgl_error = CGLTexImageIOSurface2D( |
| 352 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), | 363 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), |
| 353 size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); | 364 size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); |
| 354 if (cgl_error != kCGLNoError) { | 365 if (cgl_error != kCGLNoError) { |
| 355 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. " | 366 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. " |
| 356 << cgl_error; | 367 << cgl_error; |
| 357 return false; | 368 return false; |
| 358 } | 369 } |
| 359 { | 370 { |
| 360 gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1); | 371 gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1); |
| 361 gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB, | 372 gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB, |
| 362 yuv_textures_[1]); | 373 uv_texture); |
| 363 cgl_error = CGLTexImageIOSurface2D( | 374 cgl_error = CGLTexImageIOSurface2D( |
| 364 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, | 375 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, |
| 365 size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); | 376 size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); |
| 366 if (cgl_error != kCGLNoError) { | 377 if (cgl_error != kCGLNoError) { |
| 367 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " | 378 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " |
| 368 << cgl_error; | 379 << cgl_error; |
| 369 return false; | 380 return false; |
| 370 } | 381 } |
| 371 | 382 |
| 372 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); | 383 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 g_widget_to_layer_map.Pointer()->erase(widget); | 451 g_widget_to_layer_map.Pointer()->erase(widget); |
| 441 } | 452 } |
| 442 | 453 |
| 443 // static | 454 // static |
| 444 unsigned GLImageIOSurface::GetInternalFormatForTesting( | 455 unsigned GLImageIOSurface::GetInternalFormatForTesting( |
| 445 gfx::BufferFormat format) { | 456 gfx::BufferFormat format) { |
| 446 DCHECK(ValidFormat(format)); | 457 DCHECK(ValidFormat(format)); |
| 447 return TextureFormat(format); | 458 return TextureFormat(format); |
| 448 } | 459 } |
| 449 } // namespace gl | 460 } // namespace gl |
| OLD | NEW |