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

Side by Side Diff: content/common/gpu/client/gl_helper_unittest.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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <stdio.h> 5 #include <stdio.h>
6 #include <cmath> 6 #include <cmath>
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include <GLES2/gl2.h> 10 #include <GLES2/gl2.h>
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 float x3 = x2 * x; 132 float x3 = x2 * x;
133 if (x <= 1) { 133 if (x <= 1) {
134 return (a + 2) * x3 - (a + 3) * x2 + 1; 134 return (a + 2) * x3 - (a + 3) * x2 + 1;
135 } else if (x < 2) { 135 } else if (x < 2) {
136 return a * x3 - 5 * a * x2 + 8 * a * x - 4 * a; 136 return a * x3 - 5 * a * x2 + 8 * a * x - 4 * a;
137 } else { 137 } else {
138 return 0.0f; 138 return 0.0f;
139 } 139 }
140 } 140 }
141 141
142 // Look up a single R/G/B/A value. 142 // Look up a single channel value. Works for 4-channel and single channel
143 // Clamp x/y. 143 // bitmaps. Clamp x/y.
144 int Channel(SkBitmap* pixels, int x, int y, int c) { 144 int Channel(SkBitmap* pixels, int x, int y, int c) {
145 uint32* data = 145 if (pixels->bytesPerPixel() == 4) {
146 pixels->getAddr32(std::max(0, std::min(x, pixels->width() - 1)), 146 uint32* data =
147 std::max(0, std::min(y, pixels->height() - 1))); 147 pixels->getAddr32(std::max(0, std::min(x, pixels->width() - 1)),
148 return (*data) >> (c * 8) & 0xff; 148 std::max(0, std::min(y, pixels->height() - 1)));
149 return (*data) >> (c * 8) & 0xff;
150 } else {
151 DCHECK_EQ(pixels->bytesPerPixel(), 1);
152 DCHECK_EQ(c, 0);
153 return *pixels->getAddr8(std::max(0, std::min(x, pixels->width() - 1)),
154 std::max(0, std::min(y, pixels->height() - 1)));
155 }
149 } 156 }
150 157
151 // Set a single R/G/B/A value. 158 // Set a single channel value. Works for 4-channel and single channel
159 // bitmaps. Clamp x/y.
152 void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) { 160 void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) {
153 DCHECK_GE(x, 0); 161 DCHECK_GE(x, 0);
154 DCHECK_GE(y, 0); 162 DCHECK_GE(y, 0);
155 DCHECK_LT(x, pixels->width()); 163 DCHECK_LT(x, pixels->width());
156 DCHECK_LT(y, pixels->height()); 164 DCHECK_LT(y, pixels->height());
157 uint32* data = pixels->getAddr32(x, y); 165 if (pixels->bytesPerPixel() == 4) {
158 v = std::max(0, std::min(v, 255)); 166 uint32* data = pixels->getAddr32(x, y);
159 *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8)); 167 v = std::max(0, std::min(v, 255));
168 *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8));
169 } else {
170 DCHECK_EQ(pixels->bytesPerPixel(), 1);
171 DCHECK_EQ(c, 0);
172 uint8* data = pixels->getAddr8(x, y);
173 v = std::max(0, std::min(v, 255));
174 *data = v;
175 }
160 } 176 }
161 177
162 // Print all the R, G, B or A values from an SkBitmap in a 178 // Print all the R, G, B or A values from an SkBitmap in a
163 // human-readable format. 179 // human-readable format.
164 void PrintChannel(SkBitmap* pixels, int c) { 180 void PrintChannel(SkBitmap* pixels, int c) {
165 for (int y = 0; y < pixels->height(); y++) { 181 for (int y = 0; y < pixels->height(); y++) {
166 std::string formatted; 182 std::string formatted;
167 for (int x = 0; x < pixels->width(); x++) { 183 for (int x = 0; x < pixels->width(); x++) {
168 formatted.append(base::StringPrintf("%3d, ", Channel(pixels, x, y, c))); 184 formatted.append(base::StringPrintf("%3d, ", Channel(pixels, x, y, c)));
169 } 185 }
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 // is no more than |maxdiff| apart. If they are not similar enough, 398 // is no more than |maxdiff| apart. If they are not similar enough,
383 // prints out |truth|, |other|, |source|, |scaler_stages| and |message|. 399 // prints out |truth|, |other|, |source|, |scaler_stages| and |message|.
384 void Compare(SkBitmap* truth, 400 void Compare(SkBitmap* truth,
385 SkBitmap* other, 401 SkBitmap* other,
386 int maxdiff, 402 int maxdiff,
387 SkBitmap* source, 403 SkBitmap* source,
388 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages, 404 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages,
389 std::string message) { 405 std::string message) {
390 EXPECT_EQ(truth->width(), other->width()); 406 EXPECT_EQ(truth->width(), other->width());
391 EXPECT_EQ(truth->height(), other->height()); 407 EXPECT_EQ(truth->height(), other->height());
408 EXPECT_EQ(truth->bytesPerPixel(), other->bytesPerPixel());
409 int bpp = truth->bytesPerPixel();
392 for (int x = 0; x < truth->width(); x++) { 410 for (int x = 0; x < truth->width(); x++) {
393 for (int y = 0; y < truth->height(); y++) { 411 for (int y = 0; y < truth->height(); y++) {
394 for (int c = 0; c < 4; c++) { 412 for (int c = 0; c < bpp; c++) {
395 int a = Channel(truth, x, y, c); 413 int a = Channel(truth, x, y, c);
396 int b = Channel(other, x, y, c); 414 int b = Channel(other, x, y, c);
397 EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " c=" << c 415 EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " c=" << c
398 << " " << message; 416 << " " << message;
399 if (std::abs(a - b) > maxdiff) { 417 if (std::abs(a - b) > maxdiff) {
400 LOG(ERROR) << "-------expected--------"; 418 LOG(ERROR) << "-------expected--------";
401 PrintChannel(truth, c); 419 for (int i = 0; i < bpp; i++) {
420 LOG(ERROR) << "Channel " << i << ":";
421 PrintChannel(truth, i);
422 }
402 LOG(ERROR) << "-------actual--------"; 423 LOG(ERROR) << "-------actual--------";
403 PrintChannel(other, c); 424 for (int i = 0; i < bpp; i++) {
425 LOG(ERROR) << "Channel " << i << ":";
426 PrintChannel(other, i);
427 }
404 if (source) { 428 if (source) {
405 LOG(ERROR) << "-------before scaling--------"; 429 LOG(ERROR) << "-------original--------";
no sievers 2014/08/20 20:29:52 nit: indent
mfomitchev 2014/08/22 18:01:33 Done.
406 PrintChannel(source, c); 430 for (int i = 0; i < source->bytesPerPixel(); i++) {
431 LOG(ERROR) << "Channel " << i << ":";
432 PrintChannel(source, i);
433 }
407 } 434 }
408 LOG(ERROR) << "-----Scaler stages------"; 435 LOG(ERROR) << "-----Scaler stages------";
409 LOG(ERROR) << PrintStages(scaler_stages); 436 LOG(ERROR) << PrintStages(scaler_stages);
410 return; 437 return;
411 } 438 }
412 } 439 }
413 } 440 }
414 } 441 }
415 } 442 }
416 443
417 // Get a single R, G, B or A value as a float. 444 // Get a single R, G, B or A value as a float.
418 float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { 445 float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) {
419 return Channel(pixels, x, y, c) / 255.0; 446 return Channel(pixels, x, y, c) / 255.0;
420 } 447 }
421 448
422 // Works like a GL_LINEAR lookup on an SkBitmap. 449 // Works like a GL_LINEAR lookup on an SkBitmap.
423 float Bilinear(SkBitmap* pixels, float x, float y, int c) { 450 float Bilinear(SkBitmap* pixels, float x, float y, int c) {
424 x -= 0.5; 451 x -= 0.5;
425 y -= 0.5; 452 y -= 0.5;
426 int base_x = static_cast<int>(floorf(x)); 453 int base_x = static_cast<int>(floorf(x));
427 int base_y = static_cast<int>(floorf(y)); 454 int base_y = static_cast<int>(floorf(y));
428 x -= base_x; 455 x -= base_x;
429 y -= base_y; 456 y -= base_y;
430 return (ChannelAsFloat(pixels, base_x, base_y, c) * (1 - x) * (1 - y) + 457 return (ChannelAsFloat(pixels, base_x, base_y, c) * (1 - x) * (1 - y) +
431 ChannelAsFloat(pixels, base_x + 1, base_y, c) * x * (1 - y) + 458 ChannelAsFloat(pixels, base_x + 1, base_y, c) * x * (1 - y) +
432 ChannelAsFloat(pixels, base_x, base_y + 1, c) * (1 - x) * y + 459 ChannelAsFloat(pixels, base_x, base_y + 1, c) * (1 - x) * y +
433 ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y); 460 ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y);
434 } 461 }
435 462
463 // Encodes an RGBA bitmap to grayscale.
464 // Reference implementation for
465 // GLHelper::CopyToTextureImpl::EncodeTextureAsGrayscale.
466 void EncodeToGrayscaleSlow(SkBitmap* input,
467 SkBitmap* output) {
468 const float kRGBtoGrayscaleColorWeights[3] = {0.213f, 0.715f, 0.072f};
no sievers 2014/08/20 20:29:52 Should these constants be shared?
mfomitchev 2014/08/22 18:01:33 It wouldn't be terribly straightforward. This arra
no sievers 2014/08/22 18:44:13 If you expose them in gl_helper.h somehow, can the
mfomitchev 2014/08/25 19:21:53 Yes, I could construct the 3-element array in gl_h
469 CHECK_EQ(kAlpha_8_SkColorType, output->colorType());
470 CHECK_EQ(input->width(), output->width());
471 CHECK_EQ(input->height(), output->height());
472 CHECK_EQ(input->colorType(), kRGBA_8888_SkColorType);
473
474 for (int dst_y = 0; dst_y < output->height(); dst_y++) {
475 for (int dst_x = 0; dst_x < output->width(); dst_x++) {
476 float c0 = ChannelAsFloat(input, dst_x, dst_y, 0);
477 float c1 = ChannelAsFloat(input, dst_x, dst_y, 1);
478 float c2 = ChannelAsFloat(input, dst_x, dst_y, 2);
479 float value = c0 * kRGBtoGrayscaleColorWeights[0] +
480 c1 * kRGBtoGrayscaleColorWeights[1] +
481 c2 * kRGBtoGrayscaleColorWeights[2];
482 SetChannel(output,
483 dst_x,
484 dst_y,
485 0,
486 static_cast<int>(value * 255.0f + 0.5f));
no sievers 2014/08/20 20:29:52 hmm why +0.5?
mfomitchev 2014/08/22 18:01:33 So that it rounds to the closest int rather than r
487 }
488 }
489 }
490
436 // Very slow bicubic / bilinear scaler for reference. 491 // Very slow bicubic / bilinear scaler for reference.
437 void ScaleSlow(SkBitmap* input, 492 void ScaleSlow(SkBitmap* input,
438 SkBitmap* output, 493 SkBitmap* output,
439 content::GLHelper::ScalerQuality quality) { 494 content::GLHelper::ScalerQuality quality) {
440 float xscale = static_cast<float>(input->width()) / output->width(); 495 float xscale = static_cast<float>(input->width()) / output->width();
441 float yscale = static_cast<float>(input->height()) / output->height(); 496 float yscale = static_cast<float>(input->height()) / output->height();
442 float clamped_xscale = xscale < 1.0 ? 1.0 : 1.0 / xscale; 497 float clamped_xscale = xscale < 1.0 ? 1.0 : 1.0 / xscale;
443 float clamped_yscale = yscale < 1.0 ? 1.0 : 1.0 / yscale; 498 float clamped_yscale = yscale < 1.0 ? 1.0 : 1.0 / yscale;
444 for (int dst_y = 0; dst_y < output->height(); dst_y++) { 499 for (int dst_y = 0; dst_y < output->height(); dst_y++) {
445 for (int dst_x = 0; dst_x < output->width(); dst_x++) { 500 for (int dst_x = 0; dst_x < output->width(); dst_x++) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 dst_x, 563 dst_x,
509 dst_y, 564 dst_y,
510 channel, 565 channel,
511 static_cast<int>(value * 255.0f + 0.5f)); 566 static_cast<int>(value * 255.0f + 0.5f));
512 } 567 }
513 } 568 }
514 } 569 }
515 } 570 }
516 571
517 void FlipSKBitmap(SkBitmap* bitmap) { 572 void FlipSKBitmap(SkBitmap* bitmap) {
573 int bpp = bitmap->bytesPerPixel();
574 DCHECK(bpp == 4 || bpp == 1);
518 int top_line = 0; 575 int top_line = 0;
519 int bottom_line = bitmap->height() - 1; 576 int bottom_line = bitmap->height() - 1;
520 while (top_line < bottom_line) { 577 while (top_line < bottom_line) {
521 for (int x = 0; x < bitmap->width(); x++) { 578 for (int x = 0; x < bitmap->width(); x++) {
522 std::swap(*bitmap->getAddr32(x, top_line), 579 bpp == 4 ?
523 *bitmap->getAddr32(x, bottom_line)); 580 std::swap(*bitmap->getAddr32(x, top_line),
581 *bitmap->getAddr32(x, bottom_line))
582 : std::swap(*bitmap->getAddr8(x, top_line),
583 *bitmap->getAddr8(x, bottom_line));
524 } 584 }
525 top_line++; 585 top_line++;
526 bottom_line--; 586 bottom_line--;
527 } 587 }
528 } 588 }
529 589
590 // Swaps red and blue channels in each pixel in a 32-bit bitmap.
591 void SwizzleSKBitmap(SkBitmap* bitmap) {
592 int bpp = bitmap->bytesPerPixel();
593 DCHECK(bpp == 4);
594 for (int y = 0; y < bitmap->height(); y++) {
595 for (int x = 0; x < bitmap->width(); x++) {
596 // Swap channels 0 and 2 (red and blue)
597 int c0 = Channel(bitmap, x, y, 0);
598 int c2 = Channel(bitmap, x, y, 2);
599 SetChannel(bitmap, x, y, 2, c0);
600 SetChannel(bitmap, x, y, 0, c2);
601 }
602 }
603 }
604
530 // gl_helper scales recursively, so we'll need to do that 605 // gl_helper scales recursively, so we'll need to do that
531 // in the reference implementation too. 606 // in the reference implementation too.
532 void ScaleSlowRecursive(SkBitmap* input, 607 void ScaleSlowRecursive(SkBitmap* input,
533 SkBitmap* output, 608 SkBitmap* output,
534 content::GLHelper::ScalerQuality quality) { 609 content::GLHelper::ScalerQuality quality) {
535 if (quality == content::GLHelper::SCALER_QUALITY_FAST || 610 if (quality == content::GLHelper::SCALER_QUALITY_FAST ||
536 quality == content::GLHelper::SCALER_QUALITY_GOOD) { 611 quality == content::GLHelper::SCALER_QUALITY_GOOD) {
537 ScaleSlow(input, output, quality); 612 ScaleSlow(input, output, quality);
538 return; 613 return;
539 } 614 }
(...skipping 28 matching lines...) Expand all
568 } 643 }
569 } 644 }
570 645
571 SkBitmap tmp; 646 SkBitmap tmp;
572 tmp.allocN32Pixels(xtmp, ytmp); 647 tmp.allocN32Pixels(xtmp, ytmp);
573 648
574 ScaleSlowRecursive(input, &tmp, quality); 649 ScaleSlowRecursive(input, &tmp, quality);
575 ScaleSlowRecursive(&tmp, output, quality); 650 ScaleSlowRecursive(&tmp, output, quality);
576 } 651 }
577 652
653 // Creates an RGBA SkBitmap
654 scoped_ptr<SkBitmap> CreateTestBitmap(int width,
655 int height,
656 int test_pattern) {
657 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
658 bitmap->allocPixels(SkImageInfo::Make(
659 width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
660
661 for (int x = 0; x < width; ++x) {
662 for (int y = 0; y < height; ++y) {
663 switch (test_pattern) {
664 case 0: // Smooth test pattern
665 SetChannel(bitmap.get(), x, y, 0, x * 10);
666 SetChannel(bitmap.get(), x, y, 0, y == 0 ? x * 50 : x * 10);
667 SetChannel(bitmap.get(), x, y, 1, y * 10);
668 SetChannel(bitmap.get(), x, y, 2, (x + y) * 10);
669 SetChannel(bitmap.get(), x, y, 3, 255);
670 break;
671 case 1: // Small blocks
672 SetChannel(bitmap.get(), x, y, 0, x & 1 ? 255 : 0);
673 SetChannel(bitmap.get(), x, y, 1, y & 1 ? 255 : 0);
674 SetChannel(bitmap.get(), x, y, 2, (x + y) & 1 ? 255 : 0);
675 SetChannel(bitmap.get(), x, y, 3, 255);
676 break;
677 case 2: // Medium blocks
678 SetChannel(bitmap.get(), x, y, 0, 10 + x / 2 * 50);
679 SetChannel(bitmap.get(), x, y, 1, 10 + y / 3 * 50);
680 SetChannel(bitmap.get(), x, y, 2, (x + y) / 5 * 50 + 5);
681 SetChannel(bitmap.get(), x, y, 3, 255);
682 break;
683 }
684 }
685 }
686 return bitmap.Pass();
687 }
688
689 // Binds texture and framebuffer and loads the bitmap pixels into the texture.
690 void BindTextureAndFrameBuffer(WebGLId texture,
691 WebGLId framebuffer,
692 SkBitmap* bitmap,
693 int width,
694 int height) {
695 context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
696 context_->bindTexture(GL_TEXTURE_2D, texture);
697 context_->texImage2D(GL_TEXTURE_2D,
698 0,
699 GL_RGBA,
700 width,
701 height,
702 0,
703 GL_RGBA,
704 GL_UNSIGNED_BYTE,
705 bitmap->getPixels());
706 }
707
708 // Create a test image, transform it using
709 // GLHelper::CropScaleReadbackAndCleanTexture and a reference implementation
710 // and compare the results.
711 void TestCropScaleReadbackAndCleanTexture(int xsize,
712 int ysize,
713 int scaled_xsize,
714 int scaled_ysize,
715 int test_pattern,
716 SkColorType out_color_type,
717 bool swizzle,
718 size_t quality) {
no sievers 2014/08/20 20:29:52 nit: maybe less error-prone to just pass the Scale
mfomitchev 2014/08/22 18:01:33 Yeah, this is modeled after TestScale() below, but
no sievers 2014/08/22 18:44:13 I see, maybe just keep it as is then if it matches
719 DCHECK(out_color_type == kAlpha_8_SkColorType ||
720 out_color_type == kRGBA_8888_SkColorType ||
721 out_color_type == kBGRA_8888_SkColorType);
722 WebGLId src_texture = context_->createTexture();
723 WebGLId framebuffer = context_->createFramebuffer();
724 scoped_ptr<SkBitmap> input_pixels =
725 CreateTestBitmap(xsize, ysize, test_pattern).Pass();
726 BindTextureAndFrameBuffer(
727 src_texture, framebuffer, input_pixels.get(), xsize, ysize);
728
729 std::string message = base::StringPrintf(
730 "input size: %dx%d "
731 "output size: %dx%d "
732 "pattern: %d , quality: %s, "
733 "out_color_type: %d",
734 xsize,
735 ysize,
736 scaled_xsize,
737 scaled_ysize,
738 test_pattern,
739 kQualityNames[quality],
740 out_color_type);
741
742 // Transform the bitmap using GLHelper::CropScaleReadbackAndCleanTexture.
743 SkBitmap output_pixels;
744 output_pixels.allocPixels(SkImageInfo::Make(
745 scaled_xsize, scaled_ysize, out_color_type, kPremul_SkAlphaType));
746 base::RunLoop run_loop;
747 gfx::Size encoded_texture_size;
748 helper_->CropScaleReadbackAndCleanTexture(
749 src_texture,
750 gfx::Size(xsize, ysize),
751 gfx::Rect(xsize, ysize),
752 gfx::Size(scaled_xsize, scaled_ysize),
753 static_cast<unsigned char*>(output_pixels.getPixels()),
754 out_color_type,
755 base::Bind(&callcallback, run_loop.QuitClosure()),
756 kQualities[quality]);
757 run_loop.Run();
758 // CropScaleReadbackAndCleanTexture flips the pixels. Flip them back.
759 FlipSKBitmap(&output_pixels);
no sievers 2014/08/20 20:29:52 Why do we end up with an upside down image? That s
mfomitchev 2014/08/22 18:01:34 The old version of CropScaleReadbackAndCleanTextur
no sievers 2014/08/22 18:44:13 This is intriguing, as I believe we use this path
760
761 // Now transofrm the bitmap using the reference implementation.
no sievers 2014/08/20 20:29:52 nit, typo: 'transform'
mfomitchev 2014/08/22 18:01:33 Done.
762 SkBitmap scaled_pixels;
763 scaled_pixels.allocPixels(SkImageInfo::Make(
764 scaled_xsize,
765 scaled_ysize,
766 kRGBA_8888_SkColorType,
767 kPremul_SkAlphaType));
768 SkBitmap truth_pixels;
769 // Step 1: Scale
770 ScaleSlowRecursive(input_pixels.get(), &scaled_pixels, kQualities[quality]);
771 // Step 2: Convert to the specified output format, encoding to grayscale if
772 // needed.
773 switch (out_color_type) {
774 case kRGBA_8888_SkColorType:
775 truth_pixels = scaled_pixels;
776 break;
777 case kBGRA_8888_SkColorType:
no sievers 2014/08/20 20:29:52 nit: indent here and below
mfomitchev 2014/08/22 18:01:33 Done.
778 // Swizzle pixels of the scaled bitmap if the output needs to be BGRA
no sievers 2014/08/20 20:29:52 or could Compare() just learn to handle the format
mfomitchev 2014/08/22 18:01:33 Problem is, scale tests here use Compare() to do a
no sievers 2014/08/22 18:44:13 hmm maybe put a TODO then?
mfomitchev 2014/08/25 19:21:53 Ok, I've just updated TestScale to consistently us
779 truth_pixels.installPixels(
780 SkImageInfo::Make(scaled_xsize,
781 scaled_ysize,
782 out_color_type,
783 kPremul_SkAlphaType),
784 scaled_pixels.getPixels(),
785 scaled_pixels.width() * 4);
786 SwizzleSKBitmap(&truth_pixels);
787 break;
788 case kAlpha_8_SkColorType:
789 truth_pixels.allocPixels(SkImageInfo::Make(
790 scaled_xsize, scaled_ysize, out_color_type, kPremul_SkAlphaType));
791 EncodeToGrayscaleSlow(&scaled_pixels, &truth_pixels);
792 break;
793 default:
794 NOTREACHED();
795 }
796
797 // Now compare the results.
798 SkAutoLockPixels lock_input(truth_pixels);
799 const std::vector<GLHelperScaling::ScalerStage> dummy_stages;
800 Compare(&truth_pixels,
801 &output_pixels,
802 2,
no sievers 2014/08/20 20:29:52 Just wondering, why 2? Maybe hubbe knows. I did no
mfomitchev 2014/08/22 18:01:33 It does fail on my machine for 16x16 -> 3x6 best-q
803 input_pixels.get(),
804 dummy_stages,
805 message + " comparing against transformed/scaled");
806
807 context_->deleteTexture(src_texture);
808 context_->deleteFramebuffer(framebuffer);
809 }
810
578 // Scaling test: Create a test image, scale it using GLHelperScaling 811 // Scaling test: Create a test image, scale it using GLHelperScaling
579 // and a reference implementation and compare the results. 812 // and a reference implementation and compare the results.
580 void TestScale(int xsize, 813 void TestScale(int xsize,
581 int ysize, 814 int ysize,
582 int scaled_xsize, 815 int scaled_xsize,
583 int scaled_ysize, 816 int scaled_ysize,
584 int test_pattern, 817 int test_pattern,
585 size_t quality, 818 size_t quality,
586 bool flip) { 819 bool flip) {
587 WebGLId src_texture = context_->createTexture(); 820 WebGLId src_texture = context_->createTexture();
588 WebGLId framebuffer = context_->createFramebuffer(); 821 WebGLId framebuffer = context_->createFramebuffer();
589 SkBitmap input_pixels; 822 scoped_ptr<SkBitmap> input_pixels =
590 input_pixels.allocN32Pixels(xsize, ysize); 823 CreateTestBitmap(xsize, ysize, test_pattern).Pass();
591 824 BindTextureAndFrameBuffer(
592 for (int x = 0; x < xsize; ++x) { 825 src_texture, framebuffer, input_pixels.get(), xsize, ysize);
593 for (int y = 0; y < ysize; ++y) {
594 switch (test_pattern) {
595 case 0: // Smooth test pattern
596 SetChannel(&input_pixels, x, y, 0, x * 10);
597 SetChannel(&input_pixels, x, y, 1, y * 10);
598 SetChannel(&input_pixels, x, y, 2, (x + y) * 10);
599 SetChannel(&input_pixels, x, y, 3, 255);
600 break;
601 case 1: // Small blocks
602 SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0);
603 SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0);
604 SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0);
605 SetChannel(&input_pixels, x, y, 3, 255);
606 break;
607 case 2: // Medium blocks
608 SetChannel(&input_pixels, x, y, 0, 10 + x / 2 * 50);
609 SetChannel(&input_pixels, x, y, 1, 10 + y / 3 * 50);
610 SetChannel(&input_pixels, x, y, 2, (x + y) / 5 * 50 + 5);
611 SetChannel(&input_pixels, x, y, 3, 255);
612 break;
613 }
614 }
615 }
616
617 context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
618 context_->bindTexture(GL_TEXTURE_2D, src_texture);
619 context_->texImage2D(GL_TEXTURE_2D,
620 0,
621 GL_RGBA,
622 xsize,
623 ysize,
624 0,
625 GL_RGBA,
626 GL_UNSIGNED_BYTE,
627 input_pixels.getPixels());
628 826
629 std::string message = base::StringPrintf( 827 std::string message = base::StringPrintf(
630 "input size: %dx%d " 828 "input size: %dx%d "
631 "output size: %dx%d " 829 "output size: %dx%d "
632 "pattern: %d quality: %s", 830 "pattern: %d quality: %s",
633 xsize, 831 xsize,
634 ysize, 832 ysize,
635 scaled_xsize, 833 scaled_xsize,
636 scaled_ysize, 834 scaled_ysize,
637 test_pattern, 835 test_pattern,
(...skipping 25 matching lines...) Expand all
663 helper_->ReadbackTextureSync( 861 helper_->ReadbackTextureSync(
664 dst_texture, 862 dst_texture,
665 gfx::Rect(0, 0, scaled_xsize, scaled_ysize), 863 gfx::Rect(0, 0, scaled_xsize, scaled_ysize),
666 static_cast<unsigned char*>(output_pixels.getPixels()), 864 static_cast<unsigned char*>(output_pixels.getPixels()),
667 kRGBA_8888_SkColorType); 865 kRGBA_8888_SkColorType);
668 if (flip) { 866 if (flip) {
669 // Flip the pixels back. 867 // Flip the pixels back.
670 FlipSKBitmap(&output_pixels); 868 FlipSKBitmap(&output_pixels);
671 } 869 }
672 if (xsize == scaled_xsize && ysize == scaled_ysize) { 870 if (xsize == scaled_xsize && ysize == scaled_ysize) {
673 Compare(&input_pixels, 871 Compare(input_pixels.get(),
674 &output_pixels, 872 &output_pixels,
675 2, 873 2,
676 NULL, 874 NULL,
677 stages, 875 stages,
678 message + " comparing against input"); 876 message + " comparing against input");
679 } 877 }
680 SkBitmap truth_pixels; 878 SkBitmap truth_pixels;
681 truth_pixels.allocN32Pixels(scaled_xsize, scaled_ysize); 879 truth_pixels.allocN32Pixels(scaled_xsize, scaled_ysize);
682 880
683 ScaleSlowRecursive(&input_pixels, &truth_pixels, kQualities[quality]); 881 ScaleSlowRecursive(input_pixels.get(), &truth_pixels, kQualities[quality]);
684 Compare(&truth_pixels, 882 Compare(&truth_pixels,
685 &output_pixels, 883 &output_pixels,
686 2, 884 2,
687 &input_pixels, 885 input_pixels.get(),
688 stages, 886 stages,
689 message + " comparing against scaled"); 887 message + " comparing against scaled");
690 888
691 context_->deleteTexture(src_texture); 889 context_->deleteTexture(src_texture);
692 context_->deleteTexture(dst_texture); 890 context_->deleteTexture(dst_texture);
693 context_->deleteFramebuffer(framebuffer); 891 context_->deleteFramebuffer(framebuffer);
694 } 892 }
695 893
696 // Create a scaling pipeline and check that it is made up of 894 // Create a scaling pipeline and check that it is made up of
697 // valid scaling operations. 895 // valid scaling operations.
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 base::Bind(&callcallback, 1204 base::Bind(&callcallback,
1007 run_loop.QuitClosure())); 1205 run_loop.QuitClosure()));
1008 run_loop.Run(); 1206 run_loop.Run();
1009 } else { 1207 } else {
1010 helper_->ReadbackTextureSync(src_texture, 1208 helper_->ReadbackTextureSync(src_texture,
1011 gfx::Rect(src_size), 1209 gfx::Rect(src_size),
1012 pixels, 1210 pixels,
1013 color_type); 1211 color_type);
1014 } 1212 }
1015 } 1213 }
1016
1017 // Test basic format readback. 1214 // Test basic format readback.
1018 bool TestTextureFormatReadback(const gfx::Size& src_size, 1215 bool TestTextureFormatReadback(const gfx::Size& src_size,
1019 SkColorType color_type, 1216 SkColorType color_type,
1020 bool async) { 1217 bool async) {
1021 SkImageInfo info = 1218 SkImageInfo info =
1022 SkImageInfo::Make(src_size.width(), 1219 SkImageInfo::Make(src_size.width(),
1023 src_size.height(), 1220 src_size.height(),
1024 color_type, 1221 color_type,
1025 kPremul_SkAlphaType); 1222 kPremul_SkAlphaType);
1026 if (!helper_->IsReadbackConfigSupported(color_type)) { 1223 if (!helper_->IsReadbackConfigSupported(color_type)) {
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 } 1815 }
1619 } 1816 }
1620 } 1817 }
1621 } 1818 }
1622 } 1819 }
1623 } 1820 }
1624 } 1821 }
1625 } 1822 }
1626 } 1823 }
1627 1824
1825 // Per pixel tests, all sizes are small so that we can print
1826 // out the generated bitmaps.
1827 TEST_F(GLHelperPixelTest, CropScaleReadbackAndCleanTextureTest) {
1828 int sizes[] = {3, 6, 16};
1829 SkColorType color_types[] =
no sievers 2014/08/20 20:29:52 nit: const int kSizes[] = ... const SkColorType k
mfomitchev 2014/08/22 18:01:33 Done.
1830 {kAlpha_8_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType};
1831 // Test BEST and FAST qualities, skip GOOD
1832 for (size_t q = 0; q < arraysize(kQualities); q += 2) {
no sievers 2014/08/20 20:29:52 why q+=2 and not q++?
mfomitchev 2014/08/22 18:01:33 FAST uses a different code path in CropScaleReadba
no sievers 2014/08/22 18:44:13 Ok, maybe it's more straightforward to define your
mfomitchev 2014/08/25 19:21:53 The index is also used to fetch the name from kQua
1833 for (int color_type = 0; color_type < 3; color_type++) {
no sievers 2014/08/20 20:29:52 color_type < arraysize(kColorTypes)
mfomitchev 2014/08/22 18:01:33 Done.
1834 for (int x = 0; x < 3; x++) {
1835 for (int y = 0; y < 3; y++) {
1836 for (int dst_x = 0; dst_x < 3; dst_x++) {
1837 for (int dst_y = 0; dst_y < 3; dst_y++) {
1838 for (int pattern = 0; pattern < 3; pattern++) {
1839 TestCropScaleReadbackAndCleanTexture(sizes[x],
1840 sizes[y],
1841 sizes[dst_x],
1842 sizes[dst_y],
1843 pattern,
1844 color_types[color_type],
1845 false,
1846 q);
1847 if (HasFailure())
1848 return;
1849 }
1850 }
1851 }
1852 }
1853 }
1854 }
1855 }
1856 }
1857
1628 // Validate that all scaling generates valid pipelines. 1858 // Validate that all scaling generates valid pipelines.
1629 TEST_F(GLHelperTest, ValidateScalerPipelines) { 1859 TEST_F(GLHelperTest, ValidateScalerPipelines) {
1630 int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096}; 1860 int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096};
1631 for (size_t q = 0; q < arraysize(kQualities); q++) { 1861 for (size_t q = 0; q < arraysize(kQualities); q++) {
1632 for (size_t x = 0; x < arraysize(sizes); x++) { 1862 for (size_t x = 0; x < arraysize(sizes); x++) {
1633 for (size_t y = 0; y < arraysize(sizes); y++) { 1863 for (size_t y = 0; y < arraysize(sizes); y++) {
1634 for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) { 1864 for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) {
1635 for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) { 1865 for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) {
1636 TestScalerPipeline( 1866 TestScalerPipeline(
1637 q, sizes[x], sizes[y], sizes[dst_x], sizes[dst_y]); 1867 q, sizes[x], sizes[y], sizes[dst_x], sizes[dst_y]);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1701 base::CommandLine::Init(argc, argv); 1931 base::CommandLine::Init(argc, argv);
1702 base::TestSuite* suite = new content::ContentTestSuite(argc, argv); 1932 base::TestSuite* suite = new content::ContentTestSuite(argc, argv);
1703 #if defined(OS_MACOSX) 1933 #if defined(OS_MACOSX)
1704 base::mac::ScopedNSAutoreleasePool pool; 1934 base::mac::ScopedNSAutoreleasePool pool;
1705 #endif 1935 #endif
1706 1936
1707 content::UnitTestTestSuite runner(suite); 1937 content::UnitTestTestSuite runner(suite);
1708 base::MessageLoop message_loop; 1938 base::MessageLoop message_loop;
1709 return runner.Run(); 1939 return runner.Run();
1710 } 1940 }
OLDNEW
« content/common/gpu/client/gl_helper.cc ('K') | « content/common/gpu/client/gl_helper.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698