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.Matrix;
20
21import java.util.ArrayList;
22
23/**
24 * An implementation of display list for OpenGL ES 2.0.
25 */
26class GLES20DisplayList extends DisplayList {
27    private ArrayList<DisplayList> mChildDisplayLists;
28
29    private GLES20RecordingCanvas mCanvas;
30    private boolean mValid;
31
32    // Used for debugging
33    private final String mName;
34
35    // The native display list will be destroyed when this object dies.
36    // DO NOT overwrite this reference once it is set.
37    private DisplayListFinalizer mFinalizer;
38
39    GLES20DisplayList(String name) {
40        mName = name;
41    }
42
43    boolean hasNativeDisplayList() {
44        return mValid && mFinalizer != null;
45    }
46
47    int getNativeDisplayList() {
48        if (!mValid || mFinalizer == null) {
49            throw new IllegalStateException("The display list is not valid.");
50        }
51        return mFinalizer.mNativeDisplayList;
52    }
53
54    @Override
55    public HardwareCanvas start(int width, int height) {
56        if (mCanvas != null) {
57            throw new IllegalStateException("Recording has already started");
58        }
59
60        mValid = false;
61        mCanvas = GLES20RecordingCanvas.obtain(this);
62        mCanvas.start();
63
64        mCanvas.setViewport(width, height);
65        // The dirty rect should always be null for a display list
66        mCanvas.onPreDraw(null);
67
68        return mCanvas;
69    }
70    @Override
71    public void clear() {
72        clearDirty();
73
74        if (mCanvas != null) {
75            mCanvas.recycle();
76            mCanvas = null;
77        }
78        mValid = false;
79
80        clearReferences();
81    }
82
83    void clearReferences() {
84        if (mChildDisplayLists != null) mChildDisplayLists.clear();
85    }
86
87    ArrayList<DisplayList> getChildDisplayLists() {
88        if (mChildDisplayLists == null) mChildDisplayLists = new ArrayList<DisplayList>();
89        return mChildDisplayLists;
90    }
91
92    @Override
93    public void reset() {
94        if (hasNativeDisplayList()) {
95            nReset(mFinalizer.mNativeDisplayList);
96        }
97        clear();
98    }
99
100    @Override
101    public boolean isValid() {
102        return mValid;
103    }
104
105    @Override
106    public void end() {
107        if (mCanvas != null) {
108            mCanvas.onPostDraw();
109            if (mFinalizer != null) {
110                mCanvas.end(mFinalizer.mNativeDisplayList);
111            } else {
112                mFinalizer = new DisplayListFinalizer(mCanvas.end(0));
113                nSetDisplayListName(mFinalizer.mNativeDisplayList, mName);
114            }
115            mCanvas.recycle();
116            mCanvas = null;
117            mValid = true;
118        }
119    }
120
121    @Override
122    public int getSize() {
123        if (mFinalizer == null) return 0;
124        return nGetDisplayListSize(mFinalizer.mNativeDisplayList);
125    }
126
127    private static native void nDestroyDisplayList(int displayList);
128    private static native int nGetDisplayListSize(int displayList);
129    private static native void nSetDisplayListName(int displayList, String name);
130
131    ///////////////////////////////////////////////////////////////////////////
132    // Native View Properties
133    ///////////////////////////////////////////////////////////////////////////
134
135    @Override
136    public void setCaching(boolean caching) {
137        if (hasNativeDisplayList()) {
138            nSetCaching(mFinalizer.mNativeDisplayList, caching);
139        }
140    }
141
142    @Override
143    public void setClipToBounds(boolean clipToBounds) {
144        if (hasNativeDisplayList()) {
145            nSetClipToBounds(mFinalizer.mNativeDisplayList, clipToBounds);
146        }
147    }
148
149    @Override
150    public void setMatrix(Matrix matrix) {
151        if (hasNativeDisplayList()) {
152            nSetStaticMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance);
153        }
154    }
155
156    @Override
157    public Matrix getMatrix(Matrix matrix) {
158        if (hasNativeDisplayList()) {
159            nGetMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance);
160        }
161        return matrix;
162    }
163
164    @Override
165    public void setAnimationMatrix(Matrix matrix) {
166        if (hasNativeDisplayList()) {
167            nSetAnimationMatrix(mFinalizer.mNativeDisplayList,
168                    (matrix != null) ? matrix.native_instance : 0);
169        }
170    }
171
172    @Override
173    public void setAlpha(float alpha) {
174        if (hasNativeDisplayList()) {
175            nSetAlpha(mFinalizer.mNativeDisplayList, alpha);
176        }
177    }
178
179    @Override
180    public float getAlpha() {
181        if (hasNativeDisplayList()) {
182            return nGetAlpha(mFinalizer.mNativeDisplayList);
183        }
184        return 1.0f;
185    }
186
187    @Override
188    public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
189        if (hasNativeDisplayList()) {
190            nSetHasOverlappingRendering(mFinalizer.mNativeDisplayList, hasOverlappingRendering);
191        }
192    }
193
194    @Override
195    public boolean hasOverlappingRendering() {
196        //noinspection SimplifiableIfStatement
197        if (hasNativeDisplayList()) {
198            return nHasOverlappingRendering(mFinalizer.mNativeDisplayList);
199        }
200        return true;
201    }
202
203    @Override
204    public void setTranslationX(float translationX) {
205        if (hasNativeDisplayList()) {
206            nSetTranslationX(mFinalizer.mNativeDisplayList, translationX);
207        }
208    }
209
210    @Override
211    public float getTranslationX() {
212        if (hasNativeDisplayList()) {
213            return nGetTranslationX(mFinalizer.mNativeDisplayList);
214        }
215        return 0.0f;
216    }
217
218    @Override
219    public void setTranslationY(float translationY) {
220        if (hasNativeDisplayList()) {
221            nSetTranslationY(mFinalizer.mNativeDisplayList, translationY);
222        }
223    }
224
225    @Override
226    public float getTranslationY() {
227        if (hasNativeDisplayList()) {
228            return nGetTranslationY(mFinalizer.mNativeDisplayList);
229        }
230        return 0.0f;
231    }
232
233    @Override
234    public void setRotation(float rotation) {
235        if (hasNativeDisplayList()) {
236            nSetRotation(mFinalizer.mNativeDisplayList, rotation);
237        }
238    }
239
240    @Override
241    public float getRotation() {
242        if (hasNativeDisplayList()) {
243            return nGetRotation(mFinalizer.mNativeDisplayList);
244        }
245        return 0.0f;
246    }
247
248    @Override
249    public void setRotationX(float rotationX) {
250        if (hasNativeDisplayList()) {
251            nSetRotationX(mFinalizer.mNativeDisplayList, rotationX);
252        }
253    }
254
255    @Override
256    public float getRotationX() {
257        if (hasNativeDisplayList()) {
258            return nGetRotationX(mFinalizer.mNativeDisplayList);
259        }
260        return 0.0f;
261    }
262
263    @Override
264    public void setRotationY(float rotationY) {
265        if (hasNativeDisplayList()) {
266            nSetRotationY(mFinalizer.mNativeDisplayList, rotationY);
267        }
268    }
269
270    @Override
271    public float getRotationY() {
272        if (hasNativeDisplayList()) {
273            return nGetRotationY(mFinalizer.mNativeDisplayList);
274        }
275        return 0.0f;
276    }
277
278    @Override
279    public void setScaleX(float scaleX) {
280        if (hasNativeDisplayList()) {
281            nSetScaleX(mFinalizer.mNativeDisplayList, scaleX);
282        }
283    }
284
285    @Override
286    public float getScaleX() {
287        if (hasNativeDisplayList()) {
288            return nGetScaleX(mFinalizer.mNativeDisplayList);
289        }
290        return 1.0f;
291    }
292
293    @Override
294    public void setScaleY(float scaleY) {
295        if (hasNativeDisplayList()) {
296            nSetScaleY(mFinalizer.mNativeDisplayList, scaleY);
297        }
298    }
299
300    @Override
301    public float getScaleY() {
302        if (hasNativeDisplayList()) {
303            return nGetScaleY(mFinalizer.mNativeDisplayList);
304        }
305        return 1.0f;
306    }
307
308    @Override
309    public void setTransformationInfo(float alpha, float translationX, float translationY,
310            float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
311        if (hasNativeDisplayList()) {
312            nSetTransformationInfo(mFinalizer.mNativeDisplayList, alpha, translationX, translationY,
313                    rotation, rotationX, rotationY, scaleX, scaleY);
314        }
315    }
316
317    @Override
318    public void setPivotX(float pivotX) {
319        if (hasNativeDisplayList()) {
320            nSetPivotX(mFinalizer.mNativeDisplayList, pivotX);
321        }
322    }
323
324    @Override
325    public float getPivotX() {
326        if (hasNativeDisplayList()) {
327            return nGetPivotX(mFinalizer.mNativeDisplayList);
328        }
329        return 0.0f;
330    }
331
332    @Override
333    public void setPivotY(float pivotY) {
334        if (hasNativeDisplayList()) {
335            nSetPivotY(mFinalizer.mNativeDisplayList, pivotY);
336        }
337    }
338
339    @Override
340    public float getPivotY() {
341        if (hasNativeDisplayList()) {
342            return nGetPivotY(mFinalizer.mNativeDisplayList);
343        }
344        return 0.0f;
345    }
346
347    @Override
348    public void setCameraDistance(float distance) {
349        if (hasNativeDisplayList()) {
350            nSetCameraDistance(mFinalizer.mNativeDisplayList, distance);
351        }
352    }
353
354    @Override
355    public float getCameraDistance() {
356        if (hasNativeDisplayList()) {
357            return nGetCameraDistance(mFinalizer.mNativeDisplayList);
358        }
359        return 0.0f;
360    }
361
362    @Override
363    public void setLeft(int left) {
364        if (hasNativeDisplayList()) {
365            nSetLeft(mFinalizer.mNativeDisplayList, left);
366        }
367    }
368
369    @Override
370    public float getLeft() {
371        if (hasNativeDisplayList()) {
372            return nGetLeft(mFinalizer.mNativeDisplayList);
373        }
374        return 0.0f;
375    }
376
377    @Override
378    public void setTop(int top) {
379        if (hasNativeDisplayList()) {
380            nSetTop(mFinalizer.mNativeDisplayList, top);
381        }
382    }
383
384    @Override
385    public float getTop() {
386        if (hasNativeDisplayList()) {
387            return nGetTop(mFinalizer.mNativeDisplayList);
388        }
389        return 0.0f;
390    }
391
392    @Override
393    public void setRight(int right) {
394        if (hasNativeDisplayList()) {
395            nSetRight(mFinalizer.mNativeDisplayList, right);
396        }
397    }
398
399    @Override
400    public float getRight() {
401        if (hasNativeDisplayList()) {
402            return nGetRight(mFinalizer.mNativeDisplayList);
403        }
404        return 0.0f;
405    }
406
407    @Override
408    public void setBottom(int bottom) {
409        if (hasNativeDisplayList()) {
410            nSetBottom(mFinalizer.mNativeDisplayList, bottom);
411        }
412    }
413
414    @Override
415    public float getBottom() {
416        if (hasNativeDisplayList()) {
417            return nGetBottom(mFinalizer.mNativeDisplayList);
418        }
419        return 0.0f;
420    }
421
422    @Override
423    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
424        if (hasNativeDisplayList()) {
425            nSetLeftTopRightBottom(mFinalizer.mNativeDisplayList, left, top, right, bottom);
426        }
427    }
428
429    @Override
430    public void offsetLeftAndRight(float offset) {
431        if (hasNativeDisplayList()) {
432            nOffsetLeftAndRight(mFinalizer.mNativeDisplayList, offset);
433        }
434    }
435
436    @Override
437    public void offsetTopAndBottom(float offset) {
438        if (hasNativeDisplayList()) {
439            nOffsetTopAndBottom(mFinalizer.mNativeDisplayList, offset);
440        }
441    }
442
443    private static native void nReset(int displayList);
444    private static native void nOffsetTopAndBottom(int displayList, float offset);
445    private static native void nOffsetLeftAndRight(int displayList, float offset);
446    private static native void nSetLeftTopRightBottom(int displayList, int left, int top,
447            int right, int bottom);
448    private static native void nSetBottom(int displayList, int bottom);
449    private static native void nSetRight(int displayList, int right);
450    private static native void nSetTop(int displayList, int top);
451    private static native void nSetLeft(int displayList, int left);
452    private static native void nSetCameraDistance(int displayList, float distance);
453    private static native void nSetPivotY(int displayList, float pivotY);
454    private static native void nSetPivotX(int displayList, float pivotX);
455    private static native void nSetCaching(int displayList, boolean caching);
456    private static native void nSetClipToBounds(int displayList, boolean clipToBounds);
457    private static native void nSetAlpha(int displayList, float alpha);
458    private static native void nSetHasOverlappingRendering(int displayList,
459            boolean hasOverlappingRendering);
460    private static native void nSetTranslationX(int displayList, float translationX);
461    private static native void nSetTranslationY(int displayList, float translationY);
462    private static native void nSetRotation(int displayList, float rotation);
463    private static native void nSetRotationX(int displayList, float rotationX);
464    private static native void nSetRotationY(int displayList, float rotationY);
465    private static native void nSetScaleX(int displayList, float scaleX);
466    private static native void nSetScaleY(int displayList, float scaleY);
467    private static native void nSetTransformationInfo(int displayList, float alpha,
468            float translationX, float translationY, float rotation, float rotationX,
469            float rotationY, float scaleX, float scaleY);
470    private static native void nSetStaticMatrix(int displayList, int nativeMatrix);
471    private static native void nSetAnimationMatrix(int displayList, int animationMatrix);
472
473    private static native boolean nHasOverlappingRendering(int displayList);
474    private static native void nGetMatrix(int displayList, int matrix);
475    private static native float nGetAlpha(int displayList);
476    private static native float nGetLeft(int displayList);
477    private static native float nGetTop(int displayList);
478    private static native float nGetRight(int displayList);
479    private static native float nGetBottom(int displayList);
480    private static native float nGetCameraDistance(int displayList);
481    private static native float nGetScaleX(int displayList);
482    private static native float nGetScaleY(int displayList);
483    private static native float nGetTranslationX(int displayList);
484    private static native float nGetTranslationY(int displayList);
485    private static native float nGetRotation(int displayList);
486    private static native float nGetRotationX(int displayList);
487    private static native float nGetRotationY(int displayList);
488    private static native float nGetPivotX(int displayList);
489    private static native float nGetPivotY(int displayList);
490
491    ///////////////////////////////////////////////////////////////////////////
492    // Finalization
493    ///////////////////////////////////////////////////////////////////////////
494
495    private static class DisplayListFinalizer {
496        final int mNativeDisplayList;
497
498        public DisplayListFinalizer(int nativeDisplayList) {
499            mNativeDisplayList = nativeDisplayList;
500        }
501
502        @Override
503        protected void finalize() throws Throwable {
504            try {
505                nDestroyDisplayList(mNativeDisplayList);
506            } finally {
507                super.finalize();
508            }
509        }
510    }
511}
512