/*
- * Copyright (c) 2020 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 <dali/internal/imaging/ubuntu-x11/native-image-source-impl-x.h>
// EXTERNAL INCLUDES
-#include <dali/internal/system/linux/dali-ecore-x.h>
-#include <X11/Xutil.h>
#include <X11/Xlib.h>
+#include <X11/Xutil.h>
#include <dali/integration-api/debug.h>
+#include <dali/internal/system/linux/dali-ecore-x.h>
// INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/render-surface-interface.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>
-#include <dali/internal/adaptor/common/adaptor-impl.h>
-#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
namespace Dali
{
-
namespace Internal
{
-
namespace Adaptor
{
using Dali::Integration::PixelBuffer;
// Pieces needed to save compressed images (temporary location while plumbing):
namespace
{
-
- /**
+/**
* Free an allocated XImage on destruction.
*/
- struct XImageJanitor
+struct XImageJanitor
+{
+ XImageJanitor(XImage* const pXImage)
+ : mXImage(pXImage)
{
- XImageJanitor( XImage* const pXImage ) : mXImage( pXImage )
- {
- DALI_ASSERT_DEBUG(pXImage != 0 && "Null pointer to XImage.");
- }
+ DALI_ASSERT_DEBUG(pXImage != 0 && "Null pointer to XImage.");
+ }
- ~XImageJanitor()
+ ~XImageJanitor()
+ {
+ if(mXImage)
{
- if( mXImage )
+ if(!XDestroyImage(mXImage))
{
- if( !XDestroyImage(mXImage) )
- {
- DALI_LOG_ERROR("XImage deallocation failure");
- }
+ DALI_LOG_ERROR("XImage deallocation failure");
}
}
- XImage* const mXImage;
- private:
- XImageJanitor( const XImageJanitor& rhs );
- XImageJanitor& operator = ( const XImageJanitor& rhs );
- };
-}
+ }
+ XImage* const mXImage;
+
+private:
+ XImageJanitor(const XImageJanitor& rhs);
+ XImageJanitor& operator=(const XImageJanitor& rhs);
+};
+} // namespace
-NativeImageSourceX* NativeImageSourceX::New( uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
+NativeImageSourceX* NativeImageSourceX::New(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
{
- NativeImageSourceX* image = new NativeImageSourceX( width, height, depth, nativeImageSource );
- DALI_ASSERT_DEBUG( image && "NativeImageSource allocation failed." );
+ NativeImageSourceX* image = new NativeImageSourceX(width, height, depth, nativeImageSource);
+ DALI_ASSERT_DEBUG(image && "NativeImageSource allocation failed.");
// 2nd phase construction
if(image) //< Defensive in case we ever compile without exceptions.
return image;
}
-NativeImageSourceX::NativeImageSourceX( uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
-: mWidth( width ),
- mHeight( height ),
- mOwnPixmap( true ),
- mPixmap( 0 ),
- mBlendingRequired( false ),
- mColorDepth( depth ),
- mEglImageKHR( NULL ),
- mEglImageExtensions( NULL )
+NativeImageSourceX::NativeImageSourceX(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
+: mWidth(width),
+ mHeight(height),
+ mOwnPixmap(true),
+ mPixmap(0),
+ mBlendingRequired(false),
+ mColorDepth(depth),
+ mEglImageKHR(NULL),
+ mEglImageExtensions(NULL),
+ mResourceDestructionCallback()
{
- DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
+ DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
- GraphicsInterface* graphics = &( Adaptor::GetImplementation( Adaptor::Get() ).GetGraphicsInterface() );
- auto eglGraphics = static_cast<EglGraphics *>(graphics);
+ GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
+ auto eglGraphics = static_cast<EglGraphics*>(graphics);
mEglImageExtensions = eglGraphics->GetImageExtensions();
- DALI_ASSERT_DEBUG( mEglImageExtensions );
+ DALI_ASSERT_DEBUG(mEglImageExtensions);
// assign the pixmap
mPixmap = GetPixmapFromAny(nativeImageSource);
void NativeImageSourceX::Initialize()
{
// if pixmap has been created outside of X11 Image we can return
- if (mPixmap)
+ if(mPixmap)
{
// we don't own the pixmap
mOwnPixmap = false;
If depth = 8, Pixel::A8;
If depth = 16, Pixel::RGB565;
If depth = 32, Pixel::RGBA8888 */
- mBlendingRequired = ( depth == 32 || depth == 8 );
+ mBlendingRequired = (depth == 32 || depth == 8);
- mPixmap = ecore_x_pixmap_new( 0, mWidth, mHeight, depth );
+ mPixmap = ecore_x_pixmap_new(0, mWidth, mHeight, depth);
ecore_x_sync();
}
NativeImageSourceX::~NativeImageSourceX()
{
- if (mOwnPixmap && mPixmap)
+ if(mOwnPixmap && mPixmap)
{
- ecore_x_pixmap_free(mPixmap);
+ // Temporarily disable this as this causes a crash with EFL Version 1.24.0
+ //ecore_x_pixmap_free(mPixmap);
}
}
{
DALI_ASSERT_DEBUG(sizeof(unsigned) == 4);
bool success = false;
- width = mWidth;
- height = mHeight;
+ width = mWidth;
+ height = mHeight;
// Open a display connection
- Display* displayConnection = XOpenDisplay( 0 );
-
- XImageJanitor xImageJanitor( XGetImage( displayConnection,
- mPixmap,
- 0, 0, // x,y of subregion to extract.
- width, height, // of subregion to extract.
- 0xFFFFFFFF,
- ZPixmap ) );
- XImage* const pXImage = xImageJanitor.mXImage;
+ Display* displayConnection = XOpenDisplay(0);
+
+ XImageJanitor xImageJanitor(XGetImage(displayConnection,
+ mPixmap,
+ 0,
+ 0, // x,y of subregion to extract.
+ width,
+ height, // of subregion to extract.
+ 0xFFFFFFFF,
+ ZPixmap));
+ XImage* const pXImage = xImageJanitor.mXImage;
DALI_ASSERT_DEBUG(pXImage && "XImage (from pixmap) could not be retrieved from the server");
if(!pXImage)
{
case 24:
{
pixelFormat = Pixel::RGB888;
- pixbuf.resize(width*height*3);
+ pixbuf.resize(width * height * 3);
unsigned char* bufPtr = &pixbuf[0];
- for(unsigned y = height-1; y < height; --y)
+ for(unsigned y = 0; y < height; ++y)
{
- for(unsigned x = 0; x < width; ++x, bufPtr+=3)
+ for(unsigned x = 0; x < width; ++x, bufPtr += 3)
{
- const unsigned pixel = XGetPixel(pXImage,x,y);
+ const unsigned pixel = XGetPixel(pXImage, x, y);
// store as RGB
- const unsigned blue = pixel & 0xFFU;
- const unsigned green = (pixel >> 8) & 0xFFU;
+ const unsigned blue = pixel & 0xFFU;
+ const unsigned green = (pixel >> 8) & 0xFFU;
const unsigned red = (pixel >> 16) & 0xFFU;
- *bufPtr = red;
- *(bufPtr+1) = green;
- *(bufPtr+2) = blue;
+ *bufPtr = red;
+ *(bufPtr + 1) = green;
+ *(bufPtr + 2) = blue;
}
}
success = true;
{
// Sweep through the image, doing a vertical flip, but handling each scanline as
// an inlined intrinsic/builtin memcpy (should be fast):
- pixbuf.resize(width*height*4);
- unsigned * bufPtr = reinterpret_cast<unsigned *>(&pixbuf[0]);
+ pixbuf.resize(width * height * 4);
+ unsigned* bufPtr = reinterpret_cast<unsigned*>(&pixbuf[0]);
const unsigned xDataLineSkip = pXImage->bytes_per_line;
- const size_t copy_count = static_cast< size_t >( width ) * 4;
- pixelFormat = Pixel::BGRA8888;
+ const size_t copy_count = static_cast<size_t>(width) * 4;
+ pixelFormat = Pixel::BGRA8888;
- for(unsigned y = height-1; y < height; --y, bufPtr += width)
+ for(unsigned y = 0; y < height; ++y, bufPtr += width)
{
- const char * const in = pXImage->data + xDataLineSkip * y;
+ const char* const in = pXImage->data + xDataLineSkip * y;
// Copy a whole scanline at a time:
- DALI_ASSERT_DEBUG( size_t( bufPtr ) >= size_t( &pixbuf[0] ));
- DALI_ASSERT_DEBUG( reinterpret_cast<size_t>( bufPtr ) + copy_count <= reinterpret_cast<size_t>( &pixbuf[pixbuf.size()] ) );
- DALI_ASSERT_DEBUG( in >= pXImage->data );
- DALI_ASSERT_DEBUG( in + copy_count <= pXImage->data + xDataLineSkip * height );
- __builtin_memcpy( bufPtr, in, copy_count );
+ DALI_ASSERT_DEBUG(size_t(bufPtr) >= size_t(&pixbuf[0]));
+ DALI_ASSERT_DEBUG(reinterpret_cast<size_t>(bufPtr) + copy_count <= reinterpret_cast<size_t>(&pixbuf[pixbuf.size()]));
+ DALI_ASSERT_DEBUG(in >= pXImage->data);
+ DALI_ASSERT_DEBUG(in + copy_count <= pXImage->data + xDataLineSkip * height);
+ __builtin_memcpy(bufPtr, in, copy_count);
}
success = true;
}
{
DALI_LOG_ERROR("Failed to get pixels from NativeImageSource.\n");
pixbuf.resize(0);
- width = 0;
+ width = 0;
height = 0;
}
// Close the display connection
- XCloseDisplay( displayConnection );
+ XCloseDisplay(displayConnection);
return success;
}
-void NativeImageSourceX::SetSource( Any source )
+void NativeImageSourceX::SetSource(Any source)
{
- mPixmap = GetPixmapFromAny( source );
+ mPixmap = GetPixmapFromAny(source);
- if (mPixmap)
+ if(mPixmap)
{
// we don't own the pixmap
mOwnPixmap = false;
}
}
-bool NativeImageSourceX::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
+bool NativeImageSourceX::IsColorDepthSupported(Dali::NativeImageSource::ColorDepth colorDepth)
{
return true;
}
-bool NativeImageSourceX::GlExtensionCreate()
+bool NativeImageSourceX::CreateResource()
{
// if the image existed previously delete it.
- if (mEglImageKHR != NULL)
+ if(mEglImageKHR != NULL)
{
- GlExtensionDestroy();
+ DestroyResource();
}
// casting from an unsigned int to a void *, which should then be cast back
// to an unsigned int in the driver.
- EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer > (mPixmap);
+ EGLClientBuffer eglBuffer = reinterpret_cast<EGLClientBuffer>(mPixmap);
- mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );
+ mEglImageKHR = mEglImageExtensions->CreateImageKHR(eglBuffer);
return mEglImageKHR != NULL;
}
-void NativeImageSourceX::GlExtensionDestroy()
+void NativeImageSourceX::DestroyResource()
{
mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
mEglImageKHR = NULL;
+
+ if(mResourceDestructionCallback)
+ {
+ mResourceDestructionCallback->Trigger();
+ }
}
uint32_t NativeImageSourceX::TargetTexture()
int NativeImageSourceX::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const
{
- switch (depth)
+ switch(depth)
{
case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
{
}
}
+int NativeImageSourceX::GetTextureTarget() const
+{
+ return GL_TEXTURE_2D;
+}
+
+bool NativeImageSourceX::ApplyNativeFragmentShader(std::string& shader)
+{
+ return false;
+}
+
+const char* NativeImageSourceX::GetCustomSamplerTypename() const
+{
+ return nullptr;
+}
+
+Any NativeImageSourceX::GetNativeImageHandle() const
+{
+ return Any(mPixmap);
+}
+
+bool NativeImageSourceX::SourceChanged() const
+{
+ return false;
+}
+
Ecore_X_Pixmap NativeImageSourceX::GetPixmapFromAny(Any pixmap) const
{
- if (pixmap.Empty())
+ if(pixmap.Empty())
{
return 0;
}
// see if it is of type x11 pixmap
- if (pixmap.GetType() == typeid (Pixmap))
+ if(pixmap.GetType() == typeid(Pixmap))
{
// get the x pixmap type
Pixmap xpixmap = AnyCast<Pixmap>(pixmap);
int x, y;
// get the width, height and depth
- ecore_x_pixmap_geometry_get( mPixmap, &x, &y, reinterpret_cast< int* >( &mWidth ), reinterpret_cast< int* >( &mHeight ) );
+ ecore_x_pixmap_geometry_get(mPixmap, &x, &y, reinterpret_cast<int*>(&mWidth), reinterpret_cast<int*>(&mHeight));
// set whether blending is required according to pixel format based on the depth
/* default pixel format is RGB888
If depth = 8, Pixel::A8;
If depth = 16, Pixel::RGB565;
If depth = 32, Pixel::RGBA8888 */
- int depth = ecore_x_pixmap_depth_get(mPixmap);
- mBlendingRequired = ( depth == 32 || depth == 8 );
+ int depth = ecore_x_pixmap_depth_get(mPixmap);
+ mBlendingRequired = (depth == 32 || depth == 8);
}
-uint8_t* NativeImageSourceX::AcquireBuffer( uint16_t& width, uint16_t& height, uint16_t& stride )
+uint8_t* NativeImageSourceX::AcquireBuffer(uint16_t& width, uint16_t& height, uint16_t& stride)
{
return NULL;
}
-
bool NativeImageSourceX::ReleaseBuffer()
{
return false;
}
+void NativeImageSourceX::SetResourceDestructionCallback(EventThreadCallback* callback)
+{
+ mResourceDestructionCallback = std::unique_ptr<EventThreadCallback>(callback);
+}
+
} // namespace Adaptor
-} // namespace internal
+} // namespace Internal
} // namespace Dali