OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "cc/output/dc_layer_overlay.h" |
| 6 |
| 7 #include "cc/base/math_util.h" |
| 8 #include "cc/quads/solid_color_draw_quad.h" |
| 9 #include "cc/quads/yuv_video_draw_quad.h" |
| 10 #include "cc/resources/resource_provider.h" |
| 11 #include "gpu/GLES2/gl2extchromium.h" |
| 12 #include "ui/gfx/geometry/rect_conversions.h" |
| 13 |
| 14 namespace cc { |
| 15 |
| 16 namespace { |
| 17 |
| 18 DCLayerOverlayProcessor::DCLayerResult FromYUVQuad( |
| 19 ResourceProvider* resource_provider, |
| 20 const YUVVideoDrawQuad* quad, |
| 21 DCLayerOverlay* ca_layer_overlay) { |
| 22 unsigned resource_id = quad->y_plane_resource_id(); |
| 23 if (!resource_provider->IsOverlayCandidate(resource_id)) |
| 24 return DCLayerOverlayProcessor::DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE; |
| 25 ca_layer_overlay->contents_resource_id = resource_id; |
| 26 ca_layer_overlay->contents_rect = quad->ya_tex_coord_rect; |
| 27 ca_layer_overlay->filter = GL_LINEAR; |
| 28 return DCLayerOverlayProcessor::DC_LAYER_SUCCESS; |
| 29 } |
| 30 |
| 31 // Find a rectangle containing all the quads in a list that occlude the area |
| 32 // in target_quad. |
| 33 gfx::RectF GetOcclusionBounds(const gfx::RectF& target_quad, |
| 34 QuadList::ConstIterator quad_list_begin, |
| 35 QuadList::ConstIterator quad_list_end) { |
| 36 gfx::RectF occlusion_bounding_box; |
| 37 for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end; |
| 38 ++overlap_iter) { |
| 39 gfx::RectF overlap_rect = MathUtil::MapClippedRect( |
| 40 overlap_iter->shared_quad_state->quad_to_target_transform, |
| 41 gfx::RectF(overlap_iter->rect)); |
| 42 float opacity = overlap_iter->shared_quad_state->opacity; |
| 43 if (opacity < std::numeric_limits<float>::epsilon()) |
| 44 continue; |
| 45 const DrawQuad* quad = *overlap_iter; |
| 46 if (quad->material == DrawQuad::SOLID_COLOR) { |
| 47 SkColor color = SolidColorDrawQuad::MaterialCast(quad)->color; |
| 48 float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; |
| 49 if (quad->ShouldDrawWithBlending() && |
| 50 alpha < std::numeric_limits<float>::epsilon()) |
| 51 continue; |
| 52 } |
| 53 overlap_rect.Intersect(target_quad); |
| 54 if (!overlap_rect.IsEmpty()) { |
| 55 occlusion_bounding_box.Union(overlap_rect); |
| 56 } |
| 57 } |
| 58 return occlusion_bounding_box; |
| 59 } |
| 60 |
| 61 } // namespace |
| 62 |
| 63 DCLayerOverlay::DCLayerOverlay() : filter(GL_LINEAR) {} |
| 64 |
| 65 DCLayerOverlay::DCLayerOverlay(const DCLayerOverlay& other) = default; |
| 66 |
| 67 DCLayerOverlay::~DCLayerOverlay() {} |
| 68 |
| 69 DCLayerOverlayProcessor::DCLayerResult DCLayerOverlayProcessor::FromDrawQuad( |
| 70 ResourceProvider* resource_provider, |
| 71 const gfx::RectF& display_rect, |
| 72 QuadList::ConstIterator quad_list_begin, |
| 73 QuadList::ConstIterator quad, |
| 74 DCLayerOverlay* ca_layer_overlay) { |
| 75 if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver) |
| 76 return DC_LAYER_FAILED_QUAD_BLEND_MODE; |
| 77 |
| 78 DCLayerResult result = DC_LAYER_FAILED_UNKNOWN; |
| 79 switch (quad->material) { |
| 80 case DrawQuad::YUV_VIDEO_CONTENT: |
| 81 result = |
| 82 FromYUVQuad(resource_provider, YUVVideoDrawQuad::MaterialCast(*quad), |
| 83 ca_layer_overlay); |
| 84 break; |
| 85 default: |
| 86 return DC_LAYER_FAILED_UNKNOWN; |
| 87 } |
| 88 if (result != DC_LAYER_SUCCESS) |
| 89 return result; |
| 90 |
| 91 scoped_refptr<DCLayerOverlaySharedState> overlay_shared_state( |
| 92 new DCLayerOverlaySharedState); |
| 93 overlay_shared_state->z_order = 1; |
| 94 |
| 95 overlay_shared_state->is_clipped = quad->shared_quad_state->is_clipped; |
| 96 overlay_shared_state->clip_rect = |
| 97 gfx::RectF(quad->shared_quad_state->clip_rect); |
| 98 |
| 99 overlay_shared_state->opacity = quad->shared_quad_state->opacity; |
| 100 overlay_shared_state->transform = |
| 101 quad->shared_quad_state->quad_to_target_transform.matrix(); |
| 102 |
| 103 ca_layer_overlay->shared_state = overlay_shared_state; |
| 104 ca_layer_overlay->bounds_rect = gfx::RectF(quad->rect); |
| 105 |
| 106 return result; |
| 107 } |
| 108 |
| 109 void DCLayerOverlayProcessor::Process(ResourceProvider* resource_provider, |
| 110 const gfx::RectF& display_rect, |
| 111 QuadList* quad_list, |
| 112 gfx::Rect* overlay_damage_rect, |
| 113 gfx::Rect* damage_rect, |
| 114 DCLayerOverlayList* ca_layer_overlays) { |
| 115 gfx::Rect this_frame_underlay_rect; |
| 116 for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { |
| 117 DCLayerOverlay ca_layer; |
| 118 DCLayerResult result = FromDrawQuad(resource_provider, display_rect, |
| 119 quad_list->begin(), it, &ca_layer); |
| 120 if (result != DC_LAYER_SUCCESS) |
| 121 continue; |
| 122 gfx::Rect quad_rectangle = MathUtil::MapEnclosingClippedRect( |
| 123 it->shared_quad_state->quad_to_target_transform, it->rect); |
| 124 gfx::RectF occlusion_bounding_box = |
| 125 GetOcclusionBounds(gfx::RectF(quad_rectangle), quad_list->begin(), it); |
| 126 |
| 127 if (occlusion_bounding_box.IsEmpty()) { |
| 128 // The quad is on top, so promote it to an overlay and remove all damage |
| 129 // underneath it. |
| 130 if (it->shared_quad_state->quad_to_target_transform |
| 131 .Preserves2dAxisAlignment()) { |
| 132 damage_rect->Subtract(quad_rectangle); |
| 133 overlay_damage_rect->Union(quad_rectangle); |
| 134 } |
| 135 quad_list->EraseAndInvalidateAllPointers(it); |
| 136 } else { |
| 137 // The quad is occluded, so replace it with a black solid color quad and |
| 138 // place the overlay itself under the quad. |
| 139 if (it->shared_quad_state->quad_to_target_transform |
| 140 .IsIdentityOrIntegerTranslation()) { |
| 141 this_frame_underlay_rect = quad_rectangle; |
| 142 } |
| 143 ca_layer.shared_state->z_order = -1; |
| 144 const SharedQuadState* shared_quad_state = it->shared_quad_state; |
| 145 gfx::Rect rect = it->visible_rect; |
| 146 SolidColorDrawQuad* replacement = |
| 147 quad_list->ReplaceExistingElement<SolidColorDrawQuad>(it); |
| 148 replacement->SetAll(shared_quad_state, rect, rect, rect, false, |
| 149 SK_ColorTRANSPARENT, true); |
| 150 |
| 151 if (this_frame_underlay_rect == previous_frame_underlay_rect_) { |
| 152 // If this underlay rect is the same as for last frame, subtract its |
| 153 // area from the damage of the main surface, as the cleared area was |
| 154 // already cleared last frame. Add back the damage from the occluded |
| 155 // area for this and last frame, as that may have changed. |
| 156 if (it->shared_quad_state->quad_to_target_transform |
| 157 .Preserves2dAxisAlignment()) { |
| 158 gfx::Rect occluding_damage_rect = *damage_rect; |
| 159 occluding_damage_rect.Intersect(quad_rectangle); |
| 160 damage_rect->Subtract(quad_rectangle); |
| 161 gfx::Rect new_occlusion_bounding_box = |
| 162 gfx::ToEnclosingRect(occlusion_bounding_box); |
| 163 new_occlusion_bounding_box.Union(previous_occlusion_bounding_box_); |
| 164 occluding_damage_rect.Intersect(new_occlusion_bounding_box); |
| 165 |
| 166 damage_rect->Union(occluding_damage_rect); |
| 167 overlay_damage_rect->Union(quad_rectangle); |
| 168 } |
| 169 } else { |
| 170 // Entire replacement quad must be redrawn. |
| 171 damage_rect->Union(quad_rectangle); |
| 172 } |
| 173 previous_occlusion_bounding_box_ = |
| 174 gfx::ToEnclosingRect(occlusion_bounding_box); |
| 175 } |
| 176 |
| 177 ca_layer_overlays->push_back(ca_layer); |
| 178 // Only allow one overlay for now. |
| 179 break; |
| 180 } |
| 181 previous_frame_underlay_rect_ = this_frame_underlay_rect; |
| 182 } |
| 183 |
| 184 } // namespace cc |
OLD | NEW |