X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fimage%2Fimage-visual.cpp;h=028773d11c4539ccb17d6f8423ddde09b57c49c5;hb=f3e45e41c5f16ccc2538b283897ed6efb07e4ea9;hp=6f3231d2131bddc721e657ea1bd9a8d24e9c5bce;hpb=3e429d522301e97a4333153145d56b9a127d89e8;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 6f3231d..028773d 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -40,7 +42,6 @@ #include #include #include -#include namespace Dali { @@ -129,6 +130,7 @@ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, { ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode ) ); imageVisualPtr->SetProperties( properties ); + imageVisualPtr->Initialize(); return imageVisualPtr; } @@ -139,35 +141,37 @@ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ) { - return new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode ); + ImageVisualPtr imageVisualPtr(new ImageVisual(factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode)); + imageVisualPtr->Initialize(); + return imageVisualPtr; } -ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, - ImageVisualShaderFactory& shaderFactory, - const VisualUrl& imageUrl, - ImageDimensions size, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode ) -: Visual::Base( factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::IMAGE ), - mPixelArea( FULL_TEXTURE_RECT ), +ImageVisual::ImageVisual(VisualFactoryCache& factoryCache, + ImageVisualShaderFactory& shaderFactory, + const VisualUrl& imageUrl, + ImageDimensions size, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode) +: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::IMAGE), + mPixelArea(FULL_TEXTURE_RECT), mPlacementActor(), - mImageUrl( imageUrl ), - mMaskingData( ), - mDesiredSize( size ), - mTextureId( TextureManager::INVALID_TEXTURE_ID ), + mImageUrl(imageUrl), + mMaskingData(), + mDesiredSize(size), + mTextureId(TextureManager::INVALID_TEXTURE_ID), mTextures(), - mImageVisualShaderFactory( shaderFactory ), - mFittingMode( fittingMode ), - mSamplingMode( samplingMode ), - mWrapModeU( WrapMode::DEFAULT ), - mWrapModeV( 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 ) + mImageVisualShaderFactory(shaderFactory), + mFittingMode(fittingMode), + mSamplingMode(samplingMode), + mWrapModeU(WrapMode::DEFAULT), + mWrapModeV(WrapMode::DEFAULT), + mLoadPolicy(Toolkit::ImageVisual::LoadPolicy::ATTACHED), + mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED), + mAtlasRect(0.0f, 0.0f, 0.0f, 0.0f), + mAtlasRectSize(0, 0), + mLoadState(TextureManager::LoadState::NOT_STARTED), + mAttemptAtlasing(false), + mOrientationCorrection(true) { EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() ); } @@ -509,60 +513,33 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize ) naturalSize = Vector2::ZERO; } -void ImageVisual::CreateRenderer( TextureSet& textureSet ) +void ImageVisual::OnInitialize() { Geometry geometry; - Shader shader; - if( !mImpl->mCustomShader ) + // Get the geometry + if( mImpl->mCustomShader ) + { + geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize ); + } + else // Get any geometry associated with the texture { TextureManager& textureManager = mFactoryCache.GetTextureManager(); - uint32_t opaqueElementsCount {0u}; - uint32_t transparentElementsCount {0u}; - geometry = textureManager.GetRenderGeometry(mTextureId, opaqueElementsCount, transparentElementsCount); - if(!opaqueElementsCount && !transparentElementsCount) - { - geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); - } + uint32_t firstElementCount {0u}; + uint32_t secondElementCount {0u}; + geometry = textureManager.GetRenderGeometry(mTextureId, firstElementCount, secondElementCount); - shader = mImageVisualShaderFactory.GetShader( mFactoryCache, - mImpl->mFlags & Impl::IS_ATLASING_APPLIED, - mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE, - IsRoundedCornerRequired() ); - } - else - { - geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize ); - if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() ) - { - // Use custom hints - shader = Shader::New( mImageVisualShaderFactory.GetVertexShaderSource(), mImageVisualShaderFactory.GetFragmentShaderSource(), mImpl->mCustomShader->mHints ); - shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); - } - else + if(!firstElementCount && !secondElementCount) // Otherwise use quad { - 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 ); - } + geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); } } - // Set pixel align off as default. - // ToDo: Pixel align causes issues such as rattling image animation. - // We should trun it off until issues are resolved - shader.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF ); + Shader shader = GetShader(); + // Create the renderer mImpl->mRenderer = Renderer::New( geometry, shader ); - if( textureSet ) - { - mImpl->mRenderer.SetTextures( textureSet ); - } - // else still waiting for texture load to finish. //Register transform properties mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); @@ -589,16 +566,29 @@ void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& t ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; - textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, - mMaskingData, IsSynchronousLoadingRequired(), mTextureId, - atlasRect, mAtlasRectSize, atlasing, mLoading, mWrapModeU, - mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, - mOrientationCorrection, forceReload, preMultiplyOnLoad); + bool synchronousLoading = IsSynchronousLoadingRequired(); + bool loadingStatus; + + textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, mWrapModeU, mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad); if( textures ) { + if(loadingStatus) + { + mLoadState = TextureManager::LoadState::LOADING; + } + else + { + mLoadState = TextureManager::LoadState::LOAD_FINISHED; + } + EnablePreMultipliedAlpha( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ); } + else if(synchronousLoading) + { + // Synchronous loading is failed + mLoadState = TextureManager::LoadState::LOAD_FAILED; + } if( atlasing ) // Flag needs to be set before creating renderer { @@ -641,8 +631,11 @@ void ImageVisual::InitializeRenderer() } } - CreateRenderer( mTextures ); - mTextures.Reset(); // Visual should not keep a handle to the texture after this point. + if(mTextures) + { + mImpl->mRenderer.SetTextures(mTextures); + mTextures.Reset(); // Visual should not keep a handle to the texture after this point. + } if( attemptAtlasing ) // the texture is packed inside atlas { @@ -685,7 +678,7 @@ void ImageVisual::DoSetOnScene( Actor& actor ) mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea ); } - if( mLoading == false ) + if(mLoadState == TextureManager::LoadState::LOAD_FINISHED) { actor.AddRenderer( mImpl->mRenderer ); mPlacementActor.Reset(); @@ -693,22 +686,38 @@ void ImageVisual::DoSetOnScene( Actor& actor ) // Image loaded and ready to display ResourceReady( Toolkit::Visual::ResourceStatus::READY ); } + else if(mLoadState == TextureManager::LoadState::LOAD_FAILED) + { + Texture brokenImage = mFactoryCache.GetBrokenVisualImage(); + + mTextures = TextureSet::New(); + mTextures.SetTexture(0u, brokenImage); + mImpl->mRenderer.SetTextures(mTextures); + + actor.AddRenderer(mImpl->mRenderer); + mPlacementActor.Reset(); + + ResourceReady(Toolkit::Visual::ResourceStatus::FAILED); + } } void ImageVisual::DoSetOffScene( Actor& actor ) { // Visual::Base::SetOffScene only calls DoSetOffScene if mRenderer exists (is on onstage) - // Image release is dependent on the ReleasePolicy, renderer is destroyed. + // Image release is dependent on the ReleasePolicy, renderer is removed. actor.RemoveRenderer( mImpl->mRenderer); if( mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED ) { RemoveTexture(); // If INVALID_TEXTURE_ID then removal will be attempted on atlas mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING; + + TextureSet textureSet = TextureSet::New(); + mImpl->mRenderer.SetTextures(textureSet); + + mLoadState = TextureManager::LoadState::NOT_STARTED; } - mLoading = false; - mImpl->mRenderer.Reset(); mPlacementActor.Reset(); } @@ -788,6 +797,15 @@ bool ImageVisual::IsResourceReady() const mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED ); } +void ImageVisual::UpdateShader() +{ + if(mImpl->mRenderer) + { + Shader shader = GetShader(); + mImpl->mRenderer.SetShader(shader); + } +} + // From existing atlas manager void ImageVisual::UploadCompleted() { @@ -801,9 +819,10 @@ void ImageVisual::UploadCompleted() // reset the weak handle so that the renderer only get added to actor once mPlacementActor.Reset(); } + // Image loaded ResourceReady( Toolkit::Visual::ResourceStatus::READY ); - mLoading = false; + mLoadState = TextureManager::LoadState::LOAD_FINISHED; } // From Texture Manager @@ -854,37 +873,39 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur if( loadingSuccess ) { resourceStatus = Toolkit::Visual::ResourceStatus::READY; + mLoadState = TextureManager::LoadState::LOAD_FINISHED; } else { resourceStatus = Toolkit::Visual::ResourceStatus::FAILED; + mLoadState = TextureManager::LoadState::LOAD_FAILED; } // use geometry if needed if( loadingSuccess ) { - uint32_t opaqueElements{0u}; - uint32_t transparentElements{0u}; - auto geometry = mFactoryCache.GetTextureManager().GetRenderGeometry(mTextureId, opaqueElements, transparentElements); + uint32_t firstElementCount{0u}; + uint32_t secondElementCount{0u}; + auto geometry = mFactoryCache.GetTextureManager().GetRenderGeometry(mTextureId, firstElementCount, secondElementCount); if (mImpl->mRenderer && geometry) { mImpl->mRenderer.SetGeometry(geometry); Dali::DevelRenderer::DrawCommand drawCommand{}; drawCommand.drawType = DevelRenderer::DrawType::INDEXED; - if (opaqueElements) + if (firstElementCount) { drawCommand.firstIndex = 0; - drawCommand.elementCount = opaqueElements; - drawCommand.queue = 0; + drawCommand.elementCount = firstElementCount; + drawCommand.queue = DevelRenderer::RENDER_QUEUE_OPAQUE; DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand); } - if (transparentElements) + if (secondElementCount) { - drawCommand.firstIndex = opaqueElements; - drawCommand.elementCount = transparentElements; - drawCommand.queue = 1; + drawCommand.firstIndex = firstElementCount; + drawCommand.elementCount = secondElementCount; + drawCommand.queue = DevelRenderer::RENDER_QUEUE_TRANSPARENT; DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand); } } @@ -892,7 +913,6 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur // Signal to observers ( control ) that resources are ready. Must be all resources. ResourceReady( resourceStatus ); - mLoading = false; } void ImageVisual::RemoveTexture() @@ -913,7 +933,6 @@ void ImageVisual::RemoveTexture() } TextureSet textureSet = mImpl->mRenderer.GetTextures(); - mImpl->mRenderer.Reset(); if( index != Property::INVALID_INDEX ) { @@ -922,6 +941,76 @@ void ImageVisual::RemoveTexture() } } +Shader ImageVisual::GetShader() +{ + Shader shader; + + std::string_view vertexShaderView; + bool usesWholeTexture = true; + if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty()) + { + vertexShaderView = mImpl->mCustomShader->mVertexShader; + usesWholeTexture = false; // Impossible to tell. + } + else + { + vertexShaderView = mImageVisualShaderFactory.GetVertexShaderSource(); + } + + std::string_view fragmentShaderView; + if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty()) + { + fragmentShaderView = mImpl->mCustomShader->mFragmentShader; + } + else + { + fragmentShaderView = mImageVisualShaderFactory.GetFragmentShaderSource(); + } + + // If the texture is native, we may need to change prefix and sampler in + // the fragment shader + bool modifiedFragmentShader = false; + std::string fragmentShaderString; + if(mTextures && DevelTexture::IsNative(mTextures.GetTexture(0))) + { + Texture nativeTexture = mTextures.GetTexture(0); + fragmentShaderString = std::string(fragmentShaderView); + modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShaderString); + fragmentShaderView = fragmentShaderString; + } + + const bool useStandardShader = !mImpl->mCustomShader && !modifiedFragmentShader; + if(useStandardShader) + { + // Create and cache the standard shader + shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + mImpl->mFlags & Impl::IS_ATLASING_APPLIED, + mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE, + IsRoundedCornerRequired() ); + } + else if(mImpl->mCustomShader) + { + shader = Shader::New(vertexShaderView, fragmentShaderView, mImpl->mCustomShader->mHints); + } + else + { + shader = Shader::New(vertexShaderView, fragmentShaderView); + } + + if(usesWholeTexture) + { + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + } + + // Set pixel align off as default. + // ToDo: Pixel align causes issues such as rattling image animation. + // We should trun it off until issues are resolved + shader.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF ); + + return shader; +} + } // namespace Internal } // namespace Toolkit