Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: ui/gl/gl_image_io_surface.mm

Issue 1862183003: Mac h264: Work around CGLContext+VTDecompresionSession deadlock (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add me as ui owner for Mac Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« ui/OWNERS ('K') | « ui/gl/gl_image_io_surface.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
12 #include "base/mac/foundation_util.h"
Daniele Castagna 2016/04/06 20:36:58 Is foundation_util.h included twice?
ccameron 2016/04/06 22:35:21 Oops. Removed.
10 #include "base/mac/foundation_util.h" 13 #include "base/mac/foundation_util.h"
11 #include "base/strings/stringize_macros.h" 14 #include "base/strings/stringize_macros.h"
12 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
13 #include "base/trace_event/memory_allocator_dump.h" 16 #include "base/trace_event/memory_allocator_dump.h"
14 #include "base/trace_event/memory_dump_manager.h" 17 #include "base/trace_event/memory_dump_manager.h"
15 #include "base/trace_event/process_memory_dump.h" 18 #include "base/trace_event/process_memory_dump.h"
16 #include "ui/gl/gl_bindings.h" 19 #include "ui/gl/gl_bindings.h"
17 #include "ui/gl/gl_context.h" 20 #include "ui/gl/gl_context.h"
18 #include "ui/gl/gl_helper.h" 21 #include "ui/gl/gl_helper.h"
19 #include "ui/gl/scoped_binders.h" 22 #include "ui/gl/scoped_binders.h"
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 NOTREACHED(); 185 NOTREACHED();
183 return 0; 186 return 0;
184 } 187 }
185 188
186 NOTREACHED(); 189 NOTREACHED();
187 return 0; 190 return 0;
188 } 191 }
189 192
190 } // namespace 193 } // namespace
191 194
195 // TODO(ccameron): Share this across all GLImages that share the same context.
196 class GLImageIOSurface::RGBConverter {
Daniele Castagna 2016/04/06 20:36:58 In my original patch I had a similar struct to kee
197 public:
198 RGBConverter();
199 ~RGBConverter() {}
200 bool CopyTexImage(IOSurfaceRef io_surface, const gfx::Size& size);
201 void DestroyGLResources();
202
203 private:
204 unsigned vertex_shader_ = 0;
205 unsigned fragment_shader_ = 0;
206 unsigned program_ = 0;
207 int size_location_ = -1;
208 unsigned vertex_buffer_ = 0;
209
210 DISALLOW_COPY_AND_ASSIGN(RGBConverter);
211 };
212
192 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size, 213 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size,
193 unsigned internalformat) 214 unsigned internalformat)
194 : size_(size), 215 : size_(size),
195 internalformat_(internalformat), 216 internalformat_(internalformat),
196 format_(BufferFormat::RGBA_8888) {} 217 format_(BufferFormat::RGBA_8888) {}
197 218
198 GLImageIOSurface::~GLImageIOSurface() { 219 GLImageIOSurface::~GLImageIOSurface() {
199 DCHECK(thread_checker_.CalledOnValidThread()); 220 DCHECK(thread_checker_.CalledOnValidThread());
200 DCHECK(!io_surface_); 221 DCHECK(!io_surface_);
201 } 222 }
(...skipping 30 matching lines...) Expand all
232 return false; 253 return false;
233 } 254 }
234 255
235 if (!Initialize(io_surface, io_surface_id, format)) 256 if (!Initialize(io_surface, io_surface_id, format))
236 return false; 257 return false;
237 258
238 cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN); 259 cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
239 return true; 260 return true;
240 } 261 }
241 262
263 void GLImageIOSurface::RGBConverter::DestroyGLResources() {
264 glDeleteProgram(program_);
265 glDeleteShader(vertex_shader_);
266 glDeleteShader(fragment_shader_);
267 glDeleteBuffersARB(1, &vertex_buffer_);
268 }
269
242 void GLImageIOSurface::Destroy(bool have_context) { 270 void GLImageIOSurface::Destroy(bool have_context) {
243 DCHECK(thread_checker_.CalledOnValidThread()); 271 DCHECK(thread_checker_.CalledOnValidThread());
244 if (have_context && framebuffer_) { 272 if (have_context && rgb_converter_)
245 glDeleteProgram(program_); 273 rgb_converter_->DestroyGLResources();
246 glDeleteShader(vertex_shader_);
247 glDeleteShader(fragment_shader_);
248 glDeleteBuffersARB(1, &vertex_buffer_);
249 glDeleteFramebuffersEXT(1, &framebuffer_);
250 glDeleteTextures(2, yuv_textures_);
251 }
252 io_surface_.reset(); 274 io_surface_.reset();
253 cv_pixel_buffer_.reset(); 275 cv_pixel_buffer_.reset();
276 rgb_converter_.reset();
254 } 277 }
255 278
256 gfx::Size GLImageIOSurface::GetSize() { 279 gfx::Size GLImageIOSurface::GetSize() {
257 return size_; 280 return size_;
258 } 281 }
259 282
260 unsigned GLImageIOSurface::GetInternalFormat() { 283 unsigned GLImageIOSurface::GetInternalFormat() {
261 return internalformat_; 284 return internalformat_;
262 } 285 }
263 286
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 bool GLImageIOSurface::CopyTexImage(unsigned target) { 319 bool GLImageIOSurface::CopyTexImage(unsigned target) {
297 DCHECK(thread_checker_.CalledOnValidThread()); 320 DCHECK(thread_checker_.CalledOnValidThread());
298 321
299 if (format_ != BufferFormat::YUV_420_BIPLANAR) 322 if (format_ != BufferFormat::YUV_420_BIPLANAR)
300 return false; 323 return false;
301 if (target != GL_TEXTURE_RECTANGLE_ARB) { 324 if (target != GL_TEXTURE_RECTANGLE_ARB) {
302 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; 325 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target";
303 return false; 326 return false;
304 } 327 }
305 328
306 if (!framebuffer_) { 329 if (!rgb_converter_)
307 glGenFramebuffersEXT(1, &framebuffer_); 330 rgb_converter_.reset(new RGBConverter);
308 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); 331 return rgb_converter_->CopyTexImage(io_surface_.get(), size_);
309 vertex_shader_ = gfx::GLHelper::LoadShader( 332 }
310 GL_VERTEX_SHADER,
311 base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str());
312 fragment_shader_ = gfx::GLHelper::LoadShader(
313 GL_FRAGMENT_SHADER,
314 base::StringPrintf("%s\n%s\n%s", kGLSLVersion,
315 kTextureRectangleRequired, kFragmentShader)
316 .c_str());
317 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
318 gfx::ScopedUseProgram use_program(program_);
319 333
320 size_location_ = glGetUniformLocation(program_, "a_texScale"); 334 GLImageIOSurface::RGBConverter::RGBConverter() {
321 DCHECK_NE(-1, size_location_); 335 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer();
322 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture"); 336 vertex_shader_ = gfx::GLHelper::LoadShader(
323 DCHECK_NE(-1, y_sampler_location); 337 GL_VERTEX_SHADER,
324 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture"); 338 base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str());
325 DCHECK_NE(-1, uv_sampler_location); 339 fragment_shader_ = gfx::GLHelper::LoadShader(
340 GL_FRAGMENT_SHADER,
341 base::StringPrintf("%s\n%s\n%s", kGLSLVersion, kTextureRectangleRequired,
342 kFragmentShader)
343 .c_str());
344 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
345 gfx::ScopedUseProgram use_program(program_);
326 346
327 glUniform1i(y_sampler_location, 0); 347 size_location_ = glGetUniformLocation(program_, "a_texScale");
328 glUniform1i(uv_sampler_location, 1); 348 DCHECK_NE(-1, size_location_);
349 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture");
350 DCHECK_NE(-1, y_sampler_location);
351 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture");
352 DCHECK_NE(-1, uv_sampler_location);
329 353
330 glGenTextures(2, yuv_textures_); 354 glUniform1i(y_sampler_location, 0);
331 DCHECK(yuv_textures_[0]); 355 glUniform1i(uv_sampler_location, 1);
332 DCHECK(yuv_textures_[1]); 356 }
333 }
334 357
358 bool GLImageIOSurface::RGBConverter::CopyTexImage(IOSurfaceRef io_surface,
359 const gfx::Size& size) {
335 CGLContextObj cgl_context = 360 CGLContextObj cgl_context =
336 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); 361 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle());
337 362
338 GLint target_texture = 0; 363 GLint target_texture = 0;
339 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture); 364 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture);
340 DCHECK(target_texture); 365 DCHECK(target_texture);
341 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size_.width(), 366 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size.width(), size.height(),
342 size_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); 367 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
368
369 // Ensure that all textures bound to IOSurfaces be destroyed before the
370 // function exits. If they are not destroyed they may cause deadlocks between
371 // VTDecompressionSession at CGLContextDestroy.
372 // https://crbug.com/598388
373 unsigned y_texture = 0;
374 glGenTextures(1, &y_texture);
375 unsigned uv_texture = 0;
376 glGenTextures(1, &uv_texture);
377 unsigned framebuffer = 0;
378 glGenFramebuffersEXT(1, &framebuffer);
Daniele Castagna 2016/04/06 20:36:58 Do we need to regen this one all the time too?
ccameron 2016/04/06 22:35:21 It made the RGBConverter not capture any state of
379 base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{
Daniele Castagna 2016/04/06 20:36:58 nit: I'm assuming the caret has some special meani
ccameron 2016/04/06 22:35:21 Yeah, it's for a block, which is the ObjC version
Daniele Castagna 2016/04/07 01:35:07 Can't you just add {y,uv}_texture in the closure l
ccameron 2016/04/07 07:10:34 If I include y/uv in the closure list, then I can'
380 glDeleteTextures(1, &y_texture);
381 glDeleteTextures(1, &uv_texture);
382 glDeleteFramebuffersEXT(1, &framebuffer);
383 }));
343 384
344 CGLError cgl_error = kCGLNoError; 385 CGLError cgl_error = kCGLNoError;
345 { 386 {
346 DCHECK(io_surface_);
347
348 gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0); 387 gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0);
349 gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB, 388 gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB,
350 yuv_textures_[0]); 389 y_texture);
351 cgl_error = CGLTexImageIOSurface2D( 390 cgl_error = CGLTexImageIOSurface2D(cgl_context, GL_TEXTURE_RECTANGLE_ARB,
352 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), 391 GL_RED, size.width(), size.height(),
353 size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); 392 GL_RED, GL_UNSIGNED_BYTE, io_surface, 0);
354 if (cgl_error != kCGLNoError) { 393 if (cgl_error != kCGLNoError) {
355 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. " 394 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. "
356 << cgl_error; 395 << cgl_error;
357 return false; 396 return false;
358 } 397 }
359 { 398 {
360 gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1); 399 gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1);
361 gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB, 400 gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB,
362 yuv_textures_[1]); 401 uv_texture);
363 cgl_error = CGLTexImageIOSurface2D( 402 cgl_error = CGLTexImageIOSurface2D(
364 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, 403 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size.width() / 2,
365 size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); 404 size.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface, 1);
366 if (cgl_error != kCGLNoError) { 405 if (cgl_error != kCGLNoError) {
367 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " 406 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. "
368 << cgl_error; 407 << cgl_error;
369 return false; 408 return false;
370 } 409 }
371 410
372 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); 411 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer);
373 gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height()); 412 gfx::ScopedViewport viewport(0, 0, size.width(), size.height());
374 glViewport(0, 0, size_.width(), size_.height()); 413 glViewport(0, 0, size.width(), size.height());
375 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 414 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
376 GL_TEXTURE_RECTANGLE_ARB, target_texture, 0); 415 GL_TEXTURE_RECTANGLE_ARB, target_texture, 0);
377 DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), 416 DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
378 glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); 417 glCheckFramebufferStatusEXT(GL_FRAMEBUFFER));
379 418
380 gfx::ScopedUseProgram use_program(program_); 419 gfx::ScopedUseProgram use_program(program_);
381 glUniform2f(size_location_, size_.width(), size_.height()); 420 glUniform2f(size_location_, size.width(), size.height());
382 421
383 gfx::GLHelper::DrawQuad(vertex_buffer_); 422 gfx::GLHelper::DrawQuad(vertex_buffer_);
384 // Detach the output texture from the fbo. 423 // Detach the output texture from the fbo.
385 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 424 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
386 GL_TEXTURE_RECTANGLE_ARB, 0, 0); 425 GL_TEXTURE_RECTANGLE_ARB, 0, 0);
387 } 426 }
388 } 427 }
389 return true; 428 return true;
390 } 429 }
391 430
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 g_widget_to_layer_map.Pointer()->erase(widget); 479 g_widget_to_layer_map.Pointer()->erase(widget);
441 } 480 }
442 481
443 // static 482 // static
444 unsigned GLImageIOSurface::GetInternalFormatForTesting( 483 unsigned GLImageIOSurface::GetInternalFormatForTesting(
445 gfx::BufferFormat format) { 484 gfx::BufferFormat format) {
446 DCHECK(ValidFormat(format)); 485 DCHECK(ValidFormat(format));
447 return TextureFormat(format); 486 return TextureFormat(format);
448 } 487 }
449 } // namespace gl 488 } // namespace gl
OLDNEW
« ui/OWNERS ('K') | « ui/gl/gl_image_io_surface.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698