gpu_surface_gl.cc 11.5 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// 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 8
#include "flutter/fml/arraysize.h"
#include "flutter/fml/logging.h"
9
#include "flutter/fml/trace_event.h"
10
#include "flutter/shell/common/persistent_cache.h"
11
#include "third_party/skia/include/core/SkColorFilter.h"
12
#include "third_party/skia/include/core/SkSurface.h"
13
#include "third_party/skia/include/gpu/GrBackendSurface.h"
14
#include "third_party/skia/include/gpu/GrContextOptions.h"
15
#include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
16
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
17 18 19 20 21 22 23 24

// These are common defines present on all OpenGL headers. However, we don't
// want to perform GL header reasolution on each platform we support. So just
// define these upfront. It is unlikely we will need more. But, if we do, we can
// add the same here.
#define GPU_GL_RGBA8 0x8058
#define GPU_GL_RGBA4 0x8056
#define GPU_GL_RGB565 0x8D62
25
#define GPU_GL_VERSION 0x1F02
26

27 28
namespace shell {

29 30
// Default maximum number of budgeted resources in the cache.
static const int kGrCacheMaxCount = 8192;
31

32 33 34
// Default maximum number of bytes of GPU memory of budgeted resources in the
// cache.
static const size_t kGrCacheMaxByteSize = 512 * (1 << 20);
35

36 37 38
// Version string prefix that identifies an OpenGL ES implementation.
static const char kGLESVersionPrefix[] = "OpenGL ES";

39
GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
40
    : delegate_(delegate), weak_factory_(this) {
41
  if (!delegate_->GLContextMakeCurrent()) {
42
    FML_LOG(ERROR)
43 44
        << "Could not make the context current to setup the gr context.";
    return;
45 46
  }

47 48
  proc_resolver_ = delegate_->GetGLProcResolver();

49
  GrContextOptions options;
50 51 52

  options.fPersistentCache = PersistentCache::GetCacheForProcess();

53 54
  options.fAvoidStencilBuffers = true;

55 56 57 58
  // To get video playback on the widest range of devices, we limit Skia to
  // ES2 shading language when the ES3 external image extension is missing.
  options.fPreferExternalImagesOverES3 = true;

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
  sk_sp<const GrGLInterface> interface;

  if (proc_resolver_ == nullptr) {
    interface = GrGLMakeNativeInterface();
  } else {
    auto gl_get_proc = [](void* context,
                          const char gl_proc_name[]) -> GrGLFuncPtr {
      return reinterpret_cast<GrGLFuncPtr>(
          reinterpret_cast<GPUSurfaceGL*>(context)->proc_resolver_(
              gl_proc_name));
    };

    if (IsProcResolverOpenGLES()) {
      interface = GrGLMakeAssembledGLESInterface(this, gl_get_proc);
    } else {
      interface = GrGLMakeAssembledGLInterface(this, gl_get_proc);
    }
  }
77 78

  auto context = GrContext::MakeGL(interface, options);
79 80

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

85 86
  context_ = std::move(context);

87
  context_->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);
88

89 90
  delegate_->GLContextClearCurrent();

91
  valid_ = true;
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
  context_owner_ = true;
}

GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrContext> gr_context,
                           GPUSurfaceGLDelegate* delegate)
    : delegate_(delegate), context_(gr_context), weak_factory_(this) {
  if (!delegate_->GLContextMakeCurrent()) {
    FML_LOG(ERROR)
        << "Could not make the context current to setup the gr context.";
    return;
  }

  proc_resolver_ = delegate_->GetGLProcResolver();

  delegate_->GLContextClearCurrent();

  valid_ = true;
  context_owner_ = false;
110 111 112 113 114 115 116 117
}

GPUSurfaceGL::~GPUSurfaceGL() {
  if (!valid_) {
    return;
  }

  if (!delegate_->GLContextMakeCurrent()) {
118
    FML_LOG(ERROR) << "Could not make the context current to destroy the "
119 120 121 122 123
                      "GrContext resources.";
    return;
  }

  onscreen_surface_ = nullptr;
124 125 126
  if (context_owner_) {
    context_->releaseResourcesAndAbandonContext();
  }
127 128 129
  context_ = nullptr;

  delegate_->GLContextClearCurrent();
130 131
}

