X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fgl-resources%2Fbitmap-texture.cpp;h=58d80c265b67dd7655aad55ffe1edc033e4fbf73;hb=2b10280985738c74efa2aa0fb956a837c69acee6;hp=9481dbae4471ece532c0faae799cafe4faae41d4;hpb=5c66381841dd4dfd82c5a118d34104a00a2e0e1c;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/gl-resources/bitmap-texture.cpp b/dali/internal/render/gl-resources/bitmap-texture.cpp index 9481dba..58d80c2 100644 --- a/dali/internal/render/gl-resources/bitmap-texture.cpp +++ b/dali/internal/render/gl-resources/bitmap-texture.cpp @@ -1,33 +1,34 @@ -// -// Copyright (c) 2014 Samsung Electronics Co., Ltd. -// -// Licensed under the Flora License, Version 1.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://floralicense.org/license/ -// -// 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. -// +/* + * 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. + * 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 // EXTERNAL INCLUDES -#include -#include +#include // INTERNAL INCLUDES -#include -#include +#include +#include // For PixelBuffer #include -#include #include #include +#include + namespace Dali { @@ -35,14 +36,19 @@ 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()), mBitmap(bitmap), + mPixelFormat(bitmap->GetPixelFormat()), + mDiscardPolicy(policy), mClearPixels(false) { DALI_LOG_TRACE_METHOD(Debug::Filter::gImage); @@ -50,16 +56,18 @@ BitmapTexture::BitmapTexture(Integration::Bitmap* const bitmap, const Integratio } 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), mBitmap(NULL), + mPixelFormat( pixelFormat ), + mDiscardPolicy(policy), mClearPixels(clearPixels) { DALI_LOG_TRACE_METHOD(Debug::Filter::gImage); @@ -68,64 +76,11 @@ BitmapTexture::BitmapTexture( 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 ) -{ - 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); @@ -153,7 +108,7 @@ void BitmapTexture::AreaUpdated( const RectArea& updateArea, const unsigned char 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); @@ -163,9 +118,8 @@ void BitmapTexture::AreaUpdated( const RectArea& updateArea, const unsigned char 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. @@ -197,7 +151,6 @@ void BitmapTexture::AreaUpdated( const RectArea& updateArea, const unsigned char } } - void BitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* pixels ) { DALI_LOG_TRACE_METHOD(Debug::Filter::gImage); @@ -212,18 +165,22 @@ void BitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* pix } 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); - 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 ) @@ -232,7 +189,7 @@ 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; } @@ -242,21 +199,22 @@ void BitmapTexture::Update( Integration::Bitmap* bitmap ) 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; 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() && @@ -264,28 +222,103 @@ void BitmapTexture::Update( Integration::Bitmap* bitmap ) 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 ); + } + } +} + +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 tempBuffer; + tempBuffer.Reserve( size*4u ); + PixelBuffer* data = tempBuffer.Begin(); + + for( std::size_t i=0u; iGetBuffer(); - 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() ) { @@ -322,53 +353,6 @@ void BitmapTexture::UpdateArea( const RectArea& updateArea ) } } -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; iGetBuffer(); - 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 { const unsigned char* pixels = NULL; - std::vector pixelData; - if( ( NULL == pixels ) && ( true == mClearPixels ) ) + Dali::Vector 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 ); @@ -434,6 +421,21 @@ unsigned int BitmapTexture::GetHeight() const return height; } +void BitmapTexture::DiscardBitmapBuffer() +{ + DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "BitmapTexture::DiscardBitmapBuffer() DiscardPolicy: %s\n", mDiscardPolicy == ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN"); + + if( ResourcePolicy::OWNED_DISCARD == mDiscardPolicy ) + { + DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, " Discarding bitmap\n"); + if ( mBitmap ) + { + mBitmap->DiscardBuffer(); + } + } +} + + } //namespace Internal } //namespace Dali