From 3aff2e3556d24851e6c939e1daa4b733090e6a9f Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Wed, 26 Jun 2019 13:51:14 -0700 Subject: [PATCH] [android] External textures must be rescaled to fill the canvas (#9501) * [android] External textures must be rescaled to fill the canvas - After composition, we have a tight box that we need to fill. - Video decoders typically operate using output buffers that are a whole number of blocks (vertically and horizontally). This fixes https://github.com/flutter/flutter/issues/34641 where the decoded dimensions are rounded up. - The cropping information for the current frame arrives in the form of `SurfaceTexture.getTransformMatrix`. When we apply this transform we need to account for the fact that we have already composited. This means that in cases where the scaleX, scaleY are less than 1, we need to rescale the image. We do this while preserving the aspect ratio. --- .../android/android_external_texture_gl.cc | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/android_external_texture_gl.cc b/shell/platform/android/android_external_texture_gl.cc index 0acd0c833..935f60b45 100644 --- a/shell/platform/android/android_external_texture_gl.cc +++ b/shell/platform/android/android_external_texture_gl.cc @@ -68,6 +68,18 @@ void AndroidExternalTextureGL::Paint(SkCanvas& canvas, } } +// The bounds we set for the canvas are post composition. +// To fill the canvas we need to ensure that the transformation matrix +// on the `SurfaceTexture` will be scaled to fill. We rescale and preseve +// the scaled aspect ratio. +SkSize ScaleToFill(float scaleX, float scaleY) { + const double epsilon = std::numeric_limits::epsilon(); + // scaleY is negative. + const double minScale = fmin(scaleX, fabs(scaleY)); + const double rescale = 1.0f / (minScale + epsilon); + return SkSize::Make(scaleX * rescale, scaleY * rescale); +} + void AndroidExternalTextureGL::UpdateTransform() { JNIEnv* env = fml::jni::AttachCurrentThread(); fml::jni::ScopedJavaLocalRef surfaceTexture = @@ -77,10 +89,12 @@ void AndroidExternalTextureGL::UpdateTransform() { SurfaceTextureGetTransformMatrix(env, surfaceTexture.obj(), transformMatrix.obj()); float* m = env->GetFloatArrayElements(transformMatrix.obj(), nullptr); + float scaleX = m[0], scaleY = m[5]; + const SkSize scaled = ScaleToFill(scaleX, scaleY); SkScalar matrix3[] = { - m[0], m[1], m[2], // - m[4], m[5], m[6], // - m[8], m[9], m[10], // + scaled.fWidth, m[1], m[2], // + m[4], scaled.fHeight, m[6], // + m[8], m[9], m[10], // }; env->ReleaseFloatArrayElements(transformMatrix.obj(), m, JNI_ABORT); transform.set9(matrix3); -- GitLab