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=0669ed53e4813e8d2c3f1dca807b83a713150530;hpb=0db00ea132d7106f5adaaf1105bec2f581a2aad2;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 0669ed5..f299975 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) 2022 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. @@ -25,16 +25,19 @@ #include #include #include +#include #include #include +#include #include #include // for strlen() // INTERNAL HEADERS #include #include -#include -#include +#include +#include +#include #include #include #include @@ -52,7 +55,7 @@ namespace Internal { namespace { -const int CUSTOM_PROPERTY_COUNT(7); // ltr, wrap, pixel area, atlas, pixalign, crop to mask, mask texture ratio +const int CUSTOM_PROPERTY_COUNT(8); // ltr, wrap, pixel area, atlas, pixalign, crop to mask, mask texture ratio, pre-multiplied alpha // fitting modes DALI_ENUM_TO_STRING_TABLE_BEGIN(FITTING_MODE) @@ -60,6 +63,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) @@ -97,11 +101,38 @@ DALI_ENUM_TO_STRING_TABLE_END(RELEASE_POLICY) const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); -const float PIXEL_ALIGN_ON = 1.0f; -const float PIXEL_ALIGN_OFF = 0.0f; - 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}, + {SYNCHRONOUS_SIZING, Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING}, +}; +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; @@ -152,12 +183,15 @@ 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), + mPreMultipliedAlphaIndex(Property::INVALID_INDEX), mPlacementActor(), mImageUrl(imageUrl), mMaskingData(), mDesiredSize(size), + mLastRequiredSize(size), mTextureId(TextureManager::INVALID_TEXTURE_ID), mTextures(), mImageVisualShaderFactory(shaderFactory), @@ -171,14 +205,15 @@ ImageVisual::ImageVisual(VisualFactoryCache& factoryCache, mAtlasRectSize(0, 0), mLoadState(TextureManager::LoadState::NOT_STARTED), mAttemptAtlasing(false), - mOrientationCorrection(true) + mOrientationCorrection(true), + mEnableBrokenImage(true) { EnablePreMultipliedAlpha(mFactoryCache.GetPreMultiplyOnLoad()); } ImageVisual::~ImageVisual() { - if(Stage::IsInstalled()) + if(DALI_LIKELY(Dali::Adaptor::IsAvailable())) { if(mImageUrl.IsValid()) { @@ -188,12 +223,12 @@ ImageVisual::~ImageVisual() if(mImageUrl.GetProtocolType() == VisualUrl::TEXTURE) { TextureManager& textureManager = mFactoryCache.GetTextureManager(); - textureManager.RemoveExternalTexture(mImageUrl.GetUrl()); + textureManager.RemoveExternalTexture(mImageUrl); } else if(mImageUrl.IsBufferResource()) { TextureManager& textureManager = mFactoryCache.GetTextureManager(); - textureManager.RemoveEncodedImageBuffer(mImageUrl.GetUrl()); + textureManager.RemoveEncodedImageBuffer(mImageUrl); } } @@ -202,6 +237,8 @@ ImageVisual::~ImageVisual() { RemoveTexture(); } + + ResetFastTrackLoadingTask(); } } @@ -217,69 +254,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) + for(int i = 0; i < NAME_INDEX_MATCH_TABLE_SIZE; ++i) { - DoSetProperty(Toolkit::ImageVisual::Property::ATLASING, keyValue.second); - } - else if(keyValue.first == ALPHA_MASK_URL) - { - 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 == 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); + if(keyValue.first == NAME_INDEX_MATCH_TABLE[i].name) + { + DoSetProperty(NAME_INDEX_MATCH_TABLE[i].index, keyValue.second); + break; + } } } } @@ -287,7 +268,7 @@ void ImageVisual::DoSetProperties(const Property::Map& propertyMap) if(mLoadPolicy == Toolkit::ImageVisual::LoadPolicy::IMMEDIATE) { auto attemptAtlasing = AttemptAtlasing(); - LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::CACHED); + LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mDesiredSize, TextureManager::ReloadPolicy::CACHED); } } @@ -363,6 +344,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; } @@ -427,11 +415,26 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va if(value.Get(maskingType)) { AllocateMaskData(); - mMaskingData->mPreappliedMasking = Toolkit::DevelImageVisual::MaskingType::Type(maskingType) == Toolkit::DevelImageVisual::MaskingType::MASKING_ON_LOADING ? true : false; + if(mImageUrl.IsValid() && mImageUrl.GetProtocolType() == VisualUrl::TEXTURE) + { + // For external textures, only gpu masking is available. + // Therefore, MASKING_TYPE is set to MASKING_ON_RENDERING forcelly. + mMaskingData->mPreappliedMasking = false; + } + else + { + mMaskingData->mPreappliedMasking = (Toolkit::DevelImageVisual::MaskingType::Type(maskingType) == Toolkit::DevelImageVisual::MaskingType::MASKING_ON_LOADING); + } } break; } + case Toolkit::DevelImageVisual::Property::ENABLE_BROKEN_IMAGE: + { + value.Get(mEnableBrokenImage); + break; + } + case Toolkit::ImageVisual::Property::RELEASE_POLICY: { int releasePolicy = 0; @@ -449,11 +452,19 @@ 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: + { + value.Get(mUseFastTrackUploading); + break; + } + + case Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING: + { + value.Get(mUseSynchronousSizing); break; } } @@ -464,13 +475,57 @@ void ImageVisual::AllocateMaskData() if(!mMaskingData) { mMaskingData.reset(new TextureManager::MaskingData()); + if(mImageUrl.IsValid() && mImageUrl.GetProtocolType() == VisualUrl::TEXTURE) + { + mMaskingData->mPreappliedMasking = false; + } } } void ImageVisual::GetNaturalSize(Vector2& naturalSize) { - if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0) + if(mUseSynchronousSizing && (mLastRequiredSize.GetWidth() > 0 && mLastRequiredSize.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 = mLastRequiredSize.GetWidth(); + naturalSize.y = mLastRequiredSize.GetHeight(); + return; + } + else 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; @@ -510,7 +565,9 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize) { if(mImageUrl.GetProtocolType() == VisualUrl::LOCAL) { - ImageDimensions dimensions = Dali::GetClosestImageSize(mImageUrl.GetUrl()); + // Note that We don't consider desired image size for this case. + // Just use (0, 0) value for desired size of image. + ImageDimensions dimensions = Dali::GetClosestImageSize(mImageUrl.GetUrl(), ImageDimensions(0, 0), mFittingMode, mSamplingMode, mOrientationCorrection); if(dimensions != ImageDimensions(0, 0)) { @@ -530,6 +587,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(); @@ -543,37 +601,18 @@ 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. if(mImageUrl.IsValid() && (mImageUrl.IsBufferResource() || mImageUrl.GetProtocolType() == VisualUrl::TEXTURE)) { TextureManager& textureManager = mFactoryCache.GetTextureManager(); - textureManager.UseExternalResource(mImageUrl.GetUrl()); + textureManager.UseExternalResource(mImageUrl); } - 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); @@ -590,10 +629,12 @@ void ImageVisual::OnInitialize() } } -void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection, TextureManager::ReloadPolicy forceReload) +void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, const Dali::ImageDimensions& size, TextureManager::ReloadPolicy forceReload) { TextureManager& textureManager = mFactoryCache.GetTextureManager(); + mLastRequiredSize = size; + ImageAtlasManagerPtr atlasManager = nullptr; AtlasUploadObserver* atlasUploadObserver = nullptr; auto textureObserver = this; @@ -609,9 +650,94 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; bool synchronousLoading = IsSynchronousLoadingRequired(); - bool loadingStatus; + bool loadingStatus = false; + + // Remove previous loading task. + ResetFastTrackLoadingTask(); - textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad); + // Rare case. If someone call LoadTexture during fast track loading task running, (Ex : Action::RELOAD) + // we should remove previously added renderer now. + if(mRendererAdded) + { + Actor actor = mPlacementActor.GetHandle(); + if(actor) + { + actor.RemoveRenderer(mImpl->mRenderer); + mRendererAdded = false; + } + } + + /** + * @brief Check whether FastTrackUploading is avaliable or not. + * @return True if we can use fast track uploading feature. False otherwise. + */ + auto IsFastTrackUploadingAvailable = [&]() { + if(mUseFastTrackUploading && + mLoadPolicy == Toolkit::ImageVisual::LoadPolicy::ATTACHED && + mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED && + forceReload == TextureManager::ReloadPolicy::CACHED && + (mImageUrl.GetProtocolType() == VisualUrl::LOCAL || mImageUrl.GetProtocolType() == VisualUrl::REMOTE) && + !synchronousLoading && + !mUseSynchronousSizing && + !atlasing && + !mImpl->mCustomShader && + !(mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid())) + { + return true; + } + else if(mUseFastTrackUploading) + { + DALI_LOG_DEBUG_INFO("FastTrack : Fail to load fast track. mUrl : [%s]%s%s%s%s%s%s%s%s%s\n", + mImageUrl.GetEllipsedUrl().c_str(), + (mLoadPolicy != Toolkit::ImageVisual::LoadPolicy::ATTACHED) ? "/ mLoadPolicy != ATTACHED" : "", + (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::DETACHED) ? "/ mReleasePolicy != DETACHED" : "", + (forceReload != TextureManager::ReloadPolicy::CACHED) ? "/ forceReload != CACHED" : "", + (!(mImageUrl.GetProtocolType() == VisualUrl::LOCAL || mImageUrl.GetProtocolType() == VisualUrl::REMOTE)) ? "/ url is not image" : "", + (synchronousLoading) ? "/ synchronousLoading" : "", + (mUseSynchronousSizing) ? "/ useSynchronousSizing " : "", + (atlasing) ? "/ atlasing" : "", + (mImpl->mCustomShader) ? "/ use customs shader" : "", + (mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid()) ? "/ use masking url" : ""); + } + return false; + }; + + if(IsFastTrackUploadingAvailable()) + { + // Enable PremultipliedAlpha first. + EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD); + + // Set new TextureSet with fast track loading task + mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, size, 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(); + 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); + + mLoadState = TextureManager::LoadState::LOADING; + } + else + { + textures = textureManager.LoadTexture(mImageUrl, size, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad); + } if(textures) { @@ -625,7 +751,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); @@ -648,7 +774,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te } } -bool ImageVisual::AttemptAtlasing() +bool ImageVisual::AttemptAtlasing() const { return (!mImpl->mCustomShader && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()) && mAttemptAtlasing); } @@ -670,12 +796,14 @@ void ImageVisual::InitializeRenderer() { if(mTextureId == TextureManager::INVALID_TEXTURE_ID) { - LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::CACHED); + LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize, TextureManager::ReloadPolicy::CACHED); } 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); @@ -690,7 +818,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) { @@ -706,6 +834,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 @@ -736,22 +879,16 @@ void ImageVisual::DoSetOnScene(Actor& actor) } mPlacementActor = actor; - // Search the Actor tree to find if Layer UI behaviour set. - Layer layer = actor.GetLayer(); - if(layer && layer.GetProperty(Layer::Property::BEHAVIOR) == Layer::LAYER_3D) - { - // Layer 3D set, do not align pixels - mImpl->mRenderer.RegisterProperty(PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF); - } 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) { actor.AddRenderer(mImpl->mRenderer); + mRendererAdded = true; mPlacementActor.Reset(); // Image loaded and ready to display @@ -759,18 +896,16 @@ void ImageVisual::DoSetOnScene(Actor& actor) } else if(mLoadState == TextureManager::LoadState::LOAD_FAILED) { - Vector2 imageSize = Vector2::ZERO; - if(actor) + ShowBrokenImage(); + ResourceReady(Toolkit::Visual::ResourceStatus::FAILED); + } + else + { + if(mFastTrackLoadingTask) { - imageSize = actor.GetProperty(Actor::Property::SIZE).Get(); - mPlacementActorSize = imageSize; + actor.AddRenderer(mImpl->mRenderer); + mRendererAdded = true; } - - mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize); - actor.AddRenderer(mImpl->mRenderer); - mPlacementActor.Reset(); - - ResourceReady(Toolkit::Visual::ResourceStatus::FAILED); } } @@ -780,16 +915,11 @@ void ImageVisual::DoSetOffScene(Actor& actor) // Image release is dependent on the ReleasePolicy, renderer is removed. actor.RemoveRenderer(mImpl->mRenderer); + mRendererAdded = false; + 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); - ComputeTextureSize(); - - mLoadState = TextureManager::LoadState::NOT_STARTED; + ResetRenderer(); } mPlacementActor.Reset(); @@ -804,15 +934,27 @@ void ImageVisual::DoCreatePropertyMap(Property::Map& map) const map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, sync); if(mImageUrl.IsValid()) { + Dali::ImageDimensions size = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize; + map.Insert(Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl()); - map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth()); - map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight()); + map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, size.GetWidth()); + map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, size.GetHeight()); } 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); @@ -829,6 +971,9 @@ void ImageVisual::DoCreatePropertyMap(Property::Map& map) const map.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, mLoadPolicy); map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy); map.Insert(Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION, mOrientationCorrection); + + map.Insert(Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING, mUseFastTrackUploading); + map.Insert(Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING, mUseSynchronousSizing); } void ImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const @@ -837,11 +982,28 @@ void ImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE); if(mImageUrl.IsValid()) { - map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth()); - map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight()); + Dali::ImageDimensions size = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize; + map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, size.GetWidth()); + map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, size.GetHeight()); } } +void ImageVisual::EnablePreMultipliedAlpha(bool preMultiplied) +{ + if(mImpl->mRenderer) + { + if(mPreMultipliedAlphaIndex != Property::INVALID_INDEX || !preMultiplied) + { + // RegisterUniqueProperty call SetProperty internally. + // Register PREMULTIPLIED_ALPHA only if it become false. + // Default PREMULTIPLIED_ALPHA value is 1.0f, at image-visual-shader-factory.cpp + mPreMultipliedAlphaIndex = mImpl->mRenderer.RegisterUniqueProperty(mPreMultipliedAlphaIndex, PREMULTIPLIED_ALPHA, preMultiplied ? 1.0f : 0.0f); + } + } + + Visual::Base::EnablePreMultipliedAlpha(preMultiplied); +} + void ImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes) { // Check if action is valid for this visual type and perform action if possible @@ -851,7 +1013,16 @@ void ImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::P case DevelImageVisual::Action::RELOAD: { auto attemptAtlasing = AttemptAtlasing(); - LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::FORCED); + + // Reset resource ready status when we call reload. + ResourceReady(Toolkit::Visual::ResourceStatus::PREPARING); + mLoadState = TextureManager::LoadState::NOT_STARTED; + + // Need to reset textureset after change load state. + mTextures.Reset(); + + Dali::ImageDimensions size = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize; + LoadTexture(attemptAtlasing, mAtlasRect, mTextures, size, TextureManager::ReloadPolicy::FORCED); break; } } @@ -863,6 +1034,31 @@ void ImageVisual::OnSetTransform() { mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); } + + if(mUseSynchronousSizing) + { + // Get current visual size + Vector2 size = mImpl->mTransform.GetVisualSize(mImpl->mControlSize); + uint32_t maximumNumber = std::numeric_limits::max(); + uint32_t sizeWidth = static_cast(roundf(size.width)); + sizeWidth = std::min(sizeWidth, maximumNumber); + uint32_t sizeHeight = static_cast(roundf(size.height)); + sizeHeight = std::min(sizeHeight, maximumNumber); + Dali::ImageDimensions visualSize = Dali::ImageDimensions(sizeWidth, sizeHeight); + + // Reload if visual size is updated + if(mLastRequiredSize != visualSize) + { + RemoveTexture(); + mLoadState = TextureManager::LoadState::NOT_STARTED; + + // Need to reset textureset after change load state. + mTextures.Reset(); + + bool attemptAtlasing = AttemptAtlasing(); + LoadTexture(attemptAtlasing, mAtlasRect, mTextures, visualSize, TextureManager::ReloadPolicy::CACHED); + } + } } void ImageVisual::UpdateShader() @@ -884,6 +1080,7 @@ void ImageVisual::UploadCompleted() { mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, mAtlasRect); actor.AddRenderer(mImpl->mRenderer); + mRendererAdded = true; // reset the weak handle so that the renderer only get added to actor once mPlacementActor.Reset(); } @@ -893,39 +1090,82 @@ void ImageVisual::UploadCompleted() mLoadState = TextureManager::LoadState::LOAD_FINISHED; } -// From Texture Manager -void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureInformation) +// From FastTrackLoadingTask +void ImageVisual::FastLoadComplete(FastTrackLoadingTaskPtr task) { Toolkit::Visual::ResourceStatus resourceStatus; - if(mImpl->mRenderer) + + DALI_ASSERT_ALWAYS(mFastTrackLoadingTask == task && "Task was not canceled successfully!"); + DALI_ASSERT_ALWAYS(mRendererAdded && "Some FastTrack logic missed!"); + + Actor actor = mPlacementActor.GetHandle(); + + if(mFastTrackLoadingTask && mFastTrackLoadingTask->mLoadSuccess) { - if(textureInformation.useAtlasing) - { - mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, mAtlasRect); - } + resourceStatus = Toolkit::Visual::ResourceStatus::READY; + mLoadState = TextureManager::LoadState::LOAD_FINISHED; - EnablePreMultipliedAlpha(textureInformation.preMultiplied); + // Change premultiplied alpha flag after change renderer. + EnablePreMultipliedAlpha(mFastTrackLoadingTask->mPremultiplied); - Actor actor = mPlacementActor.GetHandle(); - if(!loadingSuccess) + if(mFastTrackLoadingTask->mLoadPlanesAvaliable) { - Vector2 imageSize = Vector2::ZERO; - if(actor) + if(mFastTrackLoadingTask->mPlanesLoaded) { - imageSize = actor.GetProperty(Actor::Property::SIZE).Get(); - mPlacementActorSize = imageSize; + // Let we use regular yuv cases. + mNeedYuvToRgb = true; } else { - imageSize = mPlacementActorSize; + // 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); } - mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize); + // 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; + + // Change renderer as broken. + ShowBrokenImage(); + } + + mFastTrackLoadingTask.Reset(); + + // Signal to observers ( control ) that resources are ready. Must be all resources. + ResourceReady(resourceStatus); +} + +// From Texture Manager +void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureInformation) +{ + Toolkit::Visual::ResourceStatus resourceStatus; + + if(mImpl->mRenderer) + { + EnablePreMultipliedAlpha(textureInformation.preMultiplied); + + Actor actor = mPlacementActor.GetHandle(); + if(!loadingSuccess) + { + ShowBrokenImage(); textureInformation.textureSet = mImpl->mRenderer.GetTextures(); } else { - if(!textureInformation.useAtlasing) + if(mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT) { Sampler sampler = Sampler::New(); sampler.SetWrapMode(mWrapModeU, mWrapModeV); @@ -936,21 +1176,42 @@ 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(actor) - { - actor.AddRenderer(mImpl->mRenderer); - // reset the weak handle so that the renderer only get added to actor once - mPlacementActor.Reset(); + if(needToUpdateShader) + { + UpdateShader(); + } + + if(actor) + { + actor.AddRenderer(mImpl->mRenderer); + mRendererAdded = true; + // 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; } } @@ -972,36 +1233,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); } @@ -1010,11 +1241,13 @@ void ImageVisual::RemoveTexture() { if(mTextureId != TextureManager::INVALID_TEXTURE_ID) { - mFactoryCache.GetTextureManager().Remove(mTextureId, this); + mFactoryCache.GetTextureManager().RequestRemove(mTextureId, this); mTextureId = TextureManager::INVALID_TEXTURE_ID; } else { + ResetFastTrackLoadingTask(); + Vector4 atlasRect(0.f, 0.f, 1.f, 1.f); Property::Index index = mImpl->mRenderer.GetPropertyIndex(ATLAS_RECT_UNIFORM_NAME); if(index != Property::INVALID_INDEX) @@ -1090,7 +1323,6 @@ Shader ImageVisual::GenerateShader() const { Shader shader; - bool usesWholeTexture = true; const bool useStandardShader = !mImpl->mCustomShader; const bool useNativeImage = (mTextures && DevelTexture::IsNative(mTextures.GetTexture(0))); @@ -1107,10 +1339,11 @@ Shader ImageVisual::GenerateShader() const .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; @@ -1154,19 +1387,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); + } } - // 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; + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); } void ImageVisual::CheckMaskTexture() @@ -1181,6 +1427,10 @@ void ImageVisual::CheckMaskTexture() { mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, ComputeMaskTextureRatio()); } + else + { + mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, Vector2::ONE); + } maskLoadFailed = false; } @@ -1192,6 +1442,126 @@ void ImageVisual::CheckMaskTexture() } } +void ImageVisual::ResetRenderer() +{ + 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); + ComputeTextureSize(); + + mLoadState = TextureManager::LoadState::NOT_STARTED; + + // Need to reset textureset after change load state. + mTextures.Reset(); +} + +void ImageVisual::ShowBrokenImage() +{ + if(mEnableBrokenImage) + { + Actor actor = mPlacementActor.GetHandle(); + + Vector2 imageSize = Vector2::ZERO; + if(actor) + { + imageSize = actor.GetProperty(Actor::Property::SIZE).Get(); + mPlacementActorSize = imageSize; + + if(mRendererAdded) + { + actor.RemoveRenderer(mImpl->mRenderer); + mRendererAdded = false; + } + } + + mUseBrokenImageRenderer = true; + mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize); + if(actor) + { + actor.AddRenderer(mImpl->mRenderer); + mRendererAdded = true; + mPlacementActor.Reset(); + } + } + else + { + if(mRendererAdded) + { + Actor actor = mPlacementActor.GetHandle(); + if(actor) + { + actor.RemoveRenderer(mImpl->mRenderer); + mRendererAdded = false; + } + } + ResetRenderer(); + } +} + +void ImageVisual::ResetFastTrackLoadingTask() +{ + if(mFastTrackLoadingTask) + { + Dali::AsyncTaskManager::Get().RemoveTask(mFastTrackLoadingTask); + mFastTrackLoadingTask.Reset(); + } +} + +Geometry ImageVisual::GenerateGeometry(TextureManager::TextureId textureId, bool createForce) +{ + Geometry geometry; + if(DALI_LIKELY(Dali::Adaptor::IsAvailable())) + { + 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