application.SendNotification();
application.Render();
- DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 3 ), true, TEST_LOCATION );
application.SendNotification();
application.Render();
application.SendNotification();
application.Render();
- DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 3 ), true, TEST_LOCATION );
application.SendNotification();
application.Render();
application.SendNotification();
application.Render();
- DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 3 ), true, TEST_LOCATION );
application.SendNotification();
application.Render();
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
return GetImplementation( asyncImageLoader ).Load( Toolkit::Internal::VisualUrl(url), dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
}
+uint32_t ApplyMask( AsyncImageLoader asyncImageLoader,
+ Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask )
+{
+ return GetImplementation( asyncImageLoader ).ApplyMask( pixelBuffer, maskPixelBuffer, contentScale, cropToMask );
+}
+
PixelBufferLoadedSignalType& PixelBufferLoadedSignal( AsyncImageLoader asyncImageLoader )
{
return GetImplementation( asyncImageLoader ).PixelBufferLoadedSignal();
#define DALI_TOOLKIT_DEVEL_API_IMAGE_LOADER_ASYNC_IMAGE_LOADER_DEVEL_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
namespace DevelAsyncImageLoader
{
-typedef Signal< void ( uint32_t, Devel::PixelBuffer ) > PixelBufferLoadedSignalType;
+typedef Signal< void ( uint32_t, Devel::PixelBuffer, bool ) > PixelBufferLoadedSignalType;
/**
* @brief Whether to multiply alpha into color channels on load
* @param[in] preMultiplyOnLoad ON if the image color should be multiplied by it's alpha. Set to OFF if there is no alpha
* @return The loading task id
*/
-DALI_TOOLKIT_API uint32_t Load( AsyncImageLoader asyncImageLoader,
- const std::string& url,
- ImageDimensions dimensions,
- FittingMode::Type fittingMode,
- SamplingMode::Type samplingMode,
- bool orientationCorrection,
- DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad );
+DALI_TOOLKIT_API uint32_t Load( AsyncImageLoader asyncImageLoader,
+ const std::string& url,
+ ImageDimensions dimensions,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
+ bool orientationCorrection,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad );
+
+/**
+ * @brief Starts an mask applying task.
+ * @REMARK_INTERNET
+ * @REMARK_STORAGE
+ * @param[in] asyncImageLoader The ayncImageLoader
+ * @param[in] pixelBuffer Pointer to raw pixel data to be masked
+ * @param[in] maskPixelBuffer Pointer to raw masking data
+ * @param[in] contentScale The factor to scale the content
+ * @param[in] cropToMask Whether to crop the content to the mask size
+ * @return The masking task id
+ */
+DALI_TOOLKIT_API uint32_t ApplyMask( AsyncImageLoader asyncImageLoader,
+ Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask );
/**
* Connect to this signal if you want to load a PixelBuffer instead of a PixelData.
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
return mLoadTaskId;
}
+uint32_t AsyncImageLoader::ApplyMask( Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask )
+{
+ if( !mIsLoadThreadStarted )
+ {
+ mLoadThread.Start();
+ mIsLoadThreadStarted = true;
+ }
+ mLoadThread.AddTask( new LoadingTask( ++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask ) );
+
+ return mLoadTaskId;
+}
+
Toolkit::AsyncImageLoader::ImageLoadedSignalType& AsyncImageLoader::ImageLoadedSignal()
{
return mLoadedSignal;
{
if( mPixelBufferLoadedSignal.GetConnectionCount() > 0 )
{
- mPixelBufferLoadedSignal.Emit( next->id, next->pixelBuffer );
+ mPixelBufferLoadedSignal.Emit( next->id, next->pixelBuffer, next->isMaskTask );
}
else if( mLoadedSignal.GetConnectionCount() > 0 )
{
#define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad );
/**
+ * @brief Starts an mask applying task.
+ * @param[in] pixelBuffer of the to be masked image
+ * @param[in] maskPixelBuffer of the mask image
+ * @param[in] contentScale The factor to scale the content
+ * @param[in] cropToMask Whether to crop the content to the mask size
+ * @return The loading task id
+ */
+ uint32_t ApplyMask( Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask );
+
+ /**
* @copydoc Toolkit::AsyncImageLoader::ImageLoadedSignal
*/
Toolkit::AsyncImageLoader::ImageLoadedSignalType& ImageLoadedSignal();
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
fittingMode( fittingMode ),
samplingMode( samplingMode ),
orientationCorrection( orientationCorrection ),
- preMultiplyOnLoad( preMultiplyOnLoad )
+ preMultiplyOnLoad( preMultiplyOnLoad ),
+ isMaskTask( false ),
+ maskPixelBuffer(),
+ contentScale( 1.0f ),
+ cropToMask( false )
+{
+}
+
+LoadingTask::LoadingTask( uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask )
+: pixelBuffer( pixelBuffer ),
+ url( "" ),
+ id( id ),
+ dimensions(),
+ fittingMode(),
+ samplingMode(),
+ orientationCorrection(),
+ preMultiplyOnLoad(),
+ isMaskTask( true ),
+ maskPixelBuffer( maskPixelBuffer ),
+ contentScale( contentScale ),
+ cropToMask( cropToMask )
{
}
}
}
+void LoadingTask::ApplyMask()
+{
+ pixelBuffer.ApplyMask( maskPixelBuffer, contentScale, cropToMask );
+}
ImageLoadThread::ImageLoadThread( EventThreadCallback* trigger )
: mTrigger( trigger ),
while( LoadingTask* task = NextTaskToProcess() )
{
- task->Load();
+ if( !task->isMaskTask )
+ {
+ task->Load();
+ }
+ else
+ {
+ task->ApplyMask();
+ }
+
AddCompletedTask( task );
}
}
* @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
* @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha.
*/
- LoadingTask( uint32_t id, const VisualUrl& url, ImageDimensions dimensions,
- FittingMode::Type fittingMode, SamplingMode::Type samplingMode,
+ LoadingTask( uint32_t id,
+ const VisualUrl& url,
+ ImageDimensions dimensions,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
bool orientationCorrection,
- DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad );
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+
+ /**
+ * Constructor.
+ * @param [in] id of the task
+ * @param [in] pixelBuffer of the to be masked image
+ * @param [in] maskPixelBuffer of the mask image
+ * @param [in] contentScale The factor to scale the content
+ * @param [in] cropToMask Whether to crop the content to the mask size
+ */
+ LoadingTask( uint32_t id,
+ Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask );
/**
* Load the image
*/
void Load();
+ /**
+ * Apply mask
+ */
+ void ApplyMask();
+
private:
// Undefined
public:
Devel::PixelBuffer pixelBuffer; ///< pixelBuffer handle after successful load
+ ///< or pixelBuffer to be masked image in the mask task
VisualUrl url; ///< url of the image to load
uint32_t id; ///< The unique id associated with this task.
ImageDimensions dimensions; ///< dimensions to load
SamplingMode::Type samplingMode; ///< sampling options
bool orientationCorrection:1; ///< if orientation correction is needed
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad; //< if the image's color should be multiplied by it's alpha
+
+ bool isMaskTask; ///< whether this task is for mask or not
+ Devel::PixelBuffer maskPixelBuffer; ///< pixelBuffer of mask image
+ float contentScale; ///< The factor to scale the content
+ bool cropToMask; ///< Whether to crop the content to the mask size
};
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
loadState == TextureManager::LOADING ? "LOADING" : \
loadState == TextureManager::LOAD_FINISHED ? "LOAD_FINISHED" : \
loadState == TextureManager::WAITING_FOR_MASK ? "WAITING_FOR_MASK" : \
+ loadState == TextureManager::MASK_APPLYING ? "MASK_APPLYING" : \
+ loadState == TextureManager::MASK_APPLIED ? "MASK_APPLIED" : \
loadState == TextureManager::UPLOADED ? "UPLOADED" : \
loadState == TextureManager::CANCELLED ? "CANCELLED" : \
loadState == TextureManager::LOAD_FAILED ? "LOAD_FAILED" : "Unknown"
// If we are loading the texture, or waiting for the ready signal handler to complete, inform
// caller that they need to wait.
loadingStatus = ( loadState == TextureManager::LOADING ||
+ loadState == TextureManager::WAITING_FOR_MASK ||
+ loadState == TextureManager::MASK_APPLYING ||
+ loadState == TextureManager::MASK_APPLIED ||
loadState == TextureManager::NOT_STARTED ||
mQueueLoadFlag );
GET_LOAD_STATE_STRING(textureInfo.loadState ) );
// Force reloading of texture by setting loadState unless already loading or cancelled.
- if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy && TextureManager::LOADING != textureInfo.loadState &&
+ if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy &&
+ TextureManager::LOADING != textureInfo.loadState &&
+ TextureManager::WAITING_FOR_MASK != textureInfo.loadState &&
+ TextureManager::MASK_APPLYING != textureInfo.loadState &&
+ TextureManager::MASK_APPLIED != textureInfo.loadState &&
TextureManager::CANCELLED != textureInfo.loadState )
{
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n",
break;
}
case TextureManager::LOADING:
+ case TextureManager::WAITING_FOR_MASK:
+ case TextureManager::MASK_APPLYING:
+ case TextureManager::MASK_APPLIED:
{
ObserveTexture( textureInfo, observer );
break;
break;
}
case TextureManager::LOAD_FINISHED:
- case TextureManager::WAITING_FOR_MASK:
// Loading has already completed. Do nothing.
break;
}
}
break;
}
- case LOADING:
case UPLOADED:
{
if( mQueueLoadFlag )
}
break;
}
+ case LOADING:
case CANCELLED:
case LOAD_FINISHED:
case WAITING_FOR_MASK:
+ case MASK_APPLYING:
+ case MASK_APPLIED:
{
break;
}
}
void TextureManager::AsyncLoadComplete( AsyncLoadingInfoContainerType& loadingContainer, uint32_t id,
- Devel::PixelBuffer pixelBuffer )
+ Devel::PixelBuffer pixelBuffer, bool isMaskTask )
{
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( id:%d )\n", id );
if( textureInfo.loadState != CANCELLED )
{
+ if( isMaskTask )
+ {
+ textureInfo.loadState = MASK_APPLIED;
+ }
// textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified)
PostLoad( textureInfo, pixelBuffer );
}
// wait for the mask to finish loading.
if( textureInfo.maskTextureId != INVALID_TEXTURE_ID )
{
- LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId );
- if( maskLoadState == LOADING )
+ if( textureInfo.loadState == MASK_APPLIED )
{
- textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
- textureInfo.loadState = WAITING_FOR_MASK;
- }
- else if( maskLoadState == LOAD_FINISHED )
- {
- ApplyMask( pixelBuffer, textureInfo.maskTextureId, textureInfo.scaleFactor, textureInfo.cropToMask );
UploadTexture( pixelBuffer, textureInfo );
NotifyObservers( textureInfo, true );
}
+ else
+ {
+ LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId );
+ textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
+ if( maskLoadState == LOADING )
+ {
+ textureInfo.loadState = WAITING_FOR_MASK;
+ }
+ else if( maskLoadState == LOAD_FINISHED )
+ {
+ // Send New Task to Thread
+ ApplyMask( textureInfo, textureInfo.maskTextureId );
+ }
+ }
}
else
{
}
else
{
- DALI_LOG_ERROR( "TextureManager::AsyncImageLoad(%s) failed\n", textureInfo.url.GetUrl().c_str() );
// @todo If the load was unsuccessful, upload the broken image.
textureInfo.loadState = LOAD_FAILED;
CheckForWaitingTexture( textureInfo );
mTextureInfoContainer[cacheIndex].loadState == WAITING_FOR_MASK )
{
TextureInfo& textureInfo( mTextureInfoContainer[cacheIndex] );
- Devel::PixelBuffer pixelBuffer = textureInfo.pixelBuffer;
- textureInfo.pixelBuffer.Reset();
if( maskTextureInfo.loadState == LOAD_FINISHED )
{
- ApplyMask( pixelBuffer, maskTextureInfo.textureId, textureInfo.scaleFactor, textureInfo.cropToMask );
- UploadTexture( pixelBuffer, textureInfo );
- NotifyObservers( textureInfo, true );
+ // Send New Task to Thread
+ ApplyMask( textureInfo, maskTextureInfo.textureId );
}
else
{
- DALI_LOG_ERROR( "TextureManager::ApplyMask to %s failed\n", textureInfo.url.GetUrl().c_str() );
+ textureInfo.pixelBuffer.Reset();
textureInfo.loadState = LOAD_FAILED;
NotifyObservers( textureInfo, false );
}
}
}
-void TextureManager::ApplyMask(
- Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
- float contentScale, bool cropToMask )
+void TextureManager::ApplyMask( TextureInfo& textureInfo, TextureId maskTextureId )
{
int maskCacheIndex = GetCacheIndexFromId( maskTextureId );
if( maskCacheIndex != INVALID_CACHE_INDEX )
{
Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
- pixelBuffer.ApplyMask( maskPixelBuffer, contentScale, cropToMask );
+ Devel::PixelBuffer pixelBuffer = textureInfo.pixelBuffer;
+ textureInfo.pixelBuffer.Reset();
+
+ DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n",
+ textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously?"T":"F" );
+
+ textureInfo.loadState = MASK_APPLYING;
+ auto& loadersContainer = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+ auto loadingHelperIt = loadersContainer.GetNext();
+ DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
+ loadingHelperIt->ApplyMask( textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask );
}
}
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
{
mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
- auto id = DevelAsyncImageLoader::Load(mLoader, url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
+ auto id = DevelAsyncImageLoader::Load( mLoader, url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad );
+ mLoadingInfoContainer.back().loadId = id;
+}
+
+void TextureManager::AsyncLoadingHelper::ApplyMask( TextureId textureId,
+ Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask )
+{
+ mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+ auto id = DevelAsyncImageLoader::ApplyMask( mLoader, pixelBuffer, maskPixelBuffer, contentScale, cropToMask );
mLoadingInfoContainer.back().loadId = id;
}
}
void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t id,
- Devel::PixelBuffer pixelBuffer)
+ Devel::PixelBuffer pixelBuffer,
+ bool isMaskTask)
{
- mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer);
+ mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer, isMaskTask);
}
void TextureManager::SetBrokenImageUrl(const std::string& brokenImageUrl)
#define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
LOADING, ///< Loading has been started, but not finished.
LOAD_FINISHED, ///< Loading has finished. (for CPU storage only)
WAITING_FOR_MASK,///< Loading has finished, but waiting for mask image
+ MASK_APPLYING, ///< Loading has finished, Mask is applying
+ MASK_APPLIED, ///< Loading has finished, Mask is applyied by GPU
UPLOADED, ///< Uploaded and ready. (For GPU upload only)
CANCELLED, ///< Removed before loading completed
LOAD_FAILED ///< Async loading failed, e.g. connection problem
* @param[in] container The Async loading container
* @param[in] id This is the async image loaders Id
* @param[in] pixelBuffer The loaded image data
+ * @param[in] isMaskTask whether this task is for mask or not
*/
- void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer );
+ void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer, bool isMaskTask );
/**
* @brief Performs Post-Load steps including atlasing.
/**
* Apply the mask to the pixelBuffer.
- * @param[in] pixelBuffer The pixelBuffer to apply the mask to
+ * @param[in] textureInfo The information of texture to apply the mask to
* @param[in] maskTextureId The texture id of the mask.
- * @param[in] contentScale The factor to scale the content
- * @param[in] cropToMask Whether to crop the content to the mask size
*/
- void ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
- float contentScale, bool cropToMask );
+ void ApplyMask( TextureInfo& textureInfo, TextureId maskTextureId );
/**
* Upload the texture specified in pixelBuffer to the appropriate location
bool orientationCorrection,
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+ /**
+ * @brief Apply mask
+ * @param [in] id of the texture
+ * @param [in] pixelBuffer of the to be masked image
+ * @param [in] maskPixelBuffer of the mask image
+ * @param [in] contentScale The factor to scale the content
+ * @param [in] cropToMask Whether to crop the content to the mask size
+ */
+ void ApplyMask( TextureId textureId,
+ Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask );
+
public:
AsyncLoadingHelper(const AsyncLoadingHelper&) = delete;
AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete;
* @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
* @param[in] id Loader id
* @param[in] pixelBuffer Image data
+ * @param[in] isMaskTask whether this task is for mask or not
*/
- void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
+ void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer, bool isMaskTask);
private:
Toolkit::AsyncImageLoader mLoader;