Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit

Permalink
Support platform view overlays with GL rendering (#6769)
Browse files Browse the repository at this point in the history
Moved the frame buffer specific logic from IOSGLContext to IOSGLRenderTarget.

use recording canvases for overlays

Support platform view overlays with gl rendering.

This also changes the overlay canvases (for both software and gl
rendering) be recording canvases, and only rasterize them after
finishing the paint traversal.
  • Loading branch information
amirh authored Nov 9, 2018
1 parent b2479f8 commit 099b4ee
Show file tree
Hide file tree
Showing 18 changed files with 399 additions and 179 deletions.
38 changes: 37 additions & 1 deletion ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,42 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================================================

====================================================================================================
LIBRARY: engine
ORIGIN: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.h + ../../../LICENSE
TYPE: LicenseType.bsd
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.mm
----------------------------------------------------------------------------------------------------
Copyright 2018 The Chromium Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================================================

====================================================================================================
LIBRARY: txt
ORIGIN: ../../../flutter/third_party/txt/LICENSE
Expand Down Expand Up @@ -912,4 +948,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================================================
Total license count: 2
Total license count: 3
2 changes: 2 additions & 0 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class ExternalViewEmbedder {
virtual SkCanvas* CompositeEmbeddedView(int view_id,
const EmbeddedViewParams& params) = 0;

virtual bool SubmitFrame(GrContext* context) { return false; };

virtual ~ExternalViewEmbedder() = default;

FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
Expand Down
3 changes: 3 additions & 0 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) {

if (compositor_frame && compositor_frame->Raster(layer_tree, false)) {
frame->Submit();
if (external_view_embedder != nullptr) {
external_view_embedder->SubmitFrame(surface_->GetContext());
}
FireNextFrameCallbackIfPresent();
return true;
}
Expand Down
22 changes: 21 additions & 1 deletion shell/gpu/gpu_surface_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,24 @@ GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
delegate_->GLContextClearCurrent();

valid_ = true;
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;
}

GPUSurfaceGL::~GPUSurfaceGL() {
Expand All @@ -103,7 +121,9 @@ GPUSurfaceGL::~GPUSurfaceGL() {
}

onscreen_surface_ = nullptr;
context_->releaseResourcesAndAbandonContext();
if (context_owner_) {
context_->releaseResourcesAndAbandonContext();
}
context_ = nullptr;

delegate_->GLContextClearCurrent();
Expand Down
4 changes: 4 additions & 0 deletions shell/gpu/gpu_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class GPUSurfaceGL : public Surface {
public:
GPUSurfaceGL(GPUSurfaceGLDelegate* delegate);

// Creates a new GL surface reusing an existing GrContext.
GPUSurfaceGL(sk_sp<GrContext> gr_context, GPUSurfaceGLDelegate* delegate);

~GPUSurfaceGL() override;

// |shell::Surface|
Expand All @@ -74,6 +77,7 @@ class GPUSurfaceGL : public Surface {
sk_sp<SkSurface> offscreen_surface_;
bool valid_ = false;
fml::WeakPtrFactory<GPUSurfaceGL> weak_factory_;
bool context_owner_;

bool CreateOrUpdateSurfaces(const SkISize& size);

Expand Down
2 changes: 2 additions & 0 deletions shell/platform/darwin/ios/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ shared_library("create_flutter_framework_dylib") {
"ios_external_texture_gl.mm",
"ios_gl_context.h",
"ios_gl_context.mm",
"ios_gl_render_target.h",
"ios_gl_render_target.mm",
"ios_surface.h",
"ios_surface.mm",
"ios_surface_gl.h",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@

#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/platform/darwin/ios/ios_gl_context.h"
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
#include "flutter/shell/platform/darwin/ios/ios_surface_gl.h"

@interface FlutterOverlayView : UIView

- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;

- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (std::unique_ptr<shell::IOSSurface>)createSurface;
- (std::unique_ptr<shell::IOSSurface>)createSoftwareSurface;
- (std::unique_ptr<shell::IOSSurfaceGL>)createGLSurfaceWithContext:
(std::shared_ptr<shell::IOSGLContext>)gl_context;

@end

Expand Down
17 changes: 9 additions & 8 deletions shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,15 @@ + (Class)layerClass {
#endif // TARGET_IPHONE_SIMULATOR
}

- (std::unique_ptr<shell::IOSSurface>)createSurface {
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
// TODO(amirh): create a GL surface.
return nullptr;
} else {
fml::scoped_nsobject<CALayer> layer(reinterpret_cast<CALayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer), nullptr);
}
- (std::unique_ptr<shell::IOSSurface>)createSoftwareSurface {
fml::scoped_nsobject<CALayer> layer(reinterpret_cast<CALayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer), nullptr);
}

- (std::unique_ptr<shell::IOSSurfaceGL>)createGLSurfaceWithContext:
(std::shared_ptr<shell::IOSGLContext>)gl_context {
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceGL>(eagl_layer, std::move(gl_context));
}

// TODO(amirh): implement drawLayer to suppoer snapshotting.
Expand Down
56 changes: 42 additions & 14 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#import "FlutterOverlayView.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"

#include <map>
#include <memory>
Expand Down Expand Up @@ -138,24 +139,24 @@
}

void FlutterPlatformViewsController::PrerollCompositeEmbeddedView(int view_id) {
EnsureOverlayInitialized(view_id);
composition_frames_[view_id] = (overlays_[view_id]->surface->AcquireFrame(frame_size_));
picture_recorders_[view_id] = std::make_unique<SkPictureRecorder>();
picture_recorders_[view_id]->beginRecording(SkRect::Make(frame_size_));
picture_recorders_[view_id]->getRecordingCanvas()->clear(SK_ColorTRANSPARENT);
composition_order_.push_back(view_id);
}

std::vector<SkCanvas*> FlutterPlatformViewsController::GetCurrentCanvases() {
std::vector<SkCanvas*> canvases;
for (size_t i = 0; i < composition_order_.size(); i++) {
int64_t view_id = composition_order_[i];
canvases.push_back(composition_frames_[view_id]->SkiaCanvas());
canvases.push_back(picture_recorders_[view_id]->getRecordingCanvas());
}
return canvases;
}

SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView(
int view_id,
const flow::EmbeddedViewParams& params,
IOSSurface& ios_surface) {
const flow::EmbeddedViewParams& params) {
// TODO(amirh): assert that this is running on the platform thread once we support the iOS
// embedded views thread configuration.
// TODO(amirh): do nothing if the params didn't change.
Expand All @@ -167,9 +168,7 @@
UIView* touch_interceptor = touch_interceptors_[view_id].get();
[touch_interceptor setFrame:rect];

SkCanvas* canvas = composition_frames_[view_id]->SkiaCanvas();
canvas->clear(SK_ColorTRANSPARENT);
return canvas;
return picture_recorders_[view_id]->getRecordingCanvas();
}

void FlutterPlatformViewsController::Reset() {
Expand All @@ -181,16 +180,27 @@
overlays_.clear();
composition_order_.clear();
active_composition_order_.clear();
composition_frames_.clear();
picture_recorders_.clear();
}

bool FlutterPlatformViewsController::Present() {
bool FlutterPlatformViewsController::SubmitFrame(bool gl_rendering,
GrContext* gr_context,
std::shared_ptr<IOSGLContext> gl_context) {
bool did_submit = true;
for (size_t i = 0; i < composition_order_.size(); i++) {
int64_t view_id = composition_order_[i];
did_submit &= composition_frames_[view_id]->Submit();
if (gl_rendering) {
EnsureGLOverlayInitialized(view_id, gl_context, gr_context);
} else {
EnsureOverlayInitialized(view_id);
}
auto frame = overlays_[view_id]->surface->AcquireFrame(frame_size_);
SkCanvas* canvas = frame->SkiaCanvas();
canvas->drawPicture(picture_recorders_[view_id]->finishRecordingAsPicture());
canvas->flush();
did_submit &= frame->Submit();
}
composition_frames_.clear();
picture_recorders_.clear();
if (composition_order_ == active_composition_order_) {
composition_order_.clear();
return did_submit;
Expand Down Expand Up @@ -226,10 +236,28 @@
overlay_view.frame = flutter_view_.get().bounds;
overlay_view.autoresizingMask =
(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
std::unique_ptr<IOSSurface> ios_surface = overlay_view.createSurface;
std::unique_ptr<IOSSurface> ios_surface = overlay_view.createSoftwareSurface;
std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface();
overlays_[overlay_id] = std::make_unique<FlutterPlatformViewLayer>(
overlay_view, std::move(ios_surface), std::move(surface));
fml::scoped_nsobject<UIView>(overlay_view), std::move(ios_surface), std::move(surface));
}

void FlutterPlatformViewsController::EnsureGLOverlayInitialized(
int64_t overlay_id,
std::shared_ptr<IOSGLContext> gl_context,
GrContext* gr_context) {
if (overlays_.count(overlay_id) != 0) {
return;
}
FlutterOverlayView* overlay_view = [[FlutterOverlayView alloc] init];
overlay_view.frame = flutter_view_.get().bounds;
overlay_view.autoresizingMask =
(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
std::unique_ptr<IOSSurfaceGL> ios_surface =
[overlay_view createGLSurfaceWithContext:std::move(gl_context)];
std::unique_ptr<Surface> surface = ios_surface->CreateSecondaryGPUSurface(gr_context);
overlays_[overlay_id] = std::make_unique<FlutterPlatformViewLayer>(
fml::scoped_nsobject<UIView>(overlay_view), std::move(ios_surface), std::move(surface));
}

} // namespace shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@

namespace shell {

class IOSGLContext;
class IOSSurface;

struct FlutterPlatformViewLayer {
FlutterPlatformViewLayer(UIView* overlay_view,
FlutterPlatformViewLayer(fml::scoped_nsobject<UIView> overlay_view,
std::unique_ptr<IOSSurface> ios_surface,
std::unique_ptr<Surface> surface)
: overlay_view([overlay_view retain]),
: overlay_view(std::move(overlay_view)),
ios_surface(std::move(ios_surface)),
surface(std::move(surface)){};

Expand All @@ -55,14 +56,14 @@ class FlutterPlatformViewsController {

std::vector<SkCanvas*> GetCurrentCanvases();

SkCanvas* CompositeEmbeddedView(int view_id,
const flow::EmbeddedViewParams& params,
IOSSurface& surface);
SkCanvas* CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params);

// Discards all platform views instances and auxiliary resources.
void Reset();

bool Present();
bool SubmitFrame(bool gl_rendering,
GrContext* gr_context,
std::shared_ptr<IOSGLContext> gl_context);

void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);

Expand All @@ -82,13 +83,16 @@ class FlutterPlatformViewsController {
// The latest composition order that was presented in Present().
std::vector<int64_t> active_composition_order_;

std::map<int64_t, std::unique_ptr<SurfaceFrame>> composition_frames_;
std::map<int64_t, std::unique_ptr<SkPictureRecorder>> picture_recorders_;

void OnCreate(FlutterMethodCall* call, FlutterResult& result);
void OnDispose(FlutterMethodCall* call, FlutterResult& result);
void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);

void EnsureOverlayInitialized(int64_t overlay_id);
void EnsureGLOverlayInitialized(int64_t overlay_id,
std::shared_ptr<IOSGLContext> gl_context,
GrContext* gr_context);

FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController);
};
Expand Down
18 changes: 4 additions & 14 deletions shell/platform/darwin/ios/ios_gl_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,18 @@
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/platform_view.h"
#include "ios_gl_render_target.h"

namespace shell {

class IOSGLContext {
public:
IOSGLContext(fml::scoped_nsobject<CAEAGLLayer> layer);
IOSGLContext();

~IOSGLContext();

bool IsValid() const;

bool PresentRenderBuffer() const;

GLuint framebuffer() const { return framebuffer_; }

bool UpdateStorageSizeIfNecessary();
std::unique_ptr<IOSGLRenderTarget> CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer);

bool MakeCurrent();

Expand All @@ -37,15 +33,9 @@ class IOSGLContext {
sk_sp<SkColorSpace> ColorSpace() const { return color_space_; }

private:
fml::scoped_nsobject<CAEAGLLayer> layer_;
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
GLuint framebuffer_;
GLuint colorbuffer_;
GLint storage_size_width_;
GLint storage_size_height_;
sk_sp<SkColorSpace> color_space_;
bool valid_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSGLContext);
};
Expand Down
Loading

0 comments on commit 099b4ee

Please sign in to comment.