/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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-toolkit/internal/visuals/image-atlas-manager.h>
#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
namespace Dali
{
const float PIXEL_ALIGN_ON = 1.0f;
const float PIXEL_ALIGN_OFF = 0.0f;
-const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
- attribute mediump vec2 aPosition;\n
- uniform mediump mat4 uModelMatrix;\n
- uniform mediump mat4 uViewMatrix;\n
- uniform mediump mat4 uProjection;\n
- uniform mediump vec3 uSize;\n
- uniform mediump vec4 pixelArea;
- varying mediump vec2 vTexCoord;\n
- uniform lowp float uPixelAligned;\n
- \n
- //Visual size and offset
- uniform mediump vec2 offset;\n
- uniform mediump vec2 size;\n
- uniform mediump vec4 offsetSizeMode;\n
- uniform mediump vec2 origin;\n
- uniform mediump vec2 anchorPoint;\n
-\n
- vec4 ComputeVertexPosition()\n
- {\n
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n
- return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
- }\n
-\n
- void main()\n
- {\n
- mediump vec4 vertexPosition = uViewMatrix * uModelMatrix * ComputeVertexPosition();\n
- vec4 alignedVertexPosition = vertexPosition;\n
- alignedVertexPosition.xy = floor ( vertexPosition.xy );\n // Pixel alignment
- vertexPosition = uProjection * mix( vertexPosition, alignedVertexPosition, uPixelAligned );\n
- vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n
- gl_Position = vertexPosition;\n
- }\n
-);
-
-const char* FRAGMENT_SHADER_NO_ATLAS = DALI_COMPOSE_SHADER(
- varying mediump vec2 vTexCoord;\n
- uniform sampler2D sTexture;\n
- uniform lowp vec4 uColor;\n
- uniform lowp vec3 mixColor;\n
- uniform lowp float opacity;\n
- uniform lowp float preMultipliedAlpha;\n
- \n
- lowp vec4 visualMixColor()\n
- {\n
- return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n
- }\n
- void main()\n
- {\n
- gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * visualMixColor();\n
- }\n
-);
-
-const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER(
- varying mediump vec2 vTexCoord;\n
- uniform sampler2D sTexture;\n
- uniform mediump vec4 uAtlasRect;\n
- uniform lowp vec4 uColor;\n
- uniform lowp vec3 mixColor;\n
- uniform lowp float opacity;\n
- uniform lowp float preMultipliedAlpha;\n
- \n
- lowp vec4 visualMixColor()\n
- {\n
- return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n
- }\n
- \n
- void main()\n
- {\n
- mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n
- gl_FragColor = texture2D( sTexture, texCoord ) * uColor * visualMixColor();\n
- }\n
-);
-
-const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER(
- varying mediump vec2 vTexCoord;\n
- uniform sampler2D sTexture;\n
- uniform mediump vec4 uAtlasRect;\n
- // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
- uniform lowp vec2 wrapMode;\n
- uniform lowp vec4 uColor;\n
- uniform lowp vec3 mixColor;\n
- uniform lowp float opacity;\n
- uniform lowp float preMultipliedAlpha;\n
- \n
- mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )\n
- {\n
- mediump float coord;\n
- if( wrap > 1.5 )\n // REFLECT
- coord = 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0);\n
- else \n// warp == 0 or 1
- coord = mix(coordinate, fract( coordinate ), wrap);\n
- return clamp( mix(range.x, range.y, coord), range.x, range.y );
- }\n
- \n
- lowp vec4 visualMixColor()\n
- {\n
- return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n
- }\n
- \n
- void main()\n
- {\n
- mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
- wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );\n
- gl_FragColor = texture2D( sTexture, texCoord ) * uColor * visualMixColor();\n
- }\n
-);
-
Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize )
{
Geometry geometry;
} // unnamed namespace
ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
+ ImageVisualShaderFactory& shaderFactory,
const VisualUrl& imageUrl,
const Property::Map& properties,
ImageDimensions size,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode )
{
- ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode ) );
+ ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode ) );
imageVisualPtr->SetProperties( properties );
return imageVisualPtr;
}
ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
+ ImageVisualShaderFactory& shaderFactory,
const VisualUrl& imageUrl,
ImageDimensions size,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode )
{
- return new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode );
+ return new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode );
}
-ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, const Image& image )
+ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
{
- return new ImageVisual( factoryCache, image );
+ return new ImageVisual( factoryCache, shaderFactory, image );
}
ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
+ ImageVisualShaderFactory& shaderFactory,
const VisualUrl& imageUrl,
ImageDimensions size,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode )
-: Visual::Base( factoryCache ),
+: Visual::Base( factoryCache, Visual::FittingMode::FILL ),
mImage(),
mPixelArea( FULL_TEXTURE_RECT ),
mPlacementActor(),
mDesiredSize( size ),
mTextureId( TextureManager::INVALID_TEXTURE_ID ),
mTextures(),
+ mImageVisualShaderFactory( shaderFactory ),
mFittingMode( fittingMode ),
mSamplingMode( samplingMode ),
mWrapModeU( WrapMode::DEFAULT ),
mLoadPolicy( Toolkit::ImageVisual::LoadPolicy::ATTACHED ),
mReleasePolicy( Toolkit::ImageVisual::ReleasePolicy::DETACHED ),
mAtlasRect( 0.0f, 0.0f, 0.0f, 0.0f ),
+ mAtlasRectSize( 0, 0 ),
mAttemptAtlasing( false ),
mLoading( false ),
mOrientationCorrection( true )
{
+ EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
-ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image )
-: Visual::Base( factoryCache ),
+ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
+: Visual::Base( factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO ),
mImage( image ),
mPixelArea( FULL_TEXTURE_RECT ),
mPlacementActor(),
mDesiredSize(),
mTextureId( TextureManager::INVALID_TEXTURE_ID ),
mTextures(),
+ mImageVisualShaderFactory( shaderFactory ),
mFittingMode( FittingMode::DEFAULT ),
mSamplingMode( SamplingMode::DEFAULT ),
mWrapModeU( WrapMode::DEFAULT ),
mLoading( false ),
mOrientationCorrection( true )
{
+ EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
ImageVisual::~ImageVisual()
if( mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID )
{
TextureManager& textureManager = mFactoryCache.GetTextureManager();
- textureManager.Remove( mMaskingData->mAlphaMaskId );
+ textureManager.Remove( mMaskingData->mAlphaMaskId, this );
}
}
{
case Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING:
{
- bool sync;
+ bool sync = false;
if( value.Get( sync ) )
{
if( sync )
case Toolkit::ImageVisual::Property::DESIRED_WIDTH:
{
- float desiredWidth;
+ float desiredWidth = 0.0f;
if( value.Get( desiredWidth ) )
{
mDesiredSize.SetWidth( desiredWidth );
case Toolkit::ImageVisual::Property::DESIRED_HEIGHT:
{
- float desiredHeight;
+ float desiredHeight = 0.0f;
if( value.Get( desiredHeight ) )
{
mDesiredSize.SetHeight( desiredHeight );
case Toolkit::ImageVisual::Property::FITTING_MODE:
{
- int fittingMode;
+ int fittingMode = 0;
Scripting::GetEnumerationProperty( value, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, fittingMode );
mFittingMode = Dali::FittingMode::Type( fittingMode );
break;
case Toolkit::ImageVisual::Property::SAMPLING_MODE:
{
- int samplingMode;
+ int samplingMode = 0;
Scripting::GetEnumerationProperty( value, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, samplingMode );
mSamplingMode = Dali::SamplingMode::Type( samplingMode );
break;
case Toolkit::ImageVisual::Property::WRAP_MODE_U:
{
- int wrapMode;
+ int wrapMode = 0;
Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode );
mWrapModeU = Dali::WrapMode::Type( wrapMode );
break;
case Toolkit::ImageVisual::Property::WRAP_MODE_V:
{
- int wrapMode;
+ int wrapMode = 0;
Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode );
mWrapModeV = Dali::WrapMode::Type( wrapMode );
break;
case Toolkit::ImageVisual::Property::ALPHA_MASK_URL:
{
- std::string alphaUrl;
+ std::string alphaUrl = "";
if( value.Get( alphaUrl ) )
{
AllocateMaskData();
- // Immediately trigger the alpha mask loading (it may just get a cached value)
mMaskingData->mAlphaMaskUrl = alphaUrl;
- TextureManager& textureManager = mFactoryCache.GetTextureManager();
- mMaskingData->mAlphaMaskId = textureManager.RequestMaskLoad( alphaUrl );
}
break;
}
case Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE:
{
- float scale;
+ float scale = 1.0f;
if( value.Get( scale ) )
{
AllocateMaskData();
case Toolkit::ImageVisual::Property::RELEASE_POLICY:
{
- int releasePolicy;
+ int releasePolicy = 0;
Scripting::GetEnumerationProperty( value, RELEASE_POLICY_TABLE, RELEASE_POLICY_TABLE_COUNT, releasePolicy );
mReleasePolicy = Toolkit::ImageVisual::ReleasePolicy::Type( releasePolicy );
break;
case Toolkit::ImageVisual::Property::LOAD_POLICY:
{
- int loadPolicy;
+ int loadPolicy = 0;
Scripting::GetEnumerationProperty( value, LOAD_POLICY_TABLE, LOAD_POLICY_TABLE_COUNT, loadPolicy );
mLoadPolicy = Toolkit::ImageVisual::LoadPolicy::Type( loadPolicy );
break;
}
else if( mImpl->mRenderer ) // Check if we have a loaded image
{
- auto textureSet = mImpl->mRenderer.GetTextures();
+ if( mImpl->mFlags & Impl::IS_ATLASING_APPLIED )
+ {
+ naturalSize.x = mAtlasRectSize.GetWidth();
+ naturalSize.y = mAtlasRectSize.GetHeight();
+ return;
+ }
+ auto textureSet = mImpl->mRenderer.GetTextures();
if( textureSet )
{
auto texture = textureSet.GetTexture(0);
}
else
{
- Image brokenImage = VisualFactoryCache::GetBrokenVisualImage();
+ Image brokenImage = mFactoryCache.GetBrokenVisualImage();
naturalSize.x = brokenImage.GetWidth();
naturalSize.y = brokenImage.GetWidth();
{
geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
- shader = GetImageShader( mFactoryCache,
+ shader = mImageVisualShaderFactory.GetShader( mFactoryCache,
mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE );
}
geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
{
- shader = GetImageShader( mFactoryCache, false, true );
+ // Use custom hints
+ shader = Shader::New( mImageVisualShaderFactory.GetVertexShaderSource(), mImageVisualShaderFactory.GetFragmentShaderSource(), mImpl->mCustomShader->mHints );
+ shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
}
else
{
- shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
- mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER_NO_ATLAS : mImpl->mCustomShader->mFragmentShader,
- mImpl->mCustomShader->mHints );
+ shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
+ mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource() : mImpl->mCustomShader->mFragmentShader,
+ mImpl->mCustomShader->mHints );
if( mImpl->mCustomShader->mVertexShader.empty() )
{
shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
//Register transform properties
mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
+
+ EnablePreMultipliedAlpha( IsPreMultipliedAlphaEnabled() );
}
void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
}
else
{
- fragmentShader += FRAGMENT_SHADER_NO_ATLAS;
+ fragmentShader += mImageVisualShaderFactory.GetFragmentShaderSource();
}
if( customSamplerTypename )
{
geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
- shader = Shader::New( VERTEX_SHADER, fragmentShader );
+ shader = Shader::New( mImageVisualShaderFactory.GetVertexShaderSource(), fragmentShader );
shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
}
else
{
geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
- shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
+ shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
fragmentShader,
mImpl->mCustomShader->mHints );
if( mImpl->mCustomShader->mVertexShader.empty() )
mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
}
-
bool ImageVisual::IsSynchronousResourceLoading() const
{
return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
atlasUploadObserver = this;
}
+ auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
+ ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+ : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode,
mMaskingData, IsSynchronousResourceLoading(), mTextureId,
- atlasRect, atlasing, mLoading, mWrapModeU,
+ atlasRect, mAtlasRectSize, atlasing, mLoading, mWrapModeU,
mWrapModeV, textureObserver, atlasUploadObserver, atlasManager,
- mOrientationCorrection,
- forceReload );
+ mOrientationCorrection, forceReload, preMultiplyOnLoad);
+
+ if( textures )
+ {
+ EnablePreMultipliedAlpha( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD );
+ }
if( atlasing ) // Flag needs to be set before creating renderer
{
if( mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED )
{
RemoveTexture(); // If INVALID_TEXTURE_ID then removal will be attempted on atlas
+ mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
}
if( mImageUrl.IsValid() )
mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED );
}
-Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping )
-{
- Shader shader;
- if( atlasing )
- {
- if( defaultTextureWrapping )
- {
- shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
- if( !shader )
- {
- shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP );
- shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
- factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
- }
- }
- else
- {
- shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP );
- if( !shader )
- {
- shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP );
- shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
- factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader );
- }
- }
- }
- else
- {
- shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
- if( !shader )
- {
- shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_NO_ATLAS );
- shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
- factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
- }
- }
-
- return shader;
-}
-
void ImageVisual::ApplyImageToSampler( const Image& image )
{
if( image )
// From Texture Manager
void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, TextureSet textureSet, bool usingAtlas,
- const Vector4& atlasRectangle )
+ const Vector4& atlasRectangle, bool preMultiplied )
{
Toolkit::Visual::ResourceStatus resourceStatus;
- Actor actor = mPlacementActor.GetHandle();
- if( actor )
+ if( mImpl->mRenderer )
{
- if( mImpl->mRenderer )
+ if( usingAtlas )
{
- if( usingAtlas )
- {
- mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
- }
+ mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
+ }
+ EnablePreMultipliedAlpha( preMultiplied );
+
+ Actor actor = mPlacementActor.GetHandle();
+ if( actor )
+ {
actor.AddRenderer( mImpl->mRenderer );
// reset the weak handle so that the renderer only get added to actor once
mPlacementActor.Reset();
- if( loadingSuccess )
- {
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode( mWrapModeU, mWrapModeV );
- textureSet.SetSampler( 0u, sampler );
- mImpl->mRenderer.SetTextures(textureSet);
- }
- else
- {
- Image brokenImage = VisualFactoryCache::GetBrokenVisualImage();
+ }
- textureSet = TextureSet::New();
- mImpl->mRenderer.SetTextures( textureSet );
+ if( loadingSuccess )
+ {
+ Sampler sampler = Sampler::New();
+ sampler.SetWrapMode( mWrapModeU, mWrapModeV );
+ textureSet.SetSampler( 0u, sampler );
+ mImpl->mRenderer.SetTextures(textureSet);
+ }
+ else
+ {
+ Image brokenImage = mFactoryCache.GetBrokenVisualImage();
- ApplyImageToSampler( brokenImage );
- }
+ textureSet = TextureSet::New();
+ mImpl->mRenderer.SetTextures( textureSet );
+
+ ApplyImageToSampler( brokenImage );
}
}
+
// Storing TextureSet needed when renderer staged.
if( ! mImpl->mRenderer )
{
{
if( mTextureId != TextureManager::INVALID_TEXTURE_ID )
{
- mFactoryCache.GetTextureManager().Remove( mTextureId );
+ mFactoryCache.GetTextureManager().Remove( mTextureId, this );
mTextureId = TextureManager::INVALID_TEXTURE_ID;
}
else