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

Commit 913949db authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Simplify matrix calculations for display adjustment"

parents f2d9391b 36f4b083
Loading
Loading
Loading
Loading
+0 −119
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.util;

import java.util.Arrays;

/**
 * A class that contains utility methods related to matrices.
 *
 * @hide
 */
public class MatrixUtils {
    private MatrixUtils() {
        // This class is non-instantiable.
    }

    /**
     * Sets a matrix to the identity matrix.
     *
     * @param out output matrix of size n*m
     * @param n number of rows in the output matrix
     * @param m number of columns in the output matrix
     */
    public static void setIdentityM(float[] out, int n, int m) {
        final int size = n * m;
        if (out.length != size) {
            throw new IllegalArgumentException("Invalid dimensions for output matrix");
        }

        Arrays.fill(out, 0, size, 0);
        for (int i = Math.min(m,n) - 1; i >= 0; i--) {
            out[i * (m + 1)] = 1;
        }
    }

    /**
     * Add two matrices. May be used in-place by specifying the same value for
     * the out matrix and one of the input matrices.
     *
     * @param ab output matrix of size n*m
     * @param a left-hand matrix of size n*m
     * @param n number of rows in the left-hand matrix
     * @param m number of columns in the left-hand matrix
     * @param b right-hand matrix of size n*m
     */
    public static void addMM(float[] ab, float[] a, int n, int m, float[] b) {
        final int size = n * m;
        if (a.length != size) {
            throw new IllegalArgumentException("Invalid dimensions for matrix a");
        } else if (b.length != size) {
            throw new IllegalArgumentException("Invalid dimensions for matrix b");
        } else if (ab.length != size) {
            throw new IllegalArgumentException("Invalid dimensions for matrix ab");
        }

        for (int i = 0; i < size; i++) {
            ab[i] = a[i] + b[i];
        }
    }

    /**
     * Multiply two matrices.
     *
     * @param ab output matrix of size n*p
     * @param a left-hand matrix of size n*m
     * @param n number of rows in the left-hand matrix
     * @param m number of columns in the left-hand matrix
     * @param b right-hand matrix of size m*p
     * @param p number of columns in the right-hand matrix
     */
    public static void multiplyMM(float[] ab, float[] a, int n, int m, float[] b, int p) {
        if (a.length != n * m) {
            throw new IllegalArgumentException("Invalid dimensions for matrix a");
        } else if (b.length != m * p) {
            throw new IllegalArgumentException("Invalid dimensions for matrix b");
        } else if (ab.length != n * p) {
            throw new IllegalArgumentException("Invalid dimensions for matrix ab");
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < p; j++) {
                float sum = 0;
                for (int k = 0; k < m; k++) {
                    sum += a[i * m + k] * b[k * p + j];
                }
                ab[i * p + j] = sum;
            }
        }
    }

    /**
     * Multiply a matrix by a scalar value. May be used in-place by specifying
     * the same value for the input and output matrices.
     *
     * @param out output matrix
     * @param in input matrix
     * @param scalar scalar value
     */
    public static void multiplyMS(float[] out, float[] in, float scalar) {
        final int n = out.length;
        for (int i = 0; i < n; i++) {
            out[i] = in[i] * scalar;
        }
    }
}
+44 −65
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.opengl.Matrix;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -62,7 +63,6 @@ import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.MatrixUtils;
import android.util.Pools.Pool;
import android.util.Pools.SimplePool;
import android.util.Slog;
@@ -141,43 +141,38 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {

    private static final int MAX_POOL_SIZE = 10;

    /** Matrix used for converting color to grayscale. */
    /** Matrix and offset used for converting color to grayscale. */
    private static final float[] GRAYSCALE_MATRIX = new float[] {
        .2126f, .2126f, .2126f,
        .7152f, .7152f, .7152f,
        .0722f, .0722f, .0722f
        .2126f, .2126f, .2126f, 0,
        .7152f, .7152f, .7152f, 0,
        .0722f, .0722f, .0722f, 0,
             0,      0,      0, 1
    };

    /** Matrix used for standard display inversion. */
    /** Matrix and offset used for standard display inversion. */
    private static final float[] INVERSION_MATRIX_STANDARD = new float[] {
        -1,  0,  0,
         0, -1,  0,
         0,  0, -1
        -1,  0,  0, 0,
         0, -1,  0, 0,
         0,  0, -1, 0,
         1,  1,  1, 1
    };

    /** Offset used for standard display inversion. */
    private static final float INVERSION_OFFSET_STANDARD = 1;

    /** Matrix and offset used for hue-only display inversion. */
    private static final float[] INVERSION_MATRIX_HUE_ONLY = new float[] {
          0, .5f, .5f,
        .5f,   0, .5f,
        .5f, .5f,   0
          0, .5f, .5f, 0,
        .5f,   0, .5f, 0,
        .5f, .5f,   0, 0,
          0,   0,   0, 1
    };

    /** Offset used for hue-only display inversion. */
    private static final float INVERSION_OFFSET_HUE_ONLY = 0;

    /** Matrix and offset used for value-only display inversion. */
    private static final float[] INVERSION_MATRIX_VALUE_ONLY = new float[] {
           0, -.5f, -.5f,
        -.5f,    0, -.5f,
        -.5f, -.5f,    0
           0, -.5f, -.5f, 0,
        -.5f,    0, -.5f, 0,
        -.5f, -.5f,    0, 0,
           1,    1,    1, 1
    };

    /** Offset used for value-only display inversion. */
    private static final float INVERSION_OFFSET_VALUE_ONLY = 1;

    /** Default contrast for display contrast enhancement. */
    private static final float DEFAULT_DISPLAY_CONTRAST = 2;

@@ -1486,14 +1481,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
    private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) {
        final ContentResolver cr = mContext.getContentResolver();
        final int userId = userState.mUserId;
        final float[] offsetVector = new float[3];
        float[] colorOffset = new float[3];
        float[] outputOffset = new float[3];
        float[] colorMatrix = new float[9];
        float[] outputMatrix = new float[9];
        float[] colorMatrix = new float[16];
        float[] outputMatrix = new float[16];
        boolean hasColorTransform = false;

        MatrixUtils.setIdentityM(colorMatrix, 3, 3);
        Matrix.setIdentityM(colorMatrix, 0);

        final boolean inversionEnabled = Settings.Secure.getIntForUser(
                cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1;
@@ -1502,30 +1494,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                    Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION, DEFAULT_DISPLAY_INVERSION,
                    userId);
            final float[] inversionMatrix;
            final float inversionOffset;
            switch (inversionMode) {
                case AccessibilityManager.INVERSION_HUE_ONLY:
                    inversionMatrix = INVERSION_MATRIX_HUE_ONLY;
                    inversionOffset = INVERSION_OFFSET_HUE_ONLY;
                    break;
                case AccessibilityManager.INVERSION_VALUE_ONLY:
                    inversionMatrix = INVERSION_MATRIX_VALUE_ONLY;
                    inversionOffset = INVERSION_OFFSET_VALUE_ONLY;
                    break;
                default:
                    inversionMatrix = INVERSION_MATRIX_STANDARD;
                    inversionOffset = INVERSION_OFFSET_STANDARD;
            }

            Arrays.fill(offsetVector, inversionOffset);

            MatrixUtils.multiplyMM(outputMatrix, colorMatrix, 3, 3, inversionMatrix, 3);
            MatrixUtils.multiplyMM(outputOffset, colorOffset, 1, 3, inversionMatrix, 3);
            MatrixUtils.addMM(colorOffset, outputOffset, 1, 3, offsetVector);
            Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, inversionMatrix, 0);

            final float[] temp = colorMatrix;
            colorMatrix = outputMatrix;
            outputMatrix = temp;
            outputMatrix = colorMatrix;

            hasColorTransform = true;
        }
