未验证 提交 2dc202d8 编写于 作者: J Jason Simmons 提交者: GitHub

Basic support for resizing overlay surfaces in hybrid composition (#19402)

上级 81489ece
......@@ -238,6 +238,9 @@ void AndroidExternalViewEmbedder::BeginFrame(
double device_pixel_ratio,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
Reset();
if (frame_size_ != frame_size) {
surface_pool_->DestroyLayers(jni_facade_);
}
frame_size_ = frame_size;
device_pixel_ratio_ = device_pixel_ratio;
// JNI method must be called on the platform thread.
......
......@@ -402,5 +402,20 @@ TEST(AndroidExternalViewEmbedder, DoesNotCallJNIPlatformThreadOnlyMethods) {
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
}
TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) {
auto jni_mock = std::make_shared<JNIMock>();
auto embedder =
std::make_unique<AndroidExternalViewEmbedder>(nullptr, jni_mock, nullptr);
auto raster_thread_merger = GetThreadMergerFromPlatformThread();
ASSERT_FALSE(raster_thread_merger->IsMerged());
embedder->BeginFrame(SkISize::Make(10, 20), nullptr, 1.0,
raster_thread_merger);
EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces());
embedder->BeginFrame(SkISize::Make(30, 40), nullptr, 1.0,
raster_thread_merger);
}
} // namespace testing
} // namespace flutter
......@@ -70,6 +70,13 @@ void SurfacePool::RecycleLayers() {
available_layer_index_ = 0;
}
void SurfacePool::DestroyLayers(
std::shared_ptr<PlatformViewAndroidJNI> jni_facade) {
layers_.clear();
available_layer_index_ = 0;
jni_facade->FlutterViewDestroyOverlaySurfaces();
}
std::vector<std::shared_ptr<OverlayLayer>> SurfacePool::GetUnusedLayers() {
std::vector<std::shared_ptr<OverlayLayer>> results;
for (size_t i = available_layer_index_; i < layers_.size(); i++) {
......
......@@ -64,6 +64,9 @@ class SurfacePool {
// Marks the layers in the pool as available for reuse.
void RecycleLayers();
// Destroys all the layers in the pool.
void DestroyLayers(std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
private:
// The index of the entry in the layers_ vector that determines the beginning
// of the unused layers. For example, consider the following vector:
......
......@@ -10,13 +10,16 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorSpace;
import android.graphics.PixelFormat;
import android.hardware.HardwareBuffer;
import android.media.Image;
import android.media.Image.Plane;
import android.media.ImageReader;
import android.view.Surface;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.RenderSurface;
......@@ -35,7 +38,7 @@ import io.flutter.embedding.engine.renderer.RenderSurface;
@SuppressLint("ViewConstructor")
@TargetApi(19)
public class FlutterImageView extends View implements RenderSurface {
private final ImageReader imageReader;
@NonNull private ImageReader imageReader;
@Nullable private Image nextImage;
@Nullable private Image currentImage;
@Nullable private Bitmap currentBitmap;
......@@ -63,13 +66,39 @@ public class FlutterImageView extends View implements RenderSurface {
* Constructs a {@code FlutterImageView} with an {@link android.media.ImageReader} that provides
* the Flutter UI.
*/
public FlutterImageView(
@NonNull Context context, @NonNull ImageReader imageReader, SurfaceKind kind) {
public FlutterImageView(@NonNull Context context, int width, int height, SurfaceKind kind) {
super(context, null);
this.imageReader = createImageReader(width, height);
this.kind = kind;
}
@VisibleForTesting
FlutterImageView(@NonNull Context context, @NonNull ImageReader imageReader, SurfaceKind kind) {
super(context, null);
this.imageReader = imageReader;
this.kind = kind;
}
@TargetApi(19)
@NonNull
private static ImageReader createImageReader(int width, int height) {
if (android.os.Build.VERSION.SDK_INT >= 29) {
return ImageReader.newInstance(
width,
height,
PixelFormat.RGBA_8888,
3,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT);
} else {
return ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 3);
}
}
@NonNull
public Surface getSurface() {
return imageReader.getSurface();
}
@Nullable
@Override
public FlutterRenderer getAttachedRenderer() {
......@@ -179,4 +208,15 @@ public class FlutterImageView extends View implements RenderSurface {
currentBitmap.copyPixelsFromBuffer(imagePlane.getBuffer());
}
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
if (width == imageReader.getWidth() && height == imageReader.getHeight()) {
return;
}
if (kind == SurfaceKind.background && flutterRenderer != null) {
imageReader = createImageReader(width, height);
flutterRenderer.swapSurface(imageReader.getSurface());
}
}
}
......@@ -10,7 +10,6 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Rect;
import android.media.ImageReader;
import android.os.Build;
import android.text.format.DateFormat;
import android.util.AttributeSet;
......@@ -945,9 +944,9 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
public void convertToImageView() {
renderSurface.pause();
ImageReader imageReader = PlatformViewsController.createImageReader(getWidth(), getHeight());
flutterImageView =
new FlutterImageView(getContext(), imageReader, FlutterImageView.SurfaceKind.background);
new FlutterImageView(
getContext(), getWidth(), getHeight(), FlutterImageView.SurfaceKind.background);
renderSurface = flutterImageView;
if (flutterEngine != null) {
renderSurface.attachToRenderer(flutterEngine.getRenderer());
......
......@@ -855,6 +855,17 @@ public class FlutterJNI {
}
return platformViewsController.createOverlaySurface();
}
@SuppressWarnings("unused")
@UiThread
public void destroyOverlaySurfaces() {
ensureRunningOnMainThread();
if (platformViewsController == null) {
throw new RuntimeException(
"platformViewsController must be set before attempting to destroy an overlay surface");
}
platformViewsController.destroyOverlaySurfaces();
}
// ----- End Engine Lifecycle Support ----
// ----- Start Localization Support ----
......
......@@ -9,9 +9,6 @@ import static android.view.MotionEvent.PointerProperties;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.HardwareBuffer;
import android.media.ImageReader;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
......@@ -693,29 +690,21 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
}
}
@TargetApi(19)
public static ImageReader createImageReader(int width, int height) {
if (android.os.Build.VERSION.SDK_INT >= 29) {
return ImageReader.newInstance(
width,
height,
PixelFormat.RGBA_8888,
3,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT);
} else {
return ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 3);
}
}
@TargetApi(19)
public FlutterOverlaySurface createOverlaySurface() {
ImageReader imageReader = createImageReader(flutterView.getWidth(), flutterView.getHeight());
FlutterImageView imageView =
new FlutterImageView(
flutterView.getContext(), imageReader, FlutterImageView.SurfaceKind.overlay);
flutterView.getContext(),
flutterView.getWidth(),
flutterView.getHeight(),
FlutterImageView.SurfaceKind.overlay);
int id = nextOverlayLayerId++;
overlayLayerViews.put(id, imageView);
return new FlutterOverlaySurface(id, imageReader.getSurface());
return new FlutterOverlaySurface(id, imageView.getSurface());
}
public void destroyOverlaySurfaces() {
overlayLayerViews.clear();
}
}
......@@ -80,6 +80,8 @@ class JNIMock final : public PlatformViewAndroidJNI {
(),
(override));
MOCK_METHOD(void, FlutterViewDestroyOverlaySurfaces, (), (override));
MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
FlutterViewComputePlatformResolvedLocale,
(std::vector<std::string> supported_locales_data),
......
......@@ -175,6 +175,13 @@ class PlatformViewAndroidJNI {
virtual std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
FlutterViewCreateOverlaySurface() = 0;
//----------------------------------------------------------------------------
/// @brief Destroys the overlay surfaces.
///
/// @note Must be called from the platform thread.
///
virtual void FlutterViewDestroyOverlaySurfaces() = 0;
//----------------------------------------------------------------------------
/// @brief Computes the locale Android would select.
///
......
......@@ -83,6 +83,8 @@ static jmethodID g_on_engine_restart_method = nullptr;
static jmethodID g_create_overlay_surface_method = nullptr;
static jmethodID g_destroy_overlay_surfaces_method = nullptr;
static jmethodID g_on_begin_frame_method = nullptr;
static jmethodID g_on_end_frame_method = nullptr;
......@@ -721,6 +723,14 @@ bool RegisterApi(JNIEnv* env) {
return false;
}
g_destroy_overlay_surfaces_method = env->GetMethodID(
g_flutter_jni_class->obj(), "destroyOverlaySurfaces", "()V");
if (g_destroy_overlay_surfaces_method == nullptr) {
FML_LOG(ERROR) << "Could not locate destroyOverlaySurfaces method";
return false;
}
fml::jni::ScopedJavaLocalRef<jclass> overlay_surface_class(
env, env->FindClass("io/flutter/embedding/engine/FlutterOverlaySurface"));
if (overlay_surface_class.is_null()) {
......@@ -1179,6 +1189,19 @@ PlatformViewAndroidJNIImpl::FlutterViewCreateOverlaySurface() {
overlay_id, std::move(overlay_window));
}
void PlatformViewAndroidJNIImpl::FlutterViewDestroyOverlaySurfaces() {
JNIEnv* env = fml::jni::AttachCurrentThread();
auto java_object = java_object_.get(env);
if (java_object.is_null()) {
return;
}
env->CallVoidMethod(java_object.obj(), g_destroy_overlay_surfaces_method);
FML_CHECK(CheckException(env));
}
std::unique_ptr<std::vector<std::string>>
PlatformViewAndroidJNIImpl::FlutterViewComputePlatformResolvedLocale(
std::vector<std::string> supported_locales_data) {
......
......@@ -69,6 +69,8 @@ class PlatformViewAndroidJNIImpl final : public PlatformViewAndroidJNI {
std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
FlutterViewCreateOverlaySurface() override;
void FlutterViewDestroyOverlaySurfaces() override;
std::unique_ptr<std::vector<std::string>>
FlutterViewComputePlatformResolvedLocale(
std::vector<std::string> supported_locales_data) override;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册