Commit e760c69ee1bf0f3a988ad01941493907f29b0db1

Authored by Adam Bialogonski
1 parent 76da76d6

DirectRendering demo

Environment variables:
MAX_CUBES = [integer] - number of cubes to render (default 100)
DR_THREAD_ENABLED = 0|1 - renders with parallel thread
EGL_ENABED = 0|1 - uses EGL instead (not working on Ubuntu)

Change-Id: I185bec2667d25c713ca9c63cf97702a8de9ea539
examples-reel/dali-examples-reel.cpp
@@ -52,6 +52,7 @@ int DALI_EXPORT_API main(int argc, char** argv) @@ -52,6 +52,7 @@ int DALI_EXPORT_API main(int argc, char** argv)
52 demo.AddExample(Example("color-transition.example", DALI_DEMO_STR_TITLE_COLOR_TRANSITION)); 52 demo.AddExample(Example("color-transition.example", DALI_DEMO_STR_TITLE_COLOR_TRANSITION));
53 demo.AddExample(Example("color-visual.example", DALI_DEMO_STR_TITLE_COLOR_VISUAL)); 53 demo.AddExample(Example("color-visual.example", DALI_DEMO_STR_TITLE_COLOR_VISUAL));
54 demo.AddExample(Example("deferred-shading.example", DALI_DEMO_STR_TITLE_DEFERRED_SHADING)); 54 demo.AddExample(Example("deferred-shading.example", DALI_DEMO_STR_TITLE_DEFERRED_SHADING));
  55 + demo.AddExample(Example("direct-rendering.example", DALI_DEMO_STR_TITLE_DIRECT_RENDERING));
