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