132 133 134 135 136 137 138 139 140 141 142 143 144 145
bool GPUSurfaceGL::IsProcResolverOpenGLES() {
  using GLGetStringProc = const char* (*)(uint32_t);
  GLGetStringProc gl_get_string =
      reinterpret_cast<GLGetStringProc>(proc_resolver_("glGetString"));
  FML_CHECK(gl_get_string)
      << "The GL proc resolver could not resolve glGetString";
  const char* gl_version_string = gl_get_string(GPU_GL_VERSION);
  FML_CHECK(gl_version_string)
      << "The GL proc resolver's glGetString(GL_VERSION) failed";

  return strncmp(gl_version_string, kGLESVersionPrefix,
                 strlen(kGLESVersionPrefix)) == 0;
}

146
// |shell::Surface|
147
bool GPUSurfaceGL::IsValid() {
148 149 150
  return valid_;
}

151 152
static SkColorType FirstSupportedColorType(GrContext* context,
                                           GrGLenum* format) {
153 154 155 156
#define RETURN_IF_RENDERABLE(x, y)                 \
  if (context->colorTypeSupportedAsSurface((x))) { \
    *format = (y);                                 \
    return (x);                                    \
157
  }
158 159 160
  RETURN_IF_RENDERABLE(kRGBA_8888_SkColorType, GPU_GL_RGBA8);
  RETURN_IF_RENDERABLE(kARGB_4444_SkColorType, GPU_GL_RGBA4);
  RETURN_IF_RENDERABLE(kRGB_565_SkColorType, GPU_GL_RGB565);
161
  return kUnknown_SkColorType;
162 163
}

164 165
static sk_sp<SkSurface> WrapOnscreenSurface(GrContext* context,
                                            const SkISize& size,
166
                                            intptr_t fbo) {
167
  GrGLenum format;
168 169
  const SkColorType color_type = FirstSupportedColorType(context, &format);

170 171 172
  GrGLFramebufferInfo framebuffer_info = {};
  framebuffer_info.fFBOID = static_cast<GrGLuint>(fbo);
  framebuffer_info.fFormat = format;
173

174 175
  GrBackendRenderTarget render_target(size.width(),     // width
                                      size.height(),    // height
176 177 178
                                      0,                // sample count
                                      0,                // stencil bits (TODO)
                                      framebuffer_info  // framebuffer info
179
  );
180

181
  sk_sp<SkColorSpace> colorspace = nullptr;
182 183 184 185 186 187 188 189

  SkSurfaceProps surface_props(
      SkSurfaceProps::InitType::kLegacyFontHost_InitType);

  return SkSurface::MakeFromBackendRenderTarget(
      context,                                       // gr context
      render_target,                                 // render target
      GrSurfaceOrigin::kBottomLeft_GrSurfaceOrigin,  // origin
190
      color_type,                                    // color type
191 192
      colorspace,                                    // colorspace
      &surface_props                                 // surface properties
193
  );
194 195
}

196 197 198 199 200 201 202 203 204 205 206 207 208
static sk_sp<SkSurface> CreateOffscreenSurface(GrContext* context,
                                               const SkISize& size) {
  const SkImageInfo image_info =
      SkImageInfo::MakeN32(size.fWidth, size.fHeight, kOpaque_SkAlphaType);

  const SkSurfaceProps surface_props(
      SkSurfaceProps::InitType::kLegacyFontHost_InitType);

  return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, image_info, 0,
                                     kBottomLeft_GrSurfaceOrigin,
                                     &surface_props);
}

209 210 211 212
bool GPUSurfaceGL::CreateOrUpdateSurfaces(const SkISize& size) {
  if (onscreen_surface_ != nullptr &&
      size == SkISize::Make(onscreen_surface_->width(),
                            onscreen_surface_->height())) {
213
    // Surface size appears unchanged. So bail.
214 215 216 217 218 219
    return true;
  }

  // We need to do some updates.
  TRACE_EVENT0("flutter", "UpdateSurfacesSize");

220
  // Either way, we need to get rid of previous surface.
221
  onscreen_surface_ = nullptr;
222
  offscreen_surface_ = nullptr;
223 224

  if (size.isEmpty()) {
225
    FML_LOG(ERROR) << "Cannot create surfaces of empty size.";
226 227 228
    return false;
  }

229
  sk_sp<SkSurface> onscreen_surface, offscreen_surface;
230

231
  onscreen_surface =
232 233 234 235
      WrapOnscreenSurface(context_.get(),            // GL context
                          size,                      // root surface size
                          delegate_->GLContextFBO()  // window FBO ID
      );
236

237
  if (onscreen_surface == nullptr) {
238 239
    // If the onscreen surface could not be wrapped. There is absolutely no
    // point in moving forward.
240
    FML_LOG(ERROR) << "Could not wrap onscreen surface.";
241 242 243
    return false;
  }

244 245 246
  if (delegate_->UseOffscreenSurface()) {
    offscreen_surface = CreateOffscreenSurface(context_.get(), size);
    if (offscreen_surface == nullptr) {
247
      FML_LOG(ERROR) << "Could not create offscreen surface.";
248 249 250 251
      return false;
    }
  }

252
  onscreen_surface_ = std::move(onscreen_surface);
253
  offscreen_surface_ = std::move(offscreen_surface);
254 255

  return true;
256 257
}

