2 * Copyright (c) 2022 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/integration-api/debug.h>
23 #include <dali/integration-api/gl-defines.h>
24 #include <tbm_surface_internal.h>
27 #include <dali/devel-api/adaptor-framework/environment-variable.h>
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/internal/graphics/common/egl-image-extensions.h>
30 #include <dali/internal/graphics/gles/egl-graphics.h>
41 int FORMATS_BLENDING_REQUIRED[] = {
42 TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
43 TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
44 TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
45 TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
46 TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
47 TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
48 TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
49 TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
50 TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
54 const char* SAMPLER_TYPE = "samplerExternalOES";
56 constexpr int32_t NUM_FORMATS_BLENDING_REQUIRED = 18;
58 constexpr int32_t DEFAULT_TBM_SURFACE_QUEUE_SIZE = 3u;
59 constexpr auto TBM_SURFACE_QUEUE_SIZE = "DALI_TBM_SURFACE_QUEUE_SIZE";
61 int32_t GetTbmSurfaceQueueSize()
63 static auto queueSizeString = EnvironmentVariable::GetEnvironmentVariable(TBM_SURFACE_QUEUE_SIZE);
64 static int32_t queueSize = queueSizeString ? std::atoi(queueSizeString) : DEFAULT_TBM_SURFACE_QUEUE_SIZE;
70 NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
72 NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(width, height, colorFormat, nativeImageSourceQueue);
73 DALI_ASSERT_DEBUG(image && "NativeImageSourceQueueTizen allocation failed.");
77 image->Initialize(colorFormat);
83 NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
88 mConsumeSurface(NULL),
92 mEglImageExtensions(NULL),
94 mBlendingRequired(false),
98 DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
100 GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
101 mEglGraphics = static_cast<EglGraphics*>(graphics);
103 mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
105 if(mTbmQueue != NULL)
107 mBlendingRequired = CheckBlending(tbm_surface_queue_get_format(mTbmQueue));
108 mWidth = tbm_surface_queue_get_width(mTbmQueue);
109 mHeight = tbm_surface_queue_get_height(mTbmQueue);
113 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
117 if(mTbmQueue != NULL)
119 tbm_surface_queue_destroy(mTbmQueue);
124 void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorFormat colorFormat)
126 if(mWidth == 0 || mHeight == 0)
131 if(mTbmQueue == NULL)
133 int tbmFormat = TBM_FORMAT_ARGB8888;
137 case Dali::NativeImageSourceQueue::ColorFormat::RGBA8888: // TODO : Implement me after other codes fixed.
138 case Dali::NativeImageSourceQueue::ColorFormat::BGRA8888:
140 tbmFormat = TBM_FORMAT_ARGB8888;
141 mBlendingRequired = true;
144 case Dali::NativeImageSourceQueue::ColorFormat::RGBX8888: // TODO : Implement me after other codes fixed.
145 case Dali::NativeImageSourceQueue::ColorFormat::BGRX8888:
147 tbmFormat = TBM_FORMAT_XRGB8888;
148 mBlendingRequired = false;
151 case Dali::NativeImageSourceQueue::ColorFormat::RGB888: // TODO : Implement me after other codes fixed.
152 case Dali::NativeImageSourceQueue::ColorFormat::BGR888:
154 tbmFormat = TBM_FORMAT_RGB888;
155 mBlendingRequired = false;
160 DALI_LOG_WARNING("Wrong color format.\n");
165 mTbmQueue = tbm_surface_queue_create(GetTbmSurfaceQueueSize(), mWidth, mHeight, tbmFormat, 0);
168 DALI_LOG_ERROR("NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue);
176 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny(Any source) const
183 if(source.GetType() == typeid(tbm_surface_queue_h))
185 return AnyCast<tbm_surface_queue_h>(source);
193 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
195 return Any(mTbmQueue);
198 void NativeImageSourceQueueTizen::SetSize(uint32_t width, uint32_t height)
200 Dali::Mutex::ScopedLock lock(mMutex);
202 if(mWidth == width && mHeight == height)
207 tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
214 void NativeImageSourceQueueTizen::IgnoreSourceImage()
216 Dali::Mutex::ScopedLock lock(mMutex);
217 tbm_surface_h surface;
219 if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
221 if(tbm_surface_queue_acquire(mTbmQueue, &surface) != TBM_SURFACE_QUEUE_ERROR_NONE)
223 DALI_LOG_ERROR("NativeImageSourceQueueTizen::IgnoreSourceImage: Failed to aquire a tbm_surface\n");
227 if(tbm_surface_internal_is_valid(surface))
229 tbm_surface_queue_release(mTbmQueue, surface);
234 bool NativeImageSourceQueueTizen::CanDequeueBuffer()
236 Dali::Mutex::ScopedLock lock(mMutex);
237 if(tbm_surface_queue_can_dequeue(mTbmQueue, 0))
244 uint8_t* NativeImageSourceQueueTizen::DequeueBuffer(uint32_t& width, uint32_t& height, uint32_t& stride)
246 Dali::Mutex::ScopedLock lock(mMutex);
247 if(mTbmQueue == NULL)
249 DALI_LOG_ERROR("TbmQueue is NULL");
253 tbm_surface_h tbmSurface;
254 if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
256 DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", tbmSurface);
260 tbm_surface_info_s info;
261 int ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
262 if(ret != TBM_SURFACE_ERROR_NONE)
264 DALI_LOG_ERROR("tbm_surface_map is failed! [%d] [%p]\n", ret, tbmSurface);
265 tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
269 unsigned char* buffer = info.planes[0].ptr;
272 DALI_LOG_ERROR("tbm buffer pointer is null! [%p]\n", tbmSurface);
273 tbm_surface_unmap(tbmSurface);
274 tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
278 tbm_surface_internal_ref(tbmSurface);
280 stride = info.planes[0].stride;
285 mBuffers.push_back(BufferPair(tbmSurface, buffer));
289 bool NativeImageSourceQueueTizen::EnqueueBuffer(uint8_t* buffer)
291 Dali::Mutex::ScopedLock lock(mMutex);
292 auto bufferInstance = std::find_if(mBuffers.begin(),
294 [buffer](BufferPair pair) { return (pair.second == buffer); });
295 if(bufferInstance != mBuffers.end())
297 tbm_surface_internal_unref((*bufferInstance).first);
298 tbm_surface_unmap((*bufferInstance).first);
299 tbm_surface_queue_enqueue(mTbmQueue, (*bufferInstance).first);
300 mBuffers.erase(bufferInstance);
306 void NativeImageSourceQueueTizen::FreeReleasedBuffers()
308 Dali::Mutex::ScopedLock lock(mMutex);
312 bool NativeImageSourceQueueTizen::CreateResource()
314 mEglImageExtensions = mEglGraphics->GetImageExtensions();
315 DALI_ASSERT_DEBUG(mEglImageExtensions);
320 void NativeImageSourceQueueTizen::DestroyResource()
322 Dali::Mutex::ScopedLock lock(mMutex);
324 ResetEglImageList(true);
327 uint32_t NativeImageSourceQueueTizen::TargetTexture()
332 void NativeImageSourceQueueTizen::PrepareTexture()
334 Dali::Mutex::ScopedLock lock(mMutex);
336 bool updated = false;
340 tbm_surface_h oldSurface = mConsumeSurface;
342 if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
344 if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
346 DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
352 if(tbm_surface_internal_is_valid(oldSurface))
354 tbm_surface_queue_release(mTbmQueue, oldSurface);
363 } while(mFreeRequest); // Get the last one if buffer free was requested
369 ResetEglImageList(false);
375 bool existing = false;
376 for(auto&& iter : mEglImages)
378 if(iter.first == mConsumeSurface)
380 // Find the surface in the existing list
382 mEglImageExtensions->TargetTextureKHR(iter.second);
390 tbm_surface_internal_ref(mConsumeSurface);
392 void* eglImageKHR = mEglImageExtensions->CreateImageKHR(reinterpret_cast<EGLClientBuffer>(mConsumeSurface));
393 mEglImageExtensions->TargetTextureKHR(eglImageKHR);
395 mEglImages.push_back(EglImagePair(mConsumeSurface, eglImageKHR));
402 auto iter = std::remove_if(mEglImages.begin(), mEglImages.end(), [&](EglImagePair& eglImage) {
403 if(mConsumeSurface == eglImage.first) return false;
404 mEglImageExtensions->DestroyImageKHR(eglImage.second);
405 tbm_surface_internal_unref(eglImage.first);
407 mEglImages.erase(iter, mEglImages.end());
409 tbm_surface_queue_free_flush(mTbmQueue);
410 mFreeRequest = false;
414 bool NativeImageSourceQueueTizen::ApplyNativeFragmentShader(std::string& shader)
416 return mEglGraphics->ApplyNativeFragmentShader(shader, SAMPLER_TYPE);
419 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
424 int NativeImageSourceQueueTizen::GetTextureTarget() const
426 return GL_TEXTURE_EXTERNAL_OES;
429 Any NativeImageSourceQueueTizen::GetNativeImageHandle() const
434 bool NativeImageSourceQueueTizen::SourceChanged() const
439 void NativeImageSourceQueueTizen::ResetEglImageList(bool releaseConsumeSurface)
441 // When Tbm surface queue is reset(resized), the surface acquired before reset() is still valid, not the others.
442 // We can still use the acquired surface so that we will release it as the oldSurface in PrepareTexture() when the next surface is ready.
443 if(releaseConsumeSurface && mConsumeSurface)
445 if(tbm_surface_internal_is_valid(mConsumeSurface))
447 tbm_surface_queue_release(mTbmQueue, mConsumeSurface);
449 mConsumeSurface = NULL;
452 for(auto&& iter : mEglImages)
454 mEglImageExtensions->DestroyImageKHR(iter.second);
456 tbm_surface_internal_unref(iter.first);
461 bool NativeImageSourceQueueTizen::CheckBlending(int format)
463 for(int32_t i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
465 if(format == FORMATS_BLENDING_REQUIRED[i])
474 } // namespace Adaptor
476 } // namespace Internal