• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.gallery3d.ui;
18 
19 import android.test.suitebuilder.annotation.SmallTest;
20 import android.util.Log;
21 
22 import junit.framework.TestCase;
23 
24 import java.util.Arrays;
25 
26 import javax.microedition.khronos.opengles.GL10;
27 import javax.microedition.khronos.opengles.GL11;
28 
29 @SmallTest
30 public class GLCanvasTest extends TestCase {
31     private static final String TAG = "GLCanvasTest";
32 
newColorPaint(int color)33     private static GLPaint newColorPaint(int color) {
34         GLPaint paint = new GLPaint();
35         paint.setColor(color);
36         return paint;
37     }
38 
39     @SmallTest
testSetSize()40     public void testSetSize() {
41         GL11 glStub = new GLStub();
42         GLCanvas canvas = new GLCanvasImpl(glStub);
43         canvas.setSize(100, 200);
44         canvas.setSize(1000, 100);
45         try {
46             canvas.setSize(-1, 100);
47             fail();
48         } catch (Throwable ex) {
49             // expected.
50         }
51     }
52 
53     @SmallTest
testClearBuffer()54     public void testClearBuffer() {
55         new ClearBufferTest().run();
56     }
57 
58     private static class ClearBufferTest extends GLMock {
run()59         void run() {
60             GLCanvas canvas = new GLCanvasImpl(this);
61             assertEquals(0, mGLClearCalled);
62             canvas.clearBuffer();
63             assertEquals(GL10.GL_COLOR_BUFFER_BIT, mGLClearMask);
64             assertEquals(1, mGLClearCalled);
65         }
66     }
67 
68     @SmallTest
testSetColor()69     public void testSetColor() {
70         new SetColorTest().run();
71     }
72 
73     // This test assumes we use pre-multipled alpha blending and should
74     // set the blending function and color correctly.
75     private static class SetColorTest extends GLMock {
run()76         void run() {
77             int[] testColors = new int[] {
78                 0, 0xFFFFFFFF, 0xFF000000, 0x00FFFFFF, 0x80FF8001,
79                 0x7F010101, 0xFEFEFDFC, 0x017F8081, 0x027F8081, 0x2ADE4C4D
80             };
81 
82             GLCanvas canvas = new GLCanvasImpl(this);
83             canvas.setSize(400, 300);
84             // Test one color to make sure blend function is set.
85             assertEquals(0, mGLColorCalled);
86             canvas.drawLine(0, 0, 1, 1, newColorPaint(0x7F804020));
87             assertEquals(1, mGLColorCalled);
88             assertEquals(0x7F402010, mGLColor);
89             assertPremultipliedBlending(this);
90 
91             // Test other colors to make sure premultiplication is right
92             for (int c : testColors) {
93                 float a = (c >>> 24) / 255f;
94                 float r = ((c >> 16) & 0xff) / 255f;
95                 float g = ((c >> 8) & 0xff) / 255f;
96                 float b = (c & 0xff) / 255f;
97                 int pre = makeColor4f(a * r, a * g, a * b, a);
98 
99                 mGLColorCalled = 0;
100                 canvas.drawLine(0, 0, 1, 1, newColorPaint(c));
101                 assertEquals(1, mGLColorCalled);
102                 assertEquals(pre, mGLColor);
103             }
104         }
105     }
106 
107     @SmallTest
testSetGetMultiplyAlpha()108     public void testSetGetMultiplyAlpha() {
109         GL11 glStub = new GLStub();
110         GLCanvas canvas = new GLCanvasImpl(glStub);
111 
112         canvas.setAlpha(1f);
113         assertEquals(1f, canvas.getAlpha());
114 
115         canvas.setAlpha(0f);
116         assertEquals(0f, canvas.getAlpha());
117 
118         canvas.setAlpha(0.5f);
119         assertEquals(0.5f, canvas.getAlpha());
120 
121         canvas.multiplyAlpha(0.5f);
122         assertEquals(0.25f, canvas.getAlpha());
123 
124         canvas.multiplyAlpha(0f);
125         assertEquals(0f, canvas.getAlpha());
126 
127         try {
128             canvas.setAlpha(-0.01f);
129             fail();
130         } catch (Throwable ex) {
131             // expected.
132         }
133 
134         try {
135             canvas.setAlpha(1.01f);
136             fail();
137         } catch (Throwable ex) {
138             // expected.
139         }
140     }
141 
142     @SmallTest
testAlpha()143     public void testAlpha() {
144         new AlphaTest().run();
145     }
146 
147     private static class AlphaTest extends GLMock {
run()148         void run() {
149             GLCanvas canvas = new GLCanvasImpl(this);
150             canvas.setSize(400, 300);
151 
152             assertEquals(0, mGLColorCalled);
153             canvas.setAlpha(0.48f);
154             canvas.drawLine(0, 0, 1, 1, newColorPaint(0xFF804020));
155             assertPremultipliedBlending(this);
156             assertEquals(1, mGLColorCalled);
157             assertEquals(0x7A3D1F0F, mGLColor);
158         }
159     }
160 
161     @SmallTest
testDrawLine()162     public void testDrawLine() {
163         new DrawLineTest().run();
164     }
165 
166     // This test assumes the drawLine() function use glDrawArrays() with
167     // GL_LINE_STRIP mode to draw the line and the input coordinates are used
168     // directly.
169     private static class DrawLineTest extends GLMock {
170         private int mDrawArrayCalled = 0;
171         private final int[] mResult = new int[4];
172 
173         @Override
glDrawArrays(int mode, int first, int count)174         public void glDrawArrays(int mode, int first, int count) {
175             assertNotNull(mGLVertexPointer);
176             assertEquals(GL10.GL_LINE_STRIP, mode);
177             assertEquals(2, count);
178             mGLVertexPointer.bindByteBuffer();
179 
180             double[] coord = new double[4];
181             mGLVertexPointer.getArrayElement(first, coord);
182             mResult[0] = (int) coord[0];
183             mResult[1] = (int) coord[1];
184             mGLVertexPointer.getArrayElement(first + 1, coord);
185             mResult[2] = (int) coord[0];
186             mResult[3] = (int) coord[1];
187             mDrawArrayCalled++;
188         }
189 
run()190         void run() {
191             GLCanvas canvas = new GLCanvasImpl(this);
192             canvas.setSize(400, 300);
193             canvas.drawLine(2, 7, 1, 8, newColorPaint(0) /* color */);
194             assertTrue(mGLVertexArrayEnabled);
195             assertEquals(1, mDrawArrayCalled);
196 
197             Log.v(TAG, "result = " + Arrays.toString(mResult));
198             int[] answer = new int[] {2, 7, 1, 8};
199             for (int i = 0; i < answer.length; i++) {
200                 assertEquals(answer[i], mResult[i]);
201             }
202         }
203     }
204 
205     @SmallTest
testFillRect()206     public void testFillRect() {
207         new FillRectTest().run();
208     }
209 
210     // This test assumes the drawLine() function use glDrawArrays() with
211     // GL_TRIANGLE_STRIP mode to draw the line and the input coordinates
212     // are used directly.
213     private static class FillRectTest extends GLMock {
214         private int mDrawArrayCalled = 0;
215         private final int[] mResult = new int[8];
216 
217         @Override
glDrawArrays(int mode, int first, int count)218         public void glDrawArrays(int mode, int first, int count) {
219             assertNotNull(mGLVertexPointer);
220             assertEquals(GL10.GL_TRIANGLE_STRIP, mode);
221             assertEquals(4, count);
222             mGLVertexPointer.bindByteBuffer();
223 
224             double[] coord = new double[4];
225             for (int i = 0; i < 4; i++) {
226                 mGLVertexPointer.getArrayElement(first + i, coord);
227                 mResult[i * 2 + 0] = (int) coord[0];
228                 mResult[i * 2 + 1] = (int) coord[1];
229             }
230 
231             mDrawArrayCalled++;
232         }
233 
run()234         void run() {
235             GLCanvas canvas = new GLCanvasImpl(this);
236             canvas.setSize(400, 300);
237             canvas.fillRect(2, 7, 1, 8, 0 /* color */);
238             assertTrue(mGLVertexArrayEnabled);
239             assertEquals(1, mDrawArrayCalled);
240             Log.v(TAG, "result = " + Arrays.toString(mResult));
241 
242             // These are the four vertics that should be used.
243             int[] answer = new int[] {
244                 2, 7,
245                 3, 7,
246                 3, 15,
247                 2, 15};
248             int count[] = new int[4];
249 
250             // Count the number of appearances for each vertex.
251             for (int i = 0; i < 4; i++) {
252                 for (int j = 0; j < 4; j++) {
253                     if (answer[i * 2] == mResult[j * 2] &&
254                         answer[i * 2 + 1] == mResult[j * 2 + 1]) {
255                         count[i]++;
256                     }
257                 }
258             }
259 
260             // Each vertex should appear exactly once.
261             for (int i = 0; i < 4; i++) {
262                 assertEquals(1, count[i]);
263             }
264         }
265     }
266 
267     @SmallTest
testTransform()268     public void testTransform() {
269         new TransformTest().run();
270     }
271 
272     // This test assumes glLoadMatrixf is used to load the model view matrix,
273     // and glOrthof is used to load the projection matrix.
274     //
275     // The projection matrix is set to an orthogonal projection which is the
276     // inverse of viewport transform. So the model view matrix maps input
277     // directly to screen coordinates (default no scaling, and the y-axis is
278     // reversed).
279     //
280     // The matrix here are all listed in column major order.
281     //
282     private static class TransformTest extends GLMock {
283         private final float[] mModelViewMatrixUsed = new float[16];
284         private final float[] mProjectionMatrixUsed = new float[16];
285 
286         @Override
glDrawArrays(int mode, int first, int count)287         public void glDrawArrays(int mode, int first, int count) {
288             copy(mModelViewMatrixUsed, mGLModelViewMatrix);
289             copy(mProjectionMatrixUsed, mGLProjectionMatrix);
290         }
291 
copy(float[] dest, float[] src)292         private void copy(float[] dest, float[] src) {
293             System.arraycopy(src, 0, dest, 0, 16);
294         }
295 
run()296         void run() {
297             GLCanvas canvas = new GLCanvasImpl(this);
298             canvas.setSize(40, 50);
299             int color = 0;
300 
301             // Initial matrix
302             canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
303             assertMatrixEq(new float[] {
304                     1,  0, 0, 0,
305                     0, -1, 0, 0,
306                     0,  0, 1, 0,
307                     0, 50, 0, 1
308                     }, mModelViewMatrixUsed);
309 
310             assertMatrixEq(new float[] {
311                     2f / 40,       0,  0, 0,
312                           0, 2f / 50,  0, 0,
313                           0,       0, -1, 0,
314                          -1,      -1,  0, 1
315                     }, mProjectionMatrixUsed);
316 
317             // Translation
318             canvas.translate(3, 4, 5);
319             canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
320             assertMatrixEq(new float[] {
321                     1,  0, 0, 0,
322                     0, -1, 0, 0,
323                     0,  0, 1, 0,
324                     3, 46, 5, 1
325                     }, mModelViewMatrixUsed);
326             canvas.save();
327 
328             // Scaling
329             canvas.scale(0.7f, 0.6f, 0.5f);
330             canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
331             assertMatrixEq(new float[] {
332                     0.7f,     0,    0, 0,
333                     0,    -0.6f,    0, 0,
334                     0,        0, 0.5f, 0,
335                     3,       46,    5, 1
336                     }, mModelViewMatrixUsed);
337 
338             // Rotation
339             canvas.rotate(90, 0, 0, 1);
340             canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
341             assertMatrixEq(new float[] {
342                         0, -0.6f,    0, 0,
343                     -0.7f,     0,    0, 0,
344                         0,     0, 0.5f, 0,
345                         3,    46,    5, 1
346                     }, mModelViewMatrixUsed);
347             canvas.restore();
348 
349             // After restoring to the point just after translation,
350             // do rotation again.
351             canvas.rotate(180, 1, 0, 0);
352             canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
353             assertMatrixEq(new float[] {
354                     1,  0,  0, 0,
355                     0,  1,  0, 0,
356                     0,  0, -1, 0,
357                     3, 46,  5, 1
358                     }, mModelViewMatrixUsed);
359         }
360     }
361 
362     @SmallTest
testGetGLInstance()363     public void testGetGLInstance() {
364         GL11 glStub = new GLStub();
365         GLCanvas canvas = new GLCanvasImpl(glStub);
366         assertSame(glStub, canvas.getGLInstance());
367     }
368 
assertPremultipliedBlending(GLMock mock)369     private static void assertPremultipliedBlending(GLMock mock) {
370         assertTrue(mock.mGLBlendFuncCalled > 0);
371         assertTrue(mock.mGLBlendEnabled);
372         assertEquals(GL11.GL_ONE, mock.mGLBlendFuncSFactor);
373         assertEquals(GL11.GL_ONE_MINUS_SRC_ALPHA, mock.mGLBlendFuncDFactor);
374     }
375 
assertMatrixEq(float[] expected, float[] actual)376     private static void assertMatrixEq(float[] expected, float[] actual) {
377         try {
378             for (int i = 0; i < 16; i++) {
379                 assertFloatEq(expected[i], actual[i]);
380             }
381         } catch (Throwable t) {
382             Log.v(TAG, "expected = " + Arrays.toString(expected) +
383                     ", actual = " + Arrays.toString(actual));
384             fail();
385         }
386     }
387 
assertFloatEq(float expected, float actual)388     public static void assertFloatEq(float expected, float actual) {
389         if (Math.abs(actual - expected) > 1e-6) {
390             Log.v(TAG, "expected: " + expected + ", actual: " + actual);
391             fail();
392         }
393     }
394 }
395