• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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