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 ¤tImage = 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