Skip to content

Commit 50cae02

Browse files
author
Emmanuel Garcia
authored
Reland: Add RAII wrapper for EGLSurface (flutter#18977)
1 parent 4dabac9 commit 50cae02

File tree

4 files changed

+108
-115
lines changed

4 files changed

+108
-115
lines changed

shell/platform/android/android_context_gl.cc

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,47 @@ static bool TeardownContext(EGLDisplay display, EGLContext context) {
105105
return true;
106106
}
107107

108+
AndroidEGLSurface::AndroidEGLSurface(EGLSurface surface,
109+
EGLDisplay display,
110+
EGLContext context)
111+
: surface_(surface), display_(display), context_(context) {}
112+
113+
AndroidEGLSurface::~AndroidEGLSurface() {
114+
auto result = eglDestroySurface(display_, surface_);
115+
FML_DCHECK(result == EGL_TRUE);
116+
}
117+
118+
bool AndroidEGLSurface::IsValid() const {
119+
return surface_ != EGL_NO_SURFACE;
120+
}
121+
122+
bool AndroidEGLSurface::MakeCurrent() {
123+
if (eglMakeCurrent(display_, surface_, surface_, context_) != EGL_TRUE) {
124+
FML_LOG(ERROR) << "Could not make the context current";
125+
LogLastEGLError();
126+
return false;
127+
}
128+
return true;
129+
}
130+
131+
bool AndroidEGLSurface::SwapBuffers() {
132+
TRACE_EVENT0("flutter", "AndroidContextGL::SwapBuffers");
133+
return eglSwapBuffers(display_, surface_);
134+
}
135+
136+
SkISize AndroidEGLSurface::GetSize() const {
137+
EGLint width = 0;
138+
EGLint height = 0;
139+
140+
if (!eglQuerySurface(display_, surface_, EGL_WIDTH, &width) ||
141+
!eglQuerySurface(display_, surface_, EGL_HEIGHT, &height)) {
142+
FML_LOG(ERROR) << "Unable to query EGL surface size";
143+
LogLastEGLError();
144+
return SkISize::Make(0, 0);
145+
}
146+
return SkISize::Make(width, height);
147+
}
148+
108149
AndroidContextGL::AndroidContextGL(
109150
AndroidRenderingAPI rendering_api,
110151
fml::RefPtr<AndroidEnvironmentGL> environment)
@@ -161,25 +202,29 @@ AndroidContextGL::~AndroidContextGL() {
161202
}
162203
}
163204

