/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 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/render/gl-resources/bitmap-texture.h>
// EXTERNAL INCLUDES
-#include <math.h>
-#include <memory.h>
+#include <cstring>
// INTERNAL INCLUDES
-#include <dali/public-api/math/rect.h>
-#include <dali/public-api/math/math-utils.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/images/buffer-image.h> // For PixelBuffer
#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
{
bitmapPackedPixelsProfile->GetBufferWidth(),
bitmapPackedPixelsProfile->GetBufferHeight(),
bitmap->GetImageWidth(),
- bitmap->GetImageHeight(),
- bitmap->GetPixelFormat()),
+ bitmap->GetImageHeight()),
mBitmap(bitmap),
- mClearPixels(false),
- mDiscardPolicy(policy)
+ mPixelFormat(bitmap->GetPixelFormat()),
+ mDiscardPolicy(policy),
+ mClearPixels(false)
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
DALI_LOG_SET_OBJECT_STRING(this, DALI_LOG_GET_OBJECT_STRING(bitmap));
ResourcePolicy::Discardable policy)
: Texture( context,
width, height,
- width, height,
- pixelFormat),
+ width, height),
mBitmap(NULL),
- mClearPixels(clearPixels),
- mDiscardPolicy(policy)
+ mPixelFormat( pixelFormat ),
+ mDiscardPolicy(policy),
+ mClearPixels(clearPixels)
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
}
// on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
}
-void BitmapTexture::UploadBitmapArray( const BitmapUploadArray& bitmapArray )
-{
- DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
-
- if( mId == 0 )
- {
- CreateGlTexture();
- }
-
- mContext.ActiveTexture(GL_TEXTURE7); // bind in unused unit so rebind works the first time
- mContext.Bind2dTexture(mId);
- mContext.PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
-
- GLenum pixelFormat = GL_RGBA;
- GLenum pixelDataType = GL_UNSIGNED_BYTE;
-
- Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
-
- // go through each bitmap uploading it
-
- for( BitmapUploadArray::const_iterator iter = bitmapArray.begin(), endIter = bitmapArray.end(); iter != endIter ; ++iter)
- {
- const BitmapUpload& bitmapItem((*iter));
-
- DALI_ASSERT_ALWAYS(bitmapItem.mPixelData);
-
- const unsigned char* pixels = bitmapItem.mPixelData;
-
- DALI_ASSERT_DEBUG( (pixels!=NULL) && "bitmap has no data \n");
-
- unsigned int bitmapWidth(bitmapItem.mWidth);
- unsigned int bitmapHeight(bitmapItem.mHeight);
-
- DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "upload bitmap to texture :%d y:%d w:%d h:%d\n",
- bitmapItem.mXpos,
- bitmapItem.mYpos,
- bitmapWidth,
- bitmapHeight);
-
- mContext.TexSubImage2D(GL_TEXTURE_2D,
- 0, /* mip map level */
- bitmapItem.mXpos, /* X pos */
- bitmapItem.mYpos, /* Y pos */
- bitmapWidth, /* width */
- bitmapHeight, /* height */
- pixelFormat, /* our bitmap format (should match internal format) */
- pixelDataType, /* pixel data type */
- pixels); /* texture data */
-
- if( BitmapUpload::DISCARD_PIXEL_DATA == bitmapItem.mDiscard)
- {
- delete [] bitmapItem.mPixelData;
- }
- }
-}
-
bool BitmapTexture::HasAlphaChannel() const
{
return Pixel::HasAlpha(mPixelFormat);
GLenum pixelDataType = GL_UNSIGNED_BYTE;
Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
- mContext.ActiveTexture(GL_TEXTURE7); // bind in unused unit so rebind works the first time
+ mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
mContext.Bind2dTexture(mId);
DALI_LOG_INFO( Debug::Filter::gImage, Debug::General, "Update x:%d y:%d w:%d h:%d\n",
updateArea.x, updateArea.y, updateArea.width ,updateArea.height );
- // TODO: obtain pitch of source image, obtain pixel depth of source image.
- const unsigned int pitchPixels = mImageWidth;
- const unsigned int pixelDepth = sizeof(unsigned int);
+ const unsigned int pitchPixels = mWidth;
+ const unsigned int pixelDepth = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
// If the width of the source update area is the same as the pitch, then can
// copy the contents in a single contiguous TexSubImage call.
}
}
-
void BitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* pixels )
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
}
DALI_ASSERT_DEBUG( mId != 0 );
- mContext.ActiveTexture(GL_TEXTURE7); // bind in unused unit so rebind works the first time
+ mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
mContext.Bind2dTexture(mId);
Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
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);
- INCREASE_BY( PerformanceMonitor::TEXTURE_DATA_UPLOADED, GetBytesPerPixel(mPixelFormat) * mWidth * mHeight );
+ // If the resource policy is to discard on upload then release buffer
+ DiscardBitmapBuffer();
+
+ if( pixels != NULL )
+ {
+ INCREASE_BY( PerformanceMonitor::TEXTURE_DATA_UPLOADED, GetBytesPerPixel(mPixelFormat) * mWidth * mHeight );
+ }
}
void BitmapTexture::Update( Integration::Bitmap* bitmap )
DALI_ASSERT_DEBUG( bitmap != 0 );
if( !bitmap )
{
- DALI_LOG_ERROR( "Passed a null bitmap to update this bitmap texture." );
+ DALI_LOG_ERROR( "Passed a null bitmap to update this bitmap texture.\n" );
return;
}
if( !bitmapPackedPixels )
{
///! This should never happen.
- DALI_LOG_ERROR("Passed an incompatible bitmap type to update this bitmap texture.");
+ DALI_LOG_ERROR("Passed an incompatible bitmap type to update this bitmap texture.\n");
return;
}
mBitmap = bitmap;
}
}
+void BitmapTexture::Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset )
+{
+ if( NULL != srcBitmap )
+ {
+ Update( srcBitmap->GetBuffer(), srcBitmap->GetImageWidth(), srcBitmap->GetImageHeight(),
+ srcBitmap->GetPixelFormat(), xOffset, yOffset);
+ }
+}
+
+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);
+ }
+}
+
+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 )
+{
+
+ 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( pixelFormat, 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++ )
+ {
+ 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,
+ 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 )
{
DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "BitmapTexture::UpdateArea()\n");
}
}
-void BitmapTexture::ClearAreas( const BitmapClearArray& areaArray, std::size_t blockSize, uint32_t color )
-{
- if(mId > 0)
- {
- DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
- DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::Verbose, "BitmapTexture::AreaUpdated()\n");
-
- GLenum pixelFormat = GL_RGBA;
- GLenum pixelDataType = GL_UNSIGNED_BYTE;
- Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
-
- mContext.ActiveTexture(GL_TEXTURE7); // bind in unused unit so rebind works the first time
- mContext.Bind2dTexture(mId);
-
- size_t numPixels = blockSize*blockSize;
- size_t bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
- char* clearPixels = (char*)malloc(numPixels * bytesPerPixel);
-
- for(size_t i=0; i<numPixels; i++)
- {
- memcpy(&clearPixels[i*bytesPerPixel], &color, bytesPerPixel);
- }
-
- for( BitmapClearArray::const_iterator iter = areaArray.begin(), endIter = areaArray.end(); iter != endIter ; ++iter)
- {
- const Vector2& clearPos((*iter));
-
- mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // We always use tightly packed data
- DALI_LOG_INFO( Debug::Filter::gImage, Debug::General, "Update x:%0.2f y:%0.2f w:%d h:%d\n",
- clearPos.x, clearPos.y, blockSize, blockSize );
-
- mContext.TexSubImage2D(GL_TEXTURE_2D,
- 0,
- clearPos.x,
- clearPos.y,
- blockSize,
- blockSize,
- pixelFormat, /* our bitmap format (should match internal format) */
- pixelDataType, /* pixel data type */
- clearPixels); /* texture data */
-
- INCREASE_BY( PerformanceMonitor::TEXTURE_DATA_UPLOADED, numPixels * bytesPerPixel );
- }
- free(clearPixels);
- }
-}
-
bool BitmapTexture::UpdateOnCreate()
{
return true;
else
{
const unsigned char* pixels = NULL;
- std::vector<unsigned char> pixelData;
- if( ( NULL == pixels ) && ( true == mClearPixels ) )
+ Dali::Vector<unsigned char> pixelData; // Okay to create outside branch as empty vector has no heap allocation.
+ if( true == mClearPixels )
{
- unsigned int size = mWidth * mHeight * Pixel::GetBytesPerPixel(mPixelFormat);
- pixelData.resize(size, 0);
+ unsigned int size = mWidth * mHeight * Pixel::GetBytesPerPixel( mPixelFormat );
+ pixelData.Resize( size, 0 );
pixels = &pixelData[0];
}
AssignBitmap( true, pixels );
void BitmapTexture::DiscardBitmapBuffer()
{
- DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "BitmapTexture::DiscardBitmapBuffer() DiscardPolicy: %s\n", mDiscardPolicy == ResourcePolicy::DISCARD?"DISCARD":"RETAIN");
+ DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "BitmapTexture::DiscardBitmapBuffer() DiscardPolicy: %s\n", mDiscardPolicy == ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN");
- if( ResourcePolicy::DISCARD == mDiscardPolicy )
+ if( ResourcePolicy::OWNED_DISCARD == mDiscardPolicy )
{
DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, " Discarding bitmap\n");
- mBitmap->DiscardBuffer();
+ if ( mBitmap )
+ {
+ mBitmap->DiscardBuffer();
+ }
}
}