1 /*
2 * Copyright (c) 2021-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 "native_window.h"
17
18 #include <cstdint>
19 #include <map>
20 #include <cinttypes>
21 #include "buffer_log.h"
22 #include "window.h"
23 #include "surface_type.h"
24 #include "sync_fence.h"
25
26 #ifndef WEAK_ALIAS
27 #define WEAK_ALIAS(old, new) \
28 extern __typeof(old) new __attribute__((__weak__, __alias__(#old)))
29 #endif
30
31 using namespace OHOS;
32
CreateNativeWindowFromSurface(void * pSurface)33 OHNativeWindow* CreateNativeWindowFromSurface(void* pSurface)
34 {
35 if (pSurface == nullptr) {
36 BLOGE("parameter error, please check input parameter");
37 return nullptr;
38 }
39 OHNativeWindow* nativeWindow = new OHNativeWindow();
40 nativeWindow->surface =
41 *reinterpret_cast<OHOS::sptr<OHOS::Surface> *>(pSurface);
42 BLOGE_CHECK_AND_RETURN_RET(nativeWindow->surface != nullptr, nullptr, "window surface is null");
43 nativeWindow->config.width = nativeWindow->surface->GetDefaultWidth();
44 nativeWindow->config.height = nativeWindow->surface->GetDefaultHeight();
45 nativeWindow->config.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA;
46 nativeWindow->config.format = GRAPHIC_PIXEL_FMT_RGBA_8888;
47 nativeWindow->config.strideAlignment = 8; // default stride is 8
48 nativeWindow->config.timeout = 3000; // default timeout is 3000 ms
49 nativeWindow->config.colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
50 nativeWindow->config.transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
51
52 NativeObjectReference(nativeWindow);
53 nativeWindow->surface->SetWptrNativeWindowToPSurface(nativeWindow);
54 return nativeWindow;
55 }
56
DestoryNativeWindow(OHNativeWindow * window)57 void DestoryNativeWindow(OHNativeWindow *window)
58 {
59 if (window == nullptr) {
60 BLOGE("parameter error, please check input parameter");
61 return;
62 }
63 // unreference nativewindow object
64 NativeObjectUnreference(window);
65 }
66
CreateNativeWindowBufferFromSurfaceBuffer(void * pSurfaceBuffer)67 OHNativeWindowBuffer* CreateNativeWindowBufferFromSurfaceBuffer(void* pSurfaceBuffer)
68 {
69 if (pSurfaceBuffer == nullptr) {
70 BLOGE("parameter error, please check input parameter");
71 return nullptr;
72 }
73 OHNativeWindowBuffer *nwBuffer = new OHNativeWindowBuffer();
74 nwBuffer->sfbuffer = *reinterpret_cast<OHOS::sptr<OHOS::SurfaceBuffer> *>(pSurfaceBuffer);
75 NativeObjectReference(nwBuffer);
76 return nwBuffer;
77 }
78
CreateNativeWindowBufferFromNativeBuffer(OH_NativeBuffer * nativeBuffer)79 OHNativeWindowBuffer* CreateNativeWindowBufferFromNativeBuffer(OH_NativeBuffer* nativeBuffer)
80 {
81 if (nativeBuffer == nullptr) {
82 BLOGE("parameter error, please check input parameter");
83 return nullptr;
84 }
85 OHNativeWindowBuffer *nwBuffer = new OHNativeWindowBuffer();
86 OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer(reinterpret_cast<OHOS::SurfaceBuffer *>(nativeBuffer));
87 nwBuffer->sfbuffer = surfaceBuffer;
88
89 NativeObjectReference(nwBuffer);
90 return nwBuffer;
91 }
92
DestroyNativeWindowBuffer(OHNativeWindowBuffer * buffer)93 void DestroyNativeWindowBuffer(OHNativeWindowBuffer* buffer)
94 {
95 if (buffer == nullptr) {
96 BLOGE("parameter error, please check input parameter");
97 return;
98 }
99 NativeObjectUnreference(buffer);
100 }
101
NativeWindowRequestBuffer(OHNativeWindow * window,OHNativeWindowBuffer ** buffer,int * fenceFd)102 int32_t NativeWindowRequestBuffer(OHNativeWindow *window,
103 OHNativeWindowBuffer **buffer, int *fenceFd)
104 {
105 if (window == nullptr || buffer == nullptr || fenceFd == nullptr) {
106 BLOGE("parameter error, please check input parameter");
107 return OHOS::GSERROR_INVALID_ARGUMENTS;
108 }
109 OHOS::sptr<OHOS::SurfaceBuffer> sfbuffer;
110 OHOS::sptr<OHOS::SyncFence> releaseFence = OHOS::SyncFence::INVALID_FENCE;
111 BLOGE_CHECK_AND_RETURN_RET(window->surface != nullptr, SURFACE_ERROR_ERROR, "window surface is null");
112 int32_t ret = window->surface->RequestBuffer(sfbuffer, releaseFence, window->config);
113 if (ret != OHOS::GSError::GSERROR_OK || sfbuffer == nullptr) {
114 BLOGE("API failed, please check RequestBuffer function ret:%{public}d, Queue Id:%{public}" PRIu64,
115 ret, window->surface->GetUniqueId());
116 return OHOS::GSERROR_NO_BUFFER;
117 }
118 uint32_t seqNum = sfbuffer->GetSeqNum();
119 if (window->bufferCache_.find(seqNum) == window->bufferCache_.end()) {
120 OHNativeWindowBuffer *nwBuffer = new OHNativeWindowBuffer();
121 nwBuffer->sfbuffer = sfbuffer;
122 nwBuffer->uiTimestamp = window->uiTimestamp;
123 *buffer = nwBuffer;
124 // Add to cache
125 NativeObjectReference(nwBuffer);
126 window->bufferCache_[seqNum] = nwBuffer;
127 } else {
128 *buffer = window->bufferCache_[seqNum];
129 (*buffer)->uiTimestamp = window->uiTimestamp;
130 }
131 *fenceFd = releaseFence->Dup();
132 return OHOS::GSERROR_OK;
133 }
134
NativeWindowFlushBuffer(OHNativeWindow * window,OHNativeWindowBuffer * buffer,int fenceFd,struct Region region)135 int32_t NativeWindowFlushBuffer(OHNativeWindow *window, OHNativeWindowBuffer *buffer,
136 int fenceFd, struct Region region)
137 {
138 if (window == nullptr || buffer == nullptr || window->surface == nullptr) {
139 BLOGE("parameter error, please check input parameter");
140 return OHOS::GSERROR_INVALID_ARGUMENTS;
141 }
142
143 OHOS::BufferFlushConfigWithDamages config;
144 if ((region.rectNumber != 0) && (region.rects != nullptr)) {
145 config.damages.reserve(region.rectNumber);
146 for (int32_t i = 0; i < region.rectNumber; i++) {
147 OHOS::Rect damage = {
148 .x = region.rects[i].x,
149 .y = region.rects[i].y,
150 .w = static_cast<int32_t>(region.rects[i].w),
151 .h = static_cast<int32_t>(region.rects[i].h),
152 };
153 config.damages.emplace_back(damage);
154 }
155 config.timestamp = buffer->uiTimestamp;
156 } else {
157 config.damages.reserve(1);
158 OHOS::Rect damage = {
159 .x = 0,
160 .y = 0,
161 .w = window->config.width,
162 .h = window->config.height,
163 };
164 config.damages.emplace_back(damage);
165 config.timestamp = buffer->uiTimestamp;
166 }
167 OHOS::sptr<OHOS::SyncFence> acquireFence = new OHOS::SyncFence(fenceFd);
168 window->surface->FlushBuffer(buffer->sfbuffer, acquireFence, config);
169
170 for (auto &[seqNum, buf] : window->bufferCache_) {
171 if (buf == buffer) {
172 window->lastBufferSeqNum = seqNum;
173 break;
174 }
175 }
176
177 return OHOS::GSERROR_OK;
178 }
179
GetLastFlushedBuffer(OHNativeWindow * window,OHNativeWindowBuffer ** buffer,int * fenceFd,float matrix[16])180 int32_t GetLastFlushedBuffer(OHNativeWindow *window, OHNativeWindowBuffer **buffer, int *fenceFd, float matrix[16])
181 {
182 if (window == nullptr || buffer == nullptr) {
183 BLOGE("parameter error, please check input parameter");
184 return OHOS::GSERROR_INVALID_ARGUMENTS;
185 }
186 OHNativeWindowBuffer *nwBuffer = new OHNativeWindowBuffer();
187 OHOS::sptr<OHOS::SyncFence> acquireFence = OHOS::SyncFence::INVALID_FENCE;
188 int32_t ret = window->surface->GetLastFlushedBuffer(nwBuffer->sfbuffer, acquireFence, matrix);
189 if (ret != OHOS::GSError::GSERROR_OK || nwBuffer->sfbuffer == nullptr) {
190 BLOGE("GetLastFlushedBuffer fail");
191 return ret;
192 }
193 *buffer = nwBuffer;
194 NativeObjectReference(nwBuffer);
195 *fenceFd = acquireFence->Dup();
196 return OHOS::GSERROR_OK;
197 }
198
NativeWindowCancelBuffer(OHNativeWindow * window,OHNativeWindowBuffer * buffer)199 int32_t NativeWindowCancelBuffer(OHNativeWindow *window, OHNativeWindowBuffer *buffer)
200 {
201 if (window == nullptr || buffer == nullptr) {
202 BLOGE("parameter error, please check input parameter");
203 return OHOS::GSERROR_INVALID_ARGUMENTS;
204 }
205 BLOGE_CHECK_AND_RETURN_RET(window->surface != nullptr, SURFACE_ERROR_ERROR, "window surface is null");
206 window->surface->CancelBuffer(buffer->sfbuffer);
207 return OHOS::GSERROR_OK;
208 }
209
InternalHandleNativeWindowOpt(OHNativeWindow * window,int code,va_list args)210 static int32_t InternalHandleNativeWindowOpt(OHNativeWindow *window, int code, va_list args)
211 {
212 switch (code) {
213 case SET_USAGE: {
214 uint64_t usage = va_arg(args, uint64_t);
215 window->config.usage = usage;
216 break;
217 }
218 case SET_BUFFER_GEOMETRY: {
219 int32_t width = va_arg(args, int32_t);
220 int32_t height = va_arg(args, int32_t);
221 window->config.height = height;
222 window->config.width = width;
223 break;
224 }
225 case SET_FORMAT: {
226 int32_t format = va_arg(args, int32_t);
227 window->config.format = format;
228 break;
229 }
230 case SET_STRIDE: {
231 int32_t stride = va_arg(args, int32_t);
232 window->config.strideAlignment = stride;
233 break;
234 }
235 case SET_TIMEOUT: {
236 int32_t timeout = va_arg(args, int32_t);
237 window->config.timeout = timeout;
238 break;
239 }
240 case SET_COLOR_GAMUT: {
241 int32_t colorGamut = va_arg(args, int32_t);
242 window->config.colorGamut = static_cast<GraphicColorGamut>(colorGamut);
243 break;
244 }
245 case SET_TRANSFORM : {
246 int32_t transform = va_arg(args, int32_t);
247 window->config.transform = static_cast<GraphicTransformType>(transform);
248 break;
249 }
250 case SET_UI_TIMESTAMP : {
251 uint64_t uiTimestamp = va_arg(args, uint64_t);
252 window->uiTimestamp = static_cast<int64_t>(uiTimestamp);
253 break;
254 }
255 case GET_USAGE: {
256 uint64_t *value = va_arg(args, uint64_t*);
257 uint64_t usage = window->config.usage;
258 *value = usage;
259 break;
260 }
261 case GET_BUFFER_GEOMETRY: {
262 int32_t *height = va_arg(args, int32_t*);
263 int32_t *width = va_arg(args, int32_t*);
264 *height = window->config.height;
265 *width = window->config.width;
266 break;
267 }
268 case GET_FORMAT: {
269 int32_t *format = va_arg(args, int32_t*);
270 *format = window->config.format;
271 break;
272 }
273 case GET_STRIDE: {
274 int32_t *stride = va_arg(args, int32_t*);
275 *stride = window->config.strideAlignment;
276 break;
277 }
278 case GET_TIMEOUT : {
279 int32_t *timeout = va_arg(args, int32_t*);
280 *timeout = window->config.timeout;
281 break;
282 }
283 case GET_COLOR_GAMUT: {
284 int32_t *colorGamut = va_arg(args, int32_t*);
285 *colorGamut = static_cast<int32_t>(window->config.colorGamut);
286 break;
287 }
288 case GET_TRANSFORM: {
289 int32_t *transform = va_arg(args, int32_t*);
290 *transform = static_cast<int32_t>(window->config.transform);
291 break;
292 }
293 default:
294 break;
295 }
296 return OHOS::GSERROR_OK;
297 }
298
NativeWindowHandleOpt(OHNativeWindow * window,int code,...)299 int32_t NativeWindowHandleOpt(OHNativeWindow *window, int code, ...)
300 {
301 if (window == nullptr) {
302 BLOGE("parameter error, please check input parameter");
303 return OHOS::GSERROR_INVALID_ARGUMENTS;
304 }
305 va_list args;
306 va_start(args, code);
307 InternalHandleNativeWindowOpt(window, code, args);
308 va_end(args);
309 return OHOS::GSERROR_OK;
310 }
311
GetBufferHandleFromNative(OHNativeWindowBuffer * buffer)312 BufferHandle *GetBufferHandleFromNative(OHNativeWindowBuffer *buffer)
313 {
314 if (buffer == nullptr || buffer->sfbuffer == nullptr) {
315 BLOGE("parameter error, please check input parameter");
316 return nullptr;
317 }
318 return buffer->sfbuffer->GetBufferHandle();
319 }
320
GetNativeObjectMagic(void * obj)321 int32_t GetNativeObjectMagic(void *obj)
322 {
323 if (obj == nullptr) {
324 BLOGE("parameter error, please check input parameter");
325 return OHOS::GSERROR_INVALID_ARGUMENTS;
326 }
327 NativeWindowMagic* nativeWindowMagic = reinterpret_cast<NativeWindowMagic *>(obj);
328 return nativeWindowMagic->magic;
329 }
330
NativeObjectReference(void * obj)331 int32_t NativeObjectReference(void *obj)
332 {
333 if (obj == nullptr) {
334 BLOGE("parameter error, please check input parameter");
335 return OHOS::GSERROR_INVALID_ARGUMENTS;
336 }
337 switch (GetNativeObjectMagic(obj)) {
338 case NATIVE_OBJECT_MAGIC_WINDOW:
339 case NATIVE_OBJECT_MAGIC_WINDOW_BUFFER:
340 break;
341 default:
342 return OHOS::GSERROR_TYPE_ERROR;
343 }
344 OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(obj);
345 ref->IncStrongRef(ref);
346 return OHOS::GSERROR_OK;
347 }
348
NativeObjectUnreference(void * obj)349 int32_t NativeObjectUnreference(void *obj)
350 {
351 if (obj == nullptr) {
352 BLOGE("parameter error, please check input parameter");
353 return OHOS::GSERROR_INVALID_ARGUMENTS;
354 }
355 switch (GetNativeObjectMagic(obj)) {
356 case NATIVE_OBJECT_MAGIC_WINDOW:
357 case NATIVE_OBJECT_MAGIC_WINDOW_BUFFER:
358 break;
359 default:
360 return OHOS::GSERROR_TYPE_ERROR;
361 }
362 OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(obj);
363 ref->DecStrongRef(ref);
364 return OHOS::GSERROR_OK;
365 }
366
NativeWindowSetScalingMode(OHNativeWindow * window,uint32_t sequence,OHScalingMode scalingMode)367 int32_t NativeWindowSetScalingMode(OHNativeWindow *window, uint32_t sequence, OHScalingMode scalingMode)
368 {
369 if (window == nullptr || window->surface == nullptr ||
370 scalingMode < OHScalingMode::OH_SCALING_MODE_FREEZE ||
371 scalingMode > OHScalingMode::OH_SCALING_MODE_NO_SCALE_CROP) {
372 BLOGE("parameter error, please check input parameter");
373 return OHOS::GSERROR_INVALID_ARGUMENTS;
374 }
375 return window->surface->SetScalingMode(sequence, static_cast<ScalingMode>(scalingMode));
376 }
377
NativeWindowSetMetaData(OHNativeWindow * window,uint32_t sequence,int32_t size,const OHHDRMetaData * metaData)378 int32_t NativeWindowSetMetaData(OHNativeWindow *window, uint32_t sequence, int32_t size,
379 const OHHDRMetaData *metaData)
380 {
381 if (window == nullptr || window->surface == nullptr || size <= 0 || metaData == nullptr) {
382 BLOGE("parameter error, please check input parameter");
383 return OHOS::GSERROR_INVALID_ARGUMENTS;
384 }
385
386 std::vector<GraphicHDRMetaData> data(reinterpret_cast<const GraphicHDRMetaData *>(metaData),
387 reinterpret_cast<const GraphicHDRMetaData *>(metaData) + size);
388 return window->surface->SetMetaData(sequence, data);
389 }
390
NativeWindowSetMetaDataSet(OHNativeWindow * window,uint32_t sequence,OHHDRMetadataKey key,int32_t size,const uint8_t * metaData)391 int32_t NativeWindowSetMetaDataSet(OHNativeWindow *window, uint32_t sequence, OHHDRMetadataKey key,
392 int32_t size, const uint8_t *metaData)
393 {
394 if (window == nullptr || window->surface == nullptr ||
395 key < OHHDRMetadataKey::OH_METAKEY_RED_PRIMARY_X || key > OHHDRMetadataKey::OH_METAKEY_HDR_VIVID ||
396 size <= 0 || metaData == nullptr) {
397 BLOGE("parameter error, please check input parameter");
398 return OHOS::GSERROR_INVALID_ARGUMENTS;
399 }
400 std::vector<uint8_t> data(metaData, metaData + size);
401 return window->surface->SetMetaDataSet(sequence, static_cast<GraphicHDRMetadataKey>(key), data);
402 }
403
NativeWindowSetTunnelHandle(OHNativeWindow * window,const OHExtDataHandle * handle)404 int32_t NativeWindowSetTunnelHandle(OHNativeWindow *window, const OHExtDataHandle *handle)
405 {
406 if (window == nullptr || window->surface == nullptr || handle == nullptr) {
407 BLOGE("parameter error, please check input parameter");
408 return OHOS::GSERROR_INVALID_ARGUMENTS;
409 }
410 return window->surface->SetTunnelHandle(reinterpret_cast<const OHOS::GraphicExtDataHandle*>(handle));
411 }
412
NativeWindow()413 NativeWindow::NativeWindow() : NativeWindowMagic(NATIVE_OBJECT_MAGIC_WINDOW), surface(nullptr)
414 {
415 }
416
~NativeWindow()417 NativeWindow::~NativeWindow()
418 {
419 for (auto &[seqNum, buffer] : bufferCache_) {
420 NativeObjectUnreference(buffer);
421 }
422 }
423
~NativeWindowBuffer()424 NativeWindowBuffer::~NativeWindowBuffer()
425 {
426 }
427
NativeWindowBuffer()428 NativeWindowBuffer::NativeWindowBuffer() : NativeWindowMagic(NATIVE_OBJECT_MAGIC_WINDOW_BUFFER), sfbuffer(nullptr)
429 {
430 }
431
432 WEAK_ALIAS(CreateNativeWindowFromSurface, OH_NativeWindow_CreateNativeWindow);
433 WEAK_ALIAS(DestoryNativeWindow, OH_NativeWindow_DestroyNativeWindow);
434 WEAK_ALIAS(CreateNativeWindowBufferFromSurfaceBuffer, OH_NativeWindow_CreateNativeWindowBufferFromSurfaceBuffer);
435 WEAK_ALIAS(CreateNativeWindowBufferFromNativeBuffer, OH_NativeWindow_CreateNativeWindowBufferFromNativeBuffer);
436 WEAK_ALIAS(DestroyNativeWindowBuffer, OH_NativeWindow_DestroyNativeWindowBuffer);
437 WEAK_ALIAS(NativeWindowRequestBuffer, OH_NativeWindow_NativeWindowRequestBuffer);
438 WEAK_ALIAS(NativeWindowFlushBuffer, OH_NativeWindow_NativeWindowFlushBuffer);
439 WEAK_ALIAS(GetLastFlushedBuffer, OH_NativeWindow_GetLastFlushedBuffer);
440 WEAK_ALIAS(NativeWindowCancelBuffer, OH_NativeWindow_NativeWindowAbortBuffer);
441 WEAK_ALIAS(NativeWindowHandleOpt, OH_NativeWindow_NativeWindowHandleOpt);
442 WEAK_ALIAS(GetBufferHandleFromNative, OH_NativeWindow_GetBufferHandleFromNative);
443 WEAK_ALIAS(NativeObjectReference, OH_NativeWindow_NativeObjectReference);
444 WEAK_ALIAS(NativeObjectUnreference, OH_NativeWindow_NativeObjectUnreference);
445 WEAK_ALIAS(GetNativeObjectMagic, OH_NativeWindow_GetNativeObjectMagic);
446 WEAK_ALIAS(NativeWindowSetScalingMode, OH_NativeWindow_NativeWindowSetScalingMode);
447 WEAK_ALIAS(NativeWindowSetMetaData, OH_NativeWindow_NativeWindowSetMetaData);
448 WEAK_ALIAS(NativeWindowSetMetaDataSet, OH_NativeWindow_NativeWindowSetMetaDataSet);
449 WEAK_ALIAS(NativeWindowSetTunnelHandle, OH_NativeWindow_NativeWindowSetTunnelHandle);
450