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