You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Copy file name to clipboardExpand all lines: impeller/docs/standalone_gles.md
+14-14Lines changed: 14 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,19 +1,19 @@
1
1
# Using Impeller as a Standalone Rendering Library (with OpenGL ES)
2
2
3
-
This guide describes how to use Impeller as a standalone rendering library using OpenGL ES. Additionally, some form of WSI (Window System Integration) is essential. Since EGL is the most popular form of performing WSI on platforms with OpenGL ES, Impeller has a toolkit that assists in working with EGL. This guide will use that toolkit.
3
+
This guide describes how to use Impeller as a standalone rendering library using OpenGL ES. Additionally, some form of Window System Integration (WSI) is essential. Since EGL is the most popular form of performing WSI on platforms with OpenGL ES, Impeller has a toolkit that assists in working with EGL. This guide will use that toolkit.
4
4
5
5
While this guide focuses on OpenGL ES with EGL, the steps to setup rendering with another client rendering API (Metal and Vulkan) are fairly similar and you should be able to follow the same pattern for other backends.
6
6
7
-
This guide details extremely low-level setup and the `//impeller/renderer` API directly above the HAL. Most users of Impeller will likely use the API using convenience wrappers already written for the platform. Interacting directly with the HAL is extremely powerful but also verbose. Applications are likely to also use higher level frameworks like Aiks or Display Lists.
7
+
This guide details extremely low-level setup and the `//impeller/renderer` API directly above the Hardware Abstraction Layer (HAL). Most users of Impeller will likely use the API using convenience wrappers already written for the platform. Interacting directly with the HAL is extremely powerful but also verbose. Applications are likely to also use higher level frameworks like Aiks or Display Lists.
8
8
9
9
Building Impeller for the target platform is outside the scope of this guide.
10
10
11
11
> [!CAUTION]
12
12
> The code provided inline is pseudo-code and doesn't include error handling. See the headerdocs for more on error handling and failure modes. All classes are assumed to be in the `impeller` namespace. For a more complete example of setting up standalone Impeller, see [this patch](https://github.com/flutter/engine/pull/52472/files) that adds support for Impeller rendering via Wasm [in the browser and WebGL 2](https://public.chinmaygarde.com/impeller/wasm/wasm.html).
13
13
14
-
# Setup
14
+
# Set up
15
15
16
-
To get started with Impeller rendering, you need to setup a context and a renderer. For backendspecific classes, the convention in Impeller is to append the backend name as a suffix. So if you need to create an instance of an `impeller::Context` for OpenGLES, look for `impeller::ContextGLES`.
16
+
To get started with Impeller rendering, you need to set up a context and a renderer. For backend-specific classes, the convention in Impeller is to append the backend name as a suffix. So if you need to create an instance of an `impeller::Context` for OpenGLES, look for `impeller::ContextGLES`.
17
17
18
18
In our case, we need a `impeller::ContextGLES` and `impeller::Renderer`.
19
19
@@ -74,7 +74,7 @@ auto gl = std::make_unique<ProcTableGLES>(resolver);
74
74
75
75
Once the proc table is created, the resolver will no longer be invoked.
76
76
77
-
Then you need to provide the context a shader library that contains a manifest of all the shaders the context will need at runtime. Remember, Impeller doesn't generate shaders at runtime. Instead `impellerc` generates blobs that can either be delivered out of band or be embedded directly in the binary. When embedding the blobs directly in the binary, find the symbols referring to the shader blob somewhere in the generated build artifacts. A vector of mappings to these blobs needs to be provided to create context creation factory.
77
+
Then you need to provide the context a shader library that contains a manifest of all the shaders the context will need at runtime. Remember, Impeller doesn't generate shaders at runtime. Instead `impellerc` generates blobs that can either be delivered out of band or be embedded directly in the binary. When embedding the blobs directly in the binary, look for the symbols referring to the shader blob somewhere in the generated build artifacts. A vector of mappings to these blobs needs to be provided to create context creation factory.
78
78
79
79
An example of creating an embedded mapping is provided below. Adjust as necessary depending on how to plan on delivering shader blobs to Impeller at during setup.
80
80
```c++
@@ -135,7 +135,7 @@ Add an instance of this reactor worker to the context. Whew, that was unnecessar
135
135
context->AddReactorWorker(worker);
136
136
```
137
137
138
-
Once you have the context, use it to crate a renderer.
138
+
Once you have the context, use it to create a renderer.
139
139
140
140
```c++
141
141
auto renderer = std::make_shared<Renderer>(context);
@@ -148,15 +148,15 @@ And setup is done. Keep the context and renderer around. We will be using it dur
148
148
Rendering frames is a matter of:
149
149
* Wrapping the onscreen texture as a Surface (`impeller::SurfaceGLES` in our case).
150
150
* Giving the surface to our renderer to render.
151
-
*The renderer will prepare a render target from this surface and invoke a callback that we'll use to setup a render pass directed at that render target.
152
-
*Populate the render pass how we see fit.
153
-
*Tell our reactor worker that all operations need to be flushed to OpenGL.
154
-
*Present the onscreen surface.
155
-
*Repeat.
151
+
*After the renderer prepares a render target from this surface and invokes a supplied callback with a render target, setting up a render pass directed at that render target.
152
+
*Populating the render pass how we see fit.
153
+
*Telling our reactor worker that all operations need to be flushed to OpenGL.
154
+
*Presenting the onscreen surface.
155
+
*Repeating for a new frame.
156
156
157
157
## Wrap the Onscreen Surface
158
158
159
-
Per frame, the onscreen surface can be wrapped using SurfaceGLES::WrapFBO where the default framebuffer in our case is FBO 0. Take care to ensure that the pixel format matches the one we used to choose the EGL config. Figuring out the pixel size is left as an exercise for the reader.
159
+
Per frame, the onscreen surface can be wrapped using `SurfaceGLES::WrapFBO` where the default framebuffer in our case is FBO 0. Take care to ensure that the pixel format matches the one we used to choose the EGL config. Figuring out the pixel size is left as an exercise for the reader.
160
160
161
161
```c++
162
162
auto surface =
@@ -168,9 +168,9 @@ auto surface =
168
168
);
169
169
```
170
170
171
-
## Setup the Swap Callback
171
+
## Set the the Swap Callback
172
172
173
-
The swap callback will get invoked when the renderer presents the surface. Remember in our list of things to do, we need to first tell the reactor worker to flush all pending OpenGL operations and then present the surface. Setup the swap callback appropriately.
173
+
The swap callback will get invoked when the renderer presents the surface. Remember in our list of things to do, we need to first tell the reactor worker to flush all pending OpenGL operations and then present the surface. Set the swap callback appropriately.
0 commit comments