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 |