Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d9a7bcc
Update the return value of GLContextFBO.
betrevisan Jul 12, 2022
926d647
Keep track of the existing damage when requesting new frames and pass…
betrevisan Jul 12, 2022
d7259fd
Add private variables to support partial repaint.
betrevisan Jul 12, 2022
4458feb
Update the embedder's GLContextFBO and GLContextPresent function and …
betrevisan Jul 12, 2022
816f0e1
Update function prototypes and add damage region.
betrevisan Jul 12, 2022
1704474
Update the way the embedder handles the fbo and the present callbacks.
betrevisan Jul 12, 2022
204dd3b
Add new structs to the embedder to support partial repaint.
betrevisan Jul 12, 2022
0135f1d
Formatting.
betrevisan Jul 12, 2022
adb609b
Adjust the way existing damage is communicated to the rendering backe…
betrevisan Jul 13, 2022
29514db
Formatting
betrevisan Jul 13, 2022
31a3278
Update comments.
betrevisan Jul 13, 2022
cc4c50d
Add initial unit tests.
betrevisan Jul 15, 2022
175f053
Address design doc and code review feedback
betrevisan Jul 15, 2022
9db2299
fix return type of other function uses.
betrevisan Jul 15, 2022
c193aec
fix compatibility issues.
betrevisan Jul 18, 2022
ea3bd1d
fix function return value.
betrevisan Jul 18, 2022
ede0f2b
casting issue
betrevisan Jul 18, 2022
b07cf31
fixes
betrevisan Jul 18, 2022
1766c2e
fixes
betrevisan Jul 18, 2022
cd34a55
static cast fix
betrevisan Jul 18, 2022
1a0e24f
formatting
betrevisan Jul 18, 2022
ace9dad
formatting
betrevisan Jul 18, 2022
8f696ff
import fix
betrevisan Jul 18, 2022
467df12
formatting
betrevisan Jul 18, 2022
770fafa
update present callback
betrevisan Jul 21, 2022
9a99192
fix affected functions
betrevisan Jul 21, 2022
7ec053b
glfw example
betrevisan Jul 21, 2022
856590f
glfw example
betrevisan Jul 21, 2022
0fabb45
fix flutterrect to skirect translation
betrevisan Jul 21, 2022
75d3fbc
remove unnecessary lib from the build file
betrevisan Jul 21, 2022
59172ec
adjust cmakelists.txt
betrevisan Jul 21, 2022
c5cafff
fix recttoints
betrevisan Jul 21, 2022
7f09584
fbo reset after present set to true
betrevisan Jul 22, 2022
0ebbfac
Updates
betrevisan Jul 25, 2022
96b2d37
Updates
betrevisan Jul 25, 2022
9d00450
fix buffer present bug
betrevisan Jul 25, 2022
0a072c2
updates
betrevisan Jul 26, 2022
04c32ed
Udpate dart example.
betrevisan Jul 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/glfw/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ if (build_embedder_examples) {
"//flutter/shell/platform/embedder:embedder",
"//third_party/glfw",
]

libs = [
"EGL",
]
}
}
4 changes: 3 additions & 1 deletion examples/glfw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ option(GLFW_BUILD_EXAMPLES "" OFF)
option(GLFW_BUILD_TESTS "" OFF)
option(GLFW_BUILD_DOCS "" OFF)
option(GLFW_INSTALL "" OFF)
find_package(OpenGL REQUIRED COMPONENTS EGL)
include_directories(${OPENGL_INCLUDE_DIRS})
add_subdirectory(${CMAKE_SOURCE_DIR}/../../../third_party/glfw glfw)
target_link_libraries(flutter_glfw glfw)
target_link_libraries(flutter_glfw glfw OpenGL::EGL)
include_directories(${CMAKE_SOURCE_DIR}/../../../third_party/glfw/include)

############################################################
Expand Down
102 changes: 98 additions & 4 deletions examples/glfw/FlutterEmbedderGLFW.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,26 @@
#include <chrono>
#include <iostream>

#define GLFW_EXPOSE_NATIVE_EGL
#define GLFW_INCLUDE_GLEXT

#include <array>
#include <list>
#include "GLFW/glfw3.h"
#include "GLFW/glfw3native.h"
#include "embedder.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>

// This value is calculated after the window is created.
static double g_pixelRatio = 1.0;
static const size_t kInitialWindowWidth = 800;
static const size_t kInitialWindowHeight = 600;
// Maximum damage history - for triple buffering we need to store damage for
// last two frames; Some Android devices (Pixel 4) use quad buffering.
static const int kMaxHistorySize = 10;

std::list<FlutterRect> damage_history_;

static_assert(FLUTTER_ENGINE_VERSION == 1,
"This Flutter Embedder was authored against the stable Flutter "
Expand Down Expand Up @@ -82,6 +95,24 @@ void GLFWwindowSizeCallback(GLFWwindow* window, int width, int height) {
&event);
}

