utc-Dali-HitTestAlgorithm.cpp
utc-Dali-Material.cpp
utc-Dali-Mutex.cpp
+ utc-Dali-PixelData.cpp
utc-Dali-PropertyBuffer.cpp
utc-Dali-Renderer.cpp
utc-Dali-Sampler.cpp
#include <dali/public-api/dali-core.h>
#include <dali/integration-api/bitmap.h>
#include <dali/devel-api/images/atlas.h>
+#include <dali/devel-api/images/pixel-data.h>
#include <dali-test-suite-utils.h>
#include <test-native-image.h>
{
static const char* gTestImageFilename = "icon_wrt.png";
-void PrepareResourceImage( TestApplication& application, unsigned int imageHeight, unsigned int imageWidth, Pixel::Format pixelFormat )
+void PrepareResourceImage( TestApplication& application, unsigned int imageWidth, unsigned int imageHeight, Pixel::Format pixelFormat )
{
TestPlatformAbstraction& platform = application.GetPlatform();
- platform.SetClosestImageSize(Vector2( 16, 16));
+ platform.SetClosestImageSize(Vector2( imageWidth, imageHeight));
Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight );
platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
}
+PixelDataPtr CreatePixelData(unsigned int width, unsigned int height, Pixel::Format pixelFormat)
+{
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( pixelFormat );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+
+ return new PixelData( buffer, width, height, pixelFormat, PixelData::DELETE_ARRAY );
+}
+
}
void utc_dali_atlas_startup(void)
test_return_value = TET_PASS;
}
-// 1.1
-int UtcDaliAtlasNew01(void)
+int UtcDaliAtlasNew(void)
{
TestApplication application;
END_TEST;
}
+int UtcDaliAtlasCopyConstructor(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 16, 16);
+ Atlas atlasCopy(atlas);
+
+
+ DALI_TEST_EQUALS( (bool)atlasCopy, true, TEST_LOCATION );
+ END_TEST;
+}
-// 1.2
-int UtcDaliAtlasUpload01(void)
+int UtcDaliAtlasAssignmentOperator(void)
{
TestApplication application;
- Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
- DALI_TEST_CHECK( atlas );
+ Atlas atlas = Atlas::New( 16, 16);
- // Using correct pixel format
- PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
- BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
- DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+ Atlas atlas2;
+ DALI_TEST_EQUALS( (bool)atlas2, false, TEST_LOCATION );
- PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
- DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
+ atlas2 = atlas;
+ DALI_TEST_EQUALS( (bool)atlas2, true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliAtlasDownCast(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 16, 16);
+
+ BaseHandle handle(atlas);
+ Atlas atlasDowncast = Atlas::DownCast(handle);
+ DALI_TEST_EQUALS( (bool)atlasDowncast, true, TEST_LOCATION );
+
+ Handle handle2 = Handle::New(); // Create a custom object
+ Atlas atlas2 = Atlas::DownCast(handle2);
+ DALI_TEST_EQUALS( (bool)atlas2, false, TEST_LOCATION );
END_TEST;
}
-// 1.3
-int UtcDaliAtlasUpload02(void)
+int UtcDaliAtlasClear(void)
{
TestApplication application;
- Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+ Atlas atlas = Atlas::New( 16, 32, Pixel::RGBA8888 );
DALI_TEST_CHECK( atlas );
- // Using INCORRECT pixel format
- PixelBuffer* buffer = new PixelBuffer[16 * 16];
- BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::A8 );
- DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+ atlas.Clear(Color::TRANSPARENT);
+
+ TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+ callStack.Reset();
+ callStack.Enable(true);
+ application.SendNotification();
+ application.Render(16);
+ application.Render(16);
+ application.SendNotification();
+ application.Render(16);
+ application.SendNotification();
+ callStack.Enable(false);
- PrepareResourceImage( application, 16, 16, Pixel::A8 );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 16, 32") );
END_TEST;
}
-// 1.4
-int UtcDaliAtlasUpload03(void)
+
+// Upload resource image, buffer image & pixel data with same pixel format
+int UtcDaliAtlasUpload01P(void)
{
TestApplication application;
- Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+ Atlas atlas = Atlas::New( 16, 40, Pixel::RGBA8888 );
DALI_TEST_CHECK( atlas );
- // Using image too big for atlas
+ // Using same pixel format
PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
- DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+ DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 16 ) );
+
+ PixelDataPtr pixelData = CreatePixelData( 6,8,Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas.Upload( pixelData, 2, 32 ) );
+
+ TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+ callStack.Reset();
+ callStack.Enable(true);
+ application.SendNotification();
+ application.Render(16);
+ application.Render(16);
+ application.SendNotification();
+ application.Render(16);
+ application.SendNotification();
+ callStack.Enable(false);
+
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 16, 16") );
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 16, 16, 16") );
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "2, 32, 6, 8") );
END_TEST;
}
-// 1.5
-int UtcDaliAtlasUpload04(void)
+// Upload resource image, buffer image & pixel data with different pixel format
+int UtcDaliAtlasUpload02P(void)
{
TestApplication application;
- Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+ Atlas atlas = Atlas::New( 20, 20, Pixel::RGBA8888 );
DALI_TEST_CHECK( atlas );
- // Using valid offsets
- PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
- BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+ // Using different pixel format
+ PixelBuffer* buffer = new PixelBuffer[16 * 16 * 3];
+ BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGB888 );
+ DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
- DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
- DALI_TEST_CHECK( atlas.Upload( image, 16, 0 ) );
- DALI_TEST_CHECK( atlas.Upload( image, 0, 16 ) );
- DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
+ PrepareResourceImage( application, 12, 12, Pixel::A8 );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 6, 6 ) );
- PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
- DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
- DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 0 ) );
- DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 16 ) );
- DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 16 ) );
+ PixelDataPtr pixelData = CreatePixelData( 8,8,Pixel::LA88 );
+ DALI_TEST_CHECK( atlas.Upload( pixelData, 10, 10 ) );
+
+ TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+ callStack.Reset();
+ callStack.Enable(true);
+ application.SendNotification();
+ application.Render(16);
+ application.Render(16);
+ application.SendNotification();
+ application.Render(16);
+ application.SendNotification();
+ callStack.Enable(false);
+
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 16, 16") );
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "6, 6, 12, 12") );
+ DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "10, 10, 8, 8") );
END_TEST;
}
-// 1.6
-int UtcDaliAtlasUpload05(void)
+// Upload resource image, buffer image & pixel data which cannot fit into the atlas with given offset
+int UtcDaliAtlasUploadN(void)
{
TestApplication application;
- Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+ Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
DALI_TEST_CHECK( atlas );
- // Using invalid offsets
- PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
- BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-
- DALI_TEST_CHECK( !atlas.Upload( image, 0, 17 ) );
- DALI_TEST_CHECK( !atlas.Upload( image, 17, 0 ) );
- DALI_TEST_CHECK( !atlas.Upload( image, 17, 17 ) );
- DALI_TEST_CHECK( !atlas.Upload( image, 99, 0 ) );
- DALI_TEST_CHECK( !atlas.Upload( image, 0, 99 ) );
- DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
+ // Using image cannot fit into atlas at the given offsets
+ PixelBuffer* buffer = new PixelBuffer[24 * 24 * 4];
+ BufferImage image = BufferImage::New( buffer, 24, 24, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
-
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 17 ) );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 0 ) );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 17 ) );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 0 ) );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 99 ) );
- DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 99 ) );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 10, 10 ) );
+
+ PixelDataPtr pixelData = CreatePixelData( 6,6,Pixel::RGBA8888 );
+ DALI_TEST_CHECK( !atlas.Upload( pixelData, 11, 11 ) );
+
+ TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+ callStack.Reset();
+ callStack.Enable(true);
+ application.SendNotification();
+ application.Render(16);
+ application.Render(16);
+ application.SendNotification();
+ application.Render(16);
+ application.SendNotification();
+ callStack.Enable(false);
+
+ // none of these three upload() call sends texture to GPU
+ DALI_TEST_CHECK( ! callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 24, 24") );
+ DALI_TEST_CHECK( ! callStack.FindMethodAndParams("TexSubImage2D", "10, 10, 16, 16") );
+ DALI_TEST_CHECK( ! callStack.FindMethodAndParams("TexSubImage2D", "11, 11, 6, 6") );
END_TEST;
}
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <cstdlib>
+#include <dali-test-suite-utils.h>
+
+#include <dali/devel-api/images/pixel-data.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/common/dali-vector.h>
+
+using namespace Dali;
+
+int UtcDaliPixelData01(void)
+{
+ TestApplication application;
+
+ unsigned int width = 10u;
+ unsigned int height = 10u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::RGB888 );
+
+ unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( bufferSize ) );
+ PixelDataPtr pixelData = PixelData::New( buffer, width, height, Pixel::RGB888, PixelData::FREE );
+
+ DALI_TEST_CHECK( pixelData );
+ DALI_TEST_CHECK( pixelData->GetWidth() == width );
+ DALI_TEST_CHECK( pixelData->GetHeight() == height );
+ DALI_TEST_CHECK( pixelData->GetPixelFormat() == Pixel::RGB888 );
+ DALI_TEST_CHECK( pixelData->GetBuffer() == buffer );
+
+ END_TEST;
+}
+
+int UtcDaliPixelData02(void)
+{
+ TestApplication application;
+
+ unsigned int width = 10u;
+ unsigned int height = 10u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+ buffer[0] = 'a';
+
+ PixelDataPtr pixelData2 = PixelData::New( buffer, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+ DALI_TEST_CHECK( pixelData2 );
+ DALI_TEST_CHECK( pixelData2->GetBuffer()[0] == 'a' );
+
+ buffer[0] = 'b';
+ DALI_TEST_CHECK( pixelData2->GetBuffer()[0] == 'b' );
+
+ END_TEST;
+}
+
+int UtcDaliPixelDataNonCopyable(void)
+{
+ // we want to make sure that PixelData is not copyable (its copy constructor is not defined)
+ // this test will stop compiling if PixelData has compiler generated copy constructor
+ DALI_COMPILE_TIME_ASSERT( !__has_trivial_copy( PixelData ) );
+
+ DALI_TEST_CHECK( true );
+ END_TEST;
+}
[enable_lock_backtrace=$enableval],
[enable_lock_backtrace=no])
+AC_ARG_ENABLE([gles],
+ [AC_HELP_STRING([--enable-gles],
+ [Specify the OpenGL ES version for backwards compatibility])],
+ [enable_gles=$enableval],
+ [enable_gles=20])
+
+DALI_CFLAGS="$DALI_CFLAGS -DDALI_GLES_VERSION=${enable_gles}"
+
if test "x$enable_debug" = "xyes"; then
DALI_CFLAGS="$DALI_CFLAGS -DDEBUG_ENABLED"
fi
$(devel_api_src_dir)/events/hit-test-algorithm.cpp \
$(devel_api_src_dir)/images/atlas.cpp \
$(devel_api_src_dir)/images/distance-field.cpp \
+ $(devel_api_src_dir)/images/pixel-data.cpp \
$(devel_api_src_dir)/object/property-buffer.cpp \
$(devel_api_src_dir)/object/weak-handle.cpp \
$(devel_api_src_dir)/rendering/cull-face.cpp \
devel_api_core_images_header_files = \
$(devel_api_src_dir)/images/atlas.h \
- $(devel_api_src_dir)/images/distance-field.h
+ $(devel_api_src_dir)/images/distance-field.h \
+ $(devel_api_src_dir)/images/pixel-data.h
devel_api_core_object_header_files = \
$(devel_api_src_dir)/object/property-buffer.h \
return GetImplementation(*this).Upload( url, xOffset, yOffset );
}
+bool Atlas::Upload( PixelDataPtr pixelData,
+ SizeType xOffset,
+ SizeType yOffset )
+{
+ return GetImplementation(*this).Upload( pixelData, xOffset, yOffset );
+}
+
Atlas Atlas::DownCast( BaseHandle handle )
{
return Atlas( dynamic_cast<Dali::Internal::Atlas*>(handle.GetObjectPtr()) );
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/images/image.h>
#include <dali/public-api/images/buffer-image.h>
+#include <dali/devel-api/images/pixel-data.h>
namespace Dali
{
* Images must be uploaded at a specified position, to populate the Atlas.
* The client is responsible for generating the appropriate geometry (UV coordinates) needed to draw images within the Atlas.
*
+ * @note For gles 2.0, matched pixel format is demanded to ensure the correct atlasing.
+ * The only exception supported is uploading image of RGB888 to atlas of RGBA8888 format which is converted manually before pushing to GPU.
+ *
* For context recovery after loss:
* By default, the atlas will re-upload the resource images automatically,
* while the buffer images are left to the client to upload again by connecting to the Stage::ContextRegainedSignal().
bool Upload( const std::string& url,
SizeType xOffset,
SizeType yOffset );
+
+ /**
+ * @brief Upload a pixel buffer to atlas
+ *
+ * @param [in] pixelData The pixel data.
+ * @param [in] xOffset Specifies an offset in the x direction within the atlas.
+ * @param [in] yOffset Specifies an offset in the y direction within the atlas.
+ */
+ bool Upload( PixelDataPtr pixelData,
+ SizeType xOffset,
+ SizeType yOffset );
/**
* @brief Downcast an Object handle to Atlas.
*
--- /dev/null
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "pixel-data.h"
+
+// EXTERNAL INLCUDES
+#include <stdlib.h>
+
+namespace Dali
+{
+
+PixelData::PixelData( unsigned char* buffer,
+ unsigned int width,
+ unsigned int height,
+ Pixel::Format pixelFormat,
+ ReleaseFunction releaseFunction )
+: mBuffer( buffer ),
+ mWidth( width ),
+ mHeight( height ),
+ mPixelFormat( pixelFormat ),
+ mReleaseFunction( releaseFunction )
+{
+}
+
+PixelData::~PixelData()
+{
+ if( mBuffer )
+ {
+ if( mReleaseFunction == FREE)
+ {
+ free( mBuffer );
+ }
+ else
+ {
+ delete[] mBuffer;
+ }
+ }
+ }
+
+PixelDataPtr PixelData::New(unsigned char* buffer,
+ unsigned int width,
+ unsigned int height,
+ Pixel::Format pixelFormat,
+ ReleaseFunction releaseFunction)
+{
+ return new PixelData( buffer, width, height, pixelFormat, releaseFunction );
+}
+
+unsigned int PixelData::GetWidth() const
+{
+ return mWidth;
+}
+
+unsigned int PixelData::GetHeight() const
+{
+ return mHeight;
+}
+
+Pixel::Format PixelData::GetPixelFormat() const
+{
+ return mPixelFormat;
+}
+
+unsigned char* PixelData::GetBuffer() const
+{
+ return mBuffer;
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_PIXEL_DATA_H__
+#define __DALI_PIXEL_DATA_H__
+
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+class PixelData;
+typedef IntrusivePtr<PixelData> PixelDataPtr;
+
+/**
+ * @brief Reference counted pixel data .
+ *
+ * The PixelData takes over the ownership of the pixel buffer.
+ * The buffer memory must NOT be released outside of this class, instead, the PixelData object will release it automatically when the reference count falls to zero.
+ */
+class DALI_IMPORT_API PixelData : public RefObject
+{
+public:
+
+ enum ReleaseFunction
+ {
+ FREE, ///< Use free function to release the pixel buffer
+ DELETE_ARRAY, ///< Use delete[] operator to release the pixel buffer
+ };
+
+ /**
+ * @brief Create a PixelData object.
+ *
+ * @param [in] buffer The raw pixel data.
+ * @param [in] width Buffer width in pixels
+ * @param [in] height Buffer height in pixels
+ * @param [in] pixelFormat The pixel format
+ * @param [in] release The function used to release the memory.
+ */
+ static PixelDataPtr New( unsigned char* buffer,
+ unsigned int width,
+ unsigned int height,
+ Pixel::Format pixelFormat,
+ ReleaseFunction releaseFunction);
+
+ /**
+ * Get the width of the buffer in pixels.
+ * @return The width of the buffer in pixels
+ */
+ unsigned int GetWidth() const;
+
+ /**
+ * Get the height of the buffer in pixels
+ * @return The height of the buffer in pixels
+ */
+ unsigned int GetHeight() const;
+
+ /**
+ * Get the pixel format
+ * @return The pixel format
+ */
+ Pixel::Format GetPixelFormat() const;
+
+ /**
+ * Get the pixel buffer if it's present.
+ * @return The buffer if exits, or NULL if there is no pixel buffer.
+ */
+ unsigned char* GetBuffer() const;
+
+public:
+
+ /**
+ * @brief Constructor.
+ *
+ * @param [in] buffer The raw pixel data.
+ * @param [in] width Buffer width in pixels
+ * @param [in] height Buffer height in pixels
+ * @param [in] pixelFormat The pixel format
+ * @param [in] release The function used to release the memory.
+ */
+ PixelData( unsigned char* buffer,
+ unsigned int width,
+ unsigned int height,
+ Pixel::Format pixelFormat,
+ ReleaseFunction releaseFunction );
+
+ /**
+ * @brief Destructor.
+ *
+ * Release the pixel buffer if exists.
+ */
+ ~PixelData();
+
+
+private:
+
+ /*
+ * Undefined copy constructor.
+ */
+ PixelData(const PixelData& other);
+
+ /*
+ * Undefined assignment operator.
+ */
+ PixelData& operator = (const PixelData& other);
+
+private:
+
+ unsigned char* mBuffer; ///< The raw pixel data.
+ unsigned int mWidth; ///< Buffer width in pixels.
+ unsigned int mHeight; ///< Buffer height in pixels.
+ Pixel::Format mPixelFormat; ///< Pixel format
+ ReleaseFunction mReleaseFunction; ///< Function for releasing memory
+};
+
+
+} //namespace Dali
+
+#endif // __DALI_PIXEL_DATA_H__
{
}
+PixelBuffer* Bitmap::GetBufferOwnership()
+{
+ PixelBuffer* buffer = mData;
+ mData = NULL;
+ return buffer;
+}
+
void Bitmap::DiscardBuffer()
{
if( mDiscardable == ResourcePolicy::OWNED_DISCARD )
}
/**
+ * Get the pixel buffer if it's present and take over the ownership.
+ * @note With this function called, the bitmap loses the ownership and is no longer responsible for the release of pixel buffer.
+ * @return The raw pointer pointing to the pixel buffer
+ */
+ PixelBuffer* GetBufferOwnership();
+
+ /**
* Get the pixel buffer size in bytes
* @return The buffer size in bytes.
* @sa ReserveBuffer GetBuffer
#include <dali/public-api/object/type-registry.h>
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/images/bitmap-packed-pixel.h>
#include <dali/internal/event/resources/resource-client.h>
#include <dali/integration-api/bitmap.h>
#include <dali/integration-api/platform-abstraction.h>
{
bool uploadSuccess( false );
- if( Compatible(bufferImage.GetPixelFormat(),
- xOffset + bufferImage.GetWidth(),
- yOffset + bufferImage.GetHeight() ) )
+ if( IsInside( xOffset + bufferImage.GetWidth(), yOffset + bufferImage.GetHeight() ) )
{
AllocateAtlas();
ResourceId destId = GetResourceId();
Integration::BitmapPtr bitmap = LoadBitmap( url );
- if( bitmap && Compatible(bitmap->GetPixelFormat(), xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
+ if( bitmap && IsInside( xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
{
AllocateAtlas();
ResourceId destId = GetResourceId();
return uploadSuccess;
}
+bool Atlas::Upload( PixelDataPtr pixelData,
+ SizeType xOffset,
+ SizeType yOffset )
+{
+ bool uploadSuccess( false );
+ if( IsInside( xOffset + pixelData->GetWidth(), yOffset + pixelData->GetHeight() ) )
+ {
+ AllocateAtlas();
+ ResourceId destId = GetResourceId();
+
+ if( destId )
+ {
+ mResourceClient.UploadBitmap( destId, pixelData, xOffset, yOffset );
+ uploadSuccess = true;
+ }
+ }
+
+ return uploadSuccess;
+}
+
void Atlas::RecoverFromContextLoss()
{
ResourceId destId = GetResourceId();
}
}
-bool Atlas::Compatible( Pixel::Format pixelFormat,
- SizeType x,
- SizeType y )
+bool Atlas::IsInside( SizeType x, SizeType y )
{
- bool Compatible(false);
+ bool fit(false);
- if( mPixelFormat != pixelFormat )
+ if( x <= mWidth && y <= mHeight )
{
- DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", pixelFormat, mPixelFormat );
+ fit = true;
}
else
{
- if( x <= mWidth && y <= mHeight )
- {
- Compatible = true;
- }
- else
- {
- DALI_LOG_ERROR( "image does not fit within the atlas \n" );
- }
+ DALI_LOG_ERROR( "image does not fit within the atlas \n" );
}
- return Compatible;
+ return fit;
}
void Atlas::AllocateAtlas()
}
}
- RectArea area;
- imageData->Update(area);
-
mClearColor = color;
mClear = true;
- mResourceClient.UploadBitmap( destId, imageData->GetResourceId(), 0, 0 );
+
+ imageData->UploadBitmap( destId, 0, 0 );
}
}
void Clear( const Vector4& color );
/**
- * @copydoc Dali::Atlas::Upload( const BufferImage&, unsigned int, unsigned int )
+ * @copydoc Dali::Atlas::Upload( const BufferImage&, uint32_t, uint32_t )
*/
bool Upload( BufferImage& bufferImage,
SizeType xOffset,
SizeType yOffset );
/**
- * @copydoc Dali::Atlas::Upload( const std::string&, unsigned int, unsigned int )
+ * @copydoc Dali::Atlas::Upload( const std::string&, uint32_t, uint32_t )
*/
bool Upload( const std::string& url,
SizeType xOffset,
SizeType yOffset );
/**
+ * @copydoc Dali::Atlas::Upload( Dali::Atlas::PixelDataPtr, uint32_t )
+ */
+ bool Upload( PixelDataPtr pixelData,
+ SizeType xOffset,
+ SizeType yOffset );
+
+ /**
* @copydoc ContextRecoveryInterface::RecoverFromContextLoss
*/
virtual void RecoverFromContextLoss();
/**
* Helper for Upload methods
- * @return True if the bitmap has the same pixel format and its size fits within the atlas at the specified offset
+ * @return True if the size of the bitmap fits within the atlas at the specified offset
*/
- bool Compatible( Pixel::Format pixelFormat,
- SizeType x,
- SizeType y );
+ bool IsInside( SizeType x, SizeType y );
+
/**
* Helper to create the Atlas resource
*/
yOffset );
}
+void ResourceClient::UploadBitmap( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset)
+{
+ RequestUploadBitmapMessage( mEventThreadServices,
+ mResourceManager,
+ destId,
+ pixelData,
+ xOffset,
+ yOffset );
+}
+
void ResourceClient::CreateGlTexture( ResourceId id )
{
RequestCreateGlTextureMessage( mEventThreadServices, mResourceManager, id );
// INTERNAL INCLUDES
#include <dali/public-api/images/frame-buffer-image.h>
-#include <dali/devel-api/common/ref-counted-dali-vector.h>
#include <dali/public-api/images/native-image-interface.h>
+#include <dali/devel-api/common/ref-counted-dali-vector.h>
+#include <dali/devel-api/images/pixel-data.h>
#include <dali/internal/event/resources/resource-client-declarations.h>
#include <dali/internal/event/resources/image-ticket.h>
#include <dali/internal/event/resources/resource-ticket-lifetime-observer.h>
void UploadBitmap( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset);
/**
+ * Upload a pixel buffer to a texture
+ * @param[in] destId The destination texture ID
+ * @param[in] bitmap The pointer pointing to the pixel data
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void UploadBitmap( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset);
+
+ /**
* @brief Trigger asynchronous creation of GL texture to back resource immediately.
* @param[in] id The resource ID to allocate a GL texture for.
*/
#include <stdint.h>
// INTERNAL INCLUDES
-#include <dali/public-api/images/native-image-interface.h>
#include <dali/public-api/images/buffer-image.h>
-#include <dali/public-api/images/pixel.h>
#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/devel-api/images/pixel-data.h>
#include <dali/internal/common/message.h>
#include <dali/internal/update/common/scene-graph-buffers.h>
#include <dali/integration-api/resource-declarations.h>
virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset ) = 0;
/**
+ * Dispatch a message to update the part of a texture with the pixel data.
+ * May be called from Update thread
+ * @param[in] destId The ID of the texture to update
+ * @param[in] pixelData The pointer pointing to the pixel data to upload.
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ virtual void DispatchUpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset ) = 0;
+
+ /**
* Dispatch a message to update the texture area
* May be called from the Update thread
* @param[in] id Resource Id of the texture
#include <dali/internal/render/gl-resources/bitmap-texture.h>
// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
#include <dali/integration-api/debug.h>
#include <dali/internal/render/common/vertex.h>
#include <dali/internal/render/common/performance-monitor.h>
#include <dali/internal/render/gl-resources/context.h>
#include <dali/internal/render/gl-resources/texture-units.h>
+
namespace Dali
{
{
if( NULL != srcBitmap )
{
- GLenum pixelFormat = GL_RGBA;
- GLenum pixelDataType = GL_UNSIGNED_BYTE;
- Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelFormat );
+ Update( srcBitmap->GetBuffer(), srcBitmap->GetImageWidth(), srcBitmap->GetImageHeight(),
+ srcBitmap->GetPixelFormat(), xOffset, yOffset);
+ }
+}
- if( !mId )
- {
- mContext.GenTextures( 1, &mId );
+void BitmapTexture::Update( PixelData* srcPixelData, std::size_t xOffset, std::size_t yOffset )
+{
+ if( NULL != srcPixelData )
+ {
+ Update( srcPixelData->GetBuffer(), srcPixelData->GetWidth(), srcPixelData->GetHeight(),
+ srcPixelData->GetPixelFormat(), xOffset, yOffset);
+ }
+}
- mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
- mContext.Bind2dTexture( mId );
- mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+void BitmapTexture::Update( const unsigned char* pixels, std::size_t width, std::size_t height, Pixel::Format pixelFormat, std::size_t xOffset, std::size_t yOffset )
+{
- mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, NULL );
- mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
- mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
- }
- else
+ GLenum pixelGLFormat = GL_RGBA;
+ GLenum pixelDataType = GL_UNSIGNED_BYTE;
+ Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelGLFormat );
+
+ if( !mId )
+ {
+ mContext.GenTextures( 1, &mId );
+
+ mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+ mContext.Bind2dTexture( mId );
+ mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelGLFormat, mWidth, mHeight, 0, pixelGLFormat, pixelDataType, NULL );
+ mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ }
+ else
+ {
+ mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+ mContext.Bind2dTexture( mId );
+ mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ }
+
+#if DALI_GLES_VERSION >= 30
+// for gles 3.0, uploading sub-image with different format is a valid operation
+ Integration::ConvertToGlFormat( srcBitmap->GetPixelFormat(), pixelDataType, pixelGLFormat );
+#else
+ // allows RGB888 source bitmap to be added to RGBA8888 texture, need to convert the bitmap format manually
+ if(pixelFormat == Pixel::RGB888 && mPixelFormat == Pixel::RGBA8888 )
+ {
+ std::size_t size = width * height;
+
+ Vector<PixelBuffer> tempBuffer;
+ tempBuffer.Reserve( size*4u );
+ PixelBuffer* data = tempBuffer.Begin();
+
+ for( std::size_t i=0u; i<size; i++ )
{
- mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
- mContext.Bind2dTexture( mId );
- mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ data[i*4u] = pixels[i*3u];
+ data[i*4u+1] = pixels[i*3u+1];
+ data[i*4u+2] = pixels[i*3u+2];
+ data[i*4u+3] = 0xFF;
}
mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
xOffset, yOffset,
- srcBitmap->GetImageWidth(), srcBitmap->GetImageHeight(),
- pixelFormat, pixelDataType, srcBitmap->GetBuffer() );
+ width, height,
+ pixelGLFormat, pixelDataType,
+ data );
+
+ return;
}
+#endif
+
+ mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
+ xOffset, yOffset,
+ width, height,
+ pixelGLFormat, pixelDataType,
+ pixels );
}
void BitmapTexture::UpdateArea( const RectArea& updateArea )
virtual void Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset );
/**
+ * Update part of the texture with a pixel buffer
+ * @param[in] srcPixelData The pixel data to copy from
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ virtual void Update( PixelData* srcPixelData, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* Bitmap area has been modified - update the texture appropriately.
* @pre The bitmap hasn't been discarded (should be external type)
* @param[in] area The updated area
*/
void DiscardBitmapBuffer();
+ /**
+ * Update part of the texture.
+ * @param [in] pixels The pixel buffer.
+ * @param [in] width The buffer width in pixels
+ * @param [in] height The buffer height in pixels
+ * @param [in] pixelFormat The pixel format
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void Update( const unsigned char* pixels, std::size_t width, std::size_t height, Pixel::Format pixelFormat, std::size_t xOffset, std::size_t yOffset );
+
private:
Integration::BitmapPtr mBitmap; ///< The Bitmap the Texture was created from (may be NULL)
bool mClearPixels:1; ///< true if initial texture should be cleared on creation
}
}
+void TextureCache::UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
+{
+ DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i pixel data:%p )\n", id, pixelData.Get());
+
+ TextureIter textureIter = mTextures.find(id);
+ if( textureIter != mTextures.end() )
+ {
+ TexturePointer texturePtr = textureIter->second;
+ if( texturePtr )
+ {
+ texturePtr->Update( pixelData.Get(), xOffset, yOffset );
+
+ ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+ mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+ }
+ }
+}
+
void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
{
DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
}
}
+void TextureCache::DispatchUpdateTexture( ResourceId id, PixelDataPtr pixelData , std::size_t xOffset, std::size_t yOffset)
+{
+ // NULL, means being shutdown, so ignore msgs
+ if( mSceneGraphBuffers != NULL )
+ {
+ typedef MessageValue4< TextureCache, ResourceId, PixelDataPtr, std::size_t, std::size_t > DerivedType;
+
+ // Reserve some memory inside the render queue
+ unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, pixelData, xOffset, yOffset );
+ }
+}
+
void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
{
// NULL, means being shutdown, so ignore msgs
void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
/**
+ * Update the texture with a pixel buffer
+ * @param[in] id Resource Id of the bitmap
+ * @param[in] pixelData The pixel data
+ * @param[in] xOffset Specifies an offset in the x direction within the texture
+ * @param[in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* Update the area of the texture from the associated bitmap
* @param[in] id Resource Id of the bitmap
* @param[in] area The area of the bitmap that has changed
virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
/**
+ * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+ */
+ virtual void DispatchUpdateTexture( ResourceId destId, PixelDataPtr srcId, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* @copydoc TextureCacheDispatcher::DispatchUpdateTextureArea()
*/
virtual void DispatchUpdateTextureArea( ResourceId id, const RectArea& area );
*/
// INTERNAL INCLUDES
+#include <dali/public-api/actors/sampling.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/native-image.h>
+#include <dali/public-api/math/rect.h>
#include <dali/public-api/object/ref-object.h>
+#include <dali/devel-api/images/pixel-data.h>
#include <dali/integration-api/bitmap.h>
#include <dali/internal/render/common/uv-rect.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/internal/render/gl-resources/gl-resource-owner.h>
#include <dali/internal/render/gl-resources/texture-units.h>
-#include <dali/public-api/images/image.h>
-#include <dali/public-api/images/pixel.h>
-#include <dali/public-api/images/native-image.h>
-#include <dali/public-api/math/rect.h>
-#include <dali/public-api/actors/sampling.h>
+
namespace Dali
{
virtual void Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset ) {}
/**
+ * Update part of the texture with a pixel buffer
+ * @param[in] srcPixelData The pixel data to copy from
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ virtual void Update( PixelData* srcPixelData, std::size_t xOffset, std::size_t yOffset ) {}
+
+ /**
* @return Return true if the texture should be updated on GL texture creation.
*/
virtual bool UpdateOnCreate();
}
}
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
+{
+ if( destId && pixelData )
+ {
+ mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, pixelData, xOffset, yOffset );
+ }
+}
+
void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority, bool resetFinishedStatus )
{
DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
#include <dali/public-api/images/native-image-interface.h>
#include <dali/public-api/images/buffer-image.h>
#include <dali/devel-api/common/ref-counted-dali-vector.h>
+#include <dali/devel-api/images/pixel-data.h>
#include <dali/integration-api/bitmap.h>
#include <dali/integration-api/platform-abstraction.h>
void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
/**
+ * Upload a pixel buffer to a position within a specified texture
+ * @param[in] destId The destination texture ID
+ * @param[in] pixelData pointer pointing to the pixel data to upload
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void HandleUploadBitmapRequest( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* Request reloading a resource from the native filesystem.
* @param[in] id The resource id
* @param[in] typePath The type & path of the resource
new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, srcId, xOffset, yOffset );
}
+inline void RequestUploadBitmapMessage(EventThreadServices& eventThreadServices,
+ ResourceManager& manager,
+ ResourceId destId,
+ PixelDataPtr pixelData,
+ std::size_t xOffset,
+ std::size_t yOffset)
+{
+ typedef MessageValue4< ResourceManager, ResourceId, PixelDataPtr , std::size_t, std::size_t > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, pixelData, xOffset, yOffset );
+}
+
inline void RequestReloadResourceMessage( EventThreadServices& eventThreadServices,
ResourceManager& manager,
ResourceId id,