[M120 Migration] Apply opacity/filter/border-radius for video hole. 18/306418/3
authorSun-woo Nam <sunny.nam@samsung.com>
Sun, 23 Apr 2023 09:12:41 +0000 (17:12 +0800)
committerBot Blink <blinkbot@samsung.com>
Thu, 22 Feb 2024 13:40:56 +0000 (13:40 +0000)
1. Pass video hole flag to DirectRenderer
2. Disable blend for border-radius case
3. Disable blend and use Black Quad with opacity to simulate
opacity effect.
4. Update render target id for filter effect node
If parent node set filter:brightness, chromium will
create a kFilter effect node. This effect node will create a
contribute render surface which will cover on video. So we need to
update it's render target, let it to render on the same surface with
video hole rectangle.
5. Implement opacity css
Update video layer's target render surface to it's parent target
In some special case, like disney+, Hoichoi.tv opacity animation
will cause opacity abnormal. opacity is 1.0f, but create render surface.

Reference:
https://review.tizen.org/gerrit/#/c/291821/
https://review.tizen.org/gerrit/#/c/292417/
https://review.tizen.org/gerrit/#/c/297840/
https://review.tizen.org/gerrit/#/c/302794/

Change-Id: I6b07af528bb5e912fabec2a7c8a831adb96fbec9
Signed-off-by: Sun-woo Nam <sunny.nam@samsung.com>
20 files changed:
cc/layers/layer_impl.h
cc/layers/video_layer_impl.cc
cc/layers/video_layer_impl.h
cc/trees/draw_property_utils.cc
cc/trees/effect_node.h
components/viz/common/quads/aggregated_render_pass.cc
components/viz/common/quads/aggregated_render_pass.h
components/viz/common/quads/compositor_render_pass.cc
components/viz/common/quads/compositor_render_pass.h
components/viz/common/quads/render_pass_internal.h
components/viz/common/transition_utils.cc
components/viz/service/display/direct_renderer.cc
components/viz/service/display/direct_renderer.h
components/viz/service/display/skia_renderer.cc
components/viz/service/display/surface_aggregator.cc
components/viz/service/display/surface_aggregator.h
services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc
services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h
services/viz/public/mojom/BUILD.gn
services/viz/public/mojom/compositing/compositor_render_pass.mojom

