blob: 453259cd67279422bd24bf11bf27097ecf48acec [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FLOW_COMPOSITOR_CONTEXT_H_
#define FLUTTER_FLOW_COMPOSITOR_CONTEXT_H_
#include <memory>
#include <string>
#include "flutter/common/graphics/texture.h"
#include "flutter/flow/diff_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/layer_snapshot_store.h"
#include "flutter/flow/raster_cache.h"
#include "flutter/flow/stopwatch.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/raster_thread_merger.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
namespace flutter {
class LayerTree;
// The result status of CompositorContext::ScopedFrame::Raster.
enum class RasterStatus {
// Frame has been successfully rasterized.
kSuccess,
// Frame has been submited, but must be submitted again. This is only used
// on Android when switching the background surface to FlutterImageView.
//
// On Android, the first frame doesn't make the image available
// to the ImageReader right away. The second frame does.
//
// TODO(egarciad): https://github.com/flutter/flutter/issues/65652
kResubmit,
// Frame has be dropped and a new frame with the same layer tree must be
// attempted.
//
// This is currently used to wait for the thread merger to merge
// the raster and platform threads.
//
// Since the thread merger may be disabled, the system will proceed
// with separate threads for rasterization and platform tasks,
// potentially leading to different performance characteristics.
kSkipAndRetry,
};
class FrameDamage {
public:
// Sets previous layer tree for calculating frame damage. If not set, entire
// frame will be repainted.
void SetPreviousLayerTree(const LayerTree* prev_layer_tree) {
prev_layer_tree_ = prev_layer_tree;
}
// Adds additional damage (accumulated for double / triple buffering).
// This is area that will be repainted alongside any changed part.
void AddAdditionalDamage(const SkIRect& damage) {
additional_damage_.join(damage);
}
// Specifies clip rect alignment.
void SetClipAlignment(int horizontal, int vertical) {
horizontal_clip_alignment_ = horizontal;
vertical_clip_alignment_ = vertical;
}
// Calculates clip rect for current rasterization. This is diff of layer tree
// and previous layer tree + any additional provided damage.
// If previous layer tree is not specified, clip rect will be nullopt,
// but the paint region of layer_tree will be calculated so that it can be
// used for diffing of subsequent frames.
std::optional<SkRect> ComputeClipRect(flutter::LayerTree& layer_tree,
bool has_raster_cache,
bool impeller_enabled);
// See Damage::frame_damage.
std::optional<SkIRect> GetFrameDamage() const {
return damage_ ? std::make_optional(damage_->frame_damage) : std::nullopt;
}
// See Damage::buffer_damage.
std::optional<SkIRect> GetBufferDamage() {
return (damage_ && !ignore_damage_)
? std::make_optional(damage_->buffer_damage)
: std::nullopt;
}
// Remove reported buffer_damage to inform clients that a partial repaint
// should not be performed on this frame.
// frame_damage is required to correctly track accumulated damage for
// subsequent frames.
void Reset() { ignore_damage_ = true; }
private:
SkIRect additional_damage_ = SkIRect::MakeEmpty();
std::optional<Damage> damage_;
const LayerTree* prev_layer_tree_ = nullptr;
int vertical_clip_alignment_ = 1;
int horizontal_clip_alignment_ = 1;
bool ignore_damage_ = false;
};
class CompositorContext {
public:
class ScopedFrame {
public:
ScopedFrame(CompositorContext& context,
GrDirectContext* gr_context,
DlCanvas* canvas,
ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled,
bool surface_supports_readback,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger,
impeller::AiksContext* aiks_context);
virtual ~ScopedFrame();
DlCanvas* canvas() { return canvas_; }
ExternalViewEmbedder* view_embedder() { return view_embedder_; }
CompositorContext& context() const { return context_; }
const SkMatrix& root_surface_transformation() const {
return root_surface_transformation_;
}
bool surface_supports_readback() { return surface_supports_readback_; }
GrDirectContext* gr_context() const { return gr_context_; }
impeller::AiksContext* aiks_context() const { return aiks_context_; }
virtual RasterStatus Raster(LayerTree& layer_tree,
bool ignore_raster_cache,
FrameDamage* frame_damage);
private:
void PaintLayerTreeSkia(flutter::LayerTree& layer_tree,
std::optional<SkRect> clip_rect,
bool needs_save_layer,
bool ignore_raster_cache);
void PaintLayerTreeImpeller(flutter::LayerTree& layer_tree,
std::optional<SkRect> clip_rect,
bool ignore_raster_cache);
CompositorContext& context_;
GrDirectContext* gr_context_;
DlCanvas* canvas_;
impeller::AiksContext* aiks_context_;
ExternalViewEmbedder* view_embedder_;
const SkMatrix& root_surface_transformation_;
const bool instrumentation_enabled_;
const bool surface_supports_readback_;
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger_;
FML_DISALLOW_COPY_AND_ASSIGN(ScopedFrame);
};
CompositorContext();
explicit CompositorContext(Stopwatch::RefreshRateUpdater& updater);
virtual ~CompositorContext();
virtual std::unique_ptr<ScopedFrame> AcquireFrame(
GrDirectContext* gr_context,
DlCanvas* canvas,
ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled,
bool surface_supports_readback,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger,
impeller::AiksContext* aiks_context);
void OnGrContextCreated();
void OnGrContextDestroyed();
RasterCache& raster_cache() { return raster_cache_; }
std::shared_ptr<TextureRegistry> texture_registry() {
return texture_registry_;
}
const Stopwatch& raster_time() const { return raster_time_; }
Stopwatch& ui_time() { return ui_time_; }
LayerSnapshotStore& snapshot_store() { return layer_snapshot_store_; }
private:
RasterCache raster_cache_;
std::shared_ptr<TextureRegistry> texture_registry_;
Stopwatch raster_time_;
Stopwatch ui_time_;
LayerSnapshotStore layer_snapshot_store_;
/// Only used by default constructor of `CompositorContext`.
FixedRefreshRateUpdater fixed_refresh_rate_updater_;
void BeginFrame(ScopedFrame& frame, bool enable_instrumentation);
void EndFrame(ScopedFrame& frame, bool enable_instrumentation);
/// @brief Whether Impeller shouild attempt a partial repaint.
/// The Impeller backend requires an additional blit pass, which may
/// not be worthwhile if the damage region is large.
static bool ShouldPerformPartialRepaint(std::optional<SkRect> damage_rect,
SkISize layer_tree_size);
FML_DISALLOW_COPY_AND_ASSIGN(CompositorContext);
};
} // namespace flutter
#endif // FLUTTER_FLOW_COMPOSITOR_CONTEXT_H_