Index: cc/output/gl_renderer.cc |
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc |
index 9ea1110568750135c6a309da7a089ab01b562751..12566a89a50f5c5e4c1e1e93dfd0d639542a773b 100644 |
--- a/cc/output/gl_renderer.cc |
+++ b/cc/output/gl_renderer.cc |
@@ -2099,6 +2099,14 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame, |
gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); |
} |
+namespace { |
+ |
+float RelativeError(float a, float b) { |
+ return std::abs(a - b) / std::max(1.f, std::abs(a + b)); |
+} |
+ |
+} // namespace |
+ |
// TODO(ccameron): This has been replicated in ui/gfx/color_transform.cc. Delete |
// one of the instances. |
void ComputeYUVToRGBMatrices(YUVVideoDrawQuad::ColorSpace color_space, |
@@ -2136,18 +2144,22 @@ void ComputeYUVToRGBMatrices(YUVVideoDrawQuad::ColorSpace color_space, |
float* yuv_to_rgb = NULL; |
float* yuv_adjust = NULL; |
+ gfx::ColorSpace gfx_color_space; |
switch (color_space) { |
case YUVVideoDrawQuad::REC_601: |
yuv_to_rgb = yuv_to_rgb_rec601; |
yuv_adjust = yuv_adjust_constrained; |
+ gfx_color_space = gfx::ColorSpace::CreateREC601(); |
break; |
case YUVVideoDrawQuad::REC_709: |
yuv_to_rgb = yuv_to_rgb_rec709; |
yuv_adjust = yuv_adjust_constrained; |
+ gfx_color_space = gfx::ColorSpace::CreateREC709(); |
break; |
case YUVVideoDrawQuad::JPEG: |
yuv_to_rgb = yuv_to_rgb_jpeg; |
yuv_adjust = yuv_adjust_full; |
+ gfx_color_space = gfx::ColorSpace::CreateJpeg(); |
break; |
} |
@@ -2165,6 +2177,60 @@ void ComputeYUVToRGBMatrices(YUVVideoDrawQuad::ColorSpace color_space, |
yuv_adjust[i] * adjustment_multiplier / resource_multiplier - |
resource_offset; |
} |
+ |
+ // TODO(ccameron): Delete the above code, and just the below code instead. |
+ // Compute the matrix |full_transform| which converts input YUV values to RGB |
+ // values. |
+ SkMatrix44 full_transform; |
+ |
+ // Start with the resource adjust. |
+ full_transform.setScale(resource_multiplier, resource_multiplier, |
+ resource_multiplier); |
+ full_transform.preTranslate(-resource_offset, -resource_offset, |
+ -resource_offset); |
+ |
+ // Then apply the range adjust. |
+ { |
+ SkMatrix44 range_adjust; |
+ gfx_color_space.GetRangeAdjustMatrix(&range_adjust); |
+ full_transform.postConcat(range_adjust); |
+ } |
+ |
+ // Then apply the YUV to RGB full_transform. |
+ { |
+ SkMatrix44 rgb_to_yuv; |
+ gfx_color_space.GetTransferMatrix(&rgb_to_yuv); |
+ SkMatrix44 yuv_to_rgb; |
+ rgb_to_yuv.invert(&yuv_to_rgb); |
+ full_transform.postConcat(yuv_to_rgb); |
+ } |
+ |
+ // For the upcoming DCHECKs, convert from the form |
+ // rgb = A*yuv+b |
+ // to the form |
+ // rgb = A*(yuv+b) |
+ float adjust[4] = {0, 0, 0, 0}; |
+ { |
+ SkMatrix44 full_transform_inverse; |
+ full_transform.invert(&full_transform_inverse); |
+ float adjust_preimage[4] = {full_transform.get(0, 3), |
+ full_transform.get(1, 3), |
+ full_transform.get(2, 3), 0}; |
+ full_transform_inverse.mapScalars(adjust_preimage, adjust); |
+ } |
+ |
+ // TODO(ccameron): The gfx::ColorSpace-based approach produces some pixel |
+ // differences. For the initial checkin, DCHECK that the parameters are |
+ // very close. The subsequent checkins will delete the old path. |
+ const float kEpsilon = 1.f / 255.f; |
+ for (int i = 0; i < 3; ++i) { |
+ for (int j = 0; j < 3; ++j) { |
+ DCHECK_LT(RelativeError(yuv_to_rgb_multiplied[3 * j + i], |
+ full_transform.get(i, j)), |
+ kEpsilon); |
+ } |
+ DCHECK_LT(RelativeError(yuv_adjust_with_offset[i], adjust[i]), kEpsilon); |
+ } |
} |
void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, |