[impeller] Wire up the OpenGL ES Backend. (flutter/engine#33405)

This commit is contained in:
Chinmay Garde 2022-05-17 13:16:25 -07:00 committed by GitHub
parent faf29ed458
commit 7df5e81ea8
61 changed files with 2199 additions and 661 deletions

View File

@ -447,6 +447,8 @@ FILE: ../../../flutter/impeller/base/thread_safety.cc
FILE: ../../../flutter/impeller/base/thread_safety.h
FILE: ../../../flutter/impeller/base/validation.cc
FILE: ../../../flutter/impeller/base/validation.h
FILE: ../../../flutter/impeller/base/version.cc
FILE: ../../../flutter/impeller/base/version.h
FILE: ../../../flutter/impeller/blobcat/blob.cc
FILE: ../../../flutter/impeller/blobcat/blob.h
FILE: ../../../flutter/impeller/blobcat/blob_library.cc
@ -634,15 +636,15 @@ FILE: ../../../flutter/impeller/renderer/backend/gles/command_buffer_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/command_buffer_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/context_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/context_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/description_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/description_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/device_buffer_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/device_buffer_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/formats_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/formats_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/gl_description.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/gl_description.h
FILE: ../../../flutter/impeller/renderer/backend/gles/gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/gles_handle.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/gles_handle.h
FILE: ../../../flutter/impeller/renderer/backend/gles/handle_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/handle_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/pipeline_gles.cc
FILE: ../../../flutter/impeller/renderer/backend/gles/pipeline_gles.h
FILE: ../../../flutter/impeller/renderer/backend/gles/pipeline_library_gles.cc
@ -764,6 +766,16 @@ FILE: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart
FILE: ../../../flutter/impeller/tessellator/tessellator.cc
FILE: ../../../flutter/impeller/tessellator/tessellator.h
FILE: ../../../flutter/impeller/tessellator/tessellator_unittests.cc
FILE: ../../../flutter/impeller/toolkit/egl/config.cc
FILE: ../../../flutter/impeller/toolkit/egl/config.h
FILE: ../../../flutter/impeller/toolkit/egl/context.cc
FILE: ../../../flutter/impeller/toolkit/egl/context.h
FILE: ../../../flutter/impeller/toolkit/egl/display.cc
FILE: ../../../flutter/impeller/toolkit/egl/display.h
FILE: ../../../flutter/impeller/toolkit/egl/egl.cc
FILE: ../../../flutter/impeller/toolkit/egl/egl.h
FILE: ../../../flutter/impeller/toolkit/egl/surface.cc
FILE: ../../../flutter/impeller/toolkit/egl/surface.h
FILE: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.cc
FILE: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.h
FILE: ../../../flutter/impeller/typographer/backends/skia/text_render_context_skia.cc
@ -1264,10 +1276,12 @@ FILE: ../../../flutter/shell/common/vsync_waiter_fallback.cc
FILE: ../../../flutter/shell/common/vsync_waiter_fallback.h
FILE: ../../../flutter/shell/common/vsync_waiters_test.cc
FILE: ../../../flutter/shell/common/vsync_waiters_test.h
FILE: ../../../flutter/shell/gpu/gpu_surface_gl.cc
FILE: ../../../flutter/shell/gpu/gpu_surface_gl.h
FILE: ../../../flutter/shell/gpu/gpu_surface_gl_delegate.cc
FILE: ../../../flutter/shell/gpu/gpu_surface_gl_delegate.h
FILE: ../../../flutter/shell/gpu/gpu_surface_gl_impeller.cc
FILE: ../../../flutter/shell/gpu/gpu_surface_gl_impeller.h
FILE: ../../../flutter/shell/gpu/gpu_surface_gl_skia.cc
FILE: ../../../flutter/shell/gpu/gpu_surface_gl_skia.h
FILE: ../../../flutter/shell/gpu/gpu_surface_metal_delegate.cc
FILE: ../../../flutter/shell/gpu/gpu_surface_metal_delegate.h
FILE: ../../../flutter/shell/gpu/gpu_surface_metal_impeller.h
@ -1285,11 +1299,15 @@ FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.h
FILE: ../../../flutter/shell/platform/android/AndroidManifest.xml
FILE: ../../../flutter/shell/platform/android/android_choreographer.cc
FILE: ../../../flutter/shell/platform/android/android_choreographer.h
FILE: ../../../flutter/shell/platform/android/android_context_gl.cc
FILE: ../../../flutter/shell/platform/android/android_context_gl.h
FILE: ../../../flutter/shell/platform/android/android_context_gl_impeller.cc
FILE: ../../../flutter/shell/platform/android/android_context_gl_impeller.h
FILE: ../../../flutter/shell/platform/android/android_context_gl_skia.cc
FILE: ../../../flutter/shell/platform/android/android_context_gl_skia.h
FILE: ../../../flutter/shell/platform/android/android_context_gl_unittests.cc
FILE: ../../../flutter/shell/platform/android/android_display.cc
FILE: ../../../flutter/shell/platform/android/android_display.h
FILE: ../../../flutter/shell/platform/android/android_egl_surface.cc
FILE: ../../../flutter/shell/platform/android/android_egl_surface.h
FILE: ../../../flutter/shell/platform/android/android_environment_gl.cc
FILE: ../../../flutter/shell/platform/android/android_environment_gl.h
FILE: ../../../flutter/shell/platform/android/android_exports.lst
@ -1300,8 +1318,10 @@ FILE: ../../../flutter/shell/platform/android/android_image_generator.h
FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc
FILE: ../../../flutter/shell/platform/android/android_shell_holder.h
FILE: ../../../flutter/shell/platform/android/android_shell_holder_unittests.cc
FILE: ../../../flutter/shell/platform/android/android_surface_gl.cc
FILE: ../../../flutter/shell/platform/android/android_surface_gl.h
FILE: ../../../flutter/shell/platform/android/android_surface_gl_impeller.cc
FILE: ../../../flutter/shell/platform/android/android_surface_gl_impeller.h
FILE: ../../../flutter/shell/platform/android/android_surface_gl_skia.cc
FILE: ../../../flutter/shell/platform/android/android_surface_gl_skia.h
FILE: ../../../flutter/shell/platform/android/android_surface_software.cc
FILE: ../../../flutter/shell/platform/android/android_surface_software.h
FILE: ../../../flutter/shell/platform/android/apk_asset_provider.cc

View File

@ -22,6 +22,8 @@ impeller_component("base") {
"thread_safety.h",
"validation.cc",
"validation.h",
"version.cc",
"version.h",
]
deps = [ "//flutter/fml" ]

View File

@ -18,4 +18,16 @@ std::string SPrintF(const char* format, ...) {
return buffer;
}
bool HasPrefix(const std::string& string, const std::string& prefix) {
return string.find(prefix) == 0u;
}
std::string StripPrefix(const std::string& string,
const std::string& to_strip) {
if (!HasPrefix(string, to_strip)) {
return string;
}
return string.substr(to_strip.length());
}
} // namespace impeller

View File

@ -13,4 +13,8 @@ namespace impeller {
IMPELLER_PRINTF_FORMAT(1, 2)
std::string SPrintF(const char* format, ...);
bool HasPrefix(const std::string& string, const std::string& prefix);
std::string StripPrefix(const std::string& string, const std::string& to_strip);
} // namespace impeller

View File

@ -0,0 +1,33 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/base/version.h"
#include <sstream>
namespace impeller {
std::optional<Version> Version::FromVector(const std::vector<size_t>& version) {
if (version.size() == 0) {
return Version{0, 0, 0};
}
if (version.size() == 1) {
return Version{version[0], 0, 0};
}
if (version.size() == 2) {
return Version{version[0], version[1], 0};
}
if (version.size() == 3) {
return Version{version[0], version[1], version[2]};
}
return std::nullopt;
}
std::string Version::ToString() const {
std::stringstream stream;
stream << major << "." << minor << "." << patch;
return stream.str();
}
} // namespace impeller

View File

@ -0,0 +1,34 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <cstddef>
#include <optional>
#include <string>
#include <tuple>
#include <vector>
namespace impeller {
struct Version {
public:
size_t major;
size_t minor;
size_t patch;
constexpr Version(size_t p_major = 0, size_t p_minor = 0, size_t p_patch = 0)
: major(p_major), minor(p_minor), patch(p_patch) {}
static std::optional<Version> FromVector(const std::vector<size_t>& version);
constexpr bool IsAtLeast(const Version& other) {
return std::tie(major, minor, patch) >=
std::tie(other.major, other.minor, other.patch);
}
std::string ToString() const;
};
} // namespace impeller

View File

