../dali-adaptor/dali-test-suite-utils/test-harness.cpp
../dali-adaptor/dali-test-suite-utils/test-application.cpp
../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
- ../dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
#include <dali-test-suite-utils.h>
#include <dali/dali.h>
-#include <dali/internal/text/text-abstraction/font-client-helper.h>
#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/internal/text/text-abstraction/font-client-helper.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
int UtcDaliFontClientAtlasLimitation(void)
{
- TestApplication application;
- bool result = 0;
+ TestApplication application;
+ bool result = 0;
TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
tet_infoline("UtcDaliFontClientAtlasLimitation Default");
fontClient.EnableAtlasLimitation(false);
result = fontClient.IsAtlasLimitationEnabled();
DALI_TEST_EQUALS(false, result, TEST_LOCATION);
- END_TEST;
- }
+ END_TEST;
+}
-const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
-const uint32_t MAX_WIDTH_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
+const std::string DEFAULT_FONT_DIR("/resources/fonts");
+const uint32_t MAX_WIDTH_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
const uint32_t MAX_HEIGHT_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
int UtcDaliFontClientAtlasLimitationEnabled(void)
{
-
TestApplication application;
- char* pathNamePtr = get_current_dir_name();
- const std::string pathName( pathNamePtr );
- free( pathNamePtr );
+ char* pathNamePtr = get_current_dir_name();
+ const std::string pathName(pathNamePtr);
+ free(pathNamePtr);
TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
fontClient.EnableAtlasLimitation(true);
// Note the block size depends on font-family.
// This is to create FontDescription and pass it to GetFontId with point-size (various cases).
TextAbstraction::FontDescription fontDescription;
- fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
+ fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
fontDescription.family = "DejaVuSans";
- fontDescription.width = TextAbstraction::FontWidth::NONE;
+ fontDescription.width = TextAbstraction::FontWidth::NONE;
fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
- fontDescription.slant = TextAbstraction::FontSlant::NONE;
-
+ fontDescription.slant = TextAbstraction::FontSlant::NONE;
// Block's width or height are less than 512
tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=200");
- uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
- TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
+ uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+ TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
glyphBufferData200.width = 0;
glyphBufferData200.height = 0;
fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
- DALI_TEST_GREATER( MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData200.width, TEST_LOCATION );
- DALI_TEST_GREATER( MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData200.height, TEST_LOCATION );
+ DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData200.width, TEST_LOCATION);
+ DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData200.height, TEST_LOCATION);
// Block's width or height are greater than 512 and less than 1024
uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=1000");
- TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+ TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
glyphBufferData1000.width = 0;
glyphBufferData1000.height = 0;
fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
- DALI_TEST_GREATER( MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData1000.width, TEST_LOCATION );
- DALI_TEST_GREATER( MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData1000.height, TEST_LOCATION );
+ DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData1000.width, TEST_LOCATION);
+ DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData1000.height, TEST_LOCATION);
// Block's width or height are greater than 1024 and less than 2048
uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=2000");
- TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+ TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
glyphBufferData2000.width = 0;
glyphBufferData2000.height = 0;
fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
- DALI_TEST_GREATER( MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData2000.width, TEST_LOCATION );
- DALI_TEST_GREATER( MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData2000.height, TEST_LOCATION );
+ DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData2000.width, TEST_LOCATION);
+ DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData2000.height, TEST_LOCATION);
- END_TEST;
+ END_TEST;
}
-
int UtcDaliFontClientAtlasLimitationDisabled(void)
{
-
TestApplication application;
- char* pathNamePtr = get_current_dir_name();
- const std::string pathName( pathNamePtr );
- free( pathNamePtr );
+ char* pathNamePtr = get_current_dir_name();
+ const std::string pathName(pathNamePtr);
+ free(pathNamePtr);
TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
fontClient.EnableAtlasLimitation(false);
TextAbstraction::FontDescription fontDescription;
- fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
+ fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
fontDescription.family = "DejaVuSans";
- fontDescription.width = TextAbstraction::FontWidth::NONE;
+ fontDescription.width = TextAbstraction::FontWidth::NONE;
fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
- fontDescription.slant = TextAbstraction::FontSlant::NONE;
+ fontDescription.slant = TextAbstraction::FontSlant::NONE;
// Block's width or height are less than 512
tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=200");
- uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
- TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
+ uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+ TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
glyphBufferData200.width = 0;
glyphBufferData200.height = 0;
fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
- DALI_TEST_GREATER(512u, glyphBufferData200.width, TEST_LOCATION ); //93u
- DALI_TEST_GREATER(512u, glyphBufferData200.height, TEST_LOCATION ); //115u
+ DALI_TEST_GREATER(512u, glyphBufferData200.width, TEST_LOCATION); //93u
+ DALI_TEST_GREATER(512u, glyphBufferData200.height, TEST_LOCATION); //115u
// Block's width or height are greater than 512 and less than 1024
tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=1000");
- uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
- TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+ uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+ TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
glyphBufferData1000.width = 0;
glyphBufferData1000.height = 0;
fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
- DALI_TEST_GREATER( 512u, glyphBufferData1000.width, TEST_LOCATION ); //462u
- DALI_TEST_GREATER( glyphBufferData1000.height, 512u, TEST_LOCATION ); //574u
+ DALI_TEST_GREATER(512u, glyphBufferData1000.width, TEST_LOCATION); //462u
+ DALI_TEST_GREATER(glyphBufferData1000.height, 512u, TEST_LOCATION); //574u
// Block's width or height are greater than 1024 and less than 2048
tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=2000");
- uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
- TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+ uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+ TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
glyphBufferData2000.width = 0;
glyphBufferData2000.height = 0;
fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
- DALI_TEST_GREATER( 1024u, glyphBufferData2000.width, TEST_LOCATION ); //924u
- DALI_TEST_GREATER( glyphBufferData2000.height, 1024u, TEST_LOCATION ); //1148u
+ DALI_TEST_GREATER(1024u, glyphBufferData2000.width, TEST_LOCATION); //924u
+ DALI_TEST_GREATER(glyphBufferData2000.height, 1024u, TEST_LOCATION); //1148u
- END_TEST;
+ END_TEST;
}
int UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas(void)
TestApplication application;
tet_infoline(" UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas ");
- bool isChanged ;
+ bool isChanged;
TextAbstraction::FontClient fontClient;
fontClient = TextAbstraction::FontClient::Get();
- Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
- Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
+ Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
+ Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
Size currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
tet_infoline("CurrentMaximumBlockSizeFitInAtlas start with default ");
- DALI_TEST_EQUALS( currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, TEST_LOCATION );
+ DALI_TEST_EQUALS(currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, TEST_LOCATION);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(currentMaximumBlockSizeFitInAtlas);
- DALI_TEST_CHECK (isChanged);
+ DALI_TEST_CHECK(isChanged);
- Size decreaseOnlyWidth (currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height);
+ Size decreaseOnlyWidth(currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with width < current ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyWidth);
- DALI_TEST_CHECK (isChanged);
+ DALI_TEST_CHECK(isChanged);
- Size decreaseOnlyHeigth (currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height - 1u);
+ Size decreaseOnlyHeigth(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height - 1u);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with height < current ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyHeigth);
- DALI_TEST_CHECK (isChanged);
+ DALI_TEST_CHECK(isChanged);
- Size decreaseBoth (currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height - 1u);
+ Size decreaseBoth(currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height - 1u);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with size < current ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseBoth);
- DALI_TEST_CHECK (isChanged);
+ DALI_TEST_CHECK(isChanged);
- Size increaseOnlyWidth (maximumTextAtlasSize.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
+ Size increaseOnlyWidth(maximumTextAtlasSize.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with width > max ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyWidth);
- DALI_TEST_CHECK (!isChanged);
+ DALI_TEST_CHECK(!isChanged);
- Size increaseOnlyHeigth (currentMaximumBlockSizeFitInAtlas.width, maximumTextAtlasSize.height + 1u);
+ Size increaseOnlyHeigth(currentMaximumBlockSizeFitInAtlas.width, maximumTextAtlasSize.height + 1u);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with height > max ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyHeigth);
- DALI_TEST_CHECK (!isChanged);
+ DALI_TEST_CHECK(!isChanged);
- Size increaseBoth (maximumTextAtlasSize.width + 1u, maximumTextAtlasSize.height + 1u);
+ Size increaseBoth(maximumTextAtlasSize.width + 1u, maximumTextAtlasSize.height + 1u);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size > max ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseBoth);
- DALI_TEST_CHECK (!isChanged);
+ DALI_TEST_CHECK(!isChanged);
currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
{
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current < size < max ");
Size increaseWidth = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
- isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseWidth);
- DALI_TEST_CHECK (isChanged);
+ isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseWidth);
+ DALI_TEST_CHECK(isChanged);
currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
Size increaseHeigth = Size(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height + 1u);
- isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseHeigth);
- DALI_TEST_CHECK (isChanged);
+ isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseHeigth);
+ DALI_TEST_CHECK(isChanged);
currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
Size sizeLessThanMax = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height + 1u);
- isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(sizeLessThanMax);
+ isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(sizeLessThanMax);
if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
{
- DALI_TEST_CHECK (isChanged);
+ DALI_TEST_CHECK(isChanged);
}
else
{
- DALI_TEST_CHECK (!isChanged);
+ DALI_TEST_CHECK(!isChanged);
}
currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
- DALI_TEST_NOT_EQUALS (currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, 0.0f, TEST_LOCATION );
- DALI_TEST_EQUALS (currentMaximumBlockSizeFitInAtlas, sizeLessThanMax, TEST_LOCATION );
+ DALI_TEST_NOT_EQUALS(currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, 0.0f, TEST_LOCATION);
+ DALI_TEST_EQUALS(currentMaximumBlockSizeFitInAtlas, sizeLessThanMax, TEST_LOCATION);
tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size == max ");
isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(maximumTextAtlasSize);
- DALI_TEST_CHECK (!isChanged);
+ DALI_TEST_CHECK(!isChanged);
}
currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
- DALI_TEST_NOT_EQUALS (currentMaximumBlockSizeFitInAtlas, maximumTextAtlasSize, 0.0f, TEST_LOCATION );
-
+ DALI_TEST_NOT_EQUALS(currentMaximumBlockSizeFitInAtlas, maximumTextAtlasSize, 0.0f, TEST_LOCATION);
END_TEST;
}
Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
Size defaultTextAtlasWidthHeight(TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_HEIGHT);
- DALI_TEST_EQUALS (defaultTextAtlasSize, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE, TEST_LOCATION );
- DALI_TEST_EQUALS (defaultTextAtlasSize, defaultTextAtlasWidthHeight, TEST_LOCATION );
-
+ DALI_TEST_EQUALS(defaultTextAtlasSize, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE, TEST_LOCATION);
+ DALI_TEST_EQUALS(defaultTextAtlasSize, defaultTextAtlasWidthHeight, TEST_LOCATION);
Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
Size maxTextAtlasWidthHeight(TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT);
- DALI_TEST_EQUALS (maximumTextAtlasSize, TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE, TEST_LOCATION );
- DALI_TEST_EQUALS (maximumTextAtlasSize, maxTextAtlasWidthHeight, TEST_LOCATION );
-
+ DALI_TEST_EQUALS(maximumTextAtlasSize, TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE, TEST_LOCATION);
+ DALI_TEST_EQUALS(maximumTextAtlasSize, maxTextAtlasWidthHeight, TEST_LOCATION);
uint32_t numberOfPointsPerOneUnitOfPointSize = fontClient.GetNumberOfPointsPerOneUnitOfPointSize();
- DALI_TEST_EQUALS (numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION );
+ DALI_TEST_EQUALS(numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION);
END_TEST;
}
\ No newline at end of file
dali-test-suite-utils/test-application.cpp
dali-test-suite-utils/test-gesture-generator.cpp
dali-test-suite-utils/test-gl-abstraction.cpp
- dali-test-suite-utils/test-gl-sync-abstraction.cpp
+ dali-test-suite-utils/test-graphics-sync-impl.cpp
+ dali-test-suite-utils/test-graphics-sync-object.cpp
dali-test-suite-utils/test-graphics-buffer.cpp
dali-test-suite-utils/test-graphics-command-buffer.cpp
dali-test-suite-utils/test-graphics-controller.cpp
+ dali-test-suite-utils/test-graphics-framebuffer.cpp
dali-test-suite-utils/test-graphics-pipeline.cpp
dali-test-suite-utils/test-graphics-reflection.cpp
dali-test-suite-utils/test-graphics-texture.cpp
/*
- * 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.
return actor;
}
+Actor CreateRenderableActor2(TextureSet textures, const std::string& vertexShader, const std::string& fragmentShader)
+{
+ // Create the geometry
+ Geometry geometry = CreateQuadGeometry();
+
+ // Create Shader
+ Shader shader = Shader::New(vertexShader, fragmentShader);
+
+ // Create renderer from geometry and material
+ Renderer renderer = Renderer::New(geometry, shader);
+
+ // Create actor and set renderer
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+
+ // If we a texture, then create a texture-set and add to renderer
+ if(textures)
+ {
+ renderer.SetTextures(textures);
+
+ auto texture = textures.GetTexture(0);
+
+ // Set actor to the size of the texture if set
+ actor.SetProperty(Actor::Property::SIZE, Vector2(texture.GetWidth(), texture.GetHeight()));
+ }
+
+ return actor;
+}
+
+Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height)
+{
+ Texture texture = Texture::New(type, format, width, height);
+
+ int bufferSize = width * height * 2;
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+ PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, format, PixelData::FREE);
+ texture.Upload(pixelData, 0u, 0u, 0u, 0u, width, height);
+ return texture;
+}
+
} // namespace Dali
#define DALI_TEST_ACTOR_UTILS_H
/*
- * 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.
*/
// EXTERNAL INCLUDES
+#include <dali/public-api/rendering/texture-set.h>
+#include <dali/public-api/rendering/texture.h>
#include <string>
namespace Dali
*/
Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader);
+/**
+ * @brief Creates a renderable-actor with a texture and custom shaders.
+ * @param[in] textures TextureSet to set.
+ * @param[in] vertexShader The vertex-shader.
+ * @param[in] fragmentShader The fragment-shader.
+ * @return An actor with a renderer.
+ */
+Actor CreateRenderableActor2(TextureSet textures, const std::string& vertexShader, const std::string& fragmentShader);
+
+Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height);
+
} // namespace Dali
#endif // DALI_TEST_ACTOR_UTILS_H
{
mScene = Dali::Integration::Scene::New(Size(static_cast<float>(mSurfaceWidth), static_cast<float>(mSurfaceHeight)));
mScene.SetDpi(Vector2(static_cast<float>(mDpi.x), static_cast<float>(mDpi.y)));
+
+ // Create render target for the scene
+ Graphics::RenderTargetCreateInfo rtInfo{};
+ rtInfo.SetExtent({mSurfaceWidth, mSurfaceHeight});
+ mRenderTarget = mGraphicsController.CreateRenderTarget(rtInfo, nullptr);
+ mScene.SetSurfaceRenderTarget(mRenderTarget.get());
}
void TestApplication::InitializeCore()
return static_cast<TestGlAbstraction&>(mGraphicsController.GetGlAbstraction());
}
-TestGlSyncAbstraction& TestApplication::GetGlSyncAbstraction()
+TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction()
{
- return static_cast<TestGlSyncAbstraction&>(mGraphicsController.GetGlSyncAbstraction());
+ return static_cast<TestGlContextHelperAbstraction&>(mGraphicsController.GetGlContextHelperAbstraction());
}
-TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction()
+TestGraphicsSyncImplementation& TestApplication::GetGraphicsSyncImpl()
{
- return static_cast<TestGlContextHelperAbstraction&>(mGraphicsController.GetGlContextHelperAbstraction());
+ return static_cast<TestGraphicsSyncImplementation&>(mGraphicsController.GetGraphicsSyncImpl());
}
void TestApplication::ProcessEvent(const Integration::Event& event)
TestGraphicsController& GetGraphicsController();
TestGlAbstraction& GetGlAbstraction();
- TestGlSyncAbstraction& GetGlSyncAbstraction();
TestGlContextHelperAbstraction& GetGlContextHelperAbstraction();
+ TestGraphicsSyncImplementation& GetGraphicsSyncImpl();
void ProcessEvent(const Integration::Event& event);
void SendNotification();
uint32_t mSurfaceHeight;
uint32_t mFrame;
+ Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget;
+
struct
{
uint32_t x;
#include "test-gl-abstraction.h"
#include "test-trace-call-stack.h"
+static const bool TRACE{
+ false};
+
namespace Dali
{
TestGlAbstraction::TestGlAbstraction()
-: mBufferTrace(true, std::string("gl")),
- mCullFaceTrace(true, "gl"),
- mEnableDisableTrace(true, "gl"),
- mShaderTrace(true, "gl"),
- mTextureTrace(true, std::string("gl")),
- mTexParameterTrace(true, "gl"),
- mDrawTrace(true, "gl"),
- mDepthFunctionTrace(true, "gl"),
- mStencilFunctionTrace(true, "gl"),
- mScissorTrace(true, "gl"),
- mSetUniformTrace(true, "Uniform "),
- mViewportTrace(true, "gl")
+: mBufferTrace(TRACE, std::string("gl")),
+ mCullFaceTrace(TRACE, "gl"),
+ mEnableDisableTrace(TRACE, "gl"),
+ mShaderTrace(TRACE, "gl"),
+ mTextureTrace(TRACE, std::string("gl")),
+ mTexParameterTrace(TRACE, "gl"),
+ mDrawTrace(TRACE, "gl"),
+ mDepthFunctionTrace(TRACE, "gl"),
+ mStencilFunctionTrace(TRACE, "gl"),
+ mScissorTrace(TRACE, "gl"),
+ mSetUniformTrace(TRACE, "Uniform "),
+ mViewportTrace(TRACE, "gl")
{
Initialize();
}
mCurrentProgram = 0;
mCompileStatus = GL_TRUE;
mLinkStatus = GL_TRUE;
- mNumberOfActiveUniforms = 0;
mGetErrorResult = 0;
mGetStringResult = NULL;
mIsBufferResult = 0;
{
mVertexAttribArrayState[i] = false;
}
+
+ mActiveUniforms = std::vector<ActiveUniform>{
+ {"uRendererColor", GL_FLOAT, 1},
+ {"uCustom", GL_FLOAT_VEC3, 1},
+ {"uCustom3", GL_FLOAT_VEC3, 1},
+ {"uFadeColor", GL_FLOAT_VEC4, 1},
+ {"uUniform1", GL_FLOAT_VEC4, 1},
+ {"uUniform2", GL_FLOAT_VEC4, 1},
+ {"uUniform3", GL_FLOAT_VEC4, 1},
+ {"uFadeProgress", GL_FLOAT, 1},
+ {"uANormalMatrix", GL_FLOAT_MAT3, 1},
+ {"sEffect", GL_SAMPLER_2D, 1},
+ {"sTexture", GL_SAMPLER_2D, 1},
+ {"sTextureRect", GL_SAMPLER_2D, 1},
+ {"sGloss", GL_SAMPLER_2D, 1},
+ {"uColor", GL_FLOAT_VEC4, 1},
+ {"uModelMatrix", GL_FLOAT_MAT4, 1},
+ {"uModelView", GL_FLOAT_MAT4, 1},
+ {"uMvpMatrix", GL_FLOAT_MAT4, 1},
+ {"uNormalMatrix", GL_FLOAT_MAT4, 1},
+ {"uProjection", GL_FLOAT_MAT4, 1},
+ {"uSize", GL_FLOAT_VEC3, 1},
+ {"uViewMatrix", GL_FLOAT_MAT4, 1},
+ {"uLightCameraProjectionMatrix", GL_FLOAT_MAT4, 1},
+ {"uLightCameraViewMatrix", GL_FLOAT_MAT4, 1}};
}
void TestGlAbstraction::PreRender()
}
};
+struct ActiveUniform
+{
+ std::string name;
+ GLenum type;
+ GLint size;
+};
+
class DALI_CORE_API TestGlAbstraction : public Dali::Integration::GlAbstraction
{
public:
{
mFramebufferStencilAttached = true;
}
+ else if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+ {
+ mFramebufferStencilAttached = true;
+ mFramebufferDepthAttached = true;
+ }
}
inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) override
{
}
+ inline void SetActiveUniforms(const std::vector<ActiveUniform>& uniforms)
+ {
+ mActiveUniforms = uniforms;
+ }
+
inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) override
{
- switch(index)
+ if(index < mActiveUniforms.size())
{
- case 0:
- *length = snprintf(name, bufsize, "sTexture");
- *type = GL_SAMPLER_2D;
- *size = 1;
- break;
- case 1:
- *length = snprintf(name, bufsize, "sEffect");
- *type = GL_SAMPLER_2D;
- *size = 1;
- break;
- case 2:
- *length = snprintf(name, bufsize, "sGloss");
- *type = GL_SAMPLER_2D;
- *size = 1;
- break;
- default:
- break;
+ *length = snprintf(name, bufsize, "%s", mActiveUniforms[index].name.c_str());
+ *type = mActiveUniforms[index].type;
+ *size = mActiveUniforms[index].size;
}
}
*params = mProgramBinaryLength;
break;
case GL_ACTIVE_UNIFORMS:
- *params = mNumberOfActiveUniforms;
+ *params = mActiveUniforms.size();
break;
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
*params = 100;
namedParams["program"] << program;
mShaderTrace.PushCall("LinkProgram", out.str(), namedParams);
- mNumberOfActiveUniforms = 3;
-
- GetUniformLocation(program, "uRendererColor");
- GetUniformLocation(program, "uCustom");
- GetUniformLocation(program, "uCustom3");
- GetUniformLocation(program, "uFadeColor");
- GetUniformLocation(program, "uUniform1");
- GetUniformLocation(program, "uUniform2");
- GetUniformLocation(program, "uUniform3");
- GetUniformLocation(program, "uFadeProgress");
- GetUniformLocation(program, "uANormalMatrix");
- GetUniformLocation(program, "sEffect");
- GetUniformLocation(program, "sTexture");
- GetUniformLocation(program, "sTextureRect");
- GetUniformLocation(program, "sGloss");
- GetUniformLocation(program, "uColor");
- GetUniformLocation(program, "uModelMatrix");
- GetUniformLocation(program, "uModelView");
- GetUniformLocation(program, "uMvpMatrix");
- GetUniformLocation(program, "uNormalMatrix");
- GetUniformLocation(program, "uProjection");
- GetUniformLocation(program, "uSize");
- GetUniformLocation(program, "uViewMatrix");
- GetUniformLocation(program, "uLightCameraProjectionMatrix");
- GetUniformLocation(program, "uLightCameraViewMatrix");
+ for(const auto& uniform : mActiveUniforms)
+ {
+ GetUniformLocation(program, uniform.name.c_str());
+ }
for(const auto& uniform : mCustomUniformData)
{
mBufferSubDataCalls.clear();
}
-private:
+public:
GLuint mCurrentProgram;
GLuint mCompileStatus;
BufferDataCalls mBufferDataCalls;
BufferSubDataCalls mBufferSubDataCalls;
GLvoid* mMappedBuffer{nullptr};
GLuint mLinkStatus;
- GLint mNumberOfActiveUniforms;
GLenum mGetErrorResult;
GLubyte* mGetStringResult;
GLboolean mIsBufferResult;
typedef std::map<std::string, GLint> UniformIDMap;
typedef std::map<GLuint, UniformIDMap> ProgramUniformMap;
ProgramUniformMap mUniforms;
-
- std::vector<UniformData> mCustomUniformData{};
+ std::vector<ActiveUniform> mActiveUniforms;
+ std::vector<UniformData> mCustomUniformData{};
template<typename T>
struct ProgramUniformValue : public std::map<GLuint, std::map<GLint, T> >
*/
#include "test-graphics-application.h"
+#include <test-graphics-sync-impl.h>
namespace Dali
{
// We always need the first update!
mStatus.keepUpdating = Integration::KeepUpdating::STAGE_KEEP_RENDERING;
+ mGraphics.Initialize();
mGraphicsController.InitializeGLES(mGlAbstraction);
- mGraphicsController.Initialize(mGlSyncAbstraction, mGlContextHelperAbstraction);
+ mGraphicsController.Initialize(mGraphicsSyncImplementation, mGlContextHelperAbstraction, mGraphics);
mCore = Dali::Integration::Core::New(mRenderController,
mPlatformAbstraction,
{
mScene = Dali::Integration::Scene::New(Size(static_cast<float>(mSurfaceWidth), static_cast<float>(mSurfaceHeight)));
mScene.SetDpi(Vector2(static_cast<float>(mDpi.x), static_cast<float>(mDpi.y)));
+
+ Graphics::RenderTargetCreateInfo createInfo{};
+ createInfo.SetSurface({nullptr})
+ .SetExtent({mSurfaceWidth, mSurfaceHeight})
+ .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
+ mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
+ mScene.SetSurfaceRenderTarget(mRenderTarget.get());
}
void TestGraphicsApplication::InitializeCore()
return static_cast<TestGlAbstraction&>(mGraphicsController.GetGlAbstraction());
}
-TestGlSyncAbstraction& TestGraphicsApplication::GetGlSyncAbstraction()
-{
- return static_cast<TestGlSyncAbstraction&>(mGraphicsController.GetGlSyncAbstraction());
-}
-
TestGlContextHelperAbstraction& TestGraphicsApplication::GetGlContextHelperAbstraction()
{
return static_cast<TestGlContextHelperAbstraction&>(mGraphicsController.GetGlContextHelperAbstraction());
{
mCore->ContextDestroyed();
mGraphicsController.InitializeGLES(mGlAbstraction);
- mGraphicsController.Initialize(mGlSyncAbstraction, mGlContextHelperAbstraction);
+ mGraphicsController.Initialize(mGraphicsSyncImplementation, mGlContextHelperAbstraction, mGraphics);
mCore->ContextCreated();
}
#include <dali/integration-api/scene.h>
#include <dali/integration-api/trace.h>
+#include <dali/internal/graphics/common/graphics-interface.h>
#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
#include <dali/public-api/common/dali-common.h>
#include <test-gl-abstraction.h>
#include <test-gl-context-helper-abstraction.h>
-#include <test-gl-sync-abstraction.h>
+#include <test-graphics-sync-impl.h>
#include <test-platform-abstraction.h>
#include <test-render-controller.h>
namespace Dali
{
+namespace Internal::Adaptor
+{
+class ConfigurationManager;
+}
+
+class TestGraphicsImpl : public Internal::Adaptor::GraphicsInterface
+{
+public:
+ TestGraphicsImpl()
+ : GraphicsInterface()
+ {
+ }
+ virtual ~TestGraphicsImpl() = default;
+
+ Dali::Graphics::Controller& GetController() override
+ {
+ Dali::Graphics::Controller* controller{nullptr};
+ return *controller;
+ }
+
+ /**
+ * Initialize the graphics subsystem, configured from environment
+ */
+ void Initialize() override
+ {
+ mCallstack.PushCall("Initialize()", "");
+ }
+
+ /**
+ * Initialize the graphics subsystem, providing explicit parameters.
+ *
+ * @param[in] depth True if depth buffer is required
+ * @param[in] stencil True if stencil buffer is required
+ * @param[in] partialRendering True if partial rendering is required
+ * @param[in] msaa level of anti-aliasing required (-1 = off)
+ */
+ void Initialize(bool depth, bool stencil, bool partialRendering, int msaa) override
+ {
+ TraceCallStack::NamedParams namedParams;
+ namedParams["depth"] << depth;
+ namedParams["stencil"] << stencil;
+ namedParams["partialRendering"] << partialRendering;
+ namedParams["msaa"] << msaa;
+ mCallstack.PushCall("Initialize()", "");
+ }
+
+ /**
+ * Configure the graphics surface
+ *
+ * @param[in] surface The surface to configure, or NULL if not present
+ */
+ void ConfigureSurface(Dali::RenderSurfaceInterface* surface) override
+ {
+ }
+
+ /**
+ * Activate the resource context
+ */
+ void ActivateResourceContext() override
+ {
+ mCallstack.PushCall("ActivateResourceContext()", "");
+ }
+
+ /**
+ * Activate the resource context
+ *
+ * @param[in] surface The surface whose context to be switched to.
+ */
+ void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface) override
+ {
+ TraceCallStack::NamedParams namedParams;
+ namedParams["surface"] << std::hex << surface;
+ mCallstack.PushCall("ActivateResourceContext()", namedParams.str(), namedParams);
+ }
+
+ /**
+ * Inform graphics interface that this is the first frame after a resume.
+ */
+ void SetFirstFrameAfterResume() override
+ {
+ }
+
+ /**
+ * Shut down the graphics implementation
+ */
+ void Shutdown() override
+ {
+ mCallstack.PushCall("Shutdown()", "");
+ }
+
+ /**
+ * Destroy the Graphics implementation
+ */
+ void Destroy() override
+ {
+ mCallstack.PushCall("Destroy()", "");
+ }
+
+ /**
+ * @return true if advanced blending options are supported
+ */
+ bool IsAdvancedBlendEquationSupported() override
+ {
+ return true;
+ }
+
+ /**
+ * @return true if graphics subsystem is initialized
+ */
+ bool IsInitialized() override
+ {
+ return true;
+ }
+
+ /**
+ * @return true if a separate resource context is supported
+ */
+ bool IsResourceContextSupported() override
+ {
+ return true;
+ }
+
+ /**
+ * @return the maximum texture size
+ */
+ uint32_t GetMaxTextureSize() override
+ {
+ return 32768u;
+ }
+
+ /**
+ * @return the version number of the shader language
+ */
+ uint32_t GetShaderLanguageVersion() override
+ {
+ return 320;
+ }
+
+ /**
+ * Store cached configurations
+ */
+ void CacheConfigurations(Internal::Adaptor::ConfigurationManager& configurationManager) override
+ {
+ }
+
+public:
+ TraceCallStack mCallstack{true, "GraphicsImpl"};
+};
+
class DALI_CORE_API TestGraphicsApplication : public ConnectionTracker
{
public:
Graphics::Controller& GetGraphicsController();
TestGlAbstraction& GetGlAbstraction();
- TestGlSyncAbstraction& GetGlSyncAbstraction();
TestGlContextHelperAbstraction& GetGlContextHelperAbstraction();
void ProcessEvent(const Integration::Event& event);
void DoUpdate(uint32_t intervalMilliseconds, const char* location = NULL);
protected:
- TestPlatformAbstraction mPlatformAbstraction;
- TestRenderController mRenderController;
- Graphics::EglGraphicsController mGraphicsController; // Use real controller in Adaptor
- TestGlAbstraction mGlAbstraction;
- TestGlSyncAbstraction mGlSyncAbstraction;
- TestGlContextHelperAbstraction mGlContextHelperAbstraction;
+ TestPlatformAbstraction mPlatformAbstraction;
+ TestRenderController mRenderController;
+ Graphics::EglGraphicsController mGraphicsController; // Use real controller in Adaptor
+ TestGlAbstraction mGlAbstraction;
+ TestGlContextHelperAbstraction mGlContextHelperAbstraction;
+ TestGraphicsSyncImplementation mGraphicsSyncImplementation;
+ TestGraphicsImpl mGraphics;
+ Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
Integration::UpdateStatus mStatus;
Integration::RenderStatus mRenderStatus;
return target;
}
-void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program) const
+void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const
{
auto* reflection = static_cast<const TestGraphicsReflection*>(&program->GetReflection());
Graphics::UniformBlockInfo uboInfo{};
reflection->GetUniformBlock(0, uboInfo);
- auto* data = memory.data();
+ auto offset = uboBinding.offset;
+ auto* data = memory.data() + offset;
for(const auto& member : uboInfo.members)
{
namespace Dali
{
class TestGraphicsProgram;
+class UniformBufferBindingDescriptor;
class TestGraphicsBuffer : public Graphics::Buffer
{
public:
return true;
}
- void BindAsUniformBuffer(const TestGraphicsProgram* program) const;
+ void BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const;
TraceCallStack& mCallStack;
TestGlAbstraction& mGl;
namespace Dali
{
+std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op)
+{
+ switch(op)
+ {
+ case Graphics::StencilOp::KEEP:
+ os << "KEEP";
+ return os;
+ case Graphics::StencilOp::ZERO:
+ os << "ZERO";
+ return os;
+ case Graphics::StencilOp::REPLACE:
+ os << "REPLACE";
+ return os;
+ case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+ os << "INCREMENT_AND_CLAMP";
+ return os;
+ case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+ os << "DECREMENT_AND_CLAMP";
+ return os;
+ case Graphics::StencilOp::INVERT:
+ os << "INVERT";
+ return os;
+ case Graphics::StencilOp::INCREMENT_AND_WRAP:
+ os << "INCREMENT_AND_WRAP";
+ return os;
+ case Graphics::StencilOp::DECREMENT_AND_WRAP:
+ os << "DECREMENT_AND_WRAP";
+ return os;
+ }
+ return os;
+};
+
+std::ostream& operator<<(std::ostream& os, Graphics::CompareOp op)
+{
+ switch(op)
+ {
+ case Graphics::CompareOp::NEVER:
+ os << "NEVER";
+ return os;
+ case Graphics::CompareOp::LESS:
+ os << "LESS";
+ return os;
+ case Graphics::CompareOp::EQUAL:
+ os << "EQUAL";
+ return os;
+ case Graphics::CompareOp::LESS_OR_EQUAL:
+ os << "LESS_OR_EQUAL";
+ return os;
+ case Graphics::CompareOp::GREATER:
+ os << "GREATER";
+ return os;
+ case Graphics::CompareOp::NOT_EQUAL:
+ os << "NOT_EQUAL";
+ return os;
+ case Graphics::CompareOp::GREATER_OR_EQUAL:
+ os << "GREATER_OR_EQUAL";
+ return os;
+ case Graphics::CompareOp::ALWAYS:
+ os << "ALWAYS";
+ return os;
+ }
+ return os;
+};
+
TestGraphicsCommandBuffer::TestGraphicsCommandBuffer(TraceCallStack& callstack, TestGlAbstraction& glAbstraction)
: mCallStack(callstack),
mGlAbstraction(glAbstraction)
}
}
-std::vector<Command*> TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask)
+std::vector<const Command*> TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask) const
{
- std::vector<Command*> mCommandStack{};
+ std::vector<const Command*> mCommandStack{};
for(auto& cmd : mCommands)
{
if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type)))
return mCommandStack;
}
+std::vector<const Command*> TestGraphicsCommandBuffer::GetChildCommandsByType(CommandTypeMask mask) const
+{
+ std::vector<const Command*> mCommandStack{};
+ for(auto& cmd : mCommands)
+ {
+ if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type)))
+ {
+ mCommandStack.emplace_back(&cmd);
+ }
+ if(cmd.type == CommandType::EXECUTE_COMMAND_BUFFERS)
+ {
+ for(auto secondaryCB : cmd.data.executeCommandBuffers.buffers)
+ {
+ for(auto command : secondaryCB->GetChildCommandsByType(mask))
+ {
+ mCommandStack.push_back(command);
+ }
+ }
+ }
+ }
+ return mCommandStack;
+}
+
} // namespace Dali
{
class TestGraphicsTexture;
class TestGraphicsBuffer;
+class TestGraphicsCommandBuffer;
class TestGraphicsSampler;
class TestGraphicsPipeline;
enum class CommandType
{
- FLUSH = 1 << 0,
- BIND_TEXTURES = 1 << 1,
- BIND_SAMPLERS = 1 << 2,
- BIND_VERTEX_BUFFERS = 1 << 3,
- BIND_INDEX_BUFFER = 1 << 4,
- BIND_UNIFORM_BUFFER = 1 << 5,
- BIND_PIPELINE = 1 << 6,
- DRAW = 1 << 7,
- DRAW_INDEXED = 1 << 8,
- DRAW_INDEXED_INDIRECT = 1 << 9,
- SET_SCISSOR = 1 << 10,
- SET_SCISSOR_TEST = 1 << 11,
- SET_VIEWPORT = 1 << 12,
- SET_VIEWPORT_TEST = 1 << 13
+ FLUSH = 1 << 0,
+ BIND_TEXTURES = 1 << 1,
+ BIND_SAMPLERS = 1 << 2,
+ BIND_VERTEX_BUFFERS = 1 << 3,
+ BIND_INDEX_BUFFER = 1 << 4,
+ BIND_UNIFORM_BUFFER = 1 << 5,
+ BIND_PIPELINE = 1 << 6,
+ DRAW = 1 << 7,
+ DRAW_INDEXED = 1 << 8,
+ DRAW_INDEXED_INDIRECT = 1 << 9,
+ SET_SCISSOR = 1 << 10,
+ SET_SCISSOR_TEST = 1 << 11,
+ SET_VIEWPORT = 1 << 12,
+ SET_VIEWPORT_TEST = 1 << 13,
+ BEGIN_RENDER_PASS = 1 << 14,
+ END_RENDER_PASS = 1 << 15,
+ EXECUTE_COMMAND_BUFFERS = 1 << 16,
+ SET_COLOR_MASK = 1 << 17,
+ CLEAR_STENCIL_BUFFER = 1 << 18,
+ CLEAR_DEPTH_BUFFER = 1 << 19,
+ SET_STENCIL_TEST_ENABLE = 1 << 20,
+ SET_STENCIL_WRITE_MASK = 1 << 21,
+ SET_STENCIL_OP = 1 << 22,
+ SET_STENCIL_FUNC = 1 << 23,
+ SET_DEPTH_COMPARE_OP = 1 << 24,
+ SET_DEPTH_TEST_ENABLE = 1 << 25,
+ SET_DEPTH_WRITE_ENABLE = 1 << 26,
};
+std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op);
+
+std::ostream& operator<<(std::ostream& os, Graphics::CompareOp op);
+
using CommandTypeMask = uint32_t;
template<typename T>
inline CommandTypeMask operator|(T flags, CommandType bit)
{
}
+ Command(CommandType type)
+ : type(type)
+ {
+ // do non-trivial initialization
+ switch(type)
+ {
+ case CommandType::BEGIN_RENDER_PASS:
+ {
+ new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor();
+ break;
+ }
+ default:
+ {
+ }
+ }
+ }
+
~Command()
{
+ switch(type)
+ {
+ case CommandType::BEGIN_RENDER_PASS:
+ {
+ data.beginRenderPass.~BeginRenderPassDescriptor();
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
}
/**
{
switch(rhs.type)
{
+ case CommandType::BEGIN_RENDER_PASS:
+ {
+ new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(rhs.data.beginRenderPass);
+ break;
+ }
+ case CommandType::END_RENDER_PASS:
+ {
+ data.endRenderPass = rhs.data.endRenderPass;
+ break;
+ }
+ case CommandType::EXECUTE_COMMAND_BUFFERS:
+ {
+ data.executeCommandBuffers = rhs.data.executeCommandBuffers;
+ break;
+ }
+
case CommandType::BIND_VERTEX_BUFFERS:
{
data.bindVertexBuffers = rhs.data.bindVertexBuffers;
data.viewportTest.enable = rhs.data.viewportTest.enable;
break;
}
+ case CommandType::SET_COLOR_MASK:
+ {
+ data.colorMask.enabled = rhs.data.colorMask.enabled;
+ break;
+ }
+ case CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ break;
+ }
+ case CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ break;
+ }
+ case CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ data.stencilTest.enabled = rhs.data.stencilTest.enabled;
+ break;
+ }
+ case CommandType::SET_STENCIL_FUNC:
+ {
+ data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask;
+ data.stencilFunc.compareOp = rhs.data.stencilFunc.compareOp;
+ data.stencilFunc.reference = rhs.data.stencilFunc.reference;
+ break;
+ }
+ case CommandType::SET_STENCIL_WRITE_MASK:
+ {
+ data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask;
+ break;
+ }
+ case CommandType::SET_STENCIL_OP:
+ {
+ data.stencilOp.failOp = rhs.data.stencilOp.failOp;
+ data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp;
+ data.stencilOp.passOp = rhs.data.stencilOp.passOp;
+ break;
+ }
+
+ case CommandType::SET_DEPTH_COMPARE_OP:
+ {
+ data.depth.compareOp = rhs.data.depth.compareOp;
+ break;
+ }
+ case CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ data.depth.testEnabled = rhs.data.depth.testEnabled;
+ break;
+ }
+ case CommandType::SET_DEPTH_WRITE_ENABLE:
+ {
+ data.depth.writeEnabled = rhs.data.depth.writeEnabled;
+ break;
+ }
}
type = rhs.type;
}
{
switch(rhs.type)
{
+ case CommandType::BEGIN_RENDER_PASS:
+ {
+ new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(std::move(rhs.data.beginRenderPass));
+ break;
+ }
+ case CommandType::END_RENDER_PASS:
+ {
+ data.endRenderPass = std::move(rhs.data.endRenderPass);
+ break;
+ }
+ case CommandType::EXECUTE_COMMAND_BUFFERS:
+ {
+ data.executeCommandBuffers = std::move(rhs.data.executeCommandBuffers);
+ break;
+ }
case CommandType::BIND_VERTEX_BUFFERS:
{
data.bindVertexBuffers = std::move(rhs.data.bindVertexBuffers);
data.viewportTest.enable = rhs.data.viewportTest.enable;
break;
}
+
+ case CommandType::SET_COLOR_MASK:
+ {
+ data.colorMask.enabled = rhs.data.colorMask.enabled;
+ break;
+ }
+ case CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ break;
+ }
+ case CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ break;
+ }
+ case CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ data.stencilTest.enabled = rhs.data.stencilTest.enabled;
+ break;
+ }
+ case CommandType::SET_STENCIL_WRITE_MASK:
+ {
+ data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask;
+ break;
+ }
+ case CommandType::SET_STENCIL_OP:
+ {
+ data.stencilOp.failOp = rhs.data.stencilOp.failOp;
+ data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp;
+ data.stencilOp.passOp = rhs.data.stencilOp.passOp;
+ break;
+ }
+ case CommandType::SET_STENCIL_FUNC:
+ {
+ data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask;
+ data.stencilFunc.compareOp = rhs.data.stencilFunc.compareOp;
+ data.stencilFunc.reference = rhs.data.stencilFunc.reference;
+ break;
+ }
+ case CommandType::SET_DEPTH_COMPARE_OP:
+ {
+ data.depth.compareOp = rhs.data.depth.compareOp;
+ break;
+ }
+ case CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ data.depth.testEnabled = rhs.data.depth.testEnabled;
+ break;
+ }
+ case CommandType::SET_DEPTH_WRITE_ENABLE:
+ {
+ data.depth.writeEnabled = rhs.data.depth.writeEnabled;
+ break;
+ }
}
type = rhs.type;
}
{
bool enable;
} viewportTest;
+
+ struct BeginRenderPassDescriptor
+ {
+ Graphics::RenderPass* renderPass;
+ Graphics::RenderTarget* renderTarget;
+ Graphics::Rect2D renderArea;
+ std::vector<Graphics::ClearValue> clearValues;
+ } beginRenderPass;
+
+ struct
+ {
+ Graphics::SyncObject* syncObject;
+ } endRenderPass;
+
+ struct
+ {
+ std::vector<const TestGraphicsCommandBuffer*> buffers;
+ } executeCommandBuffers;
+
+ struct
+ {
+ Graphics::CompareOp compareOp;
+ bool testEnabled;
+ bool writeEnabled;
+ } depth;
+
+ struct
+ {
+ Graphics::StencilOp failOp;
+ Graphics::StencilOp passOp;
+ Graphics::StencilOp depthFailOp;
+ } stencilOp;
+
+ struct
+ {
+ uint32_t mask;
+ } stencilWriteMask;
+
+ struct
+ {
+ uint32_t compareMask;
+ Graphics::CompareOp compareOp;
+ uint32_t reference;
+ } stencilFunc;
+
+ struct
+ {
+ bool enabled;
+ } stencilTest;
+
+ struct
+ {
+ bool enabled;
+ } colorMask;
} data;
};
}
void BeginRenderPass(
- Graphics::RenderPass& renderPass,
- Graphics::RenderTarget& renderTarget,
- Graphics::Extent2D renderArea,
+ Graphics::RenderPass* renderPass,
+ Graphics::RenderTarget* renderTarget,
+ Graphics::Rect2D renderArea,
std::vector<Graphics::ClearValue> clearValues) override
{
- mCallStack.PushCall("BeginRenderPass", "");
+ mCommands.emplace_back(CommandType::BEGIN_RENDER_PASS);
+ auto& cmd = mCommands.back();
+ cmd.data.beginRenderPass.renderPass = renderPass;
+ cmd.data.beginRenderPass.renderTarget = renderTarget;
+ cmd.data.beginRenderPass.renderArea = renderArea;
+ cmd.data.beginRenderPass.clearValues = clearValues;
+
+ TraceCallStack::NamedParams namedParams;
+ namedParams["renderPass"] << std::hex << renderPass;
+ namedParams["renderTarget"] << std::hex << renderTarget;
+ namedParams["renderArea"] << renderArea.width << ", " << renderArea.height;
+ mCallStack.PushCall("BeginRenderPass", namedParams.str(), namedParams);
}
/**
* dependencies (for example, to know when target texture is ready
* before passing it to another render pass).
*/
- void EndRenderPass() override
+ void EndRenderPass(Graphics::SyncObject* syncObject) override
{
- mCallStack.PushCall("EndRenderPass", "");
+ mCommands.emplace_back(CommandType::END_RENDER_PASS);
+ auto& cmd = mCommands.back();
+
+ cmd.data.endRenderPass.syncObject = syncObject;
+
+ TraceCallStack::NamedParams namedParams;
+ namedParams["syncObject"] << std::hex << syncObject;
+ mCallStack.PushCall("EndRenderPass", namedParams.str(), namedParams);
+ }
+
+ void ExecuteCommandBuffers(std::vector<const CommandBuffer*>&& commandBuffers) override
+ {
+ mCommands.emplace_back();
+ auto& cmd = mCommands.back();
+ cmd.type = CommandType::EXECUTE_COMMAND_BUFFERS;
+ cmd.data.executeCommandBuffers.buffers.reserve(commandBuffers.size());
+ for(auto&& item : commandBuffers)
+ {
+ cmd.data.executeCommandBuffers.buffers.emplace_back(static_cast<const TestGraphicsCommandBuffer*>(item));
+ }
+ mCallStack.PushCall("ExecuteCommandBuffers", "");
}
void Draw(
mCommands.back().data.viewportTest.enable = value;
}
+ void SetColorMask(bool enabled) override
+ {
+ TraceCallStack::NamedParams params;
+ params["enabled"] << (enabled ? "T" : "F");
+ mCallStack.PushCall("SetColorMask", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_COLOR_MASK;
+ mCommands.back().data.colorMask.enabled = enabled;
+ }
+
+ void ClearStencilBuffer() override
+ {
+ mCallStack.PushCall("SetStencilMask", "");
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::CLEAR_STENCIL_BUFFER;
+ }
+
+ void SetStencilTestEnable(bool stencilEnable) override
+ {
+ TraceCallStack::NamedParams params;
+ params["enabled"] << (stencilEnable ? "T" : "F");
+ mCallStack.PushCall("SetStencilTestEnable", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_STENCIL_TEST_ENABLE;
+ mCommands.back().data.stencilTest.enabled = stencilEnable;
+ }
+
+ void SetStencilWriteMask(uint32_t writeMask) override
+ {
+ TraceCallStack::NamedParams params;
+ params["writeMask"] << std::hex << writeMask;
+ mCallStack.PushCall("SetStencilWriteMask", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_STENCIL_WRITE_MASK;
+ mCommands.back().data.stencilWriteMask.mask = writeMask;
+ }
+
+ void SetStencilOp(Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp) override
+ {
+ TraceCallStack::NamedParams params;
+ params["failOp"] << failOp;
+ params["passOp"] << passOp;
+ params["depthFailOp"] << depthFailOp;
+ mCallStack.PushCall("SetStencilOp", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_STENCIL_OP;
+ mCommands.back().data.stencilOp.failOp = failOp;
+ mCommands.back().data.stencilOp.passOp = passOp;
+ mCommands.back().data.stencilOp.depthFailOp = depthFailOp;
+ }
+
+ void SetStencilFunc(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask) override
+ {
+ TraceCallStack::NamedParams params;
+ params["compareOp"] << compareOp;
+ params["compareMask"] << std::hex << compareMask;
+ params["reference"] << std::hex << reference;
+ mCallStack.PushCall("SetStencilFunc", params.str(), params);
+
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_STENCIL_FUNC;
+
+ mCommands.back().data.stencilFunc.compareOp = compareOp;
+ mCommands.back().data.stencilFunc.compareMask = compareMask;
+ mCommands.back().data.stencilFunc.reference = reference;
+ }
+
+ void SetDepthCompareOp(Graphics::CompareOp compareOp) override
+ {
+ TraceCallStack::NamedParams params;
+ params["compareOp"] << compareOp;
+ mCallStack.PushCall("SetDepthCompareOp", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_DEPTH_COMPARE_OP;
+ mCommands.back().data.depth.compareOp = compareOp;
+ }
+
+ void SetDepthTestEnable(bool depthTestEnable) override
+ {
+ TraceCallStack::NamedParams params;
+ params["enabled"] << (depthTestEnable ? "T" : "F");
+ mCallStack.PushCall("SetDepthTestEnable", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_DEPTH_TEST_ENABLE;
+ mCommands.back().data.depth.testEnabled = depthTestEnable;
+ }
+ void SetDepthWriteEnable(bool depthWriteEnable) override
+ {
+ TraceCallStack::NamedParams params;
+ params["enabled"] << (depthWriteEnable ? "T" : "F");
+ mCallStack.PushCall("SetDepthWriteEnable", params.str(), params);
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::SET_DEPTH_WRITE_ENABLE;
+ mCommands.back().data.depth.writeEnabled = depthWriteEnable;
+ }
+ void ClearDepthBuffer() override
+ {
+ mCallStack.PushCall("ClearDepthBuffer", "");
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::CLEAR_DEPTH_BUFFER;
+ }
+
[[nodiscard]] const std::vector<Command>& GetCommands() const
{
return mCommands;
/**
* Retrieves commands of specified type
*/
- std::vector<Command*> GetCommandsByType(CommandTypeMask mask);
+ std::vector<const Command*> GetCommandsByType(CommandTypeMask mask) const;
+
+ std::vector<const Command*> GetChildCommandsByType(CommandTypeMask mask) const;
private:
TraceCallStack& mCallStack;
#include "test-graphics-buffer.h"
#include "test-graphics-command-buffer.h"
+#include "test-graphics-framebuffer.h"
#include "test-graphics-reflection.h"
+#include "test-graphics-render-pass.h"
+#include "test-graphics-render-target.h"
#include "test-graphics-sampler.h"
#include "test-graphics-shader.h"
+#include "test-graphics-sync-object.h"
#include "test-graphics-texture.h"
#include <dali/integration-api/gl-defines.h>
namespace Dali
{
-template<typename T>
-T* Uncast(const Graphics::CommandBuffer* object)
-{
- return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Texture* object)
-{
- return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Sampler* object)
-{
- return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Buffer* object)
-{
- return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Shader* object)
-{
- return const_cast<T*>(static_cast<const T*>(object));
-}
-
std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
{
return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
return o;
}
-class TestGraphicsMemory : public Graphics::Memory
+std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
{
-public:
- TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
- : mCallStack(callStack),
- mBuffer(buffer),
- mMappedOffset(mappedOffset),
- mMappedSize(mappedSize),
- mLockedOffset(0u),
- mLockedSize(0u)
- {
- }
-
- void* LockRegion(uint32_t offset, uint32_t size) override
- {
- std::ostringstream o;
- o << offset << ", " << size;
- mCallStack.PushCall("Memory::LockRegion", o.str());
-
- if(offset > mMappedOffset + mMappedSize ||
- size + offset > mMappedOffset + mMappedSize)
- {
- fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
- mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
- }
- mLockedOffset = offset;
- mLockedSize = size;
- return &mBuffer.memory[mMappedOffset + offset];
- }
+ o << "attachmentId:" << colorAttachment.attachmentId
+ << " layerId:" << colorAttachment.layerId
+ << " levelId:" << colorAttachment.levelId
+ << " texture:" << colorAttachment.texture;
+ return o;
+}
- void Unlock(bool flush) override
- {
- mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
- if(flush)
- {
- Flush();
- }
- }
+std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
+{
+ o << "depthTexture:" << depthStencilAttachment.depthTexture
+ << "depthLevel:" << depthStencilAttachment.depthLevel
+ << "stencilTexture:" << depthStencilAttachment.stencilTexture
+ << "stencilLevel:" << depthStencilAttachment.stencilLevel;
+ return o;
+}
- void Flush() override
+std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
+{
+ o << "colorAttachments:";
+ for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
{
- mCallStack.PushCall("Memory::Flush", "");
- mBuffer.Bind();
- mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
- mBuffer.Unbind();
+ o << "[" << i << "]=" << createInfo.colorAttachments[i] << " ";
}
-
- TraceCallStack& mCallStack;
- TestGraphicsBuffer& mBuffer;
- uint32_t mMappedOffset;
- uint32_t mMappedSize;
- uint32_t mLockedOffset;
- uint32_t mLockedSize;
-};
-
-TestGraphicsController::TestGraphicsController()
-: mCallStack(true, "TestGraphicsController."),
- mCommandBufferCallStack(true, "TestCommandBuffer.")
-{
- mCallStack.Enable(true);
- mCommandBufferCallStack.Enable(true);
- auto& trace = mGl.GetTextureTrace();
- trace.Enable(true);
- trace.EnableLogging(true);
+ o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
+ o << "size: " << createInfo.size;
+ return o;
}
int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
return op;
}
+struct GLCompareOp
+{
+ constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
+ {
+ switch(compareOp)
+ {
+ case Graphics::CompareOp::NEVER:
+ op = GL_NEVER;
+ break;
+ case Graphics::CompareOp::LESS:
+ op = GL_LESS;
+ break;
+ case Graphics::CompareOp::EQUAL:
+ op = GL_EQUAL;
+ break;
+ case Graphics::CompareOp::LESS_OR_EQUAL:
+ op = GL_LEQUAL;
+ break;
+ case Graphics::CompareOp::GREATER:
+ op = GL_GREATER;
+ break;
+ case Graphics::CompareOp::NOT_EQUAL:
+ op = GL_NOTEQUAL;
+ break;
+ case Graphics::CompareOp::GREATER_OR_EQUAL:
+ op = GL_GEQUAL;
+ break;
+ case Graphics::CompareOp::ALWAYS:
+ op = GL_ALWAYS;
+ break;
+ }
+ }
+ GLenum op{GL_LESS};
+};
+
+struct GLStencilOp
+{
+ constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
+ {
+ switch(stencilOp)
+ {
+ case Graphics::StencilOp::KEEP:
+ op = GL_KEEP;
+ break;
+ case Graphics::StencilOp::ZERO:
+ op = GL_ZERO;
+ break;
+ case Graphics::StencilOp::REPLACE:
+ op = GL_REPLACE;
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+ op = GL_INCR;
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+ op = GL_DECR;
+ break;
+ case Graphics::StencilOp::INVERT:
+ op = GL_INVERT;
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_WRAP:
+ op = GL_INCR_WRAP;
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_WRAP:
+ op = GL_DECR_WRAP;
+ break;
+ }
+ }
+ GLenum op{GL_KEEP};
+};
+
+class TestGraphicsMemory : public Graphics::Memory
+{
+public:
+ TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
+ : mCallStack(callStack),
+ mBuffer(buffer),
+ mMappedOffset(mappedOffset),
+ mMappedSize(mappedSize),
+ mLockedOffset(0u),
+ mLockedSize(0u)
+ {
+ }
+
+ void* LockRegion(uint32_t offset, uint32_t size) override
+ {
+ std::ostringstream o;
+ o << offset << ", " << size;
+ mCallStack.PushCall("Memory::LockRegion", o.str());
+
+ if(offset > mMappedOffset + mMappedSize ||
+ size + offset > mMappedOffset + mMappedSize)
+ {
+ fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
+ mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
+ }
+ mLockedOffset = offset;
+ mLockedSize = size;
+ return &mBuffer.memory[mMappedOffset + offset];
+ }
+
+ void Unlock(bool flush) override
+ {
+ mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
+ if(flush)
+ {
+ Flush();
+ }
+ }
+
+ void Flush() override
+ {
+ mCallStack.PushCall("Memory::Flush", "");
+ mBuffer.Bind();
+ mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
+ mBuffer.Unbind();
+ }
+
+ TraceCallStack& mCallStack;
+ TestGraphicsBuffer& mBuffer;
+ uint32_t mMappedOffset;
+ uint32_t mMappedSize;
+ uint32_t mLockedOffset;
+ uint32_t mLockedSize;
+};
+
+TestGraphicsController::TestGraphicsController()
+: mCallStack(true, "TestGraphicsController."),
+ mCommandBufferCallStack(true, "TestCommandBuffer."),
+ mFrameBufferCallStack(true, "TestFrameBuffer.")
+{
+ mCallStack.Enable(true);
+ mCommandBufferCallStack.Enable(true);
+ auto& trace = mGl.GetTextureTrace();
+ trace.Enable(true);
+ trace.EnableLogging(true);
+}
+
void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
{
TraceCallStack::NamedParams namedParams;
for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
{
auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
+ ProcessCommandBuffer(*commandBuffer);
+ }
+}
+
+void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
+{
+ bool scissorEnabled = false;
+ TestGraphicsFramebuffer* currentFramebuffer{nullptr};
+ TestGraphicsPipeline* currentPipeline{nullptr};
- auto value = commandBuffer->GetCommandsByType(0 | CommandType::BIND_TEXTURES);
- if(!value.empty())
+ for(auto& cmd : commandBuffer.GetCommands())
+ {
+ // process command
+ switch(cmd.type)
{
- // must be fixed
- for(auto& binding : value[0]->data.bindTextures.textureBindings)
+ case CommandType::FLUSH:
+ {
+ // Nothing to do here
+ break;
+ }
+ case CommandType::BIND_TEXTURES:
{
- if(binding.texture)
+ for(auto& binding : cmd.data.bindTextures.textureBindings)
{
- auto texture = Uncast<TestGraphicsTexture>(binding.texture);
-
- texture->Bind(binding.binding);
-
- if(binding.sampler)
+ if(binding.texture)
{
- auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
- if(sampler)
+ auto texture = Uncast<TestGraphicsTexture>(binding.texture);
+ texture->Bind(binding.binding);
+
+ if(binding.sampler)
{
- sampler->Apply(texture->GetTarget());
+ auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
+ if(sampler)
+ {
+ sampler->Apply(texture->GetTarget());
+ }
}
- }
- texture->Prepare(); // Ensure native texture is ready
+ texture->Prepare(); // Ensure native texture is ready
+ }
}
+ break;
}
- }
-
- // IndexBuffer binding,
- auto bindIndexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_INDEX_BUFFER);
- if(!bindIndexBufferCmds.empty())
- {
- auto& indexBufferBinding = bindIndexBufferCmds[0]->data.bindIndexBuffer;
- if(indexBufferBinding.buffer)
+ case CommandType::BIND_VERTEX_BUFFERS:
{
- auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
- buffer->Bind();
+ for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
+ {
+ auto graphicsBuffer = binding.buffer;
+ auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
+ vertexBuffer->Bind();
+ }
+ break;
}
- }
-
- // VertexBuffer binding,
- auto bindVertexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_VERTEX_BUFFERS);
- if(!bindVertexBufferCmds.empty())
- {
- for(auto& binding : bindVertexBufferCmds[0]->data.bindVertexBuffers.vertexBufferBindings)
+ case CommandType::BIND_INDEX_BUFFER:
{
- auto graphicsBuffer = binding.buffer;
- auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
- vertexBuffer->Bind();
+ auto& indexBufferBinding = cmd.data.bindIndexBuffer;
+ if(indexBufferBinding.buffer)
+ {
+ auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
+ buffer->Bind();
+ }
+ break;
}
- }
-
- bool scissorEnabled = false;
+ case CommandType::BIND_UNIFORM_BUFFER:
+ {
+ auto& bindings = cmd.data.bindUniformBuffers;
+ auto buffer = bindings.standaloneUniformsBufferBinding;
- auto scissorTestList = commandBuffer->GetCommandsByType(0 | CommandType::SET_SCISSOR_TEST);
- if(!scissorTestList.empty())
- {
- if(scissorTestList[0]->data.scissorTest.enable)
+ // based on reflection, issue gl calls
+ buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program), bindings.standaloneUniformsBufferBinding);
+ break;
+ }
+ case CommandType::BIND_SAMPLERS:
{
- mGl.Enable(GL_SCISSOR_TEST);
- scissorEnabled = true;
+ break;
}
- else
+ case CommandType::BIND_PIPELINE:
{
- mGl.Disable(GL_SCISSOR_TEST);
+ currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
+ BindPipeline(currentPipeline);
+ break;
+ }
+ case CommandType::DRAW:
+ {
+ mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
+ 0,
+ cmd.data.draw.draw.vertexCount);
+ break;
+ }
+ case CommandType::DRAW_INDEXED:
+ {
+ mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
+ static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+ break;
+ }
+ case CommandType::DRAW_INDEXED_INDIRECT:
+ {
+ mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
+ static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+ break;
+ }
+ case CommandType::SET_SCISSOR:
+ {
+ if(scissorEnabled)
+ {
+ auto& rect = cmd.data.scissor.region;
+ mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
+ }
+ break;
+ }
+ case CommandType::SET_SCISSOR_TEST:
+ {
+ if(cmd.data.scissorTest.enable)
+ {
+ mGl.Enable(GL_SCISSOR_TEST);
+ scissorEnabled = true;
+ }
+ else
+ {
+ mGl.Disable(GL_SCISSOR_TEST);
+ scissorEnabled = false;
+ }
+ break;
+ }
+ case CommandType::SET_VIEWPORT_TEST:
+ {
+ break;
+ }
+ case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+ {
+ auto& rect = cmd.data.viewport.region;
+ mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
+ break;
}
- }
-
- auto scissorList = commandBuffer->GetCommandsByType(0 | CommandType::SET_SCISSOR);
- if(!scissorList.empty() && scissorEnabled)
- {
- auto& rect = scissorList[0]->data.scissor.region;
- mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
- }
- auto viewportList = commandBuffer->GetCommandsByType(0 | CommandType::SET_VIEWPORT);
- if(!viewportList.empty())
- {
- mGl.Viewport(viewportList[0]->data.viewport.region.x, viewportList[0]->data.viewport.region.y, viewportList[0]->data.viewport.region.width, viewportList[0]->data.viewport.region.height);
- }
+ case CommandType::SET_COLOR_MASK:
+ {
+ // Set all channels to the same mask
+ const bool mask = cmd.data.colorMask.enabled;
+ mGl.ColorMask(mask, mask, mask, mask);
+ break;
+ }
+ case CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ mGl.Clear(GL_STENCIL_BUFFER_BIT);
+ break;
+ }
+ case CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ mGl.Clear(GL_DEPTH_BUFFER_BIT);
+ break;
+ }
- // ignore viewport enable
+ case CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ if(cmd.data.stencilTest.enabled)
+ {
+ mGl.Enable(GL_STENCIL_TEST);
+ }
+ else
+ {
+ mGl.Disable(GL_STENCIL_TEST);
+ }
+ break;
+ }
- // Pipeline attribute setup
- auto bindPipelineCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_PIPELINE);
- if(!bindPipelineCmds.empty())
- {
- auto pipeline = bindPipelineCmds[0]->data.bindPipeline.pipeline;
- auto& vi = pipeline->vertexInputState;
- for(auto& attribute : vi.attributes)
+ case CommandType::SET_STENCIL_FUNC:
{
- mGl.EnableVertexAttribArray(attribute.location);
- uint32_t attributeOffset = attribute.offset;
- GLsizei stride = vi.bufferBindings[attribute.binding].stride;
-
- mGl.VertexAttribPointer(attribute.location,
- GetNumComponents(attribute.format),
- GetGlType(attribute.format),
- GL_FALSE, // Not normalized
- stride,
- reinterpret_cast<void*>(attributeOffset));
+ mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
+ cmd.data.stencilFunc.reference,
+ cmd.data.stencilFunc.compareMask);
+ break;
}
- // Cull face setup
- auto& rasterizationState = pipeline->rasterizationState;
- if(rasterizationState.cullMode == Graphics::CullMode::NONE)
+ case CommandType::SET_STENCIL_WRITE_MASK:
{
- mGl.Disable(GL_CULL_FACE);
+ mGl.StencilMask(cmd.data.stencilWriteMask.mask);
+ break;
}
- else
+ case CommandType::SET_STENCIL_OP:
{
- mGl.Enable(GL_CULL_FACE);
- mGl.CullFace(GetCullFace(rasterizationState.cullMode));
+ mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
+ GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
+ GLStencilOp(cmd.data.stencilOp.passOp).op);
+ break;
}
- mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
- // We don't modify glPolygonMode in our context/abstraction from GL_FILL (the GL default),
- // so it isn't present in the API (and won't have any tests!)
-
- // Blending setup
- auto& colorBlendState = pipeline->colorBlendState;
- if(colorBlendState.blendEnable)
+ case CommandType::SET_DEPTH_COMPARE_OP:
{
- mGl.Enable(GL_BLEND);
-
- mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
- GetBlendFactor(colorBlendState.dstColorBlendFactor),
- GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
- GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
- if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
+ mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op);
+ break;
+ }
+ case CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ if(cmd.data.depth.testEnabled)
{
- mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
+ mGl.Enable(GL_DEPTH_TEST);
}
else
{
- mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
+ mGl.Disable(GL_DEPTH_TEST);
}
- mGl.BlendColor(colorBlendState.blendConstants[0],
- colorBlendState.blendConstants[1],
- colorBlendState.blendConstants[2],
- colorBlendState.blendConstants[3]);
+ break;
}
- else
+ case CommandType::SET_DEPTH_WRITE_ENABLE:
{
- mGl.Disable(GL_BLEND);
+ mGl.DepthMask(cmd.data.depth.writeEnabled);
+ break;
}
- // draw call
- auto topology = pipeline->inputAssemblyState.topology;
-
- // UniformBuffer binding (once we know pipeline)
- auto bindUniformBuffersCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_UNIFORM_BUFFER);
- if(!bindUniformBuffersCmds.empty())
+ case CommandType::EXECUTE_COMMAND_BUFFERS:
{
- auto buffer = bindUniformBuffersCmds[0]->data.bindUniformBuffers.standaloneUniformsBufferBinding;
-
- // based on reflection, issue gl calls
- buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(pipeline->programState.program));
+ // Process secondary command buffers
+ for(auto& buf : cmd.data.executeCommandBuffers.buffers)
+ {
+ ProcessCommandBuffer(*Uncast<TestGraphicsCommandBuffer>(buf));
+ }
+ break;
}
-
- auto drawCmds = commandBuffer->GetCommandsByType(0 |
- CommandType::DRAW |
- CommandType::DRAW_INDEXED_INDIRECT |
- CommandType::DRAW_INDEXED);
-
- if(!drawCmds.empty())
+ case CommandType::BEGIN_RENDER_PASS:
{
- if(drawCmds[0]->data.draw.type == DrawCallDescriptor::Type::DRAW_INDEXED)
+ auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
+
+ if(renderTarget)
{
- mGl.DrawElements(GetTopology(topology),
- static_cast<GLsizei>(drawCmds[0]->data.draw.drawIndexed.indexCount),
- GL_UNSIGNED_SHORT,
- reinterpret_cast<void*>(drawCmds[0]->data.draw.drawIndexed.firstIndex));
+ auto fb = renderTarget->mCreateInfo.framebuffer;
+ if(fb)
+ {
+ if(currentFramebuffer != fb)
+ {
+ currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
+ currentFramebuffer->Bind();
+ }
+ }
+ else
+ {
+ mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
}
else
{
- mGl.DrawArrays(GetTopology(topology), 0, drawCmds[0]->data.draw.draw.vertexCount);
+ mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
}
+
+ auto& clearValues = cmd.data.beginRenderPass.clearValues;
+ if(clearValues.size() > 0)
+ {
+ const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
+ if(renderPass)
+ {
+ const auto& color0 = renderPass->attachments[0];
+ GLuint mask = 0;
+ if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
+ {
+ mask |= GL_COLOR_BUFFER_BIT;
+
+ // Set clear color (todo: cache it!)
+ // Something goes wrong here if Alpha mask is GL_TRUE
+ mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+ mGl.ClearColor(clearValues[0].color.r,
+ clearValues[0].color.g,
+ clearValues[0].color.b,
+ clearValues[0].color.a);
+ }
+
+ // check for depth stencil
+ if(renderPass->attachments.size() > 1)
+ {
+ const auto& depthStencil = renderPass->attachments.back();
+ if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
+ {
+ mGl.DepthMask(true);
+ uint32_t depthClearColor = 0u;
+ if(clearValues.size() == renderPass->attachments.size())
+ {
+ depthClearColor = clearValues.back().depthStencil.depth;
+ }
+ mGl.ClearDepthf(depthClearColor);
+ mask |= GL_DEPTH_BUFFER_BIT;
+ }
+ if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
+ {
+ uint32_t stencilClearColor = 0u;
+ if(clearValues.size() == renderPass->attachments.size())
+ {
+ stencilClearColor = clearValues.back().depthStencil.stencil;
+ }
+ mGl.ClearStencil(stencilClearColor);
+ mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8)
+ mask |= GL_STENCIL_BUFFER_BIT;
+ }
+ }
+
+ if(mask != 0)
+ {
+ // Test scissor area and RT size
+ const auto& area = cmd.data.beginRenderPass.renderArea;
+ if(area.x == 0 &&
+ area.y == 0 &&
+ area.width == renderTarget->mCreateInfo.extent.width &&
+ area.height == renderTarget->mCreateInfo.extent.height)
+ {
+ mGl.Disable(GL_SCISSOR_TEST);
+ mGl.Clear(mask);
+ }
+ else
+ {
+ mGl.Enable(GL_SCISSOR_TEST);
+ mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
+ mGl.Clear(mask);
+ mGl.Disable(GL_SCISSOR_TEST);
+ }
+ }
+ }
+ else
+ {
+ DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
+ }
+ }
+ break;
}
- // attribute clear
- for(auto& attribute : vi.attributes)
+ case CommandType::END_RENDER_PASS:
{
- mGl.DisableVertexAttribArray(attribute.location);
+ if(cmd.data.endRenderPass.syncObject != nullptr)
+ {
+ auto syncObject = Uncast<TestGraphicsSyncObject>(cmd.data.endRenderPass.syncObject);
+ syncObject->InitializeResource(); // create the sync object.
+ }
+ break;
}
}
}
}
+void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
+{
+ auto& vi = pipeline->vertexInputState;
+ for(auto& attribute : vi.attributes)
+ {
+ mGl.EnableVertexAttribArray(attribute.location);
+ uint32_t attributeOffset = attribute.offset;
+ GLsizei stride = vi.bufferBindings[attribute.binding].stride;
+
+ mGl.VertexAttribPointer(attribute.location,
+ GetNumComponents(attribute.format),
+ GetGlType(attribute.format),
+ GL_FALSE, // Not normalized
+ stride,
+ reinterpret_cast<void*>(attributeOffset));
+ }
+
+ // Cull face setup
+ auto& rasterizationState = pipeline->rasterizationState;
+ if(rasterizationState.cullMode == Graphics::CullMode::NONE)
+ {
+ mGl.Disable(GL_CULL_FACE);
+ }
+ else
+ {
+ mGl.Enable(GL_CULL_FACE);
+ mGl.CullFace(GetCullFace(rasterizationState.cullMode));
+ }
+
+ mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
+
+ // Blending setup
+ auto& colorBlendState = pipeline->colorBlendState;
+ if(colorBlendState.blendEnable)
+ {
+ mGl.Enable(GL_BLEND);
+
+ mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
+ GetBlendFactor(colorBlendState.dstColorBlendFactor),
+ GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
+ GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
+ if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
+ {
+ mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
+ }
+ else
+ {
+ mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
+ }
+ mGl.BlendColor(colorBlendState.blendConstants[0],
+ colorBlendState.blendConstants[1],
+ colorBlendState.blendConstants[2],
+ colorBlendState.blendConstants[3]);
+ }
+ else
+ {
+ mGl.Disable(GL_BLEND);
+ }
+
+ auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
+ mGl.UseProgram(program->mImpl->mId);
+}
+
/**
* @brief Presents render target
* @param renderTarget render target to present
}
}
+void TestGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
+{
+ mCallStack.PushCall("GenerateTextureMipmaps", "");
+
+ auto gfxTexture = Uncast<TestGraphicsTexture>(&texture);
+ mGl.BindTexture(gfxTexture->GetTarget(), 0);
+ mGl.GenerateMipmap(gfxTexture->GetTarget());
+}
+
bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
{
TraceCallStack::NamedParams namedParams;
Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
{
mCallStack.PushCall("CreateRenderPass", "");
- return nullptr;
+ return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
}
Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
}
-Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(const Graphics::FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
+Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
+ const Graphics::FramebufferCreateInfo& createInfo,
+ Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
{
- mCallStack.PushCall("CreateFramebuffer", "");
- return nullptr;
+ TraceCallStack::NamedParams namedParams;
+ namedParams["framebufferCreateInfo"] << createInfo;
+ mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
+
+ return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
}
Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
{
mCallStack.PushCall("CreateRenderTarget", "");
- return nullptr;
+ return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
+}
+
+Graphics::UniquePtr<Graphics::SyncObject> TestGraphicsController::CreateSyncObject(
+ const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
+ Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject)
+{
+ mCallStack.PushCall("CreateSyncObject", "");
+ return Graphics::MakeUnique<TestGraphicsSyncObject>(mGraphicsSyncImpl, syncObjectCreateInfo);
}
Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
#include <dali/graphics-api/graphics-controller.h>
#include "test-gl-abstraction.h"
#include "test-gl-context-helper-abstraction.h"
-#include "test-gl-sync-abstraction.h"
+#include "test-graphics-command-buffer.h"
#include "test-graphics-program.h"
#include "test-graphics-reflection.h"
+#include "test-graphics-sync-impl.h"
namespace Dali
{
std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode);
std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo);
+template<typename T>
+T* Uncast(const Graphics::CommandBuffer* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Texture* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Sampler* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Buffer* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Shader* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Framebuffer* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Pipeline* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::RenderTarget* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::SyncObject* object)
+{
+ return const_cast<T*>(static_cast<const T*>(object));
+}
+
class TestGraphicsController : public Dali::Graphics::Controller
{
public:
return mGl;
}
- Integration::GlSyncAbstraction& GetGlSyncAbstraction() override
+ Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override
{
- return mGlSyncAbstraction;
+ return mGlContextHelperAbstraction;
}
- Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override
+ TestGraphicsSyncImplementation& GetGraphicsSyncImpl()
{
- return mGlContextHelperAbstraction;
+ return mGraphicsSyncImpl;
}
void SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo) override;
const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList) override;
/**
+ * Auto generates mipmaps for the texture
+ * @param[in] texture The texture
+ */
+ void GenerateTextureMipmaps(const Graphics::Texture& texture) override;
+
+ /**
* TBD: do we need those functions in the new implementation?
*/
bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override;
Graphics::UniquePtr<Graphics::RenderTarget> CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget) override;
/**
+ * @brief Creates new sync object
+ * Could add timeout etc to createinfo... but nah.
+ *
+ * @return pointer to the SyncObject
+ */
+ Graphics::UniquePtr<Graphics::SyncObject> CreateSyncObject(const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
+ Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject) override;
+
+ /**
* @brief Maps memory associated with Buffer object
*
* @param[in] mapInfo Filled details of mapped resource
*
- * @return Returns pointer to Memory object or Graphicsnullptr on error
+ * @return Returns pointer to Memory object or nullptr on error
*/
Graphics::UniquePtr<Graphics::Memory> MapBufferRange(const Graphics::MapBufferInfo& mapInfo) override;
*/
bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override;
+ void ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer);
+
+ void BindPipeline(TestGraphicsPipeline* pipeline);
+
public:
mutable TraceCallStack mCallStack;
mutable TraceCallStack mCommandBufferCallStack;
+ mutable TraceCallStack mFrameBufferCallStack;
mutable std::vector<Graphics::SubmitInfo> mSubmitStack;
TestGlAbstraction mGl;
- TestGlSyncAbstraction mGlSyncAbstraction;
+ TestGraphicsSyncImplementation mGraphicsSyncImpl;
TestGlContextHelperAbstraction mGlContextHelperAbstraction;
bool isDiscardQueueEmptyResult{true};
};
std::vector<ProgramCache> mProgramCache;
+ struct PipelineCache
+ {
+ };
+
std::vector<UniformData> mCustomUniforms;
};
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test-graphics-framebuffer.h"
+#include <dali/integration-api/gl-defines.h>
+#include "test-graphics-controller.h"
+#include "test-graphics-texture.h"
+
+namespace
+{
+const GLenum COLOR_ATTACHMENTS[] =
+ {
+ GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3,
+ GL_COLOR_ATTACHMENT4,
+ GL_COLOR_ATTACHMENT5,
+ GL_COLOR_ATTACHMENT6,
+ GL_COLOR_ATTACHMENT7,
+};
+
+struct DEPTH_STENCIL_ATTACHMENT_TYPE
+{
+ constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat)
+ {
+ switch(textureFormat)
+ {
+ case Graphics::Format::D16_UNORM:
+ case Graphics::Format::D32_SFLOAT:
+ case Graphics::Format::X8_D24_UNORM_PACK32:
+ {
+ attachment = GL_DEPTH_ATTACHMENT;
+ break;
+ }
+
+ case Graphics::Format::S8_UINT:
+ {
+ attachment = GL_STENCIL_ATTACHMENT;
+ break;
+ }
+
+ case Graphics::Format::D16_UNORM_S8_UINT:
+ case Graphics::Format::D24_UNORM_S8_UINT:
+ case Graphics::Format::D32_SFLOAT_S8_UINT:
+ {
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ break;
+ }
+ default:
+ {
+ attachment = GL_NONE;
+ break;
+ }
+ }
+ }
+ GLenum attachment{GL_NONE};
+};
+
+} // namespace
+//namespace
+
+namespace Dali
+{
+TestGraphicsFramebuffer::TestGraphicsFramebuffer(
+ TraceCallStack& callStack,
+ TestGlAbstraction& glAbstraction,
+ const Graphics::FramebufferCreateInfo& createInfo)
+: mGl(glAbstraction),
+ mCallStack(callStack)
+{
+ mCreateInfo.colorAttachments = std::move(createInfo.colorAttachments);
+ mCreateInfo.depthStencilAttachment = createInfo.depthStencilAttachment;
+ mCreateInfo.size = createInfo.size;
+}
+
+TestGraphicsFramebuffer::~TestGraphicsFramebuffer()
+{
+ if(mId)
+ {
+ mGl.DeleteFramebuffers(1, &mId);
+ }
+}
+
+void TestGraphicsFramebuffer::Initialize()
+{
+ mCallStack.PushCall("Initialize", "");
+
+ mGl.GenFramebuffers(1, &mId);
+ mGl.BindFramebuffer(GL_FRAMEBUFFER, mId);
+
+ for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
+ {
+ AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId);
+ }
+ mGl.DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
+
+ if(mCreateInfo.depthStencilAttachment.depthTexture)
+ {
+ // Create a depth or depth/stencil render target.
+ auto depthTexture = Uncast<TestGraphicsTexture>(mCreateInfo.depthStencilAttachment.depthTexture);
+ auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetFormat()).attachment;
+
+ mGl.GenRenderbuffers(1, &mDepthBuffer);
+ mGl.BindRenderbuffer(GL_RENDERBUFFER, mDepthBuffer);
+ mGl.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height);
+ mGl.FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mDepthBuffer);
+
+ AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel);
+ }
+
+ if(mCreateInfo.depthStencilAttachment.stencilTexture)
+ {
+ auto stencilTexture = Uncast<TestGraphicsTexture>(mCreateInfo.depthStencilAttachment.stencilTexture);
+ auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetFormat()).attachment;
+
+ // Create a stencil render target.
+ mGl.GenRenderbuffers(1, &mStencilBuffer);
+ mGl.BindRenderbuffer(GL_RENDERBUFFER, mStencilBuffer);
+ mGl.RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height);
+ mGl.FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mStencilBuffer);
+
+ AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel);
+ }
+ mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void TestGraphicsFramebuffer::AttachTexture(Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
+{
+ auto graphicsTexture = Uncast<TestGraphicsTexture>(texture);
+ if(graphicsTexture->GetType() == Graphics::TextureType::TEXTURE_2D)
+ {
+ mGl.FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetTarget(), graphicsTexture->mId, levelId);
+ }
+ else
+ {
+ mGl.FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->mId, levelId);
+ }
+}
+
+void TestGraphicsFramebuffer::Bind()
+{
+ mCallStack.PushCall("Bind", "");
+
+ if(!mId)
+ {
+ Initialize();
+ }
+ mGl.BindFramebuffer(GL_FRAMEBUFFER, mId);
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef TEST_GRAPHICS_FRAMEBUFFER_H
+#define TEST_GRAPHICS_FRAMEBUFFER_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/graphics-api/graphics-framebuffer-create-info.h>
+#include <dali/graphics-api/graphics-framebuffer.h>
+#include <dali/graphics-api/graphics-types.h>
+#include "test-gl-abstraction.h"
+#include "test-trace-call-stack.h"
+
+namespace Dali
+{
+class TestGraphicsFramebuffer : public Graphics::Framebuffer
+{
+public:
+ TestGraphicsFramebuffer(TraceCallStack& callStack, TestGlAbstraction& glAbstraction, const Graphics::FramebufferCreateInfo& createInfo);
+ ~TestGraphicsFramebuffer();
+
+ void Initialize();
+ void AttachTexture(Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId);
+ void Bind();
+
+ TestGlAbstraction& mGl;
+ Graphics::FramebufferCreateInfo mCreateInfo;
+ TraceCallStack& mCallStack;
+
+ GLuint mId{0};
+ GLuint mDepthBuffer;
+ GLuint mStencilBuffer;
+};
+
+} // namespace Dali
+
+#endif //TEST_GRAPHICS_FRAMEBUFFER_H
TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics::PipelineCreateInfo& createInfo)
: mGl(gl)
{
- // Need to deep copy, otherwise pointed at memory will go out of scope. Probably should do something about this.
+ // Need to deep copy, otherwise pointed at memory will go out of scope. @todo Probably should do something about this.
if(createInfo.colorBlendState)
colorBlendState = *createInfo.colorBlendState;
if(createInfo.viewportState)
viewportState = *createInfo.viewportState;
- if(createInfo.framebufferState)
- framebufferState = *createInfo.framebufferState;
-
if(createInfo.depthStencilState)
depthStencilState = *createInfo.depthStencilState;
--- /dev/null
+#ifndef DALI_TEST_GRAPHICS_RENDER_PASS_H
+#define DALI_TEST_GRAPHICS_RENDER_PASS_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/graphics-api/graphics-render-pass-create-info.h>
+#include <dali/graphics-api/graphics-render-pass.h>
+
+namespace Dali
+{
+class TestGraphicsRenderPass : public Graphics::RenderPass
+{
+public:
+ TestGraphicsRenderPass(TestGlAbstraction& gl, Graphics::RenderPassCreateInfo createInfo)
+ : mGl(gl)
+ {
+ attachments = *createInfo.attachments; // Deep copy the vector's contents... @todo FIXME!
+ }
+ ~TestGraphicsRenderPass() = default;
+
+ TestGlAbstraction& mGl;
+ std::vector<Graphics::AttachmentDescription> attachments;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_RENDER_PASS_H
--- /dev/null
+#ifndef DALI_TEST_GRAPHICS_RENDER_TARGET_H
+#define DALI_TEST_GRAPHICS_RENDER_TARGET_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/graphics-api/graphics-render-target-create-info.h>
+#include <dali/graphics-api/graphics-render-target.h>
+
+namespace Dali
+{
+class TestGraphicsRenderTarget : public Graphics::RenderTarget
+{
+public:
+ TestGraphicsRenderTarget(TestGlAbstraction& gl, Graphics::RenderTargetCreateInfo createInfo)
+ : mGl(gl)
+ {
+ mCreateInfo.surface = createInfo.surface;
+ mCreateInfo.framebuffer = createInfo.framebuffer;
+ mCreateInfo.extent = createInfo.extent;
+ mCreateInfo.preTransform = createInfo.preTransform;
+ }
+ ~TestGraphicsRenderTarget() = default;
+
+ TestGlAbstraction& mGl;
+ Graphics::RenderTargetCreateInfo mCreateInfo;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_RENDER_TARGET_H
*
*/
-#include "test-gl-sync-abstraction.h"
+#include "test-graphics-sync-impl.h"
namespace Dali
{
-TestSyncObject::TestSyncObject(TraceCallStack& trace)
+TestSyncObject::TestSyncObject(Dali::TraceCallStack& trace)
+
: synced(false),
mTrace(trace)
{
+ mTrace.PushCall("TestSyncObject cons", ""); // Trace the method
}
TestSyncObject::~TestSyncObject()
{
+ mTrace.PushCall("TestSyncObject dstr", ""); // Trace the method
}
bool TestSyncObject::IsSynced()
return synced;
}
-TestGlSyncAbstraction::TestGlSyncAbstraction()
+TestGraphicsSyncImplementation::TestGraphicsSyncImplementation()
{
Initialize();
}
/**
* Destructor
*/
-TestGlSyncAbstraction::~TestGlSyncAbstraction()
+TestGraphicsSyncImplementation::~TestGraphicsSyncImplementation()
{
for(SyncIter iter = mSyncObjects.begin(), end = mSyncObjects.end(); iter != end; ++iter)
{
}
/**
- * Initialize the sync objects - clear down the map
+ * Initialize the sync objects
*/
-void TestGlSyncAbstraction::Initialize()
+void TestGraphicsSyncImplementation::Initialize()
{
mSyncObjects.clear();
}
-/**
- * Create a sync object
- * @return the sync object
- */
-Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* TestGraphicsSyncImplementation::CreateSyncObject()
{
mTrace.PushCall("CreateSyncObject", ""); // Trace the method
* Destroy a sync object
* @param[in] syncObject The object to destroy
*/
-void TestGlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
+void TestGraphicsSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
{
std::stringstream out;
out << syncObject;
}
}
-Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* TestGraphicsSyncImplementation::GetLastSyncObject()
{
if(!mSyncObjects.empty())
{
* @param[in]
* @param[in] sync The sync value to set
*/
-void TestGlSyncAbstraction::SetObjectSynced(Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync)
+void TestGraphicsSyncImplementation::SetObjectSynced(Integration::GraphicsSyncAbstraction::SyncObject* syncObject, bool sync)
{
TestSyncObject* testSyncObject = static_cast<TestSyncObject*>(syncObject);
testSyncObject->synced = sync;
/**
* Turn trace on
*/
-void TestGlSyncAbstraction::EnableTrace(bool enable)
+void TestGraphicsSyncImplementation::EnableTrace(bool enable)
{
mTrace.Enable(enable);
}
/**
* Reset the trace callstack
*/
-void TestGlSyncAbstraction::ResetTrace()
+void TestGraphicsSyncImplementation::ResetTrace()
{
mTrace.Reset();
}
/**
* Get the trace object (allows test case to find methods on it)
*/
-TraceCallStack& TestGlSyncAbstraction::GetTrace()
+TraceCallStack& TestGraphicsSyncImplementation::GetTrace()
{
return mTrace;
}
-int32_t TestGlSyncAbstraction::GetNumberOfSyncObjects()
+int32_t TestGraphicsSyncImplementation::GetNumberOfSyncObjects()
{
return static_cast<int32_t>(mSyncObjects.size());
}
-#ifndef TEST_GL_SYNC_ABSTRACTION_H
-#define TEST_GL_SYNC_ABSTRACTION_H
+#ifndef TEST_SYNC_IMPLEMENTATION_H
+#define TEST_SYNC_IMPLEMENTATION_H
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd.
#include <string>
// INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
#include <dali/integration-api/core.h>
-#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/integration-api/graphics-sync-abstraction.h>
#include "test-trace-call-stack.h"
namespace Dali
{
-class DALI_CORE_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject
+class TestGraphicsSyncImplementation;
+
+class TestSyncObject : public Integration::GraphicsSyncAbstraction::SyncObject
{
public:
TestSyncObject(TraceCallStack& trace);
};
/**
- * Class to emulate the GL sync functions with tracing
+ * Class to emulate the gpu sync functions with tracing
*/
-class DALI_CORE_API TestGlSyncAbstraction : public Integration::GlSyncAbstraction
+class TestGraphicsSyncImplementation : public Integration::GraphicsSyncAbstraction
{
public:
/**
* Constructor
*/
- TestGlSyncAbstraction();
+ TestGraphicsSyncImplementation();
/**
* Destructor
*/
- ~TestGlSyncAbstraction() override;
+ virtual ~TestGraphicsSyncImplementation();
/**
- * Initialize the sync objects - clear down the map
+ * Initialize the sync objects
*/
void Initialize();
/**
- * Create a sync object
- * @return the sync object
+ * Create a sync object that can be polled
*/
- Integration::GlSyncAbstraction::SyncObject* CreateSyncObject() override;
+ GraphicsSyncAbstraction::SyncObject* CreateSyncObject() override;
/**
* Destroy a sync object
- * @param[in] syncObject The object to destroy
*/
- void DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject) override;
+ void DestroySyncObject(GraphicsSyncAbstraction::SyncObject* syncObject) override;
public: // TEST FUNCTIONS
- Integration::GlSyncAbstraction::SyncObject* GetLastSyncObject();
+ GraphicsSyncAbstraction::SyncObject* GetLastSyncObject();
/**
* Test method to trigger the object sync behaviour.
* @param[in]
* @param[in] sync The sync value to set
*/
- void SetObjectSynced(Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync);
+ void SetObjectSynced(GraphicsSyncAbstraction::SyncObject* syncObject, bool sync);
/**
* Turn trace on
*/
int32_t GetNumberOfSyncObjects();
-private:
- TestGlSyncAbstraction(const TestGlSyncAbstraction&); ///< Undefined
- TestGlSyncAbstraction& operator=(const TestGlSyncAbstraction&); ///< Undefined
+ TestGraphicsSyncImplementation(const TestGraphicsSyncImplementation&) = delete;
+ TestGraphicsSyncImplementation& operator=(const TestGraphicsSyncImplementation&) = delete;
+private:
typedef std::vector<TestSyncObject*> SyncContainer;
typedef SyncContainer::iterator SyncIter;
SyncContainer mSyncObjects; ///< The sync objects
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test-graphics-sync-object.h"
+
+namespace Dali
+{
+TestGraphicsSyncObject::TestGraphicsSyncObject(TestGraphicsSyncImplementation& syncImpl, const Graphics::SyncObjectCreateInfo& createInfo)
+: mSyncImplementation(syncImpl),
+ mSyncObject(nullptr),
+ mCreateInfo(createInfo)
+{
+}
+
+TestGraphicsSyncObject::~TestGraphicsSyncObject()
+{
+ mSyncImplementation.DestroySyncObject(mSyncObject);
+}
+
+void TestGraphicsSyncObject::InitializeResource()
+{
+ mSyncObject = static_cast<TestSyncObject*>(mSyncImplementation.CreateSyncObject());
+}
+
+bool TestGraphicsSyncObject::IsSynced()
+{
+ bool synced = false;
+ if(mSyncObject)
+ {
+ synced = mSyncObject->IsSynced();
+ }
+ return synced;
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TEST_GRAPHICS_SYNC_OBJECT_H_
+#define DALI_TEST_GRAPHICS_SYNC_OBJECT_H_
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
+
+#include <test-graphics-sync-impl.h>
+
+namespace Dali
+{
+class TestGraphicsSyncObject : public Graphics::SyncObject
+{
+public:
+ TestGraphicsSyncObject(TestGraphicsSyncImplementation& syncImpl, const Graphics::SyncObjectCreateInfo& createInfo);
+ ~TestGraphicsSyncObject() override;
+ void InitializeResource();
+ bool IsSynced() override;
+
+public:
+ TestGraphicsSyncImplementation& mSyncImplementation;
+ TestSyncObject* mSyncObject;
+ Graphics::SyncObjectCreateInfo mCreateInfo;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_SYNC_OBJECT_H
case Graphics::Format::R64G64B64A64_SINT:
case Graphics::Format::R64G64B64A64_SFLOAT:
case Graphics::Format::B10G11R11_UFLOAT_PACK32:
+ case Graphics::Format::R11G11B10_UFLOAT_PACK32:
case Graphics::Format::E5B9G9R9_UFLOAT_PACK32:
case Graphics::Format::D16_UNORM:
case Graphics::Format::X8_D24_UNORM_PACK32:
glFormat = 0;
break;
}
+ case Graphics::Format::R11G11B10_UFLOAT_PACK32:
+ {
+ glFormat = GL_RGB;
+ pixelDataType = GL_FLOAT;
+ break;
+ }
case Graphics::Format::R4G4_UNORM_PACK8:
case Graphics::Format::A1R5G5B5_UNORM_PACK16:
{
case Graphics::Format::R16G16B16A16_SFLOAT:
case Graphics::Format::R32G32B32A32_SFLOAT:
+ case Graphics::Format::R11G11B10_UFLOAT_PACK32:
{
glInternalFormat = GL_R11F_G11F_B10F;
break;
GLuint GetTarget();
/**
+ * Get the texture type
+ */
+ Graphics::TextureType GetType()
+ {
+ return mCreateInfo.textureType;
+ }
+
+ /**
+ * Get the texture format
+ */
+ Graphics::Format GetFormat()
+ {
+ return mCreateInfo.format;
+ }
+
+ /**
* Bind this texture, ensure Native image is initialized if necessary.
*/
void Bind(uint32_t textureUnit);
*
*/
-#include <stdlib.h>
#include <dali-test-suite-utils.h>
#include <dali/dali.h>
#include <dali/devel-api/adaptor-framework/application-devel.h>
+#include <stdlib.h>
using namespace Dali;
int UtcDaliApplicationGetDataPathP(void)
{
- setenv( "DALI_APPLICATION_DATA_DIR", "MyDataPath", 1);
+ setenv("DALI_APPLICATION_DATA_DIR", "MyDataPath", 1);
std::string dataPath = DevelApplication::GetDataPath();
DALI_TEST_EQUALS(dataPath, "MyDataPath", TEST_LOCATION);
END_TEST;
{
std::string arg1;
std::string arg2;
- instance.AddAuxiliaryHint(arg1,arg2);
+ instance.AddAuxiliaryHint(arg1, arg2);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
try
{
unsigned int arg1(0u);
- std::string arg2;
- instance.SetAuxiliaryHintValue(arg1,arg2);
+ std::string arg2;
+ instance.SetAuxiliaryHintValue(arg1, arg2);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
{
std::string arg1;
std::string arg2;
- instance.SetClass(arg1,arg2);
+ instance.SetClass(arg1, arg2);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
{
try
{
- Dali::Window arg1;
+ Dali::Window arg1;
Dali::Rect<int> arg2;
- DevelWindow::SetPositionSize(arg1,arg2);
+ DevelWindow::SetPositionSize(arg1, arg2);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
{
try
{
- Dali::Window arg1;
+ Dali::Window arg1;
std::unique_ptr<Dali::CallbackBase> arg2;
- int arg3(0);
- DevelWindow::AddFrameRenderedCallback(arg1,std::move(arg2),arg3);
+ int arg3(0);
+ DevelWindow::AddFrameRenderedCallback(arg1, std::move(arg2), arg3);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
{
try
{
- Dali::Window arg1;
+ Dali::Window arg1;
Dali::Vector<Dali::WindowOrientation> arg2;
- DevelWindow::SetAvailableOrientations(arg1,arg2);
+ DevelWindow::SetAvailableOrientations(arg1, arg2);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
{
try
{
- Dali::Window arg1;
+ Dali::Window arg1;
std::unique_ptr<Dali::CallbackBase> arg2;
- int arg3(0);
- DevelWindow::AddFramePresentedCallback(arg1,std::move(arg2),arg3);
+ int arg3(0);
+ DevelWindow::AddFramePresentedCallback(arg1, std::move(arg2), arg3);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
{
Dali::Window arg1;
Dali::Window arg2;
- DevelWindow::SetParent(arg1,arg2);
+ DevelWindow::SetParent(arg1, arg2);
DALI_TEST_CHECK(false); // Should not get here
}
catch(...)
SET(TC_SOURCES
utc-Dali-GraphicsSampler.cpp
utc-Dali-GraphicsGeometry.cpp
+ utc-Dali-GraphicsProgram.cpp
utc-Dali-GraphicsNativeImage.cpp
)
../dali-adaptor/dali-test-suite-utils/test-actor-utils.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-application.cpp
../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
- ../dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/dali.h>
+
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <test-actor-utils.h>
+#include <test-graphics-application.h>
+#include <test-graphics-sampler.h>
+
+using namespace Dali;
+
+void utc_dali_program_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+void utc_dali_program_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+const std::string VERT_SHADER_SOURCE = "myVertShaderSource";
+const std::string FRAG_SHADER_SOURCE =
+ "\n"
+ "uniform sampler2D sAlbedo;\n"
+ "uniform sampler2D sMetalRoughness;\n"
+ "uniform sampler2D sNormals;\n"
+ "uniform sampler2D sAmbientOcclusion;\n"
+ "uniform mediump vec3 lightDirection;\n"
+ "in mediump vec2 vTexCoord;\n"
+ "main()\n"
+ "{\n"
+ " gl_fragColor = texture2d(sAlbedo, vTexCoord) + lightDirection*texture2d(sNormals, vTexCoord);\n"
+ "}\n";
+} //anonymous namespace
+
+int UtcDaliGraphicsProgram(void)
+{
+ TestGraphicsApplication app;
+ tet_infoline("UtcDaliProgram - check that right sampler uniforms are bound for textures");
+
+ Texture normals = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+ Texture metalroughness = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+ Texture ao = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+ Texture albedo = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+
+ TextureSet textureSet = TextureSet::New();
+ textureSet.SetTexture(0, albedo);
+ textureSet.SetTexture(1, metalroughness);
+ textureSet.SetTexture(2, normals);
+ textureSet.SetTexture(3, ao);
+
+ Actor actor = CreateRenderableActor2(textureSet, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
+ app.GetScene().Add(actor);
+
+ auto& gl = app.GetGlAbstraction();
+ auto& glUniformTrace = gl.GetSetUniformTrace();
+ glUniformTrace.Enable(true);
+ glUniformTrace.EnableLogging(true);
+
+ std::vector<ActiveUniform> activeUniforms{
+ {"sAlbedo", GL_SAMPLER_2D, 1},
+ {"sAmbientOcclusion", GL_SAMPLER_2D, 1},
+ {"sNormals", GL_SAMPLER_2D, 1},
+ {"sMetalRoughness", GL_SAMPLER_2D, 1}};
+ gl.SetActiveUniforms(activeUniforms);
+
+ app.SendNotification();
+ app.Render(16); // The above actor will get rendered and drawn once.
+
+ // Check what uniform values were set:
+ int value;
+ DALI_TEST_CHECK(gl.GetUniformValue("sAlbedo", value)); // First in frag shader
+ DALI_TEST_EQUALS(value, 0, TEST_LOCATION);
+ DALI_TEST_CHECK(gl.GetUniformValue("sAmbientOcclusion", value)); // 4th
+ DALI_TEST_EQUALS(value, 3, TEST_LOCATION);
+ DALI_TEST_CHECK(gl.GetUniformValue("sNormals", value)); // 3rd
+ DALI_TEST_EQUALS(value, 2, TEST_LOCATION);
+ DALI_TEST_CHECK(gl.GetUniformValue("sMetalRoughness", value)); // 2nd
+ DALI_TEST_EQUALS(value, 1, TEST_LOCATION);
+
+ END_TEST;
+}
test_return_value = TET_PASS;
}
-namespace
-{
-Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height)
-{
- Texture texture = Texture::New(type, format, width, height);
-
- int bufferSize = width * height * 2;
- uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(bufferSize));
- PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, format, PixelData::FREE);
- texture.Upload(pixelData, 0u, 0u, 0u, 0u, width, height);
- return texture;
-}
-
-} // namespace
-
int UtcDaliGraphicsSamplerDefault(void)
{
TestGraphicsApplication app;
DALI_TEST_CHECK(params != nullptr);
auto iter = params->find("param");
- //@todo Change back when mip-map generation is implemented
- //DALI_TEST_CHECK(*iter == GL_LINEAR_MIPMAP_NEAREST);
- DALI_TEST_CHECK(*iter == GL_LINEAR);
+ DALI_TEST_CHECK(*iter == GL_LINEAR_MIPMAP_NEAREST);
TraceCallStack::NamedParams magFilter;
magFilter["pname"] << std::hex << GL_TEXTURE_MAG_FILTER;
params = glParamTrace.FindLastMatch("TexParameteri", minFilter);
DALI_TEST_CHECK(params != nullptr);
iter = params->find("param");
- //@todo Change back when mip-map generation is implemented
- //DALI_TEST_CHECK(*iter == GL_NEAREST_MIPMAP_LINEAR);
- DALI_TEST_CHECK(*iter == GL_NEAREST);
+ DALI_TEST_CHECK(*iter == GL_NEAREST_MIPMAP_LINEAR);
END_TEST;
}
../dali-adaptor/dali-test-suite-utils/test-harness.cpp
../dali-adaptor/dali-test-suite-utils/test-application.cpp
../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
- ../dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
+ ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
{
protected:
Dali::WeakHandle<Dali::Actor> self;
- bool root = false;
+ bool root = false;
Dali::Actor Self()
{
Dali::Rect<> GetExtents(Dali::Accessibility::CoordType ctype) override
{
- Dali::Actor actor = Self();
- Vector2 screenPosition = actor.GetProperty(Actor::Property::SCREEN_POSITION).Get<Vector2>();
- Vector3 size = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
- bool positionUsesAnchorPoint = actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
- Vector3 anchorPointOffSet = size * (positionUsesAnchorPoint ? actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
- Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
+ Dali::Actor actor = Self();
+ Vector2 screenPosition = actor.GetProperty(Actor::Property::SCREEN_POSITION).Get<Vector2>();
+ Vector3 size = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
+ bool positionUsesAnchorPoint = actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
+ Vector3 anchorPointOffSet = size * (positionUsesAnchorPoint ? actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
+ Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
return {position.x, position.y, size.x, size.y};
}
#ifndef DALI_DEVEL_ATSPI_ACCESSIBILITY_H
#define DALI_DEVEL_ATSPI_ACCESSIBILITY_H
/*
- * 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.
enum class ApplicationType
{
WEB_BROWSER = 0,
- HBB_TV = 1,
+ HBB_TV = 1,
WEB_RUNTIME = 2,
- OTHER = 3
+ OTHER = 3
};
/**
*/
// EXTERNAL INCLUDES
-#include <string>
#include <functional>
+#include <string>
namespace Dali
{
/*
- * 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.
const float FontClient::DEFAULT_ITALIC_ANGLE = 12.f * Dali::Math::PI_OVER_180; // FreeType documentation states the software italic is done by doing a horizontal shear of 12 degrees (file ftsynth.h).
//Default atlas block
-const bool FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED = true;
-const uint32_t FontClient::DEFAULT_TEXT_ATLAS_WIDTH = 512u;
-const uint32_t FontClient::DEFAULT_TEXT_ATLAS_HEIGHT = 512u;
+const bool FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED = true;
+const uint32_t FontClient::DEFAULT_TEXT_ATLAS_WIDTH = 512u;
+const uint32_t FontClient::DEFAULT_TEXT_ATLAS_HEIGHT = 512u;
const Size FontClient::DEFAULT_TEXT_ATLAS_SIZE(DEFAULT_TEXT_ATLAS_WIDTH, DEFAULT_TEXT_ATLAS_HEIGHT);
//Maximum atlas block
const uint16_t FontClient::PADDING_TEXT_ATLAS_BLOCK = 5u; // 2 * DOUBLE_PIXEL_PADDING + 1u
//Maximum block size to fit into atlas block
-const Size FontClient::MAX_SIZE_FIT_IN_ATLAS(MAX_TEXT_ATLAS_WIDTH - PADDING_TEXT_ATLAS_BLOCK, MAX_TEXT_ATLAS_HEIGHT - PADDING_TEXT_ATLAS_BLOCK );
+const Size FontClient::MAX_SIZE_FIT_IN_ATLAS(MAX_TEXT_ATLAS_WIDTH - PADDING_TEXT_ATLAS_BLOCK, MAX_TEXT_ATLAS_HEIGHT - PADDING_TEXT_ATLAS_BLOCK);
-const uint32_t FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE = 64u;//Found this value from toolkit
+const uint32_t FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE = 64u; //Found this value from toolkit
FontClient::GlyphBufferData::GlyphBufferData()
: buffer{nullptr},
bool FontClient::IsAtlasLimitationEnabled() const
{
- return GetImplementation(*this).IsAtlasLimitationEnabled( );
+ return GetImplementation(*this).IsAtlasLimitationEnabled();
}
Size FontClient::GetMaximumTextAtlasSize() const
{
- return GetImplementation(*this).GetMaximumTextAtlasSize( );
+ return GetImplementation(*this).GetMaximumTextAtlasSize();
}
Size FontClient::GetDefaultTextAtlasSize() const
{
- return GetImplementation(*this).GetDefaultTextAtlasSize( );
+ return GetImplementation(*this).GetDefaultTextAtlasSize();
}
Size FontClient::GetCurrentMaximumBlockSizeFitInAtlas() const
{
- return GetImplementation(*this).GetCurrentMaximumBlockSizeFitInAtlas( );
+ return GetImplementation(*this).GetCurrentMaximumBlockSizeFitInAtlas();
}
bool FontClient::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
#define DALI_PLATFORM_TEXT_ABSTRACTION_FONT_CLIENT_H
/*
- * 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.
static const PointSize26Dot6 DEFAULT_POINT_SIZE; ///< The default point size.
static const float DEFAULT_ITALIC_ANGLE; ///< The default software italic angle in radians.
- static const bool DEFAULT_ATLAS_LIMITATION_ENABLED; ///< The default behavior of whether atlas limitation is enabled in dali.
- static const uint32_t DEFAULT_TEXT_ATLAS_WIDTH; ///< The default width of text-atlas-block.
- static const uint32_t DEFAULT_TEXT_ATLAS_HEIGHT; ///< The default height of text-atlas-block.
- static const Size DEFAULT_TEXT_ATLAS_SIZE; ///< The default size(width, height) of text-atlas-block.
+ static const bool DEFAULT_ATLAS_LIMITATION_ENABLED; ///< The default behavior of whether atlas limitation is enabled in dali.
+ static const uint32_t DEFAULT_TEXT_ATLAS_WIDTH; ///< The default width of text-atlas-block.
+ static const uint32_t DEFAULT_TEXT_ATLAS_HEIGHT; ///< The default height of text-atlas-block.
+ static const Size DEFAULT_TEXT_ATLAS_SIZE; ///< The default size(width, height) of text-atlas-block.
- static const uint32_t MAX_TEXT_ATLAS_WIDTH; ///< The maximum width of text-atlas-block.
- static const uint32_t MAX_TEXT_ATLAS_HEIGHT; ///< The maximum height of text-atlas-block.
- static const Size MAX_TEXT_ATLAS_SIZE; ///< The maximum height of text-atlas-block.
-
- static const uint16_t PADDING_TEXT_ATLAS_BLOCK ; ///< Padding per edge. How much the block size (width, height) less than the text-atlas-block size (width, height).
- static const Size MAX_SIZE_FIT_IN_ATLAS; ///< The maximum block's size fit into text-atlas-block.
-
- static const uint32_t NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE; ///< Factor multiply point-size in toolkit.
+ static const uint32_t MAX_TEXT_ATLAS_WIDTH; ///< The maximum width of text-atlas-block.
+ static const uint32_t MAX_TEXT_ATLAS_HEIGHT; ///< The maximum height of text-atlas-block.
+ static const Size MAX_TEXT_ATLAS_SIZE; ///< The maximum height of text-atlas-block.
+ static const uint16_t PADDING_TEXT_ATLAS_BLOCK; ///< Padding per edge. How much the block size (width, height) less than the text-atlas-block size (width, height).
+ static const Size MAX_SIZE_FIT_IN_ATLAS; ///< The maximum block's size fit into text-atlas-block.
+ static const uint32_t NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE; ///< Factor multiply point-size in toolkit.
/**
* @brief Struct used to retrieve the glyph's bitmap.
*/
bool IsAtlasLimitationEnabled() const;
- /**
+ /**
* @brief retrieve the maximum allowed width and height for text-atlas-block.
*
* @note Used default configuration.
*/
Size GetMaximumTextAtlasSize() const;
- /**
+ /**
* @brief retrieve the default width and height for text-atlas-block.
*
* @note Used default configuration.
*/
Size GetCurrentMaximumBlockSizeFitInAtlas() const;
- /**
+ /**
* @brief set the achieved size (width and height) for text-atlas-block.
* If @p currentMaximumBlockSizeFitInAtlas larger than the current maximum text atlas then store, otherwise ignore.
*
#define DALI_TEXT_ABSTRACTION_H
/*
- * Copyright (c) 2019 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.
#include <dali/devel-api/text-abstraction/font-client.h>
#include <dali/devel-api/text-abstraction/font-metrics.h>
#include <dali/devel-api/text-abstraction/glyph-info.h>
+#include <dali/devel-api/text-abstraction/hyphenation.h>
#include <dali/devel-api/text-abstraction/script.h>
#include <dali/devel-api/text-abstraction/segmentation.h>
#include <dali/devel-api/text-abstraction/shaping.h>
-#include <dali/devel-api/text-abstraction/hyphenation.h>
#endif // DALI_TEXT_ABSTRACTION_H
#define DALI_RENDER_SURFACE_INTERFACE_H
/*
- * 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.
mDisplayConnection(nullptr),
mScene(),
mFullSwapNextFrame(true),
+ mIsResizing(false),
mDepthBufferRequired(Integration::DepthBufferAvailable::FALSE),
mStencilBufferRequired(Integration::StencilBufferAvailable::FALSE)
{
virtual void StartRender() = 0;
/**
- * @brief Invoked by render thread before Core::Render
+ * @brief Invoked by render thread before Core::RenderScene
* If the operation fails, then Core::Render should not be called until there is
* a surface to render onto.
* @param[in] resizingSurface True if the surface is being resized
virtual bool PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect) = 0;
/**
- * @brief Invoked by render thread after Core::Render
- * @param[in] renderToFbo True if render to FBO.
- * @param[in] replacingSurface True if the surface is being replaced.
- * @param[in] resizingSurface True if the surface is being resized.
+ * @brief Invoked by render thread after Core::RenderScene
*/
- virtual void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) = 0;
+ virtual void PostRender() = 0;
/**
* @brief Invoked by render thread when the thread should be stop
mFullSwapNextFrame = true;
}
+ /**
+ * @brief Sets whether this surface is being resized.
+ */
+ void SetIsResizing(bool isResizing)
+ {
+ mIsResizing = isResizing;
+ }
+
private:
/**
* @brief Undefined copy constructor. RenderSurface cannot be copied
Dali::DisplayConnection* mDisplayConnection;
WeakHandle<Dali::Integration::Scene> mScene;
bool mFullSwapNextFrame; ///< Whether the full surface swap is required
+ bool mIsResizing; ///< Whether the surface is being resized
private:
Integration::DepthBufferAvailable mDepthBufferRequired; ///< Whether the depth buffer is required
mSurface->SetAdaptor(*mAdaptor);
mSurface->SetScene(mScene);
+ // Recreate the render target
+ CreateRenderTarget();
+
OnSurfaceSet(surface);
}
mScene.SurfaceResized(static_cast<float>(surfacePositionSize.width), static_cast<float>(surfacePositionSize.height));
mSurface->SetFullSwapNextFrame();
+
+ // Recreate the render target
+ CreateRenderTarget();
}
Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const
mSurface->SetAdaptor(*mAdaptor);
mSurface->SetScene(mScene);
+ // Create the render target
+ CreateRenderTarget();
+
OnAdaptorSet(adaptor);
}
+void SceneHolder::CreateRenderTarget()
+{
+ Graphics::RenderTargetCreateInfo rtInfo{};
+ rtInfo
+ .SetSurface(mSurface.get())
+ .SetExtent({static_cast<uint32_t>(mSurface->GetPositionSize().width), static_cast<uint32_t>(mSurface->GetPositionSize().height)})
+ .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
+ mRenderTarget = mAdaptor->GetGraphicsInterface().GetController().CreateRenderTarget(rtInfo, std::move(mRenderTarget));
+
+ mScene.SetSurfaceRenderTarget(mRenderTarget.get());
+}
+
void SceneHolder::Pause()
{
Reset();
#define DALI_INTEGRATION_INTERNAL_SCENEHOLDER_H
/*
- * 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.
*/
// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-controller.h>
#include <dali/integration-api/events/key-event-integ.h>
#include <dali/integration-api/events/point.h>
#include <dali/integration-api/events/touch-event-combiner.h>
void AddFramePresentedCallback(std::unique_ptr<CallbackBase> callback, int32_t frameId);
/**
+ * @brief Creates the render target for the surface when the surface is created/resized/replaced.
+ */
+ void CreateRenderTarget();
+
+ /**
* @copydoc Dali::Integration::SceneHolder::Get()
*/
static Dali::Integration::SceneHolder Get(Dali::Actor actor);
class SceneHolderLifeCycleObserver;
std::unique_ptr<SceneHolderLifeCycleObserver> mLifeCycleObserver; ///< The adaptor life cycle observer
+private:
+ Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
+
protected:
uint32_t mId; ///< A unique ID to identify the SceneHolder starting from 0
Dali::Integration::Scene mScene; ///< The Scene
void BridgeAccessible::SuppressScreenReader(bool suppress)
{
- suppressScreenReader = suppress;
+ suppressScreenReader = suppress;
}
DBus::ValueOrError<bool> BridgeAccessible::DoGesture(Dali::Accessibility::Gesture type, int32_t xBeg, int32_t yBeg, int32_t xEnd, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime)
void BridgeBase::RegisteredEventsUpdate()
{
using ReturnType = std::vector<std::tuple<std::string, std::string>>;
- registry.method<DBus::ValueOrError<ReturnType>()>( "GetRegisteredEvents" ).asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
+ registry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
if(!msg)
{
LOG() << "Get registered events failed";
ReturnType values = std::get<ReturnType>(msg.getValues());
for(long unsigned int i = 0; i < values.size(); i++)
{
- if (!std::get<1>(values[i]).compare("Object:BoundsChanged"))
+ if(!std::get<1>(values[i]).compare("Object:BoundsChanged"))
{
allowObjectBoundsChangedEvent = true;
}
return this->id;
}
-auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType> >
+auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType>>
{
auto root = &application;
DBus::DBusInterfaceDescription& desc, const std::string& funcName, DBus::ValueOrError<RET...> (SELF::*funcPtr)(ARGS...))
{
if(auto self = dynamic_cast<SELF*>(this))
- desc.addMethod<DBus::ValueOrError<RET...>(ARGS...)>(funcName,
- [=](ARGS... args) -> DBus::ValueOrError<RET...> {
- try
- {
- return (self->*funcPtr)(std::move(args)...);
- }
- catch(std::domain_error& e)
- {
- return DBus::Error{e.what()};
- }
- });
+ desc.addMethod<DBus::ValueOrError<RET...>(ARGS...)>(
+ funcName,
+ [=](ARGS... args) -> DBus::ValueOrError<RET...> {
+ try
+ {
+ return (self->*funcPtr)(std::move(args)...);
+ }
+ catch(std::domain_error& e)
+ {
+ return DBus::Error{e.what()};
+ }
+ });
}
template<typename T, typename SELF>
// CLASS HEADER
// EXTERNAL INCLUDES
-#include <dali/public-api/actors/layer.h>
#include <dali/devel-api/common/stage.h>
#include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/layer.h>
#include <iostream>
#include <unordered_map>
// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/internal/accessibility/bridge/bridge-accessible.h>
#include <dali/internal/accessibility/bridge/bridge-action.h>
#include <dali/internal/accessibility/bridge/bridge-collection.h>
#include <dali/internal/accessibility/bridge/dummy-atspi.h>
#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/system/common/environment-variables.h>
-#include <dali/devel-api/adaptor-framework/environment-variable.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
using namespace Dali::Accessibility;
try
{
/* check environment variable first */
- const char *envAtspiDisabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_DISABLE_ATSPI);
- if (envAtspiDisabled && std::atoi(envAtspiDisabled) != 0)
+ const char* envAtspiDisabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_DISABLE_ATSPI);
+ if(envAtspiDisabled && std::atoi(envAtspiDisabled) != 0)
{
return Dali::Accessibility::DummyBridge::GetInstance();
}
return new BridgeImpl;
}
- catch (const std::exception&)
+ catch(const std::exception&)
{
DALI_LOG_ERROR("Failed to initialize AT-SPI bridge");
return Dali::Accessibility::DummyBridge::GetInstance();
{
static Bridge* bridge;
- if (bridge)
+ if(bridge)
{
return bridge;
}
- else if (autoInitState == AutoInitState::ENABLED)
+ else if(autoInitState == AutoInitState::ENABLED)
{
bridge = CreateBridge();
/* check environment variable for suppressing screen-reader */
- const char *envSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER);
- if (envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0)
+ const char* envSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER);
+ if(envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0)
{
bridge->SuppressScreenReader(true);
}
void Bridge::DisableAutoInit()
{
- if (bridgeInitialized)
+ if(bridgeInitialized)
{
DALI_LOG_ERROR("Bridge::DisableAutoInit() called after bridge auto-initialization");
}
{
autoInitState = AutoInitState::ENABLED;
- if (bridgeInitialized)
+ if(bridgeInitialized)
{
return;
}
- auto rootLayer = Dali::Stage::GetCurrent().GetRootLayer();
- auto window = Dali::DevelWindow::Get(rootLayer);
+ auto rootLayer = Dali::Stage::GetCurrent().GetRootLayer();
+ auto window = Dali::DevelWindow::Get(rootLayer);
auto applicationName = Dali::Internal::Adaptor::Adaptor::GetApplicationPackageName();
auto* bridge = Bridge::GetCurrentBridge();
namespace Dali
{
-
Accessibility::Accessible::Accessible()
{
}
namespace Dali::Accessibility
{
-
struct DummyBridge : Dali::Accessibility::Bridge
{
- static DummyBridge *GetInstance()
+ static DummyBridge* GetInstance()
{
static DummyBridge instance;
else if(screenWidth != mWindowPositionSize.width || screenHeight != mWindowPositionSize.height)
{
//Some apps can receive screen size differently after launching by specifying size in manifest.
- mWindowPositionSize.width = screenWidth;
+ mWindowPositionSize.width = screenWidth;
mWindowPositionSize.height = screenHeight;
mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
}
// Then create a new pixmap/window and new surface
// If the new surface has a different display connection, then the context will be lost
mAdaptorInterfaces.GetDisplayConnectionInterface().Initialize();
- newSurface->InitializeGraphics();
- newSurface->MakeContextCurrent();
+ graphics.ActivateSurfaceContext(newSurface);
// TODO: ReplaceGraphicsSurface doesn't work, InitializeGraphics()
// already creates new surface window, the surface and the context.
// We probably don't need ReplaceGraphicsSurface at all.
// Get Surface Resized flag
sceneSurfaceResized = scene.IsSurfaceRectChanged();
+ windowSurface->SetIsResizing(sceneSurfaceResized);
windowSurface->InitializeGraphics();
// Switch to the context of the surface, merge damaged areas for previous frames
windowSurface->PreRender(sceneSurfaceResized, mDamagedRects, clippingRect); // Switch GL context
- if(clippingRect.IsEmpty())
- {
- mDamagedRects.clear();
- }
-
// Render the surface
mCore.RenderScene(windowRenderStatus, scene, false, clippingRect);
- if(windowRenderStatus.NeedsPostRender())
- {
- windowSurface->PostRender(false, false, sceneSurfaceResized, mDamagedRects); // Swap Buffer with damage
- }
+ // Buffer swapping now happens when the surface render target is presented.
// If surface is resized, the surface resized count is decreased.
if(DALI_UNLIKELY(sceneSurfaceResized))
}
}
+ if(!mUploadWithoutRendering)
+ {
+ graphics.ActivateResourceContext();
+ }
+
mCore.PostRender(mUploadWithoutRendering);
//////////////////////////////
virtual void ActivateResourceContext() = 0;
/**
+ * Activate the surface context
+ *
+ * @param[in] surface The surface whose context to be switched to.
+ */
+ virtual void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface) = 0;
+
+ /**
* Inform graphics interface that this is the first frame after a resume.
*/
virtual void SetFirstFrameAfterResume() = 0;
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
+#include <cstdio>
+#include <queue>
+
+namespace Dali::Graphics
+{
+std::string DumpCompareOp(Graphics::CompareOp compareOp)
+{
+ switch(compareOp)
+ {
+ case Graphics::CompareOp::NEVER:
+ return "Graphics::CompareOp::NEVER";
+ break;
+ case Graphics::CompareOp::LESS:
+ return "Graphics::CompareOp::LESS";
+ break;
+ case Graphics::CompareOp::EQUAL:
+ return "Graphics::CompareOp::EQUAL";
+ break;
+ case Graphics::CompareOp::LESS_OR_EQUAL:
+ return "Graphics::CompareOp::LESS_OR_EQUAL";
+ break;
+ case Graphics::CompareOp::GREATER:
+ return "Graphics::CompareOp::GREATER";
+ break;
+ case Graphics::CompareOp::NOT_EQUAL:
+ return "Graphics::CompareOp::NOT_EQUAL";
+ break;
+ case Graphics::CompareOp::GREATER_OR_EQUAL:
+ return "Graphics::CompareOp::GREATER_OR_EQUAL";
+ break;
+ case Graphics::CompareOp::ALWAYS:
+ return "Graphics::CompareOp::ALWAYS";
+ break;
+ }
+ return "UNKNOWN";
+}
+
+std::string DumpStencilOp(Graphics::StencilOp stencilOp)
+{
+ switch(stencilOp)
+ {
+ case Graphics::StencilOp::KEEP:
+ return "Graphics::StencilOp::KEEP";
+ break;
+ case Graphics::StencilOp::ZERO:
+ return "Graphics::StencilOp::ZERO";
+ break;
+ case Graphics::StencilOp::REPLACE:
+ return "Graphics::StencilOp::REPLACE";
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+ return "Graphics::StencilOp::INCREMENT_AND_CLAMP";
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+ return "Graphics::StencilOp::DECREMENT_AND_CLAMP";
+ break;
+ case Graphics::StencilOp::INVERT:
+ return "Graphics::StencilOp::INVERT";
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_WRAP:
+ return "Graphics::StencilOp::INCREMENT_AND_WRAP";
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_WRAP:
+ return "Graphics::StencilOp::DECREMENT_AND_WRAP";
+ break;
+ }
+ return "UNKNOWN";
+}
+
+void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
+{
+ bool first{true};
+ for(auto& cmd : commandBuffer->GetCommands())
+ {
+ if(!first)
+ {
+ fprintf(output, ",");
+ }
+ first = false;
+ // process command
+ switch(cmd.type)
+ {
+ case GLES::CommandType::FLUSH:
+ {
+ fprintf(output, "{\"Cmd\":\"FLUSH\"}\n");
+ break;
+ }
+ case GLES::CommandType::BIND_TEXTURES:
+ {
+ fprintf(output, "{\"Cmd\":\"BIND_TEXTURES\"}\n");
+ break;
+ }
+ case GLES::CommandType::BIND_VERTEX_BUFFERS:
+ {
+ fprintf(output, "{\"Cmd\":\"BIND_VERTEX_BUFFERS\"}\n");
+ break;
+ }
+ case GLES::CommandType::BIND_UNIFORM_BUFFER:
+ {
+ fprintf(output, "{\"Cmd\":\"BIND_UNIFORM_BUFFERS\"}\n");
+ break;
+ }
+ case GLES::CommandType::BIND_INDEX_BUFFER:
+ {
+ fprintf(output, "{\"Cmd\":\"BIND_INDEX_BUFFERS\"}\n");
+ break;
+ }
+ case GLES::CommandType::BIND_SAMPLERS:
+ {
+ fprintf(output, "{\"Cmd\":\"BIND_SAMPLERS\"}\n");
+ break;
+ }
+ case GLES::CommandType::BIND_PIPELINE:
+ {
+ fprintf(output, "{\"Cmd\":\"BIND_PIPELINE\"}\n");
+ break;
+ }
+ case GLES::CommandType::DRAW:
+ {
+ fprintf(output, "{\"Cmd\":\"DRAW\"}\n");
+ break;
+ }
+ case GLES::CommandType::DRAW_INDEXED:
+ {
+ fprintf(output, "{\"Cmd\":\"DRAW_INDEXED\"}\n");
+ break;
+ }
+ case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+ {
+ fprintf(output, "{\"Cmd\":\"DRAW_INDEXED_INDIRECT\"}\n");
+ break;
+ }
+ case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
+ {
+ fprintf(output, "{\"Cmd\":\"SET_SCISSOR\",\n\"region\":[%d,%d,%d,%d]\n}\n", cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
+ break;
+ }
+ case GLES::CommandType::SET_SCISSOR_TEST:
+ {
+ fprintf(output, "{\"Cmd\":\"SET_SCISSOR_TEST\",\n\"enable\":%s\n}\n", (cmd.scissorTest.enable ? "\"true\"" : "\"false\""));
+ break;
+ }
+ case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+ {
+ fprintf(output, "{\"Cmd\":\"SET_VIEWPORT\",\n\"region\":[%f,%f,%f,%f]\n}\n", cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
+ break;
+ }
+ case GLES::CommandType::SET_COLOR_MASK:
+ {
+ fprintf(output, "{\"Cmd\":\"SET_COLOR_MASK\",\n\"enable\":%s\n}\n", (cmd.colorMask.enabled ? "\"true\"" : "\"false\""));
+ break;
+ }
+ case GLES::CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ fprintf(output, "{\"Cmd\":\"CLEAR_STENCIL_BUFFER\"}\n");
+ break;
+ }
+ case GLES::CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ fprintf(output, "{\"Cmd\":\"CLEAR_DEPTH_BUFFER\"}\n");
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ fprintf(output, "{\"Cmd\":\"SET_STENCIL_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.stencilTest.enabled ? "\"true\"" : "\"false\""));
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_FUNC:
+ {
+ fprintf(output,
+ "{\"Cmd\":\"STENCIL_FUNC\",\n"
+ "\"compareOp\":\"%s\",\n"
+ "\"reference\":\"0x%x\",\n"
+ "\"compareMask\":\"0x%x\"\n}",
+ DumpCompareOp(cmd.stencilFunc.compareOp).c_str(),
+ cmd.stencilFunc.reference,
+ cmd.stencilFunc.compareMask);
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_WRITE_MASK:
+ {
+ fprintf(output, "{\"Cmd\":\"SET_STENCIL_WRITE_MASK\",\n\"mask\":%d\n}\n", cmd.stencilWriteMask.mask);
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_OP:
+ {
+ fprintf(output,
+ "{\"Cmd\":\"SET_STENCIL_OP\",\n"
+ "\"failOp\":\"%s\",\n"
+ "\"depthFailOp\":\"%s\",\n"
+ "\"passOp\":\"%s\"\n}",
+
+ DumpStencilOp(cmd.stencilOp.failOp).c_str(),
+ DumpStencilOp(cmd.stencilOp.depthFailOp).c_str(),
+ DumpStencilOp(cmd.stencilOp.passOp).c_str());
+ break;
+ }
+
+ case GLES::CommandType::SET_DEPTH_COMPARE_OP:
+ {
+ fprintf(output,
+ "{\"Cmd\":\"SET_DEPTH_COMPARE_OP\",\n"
+ "\"compareOp\":\"%s\"\n}\n",
+ DumpCompareOp(cmd.depth.compareOp).c_str());
+ break;
+ }
+ case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ fprintf(output, "{\"Cmd\":\"SET_DEPTH_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.testEnabled ? "\"true\"" : "\"false\""));
+ break;
+ }
+ case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
+ {
+ fprintf(output, "{\"Cmd\":\"SET_DEPTH_WRITE_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.writeEnabled ? "\"true\"" : "\"false\""));
+ break;
+ }
+
+ case GLES::CommandType::BEGIN_RENDERPASS:
+ {
+ fprintf(output,
+ "{\"Cmd\":\"BEGIN_RENDER_PASS\",\n"
+ "\"renderTarget\":\"%p\",\n"
+ "\"renderPass\":\"%p\",\n"
+ "\"renderArea\":[%d,%d,%d,%d],\n",
+ cmd.beginRenderPass.renderTarget,
+ cmd.beginRenderPass.renderPass,
+ cmd.beginRenderPass.renderArea.x,
+ cmd.beginRenderPass.renderArea.y,
+ cmd.beginRenderPass.renderArea.width,
+ cmd.beginRenderPass.renderArea.height);
+ fprintf(output, "\"clearValues\":[");
+ bool firstV = true;
+ for(auto& value : cmd.beginRenderPass.clearValues)
+ {
+ if(!firstV)
+ {
+ fprintf(output, ",");
+ }
+ firstV = false;
+ fprintf(output, "[%f,%f,%f,%f]", value.color.r, value.color.g, value.color.b, value.color.a);
+ }
+ fprintf(output, "]\n}");
+ break;
+ }
+ case GLES::CommandType::END_RENDERPASS:
+ {
+ fprintf(output, "{\"Cmd\":\"END_RENDER_PASS\"}\n");
+ break;
+ }
+ case GLES::CommandType::PRESENT_RENDER_TARGET:
+ {
+ fprintf(output, "{\"Cmd\":\"PRESENT_RENDER_TARGET\"}\n");
+ break;
+ }
+ case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
+ {
+ fprintf(output, "{\"Cmd\":\"EXECUTE_COMMAND_BUFFERS\",\n\"buffers\":[");
+ bool firstBuf{true};
+ for(auto& buf : cmd.executeCommandBuffers.buffers)
+ {
+ if(!firstBuf)
+ {
+ fprintf(output, ", ");
+ }
+ firstBuf = false;
+ DumpCommandBuffer(output, static_cast<const GLES::CommandBuffer*>(buf));
+ }
+ fprintf(output, "]\n}");
+ break;
+ }
+ }
+ }
+}
+
+GraphicsFrameDump::GraphicsFrameDump()
+: outputStream(nullptr, nullptr)
+{
+ char* outfile = getenv("GRAPHICS_CMDBUF_OUTFILE");
+ if(outfile)
+ {
+ outputStream = UniqueFilePtr(std::fopen(outfile, "w"), std::fclose);
+ output = outputStream.get();
+ }
+ if(!output)
+ output = stderr;
+}
+
+void GraphicsFrameDump::Start()
+{
+ if(IsDumpFrame())
+ {
+ if(!firstFrame)
+ {
+ fprintf(output, ", \n");
+ }
+ firstFrame = false;
+ firstBuffer = true;
+ dumpingFrame = true;
+ fprintf(output, "{\"Queue #%d\":[\n", frameCount);
+ }
+}
+
+void GraphicsFrameDump::DumpCommandBuffer(const GLES::CommandBuffer* cmdBuf)
+{
+ if(dumpingFrame)
+ {
+ if(!firstBuffer)
+ {
+ fprintf(output, ", \n");
+ }
+ firstBuffer = false;
+ fprintf(output, "[\n");
+ Graphics::DumpCommandBuffer(output, cmdBuf);
+ fprintf(output, "]\n");
+ }
+}
+
+void GraphicsFrameDump::End()
+{
+ if(dumpingFrame)
+ {
+ fprintf(output, "]}\n");
+ }
+ firstBuffer = true;
+ dumpingFrame = false;
+}
+
+bool GraphicsFrameDump::IsDumpFrame()
+{
+ bool dump = false;
+
+ frameCount++;
+
+ dump = (frameCount < NTH_FRAME);
+
+ // Or, could also use an enviroment variable as a trigger
+ // e.g. if getenv(X) is set, then start dumping again, and clear X.
+
+ return dump;
+}
+
+} // namespace Dali::Graphics
--- /dev/null
+#ifndef DALI_GRAPHICS_EGL_GRAPHICS_CONTROLLER_DEBUG_H
+#define DALI_GRAPHICS_EGL_GRAPHICS_CONTROLLER_DEBUG_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
+
+namespace Dali::Graphics
+{
+/**
+ * Struct to manage dumping N command buffers. In this file, "frame" really
+ * means each call to EglGraphicsController::Flush(), and doesn't necessarily
+ * correspond to a complete render frame.
+ */
+struct GraphicsFrameDump
+{
+ using UniqueFilePtr = std::unique_ptr<std::FILE, int (*)(std::FILE*)>;
+ UniqueFilePtr outputStream;
+ FILE* output{nullptr};
+ bool dumpingFrame{false};
+ bool firstBuffer{true};
+ bool firstFrame{true};
+ int frameCount{0};
+
+ const int NTH_FRAME{10}; // dump first N "frames"
+
+ // Constructor
+ GraphicsFrameDump();
+
+ void Start();
+ void End();
+ void DumpCommandBuffer(const GLES::CommandBuffer* cmdBuf);
+ bool IsDumpFrame();
+};
+
+#if defined(DEBUG_ENABLED) && defined(ENABLE_COMMAND_BUFFER_FRAME_DUMP)
+#define DUMP_FRAME_INIT() std::unique_ptr<Dali::Graphics::GraphicsFrameDump> gGraphicsFrameDump(new Dali::Graphics::GraphicsFrameDump)
+#define DUMP_FRAME_START() \
+ if(gGraphicsFrameDump) \
+ { \
+ gGraphicsFrameDump->Start(); \
+ }
+#define DUMP_FRAME_COMMAND_BUFFER(cmdBuffer) \
+ if(gGraphicsFrameDump) \
+ { \
+ gGraphicsFrameDump->DumpCommandBuffer(cmdBuffer); \
+ }
+#define DUMP_FRAME_END() \
+ if(gGraphicsFrameDump) \
+ { \
+ gGraphicsFrameDump->End(); \
+ }
+#else
+#define DUMP_FRAME_INIT()
+#define DUMP_FRAME_START()
+#define DUMP_FRAME_COMMAND_BUFFER(cmdBuffer)
+#define DUMP_FRAME_END()
+#endif
+
+} // namespace Dali::Graphics
+
+#endif //DALI_GRAPHICS_EGL_GRAPHICS_CONTROLLER_DEBUG_H
#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
// INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/gl-defines.h>
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/gles-impl/egl-sync-object.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-program.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-render-pass.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-render-target.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
+#include <dali/internal/graphics/gles-impl/gles-sync-object.h>
#include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
#include <dali/public-api/common/dali-common.h>
-#include "gles-graphics-program.h"
+
+// Uncomment the following define to turn on frame dumping
+//#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
+DUMP_FRAME_INIT();
namespace Dali::Graphics
{
void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
{
DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #1\n");
- mGlAbstraction = &glAbstraction;
- mContext = std::make_unique<GLES::Context>(*this);
+ mGlAbstraction = &glAbstraction;
+ mContext = std::make_unique<GLES::Context>(*this);
+ mCurrentContext = mContext.get();
}
-void EglGraphicsController::Initialize(Integration::GlSyncAbstraction& glSyncAbstraction,
- Integration::GlContextHelperAbstraction& glContextHelperAbstraction)
+void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction& syncImplementation,
+ Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
+ Internal::Adaptor::GraphicsInterface& graphicsInterface)
{
DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #2\n");
- mGlSyncAbstraction = &glSyncAbstraction;
+ auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
+
+ mEglSyncImplementation = syncImplPtr;
mGlContextHelperAbstraction = &glContextHelperAbstraction;
+ mGraphics = &graphicsInterface;
}
void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
}
}
-Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
+void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
{
- DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
- return *mGlAbstraction;
+ // Use command buffer to execute presentation (we should pool it)
+ CommandBufferCreateInfo info;
+ info.SetLevel(CommandBufferLevel::PRIMARY);
+ info.fixedCapacity = 1; // only one command
+ auto presentCommandBuffer = new GLES::CommandBuffer(info, *this);
+ presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
+ SubmitInfo submitInfo;
+ submitInfo.cmdBuffer = {presentCommandBuffer};
+ submitInfo.flags = 0 | SubmitFlagBits::FLUSH;
+ SubmitCommandBuffers(submitInfo);
+}
+
+void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget)
+{
+ auto* rt = static_cast<GLES::RenderTarget*>(renderTarget);
+ if(rt->GetCreateInfo().surface)
+ {
+ auto* surfaceInterface = reinterpret_cast<Dali::RenderSurfaceInterface*>(rt->GetCreateInfo().surface);
+ surfaceInterface->MakeContextCurrent();
+ surfaceInterface->PostRender();
+ }
}
-Integration::GlSyncAbstraction& EglGraphicsController::GetGlSyncAbstraction()
+Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
{
- DALI_ASSERT_DEBUG(mGlSyncAbstraction && "Graphics controller not initialized");
- return *mGlSyncAbstraction;
+ DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
+ return *mGlAbstraction;
}
Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
return *mGlContextHelperAbstraction;
}
-Graphics::UniquePtr<CommandBuffer>
-EglGraphicsController::CreateCommandBuffer(const CommandBufferCreateInfo& commandBufferCreateInfo,
- Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
+Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
+{
+ DALI_ASSERT_DEBUG(mEglSyncImplementation && "Sync implementation not initialized");
+ return *mEglSyncImplementation;
+}
+
+Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
+ const CommandBufferCreateInfo& commandBufferCreateInfo,
+ Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
{
return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
}
+Graphics::UniquePtr<RenderPass> EglGraphicsController::CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass)
+{
+ return NewObject<GLES::RenderPass>(renderPassCreateInfo, *this, std::move(oldRenderPass));
+}
+
Graphics::UniquePtr<Texture>
EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
{
return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
}
-Graphics::UniquePtr<Buffer>
-EglGraphicsController::CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
+Graphics::UniquePtr<Buffer> EglGraphicsController::CreateBuffer(
+ const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
{
return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
}
-Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
+Graphics::UniquePtr<Framebuffer> EglGraphicsController::CreateFramebuffer(
+ const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer)
+{
+ return NewObject<GLES::Framebuffer>(framebufferCreateInfo, *this, std::move(oldFramebuffer));
+}
+
+Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
+ const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
{
// Create pipeline cache if needed
if(!mPipelineCache)
return mPipelineCache->GetPipeline(pipelineCreateInfo, std::move(oldPipeline));
}
-Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
+Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
+ const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
{
// Create program cache if needed
if(!mPipelineCache)
return NewObject<GLES::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
}
+Graphics::UniquePtr<RenderTarget> EglGraphicsController::CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget)
+{
+ return NewObject<GLES::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
+}
+
+Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
+ UniquePtr<SyncObject>&& oldSyncObject)
+{
+ if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
+ {
+ return NewObject<EGL::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
+ }
+ else
+ {
+ return NewObject<GLES::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
+ }
+}
+
const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Graphics::Program& program)
{
return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
}
+void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
+ mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
+}
+
+void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ mSurfaceContexts.erase(std::remove_if(
+ mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
+ mSurfaceContexts.end());
+}
+
+void EglGraphicsController::ActivateResourceContext()
+{
+ mCurrentContext = mContext.get();
+}
+
+void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ if(surface && mGraphics->IsResourceContextSupported())
+ {
+ auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) {
+ return (iter.first == surface);
+ });
+
+ if(iter != mSurfaceContexts.end())
+ {
+ mCurrentContext = iter->second.get();
+ }
+ }
+}
+
void EglGraphicsController::AddTexture(GLES::Texture& texture)
{
// Assuming we are on the correct context
mCreateBufferQueue.push(&buffer);
}
+void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
+{
+ // Assuming we are on the correct context
+ mCreateFramebufferQueue.push(&framebuffer);
+}
+
void EglGraphicsController::ProcessDiscardQueues()
{
// Process textures
// Process buffers
ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
+ // Process Framebuffers
+ ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
+
// Process pipelines
ProcessDiscardQueue<GLES::Pipeline>(mDiscardPipelineQueue);
// Process buffers
ProcessCreateQueue(mCreateBufferQueue);
+
+ // Process framebuffers
+ ProcessCreateQueue(mCreateFramebufferQueue);
}
-void EglGraphicsController::ProcessCommandQueues()
+void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
{
- // TODO: command queue per context, sync between queues should be
- // done externally
-
- while(!mCommandQueue.empty())
+ for(auto& cmd : commandBuffer.GetCommands())
{
- auto cmdBuf = mCommandQueue.front();
- mCommandQueue.pop();
-
- for(auto& cmd : cmdBuf->GetCommands())
+ // process command
+ switch(cmd.type)
{
- // process command
- switch(cmd.type)
+ case GLES::CommandType::FLUSH:
{
- case GLES::CommandType::FLUSH:
- {
- // Nothing to do here
- break;
- }
- case GLES::CommandType::BIND_TEXTURES:
- {
- mContext->BindTextures(cmd.bindTextures.textureBindings);
- break;
- }
- case GLES::CommandType::BIND_VERTEX_BUFFERS:
- {
- auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
- mContext->BindVertexBuffers(bindings);
- break;
- }
- case GLES::CommandType::BIND_UNIFORM_BUFFER:
- {
- auto& bindings = cmd.bindUniformBuffers;
- mContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
- break;
- }
- case GLES::CommandType::BIND_INDEX_BUFFER:
- {
- mContext->BindIndexBuffer(cmd.bindIndexBuffer);
- break;
- }
- case GLES::CommandType::BIND_SAMPLERS:
- {
- break;
- }
- case GLES::CommandType::BIND_PIPELINE:
- {
- mContext->BindPipeline(cmd.bindPipeline.pipeline);
- break;
- }
- case GLES::CommandType::DRAW:
+ // Nothing to do here
+ break;
+ }
+ case GLES::CommandType::BIND_TEXTURES:
+ {
+ mCurrentContext->BindTextures(cmd.bindTextures.textureBindings);
+ break;
+ }
+ case GLES::CommandType::BIND_VERTEX_BUFFERS:
+ {
+ auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
+ mCurrentContext->BindVertexBuffers(bindings);
+ break;
+ }
+ case GLES::CommandType::BIND_UNIFORM_BUFFER:
+ {
+ auto& bindings = cmd.bindUniformBuffers;
+ mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
+ break;
+ }
+ case GLES::CommandType::BIND_INDEX_BUFFER:
+ {
+ mCurrentContext->BindIndexBuffer(cmd.bindIndexBuffer);
+ break;
+ }
+ case GLES::CommandType::BIND_SAMPLERS:
+ {
+ break;
+ }
+ case GLES::CommandType::BIND_PIPELINE:
+ {
+ auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
+ mCurrentContext->BindPipeline(pipeline);
+ break;
+ }
+ case GLES::CommandType::DRAW:
+ {
+ mCurrentContext->Flush(false, cmd.draw);
+ break;
+ }
+ case GLES::CommandType::DRAW_INDEXED:
+ {
+ mCurrentContext->Flush(false, cmd.draw);
+ break;
+ }
+ case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+ {
+ mCurrentContext->Flush(false, cmd.draw);
+ break;
+ }
+ case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
+ {
+ mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
+ break;
+ }
+ case GLES::CommandType::SET_SCISSOR_TEST:
+ {
+ if(cmd.scissorTest.enable)
{
- mContext->Flush(false, cmd.draw);
- break;
+ mGlAbstraction->Enable(GL_SCISSOR_TEST);
}
- case GLES::CommandType::DRAW_INDEXED:
+ else
{
- mContext->Flush(false, cmd.draw);
- break;
+ mGlAbstraction->Disable(GL_SCISSOR_TEST);
}
- case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+ break;
+ }
+ case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+ {
+ mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
+ break;
+ }
+
+ case GLES::CommandType::SET_COLOR_MASK:
+ {
+ mCurrentContext->ColorMask(cmd.colorMask.enabled);
+ break;
+ }
+ case GLES::CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ mCurrentContext->ClearStencilBuffer();
+ break;
+ }
+ case GLES::CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ mCurrentContext->ClearDepthBuffer();
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ mCurrentContext->SetStencilTestEnable(cmd.stencilTest.enabled);
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_FUNC:
+ {
+ mCurrentContext->StencilFunc(cmd.stencilFunc.compareOp,
+ cmd.stencilFunc.reference,
+ cmd.stencilFunc.compareMask);
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_WRITE_MASK:
+ {
+ mCurrentContext->StencilMask(cmd.stencilWriteMask.mask);
+ break;
+ }
+
+ case GLES::CommandType::SET_STENCIL_OP:
+ {
+ mCurrentContext->StencilOp(cmd.stencilOp.failOp,
+ cmd.stencilOp.depthFailOp,
+ cmd.stencilOp.passOp);
+ break;
+ }
+
+ case GLES::CommandType::SET_DEPTH_COMPARE_OP:
+ {
+ mCurrentContext->SetDepthCompareOp(cmd.depth.compareOp);
+ break;
+ }
+ case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ mCurrentContext->SetDepthTestEnable(cmd.depth.testEnabled);
+ break;
+ }
+ case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
+ {
+ mCurrentContext->SetDepthWriteEnable(cmd.depth.writeEnabled);
+ break;
+ }
+
+ case GLES::CommandType::BEGIN_RENDERPASS:
+ {
+ auto& renderTarget = *cmd.beginRenderPass.renderTarget;
+ const auto& targetInfo = renderTarget.GetCreateInfo();
+
+ if(targetInfo.surface)
{
- mContext->Flush(false, cmd.draw);
- break;
+ // switch to surface context
+ mGraphics->ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
}
- case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
+ else if(targetInfo.framebuffer)
{
- mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
- break;
+ // switch to resource context
+ mGraphics->ActivateResourceContext();
}
- case GLES::CommandType::SET_SCISSOR_TEST:
+
+ mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
+ break;
+ }
+ case GLES::CommandType::END_RENDERPASS:
+ {
+ mCurrentContext->EndRenderPass();
+
+ auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
+ if(syncObject)
{
- if(cmd.scissorTest.enable)
- {
- mGlAbstraction->Enable(GL_SCISSOR_TEST);
- }
- else
- {
- mGlAbstraction->Disable(GL_SCISSOR_TEST);
- }
- break;
+ syncObject->InitializeResource();
}
- case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+ break;
+ }
+ case GLES::CommandType::PRESENT_RENDER_TARGET:
+ {
+ ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
+
+ // push this command buffer to the discard queue
+ mDiscardCommandBufferQueue.push(const_cast<GLES::CommandBuffer*>(&commandBuffer));
+ break;
+ }
+ case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
+ {
+ // Process secondary command buffers
+ // todo: check validity of the secondaries
+ // there are operations which are illigal to be done
+ // within secondaries.
+ for(auto& buf : cmd.executeCommandBuffers.buffers)
{
- mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
- break;
+ ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
}
+ break;
}
}
}
}
+void EglGraphicsController::ProcessCommandQueues()
+{
+ // TODO: command queue per context, sync between queues should be
+ // done externally
+ currentFramebuffer = nullptr;
+
+ DUMP_FRAME_START();
+
+ while(!mCommandQueue.empty())
+ {
+ auto cmdBuf = mCommandQueue.front();
+ mCommandQueue.pop();
+ DUMP_FRAME_COMMAND_BUFFER(cmdBuf);
+ ProcessCommandBuffer(*cmdBuf);
+ }
+
+ DUMP_FRAME_END();
+}
+
void EglGraphicsController::ProcessTextureUpdateQueue()
{
while(!mTextureUpdateRequests.empty())
if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
{
- // GPU memory must be already allocated (glTexImage2D())
- auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
- const auto& createInfo = texture->GetCreateInfo();
+ // GPU memory must be already allocated.
+
+ // Check if it needs conversion
+ auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
+ const auto& createInfo = texture->GetCreateInfo();
+ auto srcFormat = GLES::GLTextureFormatType(info.srcFormat).format;
+ auto srcType = GLES::GLTextureFormatType(info.srcFormat).type;
+ auto destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
+ auto destFormat = GLES::GLTextureFormatType(createInfo.format).format;
+
+ // From render-texture.cpp
+ const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
+ info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
+ info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
+
+ auto* sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
+ std::vector<uint8_t> tempBuffer;
+ if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
+ {
+ // Convert RGB to RGBA if necessary.
+ texture->TryConvertPixelData(source.memorySource.memory, info.srcFormat, createInfo.format, info.srcSize, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer);
+ sourceBuffer = &tempBuffer[0];
+ srcFormat = destFormat;
+ srcType = GLES::GLTextureFormatType(createInfo.format).type;
+ }
- mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ // Calculate the maximum mipmap level for the texture
+ texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
- mGlAbstraction->BindTexture(GL_TEXTURE_2D, texture->GetGLTexture());
- mGlAbstraction->TexSubImage2D(GL_TEXTURE_2D,
- info.level,
- info.dstOffset2D.x,
- info.dstOffset2D.y,
- info.srcExtent2D.width,
- info.srcExtent2D.height,
- GLES::GLTextureFormatType(createInfo.format).format,
- GLES::GLTextureFormatType(createInfo.format).type,
- source.memorySource.memory);
+ GLenum bindTarget{GL_TEXTURE_2D};
+ GLenum target{GL_TEXTURE_2D};
+ if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
+ {
+ bindTarget = GL_TEXTURE_CUBE_MAP;
+ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
+ }
+
+ mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ mGlAbstraction->BindTexture(bindTarget, texture->GetGLTexture());
+
+ if(!isSubImage)
+ {
+ if(!texture->IsCompressed())
+ {
+ mGlAbstraction->TexImage2D(target,
+ info.level,
+ destInternalFormat,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ 0,
+ srcFormat,
+ srcType,
+ sourceBuffer);
+ }
+ else
+ {
+ mGlAbstraction->CompressedTexImage2D(target,
+ info.level,
+ destInternalFormat,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ 0,
+ info.srcSize,
+ sourceBuffer);
+ }
+ }
+ else
+ {
+ if(!texture->IsCompressed())
+ {
+ mGlAbstraction->TexSubImage2D(target,
+ info.level,
+ info.dstOffset2D.x,
+ info.dstOffset2D.y,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ srcFormat,
+ srcType,
+ sourceBuffer);
+ }
+ else
+ {
+ mGlAbstraction->CompressedTexSubImage2D(target,
+ info.level,
+ info.dstOffset2D.x,
+ info.dstOffset2D.y,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ srcFormat,
+ info.srcSize,
+ sourceBuffer);
+ }
+ }
// free staging memory
free(source.memorySource.memory);
}
}
// If upload buffer exceeds maximum size, flush.
- if( mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB*1024 )
+ if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024)
{
Flush();
mTextureUploadTotalCPUMemoryUsed = 0;
}
}
+void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
+{
+ while(!mTextureMipmapGenerationRequests.empty())
+ {
+ auto* texture = mTextureMipmapGenerationRequests.front();
+
+ mGlAbstraction->BindTexture(texture->GetGlTarget(), texture->GetGLTexture());
+ mGlAbstraction->GenerateMipmap(texture->GetGlTarget());
+
+ mTextureMipmapGenerationRequests.pop();
+ }
+}
+
+void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
+{
+ mTextureMipmapGenerationRequests.push(static_cast<const GLES::Texture*>(&texture));
+}
+
Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
{
+ mGraphics->ActivateResourceContext();
+
// Mapping buffer requires the object to be created NOW
// Workaround - flush now, otherwise there will be given a staging buffer
// in case when the buffer is not there yet
#include <queue>
// INTERNAL INCLUDES
-#include "gles-context.h"
-#include "gles-graphics-buffer.h"
-#include "gles-graphics-command-buffer.h"
-#include "gles-graphics-pipeline-cache.h"
-#include "gles-graphics-pipeline.h"
-#include "gles-graphics-reflection.h"
-#include "gles-graphics-sampler.h"
-#include "gles-graphics-shader.h"
-#include "gles-graphics-texture.h"
-#include "gles-graphics-types.h"
-#include "gles2-graphics-memory.h"
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/common/graphics-interface.h>
+#include <dali/internal/graphics/gles-impl/gles-context.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-buffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-framebuffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline-cache.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-reflection.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-sampler.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
+#include <dali/internal/graphics/gles-impl/gles2-graphics-memory.h>
namespace Dali
{
namespace Integration
{
class GlAbstraction;
-class GlSyncAbstraction;
class GlContextHelperAbstraction;
} // namespace Integration
*
* Note, this is now executed in the render thread, after core initialization
*/
- void Initialize(Integration::GlSyncAbstraction& glSyncAbstraction,
- Integration::GlContextHelperAbstraction& glContextHelperAbstraction);
+ void Initialize(Integration::GraphicsSyncAbstraction& syncImplementation,
+ Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
+ Internal::Adaptor::GraphicsInterface& graphicsInterface);
- Integration::GlAbstraction& GetGlAbstraction() override;
- Integration::GlSyncAbstraction& GetGlSyncAbstraction() override;
- Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override;
+ Integration::GlAbstraction& GetGlAbstraction() override;
+ Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override;
+ Internal::Adaptor::EglSyncImplementation& GetEglSyncImplementation();
/**
* @copydoc Dali::Graphics::SubmitCommandBuffers()
/**
* @copydoc Dali::Graphics::PresentRenderTarget()
*/
- void PresentRenderTarget(RenderTarget* renderTarget) override
- {
- }
+ void PresentRenderTarget(RenderTarget* renderTarget) override;
/**
* @copydoc Dali::Graphics::WaitIdle()
const std::vector<TextureUpdateSourceInfo>& sourceList) override;
/**
+ * @copydoc Dali::Graphics::GenerateTextureMipmaps()
+ */
+ void GenerateTextureMipmaps(const Texture& texture) override;
+
+ /**
* @copydoc Dali::Graphics::EnableDepthStencilBuffer()
*/
bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override
/**
* @copydoc Dali::Graphics::CreateRenderPass()
*/
- Graphics::UniquePtr<RenderPass> CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass) override
- {
- return nullptr;
- }
+ Graphics::UniquePtr<RenderPass> CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass) override;
/**
* @copydoc Dali::Graphics::CreateTexture()
/**
* @copydoc Dali::Graphics::CreateFramebuffer()
*/
- Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override
- {
- return nullptr;
- }
+ Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override;
/**
* @copydoc Dali::Graphics::CreatePipeline()
/**
* @copydoc Dali::Graphics::CreateRenderTarget()
*/
- Graphics::UniquePtr<RenderTarget> CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget) override
- {
- return nullptr;
- }
+ Graphics::UniquePtr<RenderTarget> CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget) override;
+
+ /**
+ * @copydoc Dali::Graphics::CreateSyncObject()
+ */
+ Graphics::UniquePtr<SyncObject> CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
+ Graphics::UniquePtr<SyncObject>&& oldSyncObject) override;
/**
* @copydoc Dali::Graphics::MapBufferRange()
return mGlAbstraction;
}
+ [[nodiscard]] Internal::Adaptor::GraphicsInterface* GetGraphicsInterface() const
+ {
+ return mGraphics;
+ }
+
// Internal
void AddTexture(GLES::Texture& texture);
void AddBuffer(GLES::Buffer& buffer);
/**
+ * @brief Adds framebuffer to the creation queue
+ * @param buffer
+ */
+ void AddFramebuffer(GLES::Framebuffer& framebuffer);
+
+ /**
* @brief Pushes Bufer to the discard queue
*
* Function is called from the UniquePtr custom deleter.
*
* Function is called from the UniquePtr custom deleter.
*
- * @param[in] texture Pointer to the texture
+ * @param[in] buffer Pointer to the buffer object
*/
void DiscardResource(GLES::Buffer* buffer)
{
}
/**
+ * @brief Pushes framebuffer to the discard queue
+ *
+ * Function is called from the UniquePtr custom deleter.
+ *
+ * @param[in] framebuffer Pointer to the framebuffer object
+ */
+ void DiscardResource(GLES::Framebuffer* framebuffer)
+ {
+ mDiscardFramebufferQueue.push(framebuffer);
+ }
+
+ /**
* @brief Pushes Program to the discard queue
*
* Function is called from the UniquePtr custom deleter.
*/
void Flush()
{
+ mGraphics->ActivateResourceContext();
+
// Process creations
ProcessCreateQueues();
// Process updates
ProcessTextureUpdateQueue();
+ // Process texture mipmap generation requests
+ ProcessTextureMipmapGenerationQueue();
+
// Process main command queue
ProcessCommandQueues();
{
while(!queue.empty())
{
- auto* object = queue.front();
+ auto* object = const_cast<U*>(queue.front());
// Destroy
object->DestroyResource();
void ProcessTextureUpdateQueue();
/**
+ * @brief Executes all pending texture mipmap generation
+ */
+ void ProcessTextureMipmapGenerationQueue();
+
+ /**
* @brief Returns program custom parameter
*
* This function can be used as a backdoor in order to retrieve
*/
GLES::GLESVersion GetGLESVersion() const
{
- // TODO: return proper version but for now we can
- // test fallbacks
- return GLES::GLESVersion::GLES_20;
+ return mGLESVersion;
+ }
+
+ /**
+ * @brief Sets runtime supported GLES version
+ *
+ * @param[in] glesVersion The runtime supported GLES version
+ */
+ void SetGLESVersion(GLES::GLESVersion glesVersion)
+ {
+ mGLESVersion = glesVersion;
}
bool IsShuttingDown() const
return mIsShuttingDown;
}
+ void ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer);
+
+ // Resolves presentation
+ void ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget);
+
+ /**
+ * Creates a GLES context for the given render surface
+ *
+ * @param[in] surface The surface whose GLES context to be created.
+ */
+ void CreateSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
+ /**
+ * Deletes a GLES context
+ *
+ * @param[in] surface The surface whose GLES context to be deleted.
+ */
+ void DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
+ /**
+ * Activate the resource context (shared surfaceless context)
+ */
+ void ActivateResourceContext();
+
+ /**
+ * Activate the surface context
+ *
+ * @param[in] surface The surface whose context to be switched to.
+ */
+ void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
private:
Integration::GlAbstraction* mGlAbstraction{nullptr};
- Integration::GlSyncAbstraction* mGlSyncAbstraction{nullptr};
Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr};
+ Internal::Adaptor::EglSyncImplementation* mEglSyncImplementation;
+ Internal::Adaptor::GraphicsInterface* mGraphics{nullptr}; // Pointer to owning structure via interface.
+
std::queue<GLES::Texture*> mCreateTextureQueue; ///< Create queue for texture resource
std::queue<GLES::Texture*> mDiscardTextureQueue; ///< Discard queue for texture resource
std::queue<GLES::Buffer*> mCreateBufferQueue; ///< Create queue for buffer resource
std::queue<GLES::Buffer*> mDiscardBufferQueue; ///< Discard queue for buffer resource
- std::queue<GLES::Program*> mDiscardProgramQueue; ///< Discard queue for program resource
- std::queue<GLES::Pipeline*> mDiscardPipelineQueue; ///< Discard queue of pipelines
- std::queue<GLES::Shader*> mDiscardShaderQueue; ///< Discard queue of shaders
- std::queue<GLES::Sampler*> mDiscardSamplerQueue; ///< Discard queue of samplers
- std::queue<GLES::CommandBuffer*> mDiscardCommandBufferQueue; ///< Discard queue of command buffers
+ std::queue<GLES::Program*> mDiscardProgramQueue; ///< Discard queue for program resource
+ std::queue<GLES::Pipeline*> mDiscardPipelineQueue; ///< Discard queue of pipelines
+ std::queue<GLES::Shader*> mDiscardShaderQueue; ///< Discard queue of shaders
+ std::queue<GLES::Sampler*> mDiscardSamplerQueue; ///< Discard queue of samplers
+ std::queue<const GLES::CommandBuffer*> mDiscardCommandBufferQueue; ///< Discard queue of command buffers
+ std::queue<GLES::Framebuffer*> mCreateFramebufferQueue; ///< Create queue for framebuffer resource
+ std::queue<GLES::Framebuffer*> mDiscardFramebufferQueue; ///< Discard queue for framebuffer resource
std::queue<GLES::CommandBuffer*> mCommandQueue; ///< we may have more in the future
using TextureUpdateRequest = std::pair<TextureUpdateInfo, TextureUpdateSourceInfo>;
std::queue<TextureUpdateRequest> mTextureUpdateRequests;
- std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
+ std::queue<const GLES::Texture*> mTextureMipmapGenerationRequests; ///< Queue for texture mipmap generation requests
+
+ GLES::Context* mCurrentContext{nullptr}; ///< The current context
+ std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
+ using SurfaceContextPair = std::pair<Dali::RenderSurfaceInterface*, std::unique_ptr<GLES::Context>>;
+ std::vector<SurfaceContextPair> mSurfaceContexts; ///< Vector of surface context objects handling command buffers execution
std::unique_ptr<GLES::PipelineCache> mPipelineCache{nullptr}; ///< Internal pipeline cache
- uint32_t mTextureUploadTotalCPUMemoryUsed {0u};
+ GLES::GLESVersion mGLESVersion{GLES::GLESVersion::GLES_20}; ///< Runtime supported GLES version
+ uint32_t mTextureUploadTotalCPUMemoryUsed{0u};
bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down
+
+ // todo: to be removed after renderpass
+ const Graphics::Framebuffer* currentFramebuffer{nullptr};
};
} // namespace Graphics
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles-impl/egl-sync-object.h>
+
+// EXTERNAL HEADERS
+
+// INTERNAL HEADERS
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+namespace Dali::Graphics::EGL
+{
+SyncObject::SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: SyncObjectResource(createInfo, controller),
+ mEglSyncImplementation(controller.GetEglSyncImplementation()),
+ mEglSyncObject(nullptr)
+{
+}
+
+SyncObject::~SyncObject()
+{
+}
+
+void SyncObject::DestroyResource()
+{
+}
+
+bool SyncObject::InitializeResource()
+{
+ // Initialized not from a resource queue, but from a command.
+ mEglSyncObject = static_cast<Internal::Adaptor::EglSyncObject*>(mEglSyncImplementation.CreateSyncObject());
+ return true;
+}
+
+void SyncObject::DiscardResource()
+{
+ // Called from custom deleter.
+ // Don't use discard queue, drop immediately.
+ mEglSyncImplementation.DestroySyncObject(mEglSyncObject);
+ mEglSyncObject = nullptr;
+}
+
+bool SyncObject::IsSynced()
+{
+ if(mEglSyncObject)
+ {
+ return mEglSyncObject->IsSynced();
+ }
+ return false;
+}
+
+} // namespace Dali::Graphics::EGL
--- /dev/null
+#ifndef DALI_GRAPHICS_EGL_SYNC_OBJECT_H
+#define DALI_GRAPHICS_EGL_SYNC_OBJECT_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles-impl/gles-graphics-resource.h>
+
+namespace Dali::Internal::Adaptor
+{
+class EglSyncImplementation;
+class EglSyncObject;
+} // namespace Dali::Internal::Adaptor
+
+namespace Dali::Graphics::EGL
+{
+using SyncObjectResource = GLES::Resource<Graphics::SyncObject, Graphics::SyncObjectCreateInfo>;
+
+class SyncObject : public SyncObjectResource
+{
+public:
+ /**
+ * @brief Constructor
+ * @param[in] createInfo Valid createInfo structure
+ * @param[in] controller Reference to the controller
+ */
+ SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
+
+ /**
+ * @brief Destructor
+ */
+ ~SyncObject() override;
+
+ /**
+ * @brief Called when GL resources are destroyed
+ */
+ void DestroyResource() override;
+
+ /**
+ * @brief Called when initializing the resource
+ *
+ * @return True on success
+ */
+ bool InitializeResource() override;
+
+ /**
+ * @brief Called when UniquePtr<> on client-side dies
+ */
+ void DiscardResource() override;
+
+ /**
+ * Determine if the synchronisation object has been signalled.
+ *
+ * @return false if the sync object has not been signalled, true if it has been signalled (and
+ * can now be destroyed)
+ */
+ bool IsSynced() override;
+
+private:
+ Internal::Adaptor::EglSyncImplementation& mEglSyncImplementation;
+ Internal::Adaptor::EglSyncObject* mEglSyncObject;
+};
+
+} // namespace Dali::Graphics::EGL
+
+#endif //DALI_GRAPHICS_EGL_SYNC_OBJECT_H
# module: graphics, backend: gles-impl
SET( adaptor_graphics_gles_src_files ${adaptor_graphics_gles_src_files}
${adaptor_graphics_dir}/gles-impl/egl-graphics-controller.cpp
+ ${adaptor_graphics_dir}/gles-impl/egl-graphics-controller-debug.cpp
+ ${adaptor_graphics_dir}/gles-impl/egl-sync-object.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-buffer.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-command-buffer.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-debug.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-texture.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-pipeline-cache.cpp
${adaptor_graphics_dir}/gles-impl/gles-context.cpp
+ ${adaptor_graphics_dir}/gles-impl/gles-sync-object.cpp
)
-
*/
#include "gles-context.h"
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/graphics/common/graphics-interface.h>
+
#include "egl-graphics-controller.h"
#include "gles-graphics-buffer.h"
#include "gles-graphics-pipeline.h"
#include "gles-graphics-program.h"
+#include "gles-graphics-render-pass.h"
+#include "gles-graphics-render-target.h"
namespace Dali::Graphics::GLES
{
// Currently bound UBOs (check if it's needed per program!)
std::vector<UniformBufferBindingDescriptor> mCurrentUBOBindings{};
UniformBufferBindingDescriptor mCurrentStandaloneUBOBinding{};
+
+ // Current render pass and render target
+ const GLES::RenderTarget* mCurrentRenderTarget{nullptr};
+ const GLES::RenderPass* mCurrentRenderPass{nullptr};
};
Context::Context(EglGraphicsController& controller)
ResolveUniformBuffers();
// Bind textures
+ // Map binding# to sampler location
+ const auto program = static_cast<const GLES::Program*>(mImpl->mCurrentPipeline->GetCreateInfo().programState->program);
+
+ const auto& reflection = program->GetReflection();
+ const auto& samplers = reflection.GetSamplers();
for(const auto& binding : mImpl->mCurrentTextureBindings)
{
auto texture = const_cast<GLES::Texture*>(static_cast<const GLES::Texture*>(binding.texture));
texture->Bind(binding);
texture->Prepare(); // @todo also non-const.
+
+ if(binding.binding < samplers.size()) // binding maps to texture unit. (texture bindings should also be in binding order)
+ {
+ // Offset is set to the lexical offset within the frag shader, map it to the texture unit
+ // @todo Explicitly set the texture unit through the graphics interface
+ gl.Uniform1i(samplers[binding.binding].location, samplers[binding.binding].offset);
+ }
}
// for each attribute bind vertices
auto extraInfos = reflection.GetStandaloneUniformExtraInfo();
- const auto ptr = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress());
+ const auto ptr = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress()) + mImpl->mCurrentStandaloneUBOBinding.offset;
for(const auto& info : extraInfos)
{
}
}
+void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
+{
+ auto& renderPass = *renderPassBegin.renderPass;
+ auto& renderTarget = *renderPassBegin.renderTarget;
+
+ const auto& targetInfo = renderTarget.GetCreateInfo();
+
+ auto& gl = *mImpl->mController.GetGL();
+
+ if(targetInfo.surface)
+ {
+ // Bind surface FB
+ gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+ else if(targetInfo.framebuffer)
+ {
+ // bind framebuffer and swap.
+ renderTarget.GetFramebuffer()->Bind();
+ }
+
+ // clear (ideally cache the setup)
+
+ // In GL we assume that the last attachment is depth/stencil (we may need
+ // to cache extra information inside GLES RenderTarget if we want to be
+ // more specific in case of MRT)
+
+ const auto& attachments = *renderPass.GetCreateInfo().attachments;
+ const auto& color0 = attachments[0];
+ GLuint mask = 0;
+ if(color0.loadOp == AttachmentLoadOp::CLEAR)
+ {
+ mask |= GL_COLOR_BUFFER_BIT;
+
+ // Set clear color (todo: cache it!)
+ // Something goes wrong here if Alpha mask is GL_TRUE
+ gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ gl.ClearColor(renderPassBegin.clearValues[0].color.r,
+ renderPassBegin.clearValues[0].color.g,
+ renderPassBegin.clearValues[0].color.b,
+ renderPassBegin.clearValues[0].color.a);
+ }
+
+ // check for depth stencil
+ if(attachments.size() > 1)
+ {
+ const auto& depthStencil = attachments.back();
+ if(depthStencil.loadOp == AttachmentLoadOp::CLEAR)
+ {
+ gl.DepthMask(true);
+ mask |= GL_DEPTH_BUFFER_BIT;
+ }
+ if(depthStencil.stencilLoadOp == AttachmentLoadOp::CLEAR)
+ {
+ gl.StencilMask(0xFF);
+ mask |= GL_STENCIL_BUFFER_BIT;
+ }
+ }
+
+ gl.Enable(GL_SCISSOR_TEST);
+ gl.Scissor(renderPassBegin.renderArea.x, renderPassBegin.renderArea.y, renderPassBegin.renderArea.width, renderPassBegin.renderArea.height);
+ gl.Clear(mask);
+ gl.Disable(GL_SCISSOR_TEST);
+
+ mImpl->mCurrentRenderPass = &renderPass;
+ mImpl->mCurrentRenderTarget = &renderTarget;
+}
+
+void Context::EndRenderPass()
+{
+ if(mImpl->mCurrentRenderTarget)
+ {
+ if(mImpl->mCurrentRenderTarget->GetFramebuffer())
+ {
+ auto& gl = *mImpl->mController.GetGL();
+ gl.Flush();
+ }
+ }
+}
+
void Context::ClearState()
{
mImpl->mCurrentTextureBindings.clear();
}
+void Context::ColorMask(bool enabled)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.ColorMask(enabled, enabled, enabled, enabled);
+}
+
+void Context::ClearStencilBuffer()
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.Clear(GL_STENCIL_BUFFER_BIT);
+}
+
+void Context::ClearDepthBuffer()
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.Clear(GL_DEPTH_BUFFER_BIT);
+}
+
+void Context::SetStencilTestEnable(bool stencilEnable)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ if(stencilEnable)
+ {
+ gl.Enable(GL_STENCIL_TEST);
+ }
+ else
+ {
+ gl.Disable(GL_STENCIL_TEST);
+ }
+}
+
+void Context::StencilMask(uint32_t writeMask)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.StencilMask(writeMask);
+}
+
+void Context::StencilFunc(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.StencilFunc(GLCompareOp(compareOp).op, reference, compareMask);
+}
+
+void Context::StencilOp(Graphics::StencilOp failOp,
+ Graphics::StencilOp depthFailOp,
+ Graphics::StencilOp passOp)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.StencilOp(GLStencilOp(failOp).op, GLStencilOp(depthFailOp).op, GLStencilOp(passOp).op);
+}
+
+void Context::SetDepthCompareOp(Graphics::CompareOp compareOp)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.DepthFunc(GLCompareOp(compareOp).op);
+}
+
+void Context::SetDepthTestEnable(bool depthTestEnable)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ if(depthTestEnable)
+ {
+ gl.Enable(GL_DEPTH_TEST);
+ }
+ else
+ {
+ gl.Disable(GL_DEPTH_TEST);
+ }
+}
+
+void Context::SetDepthWriteEnable(bool depthWriteEnable)
+{
+ auto& gl = *mImpl->mController.GetGL();
+ gl.DepthMask(depthWriteEnable);
+}
+
} // namespace Dali::Graphics::GLES
namespace GLES
{
class Pipeline;
-class Texture;
-
+class RenderPass;
+class RenderTarget;
/**
* @brief Context represents single GLES context
*/
*/
void ResolveStandaloneUniforms();
+ /**
+ * @brief Begins render pass for sepcified render target
+ *
+ * @param[in] renderPass render pass object to begin
+ * @param[in] renderTarget render target to be drawn onto
+ */
+ void BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin);
+
+ /**
+ * @brief Ends render pass
+ *
+ * Ending render pass is necessary in order to ensure
+ * proper implicit synchronization is in place
+ */
+ void EndRenderPass();
+
+ void ColorMask(bool enabled);
+ void ClearStencilBuffer();
+ void ClearDepthBuffer();
+ void SetStencilTestEnable(bool stencilEnable);
+ void StencilMask(uint32_t writeMask);
+ void StencilFunc(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask);
+ void StencilOp(Graphics::StencilOp failOp,
+ Graphics::StencilOp depthFailOp,
+ Graphics::StencilOp passOp);
+ void SetDepthCompareOp(Graphics::CompareOp compareOp);
+ void SetDepthTestEnable(bool depthTestEnable);
+ void SetDepthWriteEnable(bool depthWriteEnable);
+
private:
/**
* @brief Clear current state
// INTERNAL INCLUDES
#include "egl-graphics-controller.h"
#include "gles-graphics-buffer.h"
+#include "gles-graphics-framebuffer.h"
#include "gles-graphics-pipeline.h"
+#include "gles-graphics-render-pass.h"
+#include "gles-graphics-render-target.h"
#include "gles-graphics-texture.h"
namespace Dali::Graphics::GLES
}
void CommandBuffer::BeginRenderPass(
- Graphics::RenderPass& renderPass,
- Graphics::RenderTarget& renderTarget,
- Extent2D renderArea,
+ Graphics::RenderPass* renderPass,
+ Graphics::RenderTarget* renderTarget,
+ Rect2D renderArea,
std::vector<ClearValue> clearValues)
{
+ mCommands.emplace_back(CommandType::BEGIN_RENDERPASS);
+ auto& cmd = mCommands.back();
+ cmd.beginRenderPass.renderPass = static_cast<GLES::RenderPass*>(renderPass);
+ cmd.beginRenderPass.renderTarget = static_cast<GLES::RenderTarget*>(renderTarget);
+ cmd.beginRenderPass.renderArea = renderArea;
+ cmd.beginRenderPass.clearValues = clearValues;
}
-/**
- * @brief Ends current render pass
- *
- * This command must be issued in order to finalize the render pass.
- * It's up to the implementation whether anything has to be done but
- * the Controller may use end RP marker in order to resolve resource
- * dependencies (for example, to know when target texture is ready
- * before passing it to another render pass).
- */
-void CommandBuffer::EndRenderPass()
+void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject)
+{
+ mCommands.emplace_back(CommandType::END_RENDERPASS);
+ auto& cmd = mCommands.back();
+
+ cmd.endRenderPass.syncObject = static_cast<GLES::SyncObject*>(syncObject);
+}
+
+void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers)
{
+ mCommands.emplace_back(CommandType::EXECUTE_COMMAND_BUFFERS);
+ auto& cmd = mCommands.back();
+ cmd.executeCommandBuffers.buffers.reserve(commandBuffers.size());
+ for(auto&& item : commandBuffers)
+ {
+ cmd.executeCommandBuffers.buffers.emplace_back(static_cast<const GLES::CommandBuffer*>(item));
+ }
}
void CommandBuffer::Draw(
// There is no GL equivalent
}
+void CommandBuffer::SetColorMask(bool enabled)
+{
+ mCommands.emplace_back(CommandType::SET_COLOR_MASK);
+ auto& cmd = mCommands.back().colorMask;
+ ;
+ cmd.enabled = enabled;
+}
+
+void CommandBuffer::ClearStencilBuffer()
+{
+ mCommands.emplace_back(CommandType::CLEAR_STENCIL_BUFFER);
+}
+
+void CommandBuffer::SetStencilTestEnable(bool stencilEnable)
+{
+ mCommands.emplace_back(CommandType::SET_STENCIL_TEST_ENABLE);
+ mCommands.back().stencilTest.enabled = stencilEnable;
+}
+
+void CommandBuffer::SetStencilWriteMask(uint32_t writeMask)
+{
+ mCommands.emplace_back(CommandType::SET_STENCIL_WRITE_MASK);
+ mCommands.back().stencilWriteMask.mask = writeMask;
+}
+
+void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp)
+{
+ mCommands.emplace_back(CommandType::SET_STENCIL_OP);
+ auto& cmd = mCommands.back().stencilOp;
+ cmd.failOp = failOp;
+ cmd.passOp = passOp;
+ cmd.depthFailOp = depthFailOp;
+}
+
+void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask)
+{
+ mCommands.emplace_back(CommandType::SET_STENCIL_FUNC);
+ auto& cmd = mCommands.back().stencilFunc;
+ cmd.compareOp = compareOp;
+ cmd.compareMask = compareMask;
+ cmd.reference = reference;
+}
+
+void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp)
+{
+ mCommands.emplace_back(CommandType::SET_DEPTH_COMPARE_OP);
+ mCommands.back().depth.compareOp = compareOp;
+}
+
+void CommandBuffer::SetDepthTestEnable(bool depthTestEnable)
+{
+ mCommands.emplace_back(CommandType::SET_DEPTH_TEST_ENABLE);
+ mCommands.back().depth.testEnabled = depthTestEnable;
+}
+void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable)
+{
+ mCommands.emplace_back(CommandType::SET_DEPTH_WRITE_ENABLE);
+ mCommands.back().depth.writeEnabled = depthWriteEnable;
+}
+void CommandBuffer::ClearDepthBuffer()
+{
+ mCommands.emplace_back(CommandType::CLEAR_DEPTH_BUFFER);
+}
+
+void CommandBuffer::PresentRenderTarget(GLES::RenderTarget* renderTarget)
+{
+ mCommands.emplace_back(CommandType::PRESENT_RENDER_TARGET);
+ mCommands.back().presentRenderTarget.targetToPresent = renderTarget;
+}
+
[[nodiscard]] const std::vector<Command>& CommandBuffer::GetCommands() const
{
return mCommands;
GetController().DiscardResource(this);
}
-} // namespace Dali::Graphics::GLES
\ No newline at end of file
+} // namespace Dali::Graphics::GLES
// INTERNAL INCLUDES
#include "gles-graphics-resource.h"
#include "gles-graphics-types.h"
+#include "gles-sync-object.h"
namespace Dali::Graphics::GLES
{
-class Texture;
class Pipeline;
-
+class RenderPass;
+class Framebuffer;
+class CommandBuffer;
enum class CommandType
{
FLUSH,
DRAW_INDEXED_INDIRECT,
SET_SCISSOR,
SET_SCISSOR_TEST,
- SET_VIEWPORT
+ SET_VIEWPORT,
+ BEGIN_RENDERPASS,
+ END_RENDERPASS,
+ EXECUTE_COMMAND_BUFFERS,
+ PRESENT_RENDER_TARGET,
+ SET_COLOR_MASK,
+ CLEAR_STENCIL_BUFFER,
+ CLEAR_DEPTH_BUFFER,
+ SET_STENCIL_TEST_ENABLE,
+ SET_STENCIL_WRITE_MASK,
+ SET_STENCIL_OP,
+ SET_STENCIL_FUNC,
+ SET_DEPTH_COMPARE_OP,
+ SET_DEPTH_TEST_ENABLE,
+ SET_DEPTH_WRITE_ENABLE,
};
/**
new(&bindTextures) decltype(bindTextures);
break;
}
+ case CommandType::BEGIN_RENDERPASS:
+ {
+ // run destructor
+ new(&beginRenderPass) decltype(beginRenderPass);
+ break;
+ }
default:
{
}
InvokeDestructor(bindTextures);
break;
}
+ case CommandType::BEGIN_RENDERPASS:
+ {
+ // run destructor
+ InvokeDestructor(beginRenderPass);
+ break;
+ }
default:
{
}
draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
break;
}
+ case CommandType::BEGIN_RENDERPASS:
+ {
+ new(&beginRenderPass) BeginRenderPassDescriptor(rhs.beginRenderPass);
+ break;
+ }
+ case CommandType::END_RENDERPASS:
+ {
+ endRenderPass.syncObject = rhs.endRenderPass.syncObject;
+ break;
+ }
+ case CommandType::EXECUTE_COMMAND_BUFFERS:
+ {
+ executeCommandBuffers = rhs.executeCommandBuffers;
+ break;
+ }
case CommandType::FLUSH:
{
// Nothing to do
viewport.region = rhs.viewport.region;
break;
}
+ case CommandType::PRESENT_RENDER_TARGET:
+ {
+ presentRenderTarget = rhs.presentRenderTarget;
+ break;
+ }
+ case CommandType::SET_COLOR_MASK:
+ {
+ colorMask.enabled = rhs.colorMask.enabled;
+ break;
+ }
+ case CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ break;
+ }
+ case CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ break;
+ }
+ case CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ stencilTest.enabled = rhs.stencilTest.enabled;
+ break;
+ }
+ case CommandType::SET_STENCIL_FUNC:
+ {
+ stencilFunc.compareMask = rhs.stencilFunc.compareMask;
+ stencilFunc.compareOp = rhs.stencilFunc.compareOp;
+ stencilFunc.reference = rhs.stencilFunc.reference;
+ break;
+ }
+ case CommandType::SET_STENCIL_WRITE_MASK:
+ {
+ stencilWriteMask.mask = rhs.stencilWriteMask.mask;
+ break;
+ }
+ case CommandType::SET_STENCIL_OP:
+ {
+ stencilOp.failOp = rhs.stencilOp.failOp;
+ stencilOp.depthFailOp = rhs.stencilOp.depthFailOp;
+ stencilOp.passOp = rhs.stencilOp.passOp;
+ break;
+ }
+
+ case CommandType::SET_DEPTH_COMPARE_OP:
+ {
+ depth.compareOp = rhs.depth.compareOp;
+ break;
+ }
+ case CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ depth.testEnabled = rhs.depth.testEnabled;
+ break;
+ }
+ case CommandType::SET_DEPTH_WRITE_ENABLE:
+ {
+ depth.writeEnabled = rhs.depth.writeEnabled;
+ break;
+ }
}
type = rhs.type;
}
/**
- * @brief Copy constructor
+ * @brief Move constructor
* @param[in] rhs Command
*/
Command(Command&& rhs) noexcept
draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
break;
}
+ case CommandType::BEGIN_RENDERPASS:
+ {
+ new(&beginRenderPass) BeginRenderPassDescriptor(std::move(rhs.beginRenderPass));
+ break;
+ }
+ case CommandType::END_RENDERPASS:
+ {
+ endRenderPass.syncObject = rhs.endRenderPass.syncObject;
+ break;
+ }
+ case CommandType::EXECUTE_COMMAND_BUFFERS:
+ {
+ executeCommandBuffers = std::move(rhs.executeCommandBuffers);
+ break;
+ }
case CommandType::FLUSH:
{
// Nothing to do
viewport.region = rhs.viewport.region;
break;
}
+ case CommandType::PRESENT_RENDER_TARGET:
+ {
+ presentRenderTarget = rhs.presentRenderTarget;
+ break;
+ }
+ case CommandType::SET_COLOR_MASK:
+ {
+ colorMask.enabled = rhs.colorMask.enabled;
+ break;
+ }
+ case CommandType::CLEAR_STENCIL_BUFFER:
+ {
+ break;
+ }
+ case CommandType::CLEAR_DEPTH_BUFFER:
+ {
+ break;
+ }
+ case CommandType::SET_STENCIL_TEST_ENABLE:
+ {
+ stencilTest.enabled = rhs.stencilTest.enabled;
+ break;
+ }
+ case CommandType::SET_STENCIL_FUNC:
+ {
+ stencilFunc.compareMask = rhs.stencilFunc.compareMask;
+ stencilFunc.compareOp = rhs.stencilFunc.compareOp;
+ stencilFunc.reference = rhs.stencilFunc.reference;
+ break;
+ }
+ case CommandType::SET_STENCIL_WRITE_MASK:
+ {
+ stencilWriteMask.mask = rhs.stencilWriteMask.mask;
+ break;
+ }
+ case CommandType::SET_STENCIL_OP:
+ {
+ stencilOp.failOp = rhs.stencilOp.failOp;
+ stencilOp.depthFailOp = rhs.stencilOp.depthFailOp;
+ stencilOp.passOp = rhs.stencilOp.passOp;
+ break;
+ }
+
+ case CommandType::SET_DEPTH_COMPARE_OP:
+ {
+ depth.compareOp = rhs.depth.compareOp;
+ break;
+ }
+ case CommandType::SET_DEPTH_TEST_ENABLE:
+ {
+ depth.testEnabled = rhs.depth.testEnabled;
+ break;
+ }
+ case CommandType::SET_DEPTH_WRITE_ENABLE:
+ {
+ depth.writeEnabled = rhs.depth.writeEnabled;
+ break;
+ }
}
type = rhs.type;
}
{
Graphics::Viewport region;
} viewport;
+
+ struct BeginRenderPassDescriptor
+ beginRenderPass;
+
+ struct
+ {
+ Graphics::SyncObject* syncObject;
+ } endRenderPass;
+
+ struct
+ {
+ std::vector<const GLES::CommandBuffer*> buffers;
+ } executeCommandBuffers;
+
+ struct
+ {
+ GLES::RenderTarget* targetToPresent;
+ } presentRenderTarget;
+
+ struct
+ {
+ Graphics::CompareOp compareOp;
+ bool testEnabled;
+ bool writeEnabled;
+ } depth;
+
+ struct
+ {
+ Graphics::StencilOp failOp;
+ Graphics::StencilOp passOp;
+ Graphics::StencilOp depthFailOp;
+ } stencilOp;
+
+ struct
+ {
+ uint32_t mask;
+ } stencilWriteMask;
+
+ struct
+ {
+ uint32_t compareMask;
+ Graphics::CompareOp compareOp;
+ uint32_t reference;
+ } stencilFunc;
+
+ struct
+ {
+ bool enabled;
+ } stencilTest;
+
+ struct
+ {
+ bool enabled;
+ } colorMask;
};
};
~CommandBuffer() override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindVertexBuffers
+ */
void BindVertexBuffers(uint32_t firstBinding,
std::vector<const Graphics::Buffer*> buffers,
std::vector<uint32_t> offsets) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindUniformBuffers
+ */
void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindPipeline
+ */
void BindPipeline(const Graphics::Pipeline& pipeline) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindTextures
+ */
void BindTextures(std::vector<TextureBinding>& textureBindings) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindSamplers
+ */
void BindSamplers(std::vector<SamplerBinding>& samplerBindings) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindPushConstants
+ */
void BindPushConstants(void* data,
uint32_t size,
uint32_t binding) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BindIndexBuffer
+ */
void BindIndexBuffer(const Graphics::Buffer& buffer,
uint32_t offset,
Format format) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::BeginRenderPass
+ */
void BeginRenderPass(
- Graphics::RenderPass& renderPass,
- Graphics::RenderTarget& renderTarget,
- Extent2D renderArea,
+ Graphics::RenderPass* renderPass,
+ Graphics::RenderTarget* renderTarget,
+ Rect2D renderArea,
std::vector<ClearValue> clearValues) override;
/**
- * @brief Ends current render pass
- *
- * This command must be issued in order to finalize the render pass.
- * It's up to the implementation whether anything has to be done but
- * the Controller may use end RP marker in order to resolve resource
- * dependencies (for example, to know when target texture is ready
- * before passing it to another render pass).
+ * @copydoc Dali::Graphics::CommandBuffer::EndRenderPass
+ */
+ void EndRenderPass(Graphics::SyncObject* syncObject) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::ExecuteCommandBuffers
*/
- void EndRenderPass() override;
+ void ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::Draw
+ */
void Draw(
uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::DrawIndexed
+ */
void DrawIndexed(
uint32_t indexCount,
uint32_t instanceCount,
int32_t vertexOffset,
uint32_t firstInstance) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::DrawIndexedIndirect
+ */
void DrawIndexedIndirect(
Graphics::Buffer& buffer,
uint32_t offset,
uint32_t drawCount,
uint32_t stride) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::Reset
+ */
void Reset() override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetScissor
+ */
void SetScissor(Graphics::Rect2D value) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetScissorTestEnable
+ */
void SetScissorTestEnable(bool value) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetViewport
+ */
void SetViewport(Viewport value) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetViewportEnable
+ */
void SetViewportEnable(bool value) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetColorMask
+ */
+ void SetColorMask(bool enabled) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::ClearStencilBuffer
+ */
+ void ClearStencilBuffer() override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetStencilTestEnable
+ */
+ void SetStencilTestEnable(bool stencilEnable) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetStencilWriteMask
+ */
+ void SetStencilWriteMask(uint32_t writeMask) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetStencilOp
+ */
+ void SetStencilOp(Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetStencilFunc
+ */
+ void SetStencilFunc(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetDepthCompareOp
+ */
+ void SetDepthCompareOp(Graphics::CompareOp compareOp) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetDepthTestEnable
+ */
+ void SetDepthTestEnable(bool depthTestEnable) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::SetDepthWriteEnable
+ */
+ void SetDepthWriteEnable(bool depthWriteEnable) override;
+
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::ClearDepthBuffer
+ */
+ void ClearDepthBuffer() override;
+
+ /**
+ * @brief Presents specified render target
+ *
+ * @param[in] renderTarget Valid pointer to a RenderTarget
+ *
+ * It's internal command that schedules presentation of
+ * specified render target.
+ */
+ void PresentRenderTarget(GLES::RenderTarget* renderTarget);
+
[[nodiscard]] const std::vector<Command>& GetCommands() const;
+ /**
+ * @brief Destroy the associated resources
+ */
void DestroyResource() override;
+
+ /**
+ * @brief Initialize associated resources
+ */
bool InitializeResource() override;
+ /**
+ * @brief Add this resource to the discard queue
+ */
void DiscardResource() override;
private:
- std::vector<Command> mCommands;
+ std::vector<Command> mCommands; ///< List of commands in this command buffer
};
} // namespace Dali::Graphics::GLES
// CLASS HEADER
#include "gles-graphics-framebuffer.h"
+
+// external headers
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+
+// Internal headers
+#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
+#include "egl-graphics-controller.h"
+
+namespace Dali::Graphics::GLES
+{
+namespace
+{
+const GLenum COLOR_ATTACHMENTS[] =
+ {
+ GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3,
+ GL_COLOR_ATTACHMENT4,
+ GL_COLOR_ATTACHMENT5,
+ GL_COLOR_ATTACHMENT6,
+ GL_COLOR_ATTACHMENT7,
+};
+
+struct DEPTH_STENCIL_ATTACHMENT_TYPE
+{
+ constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat)
+ {
+ switch(textureFormat)
+ {
+ case Graphics::Format::D16_UNORM:
+ case Graphics::Format::D32_SFLOAT:
+ case Graphics::Format::X8_D24_UNORM_PACK32:
+ {
+ attachment = GL_DEPTH_ATTACHMENT;
+ break;
+ }
+
+ case Graphics::Format::S8_UINT: // Probably won't work as a standalone texture.
+ {
+ attachment = GL_STENCIL_ATTACHMENT;
+ break;
+ }
+
+ case Graphics::Format::D16_UNORM_S8_UINT:
+ case Graphics::Format::D24_UNORM_S8_UINT:
+ case Graphics::Format::D32_SFLOAT_S8_UINT:
+ {
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ break;
+ }
+ default:
+ {
+ attachment = GL_NONE;
+ break;
+ }
+ }
+ }
+ Dali::GLenum attachment{GL_NONE};
+};
+
+} // anonymous namespace
+
+Framebuffer::Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: FramebufferResource(createInfo, controller)
+{
+ // Add framebuffer to the Resource queue
+ mController.AddFramebuffer(*this);
+}
+
+Framebuffer::~Framebuffer() = default;
+
+bool Framebuffer::InitializeResource()
+{
+ auto gl = mController.GetGL();
+ if(gl && !mInitialized)
+ {
+ mInitialized = true;
+
+ gl->GenFramebuffers(1, &mFramebufferId);
+ gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+
+ for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
+ {
+ AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId);
+ }
+
+ // @todo is this per framebuffer, or more immediate state that needs setting when framebuffer changed?
+ gl->DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
+
+ if(mCreateInfo.depthStencilAttachment.depthTexture)
+ {
+ // Create a depth or depth/stencil render target.
+ auto depthTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.depthTexture);
+ auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetCreateInfo().format).attachment;
+
+ gl->GenRenderbuffers(1, &mDepthBufferId);
+ gl->BindRenderbuffer(GL_RENDERBUFFER, mDepthBufferId);
+ gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height);
+ gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mDepthBufferId);
+
+ AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel);
+ }
+
+ if(mCreateInfo.depthStencilAttachment.stencilTexture)
+ {
+ auto stencilTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.stencilTexture);
+ auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetCreateInfo().format).attachment;
+
+ // Create a stencil render target.
+ gl->GenRenderbuffers(1, &mStencilBufferId);
+ gl->BindRenderbuffer(GL_RENDERBUFFER, mStencilBufferId);
+ gl->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height);
+ gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mStencilBufferId);
+
+ AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel);
+ }
+ gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ return mInitialized;
+}
+
+void Framebuffer::DestroyResource()
+{
+ auto gl = mController.GetGL();
+ if(gl && mInitialized)
+ {
+ if(mDepthBufferId)
+ {
+ gl->DeleteRenderbuffers(1, &mDepthBufferId);
+ }
+ if(mStencilBufferId)
+ {
+ gl->DeleteRenderbuffers(1, &mStencilBufferId);
+ }
+
+ gl->DeleteFramebuffers(1, &mFramebufferId);
+ mFramebufferId = 0u;
+ mInitialized = false;
+ }
+}
+
+void Framebuffer::DiscardResource()
+{
+ mController.DiscardResource(this);
+}
+
+void Framebuffer::Bind() const
+{
+ auto gl = mController.GetGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+}
+
+void Framebuffer::AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
+{
+ auto gl = mController.GetGL();
+ if(gl)
+ {
+ auto graphicsTexture = static_cast<const GLES::Texture*>(texture);
+ if(graphicsTexture->GetCreateInfo().textureType == Graphics::TextureType::TEXTURE_2D)
+ {
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetGlTarget(), graphicsTexture->GetGLTexture(), levelId);
+ }
+ else
+ {
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->GetGLTexture(), levelId);
+ }
+ }
+}
+
+uint32_t Framebuffer::GetGlFramebufferId() const
+{
+ return mFramebufferId;
+}
+
+uint32_t Framebuffer::GetGlDepthBufferId() const
+{
+ return mDepthBufferId;
+}
+
+uint32_t Framebuffer::GetGlStencilBufferId() const
+{
+ return mStencilBufferId;
+}
+
+} //namespace Dali::Graphics::GLES
* @param[in] createInfo Valid createInfo structure
* @param[in] controller Reference to the controller
*/
- Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
- : FramebufferResource(createInfo, controller)
- {
- }
+ Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
/**
* @brief Destructor
*/
- ~Framebuffer() override = default;
+ ~Framebuffer() override;
/**
* @brief Called when GL resources are destroyed
*/
- void DestroyResource() override
- {
- // TODO: Implement destroying the resource
- }
+ void DestroyResource() override;
/**
* @brief Called when initializing the resource
*
* @return True on success
*/
- bool InitializeResource() override
- {
- // TODO: Implement initializing resource
- return {};
- }
+ bool InitializeResource() override;
/**
* @brief Called when UniquePtr<> on client-side dies
*/
- void DiscardResource() override
- {
- // TODO: Implement moving to the discard queue
- }
+ void DiscardResource() override;
+
+ /**
+ * Used to bind the framebuffer, e.g. when offscreen changes
+ */
+ void Bind() const;
+
+ [[nodiscard]] uint32_t GetGlFramebufferId() const;
+
+ [[nodiscard]] uint32_t GetGlDepthBufferId() const;
+
+ [[nodiscard]] uint32_t GetGlStencilBufferId() const;
+
+private:
+ /**
+ * Attach a texture to the specified attachment point
+ * @param[in] texture The texture to bind
+ * @param[in] attachmentId The attachment point to bind it to
+ * @param[in] layerId The texture layer (e.g. for cubemap)
+ * @param[in] levelId The texture mipmap level
+ */
+ void AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId);
+
+private:
+ uint32_t mFramebufferId{0u};
+ uint32_t mDepthBufferId{0u};
+ uint32_t mStencilBufferId{0u};
+ bool mInitialized{false};
};
} // namespace Dali::Graphics::GLES
-#endif
\ No newline at end of file
+#endif
{
COLOR_BLEND_STATE_BIT = 0,
VIEWPORT_STATE_BIT = 1,
- FRAMEBUFFER_STATE_BIT = 2,
- BASE_PIPELINE_STATE_BIT = 3,
- DEPTH_STENCIL_STATE_BIT = 4,
- RASTERIZATION_STATE_BIT = 5,
- VERTEX_INPUT_STATE_BIT = 6,
- INPUT_ASSEMBLY_STATE_BIT = 7,
- MAX_STATE = 8
+ BASE_PIPELINE_STATE_BIT = 2,
+ DEPTH_STENCIL_STATE_BIT = 3,
+ RASTERIZATION_STATE_BIT = 4,
+ VERTEX_INPUT_STATE_BIT = 5,
+ INPUT_ASSEMBLY_STATE_BIT = 6,
+ MAX_STATE = 7
};
/**
lvp.scissor == rvp.scissor &&
lvp.scissorTestEnable == rvp.scissorTestEnable;
},
- [](const auto* lhs, const auto* rhs) -> bool // framebufferState
- {
- const auto& lfb = *lhs->framebufferState;
- const auto& rfb = *rhs->framebufferState;
- return lfb.framebuffer == rfb.framebuffer;
- },
[](const auto* lhs, const auto* rhs) -> bool // basePipeline
{
return lhs->basePipeline == rhs->basePipeline;
uint32_t mask{0u};
mask |= bool(info.colorBlendState) << int(StateLookupIndex::COLOR_BLEND_STATE_BIT);
mask |= bool(info.viewportState) << int(StateLookupIndex::VIEWPORT_STATE_BIT);
- mask |= bool(info.framebufferState) << int(StateLookupIndex::FRAMEBUFFER_STATE_BIT);
mask |= bool(info.basePipeline) << int(StateLookupIndex::BASE_PIPELINE_STATE_BIT);
mask |= bool(info.depthStencilState) << int(StateLookupIndex::DEPTH_STENCIL_STATE_BIT);
mask |= bool(info.rasterizationState) << int(StateLookupIndex::RASTERIZATION_STATE_BIT);
DepthStencilState depthStencilState;
ProgramState programState;
ViewportState viewportState;
- FramebufferState framebufferState;
RasterizationState rasterizationState;
VertexInputState vertexInputState;
InputAssemblyState inputAssemblyState;
CopyStateIfSet(createInfo.vertexInputState, mPipelineState->vertexInputState, &mCreateInfo.vertexInputState);
CopyStateIfSet(createInfo.rasterizationState, mPipelineState->rasterizationState, &mCreateInfo.rasterizationState);
CopyStateIfSet(createInfo.programState, mPipelineState->programState, &mCreateInfo.programState);
- CopyStateIfSet(createInfo.framebufferState, mPipelineState->framebufferState, &mCreateInfo.framebufferState);
CopyStateIfSet(createInfo.colorBlendState, mPipelineState->colorBlendState, &mCreateInfo.colorBlendState);
CopyStateIfSet(createInfo.depthStencilState, mPipelineState->depthStencilState, &mCreateInfo.depthStencilState);
CopyStateIfSet(createInfo.programState, mPipelineState->programState, &mCreateInfo.programState);
return a.location < b.location;
}
-} // namespace
+struct StringSize
+{
+ const char* const mString;
+ const uint32_t mLength;
+
+ template<uint32_t kLength>
+ constexpr StringSize(const char (&string)[kLength])
+ : mString(string),
+ mLength(kLength - 1) // remove terminating null; N.B. there should be no other null.
+ {
+ }
+
+ operator const char*() const
+ {
+ return mString;
+ }
+};
+
+bool operator==(const StringSize& lhs, const char* rhs)
+{
+ return strncmp(lhs.mString, rhs, lhs.mLength) == 0;
+}
+
+const char* const DELIMITERS = " \t\n";
+constexpr StringSize UNIFORM{"uniform"};
+constexpr StringSize SAMPLER_PREFIX{"sampler"};
+constexpr StringSize SAMPLER_TYPES[] = {"2D", "Cube", "ExternalOES"};
+constexpr auto END_SAMPLER_TYPES = SAMPLER_TYPES + std::extent<decltype(SAMPLER_TYPES)>::value;
+
+} // anonymous namespace
namespace Dali::Graphics::GLES
{
}
uniformInfo.uniformClass = IsSampler(type) ? Dali::Graphics::UniformClass::COMBINED_IMAGE_SAMPLER : Dali::Graphics::UniformClass::UNIFORM;
- uniformInfo.location = IsSampler(type) ? 0 : location;
- uniformInfo.binding = IsSampler(type) ? location : 0;
+ uniformInfo.location = location; //IsSampler(type) ? 0 : location;
+ uniformInfo.binding = 0; // IsSampler(type) ? location : 0;
uniformInfo.bufferIndex = 0;
+ uniformInfo.offset = 0;
if(IsSampler(type))
{
if(mUniformOpaques.size() > 1)
{
- std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), SortUniformInfoByLocation);
+ SortOpaques();
}
// Calculate the uniform offset
return true;
}
}
- index++;
+ ++index;
}
// check samplers
+ index = 0u;
for(auto&& uniform : mUniformOpaques)
{
if(uniform.name == name)
{
out.uniformClass = Graphics::UniformClass::COMBINED_IMAGE_SAMPLER;
- out.binding = uniform.binding;
+ out.binding = 0;
out.name = name;
- out.offset = 0;
- out.location = uniform.location;
+ out.offset = index; // lexical location in shader
+ out.location = uniform.location; // uniform location mapping
return true;
}
+ ++index;
}
return false;
return version;
}
+void Reflection::SortOpaques()
+{
+ //Determine declaration order of each sampler
+ auto& programCreateInfo = mProgram.GetCreateInfo();
+
+ std::vector<uint8_t> data;
+ std::string fragShader;
+
+ for(auto& shaderState : *programCreateInfo.shaderState)
+ {
+ if(shaderState.pipelineStage == PipelineStage::FRAGMENT_SHADER)
+ {
+ auto* shader = static_cast<const GLES::Shader*>(shaderState.shader);
+ auto& shaderCreateInfo = shader->GetCreateInfo();
+ data.resize(shaderCreateInfo.sourceSize + 1);
+ std::memcpy(&data[0], shaderCreateInfo.sourceData, shaderCreateInfo.sourceSize);
+ data[shaderCreateInfo.sourceSize] = 0;
+ fragShader = std::string(reinterpret_cast<char*>(&data[0]));
+ break;
+ }
+ }
+
+ if(!fragShader.empty())
+ {
+ char* shaderStr = strdup(fragShader.c_str());
+ char* uniform = strstr(shaderStr, UNIFORM);
+ int samplerPosition = 0;
+ std::vector<int> samplerPositions(mUniformOpaques.size(), -1);
+
+ while(uniform)
+ {
+ char* outerToken = strtok_r(uniform + UNIFORM.mLength, ";", &uniform);
+
+ char* nextPtr = nullptr;
+ char* token = strtok_r(outerToken, DELIMITERS, &nextPtr);
+ while(token)
+ {
+ if(SAMPLER_PREFIX == token)
+ {
+ token += SAMPLER_PREFIX.mLength;
+ if(std::find(SAMPLER_TYPES, END_SAMPLER_TYPES, token) != END_SAMPLER_TYPES)
+ {
+ bool found(false);
+ token = strtok_r(nullptr, DELIMITERS, &nextPtr);
+
+ for(uint32_t i = 0; i < static_cast<uint32_t>(mUniformOpaques.size()); ++i)
+ {
+ if(samplerPositions[i] == -1 &&
+ strncmp(token, mUniformOpaques[i].name.c_str(), mUniformOpaques[i].name.size()) == 0)
+ {
+ samplerPositions[i] = mUniformOpaques[i].offset = samplerPosition++;
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ DALI_LOG_ERROR("Sampler uniform %s declared but not used in the shader\n", token);
+ }
+ break;
+ }
+ }
+
+ token = strtok_r(nullptr, DELIMITERS, &nextPtr);
+ }
+
+ uniform = strstr(uniform, UNIFORM);
+ }
+ free(shaderStr);
+ }
+ std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), [](const UniformInfo& a, const UniformInfo& b) { return a.offset < b.offset; });
+}
+
} // namespace Dali::Graphics::GLES
arraySize(arraySize),
type(type){};
- uint32_t location; ///< Location of uniform
- uint32_t size; ///< size of uniform
- uint32_t offset; ///< offset of uniform within UBO
+ uint32_t location; ///< Location of uniform
+ uint32_t size; ///< size of uniform
+ uint32_t offset; ///< offset of uniform within UBO
uint32_t arraySize; ///< number of array elements (1 for non-arrays)
- GLenum type; ///< type of uniform
+ GLenum type; ///< type of uniform
};
/**
*/
void BuildUniformBlockReflection();
+ /**
+ * Sort the samplers by their lexical location in the frag shader source code.
+ */
+ void SortOpaques();
+
protected:
Reflection(Reflection&&) = default;
Reflection& operator=(Reflection&&) = default;
// CLASS HEADER
#include "gles-graphics-render-pass.h"
+
+namespace Dali::Graphics::GLES
+{
+struct RenderPass::Impl
+{
+ Impl() = default;
+ ~Impl() = default;
+
+ std::vector<AttachmentDescription> attachments;
+};
+
+RenderPass::RenderPass(const Graphics::RenderPassCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: RenderPassResource(createInfo, controller)
+{
+ mImpl = std::make_unique<Impl>();
+
+ // copy attachment description
+ if(createInfo.attachments)
+ {
+ mImpl->attachments.insert(mImpl->attachments.end(), createInfo.attachments->begin(), createInfo.attachments->end());
+ mCreateInfo.attachments = &mImpl->attachments;
+ }
+}
+
+} // namespace Dali::Graphics::GLES
* @param[in] createInfo Valid createInfo structure
* @param[in] controller Reference to the controller
*/
- RenderPass(const Graphics::RenderPassCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
- : RenderPassResource(createInfo, controller)
- {
- }
+ RenderPass(const Graphics::RenderPassCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
/**
* @brief Destructor
{
// TODO: Implement moving to the discard queue
}
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> mImpl{nullptr};
};
} // namespace Dali::Graphics::GLES
// CLASS HEADER
#include "gles-graphics-render-target.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+#include "egl-graphics-controller.h"
+#include "gles-graphics-framebuffer.h"
+
+namespace Dali::Graphics::GLES
+{
+struct RenderTarget::Impl
+{
+ Impl(EglGraphicsController& controller)
+ : controller(controller){};
+
+ ~Impl() = default;
+
+ EglGraphicsController& controller;
+};
+
+RenderTarget::RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: RenderTargetResource(createInfo, controller)
+{
+ mImpl = std::make_unique<Impl>(controller);
+
+ if(createInfo.surface)
+ {
+ controller.CreateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(createInfo.surface));
+ }
+}
+
+RenderTarget::~RenderTarget()
+{
+ if(mCreateInfo.surface)
+ {
+ mImpl->controller.DeleteSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(mCreateInfo.surface));
+ }
+}
+
+GLES::Framebuffer* RenderTarget::GetFramebuffer() const
+{
+ return static_cast<GLES::Framebuffer*>(mCreateInfo.framebuffer);
+}
+
+Surface* RenderTarget::GetSurface() const
+{
+ return mCreateInfo.surface;
+}
+
+} // namespace Dali::Graphics::GLES
\ No newline at end of file
namespace Dali::Graphics::GLES
{
+class Framebuffer;
using RenderTargetResource = Resource<Graphics::RenderTarget, Graphics::RenderTargetCreateInfo>;
class RenderTarget : public RenderTargetResource
* @param[in] createInfo Valid createInfo structure
* @param[in] controller Reference to the controller
*/
- RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
- : RenderTargetResource(createInfo, controller)
- {
- }
+ RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
/**
* @brief Destructor
*/
- ~RenderTarget() override = default;
+ ~RenderTarget() override;
/**
* @brief Called when GL resources are destroyed
{
// TODO: Implement moving to the discard queue
}
+
+ /**
+ * @brief Returns framebuffer associated with the render target
+ */
+ GLES::Framebuffer* GetFramebuffer() const;
+
+ /**
+ * @brief Returns surface associated with the render target
+ */
+ Surface* GetSurface() const;
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> mImpl{nullptr};
};
} // namespace Dali::Graphics::GLES
namespace Dali::Graphics::GLES
{
+struct ColorConversion
+{
+ Format srcFormat;
+ Format destFormat;
+ std::vector<uint8_t> (*pConversionFunc)(const void*, uint32_t, uint32_t, uint32_t, uint32_t);
+ void (*pConversionWriteFunc)(const void*, uint32_t, uint32_t, uint32_t, uint32_t, void*);
+};
+
+inline void WriteRGB32ToRGBA32(const void* pData, uint32_t sizeInBytes, uint32_t width, uint32_t height, uint32_t rowStride, void* pOutput)
+{
+ auto inData = reinterpret_cast<const uint8_t*>(pData);
+ auto outData = reinterpret_cast<uint8_t*>(pOutput);
+ auto outIdx = 0u;
+ for(auto i = 0u; i < sizeInBytes; i += 3)
+ {
+ outData[outIdx] = inData[i];
+ outData[outIdx + 1] = inData[i + 1];
+ outData[outIdx + 2] = inData[i + 2];
+ outData[outIdx + 3] = 0xff;
+ outIdx += 4;
+ }
+}
+
+/**
+ * Converts RGB to RGBA
+ */
+inline std::vector<uint8_t> ConvertRGB32ToRGBA32(const void* pData, uint32_t sizeInBytes, uint32_t width, uint32_t height, uint32_t rowStride)
+{
+ std::vector<uint8_t> rgbaBuffer{};
+ rgbaBuffer.resize(width * height * 4);
+ WriteRGB32ToRGBA32(pData, sizeInBytes, width, height, rowStride, &rgbaBuffer[0]);
+ return rgbaBuffer;
+}
+
+/**
+ * Format conversion table
+ */
+static const std::vector<ColorConversion> COLOR_CONVERSION_TABLE = {
+ {Format::R8G8B8_UNORM, Format::R8G8B8A8_UNORM, ConvertRGB32ToRGBA32, WriteRGB32ToRGBA32}};
+
+/**
+ * Constructor
+ */
Texture::Texture(const Graphics::TextureCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
: TextureResource(createInfo, controller)
{
GLuint texture{0};
- mGlTarget = GLTextureTarget(mCreateInfo.textureType).target;
+ mGlTarget = GLTextureTarget(mCreateInfo.textureType).target;
+ mIsCompressed = Graphics::GLES::FormatCompression(mCreateInfo.format).compressed;
switch(mCreateInfo.textureType)
{
gl->BindTexture(GL_TEXTURE_2D, texture);
// Allocate memory for the texture
- gl->TexImage2D(GL_TEXTURE_2D,
- 0,
- format.format,
- mCreateInfo.size.width,
- mCreateInfo.size.height,
- 0,
- format.format,
- format.type,
- (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+ if(!mIsCompressed)
+ {
+ gl->TexImage2D(GL_TEXTURE_2D,
+ 0,
+ format.internalFormat,
+ mCreateInfo.size.width,
+ mCreateInfo.size.height,
+ 0,
+ format.format,
+ format.type,
+ (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+ }
+ else
+ {
+ gl->CompressedTexImage2D(GL_TEXTURE_2D,
+ 0,
+ format.internalFormat,
+ mCreateInfo.size.width,
+ mCreateInfo.size.height,
+ 0,
+ mCreateInfo.dataSize,
+ (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+ }
// Clear staging buffer if there was any
mStagingBuffer.clear();
-
mTextureId = texture;
// Default texture filtering (to be set later via command buffer binding)
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+ }
+ break;
+ }
+ // Texture Cubemap
+ case Graphics::TextureType::TEXTURE_CUBEMAP:
+ {
+ Graphics::GLES::GLTextureFormatType format(mCreateInfo.format);
+
+ if(format.format && format.type)
+ {
+ // Bind texture
+ gl->GenTextures(1, &texture);
+ gl->BindTexture(GL_TEXTURE_CUBE_MAP, texture);
+ gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
+
+ gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+ gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+ gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
+ gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+
+ // Allocate memory for the texture
+ for(uint32_t i = 0; i < 6; ++i)
+ {
+ if(!mIsCompressed)
+ {
+ gl->TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+ 0,
+ format.internalFormat,
+ mCreateInfo.size.width,
+ mCreateInfo.size.height,
+ 0,
+ format.format,
+ format.type,
+ (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+ }
+ else
+ {
+ gl->CompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+ 0,
+ format.internalFormat,
+ mCreateInfo.size.width,
+ mCreateInfo.size.height,
+ 0,
+ mCreateInfo.dataSize,
+ (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+ }
+ }
+
+ // Clear staging buffer if there was any
+ mStagingBuffer.clear();
+
+ mTextureId = texture;
+
+ gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT);
}
break;
}
const auto& samplerCreateInfo = sampler->GetCreateInfo();
auto mipMapMode = samplerCreateInfo.mipMapMode;
- mipMapMode = Graphics::SamplerMipmapMode::NONE; // @todo Remove when mip-map generation is supported
gl->TexParameteri(mGlTarget, GL_TEXTURE_MIN_FILTER, GLSamplerFilterAndMipMapMode(samplerCreateInfo.minFilter, mipMapMode).glFilter);
gl->TexParameteri(mGlTarget, GL_TEXTURE_MAG_FILTER, GLSamplerFilter(samplerCreateInfo.magFilter).glFilter);
gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT);
}
}
+
+ if(mMaxMipMapLevel)
+ {
+ gl->TexParameteri(mGlTarget, GL_TEXTURE_MAX_LEVEL, mMaxMipMapLevel);
+ }
}
void Texture::Prepare()
}
}
+/**
+ * This function tests whether format is supported by the driver. If possible it applies
+ * format conversion to suitable supported pixel format.
+ */
+bool Texture::TryConvertPixelData(const void* pData, Graphics::Format srcFormat, Graphics::Format destFormat, uint32_t sizeInBytes, uint32_t width, uint32_t height, std::vector<uint8_t>& outputBuffer)
+{
+ // No need to convert
+ if(srcFormat == destFormat)
+ {
+ return false;
+ }
+
+ auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item) {
+ return item.srcFormat == srcFormat && item.destFormat == destFormat;
+ });
+
+ // No suitable format, return empty array
+ if(it == COLOR_CONVERSION_TABLE.end())
+ {
+ return false;
+ }
+ auto begin = reinterpret_cast<const uint8_t*>(pData);
+
+ outputBuffer = std::move(it->pConversionFunc(begin, sizeInBytes, width, height, 0u));
+ return !outputBuffer.empty();
+}
+
} // namespace Dali::Graphics::GLES
*/
void Prepare();
-protected:
+ /**
+ * @brief Returns the GL Target
+ * @return the Gl target
+ */
+ [[nodiscard]] GLenum GetGlTarget() const
+ {
+ return mGlTarget;
+ }
+
+ /**
+ * @brief Sets the maximum mipmap level
+ * @param[in] maxMipMapLevel The maximum mipmap level
+ */
+ void SetMaxMipMapLevel(const uint32_t maxMipMapLevel)
+ {
+ mMaxMipMapLevel = maxMipMapLevel;
+ }
+
+ /**
+ * @brief Returns the maximum mipmap level
+ * @return The maximum mipmap level
+ */
+ [[nodiscard]] uint32_t GetMaxMipMapLevel() const
+ {
+ return mMaxMipMapLevel;
+ }
+
+ /**
+ * @param pData Input data
+ * @param sizeInBytes Size of the input data in bytes
+ * @param width Width of the output buffer
+ * @param height height of the output buffer
+ * @param outputBuffer The buffer to write to
+ * @return true if converted, or false otherwise
+ */
+ bool TryConvertPixelData(const void* pData, Graphics::Format srcFormat, Graphics::Format destFormat, uint32_t sizeInBytes, uint32_t width, uint32_t height, std::vector<uint8_t>& outputBuffer);
+
+ bool InitializeNativeImage();
+
+ bool InitializeTexture();
+
+ Format ValidateFormat(Format sourceFormat);
+
+ bool IsCompressed()
+ {
+ return mIsCompressed;
+ }
+
private:
std::vector<char> mStagingBuffer;
uint32_t mTextureId{0u};
GLenum mGlTarget{0u};
+ uint32_t mMaxMipMapLevel{0u};
void* mGLOwnerContext{nullptr};
- bool InitializeNativeImage();
- bool InitializeTexture();
+ bool mIsCompressed{false};
};
+
} // namespace Dali::Graphics::GLES
#endif
namespace Dali::Graphics::GLES
{
class Buffer;
+class RenderPass;
+class RenderTarget;
+class Framebuffer;
+
// Conversion functions
/**
* Stucture delivers format and type that can be used
case Graphics::Format::R16G16B16_SFLOAT:
{
// GLES 3.0 floating point formats.
- Assign(GL_RGB, GL_HALF_FLOAT);
+ AssignInternal(GL_RGB, GL_R11F_G11F_B10F, GL_HALF_FLOAT); // DALi uses compact internal format
break;
}
case Graphics::Format::R16G16B16A16_UNORM:
}
case Graphics::Format::R32G32B32_SFLOAT:
{
- // GLES 3.0 floating point formats.
- Assign(GL_RGB, GL_FLOAT);
+ AssignInternal(GL_RGB, GL_R11F_G11F_B10F, GL_FLOAT); // DALi uses compact internal format
break;
}
case Graphics::Format::R32G32B32A32_UINT:
Assign(0, 0);
break;
}
+ case Graphics::Format::R11G11B10_UFLOAT_PACK32:
+ {
+ AssignInternal(GL_RGB, GL_R11F_G11F_B10F, GL_FLOAT);
+ break;
+ }
case Graphics::Format::B10G11R11_UFLOAT_PACK32:
{
Assign(0, 0);
case Graphics::Format::D32_SFLOAT:
{
// GLES 3.0 depth and stencil formats
- Assign(GL_DEPTH_COMPONENT, GL_FLOAT);
+ AssignInternal(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32F, GL_FLOAT);
break;
}
case Graphics::Format::S8_UINT:
case Graphics::Format::D24_UNORM_S8_UINT:
{
// GLES 3.0 depth and stencil formats
- Assign(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
+ AssignInternal(GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);
break;
}
case Graphics::Format::D32_SFLOAT_S8_UINT:
constexpr inline void Assign(uint32_t f, uint32_t t)
{
- format = f;
- type = t;
+ format = f;
+ internalFormat = f;
+ type = t;
+ }
+ constexpr inline void AssignInternal(uint32_t f, uint32_t i, uint32_t t)
+ {
+ format = f;
+ internalFormat = i;
+ type = t;
}
uint32_t format{0};
+ uint32_t internalFormat{0};
uint32_t type{0};
};
+struct FormatCompression
+{
+ /**
+ * Constuctor from Graphics::Format
+ * @param value
+ */
+ constexpr explicit FormatCompression(Graphics::Format value)
+ {
+ switch(value)
+ {
+ case Graphics::Format::ETC2_R8G8B8_UNORM_BLOCK:
+ case Graphics::Format::ETC2_R8G8B8_SRGB_BLOCK:
+ case Graphics::Format::ETC2_R8G8B8A1_UNORM_BLOCK:
+ case Graphics::Format::ETC2_R8G8B8A1_SRGB_BLOCK:
+ case Graphics::Format::ETC2_R8G8B8A8_UNORM_BLOCK:
+ case Graphics::Format::ETC2_R8G8B8A8_SRGB_BLOCK:
+ case Graphics::Format::EAC_R11_UNORM_BLOCK:
+ case Graphics::Format::EAC_R11_SNORM_BLOCK:
+ case Graphics::Format::EAC_R11G11_UNORM_BLOCK:
+ case Graphics::Format::EAC_R11G11_SNORM_BLOCK:
+ case Graphics::Format::ASTC_4x4_UNORM_BLOCK:
+ case Graphics::Format::ASTC_4x4_SRGB_BLOCK:
+ case Graphics::Format::ASTC_5x4_UNORM_BLOCK:
+ case Graphics::Format::ASTC_5x4_SRGB_BLOCK:
+ case Graphics::Format::ASTC_5x5_UNORM_BLOCK:
+ case Graphics::Format::ASTC_5x5_SRGB_BLOCK:
+ case Graphics::Format::ASTC_6x5_UNORM_BLOCK:
+ case Graphics::Format::ASTC_6x5_SRGB_BLOCK:
+ case Graphics::Format::ASTC_6x6_UNORM_BLOCK:
+ case Graphics::Format::ASTC_6x6_SRGB_BLOCK:
+ case Graphics::Format::ASTC_8x5_UNORM_BLOCK:
+ case Graphics::Format::ASTC_8x5_SRGB_BLOCK:
+ case Graphics::Format::ASTC_8x6_UNORM_BLOCK:
+ case Graphics::Format::ASTC_8x6_SRGB_BLOCK:
+ case Graphics::Format::ASTC_8x8_UNORM_BLOCK:
+ case Graphics::Format::ASTC_8x8_SRGB_BLOCK:
+ case Graphics::Format::ASTC_10x5_UNORM_BLOCK:
+ case Graphics::Format::ASTC_10x5_SRGB_BLOCK:
+ case Graphics::Format::ASTC_10x6_UNORM_BLOCK:
+ case Graphics::Format::ASTC_10x6_SRGB_BLOCK:
+ case Graphics::Format::ASTC_10x8_UNORM_BLOCK:
+ case Graphics::Format::ASTC_10x8_SRGB_BLOCK:
+ case Graphics::Format::ASTC_10x10_UNORM_BLOCK:
+ case Graphics::Format::ASTC_10x10_SRGB_BLOCK:
+ case Graphics::Format::ASTC_12x10_UNORM_BLOCK:
+ case Graphics::Format::ASTC_12x10_SRGB_BLOCK:
+ case Graphics::Format::ASTC_12x12_UNORM_BLOCK:
+ case Graphics::Format::ASTC_12x12_SRGB_BLOCK:
+ case Graphics::Format::PVRTC1_2BPP_UNORM_BLOCK_IMG:
+ case Graphics::Format::PVRTC1_4BPP_UNORM_BLOCK_IMG:
+ case Graphics::Format::PVRTC2_2BPP_UNORM_BLOCK_IMG:
+ case Graphics::Format::PVRTC2_4BPP_UNORM_BLOCK_IMG:
+ case Graphics::Format::PVRTC1_2BPP_SRGB_BLOCK_IMG:
+ case Graphics::Format::PVRTC1_4BPP_SRGB_BLOCK_IMG:
+ case Graphics::Format::PVRTC2_2BPP_SRGB_BLOCK_IMG:
+ case Graphics::Format::PVRTC2_4BPP_SRGB_BLOCK_IMG:
+ compressed = true;
+ break;
+ default:
+ break;
+ }
+ }
+ bool compressed{false};
+};
+
struct GLSamplerFilter
{
constexpr explicit GLSamplerFilter(Graphics::SamplerFilter filter)
GLenum texParameter{GL_CLAMP_TO_EDGE};
};
+struct GLCompareOp
+{
+ constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
+ {
+ switch(compareOp)
+ {
+ case Graphics::CompareOp::NEVER:
+ op = GL_NEVER;
+ break;
+ case Graphics::CompareOp::LESS:
+ op = GL_LESS;
+ break;
+ case Graphics::CompareOp::EQUAL:
+ op = GL_EQUAL;
+ break;
+ case Graphics::CompareOp::LESS_OR_EQUAL:
+ op = GL_LEQUAL;
+ break;
+ case Graphics::CompareOp::GREATER:
+ op = GL_GREATER;
+ break;
+ case Graphics::CompareOp::NOT_EQUAL:
+ op = GL_NOTEQUAL;
+ break;
+ case Graphics::CompareOp::GREATER_OR_EQUAL:
+ op = GL_GEQUAL;
+ break;
+ case Graphics::CompareOp::ALWAYS:
+ op = GL_ALWAYS;
+ break;
+ }
+ }
+ GLenum op{GL_LESS};
+};
+
+struct GLStencilOp
+{
+ constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
+ {
+ switch(stencilOp)
+ {
+ case Graphics::StencilOp::KEEP:
+ op = GL_KEEP;
+ break;
+ case Graphics::StencilOp::ZERO:
+ op = GL_ZERO;
+ break;
+ case Graphics::StencilOp::REPLACE:
+ op = GL_REPLACE;
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+ op = GL_INCR;
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+ op = GL_DECR;
+ break;
+ case Graphics::StencilOp::INVERT:
+ op = GL_INVERT;
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_WRAP:
+ op = GL_INCR_WRAP;
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_WRAP:
+ op = GL_DECR_WRAP;
+ break;
+ }
+ }
+ GLenum op{GL_KEEP};
+};
+
/**
* @brief Descriptor of single buffer binding within
* command buffer.
GLES_32 = 32
};
+/**
+ * The descriptor of BeginRenderPass command
+ */
+struct BeginRenderPassDescriptor
+{
+ const GLES::RenderPass* renderPass{};
+ const GLES::RenderTarget* renderTarget{};
+ Rect2D renderArea{};
+ std::vector<ClearValue> clearValues{};
+};
+
} // namespace Dali::Graphics::GLES
#endif //DALI_GRAPHICS_API_TYPES_H
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles-impl/gles-sync-object.h>
+
+// EXTERNAL HEADERS
+
+// INTERNAL HEADERS
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+
+namespace Dali::Graphics::GLES
+{
+SyncObject::SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: SyncObjectResource(createInfo, controller),
+ mGlSyncObject(0)
+{
+}
+
+SyncObject::~SyncObject()
+{
+}
+
+void SyncObject::DestroyResource()
+{
+}
+
+bool SyncObject::InitializeResource()
+{
+ // Initialized not from a resource queue, but from a command.
+ auto gl = mController.GetGL();
+ if(gl)
+ {
+ mGlSyncObject = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+ return true;
+}
+
+void SyncObject::DiscardResource()
+{
+ // Called from custom deleter.
+ // Don't use discard queue, drop immediately.
+ auto gl = mController.GetGL();
+ if(gl)
+ {
+ gl->DeleteSync(mGlSyncObject);
+ }
+ mGlSyncObject = 0;
+}
+
+bool SyncObject::IsSynced()
+{
+ auto gl = mController.GetGL();
+ if(gl && mGlSyncObject)
+ {
+ GLenum result = gl->ClientWaitSync(mGlSyncObject, 0, 0ull);
+ return result == GL_ALREADY_SIGNALED || result == GL_CONDITION_SATISFIED;
+ }
+ return false;
+}
+
+} // namespace Dali::Graphics::GLES
--- /dev/null
+#ifndef DALI_GRAPHICS_GLES_SYNC_OBJECT_H
+#define DALI_GRAPHICS_GLES_SYNC_OBJECT_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-resource.h>
+
+namespace Dali::Internal::Adaptor
+{
+class EglSyncImplementation;
+class EglSyncObject;
+} // namespace Dali::Internal::Adaptor
+
+namespace Dali::Graphics::GLES
+{
+using SyncObjectResource = Resource<Graphics::SyncObject, Graphics::SyncObjectCreateInfo>;
+
+class SyncObject : public SyncObjectResource
+{
+public:
+ /**
+ * @brief Constructor
+ * @param[in] createInfo Valid createInfo structure
+ * @param[in] controller Reference to the controller
+ */
+ SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
+
+ /**
+ * @brief Destructor
+ */
+ ~SyncObject() override;
+
+ /**
+ * @brief Called when GL resources are destroyed
+ */
+ void DestroyResource() override;
+
+ /**
+ * @brief Called when initializing the resource
+ *
+ * @return True on success
+ */
+ bool InitializeResource() override;
+
+ /**
+ * @brief Called when UniquePtr<> on client-side dies
+ */
+ void DiscardResource() override;
+
+ /**
+ * Determine if the synchronisation object has been signalled.
+ *
+ * @return false if the sync object has not been signalled, true if it has been signalled (and
+ * can now be destroyed)
+ */
+ bool IsSynced() override;
+
+private:
+ GLsync mGlSyncObject;
+};
+
+} // namespace Dali::Graphics::GLES
+
+#endif //DALI_GRAPHICS_GLES_SYNC_OBJECT_H
#include <dali/integration-api/gl-defines.h>
// INTERNAL INCLUDES
+#include <dali/internal/graphics/common/graphics-interface.h>
#include "egl-graphics-controller.h"
#include "gles-graphics-buffer.h"
Memory2::~Memory2()
{
- //Unlock(true);
+ Unlock(true);
}
void* Memory2::LockRegion(uint32_t offset, uint32_t size)
auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
if(buffer->IsCPUAllocated())
{
- using Ptr = char*;
- mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
+ using Ptr = char*;
+ mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
mIsAllocatedLocally = false;
}
else
{
- auto retval = malloc(size);
- mMappedPointer = retval;
+ auto retval = malloc(size);
+ mMappedPointer = retval;
mIsAllocatedLocally = true;
}
}
auto gl = mController.GetGL();
// for buffer...
- if(mMapObjectType == MapObjectType::BUFFER&& mMappedPointer)
+ if(mMapObjectType == MapObjectType::BUFFER && mMappedPointer)
{
auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
if(!buffer->IsCPUAllocated())
#include <dali/integration-api/gl-defines.h>
// INTERNAL INCLUDES
+#include <dali/internal/graphics/common/graphics-interface.h>
#include "egl-graphics-controller.h"
namespace Dali::Graphics::GLES
if(buffer->IsCPUAllocated())
{
- using Ptr = char*;
- return Ptr(buffer->GetCPUAllocatedAddress()) + offset;
+ using Ptr = char*;
+ mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
}
else
{
{
Flush();
}
+
+ mMappedPointer = nullptr;
}
void Memory3::Flush()
}
mGLES->SetGlesVersion(glesVersion);
+
+ mGraphicsController.SetGLESVersion(static_cast<Graphics::GLES::GLESVersion>(glesVersion));
}
void EglGraphics::SetIsSurfacelessContextSupported(const bool isSupported)
void EglGraphics::ActivateResourceContext()
{
+ mGraphicsController.ActivateResourceContext();
+
if(mEglImplementation && mEglImplementation->IsSurfacelessContextSupported())
{
// Make the shared surfaceless context as current before rendering
}
}
+void EglGraphics::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ mGraphicsController.ActivateSurfaceContext(surface);
+
+ if(surface)
+ {
+ surface->InitializeGraphics();
+ surface->MakeContextCurrent();
+ }
+}
+
void EglGraphics::SetFirstFrameAfterResume()
{
if(mEglImplementation)
EglInitialize();
// Sync and context helper require EGL to be initialized first (can't execute in the constructor)
- mGraphicsController.Initialize(*mEglSync.get(), *mEglContextHelper.get());
+ mGraphicsController.Initialize(*mEglSync.get(), *mEglContextHelper.get(), *this);
}
void EglGraphics::Initialize(bool depth, bool stencil, bool partialRendering, int msaa)
void ActivateResourceContext() override;
/**
+ * Activate the surface context
+ *
+ * @param[in] surface The surface whose context to be switched to.
+ */
+ void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface) override;
+
+ /**
* Inform graphics interface that this is the first frame after a resume.
* (For debug only)
*/
mEglImplementation = eglImpl;
}
-Integration::GlSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
{
DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
if(mSyncInitialized == false)
InitializeEglSync();
}
- EglSyncObject* syncObject = new EglSyncObject(*mEglImplementation);
+ auto* syncObject = new EglSyncObject(*mEglImplementation);
mSyncObjects.PushBack(syncObject);
return syncObject;
}
-void EglSyncImplementation::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
{
DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
break;
}
}
- EglSyncObject* eglSyncObject = static_cast<EglSyncObject*>(syncObject);
- delete eglSyncObject;
+ delete static_cast<EglSyncObject*>(syncObject);
}
void EglSyncImplementation::InitializeEglSync()
mEglImplementation = eglImpl;
}
-Integration::GlSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
{
DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
return new EglSyncObject(*mEglImplementation);
}
-void EglSyncImplementation::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
{
DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
-
- // The abstraction's virtual destructor is protected, so that Core can't delete the sync objects
- // directly (This object also needs removing from the mSyncObject container in the ARM
- // implementation above). We therefore need to cast to the actual implementation object first.
- EglSyncObject* eglSyncObject = static_cast<EglSyncObject*>(syncObject);
- delete eglSyncObject;
+ delete static_cast<EglSyncObject*>(syncObject);
}
void EglSyncImplementation::InitializeEglSync()
*/
// EXTERNAL INCLUDES
-#include <dali/integration-api/gl-sync-abstraction.h>
-#include <dali/internal/graphics/common/egl-include.h>
#include <dali/public-api/common/dali-vector.h>
// INTERNAL INCLUDES
#include <dali/public-api/dali-adaptor-common.h>
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/common/egl-include.h>
+
namespace Dali
{
namespace Internal
{
class EglImplementation;
-class EglSyncObject : public Integration::GlSyncAbstraction::SyncObject
+class EglSyncObject : public Integration::GraphicsSyncAbstraction::SyncObject
{
public:
/**
*/
virtual ~EglSyncObject();
- /**
- * @copydoc Dali::Integration::GlSyncAbstraction::SyncObject::IsSynced()
- */
bool IsSynced() override;
private:
};
/**
- * GlSyncImplementation is a concrete implementation for GlSyncAbstraction.
* It provides fence syncing for resources such as FrameBuffers using EGL extensions
*
* Sync objects are created in the render thread after a render instruction
* has been processed (i.e. GL draw calls have completed for a given FB), and
- * tested in the update
+ * tested in the update thread.
*/
-class EglSyncImplementation : public Integration::GlSyncAbstraction
+class EglSyncImplementation : public Integration::GraphicsSyncAbstraction
{
public:
/**
/**
* Destructor
*/
- virtual ~EglSyncImplementation();
+ ~EglSyncImplementation();
/**
* Initialize the sync object with the Egl implementation.
void Initialize(EglImplementation* impl);
/**
- * @copydoc Dali::Integration::GlSyncAbstraction::CreateSyncObject()
+ * Create a sync object that can be polled
*/
- SyncObject* CreateSyncObject() override;
+ Integration::GraphicsSyncAbstraction::SyncObject* CreateSyncObject() override;
/**
- * @copydoc Dali::Integration::GlSyncAbstraction::DestroySyncObject()
+ * Destroy a sync object
*/
- void DestroySyncObject(SyncObject* syncObject) override;
+ void DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject) override;
private:
/**
#include <dali/internal/imaging/common/loader-astc.h>
#include <dali/internal/imaging/common/loader-bmp.h>
#include <dali/internal/imaging/common/loader-gif.h>
-#include <dali/internal/imaging/common/loader-webp.h>
#include <dali/internal/imaging/common/loader-ico.h>
#include <dali/internal/imaging/common/loader-jpeg.h>
#include <dali/internal/imaging/common/loader-ktx.h>
#include <dali/internal/imaging/common/loader-png.h>
#include <dali/internal/imaging/common/loader-wbmp.h>
+#include <dali/internal/imaging/common/loader-webp.h>
#include <dali/internal/system/common/file-reader.h>
using namespace Dali::Integration;
case Dali::Pixel::BGR8888:
case Dali::Pixel::RGB16F:
case Dali::Pixel::RGB32F:
+ case Dali::Pixel::R11G11B10F:
{
return (channel == RED || channel == GREEN || channel == BLUE);
}
{
namespace
{
-const char* SAMPLER_TYPE = "samplerExternalOES";
+const char* SAMPLER_TYPE = "samplerExternalOES";
// clang-format off
tbm_format FORMATS_BLENDING_REQUIRED[] = {
{
#define TBM_SURFACE_QUEUE_SIZE 3
-const char* SAMPLER_TYPE = "samplerExternalOES";
+const char* SAMPLER_TYPE = "samplerExternalOES";
// clang-format off
int FORMATS_BLENDING_REQUIRED[] = {
\r
// Need to undef the following constants as they are defined in one of the headers in Windows.h but used in DALi (via debug.h)\r
#undef TRANSPARENT // Used in constants.h\r
-#undef CopyMemory // Used in dali-vector.h\r
+#undef CopyMemory // Used in dali-vector.h\r
\r
#include <dali/integration-api/debug.h>\r
\r
{
return mPlugin->GetNumberOfPointsPerOneUnitOfPointSize();
}
- return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+ return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+ ;
}
FT_FaceRec_* FontClient::GetFreetypeFace(FontId fontId)
*/
Size GetMaximumTextAtlasSize() const;
- /**
+ /**
* @copydoc Dali::TextAbstraction::FontClient::GetDefaultTextAtlasSize()
*/
Size GetDefaultTextAtlasSize() const;
bool isFit = false;
error = FT_Set_Char_Size(ftFace,
- 0,
- requestedPointSize,
- horizontalDpi,
- verticalDpi);
+ 0,
+ requestedPointSize,
+ horizontalDpi,
+ verticalDpi);
- if( error == FT_Err_Ok)
+ if(error == FT_Err_Ok)
{
//Check width and height of block for requestedPointSize
//If the width or height is greater than the maximum-size then decrement by one unit of point-size.
- if( static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height
- && (static_cast<float>(ftFace->size->metrics.ascender)-static_cast<float>(ftFace->size->metrics.descender))* FROM_266 <= maxSizeFitInAtlas.width)
+ if(static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height && (static_cast<float>(ftFace->size->metrics.ascender) - static_cast<float>(ftFace->size->metrics.descender)) * FROM_266 <= maxSizeFitInAtlas.width)
{
isFit = true;
}
{
//To improve performance of sequential search. This code is applying Exponential search then followed by Binary search.
const uint32_t& pointSizePerOneUnit = TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
- bool canFitInAtlas;
- int error; // FreeType error code.
+ bool canFitInAtlas;
+ int error; // FreeType error code.
canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
if(FT_Err_Ok != error)
//Exponential search
uint32_t exponentialDecrement = 1;
- while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit*exponentialDecrement)
+ while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit * exponentialDecrement)
{
- requestedPointSize-=(pointSizePerOneUnit*exponentialDecrement);
+ requestedPointSize -= (pointSizePerOneUnit * exponentialDecrement);
canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
if(FT_Err_Ok != error)
{
return error;
}
- exponentialDecrement*=2;
+ exponentialDecrement *= 2;
}
//Binary search
if(canFitInAtlas)
{
- exponentialDecrement/=2;
+ exponentialDecrement /= 2;
minPointSize = requestedPointSize;
- maxPointSize = requestedPointSize + (pointSizePerOneUnit*exponentialDecrement);
+ maxPointSize = requestedPointSize + (pointSizePerOneUnit * exponentialDecrement);
}
else
{
while(minPointSize < maxPointSize)
{
- requestedPointSize = ((maxPointSize/pointSizePerOneUnit - minPointSize/pointSizePerOneUnit)/2) * pointSizePerOneUnit + minPointSize;
- canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+ requestedPointSize = ((maxPointSize / pointSizePerOneUnit - minPointSize / pointSizePerOneUnit) / 2) * pointSizePerOneUnit + minPointSize;
+ canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
if(FT_Err_Ok != error)
{
return error;
return error;
}
-
FontClient::Plugin::FallbackCacheItem::FallbackCacheItem(FontDescription&& font, FontList* fallbackFonts, CharacterSetList* characterSets)
: fontDescription{std::move(font)},
fallbackFonts{fallbackFonts},
const Size& maxTextAtlasSize = TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
const uint16_t& padding = TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
- if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding
- && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
+ if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
{
mCurrentMaximumBlockSizeFitInAtlas = currentMaximumBlockSizeFitInAtlas;
- isChanged = true;
+ isChanged = true;
}
return isChanged;
uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const
{
- return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+ return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+ ;
}
-
void FontClient::Plugin::InitSystemFonts()
{
DALI_LOG_INFO(gLogFilter, Debug::General, "-->FontClient::Plugin::InitSystemFonts\n");
//If the block size cannot fit into atlas size, then the system cannot draw block.
//This is workaround to avoid issue in advance
//Decrementing point-size until arriving to maximum allowed block size.
- auto requestedPointSizeBackup= requestedPointSize;
- const Size& maxSizeFitInAtlas = GetCurrentMaximumBlockSizeFitInAtlas();
- error = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
+ auto requestedPointSizeBackup = requestedPointSize;
+ const Size& maxSizeFitInAtlas = GetCurrentMaximumBlockSizeFitInAtlas();
+ error = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
if(requestedPointSize != requestedPointSizeBackup)
{
}
else
{
- error = FT_Set_Char_Size(ftFace,
- 0,
- requestedPointSize,
- mDpiHorizontal,
- mDpiVertical);
+ error = FT_Set_Char_Size(ftFace,
+ 0,
+ requestedPointSize,
+ mDpiHorizontal,
+ mDpiVertical);
}
if(FT_Err_Ok == error)
*/
Size GetMaximumTextAtlasSize() const;
- /**
+ /**
* @copydoc Dali::TextAbstraction::FontClient::GetDefaultTextAtlasSize()
*/
Size GetDefaultTextAtlasSize() const;
bool mDefaultFontDescriptionCached : 1; ///< Whether the default font is cached or not
- bool mIsAtlasLimitationEnabled : 1; ///< Whether the validation on maximum atlas block size, then reduce block size to fit into it is enabled or not.
+ bool mIsAtlasLimitationEnabled : 1; ///< Whether the validation on maximum atlas block size, then reduce block size to fit into it is enabled or not.
Vector2 mCurrentMaximumBlockSizeFitInAtlas; ///< The current maximum size (width, height) of text-atlas-block.
};
*/
enum class AnimationFormat
{
- NONE = 0,
- JSON,
- RIVE
+ NONE = 0,
+ JSON,
+ RIVE
};
/**
#define DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_RENDER_THREAD_H
/*
- * 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.
int mScreenRotationAngle; ///< The angle of screen rotation angle
// To manage the render/main thread
- ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
- volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried.
- volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause.
- volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad
- volatile unsigned int mRequestRenderOnce; ///< Request rendering once
- volatile unsigned int mSurfaceStatus; ///< When surface is changed as resized or rotated, this flag is set. 0: No changed, 1:resized, 2:window rotation, 4:screen rotation
- volatile unsigned int mPostRendering; ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
+ ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
+ volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried.
+ volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause.
+ volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad
+ volatile unsigned int mRequestRenderOnce; ///< Request rendering once
+ volatile unsigned int mSurfaceStatus; ///< When surface is changed as resized or rotated, this flag is set. 0: No changed, 1:resized, 2:window rotation, 4:screen rotation
+ volatile unsigned int mPostRendering; ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
uint64_t mDefaultFrameDurationNanoseconds; ///< Default duration of a frame (used for sleeping if not enough time elapsed). Not protected by lock, but written to rarely so not worth adding a lock when reading.
return mUpdatePositionSizeSignal;
}
-
} // namespace Adaptor
} // namespace Internal
KeyboardRepeatSettingsChangedSignalType mKeyboardRepeatSettingsChangedSignal;
WindowRedrawRequestSignalType mWindowRedrawRequestSignal;
UpdatePositionSizeType mUpdatePositionSizeSignal;
-
};
} // namespace Adaptor
bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
{
+ mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
+
Dali::Integration::Scene::FrameCallbackContainer callbacks;
Dali::Integration::Scene scene = mScene.GetHandle();
}
}
- MakeContextCurrent();
-
/**
* wl_egl_window_tizen_set_rotation(SetEglWindowRotation) -> PreRotation
* wl_egl_window_tizen_set_buffer_transform(SetEglWindowBufferTransform) -> Screen Rotation
* because output transform event should be occured before egl window is not created.
*/
- if(resizingSurface || mDefaultScreenRotationAvailable)
+ if(mIsResizing || mDefaultScreenRotationAvailable)
{
int totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
mDefaultScreenRotationAvailable = false;
}
- SetBufferDamagedRects(damagedRects, clippingRect);
+ SetBufferDamagedRects(mDamagedRects, clippingRect);
+
+ if(clippingRect.IsEmpty())
+ {
+ mDamagedRects.clear();
+ }
+
+ // This is now done when the render pass for the render surface begins
+ // MakeContextCurrent();
return true;
}
-void WindowRenderSurface::PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects)
+void WindowRenderSurface::PostRender()
{
// Inform the gl implementation that rendering has finished before informing the surface
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
GlImplementation& mGLES = eglGraphics->GetGlesInterface();
mGLES.PostRender();
- if(renderToFbo)
+ if(mIsResizing)
{
- mGLES.Flush();
- mGLES.Finish();
- }
- else
- {
- if(resizingSurface)
+ if(!mWindowRotationFinished)
{
- if(!mWindowRotationFinished)
+ if(mThreadSynchronization)
{
- if(mThreadSynchronization)
- {
- // Enable PostRender flag
- mThreadSynchronization->PostRenderStarted();
- }
+ // Enable PostRender flag
+ mThreadSynchronization->PostRenderStarted();
+ }
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n");
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n");
- mRotationTrigger->Trigger();
+ mRotationTrigger->Trigger();
- if(mThreadSynchronization)
- {
- // Wait until the event-thread complete the rotation event processing
- mThreadSynchronization->PostRenderWaitForCompletion();
- }
+ if(mThreadSynchronization)
+ {
+ // Wait until the event-thread complete the rotation event processing
+ mThreadSynchronization->PostRenderWaitForCompletion();
}
}
}
- SwapBuffers(damagedRects);
+ SwapBuffers(mDamagedRects);
if(mRenderNotification)
{
/**
* @copydoc Dali::RenderSurfaceInterface::PostRender()
*/
- void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) override;
+ void PostRender() override;
/**
* @copydoc Dali::RenderSurfaceInterface::StopRender()
int mScreenRotationAngle;
uint32_t mDpiHorizontal;
uint32_t mDpiVertical;
- bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it)
+ std::vector<Rect<int>> mDamagedRects{}; ///< Keeps collected damaged render items rects for one render pass
+ bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it)
bool mWindowRotationFinished;
bool mScreenRotationFinished;
bool mResizeFinished;
// When window is just moved or window is resized by client application,
// The configure notification event's size will be 0.
// If new size is 0, the resized work should be skip.
- int newWidth = mWindowPositionSize.width;
- int newHeight = mWindowPositionSize.height;
+ int newWidth = mWindowPositionSize.width;
+ int newHeight = mWindowPositionSize.height;
bool windowMoved = false, windowResized = false;
if(ev->x != mWindowPositionSize.x || ev->y != mWindowPositionSize.y)
if(tempWidth != 0 && tempHeight != 0 && (tempWidth != mWindowPositionSize.width || tempHeight != mWindowPositionSize.height))
{
windowResized = true;
- newWidth = tempWidth;
- newHeight = tempHeight;
+ newWidth = tempWidth;
+ newHeight = tempHeight;
}
if(windowMoved || windowResized)
bool NativeRenderSurfaceEcoreWl::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
{
+ if(!clippingRect.IsEmpty())
+ {
+ mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
+ }
+ else
+ {
+ mDamagedRects.clear();
+ }
+
//TODO: Need to support partial update
- MakeContextCurrent();
+ // This is now done when the render pass for the render surface begins
+ // MakeContextCurrent();
return true;
}
-void NativeRenderSurfaceEcoreWl::PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects)
+void NativeRenderSurfaceEcoreWl::PostRender()
{
auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
if(eglGraphics)
{
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
- eglImpl.SwapBuffers(mEGLSurface, damagedRects);
+ eglImpl.SwapBuffers(mEGLSurface, mDamagedRects);
}
if(mRenderNotification)
/**
* @copydoc Dali::RenderSurfaceInterface::PostRender()
*/
- void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) override;
+ void PostRender() override;
/**
* @copydoc Dali::RenderSurfaceInterface::StopRender()
ColorDepth mColorDepth;
tbm_format mTbmFormat;
bool mOwnSurface;
+ std::vector<Rect<int>> mDamagedRects{}; ///< Keeps collected damaged render items rects for one render pass
tbm_surface_queue_h mTbmQueue;
ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
return true;
}
-void PixmapRenderSurfaceEcoreX::PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects)
+void PixmapRenderSurfaceEcoreX::PostRender()
{
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
/**
* @copydoc Dali::RenderSurfaceInterface::PostRender()
*/
- void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) override;
+ void PostRender() override;
/**
* @copydoc Dali::RenderSurfaceInterface::StopRender()
/*
- * 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.