Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 17 additions & 21 deletions shell/gpu/gpu_surface_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,13 @@ static const int kGrCacheMaxCount = 8192;
// system channel.
static const size_t kGrCacheMaxByteSize = 24 * (1 << 20);

GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
: delegate_(delegate),
render_to_surface_(render_to_surface),
weak_factory_(this) {
auto context_switch = delegate_->GLContextMakeCurrent();
sk_sp<GrDirectContext> GPUSurfaceGL::MakeGLContext(
GPUSurfaceGLDelegate* delegate) {
auto context_switch = delegate->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to setup the gr context.";
return;
return nullptr;
}

GrContextOptions options;
Expand All @@ -64,39 +61,39 @@ GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
// TODO(goderbauer): remove option when skbug.com/7523 is fixed.
// A similar work-around is also used in shell/common/io_manager.cc.
options.fDisableGpuYUVConversion = true;
auto context = GrDirectContext::MakeGL(delegate->GetGLInterface(), options);

auto context = GrDirectContext::MakeGL(delegate_->GetGLInterface(), options);

if (context == nullptr) {
if (!context) {
FML_LOG(ERROR) << "Failed to setup Skia Gr context.";
return;
return nullptr;
}

context_ = std::move(context);

context_->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);

context_owner_ = true;

valid_ = true;
context->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);

std::vector<PersistentCache::SkSLCache> caches =
PersistentCache::GetCacheForProcess()->LoadSkSLs();
int compiled_count = 0;
for (const auto& cache : caches) {
compiled_count += context_->precompileShader(*cache.first, *cache.second);
compiled_count += context->precompileShader(*cache.first, *cache.second);
}
FML_LOG(INFO) << "Found " << caches.size() << " SkSL shaders; precompiled "
<< compiled_count;

delegate_->GLContextClearCurrent();
return context;
}

GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
: GPUSurfaceGL(MakeGLContext(delegate), delegate, render_to_surface) {
context_owner_ = true;
}

GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrDirectContext> gr_context,
GPUSurfaceGLDelegate* delegate,
bool render_to_surface)
: delegate_(delegate),
context_(gr_context),
context_owner_(false),
render_to_surface_(render_to_surface),
weak_factory_(this) {
auto context_switch = delegate_->GLContextMakeCurrent();
Expand All @@ -109,7 +106,6 @@ GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrDirectContext> gr_context,
delegate_->GLContextClearCurrent();

valid_ = true;
context_owner_ = false;
}

