1e9297d28Sopenharmony_ci/*
2e9297d28Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3e9297d28Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e9297d28Sopenharmony_ci * you may not use this file except in compliance with the License.
5e9297d28Sopenharmony_ci * You may obtain a copy of the License at
6e9297d28Sopenharmony_ci *
7e9297d28Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e9297d28Sopenharmony_ci *
9e9297d28Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e9297d28Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e9297d28Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e9297d28Sopenharmony_ci * See the License for the specific language governing permissions and
13e9297d28Sopenharmony_ci * limitations under the License.
14e9297d28Sopenharmony_ci */
15e9297d28Sopenharmony_ci
16e9297d28Sopenharmony_ci#define GL_GLEXT_PROTOTYPES
17e9297d28Sopenharmony_ci#define EGL_EGLEXT_PROTOTYPES
18e9297d28Sopenharmony_ci
19e9297d28Sopenharmony_ci#include "surface_image.h"
20e9297d28Sopenharmony_ci
21e9297d28Sopenharmony_ci#include "securec.h"
22e9297d28Sopenharmony_ci#include "sandbox_utils.h"
23e9297d28Sopenharmony_ci#include "surface_utils.h"
24e9297d28Sopenharmony_ci
25e9297d28Sopenharmony_ci#include <cinttypes>
26e9297d28Sopenharmony_ci#include <atomic>
27e9297d28Sopenharmony_ci#include <sync_fence.h>
28e9297d28Sopenharmony_ci#include <unistd.h>
29e9297d28Sopenharmony_ci#include <window.h>
30e9297d28Sopenharmony_ci
31e9297d28Sopenharmony_ci#include <EGL/egl.h>
32e9297d28Sopenharmony_ci#include <EGL/eglext.h>
33e9297d28Sopenharmony_ci#include <GLES/gl.h>
34e9297d28Sopenharmony_ci#include <GLES/glext.h>
35e9297d28Sopenharmony_ci
36e9297d28Sopenharmony_cinamespace OHOS {
37e9297d28Sopenharmony_cinamespace {
38e9297d28Sopenharmony_ci// Get a uniqueID in a process
39e9297d28Sopenharmony_cistatic int GetProcessUniqueId()
40e9297d28Sopenharmony_ci{
41e9297d28Sopenharmony_ci    static std::atomic<int> g_counter { 0 };
42e9297d28Sopenharmony_ci    return g_counter.fetch_add(1, std::memory_order_relaxed);
43e9297d28Sopenharmony_ci}
44e9297d28Sopenharmony_ci}
45e9297d28Sopenharmony_ci
46e9297d28Sopenharmony_ciSurfaceImage::SurfaceImage(uint32_t textureId, uint32_t textureTarget)
47e9297d28Sopenharmony_ci    : ConsumerSurface("SurfaceImage-" + std::to_string(GetRealPid()) + "-" + std::to_string(GetProcessUniqueId())),
48e9297d28Sopenharmony_ci      textureId_(textureId),
49e9297d28Sopenharmony_ci      textureTarget_(textureTarget),
50e9297d28Sopenharmony_ci      updateSurfaceImage_(false),
51e9297d28Sopenharmony_ci      eglDisplay_(EGL_NO_DISPLAY),
52e9297d28Sopenharmony_ci      eglContext_(EGL_NO_CONTEXT),
53e9297d28Sopenharmony_ci      currentSurfaceImage_(UINT_MAX),
54e9297d28Sopenharmony_ci      currentSurfaceBuffer_(nullptr),
55e9297d28Sopenharmony_ci      currentTimeStamp_(0)
56e9297d28Sopenharmony_ci{
57e9297d28Sopenharmony_ci    InitSurfaceImage();
58e9297d28Sopenharmony_ci}
59e9297d28Sopenharmony_ci
60e9297d28Sopenharmony_ciSurfaceImage::SurfaceImage()
61e9297d28Sopenharmony_ci    : ConsumerSurface("SurfaceImageConsumer-" + std::to_string(GetRealPid()) +
62e9297d28Sopenharmony_ci    "-" + std::to_string(GetProcessUniqueId())),
63e9297d28Sopenharmony_ci      currentSurfaceBuffer_(nullptr),
64e9297d28Sopenharmony_ci      currentTimeStamp_(0)
65e9297d28Sopenharmony_ci{
66e9297d28Sopenharmony_ci    InitSurfaceImage();
67e9297d28Sopenharmony_ci}
68e9297d28Sopenharmony_ci
69e9297d28Sopenharmony_ciSurfaceImage::~SurfaceImage()
70e9297d28Sopenharmony_ci{
71e9297d28Sopenharmony_ci    for (auto it = imageCacheSeqs_.begin(); it != imageCacheSeqs_.end(); it++) {
72e9297d28Sopenharmony_ci        DestroyEGLImage(it->second.eglImage_);
73e9297d28Sopenharmony_ci        DestroyEGLSync(it->second.eglSync_);
74e9297d28Sopenharmony_ci    }
75e9297d28Sopenharmony_ci}
76e9297d28Sopenharmony_ci
77e9297d28Sopenharmony_civoid SurfaceImage::InitSurfaceImage()
78e9297d28Sopenharmony_ci{
79e9297d28Sopenharmony_ci    std::string name = "SurfaceImage-" + std::to_string(GetRealPid()) + "-" + std::to_string(GetProcessUniqueId());
80e9297d28Sopenharmony_ci    auto ret = ConsumerSurface::Init();
81e9297d28Sopenharmony_ci    uniqueId_ = GetUniqueId();
82e9297d28Sopenharmony_ci    BLOGI("InitSurfaceImage Init ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
83e9297d28Sopenharmony_ci    surfaceImageName_ = name;
84e9297d28Sopenharmony_ci}
85e9297d28Sopenharmony_ci
86e9297d28Sopenharmony_civoid SurfaceImage::UpdateSurfaceInfo(uint32_t seqNum, sptr<SurfaceBuffer> buffer, const sptr<SyncFence> &acquireFence,
87e9297d28Sopenharmony_ci                                     int64_t timestamp, Rect damage)
88e9297d28Sopenharmony_ci{
89e9297d28Sopenharmony_ci    // release old buffer
90e9297d28Sopenharmony_ci    int releaseFence = -1;
91e9297d28Sopenharmony_ci    auto iter = imageCacheSeqs_.find(currentSurfaceImage_);
92e9297d28Sopenharmony_ci    if (iter != imageCacheSeqs_.end() && iter->second.eglSync_ != EGL_NO_SYNC_KHR) {
93e9297d28Sopenharmony_ci        releaseFence = eglDupNativeFenceFDANDROID(eglDisplay_, iter->second.eglSync_);
94e9297d28Sopenharmony_ci    }
95e9297d28Sopenharmony_ci    // There is no need to close this fd, because in function ReleaseBuffer it will be closed.
96e9297d28Sopenharmony_ci    ReleaseBuffer(currentSurfaceBuffer_, releaseFence);
97e9297d28Sopenharmony_ci
98e9297d28Sopenharmony_ci    currentSurfaceImage_ = seqNum;
99e9297d28Sopenharmony_ci    currentSurfaceBuffer_ = buffer;
100e9297d28Sopenharmony_ci    currentTimeStamp_ = timestamp;
101e9297d28Sopenharmony_ci    currentCrop_ = damage;
102e9297d28Sopenharmony_ci    currentTransformType_ = ConsumerSurface::GetTransform();
103e9297d28Sopenharmony_ci    auto utils = SurfaceUtils::GetInstance();
104e9297d28Sopenharmony_ci    utils->ComputeTransformMatrix(currentTransformMatrix_, TRANSFORM_MATRIX_ELE_COUNT,
105e9297d28Sopenharmony_ci        currentSurfaceBuffer_, currentTransformType_, currentCrop_);
106e9297d28Sopenharmony_ci    utils->ComputeTransformMatrixV2(currentTransformMatrixV2_, TRANSFORM_MATRIX_ELE_COUNT,
107e9297d28Sopenharmony_ci        currentSurfaceBuffer_, currentTransformType_, currentCrop_);
108e9297d28Sopenharmony_ci
109e9297d28Sopenharmony_ci    // wait on this acquireFence.
110e9297d28Sopenharmony_ci    if (acquireFence != nullptr) {
111e9297d28Sopenharmony_ci        acquireFence->Wait(-1);
112e9297d28Sopenharmony_ci    }
113e9297d28Sopenharmony_ci}
114e9297d28Sopenharmony_ci
115e9297d28Sopenharmony_ciSurfaceError SurfaceImage::UpdateSurfaceImage()
116e9297d28Sopenharmony_ci{
117e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
118e9297d28Sopenharmony_ci
119e9297d28Sopenharmony_ci    // validate egl state
120e9297d28Sopenharmony_ci    SurfaceError ret = ValidateEglState();
121e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
122e9297d28Sopenharmony_ci        return ret;
123e9297d28Sopenharmony_ci    }
124e9297d28Sopenharmony_ci
125e9297d28Sopenharmony_ci    // acquire buffer
126e9297d28Sopenharmony_ci    sptr<SurfaceBuffer> buffer = nullptr;
127e9297d28Sopenharmony_ci    sptr<SyncFence> acquireFence = SyncFence::InvalidFence();
128e9297d28Sopenharmony_ci    int64_t timestamp = 0;
129e9297d28Sopenharmony_ci    Rect damage;
130e9297d28Sopenharmony_ci    ret = AcquireBuffer(buffer, acquireFence, timestamp, damage);
131e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
132e9297d28Sopenharmony_ci        return ret;
133e9297d28Sopenharmony_ci    }
134e9297d28Sopenharmony_ci
135e9297d28Sopenharmony_ci    ret = UpdateEGLImageAndTexture(buffer);
136e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
137e9297d28Sopenharmony_ci        ReleaseBuffer(buffer, -1);
138e9297d28Sopenharmony_ci        return ret;
139e9297d28Sopenharmony_ci    }
140e9297d28Sopenharmony_ci
141e9297d28Sopenharmony_ci    uint32_t seqNum = buffer->GetSeqNum();
142e9297d28Sopenharmony_ci    UpdateSurfaceInfo(seqNum, buffer, acquireFence, timestamp, damage);
143e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
144e9297d28Sopenharmony_ci}
145e9297d28Sopenharmony_ci
146e9297d28Sopenharmony_ciSurfaceError SurfaceImage::AttachContext(uint32_t textureId)
147e9297d28Sopenharmony_ci{
148e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
149e9297d28Sopenharmony_ci    // validate egl state
150e9297d28Sopenharmony_ci    SurfaceError ret = ValidateEglState();
151e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
152e9297d28Sopenharmony_ci        return ret;
153e9297d28Sopenharmony_ci    }
154e9297d28Sopenharmony_ci
155e9297d28Sopenharmony_ci    textureId_ = textureId;
156e9297d28Sopenharmony_ci    auto iter = imageCacheSeqs_.find(currentSurfaceImage_);
157e9297d28Sopenharmony_ci    if (iter != imageCacheSeqs_.end()) {
158e9297d28Sopenharmony_ci        glBindTexture(textureTarget_, textureId);
159e9297d28Sopenharmony_ci        GLenum error = glGetError();
160e9297d28Sopenharmony_ci        if (error != GL_NO_ERROR) {
161e9297d28Sopenharmony_ci            BLOGE("glBindTexture failed, textureTarget:%{public}d, textureId_:%{public}d, error:%{public}d,"
162e9297d28Sopenharmony_ci                "uniqueId: %{public}" PRIu64 ".", textureTarget_, textureId_, error, uniqueId_);
163e9297d28Sopenharmony_ci            return SURFACE_ERROR_EGL_API_FAILED;
164e9297d28Sopenharmony_ci        }
165e9297d28Sopenharmony_ci        glEGLImageTargetTexture2DOES(textureTarget_, static_cast<GLeglImageOES>(iter->second.eglImage_));
166e9297d28Sopenharmony_ci        error = glGetError();
167e9297d28Sopenharmony_ci        if (error != GL_NO_ERROR) {
168e9297d28Sopenharmony_ci            BLOGE("glEGLImageTargetTexture2DOES failed, textureTarget:%{public}d, error:%{public}d"
169e9297d28Sopenharmony_ci                "uniqueId: %{public}" PRIu64 ".", textureTarget_, error, uniqueId_);
170e9297d28Sopenharmony_ci            return SURFACE_ERROR_EGL_API_FAILED;
171e9297d28Sopenharmony_ci        }
172e9297d28Sopenharmony_ci    }
173e9297d28Sopenharmony_ci
174e9297d28Sopenharmony_ci    // If there is no EGLImage, we cannot simply return an error.
175e9297d28Sopenharmony_ci    // Developers can call OH_NativeImage_UpdateSurfaceImage later to achieve their purpose.
176e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
177e9297d28Sopenharmony_ci}
178e9297d28Sopenharmony_ci
179e9297d28Sopenharmony_ciSurfaceError SurfaceImage::DetachContext()
180e9297d28Sopenharmony_ci{
181e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
182e9297d28Sopenharmony_ci    // validate egl state
183e9297d28Sopenharmony_ci    SurfaceError ret = ValidateEglState();
184e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
185e9297d28Sopenharmony_ci        return ret;
186e9297d28Sopenharmony_ci    }
187e9297d28Sopenharmony_ci
188e9297d28Sopenharmony_ci    textureId_ = 0;
189e9297d28Sopenharmony_ci    glBindTexture(textureTarget_, 0);
190e9297d28Sopenharmony_ci    GLenum error = glGetError();
191e9297d28Sopenharmony_ci    if (error != GL_NO_ERROR) {
192e9297d28Sopenharmony_ci        BLOGE("glBindTexture failed, textureTarget:%{public}d, textureId:%{public}d, error:%{public}d"
193e9297d28Sopenharmony_ci            "uniqueId: %{public}" PRIu64 ".", textureTarget_, textureId_, error, uniqueId_);
194e9297d28Sopenharmony_ci        return SURFACE_ERROR_EGL_API_FAILED;
195e9297d28Sopenharmony_ci    }
196e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
197e9297d28Sopenharmony_ci}
198e9297d28Sopenharmony_ci
199e9297d28Sopenharmony_ciint64_t SurfaceImage::GetTimeStamp()
200e9297d28Sopenharmony_ci{
201e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
202e9297d28Sopenharmony_ci    return currentTimeStamp_;
203e9297d28Sopenharmony_ci}
204e9297d28Sopenharmony_ci
205e9297d28Sopenharmony_ciSurfaceError SurfaceImage::GetTransformMatrix(float matrix[16])
206e9297d28Sopenharmony_ci{
207e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
208e9297d28Sopenharmony_ci    auto ret = memcpy_s(matrix, sizeof(float) * 16,  // 16 is the length of array
209e9297d28Sopenharmony_ci                        currentTransformMatrix_, sizeof(currentTransformMatrix_));
210e9297d28Sopenharmony_ci    if (ret != EOK) {
211e9297d28Sopenharmony_ci        BLOGE("memcpy_s failed ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
212e9297d28Sopenharmony_ci        return SURFACE_ERROR_UNKOWN;
213e9297d28Sopenharmony_ci    }
214e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
215e9297d28Sopenharmony_ci}
216e9297d28Sopenharmony_ci
217e9297d28Sopenharmony_ciSurfaceError SurfaceImage::GetTransformMatrixV2(float matrix[16])
218e9297d28Sopenharmony_ci{
219e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
220e9297d28Sopenharmony_ci    auto ret = memcpy_s(matrix, sizeof(float) * 16, // 16 is the length of array
221e9297d28Sopenharmony_ci                        currentTransformMatrixV2_, sizeof(currentTransformMatrixV2_));
222e9297d28Sopenharmony_ci    if (ret != EOK) {
223e9297d28Sopenharmony_ci        BLOGE("memcpy_s failed ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
224e9297d28Sopenharmony_ci        return SURFACE_ERROR_UNKOWN;
225e9297d28Sopenharmony_ci    }
226e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
227e9297d28Sopenharmony_ci}
228e9297d28Sopenharmony_ci
229e9297d28Sopenharmony_ciSurfaceError SurfaceImage::ValidateEglState()
230e9297d28Sopenharmony_ci{
231e9297d28Sopenharmony_ci    EGLDisplay disp = eglGetCurrentDisplay();
232e9297d28Sopenharmony_ci    EGLContext context = eglGetCurrentContext();
233e9297d28Sopenharmony_ci
234e9297d28Sopenharmony_ci    if ((eglDisplay_ != disp && eglDisplay_ != EGL_NO_DISPLAY) || (disp == EGL_NO_DISPLAY)) {
235e9297d28Sopenharmony_ci        BLOGE("EGLDisplay is invalid, errno : 0x%{public}x, uniqueId: %{public}" PRIu64 ".",
236e9297d28Sopenharmony_ci            eglGetError(), uniqueId_);
237e9297d28Sopenharmony_ci        return SURFACE_ERROR_EGL_STATE_UNKONW;
238e9297d28Sopenharmony_ci    }
239e9297d28Sopenharmony_ci    if ((eglContext_ != context && eglContext_ != EGL_NO_CONTEXT) || (context == EGL_NO_CONTEXT)) {
240e9297d28Sopenharmony_ci        BLOGE("EGLContext is invalid, errno : 0x%{public}x, uniqueId: %{public}" PRIu64 ".",
241e9297d28Sopenharmony_ci            eglGetError(), uniqueId_);
242e9297d28Sopenharmony_ci        return SURFACE_ERROR_EGL_STATE_UNKONW;
243e9297d28Sopenharmony_ci    }
244e9297d28Sopenharmony_ci
245e9297d28Sopenharmony_ci    eglDisplay_ = disp;
246e9297d28Sopenharmony_ci    eglContext_ = context;
247e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
248e9297d28Sopenharmony_ci}
249e9297d28Sopenharmony_ci
250e9297d28Sopenharmony_ciEGLImageKHR SurfaceImage::CreateEGLImage(EGLDisplay disp, const sptr<SurfaceBuffer>& buffer)
251e9297d28Sopenharmony_ci{
252e9297d28Sopenharmony_ci    sptr<SurfaceBuffer> bufferImpl = buffer;
253e9297d28Sopenharmony_ci    NativeWindowBuffer* nBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&bufferImpl);
254e9297d28Sopenharmony_ci    EGLint attrs[] = {
255e9297d28Sopenharmony_ci        EGL_IMAGE_PRESERVED,
256e9297d28Sopenharmony_ci        EGL_TRUE,
257e9297d28Sopenharmony_ci        EGL_NONE,
258e9297d28Sopenharmony_ci    };
259e9297d28Sopenharmony_ci
260e9297d28Sopenharmony_ci    EGLImageKHR img = eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, nBuffer, attrs);
261e9297d28Sopenharmony_ci    if (img == EGL_NO_IMAGE_KHR) {
262e9297d28Sopenharmony_ci        EGLint error = eglGetError();
263e9297d28Sopenharmony_ci        BLOGE("failed, error %{public}d, uniqueId: %{public}" PRIu64 ".", error, uniqueId_);
264e9297d28Sopenharmony_ci        eglTerminate(disp);
265e9297d28Sopenharmony_ci    }
266e9297d28Sopenharmony_ci    DestroyNativeWindowBuffer(nBuffer);
267e9297d28Sopenharmony_ci    return img;
268e9297d28Sopenharmony_ci}
269e9297d28Sopenharmony_ci
270e9297d28Sopenharmony_civoid SurfaceImage::CheckImageCacheNeedClean(uint32_t seqNum)
271e9297d28Sopenharmony_ci{
272e9297d28Sopenharmony_ci    for (auto it = imageCacheSeqs_.begin(); it != imageCacheSeqs_.end();) {
273e9297d28Sopenharmony_ci        bool result = true;
274e9297d28Sopenharmony_ci        if (seqNum == it->first) {
275e9297d28Sopenharmony_ci            it++;
276e9297d28Sopenharmony_ci            continue;
277e9297d28Sopenharmony_ci        }
278e9297d28Sopenharmony_ci        if (IsSurfaceBufferInCache(it->first, result) == SURFACE_ERROR_OK && !result) {
279e9297d28Sopenharmony_ci            DestroyEGLImage(it->second.eglImage_);
280e9297d28Sopenharmony_ci            DestroyEGLSync(it->second.eglSync_);
281e9297d28Sopenharmony_ci            it = imageCacheSeqs_.erase(it);
282e9297d28Sopenharmony_ci        } else {
283e9297d28Sopenharmony_ci            it++;
284e9297d28Sopenharmony_ci        }
285e9297d28Sopenharmony_ci    }
286e9297d28Sopenharmony_ci}
287e9297d28Sopenharmony_ci
288e9297d28Sopenharmony_civoid SurfaceImage::DestroyEGLImage(EGLImageKHR &eglImage)
289e9297d28Sopenharmony_ci{
290e9297d28Sopenharmony_ci    if (eglImage != EGL_NO_IMAGE_KHR) {
291e9297d28Sopenharmony_ci        eglDestroyImageKHR(eglDisplay_, eglImage);
292e9297d28Sopenharmony_ci        eglImage = EGL_NO_IMAGE_KHR;
293e9297d28Sopenharmony_ci    }
294e9297d28Sopenharmony_ci}
295e9297d28Sopenharmony_ci
296e9297d28Sopenharmony_civoid SurfaceImage::DestroyEGLSync(EGLSyncKHR &eglSync)
297e9297d28Sopenharmony_ci{
298e9297d28Sopenharmony_ci    if (eglSync != EGL_NO_SYNC_KHR) {
299e9297d28Sopenharmony_ci        eglDestroySyncKHR(eglDisplay_, eglSync);
300e9297d28Sopenharmony_ci        eglSync = EGL_NO_SYNC_KHR;
301e9297d28Sopenharmony_ci    }
302e9297d28Sopenharmony_ci}
303e9297d28Sopenharmony_ci
304e9297d28Sopenharmony_civoid SurfaceImage::DestroyEGLImageBySeq(uint32_t seqNum)
305e9297d28Sopenharmony_ci{
306e9297d28Sopenharmony_ci    auto iter = imageCacheSeqs_.find(seqNum);
307e9297d28Sopenharmony_ci    if (iter != imageCacheSeqs_.end()) {
308e9297d28Sopenharmony_ci        DestroyEGLImage(iter->second.eglImage_);
309e9297d28Sopenharmony_ci        imageCacheSeqs_.erase(seqNum);
310e9297d28Sopenharmony_ci    }
311e9297d28Sopenharmony_ci}
312e9297d28Sopenharmony_ci
313e9297d28Sopenharmony_civoid SurfaceImage::NewBufferDestroyEGLImage(bool isNewBuffer, uint32_t seqNum)
314e9297d28Sopenharmony_ci{
315e9297d28Sopenharmony_ci    if (isNewBuffer) {
316e9297d28Sopenharmony_ci        DestroyEGLImageBySeq(seqNum);
317e9297d28Sopenharmony_ci    }
318e9297d28Sopenharmony_ci}
319e9297d28Sopenharmony_ci
320e9297d28Sopenharmony_ciSurfaceError SurfaceImage::UpdateEGLImageAndTexture(const sptr<SurfaceBuffer>& buffer)
321e9297d28Sopenharmony_ci{
322e9297d28Sopenharmony_ci    bool isNewBuffer = false;
323e9297d28Sopenharmony_ci    // private function, buffer is always valid.
324e9297d28Sopenharmony_ci    uint32_t seqNum = buffer->GetSeqNum();
325e9297d28Sopenharmony_ci    // If there was no eglImage binding to this buffer, we create a new one.
326e9297d28Sopenharmony_ci    if (imageCacheSeqs_.find(seqNum) == imageCacheSeqs_.end()) {
327e9297d28Sopenharmony_ci        isNewBuffer = true;
328e9297d28Sopenharmony_ci        EGLImageKHR eglImage = CreateEGLImage(eglDisplay_, buffer);
329e9297d28Sopenharmony_ci        if (eglImage == EGL_NO_IMAGE_KHR) {
330e9297d28Sopenharmony_ci            return SURFACE_ERROR_EGL_API_FAILED;
331e9297d28Sopenharmony_ci        }
332e9297d28Sopenharmony_ci        imageCacheSeqs_[seqNum].eglImage_ = eglImage;
333e9297d28Sopenharmony_ci    }
334e9297d28Sopenharmony_ci
335e9297d28Sopenharmony_ci    auto &image = imageCacheSeqs_[seqNum];
336e9297d28Sopenharmony_ci    glBindTexture(textureTarget_, textureId_);
337e9297d28Sopenharmony_ci    GLenum error = glGetError();
338e9297d28Sopenharmony_ci    if (error != GL_NO_ERROR) {
339e9297d28Sopenharmony_ci        NewBufferDestroyEGLImage(isNewBuffer, seqNum);
340e9297d28Sopenharmony_ci        BLOGE("glBindTexture failed, textureTarget:%{public}d, textureId_:%{public}d, error:%{public}d"
341e9297d28Sopenharmony_ci            "uniqueId: %{public}" PRIu64 ".", textureTarget_, textureId_, error, uniqueId_);
342e9297d28Sopenharmony_ci        return SURFACE_ERROR_EGL_API_FAILED;
343e9297d28Sopenharmony_ci    }
344e9297d28Sopenharmony_ci    glEGLImageTargetTexture2DOES(textureTarget_, static_cast<GLeglImageOES>(image.eglImage_));
345e9297d28Sopenharmony_ci    error = glGetError();
346e9297d28Sopenharmony_ci    if (error != GL_NO_ERROR) {
347e9297d28Sopenharmony_ci        NewBufferDestroyEGLImage(isNewBuffer, seqNum);
348e9297d28Sopenharmony_ci        BLOGE("glEGLImageTargetTexture2DOES failed, textureTarget:%{public}d, error:%{public}d"
349e9297d28Sopenharmony_ci            "uniqueId: %{public}" PRIu64 ".", textureTarget_, error, uniqueId_);
350e9297d28Sopenharmony_ci        return SURFACE_ERROR_EGL_API_FAILED;
351e9297d28Sopenharmony_ci    }
352e9297d28Sopenharmony_ci
353e9297d28Sopenharmony_ci    // Create fence object for current image
354e9297d28Sopenharmony_ci    auto iter = imageCacheSeqs_.find(currentSurfaceImage_);
355e9297d28Sopenharmony_ci    if (iter != imageCacheSeqs_.end()) {
356e9297d28Sopenharmony_ci        auto &currentImage = iter->second;
357e9297d28Sopenharmony_ci        auto preSync = currentImage.eglSync_;
358e9297d28Sopenharmony_ci        if (preSync != EGL_NO_SYNC_KHR) {
359e9297d28Sopenharmony_ci            eglDestroySyncKHR(eglDisplay_, preSync);
360e9297d28Sopenharmony_ci        }
361e9297d28Sopenharmony_ci        currentImage.eglSync_ = eglCreateSyncKHR(eglDisplay_, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
362e9297d28Sopenharmony_ci        glFlush();
363e9297d28Sopenharmony_ci    }
364e9297d28Sopenharmony_ci
365e9297d28Sopenharmony_ci    if (isNewBuffer) {
366e9297d28Sopenharmony_ci        CheckImageCacheNeedClean(seqNum);
367e9297d28Sopenharmony_ci    }
368e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
369e9297d28Sopenharmony_ci}
370e9297d28Sopenharmony_ci
371e9297d28Sopenharmony_ciSurfaceError SurfaceImage::SetOnBufferAvailableListener(void *context, OnBufferAvailableListener listener)
372e9297d28Sopenharmony_ci{
373e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
374e9297d28Sopenharmony_ci    if (listener == nullptr) {
375e9297d28Sopenharmony_ci        BLOGE("listener is nullptr, uniqueId: %{public}" PRIu64 ".", uniqueId_);
376e9297d28Sopenharmony_ci        return SURFACE_ERROR_INVALID_PARAM;
377e9297d28Sopenharmony_ci    }
378e9297d28Sopenharmony_ci
379e9297d28Sopenharmony_ci    listener_ = listener;
380e9297d28Sopenharmony_ci    context_ = context;
381e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
382e9297d28Sopenharmony_ci}
383e9297d28Sopenharmony_ci
384e9297d28Sopenharmony_ciSurfaceError SurfaceImage::UnsetOnBufferAvailableListener()
385e9297d28Sopenharmony_ci{
386e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
387e9297d28Sopenharmony_ci    listener_ = nullptr;
388e9297d28Sopenharmony_ci    context_ = nullptr;
389e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
390e9297d28Sopenharmony_ci}
391e9297d28Sopenharmony_ci
392e9297d28Sopenharmony_ciSurfaceImageListener::~SurfaceImageListener()
393e9297d28Sopenharmony_ci{
394e9297d28Sopenharmony_ci    BLOGE("~SurfaceImageListener");
395e9297d28Sopenharmony_ci    surfaceImage_ = nullptr;
396e9297d28Sopenharmony_ci}
397e9297d28Sopenharmony_ci
398e9297d28Sopenharmony_civoid SurfaceImageListener::OnBufferAvailable()
399e9297d28Sopenharmony_ci{
400e9297d28Sopenharmony_ci    BLOGD("enter OnBufferAvailable");
401e9297d28Sopenharmony_ci    auto surfaceImage = surfaceImage_.promote();
402e9297d28Sopenharmony_ci    if (surfaceImage == nullptr) {
403e9297d28Sopenharmony_ci        BLOGE("surfaceImage promote failed");
404e9297d28Sopenharmony_ci        return;
405e9297d28Sopenharmony_ci    }
406e9297d28Sopenharmony_ci
407e9297d28Sopenharmony_ci    // check here maybe a messagequeue, flag instead now
408e9297d28Sopenharmony_ci    surfaceImage->OnUpdateBufferAvailableState(true);
409e9297d28Sopenharmony_ci    if (surfaceImage->listener_ != nullptr) {
410e9297d28Sopenharmony_ci        surfaceImage->listener_(surfaceImage->context_);
411e9297d28Sopenharmony_ci    }
412e9297d28Sopenharmony_ci}
413e9297d28Sopenharmony_ci
414e9297d28Sopenharmony_ciSurfaceError SurfaceImage::AcquireNativeWindowBuffer(OHNativeWindowBuffer** nativeWindowBuffer, int32_t* fenceFd)
415e9297d28Sopenharmony_ci{
416e9297d28Sopenharmony_ci    if (nativeWindowBuffer == nullptr || fenceFd == nullptr) {
417e9297d28Sopenharmony_ci        return SURFACE_ERROR_INVALID_PARAM;
418e9297d28Sopenharmony_ci    }
419e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
420e9297d28Sopenharmony_ci    sptr<SurfaceBuffer> buffer = nullptr;
421e9297d28Sopenharmony_ci    sptr<SyncFence> acquireFence = SyncFence::InvalidFence();
422e9297d28Sopenharmony_ci    int64_t timestamp;
423e9297d28Sopenharmony_ci    Rect damage;
424e9297d28Sopenharmony_ci    SurfaceError ret = AcquireBuffer(buffer, acquireFence, timestamp, damage);
425e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
426e9297d28Sopenharmony_ci        BLOGE("AcquireBuffer failed: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
427e9297d28Sopenharmony_ci        return ret;
428e9297d28Sopenharmony_ci    }
429e9297d28Sopenharmony_ci    currentSurfaceBuffer_ = buffer;
430e9297d28Sopenharmony_ci    currentTimeStamp_ = timestamp;
431e9297d28Sopenharmony_ci    currentCrop_ = damage;
432e9297d28Sopenharmony_ci    currentTransformType_ = ConsumerSurface::GetTransform();
433e9297d28Sopenharmony_ci    auto utils = SurfaceUtils::GetInstance();
434e9297d28Sopenharmony_ci    utils->ComputeTransformMatrixV2(currentTransformMatrixV2_, TRANSFORM_MATRIX_ELE_COUNT,
435e9297d28Sopenharmony_ci        currentSurfaceBuffer_, currentTransformType_, currentCrop_);
436e9297d28Sopenharmony_ci
437e9297d28Sopenharmony_ci    *fenceFd = acquireFence->Dup();
438e9297d28Sopenharmony_ci    OHNativeWindowBuffer *nwBuffer = new(std::nothrow) OHNativeWindowBuffer();
439e9297d28Sopenharmony_ci    if (nwBuffer == nullptr) {
440e9297d28Sopenharmony_ci        return SURFACE_ERROR_NOMEM;
441e9297d28Sopenharmony_ci    }
442e9297d28Sopenharmony_ci    nwBuffer->sfbuffer = buffer;
443e9297d28Sopenharmony_ci    NativeObjectReference(nwBuffer);
444e9297d28Sopenharmony_ci    *nativeWindowBuffer = nwBuffer;
445e9297d28Sopenharmony_ci
446e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
447e9297d28Sopenharmony_ci}
448e9297d28Sopenharmony_ci
449e9297d28Sopenharmony_ciSurfaceError SurfaceImage::ReleaseNativeWindowBuffer(OHNativeWindowBuffer* nativeWindowBuffer, int32_t fenceFd)
450e9297d28Sopenharmony_ci{
451e9297d28Sopenharmony_ci    if (nativeWindowBuffer == nullptr) {
452e9297d28Sopenharmony_ci        return SURFACE_ERROR_INVALID_PARAM;
453e9297d28Sopenharmony_ci    }
454e9297d28Sopenharmony_ci    std::lock_guard<std::mutex> lockGuard(opMutex_);
455e9297d28Sopenharmony_ci    // There is no need to close this fd, because in function ReleaseBuffer it will be closed.
456e9297d28Sopenharmony_ci    SurfaceError ret = ReleaseBuffer(nativeWindowBuffer->sfbuffer, fenceFd);
457e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
458e9297d28Sopenharmony_ci        BLOGE("ReleaseBuffer failed: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_);
459e9297d28Sopenharmony_ci        return ret;
460e9297d28Sopenharmony_ci    }
461e9297d28Sopenharmony_ci    NativeObjectUnreference(nativeWindowBuffer);
462e9297d28Sopenharmony_ci    return SURFACE_ERROR_OK;
463e9297d28Sopenharmony_ci}
464e9297d28Sopenharmony_ci
465e9297d28Sopenharmony_ciSurfaceError SurfaceImage::SetDefaultUsage(uint64_t usage)
466e9297d28Sopenharmony_ci{
467e9297d28Sopenharmony_ci    SurfaceError ret = ConsumerSurface::SetDefaultUsage(usage);
468e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
469e9297d28Sopenharmony_ci        BLOGE("SetDefaultUsage failed: %{public}d, uniqueId: %{public}" PRIu64 ", usage: %{public}" PRIu64 ".", ret,
470e9297d28Sopenharmony_ci            uniqueId_, usage);
471e9297d28Sopenharmony_ci    }
472e9297d28Sopenharmony_ci    return ret;
473e9297d28Sopenharmony_ci}
474e9297d28Sopenharmony_ci
475e9297d28Sopenharmony_ciSurfaceError SurfaceImage::SetDefaultSize(int32_t width, int32_t height)
476e9297d28Sopenharmony_ci{
477e9297d28Sopenharmony_ci    SurfaceError ret = SetDefaultWidthAndHeight(width, height);
478e9297d28Sopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
479e9297d28Sopenharmony_ci        BLOGE("SetDefaultWidthAndHeight failed: %{public}d, uniqueId: %{public}" PRIu64 ", width: %{public}d, "
480e9297d28Sopenharmony_ci            "height: %{public}d", ret, uniqueId_, width, height);
481e9297d28Sopenharmony_ci    }
482e9297d28Sopenharmony_ci    return ret;
483e9297d28Sopenharmony_ci}
484e9297d28Sopenharmony_ci} // namespace OHOS
485