1 /*
2 * Copyright (c) 2021 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 #define GL_GLEXT_PROTOTYPES
17 #define EGL_EGLEXT_PROTOTYPES
18
19 #include "surface_image.h"
20
21 #include "securec.h"
22 #include "sandbox_utils.h"
23 #include "surface_utils.h"
24
25 #include <cinttypes>
26 #include <atomic>
27 #include "metadata_helper.h"
28 #include <sync_fence.h>
29 #include <unistd.h>
30 #include <window.h>
31
32 #include <EGL/egl.h>
33 #include <EGL/eglext.h>
34 #include <GLES/gl.h>
35 #include <GLES/glext.h>
36
37 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
38
39 namespace OHOS {
40 namespace {
41 // Get a uniqueID in a process
GetProcessUniqueId()42 static int GetProcessUniqueId()
43 {
44 static std::atomic<int> counter { 0 };
45 return counter.fetch_add(1, std::memory_order_relaxed);
46 }
47 }
48
SurfaceImage(uint32_t textureId,uint32_t textureTarget)49 SurfaceImage::SurfaceImage(uint32_t textureId, uint32_t textureTarget)
50 : ConsumerSurface("SurfaceImage-" + std::to_string(GetRealPid()) + "-" + std::to_string(GetProcessUniqueId())),
51 textureId_(textureId),
52 textureTarget_(textureTarget),
53 updateSurfaceImage_(false),
54 eglDisplay_(EGL_NO_DISPLAY),
55 eglContext_(EGL_NO_CONTEXT),
56 currentSurfaceImage_(UINT_MAX),
57 currentSurfaceBuffer_(nullptr),
58 currentTimeStamp_(0)
59 {
60 InitSurfaceImage();
61 }
62
SurfaceImage()63 SurfaceImage::SurfaceImage()
64 : ConsumerSurface("SurfaceImageConsumer-" + std::to_string(GetRealPid()) +
65 "-" + std::to_string(GetProcessUniqueId())),
66 currentSurfaceBuffer_(nullptr),
67 currentTimeStamp_(0)
68 {
69 InitSurfaceImage();
70 }
71
~SurfaceImage()72 SurfaceImage::~SurfaceImage()
73 {
74 for (auto it = imageCacheSeqs_.begin(); it != imageCacheSeqs_.end(); it++) {
75 DestroyEGLImage(it->second.eglImage_);
76 DestroyEGLSync(it->second.eglSync_);
77 }
78 }
79
InitSurfaceImage()80 void SurfaceImage::InitSurfaceImage()
81 {
82 std::string name = "SurfaceImage-" + std::to_string(GetRealPid()) + "-" + std::to_string(GetProcessUniqueId());
83 auto ret = ConsumerSurface::Init();
84 uniqueId_ = GetUniqueId();
85 BLOGI("InitSurfaceImage Init ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
86 surfaceImageName_ = name;
87 }
88
UpdateBasicInfo(const sptr<SurfaceBuffer> & buffer,int64_t timestamp)89 void SurfaceImage::UpdateBasicInfo(const sptr<SurfaceBuffer>& buffer, int64_t timestamp)
90 {
91 currentSurfaceBuffer_ = buffer;
92 currentTimeStamp_ = timestamp;
93 preBufferProperties_ = bufferProperties_;
94 bufferProperties_ = {
95 GetBufferCropRegion(buffer),
96 ConsumerSurface::GetTransform(),
97 buffer->GetWidth(),
98 buffer->GetHeight()
99 };
100 }
101
UpdateSurfaceInfo(sptr<SurfaceBuffer> buffer,const sptr<SyncFence> & acquireFence,int64_t timestamp,const Rect & damage)102 void SurfaceImage::UpdateSurfaceInfo(sptr<SurfaceBuffer> buffer, const sptr<SyncFence> &acquireFence,
103 int64_t timestamp, const Rect& damage)
104 {
105 // release old buffer
106 int releaseFence = -1;
107 auto iter = imageCacheSeqs_.find(currentSurfaceImage_);
108 if (iter != imageCacheSeqs_.end() && iter->second.eglSync_ != EGL_NO_SYNC_KHR) {
109 releaseFence = eglDupNativeFenceFDANDROID(eglDisplay_, iter->second.eglSync_);
110 }
111 // There is no need to close this fd, because in function ReleaseBuffer it will be closed.
112 ReleaseBuffer(currentSurfaceBuffer_, releaseFence);
113
114 currentSurfaceImage_ = buffer->GetSeqNum();
115 UpdateBasicInfo(buffer, timestamp);
116
117 auto utils = SurfaceUtils::GetInstance();
118 utils->ComputeTransformMatrix(currentTransformMatrix_, TRANSFORM_MATRIX_ELE_COUNT,
119 currentSurfaceBuffer_, bufferProperties_.transformType, damage);
120 utils->ComputeTransformMatrixV2(currentTransformMatrixV2_, TRANSFORM_MATRIX_ELE_COUNT,
121 currentSurfaceBuffer_, bufferProperties_.transformType, damage);
122 if (preBufferProperties_ != bufferProperties_) {
123 utils->ComputeBufferMatrix(currentBufferMatrix_, TRANSFORM_MATRIX_ELE_COUNT,
124 currentSurfaceBuffer_, bufferProperties_.transformType, bufferProperties_.crop);
125 }
126
127 // wait on this acquireFence.
128 if (acquireFence != nullptr) {
129 acquireFence->Wait(-1);
130 }
131 }
132
GetBufferCropRegion(const sptr<OHOS::SurfaceBuffer> & buffer)133 Rect SurfaceImage::GetBufferCropRegion(const sptr<OHOS::SurfaceBuffer>& buffer)
134 {
135 BufferHandleMetaRegion cropRegion{0, 0, 0, 0};
136
137 if (MetadataHelper::GetCropRectMetadata(buffer, cropRegion) == GSERROR_OK) {
138 BLOGD("GetCropRectMetadata success,"
139 "left: %{public}d, top: %{public}d, width: %{public}d, height: %{public}d",
140 cropRegion.left, cropRegion.top, cropRegion.width, cropRegion.height);
141 return {cropRegion.left, cropRegion.top, cropRegion.width, cropRegion.height};
142 }
143
144 return {0, 0, buffer->GetWidth(), buffer->GetHeight()};
145 }
146
UpdateSurfaceImage()147 SurfaceError SurfaceImage::UpdateSurfaceImage()
148 {
149 std::lock_guard<std::mutex> lockGuard(opMutex_);
150
151 // validate egl state
152 SurfaceError ret = ValidateEglState();
153 if (ret != SURFACE_ERROR_OK) {
154 return ret;
155 }
156
157 // acquire buffer
158 sptr<SurfaceBuffer> buffer = nullptr;
159 sptr<SyncFence> acquireFence = SyncFence::InvalidFence();
160 int64_t timestamp = 0;
161 Rect damage = {0, 0, 0, 0};
162 if (!dropFrameMode_) {
163 ret = AcquireBuffer(buffer, acquireFence, timestamp, damage);
164 if (ret != SURFACE_ERROR_OK) {
165 return ret;
166 }
167 } else {
168 AcquireBufferReturnValue returnValue;
169 ret = AcquireBuffer(returnValue, INT64_MAX, true);
170 if (ret != SURFACE_ERROR_OK) {
171 BLOGE("AcquireBuffer falied: %{public}d, uniqueId: %{public}" PRIu64, ret, uniqueId_);
172 return ret;
173 }
174 buffer = returnValue.buffer;
175 acquireFence = returnValue.fence;
176 timestamp = returnValue.timestamp;
177 if (returnValue.damages.size() != 0) {
178 damage = returnValue.damages.at(0);
179 }
180 }
181
182 ret = UpdateEGLImageAndTexture(buffer);
183 if (ret != SURFACE_ERROR_OK) {
184 ReleaseBuffer(buffer, -1);
185 return ret;
186 }
187
188 UpdateSurfaceInfo(buffer, acquireFence, timestamp, damage);
189 return SURFACE_ERROR_OK;
190 }
191
AttachContext(uint32_t textureId)192 SurfaceError SurfaceImage::AttachContext(uint32_t textureId)
193 {
194 std::lock_guard<std::mutex> lockGuard(opMutex_);
195 // validate egl state
196 SurfaceError ret = ValidateEglState();
197 if (ret != SURFACE_ERROR_OK) {
198 return ret;
199 }
200
201 textureId_ = textureId;
202 auto iter = imageCacheSeqs_.find(currentSurfaceImage_);
203 if (iter != imageCacheSeqs_.end()) {
204 glBindTexture(textureTarget_, textureId);
205 GLenum error = glGetError();
206 if (error != GL_NO_ERROR) {
207 BLOGE("glBindTexture failed, textureTarget:%{public}d, textureId_:%{public}d, error:%{public}d,"
208 "uniqueId: %{public}" PRIu64 ".", textureTarget_, textureId_, error, uniqueId_);
209 return SURFACE_ERROR_EGL_API_FAILED;
210 }
211 glEGLImageTargetTexture2DOES(textureTarget_, static_cast<GLeglImageOES>(iter->second.eglImage_));
212 error = glGetError();
213 if (error != GL_NO_ERROR) {
214 BLOGE("glEGLImageTargetTexture2DOES failed, textureTarget:%{public}d, error:%{public}d"
215 "uniqueId: %{public}" PRIu64 ".", textureTarget_, error, uniqueId_);
216 return SURFACE_ERROR_EGL_API_FAILED;
217 }
218 }
219
220 // If there is no EGLImage, we cannot simply return an error.
221 // Developers can call OH_NativeImage_UpdateSurfaceImage later to achieve their purpose.
222 return SURFACE_ERROR_OK;
223 }
224
DetachContext()225 SurfaceError SurfaceImage::DetachContext()
226 {
227 std::lock_guard<std::mutex> lockGuard(opMutex_);
228 // validate egl state
229 SurfaceError ret = ValidateEglState();
230 if (ret != SURFACE_ERROR_OK) {
231 return ret;
232 }
233
234 textureId_ = 0;
235 glBindTexture(textureTarget_, 0);
236 GLenum error = glGetError();
237 if (error != GL_NO_ERROR) {
238 BLOGE("glBindTexture failed, textureTarget:%{public}d, textureId:%{public}d, error:%{public}d"
239 "uniqueId: %{public}" PRIu64 ".", textureTarget_, textureId_, error, uniqueId_);
240 return SURFACE_ERROR_EGL_API_FAILED;
241 }
242 return SURFACE_ERROR_OK;
243 }
244
GetTimeStamp()245 int64_t SurfaceImage::GetTimeStamp()
246 {
247 std::lock_guard<std::mutex> lockGuard(opMutex_);
248 return currentTimeStamp_;
249 }
250
GetTransformMatrix(float matrix[TRANSFORM_MATRIX_ELE_COUNT])251 SurfaceError SurfaceImage::GetTransformMatrix(float matrix[TRANSFORM_MATRIX_ELE_COUNT])
252 {
253 std::lock_guard<std::mutex> lockGuard(opMutex_);
254 auto ret = memcpy_s(matrix, sizeof(float) * TRANSFORM_MATRIX_ELE_COUNT,
255 currentTransformMatrix_, sizeof(currentTransformMatrix_));
256 if (ret != EOK) {
257 BLOGE("memcpy_s failed ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
258 return SURFACE_ERROR_UNKOWN;
259 }
260 return SURFACE_ERROR_OK;
261 }
262
GetTransformMatrixV2(float matrix[TRANSFORM_MATRIX_ELE_COUNT])263 SurfaceError SurfaceImage::GetTransformMatrixV2(float matrix[TRANSFORM_MATRIX_ELE_COUNT])
264 {
265 std::lock_guard<std::mutex> lockGuard(opMutex_);
266 auto ret = memcpy_s(matrix, sizeof(float) * TRANSFORM_MATRIX_ELE_COUNT,
267 currentTransformMatrixV2_, sizeof(currentTransformMatrixV2_));
268 if (ret != EOK) {
269 BLOGE("memcpy_s failed ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
270 return SURFACE_ERROR_UNKOWN;
271 }
272 return SURFACE_ERROR_OK;
273 }
274
GetBufferMatrix(float matrix[TRANSFORM_MATRIX_ELE_COUNT])275 SurfaceError SurfaceImage::GetBufferMatrix(float matrix[TRANSFORM_MATRIX_ELE_COUNT])
276 {
277 std::lock_guard<std::mutex> lockGuard(opMutex_);
278 auto ret = memcpy_s(matrix, sizeof(float) * TRANSFORM_MATRIX_ELE_COUNT,
279 currentBufferMatrix_, sizeof(currentBufferMatrix_));
280 if (ret != EOK) {
281 BLOGE("memcpy_s failed ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
282 return SURFACE_ERROR_MEM_OPERATION_ERROR;
283 }
284 return SURFACE_ERROR_OK;
285 }
286
ValidateEglState()287 SurfaceError SurfaceImage::ValidateEglState()
288 {
289 EGLDisplay disp = eglGetCurrentDisplay();
290 EGLContext context = eglGetCurrentContext();
291
292 if ((eglDisplay_ != disp && eglDisplay_ != EGL_NO_DISPLAY) || (disp == EGL_NO_DISPLAY)) {
293 BLOGE("EGLDisplay is invalid, errno : 0x%{public}x, uniqueId: %{public}" PRIu64 ".",
294 eglGetError(), uniqueId_);
295 return SURFACE_ERROR_EGL_STATE_UNKONW;
296 }
297 if ((eglContext_ != context && eglContext_ != EGL_NO_CONTEXT) || (context == EGL_NO_CONTEXT)) {
298 BLOGE("EGLContext is invalid, errno : 0x%{public}x, uniqueId: %{public}" PRIu64 ".",
299 eglGetError(), uniqueId_);
300 return SURFACE_ERROR_EGL_STATE_UNKONW;
301 }
302
303 eglDisplay_ = disp;
304 eglContext_ = context;
305 return SURFACE_ERROR_OK;
306 }
307
CreateEGLImage(EGLDisplay disp,const sptr<SurfaceBuffer> & buffer)308 EGLImageKHR SurfaceImage::CreateEGLImage(EGLDisplay disp, const sptr<SurfaceBuffer>& buffer)
309 {
310 sptr<SurfaceBuffer> bufferImpl = buffer;
311 NativeWindowBuffer* nBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&bufferImpl);
312 EGLint attrs[] = {
313 EGL_IMAGE_PRESERVED,
314 EGL_TRUE,
315 EGL_NONE,
316 };
317
318 EGLImageKHR img = eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, nBuffer, attrs);
319 if (img == EGL_NO_IMAGE_KHR) {
320 EGLint error = eglGetError();
321 BLOGE("failed, error %{public}d, uniqueId: %{public}" PRIu64 ".", error, uniqueId_);
322 eglTerminate(disp);
323 }
324 DestroyNativeWindowBuffer(nBuffer);
325 return img;
326 }
327
CheckImageCacheNeedClean(uint32_t seqNum)328 void SurfaceImage::CheckImageCacheNeedClean(uint32_t seqNum)
329 {
330 for (auto it = imageCacheSeqs_.begin(); it != imageCacheSeqs_.end();) {
331 bool result = true;
332 if (seqNum == it->first) {
333 it++;
334 continue;
335 }
336 if (IsSurfaceBufferInCache(it->first, result) == SURFACE_ERROR_OK && !result) {
337 DestroyEGLImage(it->second.eglImage_);
338 DestroyEGLSync(it->second.eglSync_);
339 it = imageCacheSeqs_.erase(it);
340 } else {
341 it++;
342 }
343 }
344 }
345
DestroyEGLImage(EGLImageKHR & eglImage)346 void SurfaceImage::DestroyEGLImage(EGLImageKHR &eglImage)
347 {
348 if (eglImage != EGL_NO_IMAGE_KHR) {
349 eglDestroyImageKHR(eglDisplay_, eglImage);
350 eglImage = EGL_NO_IMAGE_KHR;
351 }
352 }
353
DestroyEGLSync(EGLSyncKHR & eglSync)354 void SurfaceImage::DestroyEGLSync(EGLSyncKHR &eglSync)
355 {
356 if (eglSync != EGL_NO_SYNC_KHR) {
357 eglDestroySyncKHR(eglDisplay_, eglSync);
358 eglSync = EGL_NO_SYNC_KHR;
359 }
360 }
361
DestroyEGLImageBySeq(uint32_t seqNum)362 void SurfaceImage::DestroyEGLImageBySeq(uint32_t seqNum)
363 {
364 auto iter = imageCacheSeqs_.find(seqNum);
365 if (iter != imageCacheSeqs_.end()) {
366 DestroyEGLImage(iter->second.eglImage_);
367 imageCacheSeqs_.erase(seqNum);
368 }
369 }
370
NewBufferDestroyEGLImage(bool isNewBuffer,uint32_t seqNum)371 void SurfaceImage::NewBufferDestroyEGLImage(bool isNewBuffer, uint32_t seqNum)
372 {
373 if (isNewBuffer) {
374 DestroyEGLImageBySeq(seqNum);
375 }
376 }
377
UpdateEGLImageAndTexture(const sptr<SurfaceBuffer> & buffer)378 SurfaceError SurfaceImage::UpdateEGLImageAndTexture(const sptr<SurfaceBuffer>& buffer)
379 {
380 bool isNewBuffer = false;
381 // private function, buffer is always valid.
382 uint32_t seqNum = buffer->GetSeqNum();
383 // If there was no eglImage binding to this buffer, we create a new one.
384 if (imageCacheSeqs_.find(seqNum) == imageCacheSeqs_.end()) {
385 isNewBuffer = true;
386 EGLImageKHR eglImage = CreateEGLImage(eglDisplay_, buffer);
387 if (eglImage == EGL_NO_IMAGE_KHR) {
388 return SURFACE_ERROR_EGL_API_FAILED;
389 }
390 imageCacheSeqs_[seqNum].eglImage_ = eglImage;
391 }
392
393 auto &image = imageCacheSeqs_[seqNum];
394 glBindTexture(textureTarget_, textureId_);
395 GLenum error = glGetError();
396 if (error != GL_NO_ERROR) {
397 NewBufferDestroyEGLImage(isNewBuffer, seqNum);
398 BLOGE("glBindTexture failed, textureTarget:%{public}d, textureId_:%{public}d, error:%{public}d"
399 "uniqueId: %{public}" PRIu64 ".", textureTarget_, textureId_, error, uniqueId_);
400 return SURFACE_ERROR_EGL_API_FAILED;
401 }
402 glEGLImageTargetTexture2DOES(textureTarget_, static_cast<GLeglImageOES>(image.eglImage_));
403 error = glGetError();
404 if (error != GL_NO_ERROR) {
405 NewBufferDestroyEGLImage(isNewBuffer, seqNum);
406 BLOGE("glEGLImageTargetTexture2DOES failed, textureTarget:%{public}d, error:%{public}d"
407 "uniqueId: %{public}" PRIu64 ".", textureTarget_, error, uniqueId_);
408 return SURFACE_ERROR_EGL_API_FAILED;
409 }
410
411 // Create fence object for current image
412 auto iter = imageCacheSeqs_.find(currentSurfaceImage_);
413 if (iter != imageCacheSeqs_.end()) {
414 auto ¤tImage = iter->second;
415 auto preSync = currentImage.eglSync_;
416 if (preSync != EGL_NO_SYNC_KHR) {
417 eglDestroySyncKHR(eglDisplay_, preSync);
418 }
419 currentImage.eglSync_ = eglCreateSyncKHR(eglDisplay_, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
420 glFlush();
421 }
422
423 if (isNewBuffer) {
424 CheckImageCacheNeedClean(seqNum);
425 }
426 return SURFACE_ERROR_OK;
427 }
428
SetOnBufferAvailableListener(void * context,OnBufferAvailableListener listener)429 SurfaceError SurfaceImage::SetOnBufferAvailableListener(void *context, OnBufferAvailableListener listener)
430 {
431 std::lock_guard<std::mutex> lockGuard(opMutex_);
432 if (listener == nullptr) {
433 BLOGE("listener is nullptr, uniqueId: %{public}" PRIu64 ".", uniqueId_);
434 return SURFACE_ERROR_INVALID_PARAM;
435 }
436
437 listener_ = listener;
438 context_ = context;
439 return SURFACE_ERROR_OK;
440 }
441
UnsetOnBufferAvailableListener()442 SurfaceError SurfaceImage::UnsetOnBufferAvailableListener()
443 {
444 std::lock_guard<std::mutex> lockGuard(opMutex_);
445 listener_ = nullptr;
446 context_ = nullptr;
447 return SURFACE_ERROR_OK;
448 }
449
~SurfaceImageListener()450 SurfaceImageListener::~SurfaceImageListener()
451 {
452 BLOGE("~SurfaceImageListener");
453 surfaceImage_ = nullptr;
454 }
455
OnBufferAvailable()456 void SurfaceImageListener::OnBufferAvailable()
457 {
458 BLOGD("enter OnBufferAvailable");
459 auto surfaceImage = surfaceImage_.promote();
460 if (surfaceImage == nullptr) {
461 BLOGE("surfaceImage promote failed");
462 return;
463 }
464
465 // check here maybe a messagequeue, flag instead now
466 surfaceImage->OnUpdateBufferAvailableState(true);
467 if (surfaceImage->listener_ != nullptr) {
468 surfaceImage->listener_(surfaceImage->context_);
469 }
470 }
471
AcquireNativeWindowBuffer(OHNativeWindowBuffer ** nativeWindowBuffer,int32_t * fenceFd)472 SurfaceError SurfaceImage::AcquireNativeWindowBuffer(OHNativeWindowBuffer** nativeWindowBuffer, int32_t* fenceFd)
473 {
474 if (nativeWindowBuffer == nullptr || fenceFd == nullptr) {
475 return SURFACE_ERROR_INVALID_PARAM;
476 }
477 std::lock_guard<std::mutex> lockGuard(opMutex_);
478 sptr<SurfaceBuffer> buffer = nullptr;
479 sptr<SyncFence> acquireFence = SyncFence::InvalidFence();
480 int64_t timestamp;
481 Rect damage;
482 SurfaceError ret = AcquireBuffer(buffer, acquireFence, timestamp, damage);
483 if (ret != SURFACE_ERROR_OK) {
484 BLOGE("AcquireBuffer failed: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
485 return ret;
486 }
487
488 UpdateBasicInfo(buffer, timestamp);
489
490 auto utils = SurfaceUtils::GetInstance();
491 utils->ComputeTransformMatrixV2(currentTransformMatrixV2_, TRANSFORM_MATRIX_ELE_COUNT,
492 currentSurfaceBuffer_, bufferProperties_.transformType, damage);
493 if (bufferProperties_ != preBufferProperties_) {
494 utils->ComputeBufferMatrix(currentBufferMatrix_, TRANSFORM_MATRIX_ELE_COUNT,
495 currentSurfaceBuffer_, bufferProperties_.transformType, bufferProperties_.crop);
496 }
497
498 *fenceFd = acquireFence->Dup();
499 OHNativeWindowBuffer *nwBuffer = new(std::nothrow) OHNativeWindowBuffer();
500 if (nwBuffer == nullptr) {
501 return SURFACE_ERROR_NOMEM;
502 }
503 nwBuffer->sfbuffer = buffer;
504 NativeObjectReference(nwBuffer);
505 *nativeWindowBuffer = nwBuffer;
506
507 return SURFACE_ERROR_OK;
508 }
509
ReleaseNativeWindowBuffer(OHNativeWindowBuffer * nativeWindowBuffer,int32_t fenceFd)510 SurfaceError SurfaceImage::ReleaseNativeWindowBuffer(OHNativeWindowBuffer* nativeWindowBuffer, int32_t fenceFd)
511 {
512 if (nativeWindowBuffer == nullptr) {
513 return SURFACE_ERROR_INVALID_PARAM;
514 }
515 std::lock_guard<std::mutex> lockGuard(opMutex_);
516 // There is no need to close this fd, because in function ReleaseBuffer it will be closed.
517 SurfaceError ret = ReleaseBuffer(nativeWindowBuffer->sfbuffer, fenceFd);
518 if (ret != SURFACE_ERROR_OK) {
519 BLOGE("ReleaseBuffer failed: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
520 return ret;
521 }
522 NativeObjectUnreference(nativeWindowBuffer);
523 return SURFACE_ERROR_OK;
524 }
525
SetDefaultUsage(uint64_t usage)526 SurfaceError SurfaceImage::SetDefaultUsage(uint64_t usage)
527 {
528 SurfaceError ret = ConsumerSurface::SetDefaultUsage(usage);
529 if (ret != SURFACE_ERROR_OK) {
530 BLOGE("SetDefaultUsage failed: %{public}d, uniqueId: %{public}" PRIu64 ", usage: %{public}" PRIu64 ".", ret,
531 uniqueId_, usage);
532 }
533 return ret;
534 }
535
SetDefaultSize(int32_t width,int32_t height)536 SurfaceError SurfaceImage::SetDefaultSize(int32_t width, int32_t height)
537 {
538 SurfaceError ret = SetDefaultWidthAndHeight(width, height);
539 if (ret != SURFACE_ERROR_OK) {
540 BLOGE("SetDefaultWidthAndHeight failed: %{public}d, uniqueId: %{public}" PRIu64 ", width: %{public}d, "
541 "height: %{public}d", ret, uniqueId_, width, height);
542 }
543 return ret;
544 }
545
SetDropBufferSwitch(bool isOpen)546 SurfaceError SurfaceImage::SetDropBufferSwitch(bool isOpen)
547 {
548 std::lock_guard<std::mutex> lockGuard(opMutex_);
549 BLOGI("SetDropBufferSwitch switch: %{public}d", isOpen);
550 dropFrameMode_ = isOpen;
551 return SURFACE_ERROR_OK;
552 }
553 } // namespace OHOS
554