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

Commit 6c319ca1 authored by Romain Guy's avatar Romain Guy
Browse files

Better backend for hardware layers.

With this new backend, a hardware layer is only recreated when
its associated view is udpated. This offers fast composition
in GL and fast update of the layer in GL as well.

Change-Id: I97c43a612f5955c6bf1c192c8ca4af10fdf1d076
parent b7968896
Loading
Loading
Loading
Loading
+56 −2
Original line number Diff line number Diff line
@@ -73,10 +73,22 @@ class GLES20Canvas extends HardwareCanvas {
    // Constructors
    ///////////////////////////////////////////////////////////////////////////

    /**
     * Creates a canvas to render directly on screen.
     */
    GLES20Canvas(boolean translucent) {
        this(false, translucent);
    }

    /**
     * Creates a canvas to render into an FBO.
     */
    GLES20Canvas(int fbo, boolean translucent) {
        mOpaque = !translucent;
        mRenderer = nCreateLayerRenderer(fbo);
        setupFinalizer();
    }
    
    protected GLES20Canvas(boolean record, boolean translucent) {
        mOpaque = !translucent;

@@ -90,6 +102,10 @@ class GLES20Canvas extends HardwareCanvas {
            mRenderer = nCreateRenderer();
        }

        setupFinalizer();
    }

    private void setupFinalizer() {
        if (mRenderer == 0) {
            throw new IllegalStateException("Could not create GLES20Canvas renderer");
        } else {
@@ -97,7 +113,8 @@ class GLES20Canvas extends HardwareCanvas {
        }
    }

    private native int nCreateRenderer();
    private static native int nCreateRenderer();
    private static native int nCreateLayerRenderer(int fbo);
    private static native int nGetDisplayListRenderer(int renderer);
    private static native void nDestroyRenderer(int renderer);

@@ -135,6 +152,15 @@ class GLES20Canvas extends HardwareCanvas {
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Hardware layers
    ///////////////////////////////////////////////////////////////////////////
    
    static native int nCreateLayer(int width, int height, int[] layerInfo);
    static native void nResizeLayer(int layerId, int layerTextureId, int width, int height,
            int[] layerInfo);
    static native void nDestroyLayer(int layerId, int layerTextureId);    
    
    ///////////////////////////////////////////////////////////////////////////
    // Canvas management
    ///////////////////////////////////////////////////////////////////////////
@@ -226,6 +252,34 @@ class GLES20Canvas extends HardwareCanvas {

    private native void nDrawDisplayList(int renderer, int displayList);

    ///////////////////////////////////////////////////////////////////////////
    // Hardware layer
    ///////////////////////////////////////////////////////////////////////////
    
    void drawHardwareLayer(float left, float top, float right, float bottom,
            HardwareLayer layer, Paint paint) {
        final GLES20Layer glLayer = (GLES20Layer) layer;
        boolean hasColorFilter = paint != null && setupColorFilter(paint);
        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
        nDrawLayer(mRenderer, left, top, right, bottom, glLayer.mLayerTextureId,
                glLayer.getU(), glLayer.getV(), nativePaint);
        if (hasColorFilter) nResetModifiers(mRenderer);
    }

    private native void nDrawLayer(int renderer, float left, float top, float right, float bottom,
            int layerTexture, float u, float v, int paint);
    
    void interrupt() {
        nInterrupt(mRenderer);
    }
    
    void resume() {
        nResume(mRenderer);
    }

    private native void nInterrupt(int renderer);
    private native void nResume(int renderer);

    ///////////////////////////////////////////////////////////////////////////
    // Clipping
    ///////////////////////////////////////////////////////////////////////////
+5 −1
Original line number Diff line number Diff line
@@ -106,7 +106,11 @@ class GLES20DisplayList extends DisplayList {

        @Override
        protected void finalize() throws Throwable {
            try {
                replaceNativeObject(0);
            } finally {
                super.finalize();
            }
        }
    }
}
+143 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.view;

import android.graphics.Canvas;

/**
 * An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
 */
class GLES20Layer extends HardwareLayer {
    private int mLayerId;
    int mLayerTextureId;

    private int mLayerWidth;
    private int mLayerHeight;

    private final GLES20Canvas mCanvas;

    private float mU;
    private float mV;

    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
    private final Finalizer mFinalizer;

    GLES20Layer(int width, int height, boolean isOpaque) {
        super(width, height, isOpaque);

        int[] layerInfo = new int[3];
        mLayerId = GLES20Canvas.nCreateLayer(width, height, layerInfo);
        if (mLayerId != 0) {
            mLayerWidth = layerInfo[0];
            mLayerHeight = layerInfo[1];
            mLayerTextureId = layerInfo[2];

            mCanvas = new GLES20Canvas(mLayerId, !isOpaque);
            mFinalizer = new Finalizer(mLayerId, mLayerTextureId);
            
            mU = mWidth / (float) mLayerWidth;
            mV = mHeight/ (float) mLayerHeight;
        } else {
            mCanvas = null;
            mFinalizer = null;
        }
    }

    float getU() {
        return mU;
    }

    float getV() {
        return mV;
    }

    @Override
    boolean isValid() {
        return mLayerId != 0 && mLayerWidth > 0 && mLayerHeight > 0;
    }

    @Override
    void resize(int width, int height) {
        if (!isValid() || width <= 0 || height <= 0) return;
        if (width > mLayerWidth || height > mLayerHeight) {
            mWidth = width;
            mHeight = height;

            int[] layerInfo = new int[3];

            GLES20Canvas.nResizeLayer(mLayerId, mLayerTextureId, width, height, layerInfo);

            mLayerWidth = layerInfo[0];
            mLayerHeight = layerInfo[1];

            mU = mWidth / (float) mLayerWidth;
            mV = mHeight/ (float) mLayerHeight;            
        }
    }

    @Override
    HardwareCanvas getCanvas() {
        return mCanvas;
    }

    @Override
    void end(Canvas currentCanvas) {
        if (currentCanvas instanceof GLES20Canvas) {
            ((GLES20Canvas) currentCanvas).resume();
        }
    }

    @Override
    HardwareCanvas start(Canvas currentCanvas) {
        if (currentCanvas instanceof GLES20Canvas) {
            ((GLES20Canvas) currentCanvas).interrupt();
        }
        return getCanvas();
    }

    @Override
    void destroy() {
        mFinalizer.destroy();
        mLayerId = mLayerTextureId = 0;
    }

    private static class Finalizer {
        private int mLayerId;
        private int mLayerTextureId;

        public Finalizer(int layerId, int layerTextureId) {
            mLayerId = layerId;
            mLayerTextureId = layerTextureId;
        }

        @Override
        protected void finalize() throws Throwable {
            try {
                if (mLayerId != 0 || mLayerTextureId != 0) {
                    GLES20Canvas.nDestroyLayer(mLayerId, mLayerTextureId);
                }
            } finally {
                super.finalize();
            }
        }

        void destroy() {
            GLES20Canvas.nDestroyLayer(mLayerId, mLayerTextureId);
            mLayerId = mLayerTextureId = 0;
        }
    }
}
+2 −7
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ import java.util.HashSet;
class GLES20RecordingCanvas extends GLES20Canvas {
    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
    // as the DisplayList is alive.
    private HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
    private final HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();

    GLES20RecordingCanvas(boolean translucent) {
        super(true, translucent);
@@ -56,12 +57,6 @@ class GLES20RecordingCanvas extends GLES20Canvas {
        setupRenderer(true);
    }

    @Override
    public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
            Paint paint) {
        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
    }

    @Override
    public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
        super.drawPatch(bitmap, chunks, dst, paint);
+15 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.view;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;

/**
 * Hardware accelerated canvas. 
@@ -48,5 +49,18 @@ abstract class HardwareCanvas extends Canvas {
     * 
     * @param displayList The display list to replay.
     */
    public abstract void drawDisplayList(DisplayList displayList);
    abstract void drawDisplayList(DisplayList displayList);

    /**
     * Draws the specified layer onto this canvas.
     *
     * @param left The left coordinate of the layer
     * @param top The top coordinate of the layer
     * @param right The right coordinate of the layer
     * @param bottom The bottom coordinate of the layer
     * @param layer The layer to composite on this canvas
     * @param paint The paint used to draw the layer
     */
    abstract void drawHardwareLayer(float left, float top, float right, float bottom,
            HardwareLayer layer, Paint paint); 
}
Loading