ios_surface_software.mm 6.7 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/darwin/ios/ios_surface_software.h"

#include <QuartzCore/CALayer.h>

#include <memory>

11
#include "flutter/fml/logging.h"
12
#include "flutter/fml/platform/darwin/cf_utils.h"
13
#include "flutter/fml/trace_event.h"
14 15
#include "third_party/skia/include/utils/mac/SkCGUtils.h"

16
namespace flutter {
17

18
IOSSurfaceSoftware::IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> layer,
19
                                       FlutterPlatformViewsController* platform_views_controller)
20
    : IOSSurface(platform_views_controller), layer_(std::move(layer)) {
21 22 23 24 25 26
  UpdateStorageSizeIfNecessary();
}

IOSSurfaceSoftware::~IOSSurfaceSoftware() = default;

bool IOSSurfaceSoftware::IsValid() const {
27
  return layer_;
28 29 30 31 32 33 34 35 36 37 38 39 40
}

bool IOSSurfaceSoftware::ResourceContextMakeCurrent() {
  return false;
}

void IOSSurfaceSoftware::UpdateStorageSizeIfNecessary() {
  // Nothing to do here. We don't need an external entity to tell us when our
  // backing store needs to be updated. Instead, we let the frame tell us its
  // size so we can update to match. This method was added to work around
  // Android oddities.
}

41
std::unique_ptr<Surface> IOSSurfaceSoftware::CreateGPUSurface(GrContext* gr_context) {
42 43 44 45
  if (!IsValid()) {
    return nullptr;
  }

46
  auto surface = std::make_unique<GPUSurfaceSoftware>(this, true /* render to surface */);
47 48 49 50 51 52 53 54 55

  if (!surface->IsValid()) {
    return nullptr;
  }

  return surface;
}

sk_sp<SkSurface> IOSSurfaceSoftware::AcquireBackingStore(const SkISize& size) {
56
  TRACE_EVENT0("flutter", "IOSSurfaceSoftware::AcquireBackingStore");
57 58 59 60 61 62 63 64 65 66
  if (!IsValid()) {
    return nullptr;
  }

  if (sk_surface_ != nullptr &&
      SkISize::Make(sk_surface_->width(), sk_surface_->height()) == size) {
    // The old and new surface sizes are the same. Nothing to do here.
    return sk_surface_;
  }

67 68
  SkImageInfo info = SkImageInfo::MakeN32(size.fWidth, size.fHeight, kPremul_SkAlphaType,
                                          SkColorSpace::MakeSRGB());
69
  sk_surface_ = SkSurface::MakeRaster(info, nullptr);
70 71 72 73
  return sk_surface_;
}

bool IOSSurfaceSoftware::PresentBackingStore(sk_sp<SkSurface> backing_store) {
74
  TRACE_EVENT0("flutter", "IOSSurfaceSoftware::PresentBackingStore");
75 76 77 78 79 80 81 82 83
  if (!IsValid() || backing_store == nullptr) {
    return false;
  }

  SkPixmap pixmap;
  if (!backing_store->peekPixels(&pixmap)) {
    return false;
  }

84
  // Some basic sanity checking.
85 86
  uint64_t expected_pixmap_data_size = pixmap.width() * pixmap.height() * 4;

87 88 89
  const size_t pixmap_size = pixmap.computeByteSize();

  if (expected_pixmap_data_size != pixmap_size) {
90 91 92 93 94
    return false;
  }

  fml::CFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());

95 96
  // Setup the data provider that gives CG a view into the pixmap.
  fml::CFRef<CGDataProviderRef> pixmap_data_provider(CGDataProviderCreateWithData(
97 98 99 100
      nullptr,          // info
      pixmap.addr32(),  // data
      pixmap_size,      // size
      nullptr           // release callback
101 102
      ));

103
  if (!pixmap_data_provider) {
104 105 106
    return false;
  }

107
  // Create the CGImageRef representation on the pixmap.
108 109 110 111 112 113
  fml::CFRef<CGImageRef> pixmap_image(CGImageCreate(pixmap.width(),     // width
                                                    pixmap.height(),    // height
                                                    8,                  // bits per component
                                                    32,                 // bits per pixel
                                                    pixmap.rowBytes(),  // bytes per row
                                                    colorspace,         // colorspace
114 115 116 117 118 119 120 121
                                                    kCGImageAlphaPremultipliedLast,  // bitmap info
                                                    pixmap_data_provider,      // data provider
                                                    nullptr,                   // decode array
                                                    false,                     // should interpolate
                                                    kCGRenderingIntentDefault  // rendering intent
                                                    ));

  if (!pixmap_image) {
122 123 124
    return false;
  }

125
  layer_.get().contents = reinterpret_cast<id>(static_cast<CGImageRef>(pixmap_image));
126

127
  return true;
128 129
}

130
ExternalViewEmbedder* IOSSurfaceSoftware::GetExternalViewEmbedder() {
131
  if (IsIosEmbeddedViewsPreviewEnabled()) {
132 133 134 135
    return this;
  } else {
    return nullptr;
  }
136
}
137

138 139 140 141 142 143 144 145
// |ExternalViewEmbedder|
sk_sp<SkSurface> IOSSurfaceSoftware::GetRootSurface() {
  // On iOS, the root surface is created using a managed allocation that is submitted to the
  // platform. Only the surfaces for the various overlays are controlled by this class.
  return nullptr;
}

// |ExternalViewEmbedder|
146 147 148 149 150 151
void IOSSurfaceSoftware::CancelFrame() {
  FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
  FML_CHECK(platform_views_controller != nullptr);
  platform_views_controller->CancelFrame();
}

152 153
// |ExternalViewEmbedder|
void IOSSurfaceSoftware::BeginFrame(SkISize frame_size, GrContext* context) {
154 155 156 157 158
  FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
  FML_CHECK(platform_views_controller != nullptr);
  platform_views_controller->SetFrameSize(frame_size);
}

159 160 161
// |ExternalViewEmbedder|
void IOSSurfaceSoftware::PrerollCompositeEmbeddedView(int view_id,
                                                      std::unique_ptr<EmbeddedViewParams> params) {
162 163
  FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
  FML_CHECK(platform_views_controller != nullptr);
164
  platform_views_controller->PrerollCompositeEmbeddedView(view_id, std::move(params));
165 166
}

167
// |ExternalViewEmbedder|
168 169 170 171 172 173
std::vector<SkCanvas*> IOSSurfaceSoftware::GetCurrentCanvases() {
  FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
  FML_CHECK(platform_views_controller != nullptr);
  return platform_views_controller->GetCurrentCanvases();
}

174
// |ExternalViewEmbedder|
175
SkCanvas* IOSSurfaceSoftware::CompositeEmbeddedView(int view_id) {
176 177
  FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
  FML_CHECK(platform_views_controller != nullptr);
178
  return platform_views_controller->CompositeEmbeddedView(view_id);
179 180
}

181
// |ExternalViewEmbedder|
182 183 184 185 186
bool IOSSurfaceSoftware::SubmitFrame(GrContext* context) {
  FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
  if (platform_views_controller == nullptr) {
    return true;
  }
187
  return platform_views_controller->SubmitFrame(nullptr, nullptr);
188 189
}

190
}  // namespace flutter