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) {
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 return false;
541 }
542 RecordFilterInfos(rsFilter);
543 needSync_ = true;
544 stagingFilter_ = rsFilter;
545 return true;
546 }
547
FuzePixelStretch(const RSRenderNode & node)548 bool RSBackgroundFilterDrawable::FuzePixelStretch(const RSRenderNode& node)
549 {
550 return RSPropertyDrawableUtils::RSFilterSetPixelStretch(node.GetRenderProperties(), stagingFilter_);
551 }
552
RemovePixelStretch()553 void RSBackgroundFilterDrawable::RemovePixelStretch()
554 {
555 RSPropertyDrawableUtils::RSFilterRemovePixelStretch(stagingFilter_);
556 }
557
OnUpdate(const RSRenderNode & node)558 bool RSBackgroundEffectDrawable::OnUpdate(const RSRenderNode& node)
559 {
560 stagingNodeId_ = node.GetId();
561 auto& rsFilter = node.GetRenderProperties().GetBackgroundFilter();
562 if (rsFilter == nullptr) {
563 return false;
564 }
565 RecordFilterInfos(rsFilter);
566 needSync_ = true;
567 stagingFilter_ = rsFilter;
568 return true;
569 }
570
OnSync()571 void RSBackgroundEffectDrawable::OnSync()
572 {
573 RSFilterDrawable::OnSync();
574 }
575
CreateDrawFunc() const576 Drawing::RecordingCanvas::DrawFunc RSBackgroundEffectDrawable::CreateDrawFunc() const
577 {
578 auto ptr = std::static_pointer_cast<const RSBackgroundEffectDrawable>(shared_from_this());
579 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
580 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
581 Drawing::AutoCanvasRestore acr(*canvas, true);
582 paintFilterCanvas->ClipRect(*rect);
583 Drawing::Rect absRect(0.0, 0.0, 0.0, 0.0);
584 canvas->GetTotalMatrix().MapRect(absRect, *rect);
585 Drawing::RectI bounds(std::ceil(absRect.GetLeft()), std::ceil(absRect.GetTop()), std::ceil(absRect.GetRight()),
586 std::ceil(absRect.GetBottom()));
587 RS_TRACE_NAME_FMT("RSBackgroundEffectDrawable::DrawBackgroundEffect nodeId[%lld]", ptr->renderNodeId_);
588 RSPropertyDrawableUtils::DrawBackgroundEffect(
589 paintFilterCanvas, ptr->filter_, ptr->cacheManager_, ptr->renderClearFilteredCacheAfterDrawing_, bounds);
590 };
591 }
592
OnGenerate(const RSRenderNode & node)593 RSDrawable::Ptr RSUseEffectDrawable::OnGenerate(const RSRenderNode& node)
594 {
595 if (!node.GetRenderProperties().GetUseEffect()) {
596 return nullptr;
597 }
598 // Find effect render node
599 auto parentNode = node.GetParent().lock();
600 while (parentNode && !parentNode->IsInstanceOf<RSEffectRenderNode>()) {
601 parentNode = parentNode->GetParent().lock();
602 }
603 DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr effectRenderNodeDrawable = nullptr;
604 if (parentNode) {
605 effectRenderNodeDrawable = parentNode->GetRenderDrawable();
606 } else {
607 ROSEN_LOGD("RSUseEffectDrawable::OnGenerate: find EffectRenderNode failed.");
608 }
609 return std::make_shared<RSUseEffectDrawable>(effectRenderNodeDrawable);
610 }
611
OnUpdate(const RSRenderNode & node)612 bool RSUseEffectDrawable::OnUpdate(const RSRenderNode& node)
613 {
614 if (!node.GetRenderProperties().GetUseEffect()) {
615 return false;
616 }
617 return true;
618 }
619
CreateDrawFunc() const620 Drawing::RecordingCanvas::DrawFunc RSUseEffectDrawable::CreateDrawFunc() const
621 {
622 auto ptr = std::static_pointer_cast<const RSUseEffectDrawable>(shared_from_this());
623 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
624 if (!RSSystemProperties::GetEffectMergeEnabled()) {
625 return;
626 }
627 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
628 if (paintFilterCanvas == nullptr) {
629 return;
630 }
631 const auto& effectData = paintFilterCanvas->GetEffectData();
632 if (effectData == nullptr || effectData->cachedImage_ == nullptr) {
633 ROSEN_LOGD("RSPropertyDrawableUtils::DrawUseEffect effectData null, try to generate.");
634 auto drawable = ptr->effectRenderNodeDrawableWeakRef_.lock();
635 if (!drawable) {
636 return;
637 }
638 RS_TRACE_NAME_FMT("RSPropertyDrawableUtils::DrawUseEffect Fallback");
639 RSAutoCanvasRestore arc(paintFilterCanvas, RSPaintFilterCanvas::SaveType::kEnv);
640 bool disableFilterCache = paintFilterCanvas->GetDisableFilterCache();
641 paintFilterCanvas->SetDisableFilterCache(true);
642 int8_t index = drawable->drawCmdIndex_.backgroundFilterIndex_;
643 drawable->DrawImpl(*paintFilterCanvas, *rect, index);
644 paintFilterCanvas->SetDisableFilterCache(disableFilterCache);
645 RSPropertyDrawableUtils::DrawUseEffect(paintFilterCanvas);
646 return;
647 }
648 RSPropertyDrawableUtils::DrawUseEffect(paintFilterCanvas);
649 };
650 }
651
OnGenerate(const RSRenderNode & node)652 RSDrawable::Ptr RSDynamicLightUpDrawable::OnGenerate(const RSRenderNode& node)
653 {
654 const RSProperties& properties = node.GetRenderProperties();
655 if (!properties.IsDynamicLightUpValid()) {
656 return nullptr;
657 }
658
659 return std::make_shared<RSDynamicLightUpDrawable>(
660 properties.GetDynamicLightUpRate().value(), properties.GetDynamicLightUpDegree().value());
661 };
662
OnUpdate(const RSRenderNode & node)663 bool RSDynamicLightUpDrawable::OnUpdate(const RSRenderNode& node)
664 {
665 const RSProperties& properties = node.GetRenderProperties();
666 if (!properties.IsDynamicLightUpValid()) {
667 return false;
668 }
669
670 stagingDynamicLightUpRate_ = properties.GetDynamicLightUpRate().value();
671 stagingDynamicLightUpDeg_ = properties.GetDynamicLightUpDegree().value();
672 needSync_ = true;
673
674 return true;
675 }
676
OnSync()677 void RSDynamicLightUpDrawable::OnSync()
678 {
679 if (!needSync_) {
680 return;
681 }
682 dynamicLightUpRate_ = stagingDynamicLightUpRate_;
683 dynamicLightUpDeg_ = stagingDynamicLightUpDeg_;
684 needSync_ = false;
685 }
686
CreateDrawFunc() const687 Drawing::RecordingCanvas::DrawFunc RSDynamicLightUpDrawable::CreateDrawFunc() const
688 {
689 auto ptr = std::static_pointer_cast<const RSDynamicLightUpDrawable>(shared_from_this());
690 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
691 if (canvas->GetUICapture()) {
692 return;
693 }
694 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
695 auto alpha = paintFilterCanvas->GetAlpha();
696 auto blender = RSDynamicLightUpDrawable::MakeDynamicLightUpBlender(
697 ptr->dynamicLightUpRate_, ptr->dynamicLightUpDeg_, alpha);
698 RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
699 "RSDynamicLightUpDrawable::DrawDynamicLightUp, rate: %f, degree: %f, bounds: %s", ptr->dynamicLightUpRate_,
700 ptr->dynamicLightUpDeg_, rect->ToString().c_str());
701 Drawing::Brush brush;
702 brush.SetBlender(blender);
703 paintFilterCanvas->DrawBackground(brush);
704 };
705 }
706
MakeDynamicLightUpBlender(float rate,float degree,float alpha)707 std::shared_ptr<Drawing::Blender> RSDynamicLightUpDrawable::MakeDynamicLightUpBlender(
708 float rate, float degree, float alpha)
709 {
710 static constexpr char prog[] = R"(
711 uniform float dynamicLightUpRate;
712 uniform float dynamicLightUpDeg;
713
714 vec4 main(vec4 drawing_src, vec4 drawing_dst) {
715 float x = 0.299 * drawing_dst.r + 0.587 * drawing_dst.g + 0.114 * drawing_dst.b;
716 float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg;
717 float R = clamp((drawing_dst.r + y), 0.0, 1.0);
718 float G = clamp((drawing_dst.g + y), 0.0, 1.0);
719 float B = clamp((drawing_dst.b + y), 0.0, 1.0);
720 return vec4(R, G, B, 1.0);
721 }
722 )";
723 static std::shared_ptr<Drawing::RuntimeEffect> dynamicLightUpBlenderEffect_ = nullptr;
724
725 if (dynamicLightUpBlenderEffect_ == nullptr) {
726 dynamicLightUpBlenderEffect_ = Drawing::RuntimeEffect::CreateForBlender(prog);
727 if (dynamicLightUpBlenderEffect_ == nullptr) {
728 ROSEN_LOGE("RSDynamicLightUpDrawable::MakeDynamicLightUpBlender effect error!");
729 return nullptr;
730 }
731 }
732 auto builder = std::make_shared<Drawing::RuntimeBlenderBuilder>(dynamicLightUpBlenderEffect_);
733 builder->SetUniform("dynamicLightUpRate", rate * alpha);
734 builder->SetUniform("dynamicLightUpDeg", degree * alpha);
735 return builder->MakeBlender();
736 }
737 } // namespace DrawableV2
738 } // namespace OHOS::Rosen
739