1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rs_egl_image_manager.h"
17
18 #include <native_window.h>
19 #include <platform/common/rs_log.h>
20 #include "sync_fence.h"
21 #include "pipeline/rs_main_thread.h"
22 #include "pipeline/rs_hardware_thread.h"
23 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
24 #include "rs_trace.h"
25 #include "common/rs_optional_trace.h"
26
27 #ifndef NDEBUG
28 #include <cassert>
29 #endif
30
31 namespace OHOS {
32 namespace Rosen {
33 namespace Detail {
34 #ifdef NDEBUG
35 #define RS_ASSERT(exp) (void)((exp))
36 #else
37 #define RS_ASSERT(exp) assert((exp))
38 #endif
39
40 #define RS_EGL_ERR_CASE_STR(value) case value: return #value
EGLErrorString(GLint error)41 const char *EGLErrorString(GLint error)
42 {
43 switch (error) {
44 RS_EGL_ERR_CASE_STR(EGL_SUCCESS);
45 RS_EGL_ERR_CASE_STR(EGL_NOT_INITIALIZED);
46 RS_EGL_ERR_CASE_STR(EGL_BAD_ACCESS);
47 RS_EGL_ERR_CASE_STR(EGL_BAD_ALLOC);
48 RS_EGL_ERR_CASE_STR(EGL_BAD_ATTRIBUTE);
49 RS_EGL_ERR_CASE_STR(EGL_BAD_CONFIG);
50 RS_EGL_ERR_CASE_STR(EGL_BAD_CONTEXT);
51 RS_EGL_ERR_CASE_STR(EGL_BAD_CURRENT_SURFACE);
52 RS_EGL_ERR_CASE_STR(EGL_BAD_DISPLAY);
53 RS_EGL_ERR_CASE_STR(EGL_BAD_MATCH);
54 RS_EGL_ERR_CASE_STR(EGL_BAD_NATIVE_PIXMAP);
55 RS_EGL_ERR_CASE_STR(EGL_BAD_NATIVE_WINDOW);
56 RS_EGL_ERR_CASE_STR(EGL_BAD_PARAMETER);
57 RS_EGL_ERR_CASE_STR(EGL_BAD_SURFACE);
58 RS_EGL_ERR_CASE_STR(EGL_CONTEXT_LOST);
59 default: return "Unknown";
60 }
61 }
62
GetEGLCreateImageKHRFunc()63 static PFNEGLCREATEIMAGEKHRPROC GetEGLCreateImageKHRFunc()
64 {
65 static auto func = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
66 return func;
67 }
68
GetEGLDestroyImageKHRFunc()69 static PFNEGLDESTROYIMAGEKHRPROC GetEGLDestroyImageKHRFunc()
70 {
71 static auto func = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
72 return func;
73 }
74
GetGLEGLImageTargetTexture2DOESFunc()75 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC GetGLEGLImageTargetTexture2DOESFunc()
76 {
77 static auto func = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(
78 eglGetProcAddress("glEGLImageTargetTexture2DOES"));
79 return func;
80 }
81
82 // RAII object for NativeWindowBuffer
83 class NativeWindowBufferObject {
84 public:
NativeWindowBufferObject(sptr<OHOS::SurfaceBuffer> buffer)85 explicit NativeWindowBufferObject(sptr<OHOS::SurfaceBuffer> buffer)
86 : handle_(CreateNativeWindowBufferFromSurfaceBuffer(&buffer))
87 {
88 }
NativeWindowBufferObject(NativeWindowBuffer * nativeBuffer)89 explicit NativeWindowBufferObject(NativeWindowBuffer* nativeBuffer)
90 : handle_(nativeBuffer)
91 {
92 }
93
~NativeWindowBufferObject()94 ~NativeWindowBufferObject() noexcept
95 {
96 if (handle_ != nullptr) {
97 DestroyNativeWindowBuffer(handle_);
98 }
99 }
100
101 NativeWindowBufferObject(const NativeWindowBufferObject&) = delete;
102 void operator=(const NativeWindowBufferObject&) = delete;
103
operator ==(std::nullptr_t) const104 bool operator==(std::nullptr_t) const
105 {
106 return handle_ == nullptr;
107 }
operator !=(std::nullptr_t) const108 bool operator!=(std::nullptr_t) const
109 {
110 return handle_ != nullptr;
111 }
112
113 // not explicit so you can use it to do the implicit-cast.
114 // you should not delete or call DestroyNativeWindowBuffer for this pointer.
operator NativeWindowBuffer*() const115 operator NativeWindowBuffer* () const
116 {
117 return Get();
118 }
119 // you should not delete or call DestroyNativeWindowBuffer for this pointer.
Get() const120 NativeWindowBuffer* Get() const
121 {
122 return handle_;
123 }
124
Release()125 NativeWindowBuffer* Release()
126 {
127 NativeWindowBuffer* out = handle_;
128 handle_ = nullptr;
129 return out;
130 }
131
132 private:
133 NativeWindowBuffer* handle_ = nullptr;
134 };
135
CreateNativeWindowBuffer(const sptr<OHOS::SurfaceBuffer> & buffer)136 NativeWindowBufferObject CreateNativeWindowBuffer(const sptr<OHOS::SurfaceBuffer>& buffer)
137 {
138 return NativeWindowBufferObject(buffer);
139 }
140
CastToEGLClientBuffer(NativeWindowBuffer * nativeBuffer)141 EGLClientBuffer CastToEGLClientBuffer(NativeWindowBuffer* nativeBuffer)
142 {
143 return static_cast<EGLClientBuffer>(nativeBuffer);
144 }
145
CastFromEGLClientBuffer(EGLClientBuffer eglClientBuffer)146 NativeWindowBuffer* CastFromEGLClientBuffer(EGLClientBuffer eglClientBuffer)
147 {
148 return static_cast<NativeWindowBuffer*>(eglClientBuffer);
149 }
150
CreateEGLImage(EGLDisplay eglDisplay,EGLContext EGLContext,const NativeWindowBufferObject & nativeBuffer)151 EGLImageKHR CreateEGLImage(
152 EGLDisplay eglDisplay,
153 EGLContext EGLContext,
154 const NativeWindowBufferObject& nativeBuffer)
155 {
156 EGLint attrs[] = {
157 EGL_IMAGE_PRESERVED_KHR,
158 EGL_TRUE,
159 EGL_NONE,
160 };
161
162 return GetEGLCreateImageKHRFunc()(
163 eglDisplay, EGLContext, EGL_NATIVE_BUFFER_OHOS, CastToEGLClientBuffer(nativeBuffer), attrs);
164 }
165 } // namespace Detail
166
ImageCacheSeq(EGLDisplay eglDisplay,EGLImageKHR eglImage,EGLClientBuffer eglClientBuffer)167 ImageCacheSeq::ImageCacheSeq(
168 EGLDisplay eglDisplay, EGLImageKHR eglImage, EGLClientBuffer eglClientBuffer)
169 : eglDisplay_(eglDisplay),
170 eglImage_(eglImage),
171 eglClientBuffer_(eglClientBuffer)
172 {
173 }
174
~ImageCacheSeq()175 ImageCacheSeq::~ImageCacheSeq() noexcept
176 {
177 if (eglImage_ != EGL_NO_IMAGE_KHR) {
178 Detail::GetEGLDestroyImageKHRFunc()(eglDisplay_, eglImage_);
179 eglImage_ = EGL_NO_IMAGE_KHR;
180 }
181
182 if (textureId_ != 0) {
183 glDeleteTextures(1, &textureId_);
184 textureId_ = 0;
185 }
186
187 // auto dec ref.
188 Detail::NativeWindowBufferObject nBufferDecRef(
189 Detail::CastFromEGLClientBuffer(eglClientBuffer_));
190 }
191
BindToTexture()192 bool ImageCacheSeq::BindToTexture()
193 {
194 // no image check.
195 if (eglImage_ == EGL_NO_IMAGE_KHR) {
196 RS_LOGE("ImageCacheSeq::BindToTexture: eglImage_ is null.");
197 return false;
198 }
199
200 glGenTextures(1, &textureId_);
201 if (textureId_ == 0) {
202 RS_LOGE("ImageCacheSeq::BindToTexture: glGenTextures error.");
203 return false;
204 }
205
206 // bind this eglImage_ to textureId_.
207 glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
208 Detail::GetGLEGLImageTargetTexture2DOESFunc()(GL_TEXTURE_EXTERNAL_OES, eglImage_);
209 return true;
210 }
211
Create(EGLDisplay eglDisplay,EGLContext eglContext,const sptr<OHOS::SurfaceBuffer> & buffer)212 std::unique_ptr<ImageCacheSeq> ImageCacheSeq::Create(
213 EGLDisplay eglDisplay,
214 EGLContext eglContext,
215 const sptr<OHOS::SurfaceBuffer>& buffer)
216 {
217 auto nativeBuffer = Detail::CreateNativeWindowBuffer(buffer);
218 if (nativeBuffer == nullptr) {
219 return nullptr;
220 }
221
222 EGLImageKHR img = Detail::CreateEGLImage(eglDisplay, eglContext, nativeBuffer);
223 if (img == EGL_NO_IMAGE_KHR) {
224 RS_LOGE("ImageCacheSeq::Create: eglCreateImageKHR failed, error %s.",
225 Detail::EGLErrorString(eglGetError()));
226 return nullptr;
227 }
228
229 auto imageCache = std::make_unique<ImageCacheSeq>(
230 eglDisplay, img, Detail::CastToEGLClientBuffer(nativeBuffer.Release()));
231 if (!imageCache->BindToTexture()) {
232 return nullptr;
233 }
234 return imageCache;
235 }
236
RSEglImageManager(EGLDisplay display)237 RSEglImageManager::RSEglImageManager(EGLDisplay display) : eglDisplay_(display)
238 {
239 }
240
WaitAcquireFence(const sptr<SyncFence> & acquireFence)241 void RSEglImageManager::WaitAcquireFence(const sptr<SyncFence>& acquireFence)
242 {
243 if (acquireFence == nullptr) {
244 return;
245 }
246 acquireFence->Wait(3000); // 3000ms
247 }
248
CreateImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,const uint32_t threadIndex)249 GLuint RSEglImageManager::CreateImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer>& buffer,
250 const uint32_t threadIndex)
251 {
252 auto bufferId = buffer->GetSeqNum();
253 auto imageCache = ImageCacheSeq::Create(eglDisplay_, EGL_NO_CONTEXT, buffer);
254 if (imageCache == nullptr) {
255 RS_LOGE("RSEglImageManager::CreateImageCacheFromBuffer: failed to create ImageCache for buffer id %d.",
256 bufferId);
257 return 0; // return texture id 0.
258 }
259 imageCache->SetThreadIndex(threadIndex);
260 auto textureId = imageCache->TextureId();
261 imageCacheSeqs_[bufferId] = std::move(imageCache);
262 cacheQueue_.push(bufferId);
263 return textureId;
264 }
265
CreateImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,const sptr<SyncFence> & acquireFence)266 std::unique_ptr<ImageCacheSeq> RSEglImageManager::CreateImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer>& buffer,
267 const sptr<SyncFence>& acquireFence)
268 {
269 WaitAcquireFence(acquireFence);
270 auto bufferId = buffer->GetSeqNum();
271 auto imageCache = ImageCacheSeq::Create(eglDisplay_, EGL_NO_CONTEXT, buffer);
272 if (imageCache == nullptr) {
273 RS_LOGE("RSEglImageManager::CreateImageCacheFromBuffer: failed to create ImageCache for buffer id %d.",
274 bufferId);
275 return nullptr;
276 }
277 return imageCache;
278 }
279
MapEglImageFromSurfaceBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,const sptr<SyncFence> & acquireFence,uint32_t threadIndex)280 GLuint RSEglImageManager::MapEglImageFromSurfaceBuffer(const sptr<OHOS::SurfaceBuffer>& buffer,
281 const sptr<SyncFence>& acquireFence, uint32_t threadIndex)
282 {
283 WaitAcquireFence(acquireFence);
284 std::lock_guard<std::mutex> lock(opMutex_);
285 auto bufferId = buffer->GetSeqNum();
286 RS_OPTIONAL_TRACE_NAME_FMT("MapEglImage seqNum: %d", bufferId);
287 RS_LOGD("RSEglImageManager::MapEglImageFromSurfaceBuffer: %{public}d", bufferId);
288 if (imageCacheSeqs_.count(bufferId) == 0 || imageCacheSeqs_[bufferId] == nullptr) {
289 // cache not found, create it.
290 return CreateImageCacheFromBuffer(buffer, threadIndex);
291 } else {
292 auto& imageCache = imageCacheSeqs_[bufferId];
293 imageCache->SetThreadIndex(threadIndex);
294 return imageCache->TextureId();
295 }
296 }
297
ShrinkCachesIfNeeded(bool isForUniRedraw)298 void RSEglImageManager::ShrinkCachesIfNeeded(bool isForUniRedraw)
299 {
300 while (cacheQueue_.size() > MAX_CACHE_SIZE) {
301 const int32_t id = cacheQueue_.front();
302 if (isForUniRedraw) {
303 UnMapEglImageFromSurfaceBufferForUniRedraw(id);
304 } else {
305 UnMapEglImageFromSurfaceBuffer(id);
306 }
307 cacheQueue_.pop();
308 }
309 }
310
UnMapEglImageFromSurfaceBuffer(int32_t seqNum)311 void RSEglImageManager::UnMapEglImageFromSurfaceBuffer(int32_t seqNum)
312 {
313 uint32_t threadIndex = UNI_MAIN_THREAD_INDEX;
314 {
315 std::lock_guard<std::mutex> lock(opMutex_);
316 if (imageCacheSeqs_.count(seqNum) == 0) {
317 return;
318 }
319 if (imageCacheSeqs_[seqNum]) {
320 threadIndex = imageCacheSeqs_[seqNum]->GetThreadIndex();
321 }
322 }
323 auto func = [this, seqNum]() {
324 {
325 std::lock_guard<std::mutex> lock(opMutex_);
326 if (imageCacheSeqs_.count(seqNum) == 0) {
327 return;
328 }
329 (void)imageCacheSeqs_.erase(seqNum);
330 }
331 RS_OPTIONAL_TRACE_NAME_FMT("UnmapEglImage seqNum: %d", seqNum);
332 RS_LOGD("RSEglImageManager::UnMapEglImageFromSurfaceBuffer: %{public}d", seqNum);
333 };
334 if (threadIndex == UNI_MAIN_THREAD_INDEX) {
335 RSMainThread::Instance()->PostTask(func);
336 } else {
337 RSSubThreadManager::Instance()->PostTask(func, threadIndex);
338 }
339 }
340
UnMapEglImageFromSurfaceBufferForUniRedraw(int32_t seqNum)341 void RSEglImageManager::UnMapEglImageFromSurfaceBufferForUniRedraw(int32_t seqNum)
342 {
343 RSHardwareThread::Instance().PostTask([this, seqNum]() {
344 std::lock_guard<std::mutex> lock(opMutex_);
345 if (imageCacheSeqs_.count(seqNum) == 0) {
346 return;
347 }
348 (void)imageCacheSeqs_.erase(seqNum);
349 RS_LOGD("RSEglImageManager::UnMapEglImageFromSurfaceBufferForRedraw");
350 });
351 }
352 } // namespace Rosen
353 } // namespace OHOS
354