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 |