| 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 <stdint.h> | 5 #include <stdint.h> |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/memory/aligned_memory.h" | 8 #include "base/memory/aligned_memory.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "gpu/GLES2/gl2extchromium.h" | 10 #include "gpu/GLES2/gl2extchromium.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 return 0; | 43 return 0; |
| 44 if (!canvas->readPixels(&bitmap, x, y)) | 44 if (!canvas->readPixels(&bitmap, x, y)) |
| 45 return 0; | 45 return 0; |
| 46 return bitmap.getColor(0, 0); | 46 return bitmap.getColor(0, 0); |
| 47 } | 47 } |
| 48 | 48 |
| 49 SkColor GetColor(SkCanvas* canvas) { | 49 SkColor GetColor(SkCanvas* canvas) { |
| 50 return GetColorAt(canvas, 0, 0); | 50 return GetColorAt(canvas, 0, 0); |
| 51 } | 51 } |
| 52 | 52 |
| 53 // Generate frame pixels to provided |external_memory| and wrap it as frame. |
| 54 scoped_refptr<VideoFrame> CreateTestY16Frame(const gfx::Size& coded_size, |
| 55 const gfx::Rect& visible_rect, |
| 56 void* external_memory, |
| 57 base::TimeDelta timestamp) { |
| 58 const int offset_x = visible_rect.x(); |
| 59 const int offset_y = visible_rect.y(); |
| 60 const int stride = coded_size.width(); |
| 61 const size_t byte_size = stride * coded_size.height() * 2; |
| 62 |
| 63 // In the visible rect, fill upper byte with [0-255] and lower with [255-0]. |
| 64 uint16_t* data = static_cast<uint16_t*>(external_memory); |
| 65 for (int j = 0; j < visible_rect.height(); j++) { |
| 66 for (int i = 0; i < visible_rect.width(); i++) { |
| 67 const int value = i + j * visible_rect.width(); |
| 68 data[(stride * (j + offset_y)) + i + offset_x] = |
| 69 ((value & 0xFF) << 8) | (~value & 0xFF); |
| 70 } |
| 71 } |
| 72 |
| 73 return media::VideoFrame::WrapExternalData( |
| 74 media::PIXEL_FORMAT_Y16, coded_size, visible_rect, visible_rect.size(), |
| 75 static_cast<uint8_t*>(external_memory), byte_size, timestamp); |
| 76 } |
| 77 |
| 53 class SkCanvasVideoRendererTest : public testing::Test { | 78 class SkCanvasVideoRendererTest : public testing::Test { |
| 54 public: | 79 public: |
| 55 enum Color { | 80 enum Color { |
| 56 kNone, | 81 kNone, |
| 57 kRed, | 82 kRed, |
| 58 kGreen, | 83 kGreen, |
| 59 kBlue, | 84 kBlue, |
| 60 }; | 85 }; |
| 61 | 86 |
| 62 SkCanvasVideoRendererTest(); | 87 SkCanvasVideoRendererTest(); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 bitmap.allocPixels(SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType)); | 543 bitmap.allocPixels(SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType)); |
| 519 | 544 |
| 520 // |offset_x| and |offset_y| define visible rect's offset to coded rect. | 545 // |offset_x| and |offset_y| define visible rect's offset to coded rect. |
| 521 const int offset_x = 3; | 546 const int offset_x = 3; |
| 522 const int offset_y = 5; | 547 const int offset_y = 5; |
| 523 const int stride = bitmap.width() + offset_x; | 548 const int stride = bitmap.width() + offset_x; |
| 524 const size_t byte_size = stride * (bitmap.height() + offset_y) * 2; | 549 const size_t byte_size = stride * (bitmap.height() + offset_y) * 2; |
| 525 std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory( | 550 std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory( |
| 526 static_cast<unsigned char*>(base::AlignedAlloc( | 551 static_cast<unsigned char*>(base::AlignedAlloc( |
| 527 byte_size, media::VideoFrame::kFrameAddressAlignment))); | 552 byte_size, media::VideoFrame::kFrameAddressAlignment))); |
| 528 | |
| 529 // In the visible rect, fill upper byte with [0-255] and lower with [255-0]. | |
| 530 uint16_t* data = reinterpret_cast<uint16_t*>(memory.get()); | |
| 531 for (int j = 0; j < bitmap.height(); j++) { | |
| 532 for (int i = 0; i < bitmap.width(); i++) { | |
| 533 const int value = i + j * bitmap.width(); | |
| 534 data[(stride * (j + offset_y)) + i + offset_x] = | |
| 535 ((value & 0xFF) << 8) | (~value & 0xFF); | |
| 536 } | |
| 537 } | |
| 538 const gfx::Rect rect(offset_x, offset_y, bitmap.width(), bitmap.height()); | 553 const gfx::Rect rect(offset_x, offset_y, bitmap.width(), bitmap.height()); |
| 539 scoped_refptr<media::VideoFrame> video_frame = | 554 scoped_refptr<media::VideoFrame> video_frame = |
| 540 media::VideoFrame::WrapExternalData( | 555 CreateTestY16Frame(gfx::Size(stride, offset_y + bitmap.height()), rect, |
| 541 media::PIXEL_FORMAT_Y16, | 556 memory.get(), cropped_frame()->timestamp()); |
| 542 gfx::Size(stride, offset_y + bitmap.height()), rect, rect.size(), | |
| 543 memory.get(), byte_size, cropped_frame()->timestamp()); | |
| 544 | 557 |
| 545 SkCanvas canvas(bitmap); | 558 SkCanvas canvas(bitmap); |
| 546 SkPaint paint; | 559 SkPaint paint; |
| 547 paint.setFilterQuality(kNone_SkFilterQuality); | 560 paint.setFilterQuality(kNone_SkFilterQuality); |
| 548 renderer_.Paint(video_frame, &canvas, | 561 renderer_.Paint(video_frame, &canvas, |
| 549 gfx::RectF(bitmap.width(), bitmap.height()), paint, | 562 gfx::RectF(bitmap.width(), bitmap.height()), paint, |
| 550 VIDEO_ROTATION_0, Context3D()); | 563 VIDEO_ROTATION_0, Context3D()); |
| 551 SkAutoLockPixels lock(bitmap); | 564 SkAutoLockPixels lock(bitmap); |
| 552 for (int j = 0; j < bitmap.height(); j++) { | 565 for (int j = 0; j < bitmap.height(); j++) { |
| 553 for (int i = 0; i < bitmap.width(); i++) { | 566 for (int i = 0; i < bitmap.width(); i++) { |
| 554 const int value = i + j * bitmap.width(); | 567 const int value = i + j * bitmap.width(); |
| 555 EXPECT_EQ(SkColorSetRGB(value, value, value), bitmap.getColor(i, j)); | 568 EXPECT_EQ(SkColorSetRGB(value, value, value), bitmap.getColor(i, j)); |
| 556 } | 569 } |
| 557 } | 570 } |
| 558 } | 571 } |
| 559 | 572 |
| 560 namespace { | 573 namespace { |
| 561 class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub { | 574 class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub { |
| 562 public: | 575 public: |
| 563 void GenTextures(GLsizei n, GLuint* textures) override { | 576 void GenTextures(GLsizei n, GLuint* textures) override { |
| 564 DCHECK_EQ(1, n); | 577 DCHECK_EQ(1, n); |
| 565 *textures = 1; | 578 *textures = 1; |
| 566 } | 579 } |
| 580 |
| 581 void TexImage2D(GLenum target, |
| 582 GLint level, |
| 583 GLint internalformat, |
| 584 GLsizei width, |
| 585 GLsizei height, |
| 586 GLint border, |
| 587 GLenum format, |
| 588 GLenum type, |
| 589 const void* pixels) override { |
| 590 if (!teximage2d_callback_.is_null()) { |
| 591 teximage2d_callback_.Run(target, level, internalformat, width, height, |
| 592 border, format, type, pixels); |
| 593 } |
| 594 } |
| 595 |
| 596 base::Callback<void(GLenum target, |
| 597 GLint level, |
| 598 GLint internalformat, |
| 599 GLsizei width, |
| 600 GLsizei height, |
| 601 GLint border, |
| 602 GLenum format, |
| 603 GLenum type, |
| 604 const void* pixels)> |
| 605 teximage2d_callback_; |
| 567 }; | 606 }; |
| 568 void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {} | 607 void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {} |
| 569 } // namespace | 608 } // namespace |
| 570 | 609 |
| 571 // Test that SkCanvasVideoRendererTest::Paint doesn't crash when GrContext is | 610 // Test that SkCanvasVideoRendererTest::Paint doesn't crash when GrContext is |
| 572 // abandoned. | 611 // abandoned. |
| 573 TEST_F(SkCanvasVideoRendererTest, ContextLost) { | 612 TEST_F(SkCanvasVideoRendererTest, ContextLost) { |
| 574 sk_sp<const GrGLInterface> null_interface(GrGLCreateNullInterface()); | 613 sk_sp<const GrGLInterface> null_interface(GrGLCreateNullInterface()); |
| 575 sk_sp<GrContext> gr_context(GrContext::Create( | 614 sk_sp<GrContext> gr_context(GrContext::Create( |
| 576 kOpenGL_GrBackend, | 615 kOpenGL_GrBackend, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 | 667 |
| 629 gfx::RectF visible_rect(visible_size.width(), visible_size.height()); | 668 gfx::RectF visible_rect(visible_size.width(), visible_size.height()); |
| 630 SkPaint paint; | 669 SkPaint paint; |
| 631 renderer_.Paint(video_frame, canvas, visible_rect, paint, VIDEO_ROTATION_0, | 670 renderer_.Paint(video_frame, canvas, visible_rect, paint, VIDEO_ROTATION_0, |
| 632 context_3d); | 671 context_3d); |
| 633 | 672 |
| 634 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width()); | 673 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width()); |
| 635 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height()); | 674 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height()); |
| 636 } | 675 } |
| 637 | 676 |
| 677 TEST_F(SkCanvasVideoRendererTest, TexImageImplY16) { |
| 678 // Create test frame. |
| 679 // |offset_x| and |offset_y| define visible rect's offset to coded rect. |
| 680 const int offset_x = 3; |
| 681 const int offset_y = 5; |
| 682 const int width = 16; |
| 683 const int height = 16; |
| 684 const int stride = width + offset_x; |
| 685 const size_t byte_size = stride * (height + offset_y) * 2; |
| 686 std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory( |
| 687 static_cast<unsigned char*>(base::AlignedAlloc( |
| 688 byte_size, media::VideoFrame::kFrameAddressAlignment))); |
| 689 const gfx::Rect rect(offset_x, offset_y, width, height); |
| 690 scoped_refptr<media::VideoFrame> video_frame = |
| 691 CreateTestY16Frame(gfx::Size(stride, offset_y + height), rect, |
| 692 memory.get(), cropped_frame()->timestamp()); |
| 693 |
| 694 // Create GL context. |
| 695 sk_sp<const GrGLInterface> null_interface(GrGLCreateNullInterface()); |
| 696 sk_sp<GrContext> gr_context(GrContext::Create( |
| 697 kOpenGL_GrBackend, |
| 698 reinterpret_cast<GrBackendContext>(null_interface.get()))); |
| 699 TestGLES2Interface gles2; |
| 700 Context3D context_3d(&gles2, gr_context.get()); |
| 701 |
| 702 // Bind the texImage2D callback to verify the uint16 to float32 conversion. |
| 703 gles2.teximage2d_callback_ = |
| 704 base::Bind([](GLenum target, GLint level, GLint internalformat, |
| 705 GLsizei width, GLsizei height, GLint border, GLenum format, |
| 706 GLenum type, const void* pixels) { |
| 707 EXPECT_EQ(static_cast<unsigned>(GL_FLOAT), type); |
| 708 EXPECT_EQ(static_cast<unsigned>(GL_RGBA), format); |
| 709 EXPECT_EQ(GL_RGBA, internalformat); |
| 710 EXPECT_EQ(0, border); |
| 711 EXPECT_EQ(16, width); |
| 712 EXPECT_EQ(16, height); |
| 713 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); |
| 714 const float* data = static_cast<const float*>(pixels); |
| 715 for (int j = 0; j < height; j++) { |
| 716 for (int i = 0; i < width; i++) { |
| 717 const int value = i + (height - j - 1) * width; // flip_y is true. |
| 718 float expected_value = |
| 719 (((value & 0xFF) << 8) | (~value & 0xFF)) / 65535.f; |
| 720 EXPECT_EQ(expected_value, data[(i + j * width) * 4]); |
| 721 EXPECT_EQ(expected_value, data[(i + j * width) * 4 + 1]); |
| 722 EXPECT_EQ(expected_value, data[(i + j * width) * 4 + 2]); |
| 723 EXPECT_EQ(1.0f, data[(i + j * width) * 4 + 3]); |
| 724 } |
| 725 } |
| 726 }); |
| 727 SkCanvasVideoRenderer::TexImage2D(GL_TEXTURE_2D, &gles2, video_frame.get(), 0, |
| 728 GL_RGBA, GL_RGBA, GL_FLOAT, true /*flip_y*/, |
| 729 true); |
| 730 } |
| 731 |
| 638 } // namespace media | 732 } // namespace media |
| OLD | NEW |