flutter_flutter/shell/platform/android/android_surface_gl.cc
Brian Osman 0a7155d4e1
Disable linear blending, use SkColorSpaceXformCanvas instead (#4355)
This retains gamut correction (adjusting colors for screens with different capabilities), but does all blending and interpolation with sRGB-encoded values. That matches the behavior expected by most users, as well as the behavior of nearly all other systems. It also greatly simplifies the EGL code.

A future Skia change will make this behavior more of a first-class citizen, so some of these implementation details will change again, but the behavior will not. The bulk of this change (elimination of complication from the GL surface code) is permanent - it's just the SkColorSpaceXformCanvas that will be replaced.
2017-11-14 13:33:26 -05:00

153 lines
4.2 KiB
C++

// 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_surface_gl.h"
#include <utility>
#include "flutter/common/threads.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/memory/ref_ptr.h"
namespace shell {
static fxl::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 fxl::RefPtr<AndroidContextGL> global_context;
if (global_context) {
return global_context;
}
auto environment = fxl::MakeRefCounted<AndroidEnvironmentGL>();
if (!environment->IsValid()) {
return nullptr;
}
// TODO(chinmaygarde): We should check that the configurations are stable
// across multiple invocations.
auto context =
fxl::MakeRefCounted<AndroidContextGL>(environment, offscreen_config);
if (!context->IsValid()) {
return nullptr;
}
global_context = context;
return global_context;
}
AndroidSurfaceGL::AndroidSurfaceGL(
PlatformView::SurfaceConfig offscreen_config) {
// Acquire the offscreen context.
offscreen_context_ = GlobalResourceLoadingContext(offscreen_config);
if (!offscreen_context_ || !offscreen_context_->IsValid()) {
offscreen_context_ = nullptr;
}
}
AndroidSurfaceGL::~AndroidSurfaceGL() = default;
bool AndroidSurfaceGL::IsOffscreenContextValid() const {
return offscreen_context_ && offscreen_context_->IsValid();
}
void AndroidSurfaceGL::TeardownOnScreenContext() {
fxl::AutoResetWaitableEvent latch;
blink::Threads::Gpu()->PostTask([this, &latch]() {
if (IsValid()) {
GLContextClearCurrent();
}
latch.Signal();
});
latch.Wait();
onscreen_context_ = nullptr;
}
bool AndroidSurfaceGL::IsValid() const {
if (!onscreen_context_ || !offscreen_context_) {
return false;
}
return onscreen_context_->IsValid() && offscreen_context_->IsValid();
}
std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface() {
auto surface = std::make_unique<GPUSurfaceGL>(this);
return surface->IsValid() ? std::move(surface) : nullptr;
}
SkISize AndroidSurfaceGL::OnScreenSurfaceSize() const {
FXL_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->GetSize();
}
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) const {
FXL_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->Resize(size);
}
bool AndroidSurfaceGL::ResourceContextMakeCurrent() {
FXL_DCHECK(offscreen_context_ && offscreen_context_->IsValid());
return offscreen_context_->MakeCurrent();
}
bool AndroidSurfaceGL::SetNativeWindow(fxl::RefPtr<AndroidNativeWindow> window,
PlatformView::SurfaceConfig config) {
// In any case, we want to get rid of our current onscreen context.
onscreen_context_ = nullptr;
// If the offscreen context has not been setup, we dont have the sharegroup.
// So bail.
if (!offscreen_context_ || !offscreen_context_->IsValid()) {
return false;
}
// Create the onscreen context.
onscreen_context_ = fxl::MakeRefCounted<AndroidContextGL>(
offscreen_context_->Environment(), config,
offscreen_context_.get() /* sharegroup */);
if (!onscreen_context_->IsValid()) {
onscreen_context_ = nullptr;
return false;
}
if (!onscreen_context_->CreateWindowSurface(std::move(window))) {
onscreen_context_ = nullptr;
return false;
}
return true;
}
bool AndroidSurfaceGL::GLContextMakeCurrent() {
FXL_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->MakeCurrent();
}
bool AndroidSurfaceGL::GLContextClearCurrent() {
FXL_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->ClearCurrent();
}
bool AndroidSurfaceGL::GLContextPresent() {
FXL_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->SwapBuffers();
}
intptr_t AndroidSurfaceGL::GLContextFBO() const {
FXL_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
// The default window bound framebuffer on Android.
return 0;
}
} // namespace shell