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 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 uint32 sync_point) { | 135 uint32 sync_point) { |
136 return helper_->ConsumeMailboxToTexture(mailbox, sync_point); | 136 return helper_->ConsumeMailboxToTexture(mailbox, sync_point); |
137 } | 137 } |
138 | 138 |
139 void CropScaleReadbackAndCleanTexture( | 139 void CropScaleReadbackAndCleanTexture( |
140 GLuint src_texture, | 140 GLuint src_texture, |
141 const gfx::Size& src_size, | 141 const gfx::Size& src_size, |
142 const gfx::Rect& src_subrect, | 142 const gfx::Rect& src_subrect, |
143 const gfx::Size& dst_size, | 143 const gfx::Size& dst_size, |
144 unsigned char* out, | 144 unsigned char* out, |
145 const SkColorType color_type, | 145 const SkColorType out_color_type, |
146 const base::Callback<void(bool)>& callback, | 146 const base::Callback<void(bool)>& callback, |
147 GLHelper::ScalerQuality quality); | 147 GLHelper::ScalerQuality quality); |
148 | 148 |
149 void ReadbackTextureSync(GLuint texture, | 149 void ReadbackTextureSync(GLuint texture, |
150 const gfx::Rect& src_rect, | 150 const gfx::Rect& src_rect, |
151 unsigned char* out, | 151 unsigned char* out, |
152 SkColorType format); | 152 SkColorType format); |
153 | 153 |
154 void ReadbackTextureAsync(GLuint texture, | 154 void ReadbackTextureAsync(GLuint texture, |
155 const gfx::Size& dst_size, | 155 const gfx::Size& dst_size, |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 // |src_size| is the size of |src_texture|. | 318 // |src_size| is the size of |src_texture|. |
319 GLuint ScaleTexture(GLuint src_texture, | 319 GLuint ScaleTexture(GLuint src_texture, |
320 const gfx::Size& src_size, | 320 const gfx::Size& src_size, |
321 const gfx::Rect& src_subrect, | 321 const gfx::Rect& src_subrect, |
322 const gfx::Size& dst_size, | 322 const gfx::Size& dst_size, |
323 bool vertically_flip_texture, | 323 bool vertically_flip_texture, |
324 bool swizzle, | 324 bool swizzle, |
325 SkColorType color_type, | 325 SkColorType color_type, |
326 GLHelper::ScalerQuality quality); | 326 GLHelper::ScalerQuality quality); |
327 | 327 |
| 328 // Converts each four consecutive pixels of the source texture into one pixel |
| 329 // in the result texture with each pixel channel representing the grayscale |
| 330 // color of one of the four original pixels: |
| 331 // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X1X2X3X4 |
| 332 // The resulting texture is still an RGBA texture (which is ~4 times narrower |
| 333 // than the original). If rendered directly, it wouldn't show anything useful, |
| 334 // but the data in it can be used to construct a grayscale image. |
| 335 // |encoded_texture_size| is the exact size of the resulting RGBA texture. It |
| 336 // is equal to src_size.width()/4 rounded upwards. Some channels in the last |
| 337 // pixel ((-src_size.width()) % 4) to be exact) are padding and don't contain |
| 338 // useful data. |
| 339 // If swizzle is set to true, the transformed pixels are reordered: |
| 340 // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X3X2X1X4. |
| 341 GLuint EncodeTextureAsGrayscale(GLuint src_texture, |
| 342 const gfx::Size& src_size, |
| 343 gfx::Size* const encoded_texture_size, |
| 344 bool vertically_flip_texture, |
| 345 bool swizzle); |
| 346 |
328 static void nullcallback(bool success) {} | 347 static void nullcallback(bool success) {} |
329 void ReadbackDone(Request *request, int bytes_per_pixel); | 348 void ReadbackDone(Request *request, int bytes_per_pixel); |
330 void FinishRequest(Request* request, bool result); | 349 void FinishRequest(Request* request, bool result); |
331 void CancelRequests(); | 350 void CancelRequests(); |
332 | 351 |
333 static const float kRGBtoYColorWeights[]; | 352 static const float kRGBtoYColorWeights[]; |
334 static const float kRGBtoUColorWeights[]; | 353 static const float kRGBtoUColorWeights[]; |
335 static const float kRGBtoVColorWeights[]; | 354 static const float kRGBtoVColorWeights[]; |
| 355 static const float kRGBtoGrayscaleColorWeights[]; |
336 | 356 |
337 GLES2Interface* gl_; | 357 GLES2Interface* gl_; |
338 gpu::ContextSupport* context_support_; | 358 gpu::ContextSupport* context_support_; |
339 GLHelper* helper_; | 359 GLHelper* helper_; |
340 | 360 |
341 // A scoped flush that will ensure all resource deletions are flushed when | 361 // A scoped flush that will ensure all resource deletions are flushed when |
342 // this object is destroyed. Must be declared before other Scoped* fields. | 362 // this object is destroyed. Must be declared before other Scoped* fields. |
343 ScopedFlush flush_; | 363 ScopedFlush flush_; |
344 | 364 |
345 std::queue<Request*> request_queue_; | 365 std::queue<Request*> request_queue_; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 helper_->CreateScaler(quality, | 417 helper_->CreateScaler(quality, |
398 src_size, | 418 src_size, |
399 src_subrect, | 419 src_subrect, |
400 dst_size, | 420 dst_size, |
401 vertically_flip_texture, | 421 vertically_flip_texture, |
402 swizzle)); | 422 swizzle)); |
403 scaler->Scale(src_texture, dst_texture); | 423 scaler->Scale(src_texture, dst_texture); |
404 return dst_texture; | 424 return dst_texture; |
405 } | 425 } |
406 | 426 |
| 427 GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale( |
| 428 GLuint src_texture, |
| 429 const gfx::Size& src_size, |
| 430 gfx::Size* const encoded_texture_size, |
| 431 bool vertically_flip_texture, |
| 432 bool swizzle) { |
| 433 GLuint dst_texture = 0u; |
| 434 gl_->GenTextures(1, &dst_texture); |
| 435 // The size of the encoded texture. |
| 436 *encoded_texture_size = |
| 437 gfx::Size((src_size.width() + 3) / 4, src_size.height()); |
| 438 { |
| 439 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture); |
| 440 gl_->TexImage2D(GL_TEXTURE_2D, |
| 441 0, |
| 442 GL_RGBA, |
| 443 encoded_texture_size->width(), |
| 444 encoded_texture_size->height(), |
| 445 0, |
| 446 GL_RGBA, |
| 447 GL_UNSIGNED_BYTE, |
| 448 NULL); |
| 449 } |
| 450 |
| 451 helper_->InitScalerImpl(); |
| 452 scoped_ptr<ScalerInterface> grayscale_scaler( |
| 453 helper_->scaler_impl_.get()->CreatePlanarScaler( |
| 454 src_size, |
| 455 gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()), |
| 456 *encoded_texture_size, |
| 457 vertically_flip_texture, |
| 458 swizzle, |
| 459 kRGBtoGrayscaleColorWeights)); |
| 460 grayscale_scaler->Scale(src_texture, dst_texture); |
| 461 return dst_texture; |
| 462 } |
| 463 |
407 void GLHelper::CopyTextureToImpl::ReadbackAsync( | 464 void GLHelper::CopyTextureToImpl::ReadbackAsync( |
408 const gfx::Size& dst_size, | 465 const gfx::Size& dst_size, |
409 int32 bytes_per_row, | 466 int32 bytes_per_row, |
410 int32 row_stride_bytes, | 467 int32 row_stride_bytes, |
411 unsigned char* out, | 468 unsigned char* out, |
412 GLenum format, | 469 GLenum format, |
413 GLenum type, | 470 GLenum type, |
414 size_t bytes_per_pixel, | 471 size_t bytes_per_pixel, |
415 const base::Callback<void(bool)>& callback) { | 472 const base::Callback<void(bool)>& callback) { |
416 TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::ReadbackAsync"); | 473 TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::ReadbackAsync"); |
(...skipping 19 matching lines...) Expand all Loading... |
436 format, | 493 format, |
437 type, | 494 type, |
438 NULL); | 495 NULL); |
439 gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); | 496 gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); |
440 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 497 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
441 context_support_->SignalQuery( | 498 context_support_->SignalQuery( |
442 request->query, | 499 request->query, |
443 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), | 500 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), |
444 request, bytes_per_pixel)); | 501 request, bytes_per_pixel)); |
445 } | 502 } |
| 503 |
446 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( | 504 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
447 GLuint src_texture, | 505 GLuint src_texture, |
448 const gfx::Size& src_size, | 506 const gfx::Size& src_size, |
449 const gfx::Rect& src_subrect, | 507 const gfx::Rect& src_subrect, |
450 const gfx::Size& dst_size, | 508 const gfx::Size& dst_size, |
451 unsigned char* out, | 509 unsigned char* out, |
452 const SkColorType color_type, | 510 const SkColorType out_color_type, |
453 const base::Callback<void(bool)>& callback, | 511 const base::Callback<void(bool)>& callback, |
454 GLHelper::ScalerQuality quality) { | 512 GLHelper::ScalerQuality quality) { |
455 GLenum format, type; | 513 GLenum format, type; |
456 size_t bytes_per_pixel; | 514 size_t bytes_per_pixel; |
457 FormatSupport supported = | 515 SkColorType readback_color_type = out_color_type; |
458 GetReadbackConfig(color_type, true, &format, &type, &bytes_per_pixel); | 516 // Single-component textures are not supported by all GPUs, so we implement |
| 517 // kAlpha_8_SkColorType support here via a special encoding (see below) using |
| 518 // a 32-bit texture to represent an 8-bit image. |
| 519 // Thus we use generic 32-bit readback in this case. |
| 520 if (out_color_type == kAlpha_8_SkColorType) { |
| 521 readback_color_type = kRGBA_8888_SkColorType; |
| 522 } |
| 523 |
| 524 FormatSupport supported = GetReadbackConfig( |
| 525 readback_color_type, true, &format, &type, &bytes_per_pixel); |
| 526 |
459 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) { | 527 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) { |
460 callback.Run(false); | 528 callback.Run(false); |
461 return; | 529 return; |
462 } | 530 } |
463 | 531 |
464 GLuint texture = ScaleTexture(src_texture, | 532 GLuint texture = src_texture; |
465 src_size, | 533 |
466 src_subrect, | 534 // Scale texture if needed |
467 dst_size, | 535 // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we |
468 true, | 536 // can do just as well in EncodeTextureAsGrayscale, which we will do if |
469 (supported == GLHelperReadbackSupport::SWIZZLE), | 537 // out_color_type is kAlpha_8_SkColorType, so let's skip the scaling step |
470 color_type, | 538 // in that case. |
471 quality); | 539 bool scale_texture = out_color_type != kAlpha_8_SkColorType || |
472 DCHECK(texture); | 540 quality != GLHelper::SCALER_QUALITY_FAST; |
| 541 if (scale_texture) { |
| 542 // Don't swizzle during the scale step for kAlpha_8_SkColorType. |
| 543 // We will swizzle in the encode step below if needed. |
| 544 bool scale_swizzle = out_color_type == kAlpha_8_SkColorType |
| 545 ? false |
| 546 : supported == GLHelperReadbackSupport::SWIZZLE; |
| 547 texture = |
| 548 ScaleTexture(src_texture, |
| 549 src_size, |
| 550 src_subrect, |
| 551 dst_size, |
| 552 true, |
| 553 scale_swizzle, |
| 554 out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType |
| 555 : out_color_type, |
| 556 quality); |
| 557 DCHECK(texture); |
| 558 } |
| 559 |
| 560 gfx::Size readback_texture_size = dst_size; |
| 561 // Encode texture to grayscale if needed. |
| 562 if (out_color_type == kAlpha_8_SkColorType) { |
| 563 // Do the vertical flip here if we haven't already done it when we scaled |
| 564 // the texture. |
| 565 bool encode_as_grayscale_vertical_flip = !scale_texture; |
| 566 // EncodeTextureAsGrayscale by default creates a texture which should be |
| 567 // read back as RGBA, so need to swizzle if the readback format is BGRA. |
| 568 bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT; |
| 569 GLuint tmp_texture = |
| 570 EncodeTextureAsGrayscale(texture, |
| 571 dst_size, |
| 572 &readback_texture_size, |
| 573 encode_as_grayscale_vertical_flip, |
| 574 encode_as_grayscale_swizzle); |
| 575 // If the scaled texture was created - delete it |
| 576 if (scale_texture) |
| 577 gl_->DeleteTextures(1, &texture); |
| 578 texture = tmp_texture; |
| 579 DCHECK(texture); |
| 580 } |
| 581 |
| 582 // Readback the pixels of the resulting texture |
473 ScopedFramebuffer dst_framebuffer(gl_); | 583 ScopedFramebuffer dst_framebuffer(gl_); |
474 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, | 584 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, |
475 dst_framebuffer); | 585 dst_framebuffer); |
476 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); | 586 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
477 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, | 587 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, |
478 GL_COLOR_ATTACHMENT0, | 588 GL_COLOR_ATTACHMENT0, |
479 GL_TEXTURE_2D, | 589 GL_TEXTURE_2D, |
480 texture, | 590 texture, |
481 0); | 591 0); |
482 ReadbackAsync(dst_size, | 592 |
483 dst_size.width() * bytes_per_pixel, | 593 int32 bytes_per_row = out_color_type == kAlpha_8_SkColorType |
484 dst_size.width() * bytes_per_pixel, | 594 ? dst_size.width() |
| 595 : dst_size.width() * bytes_per_pixel; |
| 596 |
| 597 ReadbackAsync(readback_texture_size, |
| 598 bytes_per_row, |
| 599 bytes_per_row, |
485 out, | 600 out, |
486 format, | 601 format, |
487 type, | 602 type, |
488 bytes_per_pixel, | 603 bytes_per_pixel, |
489 callback); | 604 callback); |
490 gl_->DeleteTextures(1, &texture); | 605 gl_->DeleteTextures(1, &texture); |
491 } | 606 } |
492 | 607 |
493 void GLHelper::CopyTextureToImpl::ReadbackTextureSync( | 608 void GLHelper::CopyTextureToImpl::ReadbackTextureSync( |
494 GLuint texture, | 609 GLuint texture, |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 readback_support_(new GLHelperReadbackSupport(gl)) {} | 764 readback_support_(new GLHelperReadbackSupport(gl)) {} |
650 | 765 |
651 GLHelper::~GLHelper() {} | 766 GLHelper::~GLHelper() {} |
652 | 767 |
653 void GLHelper::CropScaleReadbackAndCleanTexture( | 768 void GLHelper::CropScaleReadbackAndCleanTexture( |
654 GLuint src_texture, | 769 GLuint src_texture, |
655 const gfx::Size& src_size, | 770 const gfx::Size& src_size, |
656 const gfx::Rect& src_subrect, | 771 const gfx::Rect& src_subrect, |
657 const gfx::Size& dst_size, | 772 const gfx::Size& dst_size, |
658 unsigned char* out, | 773 unsigned char* out, |
659 const SkColorType color_type, | 774 const SkColorType out_color_type, |
660 const base::Callback<void(bool)>& callback, | 775 const base::Callback<void(bool)>& callback, |
661 GLHelper::ScalerQuality quality) { | 776 GLHelper::ScalerQuality quality) { |
662 InitCopyTextToImpl(); | 777 InitCopyTextToImpl(); |
663 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture( | 778 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture, |
664 src_texture, | 779 src_size, |
665 src_size, | 780 src_subrect, |
666 src_subrect, | 781 dst_size, |
667 dst_size, | 782 out, |
668 out, | 783 out_color_type, |
669 color_type, | 784 callback, |
670 callback, | 785 quality); |
671 quality); | |
672 } | 786 } |
673 | 787 |
674 void GLHelper::CropScaleReadbackAndCleanMailbox( | 788 void GLHelper::CropScaleReadbackAndCleanMailbox( |
675 const gpu::Mailbox& src_mailbox, | 789 const gpu::Mailbox& src_mailbox, |
676 uint32 sync_point, | 790 uint32 sync_point, |
677 const gfx::Size& src_size, | 791 const gfx::Size& src_size, |
678 const gfx::Rect& src_subrect, | 792 const gfx::Rect& src_subrect, |
679 const gfx::Size& dst_size, | 793 const gfx::Size& dst_size, |
680 unsigned char* out, | 794 unsigned char* out, |
681 const SkColorType color_type, | 795 const SkColorType out_color_type, |
682 const base::Callback<void(bool)>& callback, | 796 const base::Callback<void(bool)>& callback, |
683 GLHelper::ScalerQuality quality) { | 797 GLHelper::ScalerQuality quality) { |
684 GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); | 798 GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); |
685 CropScaleReadbackAndCleanTexture( | 799 CropScaleReadbackAndCleanTexture(mailbox_texture, |
686 mailbox_texture, src_size, src_subrect, dst_size, out, | 800 src_size, |
687 color_type, | 801 src_subrect, |
688 callback, | 802 dst_size, |
689 quality); | 803 out, |
| 804 out_color_type, |
| 805 callback, |
| 806 quality); |
690 gl_->DeleteTextures(1, &mailbox_texture); | 807 gl_->DeleteTextures(1, &mailbox_texture); |
691 } | 808 } |
692 | 809 |
693 void GLHelper::ReadbackTextureSync(GLuint texture, | 810 void GLHelper::ReadbackTextureSync(GLuint texture, |
694 const gfx::Rect& src_rect, | 811 const gfx::Rect& src_rect, |
695 unsigned char* out, | 812 unsigned char* out, |
696 SkColorType format) { | 813 SkColorType format) { |
697 InitCopyTextToImpl(); | 814 InitCopyTextToImpl(); |
698 copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format); | 815 copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format); |
699 } | 816 } |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 4, | 1011 4, |
895 callback); | 1012 callback); |
896 } | 1013 } |
897 | 1014 |
898 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = { | 1015 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = { |
899 0.257f, 0.504f, 0.098f, 0.0625f}; | 1016 0.257f, 0.504f, 0.098f, 0.0625f}; |
900 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = { | 1017 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = { |
901 -0.148f, -0.291f, 0.439f, 0.5f}; | 1018 -0.148f, -0.291f, 0.439f, 0.5f}; |
902 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = { | 1019 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = { |
903 0.439f, -0.368f, -0.071f, 0.5f}; | 1020 0.439f, -0.368f, -0.071f, 0.5f}; |
| 1021 const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = { |
| 1022 0.213f, 0.715f, 0.072f, 0.0f}; |
904 | 1023 |
905 // YUV readback constructors. Initiates the main scaler pipeline and | 1024 // YUV readback constructors. Initiates the main scaler pipeline and |
906 // one planar scaler for each of the Y, U and V planes. | 1025 // one planar scaler for each of the Y, U and V planes. |
907 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl( | 1026 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl( |
908 GLES2Interface* gl, | 1027 GLES2Interface* gl, |
909 CopyTextureToImpl* copy_impl, | 1028 CopyTextureToImpl* copy_impl, |
910 GLHelperScaling* scaler_impl, | 1029 GLHelperScaling* scaler_impl, |
911 GLHelper::ScalerQuality quality, | 1030 GLHelper::ScalerQuality quality, |
912 const gfx::Size& src_size, | 1031 const gfx::Size& src_size, |
913 const gfx::Rect& src_subrect, | 1032 const gfx::Rect& src_subrect, |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1235 return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality, | 1354 return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality, |
1236 src_size, | 1355 src_size, |
1237 src_subrect, | 1356 src_subrect, |
1238 dst_size, | 1357 dst_size, |
1239 dst_subrect, | 1358 dst_subrect, |
1240 flip_vertically, | 1359 flip_vertically, |
1241 use_mrt); | 1360 use_mrt); |
1242 } | 1361 } |
1243 | 1362 |
1244 } // namespace content | 1363 } // namespace content |
OLD | NEW |