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