258 259 260 261 262 263
// |shell::Surface|
SkMatrix GPUSurfaceGL::GetRootTransformation() const {
  return delegate_->GLContextSurfaceTransformation();
}

// |shell::Surface|
264 265 266 267 268
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
  if (delegate_ == nullptr) {
    return nullptr;
  }

269
  if (!delegate_->GLContextMakeCurrent()) {
270
    FML_LOG(ERROR)
271
        << "Could not make the context current to acquire the frame.";
272 273 274
    return nullptr;
  }

275 276 277 278
  const auto root_surface_transformation = GetRootTransformation();

  sk_sp<SkSurface> surface =
      AcquireRenderSurface(size, root_surface_transformation);
279 280 281 282 283

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

284 285
  surface->getCanvas()->setMatrix(root_surface_transformation);

286 287 288 289 290
  SurfaceFrame::SubmitCallback submit_callback =
      [weak = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame,
                                          SkCanvas* canvas) {
        return weak ? weak->PresentSurface(canvas) : false;
      };
291

292
  return std::make_unique<SurfaceFrame>(surface, submit_callback);
293 294 295
}

bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
296
  if (delegate_ == nullptr || canvas == nullptr || context_ == nullptr) {
297 298 299
    return false;
  }

300 301 302
  if (offscreen_surface_ != nullptr) {
    TRACE_EVENT0("flutter", "CopyTextureOnscreen");
    SkPaint paint;
303 304 305 306
    SkCanvas* onscreen_canvas = onscreen_surface_->getCanvas();
    onscreen_canvas->clear(SK_ColorTRANSPARENT);
    onscreen_canvas->drawImage(offscreen_surface_->makeImageSnapshot(), 0, 0,
                               &paint);
307 308
  }

309 310
  {
    TRACE_EVENT0("flutter", "SkCanvas::Flush");
311
    onscreen_surface_->getCanvas()->flush();
312
  }
313

314 315 316 317 318 319 320 321 322 323
  if (!delegate_->GLContextPresent()) {
    return false;
  }

  if (delegate_->GLContextFBOResetAfterPresent()) {
    auto current_size =
        SkISize::Make(onscreen_surface_->width(), onscreen_surface_->height());

    // The FBO has changed, ask the delegate for the new FBO and do a surface
    // re-wrap.
324 325 326 327 328
    auto new_onscreen_surface =
        WrapOnscreenSurface(context_.get(),            // GL context
                            current_size,              // root surface size
                            delegate_->GLContextFBO()  // window FBO ID
        );
329 330 331 332 333 334 335

    if (!new_onscreen_surface) {
      return false;
    }

    onscreen_surface_ = std::move(new_onscreen_surface);
  }
336 337

  return true;
338 339
}

340 341 342 343 344 345 346 347 348 349
sk_sp<SkSurface> GPUSurfaceGL::AcquireRenderSurface(
    const SkISize& untransformed_size,
    const SkMatrix& root_surface_transformation) {
  const auto transformed_rect = root_surface_transformation.mapRect(
      SkRect::MakeWH(untransformed_size.width(), untransformed_size.height()));

  const auto transformed_size =
      SkISize::Make(transformed_rect.width(), transformed_rect.height());

  if (!CreateOrUpdateSurfaces(transformed_size)) {
350 351 352
    return nullptr;
  }

353
  return offscreen_surface_ != nullptr ? offscreen_surface_ : onscreen_surface_;
354 355
}

356
// |shell::Surface|
357
GrContext* GPUSurfaceGL::GetContext() {
358 359
  return context_.get();
}
360

361 362 363 364 365
// |shell::Surface|
flow::ExternalViewEmbedder* GPUSurfaceGL::GetExternalViewEmbedder() {
  return delegate_->GetExternalViewEmbedder();
}

366
}  // namespace shell