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

Side by Side Diff: content/common/gpu/client/gl_helper.cc

Issue 12892005: Implement client side PBOs for glReadPixel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: pbo unit test added Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/common/gpu/client/gl_helper.h" 5 #include "content/common/gpu/client/gl_helper.h"
6 6
7 #include <queue> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
13 #include "base/message_loop.h" 14 #include "base/message_loop.h"
14 #include "base/synchronization/lock.h" 15 #include "base/synchronization/lock.h"
15 #include "base/synchronization/waitable_event.h" 16 #include "base/synchronization/waitable_event.h"
16 #include "base/threading/thread.h" 17 #include "base/threading/thread.h"
17 #include "base/threading/thread_restrictions.h" 18 #include "base/threading/thread_restrictions.h"
19 #include "base/time.h"
18 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h" 20 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" 21 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
20 #include "third_party/skia/include/core/SkRegion.h" 22 #include "third_party/skia/include/core/SkRegion.h"
21 #include "ui/gfx/rect.h" 23 #include "ui/gfx/rect.h"
22 #include "ui/gfx/size.h" 24 #include "ui/gfx/size.h"
23 #include "ui/gl/gl_bindings.h" 25 #include "ui/gl/gl_bindings.h"
24 26
25 using WebKit::WebGLId; 27 using WebKit::WebGLId;
26 using WebKit::WebGraphicsContext3D; 28 using WebKit::WebGraphicsContext3D;
27 29
28 namespace { 30 namespace {
29 31
30 const char kGLHelperThreadName[] = "GLHelperThread";
31
32 class GLHelperThread : public base::Thread {
33 public:
34 GLHelperThread() : base::Thread(kGLHelperThreadName) {
35 Start();
36 }
37 virtual ~GLHelperThread() {
38 Stop();
39 }
40
41 private:
42 DISALLOW_COPY_AND_ASSIGN(GLHelperThread);
43 };
44
45 base::LazyInstance<GLHelperThread> g_gl_helper_thread =
46 LAZY_INSTANCE_INITIALIZER;
47
48 class ScopedWebGLId { 32 class ScopedWebGLId {
49 public: 33 public:
50 typedef void (WebGraphicsContext3D::*DeleteFunc)(WebGLId); 34 typedef void (WebGraphicsContext3D::*DeleteFunc)(WebGLId);
51 ScopedWebGLId(WebGraphicsContext3D* context, 35 ScopedWebGLId(WebGraphicsContext3D* context,
52 WebGLId id, 36 WebGLId id,
53 DeleteFunc delete_func) 37 DeleteFunc delete_func)
54 : context_(context), 38 : context_(context),
55 id_(id), 39 id_(id),
56 delete_func_(delete_func) { 40 delete_func_(delete_func) {
57 } 41 }
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 216
233 } // namespace 217 } // namespace
234 218
235 namespace content { 219 namespace content {
236 220
237 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates the 221 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates the
238 // data needed for it. 222 // data needed for it.
239 class GLHelper::CopyTextureToImpl { 223 class GLHelper::CopyTextureToImpl {
240 public: 224 public:
241 CopyTextureToImpl(WebGraphicsContext3D* context, 225 CopyTextureToImpl(WebGraphicsContext3D* context,
242 WebGraphicsContext3D* context_for_thread,
243 GLHelper* helper) 226 GLHelper* helper)
244 : context_(context), 227 : context_(context),
245 context_for_thread_(context_for_thread),
246 helper_(helper), 228 helper_(helper),
247 flush_(context), 229 flush_(context),
248 program_(context, context->createProgram()), 230 program_(context, context->createProgram()),
249 vertex_attributes_buffer_(context_, context_->createBuffer()), 231 vertex_attributes_buffer_(context_, context_->createBuffer()),
250 flipped_vertex_attributes_buffer_(context_, context_->createBuffer()) { 232 flipped_vertex_attributes_buffer_(context_, context_->createBuffer()) {
251 InitBuffer(); 233 InitBuffer();
252 InitProgram(); 234 InitProgram();
253 } 235 }
254 ~CopyTextureToImpl() { 236 ~CopyTextureToImpl() {
255 CancelRequests(); 237 CancelRequests();
256 DeleteContextForThread();
257 } 238 }
258 239
259 void InitBuffer(); 240 void InitBuffer();
260 void InitProgram(); 241 void InitProgram();
261 242
262 void CropScaleReadbackAndCleanTexture( 243 void CropScaleReadbackAndCleanTexture(
263 WebGLId src_texture, 244 WebGLId src_texture,
264 const gfx::Size& src_size, 245 const gfx::Size& src_size,
265 const gfx::Rect& src_subrect, 246 const gfx::Rect& src_subrect,
266 const gfx::Size& dst_size, 247 const gfx::Size& dst_size,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 297
317 // Copies the block of pixels specified with |src_subrect| from |src_texture|, 298 // Copies the block of pixels specified with |src_subrect| from |src_texture|,
318 // scales it to |dst_size|, writes it into a texture, and returns its ID. 299 // scales it to |dst_size|, writes it into a texture, and returns its ID.
319 // |src_size| is the size of |src_texture|. 300 // |src_size| is the size of |src_texture|.
320 WebGLId ScaleTexture(WebGLId src_texture, 301 WebGLId ScaleTexture(WebGLId src_texture,
321 const gfx::Size& src_size, 302 const gfx::Size& src_size,
322 const gfx::Rect& src_subrect, 303 const gfx::Rect& src_subrect,
323 const gfx::Size& dst_size, 304 const gfx::Size& dst_size,
324 bool vertically_flip_texture); 305 bool vertically_flip_texture);
325 306
326 // Deletes the context for GLHelperThread.
327 void DeleteContextForThread();
328 static void ReadBackFramebuffer(scoped_refptr<Request> request,
329 WebGraphicsContext3D* context,
330 scoped_refptr<base::TaskRunner> reply_loop);
331 static void ReadBackFramebufferComplete(scoped_refptr<Request> request, 307 static void ReadBackFramebufferComplete(scoped_refptr<Request> request,
332 bool result); 308 GLuint buffer, GLuint query);
333 void FinishRequest(scoped_refptr<Request> request); 309 void FinishRequest(scoped_refptr<Request> request);
334 void CancelRequests(); 310 void CancelRequests();
335 311
336 // Interleaved array of 2-dimentional vertex positions (x, y) and 312 // Interleaved array of 2-dimentional vertex positions (x, y) and
337 // 2-dimentional texture coordinates (s, t). 313 // 2-dimentional texture coordinates (s, t).
338 static const WebKit::WGC3Dfloat kVertexAttributes[]; 314 static const WebKit::WGC3Dfloat kVertexAttributes[];
339 // Interleaved array of 2-dimensional vertex positions (x, y) and 315 // Interleaved array of 2-dimensional vertex positions (x, y) and
340 // 2 dimensional texture coordinates (s, t). 316 // 2 dimensional texture coordinates (s, t).
341 static const WebKit::WGC3Dfloat kFlippedVertexAttributes[]; 317 static const WebKit::WGC3Dfloat kFlippedVertexAttributes[];
342 // Shader sources used for GLHelper::CropScaleReadbackAndCleanTexture and 318 // Shader sources used for GLHelper::CropScaleReadbackAndCleanTexture and
343 // GLHelper::ReadbackTextureSync 319 // GLHelper::ReadbackTextureSync
344 static const WebKit::WGC3Dchar kCopyVertexShader[]; 320 static const WebKit::WGC3Dchar kCopyVertexShader[];
345 static const WebKit::WGC3Dchar kCopyFragmentShader[]; 321 static const WebKit::WGC3Dchar kCopyFragmentShader[];
346 322
347 WebGraphicsContext3D* context_; 323 WebGraphicsContext3D* context_;
348 WebGraphicsContext3D* context_for_thread_;
349 GLHelper* helper_; 324 GLHelper* helper_;
350 325
351 // A scoped flush that will ensure all resource deletions are flushed when 326 // A scoped flush that will ensure all resource deletions are flushed when
352 // this object is destroyed. Must be declared before other Scoped* fields. 327 // this object is destroyed. Must be declared before other Scoped* fields.
353 ScopedFlush flush_; 328 ScopedFlush flush_;
354 // A program for copying a source texture into a destination texture. 329 // A program for copying a source texture into a destination texture.
355 ScopedProgram program_; 330 ScopedProgram program_;
356 // The buffer that holds the vertices and the texture coordinates data for 331 // The buffer that holds the vertices and the texture coordinates data for
357 // drawing a quad. 332 // drawing a quad.
358 ScopedBuffer vertex_attributes_buffer_; 333 ScopedBuffer vertex_attributes_buffer_;
359 ScopedBuffer flipped_vertex_attributes_buffer_; 334 ScopedBuffer flipped_vertex_attributes_buffer_;
360 335
361 // The location of the position in the program. 336 // The location of the position in the program.
362 WebKit::WGC3Dint position_location_; 337 WebKit::WGC3Dint position_location_;
363 // The location of the texture coordinate in the program. 338 // The location of the texture coordinate in the program.
364 WebKit::WGC3Dint texcoord_location_; 339 WebKit::WGC3Dint texcoord_location_;
365 // The location of the source texture in the program. 340 // The location of the source texture in the program.
366 WebKit::WGC3Dint texture_location_; 341 WebKit::WGC3Dint texture_location_;
367 // The location of the texture coordinate of the sub-rectangle in the program. 342 // The location of the texture coordinate of the sub-rectangle in the program.
368 WebKit::WGC3Dint src_subrect_location_; 343 WebKit::WGC3Dint src_subrect_location_;
369 std::queue<scoped_refptr<Request> > request_queue_; 344 std::set<scoped_refptr<Request> > request_set_;
370 }; 345 };
371 346
372 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = { 347 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = {
373 -1.0f, -1.0f, 0.0f, 0.0f, 348 -1.0f, -1.0f, 0.0f, 0.0f,
374 1.0f, -1.0f, 1.0f, 0.0f, 349 1.0f, -1.0f, 1.0f, 0.0f,
375 -1.0f, 1.0f, 0.0f, 1.0f, 350 -1.0f, 1.0f, 0.0f, 1.0f,
376 1.0f, 1.0f, 1.0f, 1.0f, 351 1.0f, 1.0f, 1.0f, 1.0f,
377 }; 352 };
378 353
379 const WebKit::WGC3Dfloat 354 const WebKit::WGC3Dfloat
380 GLHelper::CopyTextureToImpl::kFlippedVertexAttributes[] = { 355 GLHelper::CopyTextureToImpl::kFlippedVertexAttributes[] = {
381 -1.0f, -1.0f, 0.0f, 1.0f, 356 -1.0f, -1.0f, 0.0f, 1.0f,
382 1.0f, -1.0f, 1.0f, 1.0f, 357 1.0f, -1.0f, 1.0f, 1.0f,
383 -1.0f, 1.0f, 0.0f, 0.0f, 358 -1.0f, 1.0f, 0.0f, 0.0f,
384 1.0f, 1.0f, 1.0f, 0.0f, 359 1.0f, 1.0f, 1.0f, 0.0f,
385 }; 360 };
386 361
387 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyVertexShader[] = 362 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyVertexShader[] =
388 "attribute vec2 a_position;" 363 "attribute vec2 a_position;"
389 "attribute vec2 a_texcoord;" 364 "attribute vec2 a_texcoord;"
390 "varying vec2 v_texcoord;" 365 "varying vec2 v_texcoord;"
391 "uniform vec4 src_subrect;" 366 "uniform vec4 src_subrect;"
392 "void main() {" 367 "void main() {"
393 " gl_Position = vec4(a_position, 0.0, 1.0);" 368 " gl_Position = vec4(a_position, 0.0, 1.0);"
394 " v_texcoord = src_subrect.xy + a_texcoord * src_subrect.zw;" 369 " v_texcoord = src_subrect.xy + a_texcoord * src_subrect.zw;"
395 "}"; 370 "}";
396 371
372
373 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
397 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = 374 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] =
398 "precision mediump float;" 375 "precision mediump float;"
399 "varying vec2 v_texcoord;" 376 "varying vec2 v_texcoord;"
377 "uniform sampler2D s_texture;"
378 "const mediump mat4 swizzle = mat4( 0.0, 0.0, 1.0, 0.0, "
379 " 0.0, 1.0, 0.0, 0.0, "
380 " 1.0, 0.0, 0.0, 0.0, "
381 " 0.0, 0.0, 0.0, 1.0 );"
382 "void main() {"
383 " gl_FragColor = swizzle * texture2D(s_texture, v_texcoord);"
apatrick_chromium 2013/03/19 18:34:48 Will this work? Seems a bit simpler. gl_FragColor
hubbe 2013/03/19 22:42:42 Done.
384 "}";
385 #else
386 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] =
387 "precision mediump float;"
388 "varying vec2 v_texcoord;"
400 "uniform sampler2D s_texture;" 389 "uniform sampler2D s_texture;"
401 "void main() {" 390 "void main() {"
402 " gl_FragColor = texture2D(s_texture, v_texcoord);" 391 " gl_FragColor = texture2D(s_texture, v_texcoord);"
403 "}"; 392 "}";
393 #endif
394
404 395
405 void GLHelper::CopyTextureToImpl::InitBuffer() { 396 void GLHelper::CopyTextureToImpl::InitBuffer() {
406 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( 397 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(
407 context_, vertex_attributes_buffer_); 398 context_, vertex_attributes_buffer_);
408 context_->bufferData(GL_ARRAY_BUFFER, 399 context_->bufferData(GL_ARRAY_BUFFER,
409 sizeof(kVertexAttributes), 400 sizeof(kVertexAttributes),
410 kVertexAttributes, 401 kVertexAttributes,
411 GL_STATIC_DRAW); 402 GL_STATIC_DRAW);
412 ScopedBufferBinder<GL_ARRAY_BUFFER> flipped_buffer_binder( 403 ScopedBufferBinder<GL_ARRAY_BUFFER> flipped_buffer_binder(
413 context_, flipped_vertex_attributes_buffer_); 404 context_, flipped_vertex_attributes_buffer_);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 }; 501 };
511 502
512 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); 503 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord);
513 504
514 // Conduct texture mapping by drawing a quad composed of two triangles. 505 // Conduct texture mapping by drawing a quad composed of two triangles.
515 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); 506 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
516 } 507 }
517 return dst_texture; 508 return dst_texture;
518 } 509 }
519 510
520 void GLHelper::CopyTextureToImpl::DeleteContextForThread() {
521 if (!context_for_thread_)
522 return;
523
524 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(
525 FROM_HERE,
526 base::Bind(&DeleteContext,
527 context_for_thread_));
528 context_for_thread_ = NULL;
529 }
530
531 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( 511 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
532 WebGLId src_texture, 512 WebGLId src_texture,
533 const gfx::Size& src_size, 513 const gfx::Size& src_size,
534 const gfx::Rect& src_subrect, 514 const gfx::Rect& src_subrect,
535 const gfx::Size& dst_size, 515 const gfx::Size& dst_size,
536 unsigned char* out, 516 unsigned char* out,
537 const base::Callback<void(bool)>& callback) { 517 const base::Callback<void(bool)>& callback) {
538 if (!context_for_thread_) {
539 callback.Run(false);
540 return;
541 }
542
543 WebGLId texture = ScaleTexture(src_texture, 518 WebGLId texture = ScaleTexture(src_texture,
544 src_size, 519 src_size,
545 src_subrect, 520 src_subrect,
546 dst_size, 521 dst_size,
547 false); 522 #ifdef USE_SKIA
523 true
524 #else
525 false
526 #endif
527 );
548 context_->flush(); 528 context_->flush();
549 scoped_refptr<Request> request = 529 scoped_refptr<Request> request =
550 new Request(this, texture, dst_size, out, callback); 530 new Request(this, texture, dst_size, out, callback);
551 request_queue_.push(request); 531 request_set_.insert(request);
552 532
553 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, 533 ScopedFlush flush(context_);
554 base::Bind(&ReadBackFramebuffer, 534 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
555 request, 535 gfx::Size size;
556 context_for_thread_, 536 base::AutoLock auto_lock(request->lock);
557 base::MessageLoopProxy::current())); 537 size = request->size;
538
539 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
540 context_, dst_framebuffer);
541 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(
542 context_, request->texture);
543 context_->framebufferTexture2D(GL_FRAMEBUFFER,
544 GL_COLOR_ATTACHMENT0,
545 GL_TEXTURE_2D,
546 request->texture,
547 0);
548 GLuint buffer = context_->createBuffer();
549 context_->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
550 buffer);
551 context_->bufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
552 4 * size.GetArea(),
553 NULL,
554 GL_STREAM_READ);
555
556 GLuint query = context_->createQueryEXT();
557 context_->beginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query);
558 context_->readPixels(0, 0, size.width(), size.height(),
559 GL_RGBA, GL_UNSIGNED_BYTE, 0);
560 context_->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
apatrick_chromium 2013/03/19 18:34:48 You might need to call flush here to guarantee tha
greggman 2013/03/19 20:54:11 yes, you need to call flush. endQueryEXT may or ma
hubbe 2013/03/19 22:42:42 Does the flush need to happen before endQueryExt?
apatrick_chromium 2013/03/19 23:31:20 I missed the ScopedFlush. It will work.
561 context_->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
apatrick_chromium 2013/03/19 18:34:48 What if a different buffer was bound to this targe
greggman 2013/03/19 20:54:11 You can't use UNPACK_TRANSFER_BUFFER for READing.
hubbe 2013/03/19 22:42:42 Good question. Should I document what buffers are
hubbe 2013/03/19 22:42:42 I guess I have to implement that extension then, r
apatrick_chromium 2013/03/19 23:31:20 I think the issue is, before this code was using c
hubbe 2013/03/19 23:39:27 This things are cached in the client side, so rest
apatrick_chromium 2013/03/19 23:53:59 Yes it looks like getInteger(GL_PIXEL_PACK_TRANSFE
562 base::MessageLoopProxy::current()->PostDelayedTask(
563 FROM_HERE,
564 base::Bind(&ReadBackFramebufferComplete, request, buffer, query),
565 base::TimeDelta::FromMilliseconds(2));
558 } 566 }
559 567
560 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(WebGLId texture, 568 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(WebGLId texture,
561 const gfx::Rect& src_rect, 569 const gfx::Rect& src_rect,
562 unsigned char* out) { 570 unsigned char* out) {
563 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); 571 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
564 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( 572 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
565 context_, dst_framebuffer); 573 context_, dst_framebuffer);
566 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); 574 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
567 context_->framebufferTexture2D(GL_FRAMEBUFFER, 575 context_->framebufferTexture2D(GL_FRAMEBUFFER,
(...skipping 15 matching lines...) Expand all
583 const gfx::Size& src_size, 591 const gfx::Size& src_size,
584 const gfx::Size& dst_size, 592 const gfx::Size& dst_size,
585 bool vertically_flip_texture) { 593 bool vertically_flip_texture) {
586 return ScaleTexture(src_texture, 594 return ScaleTexture(src_texture,
587 src_size, 595 src_size,
588 gfx::Rect(src_size), 596 gfx::Rect(src_size),
589 dst_size, 597 dst_size,
590 vertically_flip_texture); 598 vertically_flip_texture);
591 } 599 }
592 600
593 void GLHelper::CopyTextureToImpl::ReadBackFramebuffer(
594 scoped_refptr<Request> request,
595 WebGraphicsContext3D* context,
596 scoped_refptr<base::TaskRunner> reply_loop) {
597 DCHECK(context);
598 if (!context->makeContextCurrent() || context->isContextLost()) {
599 base::AutoLock auto_lock(request->lock);
600 if (request->pixels) {
601 // Only report failure if the request wasn't canceled (otherwise the
602 // failure has already been reported).
603 request->pixels = NULL;
604 reply_loop->PostTask(
605 FROM_HERE, base::Bind(ReadBackFramebufferComplete, request, false));
606 }
607 return;
608 }
609 ScopedFlush flush(context);
610 ScopedFramebuffer dst_framebuffer(context, context->createFramebuffer());
611 unsigned char* pixels = NULL;
612 gfx::Size size;
613 {
614 // Note: We don't want to keep the lock while doing the readBack (since we
615 // don't want to block the UI thread). We rely on the fact that once the
616 // texture is bound to a FBO (that isn't current), deleting the texture is
617 // delayed until the FBO is deleted. We ensure ordering by flushing while
618 // the lock is held. Either the main thread cancelled before we get the
619 // lock, and we'll exit early, or we ensure that the texture is bound to the
620 // framebuffer before the main thread has a chance to delete it.
621 base::AutoLock auto_lock(request->lock);
622 if (!request->texture || !request->pixels)
623 return;
624 pixels = request->pixels;
625 request->pixels = NULL;
626 size = request->size;
627 {
628 ScopedFlush flush(context);
629 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
630 context, dst_framebuffer);
631 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(
632 context, request->texture);
633 context->framebufferTexture2D(GL_FRAMEBUFFER,
634 GL_COLOR_ATTACHMENT0,
635 GL_TEXTURE_2D,
636 request->texture,
637 0);
638 }
639 }
640 bool result = context->readBackFramebuffer(
641 pixels,
642 4 * size.GetArea(),
643 dst_framebuffer.id(),
644 size.width(),
645 size.height());
646 reply_loop->PostTask(
647 FROM_HERE, base::Bind(ReadBackFramebufferComplete, request, result));
648 }
649
650 void GLHelper::CopyTextureToImpl::ReadBackFramebufferComplete( 601 void GLHelper::CopyTextureToImpl::ReadBackFramebufferComplete(
651 scoped_refptr<Request> request, 602 scoped_refptr<Request> request,
652 bool result) { 603 GLuint buffer, GLuint query) {
604
605 TRACE_EVENT0("mirror",
606 "GLHelper::CopyTextureToImpl::ReadBackFramebufferComplete");
607
608 if (!request->copy_texture_impl) {
609 request->callback.Run(false);
610 return;
611 }
612
613 WebKit::WebGraphicsContext3D* context = request->copy_texture_impl->context_;
614 bool result = false;
615
616 if (buffer != 0) {
617 unsigned int done = 1;
618 context->getQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &done);
619 if (!done) {
620 TRACE_EVENT0("mirror",
621 "GLHelper::CopyTextureToImpl::Reschedule");
622 base::MessageLoopProxy::current()->PostDelayedTask(
623 FROM_HERE,
624 base::Bind(&ReadBackFramebufferComplete, request, buffer, query),
625 base::TimeDelta::FromMilliseconds(2));
626 return;
627 }
628 context->deleteQueryEXT(query);
629 context->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
630 buffer);
631 void* data = context->mapBufferCHROMIUM(
632 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY);
633
634 if (data) {
635 result = true;
636 memcpy(request->pixels, data, request->size.GetArea() * 4);
637 context->unmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
638 } else {
639 fprintf(stderr,"mapBuffer Returns NULL\n");
apatrick_chromium 2013/03/19 18:34:48 Use LOG / VLOG instead of fprintf.
hubbe 2013/03/19 22:42:42 Old useless debugging junk. Gone.
640 }
641 context->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
apatrick_chromium 2013/03/19 18:34:48 Same as above. There might have been a different b
hubbe 2013/03/19 22:42:42 This is in an async callback. Is it really reasona
apatrick_chromium 2013/03/19 23:31:20 The assumption might have been made somewhere. Nee
hubbe 2013/03/19 23:39:27 While it is possible, the browser still works when
apatrick_chromium 2013/03/19 23:53:59 You can do the same thing to get the buffer bindin
642 context->deleteBuffer(buffer);
643 } else {
644 fprintf(stderr,"Buffer is negative!\n");
apatrick_chromium 2013/03/19 18:34:48 Use LOG / VLOG instead of fprintf.
hubbe 2013/03/19 22:42:42 Gone.
645 }
646
653 request->callback.Run(result); 647 request->callback.Run(result);
654 if (request->copy_texture_impl) 648 request->copy_texture_impl->FinishRequest(request);
655 request->copy_texture_impl->FinishRequest(request);
656 } 649 }
657 650
658 void GLHelper::CopyTextureToImpl::FinishRequest( 651 void GLHelper::CopyTextureToImpl::FinishRequest(
659 scoped_refptr<Request> request) { 652 scoped_refptr<Request> request) {
660 CHECK(request_queue_.front() == request); 653 CHECK(request_set_.find(request) != request_set_.end());
661 request_queue_.pop(); 654 request_set_.erase(request);
662 base::AutoLock auto_lock(request->lock); 655 base::AutoLock auto_lock(request->lock);
663 if (request->texture != 0) { 656 if (request->texture != 0) {
664 context_->deleteTexture(request->texture); 657 context_->deleteTexture(request->texture);
665 request->texture = 0; 658 request->texture = 0;
666 context_->flush(); 659 context_->flush();
667 } 660 }
668 } 661 }
669 662
670 void GLHelper::CopyTextureToImpl::CancelRequests() { 663 void GLHelper::CopyTextureToImpl::CancelRequests() {
671 while (!request_queue_.empty()) { 664 while (!request_set_.empty()) {
672 scoped_refptr<Request> request = request_queue_.front(); 665 scoped_refptr<Request> request = *request_set_.begin();
673 request_queue_.pop(); 666 request_set_.erase(request);
674 request->copy_texture_impl = NULL; 667 request->copy_texture_impl = NULL;
675 bool cancelled = false; 668 bool cancelled = false;
676 { 669 {
677 base::AutoLock auto_lock(request->lock); 670 base::AutoLock auto_lock(request->lock);
678 if (request->texture != 0) { 671 if (request->texture != 0) {
679 context_->deleteTexture(request->texture); 672 context_->deleteTexture(request->texture);
680 request->texture = 0; 673 request->texture = 0;
681 } 674 }
682 if (request->pixels != NULL) { 675 if (request->pixels != NULL) {
683 request->pixels = NULL; 676 request->pixels = NULL;
684 cancelled = true; 677 cancelled = true;
685 } 678 }
686 } 679 }
687 if (cancelled) 680 if (cancelled)
688 request->callback.Run(false); 681 request->callback.Run(false);
689 } 682 }
690 } 683 }
691 684
692 base::subtle::Atomic32 GLHelper::count_ = 0; 685 GLHelper::GLHelper(WebGraphicsContext3D* context)
693 686 : context_(context) {
694 GLHelper::GLHelper(WebGraphicsContext3D* context,
695 WebGraphicsContext3D* context_for_thread)
696 : context_(context),
697 context_for_thread_(context_for_thread) {
698 base::subtle::NoBarrier_AtomicIncrement(&count_, 1);
699 } 687 }
700 688
701 GLHelper::~GLHelper() { 689 GLHelper::~GLHelper() {
702 DCHECK_NE(MessageLoop::current(),
703 g_gl_helper_thread.Pointer()->message_loop());
704 base::subtle::Atomic32 decremented_count =
705 base::subtle::NoBarrier_AtomicIncrement(&count_, -1);
706 if (decremented_count == 0) {
707 // When this is the last instance, we synchronize with the pending
708 // operations on GLHelperThread. Otherwise on shutdown we may kill the GPU
709 // process infrastructure (BrowserGpuChannelHostFactory) before they have
710 // a chance to complete, likely leading to a crash.
711 base::WaitableEvent event(false, false);
712 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(
713 FROM_HERE,
714 base::Bind(&SignalWaitableEvent,
715 &event));
716 // http://crbug.com/125415
717 base::ThreadRestrictions::ScopedAllowWait allow_wait;
718 event.Wait();
719 }
720 } 690 }
721 691
722 WebGraphicsContext3D* GLHelper::context() const { 692 WebGraphicsContext3D* GLHelper::context() const {
723 return context_; 693 return context_;
724 } 694 }
725 695
726 void GLHelper::CropScaleReadbackAndCleanTexture( 696 void GLHelper::CropScaleReadbackAndCleanTexture(
727 WebGLId src_texture, 697 WebGLId src_texture,
728 const gfx::Size& src_size, 698 const gfx::Size& src_size,
729 const gfx::Rect& src_subrect, 699 const gfx::Rect& src_subrect,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 if (!compile_status) { 749 if (!compile_status) {
780 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); 750 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8());
781 return 0; 751 return 0;
782 } 752 }
783 return shader.Detach(); 753 return shader.Detach();
784 } 754 }
785 755
786 void GLHelper::InitCopyTextToImpl() { 756 void GLHelper::InitCopyTextToImpl() {
787 // Lazily initialize |copy_texture_to_impl_| 757 // Lazily initialize |copy_texture_to_impl_|
788 if (!copy_texture_to_impl_.get()) 758 if (!copy_texture_to_impl_.get())
789 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, 759 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, this));
790 context_for_thread_,
791 this));
792 } 760 }
793 761
794 void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture, 762 void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture,
795 WebKit::WebGLId previous_texture, 763 WebKit::WebGLId previous_texture,
796 const SkRegion& new_damage, 764 const SkRegion& new_damage,
797 const SkRegion& old_damage) { 765 const SkRegion& old_damage) {
798 SkRegion region(old_damage); 766 SkRegion region(old_damage);
799 if (region.op(new_damage, SkRegion::kDifference_Op)) { 767 if (region.op(new_damage, SkRegion::kDifference_Op)) {
800 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); 768 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
801 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( 769 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
802 context_, dst_framebuffer); 770 context_, dst_framebuffer);
803 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); 771 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
804 context_->framebufferTexture2D(GL_FRAMEBUFFER, 772 context_->framebufferTexture2D(GL_FRAMEBUFFER,
805 GL_COLOR_ATTACHMENT0, 773 GL_COLOR_ATTACHMENT0,
806 GL_TEXTURE_2D, 774 GL_TEXTURE_2D,
807 previous_texture, 775 previous_texture,
808 0); 776 0);
809 for (SkRegion::Iterator it(region); !it.done(); it.next()) { 777 for (SkRegion::Iterator it(region); !it.done(); it.next()) {
810 const SkIRect& rect = it.rect(); 778 const SkIRect& rect = it.rect();
811 context_->copyTexSubImage2D(GL_TEXTURE_2D, 0, 779 context_->copyTexSubImage2D(GL_TEXTURE_2D, 0,
812 rect.x(), rect.y(), 780 rect.x(), rect.y(),
813 rect.x(), rect.y(), 781 rect.x(), rect.y(),
814 rect.width(), rect.height()); 782 rect.width(), rect.height());
815 } 783 }
816 context_->flush(); 784 context_->flush();
817 } 785 }
818 } 786 }
819 787
820 } // namespace content 788 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698