std::array<EGLint, 4> static RectToInts(EGLDisplay display,
EGLSurface surface,
const FlutterRect rect) {
EGLint height;
eglQuerySurface(display, surface, EGL_HEIGHT, &height);

std::array<EGLint, 4> res{static_cast<int>(rect.left), height - static_cast<int>(rect.bottom), static_cast<int>(rect.right) - static_cast<int>(rect.left),
static_cast<int>(rect.bottom) - static_cast<int>(rect.top)};
return res;
}

void JoinFlutterRect(FlutterRect* rect, FlutterRect additional_rect) {
rect->left = std::min(rect->left, additional_rect.left);
rect->top = std::min(rect->top, additional_rect.top);
rect->right = std::max(rect->right, additional_rect.right);
rect->bottom = std::max(rect->bottom, additional_rect.bottom);
}

bool RunFlutter(GLFWwindow* window,
const std::string& project_path,
const std::string& icudtl_path) {
Expand All @@ -96,17 +127,80 @@ bool RunFlutter(GLFWwindow* window,
glfwMakeContextCurrent(nullptr); // is this even a thing?
return true;
};
config.open_gl.present = [](void* userdata) -> bool {
glfwSwapBuffers(static_cast<GLFWwindow*>(userdata));
config.open_gl.present_with_info = [](void* userdata, const FlutterPresentInfo* info) -> bool {
PFNEGLSETDAMAGEREGIONKHRPROC set_damage_region_ =
reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(
eglGetProcAddress("eglSetDamageRegionKHR"));
PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage_ =
reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(
eglGetProcAddress("eglSwapBuffersWithDamageKHR"));

GLFWwindow* window = static_cast<GLFWwindow*>(userdata);
EGLDisplay display = glfwGetEGLDisplay();
EGLSurface surface = glfwGetEGLSurface(window);

auto buffer_rects = RectToInts(display, surface, {0, 0, kInitialWindowWidth, kInitialWindowHeight});
set_damage_region_(display, surface, buffer_rects.data(), 1);

// Swap buffers with frame damage
auto frame_rects = RectToInts(display, surface, info->frame_damage.damage);
swap_buffers_with_damage_(display, surface, frame_rects.data(), 1);

// Add frame damage to damage history
damage_history_.push_back(info->frame_damage.damage);
if (damage_history_.size() > kMaxHistorySize) {
damage_history_.pop_front();
}
std::cout << "Buffer Damage: " << info->buffer_damage.damage.left << ", " << info->buffer_damage.damage.top << ", " << info->buffer_damage.damage.right << ", " << info->buffer_damage.damage.bottom << std::endl;
std::cout << "Frame Damage: " << info->frame_damage.damage.left << ", " << info->frame_damage.damage.top << ", " << info->frame_damage.damage.right << ", " << info->frame_damage.damage.bottom << std::endl;
return true;
};
config.open_gl.fbo_callback = [](void*) -> uint32_t {
return 0; // FBO0
config.open_gl.fbo_with_frame_info_callback = [](void* userdata, const FlutterFrameInfo* info) -> FlutterFrameBuffer {
// Given the FBO age, create existing damage region by joining all frame
// damages since FBO was last used
GLFWwindow* window = static_cast<GLFWwindow*>(userdata);
EGLDisplay display = glfwGetEGLDisplay();
EGLSurface surface = glfwGetEGLSurface(window);

EGLint age;
if (glfwExtensionSupported("GL_EXT_buffer_age") == GLFW_TRUE) {
eglQuerySurface(display, surface, EGL_BUFFER_AGE_EXT, &age);
} else {
age = 4; // Virtually no driver should have a swapchain length > 4.
}
std::cout << "Buffer age: " << age << std::endl;

FlutterDamage existing_damage;
existing_damage.damage = {0, 0, kInitialWindowWidth, kInitialWindowHeight};

if (age > 1) {
--age;
// join up to (age - 1) last rects from damage history
for (auto i = damage_history_.rbegin();
i != damage_history_.rend() && age > 0; ++i, --age) {
std::cout << "Damage in history: " << i->left << ", " << i->top << ", " << i->right << ", " << i->bottom << std::endl;
if (i == damage_history_.rbegin()) {
if (i != damage_history_.rend()) {
existing_damage.damage = {i->left, i->top, i->right, i->bottom};
}
} else {
JoinFlutterRect(&(existing_damage.damage), *i);
}
}
}

FlutterFrameBuffer fbo;
fbo.fbo_id = 0; // FBO0
fbo.damage = existing_damage;
std::cout << "Existing Damage: " << fbo.damage.damage.left << ", " << fbo.damage.damage.top << ", " << fbo.damage.damage.right << ", " << fbo.damage.damage.bottom << std::endl;
return fbo;
};
config.open_gl.gl_proc_resolver = [](void*, const char* name) -> void* {
return reinterpret_cast<void*>(glfwGetProcAddress(name));
};

config.open_gl.fbo_reset_after_present = true;

// This directory is generated by `flutter build bundle`.
std::string assets_path = project_path + "/build/flutter_assets";
FlutterProjectArgs args = {
Expand Down
54 changes: 3 additions & 51 deletions examples/glfw/main.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// 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 'package:flutter/material.dart';
import 'package:flutter/foundation.dart'
show debugDefaultTargetPlatformOverride;
import 'package:flutter_spinkit/flutter_spinkit.dart';

void main() {
// This is a hack to make Flutter think you are running on Google Fuchsia,
// otherwise you will get an error about running from an unsupported platform.
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
runApp(MyApp());
}

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Expand All @@ -35,39 +34,20 @@ class MyApp extends StatelessWidget {
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);

// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.

// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;

void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}

@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
Expand All @@ -85,38 +65,10 @@ class _MyHomePageState extends State<MyHomePage> {
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
child: RepaintBoundary(
child: SpinKitRotatingCircle(color: Colors.blue, size: 50.0),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
1 change: 1 addition & 0 deletions flow/layers/container_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace flutter {
ContainerLayer::ContainerLayer() : child_paint_bounds_(SkRect::MakeEmpty()) {}

void ContainerLayer::Diff(DiffContext* context, const Layer* old_layer) {
std::cout << "Container layer" << std:endl;
auto old_container = static_cast<const ContainerLayer*>(old_layer);
DiffContext::AutoSubtreeRestore subtree(context);
DiffChildren(context, old_container);
Expand Down
1 change: 1 addition & 0 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
damage = std::make_unique<FrameDamage>();
if (frame->framebuffer_info().existing_damage && !force_full_repaint) {
damage->SetPreviousLayerTree(last_layer_tree_.get());
std::cout << "prev layer tree was set" << std::endl;
damage->AddAdditonalDamage(*frame->framebuffer_info().existing_damage);
damage->SetClipAlignment(
frame->framebuffer_info().horizontal_clip_alignment,
Expand Down
6 changes: 4 additions & 2 deletions shell/common/shell_test_platform_view_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "flutter/shell/common/shell_test_platform_view_gl.h"

#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#include "shell/gpu/gpu_surface_gl_delegate.h"

namespace flutter {
namespace testing {
Expand Down Expand Up @@ -69,8 +70,9 @@ bool ShellTestPlatformViewGL::GLContextPresent(
}

// |GPUSurfaceGLDelegate|
intptr_t ShellTestPlatformViewGL::GLContextFBO(GLFrameInfo frame_info) const {
return gl_surface_.GetFramebuffer(frame_info.width, frame_info.height);
GLFBOInfo ShellTestPlatformViewGL::GLContextFBO(GLFrameInfo frame_info) const {
return GLFBOInfo{
gl_surface_.GetFramebuffer(frame_info.width, frame_info.height)};
}

// |GPUSurfaceGLDelegate|
Expand Down
2 changes: 1 addition & 1 deletion shell/common/shell_test_platform_view_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ShellTestPlatformViewGL : public ShellTestPlatformView,
bool GLContextPresent(const GLPresentInfo& present_info) override;

// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override;

// |GPUSurfaceGLDelegate|
GLProcResolver GetGLProcResolver() const override;
Expand Down
16 changes: 13 additions & 3 deletions shell/gpu/gpu_surface_gl_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,25 @@ struct GLFrameInfo {

// Information passed during presentation of a frame.
struct GLPresentInfo {
uint32_t fbo_id;
intptr_t fbo_id;

// Damage is a hint to compositor telling it which parts of front buffer
// need to be updated
const std::optional<SkIRect>& damage;
const std::optional<SkIRect>& frame_damage;

// Time at which this frame is scheduled to be presented. This is a hint
// that can be passed to the platform to drop queued frames.
std::optional<fml::TimePoint> presentation_time = std::nullopt;

const std::optional<SkIRect>& buffer_damage;
};

// Information passed when an FBO is requested.
struct GLFBOInfo {
uint32_t fbo_id;

// Refers to the FBO's damage since it was last used.
const SkIRect existing_damage;
};

class GPUSurfaceGLDelegate {
Expand All @@ -55,7 +65,7 @@ class GPUSurfaceGLDelegate {
virtual bool GLContextPresent(const GLPresentInfo& present_info) = 0;

// The ID of the main window bound framebuffer. Typically FBO0.
virtual intptr_t GLContextFBO(GLFrameInfo frame_info) const = 0;
virtual GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const = 0;

// The rendering subsystem assumes that the ID of the main window bound
// framebuffer remains constant throughout. If this assumption in incorrect,
Expand Down
3 changes: 2 additions & 1 deletion shell/gpu/gpu_surface_gl_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGLImpeller::AcquireFrame(
if (weak) {
GLPresentInfo present_info = {
.fbo_id = 0,
.damage = std::nullopt,
.frame_damage = std::nullopt,
// TODO (https://github.com/flutter/flutter/issues/105597): wire-up
// presentation time to impeller backend.
.presentation_time = std::nullopt,
.buffer_damage = std::nullopt
};
delegate->GLContextPresent(present_info);
}
Expand Down
Loading