2 * Copyright (c) 2021 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-impl-tizen.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-defines.h>
24 #include <tbm_surface_internal.h>
28 #include <dali/integration-api/adaptor-framework/render-surface-interface.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>
41 const char* SAMPLER_TYPE = "samplerExternalOES";
44 tbm_format FORMATS_BLENDING_REQUIRED[] = {
45 TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
46 TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
47 TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
48 TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
49 TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
50 TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
51 TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
52 TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
53 TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
57 const int NUM_FORMATS_BLENDING_REQUIRED = 18;
61 using Dali::Integration::PixelBuffer;
63 NativeImageSourceTizen* NativeImageSourceTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
65 NativeImageSourceTizen* image = new NativeImageSourceTizen(width, height, depth, nativeImageSource);
66 DALI_ASSERT_DEBUG(image && "NativeImageSource allocation failed.");
76 NativeImageSourceTizen::NativeImageSourceTizen(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
79 mOwnTbmSurface(false),
82 mBlendingRequired(false),
86 mEglImageExtensions(NULL),
89 mIsBufferAcquired(false),
90 mResourceDestructionCallback()
93 DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
95 GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
96 mEglGraphics = static_cast<EglGraphics*>(graphics);
98 mTbmSurface = GetSurfaceFromAny(nativeImageSource);
100 if(mTbmSurface != NULL)
102 tbm_surface_internal_ref(mTbmSurface);
103 mBlendingRequired = CheckBlending(tbm_surface_get_format(mTbmSurface));
104 mWidth = tbm_surface_get_width(mTbmSurface);
105 mHeight = tbm_surface_get_height(mTbmSurface);
109 void NativeImageSourceTizen::Initialize()
111 if(mTbmSurface != NULL || mWidth == 0 || mHeight == 0)
116 tbm_format format = TBM_FORMAT_RGB888;
121 case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
123 format = TBM_FORMAT_ARGB8888;
127 case Dali::NativeImageSource::COLOR_DEPTH_8:
129 format = TBM_FORMAT_C8;
133 case Dali::NativeImageSource::COLOR_DEPTH_16:
135 format = TBM_FORMAT_RGB565;
139 case Dali::NativeImageSource::COLOR_DEPTH_24:
141 format = TBM_FORMAT_RGB888;
145 case Dali::NativeImageSource::COLOR_DEPTH_32:
147 format = TBM_FORMAT_ARGB8888;
153 DALI_LOG_WARNING("Wrong color depth.\n");
158 // set whether blending is required according to pixel format based on the depth
159 /* default pixel format is RGB888
160 If depth = 8, Pixel::A8;
161 If depth = 16, Pixel::RGB565;
162 If depth = 32, Pixel::RGBA8888 */
163 mBlendingRequired = (depth == 32 || depth == 8);
165 mTbmSurface = tbm_surface_create(mWidth, mHeight, format);
166 mOwnTbmSurface = true;
169 tbm_surface_h NativeImageSourceTizen::GetSurfaceFromAny(Any source) const
176 if(source.GetType() == typeid(tbm_surface_h))
178 return AnyCast<tbm_surface_h>(source);
186 void NativeImageSourceTizen::DestroySurface()
190 if(mIsBufferAcquired)
196 if(tbm_surface_destroy(mTbmSurface) != TBM_SURFACE_ERROR_NONE)
198 DALI_LOG_ERROR("Failed to destroy tbm_surface\n");
203 tbm_surface_internal_unref(mTbmSurface);
208 NativeImageSourceTizen::~NativeImageSourceTizen()
213 Any NativeImageSourceTizen::GetNativeImageSource() const
215 return Any(mTbmSurface);
218 bool NativeImageSourceTizen::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
220 Dali::Mutex::ScopedLock lock(mMutex);
221 if(mTbmSurface != NULL)
223 tbm_surface_info_s surface_info;
225 if(tbm_surface_map(mTbmSurface, TBM_SURF_OPTION_READ, &surface_info) != TBM_SURFACE_ERROR_NONE)
227 DALI_LOG_ERROR("Fail to map tbm_surface\n");
235 tbm_format format = surface_info.format;
236 uint32_t stride = surface_info.planes[0].stride;
237 unsigned char* ptr = surface_info.planes[0].ptr;
247 case TBM_FORMAT_RGB888:
249 lineSize = width * 3;
250 pixelFormat = Pixel::RGB888;
251 pixbuf.resize(lineSize * height);
252 unsigned char* bufptr = &pixbuf[0];
254 for(unsigned int r = 0; r < height; ++r, bufptr += lineSize)
256 for(unsigned int c = 0; c < width; ++c)
259 offset = cOffset + r * stride;
260 *(bufptr + cOffset) = ptr[offset + 2];
261 *(bufptr + cOffset + 1) = ptr[offset + 1];
262 *(bufptr + cOffset + 2) = ptr[offset];
267 case TBM_FORMAT_RGBA8888:
269 lineSize = width * 4;
270 pixelFormat = Pixel::RGBA8888;
271 pixbuf.resize(lineSize * height);
272 unsigned char* bufptr = &pixbuf[0];
274 for(unsigned int r = 0; r < height; ++r, bufptr += lineSize)
276 for(unsigned int c = 0; c < width; ++c)
279 offset = cOffset + r * stride;
280 *(bufptr + cOffset) = ptr[offset + 3];
281 *(bufptr + cOffset + 1) = ptr[offset + 2];
282 *(bufptr + cOffset + 2) = ptr[offset + 1];
283 *(bufptr + cOffset + 3) = ptr[offset];
288 case TBM_FORMAT_ARGB8888:
290 lineSize = width * 4;
291 pixelFormat = Pixel::RGBA8888;
292 pixbuf.resize(lineSize * height);
293 unsigned char* bufptr = &pixbuf[0];
295 for(unsigned int r = 0; r < height; ++r, bufptr += lineSize)
297 for(unsigned int c = 0; c < width; ++c)
300 offset = cOffset + r * stride;
301 *(bufptr + cOffset) = ptr[offset + 2];
302 *(bufptr + cOffset + 1) = ptr[offset + 1];
303 *(bufptr + cOffset + 2) = ptr[offset];
304 *(bufptr + cOffset + 3) = ptr[offset + 3];
311 DALI_ASSERT_ALWAYS(0 && "Tbm surface has unsupported pixel format.\n");
317 if(tbm_surface_unmap(mTbmSurface) != TBM_SURFACE_ERROR_NONE)
319 DALI_LOG_ERROR("Fail to unmap tbm_surface\n");
325 DALI_LOG_WARNING("TBM surface does not exist.\n");
333 void NativeImageSourceTizen::SetSource(Any source)
335 Dali::Mutex::ScopedLock lock(mMutex);
339 mOwnTbmSurface = false;
340 mTbmSurface = GetSurfaceFromAny(source);
342 if(mTbmSurface != NULL)
345 tbm_surface_internal_ref(mTbmSurface);
346 mBlendingRequired = CheckBlending(tbm_surface_get_format(mTbmSurface));
347 mWidth = tbm_surface_get_width(mTbmSurface);
348 mHeight = tbm_surface_get_height(mTbmSurface);
352 bool NativeImageSourceTizen::IsColorDepthSupported(Dali::NativeImageSource::ColorDepth colorDepth)
356 tbm_format format = TBM_FORMAT_RGB888;
360 case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
362 format = TBM_FORMAT_ARGB8888;
365 case Dali::NativeImageSource::COLOR_DEPTH_8:
367 format = TBM_FORMAT_C8;
370 case Dali::NativeImageSource::COLOR_DEPTH_16:
372 format = TBM_FORMAT_RGB565;
375 case Dali::NativeImageSource::COLOR_DEPTH_24:
377 format = TBM_FORMAT_RGB888;
380 case Dali::NativeImageSource::COLOR_DEPTH_32:
382 format = TBM_FORMAT_ARGB8888;
387 if(tbm_surface_query_formats(&formats, &formatNum))
389 for(unsigned int i = 0; i < formatNum; i++)
391 if(formats[i] == format)
403 bool NativeImageSourceTizen::CreateResource()
405 // If an EGL image exists, use it as it is without creating it.
406 if(mEglImageKHR != NULL)
411 // casting from an unsigned int to a void *, which should then be cast back
412 // to an unsigned int in the driver.
413 EGLClientBuffer eglBuffer = reinterpret_cast<EGLClientBuffer>(mTbmSurface);
414 if(!eglBuffer || !tbm_surface_internal_is_valid(mTbmSurface))
419 mEglImageExtensions = mEglGraphics->GetImageExtensions();
420 DALI_ASSERT_DEBUG(mEglImageExtensions);
422 mEglImageKHR = mEglImageExtensions->CreateImageKHR(eglBuffer);
424 return mEglImageKHR != NULL;
427 void NativeImageSourceTizen::DestroyResource()
429 Dali::Mutex::ScopedLock lock(mMutex);
432 mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
437 if(mResourceDestructionCallback)
439 mResourceDestructionCallback->Trigger();
443 uint32_t NativeImageSourceTizen::TargetTexture()
445 mEglImageExtensions->TargetTextureKHR(mEglImageKHR);
450 void NativeImageSourceTizen::PrepareTexture()
452 Dali::Mutex::ScopedLock lock(mMutex);
455 // Destroy previous eglImage because use for new one.
456 // if mEglImageKHR is not to be NULL here, it will not be updated with a new eglImage.
457 mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
469 bool NativeImageSourceTizen::ApplyNativeFragmentShader(std::string& shader)
471 return mEglGraphics->ApplyNativeFragmentShader(shader, SAMPLER_TYPE);
474 const char* NativeImageSourceTizen::GetCustomSamplerTypename() const
479 int NativeImageSourceTizen::GetTextureTarget() const
481 return GL_TEXTURE_EXTERNAL_OES;
484 Any NativeImageSourceTizen::GetNativeImageHandle() const
486 return GetNativeImageSource();
489 bool NativeImageSourceTizen::SourceChanged() const
494 bool NativeImageSourceTizen::CheckBlending(tbm_format format)
496 if(mTbmFormat != format)
498 for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
500 if(format == FORMATS_BLENDING_REQUIRED[i])
502 mBlendingRequired = true;
509 return mBlendingRequired;
512 uint8_t* NativeImageSourceTizen::AcquireBuffer(uint16_t& width, uint16_t& height, uint16_t& stride)
514 Dali::Mutex::ScopedLock lock(mMutex);
515 if(mTbmSurface != NULL)
517 tbm_surface_info_s info;
519 if(tbm_surface_map(mTbmSurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &info) != TBM_SURFACE_ERROR_NONE)
521 DALI_LOG_ERROR("Fail to map tbm_surface\n");
528 tbm_surface_internal_ref(mTbmSurface);
529 mIsBufferAcquired = true;
531 stride = info.planes[0].stride;
535 return info.planes[0].ptr;
540 bool NativeImageSourceTizen::ReleaseBuffer()
542 Dali::Mutex::ScopedLock lock(mMutex);
544 if(mTbmSurface != NULL)
546 ret = (tbm_surface_unmap(mTbmSurface) == TBM_SURFACE_ERROR_NONE);
549 DALI_LOG_ERROR("Fail to unmap tbm_surface\n");
551 tbm_surface_internal_unref(mTbmSurface);
552 mIsBufferAcquired = false;
557 void NativeImageSourceTizen::SetResourceDestructionCallback(EventThreadCallback* callback)
559 mResourceDestructionCallback = std::unique_ptr<EventThreadCallback>(callback);
562 } // namespace Adaptor
564 } // namespace Internal