1 /*
2 * Copyright (c) 2022 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 "nweb_surface_adapter.h"
17
18 #include <display_type.h>
19 #include <securec.h>
20 #include <sync_fence.h>
21
22 #include "graphic_common.h"
23 #include "graphic_common_c.h"
24 #include "nweb_log.h"
25 #include "surface_type.h"
26
27 namespace {
28 constexpr int BITS_PER_PIXEL = 4;
29 }
30
31 namespace OHOS::NWeb {
Instance()32 NWebSurfaceAdapter &NWebSurfaceAdapter::Instance()
33 {
34 static NWebSurfaceAdapter surfaceAdapter;
35 return surfaceAdapter;
36 }
37
GetCreateInfo(sptr<Surface> surface,const NWebInitArgs & initArgs,uint32_t width,uint32_t height,bool incognitoMode)38 NWebCreateInfo NWebSurfaceAdapter::GetCreateInfo(sptr<Surface> surface,
39 const NWebInitArgs &initArgs,
40 uint32_t width,
41 uint32_t height,
42 bool incognitoMode)
43 {
44 NWebCreateInfo createInfo = {
45 .init_args = initArgs,
46 .producer_surface = reinterpret_cast<void *>(&surface),
47 };
48 if (surface == nullptr) {
49 return createInfo;
50 }
51 GetSize(surface, createInfo, width, height);
52 GetRenderInterface(surface, createInfo);
53 GetIncognitoMode(createInfo, incognitoMode);
54 return createInfo;
55 }
56
GetSize(sptr<Surface> surface,NWebCreateInfo & createInfo,uint32_t width,uint32_t height) const57 void NWebSurfaceAdapter::GetSize(sptr<Surface> surface,
58 NWebCreateInfo &createInfo,
59 uint32_t width,
60 uint32_t height) const
61 {
62 if (surface == nullptr) {
63 return;
64 }
65 createInfo.width = (width == 0) ? (uint32_t)surface->GetDefaultWidth() : width;
66 createInfo.height = (height == 0) ? (uint32_t)surface->GetDefaultHeight() : height;
67 }
68
GetRenderInterface(sptr<Surface> surface,NWebCreateInfo & createInfo)69 void NWebSurfaceAdapter::GetRenderInterface(sptr<Surface> surface, NWebCreateInfo &createInfo)
70 {
71 wptr<Surface> surfaceWeak(surface);
72 createInfo.output_render_frame = [surfaceWeak, this] (const char *buffer, uint32_t width, uint32_t height) -> bool {
73 sptr<Surface> surface = surfaceWeak.promote();
74 if (surface == nullptr) {
75 WVLOG_E("surface is nullptr or has expired");
76 return false;
77 }
78
79 sptr<SurfaceBuffer> surfaceBuffer = this->RequestBuffer(surface, width, height);
80 if (surfaceBuffer == nullptr) {
81 return false;
82 }
83
84 if (!this->CopyFrame(surfaceBuffer, buffer, width, height)) {
85 surface->CancelBuffer(surfaceBuffer);
86 return false;
87 }
88
89 return this->FlushBuffer(surface, surfaceBuffer, width, height);
90 };
91 }
92
RequestBuffer(sptr<Surface> surface,uint32_t width,uint32_t height)93 sptr<SurfaceBuffer> NWebSurfaceAdapter::RequestBuffer(sptr<Surface> surface, uint32_t width, uint32_t height)
94 {
95 if (surface == nullptr) {
96 return nullptr;
97 }
98
99 BufferRequestConfig config = {
100 .width = width,
101 .height = height,
102 .strideAlignment = sizeof(void *),
103 .format = PIXEL_FMT_RGBA_8888,
104 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
105 .timeout = 0,
106 };
107
108 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
109 int32_t releaseFence = -1;
110 SurfaceError ret = surface->RequestBuffer(surfaceBuffer, releaseFence, config);
111 if (ret != SURFACE_ERROR_OK) {
112 WVLOG_E("fail to request buffer from surface, errorcode=%{public}d", ret);
113 return nullptr;
114 }
115
116 sptr<SyncFence> tempFence = new (std::nothrow) SyncFence(releaseFence);
117 if (tempFence == nullptr) {
118 WVLOG_E("new tempFence failed");
119 return nullptr;
120 }
121 tempFence->Wait(100); // 100 ms
122
123 return surfaceBuffer;
124 }
125
CopyFrame(sptr<SurfaceBuffer> surfaceBuffer,const char * src,uint32_t width,uint32_t height)126 bool NWebSurfaceAdapter::CopyFrame(
127 sptr<SurfaceBuffer> surfaceBuffer, const char *src, uint32_t width, uint32_t height)
128 {
129 if (surfaceBuffer == nullptr) {
130 return false;
131 }
132
133 char *dst = reinterpret_cast<char *>(surfaceBuffer->GetVirAddr());
134 if (dst == nullptr) {
135 WVLOG_E("fail to get buffer addr");
136 return false;
137 }
138
139 uint32_t srcStride = width * BITS_PER_PIXEL;
140 uint32_t dstStride = (uint32_t)surfaceBuffer->GetStride();
141 uint32_t copiedSize = 0;
142
143 for (uint32_t currHeight = 0; currHeight < height; ++currHeight) {
144 if (copiedSize + dstStride > surfaceBuffer->GetSize()) {
145 WVLOG_E("copy size overflow, drop this frame(%{public}u*%{public}u)", width, height);
146 return false;
147 }
148 errno_t ret = memcpy_s(dst, static_cast<size_t>(srcStride), src, static_cast<size_t>(srcStride));
149 if (ret != EOK) {
150 WVLOG_E("memcpy_s failed");
151 return false;
152 }
153 src += srcStride;
154 dst += dstStride;
155 copiedSize += dstStride;
156 }
157
158 return true;
159 }
160
FlushBuffer(sptr<Surface> surface,sptr<SurfaceBuffer> surfaceBuffer,uint32_t width,uint32_t height)161 bool NWebSurfaceAdapter::FlushBuffer(
162 sptr<Surface> surface, sptr<SurfaceBuffer> surfaceBuffer, uint32_t width, uint32_t height)
163 {
164 if (surface == nullptr) {
165 return false;
166 }
167
168 BufferFlushConfig flushConfig = {
169 .damage = {
170 .w = width,
171 .h = height,
172 },
173 .timestamp = 0,
174 };
175
176 SurfaceError ret = surface->FlushBuffer(surfaceBuffer, -1, flushConfig);
177 if (ret != SURFACE_ERROR_OK) {
178 WVLOG_E("FAIL flush nweb render frame, ret=%{public}d", ret);
179 return false;
180 }
181
182 return true;
183 }
184
GetIncognitoMode(NWebCreateInfo & createInfo,bool incognitoMode)185 void NWebSurfaceAdapter::GetIncognitoMode(NWebCreateInfo &createInfo, bool incognitoMode)
186 {
187 createInfo.incognito_mode = incognitoMode;
188 }
189 } // namespace OHOS::NWeb
190