55 demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION)); 56 demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION));
56 demo.AddExample(Example("drag-and-drop.example", DALI_DEMO_STR_TITLE_DRAG_AND_DROP)); 57 demo.AddExample(Example("drag-and-drop.example", DALI_DEMO_STR_TITLE_DRAG_AND_DROP));
57 demo.AddExample(Example("drawable-actor.example", DALI_DEMO_STR_TITLE_DRAWABLE_ACTOR)); 58 demo.AddExample(Example("drawable-actor.example", DALI_DEMO_STR_TITLE_DRAWABLE_ACTOR));
examples/direct-rendering/direct-rendering-example.cpp 0 → 100644
  1 +/*
  2 + * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + *
  16 + */
  17 +
  18 +#include <dali-toolkit/dali-toolkit.h>
  19 +#include "native-renderer.h"
  20 +
  21 +using namespace Dali;
  22 +
  23 +namespace
  24 +{
  25 +/**
  26 + * Helper function reading env variable as integer
  27 + */
  28 +int GetEnvInt(const char* name, int def)
  29 +{
  30 + auto v = getenv(name);
  31 + return v ? atoi(v) : def;
  32 +}
  33 +
  34 +/**
  35 + * Environment variable: DR_THREAD_ENABLE
  36 + *
  37 + * if set to 1 the Direct Rendering will use offscreen buffer and render in parallel. It is a direct
  38 + * equivalent of the EGL Image mode.
  39 + */
  40 +const uint32_t DR_THREAD_ENABLED = GetEnvInt("DR_THREAD_ENABLED", 0);
  41 +
  42 +/**
  43 + * Environment variable: EGL_ENABLED
  44 + *
  45 + * When set to 1 the native image is used for direct rendering (rendering is parallel by default).
  46 + */
  47 +const Toolkit::GlView::BackendMode BACKEND_MODE =
  48 + Toolkit::GlView::BackendMode(GetEnvInt("EGL_ENABLED", 0));
  49 +}
  50 +
  51 +/**
  52 + * RenderView encapsulates single GLView callback and its parameters.
  53 + */
  54 +struct RenderView
  55 +{
  56 + explicit RenderView( const Dali::Window& window )
  57 + {
  58 + mWindow = window;
  59 + }
  60 +
  61 + int Create(const Vector2& pos, Toolkit::GlView::BackendMode mode )
  62 + {
  63 + auto w = mWindow.GetSize().GetWidth();
  64 + auto h = mWindow.GetSize().GetHeight();
  65 +
  66 + NativeRenderer::CreateInfo info{};
  67 + info.clearColor = {0, 0, 0, 0};
  68 + info.name = "DR";
  69 + info.offscreen = (mode == Toolkit::GlView::BackendMode::EGL_IMAGE_OFFSCREEN_RENDERING || DR_THREAD_ENABLED);
  70 + info.viewportX = 0;
  71 + info.viewportY = 0;
  72 + info.width = w;
  73 + info.height = h;
  74 + info.threaded = (mode != Toolkit::GlView::BackendMode::EGL_IMAGE_OFFSCREEN_RENDERING) && (DR_THREAD_ENABLED);
  75 +
  76 + // Enable threaded rendering
  77 + if(info.threaded && mode == Dali::Toolkit::GlView::BackendMode::DIRECT_RENDERING)
  78 + {
  79 + mode = Dali::Toolkit::GlView::BackendMode::DIRECT_RENDERING_THREADED;
  80 + }
  81 +
  82 + mRenderer = std::make_unique<NativeRenderer>(info);
  83 + mGlInitCallback = MakeCallback(mRenderer.get(), &NativeRenderer::GlViewInitCallback);
  84 + mGlRenderCallback = MakeCallback(mRenderer.get(), &NativeRenderer::GlViewRenderCallback);
  85 + mGlTerminateCallback = MakeCallback(mRenderer.get(), &NativeRenderer::GlViewTerminateCallback);
  86 +
  87 + // Create GlView with callbacks
  88 + auto glView = Toolkit::GlView::New(mode, Toolkit::GlView::ColorFormat::RGBA8888); //, Toolkit::GlView::BackendMode::DIRECT_RENDERING);
  89 + glView.SetGraphicsConfig(true, false, 0, Toolkit::GlView::GraphicsApiVersion::GLES_VERSION_3_0);
  90 + glView.RegisterGlCallbacks(mGlInitCallback, mGlRenderCallback, mGlTerminateCallback);
  91 +
  92 + glView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
  93 + glView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
  94 +
  95 + // Set size on the actor (half the window size to show that glClear() and scissor test work together)
  96 + glView.SetProperty(Actor::Property::SIZE, Size(w, h));
  97 + glView.SetProperty(Actor::Property::POSITION, pos);
  98 + glView.SetRenderingMode(Toolkit::GlView::RenderingMode::CONTINUOUS);
  99 + mWindow.Add(glView);
  100 +
  101 + mGlView = glView;
  102 +
  103 + return 0;
  104 + }
  105 +
  106 +
  107 + Dali::Window mWindow;
  108 + Toolkit::GlView mGlView;
  109 + std::unique_ptr<NativeRenderer> mRenderer{};
  110 +
  111 + CallbackBase* mGlInitCallback{};
  112 + CallbackBase* mGlRenderCallback{};
  113 + CallbackBase* mGlTerminateCallback{};
  114 +};
  115 +
  116 +// This example oresents DirectRendering feature which allows injecting
  117 +// custom GL code into the DALi render commands stream
  118 +
  119 +class DirectRenderingExampleController : public ConnectionTracker
  120 +{
  121 +public:
  122 +
  123 + explicit DirectRenderingExampleController(Application& application)
  124 + : mApplication(application)
  125 + {
  126 + // Connect to the Application's Init signal
  127 + mApplication.InitSignal().Connect(this, &DirectRenderingExampleController::Create);
  128 + }
  129 +
  130 + ~DirectRenderingExampleController() override = default; // Nothing to do in destructor
  131 +
  132 + void Create(Application& application)
  133 + {
  134 + // Get a handle to the window
  135 + Dali::Window window = application.GetWindow();
  136 + window.SetBackgroundColor(Color::WHITE);
  137 +
  138 + mDRView = std::make_unique<RenderView>(window);
  139 + mDRView->Create( Vector2::ZERO, BACKEND_MODE );
  140 + }
  141 +
  142 + bool OnTouch(Actor actor, const TouchEvent& touch)
  143 + {
  144 + // quit the application
  145 + mApplication.Quit();
  146 + return true;
  147 + }
  148 +
  149 + void OnKeyEvent(const KeyEvent& event)
  150 + {
  151 + if(event.GetState() == KeyEvent::DOWN)
  152 + {
  153 + if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
  154 + {
  155 + mApplication.Quit();
  156 + }
  157 + }
  158 + }
  159 +
  160 +private:
  161 + Application& mApplication;
  162 + std::unique_ptr<RenderView> mDRView;
  163 +};
  164 +
  165 +int DALI_EXPORT_API main(int argc, char** argv)
  166 +{
  167 + Application application = Application::New(&argc, &argv);
  168 + DirectRenderingExampleController test(application);
  169 + application.MainLoop();
  170 + return 0;
  171 +}
