mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[impeller] Wire up the OpenGL ES Backend. (flutter/engine#33405)
This commit is contained in:
parent
faf29ed458
commit
7df5e81ea8
@ -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
|
||||
|
||||
@ -22,6 +22,8 @@ impeller_component("base") {
|
||||
"thread_safety.h",
|
||||
"validation.cc",
|
||||
"validation.h",
|
||||
"version.cc",
|
||||
"version.h",
|
||||
]
|
||||
|
||||
deps = [ "//flutter/fml" ]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
33
engine/src/flutter/impeller/base/version.cc
Normal file
33
engine/src/flutter/impeller/base/version.cc
Normal 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
|
||||
34
engine/src/flutter/impeller/base/version.h
Normal file
34
engine/src/flutter/impeller/base/version.h
Normal 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
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
@ -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_;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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_;
|
||||
|
||||
27
engine/src/flutter/impeller/toolkit/egl/BUILD.gn
Normal file
27
engine/src/flutter/impeller/toolkit/egl/BUILD.gn
Normal 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" ]
|
||||
}
|
||||
}
|
||||
30
engine/src/flutter/impeller/toolkit/egl/config.cc
Normal file
30
engine/src/flutter/impeller/toolkit/egl/config.cc
Normal 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
|
||||
74
engine/src/flutter/impeller/toolkit/egl/config.h
Normal file
74
engine/src/flutter/impeller/toolkit/egl/config.h
Normal 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
|
||||
73
engine/src/flutter/impeller/toolkit/egl/context.cc
Normal file
73
engine/src/flutter/impeller/toolkit/egl/context.cc
Normal 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
|
||||
37
engine/src/flutter/impeller/toolkit/egl/context.h
Normal file
37
engine/src/flutter/impeller/toolkit/egl/context.h
Normal 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
|
||||
210
engine/src/flutter/impeller/toolkit/egl/display.cc
Normal file
210
engine/src/flutter/impeller/toolkit/egl/display.cc
Normal 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
|
||||
47
engine/src/flutter/impeller/toolkit/egl/display.h
Normal file
47
engine/src/flutter/impeller/toolkit/egl/display.h
Normal 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
|
||||
61
engine/src/flutter/impeller/toolkit/egl/egl.cc
Normal file
61
engine/src/flutter/impeller/toolkit/egl/egl.cc
Normal 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
|
||||
21
engine/src/flutter/impeller/toolkit/egl/egl.h
Normal file
21
engine/src/flutter/impeller/toolkit/egl/egl.h
Normal 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
|
||||
38
engine/src/flutter/impeller/toolkit/egl/surface.cc
Normal file
38
engine/src/flutter/impeller/toolkit/egl/surface.cc
Normal 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
|
||||
33
engine/src/flutter/impeller/toolkit/egl/surface.h
Normal file
33
engine/src/flutter/impeller/toolkit/egl/surface.h
Normal 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
|
||||
@ -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.
|
||||
|
||||
@ -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|
|
||||
|
||||
@ -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") {
|
||||
|
||||
153
engine/src/flutter/shell/gpu/gpu_surface_gl_impeller.cc
Normal file
153
engine/src/flutter/shell/gpu/gpu_surface_gl_impeller.cc
Normal 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
|
||||
63
engine/src/flutter/shell/gpu/gpu_surface_gl_impeller.h
Normal file
63
engine/src/flutter/shell/gpu/gpu_surface_gl_impeller.h
Normal 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_
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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_
|
||||
@ -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",
|
||||
|
||||
@ -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_
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
105
engine/src/flutter/shell/platform/android/android_egl_surface.h
Normal file
105
engine/src/flutter/shell/platform/android/android_egl_surface.h
Normal 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_
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user