Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f763ef1

Browse files
authored
[Impeller] Document the EGL toolkit. (#52469)
No change in functionality. Just adds docs.
1 parent 21ae0cc commit f763ef1

File tree

6 files changed

+168
-10
lines changed

6 files changed

+168
-10
lines changed

impeller/toolkit/egl/config.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,17 @@ struct ConfigDescriptor {
5252
SurfaceType surface_type = SurfaceType::kPBuffer;
5353
};
5454

55+
class Display;
56+
57+
//------------------------------------------------------------------------------
58+
/// @brief An EGL config. These are returned by the display to indicate
59+
/// support for a specific config descriptor.
60+
///
61+
/// There is no ability to construct these manually except for
62+
/// testing.
63+
///
5564
class Config {
5665
public:
57-
Config(ConfigDescriptor descriptor, EGLConfig config);
58-
5966
~Config();
6067

6168
bool IsValid() const;
@@ -64,6 +71,9 @@ class Config {
6471

6572
const EGLConfig& GetHandle() const;
6673

74+
// Do not use. Only for testing.
75+
Config(ConfigDescriptor descriptor, EGLConfig config);
76+
6777
private:
6878
const ConfigDescriptor desc_;
6979
EGLConfig config_ = nullptr;

impeller/toolkit/egl/context.h

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,101 @@ namespace impeller {
1616
namespace egl {
1717

1818
class Surface;
19-
19+
class Display;
20+
21+
//------------------------------------------------------------------------------
22+
/// @brief An instance of an EGL context.
23+
///
24+
/// An EGL context can only be used on a single thread at a given
25+
/// time. A thread can only have a single context current at any
26+
/// given time.
27+
///
28+
/// Context cannot be created directly. Only a valid instance of an
29+
/// egl::Display can create a context.
30+
///
2031
class Context {
2132
public:
22-
Context(EGLDisplay display, EGLContext context);
23-
2433
~Context();
2534

35+
//----------------------------------------------------------------------------
36+
/// @brief Determines if a valid context could be created. The context
37+
/// still needs to be made current on the thread for it to be
38+
/// useful.
39+
///
40+
/// @return True if valid, False otherwise.
41+
///
2642
bool IsValid() const;
2743

44+
//----------------------------------------------------------------------------
45+
/// @brief Get the underlying handle to the EGL context.
46+
///
47+
/// @return The handle.
48+
///
2849
const EGLContext& GetHandle() const;
2950

51+
//----------------------------------------------------------------------------
52+
/// @brief Make the context current on the calling thread. It is the
53+
/// caller responsibility to ensure that any context previously
54+
/// current on the thread must be cleared via `ClearCurrent`.
55+
///
56+
/// @important The config used to create the surface must match the config
57+
/// used to create this context instance.
58+
///
59+
/// @param[in] surface The surface to use to make the context current.
60+
///
61+
/// @return If the context could be made current on the callers thread.
62+
///
3063
bool MakeCurrent(const Surface& surface) const;
3164

65+
//----------------------------------------------------------------------------
66+
/// @brief Clear the thread association of this context.
67+
///
68+
/// @return If the thread association could be cleared.
69+
///
3270
bool ClearCurrent() const;
3371

3472
enum class LifecycleEvent {
3573
kDidMakeCurrent,
3674
kWillClearCurrent,
3775
};
3876
using LifecycleListener = std::function<void(LifecycleEvent)>;
77+
//----------------------------------------------------------------------------
78+
/// @brief Add a listener that gets invoked when the context is made and
79+
/// cleared current from the thread. Applications typically use
80+
/// this to manage workers that schedule OpenGL API calls that
81+
/// need to be careful about the context being current when
82+
/// called.
83+
///
84+
/// @param[in] listener The listener
85+
///
86+
/// @return A unique ID for the listener that can used used in
87+
/// `RemoveLifecycleListener` to remove a previously added
88+
/// listener.
89+
///
3990
std::optional<UniqueID> AddLifecycleListener(
4091
const LifecycleListener& listener);
4192

93+
//----------------------------------------------------------------------------
94+
/// @brief Remove a previously added context listener.
95+
///
96+
/// @param[in] id The identifier obtained via a previous call to
97+
/// `AddLifecycleListener`.
98+
///
99+
/// @return True if the listener could be removed.
100+
///
42101
bool RemoveLifecycleListener(UniqueID id);
43102

44103
private:
104+
friend class Display;
105+
45106
EGLDisplay display_ = EGL_NO_DISPLAY;
46107
EGLContext context_ = EGL_NO_CONTEXT;
47108
mutable RWMutex listeners_mutex_;
48109
std::map<UniqueID, LifecycleListener> listeners_ IPLR_GUARDED_BY(
49110
listeners_mutex_);
50111

112+
Context(EGLDisplay display, EGLContext context);
113+
51114
void DispatchLifecyleEvent(LifecycleEvent event) const;
52115

53116
Context(const Context&) = delete;

impeller/toolkit/egl/display.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ std::unique_ptr<Context> Display::CreateContext(const Config& config,
6666
return nullptr;
6767
}
6868

69-
return std::make_unique<Context>(display_, context);
69+
return std::unique_ptr<Context>(new Context(display_, context));
7070
}
7171

7272
std::unique_ptr<Config> Display::ChooseConfig(ConfigDescriptor config) const {
@@ -182,7 +182,7 @@ std::unique_ptr<Surface> Display::CreateWindowSurface(
182182
IMPELLER_LOG_EGL_ERROR;
183183
return nullptr;
184184
}
185-
return std::make_unique<Surface>(display_, surface);
185+
return std::unique_ptr<Surface>(new Surface(display_, surface));
186186
}
187187

188188
std::unique_ptr<Surface> Display::CreatePixelBufferSurface(const Config& config,
@@ -203,7 +203,7 @@ std::unique_ptr<Surface> Display::CreatePixelBufferSurface(const Config& config,
203203
IMPELLER_LOG_EGL_ERROR;
204204
return nullptr;
205205
}
206-
return std::make_unique<Surface>(display_, surface);
206+
return std::unique_ptr<Surface>(new Surface(display_, surface));
207207
}
208208

209209
} // namespace egl

impeller/toolkit/egl/display.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,83 @@ namespace egl {
1818
class Context;
1919
class Surface;
2020

21+
//------------------------------------------------------------------------------
22+
/// @brief A connection to an EGL display. Only one connection per
23+
/// application instance is sufficient.
24+
///
25+
/// The display connection is used to first choose a config from
26+
/// among the available, create a context from that config, and then
27+
/// use that context with a surface on one (and only one) thread at
28+
/// a time.
29+
///
2130
class Display {
2231
public:
2332
Display();
2433

2534
virtual ~Display();
2635

36+
//----------------------------------------------------------------------------
37+
/// @return True if the display connection is valid.
38+
///
2739
virtual bool IsValid() const;
2840

41+
//----------------------------------------------------------------------------
42+
/// @brief Choose a config that most closely matches a given descriptor.
43+
/// If there are no matches, this method returns `nullptr`.
44+
///
45+
/// @param[in] config The configuration
46+
///
47+
/// @return A config that matches a descriptor if one is available.
48+
/// `nullptr` otherwise.
49+
///
2950
virtual std::unique_ptr<Config> ChooseConfig(ConfigDescriptor config) const;
3051

52+
//----------------------------------------------------------------------------
53+
/// @brief Create a context with a supported config. The supported config
54+
/// can be obtained via a successful call to `ChooseConfig`.
55+
///
56+
/// @param[in] config The configuration.
57+
/// @param[in] share_context The share context. Context within the same
58+
/// share-group use the same handle table. The
59+
/// contexts should still only be used exclusively
60+
/// on each thread however.
61+
///
62+
/// @return A context if one can be created. `nullptr` otherwise.
63+
///
3164
virtual std::unique_ptr<Context> CreateContext(const Config& config,
3265
const Context* share_context);
3366

67+
//----------------------------------------------------------------------------
68+
/// @brief Create a window surface. The window is an opaque pointer whose
69+
/// value value is platform specific. For instance, ANativeWindow
70+
/// on Android.
71+
///
72+
/// @param[in] config A valid configuration. One can be obtained via
73+
/// `ChooseConfig`.
74+
/// @param[in] window An opaque pointer to a platform specific window
75+
/// handle.
76+
///
77+
/// @return A valid window surface if one can be created. `nullptr`
78+
/// otherwise.
79+
///
3480
virtual std::unique_ptr<Surface> CreateWindowSurface(
3581
const Config& config,
3682
EGLNativeWindowType window);
3783

84+
//----------------------------------------------------------------------------
85+
/// @brief Create an offscreen pixelbuffer surface. These are of limited
86+
/// use except in the context where applications need to render to
87+
/// a texture in an offscreen context. In such cases, a 1x1 pixel
88+
/// buffer surface is created to obtain a surface that can be used
89+
/// to make the context current on the background thread.
90+
///
91+
/// @param[in] config The configuration
92+
/// @param[in] width The width
93+
/// @param[in] height The height
94+
///
95+
/// @return A valid pixel buffer surface if one can be created. `nullptr`
96+
/// otherwise.
97+
///
3898
virtual std::unique_ptr<Surface>
3999
CreatePixelBufferSurface(const Config& config, size_t width, size_t height);
40100

impeller/toolkit/egl/egl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
namespace impeller {
1515
namespace egl {
1616

17+
//------------------------------------------------------------------------------
18+
/// @brief Creates a proc address resolver that resolves function pointers
19+
/// to EGL and OpenGL (ES) procs.
20+
///
21+
/// @return The resolver if one can be created.
22+
///
1723
std::function<void*(const char*)> CreateProcAddressResolver();
1824

1925
#define IMPELLER_LOG_EGL_ERROR LogEGLError(__FILE__, __LINE__);

impeller/toolkit/egl/surface.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,41 @@
1111
namespace impeller {
1212
namespace egl {
1313

14+
//------------------------------------------------------------------------------
15+
/// @brief An instance of an EGL surface. There is no ability to create
16+
/// surfaces directly. Instead, one must be created using a Display
17+
/// connection.
18+
///
1419
class Surface {
1520
public:
16-
Surface(EGLDisplay display, EGLSurface surface);
17-
1821
~Surface();
1922

23+
//----------------------------------------------------------------------------
24+
/// @return True if this is a valid surface.
25+
///
2026
bool IsValid() const;
2127

28+
//----------------------------------------------------------------------------
29+
/// @return Get the handle to the underlying surface.
30+
///
2231
const EGLSurface& GetHandle() const;
2332

33+
//----------------------------------------------------------------------------
34+
/// @brief Present the surface. For an offscreen pixel buffer surface,
35+
/// this is a no-op.
36+
///
37+
/// @return True if the surface could be presented.
38+
///
2439
bool Present() const;
2540

2641
private:
42+
friend class Display;
43+
2744
EGLDisplay display_ = EGL_NO_DISPLAY;
2845
EGLSurface surface_ = EGL_NO_SURFACE;
2946

47+
Surface(EGLDisplay display, EGLSurface surface);
48+
3049
Surface(const Surface&) = delete;
3150

3251
Surface& operator=(const Surface&) = delete;

0 commit comments

Comments
 (0)