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_render_node_drawable.h"
17 #include "drawable/rs_surface_render_node_drawable.h"
18 
19 #include "rs_trace.h"
20 
21 #include "common/rs_obj_abs_geometry.h"
22 #include "impl_interface/region_impl.h"
23 #include "memory/rs_tag_tracker.h"
24 #include "params/rs_display_render_params.h"
25 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
26 #include "pipeline/parallel_render/rs_ui_first_render_listener.h"
27 #include "pipeline/rs_main_thread.h"
28 #include "pipeline/rs_paint_filter_canvas.h"
29 #include "pipeline/rs_surface_handler.h"
30 #include "pipeline/rs_surface_render_node.h"
31 #include "pipeline/rs_uifirst_manager.h"
32 #include "pipeline/rs_uni_render_thread.h"
33 #include "pipeline/rs_uni_render_util.h"
34 #include "platform/common/rs_log.h"
35 #ifdef RS_ENABLE_VK
36 #include "platform/ohos/backend/rs_surface_ohos_vulkan.h"
37 #endif
38 
39 namespace OHOS::Rosen::DrawableV2 {
UseDmaBuffer()40 bool RSSurfaceRenderNodeDrawable::UseDmaBuffer()
41 {
42     bool useDmaBuffer = RSUifirstManager::Instance().GetUseDmaBuffer(name_);
43     return useDmaBuffer;
44 }
45 
46 #ifndef ROSEN_CROSS_PLATFORM
CreateSurface()47 bool RSSurfaceRenderNodeDrawable::CreateSurface()
48 {
49     auto consumer = surfaceHandlerUiFirst_->GetConsumer();
50     if (consumer != nullptr && surface_ != nullptr) {
51         RS_LOGI("RSSurfaceRenderNodeDrawable::CreateSurface already created, return");
52         return true;
53     }
54     if (auto& params = GetRenderParams()) {
55         auto size = params->GetCacheSize();
56         boundsWidth_ = size.x_;
57         boundsHeight_ = size.y_;
58     } else {
59         RS_LOGE("RSSurfaceRenderNodeDrawable::CreateSurface cannot get cachesize");
60         return false;
61     }
62     if (consumerListener_ == nullptr) {
63         consumerListener_ = new RSUIFirstRenderListener(surfaceHandlerUiFirst_);
64     }
65     consumer = IConsumerSurface::Create(name_);
66     if (consumer == nullptr) {
67         RS_LOGE("RSSurfaceRenderNodeDrawable::CreateSurface get consumer surface fail");
68         return false;
69     }
70     SurfaceError ret = consumer->RegisterConsumerListener(consumerListener_);
71     if (ret != SURFACE_ERROR_OK) {
72         RS_LOGE("RSSurfaceRenderNodeDrawable::CreateSurface RegisterConsumerListener fail");
73         return false;
74     }
75     auto producer = consumer->GetProducer();
76     sptr<Surface> surface = Surface::CreateSurfaceAsProducer(producer);
77     if (surface == nullptr) {
78         return false;
79     }
80     const uint8_t queueSize = 3;
81     surface->SetQueueSize(queueSize);
82     auto client = std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
83     surface_ = client->CreateRSSurface(surface);
84     surfaceCreated_ = true;
85     surfaceHandlerUiFirst_->SetConsumer(consumer);
86     return true;
87 }
88 #endif
89 
GetFrameBufferRequestConfig()90 BufferRequestConfig RSSurfaceRenderNodeDrawable::GetFrameBufferRequestConfig()
91 {
92     BufferRequestConfig config {};
93     config.width = static_cast<int32_t>(boundsWidth_);
94     config.height = static_cast<int32_t>(boundsHeight_);
95     config.strideAlignment = 0x8;
96     config.colorGamut = GRAPHIC_COLOR_GAMUT_SRGB;
97     config.format = GRAPHIC_PIXEL_FMT_RGBA_8888;
98     config.usage = BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE | BUFFER_USAGE_HW_COMPOSER | BUFFER_USAGE_MEM_DMA;
99     config.timeout = 0;
100     return config;
101 }
102 
RequestFrame(RenderContext * renderContext,std::shared_ptr<Drawing::GPUContext> skContext)103 std::unique_ptr<RSRenderFrame> RSSurfaceRenderNodeDrawable::RequestFrame(
104     RenderContext* renderContext, std::shared_ptr<Drawing::GPUContext> skContext)
105 {
106     RS_TRACE_NAME("RSSurfaceRenderNodeDrawable:RequestFrame");
107     auto rsSurface = std::static_pointer_cast<RSSurfaceOhos>(surface_);
108     if (rsSurface == nullptr) {
109         RS_LOGE("RSSurfaceRenderNodeDrawable::RequestFrame: surface is null!");
110         return nullptr;
111     }
112 #ifdef RS_ENABLE_VK
113     RSTagTracker tagTracker(skContext.get(), RSTagTracker::TAGTYPE::TAG_ACQUIRE_SURFACE);
114 #endif
115     auto config = GetFrameBufferRequestConfig();
116     rsSurface->SetColorSpace(config.colorGamut);
117     rsSurface->SetSurfacePixelFormat(config.format);
118 
119     auto bufferUsage = config.usage;
120 #if !((defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE))
121     bufferUsage |= BUFFER_USAGE_CPU_WRITE;
122 #endif
123     rsSurface->SetSurfaceBufferUsage(bufferUsage);
124 
125 #ifdef RS_ENABLE_GL
126     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL &&
127         renderContext != nullptr) {
128         rsSurface->SetRenderContext(renderContext);
129     }
130 #endif
131 #ifdef RS_ENABLE_VK
132     if ((RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
133         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) && skContext != nullptr) {
134         std::static_pointer_cast<RSSurfaceOhosVulkan>(rsSurface)->SetSkContext(skContext);
135     }
136 #endif
137     auto surfaceFrame = rsSurface->RequestFrame(config.width, config.height, 0);
138     if (surfaceFrame == nullptr) {
139         RS_LOGE("RSSurfaceRenderNodeDrawable::RequestFrame: request SurfaceFrame failed!");
140         return nullptr;
141     }
142     return std::make_unique<RSRenderFrame>(rsSurface, std::move(surfaceFrame));
143 }
144 
DrawUIFirstCacheWithDma(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)145 bool RSSurfaceRenderNodeDrawable::DrawUIFirstCacheWithDma(
146     RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams)
147 {
148     RS_TRACE_NAME("DrawUIFirstCacheWithDma");
149     if (surfaceParams.GetHardwareEnabled()) {
150         return true;
151     }
152     if (!surfaceHandlerUiFirst_->GetBuffer() && surfaceHandlerUiFirst_->GetAvailableBufferCount() <= 0) {
153         RS_TRACE_NAME_FMT("HandleSubThreadNode wait %" PRIu64 "", surfaceParams.GetId());
154         RSSubThreadManager::Instance()->WaitNodeTask(surfaceParams.GetId());
155     }
156     // ConsumeAndUpdateBuffer may set buffer, must be before !GetBuffer()
157     if (!RSBaseRenderUtil::ConsumeAndUpdateBuffer(*surfaceHandlerUiFirst_) ||
158         !surfaceHandlerUiFirst_->GetBuffer()) {
159         RS_LOGE("DrawUIFirstCacheWithDma ConsumeAndUpdateBuffer or GetBuffer return false");
160         return false;
161     }
162     DrawDmaBufferWithGPU(canvas);
163     return true;
164 }
165 
DrawDmaBufferWithGPU(RSPaintFilterCanvas & canvas)166 void RSSurfaceRenderNodeDrawable::DrawDmaBufferWithGPU(RSPaintFilterCanvas& canvas)
167 {
168     auto buffer = surfaceHandlerUiFirst_->GetBuffer();
169     BufferDrawParam param;
170     param.srcRect = {0, 0, buffer->GetWidth(), buffer->GetHeight()};
171     param.dstRect = {0, 0, boundsWidth_, boundsHeight_};
172     param.threadIndex = 0;
173     param.buffer = buffer;
174     param.acquireFence = surfaceHandlerUiFirst_->GetAcquireFence();
175     auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
176     renderEngine->RegisterDeleteBufferListener(surfaceHandlerUiFirst_->GetConsumer());
177     renderEngine->RegisterDeleteBufferListener(*surfaceHandlerUiFirst_);
178     renderEngine->DrawUIFirstCacheWithParams(canvas, param);
179     RSBaseRenderUtil::ReleaseBuffer(*surfaceHandlerUiFirst_);
180 }
181 
ClipRoundRect(Drawing::Canvas & canvas)182 void RSSurfaceRenderNodeDrawable::ClipRoundRect(Drawing::Canvas& canvas)
183 {
184     if (!uifirstRenderParams_) {
185         return;
186     }
187     auto uifirstParams = static_cast<RSSurfaceRenderParams*>(uifirstRenderParams_.get());
188     if (!uifirstParams) {
189         return;
190     }
191     RRect rrect = uifirstParams->GetRRect();
192     canvas.ClipRoundRect(RSPropertiesPainter::RRect2DrawingRRect(rrect), Drawing::ClipOp::INTERSECT, true);
193 }
194 
ClearBufferQueue()195 void RSSurfaceRenderNodeDrawable::ClearBufferQueue()
196 {
197     if (surface_ != nullptr) {
198         surface_->ClearBuffer();
199         surface_ = nullptr;
200     }
201     auto consumer = surfaceHandlerUiFirst_->GetConsumer();
202     if (consumer != nullptr) {
203         consumer->GoBackground();
204         surfaceHandlerUiFirst_->SetConsumer(nullptr);
205     }
206     surfaceHandlerUiFirst_->ResetBufferAvailableCount();
207     surfaceHandlerUiFirst_->CleanCache();
208     surfaceCreated_ = false;
209 }
210 } // namespace OHOS::Rosen::DrawableV2
211