2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali-test-suite-utils.h>
19 #include <mesh-builder.h>
22 // access private members
23 #define private public
24 #include <dali/internal/render/renderers/pipeline-cache.h>
30 template<class Object, class... Args>
31 void InvokeNext(Object* obj, Args... args)
33 auto addr = __builtin_return_address(0);
36 auto func = dlsym(RTLD_NEXT, info.dli_sname);
37 typedef void (*FuncPtr)(void*, Args...);
38 auto memb = FuncPtr(func);
42 template<class Ret, class Object, class... Args>
43 Ret InvokeReturnNext(Object* obj, Args... args)
45 auto addr = __builtin_return_address(0);
48 auto func = dlsym(RTLD_NEXT, info.dli_sname);
49 typedef Ret (*FuncPtr)(void*, Args...);
50 auto memb = FuncPtr(func);
51 return memb(obj, args...);
54 static Dali::Internal::Render::PipelineCache* gPipelineCache{nullptr};
61 // Store internal PipelineCache as singleton
63 PipelineCache::PipelineCache(Dali::Graphics::Controller& controller)
65 gPipelineCache = this;
66 InvokeNext(this, &controller);
70 } // namespace Internal
73 int UtcDaliCorePipelineCacheTest(void)
75 TestApplication application;
76 tet_infoline("Testing Dali::Internal::Render::Pipeline");
78 using Dali::Internal::Render::PipelineCache;
80 // PipelineCache* cache = PipelineCache::GetPipelineCacheWithController( &application.GetGraphicsController() );
81 // Pipeline cache must be initialized
82 DALI_TEST_EQUALS(gPipelineCache != 0, true, TEST_LOCATION);
84 // Test size of level0 nodes (should be 0, nothing added yet)
85 DALI_TEST_EQUALS((gPipelineCache->level0nodes.size() == 0), true, TEST_LOCATION);
87 // Create something to render
88 Geometry geometry = CreateQuadGeometry();
89 Shader shader = Shader::New("vertexSrc", "fragmentSrc");
90 TextureSet textureSet = TextureSet::New();
91 Texture image = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 50, 50);
93 textureSet.SetTexture(0u, image);
94 Renderer renderer = Renderer::New(geometry, shader);
95 renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, Dali::BlendMode::ON);
96 renderer.SetTextures(textureSet);
98 Actor actor = Actor::New();
99 actor.AddRenderer(renderer);
100 actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
101 application.GetScene().Add(actor);
103 application.SendNotification();
104 application.Render();
106 // 1 pipeline should be added
107 DALI_TEST_EQUALS((gPipelineCache->level0nodes.size() == 1), true, TEST_LOCATION);
109 // Add another actor, new pipeline will be created
110 Shader shader1 = Shader::New("newVertexSrc", "newFragmentSrc");
111 Actor actor1 = Actor::New();
112 Renderer renderer1 = Renderer::New(geometry, shader1);
113 renderer1.SetProperty(Dali::Renderer::Property::BLEND_MODE, Dali::BlendMode::ON);
114 actor1.AddRenderer(renderer1);
115 actor1.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
116 application.GetScene().Add(actor1);
118 application.SendNotification();
119 application.Render();
121 DALI_TEST_EQUALS((gPipelineCache->level0nodes.size() == 2), true, TEST_LOCATION);
123 // Now add 3rd actor reusing first pipeline
125 Actor actor2 = Actor::New();
126 Renderer renderer2 = Renderer::New(geometry, shader);
127 renderer2.SetProperty(Dali::Renderer::Property::BLEND_MODE, Dali::BlendMode::ON);
128 actor2.AddRenderer(renderer);
129 actor2.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
130 application.GetScene().Add(actor2);
132 application.SendNotification();
133 application.Render();
135 // Number of pipelines shouldn't change
136 DALI_TEST_EQUALS((gPipelineCache->level0nodes.size() == 2), true, TEST_LOCATION);
138 // Test final 'noBlend' path on first pipeline
140 Actor actor3 = Actor::New();
141 Renderer renderer3 = Renderer::New(geometry, shader);
142 renderer3.SetProperty(Dali::Renderer::Property::BLEND_MODE, Dali::BlendMode::OFF);
143 actor3.AddRenderer(renderer3);
144 actor3.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
145 application.GetScene().Add(actor3);
147 application.SendNotification();
148 application.Render();
150 // Test whether noBlend pipeline is set in cache
151 DALI_TEST_EQUALS((gPipelineCache->level0nodes.size() == 2), true, TEST_LOCATION);
152 DALI_TEST_CHECK(!gPipelineCache->level0nodes.front().level1nodes.front().noBlends.empty());
153 DALI_TEST_EQUALS(gPipelineCache->level0nodes.front().level1nodes.front().noBlends.front().pipeline != nullptr, true, TEST_LOCATION);
155 // Remove renderer to test whether old pipeline is removed
156 application.GetScene().Remove(actor1);
157 actor1.RemoveRenderer(renderer1);
160 // Make the frame count of the pipeline cache large to clean cache
161 gPipelineCache->mFrameCount = 1000;
163 application.SendNotification();
164 application.Render();
166 DALI_TEST_EQUALS(gPipelineCache->level0nodes.size(), 1, TEST_LOCATION);