1/*
2 * Copyright (C) 2006 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.opengl;
18
19import android.graphics.Bitmap;
20
21import javax.microedition.khronos.egl.EGL10;
22import javax.microedition.khronos.egl.EGL11;
23
24/**
25 *
26 * Utility class to help bridging OpenGL ES and Android APIs.
27 *
28 */
29
30public final class GLUtils {
31
32    /*
33     * We use a class initializer to allow the native code to cache some
34     * field offsets.
35     */
36    static {
37        nativeClassInit();
38    }
39
40    private GLUtils() {
41    }
42
43    /**
44     * return the internal format as defined by OpenGL ES of the supplied bitmap.
45     * @param bitmap
46     * @return the internal format of the bitmap.
47     */
48    public static int getInternalFormat(Bitmap bitmap) {
49        if (bitmap == null) {
50            throw new NullPointerException("getInternalFormat can't be used with a null Bitmap");
51        }
52        if (bitmap.isRecycled()) {
53            throw new IllegalArgumentException("bitmap is recycled");
54        }
55        int result = native_getInternalFormat(bitmap);
56        if (result < 0) {
57            throw new IllegalArgumentException("Unknown internalformat");
58        }
59        return result;
60    }
61
62    /**
63     * Return the type as defined by OpenGL ES of the supplied bitmap, if there
64     * is one. If the bitmap is stored in a compressed format, it may not have
65     * a valid OpenGL ES type.
66     * @throws IllegalArgumentException if the bitmap does not have a type.
67     * @param bitmap
68     * @return the OpenGL ES type of the bitmap.
69     */
70    public static int getType(Bitmap bitmap) {
71        if (bitmap == null) {
72            throw new NullPointerException("getType can't be used with a null Bitmap");
73        }
74        if (bitmap.isRecycled()) {
75            throw new IllegalArgumentException("bitmap is recycled");
76        }
77        int result = native_getType(bitmap);
78        if (result < 0) {
79            throw new IllegalArgumentException("Unknown type");
80        }
81        return result;
82    }
83
84    /**
85     * Calls glTexImage2D() on the current OpenGL context. If no context is
86     * current the behavior is the same as calling glTexImage2D() with  no
87     * current context, that is, eglGetError() will return the appropriate
88     * error.
89     * Unlike glTexImage2D() bitmap cannot be null and will raise an exception
90     * in that case.
91     * All other parameters are identical to those used for glTexImage2D().
92     *
93     * NOTE: this method doesn't change GL_UNPACK_ALIGNMENT, you must make
94     * sure to set it properly according to the supplied bitmap.
95     *
96     * Whether or not bitmap can have non power of two dimensions depends on
97     * the current OpenGL context. Always check glGetError() some time
98     * after calling this method, just like when using OpenGL directly.
99     *
100     * @param target
101     * @param level
102     * @param internalformat
103     * @param bitmap
104     * @param border
105     */
106    public static void texImage2D(int target, int level, int internalformat,
107            Bitmap bitmap, int border) {
108        if (bitmap == null) {
109            throw new NullPointerException("texImage2D can't be used with a null Bitmap");
110        }
111        if (bitmap.isRecycled()) {
112            throw new IllegalArgumentException("bitmap is recycled");
113        }
114        if (native_texImage2D(target, level, internalformat, bitmap, -1, border)!=0) {
115            throw new IllegalArgumentException("invalid Bitmap format");
116        }
117    }
118
119    /**
120     * A version of texImage2D() that takes an explicit type parameter
121     * as defined by the OpenGL ES specification. The actual type and
122     * internalformat of the bitmap must be compatible with the specified
123     * type and internalformat parameters.
124     *
125     * @param target
126     * @param level
127     * @param internalformat
128     * @param bitmap
129     * @param type
130     * @param border
131     */
132    public static void texImage2D(int target, int level, int internalformat,
133            Bitmap bitmap, int type, int border) {
134        if (bitmap == null) {
135            throw new NullPointerException("texImage2D can't be used with a null Bitmap");
136        }
137        if (bitmap.isRecycled()) {
138            throw new IllegalArgumentException("bitmap is recycled");
139        }
140        if (native_texImage2D(target, level, internalformat, bitmap, type, border)!=0) {
141            throw new IllegalArgumentException("invalid Bitmap format");
142        }
143    }
144
145    /**
146     * A version of texImage2D that determines the internalFormat and type
147     * automatically.
148     *
149     * @param target
150     * @param level
151     * @param bitmap
152     * @param border
153     */
154    public static void texImage2D(int target, int level, Bitmap bitmap,
155            int border) {
156        if (bitmap == null) {
157            throw new NullPointerException("texImage2D can't be used with a null Bitmap");
158        }
159        if (bitmap.isRecycled()) {
160            throw new IllegalArgumentException("bitmap is recycled");
161        }
162        if (native_texImage2D(target, level, -1, bitmap, -1, border)!=0) {
163            throw new IllegalArgumentException("invalid Bitmap format");
164        }
165    }
166
167    /**
168     * Calls glTexSubImage2D() on the current OpenGL context. If no context is
169     * current the behavior is the same as calling glTexSubImage2D() with  no
170     * current context, that is, eglGetError() will return the appropriate
171     * error.
172     * Unlike glTexSubImage2D() bitmap cannot be null and will raise an exception
173     * in that case.
174     * All other parameters are identical to those used for glTexSubImage2D().
175     *
176     * NOTE: this method doesn't change GL_UNPACK_ALIGNMENT, you must make
177     * sure to set it properly according to the supplied bitmap.
178     *
179     * Whether or not bitmap can have non power of two dimensions depends on
180     * the current OpenGL context. Always check glGetError() some time
181     * after calling this method, just like when using OpenGL directly.
182     *
183     * @param target
184     * @param level
185     * @param xoffset
186     * @param yoffset
187     * @param bitmap
188     */
189    public static void texSubImage2D(int target, int level, int xoffset, int yoffset,
190            Bitmap bitmap) {
191        if (bitmap == null) {
192            throw new NullPointerException("texSubImage2D can't be used with a null Bitmap");
193        }
194        if (bitmap.isRecycled()) {
195            throw new IllegalArgumentException("bitmap is recycled");
196        }
197        int type = getType(bitmap);
198        if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, -1, type)!=0) {
199            throw new IllegalArgumentException("invalid Bitmap format");
200        }
201    }
202
203    /**
204     * A version of texSubImage2D() that takes an explicit type parameter
205     * as defined by the OpenGL ES specification.
206     *
207     * @param target
208     * @param level
209     * @param xoffset
210     * @param yoffset
211     * @param bitmap
212     * @param type
213     */
214    public static void texSubImage2D(int target, int level, int xoffset, int yoffset,
215            Bitmap bitmap, int format, int type) {
216        if (bitmap == null) {
217            throw new NullPointerException("texSubImage2D can't be used with a null Bitmap");
218        }
219        if (bitmap.isRecycled()) {
220            throw new IllegalArgumentException("bitmap is recycled");
221        }
222        if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, format, type)!=0) {
223            throw new IllegalArgumentException("invalid Bitmap format");
224        }
225    }
226
227    /**
228     * Return a string for the EGL error code, or the hex representation
229     * if the error is unknown.
230     *
231     * @param error The EGL error to convert into a String.
232     *
233     * @return An error string corresponding to the EGL error code.
234     */
235    public static String getEGLErrorString(int error) {
236        switch (error) {
237            case EGL10.EGL_SUCCESS:
238                return "EGL_SUCCESS";
239            case EGL10.EGL_NOT_INITIALIZED:
240                return "EGL_NOT_INITIALIZED";
241            case EGL10.EGL_BAD_ACCESS:
242                return "EGL_BAD_ACCESS";
243            case EGL10.EGL_BAD_ALLOC:
244                return "EGL_BAD_ALLOC";
245            case EGL10.EGL_BAD_ATTRIBUTE:
246                return "EGL_BAD_ATTRIBUTE";
247            case EGL10.EGL_BAD_CONFIG:
248                return "EGL_BAD_CONFIG";
249            case EGL10.EGL_BAD_CONTEXT:
250                return "EGL_BAD_CONTEXT";
251            case EGL10.EGL_BAD_CURRENT_SURFACE:
252                return "EGL_BAD_CURRENT_SURFACE";
253            case EGL10.EGL_BAD_DISPLAY:
254                return "EGL_BAD_DISPLAY";
255            case EGL10.EGL_BAD_MATCH:
256                return "EGL_BAD_MATCH";
257            case EGL10.EGL_BAD_NATIVE_PIXMAP:
258                return "EGL_BAD_NATIVE_PIXMAP";
259            case EGL10.EGL_BAD_NATIVE_WINDOW:
260                return "EGL_BAD_NATIVE_WINDOW";
261            case EGL10.EGL_BAD_PARAMETER:
262                return "EGL_BAD_PARAMETER";
263            case EGL10.EGL_BAD_SURFACE:
264                return "EGL_BAD_SURFACE";
265            case EGL11.EGL_CONTEXT_LOST:
266                return "EGL_CONTEXT_LOST";
267            default:
268                return "0x" + Integer.toHexString(error);
269        }
270    }
271
272    native private static void nativeClassInit();
273
274    native private static int native_getInternalFormat(Bitmap bitmap);
275    native private static int native_getType(Bitmap bitmap);
276    native private static int native_texImage2D(int target, int level, int internalformat,
277            Bitmap bitmap, int type, int border);
278    native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset,
279            Bitmap bitmap, int format, int type);
280}
281