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