@ -5,9 +5,12 @@
import("../../../tools/impeller.gni")
config("gles_config") {
# Generic GL/GLES/EGL/Vulkan headers. Any will do. We just pick one from Angle
# because they are there.
include_dirs = [ "//third_party/angle/include" ]
include_dirs = []
if (!is_android) {
# Generic GL/GLES/EGL/Vulkan headers. Any will do. We just pick one from Angle
# because they are there.
include_dirs = [ "//third_party/angle/include" ]
}
}
impeller_component("gles") {
@ -22,15 +25,15 @@ impeller_component("gles") {
"command_buffer_gles.h",
"context_gles.cc",
"context_gles.h",
"description_gles.cc",
"description_gles.h",
"device_buffer_gles.cc",
"device_buffer_gles.h",
"formats_gles.cc",
"formats_gles.h",
"gl_description.cc",
"gl_description.h",
"gles.h",
"gles_handle.cc",
"gles_handle.h",
"handle_gles.cc",
"handle_gles.h",
"pipeline_gles.cc",
"pipeline_gles.h",
"pipeline_library_gles.cc",

View File

@ -0,0 +1,148 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/gles/description_gles.h"
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "impeller/base/strings.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/gles/proc_table_gles.h"
namespace impeller {
static std::string GetGLString(const ProcTableGLES& gl, GLenum name) {
auto str = gl.GetString(name);
if (str == nullptr) {
return "";
}
return reinterpret_cast<const char*>(str);
}
static bool DetermineIfES(const std::string& version) {
return HasPrefix(version, "OpenGL ES");
}
static std::optional<Version> DetermineVersion(std::string version) {
// Format for OpenGL "OpenGL<space>ES<space><version
// number><space><vendor-specific information>".
//
// Format for OpenGL SL "OpenGL<space>ES<space>GLSL<space>ES<space><version
// number><space><vendor-specific information>"
//
// The prefixes appear to be absent on Desktop GL.
version = StripPrefix(version, "OpenGL ES ");
version = StripPrefix(version, "GLSL ES ");
if (version.empty()) {
return std::nullopt;
}
std::stringstream stream;
for (size_t i = 0; i < version.size(); i++) {
const auto character = version[i];
if (std::isdigit(character) || character == '.') {
stream << character;
} else {
break;
}
}
std::istringstream istream;
istream.str(stream.str());
std::vector<size_t> version_components;
for (std::string version_component;
std::getline(istream, version_component, '.');) {
version_components.push_back(std::stoul(version_component));
}
return Version::FromVector(std::move(version_components));
}
DescriptionGLES::DescriptionGLES(const ProcTableGLES& gl)
: vendor_(GetGLString(gl, GL_VENDOR)),
renderer_(GetGLString(gl, GL_RENDERER)),
gl_version_string_(GetGLString(gl, GL_VERSION)),
sl_version_string_(GetGLString(gl, GL_SHADING_LANGUAGE_VERSION)) {
const auto extensions = GetGLString(gl, GL_EXTENSIONS);
std::stringstream extensions_stream(extensions);
std::string extension;
while (std::getline(extensions_stream, extension, ' ')) {
extensions_.insert(extension);
}
is_es_ = DetermineIfES(gl_version_string_);
auto gl_version = DetermineVersion(gl_version_string_);
if (!gl_version.has_value()) {
VALIDATION_LOG << "Could not determine GL version.";
return;
}
gl_version_ = gl_version.value();
auto sl_version = DetermineVersion(sl_version_string_);
if (!sl_version.has_value()) {
VALIDATION_LOG << "Could not determine SL version.";
return;
}
sl_version_ = sl_version.value();
is_valid_ = true;
}
DescriptionGLES::~DescriptionGLES() = default;
bool DescriptionGLES::IsValid() const {
return is_valid_;
}
std::string DescriptionGLES::GetString() const {
if (!IsValid()) {
return "Unknown Renderer.";
}
std::vector<std::pair<std::string, std::string>> items;
items.emplace_back(std::make_pair("Vendor", vendor_));
items.emplace_back(std::make_pair("Renderer", renderer_));
items.emplace_back(std::make_pair("GL Version", gl_version_string_));
items.emplace_back(
std::make_pair("Shading Language Version", sl_version_string_));
items.emplace_back(
std::make_pair("Extensions", std::to_string(extensions_.size())));
size_t max_width = 0u;
for (const auto& item : items) {
max_width = std::max(max_width, item.first.size());
}
std::stringstream stream;
stream << "OpenGL Renderer:" << std::endl;
for (const auto& item : items) {
stream << std::setw(max_width + 1) << item.first << ": " << item.second
<< std::endl;
}
const auto pad = std::string(max_width + 3, ' ');
for (const auto& extension : extensions_) {
stream << pad << extension << std::endl;
}
return stream.str();
}
bool DescriptionGLES::HasExtension(const std::string& ext) const {
return extensions_.find(ext) != extensions_.end();
}
bool DescriptionGLES::HasDebugExtension() const {
return HasExtension("GL_KHR_debug");
}
} // namespace impeller

View File

@ -8,16 +8,17 @@
#include <string>
#include "flutter/fml/macros.h"
#include "impeller/base/version.h"
namespace impeller {
class ProcTableGLES;
class GLDescription {
class DescriptionGLES {
public:
GLDescription(const ProcTableGLES& gl);
DescriptionGLES(const ProcTableGLES& gl);
~GLDescription();
~DescriptionGLES();
bool IsValid() const;
@ -28,14 +29,17 @@ class GLDescription {
bool HasDebugExtension() const;
private:
Version gl_version_;
Version sl_version_;
bool is_es_ = true;
std::string vendor_;
std::string renderer_;
std::string gl_version_;
std::string sl_version_;
std::string gl_version_string_;
std::string sl_version_string_;
std::set<std::string> extensions_;
bool is_valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(GLDescription);
FML_DISALLOW_COPY_AND_ASSIGN(DescriptionGLES);
};
} // namespace impeller

View File

@ -17,7 +17,7 @@ DeviceBufferGLES::DeviceBufferGLES(ReactorGLES::Ref reactor,
: DeviceBuffer(size, mode),
reactor_(std::move(reactor)),
handle_(reactor_ ? reactor_->CreateHandle(HandleType::kBuffer)
: GLESHandle::DeadHandle()) {}
: HandleGLES::DeadHandle()) {}
// |DeviceBuffer|
DeviceBufferGLES::~DeviceBufferGLES() {
@ -83,6 +83,7 @@ bool DeviceBufferGLES::BindAndUploadDataIfNecessary(BindingType type) const {
gl.BufferData(target_type, data_->GetSize(), data_->GetMapping(),
GL_STATIC_DRAW);
uploaded_ = true;
reactor_->SetDebugLabel(handle_, label_);
}
return true;
@ -90,8 +91,9 @@ bool DeviceBufferGLES::BindAndUploadDataIfNecessary(BindingType type) const {
// |DeviceBuffer|
bool DeviceBufferGLES::SetLabel(const std::string& label) {
if (!handle_.IsDead()) {
reactor_->SetDebugLabel(handle_, std::move(label));
label_ = label;
if (uploaded_) {
reactor_->SetDebugLabel(handle_, label_);
}
return true;
}

View File

@ -31,7 +31,8 @@ class DeviceBufferGLES final
private:
ReactorGLES::Ref reactor_;
GLESHandle handle_;
HandleGLES handle_;
std::string label_;
mutable std::shared_ptr<fml::Mapping> data_;
mutable bool uploaded_ = false;

View File

@ -1,88 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/gles/gl_description.h"
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "impeller/renderer/backend/gles/proc_table_gles.h"
namespace impeller {
static std::string GetGLString(const ProcTableGLES& gl, GLenum name) {
auto str = gl.GetString(name);
if (str == nullptr) {
return "";
}
return reinterpret_cast<const char*>(str);
}
GLDescription::GLDescription(const ProcTableGLES& gl)
: vendor_(GetGLString(gl, GL_VENDOR)),
renderer_(GetGLString(gl, GL_RENDERER)),
gl_version_(GetGLString(gl, GL_VERSION)),
sl_version_(GetGLString(gl, GL_SHADING_LANGUAGE_VERSION)) {
const auto extensions = GetGLString(gl, GL_EXTENSIONS);
std::stringstream extensions_stream(extensions);
std::string extension;
while (std::getline(extensions_stream, extension, ' ')) {
extensions_.insert(extension);
}
is_valid_ = true;
}
GLDescription::~GLDescription() = default;
bool GLDescription::IsValid() const {
return is_valid_;
}
std::string GLDescription::GetString() const {
if (!IsValid()) {
return "Unknown Renderer.";
}
std::vector<std::pair<std::string, std::string>> items;
items.emplace_back(std::make_pair("Vendor", vendor_));
items.emplace_back(std::make_pair("Renderer", renderer_));
items.emplace_back(std::make_pair("GL Version", gl_version_));
items.emplace_back(std::make_pair("Shading Language Version", sl_version_));
items.emplace_back(
std::make_pair("Extensions", std::to_string(extensions_.size())));
size_t max_width = 0u;
for (const auto& item : items) {
max_width = std::max(max_width, item.first.size());
}
std::stringstream stream;
stream << "OpenGL Renderer:" << std::endl;
for (const auto& item : items) {
stream << std::setw(max_width + 1) << item.first << ": " << item.second
<< std::endl;
}
const auto pad = std::string(max_width + 3, ' ');
for (const auto& extension : extensions_) {
stream << pad << extension << std::endl;
}
return stream.str();
}
bool GLDescription::HasExtension(const std::string& ext) const {
return extensions_.find(ext) != extensions_.end();
}
bool GLDescription::HasDebugExtension() const {
return HasExtension("GL_KHR_debug");
}
} // namespace impeller

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/gles/gles_handle.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
namespace impeller {

View File

@ -27,17 +27,17 @@ enum class HandleType {
class ReactorGLES;
struct GLESHandle {
struct HandleGLES {
HandleType type = HandleType::kUnknown;
static GLESHandle DeadHandle() {
return GLESHandle{HandleType::kUnknown, std::nullopt};
static HandleGLES DeadHandle() {
return HandleGLES{HandleType::kUnknown, std::nullopt};
}
constexpr bool IsDead() const { return !name_.has_value(); }
struct Hash {
std::size_t operator()(const GLESHandle& handle) const {
std::size_t operator()(const HandleGLES& handle) const {
return fml::HashCombine(
std::underlying_type_t<decltype(handle.type)>(handle.type),
handle.name_);
@ -45,7 +45,7 @@ struct GLESHandle {
};
struct Equal {
bool operator()(const GLESHandle& lhs, const GLESHandle& rhs) const {
bool operator()(const HandleGLES& lhs, const HandleGLES& rhs) const {
return lhs.type == rhs.type && lhs.name_ == rhs.name_;
}
};
@ -55,21 +55,21 @@ struct GLESHandle {
std::optional<UniqueID> name_;
GLESHandle(HandleType p_type, UniqueID p_name)
HandleGLES(HandleType p_type, UniqueID p_name)
: type(p_type), name_(p_name) {}
GLESHandle(HandleType p_type, std::optional<UniqueID> p_name)
HandleGLES(HandleType p_type, std::optional<UniqueID> p_name)
: type(p_type), name_(p_name) {}
static GLESHandle Create(HandleType type) {
return GLESHandle{type, UniqueID{}};
static HandleGLES Create(HandleType type) {
return HandleGLES{type, UniqueID{}};
}
};
using GLESHandleSet =
std::unordered_set<GLESHandle, GLESHandle::Hash, GLESHandle::Equal>;
std::unordered_set<HandleGLES, HandleGLES::Hash, HandleGLES::Equal>;
template <class T>
using GLESHandleMap =
std::unordered_map<GLESHandle, T, GLESHandle::Hash, GLESHandle::Equal>;
std::unordered_map<HandleGLES, T, HandleGLES::Hash, HandleGLES::Equal>;
} // namespace impeller

View File

@ -12,7 +12,7 @@ PipelineGLES::PipelineGLES(ReactorGLES::Ref reactor,
: Pipeline(std::move(library), std::move(desc)),
reactor_(std::move(reactor)),
handle_(reactor_ ? reactor_->CreateHandle(HandleType::kProgram)
: GLESHandle::DeadHandle()),
: HandleGLES::DeadHandle()),
is_valid_(!handle_.IsDead()) {
if (is_valid_) {
reactor_->SetDebugLabel(handle_, GetDescriptor().GetLabel());
@ -31,7 +31,7 @@ bool PipelineGLES::IsValid() const {
return is_valid_;
}
const GLESHandle& PipelineGLES::GetProgramHandle() const {
const HandleGLES& PipelineGLES::GetProgramHandle() const {
return handle_;
}

View File

@ -7,7 +7,7 @@
#include "flutter/fml/macros.h"
#include "impeller/base/backend_cast.h"
#include "impeller/renderer/backend/gles/buffer_bindings_gles.h"
#include "impeller/renderer/backend/gles/gles_handle.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
#include "impeller/renderer/backend/gles/reactor_gles.h"
#include "impeller/renderer/pipeline.h"
@ -21,7 +21,7 @@ class PipelineGLES final : public Pipeline,
// |Pipeline|
~PipelineGLES() override;
const GLESHandle& GetProgramHandle() const;
const HandleGLES& GetProgramHandle() const;
[[nodiscard]] bool BindProgram() const;
@ -36,7 +36,7 @@ class PipelineGLES final : public Pipeline,
friend PipelineLibraryGLES;
ReactorGLES::Ref reactor_;
GLESHandle handle_;
HandleGLES handle_;
std::unique_ptr<BufferBindingsGLES> buffer_bindings_;
bool is_valid_ = false;

View File

@ -90,7 +90,7 @@ ProcTableGLES::ProcTableGLES(Resolver resolver) {
#undef IMPELLER_PROC
description_ = std::make_unique<GLDescription>(*this);
description_ = std::make_unique<DescriptionGLES>(*this);
if (!description_->IsValid()) {
return;
@ -125,7 +125,7 @@ void ProcTableGLES::ShaderSourceMapping(GLuint shader,
ShaderSource(shader, 1u, sources, lengths);
}
const GLDescription* ProcTableGLES::GetDescription() const {
const DescriptionGLES* ProcTableGLES::GetDescription() const {
return description_.get();
}

View File

@ -10,7 +10,7 @@
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.h"
#include "impeller/renderer/backend/gles/gl_description.h"
#include "impeller/renderer/backend/gles/description_gles.h"
#include "impeller/renderer/backend/gles/gles.h"
namespace impeller {
@ -183,7 +183,7 @@ class ProcTableGLES {
void ShaderSourceMapping(GLuint shader, const fml::Mapping& mapping) const;
const GLDescription* GetDescription() const;
const DescriptionGLES* GetDescription() const;
std::string DescribeCurrentFramebuffer() const;
@ -199,7 +199,7 @@ class ProcTableGLES {
private:
bool is_valid_ = false;
std::unique_ptr<GLDescription> description_;
std::unique_ptr<DescriptionGLES> description_;
GLint debug_label_max_length_ = 0;
FML_DISALLOW_COPY_AND_ASSIGN(ProcTableGLES);

View File

@ -36,7 +36,7 @@ const ProcTableGLES& ReactorGLES::GetProcTable() const {
return *proc_table_;
}
std::optional<GLuint> ReactorGLES::GetGLHandle(const GLESHandle& handle) const {
std::optional<GLuint> ReactorGLES::GetGLHandle(const HandleGLES& handle) const {
auto found = live_gl_handles_.find(handle);
if (found != live_gl_handles_.end()) {
return found->second;
@ -101,20 +101,20 @@ static bool CollectGLHandle(const ProcTableGLES& gl,
return false;
}
GLESHandle ReactorGLES::CreateHandle(HandleType type) {
HandleGLES ReactorGLES::CreateHandle(HandleType type) {
if (type == HandleType::kUnknown) {
return GLESHandle::DeadHandle();
return HandleGLES::DeadHandle();
}
auto new_handle = GLESHandle::Create(type);
auto new_handle = HandleGLES::Create(type);
if (new_handle.IsDead()) {
return GLESHandle::DeadHandle();
return HandleGLES::DeadHandle();
}
live_gl_handles_[new_handle] =
in_reaction_ ? CreateGLHandle(GetProcTable(), type) : std::nullopt;
return new_handle;
}
void ReactorGLES::CollectHandle(GLESHandle handle) {
void ReactorGLES::CollectHandle(HandleGLES handle) {
auto live_handle = live_gl_handles_.find(handle);
if (live_handle == live_gl_handles_.end()) {
return;
@ -219,7 +219,7 @@ bool ReactorGLES::ReactOnce() {
return true;
}
void ReactorGLES::SetDebugLabel(const GLESHandle& handle, std::string label) {
void ReactorGLES::SetDebugLabel(const HandleGLES& handle, std::string label) {
if (!can_set_debug_labels_) {
return;
}

View File

@ -10,7 +10,7 @@
#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "impeller/renderer/backend/gles/gles_handle.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
#include "impeller/renderer/backend/gles/proc_table_gles.h"
namespace impeller {
@ -29,13 +29,13 @@ class ReactorGLES {
const ProcTableGLES& GetProcTable() const;
std::optional<GLuint> GetGLHandle(const GLESHandle& handle) const;
std::optional<GLuint> GetGLHandle(const HandleGLES& handle) const;
GLESHandle CreateHandle(HandleType type);
HandleGLES CreateHandle(HandleType type);
void CollectHandle(GLESHandle handle);
void CollectHandle(HandleGLES handle);
void SetDebugLabel(const GLESHandle& handle, std::string label);
void SetDebugLabel(const HandleGLES& handle, std::string label);
using Operation = std::function<void(const ReactorGLES& reactor)>;
[[nodiscard]] bool AddOperation(Operation operation);

View File

@ -6,7 +6,7 @@
#include "flutter/fml/macros.h"
#include "impeller/base/backend_cast.h"
#include "impeller/renderer/backend/gles/gles_handle.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
#include "impeller/renderer/backend/gles/reactor_gles.h"
#include "impeller/renderer/texture.h"
@ -52,7 +52,7 @@ class TextureGLES final : public Texture,
ReactorGLES::Ref reactor_;
const Type type_;
GLESHandle handle_;
HandleGLES handle_;
mutable bool contents_initialized_ = false;
const bool is_wrapped_;
std::string label_;

View File

@ -0,0 +1,27 @@
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../../tools/impeller.gni")
impeller_component("egl") {
sources = [
"config.cc",
"config.h",
"context.cc",
"context.h",
"display.cc",
"display.h",
"egl.cc",
"egl.h",
"surface.cc",
"surface.h",
]
deps = [ "//flutter/fml" ]
libs = []
if (is_android) {
libs = [ "EGL" ]
}
}

View File

@ -0,0 +1,30 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/toolkit/egl/config.h"
#include <utility>
namespace impeller {
namespace egl {
Config::Config(ConfigDescriptor descriptor, EGLConfig config)
: desc_(std::move(descriptor)), config_(config) {}
Config::~Config() = default;
const ConfigDescriptor& Config::GetDescriptor() const {
return desc_;
}
const EGLConfig& Config::GetHandle() const {
return config_;
}
bool Config::IsValid() const {
return config_ != nullptr;
}
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,74 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "flutter/fml/macros.h"
#include "impeller/toolkit/egl/egl.h"
namespace impeller {
namespace egl {
enum class API {
kOpenGL,
kOpenGLES2,
kOpenGLES3,
};
enum class Samples {
kOne = 1,
kTwo = 2,
kFour = 4,
};
enum class ColorFormat {
kRGBA8888,
kRGB565,
};
enum class StencilBits {
kZero = 0,
kEight = 8,
};
enum class DepthBits {
kZero = 0,
kEight = 8,
};
enum class SurfaceType {
kWindow,
kPBuffer,
};
struct ConfigDescriptor {
API api = API::kOpenGLES2;
Samples samples = Samples::kOne;
ColorFormat color_format = ColorFormat::kRGB565;
StencilBits stencil_bits = StencilBits::kZero;
DepthBits depth_bits = DepthBits::kZero;
SurfaceType surface_type = SurfaceType::kPBuffer;
};
class Config {
public:
Config(ConfigDescriptor descriptor, EGLConfig config);
~Config();
bool IsValid() const;
const ConfigDescriptor& GetDescriptor() const;
const EGLConfig& GetHandle() const;
private:
const ConfigDescriptor desc_;
EGLConfig config_ = nullptr;
FML_DISALLOW_COPY_AND_ASSIGN(Config);
};
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,73 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/toolkit/egl/context.h"
#include "impeller/toolkit/egl/surface.h"
namespace impeller {
namespace egl {
Context::Context(EGLDisplay display, EGLContext context)
: display_(display), context_(context) {}
Context::~Context() {
if (context_ != EGL_NO_CONTEXT) {
if (::eglDestroyContext(display_, context_) != EGL_TRUE) {
IMPELLER_LOG_EGL_ERROR;
}
}
}
bool Context::IsValid() const {
return context_ != EGL_NO_CONTEXT;
}
const EGLContext& Context::GetHandle() const {
return context_;
}
static EGLBoolean EGLMakeCurrentIfNecessary(EGLDisplay display,
EGLSurface draw,
EGLSurface read,
EGLContext context) {
if (display != ::eglGetCurrentDisplay() ||
draw != ::eglGetCurrentSurface(EGL_DRAW) ||
read != ::eglGetCurrentSurface(EGL_READ) ||
context != ::eglGetCurrentContext()) {
return ::eglMakeCurrent(display, draw, read, context);
}
// The specified context configuration is already current.
return EGL_TRUE;
}
bool Context::MakeCurrent(const Surface& surface) const {
if (context_ == EGL_NO_CONTEXT) {
return false;
}
const auto result = EGLMakeCurrentIfNecessary(display_, //
surface.GetHandle(), //
surface.GetHandle(), //
context_ //
) == EGL_TRUE;
if (!result) {
IMPELLER_LOG_EGL_ERROR;
}
return result;
}
bool Context::ClearCurrent() const {
const auto result = EGLMakeCurrentIfNecessary(display_, //
EGL_NO_SURFACE, //
EGL_NO_SURFACE, //
EGL_NO_CONTEXT //
) == EGL_TRUE;
if (!result) {
IMPELLER_LOG_EGL_ERROR;
}
return result;
}
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,37 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "flutter/fml/macros.h"
#include "impeller/toolkit/egl/egl.h"
namespace impeller {
namespace egl {
class Surface;
class Context {
public:
Context(EGLDisplay display, EGLContext context);
~Context();
bool IsValid() const;
const EGLContext& GetHandle() const;
bool MakeCurrent(const Surface& surface) const;
bool ClearCurrent() const;
private:
EGLDisplay display_ = EGL_NO_DISPLAY;
EGLContext context_ = EGL_NO_CONTEXT;
FML_DISALLOW_COPY_AND_ASSIGN(Context);
};
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,210 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/toolkit/egl/display.h"
#include <vector>
#include "impeller/toolkit/egl/context.h"
#include "impeller/toolkit/egl/surface.h"
namespace impeller {
namespace egl {
Display::Display() {
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (::eglInitialize(display, nullptr, nullptr) != EGL_TRUE) {
IMPELLER_LOG_EGL_ERROR;
return;
}
display_ = display;
}
Display::~Display() {
if (display_ != EGL_NO_DISPLAY) {
if (::eglTerminate(display_) != EGL_TRUE) {
IMPELLER_LOG_EGL_ERROR;
}
}
}
bool Display::IsValid() const {
return display_ != EGL_NO_DISPLAY;
}
std::unique_ptr<Context> Display::CreateContext(const Config& config,
const Context* share_context) {
const auto& desc = config.GetDescriptor();
std::vector<EGLint> attributes;
switch (desc.api) {
case API::kOpenGL:
break;
case API::kOpenGLES2:
attributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
attributes.push_back(2);
break;
case API::kOpenGLES3:
attributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
attributes.push_back(3);
break;
}
// Termination sentinel must be present.
attributes.push_back(EGL_NONE);
auto context = ::eglCreateContext(
display_, // display
config.GetHandle(), // config
share_context != nullptr ? share_context->GetHandle() : nullptr, // share
attributes.data() // attributes
);
if (context == EGL_NO_CONTEXT) {
IMPELLER_LOG_EGL_ERROR;
return nullptr;
}
return std::make_unique<Context>(display_, context);
}
std::unique_ptr<Config> Display::ChooseConfig(ConfigDescriptor config) const {
if (!display_) {
return nullptr;
}
std::vector<EGLint> attributes;
{
attributes.push_back(EGL_RENDERABLE_TYPE);
switch (config.api) {
case API::kOpenGL:
attributes.push_back(EGL_OPENGL_BIT);
break;
case API::kOpenGLES2:
attributes.push_back(EGL_OPENGL_ES2_BIT);
break;
case API::kOpenGLES3:
attributes.push_back(EGL_OPENGL_ES3_BIT);
break;
}
}
{
attributes.push_back(EGL_SURFACE_TYPE);
switch (config.surface_type) {
case SurfaceType::kWindow:
attributes.push_back(EGL_WINDOW_BIT);
break;
case SurfaceType::kPBuffer:
attributes.push_back(EGL_PBUFFER_BIT);
break;
}
}
{
switch (config.color_format) {
case ColorFormat::kRGBA8888:
attributes.push_back(EGL_RED_SIZE);
attributes.push_back(8);
attributes.push_back(EGL_GREEN_SIZE);
attributes.push_back(8);
attributes.push_back(EGL_BLUE_SIZE);
attributes.push_back(8);
attributes.push_back(EGL_ALPHA_SIZE);
attributes.push_back(8);
break;
case ColorFormat::kRGB565:
attributes.push_back(EGL_RED_SIZE);
attributes.push_back(5);
attributes.push_back(EGL_GREEN_SIZE);
attributes.push_back(6);
attributes.push_back(EGL_BLUE_SIZE);
attributes.push_back(5);
break;
}
}
{
attributes.push_back(EGL_DEPTH_SIZE);
attributes.push_back(static_cast<EGLint>(config.depth_bits));
}
{
attributes.push_back(EGL_STENCIL_SIZE);
attributes.push_back(static_cast<EGLint>(config.stencil_bits));
}
{
const auto sample_count = static_cast<EGLint>(config.samples);
if (sample_count > 1) {
attributes.push_back(EGL_SAMPLE_BUFFERS);
attributes.push_back(1);
}
attributes.push_back(EGL_SAMPLES);
attributes.push_back(sample_count);
}
// termination sentinel must be present.
attributes.push_back(EGL_NONE);
EGLConfig config_out = nullptr;
EGLint config_count_out = 0;
if (::eglChooseConfig(display_, // display
attributes.data(), // attributes (null terminated)
&config_out, // matched configs
1, // configs array size
&config_count_out // match configs count
) != EGL_TRUE) {
IMPELLER_LOG_EGL_ERROR;
return nullptr;
}
if (config_count_out != 1u) {
IMPELLER_LOG_EGL_ERROR;
return nullptr;
}
return std::make_unique<Config>(std::move(config), config_out);
}
std::unique_ptr<Surface> Display::CreateWindowSurface(
const Config& config,
EGLNativeWindowType window) {
const EGLint attribs[] = {EGL_NONE};
auto surface = ::eglCreateWindowSurface(display_, // display
config.GetHandle(), // config
window, // window
attribs // attrib_list
);
if (surface == EGL_NO_SURFACE) {
IMPELLER_LOG_EGL_ERROR;
return nullptr;
}
return std::make_unique<Surface>(display_, surface);
}
std::unique_ptr<Surface> Display::CreatePixelBufferSurface(const Config& config,
size_t width,
size_t height) {
// clang-format off
const EGLint attribs[] = {
EGL_WIDTH, static_cast<EGLint>(width),
EGL_HEIGHT, static_cast<EGLint>(height),
EGL_NONE
};
// clang-format on
auto surface = ::eglCreatePbufferSurface(display_, // display
config.GetHandle(), // config
attribs // attrib_list
);
if (surface == EGL_NO_SURFACE) {
IMPELLER_LOG_EGL_ERROR;
return nullptr;
}
return std::make_unique<Surface>(display_, surface);
}
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,47 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <memory>
#include <optional>
#include "flutter/fml/macros.h"
#include "impeller/toolkit/egl/config.h"
#include "impeller/toolkit/egl/egl.h"
namespace impeller {
namespace egl {
class Context;
class Surface;
class Display {
public:
Display();
~Display();
bool IsValid() const;
std::unique_ptr<Config> ChooseConfig(ConfigDescriptor config) const;
std::unique_ptr<Context> CreateContext(const Config& config,
const Context* share_context);
std::unique_ptr<Surface> CreateWindowSurface(const Config& config,
EGLNativeWindowType window);
std::unique_ptr<Surface> CreatePixelBufferSurface(const Config& config,
size_t width,
size_t height);
private:
EGLDisplay display_ = EGL_NO_DISPLAY;
FML_DISALLOW_COPY_AND_ASSIGN(Display);
};
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,61 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/toolkit/egl/egl.h"
#include "flutter/fml/logging.h"
namespace impeller {
namespace egl {
std::function<void*(const char*)> CreateProcAddressResolver() {
return [](const char* name) -> void* {
return reinterpret_cast<void*>(::eglGetProcAddress(name));
};
}
static const char* EGLErrorToString(EGLint error) {
switch (error) {
case EGL_SUCCESS:
return "Success";
case EGL_NOT_INITIALIZED:
return "Not Initialized";
case EGL_BAD_ACCESS:
return "Bad Access";
case EGL_BAD_ALLOC:
return "Bad Alloc";
case EGL_BAD_ATTRIBUTE:
return "Bad Attribute";
case EGL_BAD_CONTEXT:
return "Bad Context";
case EGL_BAD_CONFIG:
return "Bad Config";
case EGL_BAD_CURRENT_SURFACE:
return "Bad Current Surface";
case EGL_BAD_DISPLAY:
return "Bad Display";
case EGL_BAD_SURFACE:
return "Bad Surface";
case EGL_BAD_MATCH:
return "Bad Match";
case EGL_BAD_PARAMETER:
return "Bad Parameter";
case EGL_BAD_NATIVE_PIXMAP:
return "Bad Native Pixmap";
case EGL_BAD_NATIVE_WINDOW:
return "Bad Native Window";
case EGL_CONTEXT_LOST:
return "Context Lost";
}
return "Unknown";
}
void LogEGLError(const char* file, int line) {
const auto error = ::eglGetError();
FML_LOG(ERROR) << "EGL Error: " << EGLErrorToString(error) << " (" << error
<< ") in " << file << ":" << line;
}
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,21 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <EGL/egl.h>
#include <functional>
namespace impeller {
namespace egl {
std::function<void*(const char*)> CreateProcAddressResolver();
#define IMPELLER_LOG_EGL_ERROR LogEGLError(__FILE__, __LINE__);
void LogEGLError(const char* file, int line);
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,38 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/toolkit/egl/surface.h"
namespace impeller {
namespace egl {
Surface::Surface(EGLDisplay display, EGLSurface surface)
: display_(display), surface_(surface) {}
Surface::~Surface() {
if (surface_ != EGL_NO_SURFACE) {
if (::eglDestroySurface(display_, surface_) != EGL_TRUE) {
IMPELLER_LOG_EGL_ERROR;
}
}
}
const EGLSurface& Surface::GetHandle() const {
return surface_;
}
bool Surface::IsValid() const {
return surface_ != EGL_NO_SURFACE;
}
bool Surface::Present() const {
const auto result = ::eglSwapBuffers(display_, surface_) == EGL_TRUE;
if (!result) {
IMPELLER_LOG_EGL_ERROR;
}
return result;
}
} // namespace egl
} // namespace impeller

View File

@ -0,0 +1,33 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "flutter/fml/macros.h"
#include "impeller/toolkit/egl/egl.h"
namespace impeller {
namespace egl {
class Surface {
public:
Surface(EGLDisplay display, EGLSurface surface);
~Surface();
bool IsValid() const;
const EGLSurface& GetHandle() const;
bool Present() const;
private:
EGLDisplay display_ = EGL_NO_DISPLAY;
EGLSurface surface_ = EGL_NO_SURFACE;
FML_DISALLOW_COPY_AND_ASSIGN(Surface);
};
} // namespace egl
} // namespace impeller

View File

@ -17,7 +17,7 @@ declare_args() {
impeller_enable_metal = is_mac || is_ios
# Whether the OpenGLES backend is enabled.
impeller_enable_opengles = is_mac || is_linux
impeller_enable_opengles = is_mac || is_linux || is_android
# Whether to use a prebuilt impellerc.
# If this is the empty string, impellerc will be built.

View File

@ -4,7 +4,7 @@
#include "flutter/shell/common/shell_test_platform_view_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
namespace flutter {
namespace testing {
@ -35,7 +35,7 @@ void ShellTestPlatformViewGL::SimulateVSync() {
// |PlatformView|
std::unique_ptr<Surface> ShellTestPlatformViewGL::CreateRenderingSurface() {
return std::make_unique<GPUSurfaceGL>(this, true);
return std::make_unique<GPUSurfaceGLSkia>(this, true);
}
// |PlatformView|

View File

@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//flutter/common/config.gni")
import("//flutter/impeller/tools/impeller.gni")
import("//flutter/shell/config.gni")
gpu_common_deps = [
@ -27,13 +28,22 @@ source_set("gpu_surface_software") {
source_set("gpu_surface_gl") {
sources = [
"gpu_surface_gl.cc",
"gpu_surface_gl.h",
"gpu_surface_gl_delegate.cc",
"gpu_surface_gl_delegate.h",
"gpu_surface_gl_skia.cc",
"gpu_surface_gl_skia.h",
]
public_deps = gpu_common_deps
if (impeller_enable_opengles) {
sources += [
"gpu_surface_gl_impeller.cc",
"gpu_surface_gl_impeller.h",
]
public_deps += [ "//flutter/impeller" ]
}
}
source_set("gpu_surface_vulkan") {

View File

@ -0,0 +1,153 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/gpu/gpu_surface_gl_impeller.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/impeller/display_list/display_list_dispatcher.h"
#include "flutter/impeller/renderer/backend/gles/surface_gles.h"
#include "flutter/impeller/renderer/renderer.h"
namespace flutter {
GPUSurfaceGLImpeller::GPUSurfaceGLImpeller(
GPUSurfaceGLDelegate* delegate,
std::shared_ptr<impeller::Context> context)
: weak_factory_(this) {
if (delegate == nullptr) {
return;
}
if (!context || !context->IsValid()) {
return;
}
auto renderer = std::make_shared<impeller::Renderer>(context);
if (!renderer->IsValid()) {
return;
}
auto aiks_context = std::make_shared<impeller::AiksContext>(context);
if (!aiks_context->IsValid()) {
return;
}
delegate_ = delegate;
impeller_context_ = std::move(context);
impeller_renderer_ = std::move(renderer);
aiks_context_ = std::move(aiks_context);
is_valid_ = true;
}
// |Surface|
GPUSurfaceGLImpeller::~GPUSurfaceGLImpeller() = default;
// |Surface|
bool GPUSurfaceGLImpeller::IsValid() {
return is_valid_;
}
// |Surface|
std::unique_ptr<SurfaceFrame> GPUSurfaceGLImpeller::AcquireFrame(
const SkISize& size) {
if (!IsValid()) {
FML_LOG(ERROR) << "OpenGL surface was invalid.";
return nullptr;
}
auto swap_callback = [weak = weak_factory_.GetWeakPtr(),
delegate = delegate_]() -> bool {
if (weak) {
delegate->GLContextPresent(0u, std::nullopt);
}
return true;
};
auto context_switch = delegate_->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to acquire the frame.";
return nullptr;
}
auto surface = impeller::SurfaceGLES::WrapFBO(
impeller_context_, // context
swap_callback, // swap_callback
0u, // fbo
impeller::PixelFormat::kR8G8B8A8UNormInt, // color_format
impeller::ISize{size.width(), size.height()} // fbo_size
);
SurfaceFrame::SubmitCallback submit_callback =
fml::MakeCopyable([renderer = impeller_renderer_, //
aiks_context = aiks_context_, //
surface = std::move(surface) //
](SurfaceFrame& surface_frame, SkCanvas* canvas) mutable -> bool {
if (!aiks_context) {
return false;
}
auto display_list = surface_frame.BuildDisplayList();
if (!display_list) {
FML_LOG(ERROR) << "Could not build display list for surface frame.";
return false;
}
impeller::DisplayListDispatcher impeller_dispatcher;
display_list->Dispatch(impeller_dispatcher);
auto picture = impeller_dispatcher.EndRecordingAsPicture();
return renderer->Render(
std::move(surface),
fml::MakeCopyable(
[aiks_context, picture = std::move(picture)](
impeller::RenderTarget& render_target) -> bool {
return aiks_context->Render(picture, render_target);
}));
});
return std::make_unique<SurfaceFrame>(
nullptr, // surface
SurfaceFrame::FramebufferInfo{}, // framebuffer info
submit_callback, // submit callback
std::move(context_switch), // context result
true // display list fallback
);
}
// |Surface|
SkMatrix GPUSurfaceGLImpeller::GetRootTransformation() const {
// This backend does not currently support root surface transformations. Just
// return identity.
return {};
}
// |Surface|
GrDirectContext* GPUSurfaceGLImpeller::GetContext() {
// Impeller != Skia.
return nullptr;
}
// |Surface|
std::unique_ptr<GLContextResult>
GPUSurfaceGLImpeller::MakeRenderContextCurrent() {
return delegate_->GLContextMakeCurrent();
}
// |Surface|
bool GPUSurfaceGLImpeller::ClearRenderContext() {
return delegate_->GLContextClearCurrent();
}
bool GPUSurfaceGLImpeller::AllowsDrawingWhenGpuDisabled() const {
return delegate_->AllowsDrawingWhenGpuDisabled();
}
// |Surface|
bool GPUSurfaceGLImpeller::EnableRasterCache() const {
return false;
}
} // namespace flutter

View File

@ -0,0 +1,63 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_GPU_GPU_SURFACE_GL_IMPELLER_H_
#define SHELL_GPU_GPU_SURFACE_GL_IMPELLER_H_
#include "flutter/common/graphics/gl_context_switch.h"
#include "flutter/flow/surface.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/impeller/aiks/aiks_context.h"
#include "flutter/impeller/renderer/context.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
namespace flutter {
class GPUSurfaceGLImpeller final : public Surface {
public:
explicit GPUSurfaceGLImpeller(GPUSurfaceGLDelegate* delegate,
std::shared_ptr<impeller::Context> context);
// |Surface|
~GPUSurfaceGLImpeller() override;
// |Surface|
bool IsValid() override;
private:
GPUSurfaceGLDelegate* delegate_ = nullptr;
std::shared_ptr<impeller::Context> impeller_context_;
std::shared_ptr<impeller::Renderer> impeller_renderer_;
std::shared_ptr<impeller::AiksContext> aiks_context_;
bool is_valid_ = false;
fml::WeakPtrFactory<GPUSurfaceGLImpeller> weak_factory_;
// |Surface|
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;
// |Surface|
SkMatrix GetRootTransformation() const override;
// |Surface|
GrDirectContext* GetContext() override;
// |Surface|
std::unique_ptr<GLContextResult> MakeRenderContextCurrent() override;
// |Surface|
bool ClearRenderContext() override;
// |Surface|
bool AllowsDrawingWhenGpuDisabled() const override;
// |Surface|
bool EnableRasterCache() const override;
FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGLImpeller);
};
} // namespace flutter
#endif // SHELL_GPU_GPU_SURFACE_GL_IMPELLER_H_

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#include "flutter/common/graphics/persistent_cache.h"
#include "flutter/fml/base32.h"
@ -35,7 +35,7 @@ namespace flutter {
// system channel.
static const size_t kGrCacheMaxByteSize = 24 * (1 << 20);
sk_sp<GrDirectContext> GPUSurfaceGL::MakeGLContext(
sk_sp<GrDirectContext> GPUSurfaceGLSkia::MakeGLContext(
GPUSurfaceGLDelegate* delegate) {
auto context_switch = delegate->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
@ -61,15 +61,15 @@ sk_sp<GrDirectContext> GPUSurfaceGL::MakeGLContext(
return context;
}
GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
: GPUSurfaceGL(MakeGLContext(delegate), delegate, render_to_surface) {
GPUSurfaceGLSkia::GPUSurfaceGLSkia(GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
: GPUSurfaceGLSkia(MakeGLContext(delegate), delegate, render_to_surface) {
context_owner_ = true;
}
GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrDirectContext> gr_context,
GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
GPUSurfaceGLSkia::GPUSurfaceGLSkia(sk_sp<GrDirectContext> gr_context,
GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
: delegate_(delegate),
context_(gr_context),
context_owner_(false),
@ -87,7 +87,7 @@ GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrDirectContext> gr_context,
valid_ = gr_context != nullptr;
}
GPUSurfaceGL::~GPUSurfaceGL() {
GPUSurfaceGLSkia::~GPUSurfaceGLSkia() {
if (!valid_) {
return;
}
@ -109,7 +109,7 @@ GPUSurfaceGL::~GPUSurfaceGL() {
}
// |Surface|
bool GPUSurfaceGL::IsValid() {
bool GPUSurfaceGLSkia::IsValid() {
return valid_;
}
@ -156,7 +156,7 @@ static sk_sp<SkSurface> WrapOnscreenSurface(GrDirectContext* context,
);
}
bool GPUSurfaceGL::CreateOrUpdateSurfaces(const SkISize& size) {
bool GPUSurfaceGLSkia::CreateOrUpdateSurfaces(const SkISize& size) {
if (onscreen_surface_ != nullptr &&
size == SkISize::Make(onscreen_surface_->width(),
onscreen_surface_->height())) {
@ -200,12 +200,13 @@ bool GPUSurfaceGL::CreateOrUpdateSurfaces(const SkISize& size) {
}
// |Surface|
SkMatrix GPUSurfaceGL::GetRootTransformation() const {
SkMatrix GPUSurfaceGLSkia::GetRootTransformation() const {
return delegate_->GLContextSurfaceTransformation();
}
// |Surface|
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
std::unique_ptr<SurfaceFrame> GPUSurfaceGLSkia::AcquireFrame(
const SkISize& size) {
if (delegate_ == nullptr) {
return nullptr;
}
@ -251,7 +252,8 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
std::move(context_switch));
}
bool GPUSurfaceGL::PresentSurface(const SurfaceFrame& frame, SkCanvas* canvas) {
bool GPUSurfaceGLSkia::PresentSurface(const SurfaceFrame& frame,
SkCanvas* canvas) {
if (delegate_ == nullptr || canvas == nullptr || context_ == nullptr) {
return false;
}
@ -294,7 +296,7 @@ bool GPUSurfaceGL::PresentSurface(const SurfaceFrame& frame, SkCanvas* canvas) {
return true;
}
sk_sp<SkSurface> GPUSurfaceGL::AcquireRenderSurface(
sk_sp<SkSurface> GPUSurfaceGLSkia::AcquireRenderSurface(
const SkISize& untransformed_size,
const SkMatrix& root_surface_transformation) {
const auto transformed_rect = root_surface_transformation.mapRect(
@ -311,22 +313,22 @@ sk_sp<SkSurface> GPUSurfaceGL::AcquireRenderSurface(
}
// |Surface|
GrDirectContext* GPUSurfaceGL::GetContext() {
GrDirectContext* GPUSurfaceGLSkia::GetContext() {
return context_.get();
}
// |Surface|
std::unique_ptr<GLContextResult> GPUSurfaceGL::MakeRenderContextCurrent() {
std::unique_ptr<GLContextResult> GPUSurfaceGLSkia::MakeRenderContextCurrent() {
return delegate_->GLContextMakeCurrent();
}
// |Surface|
bool GPUSurfaceGL::ClearRenderContext() {
bool GPUSurfaceGLSkia::ClearRenderContext() {
return delegate_->GLContextClearCurrent();
}
// |Surface|
bool GPUSurfaceGL::AllowsDrawingWhenGpuDisabled() const {
bool GPUSurfaceGLSkia::AllowsDrawingWhenGpuDisabled() const {
return delegate_->AllowsDrawingWhenGpuDisabled();
}

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_GPU_GPU_SURFACE_GL_H_
#define SHELL_GPU_GPU_SURFACE_GL_H_
#ifndef SHELL_GPU_GPU_SURFACE_GL_SKIA_H_
#define SHELL_GPU_GPU_SURFACE_GL_SKIA_H_
#include <functional>
#include <memory>
@ -18,19 +18,19 @@
namespace flutter {
class GPUSurfaceGL : public Surface {
class GPUSurfaceGLSkia : public Surface {
public:
static sk_sp<GrDirectContext> MakeGLContext(GPUSurfaceGLDelegate* delegate);
GPUSurfaceGL(GPUSurfaceGLDelegate* delegate, bool render_to_surface);
GPUSurfaceGLSkia(GPUSurfaceGLDelegate* delegate, bool render_to_surface);
// Creates a new GL surface reusing an existing GrDirectContext.
GPUSurfaceGL(sk_sp<GrDirectContext> gr_context,
GPUSurfaceGLDelegate* delegate,
bool render_to_surface);
GPUSurfaceGLSkia(sk_sp<GrDirectContext> gr_context,
GPUSurfaceGLDelegate* delegate,
bool render_to_surface);
// |Surface|
~GPUSurfaceGL() override;
~GPUSurfaceGLSkia() override;
// |Surface|
bool IsValid() override;
@ -76,10 +76,10 @@ class GPUSurfaceGL : public Surface {
bool valid_ = false;
// WeakPtrFactory must be the last member.
fml::TaskRunnerAffineWeakPtrFactory<GPUSurfaceGL> weak_factory_;
FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGL);
fml::TaskRunnerAffineWeakPtrFactory<GPUSurfaceGLSkia> weak_factory_;
FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGLSkia);
};
} // namespace flutter
#endif // SHELL_GPU_GPU_SURFACE_GL_H_
#endif // SHELL_GPU_GPU_SURFACE_GL_SKIA_H_

View File

@ -64,18 +64,24 @@ source_set("flutter_shell_native_src") {
"$root_build_dir/flutter_icu/icudtl.o",
"android_choreographer.cc",
"android_choreographer.h",
"android_context_gl.cc",
"android_context_gl.h",
"android_context_gl_impeller.cc",
"android_context_gl_impeller.h",
"android_context_gl_skia.cc",
"android_context_gl_skia.h",
"android_display.cc",
"android_display.h",
"android_egl_surface.cc",
"android_egl_surface.h",
"android_environment_gl.cc",
"android_environment_gl.h",
"android_external_texture_gl.cc",
"android_external_texture_gl.h",
"android_shell_holder.cc",
"android_shell_holder.h",
"android_surface_gl.cc",
"android_surface_gl.h",
"android_surface_gl_impeller.cc",
"android_surface_gl_impeller.h",
"android_surface_gl_skia.cc",
"android_surface_gl_skia.h",
"android_surface_software.cc",
"android_surface_software.h",
"apk_asset_provider.cc",
@ -104,6 +110,8 @@ source_set("flutter_shell_native_src") {
"//flutter/common/graphics",
"//flutter/flow",
"//flutter/fml",
"//flutter/impeller",
"//flutter/impeller/toolkit/egl",
"//flutter/lib/ui",
"//flutter/runtime",
"//flutter/runtime:libdart",

View File

@ -1,186 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "flutter/shell/platform/android/context/android_context.h"
#include "flutter/shell/platform/android/surface/android_native_window.h"
#include "third_party/skia/include/core/SkSize.h"
namespace flutter {
//------------------------------------------------------------------------------
/// Holds an `EGLSurface` reference.
///
///
/// This can be used in conjunction to unique_ptr to provide better guarantees
/// about the lifespan of the `EGLSurface` object.
///
class AndroidEGLSurfaceDamage;
/// Result of calling MakeCurrent on AndroidEGLSurface.
enum class AndroidEGLSurfaceMakeCurrentStatus {
/// Success, the egl context for the surface was already current.
kSuccessAlreadyCurrent,
/// Success, the egl context for the surface made current.
kSuccessMadeCurrent,
/// Failed to make the egl context for the surface current.
kFailure,
};
class AndroidEGLSurface {
public:
AndroidEGLSurface(EGLSurface surface, EGLDisplay display, EGLContext context);
~AndroidEGLSurface();
//----------------------------------------------------------------------------
/// @return Whether the current `EGLSurface` reference is valid. That is,
/// if
/// the surface doesn't point to `EGL_NO_SURFACE`.
///
bool IsValid() const;
//----------------------------------------------------------------------------
/// @brief Binds the EGLContext context to the current rendering thread
/// and to the draw and read surface.
///
/// @return Whether the surface was made current.
///
AndroidEGLSurfaceMakeCurrentStatus MakeCurrent() const;
//----------------------------------------------------------------------------
///
/// @return Whether target surface supports partial repaint.
///
bool SupportsPartialRepaint() const;
//----------------------------------------------------------------------------
/// @brief This is the minimal area that needs to be repainted to get
/// correct result.
///
/// With double or triple buffering this buffer content may lag behind
/// current front buffer and the rect accounts for accumulated damage.
///
/// @return The area of current surface where it is behind front buffer.
///
std::optional<SkIRect> InitialDamage();
//----------------------------------------------------------------------------
/// @brief Sets the damage region for current surface. Corresponds to
// eglSetDamageRegionKHR
void SetDamageRegion(const std::optional<SkIRect>& buffer_damage);
//----------------------------------------------------------------------------
/// @brief This only applies to on-screen surfaces such as those created
/// by `AndroidContextGL::CreateOnscreenSurface`.
///
/// @return Whether the EGL surface color buffer was swapped.
///
bool SwapBuffers(const std::optional<SkIRect>& surface_damage);
//----------------------------------------------------------------------------
/// @return The size of an `EGLSurface`.
///
SkISize GetSize() const;
private:
/// Returns true if the EGLContext held is current for the display and surface
bool IsContextCurrent() const;
const EGLSurface surface_;
const EGLDisplay display_;
const EGLContext context_;
std::unique_ptr<AndroidEGLSurfaceDamage> damage_;
};
//------------------------------------------------------------------------------
/// The Android context is used by `AndroidSurfaceGL` to create and manage
/// EGL surfaces.
///
/// This context binds `EGLContext` to the current rendering thread and to the
/// draw and read `EGLSurface`s.
///
class AndroidContextGL : public AndroidContext {
public:
AndroidContextGL(AndroidRenderingAPI rendering_api,
fml::RefPtr<AndroidEnvironmentGL> environment,
const TaskRunners& taskRunners,
uint8_t msaa_samples);
~AndroidContextGL();
//----------------------------------------------------------------------------
/// @brief Allocates an new EGL window surface that is used for on-screen
/// pixels.
///
/// @return The window surface.
///
std::unique_ptr<AndroidEGLSurface> CreateOnscreenSurface(
fml::RefPtr<AndroidNativeWindow> window) const;
//----------------------------------------------------------------------------
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
/// offscreen current for texture uploads.
///
/// @return The pbuffer surface.
///
std::unique_ptr<AndroidEGLSurface> CreateOffscreenSurface() const;
//----------------------------------------------------------------------------
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
/// onscreen context current for snapshotting.
///
/// @return The pbuffer surface.
///
std::unique_ptr<AndroidEGLSurface> CreatePbufferSurface() const;
//----------------------------------------------------------------------------
/// @return The Android environment that contains a reference to the
/// display.
///
fml::RefPtr<AndroidEnvironmentGL> Environment() const;
//----------------------------------------------------------------------------
/// @return Whether the current context is valid. That is, if the EGL
/// contexts were successfully created.
///
bool IsValid() const override;
//----------------------------------------------------------------------------
/// @return Whether the current context was successfully clear.
///
bool ClearCurrent() const;
//----------------------------------------------------------------------------
/// @brief Create a new EGLContext using the same EGLConfig.
///
/// @return The EGLContext.
///
EGLContext CreateNewContext() const;
//----------------------------------------------------------------------------
/// @brief The EGLConfig for this context.
///
EGLConfig Config() const { return config_; }
private:
fml::RefPtr<AndroidEnvironmentGL> environment_;
EGLConfig config_;
EGLContext context_;
EGLContext resource_context_;
bool valid_ = false;
TaskRunners task_runners_;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGL);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_

View File

@ -0,0 +1,18 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/android/android_context_gl_impeller.h"
namespace flutter {
AndroidContextGLImpeller::AndroidContextGLImpeller()
: AndroidContext(AndroidRenderingAPI::kOpenGLES) {}
AndroidContextGLImpeller::~AndroidContextGLImpeller() = default;
bool AndroidContextGLImpeller::IsValid() const {
return true;
}
} // namespace flutter

View File

@ -0,0 +1,28 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_IMPELLER_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_IMPELLER_H_
#include "flutter/fml/macros.h"
#include "flutter/shell/platform/android/context/android_context.h"
namespace flutter {
class AndroidContextGLImpeller : public AndroidContext {
public:
AndroidContextGLImpeller();
~AndroidContextGLImpeller();
// |AndroidContext|
bool IsValid() const override;
private:
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGLImpeller);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_IMPELLER_H_

View File

@ -0,0 +1,216 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/android/android_context_gl_skia.h"
#include <utility>
#include "flutter/fml/trace_event.h"
#include "flutter/shell/platform/android/android_egl_surface.h"
namespace flutter {
template <class T>
using EGLResult = std::pair<bool, T>;
static EGLResult<EGLContext> CreateContext(EGLDisplay display,
EGLConfig config,
EGLContext share = EGL_NO_CONTEXT) {
EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLContext context = eglCreateContext(display, config, share, attributes);
return {context != EGL_NO_CONTEXT, context};
}
static EGLResult<EGLConfig> ChooseEGLConfiguration(EGLDisplay display,
uint8_t msaa_samples) {
EGLint sample_buffers = msaa_samples > 1 ? 1 : 0;
EGLint attributes[] = {
// clang-format off
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_SAMPLES, static_cast<EGLint>(msaa_samples),
EGL_SAMPLE_BUFFERS, sample_buffers,
EGL_NONE, // termination sentinel
// clang-format on
};
EGLint config_count = 0;
EGLConfig egl_config = nullptr;
if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) !=
EGL_TRUE) {
return {false, nullptr};
}
bool success = config_count > 0 && egl_config != nullptr;
return {success, success ? egl_config : nullptr};
}
static bool TeardownContext(EGLDisplay display, EGLContext context) {
if (context != EGL_NO_CONTEXT) {
return eglDestroyContext(display, context) == EGL_TRUE;
}
return true;
}
AndroidContextGLSkia::AndroidContextGLSkia(
AndroidRenderingAPI rendering_api,
fml::RefPtr<AndroidEnvironmentGL> environment,
const TaskRunners& task_runners,
uint8_t msaa_samples)
: AndroidContext(AndroidRenderingAPI::kOpenGLES),
environment_(environment),
config_(nullptr),
task_runners_(task_runners) {
if (!environment_->IsValid()) {
FML_LOG(ERROR) << "Could not create an Android GL environment.";
return;
}
bool success = false;
// Choose a valid configuration.
std::tie(success, config_) =
ChooseEGLConfiguration(environment_->Display(), msaa_samples);
if (!success) {
FML_LOG(ERROR) << "Could not choose an EGL configuration.";
LogLastEGLError();
return;
}
// Create a context for the configuration.
std::tie(success, context_) =
CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
if (!success) {
FML_LOG(ERROR) << "Could not create an EGL context";
LogLastEGLError();
return;
}
std::tie(success, resource_context_) =
CreateContext(environment_->Display(), config_, context_);
if (!success) {
FML_LOG(ERROR) << "Could not create an EGL resource context";
LogLastEGLError();
return;
}
// All done!
valid_ = true;
}
AndroidContextGLSkia::~AndroidContextGLSkia() {
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
sk_sp<GrDirectContext> main_context = GetMainSkiaContext();
SetMainSkiaContext(nullptr);
fml::AutoResetWaitableEvent latch;
// This context needs to be deallocated from the raster thread in order to
// keep a coherent usage of egl from a single thread.
fml::TaskRunner::RunNowOrPostTask(task_runners_.GetRasterTaskRunner(), [&] {
if (main_context) {
std::unique_ptr<AndroidEGLSurface> pbuffer_surface =
CreatePbufferSurface();
auto status = pbuffer_surface->MakeCurrent();
if (status != AndroidEGLSurfaceMakeCurrentStatus::kFailure) {
main_context->releaseResourcesAndAbandonContext();
main_context.reset();
ClearCurrent();
}
}
latch.Signal();
});
latch.Wait();
if (!TeardownContext(environment_->Display(), context_)) {
FML_LOG(ERROR)
<< "Could not tear down the EGL context. Possible resource leak.";
LogLastEGLError();
}
if (!TeardownContext(environment_->Display(), resource_context_)) {
FML_LOG(ERROR) << "Could not tear down the EGL resource context. Possible "
"resource leak.";
LogLastEGLError();
}
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGLSkia::CreateOnscreenSurface(
fml::RefPtr<AndroidNativeWindow> window) const {
if (window->IsFakeWindow()) {
return CreatePbufferSurface();
} else {
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_NONE};
EGLSurface surface = eglCreateWindowSurface(
display, config_,
reinterpret_cast<EGLNativeWindowType>(window->handle()), attribs);
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
}
}
std::unique_ptr<AndroidEGLSurface>
AndroidContextGLSkia::CreateOffscreenSurface() const {
// We only ever create pbuffer surfaces for background resource loading
// contexts. We never bind the pbuffer to anything.
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
return std::make_unique<AndroidEGLSurface>(surface, display,
resource_context_);
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGLSkia::CreatePbufferSurface()
const {
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
}
fml::RefPtr<AndroidEnvironmentGL> AndroidContextGLSkia::Environment() const {
return environment_;
}
bool AndroidContextGLSkia::IsValid() const {
return valid_;
}
bool AndroidContextGLSkia::ClearCurrent() const {
if (eglGetCurrentContext() != context_) {
return true;
}
if (eglMakeCurrent(environment_->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT) != EGL_TRUE) {
FML_LOG(ERROR) << "Could not clear the current context";
LogLastEGLError();
return false;
}
return true;
}
EGLContext AndroidContextGLSkia::CreateNewContext() const {
bool success;
EGLContext context;
std::tie(success, context) =
CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
return success ? context : EGL_NO_CONTEXT;
}
} // namespace flutter

View File

@ -0,0 +1,104 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "flutter/shell/platform/android/context/android_context.h"
#include "flutter/shell/platform/android/surface/android_native_window.h"
#include "third_party/skia/include/core/SkSize.h"
namespace flutter {
class AndroidEGLSurface;
//------------------------------------------------------------------------------
/// The Android context is used by `AndroidSurfaceGL` to create and manage
/// EGL surfaces.
///
/// This context binds `EGLContext` to the current rendering thread and to the
/// draw and read `EGLSurface`s.
///
class AndroidContextGLSkia : public AndroidContext {
public:
AndroidContextGLSkia(AndroidRenderingAPI rendering_api,
fml::RefPtr<AndroidEnvironmentGL> environment,
const TaskRunners& taskRunners,
uint8_t msaa_samples);
~AndroidContextGLSkia();
//----------------------------------------------------------------------------
/// @brief Allocates an new EGL window surface that is used for on-screen
/// pixels.
///
/// @return The window surface.
///
std::unique_ptr<AndroidEGLSurface> CreateOnscreenSurface(
fml::RefPtr<AndroidNativeWindow> window) const;
//----------------------------------------------------------------------------
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
/// offscreen current for texture uploads.
///
/// @return The pbuffer surface.
///
std::unique_ptr<AndroidEGLSurface> CreateOffscreenSurface() const;
//----------------------------------------------------------------------------
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
/// onscreen context current for snapshotting.
///
/// @return The pbuffer surface.
///
std::unique_ptr<AndroidEGLSurface> CreatePbufferSurface() const;
//----------------------------------------------------------------------------
/// @return The Android environment that contains a reference to the
/// display.
///
fml::RefPtr<AndroidEnvironmentGL> Environment() const;
//----------------------------------------------------------------------------
/// @return Whether the current context is valid. That is, if the EGL
/// contexts were successfully created.
///
bool IsValid() const override;
//----------------------------------------------------------------------------
/// @return Whether the current context was successfully clear.
///
bool ClearCurrent() const;
//----------------------------------------------------------------------------
/// @brief Create a new EGLContext using the same EGLConfig.
///
/// @return The EGLContext.
///
EGLContext CreateNewContext() const;
//----------------------------------------------------------------------------
/// @brief The EGLConfig for this context.
///
EGLConfig Config() const { return config_; }
private:
fml::RefPtr<AndroidEnvironmentGL> environment_;
EGLConfig config_;
EGLContext context_;
EGLContext resource_context_;
bool valid_ = false;
TaskRunners task_runners_;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGLSkia);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_

View File

@ -2,9 +2,10 @@
#include <memory>
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/platform/android/android_context_gl.h"
#include "flutter/shell/platform/android/android_context_gl_skia.h"
#include "flutter/shell/platform/android/android_egl_surface.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "flutter/shell/platform/android/android_surface_gl.h"
#include "flutter/shell/platform/android/android_surface_gl_skia.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@ -85,7 +86,7 @@ TEST(AndroidContextGl, Create) {
thread_label,
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto context = std::make_unique<AndroidContextGL>(
auto context = std::make_unique<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
context->SetMainSkiaContext(main_context);
EXPECT_NE(context.get(), nullptr);
@ -106,7 +107,7 @@ TEST(AndroidContextGl, CreateSingleThread) {
TaskRunners task_runners =
TaskRunners(thread_label, platform_runner, platform_runner,
platform_runner, platform_runner);
auto context = std::make_unique<AndroidContextGL>(
auto context = std::make_unique<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
context->SetMainSkiaContext(main_context);
EXPECT_NE(context.get(), nullptr);
@ -125,11 +126,11 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNotNull) {
thread_label,
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto android_context = std::make_shared<AndroidContextGL>(
auto android_context = std::make_shared<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
auto jni = std::make_shared<MockPlatformViewAndroidJNI>();
auto android_surface =
std::make_unique<AndroidSurfaceGL>(android_context, jni);
std::make_unique<AndroidSurfaceGLSkia>(android_context, jni);
auto window = fml::MakeRefCounted<AndroidNativeWindow>(
nullptr, /*is_fake_window=*/true);
android_surface->SetNativeWindow(window);
@ -153,11 +154,11 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) {
ThreadHost thread_host(host_config);
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto android_context = std::make_shared<AndroidContextGL>(
auto android_context = std::make_shared<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
auto jni = std::make_shared<MockPlatformViewAndroidJNI>();
auto android_surface =
std::make_unique<AndroidSurfaceGL>(android_context, jni);
std::make_unique<AndroidSurfaceGLSkia>(android_context, jni);
EXPECT_EQ(android_surface->GetOnscreenSurface(), nullptr);
android_surface->CreateSnapshotSurface();
EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr);
@ -175,7 +176,7 @@ TEST(AndroidContextGl, MSAAx4) {
thread_label,
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto context = std::make_unique<AndroidContextGL>(
auto context = std::make_unique<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 4);
context->SetMainSkiaContext(main_context);
@ -197,7 +198,7 @@ TEST(AndroidContextGl, EnsureMakeCurrentChecksCurrentContextStatus) {
thread_label,
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto context = std::make_unique<AndroidContextGL>(
auto context = std::make_unique<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
auto pbuffer_surface = context->CreatePbufferSurface();

View File

@ -2,31 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/android/android_context_gl.h"
#include "flutter/shell/platform/android/android_egl_surface.h"
#include <EGL/eglext.h>
#include <list>
#include <utility>
// required to get API level
#include <sys/system_properties.h>
#include <array>
#include <list>
#include "flutter/fml/trace_event.h"
namespace flutter {
template <class T>
using EGLResult = std::pair<bool, T>;
static void LogLastEGLError() {
void LogLastEGLError() {
struct EGLNameErrorPair {
const char* name;
EGLint code;
};
#define _EGL_ERROR_DESC(a) \
{ #a, a }
{ \
#a, a \
}
const EGLNameErrorPair pairs[] = {
_EGL_ERROR_DESC(EGL_SUCCESS),
@ -63,56 +60,6 @@ static void LogLastEGLError() {
FML_LOG(ERROR) << "Unknown EGL Error";
}
static EGLResult<EGLContext> CreateContext(EGLDisplay display,
EGLConfig config,
EGLContext share = EGL_NO_CONTEXT) {
EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLContext context = eglCreateContext(display, config, share, attributes);
return {context != EGL_NO_CONTEXT, context};
}
static EGLResult<EGLConfig> ChooseEGLConfiguration(EGLDisplay display,
uint8_t msaa_samples) {
EGLint sample_buffers = msaa_samples > 1 ? 1 : 0;
EGLint attributes[] = {
// clang-format off
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_SAMPLES, static_cast<EGLint>(msaa_samples),
EGL_SAMPLE_BUFFERS, sample_buffers,
EGL_NONE, // termination sentinel
// clang-format on
};
EGLint config_count = 0;
EGLConfig egl_config = nullptr;
if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) !=
EGL_TRUE) {
return {false, nullptr};
}
bool success = config_count > 0 && egl_config != nullptr;
return {success, success ? egl_config : nullptr};
}
static bool TeardownContext(EGLDisplay display, EGLContext context) {
if (context != EGL_NO_CONTEXT) {
return eglDestroyContext(display, context) == EGL_TRUE;
}
return true;
}
class AndroidEGLSurfaceDamage {
public:
void init(EGLDisplay display, EGLContext context) {
@ -320,153 +267,4 @@ SkISize AndroidEGLSurface::GetSize() const {
return SkISize::Make(width, height);
}
AndroidContextGL::AndroidContextGL(
AndroidRenderingAPI rendering_api,
fml::RefPtr<AndroidEnvironmentGL> environment,
const TaskRunners& task_runners,
uint8_t msaa_samples)
: AndroidContext(AndroidRenderingAPI::kOpenGLES),
environment_(environment),
config_(nullptr),
task_runners_(task_runners) {
if (!environment_->IsValid()) {
FML_LOG(ERROR) << "Could not create an Android GL environment.";
return;
}
bool success = false;
// Choose a valid configuration.
std::tie(success, config_) =
ChooseEGLConfiguration(environment_->Display(), msaa_samples);
if (!success) {
FML_LOG(ERROR) << "Could not choose an EGL configuration.";
LogLastEGLError();
return;
}
// Create a context for the configuration.
std::tie(success, context_) =
CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
if (!success) {
FML_LOG(ERROR) << "Could not create an EGL context";
LogLastEGLError();
return;
}
std::tie(success, resource_context_) =
CreateContext(environment_->Display(), config_, context_);
if (!success) {
FML_LOG(ERROR) << "Could not create an EGL resource context";
LogLastEGLError();
return;
}
// All done!
valid_ = true;
}
AndroidContextGL::~AndroidContextGL() {
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
sk_sp<GrDirectContext> main_context = GetMainSkiaContext();
SetMainSkiaContext(nullptr);
fml::AutoResetWaitableEvent latch;
// This context needs to be deallocated from the raster thread in order to
// keep a coherent usage of egl from a single thread.
fml::TaskRunner::RunNowOrPostTask(task_runners_.GetRasterTaskRunner(), [&] {
if (main_context) {
std::unique_ptr<AndroidEGLSurface> pbuffer_surface =
CreatePbufferSurface();
auto status = pbuffer_surface->MakeCurrent();
if (status != AndroidEGLSurfaceMakeCurrentStatus::kFailure) {
main_context->releaseResourcesAndAbandonContext();
main_context.reset();
ClearCurrent();
}
}
latch.Signal();
});
latch.Wait();
if (!TeardownContext(environment_->Display(), context_)) {
FML_LOG(ERROR)
<< "Could not tear down the EGL context. Possible resource leak.";
LogLastEGLError();
}
if (!TeardownContext(environment_->Display(), resource_context_)) {
FML_LOG(ERROR) << "Could not tear down the EGL resource context. Possible "
"resource leak.";
LogLastEGLError();
}
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreateOnscreenSurface(
fml::RefPtr<AndroidNativeWindow> window) const {
if (window->IsFakeWindow()) {
return CreatePbufferSurface();
} else {
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_NONE};
EGLSurface surface = eglCreateWindowSurface(
display, config_,
reinterpret_cast<EGLNativeWindowType>(window->handle()), attribs);
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
}
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreateOffscreenSurface()
const {
// We only ever create pbuffer surfaces for background resource loading
// contexts. We never bind the pbuffer to anything.
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
return std::make_unique<AndroidEGLSurface>(surface, display,
resource_context_);
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreatePbufferSurface()
const {
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
}
fml::RefPtr<AndroidEnvironmentGL> AndroidContextGL::Environment() const {
return environment_;
}
bool AndroidContextGL::IsValid() const {
return valid_;
}
bool AndroidContextGL::ClearCurrent() const {
if (eglGetCurrentContext() != context_) {
return true;
}
if (eglMakeCurrent(environment_->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT) != EGL_TRUE) {
FML_LOG(ERROR) << "Could not clear the current context";
LogLastEGLError();
return false;
}
return true;
}
EGLContext AndroidContextGL::CreateNewContext() const {
bool success;
EGLContext context;
std::tie(success, context) =
CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
return success ? context : EGL_NO_CONTEXT;
}
} // namespace flutter

View File

@ -0,0 +1,105 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_EGL_SURFACE_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_EGL_SURFACE_H_
#include <optional>
#include "flutter/fml/macros.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "third_party/skia/include/core/SkRect.h"
namespace flutter {
//------------------------------------------------------------------------------
/// Holds an `EGLSurface` reference.
///
///
/// This can be used in conjunction to unique_ptr to provide better guarantees
/// about the lifespan of the `EGLSurface` object.
///
class AndroidEGLSurfaceDamage;
/// Result of calling MakeCurrent on AndroidEGLSurface.
enum class AndroidEGLSurfaceMakeCurrentStatus {
/// Success, the egl context for the surface was already current.
kSuccessAlreadyCurrent,
/// Success, the egl context for the surface made current.
kSuccessMadeCurrent,
/// Failed to make the egl context for the surface current.
kFailure,
};
void LogLastEGLError();
class AndroidEGLSurface {
public:
AndroidEGLSurface(EGLSurface surface, EGLDisplay display, EGLContext context);
~AndroidEGLSurface();
//----------------------------------------------------------------------------
/// @return Whether the current `EGLSurface` reference is valid. That is,
/// if
/// the surface doesn't point to `EGL_NO_SURFACE`.
///
bool IsValid() const;
//----------------------------------------------------------------------------
/// @brief Binds the EGLContext context to the current rendering thread
/// and to the draw and read surface.
///
/// @return Whether the surface was made current.
///
AndroidEGLSurfaceMakeCurrentStatus MakeCurrent() const;
//----------------------------------------------------------------------------
///
/// @return Whether target surface supports partial repaint.
///
bool SupportsPartialRepaint() const;
//----------------------------------------------------------------------------
/// @brief This is the minimal area that needs to be repainted to get
/// correct result.
///
/// With double or triple buffering this buffer content may lag behind
/// current front buffer and the rect accounts for accumulated damage.
///
/// @return The area of current surface where it is behind front buffer.
///
std::optional<SkIRect> InitialDamage();
//----------------------------------------------------------------------------
/// @brief Sets the damage region for current surface. Corresponds to
// eglSetDamageRegionKHR
void SetDamageRegion(const std::optional<SkIRect>& buffer_damage);
//----------------------------------------------------------------------------
/// @brief This only applies to on-screen surfaces such as those created
/// by `AndroidContextGL::CreateOnscreenSurface`.
///
/// @return Whether the EGL surface color buffer was swapped.
///
bool SwapBuffers(const std::optional<SkIRect>& surface_damage);
//----------------------------------------------------------------------------
/// @return The size of an `EGLSurface`.
///
SkISize GetSize() const;
private:
/// Returns true if the EGLContext held is current for the display and surface
bool IsContextCurrent() const;
const EGLSurface surface_;
const EGLDisplay display_;
const EGLContext context_;
std::unique_ptr<AndroidEGLSurfaceDamage> damage_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_EGL_SURFACE_H_

View File

@ -0,0 +1,263 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/android/android_surface_gl_impeller.h"
#include "flutter/fml/logging.h"
#include "flutter/impeller/entity/gles/entity_shaders_gles.h"
#include "flutter/impeller/renderer/backend/gles/context_gles.h"
#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h"
#include "flutter/impeller/toolkit/egl/context.h"
#include "flutter/impeller/toolkit/egl/surface.h"
#include "flutter/shell/gpu/gpu_surface_gl_impeller.h"
namespace flutter {
static std::shared_ptr<impeller::Context> CreateImpellerContext() {
auto proc_table = std::make_unique<impeller::ProcTableGLES>(
impeller::egl::CreateProcAddressResolver());
if (!proc_table->IsValid()) {
FML_LOG(ERROR) << "Could not create OpenGL proc table.";
return nullptr;
}
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles_data,
impeller_entity_shaders_gles_length),
};
auto context =
impeller::ContextGLES::Create(std::move(proc_table), shader_mappings);
if (!context) {
FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context.";
return nullptr;
}
return context;
}
AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller(
const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: AndroidSurface(android_context) {
auto display = std::make_unique<impeller::egl::Display>();
if (!display->IsValid()) {
FML_DLOG(ERROR) << "Could not create EGL display.";
return;
}
impeller::egl::ConfigDescriptor desc;
desc.api = impeller::egl::API::kOpenGLES2;
desc.color_format = impeller::egl::ColorFormat::kRGBA8888;
desc.depth_bits = impeller::egl::DepthBits::kZero;
desc.stencil_bits = impeller::egl::StencilBits::kEight;
desc.samples = impeller::egl::Samples::kFour;
desc.surface_type = impeller::egl::SurfaceType::kWindow;
auto onscreen_config = display->ChooseConfig(desc);
if (!onscreen_config) {
FML_DLOG(ERROR) << "Could not choose onscreen config.";
return;
}
desc.surface_type = impeller::egl::SurfaceType::kPBuffer;
auto offscreen_config = display->ChooseConfig(desc);
if (!offscreen_config) {
FML_DLOG(ERROR) << "Could not choose offscreen config.";
return;
}
auto onscreen_context = display->CreateContext(*onscreen_config, nullptr);
if (!onscreen_context) {
FML_DLOG(ERROR) << "Could not create onscreen context.";
return;
}
auto offscreen_context =
display->CreateContext(*offscreen_config, onscreen_context.get());
if (!offscreen_context) {
FML_DLOG(ERROR) << "Could not create offscreen context.";
return;
}
auto offscreen_surface =
display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u);
if (!offscreen_surface) {
FML_DLOG(ERROR) << "Could not create offscreen surface.";
return;
}
if (!offscreen_context->MakeCurrent(*offscreen_surface)) {
FML_DLOG(ERROR) << "Could not make offscreen context current.";
return;
}
auto impeller_context = CreateImpellerContext();
if (!impeller_context) {
FML_DLOG(ERROR) << "Could not create Impeller context.";
return;
}
if (!offscreen_context->ClearCurrent()) {
FML_DLOG(ERROR) << "Could not clear offscreen context.";
return;
}
display_ = std::move(display);
onscreen_config_ = std::move(onscreen_config);
offscreen_config_ = std::move(offscreen_config);
offscreen_surface_ = std::move(offscreen_surface);
onscreen_context_ = std::move(onscreen_context);
offscreen_context_ = std::move(offscreen_context);
impeller_context_ = std::move(impeller_context);
// The onscreen surface will be acquired once the native window is set.
is_valid_ = true;
}
AndroidSurfaceGLImpeller::~AndroidSurfaceGLImpeller() = default;
// |AndroidSurface|
bool AndroidSurfaceGLImpeller::IsValid() const {
return is_valid_;
}
// |AndroidSurface|
std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateGPUSurface(
GrDirectContext* gr_context) {
auto surface =
std::make_unique<GPUSurfaceGLImpeller>(this, // delegate
impeller_context_ // context
);
if (!surface->IsValid()) {
return nullptr;
}
return surface;
}
// |AndroidSurface|
void AndroidSurfaceGLImpeller::TeardownOnScreenContext() {
GLContextClearCurrent();
onscreen_surface_.reset();
}
// |AndroidSurface|
bool AndroidSurfaceGLImpeller::OnScreenSurfaceResize(const SkISize& size) {
// The size is unused. It was added only for iOS where the sizes were
// necessary to re-create auxiliary buffers (stencil, depth, etc.).
return RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent();
}
// |AndroidSurface|
bool AndroidSurfaceGLImpeller::ResourceContextMakeCurrent() {
if (!offscreen_context_ || !offscreen_surface_) {
return false;
}
return offscreen_context_->MakeCurrent(*offscreen_surface_);
}
// |AndroidSurface|
bool AndroidSurfaceGLImpeller::ResourceContextClearCurrent() {
if (!offscreen_context_ || !offscreen_surface_) {
return false;
}
return offscreen_context_->ClearCurrent();
}
// |AndroidSurface|
bool AndroidSurfaceGLImpeller::SetNativeWindow(
fml::RefPtr<AndroidNativeWindow> window) {
native_window_ = std::move(window);
return RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent();
}
// |AndroidSurface|
std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateSnapshotSurface() {
FML_UNREACHABLE();
}
// |GPUSurfaceGLDelegate|
std::unique_ptr<GLContextResult>
AndroidSurfaceGLImpeller::GLContextMakeCurrent() {
return std::make_unique<GLContextDefaultResult>(OnGLContextMakeCurrent());
}
bool AndroidSurfaceGLImpeller::OnGLContextMakeCurrent() {
if (!onscreen_surface_ || !onscreen_context_) {
return false;
}
return onscreen_context_->MakeCurrent(*onscreen_surface_);
}
// |GPUSurfaceGLDelegate|
bool AndroidSurfaceGLImpeller::GLContextClearCurrent() {
if (!onscreen_surface_ || !onscreen_context_) {
return false;
}
return onscreen_context_->ClearCurrent();
}
// |GPUSurfaceGLDelegate|
SurfaceFrame::FramebufferInfo
AndroidSurfaceGLImpeller::GLContextFramebufferInfo() const {
auto info = SurfaceFrame::FramebufferInfo{};
info.supports_readback = true;
info.supports_partial_repaint = false;
return info;
}
// |GPUSurfaceGLDelegate|
void AndroidSurfaceGLImpeller::GLContextSetDamageRegion(
const std::optional<SkIRect>& region) {
// Not supported.
}
// |GPUSurfaceGLDelegate|
bool AndroidSurfaceGLImpeller::GLContextPresent(
uint32_t fbo_id,
const std::optional<SkIRect>& damage) {
// The FBO ID is superfluous and was introduced for iOS where the default
// framebuffer was not FBO0.
if (!onscreen_surface_) {
return false;
}
return onscreen_surface_->Present();
}
// |GPUSurfaceGLDelegate|
intptr_t AndroidSurfaceGLImpeller::GLContextFBO(GLFrameInfo frame_info) const {
// FBO0 is the default window bound framebuffer in EGL environments.
return 0;
}
// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> AndroidSurfaceGLImpeller::GetGLInterface() const {
return nullptr;
}
bool AndroidSurfaceGLImpeller::
RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent() {
GLContextClearCurrent();
if (!native_window_) {
return false;
}
onscreen_surface_.reset();
auto onscreen_surface = display_->CreateWindowSurface(
*onscreen_config_, native_window_->handle());
if (!onscreen_surface) {
FML_DLOG(ERROR) << "Could not create onscreen surface.";
return false;
}
onscreen_surface_ = std::move(onscreen_surface);
return OnGLContextMakeCurrent();
}
} // namespace flutter

View File

@ -0,0 +1,96 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_IMPELLER_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_IMPELLER_H_
#include "flutter/fml/macros.h"
#include "flutter/impeller/renderer/context.h"
#include "flutter/impeller/toolkit/egl/display.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
#include "flutter/shell/platform/android/surface/android_native_window.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
namespace flutter {
class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate,
public AndroidSurface {
public:
AndroidSurfaceGLImpeller(
const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
// |AndroidSurface|
~AndroidSurfaceGLImpeller() override;
// |AndroidSurface|
bool IsValid() const override;
// |AndroidSurface|
std::unique_ptr<Surface> CreateGPUSurface(
GrDirectContext* gr_context) override;
// |AndroidSurface|
void TeardownOnScreenContext() override;
// |AndroidSurface|
bool OnScreenSurfaceResize(const SkISize& size) override;
// |AndroidSurface|
bool ResourceContextMakeCurrent() override;
// |AndroidSurface|
bool ResourceContextClearCurrent() override;
// |AndroidSurface|
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;
// |AndroidSurface|
std::unique_ptr<Surface> CreateSnapshotSurface() override;
// |GPUSurfaceGLDelegate|
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
// |GPUSurfaceGLDelegate|
SurfaceFrame::FramebufferInfo GLContextFramebufferInfo() const override;
// |GPUSurfaceGLDelegate|
void GLContextSetDamageRegion(const std::optional<SkIRect>& region) override;
// |GPUSurfaceGLDelegate|
bool GLContextPresent(uint32_t fbo_id,
const std::optional<SkIRect>& damage) override;
// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> GetGLInterface() const override;
private:
std::unique_ptr<impeller::egl::Display> display_;
std::unique_ptr<impeller::egl::Config> onscreen_config_;
std::unique_ptr<impeller::egl::Config> offscreen_config_;
std::unique_ptr<impeller::egl::Surface> onscreen_surface_;
std::unique_ptr<impeller::egl::Surface> offscreen_surface_;
std::unique_ptr<impeller::egl::Context> onscreen_context_;
std::unique_ptr<impeller::egl::Context> offscreen_context_;
std::shared_ptr<impeller::Context> impeller_context_;
fml::RefPtr<AndroidNativeWindow> native_window_;
bool is_valid_ = false;
bool OnGLContextMakeCurrent();
bool RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent();
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGLImpeller);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_IMPELLER_H_

View File

@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/android/android_surface_gl.h"
#include "flutter/shell/platform/android/android_surface_gl_skia.h"
#include <GLES/gl.h>
#include <utility>
#include "flutter/fml/logging.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/shell/platform/android/android_egl_surface.h"
#include "flutter/shell/platform/android/android_shell_holder.h"
namespace flutter {
@ -19,7 +20,7 @@ constexpr char kEmulatorRendererPrefix[] =
"Android Emulator OpenGL ES Translator";
} // anonymous namespace
AndroidSurfaceGL::AndroidSurfaceGL(
AndroidSurfaceGLSkia::AndroidSurfaceGLSkia(
const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: AndroidSurface(android_context),
@ -33,9 +34,9 @@ AndroidSurfaceGL::AndroidSurfaceGL(
}
}
AndroidSurfaceGL::~AndroidSurfaceGL() = default;
AndroidSurfaceGLSkia::~AndroidSurfaceGLSkia() = default;
void AndroidSurfaceGL::TeardownOnScreenContext() {
void AndroidSurfaceGLSkia::TeardownOnScreenContext() {
// When the onscreen surface is destroyed, the context and the surface
// instance should be deleted. Issue:
// https://github.com/flutter/flutter/issues/64414
@ -43,26 +44,27 @@ void AndroidSurfaceGL::TeardownOnScreenContext() {
onscreen_surface_ = nullptr;
}
bool AndroidSurfaceGL::IsValid() const {
bool AndroidSurfaceGLSkia::IsValid() const {
return offscreen_surface_ && GLContextPtr()->IsValid();
}
std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface(
std::unique_ptr<Surface> AndroidSurfaceGLSkia::CreateGPUSurface(
GrDirectContext* gr_context) {
if (gr_context) {
return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
return std::make_unique<GPUSurfaceGLSkia>(sk_ref_sp(gr_context), this,
true);
} else {
sk_sp<GrDirectContext> main_skia_context =
GLContextPtr()->GetMainSkiaContext();
if (!main_skia_context) {
main_skia_context = GPUSurfaceGL::MakeGLContext(this);
main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this);
GLContextPtr()->SetMainSkiaContext(main_skia_context);
}
return std::make_unique<GPUSurfaceGL>(main_skia_context, this, true);
return std::make_unique<GPUSurfaceGLSkia>(main_skia_context, this, true);
}
}
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
bool AndroidSurfaceGLSkia::OnScreenSurfaceResize(const SkISize& size) {
FML_DCHECK(IsValid());
FML_DCHECK(onscreen_surface_);
FML_DCHECK(native_window_);
@ -85,20 +87,20 @@ bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
return true;
}
bool AndroidSurfaceGL::ResourceContextMakeCurrent() {
bool AndroidSurfaceGLSkia::ResourceContextMakeCurrent() {
FML_DCHECK(IsValid());
auto status = offscreen_surface_->MakeCurrent();
return status != AndroidEGLSurfaceMakeCurrentStatus::kFailure;
}
bool AndroidSurfaceGL::ResourceContextClearCurrent() {
bool AndroidSurfaceGLSkia::ResourceContextClearCurrent() {
FML_DCHECK(IsValid());
EGLBoolean result = eglMakeCurrent(eglGetCurrentDisplay(), EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
return result == EGL_TRUE;
}
bool AndroidSurfaceGL::SetNativeWindow(
bool AndroidSurfaceGLSkia::SetNativeWindow(
fml::RefPtr<AndroidNativeWindow> window) {
FML_DCHECK(IsValid());
FML_DCHECK(window);
@ -114,7 +116,7 @@ bool AndroidSurfaceGL::SetNativeWindow(
return true;
}
std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
std::unique_ptr<GLContextResult> AndroidSurfaceGLSkia::GLContextMakeCurrent() {
FML_DCHECK(IsValid());
FML_DCHECK(onscreen_surface_);
auto status = onscreen_surface_->MakeCurrent();
@ -123,12 +125,12 @@ std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
return std::move(default_context_result);
}
bool AndroidSurfaceGL::GLContextClearCurrent() {
bool AndroidSurfaceGLSkia::GLContextClearCurrent() {
FML_DCHECK(IsValid());
return GLContextPtr()->ClearCurrent();
}
SurfaceFrame::FramebufferInfo AndroidSurfaceGL::GLContextFramebufferInfo()
SurfaceFrame::FramebufferInfo AndroidSurfaceGLSkia::GLContextFramebufferInfo()
const {
FML_DCHECK(IsValid());
SurfaceFrame::FramebufferInfo res;
@ -145,27 +147,28 @@ SurfaceFrame::FramebufferInfo AndroidSurfaceGL::GLContextFramebufferInfo()
return res;
}
void AndroidSurfaceGL::GLContextSetDamageRegion(
void AndroidSurfaceGLSkia::GLContextSetDamageRegion(
const std::optional<SkIRect>& region) {
FML_DCHECK(IsValid());
onscreen_surface_->SetDamageRegion(region);
}
bool AndroidSurfaceGL::GLContextPresent(uint32_t fbo_id,
const std::optional<SkIRect>& damage) {
bool AndroidSurfaceGLSkia::GLContextPresent(
uint32_t fbo_id,
const std::optional<SkIRect>& damage) {
FML_DCHECK(IsValid());
FML_DCHECK(onscreen_surface_);
return onscreen_surface_->SwapBuffers(damage);
}
intptr_t AndroidSurfaceGL::GLContextFBO(GLFrameInfo frame_info) const {
intptr_t AndroidSurfaceGLSkia::GLContextFBO(GLFrameInfo frame_info) const {
FML_DCHECK(IsValid());
// The default window bound framebuffer on Android.
return 0;
}
// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
sk_sp<const GrGLInterface> AndroidSurfaceGLSkia::GetGLInterface() const {
// This is a workaround for a bug in the Android emulator EGL/GLES
// implementation. Some versions of the emulator will not update the
// GL version string when the process switches to a new EGL context
@ -197,22 +200,22 @@ sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
return GPUSurfaceGLDelegate::GetGLInterface();
}
AndroidContextGL* AndroidSurfaceGL::GLContextPtr() const {
return reinterpret_cast<AndroidContextGL*>(android_context_.get());
AndroidContextGLSkia* AndroidSurfaceGLSkia::GLContextPtr() const {
return reinterpret_cast<AndroidContextGLSkia*>(android_context_.get());
}
std::unique_ptr<Surface> AndroidSurfaceGL::CreateSnapshotSurface() {
std::unique_ptr<Surface> AndroidSurfaceGLSkia::CreateSnapshotSurface() {
if (!onscreen_surface_ || !onscreen_surface_->IsValid()) {
onscreen_surface_ = GLContextPtr()->CreatePbufferSurface();
}
sk_sp<GrDirectContext> main_skia_context =
GLContextPtr()->GetMainSkiaContext();
if (!main_skia_context) {
main_skia_context = GPUSurfaceGL::MakeGLContext(this);
main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this);
GLContextPtr()->SetMainSkiaContext(main_skia_context);
}
return std::make_unique<GPUSurfaceGL>(main_skia_context, this, true);
return std::make_unique<GPUSurfaceGLSkia>(main_skia_context, this, true);
}
} // namespace flutter

View File

@ -2,29 +2,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_SKIA_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_SKIA_H_
#include <jni.h>
#include <memory>
#include "flutter/fml/macros.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/android/android_context_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#include "flutter/shell/platform/android/android_context_gl_skia.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
namespace flutter {
class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
public AndroidSurface {
class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate,
public AndroidSurface {
public:
AndroidSurfaceGL(const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
AndroidSurfaceGLSkia(const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
~AndroidSurfaceGL() override;
~AndroidSurfaceGLSkia() override;
// |AndroidSurface|
bool IsValid() const override;
@ -90,11 +90,11 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
/// @brief Takes the super class AndroidSurface's AndroidContext and
/// return a raw pointer to an AndroidContextGL.
///
AndroidContextGL* GLContextPtr() const;
AndroidContextGLSkia* GLContextPtr() const;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL);
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGLSkia);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_SKIA_H_

View File

@ -42,6 +42,8 @@ public class FlutterShellArgs {
public static final String ARG_TRACE_SKIA_ALLOWLIST = "--trace-skia-allowlist=";
public static final String ARG_KEY_TRACE_SYSTRACE = "trace-systrace";
public static final String ARG_TRACE_SYSTRACE = "--trace-systrace";
public static final String ARG_KEY_ENABLE_IMPELLER = "enable-impeller";
public static final String ARG_ENABLE_IMPELLER = "--enable-impeller";
public static final String ARG_KEY_DUMP_SHADER_SKP_ON_SHADER_COMPILATION =
"dump-skp-on-shader-compilation";
public static final String ARG_DUMP_SHADER_SKP_ON_SHADER_COMPILATION =
@ -106,6 +108,9 @@ public class FlutterShellArgs {
if (intent.getBooleanExtra(ARG_KEY_TRACE_SYSTRACE, false)) {
args.add(ARG_TRACE_SYSTRACE);
}
if (intent.getBooleanExtra(ARG_KEY_ENABLE_IMPELLER, false)) {
args.add(ARG_ENABLE_IMPELLER);
}
if (intent.getBooleanExtra(ARG_KEY_DUMP_SHADER_SKP_ON_SHADER_COMPILATION, false)) {
args.add(ARG_DUMP_SHADER_SKP_ON_SHADER_COMPILATION);
}

View File

@ -10,9 +10,11 @@
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/shell/common/shell_io_manager.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
#include "flutter/shell/platform/android/android_context_gl.h"
#include "flutter/shell/platform/android/android_context_gl_impeller.h"
#include "flutter/shell/platform/android/android_context_gl_skia.h"
#include "flutter/shell/platform/android/android_external_texture_gl.h"
#include "flutter/shell/platform/android/android_surface_gl.h"
#include "flutter/shell/platform/android/android_surface_gl_impeller.h"
#include "flutter/shell/platform/android/android_surface_gl_skia.h"
#include "flutter/shell/platform/android/android_surface_software.h"
#include "flutter/shell/platform/android/context/android_context.h"
#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
@ -26,8 +28,11 @@ namespace flutter {
AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl(
const std::shared_ptr<AndroidContext>& context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: android_context_(context), jni_facade_(jni_facade) {}
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
bool enable_impeller)
: android_context_(context),
jni_facade_(jni_facade),
enable_impeller_(enable_impeller) {}
AndroidSurfaceFactoryImpl::~AndroidSurfaceFactoryImpl() = default;
@ -37,7 +42,13 @@ std::unique_ptr<AndroidSurface> AndroidSurfaceFactoryImpl::CreateSurface() {
return std::make_unique<AndroidSurfaceSoftware>(android_context_,
jni_facade_);
case AndroidRenderingAPI::kOpenGLES:
return std::make_unique<AndroidSurfaceGL>(android_context_, jni_facade_);
if (enable_impeller_) {
return std::make_unique<AndroidSurfaceGLImpeller>(android_context_,
jni_facade_);
} else {
return std::make_unique<AndroidSurfaceGLSkia>(android_context_,
jni_facade_);
}
default:
FML_DCHECK(false);
return nullptr;
@ -47,13 +58,20 @@ std::unique_ptr<AndroidSurface> AndroidSurfaceFactoryImpl::CreateSurface() {
static std::shared_ptr<flutter::AndroidContext> CreateAndroidContext(
bool use_software_rendering,
const flutter::TaskRunners task_runners,
uint8_t msaa_samples) {
uint8_t msaa_samples,
bool enable_impeller) {
if (use_software_rendering) {
return std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
}
return std::make_unique<AndroidContextGL>(
AndroidRenderingAPI::kOpenGLES,
fml::MakeRefCounted<AndroidEnvironmentGL>(), task_runners, msaa_samples);
if (enable_impeller) {
return std::make_unique<AndroidContextGLImpeller>();
}
return std::make_unique<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, //
fml::MakeRefCounted<AndroidEnvironmentGL>(), //
task_runners, //
msaa_samples //
);
}
PlatformViewAndroid::PlatformViewAndroid(
@ -62,12 +80,15 @@ PlatformViewAndroid::PlatformViewAndroid(
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
bool use_software_rendering,
uint8_t msaa_samples)
: PlatformViewAndroid(delegate,
std::move(task_runners),
std::move(jni_facade),
CreateAndroidContext(use_software_rendering,
task_runners,
msaa_samples)) {}
: PlatformViewAndroid(
delegate,
std::move(task_runners),
std::move(jni_facade),
CreateAndroidContext(
use_software_rendering,
task_runners,
msaa_samples,
delegate.OnPlatformViewGetSettings().enable_impeller)) {}
PlatformViewAndroid::PlatformViewAndroid(
PlatformView::Delegate& delegate,
@ -83,7 +104,8 @@ PlatformViewAndroid::PlatformViewAndroid(
FML_CHECK(android_context_->IsValid())
<< "Could not create surface from invalid Android context.";
surface_factory_ = std::make_shared<AndroidSurfaceFactoryImpl>(
android_context_, jni_facade_);
android_context_, jni_facade_,
delegate.OnPlatformViewGetSettings().enable_impeller);
android_surface_ = surface_factory_->CreateSurface();
FML_CHECK(android_surface_ && android_surface_->IsValid())

View File

@ -27,7 +27,8 @@ namespace flutter {
class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory {
public:
AndroidSurfaceFactoryImpl(const std::shared_ptr<AndroidContext>& context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
bool enable_impeller);
~AndroidSurfaceFactoryImpl() override;
@ -36,6 +37,7 @@ class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory {
private:
const std::shared_ptr<AndroidContext>& android_context_;
std::shared_ptr<PlatformViewAndroidJNI> jni_facade_;
const bool enable_impeller_;
};
class PlatformViewAndroid final : public PlatformView {

View File

@ -5,7 +5,7 @@
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_MOCK_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_MOCK_H_
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
#include "gmock/gmock.h"

View File

@ -7,8 +7,8 @@
#import <OpenGLES/EAGL.h>
#include "flutter/shell/common/shell_io_manager.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#import "flutter/shell/platform/darwin/ios/ios_external_texture_gl.h"
namespace flutter {

View File

@ -7,7 +7,7 @@
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#import "flutter/shell/platform/darwin/ios/ios_context.h"
#import "flutter/shell/platform/darwin/ios/ios_render_target_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"

View File

@ -5,7 +5,7 @@
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#import "flutter/shell/platform/darwin/ios/ios_context_gl.h"
namespace flutter {
@ -37,16 +37,16 @@ void IOSSurfaceGL::UpdateStorageSizeIfNecessary() {
// |IOSSurface|
std::unique_ptr<Surface> IOSSurfaceGL::CreateGPUSurface(GrDirectContext* gr_context) {
if (gr_context) {
return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
return std::make_unique<GPUSurfaceGLSkia>(sk_ref_sp(gr_context), this, true);
} else {
IOSContextGL* gl_context = CastToGLContext(GetContext());
sk_sp<GrDirectContext> context = gl_context->GetMainContext();
if (!context) {
context = GPUSurfaceGL::MakeGLContext(this);
context = GPUSurfaceGLSkia::MakeGLContext(this);
gl_context->SetMainContext(context);
}
return std::make_unique<GPUSurfaceGL>(context, this, true);
return std::make_unique<GPUSurfaceGLSkia>(context, this, true);
}
}

View File

@ -79,8 +79,9 @@ EmbedderSurfaceGL::GLProcResolver EmbedderSurfaceGL::GetGLProcResolver() const {
// |EmbedderSurface|
std::unique_ptr<Surface> EmbedderSurfaceGL::CreateGPUSurface() {
const bool render_to_surface = !external_view_embedder_;
return std::make_unique<GPUSurfaceGL>(this, // GPU surface GL delegate
render_to_surface // render to surface
return std::make_unique<GPUSurfaceGLSkia>(
this, // GPU surface GL delegate
render_to_surface // render to surface
);
}

View File

@ -6,7 +6,7 @@
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_GL_H_
#include "flutter/fml/macros.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#include "flutter/shell/platform/embedder/embedder_external_view_embedder.h"
#include "flutter/shell/platform/embedder/embedder_surface.h"