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