@@ -1539,16 +1523,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
            final float brightness = Settings.Secure.getFloatForUser(cr,
                    Settings.Secure.ACCESSIBILITY_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY_BRIGHTNESS,
                    userId);
            final float offset = brightness * contrast - 0.5f * contrast + 0.5f;
            Arrays.fill(offsetVector, offset);
            final float off = brightness * contrast - 0.5f * contrast + 0.5f;
            final float[] contrastMatrix = {
                    contrast, 0, 0, 0,
                    0, contrast, 0, 0,
                    0, 0, contrast, 0,
                    off, off, off, 1
            };

            MatrixUtils.multiplyMS(outputMatrix, colorMatrix, contrast);
            MatrixUtils.multiplyMS(outputOffset, colorOffset, contrast);
            MatrixUtils.addMM(colorOffset, outputOffset, 1, 3, offsetVector);
            Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, contrastMatrix, 0);

            final float[] temp = colorMatrix;
            colorMatrix = outputMatrix;
            outputMatrix = temp;
            outputMatrix = colorMatrix;

            hasColorTransform = true;
        }
@@ -1561,17 +1548,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                    userId);
            // Monochromacy isn't supported by the native Daltonizer.
            if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
                MatrixUtils.multiplyMM(outputMatrix, colorMatrix, 3, 3, GRAYSCALE_MATRIX, 3);
                MatrixUtils.multiplyMM(outputOffset, colorOffset, 1, 3, GRAYSCALE_MATRIX, 3);
                Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, GRAYSCALE_MATRIX, 0);

                final float[] temp = colorMatrix;
                colorMatrix = outputMatrix;
                outputMatrix = temp;

                final float[] tempVec = colorOffset;
                colorOffset = outputOffset;
                outputOffset = temp;

                hasColorTransform = true;
                nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
            } else {
@@ -1582,9 +1564,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
        }

        if (hasColorTransform) {
            nativeSetColorTransform(colorMatrix, colorOffset);
            nativeSetColorTransform(colorMatrix);
        } else {
            nativeSetColorTransform(null, null);
            nativeSetColorTransform(null);
        }
    }

@@ -1731,25 +1713,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
    }

    /**
     * Sets the surface flinger's color transformation matrix and offset. If
     * either value is null, color transformations are disabled.
     * Sets the surface flinger's color transformation as a 4x4 matrix. If the
     * matrix is null, color transformations are disabled.
     *
     * @param matrix new color transformation matrix, or null to disable
     * @param offset new color transformation offset, or null to disable
     * @param m the float array that holds the transformation matrix, or null to
     *            disable transformation
     */
    private static void nativeSetColorTransform(float[] matrix, float[] offset) {
    private static void nativeSetColorTransform(float[] m) {
        try {
            final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
            if (flinger != null) {
                final Parcel data = Parcel.obtain();
                data.writeInterfaceToken("android.ui.ISurfaceComposer");
                if (matrix != null && offset != null) {
                if (m != null) {
                    data.writeInt(1);
                    for (int i = 0; i < 9; i++) {
                        data.writeFloat(matrix[i]);
                    }
                    for (int i = 0; i < 3; i++) {
                        data.writeFloat(offset[i]);
                    for (int i = 0; i < 16; i++) {
                        data.writeFloat(m[i]);
                    }
                } else {
                    data.writeInt(0);