• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "drawable/rs_property_drawable_background.h"
17 
18 #include "common/rs_background_thread.h"
19 #include "common/rs_obj_abs_geometry.h"
20 #include "common/rs_optional_trace.h"
21 #ifdef ROSEN_OHOS
22 #include "common/rs_common_tools.h"
23 #endif
24 #include "drawable/rs_property_drawable_utils.h"
25 #include "effect/runtime_blender_builder.h"
26 #ifdef ROSEN_OHOS
27 #include "native_buffer_inner.h"
28 #include "native_window.h"
29 #endif
30 #include "pipeline/rs_effect_render_node.h"
31 #include "pipeline/rs_recording_canvas.h"
32 #include "pipeline/rs_render_node.h"
33 #include "pipeline/rs_surface_render_node.h"
34 #include "pipeline/rs_task_dispatcher.h"
35 #include "platform/common/rs_log.h"
36 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
37 #include "platform/ohos/backend/native_buffer_utils.h"
38 #include "platform/ohos/backend/rs_vulkan_context.h"
39 #endif
40 
41 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
42 #include "include/gpu/GrBackendSemaphore.h"
43 #endif
44 #include "common/rs_rect.h"
45 
46 namespace OHOS::Rosen {
47 namespace DrawableV2 {
48 namespace {
49 constexpr int TRACE_LEVEL_TWO = 2;
50 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_VK))
51 constexpr uint8_t ASTC_HEADER_SIZE = 16;
52 #endif
53 }
54 
OnGenerate(const RSRenderNode & node)55 RSDrawable::Ptr RSShadowDrawable::OnGenerate(const RSRenderNode& node)
56 {
57     // skip shadow if not valid. ShadowMask is processed by foreground
58     if (!node.GetRenderProperties().IsShadowValid() || node.GetRenderProperties().GetShadowMask()) {
59         return nullptr;
60     }
61     RSDrawable::Ptr ret = std::make_shared<RSShadowDrawable>();
62     if (ret->OnUpdate(node)) {
63         return ret;
64     }
65     return nullptr;
66 };
67 
OnUpdate(const RSRenderNode & node)68 bool RSShadowDrawable::OnUpdate(const RSRenderNode& node)
69 {
70     const RSProperties& properties = node.GetRenderProperties();
71     // skip shadow if not valid. ShadowMask is processed by foreground
72     if (!properties.IsShadowValid() || properties.GetShadowMask()) {
73         return false;
74     }
75 
76     stagingPath_ = RSPropertyDrawableUtils::CreateShadowPath(properties.GetShadowPath(),
77         properties.GetClipBounds(), properties.GetRRect());
78     stagingOffsetX_ = properties.GetShadowOffsetX();
79     stagingOffsetY_ = properties.GetShadowOffsetY();
80     stagingElevation_ = properties.GetShadowElevation();
81     stagingColor_ = properties.GetShadowColor();
82     stagingIsFilled_ = properties.GetShadowIsFilled();
83     stagingColorStrategy_ = properties.GetShadowColorStrategy();
84     stagingRadius_ = properties.GetShadowRadius();
85     needSync_ = true;
86     return true;
87 }
88 
OnSync()89 void RSShadowDrawable::OnSync()
90 {
91     if (!needSync_) {
92         return;
93     }
94     path_ = std::move(stagingPath_);
95     color_ = std::move(stagingColor_);
96     offsetX_ = stagingOffsetX_;
97     offsetY_ = stagingOffsetY_;
98     elevation_ = stagingElevation_;
99     isFilled_ = stagingIsFilled_;
100     radius_ = stagingRadius_;
101     colorStrategy_ = stagingColorStrategy_;
102     needSync_ = false;
103 }
104 
CreateDrawFunc() const105 Drawing::RecordingCanvas::DrawFunc RSShadowDrawable::CreateDrawFunc() const
106 {
107     auto ptr = std::static_pointer_cast<const RSShadowDrawable>(shared_from_this());
108     return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
109         // skip shadow if cache is enabled
110         if (canvas->GetCacheType() == Drawing::CacheType::ENABLED) {
111             ROSEN_LOGD("RSShadowDrawable::CreateDrawFunc cache type enabled.");
112             return;
113         }
114         Drawing::Path path = ptr->path_;
115         Color shadowColor = ptr->color_;
116         if (ptr->colorStrategy_ != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE) {
117             shadowColor = RSPropertyDrawableUtils::GetColorForShadowSyn(canvas, path,
118                 ptr->color_, ptr->colorStrategy_);
119         }
120         if (ROSEN_GNE(ptr->elevation_, 0.f)) {
121             RSPropertyDrawableUtils::DrawShadow(canvas, path, ptr->offsetX_, ptr->offsetY_,
122                 ptr->elevation_, ptr->isFilled_, shadowColor);
123             return;
124         }
125         if (ROSEN_GNE(ptr->radius_, 0.f)) {
126             RSPropertyDrawableUtils::DrawShadowMaskFilter(canvas, path, ptr->offsetX_, ptr->offsetY_,
127                 ptr->radius_, ptr->isFilled_, shadowColor);
128             return;
129         }
130     };
131 }
132 
OnGenerate(const RSRenderNode & node)133 RSDrawable::Ptr RSMaskDrawable::OnGenerate(const RSRenderNode& node)
134 {
135     if (auto ret = std::make_shared<RSMaskDrawable>(); ret->OnUpdate(node)) {
136         return std::move(ret);
137     }
138     return nullptr;
139 };
140 
OnUpdate(const RSRenderNode & node)141 bool RSMaskDrawable::OnUpdate(const RSRenderNode& node)
142 {
143     const RSProperties& properties = node.GetRenderProperties();
144     std::shared_ptr<RSMask> mask = properties.GetMask();
145     if (mask == nullptr) {
146         ROSEN_LOGE("RSMaskDrawable::OnUpdate null mask");
147         return false;
148     }
149     if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
150         ROSEN_LOGE("RSMaskDrawable::OnUpdate not has Svg Mask property");
151         return false;
152     }
153 
154     RSPropertyDrawCmdListUpdater updater(0, 0, this);
155     Drawing::Canvas& canvas = *updater.GetRecordingCanvas();
156     Drawing::Rect maskBounds = RSPropertyDrawableUtils::Rect2DrawingRect(properties.GetBoundsRect());
157     canvas.Save();
158     Drawing::SaveLayerOps slr(&maskBounds, nullptr);
159     canvas.SaveLayer(slr);
160     uint32_t tmpLayer = canvas.GetSaveCount();
161 
162     Drawing::Brush maskfilter;
163     Drawing::Filter filter;
164     filter.SetColorFilter(Drawing::ColorFilter::CreateComposeColorFilter(
165         *(Drawing::ColorFilter::CreateLumaColorFilter()), *(Drawing::ColorFilter::CreateSrgbGammaToLinear())));
166     maskfilter.SetFilter(filter);
167     Drawing::SaveLayerOps slrMask(&maskBounds, &maskfilter);
168     canvas.SaveLayer(slrMask);
169     if (mask->IsSvgMask()) {
170         Drawing::AutoCanvasRestore maskSave(canvas, true);
171         canvas.Translate(maskBounds.GetLeft() + mask->GetSvgX(), maskBounds.GetTop() + mask->GetSvgY());
172         canvas.Scale(mask->GetScaleX(), mask->GetScaleY());
173         if (mask->GetSvgDom()) {
174             canvas.DrawSVGDOM(mask->GetSvgDom());
175         } else if (mask->GetSvgPicture()) {
176             canvas.DrawPicture(*mask->GetSvgPicture());
177         }
178     } else if (mask->IsGradientMask()) {
179         Drawing::AutoCanvasRestore maskSave(canvas, true);
180         canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
181         Drawing::Rect rect = Drawing::Rect(0, 0, maskBounds.GetWidth(), maskBounds.GetHeight());
182         canvas.AttachBrush(mask->GetMaskBrush());
183         canvas.DrawRect(rect);
184         canvas.DetachBrush();
185     } else if (mask->IsPathMask()) {
186         Drawing::AutoCanvasRestore maskSave(canvas, true);
187         canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
188         canvas.AttachBrush(mask->GetMaskBrush());
189         canvas.AttachPen(mask->GetMaskPen());
190         canvas.DrawPath(*mask->GetMaskPath());
191         canvas.DetachBrush();
192         canvas.DetachPen();
193     } else if (mask->IsPixelMapMask() && mask->GetImage()) {
194         Drawing::AutoCanvasRestore maskSave(canvas, true);
195         canvas.DrawImage(*mask->GetImage(), 0.f, 0.f, Drawing::SamplingOptions());
196     }
197 
198     // back to mask layer
199     canvas.RestoreToCount(tmpLayer);
200     // create content layer
201     Drawing::Brush maskPaint;
202     maskPaint.SetBlendMode(Drawing::BlendMode::SRC_IN);
203     Drawing::SaveLayerOps slrContent(&maskBounds, &maskPaint);
204     canvas.SaveLayer(slrContent);
205     canvas.ClipRect(maskBounds, Drawing::ClipOp::INTERSECT, true);
206     return true;
207 }
208 
209 // ============================================================================
210 // Background
OnGenerate(const RSRenderNode & node)211 RSDrawable::Ptr RSBackgroundColorDrawable::OnGenerate(const RSRenderNode& node)
212 {
213     if (auto ret = std::make_shared<RSBackgroundColorDrawable>(); ret->OnUpdate(node)) {
214         return std::move(ret);
215     }
216     return nullptr;
217 };
218 
OnUpdate(const RSRenderNode & node)219 bool RSBackgroundColorDrawable::OnUpdate(const RSRenderNode& node)
220 {
221     const RSProperties& properties = node.GetRenderProperties();
222     auto bgColor = properties.GetBackgroundColor();
223     if (bgColor == RgbPalette::Transparent()) {
224         return false;
225     }
226 
227     // regenerate stagingDrawCmdList_
228     RSPropertyDrawCmdListUpdater updater(0, 0, this);
229     Drawing::Canvas& canvas = *updater.GetRecordingCanvas();
230     Drawing::Brush brush;
231     brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
232     if (properties.IsBgBrightnessValid()) {
233         if (Rosen::RSSystemProperties::GetDebugTraceLevel() >= TRACE_LEVEL_TWO) {
234             RSPropertyDrawable::stagingPropertyDescription_ = properties.GetBgBrightnessDescription();
235         }
236         auto blender = RSPropertyDrawableUtils::MakeDynamicBrightnessBlender(
237             properties.GetBgBrightnessParams().value());
238         brush.SetBlender(blender);
239     }
240     canvas.AttachBrush(brush);
241     canvas.DrawRect(RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect()));
242     canvas.DetachBrush();
243     return true;
244 }
245 
OnGenerate(const RSRenderNode & node)246 RSDrawable::Ptr RSBackgroundShaderDrawable::OnGenerate(const RSRenderNode& node)
247 {
248     if (auto ret = std::make_shared<RSBackgroundShaderDrawable>(); ret->OnUpdate(node)) {
249         return std::move(ret);
250     }
251     return nullptr;
252 };
253 
OnUpdate(const RSRenderNode & node)254 bool RSBackgroundShaderDrawable::OnUpdate(const RSRenderNode& node)
255 {
256     const RSProperties& properties = node.GetRenderProperties();
257     const auto& bgShader = properties.GetBackgroundShader();
258     if (!bgShader) {
259         return false;
260     }
261 
262     // regenerate stagingDrawCmdList_
263     RSPropertyDrawCmdListUpdater updater(0, 0, this);
264     Drawing::Canvas& canvas = *updater.GetRecordingCanvas();
265     Drawing::Brush brush;
266     auto shaderEffect = bgShader->GetDrawingShader();
267     // do not draw if shaderEffect is nullptr and keep RSShader behavior consistent
268     if (shaderEffect == nullptr && bgShader->GetShaderType() != RSShader::ShaderType::DRAWING) {
269         return true;
270     }
271     brush.SetShaderEffect(shaderEffect);
272     canvas.AttachBrush(brush);
273     canvas.DrawRect(RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect()));
274     canvas.DetachBrush();
275     return true;
276 }
277 
~RSBackgroundImageDrawable()278 RSBackgroundImageDrawable::~RSBackgroundImageDrawable()
279 {
280 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
281     ReleaseNativeWindowBuffer();
282 #endif
283 }
284 
OnGenerate(const RSRenderNode & node)285 RSDrawable::Ptr RSBackgroundImageDrawable::OnGenerate(const RSRenderNode& node)
286 {
287     if (auto ret = std::make_shared<RSBackgroundImageDrawable>(); ret->OnUpdate(node)) {
288         return std::move(ret);
289     }
290     return nullptr;
291 };
292 
293 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
GetColorTypeFromVKFormat(VkFormat vkFormat)294 Drawing::ColorType RSBackgroundImageDrawable::GetColorTypeFromVKFormat(VkFormat vkFormat)
295 {
296     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
297         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
298         return Drawing::COLORTYPE_RGBA_8888;
299     }
300     switch (vkFormat) {
301         case VK_FORMAT_R8G8B8A8_UNORM:
302             return Drawing::COLORTYPE_RGBA_8888;
303         case VK_FORMAT_R16G16B16A16_SFLOAT:
304             return Drawing::COLORTYPE_RGBA_F16;
305         case VK_FORMAT_R5G6B5_UNORM_PACK16:
306             return Drawing::COLORTYPE_RGB_565;
307         case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
308             return Drawing::COLORTYPE_RGBA_1010102;
309         default:
310             return Drawing::COLORTYPE_RGBA_8888;
311     }
312 }
313 #endif
314 
315 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
ReleaseNativeWindowBuffer()316 void RSBackgroundImageDrawable::ReleaseNativeWindowBuffer()
317 {
318     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
319         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
320         if (nativeWindowBuffer_ == nullptr && cleanUpHelper_ == nullptr) {
321             return;
322         }
323         RSTaskDispatcher::GetInstance().PostTask(
324             tid_, [nativeWindowBuffer = nativeWindowBuffer_, cleanUpHelper = cleanUpHelper_]() {
325                 if (nativeWindowBuffer != nullptr) {
326                     DestroyNativeWindowBuffer(nativeWindowBuffer);
327                 }
328                 if (cleanUpHelper != nullptr) {
329                     NativeBufferUtils::DeleteVkImage(cleanUpHelper);
330                 }
331             });
332         nativeWindowBuffer_ = nullptr;
333         cleanUpHelper_ = nullptr;
334     }
335 }
336 
MakeFromTextureForVK(Drawing::Canvas & canvas,SurfaceBuffer * surfaceBuffer)337 std::shared_ptr<Drawing::Image> RSBackgroundImageDrawable::MakeFromTextureForVK(
338     Drawing::Canvas& canvas, SurfaceBuffer* surfaceBuffer)
339 {
340     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
341         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
342         return nullptr;
343     }
344     if (surfaceBuffer == nullptr || surfaceBuffer->GetBufferHandle() == nullptr) {
345         RS_LOGE("MakeFromTextureForVK surfaceBuffer is nullptr or buffer handle is nullptr");
346         return nullptr;
347     }
348     std::shared_ptr<Media::PixelMap> pixelMap = bgImage_->GetPixelMap();
349     if (pixelMapId_ != pixelMap->GetUniqueId() || !backendTexture_.IsValid()) {
350         backendTexture_ = {};
351         ReleaseNativeWindowBuffer();
352         sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
353         nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&sfBuffer);
354         if (!nativeWindowBuffer_) {
355             RS_LOGE("MakeFromTextureForVK create native window buffer fail");
356             return nullptr;
357         }
358         backendTexture_ = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(
359             nativeWindowBuffer_, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), false);
360         if (backendTexture_.IsValid()) {
361             auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
362             cleanUpHelper_ = new NativeBufferUtils::VulkanCleanupHelper(
363                 RsVulkanContext::GetSingleton(), vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
364         } else {
365             return nullptr;
366         }
367         pixelMapId_ = pixelMap->GetUniqueId();
368         tid_ = gettid();
369     }
370 
371     if (canvas.GetGPUContext() == nullptr) {
372         RS_LOGE("RSBackgroundImageDrawable::MakeFromTextureForVK canvas.GetGPUContext is nullptr");
373         ReleaseNativeWindowBuffer();
374         return nullptr;
375     }
376     std::shared_ptr<Drawing::Image> dmaImage = std::make_shared<Drawing::Image>();
377     auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
378     Drawing::ColorType colorType = GetColorTypeFromVKFormat(vkTextureInfo->format);
379     Drawing::BitmapFormat bitmapFormat = { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
380     if (!dmaImage->BuildFromTexture(*canvas.GetGPUContext(), backendTexture_.GetTextureInfo(),
381         Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr, NativeBufferUtils::DeleteVkImage,
382         cleanUpHelper_->Ref())) {
383         RS_LOGE("MakeFromTextureForVK build image failed");
384         return nullptr;
385     }
386     return dmaImage;
387 }
388 
SetCompressedDataForASTC()389 void RSBackgroundImageDrawable::SetCompressedDataForASTC()
390 {
391     std::shared_ptr<Media::PixelMap> pixelMap = bgImage_->GetPixelMap();
392     if (!pixelMap || !pixelMap->GetFd()) {
393         RS_LOGE("SetCompressedDataForASTC fail, data is null");
394         return;
395     }
396     std::shared_ptr<Drawing::Data> fileData = std::make_shared<Drawing::Data>();
397     // After RS is switched to Vulkan, the judgment of GpuApiType can be deleted.
398     if (pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC &&
399         (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
400         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)) {
401         if (pixelMapId_ != pixelMap->GetUniqueId()) {
402             if (nativeWindowBuffer_) {
403                 DestroyNativeWindowBuffer(nativeWindowBuffer_);
404             }
405             sptr<SurfaceBuffer> surfaceBuf(reinterpret_cast<SurfaceBuffer *>(pixelMap->GetFd()));
406             nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuf);
407             pixelMapId_ = pixelMap->GetUniqueId();
408         }
409         OH_NativeBuffer* nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(nativeWindowBuffer_);
410         if (nativeBuffer == nullptr || !fileData->BuildFromOHNativeBuffer(nativeBuffer, pixelMap->GetCapacity())) {
411             RS_LOGE("SetCompressedDataForASTC data BuildFromOHNativeBuffer fail");
412             return;
413         }
414     } else {
415         const void* data = pixelMap->GetPixels();
416         if (pixelMap->GetCapacity() > ASTC_HEADER_SIZE &&
417             (data == nullptr || !fileData->BuildWithoutCopy(
418                 reinterpret_cast<const void *>(reinterpret_cast<const char *>(data) + ASTC_HEADER_SIZE),
419                 pixelMap->GetCapacity() - ASTC_HEADER_SIZE))) {
420             RS_LOGE("SetCompressedDataForASTC data BuildWithoutCopy fail");
421             return;
422         }
423     }
424     bgImage_->SetCompressData(fileData);
425 }
426 #endif
427 
OnUpdate(const RSRenderNode & node)428 bool RSBackgroundImageDrawable::OnUpdate(const RSRenderNode& node)
429 {
430     const RSProperties& properties = node.GetRenderProperties();
431     stagingBgImage_ = properties.GetBgImage();
432     if (!stagingBgImage_) {
433         return false;
434     }
435 
436     stagingBoundsRect_ = RSPropertyDrawableUtils::Rect2DrawingRect(properties.GetBoundsRect());
437     auto innerRect = properties.GetBgImageInnerRect();
438     stagingBgImage_->SetDstRect(properties.GetBgImageRect());
439     stagingBgImage_->SetInnerRect(std::make_optional<Drawing::RectI>(
440         innerRect.x_, innerRect.y_, innerRect.x_ + innerRect.z_, innerRect.y_ + innerRect.w_));
441     needSync_ = true;
442     return true;
443 }
444 
OnSync()445 void RSBackgroundImageDrawable::OnSync()
446 {
447     if (!needSync_) {
448         return;
449     }
450     bgImage_ = std::move(stagingBgImage_);
451     boundsRect_ = stagingBoundsRect_;
452     needSync_ = false;
453 }
454 
CreateDrawFunc() const455 Drawing::RecordingCanvas::DrawFunc RSBackgroundImageDrawable::CreateDrawFunc() const
456 {
457     auto ptr = std::const_pointer_cast<RSBackgroundImageDrawable>(
458         std::static_pointer_cast<const RSBackgroundImageDrawable>(shared_from_this()));
459     return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
460         Drawing::Brush brush;
461         canvas->AttachBrush(brush);
462         auto bgImage = ptr->bgImage_;
463         if (!bgImage) {
464             return;
465         }
466 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
467         if (bgImage->GetPixelMap() && !bgImage->GetPixelMap()->IsAstc() &&
468             bgImage->GetPixelMap()->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
469             if (!bgImage->GetPixelMap()->GetFd()) {
470                 return;
471             }
472             auto dmaImage =
473                 ptr->MakeFromTextureForVK(*canvas, reinterpret_cast<SurfaceBuffer*>(bgImage->GetPixelMap()->GetFd()));
474             bgImage->SetDmaImage(dmaImage);
475         }
476         if (bgImage->GetPixelMap() && bgImage->GetPixelMap()->IsAstc()) {
477             ptr->SetCompressedDataForASTC();
478         }
479 #endif
480         bgImage->CanvasDrawImage(*canvas, ptr->boundsRect_, Drawing::SamplingOptions(), true);
481         canvas->DetachBrush();
482     };
483 }
484 
OnGenerate(const RSRenderNode & node)485 RSDrawable::Ptr RSBackgroundFilterDrawable::OnGenerate(const RSRenderNode& node)
486 {
487     auto& rsFilter = node.GetRenderProperties().GetBackgroundFilter();
488     if (rsFilter == nullptr && !node.NeedDrawBehindWindow()) {
489         return nullptr;
490     }
491 
492     RSDrawable::Ptr filterDrawable = nullptr;
493     if (node.IsInstanceOf<RSEffectRenderNode>()) {
494         filterDrawable = std::make_shared<RSBackgroundEffectDrawable>();
495     } else {
496         filterDrawable = std::make_shared<RSBackgroundFilterDrawable>();
497     }
498     if (filterDrawable->OnUpdate(node)) {
499         return filterDrawable;
500     }
501     return nullptr;
502 }
503 
OnUpdate(const RSRenderNode & node)504 bool RSBackgroundFilterDrawable::OnUpdate(const RSRenderNode& node)
505 {
506     stagingNodeId_ = node.GetId();
507     stagingNodeName_ = node.GetNodeName();
508     auto& rsFilter = node.GetRenderProperties().GetBackgroundFilter();
509     if (rsFilter != nullptr) {
510         RecordFilterInfos(rsFilter);
511         needSync_ = true;
512         stagingFilter_ = rsFilter;
513         stagingNeedDrawBehindWindow_ = false;
514         return true;
515     }
516     if (node.NeedDrawBehindWindow()) {
517         auto behindWindowFilter = GetBehindWindowFilter(node);
518         if (behindWindowFilter == nullptr) {
519             return false;
520         }
521         RecordFilterInfos(behindWindowFilter);
522         needSync_ = true;
523         stagingFilter_ = behindWindowFilter;
524         stagingNeedDrawBehindWindow_ = true;
525         stagingDrawBehindWindowRegion_ = node.GetBehindWindowRegion();
526         return true;
527     }
528     return false;
529 }
530 
GetBehindWindowFilter(const RSRenderNode & node)531 std::shared_ptr<RSFilter> RSBackgroundFilterDrawable::GetBehindWindowFilter(const RSRenderNode& node)
532 {
533     float radius = 0.f;
534     float saturation = 1.f;
535     float brightness = 1.f;
536     RSColor maskColor = {};
537     if (GetModifierProperty(node, RSModifierType::BEHIND_WINDOW_FILTER_RADIUS, radius) &&
538         GetModifierProperty(node, RSModifierType::BEHIND_WINDOW_FILTER_SATURATION, saturation) &&
539         GetModifierProperty(node, RSModifierType::BEHIND_WINDOW_FILTER_BRIGHTNESS, brightness) &&
540         GetModifierProperty(node, RSModifierType::BEHIND_WINDOW_FILTER_MASK_COLOR, maskColor)) {
541         return RSPropertyDrawableUtils::GenerateBehindWindowFilter(radius, saturation, brightness, maskColor);
542     }
543     return nullptr;
544 }
545 
546 template <typename T>
GetModifierProperty(const RSRenderNode & node,RSModifierType type,T & property)547 bool RSBackgroundFilterDrawable::GetModifierProperty(const RSRenderNode& node, RSModifierType type, T& property)
548 {
549     auto& drawCmdModifiers = const_cast<RSRenderContent::DrawCmdContainer&>(node.GetDrawCmdModifiers());
550     auto iter = drawCmdModifiers.find(type);
551     if (iter == drawCmdModifiers.end() || iter->second.empty()) {
552         RS_LOGE("RSBackgroundFilterDrawable::GetModifierProperty fail to get, modifierType = %{public}hd.", type);
553         return false;
554     }
555     auto& modifier = iter->second.back();
556     property = std::static_pointer_cast<RSRenderAnimatableProperty<T>>(modifier->GetProperty())->Get();
557     return true;
558 }
559 
OnSync()560 void RSBackgroundFilterDrawable::OnSync()
561 {
562     if (needSync_) {
563         needDrawBehindWindow_ = stagingNeedDrawBehindWindow_;
564     }
565     drawBehindWindowRegion_ = stagingDrawBehindWindowRegion_;
566     RSFilterDrawable::OnSync();
567 }
568 
FuzePixelStretch(const RSRenderNode & node)569 bool RSBackgroundFilterDrawable::FuzePixelStretch(const RSRenderNode& node)
570 {
571     return RSPropertyDrawableUtils::RSFilterSetPixelStretch(node.GetRenderProperties(), stagingFilter_);
572 }
573 
RemovePixelStretch()574 void RSBackgroundFilterDrawable::RemovePixelStretch()
575 {
576     RSPropertyDrawableUtils::RSFilterRemovePixelStretch(stagingFilter_);
577 }
578 
OnUpdate(const RSRenderNode & node)579 bool RSBackgroundEffectDrawable::OnUpdate(const RSRenderNode& node)
580 {
581     stagingNodeId_ = node.GetId();
582     stagingNodeName_ = node.GetNodeName();
583     auto& rsFilter = node.GetRenderProperties().GetBackgroundFilter();
584     if (rsFilter == nullptr) {
585         return false;
586     }
587     RecordFilterInfos(rsFilter);
588     needSync_ = true;
589     stagingFilter_ = rsFilter;
590     return true;
591 }
592 
OnSync()593 void RSBackgroundEffectDrawable::OnSync()
594 {
595     RSFilterDrawable::OnSync();
596 }
597 
CreateDrawFunc() const598 Drawing::RecordingCanvas::DrawFunc RSBackgroundEffectDrawable::CreateDrawFunc() const
599 {
600     auto ptr = std::static_pointer_cast<const RSBackgroundEffectDrawable>(shared_from_this());
601     return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
602         auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
603         Drawing::AutoCanvasRestore acr(*canvas, true);
604         paintFilterCanvas->ClipRect(*rect);
605         Drawing::Rect absRect(0.0, 0.0, 0.0, 0.0);
606         canvas->GetTotalMatrix().MapRect(absRect, *rect);
607         auto surface = canvas->GetSurface();
608         if (!surface) {
609             ROSEN_LOGE("RSBackgroundEffectDrawable::CreateDrawFunc surface is nullptr.");
610             return;
611         }
612         RectI deviceRect(0, 0, surface->Width(), surface->Height());
613         RectI bounds(std::ceil(absRect.GetLeft()), std::ceil(absRect.GetTop()), std::ceil(absRect.GetWidth()),
614             std::ceil(absRect.GetHeight()));
615         bounds = bounds.IntersectRect(deviceRect);
616         Drawing::RectI boundsRect(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(), bounds.GetBottom());
617         RS_TRACE_NAME_FMT("RSBackgroundEffectDrawable::DrawBackgroundEffect nodeId[%lld]", ptr->renderNodeId_);
618         RSPropertyDrawableUtils::DrawBackgroundEffect(
619             paintFilterCanvas, ptr->filter_, ptr->cacheManager_, boundsRect);
620     };
621 }
622 
OnGenerate(const RSRenderNode & node)623 RSDrawable::Ptr RSUseEffectDrawable::OnGenerate(const RSRenderNode& node)
624 {
625     if (!node.GetRenderProperties().GetUseEffect()) {
626         return nullptr;
627     }
628     if (node.GetRenderProperties().GetUseEffectType() == static_cast<int>(UseEffectType::BEHIND_WINDOW)) {
629         return std::make_shared<RSUseEffectDrawable>(UseEffectType::BEHIND_WINDOW);
630     }
631     // Find effect render node
632     auto parentNode = node.GetParent().lock();
633     while (parentNode && !parentNode->IsInstanceOf<RSEffectRenderNode>()) {
634         parentNode = parentNode->GetParent().lock();
635     }
636     DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr effectRenderNodeDrawable = nullptr;
637     if (parentNode) {
638         effectRenderNodeDrawable = parentNode->GetRenderDrawable();
639     } else {
640         ROSEN_LOGD("RSUseEffectDrawable::OnGenerate: find EffectRenderNode failed.");
641     }
642     return std::make_shared<RSUseEffectDrawable>(effectRenderNodeDrawable);
643 }
644 
OnUpdate(const RSRenderNode & node)645 bool RSUseEffectDrawable::OnUpdate(const RSRenderNode& node)
646 {
647     if (!node.GetRenderProperties().GetUseEffect()) {
648         return false;
649     }
650     needSync_ = true;
651     stagingUseEffectType_ = static_cast<UseEffectType>(node.GetRenderProperties().GetUseEffectType());
652     return true;
653 }
654 
OnSync()655 void RSUseEffectDrawable::OnSync()
656 {
657     if (!needSync_) {
658         return;
659     }
660     useEffectType_ = stagingUseEffectType_;
661     needSync_ = false;
662 }
663 
CreateDrawFunc() const664 Drawing::RecordingCanvas::DrawFunc RSUseEffectDrawable::CreateDrawFunc() const
665 {
666     auto ptr = std::static_pointer_cast<const RSUseEffectDrawable>(shared_from_this());
667     return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
668         if (!(RSSystemProperties::GetEffectMergeEnabled() && RSFilterCacheManager::isCCMEffectMergeEnable_)) {
669             return;
670         }
671         auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
672         if (paintFilterCanvas == nullptr) {
673             return;
674         }
675         if (ptr->useEffectType_ == UseEffectType::BEHIND_WINDOW && paintFilterCanvas->GetIsWindowFreezeCapture()) {
676             RS_OPTIONAL_TRACE_NAME_FMT("RSUseEffectDrawable::CreateDrawFunc drawBehindWindow in surface capturing");
677             RS_LOGD("RSUseEffectDrawable::CreateDrawFunc drawBehindWindow in surface capturing");
678             paintFilterCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
679             return;
680         }
681         const auto& effectData = paintFilterCanvas->GetEffectData();
682         if (ptr->useEffectType_ != UseEffectType::BEHIND_WINDOW &&
683             (effectData == nullptr || effectData->cachedImage_ == nullptr)) {
684             ROSEN_LOGD("RSPropertyDrawableUtils::DrawUseEffect effectData null, try to generate.");
685             auto drawable = ptr->effectRenderNodeDrawableWeakRef_.lock();
686             if (!drawable) {
687                 return;
688             }
689             RS_TRACE_NAME_FMT("RSPropertyDrawableUtils::DrawUseEffect Fallback");
690             RSAutoCanvasRestore arc(paintFilterCanvas, RSPaintFilterCanvas::SaveType::kEnv);
691             bool disableFilterCache = paintFilterCanvas->GetDisableFilterCache();
692             paintFilterCanvas->SetDisableFilterCache(true);
693             int8_t index = drawable->drawCmdIndex_.backgroundFilterIndex_;
694             drawable->DrawImpl(*paintFilterCanvas, *rect, index);
695             paintFilterCanvas->SetDisableFilterCache(disableFilterCache);
696             RSPropertyDrawableUtils::DrawUseEffect(paintFilterCanvas, ptr->useEffectType_);
697             return;
698         }
699         RSPropertyDrawableUtils::DrawUseEffect(paintFilterCanvas, ptr->useEffectType_);
700     };
701 }
702 
OnGenerate(const RSRenderNode & node)703 RSDrawable::Ptr RSDynamicLightUpDrawable::OnGenerate(const RSRenderNode& node)
704 {
705     const RSProperties& properties = node.GetRenderProperties();
706     if (!properties.IsDynamicLightUpValid()) {
707         return nullptr;
708     }
709 
710     return std::make_shared<RSDynamicLightUpDrawable>(
711         properties.GetDynamicLightUpRate().value(), properties.GetDynamicLightUpDegree().value());
712 };
713 
OnUpdate(const RSRenderNode & node)714 bool RSDynamicLightUpDrawable::OnUpdate(const RSRenderNode& node)
715 {
716     const RSProperties& properties = node.GetRenderProperties();
717     if (!properties.IsDynamicLightUpValid()) {
718         return false;
719     }
720 
721     stagingDynamicLightUpRate_ = properties.GetDynamicLightUpRate().value();
722     stagingDynamicLightUpDeg_ = properties.GetDynamicLightUpDegree().value();
723     needSync_ = true;
724 
725     return true;
726 }
727 
OnSync()728 void RSDynamicLightUpDrawable::OnSync()
729 {
730     if (!needSync_) {
731         return;
732     }
733     dynamicLightUpRate_ = stagingDynamicLightUpRate_;
734     dynamicLightUpDeg_ = stagingDynamicLightUpDeg_;
735     needSync_ = false;
736 }
737 
CreateDrawFunc() const738 Drawing::RecordingCanvas::DrawFunc RSDynamicLightUpDrawable::CreateDrawFunc() const
739 {
740     auto ptr = std::static_pointer_cast<const RSDynamicLightUpDrawable>(shared_from_this());
741     return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
742         if (canvas->GetUICapture()) {
743             return;
744         }
745         auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
746         auto alpha = paintFilterCanvas->GetAlpha();
747         auto blender = RSDynamicLightUpDrawable::MakeDynamicLightUpBlender(
748             ptr->dynamicLightUpRate_, ptr->dynamicLightUpDeg_, alpha);
749         RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
750             "RSDynamicLightUpDrawable::DrawDynamicLightUp, rate: %f, degree: %f, bounds: %s", ptr->dynamicLightUpRate_,
751             ptr->dynamicLightUpDeg_, rect->ToString().c_str());
752         Drawing::Brush brush;
753         brush.SetBlender(blender);
754         paintFilterCanvas->DrawBackground(brush);
755     };
756 }
757 
MakeDynamicLightUpBlender(float rate,float degree,float alpha)758 std::shared_ptr<Drawing::Blender> RSDynamicLightUpDrawable::MakeDynamicLightUpBlender(
759     float rate, float degree, float alpha)
760 {
761     static constexpr char prog[] = R"(
762         uniform float dynamicLightUpRate;
763         uniform float dynamicLightUpDeg;
764 
765         vec4 main(vec4 drawing_src, vec4 drawing_dst) {
766             float x = 0.299 * drawing_dst.r + 0.587 * drawing_dst.g + 0.114 * drawing_dst.b;
767             float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg;
768             float R = clamp((drawing_dst.r + y), 0.0, 1.0);
769             float G = clamp((drawing_dst.g + y), 0.0, 1.0);
770             float B = clamp((drawing_dst.b + y), 0.0, 1.0);
771             return vec4(R, G, B, 1.0);
772         }
773     )";
774     static std::shared_ptr<Drawing::RuntimeEffect> dynamicLightUpBlenderEffect_ = nullptr;
775 
776     if (dynamicLightUpBlenderEffect_ == nullptr) {
777         dynamicLightUpBlenderEffect_ = Drawing::RuntimeEffect::CreateForBlender(prog);
778         if (dynamicLightUpBlenderEffect_ == nullptr) {
779             ROSEN_LOGE("RSDynamicLightUpDrawable::MakeDynamicLightUpBlender effect error!");
780             return nullptr;
781         }
782     }
783     auto builder = std::make_shared<Drawing::RuntimeBlenderBuilder>(dynamicLightUpBlenderEffect_);
784     builder->SetUniform("dynamicLightUpRate", rate * alpha);
785     builder->SetUniform("dynamicLightUpDeg", degree * alpha);
786     return builder->MakeBlender();
787 }
788 } // namespace DrawableV2
789 } // namespace OHOS::Rosen
790