| 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 "cc/output/overlay_candidate.h" | 5 #include "cc/output/overlay_candidate.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "cc/base/math_util.h" | 10 #include "cc/base/math_util.h" |
| 11 #include "cc/quads/io_surface_draw_quad.h" |
| 12 #include "cc/quads/solid_color_draw_quad.h" |
| 13 #include "cc/quads/stream_video_draw_quad.h" |
| 14 #include "cc/quads/texture_draw_quad.h" |
| 11 #include "ui/gfx/geometry/rect_conversions.h" | 15 #include "ui/gfx/geometry/rect_conversions.h" |
| 12 #include "ui/gfx/geometry/vector3d_f.h" | 16 #include "ui/gfx/geometry/vector3d_f.h" |
| 13 | 17 |
| 14 namespace cc { | 18 namespace cc { |
| 15 | 19 |
| 16 namespace { | 20 namespace { |
| 17 // Tolerance for considering axis vector elements to be zero. | 21 // Tolerance for considering axis vector elements to be zero. |
| 18 const SkMScalar kEpsilon = std::numeric_limits<float>::epsilon(); | 22 const SkMScalar kEpsilon = std::numeric_limits<float>::epsilon(); |
| 19 | 23 |
| 20 enum Axis { NONE, AXIS_POS_X, AXIS_NEG_X, AXIS_POS_Y, AXIS_NEG_Y }; | 24 enum Axis { NONE, AXIS_POS_X, AXIS_NEG_X, AXIS_POS_Y, AXIS_NEG_Y }; |
| 21 | 25 |
| 22 Axis VectorToAxis(const gfx::Vector3dF& vec) { | 26 Axis VectorToAxis(const gfx::Vector3dF& vec) { |
| 23 if (std::abs(vec.z()) > kEpsilon) | 27 if (std::abs(vec.z()) > kEpsilon) |
| 24 return NONE; | 28 return NONE; |
| 25 const bool x_zero = (std::abs(vec.x()) <= kEpsilon); | 29 const bool x_zero = (std::abs(vec.x()) <= kEpsilon); |
| 26 const bool y_zero = (std::abs(vec.y()) <= kEpsilon); | 30 const bool y_zero = (std::abs(vec.y()) <= kEpsilon); |
| 27 if (x_zero && !y_zero) | 31 if (x_zero && !y_zero) |
| 28 return (vec.y() > 0) ? AXIS_POS_Y : AXIS_NEG_Y; | 32 return (vec.y() > 0) ? AXIS_POS_Y : AXIS_NEG_Y; |
| 29 else if (y_zero && !x_zero) | 33 else if (y_zero && !x_zero) |
| 30 return (vec.x() > 0) ? AXIS_POS_X : AXIS_NEG_X; | 34 return (vec.x() > 0) ? AXIS_POS_X : AXIS_NEG_X; |
| 31 else | 35 else |
| 32 return NONE; | 36 return NONE; |
| 33 } | 37 } |
| 34 | 38 |
| 35 } // namespace | 39 gfx::OverlayTransform GetOverlayTransform(const gfx::Transform& quad_transform, |
| 36 | 40 bool y_flipped) { |
| 37 OverlayCandidate::OverlayCandidate() | |
| 38 : transform(gfx::OVERLAY_TRANSFORM_NONE), | |
| 39 format(RGBA_8888), | |
| 40 uv_rect(0.f, 0.f, 1.f, 1.f), | |
| 41 is_clipped(false), | |
| 42 use_output_surface_for_resource(false), | |
| 43 resource_id(0), | |
| 44 plane_z_order(0), | |
| 45 overlay_handled(false) {} | |
| 46 | |
| 47 OverlayCandidate::~OverlayCandidate() {} | |
| 48 | |
| 49 // static | |
| 50 gfx::OverlayTransform OverlayCandidate::GetOverlayTransform( | |
| 51 const gfx::Transform& quad_transform, | |
| 52 bool y_flipped) { | |
| 53 if (!quad_transform.Preserves2dAxisAlignment()) { | 41 if (!quad_transform.Preserves2dAxisAlignment()) { |
| 54 return gfx::OVERLAY_TRANSFORM_INVALID; | 42 return gfx::OVERLAY_TRANSFORM_INVALID; |
| 55 } | 43 } |
| 56 | 44 |
| 57 gfx::Vector3dF x_axis = MathUtil::GetXAxis(quad_transform); | 45 gfx::Vector3dF x_axis = MathUtil::GetXAxis(quad_transform); |
| 58 gfx::Vector3dF y_axis = MathUtil::GetYAxis(quad_transform); | 46 gfx::Vector3dF y_axis = MathUtil::GetYAxis(quad_transform); |
| 59 if (y_flipped) { | 47 if (y_flipped) { |
| 60 y_axis.Scale(-1); | 48 y_axis.Scale(-1); |
| 61 } | 49 } |
| 62 | 50 |
| 63 Axis x_to = VectorToAxis(x_axis); | 51 Axis x_to = VectorToAxis(x_axis); |
| 64 Axis y_to = VectorToAxis(y_axis); | 52 Axis y_to = VectorToAxis(y_axis); |
| 65 | 53 |
| 66 if (x_to == AXIS_POS_X && y_to == AXIS_POS_Y) | 54 if (x_to == AXIS_POS_X && y_to == AXIS_POS_Y) |
| 67 return gfx::OVERLAY_TRANSFORM_NONE; | 55 return gfx::OVERLAY_TRANSFORM_NONE; |
| 68 else if (x_to == AXIS_NEG_X && y_to == AXIS_POS_Y) | 56 else if (x_to == AXIS_NEG_X && y_to == AXIS_POS_Y) |
| 69 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL; | 57 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL; |
| 70 else if (x_to == AXIS_POS_X && y_to == AXIS_NEG_Y) | 58 else if (x_to == AXIS_POS_X && y_to == AXIS_NEG_Y) |
| 71 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL; | 59 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL; |
| 72 else if (x_to == AXIS_NEG_Y && y_to == AXIS_POS_X) | 60 else if (x_to == AXIS_NEG_Y && y_to == AXIS_POS_X) |
| 73 return gfx::OVERLAY_TRANSFORM_ROTATE_270; | 61 return gfx::OVERLAY_TRANSFORM_ROTATE_270; |
| 74 else if (x_to == AXIS_NEG_X && y_to == AXIS_NEG_Y) | 62 else if (x_to == AXIS_NEG_X && y_to == AXIS_NEG_Y) |
| 75 return gfx::OVERLAY_TRANSFORM_ROTATE_180; | 63 return gfx::OVERLAY_TRANSFORM_ROTATE_180; |
| 76 else if (x_to == AXIS_POS_Y && y_to == AXIS_NEG_X) | 64 else if (x_to == AXIS_POS_Y && y_to == AXIS_NEG_X) |
| 77 return gfx::OVERLAY_TRANSFORM_ROTATE_90; | 65 return gfx::OVERLAY_TRANSFORM_ROTATE_90; |
| 78 else | 66 else |
| 79 return gfx::OVERLAY_TRANSFORM_INVALID; | 67 return gfx::OVERLAY_TRANSFORM_INVALID; |
| 80 } | 68 } |
| 81 | 69 |
| 82 // static | 70 // Apply transform |delta| to |in| and return the resulting transform, |
| 83 gfx::OverlayTransform OverlayCandidate::ModifyTransform( | 71 // or OVERLAY_TRANSFORM_INVALID. |
| 84 gfx::OverlayTransform in, | 72 gfx::OverlayTransform ComposeTransforms(gfx::OverlayTransform delta, |
| 85 gfx::OverlayTransform delta) { | 73 gfx::OverlayTransform in) { |
| 86 // There are 8 different possible transforms. We can characterize these | 74 // There are 8 different possible transforms. We can characterize these |
| 87 // by looking at where the origin moves and the direction the horizontal goes. | 75 // by looking at where the origin moves and the direction the horizontal goes. |
| 88 // (TL=top-left, BR=bottom-right, H=horizontal, V=vertical). | 76 // (TL=top-left, BR=bottom-right, H=horizontal, V=vertical). |
| 89 // NONE: TL, H | 77 // NONE: TL, H |
| 90 // FLIP_VERTICAL: BL, H | 78 // FLIP_VERTICAL: BL, H |
| 91 // FLIP_HORIZONTAL: TR, H | 79 // FLIP_HORIZONTAL: TR, H |
| 92 // ROTATE_90: TR, V | 80 // ROTATE_90: TR, V |
| 93 // ROTATE_180: BR, H | 81 // ROTATE_180: BR, H |
| 94 // ROTATE_270: BL, V | 82 // ROTATE_270: BL, V |
| 95 // Missing transforms: TL, V & BR, V | 83 // Missing transforms: TL, V & BR, V |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 return gfx::OVERLAY_TRANSFORM_ROTATE_180; | 156 return gfx::OVERLAY_TRANSFORM_ROTATE_180; |
| 169 default: | 157 default: |
| 170 return gfx::OVERLAY_TRANSFORM_INVALID; | 158 return gfx::OVERLAY_TRANSFORM_INVALID; |
| 171 } | 159 } |
| 172 break; | 160 break; |
| 173 default: | 161 default: |
| 174 return gfx::OVERLAY_TRANSFORM_INVALID; | 162 return gfx::OVERLAY_TRANSFORM_INVALID; |
| 175 } | 163 } |
| 176 } | 164 } |
| 177 | 165 |
| 166 } // namespace |
| 167 |
| 168 OverlayCandidate::OverlayCandidate() |
| 169 : transform(gfx::OVERLAY_TRANSFORM_NONE), |
| 170 format(RGBA_8888), |
| 171 uv_rect(0.f, 0.f, 1.f, 1.f), |
| 172 is_clipped(false), |
| 173 use_output_surface_for_resource(false), |
| 174 resource_id(0), |
| 175 plane_z_order(0), |
| 176 overlay_handled(false) {} |
| 177 |
| 178 OverlayCandidate::~OverlayCandidate() {} |
| 179 |
| 178 // static | 180 // static |
| 179 gfx::RectF OverlayCandidate::GetOverlayRect( | 181 bool OverlayCandidate::FromDrawQuad(const DrawQuad* quad, |
| 180 const gfx::Transform& quad_transform, | 182 OverlayCandidate* candidate) { |
| 181 const gfx::Rect& rect) { | 183 if (quad->needs_blending || quad->shared_quad_state->opacity != 1.f || |
| 182 DCHECK(quad_transform.Preserves2dAxisAlignment()); | 184 quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode) |
| 185 return false; |
| 183 | 186 |
| 184 gfx::RectF float_rect(rect); | 187 auto& transform = quad->shared_quad_state->quad_to_target_transform; |
| 185 quad_transform.TransformRect(&float_rect); | 188 candidate->display_rect = gfx::RectF(quad->rect); |
| 186 return float_rect; | 189 transform.TransformRect(&candidate->display_rect); |
| 190 candidate->quad_rect_in_target_space = |
| 191 MathUtil::MapEnclosingClippedRect(transform, quad->rect); |
| 192 |
| 193 candidate->format = RGBA_8888; |
| 194 candidate->clip_rect = quad->shared_quad_state->clip_rect; |
| 195 candidate->is_clipped = quad->shared_quad_state->is_clipped; |
| 196 |
| 197 switch (quad->material) { |
| 198 case DrawQuad::TEXTURE_CONTENT: |
| 199 return FromTextureQuad(TextureDrawQuad::MaterialCast(quad), candidate); |
| 200 case DrawQuad::STREAM_VIDEO_CONTENT: |
| 201 return FromStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad), |
| 202 candidate); |
| 203 case DrawQuad::IO_SURFACE_CONTENT: |
| 204 return FromIOSurfaceQuad(IOSurfaceDrawQuad::MaterialCast(quad), |
| 205 candidate); |
| 206 default: |
| 207 break; |
| 208 } |
| 209 |
| 210 return false; |
| 211 } |
| 212 |
| 213 // static |
| 214 bool OverlayCandidate::FromTextureQuad(const TextureDrawQuad* quad, |
| 215 OverlayCandidate* candidate) { |
| 216 if (!quad->allow_overlay()) |
| 217 return false; |
| 218 gfx::OverlayTransform overlay_transform = GetOverlayTransform( |
| 219 quad->shared_quad_state->quad_to_target_transform, quad->y_flipped); |
| 220 if (quad->background_color != SK_ColorTRANSPARENT || |
| 221 quad->premultiplied_alpha || |
| 222 overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) |
| 223 return false; |
| 224 candidate->resource_id = quad->resource_id(); |
| 225 candidate->resource_size_in_pixels = quad->resource_size_in_pixels(); |
| 226 candidate->transform = overlay_transform; |
| 227 candidate->uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right); |
| 228 return true; |
| 229 } |
| 230 |
| 231 // static |
| 232 bool OverlayCandidate::FromStreamVideoQuad(const StreamVideoDrawQuad* quad, |
| 233 OverlayCandidate* candidate) { |
| 234 if (!quad->allow_overlay()) |
| 235 return false; |
| 236 gfx::OverlayTransform overlay_transform = GetOverlayTransform( |
| 237 quad->shared_quad_state->quad_to_target_transform, false); |
| 238 if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) |
| 239 return false; |
| 240 if (!quad->matrix.IsScaleOrTranslation()) { |
| 241 // We cannot handle anything other than scaling & translation for texture |
| 242 // coordinates yet. |
| 243 return false; |
| 244 } |
| 245 candidate->resource_id = quad->resource_id(); |
| 246 candidate->resource_size_in_pixels = quad->resource_size_in_pixels(); |
| 247 candidate->transform = overlay_transform; |
| 248 |
| 249 gfx::Point3F uv0 = gfx::Point3F(0, 0, 0); |
| 250 gfx::Point3F uv1 = gfx::Point3F(1, 1, 0); |
| 251 quad->matrix.TransformPoint(&uv0); |
| 252 quad->matrix.TransformPoint(&uv1); |
| 253 gfx::Vector3dF delta = uv1 - uv0; |
| 254 if (delta.x() < 0) { |
| 255 candidate->transform = ComposeTransforms( |
| 256 gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL, candidate->transform); |
| 257 float x0 = uv0.x(); |
| 258 uv0.set_x(uv1.x()); |
| 259 uv1.set_x(x0); |
| 260 delta.set_x(-delta.x()); |
| 261 } |
| 262 |
| 263 if (delta.y() < 0) { |
| 264 // In this situation, uv0y < uv1y. Since we overlay inverted, a request |
| 265 // to invert the source texture means we can just output the texture |
| 266 // normally and it will be correct. |
| 267 candidate->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y()); |
| 268 } else { |
| 269 candidate->transform = ComposeTransforms( |
| 270 gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL, candidate->transform); |
| 271 candidate->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y()); |
| 272 } |
| 273 return true; |
| 274 } |
| 275 |
| 276 // static |
| 277 bool OverlayCandidate::FromIOSurfaceQuad(const IOSurfaceDrawQuad* quad, |
| 278 OverlayCandidate* candidate) { |
| 279 if (!quad->allow_overlay) |
| 280 return false; |
| 281 gfx::OverlayTransform overlay_transform = GetOverlayTransform( |
| 282 quad->shared_quad_state->quad_to_target_transform, false); |
| 283 if (overlay_transform != gfx::OVERLAY_TRANSFORM_NONE) |
| 284 return false; |
| 285 candidate->resource_id = quad->io_surface_resource_id(); |
| 286 candidate->resource_size_in_pixels = quad->io_surface_size; |
| 287 candidate->transform = overlay_transform; |
| 288 candidate->uv_rect = gfx::RectF(1.f, 1.f); |
| 289 return true; |
| 187 } | 290 } |
| 188 | 291 |
| 189 } // namespace cc | 292 } // namespace cc |
| OLD | NEW |