1204009b9114b33f184d7178838861d2fa9c9f88cJason Sams/*
2204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * Copyright (C) 2013 The Android Open Source Project
3204009b9114b33f184d7178838861d2fa9c9f88cJason Sams *
4204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * you may not use this file except in compliance with the License.
6204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * You may obtain a copy of the License at
7204009b9114b33f184d7178838861d2fa9c9f88cJason Sams *
8204009b9114b33f184d7178838861d2fa9c9f88cJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9204009b9114b33f184d7178838861d2fa9c9f88cJason Sams *
10204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * Unless required by applicable law or agreed to in writing, software
11204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * See the License for the specific language governing permissions and
14204009b9114b33f184d7178838861d2fa9c9f88cJason Sams * limitations under the License.
15204009b9114b33f184d7178838861d2fa9c9f88cJason Sams */
16204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
17204009b9114b33f184d7178838861d2fa9c9f88cJason Samspackage com.android.rs.genimage;
18204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
19204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport android.content.Context;
20204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
21204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport java.io.FileOutputStream;
22204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport java.nio.ByteBuffer;
23204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport java.nio.IntBuffer;
24204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport java.nio.ByteOrder;
25204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport java.nio.FloatBuffer;
26204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
27204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport android.graphics.Bitmap;
28204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport android.graphics.BitmapFactory;
29204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
30204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport javax.microedition.khronos.egl.EGLConfig;
31204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport javax.microedition.khronos.opengles.GL10;
32204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport android.opengl.GLUtils;
33204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
34204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport android.opengl.GLES20;
35204009b9114b33f184d7178838861d2fa9c9f88cJason Samsimport android.opengl.GLSurfaceView;
36204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
37204009b9114b33f184d7178838861d2fa9c9f88cJason Samspublic class GenImage implements GLSurfaceView.Renderer {
38204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private Bitmap mTestImage;
39204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
40204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private Triangle mTriangle;
41204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
42204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
43204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private Bitmap loadBitmap(Context context, int resource) {
44204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        final BitmapFactory.Options options = new BitmapFactory.Options();
45204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
46204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        return BitmapFactory.decodeResource(context.getResources(), resource, options);
47204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
48204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
49204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    GenImage(Context context) {
50204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
51204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        mTestImage = loadBitmap(context, R.drawable.test_pattern);
52204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
53204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
54204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
55204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    @Override
56204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
57204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
58204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Set the background frame color
59204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
60204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
61204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        mTriangle = new Triangle(mTestImage);
62204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
63204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
64204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    @Override
65204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public void onDrawFrame(GL10 unused) {
66204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
67204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Draw background color
68204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
69204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
70204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Draw triangle
71204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        mTriangle.draw();
72204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
73204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
74204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    @Override
75204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public void onSurfaceChanged(GL10 unused, int width, int height) {
76204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Adjust the viewport based on geometry changes,
77204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // such as screen rotation
78204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glViewport(0, 0, 512, 512);
79204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
80204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
81204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public static int loadShader(int type, String shaderCode){
82204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
83204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
84204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
85204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        int shader = GLES20.glCreateShader(type);
86204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
87204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // add the source code to the shader and compile it
88204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glShaderSource(shader, shaderCode);
89204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glCompileShader(shader);
90204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
91204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        return shader;
92204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
93204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
94204009b9114b33f184d7178838861d2fa9c9f88cJason Sams}
95204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
96204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
97204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
98204009b9114b33f184d7178838861d2fa9c9f88cJason Samsclass Triangle {
99204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    int mTextureIDs[] = new int[1];
100204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
101204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private final String vertexShaderCode =
102204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "varying vec2 vTex0;" +
103204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "varying vec2 vPos0;" +
104204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "attribute vec4 aPosition;" +
105204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "void main() {" +
106204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  gl_Position = aPosition;" +
107204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  vPos0 = aPosition.xy;" +
108204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  vTex0 = ((aPosition.xy + 1.0) * 0.6);" +
109204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        //"  vTex0 = (aPosition.xy * 1.7) + 0.5;" +
110204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "}";
111204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
112204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private final String fragmentShaderCode =
113204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "precision mediump float;" +
114204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "varying vec2 vTex0;" +
115204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "varying vec2 vPos0;" +
116204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "uniform sampler2D uSamp;" +
117204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "void main() {" +
118204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  vec2 tc = vTex0;" +
119204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        //"  tc.x *= pow(vPos0.y + 1.0, 2.0);" +
120204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        //"  tc.y *= pow(vPos0.x + 1.0, 2.0);" +
121204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  vec4 c = texture2D(uSamp, tc);" +
122204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  c.a = 1.0;" +
123204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "  gl_FragColor = c;" +
124204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        "}";
125204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
126204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private final FloatBuffer vertexBuffer;
127204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    private final int mProgram;
128204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
129204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    // number of coordinates per vertex in this array
130204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    static float triangleCoords[] = { // in counterclockwise order:
131204009b9114b33f184d7178838861d2fa9c9f88cJason Sams       -1.0f,  1.0f, 0.0f,   // top left
132204009b9114b33f184d7178838861d2fa9c9f88cJason Sams       -1.0f, -1.0f, 0.0f,   // bottom left
133204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        1.0f, -1.0f, 0.0f,   // bottom right
134204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
135204009b9114b33f184d7178838861d2fa9c9f88cJason Sams       -1.0f,  1.0f, 0.0f,   // top left
136204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        1.0f, -1.0f, 0.0f,   // bottom right
137204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        1.0f,  1.0f, 0.0f    // top right
138204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    };
139204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
140204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    FloatBuffer createFloatBuffer(float buf[]) {
141204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        ByteBuffer bb = ByteBuffer.allocateDirect(buf.length * 4);
142204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        bb.order(ByteOrder.nativeOrder());
143204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        FloatBuffer fb = bb.asFloatBuffer();
144204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        fb.put(buf);
145204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        fb.position(0);
146204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        return fb;
147204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
148204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
149204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public String setup(int key) {
150204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        String s = new String();
151204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        int tmp;
152204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
153204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        tmp = key % 2;
154204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        key /= 2;
155204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        if (tmp != 0) {
156204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "N";
157204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
158204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        } else {
159204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "L";
160204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
161204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        }
162204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
163204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        tmp = key % 2;
164204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        key /= 2;
165204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        if (tmp != 0) {
166204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "N";
167204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
168204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        } else {
169204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "L";
170204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
171204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        }
172204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
173204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        tmp = key % 3;
174204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        key /= 3;
175204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        switch(tmp) {
176204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        case 0:
177204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "_CE";
178204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
179204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            break;
180204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        case 1:
181204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "_RE";
182204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
183204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            break;
184204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        case 2:
185204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "_MR";
186204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_MIRRORED_REPEAT);
187204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            break;
188204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        }
189204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
190204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        tmp = key % 3;
191204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        key /= 3;
192204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        switch(tmp) {
193204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        case 0:
194204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "_CE";
195204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
196204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            break;
197204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        case 1:
198204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "_RE";
199204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
200204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            break;
201204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        case 2:
202204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            s += "_MR";
203204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_MIRRORED_REPEAT);
204204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            break;
205204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        }
206204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
207204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        if (key > 0) done = true;
208204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        return s;
209204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
210204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
211204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public Triangle(Bitmap testImage) {
212204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        vertexBuffer = createFloatBuffer(triangleCoords);
213204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
214204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // prepare shaders and OpenGL program
215204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        int vertexShader = GenImage.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
216204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        int fragmentShader = GenImage.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
217204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
218204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
219204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
220204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
221204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glLinkProgram(mProgram);                  // create OpenGL program executables
222204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
223204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glGenTextures(1, mTextureIDs, 0);
224204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
225204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Bind to the texture in OpenGL
226204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIDs[0]);
227204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, testImage, 0);
228204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
229204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
230204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    boolean done = false;
231204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    int key = 0;
232204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
233204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    public void draw() {
234204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
235204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        String ext = setup(key++);
236204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
237204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Add program to OpenGL environment
238204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glUseProgram(mProgram);
239204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
240204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        int posA = GLES20.glGetAttribLocation(mProgram, "aPosition");
241204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glEnableVertexAttribArray(posA);
242204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glVertexAttribPointer(posA, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer);
243204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
244204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        int sampUni = GLES20.glGetUniformLocation(mProgram, "uSamp");
245204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glUniform1i(sampUni, 0);
246204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
247204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        // Draw the triangle
248204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, triangleCoords.length / 3);
249204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
250204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        if (!done) {
251204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            IntBuffer ib = IntBuffer.allocate(512*512);
252204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            ib.position(0);
253204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            GLES20.glReadPixels(0,0, 512, 512, GLES20.GL_RGBA,
254204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                                GLES20.GL_UNSIGNED_BYTE, ib);
255204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
256204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            Bitmap bmp = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
257204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            bmp.setPixels(ib.array(), 0, 512, 0, 0, 512, 512);
258204009b9114b33f184d7178838861d2fa9c9f88cJason Sams
259204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            try {
260204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                String s = new String("/sdcard/imgs/RsSampImg_");
261204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                s += ext + ".png";
262204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                FileOutputStream out = new FileOutputStream(s);
263204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                bmp.compress(Bitmap.CompressFormat.PNG, 95, out);
264204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                out.close();
265204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            } catch (Exception e) {
266204009b9114b33f184d7178838861d2fa9c9f88cJason Sams                e.printStackTrace();
267204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            }
268204009b9114b33f184d7178838861d2fa9c9f88cJason Sams            bmp.recycle();
269204009b9114b33f184d7178838861d2fa9c9f88cJason Sams        }
270204009b9114b33f184d7178838861d2fa9c9f88cJason Sams    }
271204009b9114b33f184d7178838861d2fa9c9f88cJason Sams}
272