| OLD | NEW |
| 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 <queue> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 226 } |
| 227 | 227 |
| 228 void SignalWaitableEvent(base::WaitableEvent* event) { | 228 void SignalWaitableEvent(base::WaitableEvent* event) { |
| 229 event->Signal(); | 229 event->Signal(); |
| 230 } | 230 } |
| 231 | 231 |
| 232 } // namespace | 232 } // namespace |
| 233 | 233 |
| 234 namespace content { | 234 namespace content { |
| 235 | 235 |
| 236 // Implements GLHelper::CopyTextureTo and encapsulates the data needed for it. | 236 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates the |
| 237 // data needed for it. |
| 237 class GLHelper::CopyTextureToImpl { | 238 class GLHelper::CopyTextureToImpl { |
| 238 public: | 239 public: |
| 239 CopyTextureToImpl(WebGraphicsContext3D* context, | 240 CopyTextureToImpl(WebGraphicsContext3D* context, |
| 240 WebGraphicsContext3D* context_for_thread, | 241 WebGraphicsContext3D* context_for_thread, |
| 241 GLHelper* helper) | 242 GLHelper* helper) |
| 242 : context_(context), | 243 : context_(context), |
| 243 context_for_thread_(context_for_thread), | 244 context_for_thread_(context_for_thread), |
| 244 helper_(helper), | 245 helper_(helper), |
| 245 flush_(context), | 246 flush_(context), |
| 246 program_(context, context->createProgram()), | 247 program_(context, context->createProgram()), |
| 247 vertex_attributes_buffer_(context_, context_->createBuffer()) { | 248 vertex_attributes_buffer_(context_, context_->createBuffer()) { |
| 248 InitBuffer(); | 249 InitBuffer(); |
| 249 InitProgram(); | 250 InitProgram(); |
| 250 } | 251 } |
| 251 ~CopyTextureToImpl() { | 252 ~CopyTextureToImpl() { |
| 252 CancelRequests(); | 253 CancelRequests(); |
| 253 DeleteContextForThread(); | 254 DeleteContextForThread(); |
| 254 } | 255 } |
| 255 | 256 |
| 256 void InitBuffer(); | 257 void InitBuffer(); |
| 257 void InitProgram(); | 258 void InitProgram(); |
| 258 | 259 |
| 259 void CopyTextureTo(WebGLId src_texture, | 260 void CropScaleReadbackAndCleanTexture( |
| 260 const gfx::Size& src_size, | 261 WebGLId src_texture, |
| 261 const gfx::Rect& src_subrect, | 262 const gfx::Size& src_size, |
| 262 const gfx::Size& dst_size, | 263 const gfx::Rect& src_subrect, |
| 263 unsigned char* out, | 264 const gfx::Size& dst_size, |
| 264 const base::Callback<void(bool)>& callback); | 265 unsigned char* out, |
| 266 const base::Callback<void(bool)>& callback); |
| 265 | 267 |
| 266 WebKit::WebGLId CopyTexture(WebGLId src_texture, const gfx::Size& size); | 268 void ReadbackTextureSync(WebGLId texture, |
| 269 const gfx::Size& size, |
| 270 unsigned char* out); |
| 271 |
| 272 WebKit::WebGLId CopyAndScaleTexture(WebGLId texture, |
| 273 const gfx::Size& src_size, |
| 274 const gfx::Size& dst_size); |
| 267 | 275 |
| 268 private: | 276 private: |
| 269 // A single request to CopyTextureTo. | 277 // A single request to CropScaleReadbackAndCleanTexture. |
| 270 // Thread-safety notes: the main thread creates instances of this class. The | 278 // Thread-safety notes: the main thread creates instances of this class. The |
| 271 // main thread can cancel the request, before it's handled by the helper | 279 // main thread can cancel the request, before it's handled by the helper |
| 272 // thread, by resetting the texture and pixels fields. Alternatively, the | 280 // thread, by resetting the texture and pixels fields. Alternatively, the |
| 273 // thread marks that it handles the request by resetting the pixels field | 281 // thread marks that it handles the request by resetting the pixels field |
| 274 // (meaning it guarantees that the callback with be called). | 282 // (meaning it guarantees that the callback with be called). |
| 275 // In either case, the callback must be called exactly once, and the texture | 283 // In either case, the callback must be called exactly once, and the texture |
| 276 // must be deleted by the main thread context. | 284 // must be deleted by the main thread context. |
| 277 struct Request : public base::RefCountedThreadSafe<Request> { | 285 struct Request : public base::RefCountedThreadSafe<Request> { |
| 278 Request(CopyTextureToImpl* impl, | 286 Request(CopyTextureToImpl* impl, |
| 279 WebGLId texture_, | 287 WebGLId texture_, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 WebGraphicsContext3D* context, | 325 WebGraphicsContext3D* context, |
| 318 scoped_refptr<base::TaskRunner> reply_loop); | 326 scoped_refptr<base::TaskRunner> reply_loop); |
| 319 static void ReadBackFramebufferComplete(scoped_refptr<Request> request, | 327 static void ReadBackFramebufferComplete(scoped_refptr<Request> request, |
| 320 bool result); | 328 bool result); |
| 321 void FinishRequest(scoped_refptr<Request> request); | 329 void FinishRequest(scoped_refptr<Request> request); |
| 322 void CancelRequests(); | 330 void CancelRequests(); |
| 323 | 331 |
| 324 // Interleaved array of 2-dimentional vertex positions (x, y) and | 332 // Interleaved array of 2-dimentional vertex positions (x, y) and |
| 325 // 2-dimentional texture coordinates (s, t). | 333 // 2-dimentional texture coordinates (s, t). |
| 326 static const WebKit::WGC3Dfloat kVertexAttributes[]; | 334 static const WebKit::WGC3Dfloat kVertexAttributes[]; |
| 327 // Shader sources used for GLHelper::CopyTextureTo | 335 // Shader sources used for GLHelper::CropScaleReadbackAndCleanTexture and |
| 336 // GLHelper::ReadbackTextureSync |
| 328 static const WebKit::WGC3Dchar kCopyVertexShader[]; | 337 static const WebKit::WGC3Dchar kCopyVertexShader[]; |
| 329 static const WebKit::WGC3Dchar kCopyFragmentShader[]; | 338 static const WebKit::WGC3Dchar kCopyFragmentShader[]; |
| 330 | 339 |
| 331 WebGraphicsContext3D* context_; | 340 WebGraphicsContext3D* context_; |
| 332 WebGraphicsContext3D* context_for_thread_; | 341 WebGraphicsContext3D* context_for_thread_; |
| 333 GLHelper* helper_; | 342 GLHelper* helper_; |
| 334 | 343 |
| 335 // A scoped flush that will ensure all resource deletions are flushed when | 344 // A scoped flush that will ensure all resource deletions are flushed when |
| 336 // this object is destroyed. Must be declared before other Scoped* fields. | 345 // this object is destroyed. Must be declared before other Scoped* fields. |
| 337 ScopedFlush flush_; | 346 ScopedFlush flush_; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 if (!context_for_thread_) | 494 if (!context_for_thread_) |
| 486 return; | 495 return; |
| 487 | 496 |
| 488 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( | 497 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( |
| 489 FROM_HERE, | 498 FROM_HERE, |
| 490 base::Bind(&DeleteContext, | 499 base::Bind(&DeleteContext, |
| 491 context_for_thread_)); | 500 context_for_thread_)); |
| 492 context_for_thread_ = NULL; | 501 context_for_thread_ = NULL; |
| 493 } | 502 } |
| 494 | 503 |
| 495 void GLHelper::CopyTextureToImpl::CopyTextureTo( | 504 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
| 496 WebGLId src_texture, | 505 WebGLId src_texture, |
| 497 const gfx::Size& src_size, | 506 const gfx::Size& src_size, |
| 498 const gfx::Rect& src_subrect, | 507 const gfx::Rect& src_subrect, |
| 499 const gfx::Size& dst_size, | 508 const gfx::Size& dst_size, |
| 500 unsigned char* out, | 509 unsigned char* out, |
| 501 const base::Callback<void(bool)>& callback) { | 510 const base::Callback<void(bool)>& callback) { |
| 502 if (!context_for_thread_) { | 511 if (!context_for_thread_) { |
| 503 callback.Run(false); | 512 callback.Run(false); |
| 504 return; | 513 return; |
| 505 } | 514 } |
| 506 | 515 |
| 507 WebGLId texture = ScaleTexture(src_texture, src_size, src_subrect, dst_size); | 516 WebGLId texture = ScaleTexture(src_texture, src_size, src_subrect, dst_size); |
| 508 context_->flush(); | 517 context_->flush(); |
| 509 scoped_refptr<Request> request = | 518 scoped_refptr<Request> request = |
| 510 new Request(this, texture, dst_size, out, callback); | 519 new Request(this, texture, dst_size, out, callback); |
| 511 request_queue_.push(request); | 520 request_queue_.push(request); |
| 512 | 521 |
| 513 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, | 522 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, |
| 514 base::Bind(&ReadBackFramebuffer, | 523 base::Bind(&ReadBackFramebuffer, |
| 515 request, | 524 request, |
| 516 context_for_thread_, | 525 context_for_thread_, |
| 517 base::MessageLoopProxy::current())); | 526 base::MessageLoopProxy::current())); |
| 518 } | 527 } |
| 519 | 528 |
| 520 WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyTexture( | 529 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(WebGLId texture, |
| 530 const gfx::Size& size, |
| 531 unsigned char* out) { |
| 532 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
| 533 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( |
| 534 context_, dst_framebuffer); |
| 535 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); |
| 536 context_->framebufferTexture2D(GL_FRAMEBUFFER, |
| 537 GL_COLOR_ATTACHMENT0, |
| 538 GL_TEXTURE_2D, |
| 539 texture, |
| 540 0); |
| 541 context_->readPixels(0, |
| 542 0, |
| 543 size.width(), |
| 544 size.height(), |
| 545 GL_RGBA, |
| 546 GL_UNSIGNED_BYTE, |
| 547 out); |
| 548 } |
| 549 |
| 550 WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture( |
| 521 WebGLId src_texture, | 551 WebGLId src_texture, |
| 522 const gfx::Size& size) { | 552 const gfx::Size& src_size, |
| 523 if (!context_for_thread_) | 553 const gfx::Size& dst_size) { |
| 524 return 0; | 554 return ScaleTexture(src_texture, src_size, gfx::Rect(src_size), dst_size); |
| 525 return ScaleTexture(src_texture, size, gfx::Rect(size), size); | |
| 526 } | 555 } |
| 527 | 556 |
| 528 void GLHelper::CopyTextureToImpl::ReadBackFramebuffer( | 557 void GLHelper::CopyTextureToImpl::ReadBackFramebuffer( |
| 529 scoped_refptr<Request> request, | 558 scoped_refptr<Request> request, |
| 530 WebGraphicsContext3D* context, | 559 WebGraphicsContext3D* context, |
| 531 scoped_refptr<base::TaskRunner> reply_loop) { | 560 scoped_refptr<base::TaskRunner> reply_loop) { |
| 532 DCHECK(context); | 561 DCHECK(context); |
| 533 if (!context->makeContextCurrent() || context->isContextLost()) { | 562 if (!context->makeContextCurrent() || context->isContextLost()) { |
| 534 base::AutoLock auto_lock(request->lock); | 563 base::AutoLock auto_lock(request->lock); |
| 535 if (request->pixels) { | 564 if (request->pixels) { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 // http://crbug.com/125415 | 680 // http://crbug.com/125415 |
| 652 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 681 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 653 event.Wait(); | 682 event.Wait(); |
| 654 } | 683 } |
| 655 } | 684 } |
| 656 | 685 |
| 657 WebGraphicsContext3D* GLHelper::context() const { | 686 WebGraphicsContext3D* GLHelper::context() const { |
| 658 return context_; | 687 return context_; |
| 659 } | 688 } |
| 660 | 689 |
| 661 void GLHelper::CopyTextureTo(WebGLId src_texture, | 690 void GLHelper::CropScaleReadbackAndCleanTexture( |
| 662 const gfx::Size& src_size, | 691 WebGLId src_texture, |
| 663 const gfx::Rect& src_subrect, | 692 const gfx::Size& src_size, |
| 664 const gfx::Size& dst_size, | 693 const gfx::Rect& src_subrect, |
| 665 unsigned char* out, | 694 const gfx::Size& dst_size, |
| 666 const base::Callback<void(bool)>& callback) { | 695 unsigned char* out, |
| 696 const base::Callback<void(bool)>& callback) { |
| 667 InitCopyTextToImpl(); | 697 InitCopyTextToImpl(); |
| 668 copy_texture_to_impl_->CopyTextureTo(src_texture, | 698 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture, |
| 669 src_size, | 699 src_size, |
| 670 src_subrect, | 700 src_subrect, |
| 671 dst_size, | 701 dst_size, |
| 672 out, | 702 out, |
| 673 callback); | 703 callback); |
| 704 } |
| 705 |
| 706 void GLHelper::ReadbackTextureSync(WebKit::WebGLId texture, |
| 707 const gfx::Size& size, |
| 708 unsigned char* out) { |
| 709 InitCopyTextToImpl(); |
| 710 copy_texture_to_impl_->ReadbackTextureSync(texture, |
| 711 size, |
| 712 out); |
| 674 } | 713 } |
| 675 | 714 |
| 676 WebKit::WebGLId GLHelper::CopyTexture(WebKit::WebGLId texture, | 715 WebKit::WebGLId GLHelper::CopyTexture(WebKit::WebGLId texture, |
| 677 const gfx::Size& size) { | 716 const gfx::Size& size) { |
| 678 InitCopyTextToImpl(); | 717 InitCopyTextToImpl(); |
| 679 return copy_texture_to_impl_->CopyTexture(texture, size); | 718 return copy_texture_to_impl_->CopyAndScaleTexture(texture, size, size); |
| 719 } |
| 720 |
| 721 WebKit::WebGLId GLHelper::CopyAndScaleTexture(WebKit::WebGLId texture, |
| 722 const gfx::Size& src_size, |
| 723 const gfx::Size& dst_size) { |
| 724 InitCopyTextToImpl(); |
| 725 return copy_texture_to_impl_->CopyAndScaleTexture(texture, |
| 726 src_size, |
| 727 dst_size); |
| 680 } | 728 } |
| 681 | 729 |
| 682 WebGLId GLHelper::CompileShaderFromSource( | 730 WebGLId GLHelper::CompileShaderFromSource( |
| 683 const WebKit::WGC3Dchar* source, | 731 const WebKit::WGC3Dchar* source, |
| 684 WebKit::WGC3Denum type) { | 732 WebKit::WGC3Denum type) { |
| 685 ScopedShader shader(context_, context_->createShader(type)); | 733 ScopedShader shader(context_, context_->createShader(type)); |
| 686 context_->shaderSource(shader, source); | 734 context_->shaderSource(shader, source); |
| 687 context_->compileShader(shader); | 735 context_->compileShader(shader); |
| 688 WebKit::WGC3Dint compile_status = 0; | 736 WebKit::WGC3Dint compile_status = 0; |
| 689 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | 737 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); |
| 690 if (!compile_status) { | 738 if (!compile_status) { |
| 691 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); | 739 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); |
| 692 return 0; | 740 return 0; |
| 693 } | 741 } |
| 694 return shader.Detach(); | 742 return shader.Detach(); |
| 695 } | 743 } |
| 696 | 744 |
| 697 void GLHelper::InitCopyTextToImpl() { | 745 void GLHelper::InitCopyTextToImpl() { |
| 698 // Lazily initialize |copy_texture_to_impl_| | 746 // Lazily initialize |copy_texture_to_impl_| |
| 699 if (!copy_texture_to_impl_.get()) | 747 if (!copy_texture_to_impl_.get()) |
| 700 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, | 748 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, |
| 701 context_for_thread_, | 749 context_for_thread_, |
| 702 this)); | 750 this)); |
| 703 | 751 |
| 704 } | 752 } |
| 705 | 753 |
| 706 } // namespace content | 754 } // namespace content |
| OLD | NEW |