index a196bc7..9660e89 100644 (file)
@@ -98,7 +98,11 @@ class CC_EXPORT LayerImpl {
 
   void SetEffectTreeIndex(int index);
   int effect_tree_index() const { return effect_tree_index_; }
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual int render_target_effect_tree_index() const;
+#else
   int render_target_effect_tree_index() const;
+#endif
 
   void SetScrollTreeIndex(int index);
   int scroll_tree_index() const { return scroll_tree_index_; }
index 51f4784..b51b823 100644 (file)
@@ -242,6 +242,13 @@ void VideoLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
   if (is_clipped()) {
     clip_rect_opt = clip_rect();
   }
+
+#if defined(TIZEN_VIDEO_HOLE)
+  if (frame_->storage_type() == media::VideoFrame::STORAGE_HOLE) {
+    render_pass->has_video_hole = true;
+  }
+#endif
+
   updater_->AppendQuads(render_pass, frame_, transform, quad_rect,
                         visible_quad_rect, draw_properties().mask_filter_info,
                         clip_rect_opt, contents_opaque(), draw_opacity(),
@@ -251,6 +258,15 @@ void VideoLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
   const gfx::Rect video_rect =
       cc::MathUtil::MapEnclosingClippedRect(transform, gfx::Rect(rotated_size));
   if (previous_visible_rect_ != video_rect) {
+    LOG(INFO) << " VideoLayerImpl::AppendQuads, id: " << id()
+              << ", rect changed from: " << previous_visible_rect_.ToString()
+              << ", to: " << video_rect.ToString() << ", RenderPassId"
+              << render_pass->id << ", bounds: " << bounds().ToString()
+              << ", visible_drawable_content_rect: "
+              << visible_drawable_content_rect().ToString()
+              << ", draw_opacity: " << draw_opacity() << ", media rotation: "
+              << media::VideoRotationToString(media_transform.rotation)
+              << ", transform: " << transform.ToString();
 #if defined(USE_TTRACE)
     TTRACE(TTRACE_TAG_WEB,
            "VideoResourceUpdater::AppendQuads -> rect change start!");
@@ -319,6 +335,21 @@ gfx::ContentColorUsage VideoLayerImpl::GetContentColorUsage() const {
   return frame_color_space.GetContentColorUsage();
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+int VideoLayerImpl::render_target_effect_tree_index() const {
+  EffectNode* effect_node = GetEffectTree().Node(effect_tree_index());
+
+  // If we only set opacity style on a video element, we need to return
+  // it's target id here, or video hole rect will be drawn onto RPDQ.
+  if (may_contain_video() &&
+      (effect_node->render_surface_reason == RenderSurfaceReason::kOpacity ||
+       effect_node->render_surface_reason == RenderSurfaceReason::kFilter)) {
+    return effect_node->target_id;
+  }
+  return LayerImpl::render_target_effect_tree_index();
+}
+#endif
+
 void VideoLayerImpl::SetNeedsRedraw() {
   UnionUpdateRect(gfx::Rect(bounds()));
   layer_tree_impl()->SetNeedsRedraw();
index 9b1fa01..de261d5 100644 (file)
@@ -55,6 +55,9 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
   void DidBecomeActive() override;
   void ReleaseResources() override;
   gfx::ContentColorUsage GetContentColorUsage() const override;
+#if defined(TIZEN_VIDEO_HOLE)
+  int render_target_effect_tree_index() const override;
+#endif
 
   void SetNeedsRedraw();
 
index 06a9aa9..2e442ac 100644 (file)
@@ -754,8 +754,17 @@ gfx::Rect LayerVisibleRect(PropertyTrees* property_trees, LayerImpl* layer) {
 ConditionalClip LayerClipRect(PropertyTrees* property_trees, LayerImpl* layer) {
   const EffectTree* effect_tree = &property_trees->effect_tree();
   const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index());
+#if defined(TIZEN_VIDEO_HOLE)
+  bool is_opacity_video =
+      layer->may_contain_video() &&
+      (effect_node->render_surface_reason == RenderSurfaceReason::kOpacity ||
+       effect_node->render_surface_reason == RenderSurfaceReason::kFilter);
+#endif
   const EffectNode* target_node =
       effect_node->HasRenderSurface()
+#if defined(TIZEN_VIDEO_HOLE)
+              && !is_opacity_video
+#endif
           ? effect_node
           : effect_tree->Node(effect_node->target_id);
   bool include_expanding_clips = false;
@@ -836,7 +845,14 @@ void UpdateRenderTarget(EffectTree* effect_tree) {
     if (i == kContentsRootPropertyNodeId) {
       // Render target of the node corresponding to root is itself.
       node->target_id = kContentsRootPropertyNodeId;
-    } else if (effect_tree->parent(node)->HasRenderSurface()) {
+    } else if (effect_tree->parent(node)->HasRenderSurface()
+#if defined(TIZEN_VIDEO_HOLE)
+               && effect_tree->parent(node)->render_surface_reason !=
+                      RenderSurfaceReason::kOpacity &&
+               effect_tree->parent(node)->render_surface_reason !=
+                   RenderSurfaceReason::kFilter)
+#endif
+    {
       node->target_id = node->parent_id;
     } else {
       node->target_id = effect_tree->parent(node)->target_id;
index 45cbaac..76bac35 100644 (file)
@@ -175,7 +175,16 @@ struct CC_EXPORT EffectNode {
   viz::ViewTransitionElementResourceId view_transition_element_resource_id;
 
   bool HasRenderSurface() const {
-    return render_surface_reason != RenderSurfaceReason::kNone;
+    return render_surface_reason != RenderSurfaceReason::kNone
+#if defined(TIZEN_VIDEO_HOLE)
+           && render_surface_reason != RenderSurfaceReason::kRoundedCorner &&
+           !(render_surface_reason == RenderSurfaceReason::kFilter &&
+             filters.HasFilterOfType(FilterOperation::BRIGHTNESS)) &&
+           !(render_surface_reason == RenderSurfaceReason::kBackdropFilter &&
+             (backdrop_filters.HasFilterOfType(FilterOperation::BLUR) ||
+              backdrop_filters.HasFilterOfType(FilterOperation::OPACITY)))
+#endif
+        ;
   }
 
 #if DCHECK_IS_ON()
index b394881..9cb33cf 100644 (file)
@@ -64,6 +64,9 @@ void AggregatedRenderPass::SetAll(
     const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
     gfx::ContentColorUsage color_usage,
     bool has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool has_video_hole,
+#endif
     bool cache_render_pass,
     bool has_damage_from_contributing_content,
     bool generate_mipmap) {
@@ -78,6 +81,9 @@ void AggregatedRenderPass::SetAll(
   this->backdrop_filter_bounds = backdrop_filter_bounds;
   content_color_usage = color_usage;
   this->has_transparent_background = has_transparent_background;
+#if defined(TIZEN_VIDEO_HOLE)
+  this->has_video_hole = has_video_hole;
+#endif
   this->cache_render_pass = cache_render_pass;
   this->has_damage_from_contributing_content =
       has_damage_from_contributing_content;
@@ -164,6 +170,9 @@ std::unique_ptr<AggregatedRenderPass> AggregatedRenderPass::Copy(
   copy_pass->SetAll(new_id, output_rect, damage_rect, transform_to_root_target,
                     filters, backdrop_filters, backdrop_filter_bounds,
                     content_color_usage, has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                    has_video_hole,
+#endif
                     cache_render_pass, has_damage_from_contributing_content,
                     generate_mipmap);
   return copy_pass;
@@ -179,6 +188,9 @@ std::unique_ptr<AggregatedRenderPass> AggregatedRenderPass::DeepCopy() const {
   copy_pass->SetAll(id, output_rect, damage_rect, transform_to_root_target,
                     filters, backdrop_filters, backdrop_filter_bounds,
                     content_color_usage, has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                    has_video_hole,
+#endif
                     cache_render_pass, has_damage_from_contributing_content,
                     generate_mipmap);
 
index 5503b94..4f6497a 100644 (file)
@@ -62,6 +62,9 @@ class VIZ_COMMON_EXPORT AggregatedRenderPass : public RenderPassInternal {
               const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
               gfx::ContentColorUsage color_usage,
               bool has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+              bool has_video_hole,
+#endif
               bool cache_render_pass,
               bool has_damage_from_contributing_content,
               bool generate_mipmap);
index 2c97801..886f108 100644 (file)
@@ -92,6 +92,9 @@ void CompositorRenderPass::SetAll(
     gfx::Size subtree_capture_size,
     ViewTransitionElementResourceId resource_id,
     bool has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool has_video_hole,
+#endif
     bool cache_render_pass,
     bool has_damage_from_contributing_content,
     bool generate_mipmap,
@@ -109,6 +112,9 @@ void CompositorRenderPass::SetAll(
   this->subtree_size = subtree_capture_size;
   this->view_transition_element_resource_id = resource_id;
   this->has_transparent_background = has_transparent_background;
+#if defined(TIZEN_VIDEO_HOLE)
+  this->has_video_hole = has_video_hole;
+#endif
   this->cache_render_pass = cache_render_pass;
   this->has_damage_from_contributing_content =
       has_damage_from_contributing_content;
@@ -196,9 +202,12 @@ std::unique_ptr<CompositorRenderPass> CompositorRenderPass::DeepCopy() const {
                     filters, backdrop_filters, backdrop_filter_bounds,
                     subtree_capture_id, subtree_size,
                     view_transition_element_resource_id,
-                    has_transparent_background, cache_render_pass,
-                    has_damage_from_contributing_content, generate_mipmap,
-                    has_per_quad_damage);
+                    has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                    has_video_hole,
+#endif
+                    cache_render_pass, has_damage_from_contributing_content,
+                    generate_mipmap, has_per_quad_damage);
 
   if (shared_quad_state_list.empty()) {
     DCHECK(quad_list.empty());
index 97c2fb5..2c37d8e 100644 (file)
@@ -77,6 +77,9 @@ class VIZ_COMMON_EXPORT CompositorRenderPass : public RenderPassInternal {
               gfx::Size subtree_capture_size,
               ViewTransitionElementResourceId resource_id,
               bool has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+              bool has_video_hole,
+#endif
               bool cache_render_pass,
               bool has_damage_from_contributing_content,
               bool generate_mipmap,
index cc2bacd..b533888 100644 (file)
@@ -62,6 +62,11 @@ class VIZ_COMMON_EXPORT RenderPassInternal {
   // If false, the pixels in the render pass' texture are all opaque.
   bool has_transparent_background = true;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  // If true, disable blend when draw render pass quad
+  bool has_video_hole = false;
+#endif
+
   // If true we might reuse the texture if there is no damage.
   bool cache_render_pass = false;
 
index 3d46bf8..a87dd98 100644 (file)
@@ -229,7 +229,11 @@ TransitionUtils::CopyPassWithQuadFiltering(
       source_pass.backdrop_filters, source_pass.backdrop_filter_bounds,
       source_pass.subtree_capture_id, source_pass.subtree_size,
       source_pass.view_transition_element_resource_id,
-      source_pass.has_transparent_background, source_pass.cache_render_pass,
+      source_pass.has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+      source_pass.has_video_hole,
+#endif
+      source_pass.cache_render_pass,
       source_pass.has_damage_from_contributing_content,
       source_pass.generate_mipmap, source_pass.has_per_quad_damage);
 
index a52c7f2..003bbad 100644 (file)
@@ -366,6 +366,12 @@ void DirectRenderer::DrawFrame(
 
   // Draw all non-root render passes except for the root render pass.
   for (const auto& pass : *render_passes_in_draw_order) {
+#if defined(TIZEN_VIDEO_HOLE)
+    if (pass->has_video_hole)
+      current_frame()->has_video_hole = true;
+    else
+      current_frame()->has_video_hole = false;
+#endif
     if (pass.get() == root_render_pass)
       break;
     DrawRenderPassAndExecuteCopyRequests(pass.get());
index aea178a..c242001 100644 (file)
@@ -144,6 +144,11 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
     gfx::AxisTransform2d target_to_device_transform;
 
     OverlayProcessorInterface::CandidateList overlay_list;
+
+#if defined(TIZEN_VIDEO_HOLE)
+    bool has_video_hole = false;
+#endif
+
     // When we have a buffer queue, the output surface could be treated as an
     // overlay plane, and the struct to store that information is in
     // |output_surface_plane|.
index 3aabb29..c54bfa3 100644 (file)
 #include "components/viz/service/display/overlay_processor_surface_control.h"
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "base/numerics/math_constants.h"
+#endif
+
 namespace viz {
 
 namespace {
@@ -2284,15 +2288,38 @@ void SkiaRenderer::DrawColoredQuad(SkColor4f color,
   // account for the layer applying those effects. We need to truncate to an
   // integral value of [0, 255] to match the explicit floor workaround in
   // blink::ConversionContext::StartEffect.
+#if defined(TIZEN_VIDEO_HOLE)
+  SkColor4f dst_color = color;
+  SkBlendMode blend_mode = params->blend_mode;
+  bool is_video_hole =
+      color == SkColors::kTransparent && (current_frame()->has_video_hole);
+
+  // kSrc blend mode means disable blend
+  if (is_video_hole) {
+    blend_mode = SkBlendMode::kSrc;
+    if (std::fabs(1.f - params->opacity) >
+        std::numeric_limits<float>::epsilon()) {
+      dst_color = SkColors::kBlack;
+    }
+  }
+
+  dst_color.fA = floor(params->opacity * dst_color.fA * 255.f) / 255.f;
+#else
   color.fA = floor(params->opacity * color.fA * 255.f) / 255.f;
+#endif
 
   const SkPoint* draw_region =
       params->draw_region ? params->draw_region->points : nullptr;
 
   current_canvas_->experimental_DrawEdgeAAQuad(
       gfx::RectFToSkRect(params->visible_rect), draw_region,
-      static_cast<SkCanvas::QuadAAFlags>(params->aa_flags), color,
-      params->blend_mode);
+      static_cast<SkCanvas::QuadAAFlags>(params->aa_flags),
+#if defined(TIZEN_VIDEO_HOLE)
+      dst_color, blend_mode
+#else
+      color, params->blend_mode
+#endif
+  );
 }
 
 void SkiaRenderer::DrawSingleImage(const SkImage* image,
index e7bd483..61c78e4 100644 (file)
@@ -1003,6 +1003,9 @@ void SurfaceAggregator::EmitSurfaceContent(
         source.transform_to_root_target, source.filters,
         source.backdrop_filters, source.backdrop_filter_bounds,
         root_content_color_usage_, source.has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+        source.has_video_hole,
+#endif
         source.cache_render_pass, resolved_pass.aggregation().has_damage,
         source.generate_mipmap);
 
@@ -1244,6 +1247,9 @@ void SurfaceAggregator::AddColorConversionPass() {
   AddRenderPassHelper(color_conversion_render_pass_id_, output_rect,
                       root_render_pass->damage_rect, root_content_color_usage_,
                       root_render_pass->has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                      root_render_pass->has_video_hole,
+#endif
                       /*pass_is_color_conversion_pass=*/true,
                       /*quad_state_to_target_transform=*/gfx::Transform(),
                       /*quad_state_contents_opaque=*/false, SkBlendMode::kSrc,
@@ -1302,6 +1308,9 @@ void SurfaceAggregator::AddRootReadbackPass() {
   AddRenderPassHelper(readback_render_pass_id_, output_rect,
                       root_render_pass->damage_rect, root_content_color_usage_,
                       has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                      root_render_pass->has_video_hole,
+#endif
                       /*pass_is_color_conversion_pass=*/false,
                       /*quad_state_to_target_transform=*/gfx::Transform(),
                       /*quad_state_contents_opaque=*/false,
@@ -1336,6 +1345,9 @@ void SurfaceAggregator::AddDisplayTransformPass() {
           root_surface_transform_, root_render_pass->damage_rect),
       root_render_pass->content_color_usage,
       root_render_pass->has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+      root_render_pass->has_video_hole,
+#endif
       /*pass_is_color_conversion_pass=*/false, root_surface_transform_,
       are_contents_opaque, SkBlendMode::kSrcOver, root_render_pass->id);
 }
@@ -1346,6 +1358,9 @@ void SurfaceAggregator::AddRenderPassHelper(
     const gfx::Rect& render_pass_damage_rect,
     gfx::ContentColorUsage pass_color_usage,
     bool pass_has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool pass_is_video_hole,
+#endif
     bool pass_is_color_conversion_pass,
     const gfx::Transform& quad_state_to_target_transform,
     bool quad_state_contents_opaque,
@@ -1360,6 +1375,9 @@ void SurfaceAggregator::AddRenderPassHelper(
                       /*backdrop_filters=*/cc::FilterOperations(),
                       /*backdrop_filter_bounds=*/gfx::RRectF(),
                       pass_color_usage, pass_has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                      pass_is_video_hole,
+#endif
                       /*cache_render_pass=*/false,
                       /*has_damage_from_contributing_content=*/false,
                       /*generate_mipmap=*/false);
@@ -1399,6 +1417,15 @@ void SurfaceAggregator::CopyQuadsToPass(
   const QuadList& source_quad_list = source_pass.quad_list;
   const SharedQuadState* last_copied_source_shared_quad_state = nullptr;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  // We have this flag for checking need to disable blend mode in GLRenderer
+  // We need to pass this flag to AggregatedRenderPass as it was created by
+  // Root surface id.
+  if (source_pass.has_video_hole) {
+    dest_pass->has_video_hole = true;
+  }
+#endif
+
   // If the current frame has copy requests or cached render passes, then
   // aggregate the entire thing, as otherwise parts of the copy requests may be
   // ignored and we could cache partially drawn render pass.
@@ -1662,8 +1689,12 @@ void SurfaceAggregator::CopyPasses(ResolvedFrameData& resolved_frame) {
         resolved_pass.remapped_id(), output_rect, output_rect,
         transform_to_root_target, source.filters, source.backdrop_filters,
         source.backdrop_filter_bounds, root_content_color_usage_,
-        source.has_transparent_background, source.cache_render_pass,
-        resolved_pass.aggregation().has_damage, source.generate_mipmap);
+        source.has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+        source.has_video_hole,
+#endif
+        source.cache_render_pass, resolved_pass.aggregation().has_damage,
+        source.generate_mipmap);
 
     UpdatePersistentPassDataMergeState(resolved_pass, copy_pass.get(),
                                        /*is_merged_pass=*/false);
index c3e0063..6f1fa64 100644 (file)
@@ -268,6 +268,9 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator : public SurfaceObserver {
                            const gfx::Rect& render_pass_damage_rect,
                            gfx::ContentColorUsage pass_color_usage,
                            bool pass_has_transparent_background,
+#if defined(TIZEN_VIDEO_HOLE)
+                           bool pass_is_video_hole,
+#endif
                            bool pass_is_color_conversion_pass,
                            const gfx::Transform& quad_state_to_target_transform,
                            bool quad_state_contents_opaque,
index 40ac4e9..240da89 100644 (file)
@@ -45,6 +45,9 @@ bool StructTraits<viz::mojom::CompositorRenderPassDataView,
   }
 
   (*out)->has_transparent_background = data.has_transparent_background();
+#if defined(TIZEN_VIDEO_HOLE)
+  (*out)->has_video_hole = data.has_video_hole();
+#endif
   (*out)->has_per_quad_damage = data.has_per_quad_damage();
 
   (*out)->cache_render_pass = data.cache_render_pass();
index a491df6..7fc918b 100644 (file)
@@ -83,6 +83,13 @@ struct StructTraits<viz::mojom::CompositorRenderPassDataView,
     return input->has_transparent_background;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  static bool has_video_hole(
+      const std::unique_ptr<viz::CompositorRenderPass>& input) {
+    return input->has_video_hole;
+  }
+#endif
+
   static bool has_per_quad_damage(
       const std::unique_ptr<viz::CompositorRenderPass>& input) {
     return input->has_per_quad_damage;
index 64661c3..d3ee6e9 100644 (file)
@@ -604,6 +604,10 @@ mojom("mojom") {
   if (tizen_tbm_support) {
     enabled_features += [ "tizen_tbm_support" ]
   }
+
+  if (tizen_video_hole) {
+    enabled_features += [ "tizen_video_hole" ]
+  }
 }
 
 # The enum that SharedImageFormat uses internally to denote singleplanar
index 4dca661..440b409 100644 (file)
@@ -42,4 +42,7 @@ struct CompositorRenderPass {
   // inconsistent states give new privileges to the sender that were not already
   // available with |damage_rect| or |quad_list|.
   bool has_per_quad_damage;
+
+  [EnableIf=tizen_video_hole]
+  bool has_video_hole = false;
 };