Add support for HardwareBuffer backed Android Platform Views under Impeller/GLES (flutter/engine#44617)
- Implement Impeller/GLES code paths. - A couple of fixes for EXTERNAL_OES textures via bdero@
This commit is contained in:
@@ -269,6 +269,8 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
|
||||
CreateDefaultPipeline<BlendPipeline>(*context_);
|
||||
texture_pipelines_[default_options_] =
|
||||
CreateDefaultPipeline<TexturePipeline>(*context_);
|
||||
texture_external_pipelines_[default_options_] =
|
||||
CreateDefaultPipeline<TextureExternalPipeline>(*context_);
|
||||
position_uv_pipelines_[default_options_] =
|
||||
CreateDefaultPipeline<PositionUVPipeline>(*context_);
|
||||
tiled_texture_pipelines_[default_options_] =
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/entity/texture_fill.frag.h"
|
||||
#include "impeller/entity/texture_fill.vert.h"
|
||||
#include "impeller/entity/texture_fill_external.frag.h"
|
||||
#include "impeller/geometry/constants.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
@@ -109,12 +110,16 @@ bool TextureContents::Render(const ContentContext& renderer,
|
||||
RenderPass& pass) const {
|
||||
using VS = TextureFillVertexShader;
|
||||
using FS = TextureFillFragmentShader;
|
||||
using FSExternal = TextureFillExternalFragmentShader;
|
||||
|
||||
if (destination_rect_.size.IsEmpty() || source_rect_.IsEmpty() ||
|
||||
texture_ == nullptr || texture_->GetSize().IsEmpty()) {
|
||||
return true; // Nothing to render.
|
||||
}
|
||||
|
||||
bool is_external_texture =
|
||||
texture_->GetTextureDescriptor().type == TextureType::kTextureExternalOES;
|
||||
|
||||
// Expand the source rect by half a texel, which aligns sampled texels to the
|
||||
// pixel grid if the source rect is the same size as the destination rect.
|
||||
auto texture_coords =
|
||||
@@ -149,8 +154,7 @@ bool TextureContents::Render(const ContentContext& renderer,
|
||||
}
|
||||
pipeline_options.primitive_type = PrimitiveType::kTriangleStrip;
|
||||
|
||||
if (texture_->GetTextureDescriptor().type ==
|
||||
TextureType::kTextureExternalOES) {
|
||||
if (is_external_texture) {
|
||||
cmd.pipeline = renderer.GetTextureExternalPipeline(pipeline_options);
|
||||
} else {
|
||||
cmd.pipeline = renderer.GetTexturePipeline(pipeline_options);
|
||||
@@ -158,9 +162,17 @@ bool TextureContents::Render(const ContentContext& renderer,
|
||||
cmd.stencil_reference = entity.GetStencilDepth();
|
||||
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
|
||||
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
|
||||
FS::BindTextureSampler(cmd, texture_,
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
sampler_descriptor_));
|
||||
if (is_external_texture) {
|
||||
FSExternal::BindSAMPLEREXTERNALOESTextureSampler(
|
||||
cmd, texture_,
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
sampler_descriptor_));
|
||||
} else {
|
||||
FS::BindTextureSampler(
|
||||
cmd, texture_,
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
sampler_descriptor_));
|
||||
}
|
||||
pass.AddCommand(std::move(cmd));
|
||||
|
||||
return true;
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <android/hardware_buffer_jni.h>
|
||||
#include <android/sensor.h>
|
||||
#include "flutter/common/graphics/texture.h"
|
||||
#include "impeller/core/formats.h"
|
||||
#include "impeller/display_list/dl_image_impeller.h"
|
||||
#include "impeller/renderer/backend/gles/texture_gles.h"
|
||||
#include "impeller/toolkit/egl/image.h"
|
||||
#include "impeller/toolkit/gles/texture.h"
|
||||
#include "shell/platform/android/ndk_helpers.h"
|
||||
@@ -53,6 +57,7 @@ void HardwareBufferExternalTextureGL::ProcessFrame(PaintContext& context,
|
||||
NDKHelpers::eglGetNativeClientBufferANDROID(latest_hardware_buffer);
|
||||
if (client_buffer == nullptr) {
|
||||
FML_LOG(WARNING) << "eglGetNativeClientBufferAndroid returned null.";
|
||||
NDKHelpers::AHardwareBuffer_release(latest_hardware_buffer);
|
||||
return;
|
||||
}
|
||||
FML_CHECK(client_buffer != nullptr);
|
||||
@@ -86,4 +91,82 @@ HardwareBufferExternalTextureGL::HardwareBufferExternalTextureGL(
|
||||
|
||||
HardwareBufferExternalTextureGL::~HardwareBufferExternalTextureGL() {}
|
||||
|
||||
HardwareBufferExternalTextureImpellerGL::
|
||||
HardwareBufferExternalTextureImpellerGL(
|
||||
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)
|
||||
: HardwareBufferExternalTexture(id,
|
||||
hardware_buffer_texture_entry,
|
||||
jni_facade),
|
||||
impeller_context_(context) {}
|
||||
|
||||
HardwareBufferExternalTextureImpellerGL::
|
||||
~HardwareBufferExternalTextureImpellerGL() {}
|
||||
|
||||
void HardwareBufferExternalTextureImpellerGL::Detach() {
|
||||
egl_image_.reset();
|
||||
}
|
||||
|
||||
void HardwareBufferExternalTextureImpellerGL::ProcessFrame(
|
||||
PaintContext& context,
|
||||
const SkRect& bounds) {
|
||||
EGLDisplay display = eglGetCurrentDisplay();
|
||||
FML_CHECK(display != EGL_NO_DISPLAY);
|
||||
|
||||
if (state_ == AttachmentState::kUninitialized) {
|
||||
// First processed frame we are attached.
|
||||
state_ = AttachmentState::kAttached;
|
||||
}
|
||||
|
||||
AHardwareBuffer* latest_hardware_buffer = GetLatestHardwareBuffer();
|
||||
if (latest_hardware_buffer == nullptr) {
|
||||
FML_LOG(ERROR) << "GetLatestHardwareBuffer returned null.";
|
||||
return;
|
||||
}
|
||||
|
||||
EGLClientBuffer client_buffer =
|
||||
NDKHelpers::eglGetNativeClientBufferANDROID(latest_hardware_buffer);
|
||||
if (client_buffer == nullptr) {
|
||||
FML_LOG(ERROR) << "eglGetNativeClientBufferAndroid returned null.";
|
||||
NDKHelpers::AHardwareBuffer_release(latest_hardware_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
FML_CHECK(client_buffer != nullptr);
|
||||
egl_image_.reset(impeller::EGLImageKHRWithDisplay{
|
||||
eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
|
||||
client_buffer, 0),
|
||||
display});
|
||||
FML_CHECK(egl_image_.get().image != EGL_NO_IMAGE_KHR);
|
||||
|
||||
// Create the texture.
|
||||
impeller::TextureDescriptor desc;
|
||||
desc.type = impeller::TextureType::kTextureExternalOES;
|
||||
desc.storage_mode = impeller::StorageMode::kDevicePrivate;
|
||||
desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
|
||||
desc.size = {static_cast<int>(bounds.width()),
|
||||
static_cast<int>(bounds.height())};
|
||||
desc.mip_count = 1;
|
||||
auto texture = std::make_shared<impeller::TextureGLES>(
|
||||
impeller_context_->GetReactor(), desc,
|
||||
impeller::TextureGLES::IsWrapped::kWrapped);
|
||||
texture->SetIntent(impeller::TextureIntent::kUploadFromHost);
|
||||
if (!texture->Bind()) {
|
||||
FML_LOG(ERROR) << "Could not bind texture.";
|
||||
NDKHelpers::AHardwareBuffer_release(latest_hardware_buffer);
|
||||
return;
|
||||
}
|
||||
// Associate the hardware buffer image with the texture.
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
|
||||
(GLeglImageOES)egl_image_.get().image);
|
||||
|
||||
dl_image_ = impeller::DlImageImpeller::Make(texture);
|
||||
|
||||
// Release the reference acquired by GetLatestHardwareBuffer.
|
||||
NDKHelpers::AHardwareBuffer_release(latest_hardware_buffer);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#include "flutter/shell/platform/android/hardware_buffer_external_texture.h"
|
||||
|
||||
#include "flutter/impeller/renderer/backend/gles/context_gles.h"
|
||||
#include "flutter/impeller/renderer/backend/gles/gles.h"
|
||||
#include "flutter/impeller/renderer/backend/gles/texture_gles.h"
|
||||
#include "flutter/impeller/toolkit/egl/egl.h"
|
||||
#include "flutter/impeller/toolkit/egl/image.h"
|
||||
#include "flutter/impeller/toolkit/gles/texture.h"
|
||||
@@ -36,6 +39,29 @@ class HardwareBufferExternalTextureGL : public HardwareBufferExternalTexture {
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(HardwareBufferExternalTextureGL);
|
||||
};
|
||||
|
||||
class HardwareBufferExternalTextureImpellerGL
|
||||
: public HardwareBufferExternalTexture {
|
||||
public:
|
||||
HardwareBufferExternalTextureImpellerGL(
|
||||
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);
|
||||
|
||||
~HardwareBufferExternalTextureImpellerGL() override;
|
||||
|
||||
private:
|
||||
void ProcessFrame(PaintContext& context, const SkRect& bounds) override;
|
||||
void Detach() override;
|
||||
|
||||
const std::shared_ptr<impeller::ContextGLES> impeller_context_;
|
||||
|
||||
impeller::UniqueEGLImageKHR egl_image_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(HardwareBufferExternalTextureImpellerGL);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_HARDWARE_BUFFER_EXTERNAL_TEXTURE_GL_H_
|
||||
|
||||
@@ -54,6 +54,9 @@ void HardwareBufferExternalTextureVK::ProcessFrame(PaintContext& context,
|
||||
std::make_shared<impeller::TextureVK>(impeller_context_, texture_source);
|
||||
|
||||
dl_image_ = impeller::DlImageImpeller::Make(texture);
|
||||
|
||||
// GetLatestHardwareBuffer keeps a reference on the hardware buffer, drop it.
|
||||
NDKHelpers::AHardwareBuffer_release(latest_hardware_buffer);
|
||||
}
|
||||
|
||||
void HardwareBufferExternalTextureVK::Detach() {}
|
||||
|
||||
@@ -312,9 +312,18 @@ void PlatformViewAndroid::RegisterImageTexture(
|
||||
int64_t texture_id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry) {
|
||||
if (android_context_->RenderingApi() == AndroidRenderingAPI::kOpenGLES) {
|
||||
RegisterTexture(std::make_shared<HardwareBufferExternalTextureGL>(
|
||||
std::static_pointer_cast<AndroidContextGLSkia>(android_context_),
|
||||
texture_id, image_texture_entry, jni_facade_));
|
||||
if (android_context_->GetImpellerContext() != nullptr) {
|
||||
// Impeller GLES.
|
||||
RegisterTexture(std::make_shared<HardwareBufferExternalTextureImpellerGL>(
|
||||
std::static_pointer_cast<impeller::ContextGLES>(
|
||||
android_context_->GetImpellerContext()),
|
||||
texture_id, image_texture_entry, jni_facade_));
|
||||
} else {
|
||||
// Legacy GL.
|
||||
RegisterTexture(std::make_shared<HardwareBufferExternalTextureGL>(
|
||||
std::static_pointer_cast<AndroidContextGLSkia>(android_context_),
|
||||
texture_id, image_texture_entry, jni_facade_));
|
||||
}
|
||||
} else if (android_context_->RenderingApi() == AndroidRenderingAPI::kVulkan) {
|
||||
RegisterTexture(std::make_shared<HardwareBufferExternalTextureVK>(
|
||||
std::static_pointer_cast<impeller::ContextVK>(
|
||||
|
||||
Reference in New Issue
Block a user