examples/direct-rendering/native-renderer.cpp 0 → 100644
  1 +/*
  2 + * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + *
  16 + */
  17 +
  18 +#include "native-renderer.h"
  19 +#include <iostream>
  20 +
  21 +/**
  22 + * Set of math helper functions
  23 + */
  24 +namespace
  25 +{
  26 +
  27 +[[maybe_unused]] std::vector<std::string> split(const std::string& s, char seperator)
  28 +{
  29 + std::vector<std::string> output;
  30 + std::string::size_type prev_pos = 0, pos = 0;
  31 + while((pos = s.find(seperator, pos)) != std::string::npos)
  32 + {
  33 + std::string substring( s.substr(prev_pos, pos-prev_pos) );
  34 + output.push_back(substring);
  35 + prev_pos = ++pos;
  36 + }
  37 + output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
  38 + return output;
  39 +}
  40 +
  41 +int GetEnvInt(const char* name, int def)
  42 +{
  43 + auto v = getenv(name);
  44 + return v ? atoi(v) : def;
  45 +}
  46 +
  47 +[[maybe_unused]] std::string GetEnvString(const char* name, std::string def = "")
  48 +{
  49 + auto v = getenv(name);
  50 + return v ? std::string(v) : def;
  51 +}
  52 +
  53 +const uint32_t MAX_CUBES = GetEnvInt("MAX_CUBES", 200);
  54 +
  55 +#define GL(x) {glGetError();{x;};auto err = glGetError();if(err){ \
  56 +printf("%p:%d: ERROR: 0x%X\n", this, __LINE__, int(err));} }
  57 +
  58 +constexpr GLfloat CUBE_VERTICES[] = {-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f};
  59 +
  60 +constexpr GLfloat CUBE_COLOURS[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
  61 +
  62 +constexpr GLushort CUBE_INDICES[] = {0, 2, 3, 0, 1, 3, 4, 6, 7, 4, 5, 7, 8, 9, 10, 11, 8, 10, 12, 13, 14, 15, 12, 14, 16, 17, 18, 16, 19, 18, 20, 21, 22, 20, 23, 22};
  63 +
  64 +constexpr float QUAD_VERTS[] = {
  65 + // positions // colors // texture coords
  66 + 1.0f, 1.0f,
  67 + 1.0f, -1.0f,
  68 + -1.0f, -1.0f,
  69 + -1.0f, 1.0f,
  70 +};
  71 +
  72 +constexpr unsigned short QUAD_INDICES[] = {
  73 + 0, 1, 2,
  74 + 3, 0, 2
  75 +};
  76 +
  77 +constexpr float QUAD_UV[] = {
  78 + // positions // colors // texture coords
  79 + 1.0f, 1.0f, // top right
  80 + 1.0f, 0.0f, // bottom right
  81 + 0.0f, 0.0f, // bottom left
  82 + 0.0f, 1.0f // top left
  83 +};
  84 +
  85 +float matrixDegreesToRadians(float degrees)
  86 +{
  87 + return M_PI * degrees / 180.0f;
  88 +}
  89 +
  90 +[[maybe_unused]] void matrixIdentityFunction(float* matrix)
  91 +{
  92 + if(matrix == NULL)
  93 + {
  94 + return;
  95 + }
  96 + matrix[0] = 1.0f;
  97 + matrix[1] = 0.0f;
  98 + matrix[2] = 0.0f;
  99 + matrix[3] = 0.0f;
  100 + matrix[4] = 0.0f;
  101 + matrix[5] = 1.0f;
  102 + matrix[6] = 0.0f;
  103 + matrix[7] = 0.0f;
  104 + matrix[8] = 0.0f;
  105 + matrix[9] = 0.0f;
  106 + matrix[10] = 1.0f;
  107 + matrix[11] = 0.0f;
  108 + matrix[12] = 0.0f;
  109 + matrix[13] = 0.0f;
  110 + matrix[14] = 0.0f;
  111 + matrix[15] = 1.0f;
  112 +}
  113 +
  114 +[[maybe_unused]] void matrixMultiply(float* destination, float* operand1, float* operand2)
  115 +{
  116 + float theResult[16];
  117 + int i, j = 0;
  118 + for(i = 0; i < 4; i++)
  119 + {
  120 + for(j = 0; j < 4; j++)
  121 + {
  122 + theResult[4 * i + j] = operand1[j] * operand2[4 * i] + operand1[4 + j] * operand2[4 * i + 1] +
  123 + operand1[8 + j] * operand2[4 * i + 2] + operand1[12 + j] * operand2[4 * i + 3];
  124 + }
  125 + }
  126 + for(int i = 0; i < 16; i++)
  127 + {
  128 + destination[i] = theResult[i];
  129 + }
  130 +}
  131 +
  132 +[[maybe_unused]] void matrixTranslate(float* matrix, float x, float y, float z)
  133 +{
  134 + float temporaryMatrix[16];
  135 + matrixIdentityFunction(temporaryMatrix);
  136 + temporaryMatrix[12] = x;
  137 + temporaryMatrix[13] = y;
  138 + temporaryMatrix[14] = z;
  139 + matrixMultiply(matrix, temporaryMatrix, matrix);
  140 +}
  141 +
  142 +[[maybe_unused]] void matrixScale(float* matrix, float x, float y, float z)
  143 +{
  144 + float tempMatrix[16];
  145 + matrixIdentityFunction(tempMatrix);
  146 + tempMatrix[0] = x;
  147 + tempMatrix[5] = y;
  148 + tempMatrix[10] = z;
  149 + matrixMultiply(matrix, tempMatrix, matrix);
  150 +}
  151 +
  152 +[[maybe_unused]] void matrixRotateX(float* matrix, float angle)
  153 +{
  154 + float tempMatrix[16];
  155 + matrixIdentityFunction(tempMatrix);
  156 + tempMatrix[5] = cos(matrixDegreesToRadians(angle));
  157 + tempMatrix[9] = -sin(matrixDegreesToRadians(angle));
  158 + tempMatrix[6] = sin(matrixDegreesToRadians(angle));
  159 + tempMatrix[10] = cos(matrixDegreesToRadians(angle));
  160 + matrixMultiply(matrix, tempMatrix, matrix);
  161 +}
  162 +[[maybe_unused]] void matrixRotateY(float* matrix, float angle)
  163 +{
  164 + float tempMatrix[16];
  165 + matrixIdentityFunction(tempMatrix);
  166 + tempMatrix[0] = cos(matrixDegreesToRadians(angle));
  167 + tempMatrix[8] = sin(matrixDegreesToRadians(angle));
  168 + tempMatrix[2] = -sin(matrixDegreesToRadians(angle));
  169 + tempMatrix[10] = cos(matrixDegreesToRadians(angle));
  170 + matrixMultiply(matrix, tempMatrix, matrix);
  171 +}
  172 +[[maybe_unused]] void matrixRotateZ(float* matrix, float angle)
  173 +{
  174 + float tempMatrix[16];
  175 + matrixIdentityFunction(tempMatrix);
  176 + tempMatrix[0] = cos(matrixDegreesToRadians(angle));
  177 + tempMatrix[4] = -sin(matrixDegreesToRadians(angle));
  178 + tempMatrix[1] = sin(matrixDegreesToRadians(angle));
  179 + tempMatrix[5] = cos(matrixDegreesToRadians(angle));
  180 + matrixMultiply(matrix, tempMatrix, matrix);
  181 +}
  182 +
  183 +void matrixFrustum(float* matrix, float left, float right, float bottom, float top, float zNear, float zFar)
  184 +{
  185 + float temp, xDistance, yDistance, zDistance;
  186 + temp = 2.0 * zNear;
  187 + xDistance = right - left;
  188 + yDistance = top - bottom;
  189 + zDistance = zFar - zNear;
  190 + matrixIdentityFunction(matrix);
  191 + matrix[0] = temp / xDistance;
  192 + matrix[5] = temp / yDistance;
  193 + matrix[8] = (right + left) / xDistance;
  194 + matrix[9] = (top + bottom) / yDistance;
  195 + matrix[10] = (-zFar - zNear) / zDistance;
  196 + matrix[11] = -1.0f;
  197 + matrix[14] = (-temp * zFar) / zDistance;
  198 + matrix[15] = 0.0f;
  199 +}
  200 +
  201 +[[maybe_unused]] void matrixPerspective(float* matrix, float fieldOfView, float aspectRatio, float zNear, float zFar)
  202 +{
  203 + float ymax, xmax;
  204 + ymax = zNear * tanf(fieldOfView * M_PI / 360.0);
  205 + xmax = ymax * aspectRatio;
  206 + matrixFrustum(matrix, -xmax, xmax, -ymax, ymax, zNear, zFar);
  207 +}
  208 +
  209 +} // namespace
  210 +
  211 +NativeRenderer::~NativeRenderer() = default;
  212 +
  213 +NativeRenderer::NativeRenderer(const CreateInfo& info )
  214 +: mWidth(info.width),
  215 + mHeight(info.height),
  216 + mCreateInfo(info)
  217 +{
  218 +}
  219 +
  220 +void NativeRenderer::PrepareShader()
  221 +{
  222 + static const char glVertexShader[] =
  223 + "attribute vec4 vertexPosition;\n"
  224 + "attribute vec3 vertexColour;\n"
  225 + "varying vec3 fragColour;\n"
  226 + "uniform mat4 projection;\n"
  227 + "uniform mat4 modelView;\n"
  228 + "void main()\n"
  229 + "{\n"
  230 + " gl_Position = projection * modelView * vertexPosition;\n"
  231 + " fragColour = vertexColour;\n"
  232 + "}\n";
  233 +
  234 + static const char glFragmentShader[] =
  235 + "precision mediump float;\n"
  236 + "varying vec3 fragColour;\n"
  237 + "void main()\n"
  238 + "{\n"
  239 + " gl_FragColor = vec4(fragColour, 1.0);\n"
  240 + "}\n";
  241 +
  242 + mProgramId = CreateProgram(glVertexShader, glFragmentShader);
  243 +}
  244 +
  245 +void NativeRenderer::Setup(int width, int height)
  246 +{
  247 + PrepareShader();
  248 +
  249 + mVertexLocation = glGetAttribLocation(mProgramId, "vertexPosition");
  250 + mVertexColourLocation = glGetAttribLocation(mProgramId, "vertexColour");
  251 + mProjectionLocation = glGetUniformLocation(mProgramId, "projection");
  252 + mModelViewLocation = glGetUniformLocation(mProgramId, "modelView");
  253 +
  254 + GL(glEnable(GL_DEPTH_TEST));
  255 +}
  256 +
  257 +GLuint NativeRenderer::CreateProgram(const char* vertexSource, const char* fragmentSource)
  258 +{
  259 + GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vertexSource);
  260 + if(!vertexShader)
  261 + {
  262 + return 0;
  263 + }
  264 + GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentSource);
  265 + if(!fragmentShader)
  266 + {
  267 + return 0;
  268 + }
  269 + GLuint program = glCreateProgram();
  270 + if(program)
  271 + {
  272 + GL(glAttachShader(program, vertexShader));
  273 + GL(glAttachShader(program, fragmentShader));
  274 + GL(glLinkProgram(program));
  275 + GLint linkStatus = GL_FALSE;
  276 + GL(glGetProgramiv(program, GL_LINK_STATUS, &linkStatus));
  277 + if(linkStatus != GL_TRUE)
  278 + {
  279 + GLint bufLength = 0;
  280 + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
  281 + if(bufLength)
  282 + {
  283 + char* buf = (char*)malloc(bufLength);
  284 + if(buf)
  285 + {
  286 + glGetProgramInfoLog(program, bufLength, NULL, buf);
  287 + free(buf);
  288 + }
  289 + }
  290 + glDeleteProgram(program);
  291 + program = 0;
  292 + }
  293 + }
  294 + return program;
  295 +}
  296 +
  297 +GLuint NativeRenderer::LoadShader(GLenum shaderType, const char* shaderSource)
  298 +{
  299 + GLuint shader = glCreateShader(shaderType);
  300 + if(shader != 0)
  301 + {
  302 + GL(glShaderSource(shader, 1, &shaderSource, NULL));
  303 + GL(glCompileShader(shader));
  304 + GLint compiled = 0;
  305 + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
  306 + if(compiled != GL_TRUE)
  307 + {
  308 + GLint infoLen = 0;
  309 + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
  310 +
  311 + if(infoLen > 0)
  312 + {
  313 + char* logBuffer = (char*)malloc(infoLen);
  314 +
  315 + if(logBuffer != NULL)
  316 + {
  317 + glGetShaderInfoLog(shader, infoLen, NULL, logBuffer);
  318 + free(logBuffer);
  319 + logBuffer = NULL;
  320 + }
  321 +
  322 + glDeleteShader(shader);
  323 + shader = 0;
  324 + }
  325 + }
  326 + }
  327 +
  328 + return shader;
  329 +}
  330 +
  331 +void NativeRenderer::RenderCube(const Dali::RenderCallbackInput& input)
  332 +{
  333 + uint32_t drawCount = 0;
  334 +
  335 + float& angle = mAngle;
  336 +
  337 + [[maybe_unused]] auto x = mCreateInfo.viewportX; // float(mWidth - input.size.width) * 0.5f;
  338 + [[maybe_unused]] auto y = mCreateInfo.viewportY; // float(mHeight - input.size.height) * 0.5f;
  339 + auto w = mCreateInfo.width;
  340 + auto h = mCreateInfo.height;
  341 +
  342 + matrixPerspective(mProjectionMatrix, 45, (float)w / (float)h, 0.1f, 100);
  343 +
  344 + GL(glViewport(x, y, w, h));
  345 + GL(glEnable(GL_DEPTH_TEST));
  346 + if(!mCreateInfo.offscreen)
  347 + {
  348 + GL(glEnable(GL_SCISSOR_TEST));
  349 + GL(glScissor(x, y, w, h));
  350 + }
  351 + else
  352 + {
  353 + GL(glDisable(GL_SCISSOR_TEST));
  354 + }
  355 + GL(glClearColor(mCreateInfo.clearColor[0],
  356 + mCreateInfo.clearColor[1],
  357 + mCreateInfo.clearColor[2],
  358 + mCreateInfo.clearColor[3]
  359 + ));
  360 + {
  361 + GL(glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
  362 + }
  363 + GL(glUseProgram(mProgramId));
  364 + GL(glVertexAttribPointer(mVertexLocation, 3, GL_FLOAT, GL_FALSE, 0, CUBE_VERTICES));
  365 + GL(glEnableVertexAttribArray(mVertexLocation));
  366 + GL(glVertexAttribPointer(mVertexColourLocation, 3, GL_FLOAT, GL_FALSE, 0, CUBE_COLOURS));
  367 + GL(glEnableVertexAttribArray(mVertexColourLocation));
  368 +
  369 + srand(10);
  370 +
  371 + const auto maxCubes = int(MAX_CUBES);
  372 +
  373 + for( int i = 0; i < int(maxCubes); ++i)
  374 + {
  375 + GL(matrixIdentityFunction(mModelViewMatrix));
  376 + matrixScale(mModelViewMatrix, 0.2f, 0.2f, 0.2f);
  377 + matrixRotateX(mModelViewMatrix, angle);
  378 + matrixRotateY(mModelViewMatrix, angle);
  379 + auto max = 7000;
  380 + if(mPosX.size() == uint32_t(i))
  381 + {
  382 + auto x = float((rand() % max) - (max / 2)) / 1000.0f;
  383 + auto y = float((rand() % max) - (max / 2)) / 1000.0f;
  384 + mPosX.emplace_back(x);
  385 + mPosY.emplace_back(y);
  386 + }
  387 + matrixTranslate(mModelViewMatrix, mPosX[i], mPosY[i], -5.0f);
  388 + GL(glUniformMatrix4fv(mProjectionLocation, 1, GL_FALSE, mProjectionMatrix));
  389 + GL(glUniformMatrix4fv(mModelViewLocation, 1, GL_FALSE, mModelViewMatrix));
  390 + GL(glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, CUBE_INDICES));
  391 + drawCount++;
  392 + }
  393 + angle += 1;
  394 + if(angle > 360)
  395 + {
  396 + angle -= 360;
  397 + }
  398 +}
  399 +
  400 +void NativeRenderer::GlViewInitCallback(const Dali::RenderCallbackInput& input)
  401 +{
  402 + Setup(mWidth, mHeight);
  403 + mState = State::RENDER;
  404 +}
  405 +
  406 +int NativeRenderer::GlViewRenderCallback(const Dali::RenderCallbackInput& input)
  407 +{
  408 + RenderCube(input);
  409 + return true;
  410 +}
  411 +
  412 +void NativeRenderer::GlViewTerminateCallback(const Dali::RenderCallbackInput& input)
  413 +{
  414 + // Nothing to do here
  415 +}
