OLD | NEW |
1 // Copyright 2010 The Chromium Authors. All rights reserved. | 1 // Copyright 2010 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 "cc/output/gl_renderer.h" | 5 #include "cc/output/gl_renderer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 } | 2106 } |
2107 | 2107 |
2108 } // namespace | 2108 } // namespace |
2109 | 2109 |
2110 // TODO(ccameron): This has been replicated in ui/gfx/color_transform.cc. Delete | 2110 // TODO(ccameron): This has been replicated in ui/gfx/color_transform.cc. Delete |
2111 // one of the instances. | 2111 // one of the instances. |
2112 void ComputeYUVToRGBMatrices(YUVVideoDrawQuad::ColorSpace color_space, | 2112 void ComputeYUVToRGBMatrices(YUVVideoDrawQuad::ColorSpace color_space, |
2113 uint32_t bits_per_channel, | 2113 uint32_t bits_per_channel, |
2114 float resource_multiplier, | 2114 float resource_multiplier, |
2115 float resource_offset, | 2115 float resource_offset, |
2116 float* yuv_to_rgb_multiplied, | 2116 ColorConversionMode color_conversion_mode, |
2117 float* yuv_adjust_with_offset) { | 2117 float* yuv_to_rgb_matrix) { |
| 2118 float yuv_to_rgb_multiplied[9]; |
| 2119 float yuv_adjust_with_offset[3]; |
| 2120 |
2118 // These values are magic numbers that are used in the transformation from YUV | 2121 // These values are magic numbers that are used in the transformation from YUV |
2119 // to RGB color values. They are taken from the following webpage: | 2122 // to RGB color values. They are taken from the following webpage: |
2120 // http://www.fourcc.org/fccyvrgb.php | 2123 // http://www.fourcc.org/fccyvrgb.php |
2121 float yuv_to_rgb_rec601[9] = { | 2124 float yuv_to_rgb_rec601[9] = { |
2122 1.164f, 1.164f, 1.164f, 0.0f, -.391f, 2.018f, 1.596f, -.813f, 0.0f, | 2125 1.164f, 1.164f, 1.164f, 0.0f, -.391f, 2.018f, 1.596f, -.813f, 0.0f, |
2123 }; | 2126 }; |
2124 float yuv_to_rgb_jpeg[9] = { | 2127 float yuv_to_rgb_jpeg[9] = { |
2125 1.f, 1.f, 1.f, 0.0f, -.34414f, 1.772f, 1.402f, -.71414f, 0.0f, | 2128 1.f, 1.f, 1.f, 0.0f, -.34414f, 1.772f, 1.402f, -.71414f, 0.0f, |
2126 }; | 2129 }; |
2127 float yuv_to_rgb_rec709[9] = { | 2130 float yuv_to_rgb_rec709[9] = { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2165 | 2168 |
2166 // Formula according to BT.601-7 section 2.5.3. | 2169 // Formula according to BT.601-7 section 2.5.3. |
2167 DCHECK_LE(YUVVideoDrawQuad::kMinBitsPerChannel, bits_per_channel); | 2170 DCHECK_LE(YUVVideoDrawQuad::kMinBitsPerChannel, bits_per_channel); |
2168 DCHECK_LE(bits_per_channel, YUVVideoDrawQuad::kMaxBitsPerChannel); | 2171 DCHECK_LE(bits_per_channel, YUVVideoDrawQuad::kMaxBitsPerChannel); |
2169 float adjustment_multiplier = | 2172 float adjustment_multiplier = |
2170 (1 << (bits_per_channel - 8)) * 1.0f / ((1 << bits_per_channel) - 1); | 2173 (1 << (bits_per_channel - 8)) * 1.0f / ((1 << bits_per_channel) - 1); |
2171 | 2174 |
2172 for (int i = 0; i < 9; ++i) | 2175 for (int i = 0; i < 9; ++i) |
2173 yuv_to_rgb_multiplied[i] = yuv_to_rgb[i] * resource_multiplier; | 2176 yuv_to_rgb_multiplied[i] = yuv_to_rgb[i] * resource_multiplier; |
2174 | 2177 |
| 2178 float yuv_adjust_with_offset_untransformed[3]; |
2175 for (int i = 0; i < 3; ++i) { | 2179 for (int i = 0; i < 3; ++i) { |
2176 yuv_adjust_with_offset[i] = | 2180 yuv_adjust_with_offset_untransformed[i] = |
2177 yuv_adjust[i] * adjustment_multiplier / resource_multiplier - | 2181 yuv_adjust[i] * adjustment_multiplier / resource_multiplier - |
2178 resource_offset; | 2182 resource_offset; |
2179 } | 2183 } |
2180 | 2184 |
| 2185 for (int i = 0; i < 3; ++i) { |
| 2186 yuv_adjust_with_offset[i] = 0; |
| 2187 for (int j = 0; j < 3; ++j) { |
| 2188 yuv_adjust_with_offset[i] += yuv_to_rgb_multiplied[3 * j + i] * |
| 2189 yuv_adjust_with_offset_untransformed[j]; |
| 2190 } |
| 2191 } |
| 2192 |
2181 // TODO(ccameron): Delete the above code, and just the below code instead. | 2193 // TODO(ccameron): Delete the above code, and just the below code instead. |
2182 // Compute the matrix |full_transform| which converts input YUV values to RGB | 2194 // Compute the matrix |full_transform| which converts input YUV values to RGB |
2183 // values. | 2195 // values. |
2184 SkMatrix44 full_transform; | 2196 SkMatrix44 full_transform; |
2185 | 2197 |
2186 // Start with the resource adjust. | 2198 // Start with the resource adjust. |
2187 full_transform.setScale(resource_multiplier, resource_multiplier, | 2199 full_transform.setScale(resource_multiplier, resource_multiplier, |
2188 resource_multiplier); | 2200 resource_multiplier); |
2189 full_transform.preTranslate(-resource_offset, -resource_offset, | 2201 full_transform.preTranslate(-resource_offset, -resource_offset, |
2190 -resource_offset); | 2202 -resource_offset); |
2191 | 2203 |
| 2204 // If we're using a LUT for conversion, we only need the resource adjust, |
| 2205 // so just return this matrix. |
| 2206 if (color_conversion_mode == COLOR_CONVERSION_MODE_LUT) { |
| 2207 full_transform.asColMajorf(yuv_to_rgb_matrix); |
| 2208 return; |
| 2209 } |
| 2210 |
2192 // Then apply the range adjust. | 2211 // Then apply the range adjust. |
2193 { | 2212 { |
2194 SkMatrix44 range_adjust; | 2213 SkMatrix44 range_adjust; |
2195 gfx_color_space.GetRangeAdjustMatrix(&range_adjust); | 2214 gfx_color_space.GetRangeAdjustMatrix(&range_adjust); |
2196 full_transform.postConcat(range_adjust); | 2215 full_transform.postConcat(range_adjust); |
2197 } | 2216 } |
2198 | 2217 |
2199 // Then apply the YUV to RGB full_transform. | 2218 // Then apply the YUV to RGB full_transform. |
2200 { | 2219 { |
2201 SkMatrix44 rgb_to_yuv; | 2220 SkMatrix44 rgb_to_yuv; |
2202 gfx_color_space.GetTransferMatrix(&rgb_to_yuv); | 2221 gfx_color_space.GetTransferMatrix(&rgb_to_yuv); |
2203 SkMatrix44 yuv_to_rgb; | 2222 SkMatrix44 yuv_to_rgb; |
2204 rgb_to_yuv.invert(&yuv_to_rgb); | 2223 rgb_to_yuv.invert(&yuv_to_rgb); |
2205 full_transform.postConcat(yuv_to_rgb); | 2224 full_transform.postConcat(yuv_to_rgb); |
2206 } | 2225 } |
2207 | 2226 |
2208 // For the upcoming DCHECKs, convert from the form | 2227 SkMatrix44 full_transform_old; |
2209 // rgb = A*yuv+b | 2228 full_transform_old.set3x3RowMajorf(yuv_to_rgb_multiplied); |
2210 // to the form | 2229 full_transform_old.transpose(); |
2211 // rgb = A*(yuv+b) | 2230 full_transform_old.postTranslate(yuv_adjust_with_offset[0], |
2212 float adjust[4] = {0, 0, 0, 0}; | 2231 yuv_adjust_with_offset[1], |
2213 { | 2232 yuv_adjust_with_offset[2]); |
2214 SkMatrix44 full_transform_inverse; | |
2215 full_transform.invert(&full_transform_inverse); | |
2216 float adjust_preimage[4] = {full_transform.get(0, 3), | |
2217 full_transform.get(1, 3), | |
2218 full_transform.get(2, 3), 0}; | |
2219 full_transform_inverse.mapScalars(adjust_preimage, adjust); | |
2220 } | |
2221 | 2233 |
2222 // TODO(ccameron): The gfx::ColorSpace-based approach produces some pixel | 2234 // TODO(ccameron): The gfx::ColorSpace-based approach produces some pixel |
2223 // differences. For the initial checkin, DCHECK that the parameters are | 2235 // differences. For the initial checkin, DCHECK that the parameters are |
2224 // very close. The subsequent checkins will delete the old path. | 2236 // very close. The subsequent checkins will delete the old path. |
2225 const float kEpsilon = 1.f / 255.f; | 2237 const float kEpsilon = 1.f / 255.f; |
2226 for (int i = 0; i < 3; ++i) { | 2238 for (int i = 0; i < 4; ++i) { |
2227 for (int j = 0; j < 3; ++j) { | 2239 for (int j = 0; j < 4; ++j) { |
2228 DCHECK_LT(RelativeError(yuv_to_rgb_multiplied[3 * j + i], | 2240 DCHECK_LT( |
2229 full_transform.get(i, j)), | 2241 RelativeError(full_transform_old.get(i, j), full_transform.get(i, j)), |
2230 kEpsilon); | 2242 kEpsilon); |
2231 } | 2243 } |
2232 DCHECK_LT(RelativeError(yuv_adjust_with_offset[i], adjust[i]), kEpsilon); | |
2233 } | 2244 } |
| 2245 full_transform_old.asColMajorf(yuv_to_rgb_matrix); |
2234 } | 2246 } |
2235 | 2247 |
2236 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, | 2248 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, |
2237 const YUVVideoDrawQuad* quad, | 2249 const YUVVideoDrawQuad* quad, |
2238 const gfx::QuadF* clip_region) { | 2250 const gfx::QuadF* clip_region) { |
2239 SetBlendEnabled(quad->ShouldDrawWithBlending()); | 2251 SetBlendEnabled(quad->ShouldDrawWithBlending()); |
2240 | 2252 |
2241 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( | 2253 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( |
2242 gl_, &highp_threshold_cache_, highp_threshold_min_, | 2254 gl_, &highp_threshold_cache_, highp_threshold_min_, |
2243 quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); | 2255 quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); |
2244 YUVAlphaTextureMode alpha_texture_mode = quad->a_plane_resource_id() | 2256 YUVAlphaTextureMode alpha_texture_mode = quad->a_plane_resource_id() |
2245 ? YUV_HAS_ALPHA_TEXTURE | 2257 ? YUV_HAS_ALPHA_TEXTURE |
2246 : YUV_NO_ALPHA_TEXTURE; | 2258 : YUV_NO_ALPHA_TEXTURE; |
2247 UVTextureMode uv_texture_mode = | 2259 UVTextureMode uv_texture_mode = |
2248 quad->v_plane_resource_id() == quad->u_plane_resource_id() | 2260 quad->v_plane_resource_id() == quad->u_plane_resource_id() |
2249 ? UV_TEXTURE_MODE_UV | 2261 ? UV_TEXTURE_MODE_UV |
2250 : UV_TEXTURE_MODE_U_V; | 2262 : UV_TEXTURE_MODE_U_V; |
2251 ColorConversionMode color_conversion_mode = | 2263 ColorConversionMode color_conversion_mode = |
2252 base::FeatureList::IsEnabled(media::kVideoColorManagement) | 2264 base::FeatureList::IsEnabled(media::kVideoColorManagement) |
2253 ? COLOR_CONVERSION_MODE_LUT_FROM_YUV | 2265 ? COLOR_CONVERSION_MODE_LUT |
2254 : COLOR_CONVERSION_MODE_NONE; | 2266 : COLOR_CONVERSION_MODE_NONE; |
2255 ResourceProvider::ScopedSamplerGL y_plane_lock( | 2267 ResourceProvider::ScopedSamplerGL y_plane_lock( |
2256 resource_provider_, quad->y_plane_resource_id(), GL_TEXTURE1, GL_LINEAR); | 2268 resource_provider_, quad->y_plane_resource_id(), GL_TEXTURE1, GL_LINEAR); |
2257 ResourceProvider::ScopedSamplerGL u_plane_lock( | 2269 ResourceProvider::ScopedSamplerGL u_plane_lock( |
2258 resource_provider_, quad->u_plane_resource_id(), GL_TEXTURE2, GL_LINEAR); | 2270 resource_provider_, quad->u_plane_resource_id(), GL_TEXTURE2, GL_LINEAR); |
2259 DCHECK_EQ(y_plane_lock.target(), u_plane_lock.target()); | 2271 DCHECK_EQ(y_plane_lock.target(), u_plane_lock.target()); |
2260 // TODO(jbauman): Use base::Optional when available. | 2272 // TODO(jbauman): Use base::Optional when available. |
2261 std::unique_ptr<ResourceProvider::ScopedSamplerGL> v_plane_lock; | 2273 std::unique_ptr<ResourceProvider::ScopedSamplerGL> v_plane_lock; |
2262 | 2274 |
2263 if (uv_texture_mode == UV_TEXTURE_MODE_U_V) { | 2275 if (uv_texture_mode == UV_TEXTURE_MODE_U_V) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 gl_->Uniform1i(program->y_texture_location(), 1); | 2351 gl_->Uniform1i(program->y_texture_location(), 1); |
2340 if (uv_texture_mode == UV_TEXTURE_MODE_UV) { | 2352 if (uv_texture_mode == UV_TEXTURE_MODE_UV) { |
2341 gl_->Uniform1i(program->uv_texture_location(), 2); | 2353 gl_->Uniform1i(program->uv_texture_location(), 2); |
2342 } else { | 2354 } else { |
2343 gl_->Uniform1i(program->u_texture_location(), 2); | 2355 gl_->Uniform1i(program->u_texture_location(), 2); |
2344 gl_->Uniform1i(program->v_texture_location(), 3); | 2356 gl_->Uniform1i(program->v_texture_location(), 3); |
2345 } | 2357 } |
2346 if (alpha_texture_mode == YUV_HAS_ALPHA_TEXTURE) | 2358 if (alpha_texture_mode == YUV_HAS_ALPHA_TEXTURE) |
2347 gl_->Uniform1i(program->a_texture_location(), 4); | 2359 gl_->Uniform1i(program->a_texture_location(), 4); |
2348 | 2360 |
2349 if (color_conversion_mode == COLOR_CONVERSION_MODE_LUT_FROM_YUV) { | 2361 if (color_conversion_mode == COLOR_CONVERSION_MODE_LUT) { |
2350 ColorLUTCache::LUT lut = color_lut_cache_.GetLUT(quad->video_color_space, | 2362 ColorLUTCache::LUT lut = color_lut_cache_.GetLUT(quad->video_color_space, |
2351 frame->device_color_space); | 2363 frame->device_color_space); |
2352 gl_->ActiveTexture(GL_TEXTURE5); | 2364 gl_->ActiveTexture(GL_TEXTURE5); |
2353 gl_->BindTexture(GL_TEXTURE_2D, lut.texture); | 2365 gl_->BindTexture(GL_TEXTURE_2D, lut.texture); |
2354 gl_->Uniform1i(program->lut_texture_location(), 5); | 2366 gl_->Uniform1i(program->lut_texture_location(), 5); |
2355 gl_->Uniform1f(program->lut_size_location(), lut.size); | 2367 gl_->Uniform1f(program->lut_size_location(), lut.size); |
2356 gl_->ActiveTexture(GL_TEXTURE0); | 2368 gl_->ActiveTexture(GL_TEXTURE0); |
2357 gl_->Uniform1f(program->resource_multiplier_location(), | |
2358 quad->resource_multiplier); | |
2359 gl_->Uniform1f(program->resource_offset_location(), quad->resource_offset); | |
2360 } else { | |
2361 float yuv_to_rgb_multiplied[9] = {0}; | |
2362 float yuv_adjust_with_offset[3] = {0}; | |
2363 ComputeYUVToRGBMatrices(quad->color_space, quad->bits_per_channel, | |
2364 quad->resource_multiplier, quad->resource_offset, | |
2365 yuv_to_rgb_multiplied, yuv_adjust_with_offset); | |
2366 gl_->UniformMatrix3fv(program->yuv_matrix_location(), 1, 0, | |
2367 yuv_to_rgb_multiplied); | |
2368 gl_->Uniform3fv(program->yuv_adj_location(), 1, yuv_adjust_with_offset); | |
2369 } | 2369 } |
| 2370 DCHECK_NE(program->yuv_and_resource_matrix_location(), -1); |
| 2371 float yuv_to_rgb_matrix[16] = {0}; |
| 2372 ComputeYUVToRGBMatrices(quad->color_space, quad->bits_per_channel, |
| 2373 quad->resource_multiplier, quad->resource_offset, |
| 2374 color_conversion_mode, yuv_to_rgb_matrix); |
| 2375 gl_->UniformMatrix4fv(program->yuv_and_resource_matrix_location(), 1, 0, |
| 2376 yuv_to_rgb_matrix); |
2370 | 2377 |
2371 // The transform and vertex data are used to figure out the extents that the | 2378 // The transform and vertex data are used to figure out the extents that the |
2372 // un-antialiased quad should have and which vertex this is and the float | 2379 // un-antialiased quad should have and which vertex this is and the float |
2373 // quad passed in via uniform is the actual geometry that gets used to draw | 2380 // quad passed in via uniform is the actual geometry that gets used to draw |
2374 // it. This is why this centered rect is used and not the original quad_rect. | 2381 // it. This is why this centered rect is used and not the original quad_rect. |
2375 auto tile_rect = gfx::RectF(quad->rect); | 2382 auto tile_rect = gfx::RectF(quad->rect); |
2376 | 2383 |
2377 SetShaderOpacity(quad->shared_quad_state->opacity, program->alpha_location()); | 2384 SetShaderOpacity(quad->shared_quad_state->opacity, program->alpha_location()); |
2378 if (!clip_region) { | 2385 if (!clip_region) { |
2379 DrawQuadGeometry(frame->projection_matrix, | 2386 DrawQuadGeometry(frame->projection_matrix, |
(...skipping 1284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3664 return; | 3671 return; |
3665 | 3672 |
3666 // Report GPU overdraw as a percentage of |max_result|. | 3673 // Report GPU overdraw as a percentage of |max_result|. |
3667 TRACE_COUNTER1( | 3674 TRACE_COUNTER1( |
3668 TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), "GPU Overdraw", | 3675 TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), "GPU Overdraw", |
3669 (std::accumulate(overdraw->begin(), overdraw->end(), 0) * 100) / | 3676 (std::accumulate(overdraw->begin(), overdraw->end(), 0) * 100) / |
3670 max_result); | 3677 max_result); |
3671 } | 3678 } |
3672 | 3679 |
3673 } // namespace cc | 3680 } // namespace cc |
OLD | NEW |