GLES20Canvas.java revision d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895
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.BitmapShader;
21import android.graphics.Canvas;
22import android.graphics.DrawFilter;
23import android.graphics.LinearGradient;
24import android.graphics.Matrix;
25import android.graphics.Paint;
26import android.graphics.Path;
27import android.graphics.Picture;
28import android.graphics.PorterDuff;
29import android.graphics.RadialGradient;
30import android.graphics.Rect;
31import android.graphics.RectF;
32import android.graphics.Region;
33import android.graphics.Shader;
34import android.graphics.SweepGradient;
35
36import javax.microedition.khronos.opengles.GL;
37
38/**
39 * An implementation of Canvas on top of OpenGL ES 2.0.
40 */
41@SuppressWarnings({"deprecation"})
42class GLES20Canvas extends Canvas {
43    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
44    private final GL mGl;
45    private final boolean mOpaque;
46    private final int mRenderer;
47
48    private int mWidth;
49    private int mHeight;
50
51    private final float[] mPoint = new float[2];
52    private final float[] mLine = new float[4];
53
54    private final Rect mClipBounds = new Rect();
55
56    private DrawFilter mFilter;
57
58    ///////////////////////////////////////////////////////////////////////////
59    // Constructors
60    ///////////////////////////////////////////////////////////////////////////
61
62    GLES20Canvas(GL gl, boolean translucent) {
63        mGl = gl;
64        mOpaque = !translucent;
65
66        mRenderer = nCreateRenderer();
67    }
68
69    private native int nCreateRenderer();
70
71    @Override
72    protected void finalize() throws Throwable {
73        try {
74            super.finalize();
75        } finally {
76            nDestroyRenderer(mRenderer);
77        }
78    }
79
80    private native void nDestroyRenderer(int renderer);
81
82    ///////////////////////////////////////////////////////////////////////////
83    // Canvas management
84    ///////////////////////////////////////////////////////////////////////////
85
86    @Override
87    public boolean isHardwareAccelerated() {
88        return true;
89    }
90
91    @Override
92    public GL getGL() {
93        throw new UnsupportedOperationException();
94    }
95
96    @Override
97    public void setBitmap(Bitmap bitmap) {
98        throw new UnsupportedOperationException();
99    }
100
101    @Override
102    public boolean isOpaque() {
103        return mOpaque;
104    }
105
106    @Override
107    public int getWidth() {
108        return mWidth;
109    }
110
111    @Override
112    public int getHeight() {
113        return mHeight;
114    }
115
116    ///////////////////////////////////////////////////////////////////////////
117    // Setup
118    ///////////////////////////////////////////////////////////////////////////
119
120    @Override
121    public void setViewport(int width, int height) {
122        mWidth = width;
123        mHeight = height;
124
125        nSetViewport(mRenderer, width, height);
126    }
127
128    private native void nSetViewport(int renderer, int width, int height);
129
130    void onPreDraw() {
131        nPrepare(mRenderer);
132    }
133
134    private native void nPrepare(int renderer);
135
136    ///////////////////////////////////////////////////////////////////////////
137    // Clipping
138    ///////////////////////////////////////////////////////////////////////////
139
140    @Override
141    public boolean clipPath(Path path) {
142        throw new UnsupportedOperationException();
143    }
144
145    @Override
146    public boolean clipPath(Path path, Region.Op op) {
147        throw new UnsupportedOperationException();
148    }
149
150    @Override
151    public boolean clipRect(float left, float top, float right, float bottom) {
152        return nClipRect(mRenderer, left, top, right, bottom);
153    }
154
155    private native boolean nClipRect(int renderer, float left, float top, float right, float bottom);
156
157    @Override
158    public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
159        throw new UnsupportedOperationException();
160    }
161
162    @Override
163    public boolean clipRect(int left, int top, int right, int bottom) {
164        return nClipRect(mRenderer, left, top, right, bottom);
165    }
166
167    private native boolean nClipRect(int renderer, int left, int top, int right, int bottom);
168
169    @Override
170    public boolean clipRect(Rect rect) {
171        return clipRect(rect.left, rect.top, rect.right, rect.bottom);
172    }
173
174    @Override
175    public boolean clipRect(Rect rect, Region.Op op) {
176        // TODO: Implement
177        throw new UnsupportedOperationException();
178    }
179
180    @Override
181    public boolean clipRect(RectF rect) {
182        return clipRect(rect.left, rect.top, rect.right, rect.bottom);
183    }
184
185    @Override
186    public boolean clipRect(RectF rect, Region.Op op) {
187        // TODO: Implement
188        throw new UnsupportedOperationException();
189    }
190
191    @Override
192    public boolean clipRegion(Region region) {
193        throw new UnsupportedOperationException();
194    }
195
196    @Override
197    public boolean clipRegion(Region region, Region.Op op) {
198        throw new UnsupportedOperationException();
199    }
200
201    @Override
202    public boolean getClipBounds(Rect bounds) {
203        return nGetClipBounds(mRenderer, bounds);
204    }
205
206    private native boolean nGetClipBounds(int renderer, Rect bounds);
207
208    @Override
209    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
210        return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
211    }
212
213    private native boolean nQuickReject(int renderer, float left, float top,
214            float right, float bottom, int edge);
215
216    @Override
217    public boolean quickReject(Path path, EdgeType type) {
218        throw new UnsupportedOperationException();
219    }
220
221    @Override
222    public boolean quickReject(RectF rect, EdgeType type) {
223        return quickReject(rect.left, rect.top, rect.right, rect.bottom, type);
224    }
225
226    ///////////////////////////////////////////////////////////////////////////
227    // Transformations
228    ///////////////////////////////////////////////////////////////////////////
229
230    @Override
231    public void translate(float dx, float dy) {
232        nTranslate(mRenderer, dx, dy);
233    }
234
235    private native void nTranslate(int renderer, float dx, float dy);
236
237    @Override
238    public void skew(float sx, float sy) {
239        throw new UnsupportedOperationException();
240    }
241
242    @Override
243    public void rotate(float degrees) {
244        nRotate(mRenderer, degrees);
245    }
246
247    private native void nRotate(int renderer, float degrees);
248
249    @Override
250    public void scale(float sx, float sy) {
251        nScale(mRenderer, sx, sy);
252    }
253
254    private native void nScale(int renderer, float sx, float sy);
255
256    @Override
257    public void setMatrix(Matrix matrix) {
258        nSetMatrix(mRenderer, matrix.native_instance);
259    }
260
261    private native void nSetMatrix(int renderer, int matrix);
262
263    @Override
264    public void getMatrix(Matrix matrix) {
265        nGetMatrix(mRenderer, matrix.native_instance);
266    }
267
268    private native void nGetMatrix(int renderer, int matrix);
269
270    @Override
271    public void concat(Matrix matrix) {
272        nConcatMatrix(mRenderer, matrix.native_instance);
273    }
274
275    private native void nConcatMatrix(int renderer, int matrix);
276
277    ///////////////////////////////////////////////////////////////////////////
278    // State management
279    ///////////////////////////////////////////////////////////////////////////
280
281    @Override
282    public int save() {
283        return nSave(mRenderer, 0);
284    }
285
286    @Override
287    public int save(int saveFlags) {
288        return nSave(mRenderer, saveFlags);
289    }
290
291    private native int nSave(int renderer, int flags);
292
293    @Override
294    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
295        return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
296    }
297
298    @Override
299    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
300            int saveFlags) {
301        int nativePaint = paint == null ? 0 : paint.mNativePaint;
302        return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
303    }
304
305    private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
306            int paint, int saveFlags);
307
308    @Override
309    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
310        return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
311                alpha, saveFlags);
312    }
313
314    @Override
315    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
316            int saveFlags) {
317        return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
318    }
319
320    private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
321            float bottom, int alpha, int saveFlags);
322
323    @Override
324    public void restore() {
325        nRestore(mRenderer);
326    }
327
328    private native void nRestore(int renderer);
329
330    @Override
331    public void restoreToCount(int saveCount) {
332        nRestoreToCount(mRenderer, saveCount);
333    }
334
335    private native void nRestoreToCount(int renderer, int saveCount);
336
337    @Override
338    public int getSaveCount() {
339        return nGetSaveCount(mRenderer);
340    }
341
342    private native int nGetSaveCount(int renderer);
343
344    ///////////////////////////////////////////////////////////////////////////
345    // Filtering
346    ///////////////////////////////////////////////////////////////////////////
347
348    @Override
349    public void setDrawFilter(DrawFilter filter) {
350        // Don't crash, but ignore the draw filter
351        // TODO: Implement PaintDrawFilter
352        mFilter = filter;
353    }
354
355    @Override
356    public DrawFilter getDrawFilter() {
357        return mFilter;
358    }
359
360    ///////////////////////////////////////////////////////////////////////////
361    // Drawing
362    ///////////////////////////////////////////////////////////////////////////
363
364    @Override
365    public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
366            Paint paint) {
367        throw new UnsupportedOperationException();
368    }
369
370    @Override
371    public void drawARGB(int a, int r, int g, int b) {
372        drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
373    }
374
375    @Override
376    public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
377        // Shaders are ignored when drawing patches
378        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
379        nDrawPatch(mRenderer, bitmap.mNativeBitmap, chunks, dst.left, dst.top,
380                dst.right, dst.bottom, nativePaint);
381    }
382
383    private native void nDrawPatch(int renderer, int bitmap, byte[] chunks, float left, float top,
384            float right, float bottom, int paint);
385
386    @Override
387    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
388        // Shaders are ignored when drawing bitmaps
389        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
390        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
391    }
392
393    private native void nDrawBitmap(int renderer, int bitmap, float left, float top, int paint);
394
395    @Override
396    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
397        // Shaders are ignored when drawing bitmaps
398        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
399        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
400    }
401
402    private native void nDrawBitmap(int renderer, int bitmap, int matrix, int paint);
403
404    @Override
405    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
406        // Shaders are ignored when drawing bitmaps
407        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
408        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
409                dst.left, dst.top, dst.right, dst.bottom, nativePaint
410        );
411    }
412
413    @Override
414    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
415        // Shaders are ignored when drawing bitmaps
416        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
417        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
418                dst.left, dst.top, dst.right, dst.bottom, nativePaint
419        );
420    }
421
422    private native void nDrawBitmap(int renderer, int bitmap,
423            float srcLeft, float srcTop, float srcRight, float srcBottom,
424            float left, float top, float right, float bottom, int paint);
425
426    @Override
427    public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
428            int width, int height, boolean hasAlpha, Paint paint) {
429        // Shaders are ignored when drawing bitmaps
430        final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
431        final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config);
432        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
433        nDrawBitmap(mRenderer, b.mNativeBitmap, x, y, nativePaint);
434        b.recycle();
435    }
436
437    @Override
438    public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
439            int width, int height, boolean hasAlpha, Paint paint) {
440        // Shaders are ignored when drawing bitmaps
441        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
442    }
443
444    @Override
445    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
446            int vertOffset, int[] colors, int colorOffset, Paint paint) {
447        // TODO: Implement
448    }
449
450    @Override
451    public void drawCircle(float cx, float cy, float radius, Paint paint) {
452        throw new UnsupportedOperationException();
453    }
454
455    @Override
456    public void drawColor(int color) {
457        drawColor(color, PorterDuff.Mode.SRC_OVER);
458    }
459
460    @Override
461    public void drawColor(int color, PorterDuff.Mode mode) {
462        nDrawColor(mRenderer, color, mode.nativeInt);
463    }
464
465    private native void nDrawColor(int renderer, int color, int mode);
466
467    @Override
468    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
469        mLine[0] = startX;
470        mLine[1] = startY;
471        mLine[2] = stopX;
472        mLine[3] = stopY;
473        drawLines(mLine, 0, 1, paint);
474    }
475
476    @Override
477    public void drawLines(float[] pts, int offset, int count, Paint paint) {
478        // TODO: Implement
479    }
480
481    @Override
482    public void drawLines(float[] pts, Paint paint) {
483        drawLines(pts, 0, pts.length / 4, paint);
484    }
485
486    @Override
487    public void drawOval(RectF oval, Paint paint) {
488        throw new UnsupportedOperationException();
489    }
490
491    @Override
492    public void drawPaint(Paint paint) {
493        final Rect r = mClipBounds;
494        nGetClipBounds(mRenderer, r);
495        drawRect(r.left, r.top, r.right, r.bottom, paint);
496    }
497
498    @Override
499    public void drawPath(Path path, Paint paint) {
500        throw new UnsupportedOperationException();
501    }
502
503    @Override
504    public void drawPicture(Picture picture) {
505        throw new UnsupportedOperationException();
506    }
507
508    @Override
509    public void drawPicture(Picture picture, Rect dst) {
510        throw new UnsupportedOperationException();
511    }
512
513    @Override
514    public void drawPicture(Picture picture, RectF dst) {
515        throw new UnsupportedOperationException();
516    }
517
518    @Override
519    public void drawPoint(float x, float y, Paint paint) {
520        mPoint[0] = x;
521        mPoint[1] = y;
522        drawPoints(mPoint, 0, 1, paint);
523    }
524
525    @Override
526    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
527        // TODO: Implement
528    }
529
530    @Override
531    public void drawPoints(float[] pts, Paint paint) {
532        drawPoints(pts, 0, pts.length / 2, paint);
533    }
534
535    @Override
536    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
537        throw new UnsupportedOperationException();
538    }
539
540    @Override
541    public void drawPosText(String text, float[] pos, Paint paint) {
542        throw new UnsupportedOperationException();
543    }
544
545    @Override
546    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
547        boolean hasShader = setupShader(paint);
548        nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
549        if (hasShader) nResetShader(mRenderer);
550    }
551
552    private native void nDrawRect(int renderer, float left, float top, float right, float bottom,
553            int paint);
554
555    @Override
556    public void drawRect(Rect r, Paint paint) {
557        drawRect(r.left, r.top, r.right, r.bottom, paint);
558    }
559
560    @Override
561    public void drawRect(RectF r, Paint paint) {
562        drawRect(r.left, r.top, r.right, r.bottom, paint);
563    }
564
565    @Override
566    public void drawRGB(int r, int g, int b) {
567        drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
568    }
569
570    @Override
571    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
572        // TODO: Implement
573    }
574
575    @Override
576    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
577        // TODO: Implement
578    }
579
580    @Override
581    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
582        // TODO: Implement
583    }
584
585    @Override
586    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
587        // TODO: Implement
588    }
589
590    @Override
591    public void drawText(String text, float x, float y, Paint paint) {
592        drawText(text, 0, text.length(), x, y, paint);
593    }
594
595    @Override
596    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
597            float vOffset, Paint paint) {
598        throw new UnsupportedOperationException();
599    }
600
601    @Override
602    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
603        throw new UnsupportedOperationException();
604    }
605
606    @Override
607    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
608            float x, float y, int dir, Paint paint) {
609        throw new UnsupportedOperationException();
610    }
611
612    @Override
613    public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
614            float x, float y, int dir, Paint paint) {
615        throw new UnsupportedOperationException();
616    }
617
618    @Override
619    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
620            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
621            int indexOffset, int indexCount, Paint paint) {
622        // TODO: Implement
623    }
624
625    private boolean setupShader(Paint paint) {
626        final Shader shader = paint.getShader();
627        if (shader != null) {
628            if (shader instanceof BitmapShader) {
629                final BitmapShader bs = (BitmapShader) shader;
630                nSetupBitmapShader(mRenderer, bs.native_instance, bs.mBitmap.mNativeBitmap,
631                        bs.mTileX, bs.mTileY, bs.mLocalMatrix);
632                return true;
633            } else if (shader instanceof LinearGradient) {
634                // TODO: Implement
635            } else if (shader instanceof RadialGradient) {
636                // TODO: Implement
637            } else if (shader instanceof SweepGradient) {
638                // TODO: Implement
639            }
640        }
641        return false;
642    }
643
644    private native void nSetupBitmapShader(int renderer, int shader, int bitmap,
645            int tileX, int tileY, int matrix);
646    private native void nResetShader(int renderer);
647}
648