/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <tbm_surface_internal.h>
// INTERNAL INCLUDES
-#include <dali/internal/graphics/common/egl-image-extensions.h>
-#include <dali/internal/graphics/gles20/egl-graphics.h>
#include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/internal/graphics/common/egl-image-extensions.h>
+#include <dali/internal/graphics/gles/egl-graphics.h>
namespace Dali
{
-
namespace Internal
{
-
namespace Adaptor
{
-
namespace
{
-#define TBM_SURFACE_QUEUE_SIZE 3
+#define TBM_SURFACE_QUEUE_SIZE 3
-const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
-const char* SAMPLER_TYPE = "samplerExternalOES";
+const char* SAMPLER_TYPE = "samplerExternalOES";
+// clang-format off
int FORMATS_BLENDING_REQUIRED[] = {
TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
};
+// clang-format on
const int NUM_FORMATS_BLENDING_REQUIRED = 18;
-}
+} // namespace
-NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New( unsigned int width, unsigned int height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue )
+NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
{
- NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen( width, height, depth, nativeImageSourceQueue );
- DALI_ASSERT_DEBUG( image && "NativeImageSourceQueueTizen allocation failed." );
+ NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(width, height, colorFormat, nativeImageSourceQueue);
+ DALI_ASSERT_DEBUG(image && "NativeImageSourceQueueTizen allocation failed.");
- if( image )
+ if(image)
{
- image->Initialize( depth );
+ image->Initialize(colorFormat);
}
return image;
}
-NativeImageSourceQueueTizen::NativeImageSourceQueueTizen( unsigned int width, unsigned int height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue )
-: mWidth( width ),
- mHeight( height ),
- mTbmQueue( NULL ),
- mConsumeSurface( NULL ),
+NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
+: mMutex(),
+ mWidth(width),
+ mHeight(height),
+ mTbmQueue(NULL),
+ mConsumeSurface(NULL),
mEglImages(),
- mEglGraphics( NULL ),
- mEglImageExtensions( NULL ),
- mOwnTbmQueue( false ),
- mBlendingRequired( false )
+ mBuffers(),
+ mEglGraphics(NULL),
+ mEglImageExtensions(NULL),
+ mOwnTbmQueue(false),
+ mBlendingRequired(false),
+ mIsResized(false)
{
- DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
+ DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
- GraphicsInterface* graphics = &( Adaptor::GetImplementation( Adaptor::Get() ).GetGraphicsInterface() );
- mEglGraphics = static_cast<EglGraphics *>(graphics);
+ GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
+ mEglGraphics = static_cast<EglGraphics*>(graphics);
- mTbmQueue = GetSurfaceFromAny( nativeImageSourceQueue );
+ mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
- if( mTbmQueue != NULL )
+ if(mTbmQueue != NULL)
{
- mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
- mWidth = tbm_surface_queue_get_width( mTbmQueue );
- mHeight = tbm_surface_queue_get_height( mTbmQueue );
+ mBlendingRequired = CheckBlending(tbm_surface_queue_get_format(mTbmQueue));
+ mWidth = tbm_surface_queue_get_width(mTbmQueue);
+ mHeight = tbm_surface_queue_get_height(mTbmQueue);
}
}
NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
{
- if( mOwnTbmQueue )
+ if(mOwnTbmQueue)
{
- DestroyQueue();
+ if(mTbmQueue != NULL)
+ {
+ tbm_surface_queue_destroy(mTbmQueue);
+ }
}
}
-void NativeImageSourceQueueTizen::Initialize( Dali::NativeImageSourceQueue::ColorDepth depth )
+void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorFormat colorFormat)
{
- if( mTbmQueue != NULL || mWidth == 0 || mHeight == 0 )
+ if(mWidth == 0 || mHeight == 0)
{
return;
}
- int format = TBM_FORMAT_ARGB8888;
-
- switch( depth )
+ if(mTbmQueue == NULL)
{
- case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
- case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
- {
- format = TBM_FORMAT_ARGB8888;
- mBlendingRequired = true;
- break;
- }
- case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
+ int tbmFormat = TBM_FORMAT_ARGB8888;
+
+ switch(colorFormat)
{
- format = TBM_FORMAT_RGB888;
- mBlendingRequired = false;
- break;
+ case Dali::NativeImageSourceQueue::ColorFormat::RGBA8888:
+ {
+ tbmFormat = TBM_FORMAT_ARGB8888;
+ mBlendingRequired = true;
+ break;
+ }
+ case Dali::NativeImageSourceQueue::ColorFormat::RGBX8888:
+ {
+ tbmFormat = TBM_FORMAT_XRGB8888;
+ mBlendingRequired = false;
+ break;
+ }
+ case Dali::NativeImageSourceQueue::ColorFormat::RGB888:
+ {
+ tbmFormat = TBM_FORMAT_RGB888;
+ mBlendingRequired = false;
+ break;
+ }
+ default:
+ {
+ DALI_LOG_WARNING("Wrong color format.\n");
+ return;
+ }
}
- default:
+
+ mTbmQueue = tbm_surface_queue_create(TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, tbmFormat, 0);
+ if(!mTbmQueue)
{
- DALI_LOG_WARNING( "Wrong color depth.\n" );
+ DALI_LOG_ERROR("NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue);
return;
}
- }
- mTbmQueue = tbm_surface_queue_create( TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0 );
-
- mOwnTbmQueue = true;
+ mOwnTbmQueue = true;
+ }
}
-tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny( Any source ) const
+tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny(Any source) const
{
- if( source.Empty() )
+ if(source.Empty())
{
return NULL;
}
- if( source.GetType() == typeid( tbm_surface_queue_h ) )
+ if(source.GetType() == typeid(tbm_surface_queue_h))
{
- return AnyCast< tbm_surface_queue_h >( source );
+ return AnyCast<tbm_surface_queue_h>(source);
}
else
{
Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
{
- return Any( mTbmQueue );
+ return Any(mTbmQueue);
}
-void NativeImageSourceQueueTizen::SetSource( Any source )
+void NativeImageSourceQueueTizen::SetSize(uint32_t width, uint32_t height)
{
- if( mOwnTbmQueue )
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mWidth == width && mHeight == height)
{
- DestroyQueue();
+ return;
}
- mTbmQueue = GetSurfaceFromAny( source );
+ tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
+
+ mWidth = width;
+ mHeight = height;
+ mIsResized = true;
+}
+
+void NativeImageSourceQueueTizen::IgnoreSourceImage()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ tbm_surface_h surface;
+
+ if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
+ {
+ if(tbm_surface_queue_acquire(mTbmQueue, &surface) != TBM_SURFACE_QUEUE_ERROR_NONE)
+ {
+ DALI_LOG_ERROR("NativeImageSourceQueueTizen::IgnoreSourceImage: Failed to aquire a tbm_surface\n");
+ return;
+ }
+
+ if(tbm_surface_internal_is_valid(surface))
+ {
+ tbm_surface_queue_release(mTbmQueue, surface);
+ }
+ }
+}
- if( mTbmQueue != NULL )
+bool NativeImageSourceQueueTizen::CanDequeueBuffer()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ if(tbm_surface_queue_can_dequeue(mTbmQueue, 0))
{
- mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
- mWidth = tbm_surface_queue_get_width( mTbmQueue );
- mHeight = tbm_surface_queue_get_height( mTbmQueue );
+ return true;
}
+ return false;
}
-bool NativeImageSourceQueueTizen::GlExtensionCreate()
+uint8_t* NativeImageSourceQueueTizen::DequeueBuffer(uint32_t& width, uint32_t& height, uint32_t& stride)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ if(mTbmQueue == NULL)
+ {
+ DALI_LOG_ERROR("TbmQueue is NULL");
+ return NULL;
+ }
+
+ tbm_surface_h tbmSurface;
+ if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
+ {
+ DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", tbmSurface);
+ return NULL;
+ }
+
+ tbm_surface_info_s info;
+ int ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
+ if(ret != TBM_SURFACE_ERROR_NONE)
+ {
+ DALI_LOG_ERROR("tbm_surface_map is failed! [%d] [%p]\n", ret, tbmSurface);
+ tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
+ return NULL;
+ }
+
+ unsigned char* buffer = info.planes[0].ptr;
+ if(!buffer)
+ {
+ DALI_LOG_ERROR("tbm buffer pointer is null! [%p]\n", tbmSurface);
+ tbm_surface_unmap(tbmSurface);
+ tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
+ return NULL;
+ }
+
+ tbm_surface_internal_ref(tbmSurface);
+
+ stride = info.planes[0].stride;
+ width = mWidth;
+ height = mHeight;
+
+ // Push the buffer
+ mBuffers.push_back(BufferPair(tbmSurface, buffer));
+ return buffer;
+}
+
+bool NativeImageSourceQueueTizen::EnqueueBuffer(uint8_t* buffer)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ auto bufferInstance = std::find_if(mBuffers.begin(),
+ mBuffers.end(),
+ [buffer](BufferPair pair) { return (pair.second == buffer); });
+ if(bufferInstance != mBuffers.end())
+ {
+ tbm_surface_internal_unref((*bufferInstance).first);
+ tbm_surface_unmap((*bufferInstance).first);
+ tbm_surface_queue_enqueue(mTbmQueue, (*bufferInstance).first);
+ mBuffers.erase(bufferInstance);
+ return true;
+ }
+ return false;
+}
+
+bool NativeImageSourceQueueTizen::CreateResource()
{
mEglImageExtensions = mEglGraphics->GetImageExtensions();
- DALI_ASSERT_DEBUG( mEglImageExtensions );
+ DALI_ASSERT_DEBUG(mEglImageExtensions);
return true;
}
-void NativeImageSourceQueueTizen::GlExtensionDestroy()
+void NativeImageSourceQueueTizen::DestroyResource()
{
- for( auto&& iter : mEglImages )
- {
- mEglImageExtensions->DestroyImageKHR( iter.second );
+ Dali::Mutex::ScopedLock lock(mMutex);
- tbm_surface_internal_unref( iter.first );
- }
- mEglImages.clear();
+ ResetEglImageList(true);
}
-unsigned int NativeImageSourceQueueTizen::TargetTexture()
+uint32_t NativeImageSourceQueueTizen::TargetTexture()
{
return 0;
}
void NativeImageSourceQueueTizen::PrepareTexture()
{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
tbm_surface_h oldSurface = mConsumeSurface;
- if( tbm_surface_queue_can_acquire( mTbmQueue, 0 ) )
+ if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
{
- if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
+ if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
{
- DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
+ DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
return;
}
- if( oldSurface )
+ if(oldSurface)
{
- if( tbm_surface_internal_is_valid( oldSurface ) )
+ if(tbm_surface_internal_is_valid(oldSurface))
{
- tbm_surface_queue_release( mTbmQueue, oldSurface );
+ tbm_surface_queue_release(mTbmQueue, oldSurface);
}
}
- if( mConsumeSurface )
+ if(mIsResized)
+ {
+ ResetEglImageList(false);
+ mIsResized = false;
+ }
+
+ if(mConsumeSurface)
{
bool existing = false;
- for( auto&& iter : mEglImages )
+ for(auto&& iter : mEglImages)
{
- if( iter.first == mConsumeSurface )
+ if(iter.first == mConsumeSurface)
{
// Find the surface in the existing list
existing = true;
- mEglImageExtensions->TargetTextureKHR( iter.second );
+ mEglImageExtensions->TargetTextureKHR(iter.second);
break;
}
}
- if( !existing )
+ if(!existing)
{
// Push the surface
- tbm_surface_internal_ref( mConsumeSurface );
+ tbm_surface_internal_ref(mConsumeSurface);
- void* eglImageKHR = mEglImageExtensions->CreateImageKHR( reinterpret_cast< EGLClientBuffer >( mConsumeSurface ) );
- mEglImageExtensions->TargetTextureKHR( eglImageKHR );
+ void* eglImageKHR = mEglImageExtensions->CreateImageKHR(reinterpret_cast<EGLClientBuffer>(mConsumeSurface));
+ mEglImageExtensions->TargetTextureKHR(eglImageKHR);
- mEglImages.push_back( EglImagePair( mConsumeSurface, eglImageKHR) );
+ mEglImages.push_back(EglImagePair(mConsumeSurface, eglImageKHR));
}
}
}
}
-const char* NativeImageSourceQueueTizen::GetCustomFragmentPreFix()
+bool NativeImageSourceQueueTizen::ApplyNativeFragmentShader(std::string& shader)
{
- return FRAGMENT_PREFIX;
+ return mEglGraphics->ApplyNativeFragmentShader(shader, SAMPLER_TYPE);
}
-const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename()
+const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
{
return SAMPLER_TYPE;
}
-int NativeImageSourceQueueTizen::GetEglImageTextureTarget()
+int NativeImageSourceQueueTizen::GetTextureTarget() const
{
return GL_TEXTURE_EXTERNAL_OES;
}
-void NativeImageSourceQueueTizen::DestroyQueue()
+Any NativeImageSourceQueueTizen::GetNativeImageHandle() const
{
- if( mConsumeSurface )
- {
- tbm_surface_internal_unref( mConsumeSurface );
+ return nullptr;
+}
+
+bool NativeImageSourceQueueTizen::SourceChanged() const
+{
+ return false;
+}
- if( tbm_surface_internal_is_valid( mConsumeSurface ) )
+void NativeImageSourceQueueTizen::ResetEglImageList(bool releaseConsumeSurface)
+{
+ // When Tbm surface queue is reset(resized), the surface acquired before reset() is still valid, not the others.
+ // We can still use the acquired surface so that we will release it as the oldSurface in PrepareTexture() when the next surface is ready.
+ if(releaseConsumeSurface && mConsumeSurface)
+ {
+ if(tbm_surface_internal_is_valid(mConsumeSurface))
{
- tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
+ tbm_surface_queue_release(mTbmQueue, mConsumeSurface);
}
+ mConsumeSurface = NULL;
}
- if( mTbmQueue != NULL )
+ for(auto&& iter : mEglImages)
{
- tbm_surface_queue_destroy( mTbmQueue );
- }
+ mEglImageExtensions->DestroyImageKHR(iter.second);
- mTbmQueue = NULL;
- mOwnTbmQueue = false;
+ tbm_surface_internal_unref(iter.first);
+ }
+ mEglImages.clear();
}
-bool NativeImageSourceQueueTizen::CheckBlending( int format )
+bool NativeImageSourceQueueTizen::CheckBlending(int format)
{
- for( int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i )
+ for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
{
- if( format == FORMATS_BLENDING_REQUIRED[i] )
+ if(format == FORMATS_BLENDING_REQUIRED[i])
{
return true;
}
} // namespace Adaptor
-} // namespace internal
+} // namespace Internal
} // namespace Dali