classDiagram
class FlutterSurfaceView {
-FlutterRenderer flutterRenderer
-SurfaceHolder_Callback surfaceCallback
}
class FlutterTextureView {
-FlutterRenderer flutterRenderer;
-Surface renderSurface;
}
class FlutterImageView {
-FlutterRenderer flutterRenderer;
-ImageReader imageReader
}
TextureView<|--FlutterTextureView
RenderSurface<|--FlutterTextureView
SurfaceView<|--FlutterSurfaceView
RenderSurface<|--FlutterSurfaceView
View<|--FlutterImageView
RenderSurface<|--FlutterImageView
class FlutterView
classDiagram
class AndroidSurface {
+SetNativeWindow(AndroidNativeWindow)
}
class AndroidSurfaceGL {
fml::RefPtr<AndroidNativeWindow> native_window_;
std::unique_ptr<AndroidEGLSurface> onscreen_surface_;
std::unique_ptr<AndroidEGLSurface> offscreen_surface_;
}
GPUSurfaceSoftwareDelegate<|--AndroidSurfaceSoftware
AndroidSurface<|--AndroidSurfaceSoftware
AndroidSurface<|--AndroidSurfaceGL
GPUSurfaceGLDelegate<|--AndroidSurfaceGL
AndroidSurface<|--AndroidSurfaceVulkan
GPUSurfaceVulkanDelegate<|--AndroidSurfaceVulkan
class GPUSurfaceGL {
GPUSurfaceGLDelegate* delegate_
sk_sp<SkSurface> onscreen_surface_
}
Surface<|--GPUSurfaceGL
class AndroidEGLSurface {
const EGLSurface surface_;
const EGLDisplay display_;
const EGLContext context_;
bool SwapBuffers();
}
graph LR
subgraph Platform
Surface
end
Surface-->|flutterRenderer.startRenderingToSurface|Rasterizer'sSurface
subgraph Native
Rasterizer'sSurface
end
subgraph Flutter
Rasterizer::DrawToSurface
end
Rasterizer::DrawToSurface-->|post and draw to|Rasterizer'sSurface
public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseCursorViewDelegate {
// Internal view hierarchy references.
@Nullable private FlutterSurfaceView flutterSurfaceView;
@Nullable private FlutterTextureView flutterTextureView;
@Nullable private FlutterImageView flutterImageView;
@Nullable private RenderSurface renderSurface;
@Nullable private RenderSurface previousRenderSurface;
private final Set<FlutterUiDisplayListener> flutterUiDisplayListeners = new HashSet<>();
private boolean isFlutterUiDisplayed;
// Connections to a Flutter execution context.
@Nullable private FlutterEngine flutterEngine;
}
public FlutterView(@NonNull Context context, @NonNull FlutterSurfaceView flutterSurfaceView) {
this(context, null, flutterSurfaceView);
}
public FlutterView(@NonNull Context context, @NonNull FlutterTextureView flutterTextureView) {
this(context, null, flutterTextureView);
}
public FlutterView(@NonNull Context context, @NonNull FlutterImageView flutterImageView) {
this(context, null, flutterImageView);
}
private FlutterSurfaceView(//FlutterTextureView和FlutterImageView构造方法类似
@NonNull Context context, @Nullable AttributeSet attrs, boolean renderTransparently) {
super(context, attrs);
this.renderTransparently = renderTransparently;
init();
}
private void init() {
Log.v(TAG, "Initializing FlutterView");
if (flutterSurfaceView != null) {
Log.v(TAG, "Internally using a FlutterSurfaceView.");
addView(flutterSurfaceView);
} else if (flutterTextureView != null) {
Log.v(TAG, "Internally using a FlutterTextureView.");
addView(flutterTextureView);
} else {
Log.v(TAG, "Internally using a FlutterImageView.");
addView(flutterImageView);
}
// FlutterView needs to be focusable so that the InputMethodManager can interact with it.
setFocusable(true);
setFocusableInTouchMode(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS);
}
}
/**
* Invoked by the owner of this {@code FlutterImageView} when it wants to begin rendering a
* Flutter UI to this {@code FlutterImageView}.
*/
@Override
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
switch (kind) {
case background:
flutterRenderer.swapSurface(imageReader.getSurface());//main
break;
case overlay:
// Do nothing since the attachment is done by the handler of
// `FlutterJNI#createOverlaySurface()` in the native side.
break;
}
setAlpha(1.0f);
this.flutterRenderer = flutterRenderer;
isAttachedToFlutterRenderer = true;
}
/**
* Swaps the {@link Surface} used to render the current frame.
*
* <p>In hybrid composition, the root surfaces changes from {@link
* android.view.SurfaceHolder#getSurface()} to {@link android.media.ImageReader#getSurface()} when
* a platform view is in the current frame.
*/
public void swapSurface(@NonNull Surface surface) {
this.surface = surface;
flutterJNI.onSurfaceWindowChanged(surface);
}
@UiThread
public void onSurfaceWindowChanged(@NonNull Surface surface) {
ensureRunningOnMainThread();
ensureAttachedToNative();
nativeSurfaceWindowChanged(nativeShellHolderId, surface);
}
private void init() {
// If transparency is desired then we'll enable a transparent pixel format and place
// our Window above everything else to get transparent background rendering.
if (renderTransparently) {
getHolder().setFormat(PixelFormat.TRANSPARENT);
setZOrderOnTop(true);
}
// Grab a reference to our underlying Surface and register callbacks with that Surface so we
// can monitor changes and forward those changes on to native Flutter code.
getHolder().addCallback(surfaceCallback);
// Keep this SurfaceView transparent until Flutter has a frame ready to render. This avoids
// displaying a black rectangle in our place.
setAlpha(0.0f);
}
// Connects the {@code Surface} beneath this {@code SurfaceView} with Flutter's native code.
// Callbacks are received by this Object and then those messages are forwarded to our
// FlutterRenderer, and then on to the JNI bridge over to native Flutter code.
private final SurfaceHolder.Callback surfaceCallback =
new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
isSurfaceAvailableForRendering = true;
if (isAttachedToFlutterRenderer) {
connectSurfaceToRenderer();
}
}
@Override
public void surfaceChanged(
@NonNull SurfaceHolder holder, int format, int width, int height) {
if (isAttachedToFlutterRenderer) {
changeSurfaceSize(width, height);
}
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
isSurfaceAvailableForRendering = false;
if (isAttachedToFlutterRenderer) {
disconnectSurfaceFromRenderer();
}
}
};
/**
* Invoked by the owner of this {@code FlutterSurfaceView} when it wants to begin rendering a
* Flutter UI to this {@code FlutterSurfaceView}.
*
* <p>If an Android {@link android.view.Surface} is available, this method will give that {@link
* android.view.Surface} to the given {@link FlutterRenderer} to begin rendering Flutter's UI to
* this {@code FlutterSurfaceView}.
*
* <p>If no Android {@link android.view.Surface} is available yet, this {@code FlutterSurfaceView}
* will wait until a {@link android.view.Surface} becomes available and then give that {@link
* android.view.Surface} to the given {@link FlutterRenderer} to begin rendering Flutter's UI to
* this {@code FlutterSurfaceView}.
*/
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
Log.v(TAG, "Attaching to FlutterRenderer.");
if (this.flutterRenderer != null) {
Log.v(
TAG,
"Already connected to a FlutterRenderer. Detaching from old one and attaching to new one.");
this.flutterRenderer.stopRenderingToSurface();
this.flutterRenderer.removeIsDisplayingFlutterUiListener(flutterUiDisplayListener);
}
this.flutterRenderer = flutterRenderer;
isAttachedToFlutterRenderer = true;
this.flutterRenderer.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
// If we're already attached to an Android window then we're now attached to both a renderer
// and the Android window. We can begin rendering now.
if (isSurfaceAvailableForRendering) {
Log.v(TAG,"Surface is available for rendering. Connecting FlutterRenderer to Android surface.");
connectSurfaceToRenderer();
}
}
// FlutterRenderer and getSurfaceTexture() must both be non-null.
private void connectSurfaceToRenderer() {
flutterRenderer.startRenderingToSurface(getHolder().getSurface());
}
// Connects the {@code SurfaceTexture} beneath this {@code TextureView} with Flutter's native
// code.
// Callbacks are received by this Object and then those messages are forwarded to our
// FlutterRenderer, and then on to the JNI bridge over to native Flutter code.
private final SurfaceTextureListener surfaceTextureListener =
new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(
SurfaceTexture surfaceTexture, int width, int height) {
Log.v(TAG, "SurfaceTextureListener.onSurfaceTextureAvailable()");
isSurfaceAvailableForRendering = true;
// If we're already attached to a FlutterRenderer then we're now attached to both a
// renderer
// and the Android window, so we can begin rendering now.
if (isAttachedToFlutterRenderer) {
connectSurfaceToRenderer();
}
}
}
public FlutterTextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// Listen for when our underlying SurfaceTexture becomes available, changes size, or
// gets destroyed, and take the appropriate actions.
setSurfaceTextureListener(surfaceTextureListener);
}
/**
* Invoked by the owner of this {@code FlutterTextureView} when it wants to begin rendering a
* Flutter UI to this {@code FlutterTextureView}.
*
* <p>If an Android {@link SurfaceTexture} is available, this method will give that {@link
* SurfaceTexture} to the given {@link FlutterRenderer} to begin rendering Flutter's UI to this
* {@code FlutterTextureView}.
*
* <p>If no Android {@link SurfaceTexture} is available yet, this {@code FlutterTextureView} will
* wait until a {@link SurfaceTexture} becomes available and then give that {@link SurfaceTexture}
* to the given {@link FlutterRenderer} to begin rendering Flutter's UI to this {@code
* FlutterTextureView}.
*/
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
Log.v(TAG, "Attaching to FlutterRenderer.");
if (this.flutterRenderer != null) {
Log.v(
TAG,
"Already connected to a FlutterRenderer. Detaching from old one and attaching to new one.");
this.flutterRenderer.stopRenderingToSurface();
}
this.flutterRenderer = flutterRenderer;
isAttachedToFlutterRenderer = true;
// If we're already attached to an Android window then we're now attached to both a renderer
// and the Android window. We can begin rendering now.
if (isSurfaceAvailableForRendering) {
Log.v(TAG,"Surface is available for rendering. Connecting FlutterRenderer to Android surface.");
connectSurfaceToRenderer();
}
}
// FlutterRenderer and getSurfaceTexture() must both be non-null.
private void connectSurfaceToRenderer() {
if (flutterRenderer == null || getSurfaceTexture() == null) {
throw new IllegalStateException(
"connectSurfaceToRenderer() should only be called when flutterRenderer and getSurfaceTexture() are non-null.");
}
renderSurface = new Surface(getSurfaceTexture());
flutterRenderer.startRenderingToSurface(renderSurface);
}
/**
* Create Surface from a {@link SurfaceTexture}.
*
* Images drawn to the Surface will be made available to the {@link
* SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
* SurfaceTexture#updateTexImage}.
*
* Please note that holding onto the Surface created here is not enough to
* keep the provided SurfaceTexture from being reclaimed. In that sense,
* the Surface will act like a
* {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
*
* @param surfaceTexture The {@link SurfaceTexture} that is updated by this
* Surface.
* @throws OutOfResourcesException if the surface could not be created.
*/
public Surface(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new IllegalArgumentException("surfaceTexture must not be null");
}
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock) {
mName = surfaceTexture.toString();
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
/**
* Represents the rendering responsibilities of a {@code FlutterEngine}.
*
* <p>{@code FlutterRenderer} works in tandem with a provided {@link RenderSurface} to paint Flutter
* pixels to an Android {@code View} hierarchy.
*
* <p>{@code FlutterRenderer} manages textures for rendering, and forwards some Java calls to native
* Flutter code via JNI. The corresponding {@link RenderSurface} provides the Android {@link
* Surface} that this renderer paints.
*
* <p>{@link io.flutter.embedding.android.FlutterSurfaceView} and {@link
* io.flutter.embedding.android.FlutterTextureView} are implementations of {@link RenderSurface}.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class FlutterRenderer implements TextureRegistry {
@NonNull private final FlutterJNI flutterJNI;
public void startRenderingToSurface(@NonNull Surface surface) {
if (this.surface != null) {
stopRenderingToSurface();
}
this.surface = surface;
flutterJNI.onSurfaceCreated(surface);
}
/**
* Call this method when a {@link Surface} has been created onto which you would like Flutter to
* paint.
*
* <p>See {@link android.view.SurfaceHolder.Callback#surfaceCreated(SurfaceHolder)} for an example
* of where this call might originate.
*/
@UiThread
public void onSurfaceCreated(@NonNull Surface surface) {
ensureRunningOnMainThread();
ensureAttachedToNative();
nativeSurfaceCreated(nativeShellHolderId, surface);
}
private native void nativeSurfaceCreated(long nativeShellHolderId, @NonNull Surface surface);
shell/platform/android/platform_view_android_jni_impl.cc
static void SurfaceCreated(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jobject jsurface) {
// Note: This frame ensures that any local references used by
// ANativeWindow_fromSurface are released immediately. This is needed as a
// workaround for https://code.google.com/p/android/issues/detail?id=68174
fml::jni::ScopedJavaLocalFrame scoped_local_reference_frame(env);
auto window = fml::MakeRefCounted<AndroidNativeWindow>(
ANativeWindow_fromSurface(env, jsurface));
ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyCreated(std::move(window));//main
}
frameworks/base/native/android/native_window_jni.cpp
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) {
sp<ANativeWindow> win = android_view_Surface_getNativeWindow(env, surface);
if (win != NULL) {
win->incStrong((void*)ANativeWindow_fromSurface);
}
return win.get();
}
frameworks/base/core/jni/android_view_Surface.cpp
sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
return android_view_Surface_getSurface(env, surfaceObj);
}
sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
sp<Surface> sur;
jobject lock = env->GetObjectField(surfaceObj,
gSurfaceClassInfo.mLock);
if (env->MonitorEnter(lock) == JNI_OK) {
sur = reinterpret_cast<Surface *>(
env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
env->MonitorExit(lock);
}
env->DeleteLocalRef(lock);
return sur;
}
static struct {
jclass clazz;
jfieldID mNativeObject;//对应java对象Surface的long mNativeObject成员变量
jfieldID mLock;
jmethodID ctor;
} gSurfaceClassInfo;
shell/platform/android/platform_view_android.cc
void PlatformViewAndroid::NotifyCreated(
fml::RefPtr<AndroidNativeWindow> native_window) {
if (android_surface_) {
InstallFirstFrameCallback();
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetRasterTaskRunner(),
[&latch, surface = android_surface_.get(),
native_window = std::move(native_window)]() {
surface->SetNativeWindow(native_window);
latch.Signal();
});
latch.Wait();
}
PlatformView::NotifyCreated();
}
bool AndroidSurfaceGL::SetNativeWindow(
fml::RefPtr<AndroidNativeWindow> window) {
FML_DCHECK(IsValid());
FML_DCHECK(window);
native_window_ = window;
// Ensure the destructor is called since it destroys the `EGLSurface` before
// creating a new onscreen surface.
onscreen_surface_ = nullptr;
// Create the onscreen surface.
onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(window);
if (!onscreen_surface_->IsValid()) {
return false;
}
return true;
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreateOnscreenSurface(
fml::RefPtr<AndroidNativeWindow> window) const {
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_NONE};
EGLSurface surface = eglCreateWindowSurface(
display, config_, reinterpret_cast<EGLNativeWindowType>(window->handle()),
attribs);
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
}
void PlatformView::NotifyCreated() {
std::unique_ptr<Surface> surface;
// Threading: We want to use the platform view on the non-platform thread.
// Using the weak pointer is illegal. But, we are going to introduce a latch
// so that the platform view is not collected till the surface is obtained.
auto* platform_view = this;
fml::ManualResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetRasterTaskRunner(), [platform_view, &surface, &latch]() {
surface = platform_view->CreateRenderingSurface();
if (surface && !surface->IsValid()) {
surface.reset();
}
latch.Signal();
});
latch.Wait();
if (!surface) {
FML_LOG(ERROR) << "Failed to create platform view rendering surface";
return;
}
delegate_.OnPlatformViewCreated(std::move(surface));//main
}
// |PlatformView::Delegate|
void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
auto raster_task =
fml::MakeCopyable([&waiting_for_first_frame = waiting_for_first_frame_,
rasterizer = rasterizer_->GetWeakPtr(), //
surface = std::move(surface), //
&latch]() mutable {
if (rasterizer) {
// Enables the thread merger which may be used by the external view
// embedder.
rasterizer->EnableThreadMergerIfNeeded();
rasterizer->Setup(std::move(surface));
}
}
void Rasterizer::Setup(std::unique_ptr<Surface> surface) {
surface_ = std::move(surface);
//lib/ui/window/platform_configuration.cc
void Render(Dart_NativeArguments args) {
Scene* scene =
tonic::DartConverter<Scene*>::FromArguments(args, 1, exception);
UIDartState::Current()->platform_configuration()->client()->Render(scene);//main
}
//runtime/runtime_controller.cc
// |PlatformConfigurationClient|
void RuntimeController::Render(Scene* scene) {
client_.Render(scene->takeLayerTree());
}
//shell/common/engine.cc
void Engine::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
animator_->Render(std::move(layer_tree));
}
//shell/common/animator.cc
void Animator::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
delegate_.OnAnimatorDraw(layer_tree_pipeline_,
std::move(frame_timings_recorder_));
}
//shell/common/shell.cc
// |Animator::Delegate|
void Shell::OnAnimatorDraw(
fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline,
std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
task_runners_.GetRasterTaskRunner()->PostTask(fml::MakeCopyable(//放置任务到rasterTaskRunner
[&waiting_for_first_frame = waiting_for_first_frame_,
&waiting_for_first_frame_condition = waiting_for_first_frame_condition_,
rasterizer = rasterizer_->GetWeakPtr(), pipeline = std::move(pipeline),
discard_callback = std::move(discard_callback),
frame_timings_recorder = std::move(frame_timings_recorder)]() mutable {
if (rasterizer) {
rasterizer->Draw(std::move(frame_timings_recorder), pipeline,//main
std::move(discard_callback));
if (waiting_for_first_frame.load()) {
waiting_for_first_frame.store(false);
waiting_for_first_frame_condition.notify_all();
}
}
}));
}
//shell/common/rasterizer.cc
void Rasterizer::Draw(
std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder,
fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline,
LayerTreeDiscardCallback discardCallback) {
RasterStatus raster_status = RasterStatus::kFailed;
Pipeline<flutter::LayerTree>::Consumer consumer =
[&](std::unique_ptr<LayerTree> layer_tree) {
if (discardCallback(*layer_tree.get())) {
raster_status = RasterStatus::kDiscarded;
} else {
raster_status =
DoDraw(std::move(frame_timings_recorder), std::move(layer_tree));//main
}
};
PipelineConsumeResult consume_result = pipeline->Consume(consumer);
}
RasterStatus Rasterizer::DoDraw(
std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder,
std::unique_ptr<flutter::LayerTree> layer_tree) {
RasterStatus raster_status =
DrawToSurface(frame_timings_recorder->GetBuildDuration(), *layer_tree);
RasterStatus Rasterizer::DrawToSurface(
const fml::TimeDelta frame_build_duration,
flutter::LayerTree& layer_tree) {
SkCanvas* embedder_root_canvas = nullptr;
if (external_view_embedder_) {
external_view_embedder_->BeginFrame(
layer_tree.frame_size(), surface_->GetContext(),
layer_tree.device_pixel_ratio(), raster_thread_merger_);
embedder_root_canvas = external_view_embedder_->GetRootCanvas();
}
auto frame = surface_->AcquireFrame(layer_tree.frame_size());
if (compositor_frame) {
RasterStatus raster_status = compositor_frame->Raster(layer_tree, false);//main
frame->Submit();//main
}
}
//shell/platform/android/external_view_embedder/external_view_embedder.cc
// |ExternalViewEmbedder|
SkCanvas* AndroidExternalViewEmbedder::GetRootCanvas() {
// On Android, the root surface is created from the on-screen render target.
return nullptr;
}
// |Surface|
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
if (delegate_ == nullptr) {
return nullptr;
}
auto context_switch = delegate_->GLContextMakeCurrent();
const auto root_surface_transformation = GetRootTransformation();
sk_sp<SkSurface> surface = AcquireRenderSurface(size, root_surface_transformation);
surface->getCanvas()->setMatrix(root_surface_transformation);
SurfaceFrame::SubmitCallback submit_callback =
[weak = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame,
SkCanvas* canvas) {
return weak ? weak->PresentSurface(canvas) : false;
};
return std::make_unique<SurfaceFrame>(
surface, delegate_->SurfaceSupportsReadback(), submit_callback,
std::move(context_switch));
sk_sp<SkSurface> GPUSurfaceGL::AcquireRenderSurface(
const SkISize& untransformed_size,
const SkMatrix& root_surface_transformation) {
if (!CreateOrUpdateSurfaces(transformed_size)) {
return nullptr;
}
return onscreen_surface_;
}
bool GPUSurfaceGL::CreateOrUpdateSurfaces(const SkISize& size) {
sk_sp<SkSurface> onscreen_surface;
GLFrameInfo frame_info = {static_cast<uint32_t>(size.width()),
static_cast<uint32_t>(size.height())};
const uint32_t fbo_id = delegate_->GLContextFBO(frame_info);
onscreen_surface = WrapOnscreenSurface(context_.get(), // GL context
size, // root surface size
fbo_id // window FBO ID
);
onscreen_surface_ = std::move(onscreen_surface);
fbo_id_ = fbo_id;
return true;
}
//flow/compositor_context.cc
RasterStatus CompositorContext::ScopedFrame::Raster(
flutter::LayerTree& layer_tree,
bool ignore_raster_cache) {
layer_tree.Paint(*this, ignore_raster_cache);
}
void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
bool ignore_raster_cache) const {
if (root_layer_->needs_painting(context)) {
root_layer_->Paint(context);//main
}
}
void ContainerLayer::Paint(PaintContext& context) const {
FML_DCHECK(needs_painting(context));
PaintChildren(context);
}
//下面的两个Paint相关方法会递归进行调用,直到进入PhysicalShapeLayerg或PictureLayer等具体的child layer
void ContainerLayer::PaintChildren(PaintContext& context) const {
// We can no longer call FML_DCHECK here on the needs_painting(context)
// condition as that test is only valid for the PaintContext that
// is initially handed to a layer's Paint() method. By the time the
// layer calls PaintChildren(), though, it may have modified the
// PaintContext so the test doesn't work in this "context".
// Intentionally not tracing here as there should be no self-time
// and the trace event on this common function has a small overhead.
for (auto& layer : layers_) {
if (layer->needs_painting(context)) {
layer->Paint(context);
}
}
}
void TransformLayer::Paint(PaintContext& context) const {
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->concat(transform_);
PaintChildren(context);
}
void PhysicalShapeLayer::Paint(PaintContext& context) const {
// Call drawPath without clip if possible for better performance.
SkPaint paint;
paint.setColor(color_);
paint.setAntiAlias(true);
if (clip_behavior_ != Clip::antiAliasWithSaveLayer) {
context.leaf_nodes_canvas->drawPath(path_, paint);//main
}
void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
this->onDrawPath(path, paint);
}
void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
AutoLayerForImageFilter layer(this, paint, &pathBounds);
this->topDevice()->drawPath(path, layer.paint());
}
void SkGpuDevice::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool pathIsMutable) {
if (!paint.getMaskFilter()) {
fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint),
fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
origSrcPath, GrStyle(paint));
return;
}
}
void GrSurfaceDrawContext::drawPath(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
const SkPath& path,
const GrStyle& style) {
GrStyledShape shape(path, style, DoSimplify::kNo);
this->drawShape(clip, std::move(paint), aa, viewMatrix, std::move(shape));
}
void GrSurfaceDrawContext::drawShape(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
GrStyledShape&& shape) {
// If we get here in drawShape(), we definitely need to use path rendering
this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, std::move(shape),
/* attemptDrawSimple */ true);
}
#通过这里后续的条用堆栈可以看出,draw过程在native层也是添加drawOperation进行绘制命令的配置
GrOpsTask::OpChain::appendOp(std::__1::unique_ptr<GrOp, std::__1::default_delete<GrOp> >, GrProcessorSet::Analysis, GrXferProcessor::DstProxyView const*, GrAppliedClip const*, GrCaps const&, SkArenaAlloc*, GrAuditTrail*) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrOpsTask.cpp:335)
GrOpsTask::recordOp(std::__1::unique_ptr<GrOp, std::__1::default_delete<GrOp> >, GrProcessorSet::Analysis, GrAppliedClip*, GrXferProcessor::DstProxyView const*, GrCaps const&) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrOpsTask.cpp:988)
GrOpsTask::addDrawOp(GrDrawingManager*, std::__1::unique_ptr<GrOp, std::__1::default_delete<GrOp> >, GrDrawOp::FixedFunctionFlags, GrProcessorSet::Analysis const&, GrAppliedClip&&, GrXferProcessor::DstProxyView const&, GrTextureResolveManager, GrCaps const&) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrOpsTask.cpp:434)
GrSurfaceDrawContext::addDrawOp(GrClip const*, std::__1::unique_ptr<GrOp, std::__1::default_delete<GrOp> >, std::__1::function<void (GrOp*, unsigned int)> const&) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrSurfaceDrawContext.cpp:1972)
GrSurfaceDrawContext::drawFilledQuad(GrClip const*, GrPaint&&, GrAA, DrawQuad*, GrUserStencilSettings const*) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrSurfaceDrawContext.cpp:646)
GrSurfaceDrawContext::fillRectToRect(GrClip const*, GrPaint&&, GrAA, SkMatrix const&, SkRect const&, SkRect const&) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrSurfaceDrawContext.cpp:836)
GrSurfaceDrawContext::drawRect(GrClip const*, GrPaint&&, GrAA, SkMatrix const&, SkRect const&, GrStyle const*) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrSurfaceDrawContext.cpp:761)
GrSurfaceDrawContext::drawSimpleShape(GrClip const*, GrPaint*, GrAA, SkMatrix const&, GrStyledShape const&) (/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrSurfaceDrawContext.cpp:1729)
GrSurfaceDrawContext::drawShapeUsingPathRenderer(GrClip const*, GrPaint&&, GrAA, SkMatrix const&, GrStyledShape&&, bool)
(/Users/qianpianpian/git/flutter/fork/engine/src/third_party/skia/src/gpu/GrSurfaceDrawContext.cpp:1814)
bool SurfaceFrame::Submit() {
submitted_ = PerformSubmit();//main
return submitted_;
}
bool SurfaceFrame::PerformSubmit() {
if (submit_callback_(*this, SkiaCanvas())) {//submit_callback_为前面acquireFrame时配置的submit_callback
return true;
}
return false;
}
SurfaceFrame::SubmitCallback submit_callback =
[weak = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame,
SkCanvas* canvas) {
return weak ? weak->PresentSurface(canvas) : false;//main
};
bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
onscreen_surface_->getCanvas()->flush();
}
void SkCanvas::flush() {
this->onFlush();
}
void SkCanvas::onFlush() {
#if SK_SUPPORT_GPU
auto dContext = GrAsDirectContext(this->recordingContext());
if (dContext) {
dContext->flushAndSubmit();//main
}
#endif
}
/** engine/src/third_party/skia/include/gpu/GrDirectContext.h
* Call to ensure all drawing to the context has been flushed and submitted to the underlying 3D
* API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by
* GrContext::submit(syncCpu).
*/
void flushAndSubmit(bool syncCpu = false) {
this->flush(GrFlushInfo());
this->submit(syncCpu);
}
///engine/src/third_party/skia/src/gpu/GrDirectContext.cpp
GrSemaphoresSubmitted GrDirectContext::flush(const GrFlushInfo& info) {
return this->drawingManager()->flushSurfaces({}, SkSurface::BackendSurfaceAccess::kNoAccess,
info, nullptr);
}
bool GrDirectContext::submit(bool syncCpu) {
if (!fGpu) {
return false;
}
return fGpu->submitToGpu(syncCpu);
}