1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.graphics.Bitmap;
20import android.graphics.Matrix;
21
22import java.util.ArrayList;
23
24/**
25 * An implementation of display list for OpenGL ES 2.0.
26 */
27class GLES20DisplayList extends DisplayList {
28    // These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept
29    // alive as long as the DisplayList is alive.  The Bitmap and DisplayList lists
30    // are populated by the GLES20RecordingCanvas during appropriate drawing calls and are
31    // cleared at the start of a new drawing frame or when the view is detached from the window.
32    final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
33    final ArrayList<DisplayList> mChildDisplayLists = new ArrayList<DisplayList>();
34
35    private GLES20RecordingCanvas mCanvas;
36    private boolean mValid;
37
38    // Used for debugging
39    private final String mName;
40
41    // The native display list will be destroyed when this object dies.
42    // DO NOT overwrite this reference once it is set.
43    private DisplayListFinalizer mFinalizer;
44
45    GLES20DisplayList(String name) {
46        mName = name;
47    }
48
49    boolean hasNativeDisplayList() {
50        return mValid && mFinalizer != null;
51    }
52
53    int getNativeDisplayList() {
54        if (!mValid || mFinalizer == null) {
55            throw new IllegalStateException("The display list is not valid.");
56        }
57        return mFinalizer.mNativeDisplayList;
58    }
59
60    @Override
61    public HardwareCanvas start() {
62        if (mCanvas != null) {
63            throw new IllegalStateException("Recording has already started");
64        }
65
66        mValid = false;
67        mCanvas = GLES20RecordingCanvas.obtain(this);
68        mCanvas.start();
69        return mCanvas;
70    }
71
72    @Override
73    public void invalidate() {
74        if (mCanvas != null) {
75            mCanvas.recycle();
76            mCanvas = null;
77        }
78        mValid = false;
79    }
80
81    @Override
82    public void clear() {
83        if (!mValid) {
84            mBitmaps.clear();
85            mChildDisplayLists.clear();
86        }
87    }
88
89    @Override
90    public void reset() {
91        if (hasNativeDisplayList()) {
92            nReset(mFinalizer.mNativeDisplayList);
93        }
94    }
95
96    @Override
97    public boolean isValid() {
98        return mValid;
99    }
100
101    @Override
102    public void end() {
103        if (mCanvas != null) {
104            if (mFinalizer != null) {
105                mCanvas.end(mFinalizer.mNativeDisplayList);
106            } else {
107                mFinalizer = new DisplayListFinalizer(mCanvas.end(0));
108                GLES20Canvas.setDisplayListName(mFinalizer.mNativeDisplayList, mName);
109            }
110            mCanvas.recycle();
111            mCanvas = null;
112            mValid = true;
113        }
114    }
115
116    @Override
117    public int getSize() {
118        if (mFinalizer == null) return 0;
119        return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList);
120    }
121
122    ///////////////////////////////////////////////////////////////////////////
123    // Native View Properties
124    ///////////////////////////////////////////////////////////////////////////
125
126    @Override
127    public void setCaching(boolean caching) {
128        if (hasNativeDisplayList()) {
129            nSetCaching(mFinalizer.mNativeDisplayList, caching);
130        }
131    }
132
133    @Override
134    public void setClipChildren(boolean clipChildren) {
135        if (hasNativeDisplayList()) {
136            nSetClipChildren(mFinalizer.mNativeDisplayList, clipChildren);
137        }
138    }
139
140    @Override
141    public void setStaticMatrix(Matrix matrix) {
142        if (hasNativeDisplayList()) {
143            nSetStaticMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance);
144        }
145    }
146
147    @Override
148    public void setAnimationMatrix(Matrix matrix) {
149        if (hasNativeDisplayList()) {
150            nSetAnimationMatrix(mFinalizer.mNativeDisplayList,
151                    (matrix != null) ? matrix.native_instance : 0);
152        }
153    }
154
155    @Override
156    public void setAlpha(float alpha) {
157        if (hasNativeDisplayList()) {
158            nSetAlpha(mFinalizer.mNativeDisplayList, alpha);
159        }
160    }
161
162    @Override
163    public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
164        if (hasNativeDisplayList()) {
165            nSetHasOverlappingRendering(mFinalizer.mNativeDisplayList, hasOverlappingRendering);
166        }
167    }
168
169    @Override
170    public void setTranslationX(float translationX) {
171        if (hasNativeDisplayList()) {
172            nSetTranslationX(mFinalizer.mNativeDisplayList, translationX);
173        }
174    }
175
176    @Override
177    public void setTranslationY(float translationY) {
178        if (hasNativeDisplayList()) {
179            nSetTranslationY(mFinalizer.mNativeDisplayList, translationY);
180        }
181    }
182
183    @Override
184    public void setRotation(float rotation) {
185        if (hasNativeDisplayList()) {
186            nSetRotation(mFinalizer.mNativeDisplayList, rotation);
187        }
188    }
189
190    @Override
191    public void setRotationX(float rotationX) {
192        if (hasNativeDisplayList()) {
193            nSetRotationX(mFinalizer.mNativeDisplayList, rotationX);
194        }
195    }
196
197    @Override
198    public void setRotationY(float rotationY) {
199        if (hasNativeDisplayList()) {
200            nSetRotationY(mFinalizer.mNativeDisplayList, rotationY);
201        }
202    }
203
204    @Override
205    public void setScaleX(float scaleX) {
206        if (hasNativeDisplayList()) {
207            nSetScaleX(mFinalizer.mNativeDisplayList, scaleX);
208        }
209    }
210
211    @Override
212    public void setScaleY(float scaleY) {
213        if (hasNativeDisplayList()) {
214            nSetScaleY(mFinalizer.mNativeDisplayList, scaleY);
215        }
216    }
217
218    @Override
219    public void setTransformationInfo(float alpha, float translationX, float translationY,
220            float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
221        if (hasNativeDisplayList()) {
222            nSetTransformationInfo(mFinalizer.mNativeDisplayList, alpha, translationX, translationY,
223                    rotation, rotationX, rotationY, scaleX, scaleY);
224        }
225    }
226
227    @Override
228    public void setPivotX(float pivotX) {
229        if (hasNativeDisplayList()) {
230            nSetPivotX(mFinalizer.mNativeDisplayList, pivotX);
231        }
232    }
233
234    @Override
235    public void setPivotY(float pivotY) {
236        if (hasNativeDisplayList()) {
237            nSetPivotY(mFinalizer.mNativeDisplayList, pivotY);
238        }
239    }
240
241    @Override
242    public void setCameraDistance(float distance) {
243        if (hasNativeDisplayList()) {
244            nSetCameraDistance(mFinalizer.mNativeDisplayList, distance);
245        }
246    }
247
248    @Override
249    public void setLeft(int left) {
250        if (hasNativeDisplayList()) {
251            nSetLeft(mFinalizer.mNativeDisplayList, left);
252        }
253    }
254
255    @Override
256    public void setTop(int top) {
257        if (hasNativeDisplayList()) {
258            nSetTop(mFinalizer.mNativeDisplayList, top);
259        }
260    }
261
262    @Override
263    public void setRight(int right) {
264        if (hasNativeDisplayList()) {
265            nSetRight(mFinalizer.mNativeDisplayList, right);
266        }
267    }
268
269    @Override
270    public void setBottom(int bottom) {
271        if (hasNativeDisplayList()) {
272            nSetBottom(mFinalizer.mNativeDisplayList, bottom);
273        }
274    }
275
276    @Override
277    public void setLeftTop(int left, int top) {
278        if (hasNativeDisplayList()) {
279            nSetLeftTop(mFinalizer.mNativeDisplayList, left, top);
280        }
281    }
282
283    @Override
284    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
285        if (hasNativeDisplayList()) {
286            nSetLeftTopRightBottom(mFinalizer.mNativeDisplayList, left, top, right, bottom);
287        }
288    }
289
290    @Override
291    public void offsetLeftRight(int offset) {
292        if (hasNativeDisplayList()) {
293            nOffsetLeftRight(mFinalizer.mNativeDisplayList, offset);
294        }
295    }
296
297    @Override
298    public void offsetTopBottom(int offset) {
299        if (hasNativeDisplayList()) {
300            nOffsetTopBottom(mFinalizer.mNativeDisplayList, offset);
301        }
302    }
303
304    private static native void nReset(int displayList);
305    private static native void nOffsetTopBottom(int displayList, int offset);
306    private static native void nOffsetLeftRight(int displayList, int offset);
307    private static native void nSetLeftTopRightBottom(int displayList, int left, int top,
308            int right, int bottom);
309    private static native void nSetLeftTop(int displayList, int left, int top);
310    private static native void nSetBottom(int displayList, int bottom);
311    private static native void nSetRight(int displayList, int right);
312    private static native void nSetTop(int displayList, int top);
313    private static native void nSetLeft(int displayList, int left);
314    private static native void nSetCameraDistance(int displayList, float distance);
315    private static native void nSetPivotY(int displayList, float pivotY);
316    private static native void nSetPivotX(int displayList, float pivotX);
317    private static native void nSetCaching(int displayList, boolean caching);
318    private static native void nSetClipChildren(int displayList, boolean clipChildren);
319    private static native void nSetAlpha(int displayList, float alpha);
320    private static native void nSetHasOverlappingRendering(int displayList,
321            boolean hasOverlappingRendering);
322    private static native void nSetTranslationX(int displayList, float translationX);
323    private static native void nSetTranslationY(int displayList, float translationY);
324    private static native void nSetRotation(int displayList, float rotation);
325    private static native void nSetRotationX(int displayList, float rotationX);
326    private static native void nSetRotationY(int displayList, float rotationY);
327    private static native void nSetScaleX(int displayList, float scaleX);
328    private static native void nSetScaleY(int displayList, float scaleY);
329    private static native void nSetTransformationInfo(int displayList, float alpha,
330            float translationX, float translationY, float rotation, float rotationX,
331            float rotationY, float scaleX, float scaleY);
332    private static native void nSetStaticMatrix(int displayList, int nativeMatrix);
333    private static native void nSetAnimationMatrix(int displayList, int animationMatrix);
334
335
336    ///////////////////////////////////////////////////////////////////////////
337    // Finalization
338    ///////////////////////////////////////////////////////////////////////////
339
340    private static class DisplayListFinalizer {
341        final int mNativeDisplayList;
342
343        public DisplayListFinalizer(int nativeDisplayList) {
344            mNativeDisplayList = nativeDisplayList;
345        }
346
347        @Override
348        protected void finalize() throws Throwable {
349            try {
350                GLES20Canvas.destroyDisplayList(mNativeDisplayList);
351            } finally {
352                super.finalize();
353            }
354        }
355    }
356}
357