GPUSurfaceGL::~GPUSurfaceGL() {
Expand Down
8 changes: 5 additions & 3 deletions shell/gpu/gpu_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace flutter {

class GPUSurfaceGL : public Surface {
public:
static sk_sp<GrDirectContext> MakeGLContext(GPUSurfaceGLDelegate* delegate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible, can we add some consistency between the metal version and this one? In metal, the IOSContextMetal just decides to make a GrDirectContext the way it wants without asking anyone. Here, it seems like the IOSSurfaceGL asks the GPUSurfaceGL to make one, then pushes it into IOSContextGL which then owns it.


GPUSurfaceGL(GPUSurfaceGLDelegate* delegate, bool render_to_surface);

// Creates a new GL surface reusing an existing GrDirectContext.
Expand Down Expand Up @@ -53,13 +55,13 @@ class GPUSurfaceGL : public Surface {
sk_sp<GrDirectContext> context_;
sk_sp<SkSurface> onscreen_surface_;
/// FBO backing the current `onscreen_surface_`.
uint32_t fbo_id_;
bool context_owner_;
uint32_t fbo_id_ = 0;
bool context_owner_ = false;
// TODO(38466): Refactor GPU surface APIs take into account the fact that an
// external view embedder may want to render to the root surface. This is a
// hack to make avoid allocating resources for the root surface when an
// external view embedder is present.
const bool render_to_surface_;
const bool render_to_surface_ = true;
bool valid_ = false;
fml::TaskRunnerAffineWeakPtrFactory<GPUSurfaceGL> weak_factory_;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ - (void)testSpawnsShareGpuContext {
std::shared_ptr<flutter::IOSContext> engine_context = [engine iosPlatformView]->GetIosContext();
std::shared_ptr<flutter::IOSContext> spawn_context = [spawn iosPlatformView]->GetIosContext();
XCTAssertEqual(engine_context, spawn_context);
// If this assert fails it means we may be using the software or OpenGL
// renderer when we were expecting Metal. For software rendering, this is
// expected to be nullptr. For OpenGL, implementing this is an outstanding
// change see https://github.com/flutter/flutter/issues/73744.
// If this assert fails it means we may be using the software. For software rendering, this is
// expected to be nullptr.
XCTAssertTrue(engine_context->GetMainContext() != nullptr);
XCTAssertEqual(engine_context->GetMainContext(), spawn_context->GetMainContext());
[engine release];
Expand Down
15 changes: 9 additions & 6 deletions shell/platform/darwin/ios/ios_context_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,11 @@ class IOSContextGL final : public IOSContext {

std::unique_ptr<IOSRenderTargetGL> CreateRenderTarget(fml::scoped_nsobject<CAEAGLLayer> layer);

private:
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
void SetMainContext(const sk_sp<GrDirectContext>& main_context);

// |IOSContext|
sk_sp<GrDirectContext> CreateResourceContext() override;

// |IOSContext|
sk_sp<GrDirectContext> GetMainContext() const override;

// |IOSContext|
std::unique_ptr<GLContextResult> MakeCurrent() override;

Expand All @@ -43,6 +38,14 @@ class IOSContextGL final : public IOSContext {
int64_t texture_id,
fml::scoped_nsobject<NSObject<FlutterTexture>> texture) override;

// |IOSContext|
sk_sp<GrDirectContext> GetMainContext() const override;

private:
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
sk_sp<GrDirectContext> main_context_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSContextGL);
};

Expand Down
18 changes: 11 additions & 7 deletions shell/platform/darwin/ios/ios_context_gl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#import <OpenGLES/EAGL.h>

#include "flutter/shell/common/shell_io_manager.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
#import "flutter/shell/platform/darwin/ios/ios_external_texture_gl.h"

Expand All @@ -24,7 +25,11 @@
}
}

IOSContextGL::~IOSContextGL() = default;
IOSContextGL::~IOSContextGL() {
if (main_context_) {
main_context_->releaseResourcesAndAbandonContext();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it's possible. The various GPUSurfaceGL still has this shared pointer right? Could there be any risks?

}
}

std::unique_ptr<IOSRenderTargetGL> IOSContextGL::CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer) {
Expand All @@ -45,12 +50,11 @@

// |IOSContext|
sk_sp<GrDirectContext> IOSContextGL::GetMainContext() const {
/// TODO(73744): Currently the GPUSurfaceGL creates the main context for
/// OpenGL. With Metal the IOSContextMetal creates the main context and is
/// shared across surfaces. We should refactor the OpenGL Context/Surfaces to
/// behave like the Metal equivalents. Until then engines in the same group
/// will have a heavier memory cost if they are using OpenGL.
return nullptr;
return main_context_;
}

void IOSContextGL::SetMainContext(const sk_sp<GrDirectContext>& main_context) {
main_context_ = main_context;
}

// |IOSContext|
Expand Down
10 changes: 9 additions & 1 deletion shell/platform/darwin/ios/ios_surface_gl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@
std::unique_ptr<Surface> IOSSurfaceGL::CreateGPUSurface(GrDirectContext* gr_context) {
if (gr_context) {
return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
} else {
IOSContextGL* gl_context = CastToGLContext(GetContext());
sk_sp<GrDirectContext> context = gl_context->GetMainContext();
if (!context) {
context = GPUSurfaceGL::MakeGLContext(this);
gl_context->SetMainContext(context);
Copy link
Member

@xster xster Jan 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here. Seems like we have 2 timing characteristics. The metal case just makes this GrDirectContext way earlier when creating the shell's on_create_platform_view, whereas this makes it way later in FlutterViewController's viewWillAppear. There could be minutes in between if the engine was prewarmed.

I'm a bit worried that there might be side-effects involving platform views or memory etc that are hard to reproduce due to the rendering API differences.

It doesn't have to be in this PR, but I suppose this way works better memory wise. Can we make metal work this way too?

Though on the flip side, this likely shifts more of the latency away from the engine prewarming into the critical path for showing the first frame.

}

return std::make_unique<GPUSurfaceGL>(context, this, true);
}
return std::make_unique<GPUSurfaceGL>(this, true);
}

// |GPUSurfaceGLDelegate|
Expand Down
8 changes: 4 additions & 4 deletions shell/platform/darwin/ios/ios_surface_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@
}

// |IOSSurface|
std::unique_ptr<Surface> IOSSurfaceMetal::CreateGPUSurface(GrDirectContext* /* unused */) {
auto metal_context = CastToMetalContext(GetContext());
return std::make_unique<GPUSurfaceMetal>(this, // layer
metal_context->GetMainContext() // context
std::unique_ptr<Surface> IOSSurfaceMetal::CreateGPUSurface(GrDirectContext* context) {
FML_DCHECK(context);
return std::make_unique<GPUSurfaceMetal>(this, // layer
sk_ref_sp(context) // context
);
}

Expand Down
2 changes: 1 addition & 1 deletion shell/platform/darwin/ios/platform_view_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
"has no ViewController.";
return nullptr;
}
return ios_surface_->CreateGPUSurface();
return ios_surface_->CreateGPUSurface(ios_context_->GetMainContext().get());
}

// |PlatformView|
Expand Down
1 change: 0 additions & 1 deletion shell/platform/embedder/embedder_surface_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ std::unique_ptr<Surface> EmbedderSurfaceGL::CreateGPUSurface() {
const bool render_to_surface = !external_view_embedder_;
return std::make_unique<GPUSurfaceGL>(this, // GPU surface GL delegate
render_to_surface // render to surface

);
}

Expand Down