Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: content/common/gpu/client/gl_helper.cc

Issue 388953002: Improving GestureNav screenshotting performance - Part 1 - gl_helper (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Unit Test for CropScaleReadbackAndCleanTexture Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 = kN32_SkColorType;
no sievers 2014/08/20 20:29:51 I don't think it makes sense to check for readback
mfomitchev 2014/08/22 18:01:33 GetReadbackConfig() returns the readback format.
no sievers 2014/08/22 18:44:13 I kow this is really confusing :/ GetReadbackForm
hubbe 2014/08/22 19:19:20 The reason reading back as BGRA is faster than RGB
no sievers 2014/08/22 20:54:48 Thanks hubbe+piman, that makes sense. In that cas
522 }
523
524 FormatSupport supported = GetReadbackConfig(readback_color_type,
525 true,
526 &format,
527 &type,
528 &bytes_per_pixel);
529
459 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) { 530 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
460 callback.Run(false); 531 callback.Run(false);
461 return; 532 return;
462 } 533 }
463 534
464 GLuint texture = ScaleTexture(src_texture, 535 GLuint texture = src_texture;
465 src_size, 536
466 src_subrect, 537 // Scale texture if needed
467 dst_size, 538 // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we
468 true, 539 // can do just as well in EncodeTextureAsGrayscale, which we will do if
469 (supported == GLHelperReadbackSupport::SWIZZLE), 540 // out_color_type is kAlpha_8_SkColorType, so let's skip the scaling step
470 color_type, 541 // in that case.
471 quality); 542 bool scale_texture = out_color_type != kAlpha_8_SkColorType ||
472 DCHECK(texture); 543 quality != GLHelper::SCALER_QUALITY_FAST;
544 if (scale_texture) {
545 // Don't swizzle during the scale step for kAlpha_8_SkColorType.
546 // We will swizzle in the encode step below if needed.
547 bool scale_swizzle =
548 out_color_type == kAlpha_8_SkColorType ?
549 false : supported == GLHelperReadbackSupport::SWIZZLE;
550 texture =
551 ScaleTexture(src_texture,
552 src_size,
553 src_subrect,
554 dst_size,
555 true,
556 scale_swizzle,
557 out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType
558 : out_color_type,
559 quality);
560 DCHECK(texture);
561 }
562
563 gfx::Size readback_texture_size = dst_size;
564 // Encode texture to grayscale if needed.
565 if (out_color_type == kAlpha_8_SkColorType) {
566 // Do the vertical flip here if we haven't already done it when we scaled
567 // the texture.
568 bool encode_as_grayscale_vertical_flip = !scale_texture;
569 // EncodeTextureAsGrayscale by default creates a texture which should be
570 // read back as RGBA, so need to swizzle if the readback format is BGRA.
no sievers 2014/08/20 20:29:51 ...and this check is still correct then, I think.
571 bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT;
572 texture = EncodeTextureAsGrayscale(
no sievers 2014/08/20 20:29:51 Do we leak |texture| here if we scaled above, as i
mfomitchev 2014/08/22 18:01:33 Done.
573 texture,
574 dst_size,
575 &readback_texture_size,
576 encode_as_grayscale_vertical_flip,
577 encode_as_grayscale_swizzle);
578 DCHECK(texture);
579 }
580
581 // Readback the pixels of the resulting texture
473 ScopedFramebuffer dst_framebuffer(gl_); 582 ScopedFramebuffer dst_framebuffer(gl_);
474 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, 583 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
475 dst_framebuffer); 584 dst_framebuffer);
476 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); 585 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
477 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, 586 gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
478 GL_COLOR_ATTACHMENT0, 587 GL_COLOR_ATTACHMENT0,
479 GL_TEXTURE_2D, 588 GL_TEXTURE_2D,
480 texture, 589 texture,
481 0); 590 0);
482 ReadbackAsync(dst_size, 591
483 dst_size.width() * bytes_per_pixel, 592 int32 bytes_per_row =
484 dst_size.width() * bytes_per_pixel, 593 out_color_type == kAlpha_8_SkColorType ?
594 dst_size.width() : dst_size.width() * bytes_per_pixel;
595
596 ReadbackAsync(readback_texture_size,
597 bytes_per_row,
598 bytes_per_row,
485 out, 599 out,
486 format, 600 format,
487 type, 601 type,
488 bytes_per_pixel, 602 bytes_per_pixel,
489 callback); 603 callback);
490 gl_->DeleteTextures(1, &texture); 604 gl_->DeleteTextures(1, &texture);
491 } 605 }
492 606
493 void GLHelper::CopyTextureToImpl::ReadbackTextureSync( 607 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
494 GLuint texture, 608 GLuint texture,
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 readback_support_(new GLHelperReadbackSupport(gl)) {} 763 readback_support_(new GLHelperReadbackSupport(gl)) {}
650 764
651 GLHelper::~GLHelper() {} 765 GLHelper::~GLHelper() {}
652 766
653 void GLHelper::CropScaleReadbackAndCleanTexture( 767 void GLHelper::CropScaleReadbackAndCleanTexture(
654 GLuint src_texture, 768 GLuint src_texture,
655 const gfx::Size& src_size, 769 const gfx::Size& src_size,
656 const gfx::Rect& src_subrect, 770 const gfx::Rect& src_subrect,
657 const gfx::Size& dst_size, 771 const gfx::Size& dst_size,
658 unsigned char* out, 772 unsigned char* out,
659 const SkColorType color_type, 773 const SkColorType out_color_type,
660 const base::Callback<void(bool)>& callback, 774 const base::Callback<void(bool)>& callback,
661 GLHelper::ScalerQuality quality) { 775 GLHelper::ScalerQuality quality) {
662 InitCopyTextToImpl(); 776 InitCopyTextToImpl();
663 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture( 777 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture,
664 src_texture, 778 src_size,
665 src_size, 779 src_subrect,
666 src_subrect, 780 dst_size,
667 dst_size, 781 out,
668 out, 782 out_color_type,
669 color_type, 783 callback,
670 callback, 784 quality);
671 quality);
672 } 785 }
673 786
674 void GLHelper::CropScaleReadbackAndCleanMailbox( 787 void GLHelper::CropScaleReadbackAndCleanMailbox(
675 const gpu::Mailbox& src_mailbox, 788 const gpu::Mailbox& src_mailbox,
676 uint32 sync_point, 789 uint32 sync_point,
677 const gfx::Size& src_size, 790 const gfx::Size& src_size,
678 const gfx::Rect& src_subrect, 791 const gfx::Rect& src_subrect,
679 const gfx::Size& dst_size, 792 const gfx::Size& dst_size,
680 unsigned char* out, 793 unsigned char* out,
681 const SkColorType color_type, 794 const SkColorType out_color_type,
682 const base::Callback<void(bool)>& callback, 795 const base::Callback<void(bool)>& callback,
683 GLHelper::ScalerQuality quality) { 796 GLHelper::ScalerQuality quality) {
684 GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); 797 GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point);
685 CropScaleReadbackAndCleanTexture( 798 CropScaleReadbackAndCleanTexture(mailbox_texture,
686 mailbox_texture, src_size, src_subrect, dst_size, out, 799 src_size,
687 color_type, 800 src_subrect,
688 callback, 801 dst_size,
689 quality); 802 out,
803 out_color_type,
804 callback,
805 quality);
690 gl_->DeleteTextures(1, &mailbox_texture); 806 gl_->DeleteTextures(1, &mailbox_texture);
691 } 807 }
692 808
693 void GLHelper::ReadbackTextureSync(GLuint texture, 809 void GLHelper::ReadbackTextureSync(GLuint texture,
694 const gfx::Rect& src_rect, 810 const gfx::Rect& src_rect,
695 unsigned char* out, 811 unsigned char* out,
696 SkColorType format) { 812 SkColorType format) {
697 InitCopyTextToImpl(); 813 InitCopyTextToImpl();
698 copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format); 814 copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
699 } 815 }
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 4, 1010 4,
895 callback); 1011 callback);
896 } 1012 }
897 1013
898 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = { 1014 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = {
899 0.257f, 0.504f, 0.098f, 0.0625f}; 1015 0.257f, 0.504f, 0.098f, 0.0625f};
900 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = { 1016 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
901 -0.148f, -0.291f, 0.439f, 0.5f}; 1017 -0.148f, -0.291f, 0.439f, 0.5f};
902 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = { 1018 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
903 0.439f, -0.368f, -0.071f, 0.5f}; 1019 0.439f, -0.368f, -0.071f, 0.5f};
1020 const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = {
1021 0.213f, 0.715f, 0.072f, 0.0f};
904 1022
905 // YUV readback constructors. Initiates the main scaler pipeline and 1023 // YUV readback constructors. Initiates the main scaler pipeline and
906 // one planar scaler for each of the Y, U and V planes. 1024 // one planar scaler for each of the Y, U and V planes.
907 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl( 1025 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
908 GLES2Interface* gl, 1026 GLES2Interface* gl,
909 CopyTextureToImpl* copy_impl, 1027 CopyTextureToImpl* copy_impl,
910 GLHelperScaling* scaler_impl, 1028 GLHelperScaling* scaler_impl,
911 GLHelper::ScalerQuality quality, 1029 GLHelper::ScalerQuality quality,
912 const gfx::Size& src_size, 1030 const gfx::Size& src_size,
913 const gfx::Rect& src_subrect, 1031 const gfx::Rect& src_subrect,
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality, 1353 return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality,
1236 src_size, 1354 src_size,
1237 src_subrect, 1355 src_subrect,
1238 dst_size, 1356 dst_size,
1239 dst_subrect, 1357 dst_subrect,
1240 flip_vertically, 1358 flip_vertically,
1241 use_mrt); 1359 use_mrt);
1242 } 1360 }
1243 1361
1244 } // namespace content 1362 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698