X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fimage%2Fimage-visual.cpp;h=d5bc01093e7dd613854bcda6cafc92a0aa8ed646;hb=HEAD;hp=5b2aff89ebfbdf793bf361d6f622e964bd60b720;hpb=1c1896d3ed691afb6d80f8b20bc66a994d5bc7f8;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 5b2aff8..65af749 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) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ DALI_ENUM_TO_STRING_TABLE_BEGIN(FITTING_MODE) DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, SCALE_TO_FILL) DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, FIT_WIDTH) DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, FIT_HEIGHT) + DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, VISUAL_FITTING) DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, DEFAULT) DALI_ENUM_TO_STRING_TABLE_END(FITTING_MODE) @@ -100,6 +102,35 @@ const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); constexpr uint32_t TEXTURE_COUNT_FOR_GPU_ALPHA_MASK = 2u; +struct NameIndexMatch +{ + const char* const name; + Property::Index index; +}; + +const NameIndexMatch NAME_INDEX_MATCH_TABLE[] = + { + {IMAGE_FITTING_MODE, Toolkit::ImageVisual::Property::FITTING_MODE}, + {IMAGE_SAMPLING_MODE, Toolkit::ImageVisual::Property::SAMPLING_MODE}, + {IMAGE_DESIRED_WIDTH, Toolkit::ImageVisual::Property::DESIRED_WIDTH}, + {IMAGE_DESIRED_HEIGHT, Toolkit::ImageVisual::Property::DESIRED_HEIGHT}, + {PIXEL_AREA_UNIFORM_NAME, Toolkit::ImageVisual::Property::PIXEL_AREA}, + {IMAGE_WRAP_MODE_U, Toolkit::ImageVisual::Property::WRAP_MODE_U}, + {IMAGE_WRAP_MODE_V, Toolkit::ImageVisual::Property::WRAP_MODE_V}, + {SYNCHRONOUS_LOADING, Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING}, + {IMAGE_ATLASING, Toolkit::ImageVisual::Property::ATLASING}, + {ALPHA_MASK_URL, Toolkit::ImageVisual::Property::ALPHA_MASK_URL}, + {MASK_CONTENT_SCALE_NAME, Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE}, + {CROP_TO_MASK_NAME, Toolkit::ImageVisual::Property::CROP_TO_MASK}, + {MASKING_TYPE_NAME, Toolkit::DevelImageVisual::Property::MASKING_TYPE}, + {ENABLE_BROKEN_IMAGE, Toolkit::DevelImageVisual::Property::ENABLE_BROKEN_IMAGE}, + {LOAD_POLICY_NAME, Toolkit::ImageVisual::Property::LOAD_POLICY}, + {RELEASE_POLICY_NAME, Toolkit::ImageVisual::Property::RELEASE_POLICY}, + {ORIENTATION_CORRECTION_NAME, Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION}, + {FAST_TRACK_UPLOADING_NAME, Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING}, +}; +const int NAME_INDEX_MATCH_TABLE_SIZE = sizeof(NAME_INDEX_MATCH_TABLE) / sizeof(NAME_INDEX_MATCH_TABLE[0]); + Geometry CreateGeometry(VisualFactoryCache& factoryCache, ImageDimensions gridSize) { Geometry geometry; @@ -150,8 +181,9 @@ ImageVisual::ImageVisual(VisualFactoryCache& factoryCache, ImageDimensions size, FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode) -: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::IMAGE), +: Visual::Base(factoryCache, Visual::FittingMode::DONT_CARE, Toolkit::Visual::IMAGE), mPixelArea(FULL_TEXTURE_RECT), + mPixelAreaIndex(Property::INVALID_INDEX), mPlacementActor(), mImageUrl(imageUrl), mMaskingData(), @@ -218,77 +250,13 @@ void ImageVisual::DoSetProperties(const Property::Map& propertyMap) } else { - if(keyValue.first == IMAGE_FITTING_MODE) - { - DoSetProperty(Toolkit::ImageVisual::Property::FITTING_MODE, keyValue.second); - } - else if(keyValue.first == IMAGE_SAMPLING_MODE) - { - DoSetProperty(Toolkit::ImageVisual::Property::SAMPLING_MODE, keyValue.second); - } - else if(keyValue.first == IMAGE_DESIRED_WIDTH) - { - DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_WIDTH, keyValue.second); - } - else if(keyValue.first == IMAGE_DESIRED_HEIGHT) - { - DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, keyValue.second); - } - else if(keyValue.first == PIXEL_AREA_UNIFORM_NAME) - { - DoSetProperty(Toolkit::ImageVisual::Property::PIXEL_AREA, keyValue.second); - } - else if(keyValue.first == IMAGE_WRAP_MODE_U) - { - DoSetProperty(Toolkit::ImageVisual::Property::WRAP_MODE_U, keyValue.second); - } - else if(keyValue.first == IMAGE_WRAP_MODE_V) - { - DoSetProperty(Toolkit::ImageVisual::Property::WRAP_MODE_V, keyValue.second); - } - else if(keyValue.first == SYNCHRONOUS_LOADING) - { - DoSetProperty(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second); - } - else if(keyValue.first == IMAGE_ATLASING) - { - DoSetProperty(Toolkit::ImageVisual::Property::ATLASING, keyValue.second); - } - else if(keyValue.first == ALPHA_MASK_URL) + for(int i = 0; i < NAME_INDEX_MATCH_TABLE_SIZE; ++i) { - DoSetProperty(Toolkit::ImageVisual::Property::ALPHA_MASK_URL, keyValue.second); - } - else if(keyValue.first == MASK_CONTENT_SCALE_NAME) - { - DoSetProperty(Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, keyValue.second); - } - else if(keyValue.first == CROP_TO_MASK_NAME) - { - DoSetProperty(Toolkit::ImageVisual::Property::CROP_TO_MASK, keyValue.second); - } - else if(keyValue.first == MASKING_TYPE_NAME) - { - DoSetProperty(Toolkit::DevelImageVisual::Property::MASKING_TYPE, keyValue.second); - } - else if(keyValue.first == ENABLE_BROKEN_IMAGE) - { - DoSetProperty(Toolkit::DevelImageVisual::Property::ENABLE_BROKEN_IMAGE, keyValue.second); - } - else if(keyValue.first == LOAD_POLICY_NAME) - { - DoSetProperty(Toolkit::ImageVisual::Property::LOAD_POLICY, keyValue.second); - } - else if(keyValue.first == RELEASE_POLICY_NAME) - { - DoSetProperty(Toolkit::ImageVisual::Property::RELEASE_POLICY, keyValue.second); - } - else if(keyValue.first == ORIENTATION_CORRECTION_NAME) - { - DoSetProperty(Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION, keyValue.second); - } - else if(keyValue.first == FAST_TRACK_UPLOADING_NAME) - { - DoSetProperty(Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING, keyValue.second); + if(keyValue.first == NAME_INDEX_MATCH_TABLE[i].name) + { + DoSetProperty(NAME_INDEX_MATCH_TABLE[i].index, keyValue.second); + break; + } } } } @@ -372,6 +340,13 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va case Toolkit::ImageVisual::Property::PIXEL_AREA: { value.Get(mPixelArea); + + if(DALI_UNLIKELY(mImpl->mRenderer)) + { + // Unusual case. SetProperty called after OnInitialize(). + // Assume that DoAction call UPDATE_PROPERTY. + mPixelAreaIndex = mImpl->mRenderer.RegisterProperty(mPixelAreaIndex, PIXEL_AREA_UNIFORM_NAME, mPixelArea); + } break; } @@ -444,7 +419,7 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va } else { - mMaskingData->mPreappliedMasking = Toolkit::DevelImageVisual::MaskingType::Type(maskingType) == Toolkit::DevelImageVisual::MaskingType::MASKING_ON_LOADING ? true : false; + mMaskingData->mPreappliedMasking = (Toolkit::DevelImageVisual::MaskingType::Type(maskingType) == Toolkit::DevelImageVisual::MaskingType::MASKING_ON_LOADING); } } break; @@ -452,11 +427,7 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va case Toolkit::DevelImageVisual::Property::ENABLE_BROKEN_IMAGE: { - bool enableBrokenImage(mEnableBrokenImage); - if(value.Get(enableBrokenImage)) - { - mEnableBrokenImage = enableBrokenImage; - } + value.Get(mEnableBrokenImage); break; } @@ -477,21 +448,13 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va } case Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION: { - bool orientationCorrection(mOrientationCorrection); - if(value.Get(orientationCorrection)) - { - mOrientationCorrection = orientationCorrection; - } + value.Get(mOrientationCorrection); break; } case Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING: { - bool fastTrackUploading = false; - if(value.Get(fastTrackUploading)) - { - mUseFastTrackUploading = fastTrackUploading; - } + value.Get(mUseFastTrackUploading); break; } } @@ -513,6 +476,23 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize) { if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0) { + if(mImpl->mRenderer) + { + auto textureSet = mImpl->mRenderer.GetTextures(); + if(textureSet && textureSet.GetTextureCount()) + { + auto texture = textureSet.GetTexture(0); + if(texture) + { + if(mTextureSize != Vector2::ZERO) + { + naturalSize = mTextureSize; + return; + } + } + } + } + naturalSize.x = mDesiredSize.GetWidth(); naturalSize.y = mDesiredSize.GetHeight(); return; @@ -572,6 +552,7 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize) imageSize = mPlacementActorSize; } + mUseBrokenImageRenderer = true; mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize); Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0); naturalSize.x = brokenImage.GetWidth(); @@ -585,27 +566,6 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize) void ImageVisual::OnInitialize() { - Geometry geometry; - - // 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 firstElementCount{0u}; - uint32_t secondElementCount{0u}; - geometry = textureManager.GetRenderGeometry(mTextureId, firstElementCount, secondElementCount); - - if(!firstElementCount && !secondElementCount) // Otherwise use quad - { - geometry = CreateGeometry(mFactoryCache, ImageDimensions(1, 1)); - } - } - // Increase reference count of External Resources : // EncodedImageBuffer or ExternalTextures. // Reference count will be decreased at destructor of the visual. @@ -615,7 +575,9 @@ void ImageVisual::OnInitialize() textureManager.UseExternalResource(mImageUrl.GetUrl()); } - Shader shader = GenerateShader(); + // Generate geometry and shader. Note that we should check AddOn when generate geometry, due to LoadPolicy::IMMEDIATE case + Geometry geometry = GenerateGeometry(mTextureId, true); + Shader shader = GenerateShader(); // Create the renderer mImpl->mRenderer = DecoratedVisualRenderer::New(geometry, shader); @@ -688,7 +650,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te else if(mUseFastTrackUploading) { DALI_LOG_DEBUG_INFO("FastTrack : Fail to load fast track. mUrl : [%s]%s%s%s%s%s%s%s%s\n", - mImageUrl.GetUrl().c_str(), + mImageUrl.GetEllipsedUrl().c_str(), (mLoadPolicy != Toolkit::ImageVisual::LoadPolicy::ATTACHED) ? "/ mLoadPolicy != ATTACHED" : "", (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::DETACHED) ? "/ mReleasePolicy != DETACHED" : "", (forceReload != TextureManager::ReloadPolicy::CACHED) ? "/ forceReload != CACHED" : "", @@ -707,10 +669,26 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD); // Set new TextureSet with fast track loading task - mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, MakeCallback(this, &ImageVisual::FastLoadComplete)); + mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, mFactoryCache.GetLoadYuvPlanes(), MakeCallback(this, &ImageVisual::FastLoadComplete)); TextureSet textureSet = TextureSet::New(); - textureSet.SetTexture(0u, mFastTrackLoadingTask->mTexture); + if(!mFastTrackLoadingTask->mLoadPlanesAvaliable) + { + DALI_ASSERT_ALWAYS(mFastTrackLoadingTask->mTextures.size() >= 1u); + textureSet.SetTexture(0u, mFastTrackLoadingTask->mTextures[0]); + } + else + { + DALI_ASSERT_ALWAYS(mFastTrackLoadingTask->mTextures.size() >= 3u); + textureSet.SetTexture(2u, mFastTrackLoadingTask->mTextures[2]); + textureSet.SetTexture(1u, mFastTrackLoadingTask->mTextures[1]); + textureSet.SetTexture(0u, mFastTrackLoadingTask->mTextures[0]); + + // We cannot determine what kind of shader will be used. + // Just use unified shader, and then change shader after load completed. + mNeedUnifiedYuvAndRgb = true; + UpdateShader(); + } mImpl->mRenderer.SetTextures(textureSet); Dali::AsyncTaskManager::Get().AddTask(mFastTrackLoadingTask); @@ -734,7 +712,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te } EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD); - if(!atlasing) + if(!atlasing && (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT)) { Sampler sampler = Sampler::New(); sampler.SetWrapMode(mWrapModeU, mWrapModeV); @@ -784,7 +762,9 @@ void ImageVisual::InitializeRenderer() else { mTextures = mFactoryCache.GetTextureManager().GetTextureSet(mTextureId); - if(!(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED) && mTextures) + if(!(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED) && + mTextures && + (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT)) { Sampler sampler = Sampler::New(); sampler.SetWrapMode(mWrapModeU, mWrapModeV); @@ -799,7 +779,7 @@ void ImageVisual::InitializeRenderer() ComputeTextureSize(); CheckMaskTexture(); - bool needToUpdateShader = DevelTexture::IsNative(mTextures.GetTexture(0)); + bool needToUpdateShader = DevelTexture::IsNative(mTextures.GetTexture(0)) || mUseBrokenImageRenderer; if(mTextures.GetTextureCount() == 3) { @@ -815,6 +795,21 @@ void ImageVisual::InitializeRenderer() UpdateShader(); } mTextures.Reset(); // Visual should not keep a handle to the texture after this point. + + if(DALI_UNLIKELY(mUseBrokenImageRenderer)) + { + // We need to re-generate geometry only if it was broken image before, and result changed after Reload. + auto geometry = GenerateGeometry(mTextureId, true); + + // Update geometry only if we need. + if(geometry) + { + mImpl->mRenderer.SetGeometry(geometry); + } + } + + // We don't use broken image anymore. + mUseBrokenImageRenderer = false; } if(attemptAtlasing) // the texture is packed inside atlas @@ -848,7 +843,7 @@ void ImageVisual::DoSetOnScene(Actor& actor) if(mPixelArea != FULL_TEXTURE_RECT) { - mImpl->mRenderer.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, mPixelArea); + mPixelAreaIndex = mImpl->mRenderer.RegisterProperty(mPixelAreaIndex, PIXEL_AREA_UNIFORM_NAME, mPixelArea); } if(mLoadState == TextureManager::LoadState::LOAD_FINISHED) @@ -908,7 +903,17 @@ void ImageVisual::DoCreatePropertyMap(Property::Map& map) const map.Insert(Toolkit::ImageVisual::Property::FITTING_MODE, mFittingMode); map.Insert(Toolkit::ImageVisual::Property::SAMPLING_MODE, mSamplingMode); - map.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, mPixelArea); + if(mImpl->mRenderer && mPixelAreaIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + Vector4 pixelArea = mImpl->mRenderer.GetProperty(mPixelAreaIndex); + map.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, pixelArea); + } + else + { + map.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, mPixelArea); + } + map.Insert(Toolkit::ImageVisual::Property::WRAP_MODE_U, mWrapModeU); map.Insert(Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV); @@ -949,6 +954,11 @@ void ImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::P case DevelImageVisual::Action::RELOAD: { auto attemptAtlasing = AttemptAtlasing(); + + // Reset resource ready status when we call reload. + ResourceReady(Toolkit::Visual::ResourceStatus::PREPARING); + mLoadState = TextureManager::LoadState::NOT_STARTED; + LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::FORCED); break; } @@ -1009,11 +1019,36 @@ void ImageVisual::FastLoadComplete(FastTrackLoadingTaskPtr task) // Change premultiplied alpha flag after change renderer. EnablePreMultipliedAlpha(mFastTrackLoadingTask->mPremultiplied); + + if(mFastTrackLoadingTask->mLoadPlanesAvaliable) + { + if(mFastTrackLoadingTask->mPlanesLoaded) + { + // Let we use regular yuv cases. + mNeedYuvToRgb = true; + } + else + { + // Let we use regular image cases. + mNeedYuvToRgb = false; + + auto textureSet = mImpl->mRenderer.GetTextures(); + DALI_ASSERT_ALWAYS(textureSet && textureSet.GetTextureCount() > 0u && "Previous texture set must exist!"); + + Dali::TextureSet newTextureSet = TextureSet::New(); + newTextureSet.SetTexture(0u, textureSet.GetTexture(0u)); + mImpl->mRenderer.SetTextures(newTextureSet); + } + + // We can specify what kind of shader we need to use now. Update shader. + mNeedUnifiedYuvAndRgb = false; + UpdateShader(); + } } else { - resourceStatus = Toolkit::Visual::ResourceStatus::FAILED; - mLoadState = TextureManager::LoadState::LOAD_FAILED; + resourceStatus = Toolkit::Visual::ResourceStatus::FAILED; + mLoadState = TextureManager::LoadState::LOAD_FAILED; // Change renderer as broken. ShowBrokenImage(); @@ -1029,13 +1064,9 @@ void ImageVisual::FastLoadComplete(FastTrackLoadingTaskPtr task) void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureInformation) { Toolkit::Visual::ResourceStatus resourceStatus; + if(mImpl->mRenderer) { - if(textureInformation.useAtlasing) - { - mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, mAtlasRect); - } - EnablePreMultipliedAlpha(textureInformation.preMultiplied); Actor actor = mPlacementActor.GetHandle(); @@ -1046,7 +1077,7 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn } else { - if(!textureInformation.useAtlasing) + if(mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT) { Sampler sampler = Sampler::New(); sampler.SetWrapMode(mWrapModeU, mWrapModeV); @@ -1057,15 +1088,22 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn ComputeTextureSize(); CheckMaskTexture(); + bool needToUpdateShader = mUseBrokenImageRenderer; + if(textureInformation.textureSet.GetTextureCount() == 3) { if(textureInformation.textureSet.GetTexture(0).GetPixelFormat() == Pixel::L8 && textureInformation.textureSet.GetTexture(1).GetPixelFormat() == Pixel::CHROMINANCE_U && textureInformation.textureSet.GetTexture(2).GetPixelFormat() == Pixel::CHROMINANCE_V) { - mNeedYuvToRgb = true; - UpdateShader(); + mNeedYuvToRgb = true; + needToUpdateShader = true; } } + if(needToUpdateShader) + { + UpdateShader(); + } + if(actor) { actor.AddRenderer(mImpl->mRenderer); @@ -1073,6 +1111,19 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn // reset the weak handle so that the renderer only get added to actor once mPlacementActor.Reset(); } + + auto geometry = GenerateGeometry(textureInformation.textureId, mUseBrokenImageRenderer); + + if(DALI_UNLIKELY(geometry)) + { + // Rare cases. If load successed image don't use quad geometry (i.e. Show some n-patch broken image, and call Reload(), and success) + // or If given texture use AddOn, + // then we need to make to use quad geometry and update shader agian. + mImpl->mRenderer.SetGeometry(geometry); + } + + // We don't use broken image anymore. + mUseBrokenImageRenderer = false; } } @@ -1094,36 +1145,6 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn mLoadState = TextureManager::LoadState::LOAD_FAILED; } - // use geometry if needed - if(loadingSuccess) - { - 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(firstElementCount) - { - drawCommand.firstIndex = 0; - drawCommand.elementCount = firstElementCount; - drawCommand.queue = DevelRenderer::RENDER_QUEUE_OPAQUE; - DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand); - } - - if(secondElementCount) - { - drawCommand.firstIndex = firstElementCount; - drawCommand.elementCount = secondElementCount; - drawCommand.queue = DevelRenderer::RENDER_QUEUE_TRANSPARENT; - DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand); - } - } - } - // Signal to observers ( control ) that resources are ready. Must be all resources. ResourceReady(resourceStatus); } @@ -1214,7 +1235,6 @@ Shader ImageVisual::GenerateShader() const { Shader shader; - bool usesWholeTexture = true; const bool useStandardShader = !mImpl->mCustomShader; const bool useNativeImage = (mTextures && DevelTexture::IsNative(mTextures.GetTexture(0))); @@ -1224,17 +1244,18 @@ Shader ImageVisual::GenerateShader() const // Create and cache the standard shader shader = mImageVisualShaderFactory.GetShader( mFactoryCache, - ImageVisualShaderFeature::FeatureBuilder() + ImageVisualShaderFeatureBuilder() .EnableTextureAtlas(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED && !useNativeImage) .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE) .EnableRoundedCorner(IsRoundedCornerRequired()) .EnableBorderline(IsBorderlineRequired()) .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture()) .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering) - .EnableYuvToRgb(mNeedYuvToRgb)); + .EnableYuvToRgb(mNeedYuvToRgb, mNeedUnifiedYuvAndRgb)); } else { + bool usesWholeTexture = true; std::string_view vertexShaderView; std::string_view fragmentShaderView; @@ -1278,14 +1299,32 @@ Shader ImageVisual::GenerateShader() const { shader = Shader::New(vertexShaderView, fragmentShaderView, mImpl->mCustomShader->mHints); } + + if(usesWholeTexture) + { + shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); + } } - if(usesWholeTexture) + return shader; +} + +Dali::Property ImageVisual::OnGetPropertyObject(Dali::Property::Key key) +{ + if((key.type == Property::Key::INDEX && key.indexKey == Toolkit::ImageVisual::Property::PIXEL_AREA) || (key.type == Property::Key::STRING && key.stringKey == PIXEL_AREA_UNIFORM_NAME)) { - shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); + if(DALI_LIKELY(mImpl->mRenderer)) + { + if(mPixelAreaIndex == Property::INVALID_INDEX) + { + mPixelAreaIndex = mImpl->mRenderer.RegisterProperty(mPixelAreaIndex, PIXEL_AREA_UNIFORM_NAME, mPixelArea); + } + return Dali::Property(mImpl->mRenderer, mPixelAreaIndex); + } } - return shader; + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); } void ImageVisual::CheckMaskTexture() @@ -1300,6 +1339,10 @@ void ImageVisual::CheckMaskTexture() { mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, ComputeMaskTextureRatio()); } + else + { + mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, Vector2::ONE); + } maskLoadFailed = false; } @@ -1342,6 +1385,7 @@ void ImageVisual::ShowBrokenImage() } } + mUseBrokenImageRenderer = true; mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize); if(actor) { @@ -1374,6 +1418,59 @@ void ImageVisual::ResetFastTrackLoadingTask() } } +Geometry ImageVisual::GenerateGeometry(TextureManager::TextureId textureId, bool createForce) +{ + Geometry geometry; + if(Stage::IsInstalled()) + { + if(mImpl->mCustomShader) + { + if(createForce) + { + geometry = CreateGeometry(mFactoryCache, mImpl->mCustomShader->mGridSize); + } + } + else + { + uint32_t firstElementCount{0u}; + uint32_t secondElementCount{0u}; + + geometry = mFactoryCache.GetTextureManager().GetRenderGeometry(textureId, firstElementCount, secondElementCount); + if(geometry) + { + if(mImpl->mRenderer) + { + Dali::DevelRenderer::DrawCommand drawCommand{}; + drawCommand.drawType = DevelRenderer::DrawType::INDEXED; + + if(firstElementCount) + { + drawCommand.firstIndex = 0; + drawCommand.elementCount = firstElementCount; + drawCommand.queue = DevelRenderer::RENDER_QUEUE_OPAQUE; + DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand); + } + + if(secondElementCount) + { + drawCommand.firstIndex = firstElementCount; + drawCommand.elementCount = secondElementCount; + drawCommand.queue = DevelRenderer::RENDER_QUEUE_TRANSPARENT; + DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand); + } + } + } + else if(createForce) + { + // Create default quad geometry now + geometry = CreateGeometry(mFactoryCache, ImageDimensions(1, 1)); + } + } + } + + return geometry; +} + } // namespace Internal } // namespace Toolkit