Flutter Engine
The Flutter Engine
android_surface_gl_skia.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/shell/platform/android/android_surface_gl_skia.h"
6
7#include <GLES/gl.h>
8#include <utility>
9
10#include "flutter/fml/logging.h"
11#include "flutter/fml/memory/ref_ptr.h"
12#include "flutter/shell/platform/android/android_egl_surface.h"
13#include "flutter/shell/platform/android/android_shell_holder.h"
14
15namespace flutter {
16
17namespace {
18// GL renderer string prefix used by the Android emulator GLES implementation.
19constexpr char kEmulatorRendererPrefix[] =
20 "Android Emulator OpenGL ES Translator";
21} // anonymous namespace
22
24 const std::shared_ptr<AndroidContextGLSkia>& android_context)
25 : android_context_(android_context),
26 native_window_(nullptr),
27 onscreen_surface_(nullptr),
28 offscreen_surface_(nullptr) {
29 // Acquire the offscreen surface.
30 offscreen_surface_ = android_context_->CreateOffscreenSurface();
31 if (!offscreen_surface_->IsValid()) {
32 offscreen_surface_ = nullptr;
33 }
34}
35
37
39 // When the onscreen surface is destroyed, the context and the surface
40 // instance should be deleted. Issue:
41 // https://github.com/flutter/flutter/issues/64414
42 android_context_->ClearCurrent();
43 onscreen_surface_ = nullptr;
44}
45
47 return offscreen_surface_ && android_context_->IsValid();
48}
49
51 GrDirectContext* gr_context) {
52 if (gr_context) {
53 return std::make_unique<GPUSurfaceGLSkia>(sk_ref_sp(gr_context), this,
54 true);
55 } else {
56 sk_sp<GrDirectContext> main_skia_context =
57 android_context_->GetMainSkiaContext();
58 if (!main_skia_context) {
59 main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this);
60 android_context_->SetMainSkiaContext(main_skia_context);
61 }
62 return std::make_unique<GPUSurfaceGLSkia>(main_skia_context, this, true);
63 }
64}
65
68 FML_DCHECK(onscreen_surface_);
69 FML_DCHECK(native_window_);
70
71 if (size == onscreen_surface_->GetSize()) {
72 return true;
73 }
74
75 android_context_->ClearCurrent();
76
77 // Ensure the destructor is called since it destroys the `EGLSurface` before
78 // creating a new onscreen surface.
79 onscreen_surface_ = nullptr;
80 onscreen_surface_ = android_context_->CreateOnscreenSurface(native_window_);
81 if (!onscreen_surface_->IsValid()) {
82 FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
83 return false;
84 }
85 onscreen_surface_->MakeCurrent();
86 return true;
87}
88
91 auto status = offscreen_surface_->MakeCurrent();
93}
94
97 EGLBoolean result = eglMakeCurrent(eglGetCurrentDisplay(), EGL_NO_SURFACE,
98 EGL_NO_SURFACE, EGL_NO_CONTEXT);
99 return result == EGL_TRUE;
100}
101
106 native_window_ = window;
107 // Ensure the destructor is called since it destroys the `EGLSurface` before
108 // creating a new onscreen surface.
109 onscreen_surface_ = nullptr;
110 // Create the onscreen surface.
111 onscreen_surface_ = android_context_->CreateOnscreenSurface(window);
112 if (!onscreen_surface_->IsValid()) {
113 return false;
114 }
115 return true;
116}
117
118std::unique_ptr<GLContextResult> AndroidSurfaceGLSkia::GLContextMakeCurrent() {
120 FML_DCHECK(onscreen_surface_);
121 auto status = onscreen_surface_->MakeCurrent();
122 auto default_context_result = std::make_unique<GLContextDefaultResult>(
124 return std::move(default_context_result);
125}
126
129 return android_context_->ClearCurrent();
130}
131
133 const {
136 res.supports_readback = true;
137 res.supports_partial_repaint = onscreen_surface_->SupportsPartialRepaint();
138 res.existing_damage = onscreen_surface_->InitialDamage();
139 // Some devices (Pixel2 XL) needs EGL_KHR_partial_update rect aligned to 4,
140 // otherwise there are glitches
141 // (https://github.com/flutter/flutter/issues/97482#)
142 // Larger alignment might also be beneficial for tile base renderers.
145
146 return res;
147}
148
150 const std::optional<SkIRect>& region) {
152 onscreen_surface_->SetDamageRegion(region);
153}
154
157 FML_DCHECK(onscreen_surface_);
158 if (present_info.presentation_time) {
159 onscreen_surface_->SetPresentationTime(*present_info.presentation_time);
160 }
161 return onscreen_surface_->SwapBuffers(present_info.frame_damage);
162}
163
166 // The default window bound framebuffer on Android.
167 return GLFBOInfo{
168 .fbo_id = 0,
169 .existing_damage = onscreen_surface_->InitialDamage(),
170 };
171}
172
173// |GPUSurfaceGLDelegate|
175 // This is a workaround for a bug in the Android emulator EGL/GLES
176 // implementation. Some versions of the emulator will not update the
177 // GL version string when the process switches to a new EGL context
178 // unless the EGL context is being made current for the first time.
179 // The inaccurate version string will be rejected by Skia when it
180 // tries to build the GrGLInterface. Flutter can work around this
181 // by creating a new context, making it current to force an update
182 // of the version, and then reverting to the previous context.
183 const char* gl_renderer =
184 reinterpret_cast<const char*>(glGetString(GL_RENDERER));
185 if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix,
186 strlen(kEmulatorRendererPrefix)) == 0) {
187 EGLContext new_context = android_context_->CreateNewContext();
188 if (new_context != EGL_NO_CONTEXT) {
189 EGLContext old_context = eglGetCurrentContext();
190 EGLDisplay display = eglGetCurrentDisplay();
191 EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW);
192 EGLSurface read_surface = eglGetCurrentSurface(EGL_READ);
193 [[maybe_unused]] EGLBoolean result =
194 eglMakeCurrent(display, draw_surface, read_surface, new_context);
195 FML_DCHECK(result == EGL_TRUE);
196 result = eglMakeCurrent(display, draw_surface, read_surface, old_context);
197 FML_DCHECK(result == EGL_TRUE);
198 result = eglDestroyContext(display, new_context);
199 FML_DCHECK(result == EGL_TRUE);
200 }
201 }
202
204}
205
207 if (!onscreen_surface_ || !onscreen_surface_->IsValid()) {
208 onscreen_surface_ = android_context_->CreatePbufferSurface();
209 }
210 sk_sp<GrDirectContext> main_skia_context =
211 android_context_->GetMainSkiaContext();
212 if (!main_skia_context) {
213 main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this);
214 android_context_->SetMainSkiaContext(main_skia_context);
215 }
216
217 return std::make_unique<GPUSurfaceGLSkia>(main_skia_context, this, true);
218}
219
220} // namespace flutter
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
bool GLContextPresent(const GLPresentInfo &present_info) override
std::unique_ptr< Surface > CreateGPUSurface(GrDirectContext *gr_context) override
bool OnScreenSurfaceResize(const SkISize &size) override
void GLContextSetDamageRegion(const std::optional< SkIRect > &region) override
virtual std::unique_ptr< Surface > CreateSnapshotSurface() override
sk_sp< const GrGLInterface > GetGLInterface() const override
bool SetNativeWindow(fml::RefPtr< AndroidNativeWindow > window) override
AndroidSurfaceGLSkia(const std::shared_ptr< AndroidContextGLSkia > &android_context)
std::unique_ptr< GLContextResult > GLContextMakeCurrent() override
SurfaceFrame::FramebufferInfo GLContextFramebufferInfo() const override
GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override
virtual sk_sp< const GrGLInterface > GetGLInterface() const
static sk_sp< GrDirectContext > MakeGLContext(GPUSurfaceGLDelegate *delegate)
GLFWwindow * window
Definition: main.cc:45
GAsyncResult * result
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_DCHECK(condition)
Definition: logging.h:103
ClipOpAndAA opAA SkRegion region
Definition: SkRecords.h:238
@ kFailure
Failed to make the egl context for the surface current.
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: SkSize.h:16
const std::optional< SkIRect > & frame_damage
std::optional< fml::TimePoint > presentation_time
std::optional< SkIRect > existing_damage
Definition: surface_frame.h:56
#define ERROR(message)
Definition: elf_loader.cc:260