summaryrefslogtreecommitdiffstats
path: root/core/java/android/view/HardwareLayer.java
blob: 65ae8a649241fcfb198bd34c1b49c10a7edbb664 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * 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.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;

import com.android.internal.util.VirtualRefBasePtr;

/**
 * A hardware layer can be used to render graphics operations into a hardware
 * friendly buffer. For instance, with an OpenGL backend a hardware layer
 * would use a Frame Buffer Object (FBO.) The hardware layer can be used as
 * a drawing cache when a complex set of graphics operations needs to be
 * drawn several times.
 *
 * @hide
 */
final class HardwareLayer {
    private HardwareRenderer mRenderer;
    private VirtualRefBasePtr mFinalizer;

    private HardwareLayer(HardwareRenderer renderer, long deferredUpdater) {
        if (renderer == null || deferredUpdater == 0) {
            throw new IllegalArgumentException("Either hardware renderer: " + renderer
                    + " or deferredUpdater: " + deferredUpdater + " is invalid");
        }
        mRenderer = renderer;
        mFinalizer = new VirtualRefBasePtr(deferredUpdater);
    }

    /**
     * Update the paint used when drawing this layer.
     *
     * @param paint The paint used when the layer is drawn into the destination canvas.
     * @see View#setLayerPaint(android.graphics.Paint)
     */
    public void setLayerPaint(Paint paint) {
        nSetLayerPaint(mFinalizer.get(), paint.getNativeInstance());
        mRenderer.pushLayerUpdate(this);
    }

    /**
     * Indicates whether this layer can be rendered.
     *
     * @return True if the layer can be rendered into, false otherwise
     */
    public boolean isValid() {
        return mFinalizer != null && mFinalizer.get() != 0;
    }

    /**
     * Destroys resources without waiting for a GC.
     */
    public void destroy() {
        if (!isValid()) {
            // Already destroyed
            return;
        }
        mRenderer.onLayerDestroyed(this);
        mRenderer = null;
        mFinalizer.release();
        mFinalizer = null;
    }

    public long getDeferredLayerUpdater() {
        return mFinalizer.get();
    }

    /**
     * Copies this layer into the specified bitmap.
     *
     * @param bitmap The bitmap to copy they layer into
     *
     * @return True if the copy was successful, false otherwise
     */
    public boolean copyInto(Bitmap bitmap) {
        return mRenderer.copyLayerInto(this, bitmap);
    }

    /**
     * Update the layer's properties. Note that after calling this isValid() may
     * return false if the requested width/height cannot be satisfied
     *
     * @param width The new width of this layer
     * @param height The new height of this layer
     * @param isOpaque Whether this layer is opaque
     *
     * @return true if the layer's properties will change, false if they already
     *         match the desired values.
     */
    public boolean prepare(int width, int height, boolean isOpaque) {
        return nPrepare(mFinalizer.get(), width, height, isOpaque);
    }

    /**
     * Sets an optional transform on this layer.
     *
     * @param matrix The transform to apply to the layer.
     */
    public void setTransform(Matrix matrix) {
        nSetTransform(mFinalizer.get(), matrix.native_instance);
        mRenderer.pushLayerUpdate(this);
    }

    /**
     * Indicates that this layer has lost its texture.
     */
    public void detachSurfaceTexture() {
        mRenderer.detachSurfaceTexture(mFinalizer.get());
    }

    public long getLayerHandle() {
        return mFinalizer.get();
    }

    public void setSurfaceTexture(SurfaceTexture surface) {
        nSetSurfaceTexture(mFinalizer.get(), surface, false);
        mRenderer.pushLayerUpdate(this);
    }

    public void updateSurfaceTexture() {
        nUpdateSurfaceTexture(mFinalizer.get());
        mRenderer.pushLayerUpdate(this);
    }

    static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
        return new HardwareLayer(renderer, layer);
    }

    private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque);
    private static native void nSetLayerPaint(long layerUpdater, long paint);
    private static native void nSetTransform(long layerUpdater, long matrix);
    private static native void nSetSurfaceTexture(long layerUpdater,
            SurfaceTexture surface, boolean isAlreadyAttached);
    private static native void nUpdateSurfaceTexture(long layerUpdater);
    private static native void nUpdateRenderLayer(long layerUpdater, long displayList,
            int left, int top, int right, int bottom);

    private static native int nGetTexName(long layerUpdater);
}