mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Make the PlatformView client rendering API agnostic. (#3099)
This commit is contained in:
parent
e980741445
commit
fdf13d720e
@ -6,3 +6,4 @@ BasedOnStyle: Chromium
|
||||
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
|
||||
# 'int>>' if the file already contains at least one such instance.)
|
||||
Standard: Cpp11
|
||||
SortIncludes: true
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
|
||||
namespace flow {
|
||||
|
||||
CompositorContext::CompositorContext() {}
|
||||
CompositorContext::CompositorContext() = default;
|
||||
|
||||
CompositorContext::~CompositorContext() {}
|
||||
CompositorContext::~CompositorContext() = default;
|
||||
|
||||
void CompositorContext::BeginFrame(ScopedFrame& frame,
|
||||
bool enable_instrumentation) {
|
||||
|
||||
@ -21,10 +21,13 @@ class CompositorContext {
|
||||
class ScopedFrame {
|
||||
public:
|
||||
SkCanvas& canvas() { return *canvas_; }
|
||||
|
||||
CompositorContext& context() const { return context_; }
|
||||
|
||||
GrContext* gr_context() const { return gr_context_; }
|
||||
|
||||
ScopedFrame(ScopedFrame&& frame);
|
||||
|
||||
~ScopedFrame();
|
||||
|
||||
private:
|
||||
@ -44,6 +47,7 @@ class CompositorContext {
|
||||
};
|
||||
|
||||
CompositorContext();
|
||||
|
||||
~CompositorContext();
|
||||
|
||||
ScopedFrame AcquireFrame(GrContext* gr_context,
|
||||
@ -53,18 +57,21 @@ class CompositorContext {
|
||||
void OnGrContextDestroyed();
|
||||
|
||||
RasterCache& raster_cache() { return raster_cache_; }
|
||||
|
||||
const Counter& frame_count() const { return frame_count_; }
|
||||
|
||||
const Stopwatch& frame_time() const { return frame_time_; }
|
||||
|
||||
Stopwatch& engine_time() { return engine_time_; };
|
||||
|
||||
private:
|
||||
RasterCache raster_cache_;
|
||||
|
||||
Counter frame_count_;
|
||||
Stopwatch frame_time_;
|
||||
Stopwatch engine_time_;
|
||||
|
||||
void BeginFrame(ScopedFrame& frame, bool enable_instrumentation);
|
||||
|
||||
void EndFrame(ScopedFrame& frame, bool enable_instrumentation);
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(CompositorContext);
|
||||
|
||||
@ -22,6 +22,8 @@ source_set("common") {
|
||||
"diagnostic/diagnostic_server.h",
|
||||
"engine.cc",
|
||||
"engine.h",
|
||||
"null_rasterizer.cc",
|
||||
"null_rasterizer.h",
|
||||
"picture_serializer.cc",
|
||||
"picture_serializer.h",
|
||||
"platform_view.cc",
|
||||
@ -32,6 +34,8 @@ source_set("common") {
|
||||
"rasterizer.h",
|
||||
"shell.cc",
|
||||
"shell.h",
|
||||
"surface.cc",
|
||||
"surface.h",
|
||||
"switches.cc",
|
||||
"switches.h",
|
||||
"tracing_controller.cc",
|
||||
|
||||
41
shell/common/null_rasterizer.cc
Normal file
41
shell/common/null_rasterizer.cc
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2016 The Chromium 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/common/null_rasterizer.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
NullRasterizer::NullRasterizer() : weak_factory_(this) {}
|
||||
|
||||
void NullRasterizer::Setup(
|
||||
std::unique_ptr<Surface> surface_or_null,
|
||||
ftl::Closure rasterizer_continuation,
|
||||
ftl::AutoResetWaitableEvent* setup_completion_event) {
|
||||
rasterizer_continuation();
|
||||
setup_completion_event->Signal();
|
||||
}
|
||||
|
||||
void NullRasterizer::Teardown(
|
||||
ftl::AutoResetWaitableEvent* teardown_completion_event) {
|
||||
teardown_completion_event->Signal();
|
||||
}
|
||||
|
||||
ftl::WeakPtr<Rasterizer> NullRasterizer::GetWeakRasterizerPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
flow::LayerTree* NullRasterizer::GetLastLayerTree() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NullRasterizer::Clear(SkColor color, const SkISize& size) {
|
||||
// Null rasterizer. Nothing to do.
|
||||
}
|
||||
|
||||
void NullRasterizer::Draw(
|
||||
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
|
||||
// Null rasterizer. Nothing to do.
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
41
shell/common/null_rasterizer.h
Normal file
41
shell/common/null_rasterizer.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2016 The Chromium 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_COMMON_NULL_RASTERIZER_H_
|
||||
#define FLUTTER_SHELL_COMMON_NULL_RASTERIZER_H_
|
||||
|
||||
#include "flutter/shell/common/rasterizer.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class NullRasterizer : public Rasterizer {
|
||||
public:
|
||||
NullRasterizer();
|
||||
|
||||
void Setup(std::unique_ptr<Surface> surface_or_null,
|
||||
ftl::Closure rasterizer_continuation,
|
||||
ftl::AutoResetWaitableEvent* setup_completion_event) override;
|
||||
|
||||
void Teardown(
|
||||
ftl::AutoResetWaitableEvent* teardown_completion_event) override;
|
||||
|
||||
void Clear(SkColor color, const SkISize& size) override;
|
||||
|
||||
ftl::WeakPtr<Rasterizer> GetWeakRasterizerPtr() override;
|
||||
|
||||
flow::LayerTree* GetLastLayerTree() override;
|
||||
|
||||
void Draw(ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) override;
|
||||
|
||||
private:
|
||||
ftl::WeakPtrFactory<NullRasterizer> weak_factory_;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(NullRasterizer);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // FLUTTER_SHELL_COMMON_NULL_RASTERIZER_H_
|
||||
@ -10,6 +10,7 @@
|
||||
#include "flutter/glue/movable_wrapper.h"
|
||||
#include "flutter/lib/ui/painting/resource_context.h"
|
||||
#include "flutter/shell/common/rasterizer.h"
|
||||
#include "lib/ftl/functional/wrap_lambda.h"
|
||||
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
|
||||
|
||||
namespace shell {
|
||||
@ -18,8 +19,8 @@ PlatformView::Config::Config() : rasterizer(nullptr) {}
|
||||
|
||||
PlatformView::Config::~Config() = default;
|
||||
|
||||
PlatformView::PlatformView()
|
||||
: rasterizer_(Rasterizer::Create()), size_(SkISize::Make(0, 0)) {
|
||||
PlatformView::PlatformView(std::unique_ptr<Rasterizer> rasterizer)
|
||||
: rasterizer_(std::move(rasterizer)), size_(SkISize::Make(0, 0)) {
|
||||
engine_.reset(new Engine(rasterizer_.get()));
|
||||
|
||||
// Setup the platform config.
|
||||
@ -51,24 +52,40 @@ void PlatformView::ConnectToEngine(
|
||||
[view]() { Shell::Shared().AddPlatformView(view); });
|
||||
}
|
||||
|
||||
void PlatformView::NotifyCreated() {
|
||||
PlatformView::NotifyCreated([]() {});
|
||||
void PlatformView::NotifyCreated(std::unique_ptr<Surface> surface) {
|
||||
NotifyCreated(std::move(surface), []() {});
|
||||
}
|
||||
|
||||
void PlatformView::NotifyCreated(ftl::Closure rasterizer_continuation) {
|
||||
void PlatformView::NotifyCreated(std::unique_ptr<Surface> surface,
|
||||
ftl::Closure caller_continuation) {
|
||||
FTL_CHECK(config_.rasterizer);
|
||||
|
||||
ftl::AutoResetWaitableEvent latch;
|
||||
|
||||
auto delegate_continuation = [this, rasterizer_continuation, &latch]() {
|
||||
config_.rasterizer->Setup(this, rasterizer_continuation, &latch);
|
||||
};
|
||||
|
||||
auto delegate = config_.ui_delegate;
|
||||
blink::Threads::UI()->PostTask([delegate, delegate_continuation]() {
|
||||
delegate->OnOutputSurfaceCreated(delegate_continuation);
|
||||
auto ui_continuation = ftl::WrapLambda([
|
||||
delegate = config_.ui_delegate, //
|
||||
rasterizer = config_.rasterizer, //
|
||||
surface = std::move(surface), //
|
||||
caller_continuation, //
|
||||
&latch
|
||||
]() mutable {
|
||||
auto gpu_continuation = ftl::WrapLambda([
|
||||
rasterizer, //
|
||||
surface = std::move(surface), //
|
||||
caller_continuation, //
|
||||
&latch
|
||||
]() mutable {
|
||||
// Runs on the GPU Thread. So does the Caller Continuation.
|
||||
surface->Setup();
|
||||
rasterizer->Setup(std::move(surface), caller_continuation, &latch);
|
||||
});
|
||||
// Runs on the UI Thread.
|
||||
delegate->OnOutputSurfaceCreated(std::move(gpu_continuation));
|
||||
});
|
||||
|
||||
// Runs on the Platform Thread.
|
||||
blink::Threads::UI()->PostTask(std::move(ui_continuation));
|
||||
|
||||
latch.Wait();
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#include "flutter/shell/common/engine.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/common/surface.h"
|
||||
#include "flutter/shell/common/ui_delegate.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
@ -46,22 +47,17 @@ class PlatformView {
|
||||
|
||||
void ConnectToEngine(mojo::InterfaceRequest<sky::SkyEngine> request);
|
||||
|
||||
void NotifyCreated();
|
||||
void NotifyCreated(std::unique_ptr<Surface> surface);
|
||||
|
||||
void NotifyCreated(ftl::Closure continuation);
|
||||
void NotifyCreated(std::unique_ptr<Surface> surface,
|
||||
ftl::Closure continuation);
|
||||
|
||||
void NotifyDestroyed();
|
||||
|
||||
virtual ftl::WeakPtr<PlatformView> GetWeakViewPtr() = 0;
|
||||
|
||||
virtual uint64_t DefaultFramebuffer() const = 0;
|
||||
|
||||
virtual bool ContextMakeCurrent() = 0;
|
||||
|
||||
virtual bool ResourceContextMakeCurrent() = 0;
|
||||
|
||||
virtual bool SwapBuffers() = 0;
|
||||
|
||||
virtual SkISize GetSize();
|
||||
|
||||
virtual void Resize(const SkISize& size);
|
||||
@ -75,13 +71,11 @@ class PlatformView {
|
||||
protected:
|
||||
Config config_;
|
||||
SurfaceConfig surface_config_;
|
||||
|
||||
std::unique_ptr<Rasterizer> rasterizer_;
|
||||
std::unique_ptr<Engine> engine_;
|
||||
|
||||
SkISize size_;
|
||||
|
||||
explicit PlatformView();
|
||||
explicit PlatformView(std::unique_ptr<Rasterizer> rasterizer);
|
||||
|
||||
void SetupResourceContextOnIOThreadPerform(
|
||||
ftl::AutoResetWaitableEvent* event);
|
||||
|
||||
@ -6,6 +6,6 @@
|
||||
|
||||
namespace shell {
|
||||
|
||||
Rasterizer::~Rasterizer() {}
|
||||
Rasterizer::~Rasterizer() = default;
|
||||
|
||||
} // namespace shell
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
#define SHELL_COMMON_RASTERIZER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "flutter/shell/common/surface.h"
|
||||
#include "flutter/synchronization/pipeline.h"
|
||||
#include "lib/ftl/functional/closure.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
@ -16,30 +16,25 @@
|
||||
|
||||
namespace shell {
|
||||
|
||||
class PlatformView;
|
||||
|
||||
class Rasterizer {
|
||||
public:
|
||||
virtual ~Rasterizer();
|
||||
|
||||
virtual void Setup(PlatformView* platform_view,
|
||||
virtual void Setup(std::unique_ptr<Surface> surface_or_null,
|
||||
ftl::Closure rasterizer_continuation,
|
||||
ftl::AutoResetWaitableEvent* setup_completion_event) = 0;
|
||||
|
||||
virtual void Clear(SkColor color) = 0;
|
||||
|
||||
virtual void Teardown(
|
||||
ftl::AutoResetWaitableEvent* teardown_completion_event) = 0;
|
||||
|
||||
virtual void Clear(SkColor color, const SkISize& size) = 0;
|
||||
|
||||
virtual ftl::WeakPtr<Rasterizer> GetWeakRasterizerPtr() = 0;
|
||||
|
||||
virtual flow::LayerTree* GetLastLayerTree() = 0;
|
||||
|
||||
virtual void Draw(
|
||||
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) = 0;
|
||||
|
||||
// Implemented by each GPU backend.
|
||||
static std::unique_ptr<Rasterizer> Create();
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
27
shell/common/surface.cc
Normal file
27
shell/common/surface.cc
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2016 The Chromium 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/common/surface.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
SurfaceFrame::SurfaceFrame() : submitted_(false) {}
|
||||
|
||||
SurfaceFrame::~SurfaceFrame() = default;
|
||||
|
||||
bool SurfaceFrame::Submit() {
|
||||
if (submitted_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
submitted_ = PerformSubmit();
|
||||
|
||||
return submitted_;
|
||||
}
|
||||
|
||||
Surface::Surface() = default;
|
||||
|
||||
Surface::~Surface() = default;
|
||||
|
||||
} // namespace shell
|
||||
54
shell/common/surface.h
Normal file
54
shell/common/surface.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2016 The Chromium 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_COMMON_SURFACE_H_
|
||||
#define FLUTTER_SHELL_COMMON_SURFACE_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "lib/ftl/compiler_specific.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class SurfaceFrame {
|
||||
public:
|
||||
SurfaceFrame();
|
||||
|
||||
virtual ~SurfaceFrame();
|
||||
|
||||
bool Submit();
|
||||
|
||||
virtual SkCanvas* SkiaCanvas() = 0;
|
||||
|
||||
private:
|
||||
bool submitted_;
|
||||
|
||||
virtual bool PerformSubmit() = 0;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(SurfaceFrame);
|
||||
};
|
||||
|
||||
class Surface {
|
||||
public:
|
||||
Surface();
|
||||
|
||||
virtual ~Surface();
|
||||
|
||||
virtual bool Setup() = 0;
|
||||
|
||||
virtual bool IsValid() = 0;
|
||||
|
||||
virtual std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) = 0;
|
||||
|
||||
virtual GrContext* GetContext() = 0;
|
||||
|
||||
private:
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(Surface);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // FLUTTER_SHELL_COMMON_SURFACE_H_
|
||||
@ -4,23 +4,22 @@
|
||||
|
||||
source_set("gpu") {
|
||||
sources = [
|
||||
"gpu_canvas.cc",
|
||||
"gpu_canvas.h",
|
||||
"gpu_canvas_gl.cc",
|
||||
"gpu_canvas_gl.h",
|
||||
"gpu_canvas_vulkan.cc",
|
||||
"gpu_canvas_vulkan.h",
|
||||
"gpu_rasterizer.cc",
|
||||
"gpu_rasterizer.h",
|
||||
"gpu_surface_gl.cc",
|
||||
"gpu_surface_gl.h",
|
||||
"gpu_surface_vulkan.cc",
|
||||
"gpu_surface_vulkan.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../common",
|
||||
"//lib/ftl",
|
||||
"//flutter/skia",
|
||||
"//flutter/flow",
|
||||
"//flutter/common",
|
||||
"//flutter/flow",
|
||||
"//flutter/glue",
|
||||
"//flutter/skia",
|
||||
"//flutter/synchronization",
|
||||
"//lib/ftl",
|
||||
"//mojo/public/cpp/system",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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 "gpu_canvas.h"
|
||||
#include "gpu_canvas_gl.h"
|
||||
#include "gpu_canvas_vulkan.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
GPUCanvas::~GPUCanvas() = default;
|
||||
|
||||
std::unique_ptr<GPUCanvas> GPUCanvas::CreatePlatformCanvas(
|
||||
const PlatformView& platform_view) {
|
||||
std::unique_ptr<GPUCanvas> canvas;
|
||||
|
||||
// TODO: Vulkan capability detection will be added here to return a differnt
|
||||
// canvas instance.
|
||||
|
||||
canvas.reset(new GPUCanvasGL(platform_view.DefaultFramebuffer()));
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
@ -1,34 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_CANVAS_H_
|
||||
#define SHELL_GPU_GPU_CANVAS_H_
|
||||
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/compiler_specific.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class GPUCanvas {
|
||||
public:
|
||||
static std::unique_ptr<GPUCanvas> CreatePlatformCanvas(
|
||||
const PlatformView& platform_view);
|
||||
|
||||
virtual ~GPUCanvas();
|
||||
|
||||
FTL_WARN_UNUSED_RESULT
|
||||
virtual bool Setup() = 0;
|
||||
|
||||
virtual bool IsValid() = 0;
|
||||
|
||||
virtual SkCanvas* AcquireCanvas(const SkISize& size) = 0;
|
||||
|
||||
virtual GrContext* GetContext() = 0;
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // SHELL_GPU_GPU_CANVAS_H_
|
||||
@ -1,43 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_CANVAS_GL_H_
|
||||
#define SHELL_GPU_GPU_CANVAS_GL_H_
|
||||
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "gpu_canvas.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class GPUCanvasGL : public GPUCanvas {
|
||||
public:
|
||||
GPUCanvasGL(intptr_t fbo);
|
||||
|
||||
~GPUCanvasGL() override;
|
||||
|
||||
bool Setup() override;
|
||||
|
||||
bool IsValid() override;
|
||||
|
||||
SkCanvas* AcquireCanvas(const SkISize& size) override;
|
||||
|
||||
GrContext* GetContext() override;
|
||||
|
||||
private:
|
||||
intptr_t fbo_;
|
||||
sk_sp<GrContext> context_;
|
||||
sk_sp<SkSurface> cached_surface_;
|
||||
|
||||
sk_sp<SkSurface> CreateSurface(const SkISize& size);
|
||||
|
||||
sk_sp<SkSurface> AcquireSurface(const SkISize& size);
|
||||
|
||||
bool SelectPixelConfig(GrPixelConfig* config);
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(GPUCanvasGL);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // SHELL_GPU_GPU_CANVAS_GL_H_
|
||||
@ -9,16 +9,15 @@
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/glue/trace_event.h"
|
||||
#include "flutter/shell/common/picture_serializer.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/common/picture_serializer.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkPicture.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
GPURasterizer::GPURasterizer() : platform_view_(nullptr), weak_factory_(this) {
|
||||
GPURasterizer::GPURasterizer() : weak_factory_(this) {
|
||||
auto weak_ptr = weak_factory_.GetWeakPtr();
|
||||
blink::Threads::Gpu()->PostTask(
|
||||
[weak_ptr]() { Shell::Shared().AddRasterizer(weak_ptr); });
|
||||
@ -29,70 +28,45 @@ GPURasterizer::~GPURasterizer() {
|
||||
Shell::Shared().PurgeRasterizers();
|
||||
}
|
||||
|
||||
std::unique_ptr<Rasterizer> Rasterizer::Create() {
|
||||
return std::unique_ptr<GPURasterizer>(new GPURasterizer());
|
||||
}
|
||||
|
||||
ftl::WeakPtr<Rasterizer> GPURasterizer::GetWeakRasterizerPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
bool GPURasterizer::Setup(PlatformView* platform_view) {
|
||||
if (platform_view == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!platform_view->ContextMakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto gpu_canvas = GPUCanvas::CreatePlatformCanvas(*platform_view);
|
||||
|
||||
if (gpu_canvas == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gpu_canvas->Setup()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gpu_canvas_ = std::move(gpu_canvas);
|
||||
platform_view_ = platform_view;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPURasterizer::Setup(PlatformView* platform_view,
|
||||
void GPURasterizer::Setup(std::unique_ptr<Surface> surface,
|
||||
ftl::Closure continuation,
|
||||
ftl::AutoResetWaitableEvent* setup_completion_event) {
|
||||
auto setup_result = Setup(platform_view);
|
||||
|
||||
FTL_CHECK(setup_result) << "Must be able to setup the GPU canvas.";
|
||||
surface_ = std::move(surface);
|
||||
|
||||
continuation();
|
||||
|
||||
setup_completion_event->Signal();
|
||||
}
|
||||
|
||||
void GPURasterizer::Clear(SkColor color) {
|
||||
if (gpu_canvas_ == nullptr) {
|
||||
void GPURasterizer::Clear(SkColor color, const SkISize& size) {
|
||||
if (surface_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkCanvas* canvas = gpu_canvas_->AcquireCanvas(platform_view_->GetSize());
|
||||
auto frame = surface_->AcquireFrame(size);
|
||||
|
||||
if (frame == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkCanvas* canvas = frame->SkiaCanvas();
|
||||
|
||||
if (canvas == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
canvas->clear(color);
|
||||
canvas->flush();
|
||||
|
||||
platform_view_->SwapBuffers();
|
||||
frame->Submit();
|
||||
}
|
||||
|
||||
void GPURasterizer::Teardown(
|
||||
ftl::AutoResetWaitableEvent* teardown_completion_event) {
|
||||
platform_view_ = nullptr;
|
||||
surface_.reset();
|
||||
last_layer_tree_.reset();
|
||||
compositor_context_.OnGrContextDestroyed();
|
||||
teardown_completion_event->Signal();
|
||||
@ -106,9 +80,6 @@ void GPURasterizer::Draw(
|
||||
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
|
||||
TRACE_EVENT0("flutter", "GPURasterizer::Draw");
|
||||
|
||||
if (!platform_view_)
|
||||
return;
|
||||
|
||||
flutter::Pipeline<flow::LayerTree>::Consumer consumer =
|
||||
std::bind(&GPURasterizer::DoDraw, this, std::placeholders::_1);
|
||||
|
||||
@ -130,7 +101,7 @@ void GPURasterizer::Draw(
|
||||
}
|
||||
|
||||
void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
|
||||
if (!layer_tree || !gpu_canvas_) {
|
||||
if (!layer_tree || !surface_) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -139,62 +110,76 @@ void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
|
||||
// for instrumentation.
|
||||
compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());
|
||||
|
||||
SkISize size = layer_tree->frame_size();
|
||||
if (platform_view_->GetSize() != size) {
|
||||
platform_view_->Resize(size);
|
||||
}
|
||||
DrawToSurface(*layer_tree);
|
||||
|
||||
if (!platform_view_->ContextMakeCurrent() || !layer_tree->root_layer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
SkCanvas* canvas = gpu_canvas_->AcquireCanvas(layer_tree->frame_size());
|
||||
flow::CompositorContext::ScopedFrame frame =
|
||||
compositor_context_.AcquireFrame(gpu_canvas_->GetContext(), *canvas);
|
||||
canvas->clear(SK_ColorBLACK);
|
||||
layer_tree->Raster(frame);
|
||||
|
||||
{
|
||||
TRACE_EVENT0("flutter", "SkCanvas::Flush");
|
||||
canvas->flush();
|
||||
}
|
||||
|
||||
platform_view_->SwapBuffers();
|
||||
}
|
||||
|
||||
// Trace to a file if necessary
|
||||
static const double kOneFrameDuration = 1e3 / 60.0;
|
||||
bool frameExceededThreshold = false;
|
||||
uint32_t thresholdInterval = layer_tree->rasterizer_tracing_threshold();
|
||||
if (thresholdInterval != 0 &&
|
||||
compositor_context_.frame_time().LastLap().ToMillisecondsF() >
|
||||
thresholdInterval * kOneFrameDuration) {
|
||||
// While rendering the last frame, if we exceeded the tracing threshold
|
||||
// specified in the layer tree, we force a trace to disk.
|
||||
frameExceededThreshold = true;
|
||||
}
|
||||
|
||||
const auto& tracingController = Shell::Shared().tracing_controller();
|
||||
|
||||
if (frameExceededThreshold || tracingController.picture_tracing_enabled()) {
|
||||
std::string path = tracingController.PictureTracingPathForCurrentTime();
|
||||
LOG(INFO) << "Frame threshold exceeded. Capturing SKP to " << path;
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
recorder.beginRecording(SkRect::MakeWH(size.width(), size.height()));
|
||||
|
||||
{
|
||||
auto frame = compositor_context_.AcquireFrame(
|
||||
nullptr, *recorder.getRecordingCanvas(), false);
|
||||
layer_tree->Raster(frame, true);
|
||||
}
|
||||
|
||||
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
|
||||
SerializePicture(path, picture.get());
|
||||
}
|
||||
DrawToTraceIfNecessary(*layer_tree);
|
||||
|
||||
last_layer_tree_ = std::move(layer_tree);
|
||||
}
|
||||
|
||||
void GPURasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
|
||||
auto frame = surface_->AcquireFrame(layer_tree.frame_size());
|
||||
|
||||
if (frame == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto canvas = frame->SkiaCanvas();
|
||||
|
||||
if (canvas == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto compositor_frame =
|
||||
compositor_context_.AcquireFrame(surface_->GetContext(), *canvas);
|
||||
|
||||
canvas->clear(SK_ColorBLACK);
|
||||
|
||||
layer_tree.Raster(compositor_frame);
|
||||
|
||||
frame->Submit();
|
||||
}
|
||||
|
||||
bool GPURasterizer::ShouldDrawToTrace(flow::LayerTree& layer_tree) {
|
||||
if (Shell::Shared().tracing_controller().picture_tracing_enabled()) {
|
||||
// Picture tracing is unconditionally enabled for all frames by the tracing
|
||||
// controller.
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint32_t threshold_interval = layer_tree.rasterizer_tracing_threshold();
|
||||
|
||||
if (threshold_interval == 0) {
|
||||
// An interval of zero means tracing is disabled.
|
||||
return false;
|
||||
}
|
||||
|
||||
return compositor_context_.frame_time().LastLap().ToMillisecondsF() >
|
||||
threshold_interval * 1e3 / 60.0;
|
||||
}
|
||||
|
||||
void GPURasterizer::DrawToTraceIfNecessary(flow::LayerTree& layer_tree) {
|
||||
if (!ShouldDrawToTrace(layer_tree)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& tracing_controller = Shell::Shared().tracing_controller();
|
||||
|
||||
std::string path = tracing_controller.PictureTracingPathForCurrentTime();
|
||||
LOG(INFO) << "Frame threshold exceeded. Capturing SKP to " << path;
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
recorder.beginRecording(layer_tree.frame_size().width(),
|
||||
layer_tree.frame_size().height());
|
||||
|
||||
auto compositor_frame = compositor_context_.AcquireFrame(
|
||||
nullptr, *recorder.getRecordingCanvas(), false);
|
||||
layer_tree.Raster(compositor_frame, true /* ignore raster cache */);
|
||||
|
||||
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
|
||||
|
||||
SerializePicture(path, picture.get());
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
|
||||
@ -7,23 +7,24 @@
|
||||
|
||||
#include "flutter/flow/compositor_context.h"
|
||||
#include "flutter/shell/common/rasterizer.h"
|
||||
#include "flutter/shell/gpu/gpu_canvas.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
#include "lib/ftl/synchronization/waitable_event.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class Surface;
|
||||
|
||||
class GPURasterizer : public Rasterizer {
|
||||
public:
|
||||
GPURasterizer();
|
||||
|
||||
~GPURasterizer() override;
|
||||
|
||||
void Setup(PlatformView* platform_view,
|
||||
void Setup(std::unique_ptr<Surface> surface,
|
||||
ftl::Closure continuation,
|
||||
ftl::AutoResetWaitableEvent* setup_completion_event) override;
|
||||
|
||||
void Clear(SkColor color) override;
|
||||
void Clear(SkColor color, const SkISize& size) override;
|
||||
|
||||
void Teardown(
|
||||
ftl::AutoResetWaitableEvent* teardown_completion_event) override;
|
||||
@ -35,16 +36,18 @@ class GPURasterizer : public Rasterizer {
|
||||
void Draw(ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<GPUCanvas> gpu_canvas_;
|
||||
std::unique_ptr<Surface> surface_;
|
||||
flow::CompositorContext compositor_context_;
|
||||
std::unique_ptr<flow::LayerTree> last_layer_tree_;
|
||||
PlatformView* platform_view_;
|
||||
ftl::WeakPtrFactory<GPURasterizer> weak_factory_;
|
||||
|
||||
FTL_WARN_UNUSED_RESULT
|
||||
bool Setup(PlatformView* platform_view);
|
||||
void DoDraw(std::unique_ptr<flow::LayerTree> layer_tree);
|
||||
|
||||
void DoDraw(std::unique_ptr<flow::LayerTree> tree);
|
||||
void DrawToSurface(flow::LayerTree& layer_tree);
|
||||
|
||||
bool ShouldDrawToTrace(flow::LayerTree& layer_tree);
|
||||
|
||||
void DrawToTraceIfNecessary(flow::LayerTree& layer_tree);
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(GPURasterizer);
|
||||
};
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "gpu_canvas_gl.h"
|
||||
#include "gpu_surface_gl.h"
|
||||
|
||||
#include "flutter/flow/gl_connection.h"
|
||||
#include "lib/ftl/arraysize.h"
|
||||
#include "lib/ftl/logging.h"
|
||||
#include "flutter/flow/gl_connection.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
#include "third_party/skia/include/gpu/GrContext.h"
|
||||
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
@ -21,16 +21,59 @@ static const int kMaxGaneshResourceCacheCount = 2048;
|
||||
// GPU cache.
|
||||
static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
|
||||
|
||||
GPUCanvasGL::GPUCanvasGL(intptr_t fbo) : fbo_(fbo) {}
|
||||
GPUSurfaceFrameGL::GPUSurfaceFrameGL(sk_sp<SkSurface> surface,
|
||||
SubmitCallback submit_callback)
|
||||
: surface_(surface), submit_callback_(submit_callback) {}
|
||||
|
||||
GPUCanvasGL::~GPUCanvasGL() = default;
|
||||
GPUSurfaceFrameGL::~GPUSurfaceFrameGL() {
|
||||
if (submit_callback_) {
|
||||
// Dropping without a Submit. Callback with nullptr so that the current
|
||||
// context on the thread is cleared.
|
||||
submit_callback_(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
SkCanvas* GPUSurfaceFrameGL::SkiaCanvas() {
|
||||
return surface_->getCanvas();
|
||||
}
|
||||
|
||||
bool GPUSurfaceFrameGL::PerformSubmit() {
|
||||
if (submit_callback_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FLUTTER_THREAD_CHECKER_CHECK(checker_);
|
||||
|
||||
if (submit_callback_(surface_->getCanvas())) {
|
||||
surface_ = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
|
||||
: delegate_(delegate), weak_factory_(this) {}
|
||||
|
||||
GPUSurfaceGL::~GPUSurfaceGL() = default;
|
||||
|
||||
bool GPUSurfaceGL::Setup() {
|
||||
if (delegate_ == nullptr) {
|
||||
// Invalid delegate.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPUCanvasGL::Setup() {
|
||||
if (context_ != nullptr) {
|
||||
// Already setup.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!delegate_->GLContextMakeCurrent()) {
|
||||
// Could not make the context current to create the native interface.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the native interface.
|
||||
auto backend_context =
|
||||
reinterpret_cast<GrBackendContext>(GrGLCreateNativeInterface());
|
||||
|
||||
@ -46,24 +89,59 @@ bool GPUCanvasGL::Setup() {
|
||||
context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
|
||||
kMaxGaneshResourceCacheBytes);
|
||||
|
||||
// Clean up the current context.
|
||||
delegate_->GLContextClearCurrent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPUCanvasGL::IsValid() {
|
||||
bool GPUSurfaceGL::IsValid() {
|
||||
return context_ != nullptr;
|
||||
}
|
||||
|
||||
SkCanvas* GPUCanvasGL::AcquireCanvas(const SkISize& size) {
|
||||
auto surface = AcquireSurface(size);
|
||||
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
|
||||
if (delegate_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> surface = AcquireSurface(size);
|
||||
|
||||
if (surface == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return surface->getCanvas();
|
||||
if (!delegate_->GLContextMakeCurrent()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto weak_this = weak_factory_.GetWeakPtr();
|
||||
|
||||
GPUSurfaceFrameGL::SubmitCallback submit_callback =
|
||||
[weak_this](SkCanvas* canvas) {
|
||||
return weak_this ? weak_this->PresentSurface(canvas) : false;
|
||||
};
|
||||
|
||||
return std::unique_ptr<GPUSurfaceFrameGL>(
|
||||
new GPUSurfaceFrameGL(surface, submit_callback));
|
||||
}
|
||||
|
||||
bool GPUCanvasGL::SelectPixelConfig(GrPixelConfig* config) {
|
||||
bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
|
||||
if (delegate_ == nullptr || canvas == nullptr) {
|
||||
delegate_->GLContextClearCurrent();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
canvas->flush();
|
||||
|
||||
delegate_->GLContextPresent();
|
||||
|
||||
delegate_->GLContextClearCurrent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPUSurfaceGL::SelectPixelConfig(GrPixelConfig* config) {
|
||||
static const GrPixelConfig kConfigOptions[] = {
|
||||
kSkia8888_GrPixelConfig, kRGBA_4444_GrPixelConfig,
|
||||
};
|
||||
@ -78,8 +156,8 @@ bool GPUCanvasGL::SelectPixelConfig(GrPixelConfig* config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> GPUCanvasGL::CreateSurface(const SkISize& size) {
|
||||
if (context_ == nullptr) {
|
||||
sk_sp<SkSurface> GPUSurfaceGL::CreateSurface(const SkISize& size) {
|
||||
if (delegate_ == nullptr || context_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -93,12 +171,12 @@ sk_sp<SkSurface> GPUCanvasGL::CreateSurface(const SkISize& size) {
|
||||
desc.fHeight = size.height();
|
||||
desc.fStencilBits = 8;
|
||||
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
|
||||
desc.fRenderTargetHandle = fbo_;
|
||||
desc.fRenderTargetHandle = delegate_->GLContextFBO();
|
||||
|
||||
return SkSurface::MakeFromBackendRenderTarget(context_.get(), desc, nullptr);
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> GPUCanvasGL::AcquireSurface(const SkISize& size) {
|
||||
sk_sp<SkSurface> GPUSurfaceGL::AcquireSurface(const SkISize& size) {
|
||||
// There is no cached surface.
|
||||
if (cached_surface_ == nullptr) {
|
||||
cached_surface_ = CreateSurface(size);
|
||||
@ -115,7 +193,7 @@ sk_sp<SkSurface> GPUCanvasGL::AcquireSurface(const SkISize& size) {
|
||||
return cached_surface_;
|
||||
}
|
||||
|
||||
GrContext* GPUCanvasGL::GetContext() {
|
||||
GrContext* GPUSurfaceGL::GetContext() {
|
||||
return context_.get();
|
||||
}
|
||||
|
||||
79
shell/gpu/gpu_surface_gl.h
Normal file
79
shell/gpu/gpu_surface_gl.h
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2016 The Chromium 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_H_
|
||||
#define SHELL_GPU_GPU_SURFACE_GL_H_
|
||||
|
||||
#include "flutter/shell/common/surface.h"
|
||||
#include "flutter/synchronization/debug_thread_checker.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class GPUSurfaceGLDelegate {
|
||||
public:
|
||||
virtual bool GLContextMakeCurrent() = 0;
|
||||
|
||||
virtual bool GLContextClearCurrent() = 0;
|
||||
|
||||
virtual bool GLContextPresent() = 0;
|
||||
|
||||
virtual intptr_t GLContextFBO() const = 0;
|
||||
};
|
||||
|
||||
class GPUSurfaceGL : public Surface {
|
||||
public:
|
||||
GPUSurfaceGL(GPUSurfaceGLDelegate* delegate);
|
||||
|
||||
~GPUSurfaceGL() override;
|
||||
|
||||
bool Setup() override;
|
||||
|
||||
bool IsValid() override;
|
||||
|
||||
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;
|
||||
|
||||
GrContext* GetContext() override;
|
||||
|
||||
private:
|
||||
GPUSurfaceGLDelegate* delegate_;
|
||||
sk_sp<GrContext> context_;
|
||||
sk_sp<SkSurface> cached_surface_;
|
||||
ftl::WeakPtrFactory<GPUSurfaceGL> weak_factory_;
|
||||
|
||||
sk_sp<SkSurface> CreateSurface(const SkISize& size);
|
||||
|
||||
sk_sp<SkSurface> AcquireSurface(const SkISize& size);
|
||||
|
||||
bool PresentSurface(SkCanvas* canvas);
|
||||
|
||||
bool SelectPixelConfig(GrPixelConfig* config);
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGL);
|
||||
};
|
||||
|
||||
class GPUSurfaceFrameGL : public SurfaceFrame {
|
||||
public:
|
||||
using SubmitCallback = std::function<bool(SkCanvas* canvas)>;
|
||||
|
||||
GPUSurfaceFrameGL(sk_sp<SkSurface> surface, SubmitCallback submit_callback);
|
||||
|
||||
~GPUSurfaceFrameGL();
|
||||
|
||||
SkCanvas* SkiaCanvas() override;
|
||||
|
||||
private:
|
||||
FLUTTER_THREAD_CHECKER_DECLARE(checker_);
|
||||
sk_sp<SkSurface> surface_;
|
||||
SubmitCallback submit_callback_;
|
||||
|
||||
bool PerformSubmit() override;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceFrameGL);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // SHELL_GPU_GPU_SURFACE_GL_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 "gpu_canvas_vulkan.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_vulkan.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
@ -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_CANVAS_VULKAN_H_
|
||||
#define SHELL_GPU_GPU_CANVAS_VULKAN_H_
|
||||
#ifndef SHELL_GPU_GPU_SURFACE_VULKAN_H_
|
||||
#define SHELL_GPU_GPU_SURFACE_VULKAN_H_
|
||||
|
||||
#include "lib/ftl/macros.h"
|
||||
|
||||
@ -13,4 +13,4 @@ namespace shell {
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // SHELL_GPU_GPU_CANVAS_VULKAN_H_
|
||||
#endif // SHELL_GPU_GPU_SURFACE_VULKAN_H_
|
||||
@ -19,6 +19,14 @@ shared_library("sky_shell") {
|
||||
visibility = [ ":*" ]
|
||||
|
||||
sources = [
|
||||
"android_context_gl.cc",
|
||||
"android_context_gl.h",
|
||||
"android_environment_gl.cc",
|
||||
"android_environment_gl.h",
|
||||
"android_native_window.cc",
|
||||
"android_native_window.h",
|
||||
"android_surface_gl.cc",
|
||||
"android_surface_gl.h",
|
||||
"flutter_main.cc",
|
||||
"flutter_main.h",
|
||||
"library_loader.cc",
|
||||
|
||||
286
shell/platform/android/android_context_gl.cc
Normal file
286
shell/platform/android/android_context_gl.cc
Normal file
@ -0,0 +1,286 @@
|
||||
// Copyright 2016 The Chromium 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.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace shell {
|
||||
|
||||
template <class T>
|
||||
using EGLResult = std::pair<bool, T>;
|
||||
|
||||
static void LogLastEGLError() {
|
||||
struct EGLNameErrorPair {
|
||||
const char* name;
|
||||
EGLint code;
|
||||
};
|
||||
|
||||
#define _EGL_ERROR_DESC(a) \
|
||||
{ #a, a }
|
||||
|
||||
const EGLNameErrorPair pairs[] = {
|
||||
_EGL_ERROR_DESC(EGL_SUCCESS),
|
||||
_EGL_ERROR_DESC(EGL_NOT_INITIALIZED),
|
||||
_EGL_ERROR_DESC(EGL_BAD_ACCESS),
|
||||
_EGL_ERROR_DESC(EGL_BAD_ALLOC),
|
||||
_EGL_ERROR_DESC(EGL_BAD_ATTRIBUTE),
|
||||
_EGL_ERROR_DESC(EGL_BAD_CONTEXT),
|
||||
_EGL_ERROR_DESC(EGL_BAD_CONFIG),
|
||||
_EGL_ERROR_DESC(EGL_BAD_CURRENT_SURFACE),
|
||||
_EGL_ERROR_DESC(EGL_BAD_DISPLAY),
|
||||
_EGL_ERROR_DESC(EGL_BAD_SURFACE),
|
||||
_EGL_ERROR_DESC(EGL_BAD_MATCH),
|
||||
_EGL_ERROR_DESC(EGL_BAD_PARAMETER),
|
||||
_EGL_ERROR_DESC(EGL_BAD_NATIVE_PIXMAP),
|
||||
_EGL_ERROR_DESC(EGL_BAD_NATIVE_WINDOW),
|
||||
_EGL_ERROR_DESC(EGL_CONTEXT_LOST),
|
||||
};
|
||||
|
||||
#undef _EGL_ERROR_DESC
|
||||
|
||||
const auto count = sizeof(pairs) / sizeof(EGLNameErrorPair);
|
||||
|
||||
EGLint last_error = eglGetError();
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (last_error == pairs[i].code) {
|
||||
DLOG(INFO) << "EGL Error: " << pairs[i].name << " (" << pairs[i].code
|
||||
<< ")";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DLOG(WARNING) << "Unknown EGL Error";
|
||||
}
|
||||
|
||||
static EGLResult<EGLSurface> 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,
|
||||
PlatformView::SurfaceConfig config) {
|
||||
EGLint attributes[] = {
|
||||
// clang-format off
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, config.red_bits,
|
||||
EGL_GREEN_SIZE, config.green_bits,
|
||||
EGL_BLUE_SIZE, config.blue_bits,
|
||||
EGL_ALPHA_SIZE, config.alpha_bits,
|
||||
EGL_DEPTH_SIZE, config.depth_bits,
|
||||
EGL_STENCIL_SIZE, config.stencil_bits,
|
||||
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;
|
||||
}
|
||||
|
||||
static bool TeardownSurface(EGLDisplay display, EGLSurface surface) {
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
return eglDestroySurface(display, surface) == EGL_TRUE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// For onscreen rendering.
|
||||
static EGLResult<EGLSurface> CreateWindowSurface(
|
||||
EGLDisplay display,
|
||||
EGLConfig config,
|
||||
AndroidNativeWindow::Handle window_handle) {
|
||||
// The configurations are only required when dealing with extensions or VG.
|
||||
// We do neither.
|
||||
EGLSurface surface = eglCreateWindowSurface(
|
||||
display, config, reinterpret_cast<EGLNativeWindowType>(window_handle),
|
||||
nullptr);
|
||||
return {surface != EGL_NO_SURFACE, surface};
|
||||
}
|
||||
|
||||
// For offscreen rendering.
|
||||
static EGLResult<EGLSurface> CreatePBufferSurface(EGLDisplay display,
|
||||
EGLConfig config) {
|
||||
// We only ever create pbuffer surfaces for background resource loading
|
||||
// contexts. We never bind the pbuffer to anything.
|
||||
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||
EGLSurface surface = eglCreatePbufferSurface(display, config, attribs);
|
||||
return {surface != EGL_NO_SURFACE, surface};
|
||||
}
|
||||
|
||||
static EGLResult<EGLSurface> CreateSurface(EGLDisplay display,
|
||||
EGLConfig config,
|
||||
const AndroidNativeWindow& window) {
|
||||
return window.IsValid()
|
||||
? CreateWindowSurface(display, config, window.handle())
|
||||
: CreatePBufferSurface(display, config);
|
||||
}
|
||||
|
||||
AndroidContextGL::AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
|
||||
AndroidNativeWindow window,
|
||||
PlatformView::SurfaceConfig config,
|
||||
const AndroidContextGL* share_context)
|
||||
: environment_(env),
|
||||
window_(std::move(window)),
|
||||
config_(nullptr),
|
||||
surface_(EGL_NO_SURFACE),
|
||||
context_(EGL_NO_CONTEXT),
|
||||
valid_(false) {
|
||||
if (!environment_->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Choose a valid configuration.
|
||||
|
||||
std::tie(success, config_) =
|
||||
ChooseEGLConfiguration(environment_->Display(), config);
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not choose a configuration.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a surface for the configuration.
|
||||
|
||||
std::tie(success, surface_) =
|
||||
CreateSurface(environment_->Display(), config_, window_);
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not create the surface.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a context for the configuration.
|
||||
|
||||
std::tie(success, context_) = CreateContext(
|
||||
environment_->Display(), config_,
|
||||
share_context != nullptr ? share_context->context_ : EGL_NO_CONTEXT);
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not create a context";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// All done!
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
AndroidContextGL::AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
|
||||
PlatformView::SurfaceConfig config,
|
||||
const AndroidContextGL* share_context)
|
||||
: AndroidContextGL(env,
|
||||
AndroidNativeWindow{nullptr},
|
||||
config,
|
||||
share_context) {}
|
||||
|
||||
AndroidContextGL::~AndroidContextGL() {
|
||||
if (!TeardownContext(environment_->Display(), context_)) {
|
||||
LOG(INFO) << "Could not tear down the EGL context. Possible resource leak.";
|
||||
LogLastEGLError();
|
||||
}
|
||||
|
||||
if (!TeardownSurface(environment_->Display(), surface_)) {
|
||||
LOG(INFO) << "Could not tear down the EGL surface. Possible resource leak.";
|
||||
LogLastEGLError();
|
||||
}
|
||||
}
|
||||
|
||||
ftl::RefPtr<AndroidEnvironmentGL> AndroidContextGL::Environment() const {
|
||||
return environment_;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::IsValid() const {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::MakeCurrent() {
|
||||
if (eglMakeCurrent(environment_->Display(), surface_, surface_, context_) !=
|
||||
EGL_TRUE) {
|
||||
LOG(INFO) << "Could not make the context current";
|
||||
LogLastEGLError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::ClearCurrent() {
|
||||
if (eglMakeCurrent(environment_->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT) != EGL_TRUE) {
|
||||
LOG(INFO) << "Could not clear the current context";
|
||||
LogLastEGLError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::SwapBuffers() {
|
||||
return eglSwapBuffers(environment_->Display(), surface_);
|
||||
}
|
||||
|
||||
SkISize AndroidContextGL::GetSize() {
|
||||
EGLint width = 0;
|
||||
EGLint height = 0;
|
||||
|
||||
if (!eglQuerySurface(environment_->Display(), surface_, EGL_WIDTH, &width) ||
|
||||
!eglQuerySurface(environment_->Display(), surface_, EGL_HEIGHT,
|
||||
&height)) {
|
||||
LOG(ERROR) << "Unable to query EGL surface size";
|
||||
LogLastEGLError();
|
||||
return SkISize::Make(0, 0);
|
||||
}
|
||||
return SkISize::Make(width, height);
|
||||
}
|
||||
|
||||
bool AndroidContextGL::Resize(const SkISize& size) {
|
||||
if (size == GetSize()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ClearCurrent();
|
||||
|
||||
TeardownSurface(environment_->Display(), surface_);
|
||||
|
||||
bool success = false;
|
||||
std::tie(success, surface_) =
|
||||
CreateSurface(environment_->Display(), config_, window_);
|
||||
|
||||
if (!success) {
|
||||
LOG(ERROR) << "Unable to create EGL window surface on resize.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
66
shell/platform/android/android_context_gl.h
Normal file
66
shell/platform/android/android_context_gl.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2016 The Chromium 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/shell/common/platform_view.h"
|
||||
#include "flutter/shell/platform/android/android_environment_gl.h"
|
||||
#include "flutter/shell/platform/android/android_native_window.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/ref_counted.h"
|
||||
#include "lib/ftl/memory/ref_ptr.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class AndroidContextGL : public ftl::RefCountedThreadSafe<AndroidContextGL> {
|
||||
private:
|
||||
/// Creates a window surface context tied to the window handle for on-screen
|
||||
/// rendering.
|
||||
// MakeRefCounted
|
||||
AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
|
||||
AndroidNativeWindow window,
|
||||
PlatformView::SurfaceConfig config,
|
||||
const AndroidContextGL* share_context = nullptr);
|
||||
|
||||
/// Creates a pbuffer surface context for offscreen rendering.
|
||||
// MakeRefCounted
|
||||
AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
|
||||
PlatformView::SurfaceConfig config,
|
||||
const AndroidContextGL* share_context = nullptr);
|
||||
|
||||
~AndroidContextGL();
|
||||
|
||||
public:
|
||||
ftl::RefPtr<AndroidEnvironmentGL> Environment() const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
bool MakeCurrent();
|
||||
|
||||
bool ClearCurrent();
|
||||
|
||||
bool SwapBuffers();
|
||||
|
||||
SkISize GetSize();
|
||||
|
||||
bool Resize(const SkISize& size);
|
||||
|
||||
private:
|
||||
ftl::RefPtr<AndroidEnvironmentGL> environment_;
|
||||
AndroidNativeWindow window_;
|
||||
EGLConfig config_;
|
||||
EGLSurface surface_;
|
||||
EGLContext context_;
|
||||
bool valid_;
|
||||
|
||||
FRIEND_MAKE_REF_COUNTED(AndroidContextGL);
|
||||
FRIEND_REF_COUNTED_THREAD_SAFE(AndroidContextGL);
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidContextGL);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_
|
||||
41
shell/platform/android/android_environment_gl.cc
Normal file
41
shell/platform/android/android_environment_gl.cc
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2016 The Chromium 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_environment_gl.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
AndroidEnvironmentGL::AndroidEnvironmentGL()
|
||||
: display_(EGL_NO_DISPLAY), valid_(false) {
|
||||
// Get the display.
|
||||
display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
|
||||
if (display_ == EGL_NO_DISPLAY) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the display connection.
|
||||
if (eglInitialize(display_, nullptr, nullptr) != EGL_TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
AndroidEnvironmentGL::~AndroidEnvironmentGL() {
|
||||
// Diconnect the display if valid.
|
||||
if (display_ != EGL_NO_CONTEXT) {
|
||||
eglTerminate(display_);
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidEnvironmentGL::IsValid() const {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
EGLDisplay AndroidEnvironmentGL::Display() const {
|
||||
return display_;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
40
shell/platform/android/android_environment_gl.h
Normal file
40
shell/platform/android/android_environment_gl.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2016 The Chromium 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_ENVIRONMENT_GL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_ENVIRONMENT_GL_H_
|
||||
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/ref_counted.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
namespace shell {
|
||||
|
||||
class AndroidEnvironmentGL
|
||||
: public ftl::RefCountedThreadSafe<AndroidEnvironmentGL> {
|
||||
private:
|
||||
// MakeRefCounted
|
||||
AndroidEnvironmentGL();
|
||||
|
||||
// MakeRefCounted
|
||||
~AndroidEnvironmentGL();
|
||||
|
||||
public:
|
||||
bool IsValid() const;
|
||||
|
||||
EGLDisplay Display() const;
|
||||
|
||||
private:
|
||||
EGLDisplay display_;
|
||||
bool valid_;
|
||||
|
||||
FRIEND_MAKE_REF_COUNTED(AndroidEnvironmentGL);
|
||||
FRIEND_REF_COUNTED_THREAD_SAFE(AndroidEnvironmentGL);
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidEnvironmentGL);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_ENVIRONMENT_GL_H_
|
||||
35
shell/platform/android/android_native_window.cc
Normal file
35
shell/platform/android/android_native_window.cc
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2016 The Chromium 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_native_window.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
AndroidNativeWindow::AndroidNativeWindow(Handle window) : window_(window) {
|
||||
if (window_ != nullptr) {
|
||||
ANativeWindow_acquire(window_);
|
||||
}
|
||||
}
|
||||
|
||||
AndroidNativeWindow::AndroidNativeWindow(AndroidNativeWindow&& o)
|
||||
: window_(o.window_) {
|
||||
o.window_ = nullptr;
|
||||
}
|
||||
|
||||
AndroidNativeWindow::~AndroidNativeWindow() {
|
||||
if (window_ != nullptr) {
|
||||
ANativeWindow_release(window_);
|
||||
window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidNativeWindow::IsValid() const {
|
||||
return window_ != nullptr;
|
||||
}
|
||||
|
||||
AndroidNativeWindow::Handle AndroidNativeWindow::handle() const {
|
||||
return window_;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
35
shell/platform/android/android_native_window.h
Normal file
35
shell/platform/android/android_native_window.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2016 The Chromium 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_NATIVE_WINDOW_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_NATIVE_WINDOW_H_
|
||||
|
||||
#include <android/native_window.h>
|
||||
#include "lib/ftl/macros.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class AndroidNativeWindow {
|
||||
public:
|
||||
using Handle = ANativeWindow*;
|
||||
|
||||
AndroidNativeWindow(Handle window);
|
||||
|
||||
AndroidNativeWindow(AndroidNativeWindow&& other);
|
||||
|
||||
~AndroidNativeWindow();
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
Handle handle() const;
|
||||
|
||||
private:
|
||||
Handle window_;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidNativeWindow);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_NATIVE_WINDOW_H_
|
||||
109
shell/platform/android/android_surface_gl.cc
Normal file
109
shell/platform/android/android_surface_gl.cc
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2016 The Chromium 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 <utility>
|
||||
#include "flutter/shell/platform/android/android_surface_gl.h"
|
||||
#include "lib/ftl/logging.h"
|
||||
#include "lib/ftl/memory/ref_ptr.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
static ftl::RefPtr<AndroidContextGL> GlobalResourceLoadingContext(
|
||||
PlatformView::SurfaceConfig offscreen_config) {
|
||||
// AndroidSurfaceGL instances are only ever created on the platform thread. So
|
||||
// there is no need to lock here.
|
||||
|
||||
static ftl::RefPtr<AndroidContextGL> global_context;
|
||||
|
||||
if (global_context) {
|
||||
return global_context;
|
||||
}
|
||||
|
||||
auto environment = ftl::MakeRefCounted<AndroidEnvironmentGL>();
|
||||
|
||||
if (!environment->IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO(chinmaygarde): We should check that the configurations are stable
|
||||
// across multiple invocations.
|
||||
|
||||
auto context =
|
||||
ftl::MakeRefCounted<AndroidContextGL>(environment, offscreen_config);
|
||||
|
||||
if (!context->IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
global_context = context;
|
||||
return global_context;
|
||||
}
|
||||
|
||||
AndroidSurfaceGL::AndroidSurfaceGL(AndroidNativeWindow window,
|
||||
PlatformView::SurfaceConfig onscreen_config,
|
||||
PlatformView::SurfaceConfig offscreen_config)
|
||||
: valid_(false) {
|
||||
// Acquire the offscreen context.
|
||||
offscreen_context_ = GlobalResourceLoadingContext(offscreen_config);
|
||||
|
||||
if (!offscreen_context_ || !offscreen_context_->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the onscreen context.
|
||||
onscreen_context_ = ftl::MakeRefCounted<AndroidContextGL>(
|
||||
offscreen_context_->Environment(), std::move(window), onscreen_config,
|
||||
offscreen_context_.get() /* sharegroup */);
|
||||
|
||||
if (!onscreen_context_->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// All done.
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
AndroidSurfaceGL::~AndroidSurfaceGL() = default;
|
||||
|
||||
bool AndroidSurfaceGL::IsValid() const {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
SkISize AndroidSurfaceGL::OnScreenSurfaceSize() const {
|
||||
FTL_DCHECK(valid_);
|
||||
return onscreen_context_->GetSize();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) const {
|
||||
FTL_DCHECK(valid_);
|
||||
return onscreen_context_->Resize(size);
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::GLOffscreenContextMakeCurrent() {
|
||||
FTL_DCHECK(valid_);
|
||||
return offscreen_context_->MakeCurrent();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::GLContextMakeCurrent() {
|
||||
FTL_DCHECK(valid_);
|
||||
return onscreen_context_->MakeCurrent();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::GLContextClearCurrent() {
|
||||
FTL_DCHECK(valid_);
|
||||
return onscreen_context_->ClearCurrent();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::GLContextPresent() {
|
||||
FTL_DCHECK(valid_);
|
||||
return onscreen_context_->SwapBuffers();
|
||||
}
|
||||
|
||||
intptr_t AndroidSurfaceGL::GLContextFBO() const {
|
||||
FTL_DCHECK(valid_);
|
||||
// The default window bound framebuffer on Android.
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
51
shell/platform/android/android_surface_gl.h
Normal file
51
shell/platform/android/android_surface_gl.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2016 The Chromium 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_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
|
||||
|
||||
#include <memory>
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "flutter/shell/platform/android/android_context_gl.h"
|
||||
#include "flutter/shell/platform/android/android_environment_gl.h"
|
||||
#include "flutter/shell/platform/android/android_native_window.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class AndroidSurfaceGL : public GPUSurfaceGLDelegate {
|
||||
public:
|
||||
AndroidSurfaceGL(AndroidNativeWindow window,
|
||||
PlatformView::SurfaceConfig onscreen_config,
|
||||
PlatformView::SurfaceConfig offscreen_config);
|
||||
|
||||
~AndroidSurfaceGL();
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
SkISize OnScreenSurfaceSize() const;
|
||||
|
||||
bool OnScreenSurfaceResize(const SkISize& size) const;
|
||||
|
||||
bool GLOffscreenContextMakeCurrent();
|
||||
|
||||
bool GLContextMakeCurrent() override;
|
||||
|
||||
bool GLContextClearCurrent() override;
|
||||
|
||||
bool GLContextPresent() override;
|
||||
|
||||
intptr_t GLContextFBO() const override;
|
||||
|
||||
private:
|
||||
ftl::RefPtr<AndroidContextGL> onscreen_context_;
|
||||
ftl::RefPtr<AndroidContextGL> offscreen_context_;
|
||||
bool valid_;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
|
||||
@ -4,380 +4,29 @@
|
||||
|
||||
#include "flutter/shell/platform/android/platform_view_android.h"
|
||||
|
||||
#include <android/input.h>
|
||||
#include <android/native_window.h>
|
||||
#include <android/native_window_jni.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/android/jni_android.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/location.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/flow/compositor_context.h"
|
||||
#include "flutter/runtime/dart_service_isolate.h"
|
||||
#include "flutter/shell/common/engine.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/gpu/gpu_rasterizer.h"
|
||||
#include "jni/FlutterView_jni.h"
|
||||
#include "lib/ftl/functional/wrap_lambda.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
using EGLResult = std::pair<bool, T>;
|
||||
|
||||
EGLDisplay g_display = EGL_NO_DISPLAY;
|
||||
EGLContext g_resource_context = EGL_NO_CONTEXT;
|
||||
EGLSurface g_resource_surface = EGL_NO_SURFACE;
|
||||
|
||||
void LogLastEGLError() {
|
||||
struct EGLNameErrorPair {
|
||||
const char* name;
|
||||
EGLint code;
|
||||
};
|
||||
|
||||
#define _EGL_ERROR_DESC(a) \
|
||||
{ #a, a }
|
||||
|
||||
const EGLNameErrorPair pairs[] = {
|
||||
_EGL_ERROR_DESC(EGL_SUCCESS),
|
||||
_EGL_ERROR_DESC(EGL_NOT_INITIALIZED),
|
||||
_EGL_ERROR_DESC(EGL_BAD_ACCESS),
|
||||
_EGL_ERROR_DESC(EGL_BAD_ALLOC),
|
||||
_EGL_ERROR_DESC(EGL_BAD_ATTRIBUTE),
|
||||
_EGL_ERROR_DESC(EGL_BAD_CONTEXT),
|
||||
_EGL_ERROR_DESC(EGL_BAD_CONFIG),
|
||||
_EGL_ERROR_DESC(EGL_BAD_CURRENT_SURFACE),
|
||||
_EGL_ERROR_DESC(EGL_BAD_DISPLAY),
|
||||
_EGL_ERROR_DESC(EGL_BAD_SURFACE),
|
||||
_EGL_ERROR_DESC(EGL_BAD_MATCH),
|
||||
_EGL_ERROR_DESC(EGL_BAD_PARAMETER),
|
||||
_EGL_ERROR_DESC(EGL_BAD_NATIVE_PIXMAP),
|
||||
_EGL_ERROR_DESC(EGL_BAD_NATIVE_WINDOW),
|
||||
_EGL_ERROR_DESC(EGL_CONTEXT_LOST),
|
||||
};
|
||||
|
||||
#undef _EGL_ERROR_DESC
|
||||
|
||||
const auto count = sizeof(pairs) / sizeof(EGLNameErrorPair);
|
||||
|
||||
EGLint last_error = eglGetError();
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (last_error == pairs[i].code) {
|
||||
DLOG(INFO) << "EGL Error: " << pairs[i].name << " (" << pairs[i].code
|
||||
<< ")";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DLOG(WARNING) << "Unknown EGL Error";
|
||||
}
|
||||
|
||||
EGLResult<EGLSurface> CreatePBufferSurface(EGLDisplay display,
|
||||
EGLConfig config) {
|
||||
// We only ever create pbuffer surfaces for background resource loading
|
||||
// contexts. We never bind the pbuffer to anything.
|
||||
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||
EGLSurface surface = eglCreatePbufferSurface(display, config, attribs);
|
||||
return {surface != EGL_NO_SURFACE, surface};
|
||||
}
|
||||
|
||||
EGLResult<EGLSurface> 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};
|
||||
}
|
||||
|
||||
EGLResult<EGLConfig> ChooseEGLConfiguration(
|
||||
EGLDisplay display,
|
||||
PlatformView::SurfaceConfig config) {
|
||||
EGLint attributes[] = {
|
||||
// clang-format off
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, config.red_bits,
|
||||
EGL_GREEN_SIZE, config.green_bits,
|
||||
EGL_BLUE_SIZE, config.blue_bits,
|
||||
EGL_ALPHA_SIZE, config.alpha_bits,
|
||||
EGL_DEPTH_SIZE, config.depth_bits,
|
||||
EGL_STENCIL_SIZE, config.stencil_bits,
|
||||
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};
|
||||
}
|
||||
|
||||
void InitGlobal() {
|
||||
// Get the display.
|
||||
g_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (g_display == EGL_NO_DISPLAY)
|
||||
return;
|
||||
|
||||
// Initialize the display connection.
|
||||
if (eglInitialize(g_display, nullptr, nullptr) != EGL_TRUE)
|
||||
return;
|
||||
|
||||
bool success;
|
||||
|
||||
// Choose a config for resource loading.
|
||||
PlatformView::SurfaceConfig resource_config;
|
||||
resource_config.stencil_bits = 0;
|
||||
|
||||
EGLConfig resource_egl_config;
|
||||
std::tie(success, resource_egl_config) =
|
||||
ChooseEGLConfiguration(g_display, resource_config);
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not choose a resource configuration.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a pbuffer surface for the configuration for resource loading.
|
||||
std::tie(success, g_resource_surface) =
|
||||
CreatePBufferSurface(g_display, resource_egl_config);
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not create the pbuffer surface for resource loading.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a resource context for the configuration.
|
||||
std::tie(success, g_resource_context) =
|
||||
CreateContext(g_display, resource_egl_config);
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not create the resource context.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class AndroidNativeWindow {
|
||||
public:
|
||||
using Handle = ANativeWindow*;
|
||||
|
||||
explicit AndroidNativeWindow(Handle window) : window_(window) {
|
||||
if (window_ != nullptr) {
|
||||
ANativeWindow_acquire(window_);
|
||||
}
|
||||
}
|
||||
|
||||
~AndroidNativeWindow() {
|
||||
if (window_ != nullptr) {
|
||||
ANativeWindow_release(window_);
|
||||
window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const { return window_ != nullptr; }
|
||||
|
||||
Handle handle() const { return window_; }
|
||||
|
||||
private:
|
||||
Handle window_;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidNativeWindow);
|
||||
};
|
||||
|
||||
class AndroidGLContext {
|
||||
public:
|
||||
explicit AndroidGLContext(AndroidNativeWindow::Handle window_handle,
|
||||
PlatformView::SurfaceConfig config)
|
||||
: window_(window_handle),
|
||||
config_(nullptr),
|
||||
surface_(EGL_NO_SURFACE),
|
||||
context_(EGL_NO_CONTEXT),
|
||||
valid_(false) {
|
||||
if (!window_.IsValid()) {
|
||||
// We always require a valid window since we are only going to deal
|
||||
// with window surfaces.
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Choose a valid configuration.
|
||||
|
||||
std::tie(success, config_) = ChooseEGLConfiguration(g_display, config);
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not choose a window configuration.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a window surface for the configuration.
|
||||
|
||||
std::tie(success, surface_) =
|
||||
CreateWindowSurface(g_display, config_, window_.handle());
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not create the window surface.";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a context for the configuration.
|
||||
|
||||
std::tie(success, context_) =
|
||||
CreateContext(g_display, config_, g_resource_context);
|
||||
|
||||
if (!success) {
|
||||
DLOG(INFO) << "Could not create the main rendering context";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
// All done!
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
~AndroidGLContext() {
|
||||
if (!TeardownContext(g_display, context_)) {
|
||||
LOG(INFO)
|
||||
<< "Could not tear down the EGL context. Possible resource leak.";
|
||||
LogLastEGLError();
|
||||
}
|
||||
|
||||
if (!TeardownSurface(g_display, surface_)) {
|
||||
LOG(INFO)
|
||||
<< "Could not tear down the EGL surface. Possible resource leak.";
|
||||
LogLastEGLError();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const { return valid_; }
|
||||
|
||||
bool ContextMakeCurrent() {
|
||||
if (eglMakeCurrent(g_display, surface_, surface_, context_) != EGL_TRUE) {
|
||||
LOG(INFO) << "Could not make the context current";
|
||||
LogLastEGLError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SwapBuffers() { return eglSwapBuffers(g_display, surface_); }
|
||||
|
||||
SkISize GetSize() {
|
||||
EGLint width = 0;
|
||||
EGLint height = 0;
|
||||
if (!eglQuerySurface(g_display, surface_, EGL_WIDTH, &width) ||
|
||||
!eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)) {
|
||||
LOG(ERROR) << "Unable to query EGL surface size";
|
||||
LogLastEGLError();
|
||||
return SkISize::Make(0, 0);
|
||||
}
|
||||
return SkISize::Make(width, height);
|
||||
}
|
||||
|
||||
void Resize(const SkISize& size) {
|
||||
eglMakeCurrent(g_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
TeardownSurface(g_display, surface_);
|
||||
|
||||
bool success;
|
||||
std::tie(success, surface_) =
|
||||
CreateWindowSurface(g_display, config_, window_.handle());
|
||||
if (!success) {
|
||||
LOG(ERROR) << "Unable to create EGL window surface";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
AndroidNativeWindow window_;
|
||||
EGLConfig config_;
|
||||
EGLSurface surface_;
|
||||
EGLContext context_;
|
||||
|
||||
bool valid_;
|
||||
|
||||
static bool TeardownContext(EGLDisplay display, EGLContext context) {
|
||||
if (context != EGL_NO_CONTEXT) {
|
||||
return eglDestroyContext(display, context) == EGL_TRUE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TeardownSurface(EGLDisplay display, EGLSurface surface) {
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
return eglDestroySurface(display, surface) == EGL_TRUE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static EGLResult<EGLSurface> CreateWindowSurface(
|
||||
EGLDisplay display,
|
||||
EGLConfig config,
|
||||
AndroidNativeWindow::Handle window_handle) {
|
||||
// The configurations are only required when dealing with extensions or VG.
|
||||
// We do neither.
|
||||
EGLSurface surface = eglCreateWindowSurface(
|
||||
display, config, reinterpret_cast<EGLNativeWindowType>(window_handle),
|
||||
nullptr);
|
||||
return {surface != EGL_NO_SURFACE, surface};
|
||||
}
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidGLContext);
|
||||
};
|
||||
|
||||
static jlong Attach(JNIEnv* env,
|
||||
jclass clazz,
|
||||
jint skyEngineHandle,
|
||||
jobject flutterView) {
|
||||
PlatformViewAndroid* view = new PlatformViewAndroid();
|
||||
view->ConnectToEngine(mojo::InterfaceRequest<sky::SkyEngine>(
|
||||
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(skyEngineHandle))));
|
||||
|
||||
// Create a weak reference to the flutterView Java object so that we can make
|
||||
// calls into it later.
|
||||
view->set_flutter_view(JavaObjectWeakGlobalRef(env, flutterView));
|
||||
return reinterpret_cast<jlong>(view);
|
||||
}
|
||||
|
||||
jint GetObservatoryPort(JNIEnv* env, jclass clazz) {
|
||||
return blink::DartServiceIsolate::GetObservatoryPort();
|
||||
}
|
||||
|
||||
// static
|
||||
bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
return RegisterNativesImpl(env);
|
||||
}
|
||||
|
||||
PlatformViewAndroid::PlatformViewAndroid() : weak_factory_(this) {
|
||||
// If this is the first PlatformView, then intiialize EGL and set up
|
||||
// the resource context.
|
||||
if (g_display == EGL_NO_DISPLAY)
|
||||
InitGlobal();
|
||||
}
|
||||
PlatformViewAndroid::PlatformViewAndroid()
|
||||
: PlatformView(std::make_unique<GPURasterizer>()), weak_factory_(this) {}
|
||||
|
||||
PlatformViewAndroid::~PlatformViewAndroid() = default;
|
||||
|
||||
@ -389,26 +38,43 @@ void PlatformViewAndroid::Detach(JNIEnv* env, jobject obj) {
|
||||
void PlatformViewAndroid::SurfaceCreated(JNIEnv* env,
|
||||
jobject obj,
|
||||
jobject jsurface) {
|
||||
// Note: This ensures that any local references used by
|
||||
// Note: This frame ensures that any local references used by
|
||||
// ANativeWindow_fromSurface are released immediately. This is needed as a
|
||||
// workaround for https://code.google.com/p/android/issues/detail?id=68174
|
||||
{
|
||||
base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
|
||||
ANativeWindow* window = ANativeWindow_fromSurface(env, jsurface);
|
||||
std::unique_ptr<AndroidGLContext> context(
|
||||
new AndroidGLContext(window, surface_config_));
|
||||
if (context->IsValid()) {
|
||||
context_ = std::move(context);
|
||||
}
|
||||
ANativeWindow_release(window);
|
||||
base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
|
||||
ANativeWindow* window = ANativeWindow_fromSurface(env, jsurface);
|
||||
|
||||
// Use the default onscreen configuration.
|
||||
PlatformView::SurfaceConfig onscreen_config;
|
||||
|
||||
// The offscreen config is the same as the default except we know we don't
|
||||
// need the stencil buffer.
|
||||
PlatformView::SurfaceConfig offscreen_config;
|
||||
offscreen_config.stencil_bits = 0;
|
||||
|
||||
auto surface = std::make_unique<AndroidSurfaceGL>(window, onscreen_config,
|
||||
offscreen_config);
|
||||
|
||||
if (surface->IsValid()) {
|
||||
surface_gl_ = std::move(surface);
|
||||
} else {
|
||||
LOG(INFO) << "Could not create the OpenGL Android Surface.";
|
||||
}
|
||||
|
||||
ANativeWindow_release(window);
|
||||
}
|
||||
|
||||
void PlatformViewAndroid::SurfaceChanged(JNIEnv* env,
|
||||
jobject obj,
|
||||
jint backgroundColor) {
|
||||
NotifyCreated(
|
||||
[this, backgroundColor] { config_.rasterizer->Clear(backgroundColor); });
|
||||
if (!surface_gl_) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto surface = std::make_unique<GPUSurfaceGL>(surface_gl_.get());
|
||||
NotifyCreated(std::move(surface), [this, backgroundColor] {
|
||||
config_.rasterizer->Clear(backgroundColor, GetSize());
|
||||
});
|
||||
SetupResourceContextOnIOThread();
|
||||
UpdateThreadPriorities();
|
||||
}
|
||||
@ -441,9 +107,9 @@ void PlatformViewAndroid::DispatchPointerDataPacket(JNIEnv* env,
|
||||
}
|
||||
|
||||
void PlatformViewAndroid::ReleaseSurface() {
|
||||
if (context_) {
|
||||
if (surface_gl_) {
|
||||
NotifyDestroyed();
|
||||
context_ = nullptr;
|
||||
surface_gl_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,36 +117,18 @@ ftl::WeakPtr<shell::PlatformView> PlatformViewAndroid::GetWeakViewPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
uint64_t PlatformViewAndroid::DefaultFramebuffer() const {
|
||||
// FBO 0 is the default window bound framebuffer on Android.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PlatformViewAndroid::ContextMakeCurrent() {
|
||||
return context_ != nullptr ? context_->ContextMakeCurrent() : false;
|
||||
}
|
||||
|
||||
bool PlatformViewAndroid::ResourceContextMakeCurrent() {
|
||||
if (eglMakeCurrent(g_display, g_resource_surface, g_resource_surface,
|
||||
g_resource_context) != EGL_TRUE) {
|
||||
LOG(INFO) << "Could not make the resource context current";
|
||||
LogLastEGLError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewAndroid::SwapBuffers() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewAndroid::SwapBuffers");
|
||||
return context_ != nullptr ? context_->SwapBuffers() : false;
|
||||
return surface_gl_ ? surface_gl_->GLOffscreenContextMakeCurrent() : false;
|
||||
}
|
||||
|
||||
SkISize PlatformViewAndroid::GetSize() {
|
||||
return context_->GetSize();
|
||||
return surface_gl_ ? surface_gl_->OnScreenSurfaceSize() : SkISize::Make(0, 0);
|
||||
}
|
||||
|
||||
void PlatformViewAndroid::Resize(const SkISize& size) {
|
||||
context_->Resize(size);
|
||||
if (surface_gl_) {
|
||||
surface_gl_->OnScreenSurfaceResize(size);
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformViewAndroid::RunFromSource(const std::string& main,
|
||||
@ -625,4 +273,26 @@ void PlatformViewAndroid::GetBitmapGpuTask(ftl::AutoResetWaitableEvent* latch,
|
||||
latch->Signal();
|
||||
}
|
||||
|
||||
jint GetObservatoryPort(JNIEnv* env, jclass clazz) {
|
||||
return blink::DartServiceIsolate::GetObservatoryPort();
|
||||
}
|
||||
|
||||
bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
return RegisterNativesImpl(env);
|
||||
}
|
||||
|
||||
static jlong Attach(JNIEnv* env,
|
||||
jclass clazz,
|
||||
jint skyEngineHandle,
|
||||
jobject flutterView) {
|
||||
PlatformViewAndroid* view = new PlatformViewAndroid();
|
||||
view->ConnectToEngine(mojo::InterfaceRequest<sky::SkyEngine>(
|
||||
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(skyEngineHandle))));
|
||||
|
||||
// Create a weak reference to the flutterView Java object so that we can make
|
||||
// calls into it later.
|
||||
view->set_flutter_view(JavaObjectWeakGlobalRef(env, flutterView));
|
||||
return reinterpret_cast<jlong>(view);
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
|
||||
@ -7,16 +7,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <memory>
|
||||
#include "base/android/jni_android.h"
|
||||
#include "base/android/jni_weak_ref.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
#include "lib/ftl/synchronization/waitable_event.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/platform/android/android_surface_gl.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
class AndroidGLContext;
|
||||
|
||||
class PlatformViewAndroid : public PlatformView {
|
||||
public:
|
||||
static bool Register(JNIEnv* env);
|
||||
@ -33,7 +32,9 @@ class PlatformViewAndroid : public PlatformView {
|
||||
|
||||
void SurfaceDestroyed(JNIEnv* env, jobject obj);
|
||||
|
||||
void DispatchPointerDataPacket(JNIEnv* env, jobject obj, jobject buffer,
|
||||
void DispatchPointerDataPacket(JNIEnv* env,
|
||||
jobject obj,
|
||||
jobject buffer,
|
||||
jint position);
|
||||
|
||||
base::android::ScopedJavaLocalRef<jobject> GetBitmap(JNIEnv* env,
|
||||
@ -41,14 +42,8 @@ class PlatformViewAndroid : public PlatformView {
|
||||
|
||||
ftl::WeakPtr<shell::PlatformView> GetWeakViewPtr() override;
|
||||
|
||||
uint64_t DefaultFramebuffer() const override;
|
||||
|
||||
bool ContextMakeCurrent() override;
|
||||
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
|
||||
bool SwapBuffers() override;
|
||||
|
||||
virtual SkISize GetSize();
|
||||
|
||||
virtual void Resize(const SkISize& size);
|
||||
@ -62,18 +57,18 @@ class PlatformViewAndroid : public PlatformView {
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<AndroidSurfaceGL> surface_gl_;
|
||||
JavaObjectWeakGlobalRef flutter_view_;
|
||||
ftl::WeakPtrFactory<PlatformViewAndroid> weak_factory_;
|
||||
|
||||
void UpdateThreadPriorities();
|
||||
|
||||
void ReleaseSurface();
|
||||
|
||||
void GetBitmapGpuTask(ftl::AutoResetWaitableEvent* latch,
|
||||
jobject* pixels_out,
|
||||
SkISize* size_out);
|
||||
|
||||
std::unique_ptr<AndroidGLContext> context_;
|
||||
ftl::WeakPtrFactory<PlatformViewAndroid> weak_factory_;
|
||||
JavaObjectWeakGlobalRef flutter_view_;
|
||||
|
||||
void UpdateThreadPriorities();
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(PlatformViewAndroid);
|
||||
};
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ source_set("mac_desktop_platform") {
|
||||
"//base",
|
||||
"//flutter/common",
|
||||
"//flutter/shell/common",
|
||||
"//flutter/shell/gpu",
|
||||
"//flutter/shell/platform/darwin/common",
|
||||
"//flutter/shell/testing",
|
||||
"//flutter/skia",
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
|
||||
@class NSOpenGLView;
|
||||
@ -14,7 +15,7 @@
|
||||
|
||||
namespace shell {
|
||||
|
||||
class PlatformViewMac : public PlatformView {
|
||||
class PlatformViewMac : public PlatformView, public GPUSurfaceGLDelegate {
|
||||
public:
|
||||
PlatformViewMac(NSOpenGLView* gl_view);
|
||||
|
||||
@ -26,14 +27,16 @@ class PlatformViewMac : public PlatformView {
|
||||
|
||||
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
|
||||
|
||||
uint64_t DefaultFramebuffer() const override;
|
||||
bool GLContextMakeCurrent() override;
|
||||
|
||||
bool ContextMakeCurrent() override;
|
||||
bool GLContextClearCurrent() override;
|
||||
|
||||
bool GLContextPresent() override;
|
||||
|
||||
intptr_t GLContextFBO() const override;
|
||||
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
|
||||
bool SwapBuffers() override;
|
||||
|
||||
void RunFromSource(const std::string& main,
|
||||
const std::string& packages,
|
||||
const std::string& assets_directory) override;
|
||||
|
||||
@ -4,12 +4,13 @@
|
||||
|
||||
#include "flutter/shell/platform/darwin/desktop/platform_view_mac.h"
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "flutter/shell/common/switches.h"
|
||||
#include "flutter/shell/gpu/gpu_rasterizer.h"
|
||||
#include "flutter/shell/platform/darwin/common/platform_mac.h"
|
||||
#include "flutter/shell/platform/darwin/common/platform_service_provider.h"
|
||||
#include "flutter/shell/platform/darwin/common/view_service_provider.h"
|
||||
@ -18,7 +19,8 @@
|
||||
namespace shell {
|
||||
|
||||
PlatformViewMac::PlatformViewMac(NSOpenGLView* gl_view)
|
||||
: opengl_view_([gl_view retain]),
|
||||
: PlatformView(std::make_unique<GPURasterizer>()),
|
||||
opengl_view_([gl_view retain]),
|
||||
resource_loading_context_([[NSOpenGLContext alloc]
|
||||
initWithFormat:gl_view.pixelFormat
|
||||
shareContext:gl_view.openGLContext]),
|
||||
@ -95,12 +97,13 @@ ftl::WeakPtr<PlatformView> PlatformViewMac::GetWeakViewPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
uint64_t PlatformViewMac::DefaultFramebuffer() const {
|
||||
intptr_t PlatformViewMac::GLContextFBO() const {
|
||||
// Default window bound framebuffer FBO 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PlatformViewMac::ContextMakeCurrent() {
|
||||
bool PlatformViewMac::GLContextMakeCurrent() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewMac::GLContextMakeCurrent");
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@ -109,6 +112,26 @@ bool PlatformViewMac::ContextMakeCurrent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewMac::GLContextClearCurrent() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewMac::GLContextClearCurrent");
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewMac::GLContextPresent() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewMac::GLContextPresent");
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[opengl_view_.get().openGLContext flushBuffer];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewMac::ResourceContextMakeCurrent() {
|
||||
NSOpenGLContext* context = resource_loading_context_.get();
|
||||
|
||||
@ -120,17 +143,6 @@ bool PlatformViewMac::ResourceContextMakeCurrent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewMac::SwapBuffers() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewMac::SwapBuffers");
|
||||
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[opengl_view_.get().openGLContext flushBuffer];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewMac::IsValid() const {
|
||||
if (opengl_view_ == nullptr) {
|
||||
return false;
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
|
||||
#import "sky_window.h"
|
||||
|
||||
#include "lib/ftl/time/time_delta.h"
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "flutter/shell/platform/darwin/desktop/platform_view_mac.h"
|
||||
|
||||
@interface SkyWindow ()<NSWindowDelegate>
|
||||
@ -58,7 +58,8 @@ static inline blink::PointerData::Change PointerChangeFromNSEventPhase(
|
||||
|
||||
_platformView.reset(new shell::PlatformViewMac(self.renderSurface));
|
||||
_platformView->SetupResourceContextOnIOThread();
|
||||
_platformView->NotifyCreated();
|
||||
_platformView->NotifyCreated(
|
||||
std::make_unique<shell::GPUSurfaceGL>(_platformView.get()));
|
||||
}
|
||||
|
||||
// TODO(eseidel): This does not belong in sky_window!
|
||||
|
||||
@ -9,14 +9,16 @@
|
||||
#include "base/mac/scoped_block.h"
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "lib/ftl/time/time_delta.h"
|
||||
#include "lib/ftl/functional/wrap_lambda.h"
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/services/platform/ios/system_chrome_impl.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
|
||||
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
|
||||
#include "flutter/shell/gpu/gpu_rasterizer.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "flutter/shell/platform/darwin/common/platform_mac.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h"
|
||||
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
|
||||
#include "lib/ftl/functional/wrap_lambda.h"
|
||||
#include "lib/ftl/time/time_delta.h"
|
||||
|
||||
@interface FlutterViewController ()<UIAlertViewDelegate>
|
||||
@end
|
||||
@ -198,7 +200,8 @@ enum MapperPhase {
|
||||
Removed,
|
||||
};
|
||||
|
||||
using PointerChangeMapperPhase = std::pair<blink::PointerData::Change, MapperPhase>;
|
||||
using PointerChangeMapperPhase =
|
||||
std::pair<blink::PointerData::Change, MapperPhase>;
|
||||
static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(
|
||||
UITouchPhase phase) {
|
||||
switch (phase) {
|
||||
@ -266,12 +269,11 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(
|
||||
}
|
||||
|
||||
blink::Threads::UI()->PostTask(ftl::WrapLambda([
|
||||
engine = _platformView->engine().GetWeakPtr(),
|
||||
packet = std::move(packet)
|
||||
] {
|
||||
if (engine.get())
|
||||
engine->DispatchPointerDataPacket(*packet);
|
||||
}));
|
||||
engine = _platformView->engine().GetWeakPtr(), packet = std::move(packet)
|
||||
] {
|
||||
if (engine.get())
|
||||
engine->DispatchPointerDataPacket(*packet);
|
||||
}));
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
@ -385,7 +387,8 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(
|
||||
CHECK(_platformView != nullptr);
|
||||
|
||||
if (appeared) {
|
||||
_platformView->NotifyCreated();
|
||||
_platformView->NotifyCreated(
|
||||
std::make_unique<shell::GPUSurfaceGL>(_platformView.get()));
|
||||
} else {
|
||||
_platformView->NotifyDestroyed();
|
||||
}
|
||||
|
||||
@ -7,13 +7,14 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "flutter/services/platform/app_messages.mojom.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/application_messages_impl.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "lib/ftl/macros.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
|
||||
@class CAEAGLLayer;
|
||||
@class UIView;
|
||||
@ -22,7 +23,7 @@ namespace shell {
|
||||
|
||||
class IOSGLContext;
|
||||
|
||||
class PlatformViewIOS : public PlatformView {
|
||||
class PlatformViewIOS : public PlatformView, public GPUSurfaceGLDelegate {
|
||||
public:
|
||||
explicit PlatformViewIOS(CAEAGLLayer* layer);
|
||||
|
||||
@ -40,13 +41,15 @@ class PlatformViewIOS : public PlatformView {
|
||||
|
||||
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
|
||||
|
||||
uint64_t DefaultFramebuffer() const override;
|
||||
|
||||
bool ContextMakeCurrent() override;
|
||||
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
|
||||
bool SwapBuffers() override;
|
||||
bool GLContextMakeCurrent() override;
|
||||
|
||||
bool GLContextClearCurrent() override;
|
||||
|
||||
bool GLContextPresent() override;
|
||||
|
||||
intptr_t GLContextFBO() const override;
|
||||
|
||||
void RunFromSource(const std::string& main,
|
||||
const std::string& packages,
|
||||
|
||||
@ -4,18 +4,17 @@
|
||||
|
||||
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
|
||||
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "flutter/shell/platform/darwin/common/view_service_provider.h"
|
||||
#include "flutter/shell/platform/darwin/common/platform_service_provider.h"
|
||||
#include "flutter/sky/engine/wtf/MakeUnique.h"
|
||||
#include "lib/ftl/synchronization/waitable_event.h"
|
||||
#include "mojo/public/cpp/application/connect.h"
|
||||
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <OpenGLES/ES2/gl.h>
|
||||
#import <OpenGLES/ES2/glext.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <QuartzCore/CAEAGLLayer.h>
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "flutter/shell/gpu/gpu_rasterizer.h"
|
||||
#include "flutter/shell/platform/darwin/common/platform_service_provider.h"
|
||||
#include "flutter/shell/platform/darwin/common/view_service_provider.h"
|
||||
#include "lib/ftl/synchronization/waitable_event.h"
|
||||
#include "mojo/public/cpp/application/connect.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
@ -273,7 +272,8 @@ class IOSGLContext {
|
||||
};
|
||||
|
||||
PlatformViewIOS::PlatformViewIOS(CAEAGLLayer* layer)
|
||||
: context_(WTF::MakeUnique<IOSGLContext>(surface_config_, layer)),
|
||||
: PlatformView(std::make_unique<GPURasterizer>()),
|
||||
context_(std::make_unique<IOSGLContext>(surface_config_, layer)),
|
||||
weak_factory_(this) {
|
||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
|
||||
NSUserDomainMask, YES);
|
||||
@ -351,20 +351,25 @@ ftl::WeakPtr<PlatformView> PlatformViewIOS::GetWeakViewPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
uint64_t PlatformViewIOS::DefaultFramebuffer() const {
|
||||
return context_ != nullptr ? context_->framebuffer() : GL_NONE;
|
||||
}
|
||||
|
||||
bool PlatformViewIOS::ContextMakeCurrent() {
|
||||
return context_ != nullptr ? context_->MakeCurrent() : false;
|
||||
}
|
||||
|
||||
bool PlatformViewIOS::ResourceContextMakeCurrent() {
|
||||
return context_ != nullptr ? context_->ResourceMakeCurrent() : false;
|
||||
}
|
||||
|
||||
bool PlatformViewIOS::SwapBuffers() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewIOS::SwapBuffers");
|
||||
intptr_t PlatformViewIOS::GLContextFBO() const {
|
||||
return context_ != nullptr ? context_->framebuffer() : GL_NONE;
|
||||
}
|
||||
|
||||
bool PlatformViewIOS::GLContextMakeCurrent() {
|
||||
return context_ != nullptr ? context_->MakeCurrent() : false;
|
||||
}
|
||||
|
||||
bool PlatformViewIOS::GLContextClearCurrent() {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewIOS::GLContextPresent() {
|
||||
TRACE_EVENT0("flutter", "PlatformViewIOS::GLContextPresent");
|
||||
return context_ != nullptr ? context_->PresentRenderBuffer() : false;
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/common/switches.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "flutter/shell/platform/linux/message_pump_glfw.h"
|
||||
#include "flutter/shell/platform/linux/platform_view_glfw.h"
|
||||
#include "flutter/shell/testing/testing.h"
|
||||
@ -66,7 +67,8 @@ int RunInteractive() {
|
||||
|
||||
platform_view->ConnectToEngineAndSetupServices();
|
||||
|
||||
platform_view->NotifyCreated();
|
||||
platform_view->NotifyCreated(
|
||||
std::make_unique<shell::GPUSurfaceGL>(platform_view.get()));
|
||||
|
||||
if (IsDartFile(bundle_path)) {
|
||||
// Load directly from source.
|
||||
|
||||
@ -3,11 +3,10 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/linux/platform_view_glfw.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/shell/platform/linux/glfw_service_provider.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/shell/gpu/gpu_rasterizer.h"
|
||||
#include "flutter/shell/platform/linux/glfw_service_provider.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
@ -16,7 +15,11 @@ inline PlatformViewGLFW* ToPlatformView(GLFWwindow* window) {
|
||||
}
|
||||
|
||||
PlatformViewGLFW::PlatformViewGLFW()
|
||||
: valid_(false), glfw_window_(nullptr), buttons_(0), weak_factory_(this) {
|
||||
: PlatformView(std::make_unique<GPURasterizer>()),
|
||||
valid_(false),
|
||||
glfw_window_(nullptr),
|
||||
buttons_(0),
|
||||
weak_factory_(this) {
|
||||
if (!glfwInit()) {
|
||||
return;
|
||||
}
|
||||
@ -79,22 +82,27 @@ ftl::WeakPtr<PlatformView> PlatformViewGLFW::GetWeakViewPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
uint64_t PlatformViewGLFW::DefaultFramebuffer() const {
|
||||
intptr_t PlatformViewGLFW::GLContextFBO() const {
|
||||
// The default window bound FBO.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PlatformViewGLFW::ContextMakeCurrent() {
|
||||
bool PlatformViewGLFW::GLContextMakeCurrent() {
|
||||
glfwMakeContextCurrent(glfw_window_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewGLFW::GLContextClearCurrent() {
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlatformViewGLFW::ResourceContextMakeCurrent() {
|
||||
// Resource loading contexts are not supported on this platform.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformViewGLFW::SwapBuffers() {
|
||||
bool PlatformViewGLFW::GLContextPresent() {
|
||||
glfwSwapBuffers(glfw_window_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6,15 +6,15 @@
|
||||
#define SHELL_PLATFORM_GLFW_PLATFORM_VIEW_GLFW_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl.h"
|
||||
#include "lib/ftl/memory/weak_ptr.h"
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
namespace shell {
|
||||
|
||||
class PlatformViewGLFW : public PlatformView {
|
||||
class PlatformViewGLFW : public PlatformView, public GPUSurfaceGLDelegate {
|
||||
public:
|
||||
PlatformViewGLFW();
|
||||
|
||||
@ -28,13 +28,15 @@ class PlatformViewGLFW : public PlatformView {
|
||||
|
||||
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
|
||||
|
||||
uint64_t DefaultFramebuffer() const override;
|
||||
|
||||
bool ContextMakeCurrent() override;
|
||||
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
|
||||
bool SwapBuffers() override;
|
||||
bool GLContextMakeCurrent() override;
|
||||
|
||||
bool GLContextClearCurrent() override;
|
||||
|
||||
bool GLContextPresent() override;
|
||||
|
||||
intptr_t GLContextFBO() const override;
|
||||
|
||||
void RunFromSource(const std::string& main,
|
||||
const std::string& packages,
|
||||
|
||||
@ -5,10 +5,13 @@
|
||||
#include "flutter/shell/testing/platform_view_test.h"
|
||||
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/common/null_rasterizer.h"
|
||||
|
||||
namespace shell {
|
||||
|
||||
PlatformViewTest::PlatformViewTest() : weak_factory_(this) {}
|
||||
PlatformViewTest::PlatformViewTest()
|
||||
: PlatformView(std::unique_ptr<Rasterizer>(new NullRasterizer())),
|
||||
weak_factory_(this) {}
|
||||
|
||||
PlatformViewTest::~PlatformViewTest() = default;
|
||||
|
||||
@ -16,22 +19,10 @@ ftl::WeakPtr<PlatformView> PlatformViewTest::GetWeakViewPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
uint64_t PlatformViewTest::DefaultFramebuffer() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PlatformViewTest::ContextMakeCurrent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformViewTest::ResourceContextMakeCurrent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformViewTest::SwapBuffers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlatformViewTest::RunFromSource(const std::string& main,
|
||||
const std::string& packages,
|
||||
const std::string& assets_directory) {}
|
||||
|
||||
@ -21,14 +21,8 @@ class PlatformViewTest : public PlatformView {
|
||||
|
||||
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
|
||||
|
||||
uint64_t DefaultFramebuffer() const override;
|
||||
|
||||
bool ContextMakeCurrent() override;
|
||||
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
|
||||
bool SwapBuffers() override;
|
||||
|
||||
void RunFromSource(const std::string& main,
|
||||
const std::string& packages,
|
||||
const std::string& assets_directory) override;
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
source_set("synchronization") {
|
||||
sources = [
|
||||
"debug_thread_checker.h",
|
||||
"pipeline.cc",
|
||||
"pipeline.h",
|
||||
"semaphore.cc",
|
||||
|
||||
25
synchronization/debug_thread_checker.h
Normal file
25
synchronization/debug_thread_checker.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2016 The Chromium 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_SYNCHRONIZATION_DEBUG_THREAD_CHECKER_H_
|
||||
#define FLUTTER_SYNCHRONIZATION_DEBUG_THREAD_CHECKER_H_
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
#include <pthread.h>
|
||||
#include "lib/ftl/synchronization/thread_checker.h"
|
||||
|
||||
#define FLUTTER_THREAD_CHECKER_DECLARE(x) ::ftl::ThreadChecker x;
|
||||
|
||||
#define FLUTTER_THREAD_CHECKER_CHECK(x) FTL_CHECK(x.IsCreationThreadCurrent());
|
||||
|
||||
#else // NDEBUG
|
||||
|
||||
#define FLUTTER_THREAD_CHECKER_DECLARE(x)
|
||||
|
||||
#define FLUTTER_THREAD_CHECKER_CHECK(x)
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif // FLUTTER_SYNCHRONIZATION_DEBUG_THREAD_CHECKER_H_
|
||||
Loading…
x
Reference in New Issue
Block a user