Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9bc3559 authored by Ruben Brunk's avatar Ruben Brunk
Browse files

camera2: Fix shim aspect ratio scaling.

Bug: 16494207
Change-Id: I4bd40dee1caaf8c83a0853d48d44cc97151f9b41
parent a2897ea9
Loading
Loading
Loading
Loading
+25 −24
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.hardware.camera2.legacy;

import android.graphics.ImageFormat;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.os.Environment;
import android.opengl.EGL14;
@@ -194,6 +195,9 @@ public class SurfaceTextureRenderer {
        checkGlError("onDrawFrame start");
        st.getTransformMatrix(mSTMatrix);

        Matrix.setIdentityM(mMVPMatrix, /*smOffset*/0);

        // Find intermediate buffer dimensions
        Size dimens;
        try {
            dimens = LegacyCameraDevice.getTextureSize(st);
@@ -201,9 +205,6 @@ public class SurfaceTextureRenderer {
            // Should never hit this.
            throw new IllegalStateException("Surface abandoned, skipping drawFrame...", e);
        }

        Matrix.setIdentityM(mMVPMatrix, /*smOffset*/0);

        float texWidth = dimens.getWidth();
        float texHeight = dimens.getHeight();

@@ -211,32 +212,30 @@ public class SurfaceTextureRenderer {
            throw new IllegalStateException("Illegal intermediate texture with dimension of 0");
        }

        // Find largest scaling factor from the intermediate texture dimension to the
        // output surface dimension.  Scaling the intermediate texture by this allows
        // us to letterbox/pillerbox the output surface into the intermediate texture.
        float widthRatio = width / texWidth;
        float heightRatio = height / texHeight;
        float actual = (widthRatio < heightRatio) ? heightRatio : widthRatio;

        if (DEBUG) {
            Log.d(TAG, "Scaling factor " + actual + " used for " + width + "x" + height +
                    " surface, intermediate buffer size is " + texWidth + "x" + texHeight);
        }
        // Letterbox or pillerbox output dimensions into intermediate dimensions.
        RectF intermediate = new RectF(/*left*/0, /*top*/0, /*right*/texWidth, /*bottom*/texHeight);
        RectF output = new RectF(/*left*/0, /*top*/0, /*right*/width, /*bottom*/height);
        android.graphics.Matrix boxingXform = new android.graphics.Matrix();
        boxingXform.setRectToRect(output, intermediate, android.graphics.Matrix.ScaleToFit.CENTER);
        boxingXform.mapRect(output);

        // Set the viewport height and width to be the scaled intermediate texture dimensions.
        int viewportW = (int) (actual * texWidth);
        int viewportH = (int) (actual * texHeight);
        // Find scaling factor from pillerboxed/letterboxed output dimensions to intermediate
        // buffer dimensions.
        float scaleX = intermediate.width() / output.width();
        float scaleY = intermediate.height() / output.height();

        // Set the offset of the viewport so that the output surface is centered in the viewport.
        float dx = (width - viewportW) / 2f;
        float dy = (height - viewportH) / 2f;
        // Scale opposite dimension in clip coordinates so output is letterboxed/pillerboxed into
        // the intermediate dimensions (rather than vice-versa).
        Matrix.scaleM(mMVPMatrix, /*offset*/0, /*x*/scaleY, /*y*/scaleX, /*z*/1);

        if (DEBUG) {
            Log.d(TAG, "Translation " + dx + "," + dy + " used for " + width + "x" + height +
                    " surface");
            Log.d(TAG, "Scaling factors (S_x = " + scaleX + ",S_y = " + scaleY + ") used for " +
                    width + "x" + height + " surface, intermediate buffer size is " + texWidth +
                    "x" + texHeight);
        }

        GLES20.glViewport((int) dx, (int) dy, viewportW, viewportH);
        // Set viewport to be output buffer dimensions
        GLES20.glViewport(0, 0, width, height);

        if (DEBUG) {
            GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
@@ -654,6 +653,8 @@ public class SurfaceTextureRenderer {
            if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) {
                makeCurrent(holder.eglSurface);
                try {
                    LegacyCameraDevice.setSurfaceDimens(holder.surface, holder.width,
                            holder.height);
                    LegacyCameraDevice.setNextTimestamp(holder.surface, captureHolder.second);
                    drawFrame(mSurfaceTexture, holder.width, holder.height);
                    swapBuffers(holder.eglSurface);
+9 −0
Original line number Diff line number Diff line
@@ -541,6 +541,15 @@ static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz,
        ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err);
        return err;
    }

    // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation
    // change.
    err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
    if (err != NO_ERROR) {
        ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
                err);
        return err;
    }
    return NO_ERROR;
}