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 |