gpu_surface_gl.cc 4.5 KB
Newer Older
1 2 3 4
// 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.

5
#include "gpu_surface_gl.h"
6

7
#include "flutter/glue/trace_event.h"
8 9
#include "lib/ftl/arraysize.h"
#include "lib/ftl/logging.h"
10
#include "third_party/skia/include/core/SkSurface.h"
11
#include "third_party/skia/include/gpu/GrContextOptions.h"
12 13
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"

14 15
namespace shell {

16 17
// Default maximum number of budgeted resources in the cache.
static const int kGrCacheMaxCount = 8192;
18

19 20 21
// Default maximum number of bytes of GPU memory of budgeted resources in the
// cache.
static const size_t kGrCacheMaxByteSize = 512 * (1 << 20);
22

23 24 25 26 27 28 29 30 31 32
GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
    : delegate_(delegate), weak_factory_(this) {}

GPUSurfaceGL::~GPUSurfaceGL() = default;

bool GPUSurfaceGL::Setup() {
  if (delegate_ == nullptr) {
    // Invalid delegate.
    return false;
  }
33 34 35 36 37 38

  if (context_ != nullptr) {
    // Already setup.
    return false;
  }

39 40 41 42 43 44
  if (!delegate_->GLContextMakeCurrent()) {
    // Could not make the context current to create the native interface.
    return false;
  }

  // Create the native interface.
45 46 47
  auto backend_context =
      reinterpret_cast<GrBackendContext>(GrGLCreateNativeInterface());

48 49
  GrContextOptions options;
  options.fRequireDecodeDisableForSRGB = false;
50

51 52 53
  context_ =
      sk_sp<GrContext>(GrContext::Create(kOpenGL_GrBackend, backend_context,
                                         options));
54
  if (context_ == nullptr) {
55
    FTL_LOG(INFO) << "Failed to setup Skia Gr context.";
56
    return false;
57 58
  }

59
  context_->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);
60

61 62
  delegate_->GLContextClearCurrent();

63 64 65
  return true;
}

66
bool GPUSurfaceGL::IsValid() {
67 68 69
  return context_ != nullptr;
}

70 71 72 73 74
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
  if (delegate_ == nullptr) {
    return nullptr;
  }

75 76 77 78
  if (!delegate_->GLContextMakeCurrent()) {
    return nullptr;
  }

79
  sk_sp<SkSurface> surface = AcquireSurface(size);
80 81 82 83 84

  if (surface == nullptr) {
    return nullptr;
  }

85 86
  auto weak_this = weak_factory_.GetWeakPtr();

87 88
  SurfaceFrame::SubmitCallback submit_callback = [weak_this](
      const SurfaceFrame& surface_frame, SkCanvas* canvas) {
89 90
    return weak_this ? weak_this->PresentSurface(canvas) : false;
  };
91

92
  return std::make_unique<SurfaceFrame>(surface, submit_callback);
93 94 95 96 97 98 99
}

bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
  if (delegate_ == nullptr || canvas == nullptr) {
    return false;
  }

100 101 102 103
  {
    TRACE_EVENT0("flutter", "SkCanvas::Flush");
    canvas->flush();
  }
104 105 106 107

  delegate_->GLContextPresent();

  return true;
108 109
}

110
bool GPUSurfaceGL::SelectPixelConfig(GrPixelConfig* config) {
111 112 113 114 115 116
  if (delegate_->ColorSpace() && delegate_->ColorSpace()->gammaCloseToSRGB()) {
    FTL_DCHECK(context_->caps()->isConfigRenderable(kSRGBA_8888_GrPixelConfig,
                                                    false));
    *config = kSRGBA_8888_GrPixelConfig;
    return true;
  }
117

118 119 120 121 122 123 124 125 126 127
  // FIXME:
  // If sRGB support is not available, we should instead fall back to software.
  if (context_->caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig, false)) {
    *config = kRGBA_8888_GrPixelConfig;
    return true;
  }

  if (context_->caps()->isConfigRenderable(kRGBA_4444_GrPixelConfig, false)) {
    *config = kRGBA_4444_GrPixelConfig;
    return true;
128 129 130 131 132
  }

  return false;
}

133 134
sk_sp<SkSurface> GPUSurfaceGL::CreateSurface(const SkISize& size) {
  if (delegate_ == nullptr || context_ == nullptr) {
135 136 137 138 139 140 141 142 143 144 145 146
    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;
147
  desc.fRenderTargetHandle = delegate_->GLContextFBO();
148

149 150
  return SkSurface::MakeFromBackendRenderTarget(context_.get(), desc,
                                                delegate_->ColorSpace(), nullptr);
151 152
}

153
sk_sp<SkSurface> GPUSurfaceGL::AcquireSurface(const SkISize& size) {
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
  // 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_;
}

170
GrContext* GPUSurfaceGL::GetContext() {
171 172
  return context_.get();
}
173 174

}  // namespace shell