#include <stdlib.h>
#include <dali-toolkit-test-suite-utils.h>
+#include <toolkit-timer.h>
+#include <toolkit-event-thread-callback.h>
#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
using namespace Dali::Toolkit::Internal;
test_return_value = TET_PASS;
}
+namespace
+{
+
+const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
+
+}
+
class TestObserver : public Dali::Toolkit::TextureUploadObserver
{
public:
+ enum class CompleteType
+ {
+ NOT_COMPLETED = 0,
+ UPLOAD_COMPLETE,
+ LOAD_COMPLETE
+ };
+
+public:
TestObserver()
- : mLoaded(false),
+ : mCompleteType( CompleteType::NOT_COMPLETED ),
+ mLoaded(false),
mObserverCalled(false)
{
}
virtual void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet,
bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override
{
+ mCompleteType = CompleteType::UPLOAD_COMPLETE;
mLoaded = loadSuccess;
mObserverCalled = true;
}
virtual void LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied ) override
{
+ mCompleteType = CompleteType::LOAD_COMPLETE;
mLoaded = loadSuccess;
mObserverCalled = true;
}
+ CompleteType mCompleteType;
bool mLoaded;
bool mObserverCalled;
};
END_TEST;
}
+
+int UtcTextureManagerCachingForDifferentLoadingType(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcTextureManagerCachingForDifferentLoadingType" );
+
+ TextureManager textureManager; // Create new texture manager
+
+ TestObserver observer1;
+ std::string filename( TEST_IMAGE_FILE_NAME );
+ auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+ textureManager.RequestLoad(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ TextureManager::NO_ATLAS,
+ &observer1,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply);
+
+ DALI_TEST_EQUALS( observer1.mLoaded, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( observer1.mObserverCalled, false, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( observer1.mLoaded, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( observer1.mObserverCalled, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( observer1.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION );
+
+ TestObserver observer2;
+ Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ false,
+ &observer2,
+ true,
+ preMultiply);
+
+ DALI_TEST_EQUALS( observer2.mLoaded, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( observer2.mObserverCalled, false, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( observer2.mLoaded, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( observer2.mObserverCalled, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( observer2.mCompleteType, TestObserver::CompleteType::LOAD_COMPLETE, TEST_LOCATION );
+
+ END_TEST;
+}
else
{
RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS,
- false, KEEP_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED,
- preMultiplyOnLoad, true );
+ false, RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED,
+ preMultiplyOnLoad );
}
return pixelBuffer;
{
return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas,
false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy,
- preMultiplyOnLoad, false );
+ preMultiplyOnLoad );
}
TextureManager::TextureId TextureManager::RequestLoad(
{
return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas,
cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy,
- preMultiplyOnLoad, false );
+ preMultiplyOnLoad );
}
TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl )
auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL,
SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL, true,
- TextureManager::ReloadPolicy::CACHED, preMultiply, false );
+ TextureManager::ReloadPolicy::CACHED, preMultiply );
}
TextureManager::TextureId TextureManager::RequestLoadInternal(
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
- bool loadPixelBuffer )
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
{
// First check if the requested Texture is cached.
const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
maskTextureId );
TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
-
// Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
int cacheIndex = FindCachedTexture( textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
- maskTextureId, preMultiplyOnLoad );
+ maskTextureId, preMultiplyOnLoad, storageType );
// Check if the requested Texture exists in the cache.
if( cacheIndex != INVALID_CACHE_INDEX )
mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(),
desiredSize, contentScale, fittingMode, samplingMode,
false, cropToMask, useAtlas, textureHash, orientationCorrection,
- preMultiply, loadPixelBuffer ) );
+ preMultiply ) );
cacheIndex = mTextureInfoContainer.size() - 1u;
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n",
{
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n",
url.GetUrl().c_str(), observer, cacheIndex, textureId );
+
textureInfo.loadState = TextureManager::NOT_STARTED;
}
break;
}
case TextureManager::LOAD_FINISHED:
+ {
// Loading has already completed.
- if( observer && textureInfo.loadPixelBuffer )
+ if( observer && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER )
{
LoadOrQueueTexture( textureInfo, observer );
}
break;
+ }
}
// Return the TextureId for which this Texture can now be referenced by externally.
textureInfo.useAtlas, textureInfo.atlasRect,
textureInfo.preMultiplied );
}
- else if ( textureInfo.loadState == LOAD_FINISHED && textureInfo.loadPixelBuffer )
+ else if ( textureInfo.loadState == LOAD_FINISHED && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER )
{
element.mObserver->LoadComplete( true, textureInfo.pixelBuffer, textureInfo.url, textureInfo.preMultiplied );
}
textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
textureInfo.loadState = LOAD_FINISHED;
- if( textureInfo.loadPixelBuffer )
+ if( textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER )
{
NotifyObservers( textureInfo, true );
}
- // Check if there was another texture waiting for this load to complete
- // (e.g. if this was an image mask, and its load is on a different thread)
- CheckForWaitingTexture( textureInfo );
+ else
+ {
+ // Check if there was another texture waiting for this load to complete
+ // (e.g. if this was an image mask, and its load is on a different thread)
+ CheckForWaitingTexture( textureInfo );
+ }
}
}
else
info->observerList.Erase( info->observerList.begin() );
- if( info->loadPixelBuffer )
+ if( info->storageType == StorageType::RETURN_PIXEL_BUFFER )
{
observer->LoadComplete( success, info->pixelBuffer, info->url, info->preMultiplied );
}
mQueueLoadFlag = false;
ProcessQueuedTextures();
- if( info->loadPixelBuffer && info->observerList.Count() == 0 )
+ if( info->storageType == StorageType::RETURN_PIXEL_BUFFER && info->observerList.Count() == 0 )
{
Remove( info->textureId, nullptr );
}
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
TextureId maskTextureId,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad )
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad,
+ StorageType storageType )
{
// Default to an invalid ID, in case we do not find a match.
int cacheIndex = INVALID_CACHE_INDEX;
( size == textureInfo.desiredSize ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
- samplingMode == textureInfo.samplingMode ) ) )
+ samplingMode == textureInfo.samplingMode ) ) &&
+ ( storageType == textureInfo.storageType ) )
{
// 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
// 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
};
/**
- * Whether the pixel data should be kept in TextureManager, or uploaded for rendering
+ * Whether the pixel data should be kept in TextureManager, returned with pixelBuffer or uploaded for rendering
*/
enum StorageType
{
KEEP_PIXEL_BUFFER,
+ RETURN_PIXEL_BUFFER,
UPLOAD_TO_TEXTURE
};
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- MultiplyOnLoad& preMultiplyOnLoad,
- bool loadPixelBuffer );
+ MultiplyOnLoad& preMultiplyOnLoad );
/**
* @brief Get the current state of a texture
UseAtlas useAtlas,
TextureManager::TextureHash hash,
bool orientationCorrection,
- bool preMultiplyOnLoad,
- bool loadPixelBuffer )
+ bool preMultiplyOnLoad )
: url( url ),
desiredSize( desiredSize ),
useSize( desiredSize ),
cropToMask( cropToMask ),
orientationCorrection( true ),
preMultiplyOnLoad( preMultiplyOnLoad ),
- preMultiplied( false ),
- loadPixelBuffer( loadPixelBuffer )
+ preMultiplied( false )
{
}
bool orientationCorrection:1; ///< true if the image should be rotated to match exif orientation data
bool preMultiplyOnLoad:1; ///< true if the image's color should be multiplied by it's alpha
bool preMultiplied:1; ///< true if the image's color was multiplied by it's alpha
- bool loadPixelBuffer:1; ///< true if the image is needed to be returned as PixelBuffer
};
/**
/**
* @brief Looks up a cached texture by its hash.
* If found, the given parameters are used to check there is no hash-collision.
- * @param[in] hash The hash to look up
- * @param[in] url The URL of the image to load
- * @param[in] size The image size
- * @param[in] fittingMode The FittingMode to use
- * @param[in] samplingMode The SamplingMode to use
- * @param[in] useAtlas True if atlased
- * @param[in] maskTextureId Optional texture ID to use to mask this image
+ * @param[in] hash The hash to look up
+ * @param[in] url The URL of the image to load
+ * @param[in] size The image size
+ * @param[in] fittingMode The FittingMode to use
+ * @param[in] samplingMode The SamplingMode to use
+ * @param[in] useAtlas True if atlased
+ * @param[in] maskTextureId Optional texture ID to use to mask this image
+ * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
+ * @param[in] storageType Whether the pixel data is stored in the cache, returned with PixelBuffer or uploaded to the GPU
* @return A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
*/
TextureManager::TextureId FindCachedTexture(
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
TextureId maskTextureId,
- MultiplyOnLoad preMultiplyOnLoad);
+ MultiplyOnLoad preMultiplyOnLoad,
+ StorageType storageType );
private: