9 #include "flutter/fml/closure.h"
10 #include "flutter/fml/trace_event.h"
23 static constexpr
const char*
kVertShader = R
"IMPELLER_SHADER(#version 100
25 precision mediump float;
27 attribute vec2 aPosition;
28 attribute vec2 aTexCoord;
30 varying vec2 vTexCoord;
33 gl_Position = vec4(aPosition, 0.0, 1.0);
34 vTexCoord = aTexCoord;
39 static constexpr
const char*
kFragShader = R
"IMPELLER_SHADER(#version 100
41 #extension GL_OES_EGL_image_external : require
43 precision mediump float;
45 uniform samplerExternalOES uTexture;
46 uniform mat4 uUVTransformation;
48 varying vec2 vTexCoord;
51 vec2 texture_coords = (uUVTransformation * vec4(vTexCoord, 0, 1)).xy;
52 gl_FragColor = texture2D(uTexture, texture_coords);
58 auto egl_display = std::make_unique<egl::Display>();
59 if (!egl_display->IsValid()) {
61 <<
"Could not create EGL display for external texture interop.";
72 auto egl_config = egl_display->ChooseConfig(egl_config_desc);
75 <<
"Could not choose EGL config for external texture interop.";
79 auto egl_surface = egl_display->CreatePixelBufferSurface(*egl_config, 1u, 1u);
80 auto egl_context = egl_display->CreateContext(*egl_config,
nullptr);
82 if (!egl_surface || !egl_context) {
83 VALIDATION_LOG <<
"Could not create EGL surface and/or context for "
84 "external texture interop.";
89 if (!egl_context->MakeCurrent(*egl_surface)) {
97 egl_context->ClearCurrent();
103 auto vert_shader = gl->CreateShader(GL_VERTEX_SHADER);
104 auto frag_shader = gl->CreateShader(GL_FRAGMENT_SHADER);
109 gl->ShaderSource(vert_shader, 1u, &
kVertShader, &vert_shader_size);
110 gl->ShaderSource(frag_shader, 1u, &
kFragShader, &frag_shader_size);
112 gl->CompileShader(vert_shader);
113 gl->CompileShader(frag_shader);
115 GLint vert_status = GL_FALSE;
116 GLint frag_status = GL_FALSE;
118 gl->GetShaderiv(vert_shader, GL_COMPILE_STATUS, &vert_status);
119 gl->GetShaderiv(frag_shader, GL_COMPILE_STATUS, &frag_status);
121 FML_CHECK(vert_status == GL_TRUE);
122 FML_CHECK(frag_status == GL_TRUE);
124 program_ = gl->CreateProgram();
125 gl->AttachShader(program_, vert_shader);
126 gl->AttachShader(program_, frag_shader);
131 gl->LinkProgram(program_);
133 GLint link_status = GL_FALSE;
134 gl->GetProgramiv(program_, GL_LINK_STATUS, &link_status);
135 FML_CHECK(link_status == GL_TRUE);
137 texture_uniform_location_ = gl->GetUniformLocation(program_,
"uTexture");
138 uv_transformation_location_ =
139 gl->GetUniformLocation(program_,
"uUVTransformation");
141 gl->DeleteShader(vert_shader);
142 gl->DeleteShader(frag_shader);
144 egl_context->ClearCurrent();
147 egl_display_ = std::move(egl_display);
148 egl_context_ = std::move(egl_context);
149 egl_surface_ = std::move(egl_surface);
158 gl_->DeleteProgram(program_);
166 const EGLDisplay& display,
173 EGLClientBuffer client_buffer =
177 if (!client_buffer) {
179 <<
"Could not get client buffer from Android hardware buffer.";
183 auto image = ::eglCreateImageKHR(display,
185 EGL_NATIVE_BUFFER_ANDROID,
200 TRACE_EVENT0(
"impeller", __FUNCTION__);
205 FML_DCHECK(egl_context_->IsCurrent());
209 if (!dst_egl_image.is_valid()) {
214 const auto& gl = *gl_;
216 GLuint dst_gl_texture = GL_NONE;
217 gl.GenTextures(1u, &dst_gl_texture);
218 gl.BindTexture(GL_TEXTURE_2D, dst_gl_texture);
219 gl.EGLImageTargetTexture2DOES(GL_TEXTURE_2D, dst_egl_image.get().image);
221 GLuint offscreen_fbo = GL_NONE;
222 gl.GenFramebuffers(1u, &offscreen_fbo);
223 gl.BindFramebuffer(GL_FRAMEBUFFER, offscreen_fbo);
224 gl.FramebufferTexture2D(GL_FRAMEBUFFER,
225 GL_COLOR_ATTACHMENT0,
231 FML_CHECK(gl.CheckFramebufferStatus(GL_FRAMEBUFFER) ==
232 GL_FRAMEBUFFER_COMPLETE);
234 gl.Disable(GL_BLEND);
235 gl.Disable(GL_SCISSOR_TEST);
236 gl.Disable(GL_DITHER);
237 gl.Disable(GL_CULL_FACE);
238 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
240 gl.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
241 gl.Clear(GL_COLOR_BUFFER_BIT);
244 gl.Viewport(0, 0, fb_size.width, fb_size.height);
246 gl.UseProgram(program_);
260 static constexpr
const VertexData kVertData[] = {
269 GLuint vertex_buffer = GL_NONE;
270 gl.GenBuffers(1u, &vertex_buffer);
271 gl.BindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
272 gl.BufferData(GL_ARRAY_BUFFER,
sizeof(kVertData), kVertData, GL_STATIC_DRAW);
275 gl.VertexAttribPointer(
277 reinterpret_cast<void*
>(offsetof(VertexData, position)));
278 gl.VertexAttribPointer(
280 reinterpret_cast<void*
>(offsetof(VertexData, tex_coord)));
282 gl.ActiveTexture(GL_TEXTURE0);
284 gl.TexParameteri(src_texture.
target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
285 gl.TexParameteri(src_texture.
target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
286 gl.TexParameteri(src_texture.
target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
287 gl.TexParameteri(src_texture.
target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
288 gl.Uniform1i(texture_uniform_location_, 0u);
292 gl.UniformMatrix4fv(uv_transformation_location_, 1u, GL_FALSE,
293 reinterpret_cast<GLfloat*
>(&gl_uv_transformation));
295 gl.DrawArrays(GL_TRIANGLE_FAN, 0, 4);
297 gl.UseProgram(GL_NONE);
301 gl.DeleteFramebuffers(1u, &offscreen_fbo);
302 gl.DeleteTextures(1u, &dst_gl_texture);
303 gl.DeleteBuffers(1u, &vertex_buffer);
308 eglSwapBuffers(egl_display_->GetHandle(), egl_surface_->GetHandle());
314 FML_DCHECK(is_valid_);
319 : context_(trampoline.egl_context_.get()),
320 surface_(trampoline.egl_surface_.get()) {
A texture source that wraps an instance of AHardwareBuffer.
const android::HardwareBuffer * GetBackingStore() const
const TextureDescriptor & GetTextureDescriptor() const
Gets the texture descriptor for this image source.
AHardwareBuffer * GetHandle() const
bool MakeCurrent(const Surface &surface) const
Make the context current on the calling thread. It is the caller responsibility to ensure that any co...
bool ClearCurrent() const
Clear the thread association of this context.
An RAII object that makes the trampolines EGL context current when constructed and clears the EGL bin...
~AutoTrampolineContext()
Destroys the object and clears the previous EGL binding.
AutoTrampolineContext(const Trampoline &trampoline)
Constructs a new instance and makes the trampolines EGL context current on the calling thread.
An object used to interoperate between OpenGL and Vulkan.
~Trampoline()
Destroys the trampoline. There are no threading restrictions. EGL contexts on already bound to the ca...
bool BlitTextureOpenGLToVulkan(const GLTextureInfo &src_texture, const AHBTextureSourceVK &dst_texture) const
Perform a blit operation from the source OpenGL texture to a target Vulkan texture.
bool IsValid() const
Determines if this is a valid trampoline. There is no error recovery mechanism if a trampoline cannot...
AutoTrampolineContext MakeCurrentContext() const
Make the EGL context associated with this trampoline current on the calling thread.
Trampoline()
Constructs a new trampoline. It is recommended that these objects be cached and reused for all conver...
const ProcTable & GetProcTable()
std::function< void *(const char *)> CreateProcAddressResolver()
Creates a proc address resolver that resolves function pointers to EGL and OpenGL (ES) procs.
static GLuint kAttributeIndexTexCoord
static GLuint kAttributeIndexPosition
static UniqueEGLImageKHR CreateEGLImageFromAHBTexture(const EGLDisplay &display, const AHBTextureSourceVK &to_texture)
static constexpr const char * kFragShader
static constexpr const char * kVertShader
fml::UniqueObject< EGLImageKHRWithDisplay, EGLImageKHRWithDisplayTraits > UniqueEGLImageKHR
Describes an OpenGL texture along with information on how to sample from it.