Chromium Code Reviews| 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;" |
| 352 "void main() {" | 359 "void main() {" |
| 353 " gl_Position = vec4(a_position, 0.0, 1.0);" | 360 " gl_Position = vec4(a_position, 0.0, 1.0);" |
| 354 " v_texcoord = a_texcoord;" | 361 " v_texcoord = a_texcoord;" |
| 355 "}"; | 362 "}"; |
| 356 | 363 |
| 357 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = | 364 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = |
| 358 "precision mediump float;" | 365 "precision mediump float;" |
| 359 "varying vec2 v_texcoord;" | 366 "varying vec2 v_texcoord;" |
| 367 "uniform vec4 src_subrect;" | |
| 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," |
| 371 " src_subrect.xy + v_texcoord * src_subrect.zw);" | |
|
piman
2012/07/26 00:04:51
It would be better to do the UV transformation in
mazda
2012/07/26 02:20:04
Oh, that's right. Fixed.
| |
| 363 "}"; | 372 "}"; |
| 364 | 373 |
| 365 void GLHelper::CopyTextureToImpl::InitBuffer() { | 374 void GLHelper::CopyTextureToImpl::InitBuffer() { |
| 366 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( | 375 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( |
| 367 context_, vertex_attributes_buffer_); | 376 context_, vertex_attributes_buffer_); |
| 368 context_->bufferData(GL_ARRAY_BUFFER, | 377 context_->bufferData(GL_ARRAY_BUFFER, |
| 369 sizeof(kVertexAttributes), | 378 sizeof(kVertexAttributes), |
| 370 kVertexAttributes, | 379 kVertexAttributes, |
| 371 GL_STATIC_DRAW); | 380 GL_STATIC_DRAW); |
| 372 } | 381 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 386 WebKit::WGC3Dint link_status = 0; | 395 WebKit::WGC3Dint link_status = 0; |
| 387 context_->getProgramiv(program_, GL_LINK_STATUS, &link_status); | 396 context_->getProgramiv(program_, GL_LINK_STATUS, &link_status); |
| 388 if (!link_status) { | 397 if (!link_status) { |
| 389 LOG(ERROR) << std::string(context_->getProgramInfoLog(program_).utf8()); | 398 LOG(ERROR) << std::string(context_->getProgramInfoLog(program_).utf8()); |
| 390 return; | 399 return; |
| 391 } | 400 } |
| 392 | 401 |
| 393 position_location_ = context_->getAttribLocation(program_, "a_position"); | 402 position_location_ = context_->getAttribLocation(program_, "a_position"); |
| 394 texcoord_location_ = context_->getAttribLocation(program_, "a_texcoord"); | 403 texcoord_location_ = context_->getAttribLocation(program_, "a_texcoord"); |
| 395 texture_location_ = context_->getUniformLocation(program_, "s_texture"); | 404 texture_location_ = context_->getUniformLocation(program_, "s_texture"); |
| 405 src_subrect_location_ = context_->getUniformLocation(program_, "src_subrect"); | |
| 396 } | 406 } |
| 397 | 407 |
| 398 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( | 408 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( |
| 399 WebGLId src_texture, | 409 WebGLId src_texture, |
| 400 const gfx::Size& src_size, | 410 const gfx::Size& src_size, |
| 411 const gfx::Rect& src_subrect, | |
| 401 const gfx::Size& dst_size) { | 412 const gfx::Size& dst_size) { |
| 402 WebGLId dst_texture = context_->createTexture(); | 413 WebGLId dst_texture = context_->createTexture(); |
| 403 { | 414 { |
| 404 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 415 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
| 405 ScopedFramebufferBinder<GL_DRAW_FRAMEBUFFER> framebuffer_binder( | 416 ScopedFramebufferBinder<GL_DRAW_FRAMEBUFFER> framebuffer_binder( |
| 406 context_, dst_framebuffer); | 417 context_, dst_framebuffer); |
| 407 { | 418 { |
| 408 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( | 419 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( |
| 409 context_, dst_texture); | 420 context_, dst_texture); |
| 410 context_->texImage2D(GL_TEXTURE_2D, | 421 context_->texImage2D(GL_TEXTURE_2D, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 context_->vertexAttribPointer(texcoord_location_, | 454 context_->vertexAttribPointer(texcoord_location_, |
| 444 2, | 455 2, |
| 445 GL_FLOAT, | 456 GL_FLOAT, |
| 446 GL_FALSE, | 457 GL_FALSE, |
| 447 4 * sizeof(WebKit::WGC3Dfloat), | 458 4 * sizeof(WebKit::WGC3Dfloat), |
| 448 offset); | 459 offset); |
| 449 context_->enableVertexAttribArray(texcoord_location_); | 460 context_->enableVertexAttribArray(texcoord_location_); |
| 450 | 461 |
| 451 context_->uniform1i(texture_location_, 0); | 462 context_->uniform1i(texture_location_, 0); |
| 452 | 463 |
| 464 // Convert |src_subrect| to texture coordinates. | |
| 465 GLfloat src_subrect_texcoord[] = { | |
| 466 static_cast<float>(src_subrect.x()) / src_size.width(), | |
| 467 static_cast<float>(src_subrect.y()) / src_size.height(), | |
| 468 static_cast<float>(src_subrect.width()) / src_size.width(), | |
| 469 static_cast<float>(src_subrect.height()) / src_size.height(), | |
| 470 }; | |
| 471 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); | |
| 472 | |
| 453 // Conduct texture mapping by drawing a quad composed of two triangles. | 473 // Conduct texture mapping by drawing a quad composed of two triangles. |
| 454 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); | 474 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 455 } | 475 } |
| 456 return dst_texture; | 476 return dst_texture; |
| 457 } | 477 } |
| 458 | 478 |
| 459 void GLHelper::CopyTextureToImpl::DeleteContextForThread() { | 479 void GLHelper::CopyTextureToImpl::DeleteContextForThread() { |
| 460 if (!context_for_thread_) | 480 if (!context_for_thread_) |
| 461 return; | 481 return; |
| 462 | 482 |
| 463 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( | 483 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( |
| 464 FROM_HERE, | 484 FROM_HERE, |
| 465 base::Bind(&DeleteContext, | 485 base::Bind(&DeleteContext, |
| 466 context_for_thread_)); | 486 context_for_thread_)); |
| 467 context_for_thread_ = NULL; | 487 context_for_thread_ = NULL; |
| 468 } | 488 } |
| 469 | 489 |
| 470 void GLHelper::CopyTextureToImpl::CopyTextureTo( | 490 void GLHelper::CopyTextureToImpl::CopyTextureTo( |
| 471 WebGLId src_texture, | 491 WebGLId src_texture, |
| 472 const gfx::Size& src_size, | 492 const gfx::Size& src_size, |
| 493 const gfx::Rect& src_subrect, | |
| 473 const gfx::Size& dst_size, | 494 const gfx::Size& dst_size, |
| 474 unsigned char* out, | 495 unsigned char* out, |
| 475 const base::Callback<void(bool)>& callback) { | 496 const base::Callback<void(bool)>& callback) { |
| 476 if (!context_for_thread_) { | 497 if (!context_for_thread_) { |
| 477 callback.Run(false); | 498 callback.Run(false); |
| 478 return; | 499 return; |
| 479 } | 500 } |
| 480 | 501 |
| 481 WebGLId texture = ScaleTexture(src_texture, src_size, dst_size); | 502 WebGLId texture = ScaleTexture(src_texture, src_size, src_subrect, dst_size); |
| 482 context_->flush(); | 503 context_->flush(); |
| 483 scoped_refptr<Request> request = | 504 scoped_refptr<Request> request = |
| 484 new Request(this, texture, dst_size, out, callback); | 505 new Request(this, texture, dst_size, out, callback); |
| 485 request_queue_.push(request); | 506 request_queue_.push(request); |
| 486 | 507 |
| 487 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, | 508 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, |
| 488 base::Bind(&ReadBackFramebuffer, | 509 base::Bind(&ReadBackFramebuffer, |
| 489 request, | 510 request, |
| 490 context_for_thread_, | 511 context_for_thread_, |
| 491 base::MessageLoopProxy::current())); | 512 base::MessageLoopProxy::current())); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 event.Wait(); | 640 event.Wait(); |
| 620 } | 641 } |
| 621 } | 642 } |
| 622 | 643 |
| 623 WebGraphicsContext3D* GLHelper::context() const { | 644 WebGraphicsContext3D* GLHelper::context() const { |
| 624 return context_; | 645 return context_; |
| 625 } | 646 } |
| 626 | 647 |
| 627 void GLHelper::CopyTextureTo(WebGLId src_texture, | 648 void GLHelper::CopyTextureTo(WebGLId src_texture, |
| 628 const gfx::Size& src_size, | 649 const gfx::Size& src_size, |
| 650 const gfx::Rect& src_subrect, | |
| 629 const gfx::Size& dst_size, | 651 const gfx::Size& dst_size, |
| 630 unsigned char* out, | 652 unsigned char* out, |
| 631 const base::Callback<void(bool)>& callback) { | 653 const base::Callback<void(bool)>& callback) { |
| 632 // Lazily initialize |copy_texture_to_impl_| | 654 // Lazily initialize |copy_texture_to_impl_| |
| 633 if (!copy_texture_to_impl_.get()) | 655 if (!copy_texture_to_impl_.get()) |
| 634 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, | 656 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, |
| 635 context_for_thread_, | 657 context_for_thread_, |
| 636 this)); | 658 this)); |
| 637 | 659 |
| 638 copy_texture_to_impl_->CopyTextureTo(src_texture, | 660 copy_texture_to_impl_->CopyTextureTo(src_texture, |
| 639 src_size, | 661 src_size, |
| 662 src_subrect, | |
| 640 dst_size, | 663 dst_size, |
| 641 out, | 664 out, |
| 642 callback); | 665 callback); |
| 643 } | 666 } |
| 644 | 667 |
| 645 WebGLId GLHelper::CompileShaderFromSource( | 668 WebGLId GLHelper::CompileShaderFromSource( |
| 646 const WebKit::WGC3Dchar* source, | 669 const WebKit::WGC3Dchar* source, |
| 647 WebKit::WGC3Denum type) { | 670 WebKit::WGC3Denum type) { |
| 648 ScopedShader shader(context_, context_->createShader(type)); | 671 ScopedShader shader(context_, context_->createShader(type)); |
| 649 context_->shaderSource(shader, source); | 672 context_->shaderSource(shader, source); |
| 650 context_->compileShader(shader); | 673 context_->compileShader(shader); |
| 651 WebKit::WGC3Dint compile_status = 0; | 674 WebKit::WGC3Dint compile_status = 0; |
| 652 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | 675 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); |
| 653 if (!compile_status) { | 676 if (!compile_status) { |
| 654 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); | 677 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); |
| 655 return 0; | 678 return 0; |
| 656 } | 679 } |
| 657 return shader.Detach(); | 680 return shader.Detach(); |
| 658 } | 681 } |
| 659 | 682 |
| 660 } // namespace content | 683 } // namespace content |
| OLD | NEW |