Index: cc/output/renderer_pixeltest.cc |
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc |
index 08a40530eb4753c1257a963e72bcc15c5a2f0af3..d503cc4462160623e84d19d49898a5875334b475 100644 |
--- a/cc/output/renderer_pixeltest.cc |
+++ b/cc/output/renderer_pixeltest.cc |
@@ -423,8 +423,9 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest { |
v_row[j] = (v_value += 5); |
} |
} |
+ uint8 alpha_value = is_transparent ? 0 : 128; |
CreateTestYUVVideoDrawQuad_FromVideoFrame( |
- shared_state, video_frame, is_transparent, tex_coord_rect, render_pass); |
+ shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); |
} |
void CreateTestYUVVideoDrawQuad_Solid(const SharedQuadState* shared_state, |
@@ -456,14 +457,110 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest { |
video_frame->stride(media::VideoFrame::kVPlane) * |
video_frame->rows(media::VideoFrame::kVPlane)); |
+ uint8 alpha_value = is_transparent ? 0 : 128; |
CreateTestYUVVideoDrawQuad_FromVideoFrame( |
- shared_state, video_frame, is_transparent, tex_coord_rect, render_pass); |
+ shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); |
+ } |
+ |
+ void CreateEdgeBleedPass(media::VideoFrame::Format format, |
+ RenderPassList* pass_list) { |
+ gfx::Rect rect(200, 200); |
+ |
+ RenderPassId id(1, 1); |
+ scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); |
+ |
+ // Scale the video up so that bilinear filtering kicks in to sample more |
+ // than just nearest neighbor would. |
+ gfx::Transform scale_by_2; |
+ scale_by_2.Scale(2.f, 2.f); |
+ gfx::Rect half_rect(100, 100); |
+ SharedQuadState* shared_state = |
+ CreateTestSharedQuadState(scale_by_2, half_rect, pass.get()); |
+ |
+ gfx::Size background_size(200, 200); |
+ gfx::Rect green_rect(16, 20, 100, 100); |
+ gfx::RectF tex_coord_rect( |
+ static_cast<float>(green_rect.x()) / background_size.width(), |
+ static_cast<float>(green_rect.y()) / background_size.height(), |
+ static_cast<float>(green_rect.width()) / background_size.width(), |
+ static_cast<float>(green_rect.height()) / background_size.height()); |
+ |
+ // YUV of (149,43,21) should be green (0,255,0) in RGB. |
+ // Create a video frame that has a non-green background rect, with a |
+ // green sub-rectangle that should be the only thing displayed in |
+ // the final image. Bleeding will appear on all four sides of the video |
+ // if the tex coords are not clamped. |
+ CreateTestYUVVideoDrawQuad_TwoColor(shared_state, format, false, |
+ tex_coord_rect, background_size, 0, 0, |
+ 0, green_rect, 149, 43, 21, pass.get()); |
+ pass_list->push_back(pass.Pass()); |
+ } |
+ |
+ // Creates a video frame of size background_size filled with yuv_background, |
+ // and then draws a foreground rectangle in a different color on top of |
+ // that. The foreground rectangle must have coordinates that are divisible |
+ // by 2 because YUV is a block format. |
+ void CreateTestYUVVideoDrawQuad_TwoColor(const SharedQuadState* shared_state, |
+ media::VideoFrame::Format format, |
+ bool is_transparent, |
+ const gfx::RectF& tex_coord_rect, |
+ const gfx::Size& background_size, |
+ uint8 y_background, |
+ uint8 u_background, |
+ uint8 v_background, |
+ const gfx::Rect& foreground_rect, |
+ uint8 y_foreground, |
+ uint8 u_foreground, |
+ uint8 v_foreground, |
+ RenderPass* render_pass) { |
+ const gfx::Rect rect(background_size); |
+ |
+ scoped_refptr<media::VideoFrame> video_frame = |
+ media::VideoFrame::CreateFrame(format, background_size, foreground_rect, |
+ foreground_rect.size(), |
+ base::TimeDelta()); |
+ |
+ int planes[] = {media::VideoFrame::kYPlane, |
+ media::VideoFrame::kUPlane, |
+ media::VideoFrame::kVPlane}; |
+ uint8 yuv_background[] = {y_background, u_background, v_background}; |
+ uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground}; |
+ int sample_size[] = {1, 2, 2}; |
+ |
+ for (int i = 0; i < 3; ++i) { |
+ memset(video_frame->data(planes[i]), yuv_background[i], |
+ video_frame->stride(planes[i]) * video_frame->rows(planes[i])); |
+ } |
+ |
+ for (int i = 0; i < 3; ++i) { |
+ // Since yuv encoding uses block encoding, widths have to be divisible |
+ // by the sample size in order for this function to behave properly. |
+ DCHECK_EQ(foreground_rect.x() % sample_size[i], 0); |
+ DCHECK_EQ(foreground_rect.y() % sample_size[i], 0); |
+ DCHECK_EQ(foreground_rect.width() % sample_size[i], 0); |
+ DCHECK_EQ(foreground_rect.height() % sample_size[i], 0); |
+ |
+ gfx::Rect sample_rect(foreground_rect.x() / sample_size[i], |
+ foreground_rect.y() / sample_size[i], |
+ foreground_rect.width() / sample_size[i], |
+ foreground_rect.height() / sample_size[i]); |
+ for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) { |
+ for (int x = sample_rect.x(); x < sample_rect.right(); ++x) { |
+ size_t offset = y * video_frame->stride(planes[i]) + x; |
+ video_frame->data(planes[i])[offset] = yuv_foreground[i]; |
+ } |
+ } |
+ } |
+ |
+ uint8 alpha_value = 255; |
+ CreateTestYUVVideoDrawQuad_FromVideoFrame( |
+ shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); |
} |
void CreateTestYUVVideoDrawQuad_FromVideoFrame( |
const SharedQuadState* shared_state, |
scoped_refptr<media::VideoFrame> video_frame, |
- bool is_transparent, |
+ uint8 alpha_value, |
const gfx::RectF& tex_coord_rect, |
RenderPass* render_pass) { |
const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A); |
@@ -471,12 +568,11 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest { |
(video_frame->format() == media::VideoFrame::YV12J |
? YUVVideoDrawQuad::REC_601_JPEG |
: YUVVideoDrawQuad::REC_601); |
- const gfx::Rect rect(this->device_viewport_size_); |
+ const gfx::Rect rect(shared_state->content_bounds); |
const gfx::Rect opaque_rect(0, 0, 0, 0); |
if (with_alpha) |
- memset(video_frame->data(media::VideoFrame::kAPlane), |
- is_transparent ? 0 : 128, |
+ memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value, |
video_frame->stride(media::VideoFrame::kAPlane) * |
video_frame->rows(media::VideoFrame::kAPlane)); |
@@ -515,16 +611,9 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest { |
YUVVideoDrawQuad* yuv_quad = |
render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); |
- yuv_quad->SetNew(shared_state, |
- rect, |
- opaque_rect, |
- rect, |
- tex_coord_rect, |
- y_resource, |
- u_resource, |
- v_resource, |
- a_resource, |
- color_space); |
+ yuv_quad->SetNew(shared_state, rect, opaque_rect, rect, tex_coord_rect, |
+ video_frame->coded_size(), y_resource, u_resource, |
+ v_resource, a_resource, color_space); |
} |
void SetUp() override { |
@@ -642,6 +731,24 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) { |
FuzzyPixelOffByOneComparator(true))); |
} |
+// Test that a YUV video doesn't bleed outside of its tex coords when the |
+// tex coord rect is only a partial subrectangle of the coded contents. |
+TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) { |
+ RenderPassList pass_list; |
+ CreateEdgeBleedPass(media::VideoFrame::YV12J, &pass_list); |
+ EXPECT_TRUE(this->RunPixelTest(&pass_list, |
+ base::FilePath(FILE_PATH_LITERAL("green.png")), |
+ FuzzyPixelOffByOneComparator(true))); |
+} |
+ |
+TEST_F(VideoGLRendererPixelTest, YUVAEdgeBleed) { |
+ RenderPassList pass_list; |
+ CreateEdgeBleedPass(media::VideoFrame::YV12A, &pass_list); |
+ EXPECT_TRUE(this->RunPixelTest(&pass_list, |
+ base::FilePath(FILE_PATH_LITERAL("green.png")), |
+ FuzzyPixelOffByOneComparator(true))); |
+} |
+ |
TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) { |
gfx::Rect rect(this->device_viewport_size_); |