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