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