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