Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
9 changes: 8 additions & 1 deletion flow/layers/transform_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
//
// We have to write this flaky test because there is no reliable way to test
// whether a variable is initialized or not in C++.
FML_CHECK(transform_.isFinite());

//fix crash:https://github.com/flutter/flutter/issues/31650
// FML_CHECK(transform_.isFinite());
FML_DCHECK(transform_.isFinite());
if (!transform_.isFinite()) {
FML_LOG(ERROR) << "TransformLayer is constructed with an invalid matrix.";
transform_.setIdentity();
}

SkMatrix child_matrix;
child_matrix.setConcat(matrix, transform_);
Expand Down
28 changes: 22 additions & 6 deletions fml/message_loop_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ fml::RefPtr<MessageLoopImpl> MessageLoopImpl::Create() {
#endif
}

MessageLoopImpl::MessageLoopImpl() : order_(0), terminated_(false) {}
MessageLoopImpl::MessageLoopImpl()
: order_(0), terminated_(false), task_limit_per_looprun_(10000) {}

MessageLoopImpl::~MessageLoopImpl() = default;

Expand Down Expand Up @@ -112,28 +113,39 @@ void MessageLoopImpl::FlushTasks(FlushType type) {
TRACE_EVENT0("fml", "MessageLoop::FlushTasks");
std::vector<fml::closure> invocations;

int i_tasks_cnt = 0;
bool need_call_run_again = false;
auto now = fml::TimePoint::Now();

{
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);

if (delayed_tasks_.empty()) {
if (delayed_tasks_.empty() || !IsMessageLoopEnabled()) {
return;
}

auto now = fml::TimePoint::Now();
while (!delayed_tasks_.empty()) {
is_runninging_expired_tasks_ = true;
while (!delayed_tasks_.empty() && i_tasks_cnt < task_limit_per_looprun_) {
const auto& top = delayed_tasks_.top();
if (top.target_time > now) {
break;
}
invocations.emplace_back(std::move(top.task));
delayed_tasks_.pop();
i_tasks_cnt++;
if (type == FlushType::kSingle) {
break;
}
}

WakeUp(delayed_tasks_.empty() ? fml::TimePoint::Max()
: delayed_tasks_.top().target_time);
// WakeUp(delayed_tasks_.empty() ? fml::TimePoint::Max()
// : delayed_tasks_.top().target_time);
if (i_tasks_cnt >= task_limit_per_looprun_ && !delayed_tasks_.empty()) {
need_call_run_again = true;
} else {
WakeUp(delayed_tasks_.empty() ? fml::TimePoint::Max()
: delayed_tasks_.top().target_time);
}
}

for (const auto& invocation : invocations) {
Expand All @@ -142,6 +154,10 @@ void MessageLoopImpl::FlushTasks(FlushType type) {
observer.second();
}
}
is_runninging_expired_tasks_ = false;
if (need_call_run_again) {
FlushTasks(FlushType::kAll);
}
}

void MessageLoopImpl::RunExpiredTasksNow() {
Expand Down
17 changes: 17 additions & 0 deletions fml/message_loop_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ class MessageLoopImpl : public fml::RefCountedThreadSafe<MessageLoopImpl> {

void DoTerminate();

void EnableMessageLoop(bool isEnable) { is_loop_enabled_ = isEnable; }

void SetTaskLimitPerLoopRun(int task_limit_per_looprun) {
task_limit_per_looprun_ = task_limit_per_looprun;
}

inline bool IsMessageLoopEnabled() { return is_loop_enabled_; }

inline bool IsRunningingExpiredTasks() {
return is_runninging_expired_tasks_;
}


protected:
// Exposed for the embedder shell which allows clients to poll for events
// instead of dedicating a thread to the message loop.
Expand Down Expand Up @@ -80,12 +93,16 @@ class MessageLoopImpl : public fml::RefCountedThreadSafe<MessageLoopImpl> {
using DelayedTaskQueue = std::
priority_queue<DelayedTask, std::deque<DelayedTask>, DelayedTaskCompare>;

bool is_loop_enabled_ = true;
std::map<intptr_t, fml::closure> task_observers_;
std::mutex delayed_tasks_mutex_;
DelayedTaskQueue delayed_tasks_ FML_GUARDED_BY(delayed_tasks_mutex_);
size_t order_ FML_GUARDED_BY(delayed_tasks_mutex_);
std::atomic_bool terminated_;

bool is_runninging_expired_tasks_;
int task_limit_per_looprun_;

void RegisterTask(fml::closure task, fml::TimePoint target_time);

enum class FlushType {
Expand Down
8 changes: 8 additions & 0 deletions fml/task_runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ bool TaskRunner::RunsTasksOnCurrentThread() {
return MessageLoop::GetCurrent().GetLoopImpl() == loop_;
}

void TaskRunner::EnableMessageLoop(bool isEnable) {
loop_->EnableMessageLoop(isEnable);
}

MessageLoopImpl* TaskRunner::getMessageLoop() {
return loop_.get();
}

void TaskRunner::RunNowOrPostTask(fml::RefPtr<fml::TaskRunner> runner,
fml::closure task) {
FML_DCHECK(runner);
Expand Down
3 changes: 3 additions & 0 deletions fml/task_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class TaskRunner : public fml::RefCountedThreadSafe<TaskRunner> {

virtual bool RunsTasksOnCurrentThread();

void EnableMessageLoop(bool isEnable);
MessageLoopImpl* getMessageLoop();

static void RunNowOrPostTask(fml::RefPtr<fml::TaskRunner> runner,
fml::closure task);

Expand Down
8 changes: 8 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,14 @@ Rasterizer::Screenshot Shell::Screenshot(
Rasterizer::ScreenshotType screenshot_type,
bool base64_encode) {
TRACE_EVENT0("flutter", "Shell::Screenshot");
fml::TaskRunner* taskRunner =
(fml::TaskRunner*)this->GetTaskRunners().GetUITaskRunner().get();
taskRunner->EnableMessageLoop(true);

taskRunner =
(fml::TaskRunner*)this->GetTaskRunners().GetGPUTaskRunner().get();
taskRunner->EnableMessageLoop(true);

fml::AutoResetWaitableEvent latch;
Rasterizer::Screenshot screenshot;
fml::TaskRunner::RunNowOrPostTask(
Expand Down
10 changes: 10 additions & 0 deletions shell/platform/android/android_context_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ static EGLResult<EGLSurface> CreateContext(EGLDisplay display,
EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

EGLContext context = eglCreateContext(display, config, share, attributes);
if (context == EGL_NO_CONTEXT) {
EGLint last_error = eglGetError();
if (last_error == EGL_BAD_MATCH && share != EGL_NO_CONTEXT) {
context = eglCreateContext(display, config, EGL_NO_CONTEXT, attributes);
}
}

return {context != EGL_NO_CONTEXT, context};
}
Expand Down Expand Up @@ -143,6 +149,10 @@ bool AndroidContextGL::CreatePBufferSurface() {
return surface_ != EGL_NO_SURFACE;
}

void* AndroidContextGL::GetContext() {
return context_;
}

AndroidContextGL::AndroidContextGL(fml::RefPtr<AndroidEnvironmentGL> env,
const AndroidContextGL* share_context)
: environment_(env),
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/android/android_context_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class AndroidContextGL : public fml::RefCountedThreadSafe<AndroidContextGL> {

bool Resize(const SkISize& size);

void* GetContext();

private:
fml::RefPtr<AndroidEnvironmentGL> environment_;
fml::RefPtr<AndroidNativeWindow> window_;
Expand Down
30 changes: 23 additions & 7 deletions shell/platform/android/android_external_texture_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ AndroidExternalTextureGL::AndroidExternalTextureGL(
int64_t id,
const fml::jni::JavaObjectWeakGlobalRef& surfaceTexture)
: Texture(id), surface_texture_(surfaceTexture), transform(SkMatrix::I()) {}

AndroidExternalTextureGL::AndroidExternalTextureGL(int64_t id,
int64_t texture_id)
: Texture(id), texture_name_(texture_id) {
use_out_texture_ = true;
}

AndroidExternalTextureGL::~AndroidExternalTextureGL() {
if (state_ == AttachmentState::attached) {
glDeleteTextures(1, &texture_name_);
}
}
if (texture_name_ != 0 && !use_out_texture_) {
glDeleteTextures(1, &texture_name_);
texture_name_ = 0;
}
};

void AndroidExternalTextureGL::OnGrContextCreated() {
state_ = AttachmentState::uninitialized;
Expand All @@ -38,16 +45,25 @@ void AndroidExternalTextureGL::Paint(SkCanvas& canvas,
return;
}
if (state_ == AttachmentState::uninitialized) {
glGenTextures(1, &texture_name_);
Attach(static_cast<jint>(texture_name_));
if (!use_out_texture_) {
glGenTextures(1, &texture_name_);
Attach(static_cast<jint>(texture_name_));
}
state_ = AttachmentState::attached;
}
if (!freeze && new_frame_ready_) {
Update();
if (!use_out_texture_) {
Update();
}
new_frame_ready_ = false;
}
GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_name_,
GL_RGBA8_OES};
if (use_out_texture_) {
textureInfo.fTarget = GL_TEXTURE_2D;
transform.setIdentity();
}

GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo);
sk_sp<SkImage> image = SkImage::MakeFromTexture(
canvas.getGrContext(), backendTexture, kTopLeft_GrSurfaceOrigin,
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/android/android_external_texture_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class AndroidExternalTextureGL : public flutter::Texture {
AndroidExternalTextureGL(
int64_t id,
const fml::jni::JavaObjectWeakGlobalRef& surfaceTexture);
AndroidExternalTextureGL(int64_t id, int64_t texture_id);

~AndroidExternalTextureGL() override;

Expand Down Expand Up @@ -47,6 +48,8 @@ class AndroidExternalTextureGL : public flutter::Texture {

bool new_frame_ready_ = false;

bool use_out_texture_ = false;

GLuint texture_name_ = 0;

SkMatrix transform;
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/android/android_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class AndroidSurface {
virtual bool ResourceContextClearCurrent() = 0;

virtual bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) = 0;

virtual void* GetContext() = 0;
};

} // namespace flutter
Expand Down
4 changes: 4 additions & 0 deletions shell/platform/android/android_surface_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ bool AndroidSurfaceGL::ResourceContextClearCurrent() {
return offscreen_context_->ClearCurrent();
}

void* AndroidSurfaceGL::GetContext() {
return offscreen_context_->GetContext();
}

bool AndroidSurfaceGL::SetNativeWindow(
fml::RefPtr<AndroidNativeWindow> window) {
// In any case, we want to get rid of our current onscreen context.
Expand Down
1 change: 1 addition & 0 deletions shell/platform/android/android_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO() const override;

void* GetContext() override;
private:
fml::RefPtr<AndroidContextGL> onscreen_context_;
fml::RefPtr<AndroidContextGL> offscreen_context_;
Expand Down
4 changes: 4 additions & 0 deletions shell/platform/android/android_surface_software.cc
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ bool AndroidSurfaceSoftware::OnScreenSurfaceResize(const SkISize& size) const {
return true;
}

void* AndroidSurfaceSoftware::GetContext() {
return 0;
}

bool AndroidSurfaceSoftware::SetNativeWindow(
fml::RefPtr<AndroidNativeWindow> window) {
native_window_ = std::move(window);
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/android/android_surface_software.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class AndroidSurfaceSoftware final : public AndroidSurface,
// |GPUSurfaceSoftwareDelegate|
bool PresentBackingStore(sk_sp<SkSurface> backing_store) override;

void* GetContext() override;

private:
sk_sp<SkSurface> sk_surface_;
fml::RefPtr<AndroidNativeWindow> native_window_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import android.support.annotation.UiThread;
import android.util.Log;
import android.view.Surface;
import android.opengl.EGLContext;

import java.nio.ByteBuffer;
import java.util.HashSet;
Expand Down Expand Up @@ -409,7 +410,25 @@ public void unregisterTexture(long textureId) {
}

private native void nativeUnregisterTexture(long nativePlatformViewId, long textureId);
//------- End from FlutterView -----

@UiThread
public void registerGLTexture(long texIndex, long textureId) {
ensureAttachedToNative();
nativeGLRegisterTexture(nativePlatformViewId, texIndex, textureId);
}

private native void nativeGLRegisterTexture(long nativePlatformViewId, long texIndex, long textureId);

@UiThread
public EGLContext getGLContext() {
ensureAttachedToNative();
return nativeGetContext(nativePlatformViewId);
}

private native EGLContext nativeGetContext(long nativePlatformViewId);


//------- End from FlutterView -----

// TODO(mattcarroll): rename comments after refactor is done and their origin no longer matters (https://github.com/flutter/flutter/issues/25533)
//------ Start from FlutterNativeView ----
Expand Down
Loading