//Upload data to the texture
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data );
+
+ unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( width * height * 4 ) );
+ PixelData pixelData = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+ texture.Upload( pixelData );
application.SendNotification();
application.Render();
//Upload part of the texture
callStack.Reset();
- Vector<unsigned char> subImage;
- subImage.Resize( width * height * 2 );
- texture.Upload( subImage, 0u, 0u, width/2, height/2, width/2, height/2 );
+ buffer = reinterpret_cast<unsigned char*>( malloc( width * height * 2 ) );
+ PixelData pixelDataSubImage = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+ texture.Upload( pixelDataSubImage, 0u, 0u, width/2, height/2, width/2, height/2 );
application.SendNotification();
application.Render();
DALI_TEST_CHECK( callStack.FindMethodAndParams("TexImage2D", out.str().c_str() ) );
}
+ unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( width * height * 4 ) );
+ PixelData pixelData = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+
//Upload data to the POSITIVE_X face of the texture
{
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::POSITIVE_X, 0u, 0u, 0u, width, height );
+
+ texture.Upload( pixelData, CubeMap::POSITIVE_X, 0u, 0u, 0u, width, height );
application.SendNotification();
application.Render();
//Upload data to the NEGATIVE_X face of the texture
{
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::NEGATIVE_X, 0u, 0u, 0u, width, height );
+
+ texture.Upload( pixelData, CubeMap::NEGATIVE_X, 0u, 0u, 0u, width, height );
application.SendNotification();
application.Render();
//Upload data to the POSITIVE_Y face of the texture
{
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::POSITIVE_Y, 0u, 0u, 0u, width, height );
+ texture.Upload( pixelData, CubeMap::POSITIVE_Y, 0u, 0u, 0u, width, height );
application.SendNotification();
application.Render();
//Upload data to the NEGATIVE_Y face of the texture
{
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::NEGATIVE_Y, 0u, 0u, 0u, width, height );
+ texture.Upload( pixelData, CubeMap::NEGATIVE_Y, 0u, 0u, 0u, width, height );
application.SendNotification();
application.Render();
//Upload data to the POSITIVE_Z face of the texture
{
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::POSITIVE_Z, 0u, 0u, 0u, width, height );
+ texture.Upload( pixelData, CubeMap::POSITIVE_Z, 0u, 0u, 0u, width, height );
application.SendNotification();
application.Render();
//Upload data to the NEGATIVE_Z face of the texture
{
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::NEGATIVE_Z, 0u, 0u, 0u, width, height );
+ texture.Upload( pixelData, CubeMap::NEGATIVE_Z, 0u, 0u, 0u, width, height );
application.SendNotification();
application.Render();
//Upload data to the texture mipmap 0 and mipmap 1
callStack.Reset();
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, 0u, 0u, 0u, 0u, width, height );
+ unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( width * height * 4 ) );
+ PixelData pixelData = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+ texture.Upload( pixelData, 0u, 0u, 0u, 0u, width, height );
- Vector<unsigned char> dataMipmap1;
- dataMipmap1.Resize( widthMipmap1 * heightMipmap1 * 4 );
- texture.Upload( dataMipmap1, 0u, 1u, 0u, 0u, widthMipmap1, heightMipmap1 );
+ buffer = reinterpret_cast<unsigned char*>( malloc( widthMipmap1 * heightMipmap1 * 4 ) );
+ PixelData pixelDataMipmap1 = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+ texture.Upload( pixelDataMipmap1, 0u, 1u, 0u, 0u, widthMipmap1, heightMipmap1 );
application.SendNotification();
application.Render();
TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
//Upload data to the NEGATIVE_X face mipmap 0 and mipmap 1
- Vector<unsigned char> data;
- data.Resize( width * height * 4 );
- texture.Upload( data, CubeMap::NEGATIVE_X, 0u, 0u, 0u, width, height );
+ unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( width * height * 4 ) );
+ PixelData pixelData = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+ texture.Upload( pixelData, CubeMap::NEGATIVE_X, 0u, 0u, 0u, width, height );
- Vector<unsigned char> dataMipmap1;
- dataMipmap1.Resize( widthMipmap1 * widthMipmap1 * 4 );
- texture.Upload( dataMipmap1, CubeMap::NEGATIVE_X, 1u, 0u, 0u, widthMipmap1, heightMipmap1 );
+ buffer= reinterpret_cast<unsigned char*>( malloc( widthMipmap1 * heightMipmap1 * 4 ) );
+ PixelData pixelDataMipmap1 = PixelData::New( buffer, width, height, Pixel::RGBA8888, PixelData::FREE );
+ texture.Upload( pixelDataMipmap1, CubeMap::NEGATIVE_X, 1u, 0u, 0u, widthMipmap1, heightMipmap1 );
application.SendNotification();
application.Render();
return *this;
}
-void Texture::Upload( Vector<unsigned char>& buffer )
+void Texture::Upload( PixelData pixelData )
{
- return GetImplementation(*this).Upload( buffer );
+ Internal::PixelData& internalPixelData = GetImplementation( pixelData );
+ return GetImplementation(*this).Upload( &internalPixelData );
}
-void Texture::Upload( Vector<unsigned char>& buffer,
+void Texture::Upload( PixelData pixelData,
unsigned int layer, unsigned int mipmap,
unsigned int xOffset, unsigned int yOffset,
unsigned int width, unsigned int height )
{
- return GetImplementation(*this).Upload( buffer, layer, mipmap, xOffset, yOffset, width, height );
-}
-
-void Texture::Upload( PixelData pixelData )
-{
- //TODO: Implement this method once PixelData uses handle/body pattern
- DALI_ASSERT_ALWAYS( false && "Not implemented yet");
+ Internal::PixelData& internalPixelData = GetImplementation( pixelData );
+ return GetImplementation(*this).Upload( &internalPixelData, layer, mipmap, xOffset, yOffset, width, height );
}
void Texture::GenerateMipmaps()
Texture& operator=( const Texture& handle );
/**
- * @brief Upload data to the texture
- * @param[in] buffer A vector with the data to be uploaded
- * @note buffer data will be moved after this call. If the application needs to keep the data,
- * it will have to pass a copy of the original buffer into this function, otherwise the data
- * will be lost
+ * @brief Upload data to the texture from a PixelData object
+ * @param[in] pixelData The pixelData object
*/
- void Upload( Vector<unsigned char>& buffer );
+ void Upload( PixelData pixelData );
/**
- * @brief Upload data to the texture
- * @param[in] buffer A vector with the data to be uploaded
+ * @brief Upload data to the texture from a PixelData object
+ * @param[in] pixelData The pixelData object
* @param[in] layer Specifies the layer of a cube map or array texture. (Unused for 2D textures)
* @param[in] mipmap Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image
- * @param[in] xOffset Specifies a texel offset in the x direction within the texture array
- * @param[in] yOffset Specifies a texel offset in the y direction within the texture array
- * @param[in] width Specifies the width of the texture subimage
- * @param[in] height Specifies the height of the texture subimage
- * @note buffer data will be moved after this call. If the application needs to keep the data,
- * it will have to pass a copy of the original buffer into this function, otherwise the data
- * will be lost
+ * @param[in] xOffset Specifies an horizontal offset of the rectangular area in the texture that will be updated
+ * @param[in] yOffset Specifies a vertical offset of the rectangular area in the texture that will be updated
+ * @param[in] width Specifies the width of the rectangular area in the texture that will be updated
+ * @param[in] height Specifies the height of the rectangular area in the texture that will be updated
+ * @note Upload does not upsample or downsample pixel data to fit the specified rectangular area in the texture.
*/
- void Upload( Vector<unsigned char>& buffer,
+ void Upload( PixelData pixelData,
unsigned int layer, unsigned int mipmap,
unsigned int xOffset, unsigned int yOffset,
unsigned int width, unsigned int height );
- /**
- * @brief Upload data to the texture from a PixelData object
- * @param[in] pixelData The pixelData object
- */
- void Upload( PixelData pixelData );
-
/**
* @brief Generate mipmaps for the texture
* This will auto generate all the mipmaps for the texture based on the data in the base level
}
}
-bool NewTexture::CheckUploadParametres( const Vector<unsigned char>& buffer, const UploadParams& parameters ) const
+void NewTexture::Upload( PixelDataPtr pixelData )
{
- if( mNativeImage )
- {
- DALI_LOG_ERROR( "Error: Uploading data to a native texture");
- return false;
- }
- else if( buffer.Size() < GetBytesPerPixel( mFormat ) * parameters.width * parameters.height )
- {
- DALI_LOG_ERROR( "Error: Buffer of an incorrect size when trying to update texture");
- return false;
- }
- else if( ( parameters.xOffset + parameters.width > static_cast<unsigned int>( mWidth/(1<<parameters.mipmap ))) ||
- ( parameters.yOffset + parameters.height > static_cast<unsigned int>( mHeight/(1<<parameters.mipmap ))))
- {
- DALI_LOG_ERROR( "Error: Out of bounds texture update");
- return false;
- }
- else
- {
- return true;
- }
+ Upload( pixelData, 0u, 0u, 0u, 0u, mWidth, mHeight );
}
-void NewTexture::Upload( Vector<unsigned char>& buffer,
+void NewTexture::Upload( PixelDataPtr pixelData,
unsigned int layer, unsigned int mipmap,
unsigned int xOffset, unsigned int yOffset,
unsigned int width, unsigned int height )
{
- UploadParams params = { layer, mipmap, xOffset, yOffset, width, height };
- if( CheckUploadParametres( buffer, params ) )
+ if( mNativeImage )
{
- UploadTextureMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, buffer, params );
+ DALI_LOG_ERROR( "OpenGLES does not support uploading data to native texture");
}
-}
-
-void NewTexture::Upload( Vector<unsigned char>& buffer )
-{
- UploadParams params = {0u,0u,0u,0u,mWidth,mHeight};
- if( CheckUploadParametres( buffer, params ) )
+ else
{
- UploadTextureMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, buffer, params );
+ unsigned int pixelDataSize = pixelData->GetWidth()*pixelData->GetHeight();
+ if( pixelData->GetBuffer() == NULL || pixelDataSize == 0 )
+ {
+ DALI_LOG_ERROR( "PixelData is empty");
+ }
+ else
+ {
+ Pixel::Format pixelDataFormat = pixelData->GetPixelFormat();
+ if( ( pixelDataFormat == mFormat ) || ( (pixelDataFormat == Pixel::RGB888 ) && ( mFormat == Pixel::RGBA8888 ) ) )
+ {
+ if( pixelDataSize < width * height )
+ {
+ DALI_LOG_ERROR( "Pixel data of an incorrect size when trying to update texture");
+ }
+ else if( ( xOffset + width > static_cast<unsigned int>( mWidth / (1<<mipmap ))) ||
+ ( yOffset + height > static_cast<unsigned int>( mHeight / (1<<mipmap ))))
+ {
+ DALI_LOG_ERROR( "Texture update area out of bounds");
+ }
+ else
+ {
+ //Parameters are correct. Send message to upload data to the texture
+ UploadParams params = { layer, mipmap, xOffset, yOffset, width, height };
+ UploadTextureMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, pixelData, params );
+ }
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Bad format");
+ }
+ }
}
}
#include <dali/public-api/images/pixel.h>
#include <dali/devel-api/rendering/texture.h> // Dali::Internal::Render::Texture
#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/images/pixel-data-impl.h>
namespace Dali
{
/**
* @copydoc Dali::Texture::Upload()
*/
- void Upload( Vector<unsigned char>& buffer );
+ void Upload( PixelDataPtr pixelData );
/**
* @copydoc Dali::Texture::Upload()
*/
- void Upload( Vector<unsigned char>& buffer,
+ void Upload( PixelDataPtr pixelData,
unsigned int layer, unsigned int mipmap,
unsigned int xOffset, unsigned int yOffset,
unsigned int width, unsigned int height );
private: // data
- /**
- * @brief Helper method to check that upload parameters are correct
- * @param[in] buffer A vector with the data to be uploaded
- * @param[in] parameters The uploading parameters
- */
- bool CheckUploadParametres( const Vector<unsigned char>& buffer, const UploadParams& parameters) const;
-
Internal::EventThreadServices& mEventThreadServices; ///<Used to send messages to the render thread via update thread
Internal::Render::NewTexture* mRenderObject; ///<The Render::Texture associated to this texture
}
}
-void RenderManager::UploadTexture( Render::NewTexture* texture, Vector<unsigned char>& buffer, const NewTexture::UploadParams& params )
+void RenderManager::UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params )
{
- texture->Upload( mImpl->context, buffer, params );
+ texture->Upload( mImpl->context, pixelData, params );
}
void RenderManager::GenerateMipmaps( Render::NewTexture* texture )
/**
* Uploads data to an existing texture
* @param[in] texture The texture
- * @param[in] buffer Vector with the data to be uploaded
+ * @param[in] pixelData The pixel data object
* @param[in] params The parameters for the upload
*/
- void UploadTexture( Render::NewTexture* texture, Vector<unsigned char>& buffer, const NewTexture::UploadParams& params );
+ void UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params );
/**
* Generates mipmaps for a given texture
}
}
-void NewTexture::Upload( Context& context, Vector<unsigned char>& buffer, const Internal::NewTexture::UploadParams& params )
+void NewTexture::Upload( Context& context, PixelDataPtr pixelData, const Internal::NewTexture::UploadParams& params )
{
DALI_ASSERT_ALWAYS( mNativeImage == NULL );
+ //Get pointer to the data of the PixelData object
+ unsigned char* buffer( pixelData->GetBuffer() );
+
+ //This buffer is only used if manually converting from RGB to RGBA
+ unsigned char* tempBuffer(0);
+
+ //Get pixel format and data type of the data contained in the PixelData object
+ GLenum pixelDataFormat, pixelDataElementType;
+ PixelFormatToGl( pixelData->GetPixelFormat(), pixelDataElementType, pixelDataFormat );
+
+#if DALI_GLES_VERSION < 30
+ if( pixelDataFormat == GL_RGB && mInternalFormat == GL_RGBA )
+ {
+ //Convert manually from RGB to RGBA if GLES < 3 ( GLES 3 can do the conversion automatically when uploading )
+ size_t dataSize = params.width * params.height;
+ tempBuffer = new unsigned char[dataSize*4u];
+ for( size_t i(0u); i<dataSize; i++ )
+ {
+ tempBuffer[i*4u] = buffer[i*3u];
+ tempBuffer[i*4u+1] = buffer[i*3u+1];
+ tempBuffer[i*4u+2] = buffer[i*3u+2];
+ tempBuffer[i*4u+3] = 0xFF;
+ }
+
+ buffer = tempBuffer;
+ pixelDataFormat = mInternalFormat;
+ }
+#endif
+
+ //Upload data to the texture
if( mType == TextureType::TEXTURE_2D )
{
context.Bind2dTexture( mId );
context.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
if( params.xOffset == 0 && params.yOffset == 0 &&
- params.width == (unsigned int)(mWidth / (1<<params.mipmap)) &&
- params.height == (unsigned int)(mHeight / (1<<params.mipmap)) )
+ params.width == static_cast<unsigned int>(mWidth / (1<<params.mipmap)) &&
+ params.height == static_cast<unsigned int>(mHeight / (1<<params.mipmap)) )
{
//Specifying the whole image for the mipmap. We cannot assume that storage for that mipmap has been created so we need to use TexImage2D
- context.TexImage2D(GL_TEXTURE_2D, params.mipmap, mInternalFormat, params.width, params.height, 0, mInternalFormat, mPixelDataType, &buffer[0] );
+ context.TexImage2D(GL_TEXTURE_2D, params.mipmap, mInternalFormat, params.width, params.height, 0, pixelDataFormat, pixelDataElementType, buffer );
}
else
{
//Specifying part of the image for the mipmap
- context.TexSubImage2D( GL_TEXTURE_2D, params.mipmap, params.xOffset, params.yOffset, params.width, params.height, mInternalFormat, mPixelDataType, &buffer[0] );
+ context.TexSubImage2D( GL_TEXTURE_2D, params.mipmap, params.xOffset, params.yOffset, params.width, params.height, pixelDataFormat, pixelDataElementType, buffer );
}
}
else if( mType == TextureType::TEXTURE_CUBE )
//Specifying the whole image for the mipmap. We cannot assume that storage for that mipmap has been created so we need to use TexImage2D
context.TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + params.layer, params.mipmap, mInternalFormat,
params.width, params.height, 0,
- mInternalFormat, mPixelDataType, &buffer[0] );
+ pixelDataFormat, pixelDataElementType, buffer );
}
else
{
//Specifying part of the image for the mipmap
context.TexSubImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + params.layer, params.mipmap,
params.xOffset, params.yOffset, params.width, params.height,
- mInternalFormat, mPixelDataType, &buffer[0] );
+ pixelDataFormat, pixelDataElementType, buffer );
}
}
+
+ //Destroy temp buffer used for conversion RGB->RGBA
+ delete[] tempBuffer;
}
bool NewTexture::Bind( Context& context, unsigned int textureUnit, Render::Sampler* sampler )
void NewTexture::ApplySampler( Context& context, Render::Sampler* sampler )
{
Render::Sampler oldSampler = mSampler;
- if( sampler )
- {
- mSampler = *sampler;
- }
+ mSampler = sampler ? *sampler : Sampler();
if( mSampler.mBitfield != oldSampler.mBitfield )
{
/**
* Uploads data to the texture.
* @param[in] context The GL context
- * @param[in] buffer A vector with the data to be uploaded
+ * @param[in] pixelData A pixel data object
* @param[in] params Upload parameters. See UploadParams
*/
- void Upload( Context& context, Vector<unsigned char>& buffer, const Internal::NewTexture::UploadParams& params );
+ void Upload( Context& context, PixelDataPtr pixelData, const Internal::NewTexture::UploadParams& params );
/**
* Bind the texture to the given texture unit and applies the given sampler
new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
}
-void UpdateManager::UploadTexture( Render::NewTexture* texture, Vector<unsigned char>& buffer, const NewTexture::UploadParams& params )
+void UpdateManager::UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params )
{
- typedef UploadTextureDataMessage< RenderManager > DerivedType;
+ typedef MessageValue3< RenderManager, Render::NewTexture*, PixelDataPtr, NewTexture::UploadParams > DerivedType;
// Reserve some memory inside the message queue
unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
// Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) DerivedType( &mImpl->renderManager, texture, buffer, params );
+ new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
}
void UpdateManager::GenerateMipmaps( Render::NewTexture* texture )
/**
* Uploads data to a texture owned by the RenderManager
* @param[in] texture The texture
- * @param[in] buffer Vector with the data to be uploaded
+ * @param[in] pixelData The pixel data object
* @param[in] params The parameters for the upload
*/
- void UploadTexture( Render::NewTexture* texture, Vector<unsigned char>& buffer, const NewTexture::UploadParams& params );
+ void UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params );
/**
* Generates mipmaps for a texture owned by the RenderManager
new (slot) LocalType( &manager, &UpdateManager::RemoveTexture, &texture );
}
-template< typename T >
-class UploadTextureDataMessage : public MessageBase
-{
-public:
-
- /**
- * Constructor which does a Vector::Swap()
- */
- UploadTextureDataMessage( T* manager, Render::NewTexture* texture, Dali::Vector<unsigned char>& data, const NewTexture::UploadParams& params )
- : MessageBase(),
- mManager( manager ),
- mRenderTexture( texture ),
- mParams( params )
- {
- mData.Swap( data );
- }
-
- /**
- * Virtual destructor
- */
- virtual ~UploadTextureDataMessage()
- {
- }
-
- /**
- * @copydoc MessageBase::Process
- */
- virtual void Process( BufferIndex /*bufferIndex*/ )
- {
- DALI_ASSERT_DEBUG( mManager && "Message does not have an object" );
- mManager->UploadTexture( mRenderTexture, mData, mParams );
- }
-
-private:
-
- T* mManager;
- Render::NewTexture* mRenderTexture;
- Dali::Vector<unsigned char> mData;
- NewTexture::UploadParams mParams;
-};
-
-inline void UploadTextureMessage( UpdateManager& manager, Render::NewTexture& texture, Dali::Vector<unsigned char>& data, const NewTexture::UploadParams& params )
+inline void UploadTextureMessage( UpdateManager& manager, Render::NewTexture& texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params )
{
- typedef UploadTextureDataMessage< UpdateManager > LocalType;
+ typedef MessageValue3< UpdateManager, Render::NewTexture*, PixelDataPtr, NewTexture::UploadParams > LocalType;
// Reserve some memory inside the message queue
unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
// Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) LocalType( &manager, &texture, data, params );
+ new (slot) LocalType( &manager, &UpdateManager::UploadTexture, &texture, pixelData, params );
}
inline void GenerateMipmapsMessage( UpdateManager& manager, Render::NewTexture& texture )