| 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
| 15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
| 16 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
| 17 #include "base/threading/thread_restrictions.h" | 17 #include "base/threading/thread_restrictions.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h
" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h
" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
| 20 #include "ui/gfx/rect.h" |
| 20 #include "ui/gfx/size.h" | 21 #include "ui/gfx/size.h" |
| 21 #include "ui/gl/gl_bindings.h" | 22 #include "ui/gl/gl_bindings.h" |
| 22 | 23 |
| 23 using WebKit::WebGLId; | 24 using WebKit::WebGLId; |
| 24 using WebKit::WebGraphicsContext3D; | 25 using WebKit::WebGraphicsContext3D; |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 const char kGLHelperThreadName[] = "GLHelperThread"; | 29 const char kGLHelperThreadName[] = "GLHelperThread"; |
| 29 | 30 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 ~CopyTextureToImpl() { | 248 ~CopyTextureToImpl() { |
| 248 CancelRequests(); | 249 CancelRequests(); |
| 249 DeleteContextForThread(); | 250 DeleteContextForThread(); |
| 250 } | 251 } |
| 251 | 252 |
| 252 void InitBuffer(); | 253 void InitBuffer(); |
| 253 void InitProgram(); | 254 void InitProgram(); |
| 254 | 255 |
| 255 void CopyTextureTo(WebGLId src_texture, | 256 void CopyTextureTo(WebGLId src_texture, |
| 256 const gfx::Size& src_size, | 257 const gfx::Size& src_size, |
| 258 const gfx::Rect& src_subrect, |
| 257 const gfx::Size& dst_size, | 259 const gfx::Size& dst_size, |
| 258 unsigned char* out, | 260 unsigned char* out, |
| 259 const base::Callback<void(bool)>& callback); | 261 const base::Callback<void(bool)>& callback); |
| 260 private: | 262 private: |
| 261 // A single request to CopyTextureTo. | 263 // A single request to CopyTextureTo. |
| 262 // Thread-safety notes: the main thread creates instances of this class. The | 264 // Thread-safety notes: the main thread creates instances of this class. The |
| 263 // main thread can cancel the request, before it's handled by the helper | 265 // main thread can cancel the request, before it's handled by the helper |
| 264 // thread, by resetting the texture and pixels fields. Alternatively, the | 266 // thread, by resetting the texture and pixels fields. Alternatively, the |
| 265 // thread marks that it handles the request by resetting the pixels field | 267 // thread marks that it handles the request by resetting the pixels field |
| 266 // (meaning it guarantees that the callback with be called). | 268 // (meaning it guarantees that the callback with be called). |
| (...skipping 21 matching lines...) Expand all Loading... |
| 288 // Locks access to below members, which can be accessed on any thread. | 290 // Locks access to below members, which can be accessed on any thread. |
| 289 base::Lock lock; | 291 base::Lock lock; |
| 290 WebGLId texture; | 292 WebGLId texture; |
| 291 unsigned char* pixels; | 293 unsigned char* pixels; |
| 292 | 294 |
| 293 private: | 295 private: |
| 294 friend class base::RefCountedThreadSafe<Request>; | 296 friend class base::RefCountedThreadSafe<Request>; |
| 295 ~Request() {} | 297 ~Request() {} |
| 296 }; | 298 }; |
| 297 | 299 |
| 298 // Returns the id of a framebuffer that | 300 // Copies the block of pixels specified with |src_subrect| from |src_texture|, |
| 301 // scales it to |dst_size|, writes it into a texture, and returns its ID. |
| 302 // |src_size| is the size of |src_texture|. |
| 299 WebGLId ScaleTexture(WebGLId src_texture, | 303 WebGLId ScaleTexture(WebGLId src_texture, |
| 300 const gfx::Size& src_size, | 304 const gfx::Size& src_size, |
| 301 const gfx::Size& dst_size); | 305 const gfx::Rect& src_subrect, |
| 306 const gfx::Size& dst_size); |
| 302 | 307 |
| 303 // Deletes the context for GLHelperThread. | 308 // Deletes the context for GLHelperThread. |
| 304 void DeleteContextForThread(); | 309 void DeleteContextForThread(); |
| 305 static void ReadBackFramebuffer(scoped_refptr<Request> request, | 310 static void ReadBackFramebuffer(scoped_refptr<Request> request, |
| 306 WebGraphicsContext3D* context, | 311 WebGraphicsContext3D* context, |
| 307 scoped_refptr<base::TaskRunner> reply_loop); | 312 scoped_refptr<base::TaskRunner> reply_loop); |
| 308 static void ReadBackFramebufferComplete(scoped_refptr<Request> request, | 313 static void ReadBackFramebufferComplete(scoped_refptr<Request> request, |
| 309 bool result); | 314 bool result); |
| 310 void FinishRequest(scoped_refptr<Request> request); | 315 void FinishRequest(scoped_refptr<Request> request); |
| 311 void CancelRequests(); | 316 void CancelRequests(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 328 ScopedProgram program_; | 333 ScopedProgram program_; |
| 329 // The buffer that holds the vertices and the texture coordinates data for | 334 // The buffer that holds the vertices and the texture coordinates data for |
| 330 // drawing a quad. | 335 // drawing a quad. |
| 331 ScopedBuffer vertex_attributes_buffer_; | 336 ScopedBuffer vertex_attributes_buffer_; |
| 332 // The location of the position in the program. | 337 // The location of the position in the program. |
| 333 WebKit::WGC3Dint position_location_; | 338 WebKit::WGC3Dint position_location_; |
| 334 // The location of the texture coordinate in the program. | 339 // The location of the texture coordinate in the program. |
| 335 WebKit::WGC3Dint texcoord_location_; | 340 WebKit::WGC3Dint texcoord_location_; |
| 336 // The location of the source texture in the program. | 341 // The location of the source texture in the program. |
| 337 WebKit::WGC3Dint texture_location_; | 342 WebKit::WGC3Dint texture_location_; |
| 343 // The location of the texture coordinate of the sub-rectangle in the program. |
| 344 WebKit::WGC3Dint src_subrect_location_; |
| 338 std::queue<scoped_refptr<Request> > request_queue_; | 345 std::queue<scoped_refptr<Request> > request_queue_; |
| 339 }; | 346 }; |
| 340 | 347 |
| 341 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = { | 348 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = { |
| 342 -1.0f, -1.0f, 0.0f, 0.0f, | 349 -1.0f, -1.0f, 0.0f, 0.0f, |
| 343 1.0f, -1.0f, 1.0f, 0.0f, | 350 1.0f, -1.0f, 1.0f, 0.0f, |
| 344 -1.0f, 1.0f, 0.0f, 1.0f, | 351 -1.0f, 1.0f, 0.0f, 1.0f, |
| 345 1.0f, 1.0f, 1.0f, 1.0f, | 352 1.0f, 1.0f, 1.0f, 1.0f, |
| 346 }; | 353 }; |
| 347 | 354 |
| 348 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyVertexShader[] = | 355 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyVertexShader[] = |
| 349 "attribute vec2 a_position;" | 356 "attribute vec2 a_position;" |
| 350 "attribute vec2 a_texcoord;" | 357 "attribute vec2 a_texcoord;" |
| 351 "varying vec2 v_texcoord;" | 358 "varying vec2 v_texcoord;" |
| 359 "uniform vec4 src_subrect;" |
| 352 "void main() {" | 360 "void main() {" |
| 353 " gl_Position = vec4(a_position, 0.0, 1.0);" | 361 " gl_Position = vec4(a_position, 0.0, 1.0);" |
| 354 " v_texcoord = a_texcoord;" | 362 " v_texcoord = src_subrect.xy + a_texcoord * src_subrect.zw;" |
| 355 "}"; | 363 "}"; |
| 356 | 364 |
| 357 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = | 365 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = |
| 358 "precision mediump float;" | 366 "precision mediump float;" |
| 359 "varying vec2 v_texcoord;" | 367 "varying vec2 v_texcoord;" |
| 360 "uniform sampler2D s_texture;" | 368 "uniform sampler2D s_texture;" |
| 361 "void main() {" | 369 "void main() {" |
| 362 " gl_FragColor = texture2D(s_texture, v_texcoord);" | 370 " gl_FragColor = texture2D(s_texture, v_texcoord);" |
| 363 "}"; | 371 "}"; |
| 364 | 372 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 386 WebKit::WGC3Dint link_status = 0; | 394 WebKit::WGC3Dint link_status = 0; |
| 387 context_->getProgramiv(program_, GL_LINK_STATUS, &link_status); | 395 context_->getProgramiv(program_, GL_LINK_STATUS, &link_status); |
| 388 if (!link_status) { | 396 if (!link_status) { |
| 389 LOG(ERROR) << std::string(context_->getProgramInfoLog(program_).utf8()); | 397 LOG(ERROR) << std::string(context_->getProgramInfoLog(program_).utf8()); |
| 390 return; | 398 return; |
| 391 } | 399 } |
| 392 | 400 |
| 393 position_location_ = context_->getAttribLocation(program_, "a_position"); | 401 position_location_ = context_->getAttribLocation(program_, "a_position"); |
| 394 texcoord_location_ = context_->getAttribLocation(program_, "a_texcoord"); | 402 texcoord_location_ = context_->getAttribLocation(program_, "a_texcoord"); |
| 395 texture_location_ = context_->getUniformLocation(program_, "s_texture"); | 403 texture_location_ = context_->getUniformLocation(program_, "s_texture"); |
| 404 src_subrect_location_ = context_->getUniformLocation(program_, "src_subrect"); |
| 396 } | 405 } |
| 397 | 406 |
| 398 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( | 407 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( |
| 399 WebGLId src_texture, | 408 WebGLId src_texture, |
| 400 const gfx::Size& src_size, | 409 const gfx::Size& src_size, |
| 410 const gfx::Rect& src_subrect, |
| 401 const gfx::Size& dst_size) { | 411 const gfx::Size& dst_size) { |
| 402 WebGLId dst_texture = context_->createTexture(); | 412 WebGLId dst_texture = context_->createTexture(); |
| 403 { | 413 { |
| 404 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 414 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
| 405 ScopedFramebufferBinder<GL_DRAW_FRAMEBUFFER> framebuffer_binder( | 415 ScopedFramebufferBinder<GL_DRAW_FRAMEBUFFER> framebuffer_binder( |
| 406 context_, dst_framebuffer); | 416 context_, dst_framebuffer); |
| 407 { | 417 { |
| 408 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( | 418 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( |
| 409 context_, dst_texture); | 419 context_, dst_texture); |
| 410 context_->texImage2D(GL_TEXTURE_2D, | 420 context_->texImage2D(GL_TEXTURE_2D, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 context_->vertexAttribPointer(texcoord_location_, | 453 context_->vertexAttribPointer(texcoord_location_, |
| 444 2, | 454 2, |
| 445 GL_FLOAT, | 455 GL_FLOAT, |
| 446 GL_FALSE, | 456 GL_FALSE, |
| 447 4 * sizeof(WebKit::WGC3Dfloat), | 457 4 * sizeof(WebKit::WGC3Dfloat), |
| 448 offset); | 458 offset); |
| 449 context_->enableVertexAttribArray(texcoord_location_); | 459 context_->enableVertexAttribArray(texcoord_location_); |
| 450 | 460 |
| 451 context_->uniform1i(texture_location_, 0); | 461 context_->uniform1i(texture_location_, 0); |
| 452 | 462 |
| 463 // Convert |src_subrect| to texture coordinates. |
| 464 GLfloat src_subrect_texcoord[] = { |
| 465 static_cast<float>(src_subrect.x()) / src_size.width(), |
| 466 static_cast<float>(src_subrect.y()) / src_size.height(), |
| 467 static_cast<float>(src_subrect.width()) / src_size.width(), |
| 468 static_cast<float>(src_subrect.height()) / src_size.height(), |
| 469 }; |
| 470 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); |
| 471 |
| 453 // Conduct texture mapping by drawing a quad composed of two triangles. | 472 // Conduct texture mapping by drawing a quad composed of two triangles. |
| 454 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); | 473 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 455 } | 474 } |
| 456 return dst_texture; | 475 return dst_texture; |
| 457 } | 476 } |
| 458 | 477 |
| 459 void GLHelper::CopyTextureToImpl::DeleteContextForThread() { | 478 void GLHelper::CopyTextureToImpl::DeleteContextForThread() { |
| 460 if (!context_for_thread_) | 479 if (!context_for_thread_) |
| 461 return; | 480 return; |
| 462 | 481 |
| 463 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( | 482 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( |
| 464 FROM_HERE, | 483 FROM_HERE, |
| 465 base::Bind(&DeleteContext, | 484 base::Bind(&DeleteContext, |
| 466 context_for_thread_)); | 485 context_for_thread_)); |
| 467 context_for_thread_ = NULL; | 486 context_for_thread_ = NULL; |
| 468 } | 487 } |
| 469 | 488 |
| 470 void GLHelper::CopyTextureToImpl::CopyTextureTo( | 489 void GLHelper::CopyTextureToImpl::CopyTextureTo( |
| 471 WebGLId src_texture, | 490 WebGLId src_texture, |
| 472 const gfx::Size& src_size, | 491 const gfx::Size& src_size, |
| 492 const gfx::Rect& src_subrect, |
| 473 const gfx::Size& dst_size, | 493 const gfx::Size& dst_size, |
| 474 unsigned char* out, | 494 unsigned char* out, |
| 475 const base::Callback<void(bool)>& callback) { | 495 const base::Callback<void(bool)>& callback) { |
| 476 if (!context_for_thread_) { | 496 if (!context_for_thread_) { |
| 477 callback.Run(false); | 497 callback.Run(false); |
| 478 return; | 498 return; |
| 479 } | 499 } |
| 480 | 500 |
| 481 WebGLId texture = ScaleTexture(src_texture, src_size, dst_size); | 501 WebGLId texture = ScaleTexture(src_texture, src_size, src_subrect, dst_size); |
| 482 context_->flush(); | 502 context_->flush(); |
| 483 scoped_refptr<Request> request = | 503 scoped_refptr<Request> request = |
| 484 new Request(this, texture, dst_size, out, callback); | 504 new Request(this, texture, dst_size, out, callback); |
| 485 request_queue_.push(request); | 505 request_queue_.push(request); |
| 486 | 506 |
| 487 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, | 507 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, |
| 488 base::Bind(&ReadBackFramebuffer, | 508 base::Bind(&ReadBackFramebuffer, |
| 489 request, | 509 request, |
| 490 context_for_thread_, | 510 context_for_thread_, |
| 491 base::MessageLoopProxy::current())); | 511 base::MessageLoopProxy::current())); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 event.Wait(); | 639 event.Wait(); |
| 620 } | 640 } |
| 621 } | 641 } |
| 622 | 642 |
| 623 WebGraphicsContext3D* GLHelper::context() const { | 643 WebGraphicsContext3D* GLHelper::context() const { |
| 624 return context_; | 644 return context_; |
| 625 } | 645 } |
| 626 | 646 |
| 627 void GLHelper::CopyTextureTo(WebGLId src_texture, | 647 void GLHelper::CopyTextureTo(WebGLId src_texture, |
| 628 const gfx::Size& src_size, | 648 const gfx::Size& src_size, |
| 649 const gfx::Rect& src_subrect, |
| 629 const gfx::Size& dst_size, | 650 const gfx::Size& dst_size, |
| 630 unsigned char* out, | 651 unsigned char* out, |
| 631 const base::Callback<void(bool)>& callback) { | 652 const base::Callback<void(bool)>& callback) { |
| 632 // Lazily initialize |copy_texture_to_impl_| | 653 // Lazily initialize |copy_texture_to_impl_| |
| 633 if (!copy_texture_to_impl_.get()) | 654 if (!copy_texture_to_impl_.get()) |
| 634 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, | 655 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, |
| 635 context_for_thread_, | 656 context_for_thread_, |
| 636 this)); | 657 this)); |
| 637 | 658 |
| 638 copy_texture_to_impl_->CopyTextureTo(src_texture, | 659 copy_texture_to_impl_->CopyTextureTo(src_texture, |
| 639 src_size, | 660 src_size, |
| 661 src_subrect, |
| 640 dst_size, | 662 dst_size, |
| 641 out, | 663 out, |
| 642 callback); | 664 callback); |
| 643 } | 665 } |
| 644 | 666 |
| 645 WebGLId GLHelper::CompileShaderFromSource( | 667 WebGLId GLHelper::CompileShaderFromSource( |
| 646 const WebKit::WGC3Dchar* source, | 668 const WebKit::WGC3Dchar* source, |
| 647 WebKit::WGC3Denum type) { | 669 WebKit::WGC3Denum type) { |
| 648 ScopedShader shader(context_, context_->createShader(type)); | 670 ScopedShader shader(context_, context_->createShader(type)); |
| 649 context_->shaderSource(shader, source); | 671 context_->shaderSource(shader, source); |
| 650 context_->compileShader(shader); | 672 context_->compileShader(shader); |
| 651 WebKit::WGC3Dint compile_status = 0; | 673 WebKit::WGC3Dint compile_status = 0; |
| 652 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | 674 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); |
| 653 if (!compile_status) { | 675 if (!compile_status) { |
| 654 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); | 676 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); |
| 655 return 0; | 677 return 0; |
| 656 } | 678 } |
| 657 return shader.Detach(); | 679 return shader.Detach(); |
| 658 } | 680 } |
| 659 | 681 |
| 660 } // namespace content | 682 } // namespace content |
| OLD | NEW |