2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/imaging/tizen/native-image-source-queue-impl-tizen.h>
22 #include <dali/devel-api/common/stage.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/integration-api/gl-defines.h>
25 #include <tbm_surface_internal.h>
28 #include <dali/devel-api/adaptor-framework/environment-variable.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/graphics/common/egl-image-extensions.h>
31 #include <dali/internal/graphics/gles/egl-graphics.h>
32 #include <dali/internal/system/common/environment-variables.h>
43 int FORMATS_BLENDING_REQUIRED[] = {
44 TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
45 TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
46 TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
47 TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
48 TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
49 TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
50 TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
51 TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
52 TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
56 const char* SAMPLER_TYPE = "samplerExternalOES";
58 constexpr int32_t NUM_FORMATS_BLENDING_REQUIRED = 18;
60 constexpr int32_t DEFAULT_TBM_SURFACE_QUEUE_SIZE = 3u;
62 int32_t GetTbmSurfaceQueueSize()
64 static auto queueSizeString = EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_TBM_SURFACE_QUEUE_SIZE);
65 static int32_t queueSize = queueSizeString ? std::atoi(queueSizeString) : DEFAULT_TBM_SURFACE_QUEUE_SIZE;
71 NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t queueCount, uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
73 NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(queueCount, width, height, colorFormat, nativeImageSourceQueue);
74 DALI_ASSERT_DEBUG(image && "NativeImageSourceQueueTizen allocation failed.");
78 image->Initialize(colorFormat);
84 NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t queueCount, uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
86 mQueueCount(queueCount),
90 mConsumeSurface(NULL),
94 mEglImageExtensions(NULL),
96 mBlendingRequired(false),
100 DALI_ASSERT_ALWAYS(Dali::Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
102 GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
103 mEglGraphics = static_cast<EglGraphics*>(graphics);
105 mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
107 if(mTbmQueue != NULL)
109 mBlendingRequired = CheckBlending(tbm_surface_queue_get_format(mTbmQueue));
110 mQueueCount = tbm_surface_queue_get_size(mTbmQueue);
111 mWidth = tbm_surface_queue_get_width(mTbmQueue);
112 mHeight = tbm_surface_queue_get_height(mTbmQueue);
116 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
120 if(mTbmQueue != NULL)
122 tbm_surface_queue_destroy(mTbmQueue);
127 void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorFormat colorFormat)
129 if(mWidth == 0 || mHeight == 0)
134 if(mTbmQueue == NULL)
136 int tbmFormat = TBM_FORMAT_ARGB8888;
140 case Dali::NativeImageSourceQueue::ColorFormat::RGBA8888: // TODO : Implement me after other codes fixed.
141 case Dali::NativeImageSourceQueue::ColorFormat::BGRA8888:
143 tbmFormat = TBM_FORMAT_ARGB8888;
144 mBlendingRequired = true;
147 case Dali::NativeImageSourceQueue::ColorFormat::RGBX8888: // TODO : Implement me after other codes fixed.
148 case Dali::NativeImageSourceQueue::ColorFormat::BGRX8888:
150 tbmFormat = TBM_FORMAT_XRGB8888;
151 mBlendingRequired = false;
154 case Dali::NativeImageSourceQueue::ColorFormat::RGB888: // TODO : Implement me after other codes fixed.
155 case Dali::NativeImageSourceQueue::ColorFormat::BGR888:
157 tbmFormat = TBM_FORMAT_RGB888;
158 mBlendingRequired = false;
163 DALI_LOG_WARNING("Wrong color format.\n");
170 mQueueCount = GetTbmSurfaceQueueSize();
173 mTbmQueue = tbm_surface_queue_create(mQueueCount, mWidth, mHeight, tbmFormat, 0);
176 DALI_LOG_ERROR("NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue);
184 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny(Any source) const
191 if(source.GetType() == typeid(tbm_surface_queue_h))
193 return AnyCast<tbm_surface_queue_h>(source);
201 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
203 return Any(mTbmQueue);
206 void NativeImageSourceQueueTizen::SetSize(uint32_t width, uint32_t height)
208 Dali::Mutex::ScopedLock lock(mMutex);
210 if(mWidth == width && mHeight == height)
215 tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
222 void NativeImageSourceQueueTizen::IgnoreSourceImage()
224 Dali::Mutex::ScopedLock lock(mMutex);
225 tbm_surface_h surface;
227 if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
229 if(tbm_surface_queue_acquire(mTbmQueue, &surface) != TBM_SURFACE_QUEUE_ERROR_NONE)
231 DALI_LOG_ERROR("NativeImageSourceQueueTizen::IgnoreSourceImage: Failed to aquire a tbm_surface\n");
235 if(tbm_surface_internal_is_valid(surface))
237 tbm_surface_queue_release(mTbmQueue, surface);
242 bool NativeImageSourceQueueTizen::CanDequeueBuffer()
244 Dali::Mutex::ScopedLock lock(mMutex);
245 if(tbm_surface_queue_can_dequeue(mTbmQueue, 0))
252 uint8_t* NativeImageSourceQueueTizen::DequeueBuffer(uint32_t& width, uint32_t& height, uint32_t& stride)
254 Dali::Mutex::ScopedLock lock(mMutex);
255 if(mTbmQueue == NULL)
257 DALI_LOG_ERROR("TbmQueue is NULL");
261 tbm_surface_h tbmSurface;
262 if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
264 DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", tbmSurface);
268 tbm_surface_info_s info;
269 int ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
270 if(ret != TBM_SURFACE_ERROR_NONE)
272 DALI_LOG_ERROR("tbm_surface_map is failed! [%d] [%p]\n", ret, tbmSurface);
273 tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
277 uint8_t* buffer = info.planes[0].ptr;
280 DALI_LOG_ERROR("tbm buffer pointer is null! [%p]\n", tbmSurface);
281 tbm_surface_unmap(tbmSurface);
282 tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
286 tbm_surface_internal_ref(tbmSurface);
288 stride = info.planes[0].stride;
293 mBuffers.insert({buffer, tbmSurface});
297 bool NativeImageSourceQueueTizen::EnqueueBuffer(uint8_t* buffer)
299 Dali::Mutex::ScopedLock lock(mMutex);
300 auto bufferInstance = mBuffers.find(buffer);
301 if(bufferInstance != mBuffers.end())
303 tbm_surface_internal_unref((*bufferInstance).second);
304 tbm_surface_unmap((*bufferInstance).second);
305 tbm_surface_queue_enqueue(mTbmQueue, (*bufferInstance).second);
306 mBuffers.erase(bufferInstance);
312 void NativeImageSourceQueueTizen::FreeReleasedBuffers()
314 Dali::Mutex::ScopedLock lock(mMutex);
318 bool NativeImageSourceQueueTizen::CreateResource()
320 mEglImageExtensions = mEglGraphics->GetImageExtensions();
321 DALI_ASSERT_DEBUG(mEglImageExtensions);
326 void NativeImageSourceQueueTizen::DestroyResource()
328 Dali::Mutex::ScopedLock lock(mMutex);
330 ResetEglImageList(true);
333 uint32_t NativeImageSourceQueueTizen::TargetTexture()
338 void NativeImageSourceQueueTizen::PrepareTexture()
340 Dali::Mutex::ScopedLock lock(mMutex);
342 bool updated = false;
346 tbm_surface_h oldSurface = mConsumeSurface;
348 if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
350 if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
352 DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
358 if(tbm_surface_internal_is_valid(oldSurface))
360 tbm_surface_queue_release(mTbmQueue, oldSurface);
369 } while(mFreeRequest); // Get the last one if buffer free was requested
375 ResetEglImageList(false);
381 auto iter = mEglImages.find(mConsumeSurface);
382 if(iter == mEglImages.end())
385 tbm_surface_internal_ref(mConsumeSurface);
387 void* eglImageKHR = mEglImageExtensions->CreateImageKHR(reinterpret_cast<EGLClientBuffer>(mConsumeSurface));
388 mEglImageExtensions->TargetTextureKHR(eglImageKHR);
390 mEglImages.insert({mConsumeSurface, eglImageKHR});
394 mEglImageExtensions->TargetTextureKHR(iter->second);
401 // Destroy all egl images which is not mConsumeSurface.
402 for(auto iter = mEglImages.begin(); iter != mEglImages.end();)
404 if(iter->first == mConsumeSurface)
410 mEglImageExtensions->DestroyImageKHR(iter->second);
411 tbm_surface_internal_unref(iter->first);
413 iter = mEglImages.erase(iter);
417 tbm_surface_queue_free_flush(mTbmQueue);
418 mFreeRequest = false;
422 bool NativeImageSourceQueueTizen::ApplyNativeFragmentShader(std::string& shader)
424 return mEglGraphics->ApplyNativeFragmentShader(shader, SAMPLER_TYPE);
427 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
432 int NativeImageSourceQueueTizen::GetTextureTarget() const
434 return GL_TEXTURE_EXTERNAL_OES;
437 Any NativeImageSourceQueueTizen::GetNativeImageHandle() const
442 bool NativeImageSourceQueueTizen::SourceChanged() const
447 void NativeImageSourceQueueTizen::ResetEglImageList(bool releaseConsumeSurface)
449 // When Tbm surface queue is reset(resized), the surface acquired before reset() is still valid, not the others.
450 // We can still use the acquired surface so that we will release it as the oldSurface in PrepareTexture() when the next surface is ready.
451 if(releaseConsumeSurface && mConsumeSurface)
453 if(tbm_surface_internal_is_valid(mConsumeSurface))
455 tbm_surface_queue_release(mTbmQueue, mConsumeSurface);
457 mConsumeSurface = NULL;
460 for(auto&& iter : mEglImages)
462 mEglImageExtensions->DestroyImageKHR(iter.second);
464 tbm_surface_internal_unref(iter.first);
469 bool NativeImageSourceQueueTizen::CheckBlending(int format)
471 for(int32_t i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
473 if(format == FORMATS_BLENDING_REQUIRED[i])
482 } // namespace Adaptor
484 } // namespace Internal