Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 13 additions & 56 deletions fml/platform/android/message_loop_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,6 @@ namespace fml {

static constexpr int kClockType = CLOCK_MONOTONIC;

static fml::jni::ScopedJavaGlobalRef<jclass>* g_looper_class = nullptr;
static jmethodID g_looper_prepare_method_ = nullptr;
static jmethodID g_looper_loop_method_ = nullptr;
static jmethodID g_looper_my_looper_method_ = nullptr;
static jmethodID g_looper_quit_method_ = nullptr;

static void LooperPrepare() {
JNIEnv* env = fml::jni::AttachCurrentThread();
env->CallStaticVoidMethod(g_looper_class->obj(), g_looper_prepare_method_);
}

static void LooperLoop() {
JNIEnv* env = fml::jni::AttachCurrentThread();
env->CallStaticVoidMethod(g_looper_class->obj(), g_looper_loop_method_);
}

static void LooperQuit() {
JNIEnv* env = fml::jni::AttachCurrentThread();
auto my_looper = env->CallStaticObjectMethod(g_looper_class->obj(),
g_looper_my_looper_method_);
if (my_looper != nullptr) {
env->CallVoidMethod(my_looper, g_looper_quit_method_);
}
}

static ALooper* AcquireLooperForThread() {
ALooper* looper = ALooper_forThread();

Expand Down Expand Up @@ -88,15 +63,23 @@ void MessageLoopAndroid::Run() {
FML_DCHECK(looper_.get() == ALooper_forThread());

running_ = true;
// Initialize the current thread as a looper.
LooperPrepare();
// Run the message queue in this thread.
LooperLoop();

while (running_) {
int result = ::ALooper_pollOnce(-1, // infinite timeout
nullptr, // out fd,
nullptr, // out events,
nullptr // out data
);
if (result == ALOOPER_POLL_TIMEOUT || result == ALOOPER_POLL_ERROR) {
// This handles the case where the loop is terminated using ALooper APIs.
running_ = false;
}
}
}

void MessageLoopAndroid::Terminate() {
running_ = false;
LooperQuit();
ALooper_wake(looper_.get());
}

void MessageLoopAndroid::WakeUp(fml::TimePoint time_point) {
Expand All @@ -110,30 +93,4 @@ void MessageLoopAndroid::OnEventFired() {
}
}

bool MessageLoopAndroid::Register(JNIEnv* env) {
jclass clazz = env->FindClass("android/os/Looper");
FML_CHECK(clazz != nullptr);

g_looper_class = new fml::jni::ScopedJavaGlobalRef<jclass>(env, clazz);
FML_CHECK(!g_looper_class->is_null());

g_looper_prepare_method_ =
env->GetStaticMethodID(g_looper_class->obj(), "prepare", "()V");
FML_CHECK(g_looper_prepare_method_ != nullptr);

g_looper_loop_method_ =
env->GetStaticMethodID(g_looper_class->obj(), "loop", "()V");
FML_CHECK(g_looper_loop_method_ != nullptr);

g_looper_my_looper_method_ = env->GetStaticMethodID(
g_looper_class->obj(), "myLooper", "()Landroid/os/Looper;");
FML_CHECK(g_looper_my_looper_method_ != nullptr);

g_looper_quit_method_ =
env->GetMethodID(g_looper_class->obj(), "quit", "()V");
FML_CHECK(g_looper_quit_method_ != nullptr);

return true;
}

} // namespace fml
4 changes: 0 additions & 4 deletions fml/platform/android/message_loop_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include "flutter/fml/macros.h"
#include "flutter/fml/message_loop_impl.h"
#include "flutter/fml/platform/android/jni_util.h"
#include "flutter/fml/unique_fd.h"

namespace fml {
Expand All @@ -27,9 +26,6 @@ struct UniqueLooperTraits {
/// This implemenation wraps usage of Android's \p looper.
/// \see https://developer.android.com/ndk/reference/group/looper
class MessageLoopAndroid : public MessageLoopImpl {
public:
static bool Register(JNIEnv* env);

private:
fml::UniqueObject<ALooper*, UniqueLooperTraits> looper_;
fml::UniqueFD timer_fd_;
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/painting/fragment_program.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void FragmentProgram::init(std::string sksl, bool debugPrintSksl) {

fml::RefPtr<FragmentShader> FragmentProgram::shader(
Dart_Handle shader,
const tonic::Float32List& uniforms,
tonic::Float32List& uniforms,
Dart_Handle samplers) {
auto sampler_shaders =
tonic::DartConverter<std::vector<ImageShader*>>::FromDart(samplers);
Expand All @@ -69,6 +69,7 @@ fml::RefPtr<FragmentShader> FragmentProgram::shader(
for (size_t i = 0; i < uniform_count; i++) {
uniform_floats[i] = uniforms[i];
}
uniforms.Release();
std::vector<sk_sp<SkShader>> sk_samplers(sampler_shaders.size());
for (size_t i = 0; i < sampler_shaders.size(); i++) {
ImageShader* image_shader = sampler_shaders[i];
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/painting/fragment_program.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class FragmentProgram : public RefCountedDartWrappable<FragmentProgram> {
void init(std::string sksl, bool debugPrintSksl);

fml::RefPtr<FragmentShader> shader(Dart_Handle shader,
const tonic::Float32List& uniforms,
tonic::Float32List& uniforms,
Dart_Handle samplers);

static void RegisterNatives(tonic::DartLibraryNatives* natives);
Expand Down
11 changes: 7 additions & 4 deletions lib/ui/painting/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,16 +253,17 @@ void CanvasPath::addPathWithMatrix(CanvasPath* path,
double dy,
tonic::Float64List& matrix4) {
if (!path) {
matrix4.Release();
Dart_ThrowException(
ToDart("Path.addPathWithMatrix called with non-genuine Path."));
return;
}

SkMatrix matrix = ToSkMatrix(matrix4);
matrix4.Release();
matrix.setTranslateX(matrix.getTranslateX() + dx);
matrix.setTranslateY(matrix.getTranslateY() + dy);
mutable_path().addPath(path->path(), matrix, SkPath::kAppend_AddPathMode);
matrix4.Release();
resetVolatility();
}

Expand All @@ -281,16 +282,17 @@ void CanvasPath::extendWithPathAndMatrix(CanvasPath* path,
double dy,
tonic::Float64List& matrix4) {
if (!path) {
matrix4.Release();
Dart_ThrowException(
ToDart("Path.addPathWithMatrix called with non-genuine Path."));
return;
}

SkMatrix matrix = ToSkMatrix(matrix4);
matrix4.Release();
matrix.setTranslateX(matrix.getTranslateX() + dx);
matrix.setTranslateY(matrix.getTranslateY() + dy);
mutable_path().addPath(path->path(), matrix, SkPath::kExtend_AddPathMode);
matrix4.Release();
resetVolatility();
}

Expand All @@ -317,10 +319,11 @@ void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) {

void CanvasPath::transform(Dart_Handle path_handle,
tonic::Float64List& matrix4) {
auto sk_matrix = ToSkMatrix(matrix4);
matrix4.Release();
fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle);
auto& other_mutable_path = path->mutable_path();
mutable_path().transform(ToSkMatrix(matrix4), &other_mutable_path);
matrix4.Release();
mutable_path().transform(sk_matrix, &other_mutable_path);
}

tonic::Float32List CanvasPath::getBounds() {
Expand Down
14 changes: 10 additions & 4 deletions lib/ui/painting/vertices.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ void Vertices::RegisterNatives(tonic::DartLibraryNatives* natives) {

bool Vertices::init(Dart_Handle vertices_handle,
SkVertices::VertexMode vertex_mode,
const tonic::Float32List& positions,
const tonic::Float32List& texture_coordinates,
const tonic::Int32List& colors,
const tonic::Uint16List& indices) {
tonic::Float32List& positions,
tonic::Float32List& texture_coordinates,
tonic::Int32List& colors,
tonic::Uint16List& indices) {
UIDartState::ThrowIfUIOperationsProhibited();
uint32_t builderFlags = 0;
if (texture_coordinates.data()) {
Expand Down Expand Up @@ -76,6 +76,7 @@ bool Vertices::init(Dart_Handle vertices_handle,
FML_DCHECK(positions.num_elements() == texture_coordinates.num_elements());
DecodePoints(texture_coordinates, builder.texCoords());
}

if (colors.data()) {
// SkVertices::Builder assumes equal numbers of elements
FML_DCHECK(positions.num_elements() / 2 == colors.num_elements());
Expand All @@ -87,6 +88,11 @@ bool Vertices::init(Dart_Handle vertices_handle,
builder.indices());
}

positions.Release();
texture_coordinates.Release();
colors.Release();
indices.Release();

auto vertices = fml::MakeRefCounted<Vertices>();
vertices->vertices_ = builder.detach();
vertices->AssociateWithDartWrapper(vertices_handle);
Expand Down
8 changes: 4 additions & 4 deletions lib/ui/painting/vertices.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ class Vertices : public RefCountedDartWrappable<Vertices> {

static bool init(Dart_Handle vertices_handle,
SkVertices::VertexMode vertex_mode,
const tonic::Float32List& positions,
const tonic::Float32List& texture_coordinates,
const tonic::Int32List& colors,
const tonic::Uint16List& indices);
tonic::Float32List& positions,
tonic::Float32List& texture_coordinates,
tonic::Int32List& colors,
tonic::Uint16List& indices);

const sk_sp<SkVertices>& vertices() const { return vertices_; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,9 @@ public void setRefreshRateFPS(float refreshRateFPS) {

/**
* The Android vsync waiter implementation in C++ needs to know when a vsync signal arrives, which
* is obtained via Java API. The delegate set here is called on the C++ side on the ui thread when
* the engine is ready to wait for the next vsync signal. The delegate is expected to add a
* postFrameCallback to the {@link android.view.Choreographer}, and call {@link onVsync} to notify
* the engine.
* is obtained via Java API. The delegate set here is called on the C++ side when the engine is
* ready to wait for the next vsync signal. The delegate is expected to add a postFrameCallback to
* the {@link android.view.Choreographer}, and call {@link onVsync} to notify the engine.
*
* @param delegate The delegate that will call the engine back on the next vsync signal.
*/
Expand All @@ -273,7 +272,7 @@ public void setAsyncWaitForVsyncDelegate(@Nullable AsyncWaitForVsyncDelegate del
}

// TODO(mattcarroll): add javadocs
// Called by native on the ui thread.
// Called by native.
private static void asyncWaitForVsync(final long cookie) {
if (asyncWaitForVsyncDelegate != null) {
asyncWaitForVsyncDelegate.asyncWaitForVsync(cookie);
Expand Down
5 changes: 0 additions & 5 deletions shell/platform/android/library_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// found in the LICENSE file.

#include "flutter/fml/platform/android/jni_util.h"
#include "flutter/fml/platform/android/message_loop_android.h"
#include "flutter/shell/platform/android/android_image_generator.h"
#include "flutter/shell/platform/android/flutter_main.h"
#include "flutter/shell/platform/android/platform_view_android.h"
Expand Down Expand Up @@ -33,9 +32,5 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
result = flutter::AndroidImageGenerator::Register(env);
FML_CHECK(result);

// Register MessageLoopAndroid.
result = fml::MessageLoopAndroid::Register(env);
FML_CHECK(result);

return JNI_VERSION_1_4;
}
12 changes: 7 additions & 5 deletions shell/platform/android/vsync_waiter_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ void VsyncWaiterAndroid::AwaitVSync() {
auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
jlong java_baton = reinterpret_cast<jlong>(weak_this);

JNIEnv* env = fml::jni::AttachCurrentThread();
env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
g_async_wait_for_vsync_method_, //
java_baton //
);
task_runners_.GetPlatformTaskRunner()->PostTask([java_baton]() {
JNIEnv* env = fml::jni::AttachCurrentThread();
env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
g_async_wait_for_vsync_method_, //
java_baton //
);
});
}

// static
Expand Down