Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 } | 387 } |
| 372 } | 388 } |
| 373 | 389 |
| 374 if (HasFailure() && !previous_error) { | 390 if (HasFailure() && !previous_error) { |
| 375 LOG(ERROR) << "Invalid scaler stages: " << message; | 391 LOG(ERROR) << "Invalid scaler stages: " << message; |
| 376 LOG(ERROR) << "Scaler stages:"; | 392 LOG(ERROR) << "Scaler stages:"; |
| 377 LOG(ERROR) << PrintStages(scaler_stages); | 393 LOG(ERROR) << PrintStages(scaler_stages); |
| 378 } | 394 } |
| 379 } | 395 } |
| 380 | 396 |
| 381 // Compare two bitmaps, make sure that each component of each pixel | 397 // Compares two bitmaps taking color types into account. Checks whether each |
| 382 // is no more than |maxdiff| apart. If they are not similar enough, | 398 // component of each pixel is no more than |maxdiff| apart. If bitmaps are not |
| 383 // prints out |truth|, |other|, |source|, |scaler_stages| and |message|. | 399 // similar enough, prints out |truth|, |other|, |source|, |scaler_stages| |
| 400 // and |message|. | |
| 384 void Compare(SkBitmap* truth, | 401 void Compare(SkBitmap* truth, |
| 385 SkBitmap* other, | 402 SkBitmap* other, |
| 386 int maxdiff, | 403 int maxdiff, |
| 387 SkBitmap* source, | 404 SkBitmap* source, |
| 388 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages, | 405 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages, |
| 389 std::string message) { | 406 std::string message) { |
| 390 EXPECT_EQ(truth->width(), other->width()); | 407 EXPECT_EQ(truth->width(), other->width()); |
| 391 EXPECT_EQ(truth->height(), other->height()); | 408 EXPECT_EQ(truth->height(), other->height()); |
| 409 bool swizzle = (truth->colorType() == kRGBA_8888_SkColorType && | |
| 410 other->colorType() == kBGRA_8888_SkColorType) || | |
| 411 (truth->colorType() == kBGRA_8888_SkColorType && | |
| 412 other->colorType() == kRGBA_8888_SkColorType); | |
| 413 EXPECT_TRUE(swizzle || truth->colorType() == other->colorType()); | |
| 414 int bpp = truth->bytesPerPixel(); | |
| 392 for (int x = 0; x < truth->width(); x++) { | 415 for (int x = 0; x < truth->width(); x++) { |
| 393 for (int y = 0; y < truth->height(); y++) { | 416 for (int y = 0; y < truth->height(); y++) { |
| 394 for (int c = 0; c < 4; c++) { | 417 for (int c = 0; c < bpp; c++) { |
| 395 int a = Channel(truth, x, y, c); | 418 int a = Channel(truth, x, y, c); |
| 396 int b = Channel(other, x, y, c); | 419 // swizzle when comparing if needed |
| 420 int b = swizzle && (c == 0 || c == 2) | |
| 421 ? Channel(other, x, y, (c + 2) & 2) | |
| 422 : Channel(other, x, y, c); | |
| 397 EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " c=" << c | 423 EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " c=" << c |
| 398 << " " << message; | 424 << " " << message; |
| 399 if (std::abs(a - b) > maxdiff) { | 425 if (std::abs(a - b) > maxdiff) { |
| 400 LOG(ERROR) << "-------expected--------"; | 426 LOG(ERROR) << "-------expected--------"; |
| 401 PrintChannel(truth, c); | 427 for (int i = 0; i < bpp; i++) { |
| 428 LOG(ERROR) << "Channel " << i << ":"; | |
| 429 PrintChannel(truth, i); | |
| 430 } | |
| 402 LOG(ERROR) << "-------actual--------"; | 431 LOG(ERROR) << "-------actual--------"; |
| 403 PrintChannel(other, c); | 432 for (int i = 0; i < bpp; i++) { |
| 433 LOG(ERROR) << "Channel " << i << ":"; | |
| 434 PrintChannel(other, i); | |
| 435 } | |
| 404 if (source) { | 436 if (source) { |
| 405 LOG(ERROR) << "-------before scaling--------"; | 437 LOG(ERROR) << "-------original--------"; |
| 406 PrintChannel(source, c); | 438 for (int i = 0; i < source->bytesPerPixel(); i++) { |
| 439 LOG(ERROR) << "Channel " << i << ":"; | |
| 440 PrintChannel(source, i); | |
| 441 } | |
| 407 } | 442 } |
| 408 LOG(ERROR) << "-----Scaler stages------"; | 443 LOG(ERROR) << "-----Scaler stages------"; |
| 409 LOG(ERROR) << PrintStages(scaler_stages); | 444 LOG(ERROR) << PrintStages(scaler_stages); |
| 410 return; | 445 return; |
| 411 } | 446 } |
| 412 } | 447 } |
| 413 } | 448 } |
| 414 } | 449 } |
| 415 } | 450 } |
| 416 | 451 |
| 417 // Get a single R, G, B or A value as a float. | 452 // Get a single R, G, B or A value as a float. |
| 418 float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { | 453 float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { |
| 419 return Channel(pixels, x, y, c) / 255.0; | 454 return Channel(pixels, x, y, c) / 255.0; |
| 420 } | 455 } |
| 421 | 456 |
| 422 // Works like a GL_LINEAR lookup on an SkBitmap. | 457 // Works like a GL_LINEAR lookup on an SkBitmap. |
| 423 float Bilinear(SkBitmap* pixels, float x, float y, int c) { | 458 float Bilinear(SkBitmap* pixels, float x, float y, int c) { |
| 424 x -= 0.5; | 459 x -= 0.5; |
| 425 y -= 0.5; | 460 y -= 0.5; |
| 426 int base_x = static_cast<int>(floorf(x)); | 461 int base_x = static_cast<int>(floorf(x)); |
| 427 int base_y = static_cast<int>(floorf(y)); | 462 int base_y = static_cast<int>(floorf(y)); |
| 428 x -= base_x; | 463 x -= base_x; |
| 429 y -= base_y; | 464 y -= base_y; |
| 430 return (ChannelAsFloat(pixels, base_x, base_y, c) * (1 - x) * (1 - y) + | 465 return (ChannelAsFloat(pixels, base_x, base_y, c) * (1 - x) * (1 - y) + |
| 431 ChannelAsFloat(pixels, base_x + 1, base_y, c) * x * (1 - y) + | 466 ChannelAsFloat(pixels, base_x + 1, base_y, c) * x * (1 - y) + |
| 432 ChannelAsFloat(pixels, base_x, base_y + 1, c) * (1 - x) * y + | 467 ChannelAsFloat(pixels, base_x, base_y + 1, c) * (1 - x) * y + |
| 433 ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y); | 468 ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y); |
| 434 } | 469 } |
| 435 | 470 |
| 471 // Encodes an RGBA bitmap to grayscale. | |
| 472 // Reference implementation for | |
| 473 // GLHelper::CopyToTextureImpl::EncodeTextureAsGrayscale. | |
| 474 void EncodeToGrayscaleSlow(SkBitmap* input, SkBitmap* output) { | |
| 475 const float kRGBtoGrayscaleColorWeights[3] = {0.213f, 0.715f, 0.072f}; | |
| 476 CHECK_EQ(kAlpha_8_SkColorType, output->colorType()); | |
| 477 CHECK_EQ(input->width(), output->width()); | |
| 478 CHECK_EQ(input->height(), output->height()); | |
| 479 CHECK_EQ(input->colorType(), kRGBA_8888_SkColorType); | |
| 480 | |
| 481 for (int dst_y = 0; dst_y < output->height(); dst_y++) { | |
| 482 for (int dst_x = 0; dst_x < output->width(); dst_x++) { | |
| 483 float c0 = ChannelAsFloat(input, dst_x, dst_y, 0); | |
| 484 float c1 = ChannelAsFloat(input, dst_x, dst_y, 1); | |
| 485 float c2 = ChannelAsFloat(input, dst_x, dst_y, 2); | |
| 486 float value = c0 * kRGBtoGrayscaleColorWeights[0] + | |
| 487 c1 * kRGBtoGrayscaleColorWeights[1] + | |
| 488 c2 * kRGBtoGrayscaleColorWeights[2]; | |
| 489 SetChannel( | |
| 490 output, dst_x, dst_y, 0, static_cast<int>(value * 255.0f + 0.5f)); | |
| 491 } | |
| 492 } | |
| 493 } | |
| 494 | |
| 436 // Very slow bicubic / bilinear scaler for reference. | 495 // Very slow bicubic / bilinear scaler for reference. |
| 437 void ScaleSlow(SkBitmap* input, | 496 void ScaleSlow(SkBitmap* input, |
| 438 SkBitmap* output, | 497 SkBitmap* output, |
| 439 content::GLHelper::ScalerQuality quality) { | 498 content::GLHelper::ScalerQuality quality) { |
| 440 float xscale = static_cast<float>(input->width()) / output->width(); | 499 float xscale = static_cast<float>(input->width()) / output->width(); |
| 441 float yscale = static_cast<float>(input->height()) / output->height(); | 500 float yscale = static_cast<float>(input->height()) / output->height(); |
| 442 float clamped_xscale = xscale < 1.0 ? 1.0 : 1.0 / xscale; | 501 float clamped_xscale = xscale < 1.0 ? 1.0 : 1.0 / xscale; |
| 443 float clamped_yscale = yscale < 1.0 ? 1.0 : 1.0 / yscale; | 502 float clamped_yscale = yscale < 1.0 ? 1.0 : 1.0 / yscale; |
| 444 for (int dst_y = 0; dst_y < output->height(); dst_y++) { | 503 for (int dst_y = 0; dst_y < output->height(); dst_y++) { |
| 445 for (int dst_x = 0; dst_x < output->width(); dst_x++) { | 504 for (int dst_x = 0; dst_x < output->width(); dst_x++) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 dst_x, | 567 dst_x, |
| 509 dst_y, | 568 dst_y, |
| 510 channel, | 569 channel, |
| 511 static_cast<int>(value * 255.0f + 0.5f)); | 570 static_cast<int>(value * 255.0f + 0.5f)); |
| 512 } | 571 } |
| 513 } | 572 } |
| 514 } | 573 } |
| 515 } | 574 } |
| 516 | 575 |
| 517 void FlipSKBitmap(SkBitmap* bitmap) { | 576 void FlipSKBitmap(SkBitmap* bitmap) { |
| 577 int bpp = bitmap->bytesPerPixel(); | |
| 578 DCHECK(bpp == 4 || bpp == 1); | |
| 518 int top_line = 0; | 579 int top_line = 0; |
| 519 int bottom_line = bitmap->height() - 1; | 580 int bottom_line = bitmap->height() - 1; |
| 520 while (top_line < bottom_line) { | 581 while (top_line < bottom_line) { |
| 521 for (int x = 0; x < bitmap->width(); x++) { | 582 for (int x = 0; x < bitmap->width(); x++) { |
| 522 std::swap(*bitmap->getAddr32(x, top_line), | 583 bpp == 4 ? std::swap(*bitmap->getAddr32(x, top_line), |
| 523 *bitmap->getAddr32(x, bottom_line)); | 584 *bitmap->getAddr32(x, bottom_line)) |
| 585 : std::swap(*bitmap->getAddr8(x, top_line), | |
| 586 *bitmap->getAddr8(x, bottom_line)); | |
| 524 } | 587 } |
| 525 top_line++; | 588 top_line++; |
| 526 bottom_line--; | 589 bottom_line--; |
| 527 } | 590 } |
| 528 } | 591 } |
| 529 | 592 |
| 593 // Swaps red and blue channels in each pixel in a 32-bit bitmap. | |
| 594 void SwizzleSKBitmap(SkBitmap* bitmap) { | |
| 595 int bpp = bitmap->bytesPerPixel(); | |
| 596 DCHECK(bpp == 4); | |
| 597 for (int y = 0; y < bitmap->height(); y++) { | |
| 598 for (int x = 0; x < bitmap->width(); x++) { | |
| 599 // Swap channels 0 and 2 (red and blue) | |
| 600 int c0 = Channel(bitmap, x, y, 0); | |
| 601 int c2 = Channel(bitmap, x, y, 2); | |
| 602 SetChannel(bitmap, x, y, 2, c0); | |
| 603 SetChannel(bitmap, x, y, 0, c2); | |
| 604 } | |
| 605 } | |
| 606 } | |
| 607 | |
| 530 // gl_helper scales recursively, so we'll need to do that | 608 // gl_helper scales recursively, so we'll need to do that |
| 531 // in the reference implementation too. | 609 // in the reference implementation too. |
| 532 void ScaleSlowRecursive(SkBitmap* input, | 610 void ScaleSlowRecursive(SkBitmap* input, |
| 533 SkBitmap* output, | 611 SkBitmap* output, |
| 534 content::GLHelper::ScalerQuality quality) { | 612 content::GLHelper::ScalerQuality quality) { |
| 535 if (quality == content::GLHelper::SCALER_QUALITY_FAST || | 613 if (quality == content::GLHelper::SCALER_QUALITY_FAST || |
| 536 quality == content::GLHelper::SCALER_QUALITY_GOOD) { | 614 quality == content::GLHelper::SCALER_QUALITY_GOOD) { |
| 537 ScaleSlow(input, output, quality); | 615 ScaleSlow(input, output, quality); |
| 538 return; | 616 return; |
| 539 } | 617 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 568 } | 646 } |
| 569 } | 647 } |
| 570 | 648 |
| 571 SkBitmap tmp; | 649 SkBitmap tmp; |
| 572 tmp.allocN32Pixels(xtmp, ytmp); | 650 tmp.allocN32Pixels(xtmp, ytmp); |
| 573 | 651 |
| 574 ScaleSlowRecursive(input, &tmp, quality); | 652 ScaleSlowRecursive(input, &tmp, quality); |
| 575 ScaleSlowRecursive(&tmp, output, quality); | 653 ScaleSlowRecursive(&tmp, output, quality); |
| 576 } | 654 } |
| 577 | 655 |
| 656 // Creates an RGBA SkBitmap | |
| 657 scoped_ptr<SkBitmap> CreateTestBitmap(int width, | |
| 658 int height, | |
| 659 int test_pattern) { | |
| 660 scoped_ptr<SkBitmap> bitmap(new SkBitmap); | |
| 661 bitmap->allocPixels(SkImageInfo::Make( | |
| 662 width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType)); | |
| 663 | |
| 664 for (int x = 0; x < width; ++x) { | |
| 665 for (int y = 0; y < height; ++y) { | |
| 666 switch (test_pattern) { | |
| 667 case 0: // Smooth test pattern | |
| 668 SetChannel(bitmap.get(), x, y, 0, x * 10); | |
| 669 SetChannel(bitmap.get(), x, y, 0, y == 0 ? x * 50 : x * 10); | |
| 670 SetChannel(bitmap.get(), x, y, 1, y * 10); | |
| 671 SetChannel(bitmap.get(), x, y, 2, (x + y) * 10); | |
| 672 SetChannel(bitmap.get(), x, y, 3, 255); | |
| 673 break; | |
| 674 case 1: // Small blocks | |
| 675 SetChannel(bitmap.get(), x, y, 0, x & 1 ? 255 : 0); | |
| 676 SetChannel(bitmap.get(), x, y, 1, y & 1 ? 255 : 0); | |
| 677 SetChannel(bitmap.get(), x, y, 2, (x + y) & 1 ? 255 : 0); | |
| 678 SetChannel(bitmap.get(), x, y, 3, 255); | |
| 679 break; | |
| 680 case 2: // Medium blocks | |
| 681 SetChannel(bitmap.get(), x, y, 0, 10 + x / 2 * 50); | |
| 682 SetChannel(bitmap.get(), x, y, 1, 10 + y / 3 * 50); | |
| 683 SetChannel(bitmap.get(), x, y, 2, (x + y) / 5 * 50 + 5); | |
| 684 SetChannel(bitmap.get(), x, y, 3, 255); | |
| 685 break; | |
| 686 } | |
| 687 } | |
| 688 } | |
| 689 return bitmap.Pass(); | |
| 690 } | |
| 691 | |
| 692 // Binds texture and framebuffer and loads the bitmap pixels into the texture. | |
| 693 void BindTextureAndFrameBuffer(WebGLId texture, | |
| 694 WebGLId framebuffer, | |
| 695 SkBitmap* bitmap, | |
| 696 int width, | |
| 697 int height) { | |
| 698 context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); | |
| 699 context_->bindTexture(GL_TEXTURE_2D, texture); | |
| 700 context_->texImage2D(GL_TEXTURE_2D, | |
| 701 0, | |
| 702 GL_RGBA, | |
| 703 width, | |
| 704 height, | |
| 705 0, | |
| 706 GL_RGBA, | |
| 707 GL_UNSIGNED_BYTE, | |
| 708 bitmap->getPixels()); | |
| 709 } | |
| 710 | |
| 711 // Create a test image, transform it using | |
| 712 // GLHelper::CropScaleReadbackAndCleanTexture and a reference implementation | |
| 713 // and compare the results. | |
| 714 void TestCropScaleReadbackAndCleanTexture(int xsize, | |
| 715 int ysize, | |
| 716 int scaled_xsize, | |
| 717 int scaled_ysize, | |
| 718 int test_pattern, | |
| 719 SkColorType out_color_type, | |
| 720 bool swizzle, | |
| 721 size_t quality_index) { | |
| 722 DCHECK(out_color_type == kAlpha_8_SkColorType || | |
| 723 out_color_type == kRGBA_8888_SkColorType || | |
| 724 out_color_type == kBGRA_8888_SkColorType); | |
| 725 WebGLId src_texture = context_->createTexture(); | |
| 726 WebGLId framebuffer = context_->createFramebuffer(); | |
| 727 scoped_ptr<SkBitmap> input_pixels = | |
| 728 CreateTestBitmap(xsize, ysize, test_pattern).Pass(); | |
| 729 BindTextureAndFrameBuffer( | |
| 730 src_texture, framebuffer, input_pixels.get(), xsize, ysize); | |
| 731 | |
| 732 std::string message = base::StringPrintf( | |
| 733 "input size: %dx%d " | |
| 734 "output size: %dx%d " | |
| 735 "pattern: %d , quality: %s, " | |
| 736 "out_color_type: %d", | |
| 737 xsize, | |
| 738 ysize, | |
| 739 scaled_xsize, | |
| 740 scaled_ysize, | |
| 741 test_pattern, | |
| 742 kQualityNames[quality_index], | |
| 743 out_color_type); | |
| 744 | |
| 745 // Transform the bitmap using GLHelper::CropScaleReadbackAndCleanTexture. | |
| 746 SkBitmap output_pixels; | |
| 747 output_pixels.allocPixels(SkImageInfo::Make( | |
| 748 scaled_xsize, scaled_ysize, out_color_type, kPremul_SkAlphaType)); | |
| 749 base::RunLoop run_loop; | |
| 750 gfx::Size encoded_texture_size; | |
| 751 helper_->CropScaleReadbackAndCleanTexture( | |
| 752 src_texture, | |
| 753 gfx::Size(xsize, ysize), | |
| 754 gfx::Rect(xsize, ysize), | |
| 755 gfx::Size(scaled_xsize, scaled_ysize), | |
| 756 static_cast<unsigned char*>(output_pixels.getPixels()), | |
| 757 out_color_type, | |
| 758 base::Bind(&callcallback, run_loop.QuitClosure()), | |
| 759 kQualities[quality_index]); | |
| 760 run_loop.Run(); | |
| 761 // CropScaleReadbackAndCleanTexture flips the pixels. Flip them back. | |
| 762 FlipSKBitmap(&output_pixels); | |
| 763 | |
| 764 // If the bitmap shouldn't have changed - compare against input. | |
| 765 if (xsize == scaled_xsize && ysize == scaled_ysize && | |
| 766 out_color_type != kAlpha_8_SkColorType) { | |
| 767 const std::vector<GLHelperScaling::ScalerStage> dummy_stages; | |
| 768 Compare(input_pixels.get(), | |
| 769 &output_pixels, | |
| 770 2, | |
|
no sievers
2014/08/25 19:34:52
If there was no scaling should the tolerance be 0?
mfomitchev
2014/08/25 20:05:04
Done.
| |
| 771 NULL, | |
| 772 dummy_stages, | |
| 773 message + " comparing against input"); | |
| 774 return; | |
| 775 } | |
| 776 | |
| 777 // Now transform the bitmap using the reference implementation. | |
| 778 SkBitmap scaled_pixels; | |
| 779 scaled_pixels.allocPixels(SkImageInfo::Make(scaled_xsize, | |
| 780 scaled_ysize, | |
| 781 kRGBA_8888_SkColorType, | |
| 782 kPremul_SkAlphaType)); | |
| 783 SkBitmap truth_pixels; | |
| 784 // Step 1: Scale | |
| 785 ScaleSlowRecursive( | |
| 786 input_pixels.get(), &scaled_pixels, kQualities[quality_index]); | |
| 787 // Step 2: Encode to grayscale if needed. | |
| 788 if (out_color_type == 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 } else { | |
| 793 truth_pixels = scaled_pixels; | |
| 794 } | |
| 795 | |
| 796 // Now compare the results. | |
| 797 SkAutoLockPixels lock_input(truth_pixels); | |
| 798 const std::vector<GLHelperScaling::ScalerStage> dummy_stages; | |
| 799 Compare(&truth_pixels, | |
| 800 &output_pixels, | |
| 801 2, | |
| 802 input_pixels.get(), | |
| 803 dummy_stages, | |
| 804 message + " comparing against transformed/scaled"); | |
| 805 | |
| 806 context_->deleteTexture(src_texture); | |
| 807 context_->deleteFramebuffer(framebuffer); | |
| 808 } | |
| 809 | |
| 578 // Scaling test: Create a test image, scale it using GLHelperScaling | 810 // Scaling test: Create a test image, scale it using GLHelperScaling |
| 579 // and a reference implementation and compare the results. | 811 // and a reference implementation and compare the results. |
| 580 void TestScale(int xsize, | 812 void TestScale(int xsize, |
| 581 int ysize, | 813 int ysize, |
| 582 int scaled_xsize, | 814 int scaled_xsize, |
| 583 int scaled_ysize, | 815 int scaled_ysize, |
| 584 int test_pattern, | 816 int test_pattern, |
| 585 size_t quality, | 817 size_t quality_index, |
| 586 bool flip) { | 818 bool flip) { |
| 587 WebGLId src_texture = context_->createTexture(); | 819 WebGLId src_texture = context_->createTexture(); |
| 588 WebGLId framebuffer = context_->createFramebuffer(); | 820 WebGLId framebuffer = context_->createFramebuffer(); |
| 589 SkBitmap input_pixels; | 821 scoped_ptr<SkBitmap> input_pixels = |
| 590 input_pixels.allocN32Pixels(xsize, ysize); | 822 CreateTestBitmap(xsize, ysize, test_pattern).Pass(); |
| 591 | 823 BindTextureAndFrameBuffer( |
| 592 for (int x = 0; x < xsize; ++x) { | 824 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 | 825 |
| 629 std::string message = base::StringPrintf( | 826 std::string message = base::StringPrintf( |
| 630 "input size: %dx%d " | 827 "input size: %dx%d " |
| 631 "output size: %dx%d " | 828 "output size: %dx%d " |
| 632 "pattern: %d quality: %s", | 829 "pattern: %d quality: %s", |
| 633 xsize, | 830 xsize, |
| 634 ysize, | 831 ysize, |
| 635 scaled_xsize, | 832 scaled_xsize, |
| 636 scaled_ysize, | 833 scaled_ysize, |
| 637 test_pattern, | 834 test_pattern, |
| 638 kQualityNames[quality]); | 835 kQualityNames[quality_index]); |
| 639 | 836 |
| 640 std::vector<GLHelperScaling::ScalerStage> stages; | 837 std::vector<GLHelperScaling::ScalerStage> stages; |
| 641 helper_scaling_->ComputeScalerStages(kQualities[quality], | 838 helper_scaling_->ComputeScalerStages(kQualities[quality_index], |
| 642 gfx::Size(xsize, ysize), | 839 gfx::Size(xsize, ysize), |
| 643 gfx::Rect(0, 0, xsize, ysize), | 840 gfx::Rect(0, 0, xsize, ysize), |
| 644 gfx::Size(scaled_xsize, scaled_ysize), | 841 gfx::Size(scaled_xsize, scaled_ysize), |
| 645 flip, | 842 flip, |
| 646 false, | 843 false, |
| 647 &stages); | 844 &stages); |
| 648 ValidateScalerStages(kQualities[quality], | 845 ValidateScalerStages(kQualities[quality_index], |
| 649 stages, | 846 stages, |
| 650 gfx::Size(scaled_xsize, scaled_ysize), | 847 gfx::Size(scaled_xsize, scaled_ysize), |
| 651 message); | 848 message); |
| 652 | 849 |
| 653 WebGLId dst_texture = | 850 WebGLId dst_texture = |
| 654 helper_->CopyAndScaleTexture(src_texture, | 851 helper_->CopyAndScaleTexture(src_texture, |
| 655 gfx::Size(xsize, ysize), | 852 gfx::Size(xsize, ysize), |
| 656 gfx::Size(scaled_xsize, scaled_ysize), | 853 gfx::Size(scaled_xsize, scaled_ysize), |
| 657 flip, | 854 flip, |
| 658 kQualities[quality]); | 855 kQualities[quality_index]); |
| 659 | 856 |
| 660 SkBitmap output_pixels; | 857 SkBitmap output_pixels; |
| 661 output_pixels.allocN32Pixels(scaled_xsize, scaled_ysize); | 858 output_pixels.allocPixels(SkImageInfo::Make(scaled_xsize, |
| 859 scaled_ysize, | |
| 860 kRGBA_8888_SkColorType, | |
| 861 kPremul_SkAlphaType)); | |
| 662 | 862 |
| 663 helper_->ReadbackTextureSync( | 863 helper_->ReadbackTextureSync( |
| 664 dst_texture, | 864 dst_texture, |
| 665 gfx::Rect(0, 0, scaled_xsize, scaled_ysize), | 865 gfx::Rect(0, 0, scaled_xsize, scaled_ysize), |
| 666 static_cast<unsigned char*>(output_pixels.getPixels()), | 866 static_cast<unsigned char*>(output_pixels.getPixels()), |
| 667 kRGBA_8888_SkColorType); | 867 kRGBA_8888_SkColorType); |
| 668 if (flip) { | 868 if (flip) { |
| 669 // Flip the pixels back. | 869 // Flip the pixels back. |
| 670 FlipSKBitmap(&output_pixels); | 870 FlipSKBitmap(&output_pixels); |
| 671 } | 871 } |
| 872 | |
| 873 // If the bitmap shouldn't have changed - compare against input. | |
| 672 if (xsize == scaled_xsize && ysize == scaled_ysize) { | 874 if (xsize == scaled_xsize && ysize == scaled_ysize) { |
| 673 Compare(&input_pixels, | 875 Compare(input_pixels.get(), |
| 674 &output_pixels, | 876 &output_pixels, |
| 675 2, | 877 2, |
| 676 NULL, | 878 NULL, |
| 677 stages, | 879 stages, |
| 678 message + " comparing against input"); | 880 message + " comparing against input"); |
| 881 return; | |
| 679 } | 882 } |
| 883 | |
| 884 // Now scale the bitmap using the reference implementation. | |
| 680 SkBitmap truth_pixels; | 885 SkBitmap truth_pixels; |
| 681 truth_pixels.allocN32Pixels(scaled_xsize, scaled_ysize); | 886 truth_pixels.allocPixels(SkImageInfo::Make(scaled_xsize, |
| 682 | 887 scaled_ysize, |
| 683 ScaleSlowRecursive(&input_pixels, &truth_pixels, kQualities[quality]); | 888 kRGBA_8888_SkColorType, |
| 889 kPremul_SkAlphaType)); | |
| 890 ScaleSlowRecursive( | |
| 891 input_pixels.get(), &truth_pixels, kQualities[quality_index]); | |
| 684 Compare(&truth_pixels, | 892 Compare(&truth_pixels, |
| 685 &output_pixels, | 893 &output_pixels, |
| 686 2, | 894 2, |
| 687 &input_pixels, | 895 input_pixels.get(), |
| 688 stages, | 896 stages, |
| 689 message + " comparing against scaled"); | 897 message + " comparing against scaled"); |
| 690 | 898 |
| 691 context_->deleteTexture(src_texture); | 899 context_->deleteTexture(src_texture); |
| 692 context_->deleteTexture(dst_texture); | 900 context_->deleteTexture(dst_texture); |
| 693 context_->deleteFramebuffer(framebuffer); | 901 context_->deleteFramebuffer(framebuffer); |
| 694 } | 902 } |
| 695 | 903 |
| 696 // Create a scaling pipeline and check that it is made up of | 904 // Create a scaling pipeline and check that it is made up of |
| 697 // valid scaling operations. | 905 // valid scaling operations. |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1006 base::Bind(&callcallback, | 1214 base::Bind(&callcallback, |
| 1007 run_loop.QuitClosure())); | 1215 run_loop.QuitClosure())); |
| 1008 run_loop.Run(); | 1216 run_loop.Run(); |
| 1009 } else { | 1217 } else { |
| 1010 helper_->ReadbackTextureSync(src_texture, | 1218 helper_->ReadbackTextureSync(src_texture, |
| 1011 gfx::Rect(src_size), | 1219 gfx::Rect(src_size), |
| 1012 pixels, | 1220 pixels, |
| 1013 color_type); | 1221 color_type); |
| 1014 } | 1222 } |
| 1015 } | 1223 } |
| 1016 | |
| 1017 // Test basic format readback. | 1224 // Test basic format readback. |
| 1018 bool TestTextureFormatReadback(const gfx::Size& src_size, | 1225 bool TestTextureFormatReadback(const gfx::Size& src_size, |
| 1019 SkColorType color_type, | 1226 SkColorType color_type, |
| 1020 bool async) { | 1227 bool async) { |
| 1021 SkImageInfo info = | 1228 SkImageInfo info = |
| 1022 SkImageInfo::Make(src_size.width(), | 1229 SkImageInfo::Make(src_size.width(), |
| 1023 src_size.height(), | 1230 src_size.height(), |
| 1024 color_type, | 1231 color_type, |
| 1025 kPremul_SkAlphaType); | 1232 kPremul_SkAlphaType); |
| 1026 if (!helper_->IsReadbackConfigSupported(color_type)) { | 1233 if (!helper_->IsReadbackConfigSupported(color_type)) { |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1593 } | 1800 } |
| 1594 } | 1801 } |
| 1595 } | 1802 } |
| 1596 } | 1803 } |
| 1597 | 1804 |
| 1598 // Per pixel tests, all sizes are small so that we can print | 1805 // Per pixel tests, all sizes are small so that we can print |
| 1599 // out the generated bitmaps. | 1806 // out the generated bitmaps. |
| 1600 TEST_F(GLHelperPixelTest, ScaleTest) { | 1807 TEST_F(GLHelperPixelTest, ScaleTest) { |
| 1601 int sizes[] = {3, 6, 16}; | 1808 int sizes[] = {3, 6, 16}; |
| 1602 for (int flip = 0; flip <= 1; flip++) { | 1809 for (int flip = 0; flip <= 1; flip++) { |
| 1603 for (size_t q = 0; q < arraysize(kQualities); q++) { | 1810 for (size_t q_index = 0; q_index < arraysize(kQualities); q_index++) { |
| 1604 for (int x = 0; x < 3; x++) { | 1811 for (int x = 0; x < 3; x++) { |
| 1605 for (int y = 0; y < 3; y++) { | 1812 for (int y = 0; y < 3; y++) { |
| 1606 for (int dst_x = 0; dst_x < 3; dst_x++) { | 1813 for (int dst_x = 0; dst_x < 3; dst_x++) { |
| 1607 for (int dst_y = 0; dst_y < 3; dst_y++) { | 1814 for (int dst_y = 0; dst_y < 3; dst_y++) { |
| 1608 for (int pattern = 0; pattern < 3; pattern++) { | 1815 for (int pattern = 0; pattern < 3; pattern++) { |
| 1609 TestScale(sizes[x], | 1816 TestScale(sizes[x], |
| 1610 sizes[y], | 1817 sizes[y], |
| 1611 sizes[dst_x], | 1818 sizes[dst_x], |
| 1612 sizes[dst_y], | 1819 sizes[dst_y], |
| 1613 pattern, | 1820 pattern, |
| 1614 q, | 1821 q_index, |
| 1615 flip == 1); | 1822 flip == 1); |
| 1616 if (HasFailure()) { | 1823 if (HasFailure()) { |
| 1617 return; | 1824 return; |
| 1618 } | 1825 } |
| 1619 } | 1826 } |
| 1620 } | 1827 } |
| 1621 } | 1828 } |
| 1622 } | 1829 } |
| 1623 } | 1830 } |
| 1624 } | 1831 } |
| 1625 } | 1832 } |
| 1626 } | 1833 } |
| 1627 | 1834 |
| 1835 // Per pixel tests, all sizes are small so that we can print | |
| 1836 // out the generated bitmaps. | |
| 1837 TEST_F(GLHelperPixelTest, CropScaleReadbackAndCleanTextureTest) { | |
| 1838 const int kSizes[] = {3, 6, 16}; | |
| 1839 const SkColorType kColorTypes[] = { | |
| 1840 kAlpha_8_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType}; | |
| 1841 for (size_t color_type = 0; color_type < arraysize(kColorTypes); | |
| 1842 color_type++) { | |
| 1843 // Test BEST and FAST qualities, skip GOOD | |
| 1844 for (size_t q_index = 0; q_index < arraysize(kQualities); q_index += 2) { | |
| 1845 for (size_t x = 0; x < arraysize(kSizes); x++) { | |
| 1846 for (size_t y = 0; y < arraysize(kSizes); y++) { | |
| 1847 for (size_t dst_x = 0; dst_x < arraysize(kSizes); dst_x++) { | |
| 1848 for (size_t dst_y = 0; dst_y < arraysize(kSizes); dst_y++) { | |
| 1849 for (int pattern = 0; pattern < 3; pattern++) { | |
| 1850 TestCropScaleReadbackAndCleanTexture(kSizes[x], | |
| 1851 kSizes[y], | |
| 1852 kSizes[dst_x], | |
| 1853 kSizes[dst_y], | |
| 1854 pattern, | |
| 1855 kColorTypes[color_type], | |
| 1856 false, | |
| 1857 q_index); | |
| 1858 if (HasFailure()) | |
| 1859 return; | |
| 1860 } | |
| 1861 } | |
| 1862 } | |
| 1863 } | |
| 1864 } | |
| 1865 } | |
| 1866 } | |
| 1867 } | |
| 1868 | |
| 1628 // Validate that all scaling generates valid pipelines. | 1869 // Validate that all scaling generates valid pipelines. |
| 1629 TEST_F(GLHelperTest, ValidateScalerPipelines) { | 1870 TEST_F(GLHelperTest, ValidateScalerPipelines) { |
| 1630 int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096}; | 1871 int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096}; |
| 1631 for (size_t q = 0; q < arraysize(kQualities); q++) { | 1872 for (size_t q = 0; q < arraysize(kQualities); q++) { |
| 1632 for (size_t x = 0; x < arraysize(sizes); x++) { | 1873 for (size_t x = 0; x < arraysize(sizes); x++) { |
| 1633 for (size_t y = 0; y < arraysize(sizes); y++) { | 1874 for (size_t y = 0; y < arraysize(sizes); y++) { |
| 1634 for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) { | 1875 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++) { | 1876 for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) { |
| 1636 TestScalerPipeline( | 1877 TestScalerPipeline( |
| 1637 q, sizes[x], sizes[y], sizes[dst_x], sizes[dst_y]); | 1878 q, sizes[x], sizes[y], sizes[dst_x], sizes[dst_y]); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1701 base::CommandLine::Init(argc, argv); | 1942 base::CommandLine::Init(argc, argv); |
| 1702 base::TestSuite* suite = new content::ContentTestSuite(argc, argv); | 1943 base::TestSuite* suite = new content::ContentTestSuite(argc, argv); |
| 1703 #if defined(OS_MACOSX) | 1944 #if defined(OS_MACOSX) |
| 1704 base::mac::ScopedNSAutoreleasePool pool; | 1945 base::mac::ScopedNSAutoreleasePool pool; |
| 1705 #endif | 1946 #endif |
| 1706 | 1947 |
| 1707 content::UnitTestTestSuite runner(suite); | 1948 content::UnitTestTestSuite runner(suite); |
| 1708 base::MessageLoop message_loop; | 1949 base::MessageLoop message_loop; |
| 1709 return runner.Run(); | 1950 return runner.Run(); |
| 1710 } | 1951 } |
| OLD | NEW |