// CLASS HEADER
#include <dali/internal/render/gl-resources/bitmap-texture.h>
-// EXTERNAL INCLUDES
-#include <math.h>
-#include <memory.h>
-
// INTERNAL INCLUDES
-#include <dali/public-api/math/rect.h>
-#include <dali/public-api/math/math-utils.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
{
namespace Internal
{
-BitmapTexture::BitmapTexture(Integration::Bitmap* const bitmap, const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile, Context& context)
-: Texture(context,
- bitmapPackedPixelsProfile->GetBufferWidth(),
- bitmapPackedPixelsProfile->GetBufferHeight(),
- bitmap->GetImageWidth(),
- bitmap->GetImageHeight(),
- bitmap->GetPixelFormat()),
+BitmapTexture::BitmapTexture(
+ Integration::Bitmap* const bitmap,
+ const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile,
+ Context& context,
+ ResourcePolicy::Discardable policy)
+: Texture( context,
+ bitmapPackedPixelsProfile->GetBufferWidth(),
+ bitmapPackedPixelsProfile->GetBufferHeight(),
+ bitmap->GetImageWidth(),
+ bitmap->GetImageHeight(),
+ bitmap->GetPixelFormat()),
mBitmap(bitmap),
- mClearPixels(false)
+ mClearPixels(false),
+ mDiscardPolicy(policy)
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
DALI_LOG_SET_OBJECT_STRING(this, DALI_LOG_GET_OBJECT_STRING(bitmap));
}
BitmapTexture::BitmapTexture(
- unsigned int width,
- unsigned int height,
+ unsigned int width,
+ unsigned int height,
Pixel::Format pixelFormat,
- bool clearPixels,
- Context& context)
-: Texture(context,
- width, height,
- width, height,
- pixelFormat),
+ bool clearPixels,
+ Context& context,
+ ResourcePolicy::Discardable policy)
+: Texture( context,
+ width, height,
+ width, height,
+ pixelFormat),
mBitmap(NULL),
- mClearPixels(clearPixels)
+ mClearPixels(clearPixels),
+ mDiscardPolicy(policy)
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
}
BitmapTexture::~BitmapTexture()
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
// GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
// 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.ActiveTexture( TEXTURE_UNIT_UPLOAD );
mContext.Bind2dTexture(mId);
mContext.PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
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;
- }
+ 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;
+ }
}
}
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_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.PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
mContext.TexImage2D(GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, pixels);
- mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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);
const unsigned char* pixels = mBitmap->GetBuffer();
+ // We should never have null pixel data here - resource manager has deliberately loaded/reloaded data
+
DALI_ASSERT_DEBUG( pixels != NULL );
- if ( NULL == pixels )
+ if( NULL == pixels )
{
- DALI_LOG_ERROR("bitmap has no data\n");
- GlCleanup(); // Note, We suicide here in the case of bad input.
+ DALI_LOG_ERROR("BitmapTexture::Upload() - Bitmap has no pixel data.\n");
}
- else
+ else if( mId != 0 )
{
if( mImageWidth == mBitmap->GetImageWidth() &&
mImageHeight == mBitmap->GetImageHeight() &&
mHeight == bitmapPackedPixels->GetBufferHeight() &&
mPixelFormat == mBitmap->GetPixelFormat() ) // and size hasn't changed
{
- if ( mId ) // If the texture is already bound
- {
- RectArea area(0, 0, mImageWidth, mImageHeight); // just update whole texture
- AreaUpdated( area, pixels );
- mBitmap->DiscardBuffer();
- }
+ RectArea area(0, 0, mImageWidth, mImageHeight); // just update whole texture
+ AreaUpdated( area, pixels );
+ DiscardBitmapBuffer();
}
- else
- { // Otherwise, reload the pixel data
+ else // Otherwise, reload the pixel data
+ {
mImageWidth = mBitmap->GetImageWidth();
mImageHeight = mBitmap->GetImageHeight();
mWidth = bitmapPackedPixels->GetBufferWidth();
mHeight = bitmapPackedPixels->GetBufferHeight();
mPixelFormat = mBitmap->GetPixelFormat();
- if ( mId ) // If the texture is already bound
- {
- AssignBitmap( false, pixels );
- mBitmap->DiscardBuffer();
- }
+ AssignBitmap( false, pixels );
}
}
}
if( mBitmap != 0 )
{
const unsigned char* pixels = mBitmap->GetBuffer();
- if ( NULL == pixels )
- {
- DALI_LOG_ERROR("bitmap has no data\n");
- GlCleanup(); ///!ToDo: Why do we suicide in the case of bad input?
- }
- else
+
+ // Pixel data could be null if we've uploaded to GL and discarded the data.
+
+ if( NULL != pixels )
{
- if ( mId ) // If the texture is already bound
+ if( mId ) // If the texture is already bound
{
if( updateArea.IsEmpty() )
{
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);
size_t numPixels = blockSize*blockSize;
bool BitmapTexture::CreateGlTexture()
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
- DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Bitmap: %s\n", DALI_LOG_GET_OBJECT_C_STR(this));
+ DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "BitmapTexture::CreateGlTexture() Bitmap: %s\n", DALI_LOG_GET_OBJECT_C_STR(this));
if( mBitmap )
{
const unsigned char* pixels = mBitmap->GetBuffer();
- DALI_ASSERT_DEBUG(pixels != NULL);
+ // pixel data could be NULL here if we've had a context loss and we previously discarded
+ // the pixel data on the previous upload. If it is null, then we shouldn't generate a
+ // new GL Texture; leaving mId as zero. Eventually, the bitmap will get reloaded,
+ // and pixels will become non-null.
if( NULL != pixels )
{
AssignBitmap( true, pixels );
- mBitmap->DiscardBuffer();
+ DiscardBitmapBuffer();
}
}
else
return height;
}
+void BitmapTexture::DiscardBitmapBuffer()
+{
+ DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "BitmapTexture::DiscardBitmapBuffer() DiscardPolicy: %s\n", mDiscardPolicy == ResourcePolicy::DISCARD?"DISCARD":"RETAIN");
+
+ if( ResourcePolicy::DISCARD == mDiscardPolicy )
+ {
+ DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, " Discarding bitmap\n");
+ mBitmap->DiscardBuffer();
+ }
+}
+
+
} //namespace Internal
} //namespace Dali