diff options
Diffstat (limited to 'opengl/java/android')
-rw-r--r-- | opengl/java/android/opengl/EGLLogWrapper.java | 545 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLDebugHelper.java | 107 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLErrorWrapper.java | 961 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLException.java | 49 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLLogWrapper.java | 3065 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLSurfaceView.java | 661 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLU.java | 288 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLUtils.java | 220 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLWrapperBase.java | 495 | ||||
-rw-r--r-- | opengl/java/android/opengl/Group.java | 155 | ||||
-rw-r--r-- | opengl/java/android/opengl/Material.java | 120 | ||||
-rw-r--r-- | opengl/java/android/opengl/Matrix.java | 585 | ||||
-rw-r--r-- | opengl/java/android/opengl/Object3D.java | 245 | ||||
-rw-r--r-- | opengl/java/android/opengl/Texture.java | 135 | ||||
-rw-r--r-- | opengl/java/android/opengl/Visibility.java | 123 | ||||
-rw-r--r-- | opengl/java/android/opengl/package.html | 5 |
16 files changed, 7759 insertions, 0 deletions
diff --git a/opengl/java/android/opengl/EGLLogWrapper.java b/opengl/java/android/opengl/EGLLogWrapper.java new file mode 100644 index 00000000000..521fc8cac3b --- /dev/null +++ b/opengl/java/android/opengl/EGLLogWrapper.java @@ -0,0 +1,545 @@ +package android.opengl; + +import java.io.IOException; +import java.io.Writer; + +import javax.microedition.khronos.egl.EGL; +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; + +class EGLLogWrapper implements EGL11 { + private EGL10 mEgl10; + Writer mLog; + boolean mLogArgumentNames; + boolean mCheckError; + private int mArgCount; + + + public EGLLogWrapper(EGL egl, int configFlags, Writer log) { + mEgl10 = (EGL10) egl; + mLog = log; + mLogArgumentNames = + (GLDebugHelper.CONFIG_LOG_ARGUMENT_NAMES & configFlags) != 0; + mCheckError = + (GLDebugHelper.CONFIG_CHECK_GL_ERROR & configFlags) != 0; + } + + public boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, + EGLConfig[] configs, int config_size, int[] num_config) { + begin("eglChooseConfig"); + arg("display", display); + arg("attrib_list", attrib_list); + arg("config_size", config_size); + end(); + + boolean result = mEgl10.eglChooseConfig(display, attrib_list, configs, + config_size, num_config); + arg("configs", configs); + arg("num_config", num_config); + returns(result); + checkError(); + return result; + } + + public boolean eglCopyBuffers(EGLDisplay display, EGLSurface surface, + Object native_pixmap) { + begin("eglCopyBuffers"); + arg("display", display); + arg("surface", surface); + arg("native_pixmap", native_pixmap); + end(); + + boolean result = mEgl10.eglCopyBuffers(display, surface, native_pixmap); + returns(result); + checkError(); + return result; + } + + public EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, + EGLContext share_context, int[] attrib_list) { + begin("eglCreateContext"); + arg("display", display); + arg("config", config); + arg("share_context", share_context); + arg("attrib_list", attrib_list); + end(); + + EGLContext result = mEgl10.eglCreateContext(display, config, + share_context, attrib_list); + returns(result); + checkError(); + return result; + } + + public EGLSurface eglCreatePbufferSurface(EGLDisplay display, + EGLConfig config, int[] attrib_list) { + begin("eglCreatePbufferSurface"); + arg("display", display); + arg("config", config); + arg("attrib_list", attrib_list); + end(); + + EGLSurface result = mEgl10.eglCreatePbufferSurface(display, config, + attrib_list); + returns(result); + checkError(); + return result; + } + + public EGLSurface eglCreatePixmapSurface(EGLDisplay display, + EGLConfig config, Object native_pixmap, int[] attrib_list) { + begin("eglCreatePixmapSurface"); + arg("display", display); + arg("config", config); + arg("native_pixmap", native_pixmap); + arg("attrib_list", attrib_list); + end(); + + EGLSurface result = mEgl10.eglCreatePixmapSurface(display, config, + native_pixmap, attrib_list); + returns(result); + checkError(); + return result; + } + + public EGLSurface eglCreateWindowSurface(EGLDisplay display, + EGLConfig config, Object native_window, int[] attrib_list) { + begin("eglCreateWindowSurface"); + arg("display", display); + arg("config", config); + arg("native_window", native_window); + arg("attrib_list", attrib_list); + end(); + + EGLSurface result = mEgl10.eglCreateWindowSurface(display, config, + native_window, attrib_list); + returns(result); + checkError(); + return result; + } + + public boolean eglDestroyContext(EGLDisplay display, EGLContext context) { + begin("eglDestroyContext"); + arg("display", display); + arg("context", context); + end(); + + boolean result = mEgl10.eglDestroyContext(display, context); + returns(result); + checkError(); + return result; + } + + public boolean eglDestroySurface(EGLDisplay display, EGLSurface surface) { + begin("eglDestroySurface"); + arg("display", display); + arg("surface", surface); + end(); + + boolean result = mEgl10.eglDestroySurface(display, surface); + returns(result); + checkError(); + return result; + } + + public boolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, + int attribute, int[] value) { + begin("eglGetConfigAttrib"); + arg("display", display); + arg("config", config); + arg("attribute", attribute); + end(); + boolean result = mEgl10.eglGetConfigAttrib(display, config, attribute, + value); + arg("value", value); + returns(result); + checkError(); + return false; + } + + public boolean eglGetConfigs(EGLDisplay display, EGLConfig[] configs, + int config_size, int[] num_config) { + begin("eglGetConfigs"); + arg("display", display); + arg("config_size", config_size); + end(); + + boolean result = mEgl10.eglGetConfigs(display, configs, config_size, + num_config); + arg("configs", configs); + arg("num_config", num_config); + returns(result); + checkError(); + return result; + } + + public EGLContext eglGetCurrentContext() { + begin("eglGetCurrentContext"); + end(); + + EGLContext result = mEgl10.eglGetCurrentContext(); + returns(result); + + checkError(); + return result; + } + + public EGLDisplay eglGetCurrentDisplay() { + begin("eglGetCurrentDisplay"); + end(); + + EGLDisplay result = mEgl10.eglGetCurrentDisplay(); + returns(result); + + checkError(); + return result; + } + + public EGLSurface eglGetCurrentSurface(int readdraw) { + begin("eglGetCurrentSurface"); + arg("readdraw", readdraw); + end(); + + EGLSurface result = mEgl10.eglGetCurrentSurface(readdraw); + returns(result); + + checkError(); + return result; + } + + public EGLDisplay eglGetDisplay(Object native_display) { + begin("eglGetDisplay"); + arg("native_display", native_display); + end(); + + EGLDisplay result = mEgl10.eglGetDisplay(native_display); + returns(result); + + checkError(); + return result; + } + + public int eglGetError() { + begin("eglGetError"); + end(); + + int result = mEgl10.eglGetError(); + returns(getErrorString(result)); + + return result; + } + + public boolean eglInitialize(EGLDisplay display, int[] major_minor) { + begin("eglInitialize"); + arg("display", display); + end(); + boolean result = mEgl10.eglInitialize(display, major_minor); + returns(result); + arg("major_minor", major_minor); + checkError(); + return result; + } + + public boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, + EGLSurface read, EGLContext context) { + begin("eglMakeCurrent"); + arg("display", display); + arg("draw", draw); + arg("read", read); + arg("context", context); + end(); + boolean result = mEgl10.eglMakeCurrent(display, draw, read, context); + returns(result); + checkError(); + return result; + } + + public boolean eglQueryContext(EGLDisplay display, EGLContext context, + int attribute, int[] value) { + begin("eglQueryContext"); + arg("display", display); + arg("context", context); + arg("attribute", attribute); + end(); + boolean result = mEgl10.eglQueryContext(display, context, attribute, + value); + returns(value[0]); + returns(result); + checkError(); + return result; + } + + public String eglQueryString(EGLDisplay display, int name) { + begin("eglQueryString"); + arg("display", display); + arg("name", name); + end(); + String result = mEgl10.eglQueryString(display, name); + returns(result); + checkError(); + return result; + } + + public boolean eglQuerySurface(EGLDisplay display, EGLSurface surface, + int attribute, int[] value) { + begin("eglQuerySurface"); + arg("display", display); + arg("surface", surface); + arg("attribute", attribute); + end(); + boolean result = mEgl10.eglQuerySurface(display, surface, attribute, + value); + returns(value[0]); + returns(result); + checkError(); + return result; + } + + public boolean eglSwapBuffers(EGLDisplay display, EGLSurface surface) { + begin("eglInitialize"); + arg("display", display); + arg("surface", surface); + end(); + boolean result = mEgl10.eglSwapBuffers(display, surface); + returns(result); + checkError(); + return result; + } + + public boolean eglTerminate(EGLDisplay display) { + begin("eglTerminate"); + arg("display", display); + end(); + boolean result = mEgl10.eglTerminate(display); + returns(result); + checkError(); + return result; + } + + public boolean eglWaitGL() { + begin("eglWaitGL"); + end(); + boolean result = mEgl10.eglWaitGL(); + returns(result); + checkError(); + return result; + } + + public boolean eglWaitNative(int engine, Object bindTarget) { + begin("eglWaitNative"); + arg("engine", engine); + arg("bindTarget", bindTarget); + end(); + boolean result = mEgl10.eglWaitNative(engine, bindTarget); + returns(result); + checkError(); + return result; + } + + private void checkError() { + int eglError; + if ((eglError = mEgl10.eglGetError()) != EGL_SUCCESS) { + String errorMessage = "eglError: " + getErrorString(eglError); + logLine(errorMessage); + if (mCheckError) { + throw new GLException(eglError, errorMessage); + } + } + } + + private void logLine(String message) { + log(message + '\n'); + } + + private void log(String message) { + try { + mLog.write(message); + } catch (IOException e) { + // Ignore exception, keep on trying + } + } + + private void begin(String name) { + log(name + '('); + mArgCount = 0; + } + + private void arg(String name, String value) { + if (mArgCount++ > 0) { + log(", "); + } + if (mLogArgumentNames) { + log(name + "="); + } + log(value); + } + + private void end() { + log(");\n"); + flush(); + } + + private void flush() { + try { + mLog.flush(); + } catch (IOException e) { + mLog = null; + } + } + + private void arg(String name, int value) { + arg(name, Integer.toString(value)); + } + + private void arg(String name, Object object) { + arg(name, toString(object)); + } + + private void arg(String name, EGLDisplay object) { + if (object == EGL10.EGL_DEFAULT_DISPLAY) { + arg(name, "EGL10.EGL_DEFAULT_DISPLAY"); + } else if (object == EGL_NO_DISPLAY) { + arg(name, "EGL10.EGL_NO_DISPLAY"); + } else { + arg(name, toString(object)); + } + } + + private void arg(String name, EGLContext object) { + if (object == EGL10.EGL_NO_CONTEXT) { + arg(name, "EGL10.EGL_NO_CONTEXT"); + } else { + arg(name, toString(object)); + } + } + + private void arg(String name, EGLSurface object) { + if (object == EGL10.EGL_NO_SURFACE) { + arg(name, "EGL10.EGL_NO_SURFACE"); + } else { + arg(name, toString(object)); + } + } + + private void returns(String result) { + log(" returns " + result + ";\n"); + flush(); + } + + private void returns(int result) { + returns(Integer.toString(result)); + } + + private void returns(boolean result) { + returns(Boolean.toString(result)); + } + + private void returns(Object result) { + returns(toString(result)); + } + + private String toString(Object obj) { + if (obj == null) { + return "null"; + } else { + return obj.toString(); + } + } + + private void arg(String name, int[] arr) { + if (arr == null) { + arg(name, "null"); + } else { + arg(name, toString(arr.length, arr, 0)); + } + } + + private void arg(String name, Object[] arr) { + if (arr == null) { + arg(name, "null"); + } else { + arg(name, toString(arr.length, arr, 0)); + } + } + + private String toString(int n, int[] arr, int offset) { + StringBuilder buf = new StringBuilder(); + buf.append("{\n"); + int arrLen = arr.length; + for (int i = 0; i < n; i++) { + int index = offset + i; + buf.append(" [" + index + "] = "); + if (index < 0 || index >= arrLen) { + buf.append("out of bounds"); + } else { + buf.append(arr[index]); + } + buf.append('\n'); + } + buf.append("}"); + return buf.toString(); + } + + private String toString(int n, Object[] arr, int offset) { + StringBuilder buf = new StringBuilder(); + buf.append("{\n"); + int arrLen = arr.length; + for (int i = 0; i < n; i++) { + int index = offset + i; + buf.append(" [" + index + "] = "); + if (index < 0 || index >= arrLen) { + buf.append("out of bounds"); + } else { + buf.append(arr[index]); + } + buf.append('\n'); + } + buf.append("}"); + return buf.toString(); + } + + private static String getHex(int value) { + return "0x" + Integer.toHexString(value); + } + + public static String getErrorString(int error) { + switch (error) { + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL11.EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + default: + return getHex(error); + } + } +} diff --git a/opengl/java/android/opengl/GLDebugHelper.java b/opengl/java/android/opengl/GLDebugHelper.java new file mode 100644 index 00000000000..18a1e730bc0 --- /dev/null +++ b/opengl/java/android/opengl/GLDebugHelper.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.io.Writer; + +import javax.microedition.khronos.egl.EGL; +import javax.microedition.khronos.opengles.GL; + +/** + * A helper class for debugging OpenGL ES applications. + * + * Wraps the supplied GL interface with a new GL interface that adds support for + * error checking and logging. + * + */ +public class GLDebugHelper { + + /** + * Wrap an existing GL interface in a new GL interface that adds support for + * error checking and/or logging. + * <p> + * Wrapping means that the GL instance that is passed in to this method is + * wrapped inside a new GL instance that optionally performs additional + * operations before and after calling the wrapped GL instance. + * <p> + * Error checking means that the wrapper will automatically call + * glError after each GL operation, + * and throw a GLException if an error occurs. (By design, calling glError + * itself will not cause an exception to be thrown.) Enabling error checking + * is an alternative to manually calling glError after every GL operation. + * <p> + * Logging means writing a text representation of each GL method call to + * a log. + * <p> + * @param gl the existing GL interface. Must implement GL and GL10. May + * optionally implement GL11 as well. + * @param configFlags A bitmask of error checking flags. + * @param log - null to disable logging, non-null to enable logging. + * @return the wrapped GL instance. + */ + + /** + * Check glError() after every call. + */ + public static final int CONFIG_CHECK_GL_ERROR = (1 << 0); + + /** + * Check if all calls are on the same thread. + */ + public static final int CONFIG_CHECK_THREAD = (1 << 1); + + /** + * Print argument names when logging GL Calls. + */ + public static final int CONFIG_LOG_ARGUMENT_NAMES = (1 << 2); + + /** + * The Error number used in the GLException that is thrown if + * CONFIG_CHECK_THREAD is enabled and you call OpenGL ES on the + * a different thread. + */ + public static final int ERROR_WRONG_THREAD = 0x7000; + + public static GL wrap(GL gl, int configFlags, Writer log) { + if ( configFlags != 0 ) { + gl = new GLErrorWrapper(gl, configFlags); + } + if ( log != null ) { + boolean logArgumentNames = + (CONFIG_LOG_ARGUMENT_NAMES & configFlags) != 0; + gl = new GLLogWrapper(gl, log, logArgumentNames); + } + return gl; + } + + /** + * Wrap an existing EGL interface in a new EGL interface that adds + * support for error checking and/or logging. + * @param egl the existing GL interface. Must implement EGL and EGL10. May + * optionally implement EGL11 as well. + * @param configFlags A bitmask of error checking flags. + * @param log - null to disable logging, non-null to enable logging. + * @return the wrapped EGL interface. + */ + public static EGL wrap(EGL egl, int configFlags, Writer log) { + if (log != null) { + egl = new EGLLogWrapper(egl, configFlags, log); + } + return egl; + } +} + diff --git a/opengl/java/android/opengl/GLErrorWrapper.java b/opengl/java/android/opengl/GLErrorWrapper.java new file mode 100644 index 00000000000..884a1a09539 --- /dev/null +++ b/opengl/java/android/opengl/GLErrorWrapper.java @@ -0,0 +1,961 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; + +import javax.microedition.khronos.opengles.GL; + +/** + * Implement an error checking wrapper. The wrapper will automatically call + * glError after each GL operation, and throw a GLException if an error + * occurs. (By design, calling glError itself will not cause an exception + * to be thrown.) Enabling error checking is an alternative to manually + * calling glError after every GL operation. + */ +class GLErrorWrapper extends GLWrapperBase { + boolean mCheckError; + boolean mCheckThread; + Thread mOurThread; + + public GLErrorWrapper(GL gl, int configFlags) { + super(gl); + mCheckError = (configFlags & GLDebugHelper.CONFIG_CHECK_GL_ERROR) != 0; + mCheckThread = (configFlags & GLDebugHelper.CONFIG_CHECK_THREAD) != 0; + } + + private void checkThread() { + if (mCheckThread) { + Thread currentThread = Thread.currentThread(); + if (mOurThread == null) { + mOurThread = currentThread; + } else { + if (!mOurThread.equals(currentThread)) { + throw new GLException(GLDebugHelper.ERROR_WRONG_THREAD, + "OpenGL method called from wrong thread."); + } + } + } + } + + private void checkError() { + if (mCheckError) { + int glError; + if ((glError = mgl.glGetError()) != 0) { + throw new GLException(glError); + } + } + } + + // --------------------------------------------------------------------- + // GL10 methods: + + public void glActiveTexture(int texture) { + checkThread(); + mgl.glActiveTexture(texture); + checkError(); + } + + public void glAlphaFunc(int func, float ref) { + checkThread(); + mgl.glAlphaFunc(func, ref); + checkError(); + } + + public void glAlphaFuncx(int func, int ref) { + checkThread(); + mgl.glAlphaFuncx(func, ref); + checkError(); + } + + public void glBindTexture(int target, int texture) { + checkThread(); + mgl.glBindTexture(target, texture); + checkError(); + } + + public void glBlendFunc(int sfactor, int dfactor) { + checkThread(); + mgl.glBlendFunc(sfactor, dfactor); + checkError(); + } + + public void glClear(int mask) { + checkThread(); + mgl.glClear(mask); + checkError(); + } + + public void glClearColor(float red, float green, float blue, float alpha) { + checkThread(); + mgl.glClearColor(red, green, blue, alpha); + checkError(); + } + + public void glClearColorx(int red, int green, int blue, int alpha) { + checkThread(); + mgl.glClearColorx(red, green, blue, alpha); + checkError(); + } + + public void glClearDepthf(float depth) { + checkThread(); + mgl.glClearDepthf(depth); + checkError(); + } + + public void glClearDepthx(int depth) { + checkThread(); + mgl.glClearDepthx(depth); + checkError(); + } + + public void glClearStencil(int s) { + checkThread(); + mgl.glClearStencil(s); + checkError(); + } + + public void glClientActiveTexture(int texture) { + checkThread(); + mgl.glClientActiveTexture(texture); + checkError(); + } + + public void glColor4f(float red, float green, float blue, float alpha) { + checkThread(); + mgl.glColor4f(red, green, blue, alpha); + checkError(); + } + + public void glColor4x(int red, int green, int blue, int alpha) { + checkThread(); + mgl.glColor4x(red, green, blue, alpha); + checkError(); + } + + public void glColorMask(boolean red, boolean green, boolean blue, + boolean alpha) { + checkThread(); + mgl.glColorMask(red, green, blue, alpha); + checkError(); + } + + public void glColorPointer(int size, int type, int stride, Buffer pointer) { + checkThread(); + mgl.glColorPointer(size, type, stride, pointer); + checkError(); + } + + public void glCompressedTexImage2D(int target, int level, + int internalformat, int width, int height, int border, + int imageSize, Buffer data) { + checkThread(); + mgl.glCompressedTexImage2D(target, level, internalformat, width, + height, border, imageSize, data); + checkError(); + } + + public void glCompressedTexSubImage2D(int target, int level, int xoffset, + int yoffset, int width, int height, int format, int imageSize, + Buffer data) { + checkThread(); + mgl.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, + height, format, imageSize, data); + checkError(); + } + + public void glCopyTexImage2D(int target, int level, int internalformat, + int x, int y, int width, int height, int border) { + checkThread(); + mgl.glCopyTexImage2D(target, level, internalformat, x, y, width, + height, border); + checkError(); + } + + public void glCopyTexSubImage2D(int target, int level, int xoffset, + int yoffset, int x, int y, int width, int height) { + checkThread(); + mgl.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, + height); + checkError(); + } + + public void glCullFace(int mode) { + checkThread(); + mgl.glCullFace(mode); + checkError(); + } + + public void glDeleteTextures(int n, int[] textures, int offset) { + checkThread(); + mgl.glDeleteTextures(n, textures, offset); + checkError(); + } + + public void glDeleteTextures(int n, IntBuffer textures) { + checkThread(); + mgl.glDeleteTextures(n, textures); + checkError(); + } + + public void glDepthFunc(int func) { + checkThread(); + mgl.glDepthFunc(func); + checkError(); + } + + public void glDepthMask(boolean flag) { + checkThread(); + mgl.glDepthMask(flag); + checkError(); + } + + public void glDepthRangef(float near, float far) { + checkThread(); + mgl.glDepthRangef(near, far); + checkError(); + } + + public void glDepthRangex(int near, int far) { + checkThread(); + mgl.glDepthRangex(near, far); + checkError(); + } + + public void glDisable(int cap) { + checkThread(); + mgl.glDisable(cap); + checkError(); + } + + public void glDisableClientState(int array) { + checkThread(); + mgl.glDisableClientState(array); + checkError(); + } + + public void glDrawArrays(int mode, int first, int count) { + checkThread(); + mgl.glDrawArrays(mode, first, count); + checkError(); + } + + public void glDrawElements(int mode, int count, int type, Buffer indices) { + checkThread(); + mgl.glDrawElements(mode, count, type, indices); + checkError(); + } + + public void glEnable(int cap) { + checkThread(); + mgl.glEnable(cap); + checkError(); + } + + public void glEnableClientState(int array) { + checkThread(); + mgl.glEnableClientState(array); + checkError(); + } + + public void glFinish() { + checkThread(); + mgl.glFinish(); + checkError(); + } + + public void glFlush() { + checkThread(); + mgl.glFlush(); + checkError(); + } + + public void glFogf(int pname, float param) { + checkThread(); + mgl.glFogf(pname, param); + checkError(); + } + + public void glFogfv(int pname, float[] params, int offset) { + checkThread(); + mgl.glFogfv(pname, params, offset); + checkError(); + } + + public void glFogfv(int pname, FloatBuffer params) { + checkThread(); + mgl.glFogfv(pname, params); + checkError(); + } + + public void glFogx(int pname, int param) { + checkThread(); + mgl.glFogx(pname, param); + checkError(); + } + + public void glFogxv(int pname, int[] params, int offset) { + checkThread(); + mgl.glFogxv(pname, params, offset); + checkError(); + } + + public void glFogxv(int pname, IntBuffer params) { + checkThread(); + mgl.glFogxv(pname, params); + checkError(); + } + + public void glFrontFace(int mode) { + checkThread(); + mgl.glFrontFace(mode); + checkError(); + } + + public void glFrustumf(float left, float right, float bottom, float top, + float near, float far) { + checkThread(); + mgl.glFrustumf(left, right, bottom, top, near, far); + checkError(); + } + + public void glFrustumx(int left, int right, int bottom, int top, int near, + int far) { + checkThread(); + mgl.glFrustumx(left, right, bottom, top, near, far); + checkError(); + } + + public void glGenTextures(int n, int[] textures, int offset) { + checkThread(); + mgl.glGenTextures(n, textures, offset); + checkError(); + } + + public void glGenTextures(int n, IntBuffer textures) { + checkThread(); + mgl.glGenTextures(n, textures); + checkError(); + } + + public int glGetError() { + checkThread(); + int result = mgl.glGetError(); + return result; + } + + public void glGetIntegerv(int pname, int[] params, int offset) { + checkThread(); + mgl.glGetIntegerv(pname, params, offset); + checkError(); + } + + public void glGetIntegerv(int pname, IntBuffer params) { + checkThread(); + mgl.glGetIntegerv(pname, params); + checkError(); + } + + public String glGetString(int name) { + checkThread(); + String result = mgl.glGetString(name); + checkError(); + return result; + } + + public void glHint(int target, int mode) { + checkThread(); + mgl.glHint(target, mode); + checkError(); + } + + public void glLightModelf(int pname, float param) { + checkThread(); + mgl.glLightModelf(pname, param); + checkError(); + } + + public void glLightModelfv(int pname, float[] params, int offset) { + checkThread(); + mgl.glLightModelfv(pname, params, offset); + checkError(); + } + + public void glLightModelfv(int pname, FloatBuffer params) { + checkThread(); + mgl.glLightModelfv(pname, params); + checkError(); + } + + public void glLightModelx(int pname, int param) { + checkThread(); + mgl.glLightModelx(pname, param); + checkError(); + } + + public void glLightModelxv(int pname, int[] params, int offset) { + checkThread(); + mgl.glLightModelxv(pname, params, offset); + checkError(); + } + + public void glLightModelxv(int pname, IntBuffer params) { + checkThread(); + mgl.glLightModelxv(pname, params); + checkError(); + } + + public void glLightf(int light, int pname, float param) { + checkThread(); + mgl.glLightf(light, pname, param); + checkError(); + } + + public void glLightfv(int light, int pname, float[] params, int offset) { + checkThread(); + mgl.glLightfv(light, pname, params, offset); + checkError(); + } + + public void glLightfv(int light, int pname, FloatBuffer params) { + checkThread(); + mgl.glLightfv(light, pname, params); + checkError(); + } + + public void glLightx(int light, int pname, int param) { + checkThread(); + mgl.glLightx(light, pname, param); + checkError(); + } + + public void glLightxv(int light, int pname, int[] params, int offset) { + checkThread(); + mgl.glLightxv(light, pname, params, offset); + checkError(); + } + + public void glLightxv(int light, int pname, IntBuffer params) { + checkThread(); + mgl.glLightxv(light, pname, params); + checkError(); + } + + public void glLineWidth(float width) { + checkThread(); + mgl.glLineWidth(width); + checkError(); + } + + public void glLineWidthx(int width) { + checkThread(); + mgl.glLineWidthx(width); + checkError(); + } + + public void glLoadIdentity() { + checkThread(); + mgl.glLoadIdentity(); + checkError(); + } + + public void glLoadMatrixf(float[] m, int offset) { + checkThread(); + mgl.glLoadMatrixf(m, offset); + checkError(); + } + + public void glLoadMatrixf(FloatBuffer m) { + checkThread(); + mgl.glLoadMatrixf(m); + checkError(); + } + + public void glLoadMatrixx(int[] m, int offset) { + checkThread(); + mgl.glLoadMatrixx(m, offset); + checkError(); + } + + public void glLoadMatrixx(IntBuffer m) { + checkThread(); + mgl.glLoadMatrixx(m); + checkError(); + } + + public void glLogicOp(int opcode) { + checkThread(); + mgl.glLogicOp(opcode); + checkError(); + } + + public void glMaterialf(int face, int pname, float param) { + checkThread(); + mgl.glMaterialf(face, pname, param); + checkError(); + } + + public void glMaterialfv(int face, int pname, float[] params, int offset) { + checkThread(); + mgl.glMaterialfv(face, pname, params, offset); + checkError(); + } + + public void glMaterialfv(int face, int pname, FloatBuffer params) { + checkThread(); + mgl.glMaterialfv(face, pname, params); + checkError(); + } + + public void glMaterialx(int face, int pname, int param) { + checkThread(); + mgl.glMaterialx(face, pname, param); + checkError(); + } + + public void glMaterialxv(int face, int pname, int[] params, int offset) { + checkThread(); + mgl.glMaterialxv(face, pname, params, offset); + checkError(); + } + + public void glMaterialxv(int face, int pname, IntBuffer params) { + checkThread(); + mgl.glMaterialxv(face, pname, params); + checkError(); + } + + public void glMatrixMode(int mode) { + checkThread(); + mgl.glMatrixMode(mode); + checkError(); + } + + public void glMultMatrixf(float[] m, int offset) { + checkThread(); + mgl.glMultMatrixf(m, offset); + checkError(); + } + + public void glMultMatrixf(FloatBuffer m) { + checkThread(); + mgl.glMultMatrixf(m); + checkError(); + } + + public void glMultMatrixx(int[] m, int offset) { + checkThread(); + mgl.glMultMatrixx(m, offset); + checkError(); + } + + public void glMultMatrixx(IntBuffer m) { + checkThread(); + mgl.glMultMatrixx(m); + checkError(); + } + + public void glMultiTexCoord4f(int target, + float s, float t, float r, float q) { + checkThread(); + mgl.glMultiTexCoord4f(target, s, t, r, q); + checkError(); + } + + public void glMultiTexCoord4x(int target, int s, int t, int r, int q) { + checkThread(); + mgl.glMultiTexCoord4x(target, s, t, r, q); + checkError(); + } + + public void glNormal3f(float nx, float ny, float nz) { + checkThread(); + mgl.glNormal3f(nx, ny, nz); + checkError(); + } + + public void glNormal3x(int nx, int ny, int nz) { + checkThread(); + mgl.glNormal3x(nx, ny, nz); + checkError(); + } + + public void glNormalPointer(int type, int stride, Buffer pointer) { + checkThread(); + mgl.glNormalPointer(type, stride, pointer); + checkError(); + } + + public void glOrthof(float left, float right, float bottom, float top, + float near, float far) { + checkThread(); + mgl.glOrthof(left, right, bottom, top, near, far); + checkError(); + } + + public void glOrthox(int left, int right, int bottom, int top, int near, + int far) { + checkThread(); + mgl.glOrthox(left, right, bottom, top, near, far); + checkError(); + } + + public void glPixelStorei(int pname, int param) { + checkThread(); + mgl.glPixelStorei(pname, param); + checkError(); + } + + public void glPointSize(float size) { + checkThread(); + mgl.glPointSize(size); + checkError(); + } + + public void glPointSizex(int size) { + checkThread(); + mgl.glPointSizex(size); + checkError(); + } + + public void glPolygonOffset(float factor, float units) { + checkThread(); + mgl.glPolygonOffset(factor, units); + checkError(); + } + + public void glPolygonOffsetx(int factor, int units) { + checkThread(); + mgl.glPolygonOffsetx(factor, units); + checkError(); + } + + public void glPopMatrix() { + checkThread(); + mgl.glPopMatrix(); + checkError(); + } + + public void glPushMatrix() { + checkThread(); + mgl.glPushMatrix(); + checkError(); + } + + public void glReadPixels(int x, int y, int width, int height, int format, + int type, Buffer pixels) { + checkThread(); + mgl.glReadPixels(x, y, width, height, format, type, pixels); + checkError(); + } + + public void glRotatef(float angle, float x, float y, float z) { + checkThread(); + mgl.glRotatef(angle, x, y, z); + checkError(); + } + + public void glRotatex(int angle, int x, int y, int z) { + checkThread(); + mgl.glRotatex(angle, x, y, z); + checkError(); + } + + public void glSampleCoverage(float value, boolean invert) { + checkThread(); + mgl.glSampleCoverage(value, invert); + checkError(); + } + + public void glSampleCoveragex(int value, boolean invert) { + checkThread(); + mgl.glSampleCoveragex(value, invert); + checkError(); + } + + public void glScalef(float x, float y, float z) { + checkThread(); + mgl.glScalef(x, y, z); + checkError(); + } + + public void glScalex(int x, int y, int z) { + checkThread(); + mgl.glScalex(x, y, z); + checkError(); + } + + public void glScissor(int x, int y, int width, int height) { + checkThread(); + mgl.glScissor(x, y, width, height); + checkError(); + } + + public void glShadeModel(int mode) { + checkThread(); + mgl.glShadeModel(mode); + checkError(); + } + + public void glStencilFunc(int func, int ref, int mask) { + checkThread(); + mgl.glStencilFunc(func, ref, mask); + checkError(); + } + + public void glStencilMask(int mask) { + checkThread(); + mgl.glStencilMask(mask); + checkError(); + } + + public void glStencilOp(int fail, int zfail, int zpass) { + checkThread(); + mgl.glStencilOp(fail, zfail, zpass); + checkError(); + } + + public void glTexCoordPointer(int size, int type, + int stride, Buffer pointer) { + checkThread(); + mgl.glTexCoordPointer(size, type, stride, pointer); + checkError(); + } + + public void glTexEnvf(int target, int pname, float param) { + checkThread(); + mgl.glTexEnvf(target, pname, param); + checkError(); + } + + public void glTexEnvfv(int target, int pname, float[] params, int offset) { + checkThread(); + mgl.glTexEnvfv(target, pname, params, offset); + checkError(); + } + + public void glTexEnvfv(int target, int pname, FloatBuffer params) { + checkThread(); + mgl.glTexEnvfv(target, pname, params); + checkError(); + } + + public void glTexEnvx(int target, int pname, int param) { + checkThread(); + mgl.glTexEnvx(target, pname, param); + checkError(); + } + + public void glTexEnvxv(int target, int pname, int[] params, int offset) { + checkThread(); + mgl.glTexEnvxv(target, pname, params, offset); + checkError(); + } + + public void glTexEnvxv(int target, int pname, IntBuffer params) { + checkThread(); + mgl.glTexEnvxv(target, pname, params); + checkError(); + } + + public void glTexImage2D(int target, int level, int internalformat, + int width, int height, int border, int format, int type, + Buffer pixels) { + checkThread(); + mgl.glTexImage2D(target, level, internalformat, width, height, border, + format, type, pixels); + checkError(); + } + + public void glTexParameterf(int target, int pname, float param) { + checkThread(); + mgl.glTexParameterf(target, pname, param); + checkError(); + } + + public void glTexParameterx(int target, int pname, int param) { + checkThread(); + mgl.glTexParameterx(target, pname, param); + checkError(); + } + + public void glTexParameteriv(int target, int pname, int[] params, int offset) { + checkThread(); + mgl11.glTexParameteriv(target, pname, params, offset); + checkError(); + } + + public void glTexParameteriv(int target, int pname, IntBuffer params) { + checkThread(); + mgl11.glTexParameteriv(target, pname, params); + checkError(); + } + + public void glTexSubImage2D(int target, int level, int xoffset, + int yoffset, int width, int height, int format, int type, + Buffer pixels) { + checkThread(); + mgl.glTexSubImage2D(target, level, xoffset, yoffset, width, height, + format, type, pixels); + checkError(); + } + + public void glTranslatef(float x, float y, float z) { + checkThread(); + mgl.glTranslatef(x, y, z); + checkError(); + } + + public void glTranslatex(int x, int y, int z) { + checkThread(); + mgl.glTranslatex(x, y, z); + checkError(); + } + + public void glVertexPointer(int size, int type, + int stride, Buffer pointer) { + checkThread(); + mgl.glVertexPointer(size, type, stride, pointer); + checkError(); + } + + public void glViewport(int x, int y, int width, int height) { + checkThread(); + mgl.glViewport(x, y, width, height); + checkError(); + } + + public void glClipPlanef(int plane, float[] equation, int offset) { + checkThread(); + mgl11.glClipPlanef(plane, equation, offset); + checkError(); + } + + public void glClipPlanef(int plane, FloatBuffer equation) { + checkThread(); + mgl11.glClipPlanef(plane, equation); + checkError(); + } + + public void glClipPlanex(int plane, int[] equation, int offset) { + checkThread(); + mgl11.glClipPlanex(plane, equation, offset); + checkError(); + } + + public void glClipPlanex(int plane, IntBuffer equation) { + checkThread(); + mgl11.glClipPlanex(plane, equation); + checkError(); + } + + // Draw Texture Extension + + public void glDrawTexfOES(float x, float y, float z, + float width, float height) { + checkThread(); + mgl11Ext.glDrawTexfOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexfvOES(float[] coords, int offset) { + checkThread(); + mgl11Ext.glDrawTexfvOES(coords, offset); + checkError(); + } + + public void glDrawTexfvOES(FloatBuffer coords) { + checkThread(); + mgl11Ext.glDrawTexfvOES(coords); + checkError(); + } + + public void glDrawTexiOES(int x, int y, int z, int width, int height) { + checkThread(); + mgl11Ext.glDrawTexiOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexivOES(int[] coords, int offset) { + checkThread(); + mgl11Ext.glDrawTexivOES(coords, offset); + checkError(); + } + + public void glDrawTexivOES(IntBuffer coords) { + checkThread(); + mgl11Ext.glDrawTexivOES(coords); + checkError(); + } + + public void glDrawTexsOES(short x, short y, short z, + short width, short height) { + checkThread(); + mgl11Ext.glDrawTexsOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexsvOES(short[] coords, int offset) { + checkThread(); + mgl11Ext.glDrawTexsvOES(coords, offset); + checkError(); + } + + public void glDrawTexsvOES(ShortBuffer coords) { + checkThread(); + mgl11Ext.glDrawTexsvOES(coords); + checkError(); + } + + public void glDrawTexxOES(int x, int y, int z, int width, int height) { + checkThread(); + mgl11Ext.glDrawTexxOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexxvOES(int[] coords, int offset) { + checkThread(); + mgl11Ext.glDrawTexxvOES(coords, offset); + checkError(); + } + + public void glDrawTexxvOES(IntBuffer coords) { + checkThread(); + mgl11Ext.glDrawTexxvOES(coords); + checkError(); + } + + public int glQueryMatrixxOES(int[] mantissa, int mantissaOffset, + int[] exponent, int exponentOffset) { + checkThread(); + int valid = mgl10Ext.glQueryMatrixxOES(mantissa, mantissaOffset, + exponent, exponentOffset); + checkError(); + return valid; + } + + public int glQueryMatrixxOES(IntBuffer mantissa, IntBuffer exponent) { + checkThread(); + int valid = mgl10Ext.glQueryMatrixxOES(mantissa, exponent); + checkError(); + return valid; + } +} diff --git a/opengl/java/android/opengl/GLException.java b/opengl/java/android/opengl/GLException.java new file mode 100644 index 00000000000..762fccf557d --- /dev/null +++ b/opengl/java/android/opengl/GLException.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +/** + * An exception class for OpenGL errors. + * + */ +@SuppressWarnings("serial") +public class GLException extends RuntimeException { + public GLException(final int error) { + super(getErrorString(error)); + mError = error; + } + + public GLException(final int error, final String string) { + super(string); + mError = error; + } + + private static String getErrorString(int error) { + String errorString = GLU.gluErrorString(error); + if ( errorString == null ) { + errorString = "Unknown error 0x" + Integer.toHexString(error); + } + return errorString; + } + + int getError() { + return mError; + } + + private final int mError; +} + diff --git a/opengl/java/android/opengl/GLLogWrapper.java b/opengl/java/android/opengl/GLLogWrapper.java new file mode 100644 index 00000000000..4119bf82182 --- /dev/null +++ b/opengl/java/android/opengl/GLLogWrapper.java @@ -0,0 +1,3065 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.io.IOException; +import java.io.Writer; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.CharBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; +import java.util.Arrays; + +import javax.microedition.khronos.opengles.GL; + +/** + * A wrapper that logs all GL calls (and results) in human-readable form. + * + */ +class GLLogWrapper extends GLWrapperBase { + private static final int FORMAT_INT = 0; + private static final int FORMAT_FLOAT = 1; + private static final int FORMAT_FIXED = 2; + + public GLLogWrapper(GL gl, Writer log, boolean logArgumentNames) { + super(gl); + mLog = log; + mLogArgumentNames = logArgumentNames; + } + + private void checkError() { + int glError; + if ((glError = mgl.glGetError()) != 0) { + String errorMessage = "glError: " + Integer.toString(glError); + logLine(errorMessage); + } + } + + private void logLine(String message) { + log(message + '\n'); + } + + private void log(String message) { + try { + mLog.write(message); + } catch (IOException e) { + // Ignore exception, keep on trying + } + } + + private void begin(String name) { + log(name + '('); + mArgCount = 0; + } + + private void arg(String name, String value) { + if (mArgCount++ > 0) { + log(", "); + } + if (mLogArgumentNames) { + log(name + "="); + } + log(value); + } + + private void end() { + log(");\n"); + flush(); + } + + private void flush() { + try { + mLog.flush(); + } catch (IOException e) { + mLog = null; + } + } + + private void arg(String name, boolean value) { + arg(name, Boolean.toString(value)); + } + + private void arg(String name, int value) { + arg(name, Integer.toString(value)); + } + + private void arg(String name, float value) { + arg(name, Float.toString(value)); + } + + private void returns(String result) { + log(") returns " + result + ";\n"); + flush(); + } + + private void returns(int result) { + returns(Integer.toString(result)); + } + + private void arg(String name, int n, int[] arr, int offset) { + arg(name, toString(n, FORMAT_INT, arr, offset)); + } + + private void arg(String name, int n, short[] arr, int offset) { + arg(name, toString(n, arr, offset)); + } + + private void arg(String name, int n, float[] arr, int offset) { + arg(name, toString(n, arr, offset)); + } + + private void formattedAppend(StringBuilder buf, int value, int format) { + switch (format) { + case FORMAT_INT: + buf.append(value); + break; + case FORMAT_FLOAT: + buf.append(Float.intBitsToFloat(value)); + break; + case FORMAT_FIXED: + buf.append(value / 65536.0f); + break; + } + } + + private String toString(int n, int format, int[] arr, int offset) { + StringBuilder buf = new StringBuilder(); + buf.append("{\n"); + int arrLen = arr.length; + for (int i = 0; i < n; i++) { + int index = offset + i; + buf.append(" [" + index + "] = "); + if (index < 0 || index >= arrLen) { + buf.append("out of bounds"); + } else { + formattedAppend(buf, arr[index], format); + } + buf.append('\n'); + } + buf.append("}"); + return buf.toString(); + } + + private String toString(int n, short[] arr, int offset) { + StringBuilder buf = new StringBuilder(); + buf.append("{\n"); + int arrLen = arr.length; + for (int i = 0; i < n; i++) { + int index = offset + i; + buf.append(" [" + index + "] = "); + if (index < 0 || index >= arrLen) { + buf.append("out of bounds"); + } else { + buf.append(arr[index]); + } + buf.append('\n'); + } + buf.append("}"); + return buf.toString(); + } + + private String toString(int n, float[] arr, int offset) { + StringBuilder buf = new StringBuilder(); + buf.append("{\n"); + int arrLen = arr.length; + for (int i = 0; i < n; i++) { + int index = offset + i; + buf.append("[" + index + "] = "); + if (index < 0 || index >= arrLen) { + buf.append("out of bounds"); + } else { + buf.append(arr[index]); + } + buf.append('\n'); + } + buf.append("}"); + return buf.toString(); + } + + private String toString(int n, FloatBuffer buf) { + StringBuilder builder = new StringBuilder(); + builder.append("{\n"); + for (int i = 0; i < n; i++) { + builder.append(" [" + i + "] = " + buf.get(i) + '\n'); + } + builder.append("}"); + return builder.toString(); + } + + private String toString(int n, int format, IntBuffer buf) { + StringBuilder builder = new StringBuilder(); + builder.append("{\n"); + for (int i = 0; i < n; i++) { + builder.append(" [" + i + "] = "); + formattedAppend(builder, buf.get(i), format); + builder.append('\n'); + } + builder.append("}"); + return builder.toString(); + } + + private String toString(int n, ShortBuffer buf) { + StringBuilder builder = new StringBuilder(); + builder.append("{\n"); + for (int i = 0; i < n; i++) { + builder.append(" [" + i + "] = " + buf.get(i) + '\n'); + } + builder.append("}"); + return builder.toString(); + } + + private void arg(String name, int n, FloatBuffer buf) { + arg(name, toString(n, buf)); + } + + private void arg(String name, int n, IntBuffer buf) { + arg(name, toString(n, FORMAT_INT, buf)); + } + + private void arg(String name, int n, ShortBuffer buf) { + arg(name, toString(n, buf)); + } + + private void argPointer(int size, int type, int stride, Buffer pointer) { + arg("size", size); + arg("type", getPointerTypeName(type)); + arg("stride", stride); + arg("pointer", pointer.toString()); + } + + private static String getHex(int value) { + return "0x" + Integer.toHexString(value); + } + + public static String getErrorString(int error) { + switch (error) { + case GL_NO_ERROR: + return "GL_NO_ERROR"; + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + default: + return getHex(error); + } + } + + private String getClearBufferMask(int mask) { + StringBuilder b = new StringBuilder(); + if ((mask & GL_DEPTH_BUFFER_BIT) != 0) { + b.append("GL_DEPTH_BUFFER_BIT"); + mask &= ~GL_DEPTH_BUFFER_BIT; + } + if ((mask & GL_STENCIL_BUFFER_BIT) != 0) { + if (b.length() > 0) { + b.append(" | "); + } + b.append("GL_STENCIL_BUFFER_BIT"); + mask &= ~GL_STENCIL_BUFFER_BIT; + } + if ((mask & GL_COLOR_BUFFER_BIT) != 0) { + if (b.length() > 0) { + b.append(" | "); + } + b.append("GL_COLOR_BUFFER_BIT"); + mask &= ~GL_COLOR_BUFFER_BIT; + } + if (mask != 0) { + if (b.length() > 0) { + b.append(" | "); + } + b.append(getHex(mask)); + } + return b.toString(); + } + + private String getFactor(int factor) { + switch(factor) { + case GL_ZERO: + return "GL_ZERO"; + case GL_ONE: + return "GL_ONE"; + case GL_SRC_COLOR: + return "GL_SRC_COLOR"; + case GL_ONE_MINUS_SRC_COLOR: + return "GL_ONE_MINUS_SRC_COLOR"; + case GL_DST_COLOR: + return "GL_DST_COLOR"; + case GL_ONE_MINUS_DST_COLOR: + return "GL_ONE_MINUS_DST_COLOR"; + case GL_SRC_ALPHA: + return "GL_SRC_ALPHA"; + case GL_ONE_MINUS_SRC_ALPHA: + return "GL_ONE_MINUS_SRC_ALPHA"; + case GL_DST_ALPHA: + return "GL_DST_ALPHA"; + case GL_ONE_MINUS_DST_ALPHA: + return "GL_ONE_MINUS_DST_ALPHA"; + case GL_SRC_ALPHA_SATURATE: + return "GL_SRC_ALPHA_SATURATE"; + + default: + return getHex(factor); + } + } + + private String getShadeModel(int model) { + switch(model) { + case GL_FLAT: + return "GL_FLAT"; + case GL_SMOOTH: + return "GL_SMOOTH"; + default: + return getHex(model); + } + } + + private String getTextureTarget(int target) { + switch (target) { + case GL_TEXTURE_2D: + return "GL_TEXTURE_2D"; + default: + return getHex(target); + } + } + + private String getTextureEnvTarget(int target) { + switch (target) { + case GL_TEXTURE_ENV: + return "GL_TEXTURE_ENV"; + default: + return getHex(target); + } + } + + private String getTextureEnvPName(int pname) { + switch (pname) { + case GL_TEXTURE_ENV_MODE: + return "GL_TEXTURE_ENV_MODE"; + case GL_TEXTURE_ENV_COLOR: + return "GL_TEXTURE_ENV_COLOR"; + default: + return getHex(pname); + } + } + + private int getTextureEnvParamCount(int pname) { + switch (pname) { + case GL_TEXTURE_ENV_MODE: + return 1; + case GL_TEXTURE_ENV_COLOR: + return 4; + default: + return 0; + } + } + + private String getTextureEnvParamName(float param) { + int iparam = (int) param; + if (param == (float) iparam) { + switch (iparam) { + case GL_REPLACE: + return "GL_REPLACE"; + case GL_MODULATE: + return "GL_MODULATE"; + case GL_DECAL: + return "GL_DECAL"; + case GL_BLEND: + return "GL_BLEND"; + case GL_ADD: + return "GL_ADD"; + case GL_COMBINE: + return "GL_COMBINE"; + default: + return getHex(iparam); + } + } + return Float.toString(param); + } + + private String getMatrixMode(int matrixMode) { + switch (matrixMode) { + case GL_MODELVIEW: + return "GL_MODELVIEW"; + case GL_PROJECTION: + return "GL_PROJECTION"; + case GL_TEXTURE: + return "GL_TEXTURE"; + default: + return getHex(matrixMode); + } + } + + private String getClientState(int clientState) { + switch (clientState) { + case GL_COLOR_ARRAY: + return "GL_COLOR_ARRAY"; + case GL_VERTEX_ARRAY: + return "GL_VERTEX_ARRAY"; + case GL_NORMAL_ARRAY: + return "GL_NORMAL_ARRAY"; + case GL_TEXTURE_COORD_ARRAY: + return "GL_TEXTURE_COORD_ARRAY"; + default: + return getHex(clientState); + } + } + + private String getCap(int cap) { + switch (cap) { + case GL_FOG: + return "GL_FOG"; + case GL_LIGHTING: + return "GL_LIGHTING"; + case GL_TEXTURE_2D: + return "GL_TEXTURE_2D"; + case GL_CULL_FACE: + return "GL_CULL_FACE"; + case GL_ALPHA_TEST: + return "GL_ALPHA_TEST"; + case GL_BLEND: + return "GL_BLEND"; + case GL_COLOR_LOGIC_OP: + return "GL_COLOR_LOGIC_OP"; + case GL_DITHER: + return "GL_DITHER"; + case GL_STENCIL_TEST: + return "GL_STENCIL_TEST"; + case GL_DEPTH_TEST: + return "GL_DEPTH_TEST"; + case GL_LIGHT0: + return "GL_LIGHT0"; + case GL_LIGHT1: + return "GL_LIGHT1"; + case GL_LIGHT2: + return "GL_LIGHT2"; + case GL_LIGHT3: + return "GL_LIGHT3"; + case GL_LIGHT4: + return "GL_LIGHT4"; + case GL_LIGHT5: + return "GL_LIGHT5"; + case GL_LIGHT6: + return "GL_LIGHT6"; + case GL_LIGHT7: + return "GL_LIGHT7"; + case GL_POINT_SMOOTH: + return "GL_POINT_SMOOTH"; + case GL_LINE_SMOOTH: + return "GL_LINE_SMOOTH"; + case GL_COLOR_MATERIAL: + return "GL_COLOR_MATERIAL"; + case GL_NORMALIZE: + return "GL_NORMALIZE"; + case GL_RESCALE_NORMAL: + return "GL_RESCALE_NORMAL"; + case GL_VERTEX_ARRAY: + return "GL_VERTEX_ARRAY"; + case GL_NORMAL_ARRAY: + return "GL_NORMAL_ARRAY"; + case GL_COLOR_ARRAY: + return "GL_COLOR_ARRAY"; + case GL_TEXTURE_COORD_ARRAY: + return "GL_TEXTURE_COORD_ARRAY"; + case GL_MULTISAMPLE: + return "GL_MULTISAMPLE"; + case GL_SAMPLE_ALPHA_TO_COVERAGE: + return "GL_SAMPLE_ALPHA_TO_COVERAGE"; + case GL_SAMPLE_ALPHA_TO_ONE: + return "GL_SAMPLE_ALPHA_TO_ONE"; + case GL_SAMPLE_COVERAGE: + return "GL_SAMPLE_COVERAGE"; + case GL_SCISSOR_TEST: + return "GL_SCISSOR_TEST"; + default: + return getHex(cap); + } + } + + private String getTexturePName(int pname) { + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + return "GL_TEXTURE_MAG_FILTER"; + case GL_TEXTURE_MIN_FILTER: + return "GL_TEXTURE_MIN_FILTER"; + case GL_TEXTURE_WRAP_S: + return "GL_TEXTURE_WRAP_S"; + case GL_TEXTURE_WRAP_T: + return "GL_TEXTURE_WRAP_T"; + case GL_GENERATE_MIPMAP: + return "GL_GENERATE_MIPMAP"; + case GL_TEXTURE_CROP_RECT_OES: + return "GL_TEXTURE_CROP_RECT_OES"; + default: + return getHex(pname); + } + } + + private String getTextureParamName(float param) { + int iparam = (int) param; + if (param == (float) iparam) { + switch (iparam) { + case GL_CLAMP_TO_EDGE: + return "GL_CLAMP_TO_EDGE"; + case GL_REPEAT: + return "GL_REPEAT"; + case GL_NEAREST: + return "GL_NEAREST"; + case GL_LINEAR: + return "GL_LINEAR"; + case GL_NEAREST_MIPMAP_NEAREST: + return "GL_NEAREST_MIPMAP_NEAREST"; + case GL_LINEAR_MIPMAP_NEAREST: + return "GL_LINEAR_MIPMAP_NEAREST"; + case GL_NEAREST_MIPMAP_LINEAR: + return "GL_NEAREST_MIPMAP_LINEAR"; + case GL_LINEAR_MIPMAP_LINEAR: + return "GL_LINEAR_MIPMAP_LINEAR"; + default: + return getHex(iparam); + } + } + return Float.toString(param); + } + + private String getFogPName(int pname) { + switch (pname) { + case GL_FOG_DENSITY: + return "GL_FOG_DENSITY"; + case GL_FOG_START: + return "GL_FOG_START"; + case GL_FOG_END: + return "GL_FOG_END"; + case GL_FOG_MODE: + return "GL_FOG_MODE"; + case GL_FOG_COLOR: + return "GL_FOG_COLOR"; + default: + return getHex(pname); + } + } + + private int getFogParamCount(int pname) { + switch (pname) { + case GL_FOG_DENSITY: + return 1; + case GL_FOG_START: + return 1; + case GL_FOG_END: + return 1; + case GL_FOG_MODE: + return 1; + case GL_FOG_COLOR: + return 4; + default: + return 0; + } + } + + private String getBeginMode(int mode) { + switch (mode) { + case GL_POINTS: + return "GL_POINTS"; + case GL_LINES: + return "GL_LINES"; + case GL_LINE_LOOP: + return "GL_LINE_LOOP"; + case GL_LINE_STRIP: + return "GL_LINE_STRIP"; + case GL_TRIANGLES: + return "GL_TRIANGLES"; + case GL_TRIANGLE_STRIP: + return "GL_TRIANGLE_STRIP"; + case GL_TRIANGLE_FAN: + return "GL_TRIANGLE_FAN"; + default: + return getHex(mode); + } + } + + private String getIndexType(int type) { + switch (type) { + case GL_UNSIGNED_SHORT: + return "GL_UNSIGNED_SHORT"; + case GL_UNSIGNED_BYTE: + return "GL_UNSIGNED_BYTE"; + default: + return getHex(type); + } + } + + private String getIntegerStateName(int pname) { + switch (pname) { + case GL_ALPHA_BITS: + return "GL_ALPHA_BITS"; + case GL_ALIASED_LINE_WIDTH_RANGE: + return "GL_ALIASED_LINE_WIDTH_RANGE"; + case GL_ALIASED_POINT_SIZE_RANGE: + return "GL_ALIASED_POINT_SIZE_RANGE"; + case GL_BLUE_BITS: + return "GL_BLUE_BITS"; + case GL_COMPRESSED_TEXTURE_FORMATS: + return "GL_COMPRESSED_TEXTURE_FORMATS"; + case GL_DEPTH_BITS: + return "GL_DEPTH_BITS"; + case GL_GREEN_BITS: + return "GL_GREEN_BITS"; + case GL_MAX_ELEMENTS_INDICES: + return "GL_MAX_ELEMENTS_INDICES"; + case GL_MAX_ELEMENTS_VERTICES: + return "GL_MAX_ELEMENTS_VERTICES"; + case GL_MAX_LIGHTS: + return "GL_MAX_LIGHTS"; + case GL_MAX_TEXTURE_SIZE: + return "GL_MAX_TEXTURE_SIZE"; + case GL_MAX_VIEWPORT_DIMS: + return "GL_MAX_VIEWPORT_DIMS"; + case GL_MAX_MODELVIEW_STACK_DEPTH: + return "GL_MAX_MODELVIEW_STACK_DEPTH"; + case GL_MAX_PROJECTION_STACK_DEPTH: + return "GL_MAX_PROJECTION_STACK_DEPTH"; + case GL_MAX_TEXTURE_STACK_DEPTH: + return "GL_MAX_TEXTURE_STACK_DEPTH"; + case GL_MAX_TEXTURE_UNITS: + return "GL_MAX_TEXTURE_UNITS"; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + return "GL_NUM_COMPRESSED_TEXTURE_FORMATS"; + case GL_RED_BITS: + return "GL_RED_BITS"; + case GL_SMOOTH_LINE_WIDTH_RANGE: + return "GL_SMOOTH_LINE_WIDTH_RANGE"; + case GL_SMOOTH_POINT_SIZE_RANGE: + return "GL_SMOOTH_POINT_SIZE_RANGE"; + case GL_STENCIL_BITS: + return "GL_STENCIL_BITS"; + case GL_SUBPIXEL_BITS: + return "GL_SUBPIXEL_BITS"; + + case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES: + return "GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES"; + case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES: + return "GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES"; + case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES: + return "GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES"; + + default: + return getHex(pname); + } + } + + private int getIntegerStateSize(int pname) { + switch (pname) { + case GL_ALPHA_BITS: + return 1; + case GL_ALIASED_LINE_WIDTH_RANGE: + return 2; + case GL_ALIASED_POINT_SIZE_RANGE: + return 2; + case GL_BLUE_BITS: + return 1; + case GL_COMPRESSED_TEXTURE_FORMATS: + // Have to ask the implementation for the size + { + int[] buffer = new int[1]; + mgl.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, buffer, 0); + return buffer[0]; + } + case GL_DEPTH_BITS: + return 1; + case GL_GREEN_BITS: + return 1; + case GL_MAX_ELEMENTS_INDICES: + return 1; + case GL_MAX_ELEMENTS_VERTICES: + return 1; + case GL_MAX_LIGHTS: + return 1; + case GL_MAX_TEXTURE_SIZE: + return 1; + case GL_MAX_VIEWPORT_DIMS: + return 2; + case GL_MAX_MODELVIEW_STACK_DEPTH: + return 1; + case GL_MAX_PROJECTION_STACK_DEPTH: + return 1; + case GL_MAX_TEXTURE_STACK_DEPTH: + return 1; + case GL_MAX_TEXTURE_UNITS: + return 1; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + return 1; + case GL_RED_BITS: + return 1; + case GL_SMOOTH_LINE_WIDTH_RANGE: + return 2; + case GL_SMOOTH_POINT_SIZE_RANGE: + return 2; + case GL_STENCIL_BITS: + return 1; + case GL_SUBPIXEL_BITS: + return 1; + + case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES: + case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES: + case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES: + return 16; + + default: + return 0; + } + } + + private int getIntegerStateFormat(int pname) { + switch (pname) { + case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES: + case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES: + case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES: + return FORMAT_FLOAT; + + default: + return FORMAT_INT; + } + } + + private String getHintTarget(int target) { + switch (target) { + case GL_FOG_HINT: + return "GL_FOG_HINT"; + case GL_LINE_SMOOTH_HINT: + return "GL_LINE_SMOOTH_HINT"; + case GL_PERSPECTIVE_CORRECTION_HINT: + return "GL_PERSPECTIVE_CORRECTION_HINT"; + case GL_POINT_SMOOTH_HINT: + return "GL_POINT_SMOOTH_HINT"; + case GL_POLYGON_SMOOTH_HINT: + return "GL_POLYGON_SMOOTH_HINT"; + case GL_GENERATE_MIPMAP_HINT: + return "GL_GENERATE_MIPMAP_HINT"; + default: + return getHex(target); + } + } + + private String getHintMode(int mode) { + switch (mode) { + case GL_FASTEST: + return "GL_FASTEST"; + case GL_NICEST: + return "GL_NICEST"; + case GL_DONT_CARE: + return "GL_DONT_CARE"; + default: + return getHex(mode); + } + } + + private String getFaceName(int face) { + switch (face) { + case GL_FRONT_AND_BACK: + return "GL_FRONT_AND_BACK"; + default: + return getHex(face); + } + } + + private String getMaterialPName(int pname) { + switch (pname) { + case GL_AMBIENT: + return "GL_AMBIENT"; + case GL_DIFFUSE: + return "GL_DIFFUSE"; + case GL_SPECULAR: + return "GL_SPECULAR"; + case GL_EMISSION: + return "GL_EMISSION"; + case GL_SHININESS: + return "GL_SHININESS"; + case GL_AMBIENT_AND_DIFFUSE: + return "GL_AMBIENT_AND_DIFFUSE"; + default: + return getHex(pname); + } + } + + private int getMaterialParamCount(int pname) { + switch (pname) { + case GL_AMBIENT: + return 4; + case GL_DIFFUSE: + return 4; + case GL_SPECULAR: + return 4; + case GL_EMISSION: + return 4; + case GL_SHININESS: + return 1; + case GL_AMBIENT_AND_DIFFUSE: + return 4; + default: + return 0; + } + } + + private String getLightName(int light) { + if (light >= GL_LIGHT0 && light <= GL_LIGHT7) { + return "GL_LIGHT" + Integer.toString(light); + } + return getHex(light); + } + + private String getLightPName(int pname) { + switch (pname) { + case GL_AMBIENT: + return "GL_AMBIENT"; + case GL_DIFFUSE: + return "GL_DIFFUSE"; + case GL_SPECULAR: + return "GL_SPECULAR"; + case GL_POSITION: + return "GL_POSITION"; + case GL_SPOT_DIRECTION: + return "GL_SPOT_DIRECTION"; + case GL_SPOT_EXPONENT: + return "GL_SPOT_EXPONENT"; + case GL_SPOT_CUTOFF: + return "GL_SPOT_CUTOFF"; + case GL_CONSTANT_ATTENUATION: + return "GL_CONSTANT_ATTENUATION"; + case GL_LINEAR_ATTENUATION: + return "GL_LINEAR_ATTENUATION"; + case GL_QUADRATIC_ATTENUATION: + return "GL_QUADRATIC_ATTENUATION"; + default: + return getHex(pname); + } + } + + private int getLightParamCount(int pname) { + switch (pname) { + case GL_AMBIENT: + return 4; + case GL_DIFFUSE: + return 4; + case GL_SPECULAR: + return 4; + case GL_POSITION: + return 4; + case GL_SPOT_DIRECTION: + return 3; + case GL_SPOT_EXPONENT: + return 1; + case GL_SPOT_CUTOFF: + return 1; + case GL_CONSTANT_ATTENUATION: + return 1; + case GL_LINEAR_ATTENUATION: + return 1; + case GL_QUADRATIC_ATTENUATION: + return 1; + default: + return 0; + } + } + + private String getLightModelPName(int pname) { + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + return "GL_LIGHT_MODEL_AMBIENT"; + case GL_LIGHT_MODEL_TWO_SIDE: + return "GL_LIGHT_MODEL_TWO_SIDE"; + default: + return getHex(pname); + } + } + + private int getLightModelParamCount(int pname) { + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + return 4; + case GL_LIGHT_MODEL_TWO_SIDE: + return 1; + default: + return 0; + } + } + + private String getPointerTypeName(int type) { + switch (type) { + case GL_BYTE: + return "GL_BYTE"; + case GL_UNSIGNED_BYTE: + return "GL_UNSIGNED_BYTE"; + case GL_SHORT: + return "GL_SHORT"; + case GL_FIXED: + return "GL_FIXED"; + case GL_FLOAT: + return "GL_FLOAT"; + default: + return getHex(type); + } + } + + private ByteBuffer toByteBuffer(int byteCount, Buffer input) { + ByteBuffer result = null; + boolean convertWholeBuffer = (byteCount < 0); + if (input instanceof ByteBuffer) { + ByteBuffer input2 = (ByteBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit(); + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + int position = input2.position(); + for (int i = 0; i < byteCount; i++) { + result.put(input2.get()); + } + input2.position(position); + } else if (input instanceof CharBuffer) { + CharBuffer input2 = (CharBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit() * 2; + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + CharBuffer result2 = result.asCharBuffer(); + int position = input2.position(); + for (int i = 0; i < byteCount / 2; i++) { + result2.put(input2.get()); + } + input2.position(position); + } else if (input instanceof ShortBuffer) { + ShortBuffer input2 = (ShortBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit() * 2; + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + ShortBuffer result2 = result.asShortBuffer(); + int position = input2.position(); + for (int i = 0; i < byteCount / 2; i++) { + result2.put(input2.get()); + } + input2.position(position); + } else if (input instanceof IntBuffer) { + IntBuffer input2 = (IntBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit() * 4; + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + IntBuffer result2 = result.asIntBuffer(); + int position = input2.position(); + for (int i = 0; i < byteCount / 4; i++) { + result2.put(input2.get()); + } + input2.position(position); + } else if (input instanceof FloatBuffer) { + FloatBuffer input2 = (FloatBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit() * 4; + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + FloatBuffer result2 = result.asFloatBuffer(); + int position = input2.position(); + for (int i = 0; i < byteCount / 4; i++) { + result2.put(input2.get()); + } + input2.position(position); + } else if (input instanceof DoubleBuffer) { + DoubleBuffer input2 = (DoubleBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit() * 8; + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + DoubleBuffer result2 = result.asDoubleBuffer(); + int position = input2.position(); + for (int i = 0; i < byteCount / 8; i++) { + result2.put(input2.get()); + } + input2.position(position); + } else if (input instanceof LongBuffer) { + LongBuffer input2 = (LongBuffer) input; + if (convertWholeBuffer) { + byteCount = input2.limit() * 8; + } + result = ByteBuffer.allocate(byteCount).order(input2.order()); + LongBuffer result2 = result.asLongBuffer(); + int position = input2.position(); + for (int i = 0; i < byteCount / 8; i++) { + result2.put(input2.get()); + } + input2.position(position); + } else { + throw new RuntimeException("Unimplemented Buffer subclass."); + } + result.rewind(); + // The OpenGL API will interpret the result in hardware byte order, + // so we better do that as well: + result.order(ByteOrder.nativeOrder()); + return result; + } + + private char[] toCharIndices(int count, int type, Buffer indices) { + char[] result = new char[count]; + switch (type) { + case GL_UNSIGNED_BYTE: { + ByteBuffer byteBuffer = toByteBuffer(count, indices); + byte[] array = byteBuffer.array(); + int offset = byteBuffer.arrayOffset(); + for (int i = 0; i < count; i++) { + result[i] = (char) (0xff & array[offset + i]); + } + } + break; + case GL_UNSIGNED_SHORT: { + CharBuffer charBuffer; + if (indices instanceof CharBuffer) { + charBuffer = (CharBuffer) indices; + } else { + ByteBuffer byteBuffer = toByteBuffer(count * 2, indices); + charBuffer = byteBuffer.asCharBuffer(); + } + int oldPosition = charBuffer.position(); + charBuffer.position(0); + charBuffer.get(result); + charBuffer.position(oldPosition); + } + break; + default: + // Don't throw an exception, because we don't want logging to + // change the behavior. + break; + } + return result; + } + + private void doArrayElement(StringBuilder builder, boolean enabled, + String name, PointerInfo pointer, int index) { + if (!enabled) { + return; + } + builder.append(" "); + builder.append(name + ":{"); + if (pointer == null) { + builder.append("undefined"); + return; + } + if (pointer.mStride < 0) { + builder.append("invalid stride"); + return; + } + + int stride = pointer.getStride(); + ByteBuffer byteBuffer = pointer.mTempByteBuffer; + int size = pointer.mSize; + int type = pointer.mType; + int sizeofType = pointer.sizeof(type); + int byteOffset = stride * index; + for (int i = 0; i < size; i++) { + if (i > 0) { + builder.append(", "); + } + switch (type) { + case GL_BYTE: { + byte d = byteBuffer.get(byteOffset); + builder.append(Integer.toString(d)); + } + break; + case GL_UNSIGNED_BYTE: { + byte d = byteBuffer.get(byteOffset); + builder.append(Integer.toString(0xff & d)); + } + break; + case GL_SHORT: { + ShortBuffer shortBuffer = byteBuffer.asShortBuffer(); + short d = shortBuffer.get(byteOffset / 2); + builder.append(Integer.toString(d)); + } + break; + case GL_FIXED: { + IntBuffer intBuffer = byteBuffer.asIntBuffer(); + int d = intBuffer.get(byteOffset / 4); + builder.append(Integer.toString(d)); + } + break; + case GL_FLOAT: { + FloatBuffer intBuffer = byteBuffer.asFloatBuffer(); + float d = intBuffer.get(byteOffset / 4); + builder.append(Float.toString(d)); + } + break; + default: + builder.append("?"); + break; + } + byteOffset += sizeofType; + } + builder.append("}"); + } + + private void doElement(StringBuilder builder, int ordinal, int vertexIndex) { + builder.append(" [" + ordinal + " : " + vertexIndex + "] ="); + doArrayElement(builder, mVertexArrayEnabled, "v", mVertexPointer, + vertexIndex); + doArrayElement(builder, mNormalArrayEnabled, "n", mNormalPointer, + vertexIndex); + doArrayElement(builder, mColorArrayEnabled, "c", mColorPointer, + vertexIndex); + doArrayElement(builder, mTextureCoordArrayEnabled, "t", + mTexCoordPointer, vertexIndex); + builder.append("\n"); + // Vertex + // Normal + // Color + // TexCoord + } + + private void bindArrays() { + if (mColorArrayEnabled) + mColorPointer.bindByteBuffer(); + if (mNormalArrayEnabled) + mNormalPointer.bindByteBuffer(); + if (mTextureCoordArrayEnabled) + mTexCoordPointer.bindByteBuffer(); + if (mVertexArrayEnabled) + mVertexPointer.bindByteBuffer(); + } + + private void unbindArrays() { + if (mColorArrayEnabled) + mColorPointer.unbindByteBuffer(); + if (mNormalArrayEnabled) + mNormalPointer.unbindByteBuffer(); + if (mTextureCoordArrayEnabled) + mTexCoordPointer.unbindByteBuffer(); + if (mVertexArrayEnabled) + mVertexPointer.unbindByteBuffer(); + } + + private void startLogIndices() { + mStringBuilder = new StringBuilder(); + mStringBuilder.append("\n"); + bindArrays(); + } + + private void endLogIndices() { + log(mStringBuilder.toString()); + unbindArrays(); + } + + // --------------------------------------------------------------------- + // GL10 methods: + + public void glActiveTexture(int texture) { + begin("glActiveTexture"); + arg("texture", texture); + end(); + mgl.glActiveTexture(texture); + checkError(); + } + + public void glAlphaFunc(int func, float ref) { + begin("glAlphaFunc"); + arg("func", func); + arg("ref", ref); + end(); + mgl.glAlphaFunc(func, ref); + checkError(); + } + + public void glAlphaFuncx(int func, int ref) { + begin("glAlphaFuncx"); + arg("func", func); + arg("ref", ref); + end(); + mgl.glAlphaFuncx(func, ref); + checkError(); + } + + public void glBindTexture(int target, int texture) { + begin("glBindTexture"); + arg("target", getTextureTarget(target)); + arg("texture", texture); + end(); + mgl.glBindTexture(target, texture); + checkError(); + } + + public void glBlendFunc(int sfactor, int dfactor) { + begin("glBlendFunc"); + arg("sfactor", getFactor(sfactor)); + arg("dfactor", getFactor(dfactor)); + end(); + + mgl.glBlendFunc(sfactor, dfactor); + checkError(); + } + + public void glClear(int mask) { + begin("glClear"); + arg("mask", getClearBufferMask(mask)); + end(); + + mgl.glClear(mask); + checkError(); + } + + public void glClearColor(float red, float green, float blue, float alpha) { + begin("glClearColor"); + arg("red", red); + arg("green", green); + arg("blue", blue); + arg("alpha", alpha); + end(); + + mgl.glClearColor(red, green, blue, alpha); + checkError(); + } + + public void glClearColorx(int red, int green, int blue, int alpha) { + begin("glClearColor"); + arg("red", red); + arg("green", green); + arg("blue", blue); + arg("alpha", alpha); + end(); + + mgl.glClearColorx(red, green, blue, alpha); + checkError(); + } + + public void glClearDepthf(float depth) { + begin("glClearDepthf"); + arg("depth", depth); + end(); + + mgl.glClearDepthf(depth); + checkError(); + } + + public void glClearDepthx(int depth) { + begin("glClearDepthx"); + arg("depth", depth); + end(); + + mgl.glClearDepthx(depth); + checkError(); + } + + public void glClearStencil(int s) { + begin("glClearStencil"); + arg("s", s); + end(); + + mgl.glClearStencil(s); + checkError(); + } + + public void glClientActiveTexture(int texture) { + begin("glClientActiveTexture"); + arg("texture", texture); + end(); + + mgl.glClientActiveTexture(texture); + checkError(); + } + + public void glColor4f(float red, float green, float blue, float alpha) { + begin("glColor4f"); + arg("red", red); + arg("green", green); + arg("blue", blue); + arg("alpha", alpha); + end(); + + mgl.glColor4f(red, green, blue, alpha); + checkError(); + } + + public void glColor4x(int red, int green, int blue, int alpha) { + begin("glColor4x"); + arg("red", red); + arg("green", green); + arg("blue", blue); + arg("alpha", alpha); + end(); + + mgl.glColor4x(red, green, blue, alpha); + checkError(); + } + + public void glColorMask(boolean red, boolean green, boolean blue, + boolean alpha) { + begin("glColorMask"); + arg("red", red); + arg("green", green); + arg("blue", blue); + arg("alpha", alpha); + end(); + + mgl.glColorMask(red, green, blue, alpha); + checkError(); + } + + public void glColorPointer(int size, int type, int stride, Buffer pointer) { + begin("glColorPointer"); + argPointer(size, type, stride, pointer); + end(); + mColorPointer = new PointerInfo(size, type, stride, pointer); + + mgl.glColorPointer(size, type, stride, pointer); + checkError(); + } + + public void glCompressedTexImage2D(int target, int level, + int internalformat, int width, int height, int border, + int imageSize, Buffer data) { + begin("glCompressedTexImage2D"); + arg("target", getTextureTarget(target)); + arg("level", level); + arg("internalformat", internalformat); + arg("width", width); + arg("height", height); + arg("border", border); + arg("imageSize", imageSize); + arg("data", data.toString()); + end(); + + mgl.glCompressedTexImage2D(target, level, internalformat, width, + height, border, imageSize, data); + checkError(); + } + + public void glCompressedTexSubImage2D(int target, int level, int xoffset, + int yoffset, int width, int height, int format, int imageSize, + Buffer data) { + begin("glCompressedTexSubImage2D"); + arg("target", getTextureTarget(target)); + arg("level", level); + arg("xoffset", xoffset); + arg("yoffset", yoffset); + arg("width", width); + arg("height", height); + arg("format", format); + arg("imageSize", imageSize); + arg("data", data.toString()); + end(); + + mgl.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, + height, format, imageSize, data); + checkError(); + } + + public void glCopyTexImage2D(int target, int level, int internalformat, + int x, int y, int width, int height, int border) { + begin("glCopyTexImage2D"); + arg("target", getTextureTarget(target)); + arg("level", level); + arg("internalformat", internalformat); + arg("x", x); + arg("y", y); + arg("width", width); + arg("height", height); + arg("border", border); + end(); + + mgl.glCopyTexImage2D(target, level, internalformat, x, y, width, + height, border); + checkError(); + } + + public void glCopyTexSubImage2D(int target, int level, int xoffset, + int yoffset, int x, int y, int width, int height) { + begin("glCopyTexSubImage2D"); + arg("target", getTextureTarget(target)); + arg("level", level); + arg("xoffset", xoffset); + arg("yoffset", yoffset); + arg("x", x); + arg("y", y); + arg("width", width); + arg("height", height); + end(); + + mgl.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, + height); + checkError(); + } + + public void glCullFace(int mode) { + begin("glCullFace"); + arg("mode", mode); + end(); + + mgl.glCullFace(mode); + checkError(); + } + + public void glDeleteTextures(int n, int[] textures, int offset) { + begin("glDeleteTextures"); + arg("n", n); + arg("textures", n, textures, offset); + arg("offset", offset); + end(); + + mgl.glDeleteTextures(n, textures, offset); + checkError(); + } + + public void glDeleteTextures(int n, IntBuffer textures) { + begin("glDeleteTextures"); + arg("n", n); + arg("textures", n, textures); + end(); + + mgl.glDeleteTextures(n, textures); + checkError(); + } + + public void glDepthFunc(int func) { + begin("glDepthFunc"); + arg("func", func); + end(); + + mgl.glDepthFunc(func); + checkError(); + } + + public void glDepthMask(boolean flag) { + begin("glDepthMask"); + arg("flag", flag); + end(); + + mgl.glDepthMask(flag); + checkError(); + } + + public void glDepthRangef(float near, float far) { + begin("glDepthRangef"); + arg("near", near); + arg("far", far); + end(); + + mgl.glDepthRangef(near, far); + checkError(); + } + + public void glDepthRangex(int near, int far) { + begin("glDepthRangex"); + arg("near", near); + arg("far", far); + end(); + + mgl.glDepthRangex(near, far); + checkError(); + } + + public void glDisable(int cap) { + begin("glDisable"); + arg("cap", getCap(cap)); + end(); + + mgl.glDisable(cap); + checkError(); + } + + public void glDisableClientState(int array) { + begin("glDisableClientState"); + arg("array", getClientState(array)); + end(); + + switch (array) { + case GL_COLOR_ARRAY: + mColorArrayEnabled = false; + break; + case GL_NORMAL_ARRAY: + mNormalArrayEnabled = false; + break; + case GL_TEXTURE_COORD_ARRAY: + mTextureCoordArrayEnabled = false; + break; + case GL_VERTEX_ARRAY: + mVertexArrayEnabled = false; + break; + } + mgl.glDisableClientState(array); + checkError(); + } + + public void glDrawArrays(int mode, int first, int count) { + begin("glDrawArrays"); + arg("mode", mode); + arg("first", first); + arg("count", count); + startLogIndices(); + for (int i = 0; i < count; i++) { + doElement(mStringBuilder, i, first + count); + } + endLogIndices(); + end(); + + mgl.glDrawArrays(mode, first, count); + checkError(); + } + + public void glDrawElements(int mode, int count, int type, Buffer indices) { + begin("glDrawElements"); + arg("mode", getBeginMode(mode)); + arg("count", count); + arg("type", getIndexType(type)); + char[] indexArray = toCharIndices(count, type, indices); + int indexArrayLength = indexArray.length; + startLogIndices(); + for (int i = 0; i < indexArrayLength; i++) { + doElement(mStringBuilder, i, indexArray[i]); + } + endLogIndices(); + end(); + + mgl.glDrawElements(mode, count, type, indices); + checkError(); + } + + public void glEnable(int cap) { + begin("glEnable"); + arg("cap", getCap(cap)); + end(); + + mgl.glEnable(cap); + checkError(); + } + + public void glEnableClientState(int array) { + begin("glEnableClientState"); + arg("array", getClientState(array)); + end(); + + switch (array) { + case GL_COLOR_ARRAY: + mColorArrayEnabled = true; + break; + case GL_NORMAL_ARRAY: + mNormalArrayEnabled = true; + break; + case GL_TEXTURE_COORD_ARRAY: + mTextureCoordArrayEnabled = true; + break; + case GL_VERTEX_ARRAY: + mVertexArrayEnabled = true; + break; + } + mgl.glEnableClientState(array); + checkError(); + } + + public void glFinish() { + begin("glFinish"); + end(); + + mgl.glFinish(); + checkError(); + } + + public void glFlush() { + begin("glFlush"); + end(); + + mgl.glFlush(); + checkError(); + } + + public void glFogf(int pname, float param) { + begin("glFogf"); + arg("pname", pname); + arg("param", param); + end(); + + mgl.glFogf(pname, param); + checkError(); + } + + public void glFogfv(int pname, float[] params, int offset) { + begin("glFogfv"); + arg("pname", getFogPName(pname)); + arg("params", getFogParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glFogfv(pname, params, offset); + checkError(); + } + + public void glFogfv(int pname, FloatBuffer params) { + begin("glFogfv"); + arg("pname", getFogPName(pname)); + arg("params", getFogParamCount(pname), params); + end(); + + mgl.glFogfv(pname, params); + checkError(); + } + + public void glFogx(int pname, int param) { + begin("glFogx"); + arg("pname", getFogPName(pname)); + arg("param", param); + end(); + + mgl.glFogx(pname, param); + checkError(); + } + + public void glFogxv(int pname, int[] params, int offset) { + begin("glFogxv"); + arg("pname", getFogPName(pname)); + arg("params", getFogParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glFogxv(pname, params, offset); + checkError(); + } + + public void glFogxv(int pname, IntBuffer params) { + begin("glFogxv"); + arg("pname", getFogPName(pname)); + arg("params", getFogParamCount(pname), params); + end(); + + mgl.glFogxv(pname, params); + checkError(); + } + + public void glFrontFace(int mode) { + begin("glFrontFace"); + arg("mode", mode); + end(); + + mgl.glFrontFace(mode); + checkError(); + } + + public void glFrustumf(float left, float right, float bottom, float top, + float near, float far) { + begin("glFrustumf"); + arg("left", left); + arg("right", right); + arg("bottom", bottom); + arg("top", top); + arg("near", near); + arg("far", far); + end(); + + mgl.glFrustumf(left, right, bottom, top, near, far); + checkError(); + } + + public void glFrustumx(int left, int right, int bottom, int top, int near, + int far) { + begin("glFrustumx"); + arg("left", left); + arg("right", right); + arg("bottom", bottom); + arg("top", top); + arg("near", near); + arg("far", far); + end(); + + mgl.glFrustumx(left, right, bottom, top, near, far); + checkError(); + } + + public void glGenTextures(int n, int[] textures, int offset) { + begin("glGenTextures"); + arg("n", n); + arg("textures", Arrays.toString(textures)); + arg("offset", offset); + + mgl.glGenTextures(n, textures, offset); + + returns(toString(n, FORMAT_INT, textures, offset)); + + checkError(); + } + + public void glGenTextures(int n, IntBuffer textures) { + begin("glGenTextures"); + arg("n", n); + arg("textures", textures.toString()); + + mgl.glGenTextures(n, textures); + + returns(toString(n, FORMAT_INT, textures)); + + checkError(); + } + + public int glGetError() { + begin("glGetError"); + + int result = mgl.glGetError(); + + returns(result); + + return result; + } + + public void glGetIntegerv(int pname, int[] params, int offset) { + begin("glGetIntegerv"); + arg("pname", getIntegerStateName(pname)); + arg("params", Arrays.toString(params)); + arg("offset", offset); + + mgl.glGetIntegerv(pname, params, offset); + + returns(toString(getIntegerStateSize(pname), + getIntegerStateFormat(pname), params, offset)); + + checkError(); + } + + public void glGetIntegerv(int pname, IntBuffer params) { + begin("glGetIntegerv"); + arg("pname", getIntegerStateName(pname)); + arg("params", params.toString()); + + mgl.glGetIntegerv(pname, params); + + returns(toString(getIntegerStateSize(pname), + getIntegerStateFormat(pname), params)); + + checkError(); + } + + public String glGetString(int name) { + begin("glGetString"); + arg("name", name); + + String result = mgl.glGetString(name); + + returns(result); + + checkError(); + return result; + } + + public void glHint(int target, int mode) { + begin("glHint"); + arg("target", getHintTarget(target)); + arg("mode", getHintMode(mode)); + end(); + + mgl.glHint(target, mode); + checkError(); + } + + public void glLightModelf(int pname, float param) { + begin("glLightModelf"); + arg("pname", getLightModelPName(pname)); + arg("param", param); + end(); + + mgl.glLightModelf(pname, param); + checkError(); + } + + public void glLightModelfv(int pname, float[] params, int offset) { + begin("glLightModelfv"); + arg("pname", getLightModelPName(pname)); + arg("params", getLightModelParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glLightModelfv(pname, params, offset); + checkError(); + } + + public void glLightModelfv(int pname, FloatBuffer params) { + begin("glLightModelfv"); + arg("pname", getLightModelPName(pname)); + arg("params", getLightModelParamCount(pname), params); + end(); + + mgl.glLightModelfv(pname, params); + checkError(); + } + + public void glLightModelx(int pname, int param) { + begin("glLightModelx"); + arg("pname", getLightModelPName(pname)); + arg("param", param); + end(); + + mgl.glLightModelx(pname, param); + checkError(); + } + + public void glLightModelxv(int pname, int[] params, int offset) { + begin("glLightModelxv"); + arg("pname", getLightModelPName(pname)); + arg("params", getLightModelParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glLightModelxv(pname, params, offset); + checkError(); + } + + public void glLightModelxv(int pname, IntBuffer params) { + begin("glLightModelfv"); + arg("pname", getLightModelPName(pname)); + arg("params", getLightModelParamCount(pname), params); + end(); + + mgl.glLightModelxv(pname, params); + checkError(); + } + + public void glLightf(int light, int pname, float param) { + begin("glLightf"); + arg("light", getLightName(light)); + arg("pname", getLightPName(pname)); + arg("param", param); + end(); + + mgl.glLightf(light, pname, param); + checkError(); + } + + public void glLightfv(int light, int pname, float[] params, int offset) { + begin("glLightfv"); + arg("light", getLightName(light)); + arg("pname", getLightPName(pname)); + arg("params", getLightParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glLightfv(light, pname, params, offset); + checkError(); + } + + public void glLightfv(int light, int pname, FloatBuffer params) { + begin("glLightfv"); + arg("light", getLightName(light)); + arg("pname", getLightPName(pname)); + arg("params", getLightParamCount(pname), params); + end(); + + mgl.glLightfv(light, pname, params); + checkError(); + } + + public void glLightx(int light, int pname, int param) { + begin("glLightx"); + arg("light", getLightName(light)); + arg("pname", getLightPName(pname)); + arg("param", param); + end(); + + mgl.glLightx(light, pname, param); + checkError(); + } + + public void glLightxv(int light, int pname, int[] params, int offset) { + begin("glLightxv"); + arg("light", getLightName(light)); + arg("pname", getLightPName(pname)); + arg("params", getLightParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glLightxv(light, pname, params, offset); + checkError(); + } + + public void glLightxv(int light, int pname, IntBuffer params) { + begin("glLightxv"); + arg("light", getLightName(light)); + arg("pname", getLightPName(pname)); + arg("params", getLightParamCount(pname), params); + end(); + + mgl.glLightxv(light, pname, params); + checkError(); + } + + public void glLineWidth(float width) { + begin("glLineWidth"); + arg("width", width); + end(); + + mgl.glLineWidth(width); + checkError(); + } + + public void glLineWidthx(int width) { + begin("glLineWidthx"); + arg("width", width); + end(); + + mgl.glLineWidthx(width); + checkError(); + } + + public void glLoadIdentity() { + begin("glLoadIdentity"); + end(); + + mgl.glLoadIdentity(); + checkError(); + } + + public void glLoadMatrixf(float[] m, int offset) { + begin("glLoadMatrixf"); + arg("m", 16, m, offset); + arg("offset", offset); + end(); + + mgl.glLoadMatrixf(m, offset); + checkError(); + } + + public void glLoadMatrixf(FloatBuffer m) { + begin("glLoadMatrixf"); + arg("m", 16, m); + end(); + + mgl.glLoadMatrixf(m); + checkError(); + } + + public void glLoadMatrixx(int[] m, int offset) { + begin("glLoadMatrixx"); + arg("m", 16, m, offset); + arg("offset", offset); + end(); + + mgl.glLoadMatrixx(m, offset); + checkError(); + } + + public void glLoadMatrixx(IntBuffer m) { + begin("glLoadMatrixx"); + arg("m", 16, m); + end(); + + mgl.glLoadMatrixx(m); + checkError(); + } + + public void glLogicOp(int opcode) { + begin("glLogicOp"); + arg("opcode", opcode); + end(); + + mgl.glLogicOp(opcode); + checkError(); + } + + public void glMaterialf(int face, int pname, float param) { + begin("glMaterialf"); + arg("face", getFaceName(face)); + arg("pname", getMaterialPName(pname)); + arg("param", param); + end(); + + mgl.glMaterialf(face, pname, param); + checkError(); + } + + public void glMaterialfv(int face, int pname, float[] params, int offset) { + begin("glMaterialfv"); + arg("face", getFaceName(face)); + arg("pname", getMaterialPName(pname)); + arg("params", getMaterialParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glMaterialfv(face, pname, params, offset); + checkError(); + } + + public void glMaterialfv(int face, int pname, FloatBuffer params) { + begin("glMaterialfv"); + arg("face", getFaceName(face)); + arg("pname", getMaterialPName(pname)); + arg("params", getMaterialParamCount(pname), params); + end(); + + mgl.glMaterialfv(face, pname, params); + checkError(); + } + + public void glMaterialx(int face, int pname, int param) { + begin("glMaterialx"); + arg("face", getFaceName(face)); + arg("pname", getMaterialPName(pname)); + arg("param", param); + end(); + + mgl.glMaterialx(face, pname, param); + checkError(); + } + + public void glMaterialxv(int face, int pname, int[] params, int offset) { + begin("glMaterialxv"); + arg("face", getFaceName(face)); + arg("pname", getMaterialPName(pname)); + arg("params", getMaterialParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glMaterialxv(face, pname, params, offset); + checkError(); + } + + public void glMaterialxv(int face, int pname, IntBuffer params) { + begin("glMaterialxv"); + arg("face", getFaceName(face)); + arg("pname", getMaterialPName(pname)); + arg("params", getMaterialParamCount(pname), params); + end(); + + mgl.glMaterialxv(face, pname, params); + checkError(); + } + + public void glMatrixMode(int mode) { + begin("glMatrixMode"); + arg("mode", getMatrixMode(mode)); + end(); + + mgl.glMatrixMode(mode); + checkError(); + } + + public void glMultMatrixf(float[] m, int offset) { + begin("glMultMatrixf"); + arg("m", 16, m, offset); + arg("offset", offset); + end(); + + mgl.glMultMatrixf(m, offset); + checkError(); + } + + public void glMultMatrixf(FloatBuffer m) { + begin("glMultMatrixf"); + arg("m", 16, m); + end(); + + mgl.glMultMatrixf(m); + checkError(); + } + + public void glMultMatrixx(int[] m, int offset) { + begin("glMultMatrixx"); + arg("m", 16, m, offset); + arg("offset", offset); + end(); + + mgl.glMultMatrixx(m, offset); + checkError(); + } + + public void glMultMatrixx(IntBuffer m) { + begin("glMultMatrixx"); + arg("m", 16, m); + end(); + + mgl.glMultMatrixx(m); + checkError(); + } + + public void glMultiTexCoord4f(int target, float s, float t, float r, float q) { + begin("glMultiTexCoord4f"); + arg("target", target); + arg("s", s); + arg("t", t); + arg("r", r); + arg("q", q); + end(); + + mgl.glMultiTexCoord4f(target, s, t, r, q); + checkError(); + } + + public void glMultiTexCoord4x(int target, int s, int t, int r, int q) { + begin("glMultiTexCoord4x"); + arg("target", target); + arg("s", s); + arg("t", t); + arg("r", r); + arg("q", q); + end(); + + mgl.glMultiTexCoord4x(target, s, t, r, q); + checkError(); + } + + public void glNormal3f(float nx, float ny, float nz) { + begin("glNormal3f"); + arg("nx", nx); + arg("ny", ny); + arg("nz", nz); + end(); + + mgl.glNormal3f(nx, ny, nz); + checkError(); + } + + public void glNormal3x(int nx, int ny, int nz) { + begin("glNormal3x"); + arg("nx", nx); + arg("ny", ny); + arg("nz", nz); + end(); + + mgl.glNormal3x(nx, ny, nz); + checkError(); + } + + public void glNormalPointer(int type, int stride, Buffer pointer) { + begin("glNormalPointer"); + arg("type", type); + arg("stride", stride); + arg("pointer", pointer.toString()); + end(); + mNormalPointer = new PointerInfo(3, type, stride, pointer); + + mgl.glNormalPointer(type, stride, pointer); + checkError(); + } + + public void glOrthof(float left, float right, float bottom, float top, + float near, float far) { + begin("glOrthof"); + arg("left", left); + arg("right", right); + arg("bottom", bottom); + arg("top", top); + arg("near", near); + arg("far", far); + end(); + + mgl.glOrthof(left, right, bottom, top, near, far); + checkError(); + } + + public void glOrthox(int left, int right, int bottom, int top, int near, + int far) { + begin("glOrthox"); + arg("left", left); + arg("right", right); + arg("bottom", bottom); + arg("top", top); + arg("near", near); + arg("far", far); + end(); + + mgl.glOrthox(left, right, bottom, top, near, far); + checkError(); + } + + public void glPixelStorei(int pname, int param) { + begin("glPixelStorei"); + arg("pname", pname); + arg("param", param); + end(); + + mgl.glPixelStorei(pname, param); + checkError(); + } + + public void glPointSize(float size) { + begin("glPointSize"); + arg("size", size); + end(); + + mgl.glPointSize(size); + checkError(); + } + + public void glPointSizex(int size) { + begin("glPointSizex"); + arg("size", size); + end(); + + mgl.glPointSizex(size); + checkError(); + } + + public void glPolygonOffset(float factor, float units) { + begin("glPolygonOffset"); + arg("factor", factor); + arg("units", units); + end(); + mgl.glPolygonOffset(factor, units); + checkError(); + } + + public void glPolygonOffsetx(int factor, int units) { + begin("glPolygonOffsetx"); + arg("factor", factor); + arg("units", units); + end(); + + mgl.glPolygonOffsetx(factor, units); + checkError(); + } + + public void glPopMatrix() { + begin("glPopMatrix"); + end(); + + mgl.glPopMatrix(); + checkError(); + } + + public void glPushMatrix() { + begin("glPushMatrix"); + end(); + + mgl.glPushMatrix(); + checkError(); + } + + public void glReadPixels(int x, int y, int width, int height, int format, + int type, Buffer pixels) { + begin("glReadPixels"); + arg("x", x); + arg("y", y); + arg("width", width); + arg("height", height); + arg("format", format); + arg("type", type); + arg("pixels", pixels.toString()); + end(); + + mgl.glReadPixels(x, y, width, height, format, type, pixels); + checkError(); + } + + public void glRotatef(float angle, float x, float y, float z) { + begin("glRotatef"); + arg("angle", angle); + arg("x", x); + arg("y", y); + arg("z", z); + end(); + + mgl.glRotatef(angle, x, y, z); + checkError(); + } + + public void glRotatex(int angle, int x, int y, int z) { + begin("glRotatex"); + arg("angle", angle); + arg("x", x); + arg("y", y); + arg("z", z); + end(); + + mgl.glRotatex(angle, x, y, z); + checkError(); + } + + public void glSampleCoverage(float value, boolean invert) { + begin("glSampleCoveragex"); + arg("value", value); + arg("invert", invert); + end(); + + mgl.glSampleCoverage(value, invert); + checkError(); + } + + public void glSampleCoveragex(int value, boolean invert) { + begin("glSampleCoveragex"); + arg("value", value); + arg("invert", invert); + end(); + + mgl.glSampleCoveragex(value, invert); + checkError(); + } + + public void glScalef(float x, float y, float z) { + begin("glScalef"); + arg("x", x); + arg("y", y); + arg("z", z); + end(); + + mgl.glScalef(x, y, z); + checkError(); + } + + public void glScalex(int x, int y, int z) { + begin("glScalex"); + arg("x", x); + arg("y", y); + arg("z", z); + end(); + + mgl.glScalex(x, y, z); + checkError(); + } + + public void glScissor(int x, int y, int width, int height) { + begin("glScissor"); + arg("x", x); + arg("y", y); + arg("width", width); + arg("height", height); + end(); + + mgl.glScissor(x, y, width, height); + checkError(); + } + + public void glShadeModel(int mode) { + begin("glShadeModel"); + arg("mode", getShadeModel(mode)); + end(); + + mgl.glShadeModel(mode); + checkError(); + } + + public void glStencilFunc(int func, int ref, int mask) { + begin("glStencilFunc"); + arg("func", func); + arg("ref", ref); + arg("mask", mask); + end(); + + mgl.glStencilFunc(func, ref, mask); + checkError(); + } + + public void glStencilMask(int mask) { + begin("glStencilMask"); + arg("mask", mask); + end(); + + mgl.glStencilMask(mask); + checkError(); + } + + public void glStencilOp(int fail, int zfail, int zpass) { + begin("glStencilOp"); + arg("fail", fail); + arg("zfail", zfail); + arg("zpass", zpass); + end(); + + mgl.glStencilOp(fail, zfail, zpass); + checkError(); + } + + public void glTexCoordPointer(int size, int type, int stride, Buffer pointer) { + begin("glTexCoordPointer"); + argPointer(size, type, stride, pointer); + end(); + mTexCoordPointer = new PointerInfo(size, type, stride, pointer); + + mgl.glTexCoordPointer(size, type, stride, pointer); + checkError(); + } + + public void glTexEnvf(int target, int pname, float param) { + begin("glTexEnvf"); + arg("target", getTextureEnvTarget(target)); + arg("pname", getTextureEnvPName(pname)); + arg("param", getTextureEnvParamName(param)); + end(); + + mgl.glTexEnvf(target, pname, param); + checkError(); + } + + public void glTexEnvfv(int target, int pname, float[] params, int offset) { + begin("glTexEnvfv"); + arg("target", getTextureEnvTarget(target)); + arg("pname", getTextureEnvPName(pname)); + arg("params", getTextureEnvParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glTexEnvfv(target, pname, params, offset); + checkError(); + } + + public void glTexEnvfv(int target, int pname, FloatBuffer params) { + begin("glTexEnvfv"); + arg("target", getTextureEnvTarget(target)); + arg("pname", getTextureEnvPName(pname)); + arg("params", getTextureEnvParamCount(pname), params); + end(); + + mgl.glTexEnvfv(target, pname, params); + checkError(); + } + + public void glTexEnvx(int target, int pname, int param) { + begin("glTexEnvx"); + arg("target", getTextureEnvTarget(target)); + arg("pname", getTextureEnvPName(pname)); + arg("param", param); + end(); + + mgl.glTexEnvx(target, pname, param); + checkError(); + } + + public void glTexEnvxv(int target, int pname, int[] params, int offset) { + begin("glTexEnvxv"); + arg("target", getTextureEnvTarget(target)); + arg("pname", getTextureEnvPName(pname)); + arg("params", getTextureEnvParamCount(pname), params, offset); + arg("offset", offset); + end(); + + mgl.glTexEnvxv(target, pname, params, offset); + checkError(); + } + + public void glTexEnvxv(int target, int pname, IntBuffer params) { + begin("glTexEnvxv"); + arg("target", getTextureEnvTarget(target)); + arg("pname", getTextureEnvPName(pname)); + arg("params", getTextureEnvParamCount(pname), params); + end(); + + mgl.glTexEnvxv(target, pname, params); + checkError(); + } + + public void glTexImage2D(int target, int level, int internalformat, + int width, int height, int border, int format, int type, + Buffer pixels) { + begin("glTexImage2D"); + arg("target", target); + arg("level", level); + arg("internalformat", internalformat); + arg("width", width); + arg("height", height); + arg("border", border); + arg("format", format); + arg("type", type); + arg("pixels", pixels.toString()); + end(); + + mgl.glTexImage2D(target, level, internalformat, width, height, border, + format, type, pixels); + checkError(); + } + + public void glTexParameterf(int target, int pname, float param) { + begin("glTexParameterf"); + arg("target", getTextureTarget(target)); + arg("pname", getTexturePName(pname)); + arg("param", getTextureParamName(param)); + end(); + + mgl.glTexParameterf(target, pname, param); + checkError(); + } + + public void glTexParameterx(int target, int pname, int param) { + begin("glTexParameterx"); + arg("target", getTextureTarget(target)); + arg("pname", getTexturePName(pname)); + arg("param", param); + end(); + + mgl.glTexParameterx(target, pname, param); + checkError(); + } + + public void glTexParameteriv(int target, int pname, int[] params, int offset) { + begin("glTexParameteriv"); + arg("target", getTextureTarget(target)); + arg("pname", getTexturePName(pname)); + arg("params", 4, params, offset); + end(); + + mgl11.glTexParameteriv(target, pname, params, offset); + checkError(); + } + + public void glTexParameteriv(int target, int pname, IntBuffer params) { + begin("glTexParameteriv"); + arg("target", getTextureTarget(target)); + arg("pname", getTexturePName(pname)); + arg("params", 4, params); + end(); + + mgl11.glTexParameteriv(target, pname, params); + checkError(); + } + + public void glTexSubImage2D(int target, int level, int xoffset, + int yoffset, int width, int height, int format, int type, + Buffer pixels) { + begin("glTexSubImage2D"); + arg("target", getTextureTarget(target)); + arg("level", level); + arg("xoffset", xoffset); + arg("yoffset", yoffset); + arg("width", width); + arg("height", height); + arg("format", format); + arg("type", type); + arg("pixels", pixels.toString()); + end(); + mgl.glTexSubImage2D(target, level, xoffset, yoffset, width, height, + format, type, pixels); + checkError(); + } + + public void glTranslatef(float x, float y, float z) { + begin("glTranslatef"); + arg("x", x); + arg("y", y); + arg("z", z); + end(); + mgl.glTranslatef(x, y, z); + checkError(); + } + + public void glTranslatex(int x, int y, int z) { + begin("glTranslatex"); + arg("x", x); + arg("y", y); + arg("z", z); + end(); + mgl.glTranslatex(x, y, z); + checkError(); + } + + public void glVertexPointer(int size, int type, int stride, Buffer pointer) { + begin("glVertexPointer"); + argPointer(size, type, stride, pointer); + end(); + mVertexPointer = new PointerInfo(size, type, stride, pointer); + mgl.glVertexPointer(size, type, stride, pointer); + checkError(); + } + + public void glViewport(int x, int y, int width, int height) { + begin("glViewport"); + arg("x", x); + arg("y", y); + arg("width", width); + arg("height", height); + end(); + mgl.glViewport(x, y, width, height); + checkError(); + } + + public void glClipPlanef(int plane, float[] equation, int offset) { + begin("glClipPlanef"); + arg("plane", plane); + arg("equation", 4, equation, offset); + arg("offset", offset); + end(); + mgl11.glClipPlanef(plane, equation, offset); + checkError(); + } + + public void glClipPlanef(int plane, FloatBuffer equation) { + begin("glClipPlanef"); + arg("plane", plane); + arg("equation", 4, equation); + end(); + mgl11.glClipPlanef(plane, equation); + checkError(); + } + + public void glClipPlanex(int plane, int[] equation, int offset) { + begin("glClipPlanex"); + arg("plane", plane); + arg("equation", 4, equation, offset); + arg("offset", offset); + end(); + mgl11.glClipPlanex(plane, equation, offset); + checkError(); + } + + public void glClipPlanex(int plane, IntBuffer equation) { + begin("glClipPlanef"); + arg("plane", plane); + arg("equation", 4, equation); + end(); + mgl11.glClipPlanex(plane, equation); + checkError(); + } + + // Draw Texture Extension + + public void glDrawTexfOES(float x, float y, float z, + float width, float height) { + begin("glDrawTexfOES"); + arg("x", x); + arg("y", y); + arg("z", z); + arg("width", width); + arg("height", height); + end(); + mgl11Ext.glDrawTexfOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexfvOES(float[] coords, int offset) { + begin("glDrawTexfvOES"); + arg("coords", 5, coords, offset); + arg("offset", offset); + end(); + mgl11Ext.glDrawTexfvOES(coords, offset); + checkError(); + } + + public void glDrawTexfvOES(FloatBuffer coords) { + begin("glDrawTexfvOES"); + arg("coords", 5, coords); + end(); + mgl11Ext.glDrawTexfvOES(coords); + checkError(); + } + + public void glDrawTexiOES(int x, int y, int z, int width, int height) { + begin("glDrawTexiOES"); + arg("x", x); + arg("y", y); + arg("z", z); + arg("width", width); + arg("height", height); + end(); + mgl11Ext.glDrawTexiOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexivOES(int[] coords, int offset) { + begin("glDrawTexivOES"); + arg("coords", 5, coords, offset); + arg("offset", offset); + end(); + mgl11Ext.glDrawTexivOES(coords, offset); + checkError(); + } + + public void glDrawTexivOES(IntBuffer coords) { + begin("glDrawTexivOES"); + arg("coords", 5, coords); + end(); + mgl11Ext.glDrawTexivOES(coords); + checkError(); + } + + public void glDrawTexsOES(short x, short y, short z, + short width, short height) { + begin("glDrawTexsOES"); + arg("x", x); + arg("y", y); + arg("z", z); + arg("width", width); + arg("height", height); + end(); + mgl11Ext.glDrawTexsOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexsvOES(short[] coords, int offset) { + begin("glDrawTexsvOES"); + arg("coords", 5, coords, offset); + arg("offset", offset); + end(); + mgl11Ext.glDrawTexsvOES(coords, offset); + checkError(); + } + + public void glDrawTexsvOES(ShortBuffer coords) { + begin("glDrawTexsvOES"); + arg("coords", 5, coords); + end(); + mgl11Ext.glDrawTexsvOES(coords); + checkError(); + } + + public void glDrawTexxOES(int x, int y, int z, int width, int height) { + begin("glDrawTexxOES"); + arg("x", x); + arg("y", y); + arg("z", z); + arg("width", width); + arg("height", height); + end(); + mgl11Ext.glDrawTexxOES(x, y, z, width, height); + checkError(); + } + + public void glDrawTexxvOES(int[] coords, int offset) { + begin("glDrawTexxvOES"); + arg("coords", 5, coords, offset); + arg("offset", offset); + end(); + mgl11Ext.glDrawTexxvOES(coords, offset); + checkError(); + } + + public void glDrawTexxvOES(IntBuffer coords) { + begin("glDrawTexxvOES"); + arg("coords", 5, coords); + end(); + mgl11Ext.glDrawTexxvOES(coords); + checkError(); + } + + public int glQueryMatrixxOES(int[] mantissa, int mantissaOffset, + int[] exponent, int exponentOffset) { + begin("glQueryMatrixxOES"); + arg("mantissa", Arrays.toString(mantissa)); + arg("exponent", Arrays.toString(exponent)); + end(); + int valid = mgl10Ext.glQueryMatrixxOES(mantissa, mantissaOffset, + exponent, exponentOffset); + returns(toString(16, FORMAT_FIXED, mantissa, mantissaOffset)); + returns(toString(16, FORMAT_INT, exponent, exponentOffset)); + checkError(); + return valid; + } + + public int glQueryMatrixxOES(IntBuffer mantissa, IntBuffer exponent) { + begin("glQueryMatrixxOES"); + arg("mantissa", mantissa.toString()); + arg("exponent", exponent.toString()); + end(); + int valid = mgl10Ext.glQueryMatrixxOES(mantissa, exponent); + returns(toString(16, FORMAT_FIXED, mantissa)); + returns(toString(16, FORMAT_INT, exponent)); + checkError(); + return valid; + } + + // Unsupported GL11 methods + + public void glBindBuffer(int target, int buffer) { + throw new UnsupportedOperationException(); + } + + public void glBufferData(int target, int size, Buffer data, int usage) { + throw new UnsupportedOperationException(); + } + + public void glBufferSubData(int target, int offset, int size, Buffer data) { + throw new UnsupportedOperationException(); + } + + public void glColor4ub(byte red, byte green, byte blue, byte alpha) { + throw new UnsupportedOperationException(); + } + + public void glDeleteBuffers(int n, int[] buffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glDeleteBuffers(int n, IntBuffer buffers) { + throw new UnsupportedOperationException(); + } + + public void glGenBuffers(int n, int[] buffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGenBuffers(int n, IntBuffer buffers) { + throw new UnsupportedOperationException(); + } + + public void glGetBooleanv(int pname, boolean[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetBooleanv(int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetBufferParameteriv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetBufferParameteriv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanef(int pname, float[] eqn, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanef(int pname, FloatBuffer eqn) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanex(int pname, int[] eqn, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanex(int pname, IntBuffer eqn) { + throw new UnsupportedOperationException(); + } + + public void glGetFixedv(int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetFixedv(int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetFloatv(int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetFloatv(int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetLightfv(int light, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetLightfv(int light, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetLightxv(int light, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetLightxv(int light, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialfv(int face, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialfv(int face, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialxv(int face, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialxv(int face, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnviv(int env, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnviv(int env, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnvxv(int env, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnvxv(int env, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterfv(int target, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterfv(int target, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameteriv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameteriv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterxv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterxv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public boolean glIsBuffer(int buffer) { + throw new UnsupportedOperationException(); + } + + public boolean glIsEnabled(int cap) { + throw new UnsupportedOperationException(); + } + + public boolean glIsTexture(int texture) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterf(int pname, float param) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterfv(int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterfv(int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterx(int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterxv(int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterxv(int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glPointSizePointerOES(int type, int stride, Buffer pointer) { + throw new UnsupportedOperationException(); + } + + public void glTexEnvi(int target, int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glTexEnviv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexEnviv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterfv(int target, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterfv(int target, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glTexParameteri(int target, int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterxv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterxv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + private class PointerInfo { + /** + * The number of coordinates per vertex. 1..4 + */ + public int mSize; + /** + * The type of each coordinate. + */ + public int mType; + /** + * The byte offset between consecutive vertices. 0 means mSize * + * sizeof(mType) + */ + public int mStride; + public Buffer mPointer; + public ByteBuffer mTempByteBuffer; // Only valid during glDrawXXX calls + + public PointerInfo(int size, int type, int stride, Buffer pointer) { + mSize = size; + mType = type; + mStride = stride; + mPointer = pointer; + } + + public int sizeof(int type) { + switch (type) { + case GL_UNSIGNED_BYTE: + return 1; + case GL_BYTE: + return 1; + case GL_SHORT: + return 2; + case GL_FIXED: + return 4; + case GL_FLOAT: + return 4; + default: + return 0; + } + } + + public int getStride() { + return mStride > 0 ? mStride : sizeof(mType) * mSize; + } + + public void bindByteBuffer() { + mTempByteBuffer = toByteBuffer(-1, mPointer); + } + + public void unbindByteBuffer() { + mTempByteBuffer = null; + } + } + + private Writer mLog; + private boolean mLogArgumentNames; + private int mArgCount; + + private PointerInfo mColorPointer; + private PointerInfo mNormalPointer; + private PointerInfo mTexCoordPointer; + private PointerInfo mVertexPointer; + + boolean mColorArrayEnabled; + boolean mNormalArrayEnabled; + boolean mTextureCoordArrayEnabled; + boolean mVertexArrayEnabled; + + StringBuilder mStringBuilder; +} diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java new file mode 100644 index 00000000000..42c53f9ed45 --- /dev/null +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -0,0 +1,661 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; +import javax.microedition.khronos.opengles.GL; +import javax.microedition.khronos.opengles.GL10; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +/** + * An implementation of SurfaceView that uses the dedicated surface for + * displaying an OpenGL animation. This allows the animation to run in a + * separate thread, without requiring that it be driven by the update mechanism + * of the view hierarchy. + * + * The application-specific rendering code is delegated to a GLView.Renderer + * instance. + */ +public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { + public final static int RENDERMODE_WHEN_DIRTY = 0; + public final static int RENDERMODE_CONTUOUSLY = 1; + + /** + * Check glError() after every GL call. + */ + public final static int DEBUG_CHECK_GL_ERROR = 1; + + /** + * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". + */ + public final static int DEBUG_LOG_GL_CALLS = 2; + + public GLSurfaceView(Context context) { + super(context); + init(); + } + + public GLSurfaceView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + // Install a SurfaceHolder.Callback so we get notified when the + // underlying surface is created and destroyed + SurfaceHolder holder = getHolder(); + holder.addCallback(this); + holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); + } + + /** + * Set the glWrapper to a new value. The current glWrapper is used + * whenever a surface is created. The default value is null. + * @param glWrapper the new GLWrapper + */ + public void setGLWrapper(GLWrapper glWrapper) { + mGLWrapper = glWrapper; + } + + /** + * Set the debug flags to a new value. The debug flags take effect + * whenever a surface is created. The default value is zero. + * @param debugFlags the new debug flags + * @see #DEBUG_CHECK_GL_ERROR + * @see #DEBUG_LOG_GL_CALLS + */ + public void setDebugFlags(int debugFlags) { + mDebugFlags = debugFlags; + } + + public int getDebugFlags() { + return mDebugFlags; + } + + /** + * Set the renderer associated with this view. Can only be called once. + * @param renderer + */ + public void setRenderer(Renderer renderer) { + if (mGLThread != null) { + throw new IllegalStateException("setRenderer has already been called for this instance."); + } + mGLThread = new GLThread(renderer); + mGLThread.start(); + } + + /** + * Set the rendering mode. When the renderMode is + * RENDERMODE_CONTINUOUSLY, the renderer is called + * repeatedly to re-render the scene. When the rendermode + * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface + * is created, or when requestRender is called. Defaults to RENDERMODE_CONTINUOUSLY. + * @param renderMode one of the RENDERMODE_X constants + */ + public void setRenderMode(int renderMode) { + mGLThread.setRenderMode(renderMode); + } + + /** + * Get the current rendering mode. May be called + * from any thread. Must not be called before a renderer has been set. + * @return true if the renderer will render continuously. + */ + public int getRenderMode() { + return mGLThread.getRenderMode(); + } + + /** + * Request that the renderer render a frame. May be called + * from any thread. Must not be called before a renderer has been set. + * This method is typically used when the render mode has been set to + * false, so that frames are only rendered on demand. + */ + public void requestRender() { + mGLThread.requestRender(); + } + + public void surfaceCreated(SurfaceHolder holder) { + mGLThread.surfaceCreated(); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + // Surface will be destroyed when we return + mGLThread.surfaceDestroyed(); + } + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + mGLThread.onWindowResize(w, h); + } + + /** + * Inform the view that the activity is paused. The owner of this view must + * call this method when the activity is paused. + */ + public void onPause() { + mGLThread.onPause(); + } + + /** + * Inform the view that the activity is resumed. The owner of this view must + * call this method when the activity is resumed. + */ + public void onResume() { + mGLThread.onResume(); + } + + /** + * Queue an "event" to be run on the GL rendering thread. + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + mGLThread.queueEvent(r); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mGLThread.requestExitAndWait(); + } + + // ---------------------------------------------------------------------- + + public interface GLWrapper { + GL wrap(GL gl); + } + + // ---------------------------------------------------------------------- + + /** + * A generic renderer interface. + */ + public interface Renderer { + /** + * @return the EGL configuration specification desired by the renderer. + */ + int[] getConfigSpec(); + + /** + * Surface created. + * Called when the surface is created. Called when the application + * starts, and whenever the GPU is reinitialized. This will + * typically happen when the device awakes after going to sleep. + * Set your textures here. + * @param gl the GL interface. Use <code>instanceof</code> to + * test if the interface supports GL11 or higher interfaces. + * @param config the EGLConfig of the created surface. Can be used + * to create matching pbuffers. + */ + void onSurfaceCreated(GL10 gl, EGLConfig config); + /** + * Surface changed size. + * Called after the surface is created and whenever + * the OpenGL ES surface size changes. Set your viewport here. + * @param gl the GL interface. Use <code>instanceof</code> to + * test if the interface supports GL11 or higher interfaces. + * @param width + * @param height + */ + void onSurfaceChanged(GL10 gl, int width, int height); + /** + * Draw the current frame. + * @param gl the GL interface. Use <code>instanceof</code> to + * test if the interface supports GL11 or higher interfaces. + */ + void onDrawFrame(GL10 gl); + } + + /** + * An EGL helper class. + */ + + private class EglHelper { + public EglHelper() { + + } + + /** + * Initialize EGL for a given configuration spec. + * @param configSpec + */ + public void start(int[] configSpec){ + /* + * Get an EGL instance + */ + mEgl = (EGL10) EGLContext.getEGL(); + + /* + * Get to the default display. + */ + mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + + /* + * We can now initialize EGL for that display + */ + int[] version = new int[2]; + mEgl.eglInitialize(mEglDisplay, version); + + EGLConfig[] configs = new EGLConfig[1]; + int[] num_config = new int[1]; + mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, + num_config); + mEglConfig = configs[0]; + + /* + * Create an OpenGL ES context. This must be done only once, an + * OpenGL context is a somewhat heavy object. + */ + mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, + EGL10.EGL_NO_CONTEXT, null); + + mEglSurface = null; + } + + /* + * React to the creation of a new surface by creating and returning an + * OpenGL interface that renders to that surface. + */ + public GL createSurface(SurfaceHolder holder) { + /* + * The window size has changed, so we need to create a new + * surface. + */ + if (mEglSurface != null) { + + /* + * Unbind and destroy the old EGL surface, if + * there is one. + */ + mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + } + + /* + * Create an EGL surface we can render into. + */ + mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, + mEglConfig, holder, null); + + /* + * Before we can issue GL commands, we need to make sure + * the context is current and bound to a surface. + */ + mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, + mEglContext); + + + GL gl = mEglContext.getGL(); + if (mGLWrapper != null) { + gl = mGLWrapper.wrap(gl); + } + + if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS))!= 0) { + int configFlags = 0; + Writer log = null; + if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { + configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; + } + if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { + log = new LogWriter(); + } + gl = GLDebugHelper.wrap(gl, configFlags, log); + } + return gl; + } + + /** + * Display the current render surface. + * @return false if the context has been lost. + */ + public boolean swap() { + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + + /* + * Always check for EGL_CONTEXT_LOST, which means the context + * and all associated data were lost (For instance because + * the device went to sleep). We need to sleep until we + * get a new surface. + */ + return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; + } + + public void finish() { + if (mEglSurface != null) { + mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_CONTEXT); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + mEglSurface = null; + } + if (mEglContext != null) { + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEglContext = null; + } + if (mEglDisplay != null) { + mEgl.eglTerminate(mEglDisplay); + mEglDisplay = null; + } + } + + EGL10 mEgl; + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLConfig mEglConfig; + EGLContext mEglContext; + } + + /** + * A generic GL Thread. Takes care of initializing EGL and GL. Delegates + * to a Renderer instance to do the actual drawing. Can be configured to + * render continuously or on request. + * + */ + class GLThread extends Thread { + GLThread(Renderer renderer) { + super(); + mDone = false; + mWidth = 0; + mHeight = 0; + mRequestRender = true; + mRenderMode = RENDERMODE_CONTUOUSLY; + mRenderer = renderer; + setName("GLThread"); + } + + @Override + public void run() { + /* + * When the android framework launches a second instance of + * an activity, the new instance's onCreate() method may be + * called before the first instance returns from onDestroy(). + * + * This semaphore ensures that only one instance at a time + * accesses EGL. + */ + try { + try { + sEglSemaphore.acquire(); + } catch (InterruptedException e) { + return; + } + guardedRun(); + } catch (InterruptedException e) { + // fall thru and exit normally + } finally { + sEglSemaphore.release(); + } + } + + private void guardedRun() throws InterruptedException { + mEglHelper = new EglHelper(); + /* + * Specify a configuration for our opengl session + * and grab the first configuration that matches is + */ + int[] configSpec = mRenderer.getConfigSpec(); + mEglHelper.start(configSpec); + + GL10 gl = null; + boolean tellRendererSurfaceCreated = true; + boolean tellRendererSurfaceChanged = true; + + /* + * This is our main activity thread's loop, we go until + * asked to quit. + */ + while (!mDone) { + + /* + * Update the asynchronous state (window size) + */ + int w, h; + boolean changed; + boolean needStart = false; + synchronized (this) { + Runnable r; + while ((r = getEvent()) != null) { + r.run(); + } + if (mPaused) { + mEglHelper.finish(); + needStart = true; + } + while (needToWait()) { + wait(); + } + if (mDone) { + break; + } + changed = mSizeChanged; + w = mWidth; + h = mHeight; + mSizeChanged = false; + mRequestRender = false; + } + if (needStart) { + mEglHelper.start(configSpec); + tellRendererSurfaceCreated = true; + changed = true; + } + if (changed) { + gl = (GL10) mEglHelper.createSurface(getHolder()); + tellRendererSurfaceChanged = true; + } + if (tellRendererSurfaceCreated) { + mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); + tellRendererSurfaceCreated = false; + } + if (tellRendererSurfaceChanged) { + mRenderer.onSurfaceChanged(gl, w, h); + tellRendererSurfaceChanged = false; + } + if ((w > 0) && (h > 0)) { + /* draw a frame here */ + mRenderer.onDrawFrame(gl); + + /* + * Once we're done with GL, we need to call swapBuffers() + * to instruct the system to display the rendered frame + */ + mEglHelper.swap(); + } + } + + /* + * clean-up everything... + */ + mEglHelper.finish(); + } + + private boolean needToWait() { + if (mDone) { + return false; + } + + if (mPaused || (! mHasSurface)) { + return true; + } + + if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTUOUSLY))) { + return false; + } + + return true; + } + + public void setRenderMode(int renderMode) { + if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTUOUSLY)) ) { + throw new IllegalArgumentException("renderMode"); + } + synchronized(this) { + mRenderMode = renderMode; + if (renderMode == RENDERMODE_CONTUOUSLY) { + notify(); + } + } + } + + public int getRenderMode() { + synchronized(this) { + return mRenderMode; + } + } + + public void requestRender() { + synchronized(this) { + mRequestRender = true; + notify(); + } + } + + public void surfaceCreated() { + synchronized(this) { + mHasSurface = true; + notify(); + } + } + + public void surfaceDestroyed() { + synchronized(this) { + mHasSurface = false; + notify(); + } + } + + public void onPause() { + synchronized (this) { + mPaused = true; + } + } + + public void onResume() { + synchronized (this) { + mPaused = false; + notify(); + } + } + + public void onWindowResize(int w, int h) { + synchronized (this) { + mWidth = w; + mHeight = h; + mSizeChanged = true; + notify(); + } + } + + public void requestExitAndWait() { + // don't call this from GLThread thread or it is a guaranteed + // deadlock! + synchronized(this) { + mDone = true; + notify(); + } + try { + join(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + + /** + * Queue an "event" to be run on the GL rendering thread. + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + synchronized(this) { + mEventQueue.add(r); + } + } + + private Runnable getEvent() { + synchronized(this) { + if (mEventQueue.size() > 0) { + return mEventQueue.remove(0); + } + + } + return null; + } + + private boolean mDone; + private boolean mPaused; + private boolean mHasSurface; + private int mWidth; + private int mHeight; + private int mRenderMode; + private boolean mRequestRender; + private Renderer mRenderer; + private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); + private EglHelper mEglHelper; + } + + static class LogWriter extends Writer { + + @Override public void close() { + flushBuilder(); + } + + @Override public void flush() { + flushBuilder(); + } + + @Override public void write(char[] buf, int offset, int count) { + for(int i = 0; i < count; i++) { + char c = buf[offset + i]; + if ( c == '\n') { + flushBuilder(); + } + else { + mBuilder.append(c); + } + } + } + + private void flushBuilder() { + if (mBuilder.length() > 0) { + Log.v("GLSurfaceView", mBuilder.toString()); + mBuilder.delete(0, mBuilder.length()); + } + } + + private StringBuilder mBuilder = new StringBuilder(); + } + + private static final Semaphore sEglSemaphore = new Semaphore(1); + private boolean mSizeChanged = true; + + private GLThread mGLThread; + private GLWrapper mGLWrapper; + private int mDebugFlags; +} diff --git a/opengl/java/android/opengl/GLU.java b/opengl/java/android/opengl/GLU.java new file mode 100644 index 00000000000..0152f42b0e4 --- /dev/null +++ b/opengl/java/android/opengl/GLU.java @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import javax.microedition.khronos.opengles.GL10; + +/** + * A set of GL utilities inspired by the OpenGL Utility Toolkit. + * + */ + +public class GLU { + + /** + * Return an error string from a GL or GLU error code. + * + * @param error - a GL or GLU error code. + * @return the error string for the input error code, or NULL if the input + * was not a valid GL or GLU error code. + */ + public static String gluErrorString(int error) { + switch (error) { + case GL10.GL_NO_ERROR: + return "no error"; + case GL10.GL_INVALID_ENUM: + return "invalid enum"; + case GL10.GL_INVALID_VALUE: + return "invalid value"; + case GL10.GL_INVALID_OPERATION: + return "invalid operation"; + case GL10.GL_STACK_OVERFLOW: + return "stack overflow"; + case GL10.GL_STACK_UNDERFLOW: + return "stack underflow"; + case GL10.GL_OUT_OF_MEMORY: + return "out of memory"; + default: + return null; + } + } + + /** + * Define a viewing transformation in terms of an eye point, a center of + * view, and an up vector. + * + * @param gl a GL10 interface + * @param eyeX eye point X + * @param eyeY eye point Y + * @param eyeZ eye point Z + * @param centerX center of view X + * @param centerY center of view Y + * @param centerZ center of view Z + * @param upX up vector X + * @param upY up vector Y + * @param upZ up vector Z + */ + public static void gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, + float centerX, float centerY, float centerZ, float upX, float upY, + float upZ) { + + // See the OpenGL GLUT documentation for gluLookAt for a description + // of the algorithm. We implement it in a straightforward way: + + float fx = centerX - eyeX; + float fy = centerY - eyeY; + float fz = centerZ - eyeZ; + + // Normalize f + float rlf = 1.0f / Matrix.length(fx, fy, fz); + fx *= rlf; + fy *= rlf; + fz *= rlf; + + // compute s = f x up (x means "cross product") + float sx = fy * upZ - fz * upY; + float sy = fz * upX - fx * upZ; + float sz = fx * upY - fy * upX; + + // and normalize s + float rls = 1.0f / Matrix.length(sx, sy, sz); + sx *= rls; + sy *= rls; + sz *= rls; + + // compute u = s x f + float ux = sy * fz - sz * fy; + float uy = sz * fx - sx * fz; + float uz = sx * fy - sy * fx; + + float[] m = new float[16]; + m[0] = sx; + m[1] = ux; + m[2] = -fx; + m[3] = 0.0f; + + m[4] = sy; + m[5] = uy; + m[6] = -fy; + m[7] = 0.0f; + + m[8] = sz; + m[9] = uz; + m[10] = -fz; + m[11] = 0.0f; + + m[12] = 0.0f; + m[13] = 0.0f; + m[14] = 0.0f; + m[15] = 1.0f; + + gl.glMultMatrixf(m, 0); + gl.glTranslatef(-eyeX, -eyeY, -eyeZ); + } + + /** + * Set up a 2D orthographic projection matrix + * + * @param gl + * @param left + * @param right + * @param bottom + * @param top + */ + public static void gluOrtho2D(GL10 gl, float left, float right, + float bottom, float top) { + gl.glOrthof(left, right, bottom, top, -1.0f, 1.0f); + } + + /** + * Set up a perspective projection matrix + * + * @param gl a GL10 interface + * @param fovy specifies the field of view angle, in degrees, in the Y + * direction. + * @param aspect specifies the aspect ration that determins the field of + * view in the x direction. The aspect ratio is the ratio of x + * (width) to y (height). + * @param zNear specifies the distance from the viewer to the near clipping + * plane (always positive). + * @param zFar specifies the distance from the viewer to the far clipping + * plane (always positive). + */ + public static void gluPerspective(GL10 gl, float fovy, float aspect, + float zNear, float zFar) { + float top = zNear * (float) Math.tan(fovy * (Math.PI / 360.0)); + float bottom = -top; + float left = bottom * aspect; + float right = top * aspect; + gl.glFrustumf(left, right, bottom, top, zNear, zFar); + } + + /** + * Map object coordinates into window coordinates. gluProject transforms the + * specified object coordinates into window coordinates using model, proj, + * and view. The result is stored in win. + * <p> + * Note that you can use the OES_matrix_get extension, if present, to get + * the current modelView and projection matrices. + * + * @param objX object coordinates X + * @param objY object coordinates Y + * @param objZ object coordinates Z + * @param model the current modelview matrix + * @param modelOffset the offset into the model array where the modelview + * maxtrix data starts. + * @param project the current projection matrix + * @param projectOffset the offset into the project array where the project + * matrix data starts. + * @param view the current view, {x, y, width, height} + * @param viewOffset the offset into the view array where the view vector + * data starts. + * @param win the output vector {winX, winY, winZ}, that returns the + * computed window coordinates. + * @param winOffset the offset into the win array where the win vector data + * starts. + * @return A return value of GL_TRUE indicates success, a return value of + * GL_FALSE indicates failure. + */ + public static int gluProject(float objX, float objY, float objZ, + float[] model, int modelOffset, float[] project, int projectOffset, + int[] view, int viewOffset, float[] win, int winOffset) { + float[] m = new float[16]; + Matrix.multiplyMM(m, 0, project, projectOffset, model, modelOffset); + + float[] v = new float[4]; + + v[0] = objX; + v[1] = objY; + v[2] = objZ; + v[3] = 1.0f; + + float[] v2 = new float[4]; + + Matrix.multiplyMV(v2, 0, m, 0, v, 0); + + float w = v2[3]; + if (w == 0.0f) { + return GL10.GL_FALSE; + } + + float rw = 1.0f / w; + + win[winOffset] = + view[viewOffset] + view[viewOffset + 2] * (v2[0] * rw + 1.0f) + * 0.5f; + win[winOffset + 1] = + view[viewOffset + 1] + view[viewOffset + 3] + * (v2[1] * rw + 1.0f) * 0.5f; + win[winOffset + 2] = (v2[2] * rw + 1.0f) * 0.5f; + + return GL10.GL_TRUE; + } + + /** + * Map window coordinates to object coordinates. gluUnProject maps the + * specified window coordinates into object coordinates using model, proj, + * and view. The result is stored in obj. + * <p> + * Note that you can use the OES_matrix_get extension, if present, to get + * the current modelView and projection matrices. + * + * @param winX window coordinates X + * @param winY window coordinates Y + * @param winZ window coordinates Z + * @param model the current modelview matrix + * @param modelOffset the offset into the model array where the modelview + * maxtrix data starts. + * @param project the current projection matrix + * @param projectOffset the offset into the project array where the project + * matrix data starts. + * @param view the current view, {x, y, width, height} + * @param viewOffset the offset into the view array where the view vector + * data starts. + * @param obj the output vector {objX, objY, objZ}, that returns the + * computed object coordinates. + * @param objOffset the offset into the obj array where the obj vector data + * starts. + * @return A return value of GL10.GL_TRUE indicates success, a return value + * of GL10.GL_FALSE indicates failure. + */ + public static int gluUnProject(float winX, float winY, float winZ, + float[] model, int modelOffset, float[] project, int projectOffset, + int[] view, int viewOffset, float[] obj, int objOffset) { + float[] pm = new float[16]; + Matrix.multiplyMM(pm, 0, project, projectOffset, model, modelOffset); + + float[] invPM = new float[16]; + if (!Matrix.invertM(invPM, 0, pm, 0)) { + return GL10.GL_FALSE; + } + + float[] v = new float[4]; + + v[0] = + 2.0f * (winX - view[viewOffset + 0]) / view[viewOffset + 2] + - 1.0f; + v[1] = + 2.0f * (winY - view[viewOffset + 1]) / view[viewOffset + 3] + - 1.0f; + v[2] = 2.0f * winZ - 1.0f; + v[3] = 1.0f; + + float[] v2 = new float[4]; + + Matrix.multiplyMV(v2, 0, invPM, 0, v, 0); + + obj[objOffset] = v2[0]; + obj[objOffset + 1] = v2[1]; + obj[objOffset + 2] = v2[2]; + + return GL10.GL_TRUE; + } + + } diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java new file mode 100644 index 00000000000..df6c557c816 --- /dev/null +++ b/opengl/java/android/opengl/GLUtils.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import javax.microedition.khronos.opengles.GL10; +import android.graphics.Bitmap; + +/** + * + * Utility class to help bridging OpenGL ES and Android APIs. + * + */ + +public final class GLUtils { + + /* + * We use a class initializer to allow the native code to cache some + * field offsets. + */ + static { + nativeClassInit(); + } + + private GLUtils() { + } + + /** + * return the internal format as defined by OpenGL ES of the supplied bitmap. + * + * @param bitmap + * @return the internal format of the bitmap. + */ + public static int getInternalFormat(Bitmap bitmap) { + if (bitmap == null) { + throw new NullPointerException("getInternalFormat can't be used with a null Bitmap"); + } + switch (bitmap.getConfig()) { + case ALPHA_8: + return GL10.GL_ALPHA; + case ARGB_4444: + case ARGB_8888: + return GL10.GL_RGBA; + case RGB_565: + return GL10.GL_RGB; + } + throw new IllegalArgumentException("Unknown internalformat"); + } + + /** + * Return the type as defined by OpenGL ES of the supplied bitmap. + */ + public static int getType(Bitmap bitmap) { + if (bitmap == null) { + throw new NullPointerException("getType can't be used with a null Bitmap"); + } + int type; + switch(bitmap.getConfig()) { + case ARGB_4444: + type = GL10.GL_UNSIGNED_SHORT_4_4_4_4; + break; + case RGB_565: + type = GL10.GL_UNSIGNED_SHORT_5_6_5; + break; + case ALPHA_8: + case ARGB_8888: + default: + type = GL10.GL_UNSIGNED_BYTE; + break; + } + return type; + } + + /** + * Calls glTexImage2D() on the current OpenGL context. If no context is + * current the behavior is the same as calling glTexImage2D() with no + * current context, that is, eglGetError() will return the appropriate + * error. + * Unlike glTexImage2D() bitmap cannot be null and will raise an exception + * in that case. + * All other parameters are identical to those used for glTexImage2D(). + * + * NOTE: this method doesn't change GL_UNPACK_ALIGNMENT, you must make + * sure to set it properly according to the supplied bitmap. + * + * Whether or not bitmap can have non power of two dimensions depends on + * the current OpenGL context. Always check glGetError() some time + * after calling this method, just like when using OpenGL directly. + * + * @param target + * @param level + * @param internalformat + * @param bitmap + * @param border + */ + public static void texImage2D(int target, int level, int internalformat, + Bitmap bitmap, int border) { + if (bitmap == null) { + throw new NullPointerException("texImage2D can't be used with a null Bitmap"); + } + int type = getType(bitmap); + if (native_texImage2D(target, level, internalformat, bitmap, type, border)!=0) { + throw new IllegalArgumentException("invalid Bitmap format"); + } + } + + /** + * A version of texImage2D() that takes an explicit type parameter + * as defined by the OpenGL ES specification. + * + * @param target + * @param level + * @param internalformat + * @param bitmap + * @param type + * @param border + */ + public static void texImage2D(int target, int level, int internalformat, + Bitmap bitmap, int type, int border) { + if (bitmap == null) { + throw new NullPointerException("texImage2D can't be used with a null Bitmap"); + } + if (native_texImage2D(target, level, internalformat, bitmap, type, border)!=0) { + throw new IllegalArgumentException("invalid Bitmap format"); + } + } + + /** + * A version of texImage2D that determines the internalFormat automatically. + * + * @param target + * @param level + * @param bitmap + * @param border + */ + public static void texImage2D(int target, int level, Bitmap bitmap, + int border) { + if (bitmap == null) { + throw new NullPointerException("texImage2D can't be used with a null Bitmap"); + } + int type = getType(bitmap); + if (native_texImage2D(target, level, -1, bitmap, type, border)!=0) { + throw new IllegalArgumentException("invalid Bitmap format"); + } + } + + /** + * Calls glTexSubImage2D() on the current OpenGL context. If no context is + * current the behavior is the same as calling glTexSubImage2D() with no + * current context, that is, eglGetError() will return the appropriate + * error. + * Unlike glTexSubImage2D() bitmap cannot be null and will raise an exception + * in that case. + * All other parameters are identical to those used for glTexSubImage2D(). + * + * NOTE: this method doesn't change GL_UNPACK_ALIGNMENT, you must make + * sure to set it properly according to the supplied bitmap. + * + * Whether or not bitmap can have non power of two dimensions depends on + * the current OpenGL context. Always check glGetError() some time + * after calling this method, just like when using OpenGL directly. + * + * @param target + * @param level + * @param xoffset + * @param yoffset + * @param bitmap + */ + public static void texSubImage2D(int target, int level, int xoffset, int yoffset, + Bitmap bitmap) { + if (bitmap == null) { + throw new NullPointerException("texSubImage2D can't be used with a null Bitmap"); + } + int type = getType(bitmap); + if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, -1, type)!=0) { + throw new IllegalArgumentException("invalid Bitmap format"); + } + } + + /** + * A version of texSubImage2D() that takes an explicit type parameter + * as defined by the OpenGL ES specification. + * + * @param target + * @param level + * @param xoffset + * @param yoffset + * @param bitmap + * @param type + */ + public static void texSubImage2D(int target, int level, int xoffset, int yoffset, + Bitmap bitmap, int format, int type) { + if (bitmap == null) { + throw new NullPointerException("texSubImage2D can't be used with a null Bitmap"); + } + if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, format, type)!=0) { + throw new IllegalArgumentException("invalid Bitmap format"); + } + } + + native private static void nativeClassInit(); + + native private static int native_texImage2D(int target, int level, int internalformat, + Bitmap bitmap, int type, int border); + native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset, + Bitmap bitmap, int format, int type); +} diff --git a/opengl/java/android/opengl/GLWrapperBase.java b/opengl/java/android/opengl/GLWrapperBase.java new file mode 100644 index 00000000000..067f95fce1a --- /dev/null +++ b/opengl/java/android/opengl/GLWrapperBase.java @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import javax.microedition.khronos.opengles.GL; +import javax.microedition.khronos.opengles.GL10; +import javax.microedition.khronos.opengles.GL10Ext; +import javax.microedition.khronos.opengles.GL11; +import javax.microedition.khronos.opengles.GL11Ext; +import javax.microedition.khronos.opengles.GL11ExtensionPack; + +/** + * The abstract base class for a GL wrapper. Provides + * some convenient instance variables and default implementations. + */ +abstract class GLWrapperBase + implements GL, GL10, GL10Ext, GL11, GL11Ext { + public GLWrapperBase(GL gl) { + mgl = (GL10) gl; + if (gl instanceof GL10Ext) { + mgl10Ext = (GL10Ext) gl; + } + if (gl instanceof GL11) { + mgl11 = (GL11) gl; + } + if (gl instanceof GL11Ext) { + mgl11Ext = (GL11Ext) gl; + } + if (gl instanceof GL11ExtensionPack) { + mgl11ExtensionPack = (GL11ExtensionPack) gl; + } + } + + protected GL10 mgl; + protected GL10Ext mgl10Ext; + protected GL11 mgl11; + protected GL11Ext mgl11Ext; + protected GL11ExtensionPack mgl11ExtensionPack; + + // Unsupported GL11 methods + + public void glGetPointerv(int pname, java.nio.Buffer[] params) { + throw new UnsupportedOperationException(); + } + + // VBO versions of *Pointer and *Elements methods + public void glColorPointer(int size, int type, int stride, int offset) { + throw new UnsupportedOperationException(); + } + + public void glNormalPointer(int type, int stride, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexCoordPointer(int size, int type, int stride, int offset) { + throw new UnsupportedOperationException(); + } + + public void glVertexPointer(int size, int type, int stride, int offset) { + throw new UnsupportedOperationException(); + } + + public void glDrawElements(int mode, int count, int type, int offset) { + throw new UnsupportedOperationException(); + } + + public void glBindBuffer(int target, int buffer) { + throw new UnsupportedOperationException(); + } + + public void glBufferData(int target, int size, Buffer data, int usage) { + throw new UnsupportedOperationException(); + } + + public void glBufferSubData(int target, int offset, int size, Buffer data) { + throw new UnsupportedOperationException(); + } + + public void glColor4ub(byte red, byte green, byte blue, byte alpha) { + throw new UnsupportedOperationException(); + } + + public void glDeleteBuffers(int n, int[] buffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glDeleteBuffers(int n, IntBuffer buffers) { + throw new UnsupportedOperationException(); + } + + public void glGenBuffers(int n, int[] buffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGenBuffers(int n, IntBuffer buffers) { + throw new UnsupportedOperationException(); + } + + public void glGetBooleanv(int pname, boolean[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetBooleanv(int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetBufferParameteriv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetBufferParameteriv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanef(int pname, float[] eqn, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanef(int pname, FloatBuffer eqn) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanex(int pname, int[] eqn, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetClipPlanex(int pname, IntBuffer eqn) { + throw new UnsupportedOperationException(); + } + + public void glGetFixedv(int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetFixedv(int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetFloatv(int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetFloatv(int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetLightfv(int light, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetLightfv(int light, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetLightxv(int light, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetLightxv(int light, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialfv(int face, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialfv(int face, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialxv(int face, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetMaterialxv(int face, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnviv(int env, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnviv(int env, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnvxv(int env, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexEnvxv(int env, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterfv(int target, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterfv(int target, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameteriv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameteriv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterxv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexParameterxv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public boolean glIsBuffer(int buffer) { + throw new UnsupportedOperationException(); + } + + public boolean glIsEnabled(int cap) { + throw new UnsupportedOperationException(); + } + + public boolean glIsTexture(int texture) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterf(int pname, float param) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterfv(int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterfv(int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterx(int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterxv(int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glPointParameterxv(int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glPointSizePointerOES(int type, int stride, Buffer pointer) { + throw new UnsupportedOperationException(); + } + + public void glTexEnvi(int target, int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glTexEnviv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexEnviv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterfv(int target, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterfv(int target, int pname, FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glTexParameteri(int target, int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterxv(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexParameterxv(int target, int pname, IntBuffer params) { + throw new UnsupportedOperationException(); + } + + // Unsupported GL11Ext methods + + public void glCurrentPaletteMatrixOES(int matrixpaletteindex) { + throw new UnsupportedOperationException(); + } + + public void glLoadPaletteFromModelViewMatrixOES() { + throw new UnsupportedOperationException(); + } + + public void glMatrixIndexPointerOES(int size, int type, int stride, Buffer pointer) { + throw new UnsupportedOperationException(); + } + + public void glMatrixIndexPointerOES(int size, int type, int stride, int offset) { + throw new UnsupportedOperationException(); + } + + public void glWeightPointerOES(int size, int type, int stride, Buffer pointer) { + throw new UnsupportedOperationException(); + } + + public void glWeightPointerOES(int size, int type, int stride, int offset) { + throw new UnsupportedOperationException(); + } + + // Unsupported GL11ExtensionPack methods + + public void glBindFramebufferOES(int target, int framebuffer) { + throw new UnsupportedOperationException(); + } + + public void glBindRenderbufferOES(int target, int renderbuffer) { + throw new UnsupportedOperationException(); + } + + public void glBlendEquation(int mode) { + throw new UnsupportedOperationException(); + } + + public void glBlendEquationSeparate(int modeRGB, int modeAlpha) { + throw new UnsupportedOperationException(); + } + + public void glBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { + throw new UnsupportedOperationException(); + } + + int glCheckFramebufferStatusOES(int target) { + throw new UnsupportedOperationException(); + } + + public void glCompressedTexImage2D(int target, int level, int internalformat, int width, int height, int border, int imageSize) { + throw new UnsupportedOperationException(); + } + + public void glDeleteFramebuffersOES(int n, int[] framebuffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glDeleteFramebuffersOES(int n, java.nio.IntBuffer framebuffers) { + throw new UnsupportedOperationException(); + } + + public void glDeleteRenderbuffersOES(int n, int[] renderbuffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glDeleteRenderbuffersOES(int n, java.nio.IntBuffer renderbuffers) { + throw new UnsupportedOperationException(); + } + + public void glFramebufferRenderbufferOES(int target, int attachment, int renderbuffertarget, int renderbuffer) { + throw new UnsupportedOperationException(); + } + + public void glFramebufferTexture2DOES(int target, int attachment, int textarget, int texture, int level) { + throw new UnsupportedOperationException(); + } + + public void glGenerateMipmapOES(int target) { + throw new UnsupportedOperationException(); + } + + public void glGenFramebuffersOES(int n, int[] framebuffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGenFramebuffersOES(int n, java.nio.IntBuffer framebuffers) { + throw new UnsupportedOperationException(); + } + + public void glGenRenderbuffersOES(int n, int[] renderbuffers, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGenRenderbuffersOES(int n, java.nio.IntBuffer renderbuffers) { + throw new UnsupportedOperationException(); + } + + public void glGetFramebufferAttachmentParameterivOES(int target, int attachment, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetFramebufferAttachmentParameterivOES(int target, int attachment, int pname, java.nio.IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetRenderbufferParameterivOES(int target, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetRenderbufferParameterivOES(int target, int pname, java.nio.IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexGenfv(int coord, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexGenfv(int coord, int pname, java.nio.FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexGeniv(int coord, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexGeniv(int coord, int pname, java.nio.IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glGetTexGenxv(int coord, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glGetTexGenxv(int coord, int pname, java.nio.IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public boolean glIsFramebufferOES(int framebuffer) { + throw new UnsupportedOperationException(); + } + + public boolean glIsRenderbufferOES(int renderbuffer) { + throw new UnsupportedOperationException(); + } + + public void glRenderbufferStorageOES(int target, int internalformat, int width, int height) { + throw new UnsupportedOperationException(); + } + + public void glTexGenf(int coord, int pname, float param) { + throw new UnsupportedOperationException(); + } + + public void glTexGenfv(int coord, int pname, float[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexGenfv(int coord, int pname, java.nio.FloatBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glTexGeni(int coord, int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glTexGeniv(int coord, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexGeniv(int coord, int pname, java.nio.IntBuffer params) { + throw new UnsupportedOperationException(); + } + + public void glTexGenx(int coord, int pname, int param) { + throw new UnsupportedOperationException(); + } + + public void glTexGenxv(int coord, int pname, int[] params, int offset) { + throw new UnsupportedOperationException(); + } + + public void glTexGenxv(int coord, int pname, java.nio.IntBuffer params) { + throw new UnsupportedOperationException(); + } +} diff --git a/opengl/java/android/opengl/Group.java b/opengl/java/android/opengl/Group.java new file mode 100644 index 00000000000..1ef29539d2c --- /dev/null +++ b/opengl/java/android/opengl/Group.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.ShortBuffer; +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; +import javax.microedition.khronos.opengles.*; + +class MaterialIndices { + + private Material material = null; + private ShortBuffer indexBuffer = null; + + public MaterialIndices(Material material, ShortBuffer indexBuffer) { + this.material = material; + this.indexBuffer = indexBuffer; + } + + public Material getMaterial() { + return material; + } + + public ShortBuffer getIndexBuffer() { + return indexBuffer; + } +} + +/** + * {@hide} + */ +public class Group { + + private Object3D parent; + private String name; + + private List<MaterialIndices> materialIndices = + new ArrayList<MaterialIndices>(); + + public Group(Object3D parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public void load(DataInputStream dis) throws IOException { + dis.readInt(); // name length + this.name = dis.readUTF(); + + int numMaterials = dis.readInt(); + + for (int i = 0; i < numMaterials; i++) { + dis.readInt(); // material name length + String matName = dis.readUTF(); + Material material = parent.getMaterial(matName); + + int numIndices = dis.readInt(); + byte[] indicesBytes = new byte[numIndices * 2]; + dis.readFully(indicesBytes); + + // Swap bytes from network to native order if necessary + if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) { + int idx = 0; + for (int j = 0; j < numIndices; j++) { + byte b0 = indicesBytes[idx]; + byte b1 = indicesBytes[idx + 1]; + indicesBytes[idx] = b1; + indicesBytes[idx + 1] = b0; + idx += 2; + } + } + + ByteBuffer ibb = ByteBuffer.allocateDirect(2*numIndices); + ibb.order(ByteOrder.nativeOrder()); + ibb.put(indicesBytes); + ibb.position(0); + + ShortBuffer sb = ibb.asShortBuffer(); + materialIndices.add(new MaterialIndices(material, sb)); + } + } + + public int getNumTriangles() { + int numTriangles = 0; + Iterator<MaterialIndices> iter = materialIndices.iterator(); + while (iter.hasNext()) { + MaterialIndices matIdx = iter.next(); + ShortBuffer indexBuffer = matIdx.getIndexBuffer(); + numTriangles += indexBuffer.capacity()/3; + } + return numTriangles; + } + + public void draw(GL10 gl) { + gl.glDisableClientState(gl.GL_COLOR_ARRAY); + + gl.glVertexPointer(3, gl.GL_FIXED, 0, parent.getVertexBuffer()); + gl.glEnableClientState(gl.GL_VERTEX_ARRAY); + + gl.glNormalPointer(gl.GL_FIXED, 0, parent.getNormalBuffer()); + gl.glEnableClientState(gl.GL_NORMAL_ARRAY); + + if (parent.hasTexcoords()) { + gl.glTexCoordPointer(2, gl.GL_FIXED, 0, parent.getTexcoordBuffer()); + gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY); + gl.glEnable(gl.GL_TEXTURE_2D); + } else { + gl.glDisable(gl.GL_TEXTURE_2D); + } + + Iterator<MaterialIndices> iter = materialIndices.iterator(); + while (iter.hasNext()) { + MaterialIndices matIdx = iter.next(); + ShortBuffer indexBuffer = matIdx.getIndexBuffer(); + Material mat = matIdx.getMaterial(); + mat.setMaterialParameters(gl); + if (parent.hasTexcoords() && mat.getMap_Kd().length() > 0) { + Texture texture = parent.getTexture(mat.getMap_Kd()); + texture.setTextureParameters(gl); + } + + gl.glDrawElements(gl.GL_TRIANGLES, + indexBuffer.capacity(), + gl.GL_UNSIGNED_SHORT, + indexBuffer); + } + } + + public String toString() { + return "Group[" + + "name=" + name + + "]"; + } +} diff --git a/opengl/java/android/opengl/Material.java b/opengl/java/android/opengl/Material.java new file mode 100644 index 00000000000..60a3e7256ea --- /dev/null +++ b/opengl/java/android/opengl/Material.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.io.DataInputStream; +import java.io.IOException; +import javax.microedition.khronos.opengles.GL10; + +/** + * {@hide} + */ +public class Material { + + private Object3D parent; + private String name; + private String map_kd; + private float[] ka = new float[4]; + private float[] kd = new float[4]; + private float[] ks = new float[4]; + private float ns; + private int illum; + private float d; + + private static float[] black = { 0.0f, 0.0f, 0.0f, 1.0f }; + + public Material(Object3D parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public String getMap_Kd() { + return map_kd; + } + + public void setMaterialParameters(GL10 gl) { + gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, kd, 0); + gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, kd, 0); + gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, ks, 0); + gl.glMaterialf(gl.GL_FRONT_AND_BACK, gl.GL_SHININESS, + Math.min(Math.max(ns, 0), 128)); + +// if (illum == 0) { +// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, kd, 0); +// } else { +// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, ka, 0); +// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, kd, 0); +// } + +// if (illum > 1) { +// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, ks, 0); +// gl.glMaterialf(gl.GL_FRONT_AND_BACK, gl.GL_SHININESS, +// Math.min(Math.max(ns, 0), 128)); +// } else { +// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, black, 0); +// } + } + + public void load(DataInputStream dis) throws IOException { + dis.readInt(); // name length + this.name = dis.readUTF(); + + dis.readInt(); // map_kdLength + this.map_kd = dis.readUTF(); + + if (parent.hasTexcoords() && map_kd.length() > 0) { + parent.loadTexture(map_kd); + } + + this.ka[0] = dis.readFloat(); + this.ka[1] = dis.readFloat(); + this.ka[2] = dis.readFloat(); + this.ka[3] = dis.readFloat(); + + this.kd[0] = dis.readFloat(); + this.kd[1] = dis.readFloat(); + this.kd[2] = dis.readFloat(); + this.kd[3] = dis.readFloat(); + + this.ks[0] = dis.readFloat(); + this.ks[1] = dis.readFloat(); + this.ks[2] = dis.readFloat(); + this.ks[3] = dis.readFloat(); + + this.ns = dis.readFloat(); + this.illum = dis.readInt(); + this.d = dis.readFloat(); + } + + public String toString() { + return "Material[" + + "name=\"" + name + "\"," + + "ka={" + ka[0] + "," + ka[1] + "," + ka[2] + "}," + + "kd={" + kd[0] + "," + kd[1] + "," + kd[2] + "}," + + "ks={" + ks[0] + "," + ks[1] + "," + ks[2] + "}," + + "ns=" + ns + "," + + "map_kd=\"" + + (map_kd == null ? "" : map_kd) + + "\"," + + "illum=" + illum + "," + + "d=" + d + + "]"; + } +} diff --git a/opengl/java/android/opengl/Matrix.java b/opengl/java/android/opengl/Matrix.java new file mode 100644 index 00000000000..13ba36e8228 --- /dev/null +++ b/opengl/java/android/opengl/Matrix.java @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +/** + * Matrix math utilities. These methods operate on OpenGL ES format + * matrices and vectors stored in float arrays. + * + * Matrices are 4 x 4 column-vector matrices stored in column-major + * order: + * <pre> + * m[offset + 0] m[offset + 4] m[offset + 8] m[offset + 12] + * m[offset + 1] m[offset + 5] m[offset + 9] m[offset + 13] + * m[offset + 2] m[offset + 6] m[offset + 10] m[offset + 14] + * m[offset + 3] m[offset + 7] m[offset + 11] m[offset + 15] + * </pre> + * + * Vectors are 4 row x 1 column column-vectors stored in order: + * <pre> + * v[offset + 0] + * v[offset + 1] + * v[offset + 2] + * v[offset + 3] + * </pre> + * + */ +public class Matrix { + /** + * Multiply two 4x4 matrices together and store the result in a third 4x4 + * matrix. In matrix notation: result = lhs x rhs. Due to the way + * matrix multiplication works, the result matrix will have the same + * effect as first multiplying by the rhs matrix, then multiplying by + * the lhs matrix. This is the opposite of what you might expect. + * + * The same float array may be passed for result, lhs, and/or rhs. However, + * the result element values are undefined if the result elements overlap + * either the lhs or rhs elements. + * + * @param result The float array that holds the result. + * @param resultOffset The offset into the result array where the result is + * stored. + * @param lhs The float array that holds the left-hand-side matrix. + * @param lhsOffset The offset into the lhs array where the lhs is stored + * @param rhs The float array that holds the right-hand-side matrix. + * @param rhsOffset The offset into the rhs array where the rhs is stored. + * + * @throws IllegalArgumentException if result, lhs, or rhs are null, or if + * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or + * rhsOffset + 16 > rhs.length. + */ + public static native void multiplyMM(float[] result, int resultOffset, + float[] lhs, int lhsOffset, float[] rhs, int rhsOffset); + + /** + * Multiply a 4 element vector by a 4x4 matrix and store the result in a 4 + * element column vector. In matrix notation: result = lhs x rhs + * + * The same float array may be passed for resultVec, lhsMat, and/or rhsVec. + * However, the resultVec element values are undefined if the resultVec + * elements overlap either the lhsMat or rhsVec elements. + * + * @param resultVec The float array that holds the result vector. + * @param resultVecOffset The offset into the result array where the result + * vector is stored. + * @param lhsMat The float array that holds the left-hand-side matrix. + * @param lhsMatOffset The offset into the lhs array where the lhs is stored + * @param rhsVec The float array that holds the right-hand-side vector. + * @param rhsVecOffset The offset into the rhs vector where the rhs vector + * is stored. + * + * @throws IllegalArgumentException if resultVec, lhsMat, + * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length + * or lhsMatOffset + 16 > lhsMat.length or + * rhsVecOffset + 4 > rhsVec.length. + */ + public static native void multiplyMV(float[] resultVec, + int resultVecOffset, float[] lhsMat, int lhsMatOffset, + float[] rhsVec, int rhsVecOffset); + + /** + * Transposes a 4 x 4 matrix. + * + * @param mTrans the array that holds the output inverted matrix + * @param mTransOffset an offset into mInv where the inverted matrix is + * stored. + * @param m the input array + * @param mOffset an offset into m where the matrix is stored. + */ + public static void transposeM(float[] mTrans, int mTransOffset, float[] m, + int mOffset) { + for (int i = 0; i < 4; i++) { + int mBase = i * 4 + mOffset; + mTrans[i + mTransOffset] = m[mBase]; + mTrans[i + 4 + mTransOffset] = m[mBase + 1]; + mTrans[i + 8 + mTransOffset] = m[mBase + 2]; + mTrans[i + 12 + mTransOffset] = m[mBase + 3]; + } + } + + /** + * Inverts a 4 x 4 matrix. + * + * @param mInv the array that holds the output inverted matrix + * @param mInvOffset an offset into mInv where the inverted matrix is + * stored. + * @param m the input array + * @param mOffset an offset into m where the matrix is stored. + * @return true if the matrix could be inverted, false if it could not. + */ + public static boolean invertM(float[] mInv, int mInvOffset, float[] m, + int mOffset) { + // Invert a 4 x 4 matrix using Cramer's Rule + + // array of transpose source matrix + float[] src = new float[16]; + + // transpose matrix + transposeM(src, 0, m, mOffset); + + // temp array for pairs + float[] tmp = new float[12]; + + // calculate pairs for first 8 elements (cofactors) + tmp[0] = src[10] * src[15]; + tmp[1] = src[11] * src[14]; + tmp[2] = src[9] * src[15]; + tmp[3] = src[11] * src[13]; + tmp[4] = src[9] * src[14]; + tmp[5] = src[10] * src[13]; + tmp[6] = src[8] * src[15]; + tmp[7] = src[11] * src[12]; + tmp[8] = src[8] * src[14]; + tmp[9] = src[10] * src[12]; + tmp[10] = src[8] * src[13]; + tmp[11] = src[9] * src[12]; + + // Holds the destination matrix while we're building it up. + float[] dst = new float[16]; + + // calculate first 8 elements (cofactors) + dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; + dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; + dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; + dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7]; + dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7]; + dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7]; + dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6]; + dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6]; + dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3]; + dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3]; + dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3]; + dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3]; + dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3]; + dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; + dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; + dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; + + // calculate pairs for second 8 elements (cofactors) + tmp[0] = src[2] * src[7]; + tmp[1] = src[3] * src[6]; + tmp[2] = src[1] * src[7]; + tmp[3] = src[3] * src[5]; + tmp[4] = src[1] * src[6]; + tmp[5] = src[2] * src[5]; + tmp[6] = src[0] * src[7]; + tmp[7] = src[3] * src[4]; + tmp[8] = src[0] * src[6]; + tmp[9] = src[2] * src[4]; + tmp[10] = src[0] * src[5]; + tmp[11] = src[1] * src[4]; + + // calculate second 8 elements (cofactors) + dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; + dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; + dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; + dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]; + dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15]; + dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15]; + dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14]; + dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14]; + dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]; + dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]; + dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]; + dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]; + dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8]; + dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; + dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; + dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; + + // calculate determinant + float det = + src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] + * dst[3]; + + if (det == 0.0f) { + + } + + // calculate matrix inverse + det = 1 / det; + for (int j = 0; j < 16; j++) + mInv[j + mInvOffset] = dst[j] * det; + + return true; + } + + /** + * Computes an orthographic projection matrix. + * + * @param m returns the result + * @param mOffset + * @param left + * @param right + * @param bottom + * @param top + * @param near + * @param far + */ + public static void orthoM(float[] m, int mOffset, + float left, float right, float bottom, float top, + float near, float far) { + if (left == right) { + throw new IllegalArgumentException("left == right"); + } + if (bottom == top) { + throw new IllegalArgumentException("bottom == top"); + } + if (near == far) { + throw new IllegalArgumentException("near == far"); + } + + final float r_width = 1.0f / (right - left); + final float r_height = 1.0f / (top - bottom); + final float r_depth = 1.0f / (far - near); + final float x = 2.0f * (r_width); + final float y = 2.0f * (r_height); + final float z = -2.0f * (r_depth); + final float tx = -(right + left) * r_width; + final float ty = -(top + bottom) * r_height; + final float tz = -(far + near) * r_depth; + m[mOffset + 0] = x; + m[mOffset + 5] = y; + m[mOffset +10] = z; + m[mOffset +12] = tx; + m[mOffset +13] = ty; + m[mOffset +14] = tz; + m[mOffset +15] = 1.0f; + m[mOffset + 1] = 0.0f; + m[mOffset + 2] = 0.0f; + m[mOffset + 3] = 0.0f; + m[mOffset + 4] = 0.0f; + m[mOffset + 6] = 0.0f; + m[mOffset + 7] = 0.0f; + m[mOffset + 8] = 0.0f; + m[mOffset + 9] = 0.0f; + m[mOffset + 11] = 0.0f; + } + + + /** + * Define a projection matrix in terms of six clip planes + * @param m the float array that holds the perspective matrix + * @param offset the offset into float array m where the perspective + * matrix data is written + * @param left + * @param right + * @param bottom + * @param top + * @param near + * @param far + */ + + public static void frustumM(float[] m, int offset, + float left, float right, float bottom, float top, + float near, float far) { + if (left == right) { + throw new IllegalArgumentException("left == right"); + } + if (top == bottom) { + throw new IllegalArgumentException("top == bottom"); + } + if (near == far) { + throw new IllegalArgumentException("near == far"); + } + if (near <= 0.0f) { + throw new IllegalArgumentException("near <= 0.0f"); + } + if (far <= 0.0f) { + throw new IllegalArgumentException("far <= 0.0f"); + } + final float r_width = 1.0f / (right - left); + final float r_height = 1.0f / (top - bottom); + final float r_depth = 1.0f / (near - far); + final float x = 2.0f * (near * r_width); + final float y = 2.0f * (near * r_height); + final float A = 2.0f * ((right + left) * r_width); + final float B = (top + bottom) * r_height; + final float C = (far + near) * r_depth; + final float D = 2.0f * (far * near * r_depth); + m[offset + 0] = x; + m[offset + 5] = y; + m[offset + 8] = A; + m[offset + 9] = B; + m[offset + 10] = C; + m[offset + 14] = D; + m[offset + 11] = -1.0f; + m[offset + 1] = 0.0f; + m[offset + 2] = 0.0f; + m[offset + 3] = 0.0f; + m[offset + 4] = 0.0f; + m[offset + 6] = 0.0f; + m[offset + 7] = 0.0f; + m[offset + 12] = 0.0f; + m[offset + 13] = 0.0f; + m[offset + 15] = 0.0f; + } + + /** + * Computes the length of a vector + * + * @param x x coordinate of a vector + * @param y y coordinate of a vector + * @param z z coordinate of a vector + * @return the length of a vector + */ + public static float length(float x, float y, float z) { + return (float) Math.sqrt(x * x + y * y + z * z); + } + + /** + * Sets matrix m to the identity matrix. + * @param sm returns the result + * @param smOffset index into sm where the result matrix starts + */ + public static void setIdentityM(float[] sm, int smOffset) { + for (int i=0 ; i<16 ; i++) { + sm[smOffset + i] = 0; + } + for(int i = 0; i < 16; i += 5) { + sm[smOffset + i] = 1.0f; + } + } + + /** + * Scales matrix m by x, y, and z, putting the result in sm + * @param sm returns the result + * @param smOffset index into sm where the result matrix starts + * @param m source matrix + * @param mOffset index into m where the source matrix starts + * @param x scale factor x + * @param y scale factor y + * @param z scale factor z + */ + public static void scaleM(float[] sm, int smOffset, + float[] m, int mOffset, + float x, float y, float z) { + for (int i=0 ; i<4 ; i++) { + int smi = smOffset + i; + int mi = mOffset + i; + sm[ smi] = m[ mi] * x; + sm[ 4 + smi] = m[ 4 + mi] * y; + sm[ 8 + smi] = m[ 8 + mi] * z; + sm[12 + smi] = m[12 + mi]; + } + } + + /** + * Scales matrix m in place by sx, sy, and sz + * @param m matrix to scale + * @param mOffset index into m where the matrix starts + * @param x scale factor x + * @param y scale factor y + * @param z scale factor z + */ + public static void scaleM(float[] m, int mOffset, + float x, float y, float z) { + for (int i=0 ; i<4 ; i++) { + int mi = mOffset + i; + m[ mi] *= x; + m[ 4 + mi] *= y; + m[ 8 + mi] *= z; + } + } + + /** + * Translates matrix m by x, y, and z, putting the result in tm + * @param tm returns the result + * @param tmOffset index into sm where the result matrix starts + * @param m source matrix + * @param mOffset index into m where the source matrix starts + * @param x translation factor x + * @param y translation factor y + * @param z translation factor z + */ + public static void translateM(float[] tm, int tmOffset, + float[] m, int mOffset, + float x, float y, float z) { + for (int i=0 ; i<12 ; i++) { + tm[tmOffset + i] = m[mOffset + i]; + } + for (int i=0 ; i<4 ; i++) { + int tmi = tmOffset + i; + int mi = mOffset + i; + tm[12 + tmi] = m[mi] * x + m[4 + mi] * y + m[8 + mi] * z + + m[12 + mi]; + } + } + + /** + * Translates matrix m by x, y, and z in place. + * @param m matrix + * @param mOffset index into m where the matrix starts + * @param x translation factor x + * @param y translation factor y + * @param z translation factor z + */ + public static void translateM( + float[] m, int mOffset, + float x, float y, float z) { + for (int i=0 ; i<4 ; i++) { + int mi = mOffset + i; + m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z; + } + } + + /** + * Rotates matrix m by angle a (in degrees) around the axis (x, y, z) + * @param rm returns the result + * @param rmOffset index into rm where the result matrix starts + * @param m source matrix + * @param mOffset index into m where the source matrix starts + * @param a angle to rotate in degrees + * @param x scale factor x + * @param y scale factor y + * @param z scale factor z + */ + public static void rotateM(float[] rm, int rmOffset, + float[] m, int mOffset, + float a, float x, float y, float z) { + float[] r = new float[16]; + setRotateM(r, 0, a, x, y, z); + multiplyMM(rm, rmOffset, m, mOffset, r, 0); + } + + /** + * Rotates matrix m in place by angle a (in degrees) + * around the axis (x, y, z) + * @param m source matrix + * @param mOffset index into m where the matrix starts + * @param a angle to rotate in degrees + * @param x scale factor x + * @param y scale factor y + * @param z scale factor z + */ + public static void rotateM(float[] m, int mOffset, + float a, float x, float y, float z) { + float[] temp = new float[32]; + setRotateM(temp, 0, a, x, y, z); + multiplyMM(temp, 16, m, mOffset, temp, 0); + System.arraycopy(temp, 16, m, mOffset, 16); + } + + /** + * Rotates matrix m by angle a (in degrees) around the axis (x, y, z) + * @param rm returns the result + * @param rmOffset index into rm where the result matrix starts + * @param a angle to rotate in degrees + * @param x scale factor x + * @param y scale factor y + * @param z scale factor z + */ + public static void setRotateM(float[] rm, int rmOffset, + float a, float x, float y, float z) { + rm[rmOffset + 3] = 0; + rm[rmOffset + 7] = 0; + rm[rmOffset + 11]= 0; + rm[rmOffset + 12]= 0; + rm[rmOffset + 13]= 0; + rm[rmOffset + 14]= 0; + rm[rmOffset + 15]= 1; + a *= (float) (Math.PI / 180.0f); + float s = (float) Math.sin(a); + float c = (float) Math.cos(a); + if (1.0f == x && 0.0f == y && 0.0f == z) { + rm[rmOffset + 5] = c; rm[rmOffset + 10]= c; + rm[rmOffset + 6] = s; rm[rmOffset + 9] = -s; + rm[rmOffset + 1] = 0; rm[rmOffset + 2] = 0; + rm[rmOffset + 4] = 0; rm[rmOffset + 8] = 0; + rm[rmOffset + 0] = 1; + } else if (0.0f == x && 1.0f == y && 0.0f == z) { + rm[rmOffset + 0] = c; rm[rmOffset + 10]= c; + rm[rmOffset + 8] = s; rm[rmOffset + 2] = -s; + rm[rmOffset + 1] = 0; rm[rmOffset + 4] = 0; + rm[rmOffset + 6] = 0; rm[rmOffset + 9] = 0; + rm[rmOffset + 5] = 1; + } else if (0.0f == x && 0.0f == y && 1.0f == z) { + rm[rmOffset + 0] = c; rm[rmOffset + 5] = c; + rm[rmOffset + 1] = s; rm[rmOffset + 4] = -s; + rm[rmOffset + 2] = 0; rm[rmOffset + 6] = 0; + rm[rmOffset + 8] = 0; rm[rmOffset + 9] = 0; + rm[rmOffset + 10]= 1; + } else { + float len = length(x, y, z); + if (1.0f != len) { + float recipLen = 1.0f / len; + x *= recipLen; + y *= recipLen; + z *= recipLen; + } + float nc = 1.0f - c; + float xy = x * y; + float yz = y * z; + float zx = z * x; + float xs = x * s; + float ys = y * s; + float zs = z * s; + rm[rmOffset + 0] = x*x*nc + c; + rm[rmOffset + 4] = xy*nc - zs; + rm[rmOffset + 8] = zx*nc + ys; + rm[rmOffset + 1] = xy*nc + zs; + rm[rmOffset + 5] = y*y*nc + c; + rm[rmOffset + 9] = yz*nc - xs; + rm[rmOffset + 2] = zx*nc - ys; + rm[rmOffset + 6] = yz*nc + xs; + rm[rmOffset + 10] = z*z*nc + c; + } + } + + /** + * Converts Euler angles to a rotation matrix + * @param rm returns the result + * @param rmOffset index into rm where the result matrix starts + * @param x angle of rotation, in degrees + * @param y angle of rotation, in degrees + * @param z angle of rotation, in degrees + */ + public static void setRotateEulerM(float[] rm, int rmOffset, + float x, float y, float z) { + x *= (float) (Math.PI / 180.0f); + y *= (float) (Math.PI / 180.0f); + z *= (float) (Math.PI / 180.0f); + float cx = (float) Math.cos(x); + float sx = (float) Math.sin(x); + float cy = (float) Math.cos(y); + float sy = (float) Math.sin(y); + float cz = (float) Math.cos(z); + float sz = (float) Math.sin(z); + float cxsy = cx * sy; + float sxsy = sx * sy; + + rm[rmOffset + 0] = cy * cz; + rm[rmOffset + 1] = -cy * sz; + rm[rmOffset + 2] = sy; + rm[rmOffset + 3] = 0.0f; + + rm[rmOffset + 4] = cxsy * cz + cx * sz; + rm[rmOffset + 5] = -cxsy * sz + cx * cz; + rm[rmOffset + 6] = -sx * cy; + rm[rmOffset + 7] = 0.0f; + + rm[rmOffset + 8] = -sxsy * cz + sx * sz; + rm[rmOffset + 9] = sxsy * sz + sx * cz; + rm[rmOffset + 10] = cx * cy; + rm[rmOffset + 11] = 0.0f; + + rm[rmOffset + 12] = 0.0f; + rm[rmOffset + 13] = 0.0f; + rm[rmOffset + 14] = 0.0f; + rm[rmOffset + 15] = 1.0f; + } +} diff --git a/opengl/java/android/opengl/Object3D.java b/opengl/java/android/opengl/Object3D.java new file mode 100644 index 00000000000..340c6a78815 --- /dev/null +++ b/opengl/java/android/opengl/Object3D.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.microedition.khronos.opengles.*; + +/** + * {@hide} + */ +public abstract class Object3D { + + private boolean mHasTexcoords = false; + + private float mBoundsMinX = Float.MAX_VALUE; + private float mBoundsMaxX = Float.MIN_VALUE; + private float mBoundsMinY = Float.MAX_VALUE; + private float mBoundsMaxY = Float.MIN_VALUE; + private float mBoundsMinZ = Float.MAX_VALUE; + private float mBoundsMaxZ = Float.MIN_VALUE; + + private IntBuffer mVertexBuffer; + private IntBuffer mNormalBuffer; + private IntBuffer mTexcoordBuffer; + + // All groups, by name + private Map<String, Group> mGroups; + + // All materials, by name + private Map<String, Material> mMaterials; + + // All texture maps, by name + private Map<String, Texture> mTextures; + + public Object3D() { + reset(); + } + + /** + * Override this method with an implementation that contructs + * and InputStream from the given filename. For example, if the + * source files are to be retrieved using an AssetManager, + * the implementation would use AssetManager.load() to + * get the input stream. + */ + public abstract InputStream readFile(String filename) throws IOException; + + private void reset() { + mVertexBuffer = mNormalBuffer = mTexcoordBuffer = null; + + mGroups = new HashMap<String,Group>(); + mMaterials = new HashMap<String,Material>(); + mTextures = new HashMap<String,Texture>(); + } + + public Material getMaterial(String name) { + Material mat = mMaterials.get(name); + return mat; + } + + public Texture getTexture(String name) { + return mTextures.get(name); + } + + public IntBuffer getVertexBuffer() { + return mVertexBuffer; + } + + public IntBuffer getNormalBuffer() { + return mNormalBuffer; + } + + public IntBuffer getTexcoordBuffer() { + return mTexcoordBuffer; + } + + public int getNumTriangles() { + int numTriangles = 0; + Iterator<Group> iter = mGroups.values().iterator(); + while (iter.hasNext()) { + numTriangles += iter.next().getNumTriangles(); + } + return numTriangles; + } + + public boolean hasTexcoords() { + return mHasTexcoords; + } + + public float getBoundsMinX() { + return mBoundsMinX; + } + + public float getBoundsMaxX() { + return mBoundsMaxX; + } + + public float getBoundsMinY() { + return mBoundsMinY; + } + + public float getBoundsMaxY() { + return mBoundsMaxY; + } + + public float getBoundsMinZ() { + return mBoundsMinZ; + } + + public float getBoundsMaxZ() { + return mBoundsMaxZ; + } + + public void loadTexture(String name) throws IOException { + InputStream is = readFile(name + ".raw"); + Texture texture = new Texture(is); + mTextures.put(name, texture); + } + + private static void verifyByte(DataInputStream dis, int b) + throws IOException { + int x = dis.read() & 0xff; + if (x != b) { + throw new RuntimeException("Bad byte: " + + x + + " (expected " + b + ")"); + } + } + + public void load(String filename) throws IOException { + reset(); + + DataInputStream dis = new DataInputStream(readFile(filename)); + verifyByte(dis, 'g' + 128); + verifyByte(dis, 'l'); + verifyByte(dis, 'e'); + verifyByte(dis, 's'); + + int numTuples = dis.readInt(); + + this.mBoundsMinX = dis.readFloat(); + this.mBoundsMaxX = dis.readFloat(); + this.mBoundsMinY = dis.readFloat(); + this.mBoundsMaxY = dis.readFloat(); + this.mBoundsMinZ = dis.readFloat(); + this.mBoundsMaxZ = dis.readFloat(); + + this.mHasTexcoords = dis.readInt() == 1; + + int intsPerTuple = mHasTexcoords ? 8 : 6; + int numInts = numTuples*intsPerTuple; + + int len = 4*numTuples*(mHasTexcoords ? 8 : 6); + + byte[] tmp = new byte[len]; + int tidx = 0; + while (tidx < len) { + tidx += dis.read(tmp, tidx, len - tidx); + } + if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + for (int i = 0; i < len; i += 4) { + byte tmp0 = tmp[i]; + byte tmp1 = tmp[i + 1]; + byte tmp2 = tmp[i + 2]; + byte tmp3 = tmp[i + 3]; + tmp[i] = tmp3; + tmp[i + 1] = tmp2; + tmp[i + 2] = tmp1; + tmp[i + 3] = tmp0; + } + } + + ByteBuffer allbb = ByteBuffer.allocateDirect(len); + allbb.order(ByteOrder.nativeOrder()); + allbb.put(tmp); + + allbb.position(0); + allbb.limit(4*3*numTuples); + ByteBuffer vbb = allbb.slice(); + this.mVertexBuffer = vbb.asIntBuffer(); + mVertexBuffer.position(0); + + if (mHasTexcoords) { + allbb.position(allbb.limit()); + allbb.limit(allbb.position() + 4*2*numTuples); + ByteBuffer tbb = allbb.slice(); + this.mTexcoordBuffer = tbb.asIntBuffer(); + mTexcoordBuffer.position(0); + } + + allbb.position(allbb.limit()); + allbb.limit(allbb.position() + 4*3*numTuples); + ByteBuffer nbb = allbb.slice(); + this.mNormalBuffer = nbb.asIntBuffer(); + mNormalBuffer.position(0); + + int numMaterials = dis.readInt(); + for (int i = 0; i < numMaterials; i++) { + Material mat = new Material(this); + mat.load(dis); + mMaterials.put(mat.getName(), mat); + } + + int numGroups = dis.readInt(); + for (int i = 0; i < numGroups; i++) { + Group g = new Group(this); + g.load(dis); + mGroups.put(g.getName(), g); + } + } + + public void draw(GL10 gl) { + Iterator<Group> iter = mGroups.values().iterator(); + while (iter.hasNext()) { + iter.next().draw(gl); + } + } +} + diff --git a/opengl/java/android/opengl/Texture.java b/opengl/java/android/opengl/Texture.java new file mode 100644 index 00000000000..dcd894d19cf --- /dev/null +++ b/opengl/java/android/opengl/Texture.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +import java.io.InputStream; +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import javax.microedition.khronos.opengles.GL10; + +import android.content.res.AssetManager; + +/** + * {@hide} + */ +public class Texture { + + private int width, height, bpp; + private ByteBuffer data; + private int name = -1; + + // Texture maps have the following format. All integers + // are 16 bits, high byte first. Pixels are in 5/6/5 + // RGB format, low byte first. + // + // width + // height + // pixel (0, 0) + // pixel (1, 0) + // ... + // pixel (width - 1, height - 1) + + private int readInt16(InputStream is) throws IOException { + return is.read() | (is.read() << 8); + } + + public Texture(InputStream is) throws IOException { + this.width = readInt16(is); + this.height = readInt16(is); + this.bpp = 2; + + int npixels = width*height; + int nbytes = npixels*bpp; + byte[] arr = new byte[nbytes]; + + int idx = 0; + while (idx < nbytes) { + int nread = is.read(arr, idx, nbytes - idx); + idx += nread; + } + + if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + // Swap pairs of bytes on big-endian platforms + for (int i = 0; i < npixels; i++) { + int j = i*2; + int k = j + 1; + + byte tmp = arr[j]; + arr[j] = arr[k]; + arr[k] = tmp; + } + } + + this.data = ByteBuffer.allocateDirect(arr.length); + this.data.order(ByteOrder.nativeOrder()); + data.put(arr); + data.position(0); + } + + private int loadTexture(GL10 gl, + int textureUnit, + int minFilter, int magFilter, + int wrapS, int wrapT, + int mode, + int width, int height, + int dataType, + Buffer data) { + int[] texture = new int[1]; + gl.glGenTextures(1, texture, 0); + + gl.glEnable(gl.GL_TEXTURE_2D); + gl.glClientActiveTexture(textureUnit); + gl.glBindTexture(gl.GL_TEXTURE_2D, texture[0]); + gl.glTexParameterf(gl.GL_TEXTURE_2D, + gl.GL_TEXTURE_MIN_FILTER, + minFilter); + gl.glTexParameterf(gl.GL_TEXTURE_2D, + gl.GL_TEXTURE_MAG_FILTER, + magFilter); + gl.glTexParameterf(gl.GL_TEXTURE_2D, + gl.GL_TEXTURE_WRAP_S, + wrapS); + gl.glTexParameterf(gl.GL_TEXTURE_2D, + gl.GL_TEXTURE_WRAP_T, + wrapT); + gl.glTexEnvf(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, mode); + + gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, + width, height, + 0, gl.GL_RGB, dataType, + data); + + return texture[0]; + } + + public void setTextureParameters(GL10 gl) { + if (name < 0) { + name = loadTexture(gl, + gl.GL_TEXTURE0, + gl.GL_NEAREST, gl.GL_NEAREST, + gl.GL_REPEAT, gl.GL_REPEAT, + gl.GL_MODULATE, + width, height, + gl.GL_UNSIGNED_SHORT_5_6_5, + data); + } + + gl.glBindTexture(gl.GL_TEXTURE_2D, name); + } +} diff --git a/opengl/java/android/opengl/Visibility.java b/opengl/java/android/opengl/Visibility.java new file mode 100644 index 00000000000..40e446f67db --- /dev/null +++ b/opengl/java/android/opengl/Visibility.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.opengl; + +/** + * A collection of utility methods for computing the visibility of triangle + * meshes. + * + */ +public class Visibility { + /** + * Test whether a given triangle mesh is visible on the screen. The mesh + * is specified as an indexed triangle list. + * + * @param ws the world space to screen space transform matrix, as an OpenGL + * column matrix. + * @param wsOffset an index into the ws array where the data starts. + * @param positions the vertex positions (x, y, z). + * @param positionsOffset the index in the positions array where the data + * starts. + * @param indices the indices of the triangle list. The indices are + * expressed as chars because they are unsigned 16-bit values. + * @param indicesOffset the index in the indices array where the index data + * starts. + * @param indexCount the number of indices in use. Typically a multiple of + * three. If not a multiple of three, the remaining one or two indices will + * be ignored. + * @return 2 if all of the mesh is visible, 1 if some part of the mesh is + * visible, 0 if no part is visible. + * + * @throws IllegalArgumentException if ws is null, wsOffset < 0, + * positions is null, positionsOffset < 0, indices is null, + * indicesOffset < 0, indicesOffset > indices.length - indexCount + */ + public static native int visibilityTest(float[] ws, int wsOffset, + float[] positions, int positionsOffset, char[] indices, + int indicesOffset, int indexCount); + + /** + * Given an OpenGL ES ModelView-Projection matrix (which implicitly + * describes a frustum) and a list of spheres, determine which spheres + * intersect the frustum. + * <p> + * A ModelView-Projection matrix can be computed by multiplying the + * a Projection matrix by the a ModelView matrix (in that order.). There + * are several possible ways to obtain the current ModelView and + * Projection matrices. The most generally applicable way is to keep + * track of the current matrices in application code. If that is not + * convenient, there are two optional OpenGL ES extensions which may + * be used to read the current matrices from OpenGL ES: + * <ul> + * <li>GL10Ext.glQueryMatrixxOES + * <li>GL11.GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES and + * GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES + * </ul> + * The problem with reading back the matrices is that your application + * will only work with devices that support the extension(s) that + * it uses. + * <p> + * A frustum is a six-sided truncated pyramid that defines the portion of + * world space that is visible in the view. + * <p> + * Spheres are described as four floating point values: x, y, z, and r, in + * world-space coordinates. R is the radius of the sphere. + * <p> + * @param mvp a float array containing the mode-view-projection matrix + * @param mvpOffset The offset of the mvp data within the mvp array. + * @param spheres a float array containing the sphere data. + * @param spheresOffset an offset into the sphere array where the sphere + * data starts + * @param spheresCount the number of spheres to cull. + * @param results an integer array containing the indices of the spheres + * that are either contained entirely within or intersect the frustum. + * @param resultsOffset an offset into the results array where the results + * start. + * @param resultsCapacity the number of array elements available for storing + * results. + * @return the number of spheres that intersected the frustum. Can be + * larger than resultsCapacity, in which case only the first resultsCapacity + * results are written into the results array. + * + * @throws IllegalArgumentException if mvp is null, mvpOffset < 0, + * mvpOffset > mvp.length - 16, spheres is null, spheresOffset < 0, + * spheresOffset > spheres.length - sphereCount, + * results is null, resultsOffset < 0, resultsOffset > results.length - + * resultsCapacity. + */ + public static native int frustumCullSpheres(float[] mvp, int mvpOffset, + float[] spheres, int spheresOffset, int spheresCount, + int[] results, int resultsOffset, int resultsCapacity); + + /** + * Compute a bounding sphere for a set of points. It is approximately the + * minimal bounding sphere of an axis-aligned box that bounds the points. + * + * @param positions positions in x, y, z triples + * @param positionsOffset offset into positions array + * @param positionsCount number of position triples to process + * @param sphere array containing the output as (x, y, z, r) + * @param sphereOffset offset where the sphere data will be written + * + * @throws IllegalArgumentException if positions is null, + * positionsOffset < 0, positionsOffset > positions.length - positionsCount, + * sphere is null, sphereOffset < 0, sphereOffset > sphere.length - 4. + */ + public static native void computeBoundingSphere(float[] positions, + int positionsOffset, int positionsCount, float[] sphere, + int sphereOffset); +} diff --git a/opengl/java/android/opengl/package.html b/opengl/java/android/opengl/package.html new file mode 100644 index 00000000000..7175b334c5b --- /dev/null +++ b/opengl/java/android/opengl/package.html @@ -0,0 +1,5 @@ +<HTML> +<BODY> +Provides OpenGL utilities. +</BODY> +</HTML> |