examples/direct-rendering/native-renderer.h 0 → 100644
  1 +#ifndef DALI_DIRECT_RENDERING_NATIVE_RENDERER_H
  2 +#define DALI_DIRECT_RENDERING_NATIVE_RENDERER_H
  3 +
  4 +/*
  5 + * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  6 + *
  7 + * Licensed under the Apache License, Version 2.0 (the "License");
  8 + * you may not use this file except in compliance with the License.
  9 + * You may obtain a copy of the License at
  10 + *
  11 + * http://www.apache.org/licenses/LICENSE-2.0
  12 + *
  13 + * Unless required by applicable law or agreed to in writing, software
  14 + * distributed under the License is distributed on an "AS IS" BASIS,
  15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16 + * See the License for the specific language governing permissions and
  17 + * limitations under the License.
  18 + *
  19 + */
  20 +
  21 +#include <dali/public-api/signals/render-callback.h>
  22 +
  23 +#include <cmath>
  24 +#include <GLES3/gl3.h>
  25 +#include <EGL/egl.h>
  26 +#include <vector>
  27 +#include <thread>
  28 +#include <atomic>
  29 +#include <mutex>
  30 +#include <deque>
  31 +#include <map>
  32 +#include <array>
  33 +
  34 +/**
  35 + * Class NativeRenderer uses GL directly in order to render
  36 + * custom GL code within DirectRendering callbacks.
  37 + */
  38 +class NativeRenderer
  39 +{
  40 +public:
  41 +
  42 + /**
  43 + * Structure encapsulates initialization parameters
  44 + */
  45 + struct CreateInfo
  46 + {
  47 + std::string name;
  48 + uint32_t width;
  49 + uint32_t height;
  50 + int32_t viewportX;
  51 + int32_t viewportY;
  52 + std::array<float,4> clearColor { 0, 0, 0, 1};
  53 + bool offscreen{false};
  54 + bool threaded{false};
  55 + };
  56 +
  57 + /**
  58 + * Constructor
  59 + */
  60 + explicit NativeRenderer(const CreateInfo& info);
  61 +
  62 + /**
  63 + * Destructor
  64 + */
  65 + ~NativeRenderer();
  66 +
  67 + /**
  68 + * Prepare main shader
  69 + */
  70 + void PrepareShader();
  71 +
  72 + /**
  73 + * Setup custom scene
  74 + */
  75 + void Setup(int width, int height);
  76 +
  77 + /**
  78 + * Render cube with given callback input
  79 + */
  80 + void RenderCube( const Dali::RenderCallbackInput& input );
  81 +
  82 + /**
  83 + * Creates GL program from shader sources
  84 + */
  85 + GLuint CreateProgram(const char* vertexSource, const char* fragmentSource);
  86 +
  87 + /**
  88 + * Loads shader
  89 + */
  90 + GLuint LoadShader(GLenum shaderType, const char* shaderSource);
  91 +
  92 + enum class State
  93 + {
  94 + INIT,
  95 + RENDER
  96 + };
  97 +
  98 + // GLView-compatible callbacks
  99 + void GlViewInitCallback(const Dali::RenderCallbackInput& input);
  100 + int GlViewRenderCallback(const Dali::RenderCallbackInput& input);
  101 + void GlViewTerminateCallback(const Dali::RenderCallbackInput& input);
  102 +
  103 +private:
  104 +
  105 + State mState {State::INIT};
  106 +
  107 + GLuint mProgramId{0u};
  108 +
  109 + GLint mVertexLocation{};
  110 + GLint mVertexColourLocation{};
  111 + GLint mProjectionLocation{};
  112 + GLint mModelViewLocation{};
  113 +
  114 + float mModelViewMatrix[16];
  115 + float mProjectionMatrix[16];
  116 +
  117 + uint32_t mWidth;
  118 + uint32_t mHeight;
  119 +
  120 + CreateInfo mCreateInfo;
  121 +
  122 + float mAngle{0.f};
  123 +
  124 + std::vector<float> mPosX;
  125 + std::vector<float> mPosY;
  126 +};
  127 +
  128 +#endif // DALI_DIRECT_RENDERING_NATIVE_RENDERER_H
