1/*
2 * Copyright (C) 2008 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 com.example.android.apis.graphics;
18
19import java.io.ByteArrayInputStream;
20import java.io.ByteArrayOutputStream;
21import java.io.IOException;
22import java.io.InputStream;
23import java.nio.Buffer;
24import java.nio.ByteBuffer;
25import java.nio.ByteOrder;
26
27import javax.microedition.khronos.opengles.GL10;
28
29import android.app.Activity;
30import android.opengl.ETC1Util;
31import android.opengl.GLES10;
32import android.opengl.GLSurfaceView;
33import android.os.Bundle;
34import android.util.Log;
35
36import com.example.android.apis.R;
37
38/**
39 * Demonstrate how to use ETC1 format compressed textures.
40 * This sample can be recompiled to use either resource-based
41 * textures (compressed offline using the etc1tool), or
42 * textures created on the fly by compressing images.
43 *
44 */
45public class CompressedTextureActivity extends Activity {
46    private final static String TAG = "CompressedTextureActivity";
47    /**
48     * Choose between creating a compressed texture on the fly or
49     * loading a compressed texture from a resource.
50     */
51    private final static boolean TEST_CREATE_TEXTURE = false;
52    /**
53     * When creating a compressed texture on the fly, choose
54     * whether or not to use the i/o stream APIs.
55     */
56    private final static boolean USE_STREAM_IO = false;
57
58    @Override
59    protected void onCreate(Bundle savedInstanceState) {
60        super.onCreate(savedInstanceState);
61        mGLView = new GLSurfaceView(this);
62        mGLView.setEGLConfigChooser(false);
63        StaticTriangleRenderer.TextureLoader loader;
64        if (TEST_CREATE_TEXTURE) {
65            loader = new SyntheticCompressedTextureLoader();
66        } else {
67            loader = new CompressedTextureLoader();
68        }
69        mGLView.setRenderer(new StaticTriangleRenderer(this, loader));
70        setContentView(mGLView);
71    }
72
73    @Override
74    protected void onPause() {
75        super.onPause();
76        mGLView.onPause();
77    }
78
79    @Override
80    protected void onResume() {
81        super.onResume();
82        mGLView.onResume();
83    }
84
85    /**
86     * Demonstrate how to load a compressed texture from an APK resource.
87     *
88     */
89    private class CompressedTextureLoader implements StaticTriangleRenderer.TextureLoader {
90        public void load(GL10 gl) {
91            Log.w(TAG, "ETC1 texture support: " + ETC1Util.isETC1Supported());
92            InputStream input = getResources().openRawResource(R.raw.androids);
93            try {
94                ETC1Util.loadTexture(GLES10.GL_TEXTURE_2D, 0, 0,
95                        GLES10.GL_RGB, GLES10.GL_UNSIGNED_SHORT_5_6_5, input);
96            } catch (IOException e) {
97                Log.w(TAG, "Could not load texture: " + e);
98            } finally {
99                try {
100                    input.close();
101                } catch (IOException e) {
102                    // ignore exception thrown from close.
103                }
104            }
105        }
106    }
107
108    /**
109     * Demonstrate how to create a compressed texture on the fly.
110     */
111    private class SyntheticCompressedTextureLoader implements StaticTriangleRenderer.TextureLoader {
112        public void load(GL10 gl) {
113            int width = 128;
114            int height = 128;
115            Buffer image = createImage(width, height);
116            ETC1Util.ETC1Texture etc1Texture = ETC1Util.compressTexture(image, width, height, 3, 3 * width);
117            if (USE_STREAM_IO) {
118                // Test the ETC1Util APIs for reading and writing compressed textures to I/O streams.
119                try {
120                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
121                    ETC1Util.writeTexture(etc1Texture, bos);
122                    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
123                    ETC1Util.loadTexture(GLES10.GL_TEXTURE_2D, 0, 0,
124                            GLES10.GL_RGB, GLES10.GL_UNSIGNED_SHORT_5_6_5, bis);
125                } catch (IOException e) {
126                    Log.w(TAG, "Could not load texture: " + e);
127                }
128            } else {
129                ETC1Util.loadTexture(GLES10.GL_TEXTURE_2D, 0, 0,
130                        GLES10.GL_RGB, GLES10.GL_UNSIGNED_SHORT_5_6_5, etc1Texture);
131            }
132        }
133
134        private Buffer createImage(int width, int height) {
135            int stride = 3 * width;
136            ByteBuffer image = ByteBuffer.allocateDirect(height * stride)
137                .order(ByteOrder.nativeOrder());
138
139            // Fill with a pretty "munching squares" pattern:
140            for (int t = 0; t < height; t++) {
141                byte red = (byte)(255-2*t);
142                byte green = (byte)(2*t);
143                byte blue = 0;
144                for (int x = 0; x < width; x++) {
145                    int y = x ^ t;
146                    image.position(stride*y+x*3);
147                    image.put(red);
148                    image.put(green);
149                    image.put(blue);
150                }
151            }
152            image.position(0);
153            return image;
154        }
155    }
156    private GLSurfaceView mGLView;
157}
158