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