flutter_flutter/shell/gpu/gpu_surface_gl.cc
Chinmay Garde 2868251402 Remove rarely used GLConnection stuff in flow. (#3440)
I had added this initially as a means of making it easier to deal with OpenGL directly in Flow. However, we are moving away from dealing with the client rendering APIs directly. Instead, delegating everything to Skia. Besides, we only ever used this to log the GPU description in case of context setup failures. This has not proved to be useful so far. Also, having this in place is making it difficult to remove all dependencies on GL in Shell.
2017-02-23 16:02:53 -08:00

164 lines
4.0 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 "gpu_surface_gl.h"
#include "flutter/glue/trace_event.h"
#include "lib/ftl/arraysize.h"
#include "lib/ftl/logging.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"
namespace shell {
// Default maximum number of budgeted resources in the cache.
static const int kGrCacheMaxCount = 8192;
// Default maximum number of bytes of GPU memory of budgeted resources in the
// cache.
static const size_t kGrCacheMaxByteSize = 512 * (1 << 20);
GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
: delegate_(delegate), weak_factory_(this) {}
GPUSurfaceGL::~GPUSurfaceGL() = default;
bool GPUSurfaceGL::Setup() {
if (delegate_ == nullptr) {
// Invalid delegate.
return false;
}
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());
context_ =
sk_sp<GrContext>(GrContext::Create(kOpenGL_GrBackend, backend_context));
if (context_ == nullptr) {
FTL_LOG(INFO) << "Failed to setup Skia Gr context.";
return false;
}
context_->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);
delegate_->GLContextClearCurrent();
return true;
}
bool GPUSurfaceGL::IsValid() {
return context_ != nullptr;
}
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
if (delegate_ == nullptr) {
return nullptr;
}
if (!delegate_->GLContextMakeCurrent()) {
return nullptr;
}
sk_sp<SkSurface> surface = AcquireSurface(size);
if (surface == nullptr) {
return nullptr;
}
auto weak_this = weak_factory_.GetWeakPtr();
SurfaceFrame::SubmitCallback submit_callback = [weak_this](
const SurfaceFrame& surface_frame, SkCanvas* canvas) {
return weak_this ? weak_this->PresentSurface(canvas) : false;
};
return std::make_unique<SurfaceFrame>(surface, submit_callback);
}
bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
if (delegate_ == nullptr || canvas == nullptr) {
return false;
}
{
TRACE_EVENT0("flutter", "SkCanvas::Flush");
canvas->flush();
}
delegate_->GLContextPresent();
return true;
}
bool GPUSurfaceGL::SelectPixelConfig(GrPixelConfig* config) {
static const GrPixelConfig kConfigOptions[] = {
kSkia8888_GrPixelConfig, kRGBA_4444_GrPixelConfig,
};
for (size_t i = 0; i < arraysize(kConfigOptions); i++) {
if (context_->caps()->isConfigRenderable(kConfigOptions[i], false)) {
*config = kConfigOptions[i];
return true;
}
}
return false;
}
sk_sp<SkSurface> GPUSurfaceGL::CreateSurface(const SkISize& size) {
if (delegate_ == nullptr || context_ == nullptr) {
return nullptr;
}
GrBackendRenderTargetDesc desc;
if (!SelectPixelConfig(&desc.fConfig)) {
return nullptr;
}
desc.fWidth = size.width();
desc.fHeight = size.height();
desc.fStencilBits = 8;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fRenderTargetHandle = delegate_->GLContextFBO();
return SkSurface::MakeFromBackendRenderTarget(context_.get(), desc, nullptr);
}
sk_sp<SkSurface> GPUSurfaceGL::AcquireSurface(const SkISize& size) {
// There is no cached surface.
if (cached_surface_ == nullptr) {
cached_surface_ = CreateSurface(size);
return cached_surface_;
}
// There is a surface previously created of the same size.
if (cached_surface_->width() == size.width() &&
cached_surface_->height() == size.height()) {
return cached_surface_;
}
cached_surface_ = CreateSurface(size);
return cached_surface_;
}
GrContext* GPUSurfaceGL::GetContext() {
return context_.get();
}
} // namespace shell