Flutter Engine
The Flutter Engine
image_external_texture_gl.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/image_external_texture_gl.h"
6
7#include <android/hardware_buffer_jni.h>
8#include <android/sensor.h>
9
10#include "flutter/common/graphics/texture.h"
11#include "flutter/impeller/core/formats.h"
12#include "flutter/impeller/display_list/dl_image_impeller.h"
13#include "flutter/impeller/toolkit/android/hardware_buffer.h"
14#include "flutter/impeller/toolkit/egl/image.h"
15#include "flutter/impeller/toolkit/gles/texture.h"
21
22namespace flutter {
23
25 int64_t id,
26 const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
27 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
28 : ImageExternalTexture(id, image_texture_entry, jni_facade) {}
29
32 // TODO(johnmccurtchan): We currently display the first frame after an
33 // attach-detach cycle as blank. There seems to be an issue on some
34 // devices where ImageReaders/Images from before the detach aren't
35 // valid after the attach. According to Android folks this doesn't
36 // match the spec. Revisit this in the future.
37 // See https://github.com/flutter/flutter/issues/142978 and
38 // https://github.com/flutter/flutter/issues/139039.
40 }
41}
42
44 const SkRect& bounds,
45 PaintContext& context) {
46 AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer);
47 std::optional<HardwareBufferKey> key =
49 latest_hardware_buffer);
50 auto existing_image = image_lru_.FindImage(key);
51 if (existing_image != nullptr) {
52 dl_image_ = existing_image;
53 return;
54 }
55
56 auto egl_image = CreateEGLImage(latest_hardware_buffer);
57 if (!egl_image.is_valid()) {
58 return;
59 }
60
61 dl_image_ = CreateDlImage(context, bounds, key, std::move(egl_image));
62 if (key.has_value()) {
64 }
65}
66
68 const SkRect& bounds) {
70 if (image.is_null()) {
71 return;
72 }
73 JavaLocalRef hardware_buffer = HardwareBufferFor(image);
74 UpdateImage(hardware_buffer, bounds, context);
75 CloseHardwareBuffer(hardware_buffer);
76}
77
80 gl_entries_.clear();
81}
82
84 AHardwareBuffer* hardware_buffer) {
85 if (hardware_buffer == nullptr) {
87 }
88
89 EGLDisplay display = eglGetCurrentDisplay();
90 FML_CHECK(display != EGL_NO_DISPLAY);
91
92 EGLClientBuffer client_buffer =
93 impeller::android::GetProcTable().eglGetNativeClientBufferANDROID(
94 hardware_buffer);
95 FML_DCHECK(client_buffer != nullptr);
96 if (client_buffer == nullptr) {
97 FML_LOG(ERROR) << "eglGetNativeClientBufferAndroid returned null.";
99 }
100
103 eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
104 client_buffer, 0),
105 display};
106
107 return impeller::UniqueEGLImageKHR(maybe_image);
108}
109
111 const std::shared_ptr<AndroidContextGLSkia>& context,
112 int64_t id,
113 const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
114 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
115 : ImageExternalTextureGL(id, image_texture_entry, jni_facade) {}
116
117void ImageExternalTextureGLSkia::Attach(PaintContext& context) {
119 // After this call state_ will be AttachmentState::kAttached and egl_image_
120 // will have been created if we still have an Image associated with us.
122 }
123}
124
125void ImageExternalTextureGLSkia::Detach() {
127}
128
129void ImageExternalTextureGLSkia::BindImageToTexture(
131 GLuint tex) {
132 if (!image.is_valid() || tex == 0) {
133 return;
134 }
135 glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
136 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
137 (GLeglImageOES)image.get().image);
138}
139
140sk_sp<flutter::DlImage> ImageExternalTextureGLSkia::CreateDlImage(
141 PaintContext& context,
142 const SkRect& bounds,
143 std::optional<HardwareBufferKey> id,
144 impeller::UniqueEGLImageKHR&& egl_image) {
145 GLuint texture_name;
146 glGenTextures(1, &texture_name);
147 auto gl_texture = impeller::GLTexture{texture_name};
148 impeller::UniqueGLTexture unique_texture;
149 unique_texture.reset(gl_texture);
150
151 BindImageToTexture(egl_image, unique_texture.get().texture_name);
152 GrGLTextureInfo textureInfo = {
153 GL_TEXTURE_EXTERNAL_OES, unique_texture.get().texture_name, GL_RGBA8_OES};
154 auto backendTexture =
156
157 gl_entries_[id.value_or(0)] = GlEntry{.egl_image = std::move(egl_image),
158 .texture = std::move(unique_texture)};
160 context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin,
162}
163
165 const std::shared_ptr<impeller::ContextGLES>& context,
166 int64_t id,
167 const fml::jni::ScopedJavaGlobalRef<jobject>& image_textury_entry,
168 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
169 : ImageExternalTextureGL(id, image_textury_entry, jni_facade),
170 impeller_context_(context) {}
171
172void ImageExternalTextureGLImpeller::Detach() {}
173
174void ImageExternalTextureGLImpeller::Attach(PaintContext& context) {
177 }
178}
179
180sk_sp<flutter::DlImage> ImageExternalTextureGLImpeller::CreateDlImage(
181 PaintContext& context,
182 const SkRect& bounds,
183 std::optional<HardwareBufferKey> id,
184 impeller::UniqueEGLImageKHR&& egl_image) {
189 desc.size = {static_cast<int>(bounds.width()),
190 static_cast<int>(bounds.height())};
191 desc.mip_count = 1;
192 auto texture = std::make_shared<impeller::TextureGLES>(
193 impeller_context_->GetReactor(), desc,
195 texture->SetCoordinateSystem(
197 if (!texture->Bind()) {
198 return nullptr;
199 }
200 // Associate the hardware buffer image with the texture.
201 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
202 (GLeglImageOES)egl_image.get().image);
203 gl_entries_[id.value_or(0)] = GlEntry{
204 .egl_image = std::move(egl_image),
205 };
207}
208
209} // namespace flutter
struct AHardwareBuffer AHardwareBuffer
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
static sk_sp< DlImage > Make(const SkImage *image)
Definition: dl_image.cc:11
ImageExternalTextureGLImpeller(const std::shared_ptr< impeller::ContextGLES > &context, int64_t id, const fml::jni::ScopedJavaGlobalRef< jobject > &hardware_buffer_texture_entry, const std::shared_ptr< PlatformViewAndroidJNI > &jni_facade)
ImageExternalTextureGLSkia(const std::shared_ptr< AndroidContextGLSkia > &context, int64_t id, const fml::jni::ScopedJavaGlobalRef< jobject > &image_textury_entry, const std::shared_ptr< PlatformViewAndroidJNI > &jni_facade)
void ProcessFrame(PaintContext &context, const SkRect &bounds) override
void UpdateImage(JavaLocalRef &hardware_buffer, const SkRect &bounds, PaintContext &context)
virtual sk_sp< flutter::DlImage > CreateDlImage(PaintContext &context, const SkRect &bounds, std::optional< HardwareBufferKey > id, impeller::UniqueEGLImageKHR &&egl_image)=0
impeller::UniqueEGLImageKHR CreateEGLImage(AHardwareBuffer *buffer)
std::unordered_map< HardwareBufferKey, GlEntry > gl_entries_
ImageExternalTextureGL(int64_t id, const fml::jni::ScopedJavaGlobalRef< jobject > &image_textury_entry, const std::shared_ptr< PlatformViewAndroidJNI > &jni_facade)
void Attach(PaintContext &context) override
AHardwareBuffer * AHardwareBufferFor(const fml::jni::JavaRef< jobject > &hardware_buffer)
JavaLocalRef HardwareBufferFor(const fml::jni::JavaRef< jobject > &image)
void CloseHardwareBuffer(const fml::jni::JavaRef< jobject > &hardware_buffer)
sk_sp< flutter::DlImage > dl_image_
HardwareBufferKey AddImage(const sk_sp< flutter::DlImage > &image, HardwareBufferKey key)
Add a new image to the cache with a key, returning the key of the LRU entry that was removed.
Definition: image_lru.cc:42
sk_sp< flutter::DlImage > FindImage(std::optional< HardwareBufferKey > key)
Retrieve the image associated with the given [key], or nullptr.
Definition: image_lru.cc:9
void Clear()
Remove all entires from the image cache.
Definition: image_lru.cc:60
void reset(const T &value=Traits::InvalidValue())
Definition: unique_object.h:62
const T & get() const
Definition: unique_object.h:87
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
std::optional< uint64_t > GetSystemUniqueID() const
Get the system wide unique ID of the hardware buffer if possible. This is only available on Android A...
T * get() const
Definition: SkRefCnt.h:303
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
#define FML_DCHECK(condition)
Definition: logging.h:103
FlTexture * texture
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
SK_API sk_sp< SkImage > BorrowTextureFrom(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImage > image
Definition: SkRecords.h:269
std::nullptr_t JavaLocalRef
const ProcTable & GetProcTable()
Definition: proc_table.cc:12
fml::UniqueObject< EGLImageKHRWithDisplay, EGLImageKHRWithDisplayTraits > UniqueEGLImageKHR
Definition: image.h:73
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
const uintptr_t id
#define ERROR(message)
Definition: elf_loader.cc:260