resources/po/en_US.po
@@ -61,6 +61,9 @@ msgstr &quot;Color Visual&quot; @@ -61,6 +61,9 @@ msgstr &quot;Color Visual&quot;
61 msgid "DALI_DEMO_STR_TITLE_DEFERRED_SHADING" 61 msgid "DALI_DEMO_STR_TITLE_DEFERRED_SHADING"
62 msgstr "Deferred Shading" 62 msgstr "Deferred Shading"
63 63
  64 +msgid "DALI_DEMO_STR_TITLE_DIRECT_RENDERING"
  65 +msgstr "Direct Rendering"
  66 +
64 msgid "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW" 67 msgid "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW"
65 msgstr "Gaussian Blur" 68 msgstr "Gaussian Blur"
66 69
shared/dali-demo-strings.h
@@ -55,6 +55,7 @@ extern &quot;C&quot; @@ -55,6 +55,7 @@ extern &quot;C&quot;
55 #define DALI_DEMO_STR_TITLE_COLOR_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_TRANSITION") 55 #define DALI_DEMO_STR_TITLE_COLOR_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_TRANSITION")
56 #define DALI_DEMO_STR_TITLE_COLOR_VISUAL dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_VISUAL") 56 #define DALI_DEMO_STR_TITLE_COLOR_VISUAL dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_VISUAL")
57 #define DALI_DEMO_STR_TITLE_DEFERRED_SHADING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_DEFERRED_SHADING") 57 #define DALI_DEMO_STR_TITLE_DEFERRED_SHADING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_DEFERRED_SHADING")
  58 +#define DALI_DEMO_STR_TITLE_DIRECT_RENDERING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_DIRECT_RENDERING")