164-
EGLSurface AndroidContextGL::CreateOnscreenSurface(
205+
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreateOnscreenSurface(
165206
fml::RefPtr<AndroidNativeWindow> window) const {
166207
EGLDisplay display = environment_->Display();
167208

168209
const EGLint attribs[] = {EGL_NONE};
169210

170-
return eglCreateWindowSurface(
211+
EGLSurface surface = eglCreateWindowSurface(
171212
display, config_, reinterpret_cast<EGLNativeWindowType>(window->handle()),
172213
attribs);
214+
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
173215
}
174216

175-
EGLSurface AndroidContextGL::CreateOffscreenSurface() const {
217+
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreateOffscreenSurface()
218+
const {
176219
// We only ever create pbuffer surfaces for background resource loading
177220
// contexts. We never bind the pbuffer to anything.
178221
EGLDisplay display = environment_->Display();
179222

180223
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
181224

182-
return eglCreatePbufferSurface(display, config_, attribs);
225+
EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
226+
return std::make_unique<AndroidEGLSurface>(surface, display,
227+
resource_context_);
183228
}
184229

185230
fml::RefPtr<AndroidEnvironmentGL> AndroidContextGL::Environment() const {
@@ -190,26 +235,6 @@ bool AndroidContextGL::IsValid() const {
190235
return valid_;
191236
}
192237

193-
bool AndroidContextGL::MakeCurrent(EGLSurface& surface) {
194-
if (eglMakeCurrent(environment_->Display(), surface, surface, context_) !=
195-
EGL_TRUE) {
196-
FML_LOG(ERROR) << "Could not make the context current";
197-
LogLastEGLError();
198-
return false;
199-
}
200-
return true;
201-
}
202-
203-
bool AndroidContextGL::ResourceMakeCurrent(EGLSurface& surface) {
204-
if (eglMakeCurrent(environment_->Display(), surface, surface,
205-
resource_context_) != EGL_TRUE) {
206-
FML_LOG(ERROR) << "Could not make the context current";
207-
LogLastEGLError();
208-
return false;
209-
}
210-
return true;
211-
}
212-
213238
bool AndroidContextGL::ClearCurrent() {
214239
if (eglGetCurrentContext() != context_) {
215240
return true;
@@ -223,30 +248,4 @@ bool AndroidContextGL::ClearCurrent() {
223248
return true;
224249
}
225250

226-
bool AndroidContextGL::SwapBuffers(EGLSurface& surface) {
227-
TRACE_EVENT0("flutter", "AndroidContextGL::SwapBuffers");
228-
return eglSwapBuffers(environment_->Display(), surface);
229-
}
230-
231-
SkISize AndroidContextGL::GetSize(EGLSurface& surface) {
232-
EGLint width = 0;
233-
EGLint height = 0;
234-
235-
if (!eglQuerySurface(environment_->Display(), surface, EGL_WIDTH, &width) ||
236-
!eglQuerySurface(environment_->Display(), surface, EGL_HEIGHT, &height)) {
237-
FML_LOG(ERROR) << "Unable to query EGL surface size";
238-
LogLastEGLError();
239-
return SkISize::Make(0, 0);
240-
}
241-
return SkISize::Make(width, height);
242-
}
243-
244-
bool AndroidContextGL::TeardownSurface(EGLSurface& surface) {
245-
if (surface != EGL_NO_SURFACE) {
246-
return eglDestroySurface(environment_->Display(), surface) == EGL_TRUE;
247-
}
248-
249-
return true;
250-
}
251-
252251
} // namespace flutter

shell/platform/android/android_context_gl.h

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,52 @@
1616

1717
namespace flutter {
1818

19+
//------------------------------------------------------------------------------
20+
/// Holds an `EGLSurface` reference.
21+
///
22+
///
23+
/// This can be used in conjuction to unique_ptr to provide better guarantees
24+
/// about the lifespam of the `EGLSurface` object.
25+
///
26+
class AndroidEGLSurface {
27+
public:
28+
AndroidEGLSurface(EGLSurface surface, EGLDisplay display, EGLContext context);
29+
~AndroidEGLSurface();
30+
31+
//----------------------------------------------------------------------------
32+
/// @return Whether the current `EGLSurface` reference is valid. That is,
33+
/// if
34+
/// the surface doesn't point to `EGL_NO_SURFACE`.
35+
///
36+
bool IsValid() const;
37+
38+
//----------------------------------------------------------------------------
39+
/// @brief Binds the EGLContext context to the current rendering thread
40+
/// and to the draw and read surface.
41+
///
42+
/// @return Whether the surface was made current.
43+
///
44+
bool MakeCurrent();
45+
46+
//----------------------------------------------------------------------------
47+
/// @brief This only applies to on-screen surfaces such as those created
48+
/// by `AndroidContextGL::CreateOnscreenSurface`.
49+
///
50+
/// @return Whether the EGL surface color buffer was swapped.
51+
///
52+
bool SwapBuffers();
53+
54+
//----------------------------------------------------------------------------
55+
/// @return The size of an `EGLSurface`.
56+
///
57+
SkISize GetSize() const;
58+
59+
private:
60+
const EGLSurface surface_;
61+
const EGLDisplay display_;
62+
const EGLContext context_;
63+
};
64+
1965
//------------------------------------------------------------------------------
2066
/// The Android context is used by `AndroidSurfaceGL` to create and manage
2167
/// EGL surfaces.
@@ -34,24 +80,18 @@ class AndroidContextGL : public AndroidContext {
3480
/// @brief Allocates an new EGL window surface that is used for on-screen
3581
/// pixels.
3682
///
37-
/// @attention Consumers must tear down the surface by calling
38-
/// `AndroidContextGL::TeardownSurface`.
39-
///
4083
/// @return The window surface.
4184
///
42-
EGLSurface CreateOnscreenSurface(
85+
std::unique_ptr<AndroidEGLSurface> CreateOnscreenSurface(
4386
fml::RefPtr<AndroidNativeWindow> window) const;
4487

4588
//----------------------------------------------------------------------------
4689
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
4790
/// offscreen current for texture uploads.
4891
///
49-
/// @attention Consumers must tear down the surface by calling
50-
/// `AndroidContextGL::TeardownSurface`.
51-
///
5292
/// @return The pbuffer surface.
5393
///
54-
EGLSurface CreateOffscreenSurface() const;
94+
std::unique_ptr<AndroidEGLSurface> CreateOffscreenSurface() const;
5595

5696
//----------------------------------------------------------------------------
5797
/// @return The Android environment that contains a reference to the
@@ -71,42 +111,6 @@ class AndroidContextGL : public AndroidContext {
71111
///
72112
bool ClearCurrent();
73113

74-
//----------------------------------------------------------------------------
75-
/// @brief Binds the EGLContext context to the current rendering thread
76-
/// and to the draw and read surface.
77-
///
78-
/// @return Whether the surface was made current.
79-
///
80-
bool MakeCurrent(EGLSurface& surface);
81-
82-
//----------------------------------------------------------------------------
83-
/// @brief Binds the resource EGLContext context to the current rendering
84-
/// thread and to the draw and read surface.
85-
///
86-
/// @return Whether the surface was made current.
87-
///
88-
bool ResourceMakeCurrent(EGLSurface& surface);
89-
90-
//----------------------------------------------------------------------------
91-
/// @brief This only applies to on-screen surfaces such as those created
92-
/// by `AndroidContextGL::CreateOnscreenSurface`.
93-
///
94-
/// @return Whether the EGL surface color buffer was swapped.
95-
///
96-
bool SwapBuffers(EGLSurface& surface);
97-
98-
//----------------------------------------------------------------------------
99-
/// @return The size of an `EGLSurface`.
100-
///
101-
SkISize GetSize(EGLSurface& surface);
102-
103-
//----------------------------------------------------------------------------
104-
/// @brief Destroys an `EGLSurface`.
105-
///
106-
/// @return Whether the surface was destroyed.
107-
///
108-
bool TeardownSurface(EGLSurface& surface);
109-
110114
private:
111115
fml::RefPtr<AndroidEnvironmentGL> environment_;
112116
EGLConfig config_;

shell/platform/android/android_surface_gl.cc

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,13 @@ AndroidSurfaceGL::AndroidSurfaceGL(
2020
std::static_pointer_cast<AndroidContextGL>(android_context);
2121
// Acquire the offscreen surface.
2222
offscreen_surface_ = android_context_->CreateOffscreenSurface();
23-
if (offscreen_surface_ == EGL_NO_SURFACE) {
23+
if (!offscreen_surface_->IsValid()) {
2424
offscreen_surface_ = nullptr;
2525
}
2626
external_view_embedder_ = std::make_unique<AndroidExternalViewEmbedder>();
2727
}
2828

29-
AndroidSurfaceGL::~AndroidSurfaceGL() {
30-
if (offscreen_surface_) {
31-
android_context_->TeardownSurface(offscreen_surface_);
32-
offscreen_surface_ = nullptr;
33-
}
34-
if (onscreen_surface_) {
35-
android_context_->TeardownSurface(onscreen_surface_);
36-
onscreen_surface_ = nullptr;
37-
}
38-
}
29+
AndroidSurfaceGL::~AndroidSurfaceGL() = default;
3930

4031
void AndroidSurfaceGL::TeardownOnScreenContext() {
4132
android_context_->ClearCurrent();
@@ -58,25 +49,24 @@ bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
5849
FML_DCHECK(onscreen_surface_);
5950
FML_DCHECK(native_window_);
6051

61-
if (size == android_context_->GetSize(onscreen_surface_)) {
52+
if (size == onscreen_surface_->GetSize()) {
6253
return true;
6354
}
6455

6556
android_context_->ClearCurrent();
66-
android_context_->TeardownSurface(onscreen_surface_);
6757

6858
onscreen_surface_ = android_context_->CreateOnscreenSurface(native_window_);
69-
if (!onscreen_surface_ || onscreen_surface_ == EGL_NO_SURFACE) {
59+
if (onscreen_surface_->IsValid()) {
7060
FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
7161
return false;
7262
}
73-
android_context_->MakeCurrent(onscreen_surface_);
63+
onscreen_surface_->MakeCurrent();
7464
return true;
7565
}
7666

7767
bool AndroidSurfaceGL::ResourceContextMakeCurrent() {
7868
FML_DCHECK(IsValid());
79-
return android_context_->ResourceMakeCurrent(offscreen_surface_);
69+
return offscreen_surface_->MakeCurrent();
8070
}
8171

8272
bool AndroidSurfaceGL::ResourceContextClearCurrent() {
@@ -91,7 +81,7 @@ bool AndroidSurfaceGL::SetNativeWindow(
9181
native_window_ = window;
9282
// Create the onscreen surface.
9383
onscreen_surface_ = android_context_->CreateOnscreenSurface(window);
94-
if (onscreen_surface_ == EGL_NO_SURFACE) {
84+
if (!onscreen_surface_->IsValid()) {
9585
return false;
9686
}
9787
return true;
@@ -101,7 +91,7 @@ std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
10191
FML_DCHECK(IsValid());
10292
FML_DCHECK(onscreen_surface_);
10393
auto default_context_result = std::make_unique<GLContextDefaultResult>(
104-
android_context_->MakeCurrent(onscreen_surface_));
94+
onscreen_surface_->MakeCurrent());
10595
return std::move(default_context_result);
10696
}
10797

@@ -113,7 +103,7 @@ bool AndroidSurfaceGL::GLContextClearCurrent() {
113103
bool AndroidSurfaceGL::GLContextPresent() {
114104
FML_DCHECK(IsValid());
115105
FML_DCHECK(onscreen_surface_);
116-
return android_context_->SwapBuffers(onscreen_surface_);
106+
return onscreen_surface_->SwapBuffers();
117107
}
118108

119109
intptr_t AndroidSurfaceGL::GLContextFBO() const {

shell/platform/android/android_surface_gl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
6464
fml::RefPtr<AndroidNativeWindow> native_window_;
6565
std::unique_ptr<AndroidExternalViewEmbedder> external_view_embedder_;
6666
std::shared_ptr<AndroidContextGL> android_context_;
67-
EGLSurface onscreen_surface_;
68-
EGLSurface offscreen_surface_;
67+
std::unique_ptr<AndroidEGLSurface> onscreen_surface_;
68+
std::unique_ptr<AndroidEGLSurface> offscreen_surface_;
6969

7070
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL);
7171
};

0 commit comments

Comments
 (0)