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