58 #define DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW") 59 #define DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW")
59 #define DALI_DEMO_STR_TITLE_GESTURES dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GESTURES") 60 #define DALI_DEMO_STR_TITLE_GESTURES dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GESTURES")
60 #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_GRADIENT") 61 #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_GRADIENT")
@@ -173,6 +174,7 @@ extern &quot;C&quot; @@ -173,6 +174,7 @@ extern &quot;C&quot;
173 #define DALI_DEMO_STR_TITLE_CONTACT_CARDS "Contact Cards" 174 #define DALI_DEMO_STR_TITLE_CONTACT_CARDS "Contact Cards"
174 #define DALI_DEMO_STR_TITLE_CUBE_TRANSITION "Cube Effect" 175 #define DALI_DEMO_STR_TITLE_CUBE_TRANSITION "Cube Effect"
175 #define DALI_DEMO_STR_TITLE_DEFERRED_SHADING "Deferred Shading" 176 #define DALI_DEMO_STR_TITLE_DEFERRED_SHADING "Deferred Shading"
  177 +#define DALI_DEMO_STR_TITLE_DIRECT_RENDERING "Direct Rendering"
176 #define DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION "Dissolve Effect" 178 #define DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION "Dissolve Effect"
177 #define DALI_DEMO_STR_TITLE_DRAG_AND_DROP "Drag and Drop" 179 #define DALI_DEMO_STR_TITLE_DRAG_AND_DROP "Drag and Drop"
178 #define DALI_DEMO_STR_TITLE_DRAWABLE_ACTOR "DrawableActor" 180 #define DALI_DEMO_STR_TITLE_DRAWABLE_ACTOR "DrawableActor"