diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch) | |
tree | 35051494d2af230dce54d6b31c6af8fc24091316 /opengl | |
download | frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2 |
Initial Contribution
Diffstat (limited to 'opengl')
75 files changed, 27180 insertions, 0 deletions
diff --git a/opengl/java/android/opengl/EGLLogWrapper.java b/opengl/java/android/opengl/EGLLogWrapper.java new file mode 100644 index 0000000..521fc8c --- /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 0000000..09b5878 --- /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); + + /** + * Check if all calls are on the same thread. + */ + 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 0000000..884a1a0 --- /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 0000000..762fccf --- /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 0000000..4119bf8 --- /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/GLU.java b/opengl/java/android/opengl/GLU.java new file mode 100644 index 0000000..ff2741a --- /dev/null +++ b/opengl/java/android/opengl/GLU.java @@ -0,0 +1,289 @@ +/* + * 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; + + // Normalize up + float rlup = 1.0f / Matrix.length(upX, upY, upZ); + upX *= rlup; + upY *= rlup; + upZ *= rlup; + + // 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; + + // 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 0000000..df6c557 --- /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 0000000..067f95f --- /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 0000000..1ef2953 --- /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 0000000..60a3e72 --- /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 0000000..38be6be --- /dev/null +++ b/opengl/java/android/opengl/Matrix.java @@ -0,0 +1,582 @@ +/* + * 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 sx, sy, and sz, 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 sx, sy, and sz, 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<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 sx, sy, and sz 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 0000000..340c6a7 --- /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 0000000..dcd894d --- /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 0000000..b802160 --- /dev/null +++ b/opengl/java/android/opengl/Visibility.java @@ -0,0 +1,124 @@ +/* + * 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; + +/** + * {@hide} + * 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 0000000..7175b33 --- /dev/null +++ b/opengl/java/android/opengl/package.html @@ -0,0 +1,5 @@ +<HTML> +<BODY> +Provides OpenGL utilities. +</BODY> +</HTML> diff --git a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java new file mode 100644 index 0000000..b03392e --- /dev/null +++ b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java @@ -0,0 +1,32 @@ +/* +** +** Copyright 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 com.google.android.gles_jni; + +import javax.microedition.khronos.egl.*; + +public class EGLConfigImpl extends EGLConfig { + private int mEGLConfig; + + EGLConfigImpl(int config) { + mEGLConfig = config; + } + + int get() { + return mEGLConfig; + } +} diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java new file mode 100644 index 0000000..f10c02f --- /dev/null +++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java @@ -0,0 +1,36 @@ +/* +** +** Copyright 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 com.google.android.gles_jni; + +import javax.microedition.khronos.egl.*; +import javax.microedition.khronos.opengles.GL; + +public class EGLContextImpl extends EGLContext { + private GLImpl mGLContext; + int mEGLContext; + + public EGLContextImpl(int ctx) { + mEGLContext = ctx; + mGLContext = new GLImpl(); + } + + @Override + public GL getGL() { + return mGLContext; + } +} diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java new file mode 100644 index 0000000..6321632 --- /dev/null +++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java @@ -0,0 +1,28 @@ +/* +** +** Copyright 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 com.google.android.gles_jni; + +import javax.microedition.khronos.egl.*; + +public class EGLDisplayImpl extends EGLDisplay { + int mEGLDisplay; + + public EGLDisplayImpl(int dpy) { + mEGLDisplay = dpy; + } +} diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java new file mode 100644 index 0000000..a667e8d --- /dev/null +++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java @@ -0,0 +1,118 @@ +/* +** +** Copyright 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 com.google.android.gles_jni; + +import javax.microedition.khronos.egl.*; + +import android.view.Surface; +import android.view.SurfaceView; +import android.view.SurfaceHolder; +import android.view.View; + +public class EGLImpl implements EGL10 { + private EGLContextImpl mContext = new EGLContextImpl(-1); + private EGLDisplayImpl mDisplay = new EGLDisplayImpl(-1); + private EGLSurfaceImpl mSurface = new EGLSurfaceImpl(-1); + + public native boolean eglInitialize(EGLDisplay display, int[] major_minor); + public native boolean eglQueryContext(EGLDisplay display, EGLContext context, int attribute, int[] value); + public native boolean eglQuerySurface(EGLDisplay display, EGLSurface surface, int attribute, int[] value); + public native boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config); + public native boolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, int attribute, int[] value); + public native boolean eglGetConfigs(EGLDisplay display, EGLConfig[] configs, int config_size, int[] num_config); + public native int eglGetError(); + public native boolean eglDestroyContext(EGLDisplay display, EGLContext context); + public native boolean eglDestroySurface(EGLDisplay display, EGLSurface surface); + public native boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context); + public native String eglQueryString(EGLDisplay display, int name); + public native boolean eglSwapBuffers(EGLDisplay display, EGLSurface surface); + public native boolean eglTerminate(EGLDisplay display); + public native boolean eglCopyBuffers(EGLDisplay display, EGLSurface surface, Object native_pixmap); + public native boolean eglWaitGL(); + public native boolean eglWaitNative(int engine, Object bindTarget); + + public EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list) { + return new EGLContextImpl( _eglCreateContext(display, config, share_context, attrib_list) ); + } + + public EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list) { + return new EGLSurfaceImpl( _eglCreatePbufferSurface(display, config, attrib_list) ); + } + + public EGLSurface eglCreatePixmapSurface(EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list) { + EGLSurfaceImpl sur = new EGLSurfaceImpl(); + _eglCreatePixmapSurface(sur, display, config, native_pixmap, attrib_list); + return sur; + } + + public EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list) { + Surface sur; + if (native_window instanceof SurfaceView) { + SurfaceView surfaceView = (SurfaceView)native_window; + sur = surfaceView.getHolder().getSurface(); + } else if (native_window instanceof SurfaceHolder) { + SurfaceHolder holder = (SurfaceHolder)native_window; + sur = holder.getSurface(); + } else { + throw new java.lang.UnsupportedOperationException( + "eglCreateWindowSurface() can only be called with an instance of " + + "SurfaceView or SurfaceHolder at the moment, this will be fixed later."); + } + return new EGLSurfaceImpl( _eglCreateWindowSurface(display, config, sur, attrib_list) ); + } + + public synchronized EGLDisplay eglGetDisplay(Object native_display) { + int value = _eglGetDisplay(native_display); + if (mDisplay.mEGLDisplay != value) + mDisplay = new EGLDisplayImpl(value); + return mDisplay; + } + + public synchronized EGLContext eglGetCurrentContext() { + int value = _eglGetCurrentContext(); + if (mContext.mEGLContext != value) + mContext = new EGLContextImpl(value); + return mContext; + } + + public synchronized EGLDisplay eglGetCurrentDisplay() { + int value = _eglGetCurrentDisplay(); + if (mDisplay.mEGLDisplay != value) + mDisplay = new EGLDisplayImpl(value); + return mDisplay; + } + + public synchronized EGLSurface eglGetCurrentSurface(int readdraw) { + int value = _eglGetCurrentSurface(readdraw); + if (mSurface.mEGLSurface != value) + mSurface = new EGLSurfaceImpl(value); + return mSurface; + } + + private native int _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list); + private native int _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list); + private native void _eglCreatePixmapSurface(EGLSurface sur, EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list); + private native int _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list); + private native int _eglGetDisplay(Object native_display); + private native int _eglGetCurrentContext(); + private native int _eglGetCurrentDisplay(); + private native int _eglGetCurrentSurface(int readdraw); + + native private static void _nativeClassInit(); + static { _nativeClassInit(); } +} diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java new file mode 100644 index 0000000..66cc200 --- /dev/null +++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java @@ -0,0 +1,33 @@ +/* +** +** Copyright 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 com.google.android.gles_jni; + +import javax.microedition.khronos.egl.*; + +public class EGLSurfaceImpl extends EGLSurface { + int mEGLSurface; + private int mNativePixelRef; + public EGLSurfaceImpl() { + mEGLSurface = 0; + mNativePixelRef = 0; + } + public EGLSurfaceImpl(int surface) { + mEGLSurface = surface; + mNativePixelRef = 0; + } +} diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java new file mode 100644 index 0000000..47f07d0 --- /dev/null +++ b/opengl/java/com/google/android/gles_jni/GLImpl.java @@ -0,0 +1,2115 @@ +/* //device/java/android/com/google/android/gles_jni/GLImpl.java +** +** Copyright 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. +*/ + +// This source file is automatically generated + +package com.google.android.gles_jni; + +import java.nio.Buffer; +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; + +public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack { + + // Private accessors for native code + + native private static void _nativeClassInit(); + static { + _nativeClassInit(); + } + + Buffer _colorPointer = null; + Buffer _normalPointer = null; + Buffer _texCoordPointer = null; + Buffer _vertexPointer = null; + + public GLImpl() { + } + + public void glGetPointerv(int pname, java.nio.Buffer[] params) { + throw new UnsupportedOperationException("glGetPointerv"); + } + + // C function void glActiveTexture ( GLenum texture ) + + public native void glActiveTexture( + int texture + ); + + // C function void glAlphaFunc ( GLenum func, GLclampf ref ) + + public native void glAlphaFunc( + int func, + float ref + ); + + // C function void glAlphaFuncx ( GLenum func, GLclampx ref ) + + public native void glAlphaFuncx( + int func, + int ref + ); + + // C function void glBindTexture ( GLenum target, GLuint texture ) + + public native void glBindTexture( + int target, + int texture + ); + + // C function void glBlendFunc ( GLenum sfactor, GLenum dfactor ) + + public native void glBlendFunc( + int sfactor, + int dfactor + ); + + // C function void glClear ( GLbitfield mask ) + + public native void glClear( + int mask + ); + + // C function void glClearColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) + + public native void glClearColor( + float red, + float green, + float blue, + float alpha + ); + + // C function void glClearColorx ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha ) + + public native void glClearColorx( + int red, + int green, + int blue, + int alpha + ); + + // C function void glClearDepthf ( GLclampf depth ) + + public native void glClearDepthf( + float depth + ); + + // C function void glClearDepthx ( GLclampx depth ) + + public native void glClearDepthx( + int depth + ); + + // C function void glClearStencil ( GLint s ) + + public native void glClearStencil( + int s + ); + + // C function void glClientActiveTexture ( GLenum texture ) + + public native void glClientActiveTexture( + int texture + ); + + // C function void glColor4f ( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) + + public native void glColor4f( + float red, + float green, + float blue, + float alpha + ); + + // C function void glColor4x ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ) + + public native void glColor4x( + int red, + int green, + int blue, + int alpha + ); + + // C function void glColorMask ( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ) + + public native void glColorMask( + boolean red, + boolean green, + boolean blue, + boolean alpha + ); + + // C function void glColorPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + + private native void glColorPointerBounds( + int size, + int type, + int stride, + java.nio.Buffer pointer, + int remaining + ); + + public void glColorPointer( + int size, + int type, + int stride, + java.nio.Buffer pointer + ) { + if ((size == 4) && + ((type == GL_FLOAT) || + (type == GL_UNSIGNED_BYTE) || + (type == GL_FIXED)) && + (stride >= 0)) { + _colorPointer = pointer; + } + glColorPointerBounds( + size, + type, + stride, + pointer, + pointer.remaining() + ); + } + + // C function void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) + + public native void glCompressedTexImage2D( + int target, + int level, + int internalformat, + int width, + int height, + int border, + int imageSize, + java.nio.Buffer data + ); + + // C function void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) + + public native void glCompressedTexSubImage2D( + int target, + int level, + int xoffset, + int yoffset, + int width, + int height, + int format, + int imageSize, + java.nio.Buffer data + ); + + // C function void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) + + public native void glCopyTexImage2D( + int target, + int level, + int internalformat, + int x, + int y, + int width, + int height, + int border + ); + + // C function void glCopyTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ) + + public native void glCopyTexSubImage2D( + int target, + int level, + int xoffset, + int yoffset, + int x, + int y, + int width, + int height + ); + + // C function void glCullFace ( GLenum mode ) + + public native void glCullFace( + int mode + ); + + // C function void glDeleteTextures ( GLsizei n, const GLuint *textures ) + + public native void glDeleteTextures( + int n, + int[] textures, + int offset + ); + + // C function void glDeleteTextures ( GLsizei n, const GLuint *textures ) + + public native void glDeleteTextures( + int n, + java.nio.IntBuffer textures + ); + + // C function void glDepthFunc ( GLenum func ) + + public native void glDepthFunc( + int func + ); + + // C function void glDepthMask ( GLboolean flag ) + + public native void glDepthMask( + boolean flag + ); + + // C function void glDepthRangef ( GLclampf zNear, GLclampf zFar ) + + public native void glDepthRangef( + float zNear, + float zFar + ); + + // C function void glDepthRangex ( GLclampx zNear, GLclampx zFar ) + + public native void glDepthRangex( + int zNear, + int zFar + ); + + // C function void glDisable ( GLenum cap ) + + public native void glDisable( + int cap + ); + + // C function void glDisableClientState ( GLenum array ) + + public native void glDisableClientState( + int array + ); + + // C function void glDrawArrays ( GLenum mode, GLint first, GLsizei count ) + + public native void glDrawArrays( + int mode, + int first, + int count + ); + + // C function void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ) + + public native void glDrawElements( + int mode, + int count, + int type, + java.nio.Buffer indices + ); + + // C function void glEnable ( GLenum cap ) + + public native void glEnable( + int cap + ); + + // C function void glEnableClientState ( GLenum array ) + + public native void glEnableClientState( + int array + ); + + // C function void glFinish ( void ) + + public native void glFinish( + ); + + // C function void glFlush ( void ) + + public native void glFlush( + ); + + // C function void glFogf ( GLenum pname, GLfloat param ) + + public native void glFogf( + int pname, + float param + ); + + // C function void glFogfv ( GLenum pname, const GLfloat *params ) + + public native void glFogfv( + int pname, + float[] params, + int offset + ); + + // C function void glFogfv ( GLenum pname, const GLfloat *params ) + + public native void glFogfv( + int pname, + java.nio.FloatBuffer params + ); + + // C function void glFogx ( GLenum pname, GLfixed param ) + + public native void glFogx( + int pname, + int param + ); + + // C function void glFogxv ( GLenum pname, const GLfixed *params ) + + public native void glFogxv( + int pname, + int[] params, + int offset + ); + + // C function void glFogxv ( GLenum pname, const GLfixed *params ) + + public native void glFogxv( + int pname, + java.nio.IntBuffer params + ); + + // C function void glFrontFace ( GLenum mode ) + + public native void glFrontFace( + int mode + ); + + // C function void glFrustumf ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) + + public native void glFrustumf( + float left, + float right, + float bottom, + float top, + float zNear, + float zFar + ); + + // C function void glFrustumx ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) + + public native void glFrustumx( + int left, + int right, + int bottom, + int top, + int zNear, + int zFar + ); + + // C function void glGenTextures ( GLsizei n, GLuint *textures ) + + public native void glGenTextures( + int n, + int[] textures, + int offset + ); + + // C function void glGenTextures ( GLsizei n, GLuint *textures ) + + public native void glGenTextures( + int n, + java.nio.IntBuffer textures + ); + + // C function GLenum glGetError ( void ) + + public native int glGetError( + ); + + // C function void glGetIntegerv ( GLenum pname, GLint *params ) + + public native void glGetIntegerv( + int pname, + int[] params, + int offset + ); + + // C function void glGetIntegerv ( GLenum pname, GLint *params ) + + public native void glGetIntegerv( + int pname, + java.nio.IntBuffer params + ); + + // C function const GLubyte * glGetString ( GLenum name ) + + public native String _glGetString( + int name + ); + + public String glGetString( + int name + ) { + String returnValue; + returnValue = _glGetString( + name + ); + return returnValue; + } + + // C function void glHint ( GLenum target, GLenum mode ) + + public native void glHint( + int target, + int mode + ); + + // C function void glLightModelf ( GLenum pname, GLfloat param ) + + public native void glLightModelf( + int pname, + float param + ); + + // C function void glLightModelfv ( GLenum pname, const GLfloat *params ) + + public native void glLightModelfv( + int pname, + float[] params, + int offset + ); + + // C function void glLightModelfv ( GLenum pname, const GLfloat *params ) + + public native void glLightModelfv( + int pname, + java.nio.FloatBuffer params + ); + + // C function void glLightModelx ( GLenum pname, GLfixed param ) + + public native void glLightModelx( + int pname, + int param + ); + + // C function void glLightModelxv ( GLenum pname, const GLfixed *params ) + + public native void glLightModelxv( + int pname, + int[] params, + int offset + ); + + // C function void glLightModelxv ( GLenum pname, const GLfixed *params ) + + public native void glLightModelxv( + int pname, + java.nio.IntBuffer params + ); + + // C function void glLightf ( GLenum light, GLenum pname, GLfloat param ) + + public native void glLightf( + int light, + int pname, + float param + ); + + // C function void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) + + public native void glLightfv( + int light, + int pname, + float[] params, + int offset + ); + + // C function void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) + + public native void glLightfv( + int light, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glLightx ( GLenum light, GLenum pname, GLfixed param ) + + public native void glLightx( + int light, + int pname, + int param + ); + + // C function void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) + + public native void glLightxv( + int light, + int pname, + int[] params, + int offset + ); + + // C function void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) + + public native void glLightxv( + int light, + int pname, + java.nio.IntBuffer params + ); + + // C function void glLineWidth ( GLfloat width ) + + public native void glLineWidth( + float width + ); + + // C function void glLineWidthx ( GLfixed width ) + + public native void glLineWidthx( + int width + ); + + // C function void glLoadIdentity ( void ) + + public native void glLoadIdentity( + ); + + // C function void glLoadMatrixf ( const GLfloat *m ) + + public native void glLoadMatrixf( + float[] m, + int offset + ); + + // C function void glLoadMatrixf ( const GLfloat *m ) + + public native void glLoadMatrixf( + java.nio.FloatBuffer m + ); + + // C function void glLoadMatrixx ( const GLfixed *m ) + + public native void glLoadMatrixx( + int[] m, + int offset + ); + + // C function void glLoadMatrixx ( const GLfixed *m ) + + public native void glLoadMatrixx( + java.nio.IntBuffer m + ); + + // C function void glLogicOp ( GLenum opcode ) + + public native void glLogicOp( + int opcode + ); + + // C function void glMaterialf ( GLenum face, GLenum pname, GLfloat param ) + + public native void glMaterialf( + int face, + int pname, + float param + ); + + // C function void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) + + public native void glMaterialfv( + int face, + int pname, + float[] params, + int offset + ); + + // C function void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) + + public native void glMaterialfv( + int face, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glMaterialx ( GLenum face, GLenum pname, GLfixed param ) + + public native void glMaterialx( + int face, + int pname, + int param + ); + + // C function void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) + + public native void glMaterialxv( + int face, + int pname, + int[] params, + int offset + ); + + // C function void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) + + public native void glMaterialxv( + int face, + int pname, + java.nio.IntBuffer params + ); + + // C function void glMatrixMode ( GLenum mode ) + + public native void glMatrixMode( + int mode + ); + + // C function void glMultMatrixf ( const GLfloat *m ) + + public native void glMultMatrixf( + float[] m, + int offset + ); + + // C function void glMultMatrixf ( const GLfloat *m ) + + public native void glMultMatrixf( + java.nio.FloatBuffer m + ); + + // C function void glMultMatrixx ( const GLfixed *m ) + + public native void glMultMatrixx( + int[] m, + int offset + ); + + // C function void glMultMatrixx ( const GLfixed *m ) + + public native void glMultMatrixx( + java.nio.IntBuffer m + ); + + // C function void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) + + public native void glMultiTexCoord4f( + int target, + float s, + float t, + float r, + float q + ); + + // C function void glMultiTexCoord4x ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ) + + public native void glMultiTexCoord4x( + int target, + int s, + int t, + int r, + int q + ); + + // C function void glNormal3f ( GLfloat nx, GLfloat ny, GLfloat nz ) + + public native void glNormal3f( + float nx, + float ny, + float nz + ); + + // C function void glNormal3x ( GLfixed nx, GLfixed ny, GLfixed nz ) + + public native void glNormal3x( + int nx, + int ny, + int nz + ); + + // C function void glNormalPointer ( GLenum type, GLsizei stride, const GLvoid *pointer ) + + private native void glNormalPointerBounds( + int type, + int stride, + java.nio.Buffer pointer, + int remaining + ); + + public void glNormalPointer( + int type, + int stride, + java.nio.Buffer pointer + ) { + if (((type == GL_FLOAT) || + (type == GL_BYTE) || + (type == GL_SHORT) || + (type == GL_FIXED)) && + (stride >= 0)) { + _normalPointer = pointer; + } + glNormalPointerBounds( + type, + stride, + pointer, + pointer.remaining() + ); + } + + // C function void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) + + public native void glOrthof( + float left, + float right, + float bottom, + float top, + float zNear, + float zFar + ); + + // C function void glOrthox ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) + + public native void glOrthox( + int left, + int right, + int bottom, + int top, + int zNear, + int zFar + ); + + // C function void glPixelStorei ( GLenum pname, GLint param ) + + public native void glPixelStorei( + int pname, + int param + ); + + // C function void glPointSize ( GLfloat size ) + + public native void glPointSize( + float size + ); + + // C function void glPointSizex ( GLfixed size ) + + public native void glPointSizex( + int size + ); + + // C function void glPolygonOffset ( GLfloat factor, GLfloat units ) + + public native void glPolygonOffset( + float factor, + float units + ); + + // C function void glPolygonOffsetx ( GLfixed factor, GLfixed units ) + + public native void glPolygonOffsetx( + int factor, + int units + ); + + // C function void glPopMatrix ( void ) + + public native void glPopMatrix( + ); + + // C function void glPushMatrix ( void ) + + public native void glPushMatrix( + ); + + // C function void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) + + public native void glReadPixels( + int x, + int y, + int width, + int height, + int format, + int type, + java.nio.Buffer pixels + ); + + // C function void glRotatef ( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) + + public native void glRotatef( + float angle, + float x, + float y, + float z + ); + + // C function void glRotatex ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z ) + + public native void glRotatex( + int angle, + int x, + int y, + int z + ); + + // C function void glSampleCoverage ( GLclampf value, GLboolean invert ) + + public native void glSampleCoverage( + float value, + boolean invert + ); + + // C function void glSampleCoveragex ( GLclampx value, GLboolean invert ) + + public native void glSampleCoveragex( + int value, + boolean invert + ); + + // C function void glScalef ( GLfloat x, GLfloat y, GLfloat z ) + + public native void glScalef( + float x, + float y, + float z + ); + + // C function void glScalex ( GLfixed x, GLfixed y, GLfixed z ) + + public native void glScalex( + int x, + int y, + int z + ); + + // C function void glScissor ( GLint x, GLint y, GLsizei width, GLsizei height ) + + public native void glScissor( + int x, + int y, + int width, + int height + ); + + // C function void glShadeModel ( GLenum mode ) + + public native void glShadeModel( + int mode + ); + + // C function void glStencilFunc ( GLenum func, GLint ref, GLuint mask ) + + public native void glStencilFunc( + int func, + int ref, + int mask + ); + + // C function void glStencilMask ( GLuint mask ) + + public native void glStencilMask( + int mask + ); + + // C function void glStencilOp ( GLenum fail, GLenum zfail, GLenum zpass ) + + public native void glStencilOp( + int fail, + int zfail, + int zpass + ); + + // C function void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + + private native void glTexCoordPointerBounds( + int size, + int type, + int stride, + java.nio.Buffer pointer, + int remaining + ); + + public void glTexCoordPointer( + int size, + int type, + int stride, + java.nio.Buffer pointer + ) { + if (((size == 2) || + (size == 3) || + (size == 4)) && + ((type == GL_FLOAT) || + (type == GL_BYTE) || + (type == GL_SHORT) || + (type == GL_FIXED)) && + (stride >= 0)) { + _texCoordPointer = pointer; + } + glTexCoordPointerBounds( + size, + type, + stride, + pointer, + pointer.remaining() + ); + } + + // C function void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) + + public native void glTexEnvf( + int target, + int pname, + float param + ); + + // C function void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) + + public native void glTexEnvfv( + int target, + int pname, + float[] params, + int offset + ); + + // C function void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) + + public native void glTexEnvfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glTexEnvx ( GLenum target, GLenum pname, GLfixed param ) + + public native void glTexEnvx( + int target, + int pname, + int param + ); + + // C function void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) + + public native void glTexEnvxv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) + + public native void glTexEnvxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) + + public native void glTexImage2D( + int target, + int level, + int internalformat, + int width, + int height, + int border, + int format, + int type, + java.nio.Buffer pixels + ); + + // C function void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) + + public native void glTexParameterf( + int target, + int pname, + float param + ); + + // C function void glTexParameterx ( GLenum target, GLenum pname, GLfixed param ) + + public native void glTexParameterx( + int target, + int pname, + int param + ); + + // C function void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) + + public native void glTexSubImage2D( + int target, + int level, + int xoffset, + int yoffset, + int width, + int height, + int format, + int type, + java.nio.Buffer pixels + ); + + // C function void glTranslatef ( GLfloat x, GLfloat y, GLfloat z ) + + public native void glTranslatef( + float x, + float y, + float z + ); + + // C function void glTranslatex ( GLfixed x, GLfixed y, GLfixed z ) + + public native void glTranslatex( + int x, + int y, + int z + ); + + // C function void glVertexPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + + private native void glVertexPointerBounds( + int size, + int type, + int stride, + java.nio.Buffer pointer, + int remaining + ); + + public void glVertexPointer( + int size, + int type, + int stride, + java.nio.Buffer pointer + ) { + if (((size == 2) || + (size == 3) || + (size == 4)) && + ((type == GL_FLOAT) || + (type == GL_BYTE) || + (type == GL_SHORT) || + (type == GL_FIXED)) && + (stride >= 0)) { + _vertexPointer = pointer; + } + glVertexPointerBounds( + size, + type, + stride, + pointer, + pointer.remaining() + ); + } + + // C function void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) + + public native void glViewport( + int x, + int y, + int width, + int height + ); + + // C function GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) + + public native int glQueryMatrixxOES( + int[] mantissa, + int mantissaOffset, + int[] exponent, + int exponentOffset + ); + + // C function GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) + + public native int glQueryMatrixxOES( + java.nio.IntBuffer mantissa, + java.nio.IntBuffer exponent + ); + + // C function void glBindBuffer ( GLenum target, GLuint buffer ) + + public native void glBindBuffer( + int target, + int buffer + ); + + // C function void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage ) + + public native void glBufferData( + int target, + int size, + java.nio.Buffer data, + int usage + ); + + // C function void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) + + public native void glBufferSubData( + int target, + int offset, + int size, + java.nio.Buffer data + ); + + // C function void glClipPlanef ( GLenum plane, const GLfloat *equation ) + + public native void glClipPlanef( + int plane, + float[] equation, + int offset + ); + + // C function void glClipPlanef ( GLenum plane, const GLfloat *equation ) + + public native void glClipPlanef( + int plane, + java.nio.FloatBuffer equation + ); + + // C function void glClipPlanex ( GLenum plane, const GLfixed *equation ) + + public native void glClipPlanex( + int plane, + int[] equation, + int offset + ); + + // C function void glClipPlanex ( GLenum plane, const GLfixed *equation ) + + public native void glClipPlanex( + int plane, + java.nio.IntBuffer equation + ); + + // C function void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) + + public native void glColor4ub( + byte red, + byte green, + byte blue, + byte alpha + ); + + // C function void glColorPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) + + public native void glColorPointer( + int size, + int type, + int stride, + int offset + ); + + // C function void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) + + public native void glDeleteBuffers( + int n, + int[] buffers, + int offset + ); + + // C function void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) + + public native void glDeleteBuffers( + int n, + java.nio.IntBuffer buffers + ); + + // C function void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset ) + + public native void glDrawElements( + int mode, + int count, + int type, + int offset + ); + + // C function void glGenBuffers ( GLsizei n, GLuint *buffers ) + + public native void glGenBuffers( + int n, + int[] buffers, + int offset + ); + + // C function void glGenBuffers ( GLsizei n, GLuint *buffers ) + + public native void glGenBuffers( + int n, + java.nio.IntBuffer buffers + ); + + // C function void glGetBooleanv ( GLenum pname, GLboolean *params ) + + public native void glGetBooleanv( + int pname, + boolean[] params, + int offset + ); + + // C function void glGetBooleanv ( GLenum pname, GLboolean *params ) + + public native void glGetBooleanv( + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) + + public native void glGetBufferParameteriv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) + + public native void glGetBufferParameteriv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) + + public native void glGetClipPlanef( + int pname, + float[] eqn, + int offset + ); + + // C function void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) + + public native void glGetClipPlanef( + int pname, + java.nio.FloatBuffer eqn + ); + + // C function void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) + + public native void glGetClipPlanex( + int pname, + int[] eqn, + int offset + ); + + // C function void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) + + public native void glGetClipPlanex( + int pname, + java.nio.IntBuffer eqn + ); + + // C function void glGetFixedv ( GLenum pname, GLfixed *params ) + + public native void glGetFixedv( + int pname, + int[] params, + int offset + ); + + // C function void glGetFixedv ( GLenum pname, GLfixed *params ) + + public native void glGetFixedv( + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetFloatv ( GLenum pname, GLfloat *params ) + + public native void glGetFloatv( + int pname, + float[] params, + int offset + ); + + // C function void glGetFloatv ( GLenum pname, GLfloat *params ) + + public native void glGetFloatv( + int pname, + java.nio.FloatBuffer params + ); + + // C function void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) + + public native void glGetLightfv( + int light, + int pname, + float[] params, + int offset + ); + + // C function void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) + + public native void glGetLightfv( + int light, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) + + public native void glGetLightxv( + int light, + int pname, + int[] params, + int offset + ); + + // C function void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) + + public native void glGetLightxv( + int light, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) + + public native void glGetMaterialfv( + int face, + int pname, + float[] params, + int offset + ); + + // C function void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) + + public native void glGetMaterialfv( + int face, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) + + public native void glGetMaterialxv( + int face, + int pname, + int[] params, + int offset + ); + + // C function void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) + + public native void glGetMaterialxv( + int face, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) + + public native void glGetTexEnviv( + int env, + int pname, + int[] params, + int offset + ); + + // C function void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) + + public native void glGetTexEnviv( + int env, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) + + public native void glGetTexEnvxv( + int env, + int pname, + int[] params, + int offset + ); + + // C function void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) + + public native void glGetTexEnvxv( + int env, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) + + public native void glGetTexParameterfv( + int target, + int pname, + float[] params, + int offset + ); + + // C function void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) + + public native void glGetTexParameterfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) + + public native void glGetTexParameteriv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) + + public native void glGetTexParameteriv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) + + public native void glGetTexParameterxv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) + + public native void glGetTexParameterxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function GLboolean glIsBuffer ( GLuint buffer ) + + public native boolean glIsBuffer( + int buffer + ); + + // C function GLboolean glIsEnabled ( GLenum cap ) + + public native boolean glIsEnabled( + int cap + ); + + // C function GLboolean glIsTexture ( GLuint texture ) + + public native boolean glIsTexture( + int texture + ); + + // C function void glNormalPointer ( GLenum type, GLsizei stride, GLint offset ) + + public native void glNormalPointer( + int type, + int stride, + int offset + ); + + // C function void glPointParameterf ( GLenum pname, GLfloat param ) + + public native void glPointParameterf( + int pname, + float param + ); + + // C function void glPointParameterfv ( GLenum pname, const GLfloat *params ) + + public native void glPointParameterfv( + int pname, + float[] params, + int offset + ); + + // C function void glPointParameterfv ( GLenum pname, const GLfloat *params ) + + public native void glPointParameterfv( + int pname, + java.nio.FloatBuffer params + ); + + // C function void glPointParameterx ( GLenum pname, GLfixed param ) + + public native void glPointParameterx( + int pname, + int param + ); + + // C function void glPointParameterxv ( GLenum pname, const GLfixed *params ) + + public native void glPointParameterxv( + int pname, + int[] params, + int offset + ); + + // C function void glPointParameterxv ( GLenum pname, const GLfixed *params ) + + public native void glPointParameterxv( + int pname, + java.nio.IntBuffer params + ); + + // C function void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer ) + + public native void glPointSizePointerOES( + int type, + int stride, + java.nio.Buffer pointer + ); + + // C function void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) + + public native void glTexCoordPointer( + int size, + int type, + int stride, + int offset + ); + + // C function void glTexEnvi ( GLenum target, GLenum pname, GLint param ) + + public native void glTexEnvi( + int target, + int pname, + int param + ); + + // C function void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) + + public native void glTexEnviv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) + + public native void glTexEnviv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) + + public native void glTexParameterfv( + int target, + int pname, + float[] params, + int offset + ); + + // C function void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) + + public native void glTexParameterfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glTexParameteri ( GLenum target, GLenum pname, GLint param ) + + public native void glTexParameteri( + int target, + int pname, + int param + ); + + // C function void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) + + public native void glTexParameteriv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) + + public native void glTexParameteriv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) + + public native void glTexParameterxv( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) + + public native void glTexParameterxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) + + public native void glVertexPointer( + int size, + int type, + int stride, + int offset + ); + + // C function void glCurrentPaletteMatrixOES ( GLuint matrixpaletteindex ) + + public native void glCurrentPaletteMatrixOES( + int matrixpaletteindex + ); + + // C function void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height ) + + public native void glDrawTexfOES( + float x, + float y, + float z, + float width, + float height + ); + + // C function void glDrawTexfvOES ( const GLfloat *coords ) + + public native void glDrawTexfvOES( + float[] coords, + int offset + ); + + // C function void glDrawTexfvOES ( const GLfloat *coords ) + + public native void glDrawTexfvOES( + java.nio.FloatBuffer coords + ); + + // C function void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height ) + + public native void glDrawTexiOES( + int x, + int y, + int z, + int width, + int height + ); + + // C function void glDrawTexivOES ( const GLint *coords ) + + public native void glDrawTexivOES( + int[] coords, + int offset + ); + + // C function void glDrawTexivOES ( const GLint *coords ) + + public native void glDrawTexivOES( + java.nio.IntBuffer coords + ); + + // C function void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height ) + + public native void glDrawTexsOES( + short x, + short y, + short z, + short width, + short height + ); + + // C function void glDrawTexsvOES ( const GLshort *coords ) + + public native void glDrawTexsvOES( + short[] coords, + int offset + ); + + // C function void glDrawTexsvOES ( const GLshort *coords ) + + public native void glDrawTexsvOES( + java.nio.ShortBuffer coords + ); + + // C function void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height ) + + public native void glDrawTexxOES( + int x, + int y, + int z, + int width, + int height + ); + + // C function void glDrawTexxvOES ( const GLfixed *coords ) + + public native void glDrawTexxvOES( + int[] coords, + int offset + ); + + // C function void glDrawTexxvOES ( const GLfixed *coords ) + + public native void glDrawTexxvOES( + java.nio.IntBuffer coords + ); + + // C function void glLoadPaletteFromModelViewMatrixOES ( void ) + + public native void glLoadPaletteFromModelViewMatrixOES( + ); + + // C function void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + + public native void glMatrixIndexPointerOES( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + // C function void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, GLint offset ) + + public native void glMatrixIndexPointerOES( + int size, + int type, + int stride, + int offset + ); + + // C function void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + + public native void glWeightPointerOES( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + // C function void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, GLint offset ) + + public native void glWeightPointerOES( + int size, + int type, + int stride, + int offset + ); + + // C function void glBindFramebufferOES ( GLint target, GLint framebuffer ) + + public native void glBindFramebufferOES( + int target, + int framebuffer + ); + + // C function void glBindRenderbufferOES ( GLint target, GLint renderbuffer ) + + public native void glBindRenderbufferOES( + int target, + int renderbuffer + ); + + // C function void glBlendEquation ( GLint mode ) + + public native void glBlendEquation( + int mode + ); + + // C function void glBlendEquationSeparate ( GLint modeRGB, GLint modeAlpha ) + + public native void glBlendEquationSeparate( + int modeRGB, + int modeAlpha + ); + + // C function void glBlendFuncSeparate ( GLint srcRGB, GLint dstRGB, GLint srcAlpha, GLint dstAlpha ) + + public native void glBlendFuncSeparate( + int srcRGB, + int dstRGB, + int srcAlpha, + int dstAlpha + ); + + // C function GLint glCheckFramebufferStatusOES ( GLint target ) + + public native int glCheckFramebufferStatusOES( + int target + ); + + // C function void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers ) + + public native void glDeleteFramebuffersOES( + int n, + int[] framebuffers, + int offset + ); + + // C function void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers ) + + public native void glDeleteFramebuffersOES( + int n, + java.nio.IntBuffer framebuffers + ); + + // C function void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers ) + + public native void glDeleteRenderbuffersOES( + int n, + int[] renderbuffers, + int offset + ); + + // C function void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers ) + + public native void glDeleteRenderbuffersOES( + int n, + java.nio.IntBuffer renderbuffers + ); + + // C function void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer ) + + public native void glFramebufferRenderbufferOES( + int target, + int attachment, + int renderbuffertarget, + int renderbuffer + ); + + // C function void glFramebufferTexture2DOES ( GLint target, GLint attachment, GLint textarget, GLint texture, GLint level ) + + public native void glFramebufferTexture2DOES( + int target, + int attachment, + int textarget, + int texture, + int level + ); + + // C function void glGenerateMipmapOES ( GLint target ) + + public native void glGenerateMipmapOES( + int target + ); + + // C function void glGenFramebuffersOES ( GLint n, GLint *framebuffers ) + + public native void glGenFramebuffersOES( + int n, + int[] framebuffers, + int offset + ); + + // C function void glGenFramebuffersOES ( GLint n, GLint *framebuffers ) + + public native void glGenFramebuffersOES( + int n, + java.nio.IntBuffer framebuffers + ); + + // C function void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers ) + + public native void glGenRenderbuffersOES( + int n, + int[] renderbuffers, + int offset + ); + + // C function void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers ) + + public native void glGenRenderbuffersOES( + int n, + java.nio.IntBuffer renderbuffers + ); + + // C function void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) + + public native void glGetFramebufferAttachmentParameterivOES( + int target, + int attachment, + int pname, + int[] params, + int offset + ); + + // C function void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) + + public native void glGetFramebufferAttachmentParameterivOES( + int target, + int attachment, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) + + public native void glGetRenderbufferParameterivOES( + int target, + int pname, + int[] params, + int offset + ); + + // C function void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) + + public native void glGetRenderbufferParameterivOES( + int target, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) + + public native void glGetTexGenfv( + int coord, + int pname, + float[] params, + int offset + ); + + // C function void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) + + public native void glGetTexGenfv( + int coord, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) + + public native void glGetTexGeniv( + int coord, + int pname, + int[] params, + int offset + ); + + // C function void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) + + public native void glGetTexGeniv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + // C function void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) + + public native void glGetTexGenxv( + int coord, + int pname, + int[] params, + int offset + ); + + // C function void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) + + public native void glGetTexGenxv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + // C function GLboolean glIsFramebufferOES ( GLint framebuffer ) + + public native boolean glIsFramebufferOES( + int framebuffer + ); + + // C function GLboolean glIsRenderbufferOES ( GLint renderbuffer ) + + public native boolean glIsRenderbufferOES( + int renderbuffer + ); + + // C function void glRenderbufferStorageOES ( GLint target, GLint internalformat, GLint width, GLint height ) + + public native void glRenderbufferStorageOES( + int target, + int internalformat, + int width, + int height + ); + + // C function void glTexGenf ( GLint coord, GLint pname, GLfloat param ) + + public native void glTexGenf( + int coord, + int pname, + float param + ); + + // C function void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) + + public native void glTexGenfv( + int coord, + int pname, + float[] params, + int offset + ); + + // C function void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) + + public native void glTexGenfv( + int coord, + int pname, + java.nio.FloatBuffer params + ); + + // C function void glTexGeni ( GLint coord, GLint pname, GLint param ) + + public native void glTexGeni( + int coord, + int pname, + int param + ); + + // C function void glTexGeniv ( GLint coord, GLint pname, GLint *params ) + + public native void glTexGeniv( + int coord, + int pname, + int[] params, + int offset + ); + + // C function void glTexGeniv ( GLint coord, GLint pname, GLint *params ) + + public native void glTexGeniv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + // C function void glTexGenx ( GLint coord, GLint pname, GLint param ) + + public native void glTexGenx( + int coord, + int pname, + int param + ); + + // C function void glTexGenxv ( GLint coord, GLint pname, GLint *params ) + + public native void glTexGenxv( + int coord, + int pname, + int[] params, + int offset + ); + + // C function void glTexGenxv ( GLint coord, GLint pname, GLint *params ) + + public native void glTexGenxv( + int coord, + int pname, + java.nio.IntBuffer params + ); + +} diff --git a/opengl/java/javax/microedition/khronos/egl/EGL.java b/opengl/java/javax/microedition/khronos/egl/EGL.java new file mode 100644 index 0000000..b743968 --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGL.java @@ -0,0 +1,22 @@ +/* +** +** Copyright 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 javax.microedition.khronos.egl; + +public interface EGL { +} + diff --git a/opengl/java/javax/microedition/khronos/egl/EGL10.java b/opengl/java/javax/microedition/khronos/egl/EGL10.java new file mode 100644 index 0000000..2ae793a --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGL10.java @@ -0,0 +1,121 @@ +/* + * 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 javax.microedition.khronos.egl; + +import java.lang.String; + +public interface EGL10 extends EGL { + int EGL_SUCCESS = 0x3000; + int EGL_NOT_INITIALIZED = 0x3001; + int EGL_BAD_ACCESS = 0x3002; + int EGL_BAD_ALLOC = 0x3003; + int EGL_BAD_ATTRIBUTE = 0x3004; + int EGL_BAD_CONFIG = 0x3005; + int EGL_BAD_CONTEXT = 0x3006; + int EGL_BAD_CURRENT_SURFACE = 0x3007; + int EGL_BAD_DISPLAY = 0x3008; + int EGL_BAD_MATCH = 0x3009; + int EGL_BAD_NATIVE_PIXMAP = 0x300A; + int EGL_BAD_NATIVE_WINDOW = 0x300B; + int EGL_BAD_PARAMETER = 0x300C; + int EGL_BAD_SURFACE = 0x300D; + int EGL_BUFFER_SIZE = 0x3020; + int EGL_ALPHA_SIZE = 0x3021; + int EGL_BLUE_SIZE = 0x3022; + int EGL_GREEN_SIZE = 0x3023; + int EGL_RED_SIZE = 0x3024; + int EGL_DEPTH_SIZE = 0x3025; + int EGL_STENCIL_SIZE = 0x3026; + int EGL_CONFIG_CAVEAT = 0x3027; + int EGL_CONFIG_ID = 0x3028; + int EGL_LEVEL = 0x3029; + int EGL_MAX_PBUFFER_HEIGHT = 0x302A; + int EGL_MAX_PBUFFER_PIXELS = 0x302B; + int EGL_MAX_PBUFFER_WIDTH = 0x302C; + int EGL_NATIVE_RENDERABLE = 0x302D; + int EGL_NATIVE_VISUAL_ID = 0x302E; + int EGL_NATIVE_VISUAL_TYPE = 0x302F; + int EGL_SAMPLES = 0x3031; + int EGL_SAMPLE_BUFFERS = 0x3032; + int EGL_SURFACE_TYPE = 0x3033; + int EGL_TRANSPARENT_TYPE = 0x3034; + int EGL_TRANSPARENT_BLUE_VALUE = 0x3035; + int EGL_TRANSPARENT_GREEN_VALUE = 0x3036; + int EGL_TRANSPARENT_RED_VALUE = 0x3037; + int EGL_NONE = 0x3038; + int EGL_LUMINANCE_SIZE = 0x303D; + int EGL_ALPHA_MASK_SIZE = 0x303E; + int EGL_COLOR_BUFFER_TYPE = 0x303F; + int EGL_RENDERABLE_TYPE = 0x3040; + int EGL_SLOW_CONFIG = 0x3050; + int EGL_NON_CONFORMANT_CONFIG = 0x3051; + int EGL_TRANSPARENT_RGB = 0x3052; + int EGL_RGB_BUFFER = 0x308E; + int EGL_LUMINANCE_BUFFER = 0x308F; + int EGL_VENDOR = 0x3053; + int EGL_VERSION = 0x3054; + int EGL_EXTENSIONS = 0x3055; + int EGL_HEIGHT = 0x3056; + int EGL_WIDTH = 0x3057; + int EGL_LARGEST_PBUFFER = 0x3058; + int EGL_RENDER_BUFFER = 0x3086; + int EGL_COLORSPACE = 0x3087; + int EGL_ALPHA_FORMAT = 0x3088; + int EGL_HORIZONTAL_RESOLUTION = 0x3090; + int EGL_VERTICAL_RESOLUTION = 0x3091; + int EGL_PIXEL_ASPECT_RATIO = 0x3092; + int EGL_SINGLE_BUFFER = 0x3085; + int EGL_CORE_NATIVE_ENGINE = 0x305B; + int EGL_DRAW = 0x3059; + int EGL_READ = 0x305A; + + int EGL_DONT_CARE = -1; + + int EGL_PBUFFER_BIT = 0x01; + int EGL_PIXMAP_BIT = 0x02; + int EGL_WINDOW_BIT = 0x04; + + Object EGL_DEFAULT_DISPLAY = null; + EGLDisplay EGL_NO_DISPLAY = new com.google.android.gles_jni.EGLDisplayImpl(0); + EGLContext EGL_NO_CONTEXT = new com.google.android.gles_jni.EGLContextImpl(0); + EGLSurface EGL_NO_SURFACE = new com.google.android.gles_jni.EGLSurfaceImpl(0); + + boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config); + boolean eglCopyBuffers(EGLDisplay display, EGLSurface surface, Object native_pixmap); + EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list); + EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list); + EGLSurface eglCreatePixmapSurface(EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list); + EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list); + boolean eglDestroyContext(EGLDisplay display, EGLContext context); + boolean eglDestroySurface(EGLDisplay display, EGLSurface surface); + boolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, int attribute, int[] value); + boolean eglGetConfigs(EGLDisplay display, EGLConfig[] configs, int config_size, int[] num_config); + EGLContext eglGetCurrentContext(); + EGLDisplay eglGetCurrentDisplay(); + EGLSurface eglGetCurrentSurface(int readdraw); + EGLDisplay eglGetDisplay(Object native_display); + int eglGetError(); + boolean eglInitialize(EGLDisplay display, int[] major_minor); + boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context); + boolean eglQueryContext(EGLDisplay display, EGLContext context, int attribute, int[] value); + String eglQueryString(EGLDisplay display, int name); + boolean eglQuerySurface(EGLDisplay display, EGLSurface surface, int attribute, int[] value); + boolean eglSwapBuffers(EGLDisplay display, EGLSurface surface); + boolean eglTerminate(EGLDisplay display); + boolean eglWaitGL(); + boolean eglWaitNative(int engine, Object bindTarget); +} diff --git a/opengl/java/javax/microedition/khronos/egl/EGL11.java b/opengl/java/javax/microedition/khronos/egl/EGL11.java new file mode 100644 index 0000000..41d62e6 --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGL11.java @@ -0,0 +1,21 @@ +/* + * 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 javax.microedition.khronos.egl; + +public interface EGL11 extends EGL10 { + int EGL_CONTEXT_LOST = 0x300E; +} diff --git a/opengl/java/javax/microedition/khronos/egl/EGLConfig.java b/opengl/java/javax/microedition/khronos/egl/EGLConfig.java new file mode 100644 index 0000000..a1e496c --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGLConfig.java @@ -0,0 +1,22 @@ +/* +** +** Copyright 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 javax.microedition.khronos.egl; + +public abstract class EGLConfig +{ +} diff --git a/opengl/java/javax/microedition/khronos/egl/EGLContext.java b/opengl/java/javax/microedition/khronos/egl/EGLContext.java new file mode 100644 index 0000000..fc94492 --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGLContext.java @@ -0,0 +1,31 @@ +/* +** +** Copyright 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 javax.microedition.khronos.egl; + +import javax.microedition.khronos.opengles.GL; + +public abstract class EGLContext +{ + private static final EGL EGL_INSTANCE = new com.google.android.gles_jni.EGLImpl(); + + public static EGL getEGL() { + return EGL_INSTANCE; + } + + public abstract GL getGL(); +} diff --git a/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java b/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java new file mode 100644 index 0000000..cd8a755 --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java @@ -0,0 +1,22 @@ +/* +** +** Copyright 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 javax.microedition.khronos.egl; + +public abstract class EGLDisplay +{ +} diff --git a/opengl/java/javax/microedition/khronos/egl/EGLSurface.java b/opengl/java/javax/microedition/khronos/egl/EGLSurface.java new file mode 100644 index 0000000..5349bc1 --- /dev/null +++ b/opengl/java/javax/microedition/khronos/egl/EGLSurface.java @@ -0,0 +1,22 @@ +/* +** +** Copyright 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 javax.microedition.khronos.egl; + +public abstract class EGLSurface +{ +} diff --git a/opengl/java/javax/microedition/khronos/opengles/GL.java b/opengl/java/javax/microedition/khronos/opengles/GL.java new file mode 100644 index 0000000..3b78f3d --- /dev/null +++ b/opengl/java/javax/microedition/khronos/opengles/GL.java @@ -0,0 +1,22 @@ +/* //device/java/android/javax/microedition/khronos/opengles/GL.java +** +** Copyright 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 javax.microedition.khronos.opengles; + +public interface GL { +} + diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10.java b/opengl/java/javax/microedition/khronos/opengles/GL10.java new file mode 100644 index 0000000..4fcfb52 --- /dev/null +++ b/opengl/java/javax/microedition/khronos/opengles/GL10.java @@ -0,0 +1,972 @@ +/* //device/java/android/javax/microedition/khronos/opengles/GL10.java +** +** Copyright 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. +*/ + +// This source file is automatically generated + +package javax.microedition.khronos.opengles; + +public interface GL10 extends GL { + int GL_ADD = 0x0104; + int GL_ALIASED_LINE_WIDTH_RANGE = 0x846E; + int GL_ALIASED_POINT_SIZE_RANGE = 0x846D; + int GL_ALPHA = 0x1906; + int GL_ALPHA_BITS = 0x0D55; + int GL_ALPHA_TEST = 0x0BC0; + int GL_ALWAYS = 0x0207; + int GL_AMBIENT = 0x1200; + int GL_AMBIENT_AND_DIFFUSE = 0x1602; + int GL_AND = 0x1501; + int GL_AND_INVERTED = 0x1504; + int GL_AND_REVERSE = 0x1502; + int GL_BACK = 0x0405; + int GL_BLEND = 0x0BE2; + int GL_BLUE_BITS = 0x0D54; + int GL_BYTE = 0x1400; + int GL_CCW = 0x0901; + int GL_CLAMP_TO_EDGE = 0x812F; + int GL_CLEAR = 0x1500; + int GL_COLOR_ARRAY = 0x8076; + int GL_COLOR_BUFFER_BIT = 0x4000; + int GL_COLOR_LOGIC_OP = 0x0BF2; + int GL_COLOR_MATERIAL = 0x0B57; + int GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3; + int GL_CONSTANT_ATTENUATION = 0x1207; + int GL_COPY = 0x1503; + int GL_COPY_INVERTED = 0x150C; + int GL_CULL_FACE = 0x0B44; + int GL_CW = 0x0900; + int GL_DECAL = 0x2101; + int GL_DECR = 0x1E03; + int GL_DEPTH_BITS = 0x0D56; + int GL_DEPTH_BUFFER_BIT = 0x0100; + int GL_DEPTH_TEST = 0x0B71; + int GL_DIFFUSE = 0x1201; + int GL_DITHER = 0x0BD0; + int GL_DONT_CARE = 0x1100; + int GL_DST_ALPHA = 0x0304; + int GL_DST_COLOR = 0x0306; + int GL_EMISSION = 0x1600; + int GL_EQUAL = 0x0202; + int GL_EQUIV = 0x1509; + int GL_EXP = 0x0800; + int GL_EXP2 = 0x0801; + int GL_EXTENSIONS = 0x1F03; + int GL_FALSE = 0; + int GL_FASTEST = 0x1101; + int GL_FIXED = 0x140C; + int GL_FLAT = 0x1D00; + int GL_FLOAT = 0x1406; + int GL_FOG = 0x0B60; + int GL_FOG_COLOR = 0x0B66; + int GL_FOG_DENSITY = 0x0B62; + int GL_FOG_END = 0x0B64; + int GL_FOG_HINT = 0x0C54; + int GL_FOG_MODE = 0x0B65; + int GL_FOG_START = 0x0B63; + int GL_FRONT = 0x0404; + int GL_FRONT_AND_BACK = 0x0408; + int GL_GEQUAL = 0x0206; + int GL_GREATER = 0x0204; + int GL_GREEN_BITS = 0x0D53; + int GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES = 0x8B9B; + int GL_IMPLEMENTATION_COLOR_READ_TYPE_OES = 0x8B9A; + int GL_INCR = 0x1E02; + int GL_INVALID_ENUM = 0x0500; + int GL_INVALID_OPERATION = 0x0502; + int GL_INVALID_VALUE = 0x0501; + int GL_INVERT = 0x150A; + int GL_KEEP = 0x1E00; + int GL_LEQUAL = 0x0203; + int GL_LESS = 0x0201; + int GL_LIGHT_MODEL_AMBIENT = 0x0B53; + int GL_LIGHT_MODEL_TWO_SIDE = 0x0B52; + int GL_LIGHT0 = 0x4000; + int GL_LIGHT1 = 0x4001; + int GL_LIGHT2 = 0x4002; + int GL_LIGHT3 = 0x4003; + int GL_LIGHT4 = 0x4004; + int GL_LIGHT5 = 0x4005; + int GL_LIGHT6 = 0x4006; + int GL_LIGHT7 = 0x4007; + int GL_LIGHTING = 0x0B50; + int GL_LINE_LOOP = 0x0002; + int GL_LINE_SMOOTH = 0x0B20; + int GL_LINE_SMOOTH_HINT = 0x0C52; + int GL_LINE_STRIP = 0x0003; + int GL_LINEAR = 0x2601; + int GL_LINEAR_ATTENUATION = 0x1208; + int GL_LINEAR_MIPMAP_LINEAR = 0x2703; + int GL_LINEAR_MIPMAP_NEAREST = 0x2701; + int GL_LINES = 0x0001; + int GL_LUMINANCE = 0x1909; + int GL_LUMINANCE_ALPHA = 0x190A; + int GL_MAX_ELEMENTS_INDICES = 0x80E9; + int GL_MAX_ELEMENTS_VERTICES = 0x80E8; + int GL_MAX_LIGHTS = 0x0D31; + int GL_MAX_MODELVIEW_STACK_DEPTH = 0x0D36; + int GL_MAX_PROJECTION_STACK_DEPTH = 0x0D38; + int GL_MAX_TEXTURE_SIZE = 0x0D33; + int GL_MAX_TEXTURE_STACK_DEPTH = 0x0D39; + int GL_MAX_TEXTURE_UNITS = 0x84E2; + int GL_MAX_VIEWPORT_DIMS = 0x0D3A; + int GL_MODELVIEW = 0x1700; + int GL_MODULATE = 0x2100; + int GL_MULTISAMPLE = 0x809D; + int GL_NAND = 0x150E; + int GL_NEAREST = 0x2600; + int GL_NEAREST_MIPMAP_LINEAR = 0x2702; + int GL_NEAREST_MIPMAP_NEAREST = 0x2700; + int GL_NEVER = 0x0200; + int GL_NICEST = 0x1102; + int GL_NO_ERROR = 0; + int GL_NOOP = 0x1505; + int GL_NOR = 0x1508; + int GL_NORMAL_ARRAY = 0x8075; + int GL_NORMALIZE = 0x0BA1; + int GL_NOTEQUAL = 0x0205; + int GL_NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2; + int GL_ONE = 1; + int GL_ONE_MINUS_DST_ALPHA = 0x0305; + int GL_ONE_MINUS_DST_COLOR = 0x0307; + int GL_ONE_MINUS_SRC_ALPHA = 0x0303; + int GL_ONE_MINUS_SRC_COLOR = 0x0301; + int GL_OR = 0x1507; + int GL_OR_INVERTED = 0x150D; + int GL_OR_REVERSE = 0x150B; + int GL_OUT_OF_MEMORY = 0x0505; + int GL_PACK_ALIGNMENT = 0x0D05; + int GL_PALETTE4_R5_G6_B5_OES = 0x8B92; + int GL_PALETTE4_RGB5_A1_OES = 0x8B94; + int GL_PALETTE4_RGB8_OES = 0x8B90; + int GL_PALETTE4_RGBA4_OES = 0x8B93; + int GL_PALETTE4_RGBA8_OES = 0x8B91; + int GL_PALETTE8_R5_G6_B5_OES = 0x8B97; + int GL_PALETTE8_RGB5_A1_OES = 0x8B99; + int GL_PALETTE8_RGB8_OES = 0x8B95; + int GL_PALETTE8_RGBA4_OES = 0x8B98; + int GL_PALETTE8_RGBA8_OES = 0x8B96; + int GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50; + int GL_POINT_SMOOTH = 0x0B10; + int GL_POINT_SMOOTH_HINT = 0x0C51; + int GL_POINTS = 0x0000; + int GL_POINT_FADE_THRESHOLD_SIZE = 0x8128; + int GL_POINT_SIZE = 0x0B11; + int GL_POLYGON_OFFSET_FILL = 0x8037; + int GL_POLYGON_SMOOTH_HINT = 0x0C53; + int GL_POSITION = 0x1203; + int GL_PROJECTION = 0x1701; + int GL_QUADRATIC_ATTENUATION = 0x1209; + int GL_RED_BITS = 0x0D52; + int GL_RENDERER = 0x1F01; + int GL_REPEAT = 0x2901; + int GL_REPLACE = 0x1E01; + int GL_RESCALE_NORMAL = 0x803A; + int GL_RGB = 0x1907; + int GL_RGBA = 0x1908; + int GL_SAMPLE_ALPHA_TO_COVERAGE = 0x809E; + int GL_SAMPLE_ALPHA_TO_ONE = 0x809F; + int GL_SAMPLE_COVERAGE = 0x80A0; + int GL_SCISSOR_TEST = 0x0C11; + int GL_SET = 0x150F; + int GL_SHININESS = 0x1601; + int GL_SHORT = 0x1402; + int GL_SMOOTH = 0x1D01; + int GL_SMOOTH_LINE_WIDTH_RANGE = 0x0B22; + int GL_SMOOTH_POINT_SIZE_RANGE = 0x0B12; + int GL_SPECULAR = 0x1202; + int GL_SPOT_CUTOFF = 0x1206; + int GL_SPOT_DIRECTION = 0x1204; + int GL_SPOT_EXPONENT = 0x1205; + int GL_SRC_ALPHA = 0x0302; + int GL_SRC_ALPHA_SATURATE = 0x0308; + int GL_SRC_COLOR = 0x0300; + int GL_STACK_OVERFLOW = 0x0503; + int GL_STACK_UNDERFLOW = 0x0504; + int GL_STENCIL_BITS = 0x0D57; + int GL_STENCIL_BUFFER_BIT = 0x0400; + int GL_STENCIL_TEST = 0x0B90; + int GL_SUBPIXEL_BITS = 0x0D50; + int GL_TEXTURE = 0x1702; + int GL_TEXTURE_2D = 0x0DE1; + int GL_TEXTURE_COORD_ARRAY = 0x8078; + int GL_TEXTURE_ENV = 0x2300; + int GL_TEXTURE_ENV_COLOR = 0x2201; + int GL_TEXTURE_ENV_MODE = 0x2200; + int GL_TEXTURE_MAG_FILTER = 0x2800; + int GL_TEXTURE_MIN_FILTER = 0x2801; + int GL_TEXTURE_WRAP_S = 0x2802; + int GL_TEXTURE_WRAP_T = 0x2803; + int GL_TEXTURE0 = 0x84C0; + int GL_TEXTURE1 = 0x84C1; + int GL_TEXTURE2 = 0x84C2; + int GL_TEXTURE3 = 0x84C3; + int GL_TEXTURE4 = 0x84C4; + int GL_TEXTURE5 = 0x84C5; + int GL_TEXTURE6 = 0x84C6; + int GL_TEXTURE7 = 0x84C7; + int GL_TEXTURE8 = 0x84C8; + int GL_TEXTURE9 = 0x84C9; + int GL_TEXTURE10 = 0x84CA; + int GL_TEXTURE11 = 0x84CB; + int GL_TEXTURE12 = 0x84CC; + int GL_TEXTURE13 = 0x84CD; + int GL_TEXTURE14 = 0x84CE; + int GL_TEXTURE15 = 0x84CF; + int GL_TEXTURE16 = 0x84D0; + int GL_TEXTURE17 = 0x84D1; + int GL_TEXTURE18 = 0x84D2; + int GL_TEXTURE19 = 0x84D3; + int GL_TEXTURE20 = 0x84D4; + int GL_TEXTURE21 = 0x84D5; + int GL_TEXTURE22 = 0x84D6; + int GL_TEXTURE23 = 0x84D7; + int GL_TEXTURE24 = 0x84D8; + int GL_TEXTURE25 = 0x84D9; + int GL_TEXTURE26 = 0x84DA; + int GL_TEXTURE27 = 0x84DB; + int GL_TEXTURE28 = 0x84DC; + int GL_TEXTURE29 = 0x84DD; + int GL_TEXTURE30 = 0x84DE; + int GL_TEXTURE31 = 0x84DF; + int GL_TRIANGLE_FAN = 0x0006; + int GL_TRIANGLE_STRIP = 0x0005; + int GL_TRIANGLES = 0x0004; + int GL_TRUE = 1; + int GL_UNPACK_ALIGNMENT = 0x0CF5; + int GL_UNSIGNED_BYTE = 0x1401; + int GL_UNSIGNED_SHORT = 0x1403; + int GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033; + int GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034; + int GL_UNSIGNED_SHORT_5_6_5 = 0x8363; + int GL_VENDOR = 0x1F00; + int GL_VERSION = 0x1F02; + int GL_VERTEX_ARRAY = 0x8074; + int GL_XOR = 0x1506; + int GL_ZERO = 0; + + void glActiveTexture( + int texture + ); + + void glAlphaFunc( + int func, + float ref + ); + + void glAlphaFuncx( + int func, + int ref + ); + + void glBindTexture( + int target, + int texture + ); + + void glBlendFunc( + int sfactor, + int dfactor + ); + + void glClear( + int mask + ); + + void glClearColor( + float red, + float green, + float blue, + float alpha + ); + + void glClearColorx( + int red, + int green, + int blue, + int alpha + ); + + void glClearDepthf( + float depth + ); + + void glClearDepthx( + int depth + ); + + void glClearStencil( + int s + ); + + void glClientActiveTexture( + int texture + ); + + void glColor4f( + float red, + float green, + float blue, + float alpha + ); + + void glColor4x( + int red, + int green, + int blue, + int alpha + ); + + void glColorMask( + boolean red, + boolean green, + boolean blue, + boolean alpha + ); + + void glColorPointer( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + void glCompressedTexImage2D( + int target, + int level, + int internalformat, + int width, + int height, + int border, + int imageSize, + java.nio.Buffer data + ); + + void glCompressedTexSubImage2D( + int target, + int level, + int xoffset, + int yoffset, + int width, + int height, + int format, + int imageSize, + java.nio.Buffer data + ); + + void glCopyTexImage2D( + int target, + int level, + int internalformat, + int x, + int y, + int width, + int height, + int border + ); + + void glCopyTexSubImage2D( + int target, + int level, + int xoffset, + int yoffset, + int x, + int y, + int width, + int height + ); + + void glCullFace( + int mode + ); + + void glDeleteTextures( + int n, + int[] textures, + int offset + ); + + void glDeleteTextures( + int n, + java.nio.IntBuffer textures + ); + + void glDepthFunc( + int func + ); + + void glDepthMask( + boolean flag + ); + + void glDepthRangef( + float zNear, + float zFar + ); + + void glDepthRangex( + int zNear, + int zFar + ); + + void glDisable( + int cap + ); + + void glDisableClientState( + int array + ); + + void glDrawArrays( + int mode, + int first, + int count + ); + + void glDrawElements( + int mode, + int count, + int type, + java.nio.Buffer indices + ); + + void glEnable( + int cap + ); + + void glEnableClientState( + int array + ); + + void glFinish( + ); + + void glFlush( + ); + + void glFogf( + int pname, + float param + ); + + void glFogfv( + int pname, + float[] params, + int offset + ); + + void glFogfv( + int pname, + java.nio.FloatBuffer params + ); + + void glFogx( + int pname, + int param + ); + + void glFogxv( + int pname, + int[] params, + int offset + ); + + void glFogxv( + int pname, + java.nio.IntBuffer params + ); + + void glFrontFace( + int mode + ); + + void glFrustumf( + float left, + float right, + float bottom, + float top, + float zNear, + float zFar + ); + + void glFrustumx( + int left, + int right, + int bottom, + int top, + int zNear, + int zFar + ); + + void glGenTextures( + int n, + int[] textures, + int offset + ); + + void glGenTextures( + int n, + java.nio.IntBuffer textures + ); + + int glGetError( + ); + + void glGetIntegerv( + int pname, + int[] params, + int offset + ); + + void glGetIntegerv( + int pname, + java.nio.IntBuffer params + ); + + public String glGetString( + int name + ); + + void glHint( + int target, + int mode + ); + + void glLightModelf( + int pname, + float param + ); + + void glLightModelfv( + int pname, + float[] params, + int offset + ); + + void glLightModelfv( + int pname, + java.nio.FloatBuffer params + ); + + void glLightModelx( + int pname, + int param + ); + + void glLightModelxv( + int pname, + int[] params, + int offset + ); + + void glLightModelxv( + int pname, + java.nio.IntBuffer params + ); + + void glLightf( + int light, + int pname, + float param + ); + + void glLightfv( + int light, + int pname, + float[] params, + int offset + ); + + void glLightfv( + int light, + int pname, + java.nio.FloatBuffer params + ); + + void glLightx( + int light, + int pname, + int param + ); + + void glLightxv( + int light, + int pname, + int[] params, + int offset + ); + + void glLightxv( + int light, + int pname, + java.nio.IntBuffer params + ); + + void glLineWidth( + float width + ); + + void glLineWidthx( + int width + ); + + void glLoadIdentity( + ); + + void glLoadMatrixf( + float[] m, + int offset + ); + + void glLoadMatrixf( + java.nio.FloatBuffer m + ); + + void glLoadMatrixx( + int[] m, + int offset + ); + + void glLoadMatrixx( + java.nio.IntBuffer m + ); + + void glLogicOp( + int opcode + ); + + void glMaterialf( + int face, + int pname, + float param + ); + + void glMaterialfv( + int face, + int pname, + float[] params, + int offset + ); + + void glMaterialfv( + int face, + int pname, + java.nio.FloatBuffer params + ); + + void glMaterialx( + int face, + int pname, + int param + ); + + void glMaterialxv( + int face, + int pname, + int[] params, + int offset + ); + + void glMaterialxv( + int face, + int pname, + java.nio.IntBuffer params + ); + + void glMatrixMode( + int mode + ); + + void glMultMatrixf( + float[] m, + int offset + ); + + void glMultMatrixf( + java.nio.FloatBuffer m + ); + + void glMultMatrixx( + int[] m, + int offset + ); + + void glMultMatrixx( + java.nio.IntBuffer m + ); + + void glMultiTexCoord4f( + int target, + float s, + float t, + float r, + float q + ); + + void glMultiTexCoord4x( + int target, + int s, + int t, + int r, + int q + ); + + void glNormal3f( + float nx, + float ny, + float nz + ); + + void glNormal3x( + int nx, + int ny, + int nz + ); + + void glNormalPointer( + int type, + int stride, + java.nio.Buffer pointer + ); + + void glOrthof( + float left, + float right, + float bottom, + float top, + float zNear, + float zFar + ); + + void glOrthox( + int left, + int right, + int bottom, + int top, + int zNear, + int zFar + ); + + void glPixelStorei( + int pname, + int param + ); + + void glPointSize( + float size + ); + + void glPointSizex( + int size + ); + + void glPolygonOffset( + float factor, + float units + ); + + void glPolygonOffsetx( + int factor, + int units + ); + + void glPopMatrix( + ); + + void glPushMatrix( + ); + + void glReadPixels( + int x, + int y, + int width, + int height, + int format, + int type, + java.nio.Buffer pixels + ); + + void glRotatef( + float angle, + float x, + float y, + float z + ); + + void glRotatex( + int angle, + int x, + int y, + int z + ); + + void glSampleCoverage( + float value, + boolean invert + ); + + void glSampleCoveragex( + int value, + boolean invert + ); + + void glScalef( + float x, + float y, + float z + ); + + void glScalex( + int x, + int y, + int z + ); + + void glScissor( + int x, + int y, + int width, + int height + ); + + void glShadeModel( + int mode + ); + + void glStencilFunc( + int func, + int ref, + int mask + ); + + void glStencilMask( + int mask + ); + + void glStencilOp( + int fail, + int zfail, + int zpass + ); + + void glTexCoordPointer( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + void glTexEnvf( + int target, + int pname, + float param + ); + + void glTexEnvfv( + int target, + int pname, + float[] params, + int offset + ); + + void glTexEnvfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + void glTexEnvx( + int target, + int pname, + int param + ); + + void glTexEnvxv( + int target, + int pname, + int[] params, + int offset + ); + + void glTexEnvxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glTexImage2D( + int target, + int level, + int internalformat, + int width, + int height, + int border, + int format, + int type, + java.nio.Buffer pixels + ); + + void glTexParameterf( + int target, + int pname, + float param + ); + + void glTexParameterx( + int target, + int pname, + int param + ); + + void glTexSubImage2D( + int target, + int level, + int xoffset, + int yoffset, + int width, + int height, + int format, + int type, + java.nio.Buffer pixels + ); + + void glTranslatef( + float x, + float y, + float z + ); + + void glTranslatex( + int x, + int y, + int z + ); + + void glVertexPointer( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + void glViewport( + int x, + int y, + int width, + int height + ); + +} diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java new file mode 100644 index 0000000..562b20a --- /dev/null +++ b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java @@ -0,0 +1,36 @@ +/* //device/java/android/javax/microedition/khronos/opengles/GL10Ext.java +** +** Copyright 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. +*/ + +// This source file is automatically generated + +package javax.microedition.khronos.opengles; + +public interface GL10Ext extends GL { + + int glQueryMatrixxOES( + int[] mantissa, + int mantissaOffset, + int[] exponent, + int exponentOffset + ); + + int glQueryMatrixxOES( + java.nio.IntBuffer mantissa, + java.nio.IntBuffer exponent + ); + +} diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11.java b/opengl/java/javax/microedition/khronos/opengles/GL11.java new file mode 100644 index 0000000..3ba110c --- /dev/null +++ b/opengl/java/javax/microedition/khronos/opengles/GL11.java @@ -0,0 +1,550 @@ +/* //device/java/android/javax/microedition/khronos/opengles/GL11.java +** +** Copyright 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. +*/ + +// This source file is automatically generated + +package javax.microedition.khronos.opengles; + +public interface GL11 extends GL10 { + int GL_ACTIVE_TEXTURE = 0x84E0; + int GL_ADD_SIGNED = 0x8574; + int GL_ALPHA_SCALE = 0x0D1C; + int GL_ALPHA_TEST_FUNC = 0x0BC1; + int GL_ALPHA_TEST_REF = 0x0BC2; + int GL_ARRAY_BUFFER = 0x8892; + int GL_ARRAY_BUFFER_BINDING = 0x8894; + int GL_BLEND_DST = 0x0BE0; + int GL_BLEND_SRC = 0x0BE1; + int GL_BUFFER_ACCESS = 0x88BB; + int GL_BUFFER_SIZE = 0x8764; + int GL_BUFFER_USAGE = 0x8765; + int GL_CLIENT_ACTIVE_TEXTURE = 0x84E1; + int GL_CLIP_PLANE0 = 0x3000; + int GL_CLIP_PLANE1 = 0x3001; + int GL_CLIP_PLANE2 = 0x3002; + int GL_CLIP_PLANE3 = 0x3003; + int GL_CLIP_PLANE4 = 0x3004; + int GL_CLIP_PLANE5 = 0x3005; + int GL_COLOR_ARRAY_BUFFER_BINDING = 0x8898; + int GL_COLOR_ARRAY_POINTER = 0x8090; + int GL_COLOR_ARRAY_SIZE = 0x8081; + int GL_COLOR_ARRAY_STRIDE = 0x8083; + int GL_COLOR_ARRAY_TYPE = 0x8082; + int GL_COLOR_CLEAR_VALUE = 0x0C22; + int GL_COLOR_WRITEMASK = 0x0C23; + int GL_COMBINE = 0x8570; + int GL_COMBINE_ALPHA = 0x8572; + int GL_COMBINE_RGB = 0x8571; + int GL_CONSTANT = 0x8576; + int GL_COORD_REPLACE_OES = 0x8862; + int GL_CULL_FACE_MODE = 0x0B45; + int GL_CURRENT_COLOR = 0x0B00; + int GL_CURRENT_NORMAL = 0x0B02; + int GL_CURRENT_TEXTURE_COORDS = 0x0B03; + int GL_DEPTH_CLEAR_VALUE = 0x0B73; + int GL_DEPTH_FUNC = 0x0B74; + int GL_DEPTH_RANGE = 0x0B70; + int GL_DEPTH_WRITEMASK = 0x0B72; + int GL_DOT3_RGB = 0x86AE; + int GL_DOT3_RGBA = 0x86AF; + int GL_DYNAMIC_DRAW = 0x88E8; + int GL_ELEMENT_ARRAY_BUFFER = 0x8893; + int GL_ELEMENT_ARRAY_BUFFER_BINDING = 0x8895; + int GL_FRONT_FACE = 0x0B46; + int GL_GENERATE_MIPMAP = 0x8191; + int GL_GENERATE_MIPMAP_HINT = 0x8192; + int GL_INTERPOLATE = 0x8575; + int GL_LINE_WIDTH = 0x0B21; + int GL_LOGIC_OP_MODE = 0x0BF0; + int GL_MATRIX_MODE = 0x0BA0; + int GL_MAX_CLIP_PLANES = 0x0D32; + int GL_MODELVIEW_MATRIX = 0x0BA6; + int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES = 0x898D; + int GL_MODELVIEW_STACK_DEPTH = 0x0BA3; + int GL_NORMAL_ARRAY_BUFFER_BINDING = 0x8897; + int GL_NORMAL_ARRAY_POINTER = 0x808F; + int GL_NORMAL_ARRAY_STRIDE = 0x807F; + int GL_NORMAL_ARRAY_TYPE = 0x807E; + int GL_OPERAND0_ALPHA = 0x8598; + int GL_OPERAND0_RGB = 0x8590; + int GL_OPERAND1_ALPHA = 0x8599; + int GL_OPERAND1_RGB = 0x8591; + int GL_OPERAND2_ALPHA = 0x859A; + int GL_OPERAND2_RGB = 0x8592; + int GL_POINT_DISTANCE_ATTENUATION = 0x8129; + int GL_POINT_FADE_THRESHOLD_SIZE = 0x8128; + int GL_POINT_SIZE = 0x0B11; + int GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES = 0x8B9F; + int GL_POINT_SIZE_ARRAY_OES = 0x8B9C; + int GL_POINT_SIZE_ARRAY_POINTER_OES = 0x898C; + int GL_POINT_SIZE_ARRAY_STRIDE_OES = 0x898B; + int GL_POINT_SIZE_ARRAY_TYPE_OES = 0x898A; + int GL_POINT_SIZE_MAX = 0x8127; + int GL_POINT_SIZE_MIN = 0x8126; + int GL_POINT_SPRITE_OES = 0x8861; + int GL_POLYGON_OFFSET_FACTOR = 0x8038; + int GL_POLYGON_OFFSET_UNITS = 0x2A00; + int GL_PREVIOUS = 0x8578; + int GL_PRIMARY_COLOR = 0x8577; + int GL_PROJECTION_MATRIX = 0x0BA7; + int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 0x898E; + int GL_PROJECTION_STACK_DEPTH = 0x0BA4; + int GL_RGB_SCALE = 0x8573; + int GL_SAMPLE_BUFFERS = 0x80A8; + int GL_SAMPLE_COVERAGE_INVERT = 0x80AB; + int GL_SAMPLE_COVERAGE_VALUE = 0x80AA; + int GL_SAMPLES = 0x80A9; + int GL_SCISSOR_BOX = 0x0C10; + int GL_SHADE_MODEL = 0x0B54; + int GL_SRC0_ALPHA = 0x8588; + int GL_SRC0_RGB = 0x8580; + int GL_SRC1_ALPHA = 0x8589; + int GL_SRC1_RGB = 0x8581; + int GL_SRC2_ALPHA = 0x858A; + int GL_SRC2_RGB = 0x8582; + int GL_STATIC_DRAW = 0x88E4; + int GL_STENCIL_CLEAR_VALUE = 0x0B91; + int GL_STENCIL_FAIL = 0x0B94; + int GL_STENCIL_FUNC = 0x0B92; + int GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95; + int GL_STENCIL_PASS_DEPTH_PASS = 0x0B96; + int GL_STENCIL_REF = 0x0B97; + int GL_STENCIL_VALUE_MASK = 0x0B93; + int GL_STENCIL_WRITEMASK = 0x0B98; + int GL_SUBTRACT = 0x84E7; + int GL_TEXTURE_BINDING_2D = 0x8069; + int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = 0x889A; + int GL_TEXTURE_COORD_ARRAY_POINTER = 0x8092; + int GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088; + int GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808A; + int GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089; + int GL_TEXTURE_MATRIX = 0x0BA8; + int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES = 0x898F; + int GL_TEXTURE_STACK_DEPTH = 0x0BA5; + int GL_VERTEX_ARRAY_BUFFER_BINDING = 0x8896; + int GL_VERTEX_ARRAY_POINTER = 0x808E; + int GL_VERTEX_ARRAY_SIZE = 0x807A; + int GL_VERTEX_ARRAY_STRIDE = 0x807C; + int GL_VERTEX_ARRAY_TYPE = 0x807B; + int GL_VIEWPORT = 0x0BA2; + int GL_WRITE_ONLY = 0x88B9; + + void glGetPointerv(int pname, java.nio.Buffer[] params); + void glBindBuffer( + int target, + int buffer + ); + + void glBufferData( + int target, + int size, + java.nio.Buffer data, + int usage + ); + + void glBufferSubData( + int target, + int offset, + int size, + java.nio.Buffer data + ); + + void glClipPlanef( + int plane, + float[] equation, + int offset + ); + + void glClipPlanef( + int plane, + java.nio.FloatBuffer equation + ); + + void glClipPlanex( + int plane, + int[] equation, + int offset + ); + + void glClipPlanex( + int plane, + java.nio.IntBuffer equation + ); + + void glColor4ub( + byte red, + byte green, + byte blue, + byte alpha + ); + + void glColorPointer( + int size, + int type, + int stride, + int offset + ); + + void glDeleteBuffers( + int n, + int[] buffers, + int offset + ); + + void glDeleteBuffers( + int n, + java.nio.IntBuffer buffers + ); + + void glDrawElements( + int mode, + int count, + int type, + int offset + ); + + void glGenBuffers( + int n, + int[] buffers, + int offset + ); + + void glGenBuffers( + int n, + java.nio.IntBuffer buffers + ); + + void glGetBooleanv( + int pname, + boolean[] params, + int offset + ); + + void glGetBooleanv( + int pname, + java.nio.IntBuffer params + ); + + void glGetBufferParameteriv( + int target, + int pname, + int[] params, + int offset + ); + + void glGetBufferParameteriv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glGetClipPlanef( + int pname, + float[] eqn, + int offset + ); + + void glGetClipPlanef( + int pname, + java.nio.FloatBuffer eqn + ); + + void glGetClipPlanex( + int pname, + int[] eqn, + int offset + ); + + void glGetClipPlanex( + int pname, + java.nio.IntBuffer eqn + ); + + void glGetFixedv( + int pname, + int[] params, + int offset + ); + + void glGetFixedv( + int pname, + java.nio.IntBuffer params + ); + + void glGetFloatv( + int pname, + float[] params, + int offset + ); + + void glGetFloatv( + int pname, + java.nio.FloatBuffer params + ); + + void glGetLightfv( + int light, + int pname, + float[] params, + int offset + ); + + void glGetLightfv( + int light, + int pname, + java.nio.FloatBuffer params + ); + + void glGetLightxv( + int light, + int pname, + int[] params, + int offset + ); + + void glGetLightxv( + int light, + int pname, + java.nio.IntBuffer params + ); + + void glGetMaterialfv( + int face, + int pname, + float[] params, + int offset + ); + + void glGetMaterialfv( + int face, + int pname, + java.nio.FloatBuffer params + ); + + void glGetMaterialxv( + int face, + int pname, + int[] params, + int offset + ); + + void glGetMaterialxv( + int face, + int pname, + java.nio.IntBuffer params + ); + + void glGetTexEnviv( + int env, + int pname, + int[] params, + int offset + ); + + void glGetTexEnviv( + int env, + int pname, + java.nio.IntBuffer params + ); + + void glGetTexEnvxv( + int env, + int pname, + int[] params, + int offset + ); + + void glGetTexEnvxv( + int env, + int pname, + java.nio.IntBuffer params + ); + + void glGetTexParameterfv( + int target, + int pname, + float[] params, + int offset + ); + + void glGetTexParameterfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + void glGetTexParameteriv( + int target, + int pname, + int[] params, + int offset + ); + + void glGetTexParameteriv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glGetTexParameterxv( + int target, + int pname, + int[] params, + int offset + ); + + void glGetTexParameterxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + boolean glIsBuffer( + int buffer + ); + + boolean glIsEnabled( + int cap + ); + + boolean glIsTexture( + int texture + ); + + void glNormalPointer( + int type, + int stride, + int offset + ); + + void glPointParameterf( + int pname, + float param + ); + + void glPointParameterfv( + int pname, + float[] params, + int offset + ); + + void glPointParameterfv( + int pname, + java.nio.FloatBuffer params + ); + + void glPointParameterx( + int pname, + int param + ); + + void glPointParameterxv( + int pname, + int[] params, + int offset + ); + + void glPointParameterxv( + int pname, + java.nio.IntBuffer params + ); + + void glPointSizePointerOES( + int type, + int stride, + java.nio.Buffer pointer + ); + + void glTexCoordPointer( + int size, + int type, + int stride, + int offset + ); + + void glTexEnvi( + int target, + int pname, + int param + ); + + void glTexEnviv( + int target, + int pname, + int[] params, + int offset + ); + + void glTexEnviv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glTexParameterfv( + int target, + int pname, + float[] params, + int offset + ); + + void glTexParameterfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + void glTexParameteri( + int target, + int pname, + int param + ); + + void glTexParameteriv( + int target, + int pname, + int[] params, + int offset + ); + + void glTexParameteriv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glTexParameterxv( + int target, + int pname, + int[] params, + int offset + ); + + void glTexParameterxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glVertexPointer( + int size, + int type, + int stride, + int offset + ); + +} diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java new file mode 100644 index 0000000..459a1ab --- /dev/null +++ b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java @@ -0,0 +1,153 @@ +/* //device/java/android/javax/microedition/khronos/opengles/GL11Ext.java +** +** Copyright 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. +*/ + +// This source file is automatically generated + +package javax.microedition.khronos.opengles; + +public interface GL11Ext extends GL { + int GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES = 0x8B9E; + int GL_MATRIX_INDEX_ARRAY_OES = 0x8844; + int GL_MATRIX_INDEX_ARRAY_POINTER_OES = 0x8849; + int GL_MATRIX_INDEX_ARRAY_SIZE_OES = 0x8846; + int GL_MATRIX_INDEX_ARRAY_STRIDE_OES = 0x8848; + int GL_MATRIX_INDEX_ARRAY_TYPE_OES = 0x8847; + int GL_MATRIX_PALETTE_OES = 0x8840; + int GL_MAX_PALETTE_MATRICES_OES = 0x8842; + int GL_MAX_VERTEX_UNITS_OES = 0x86A4; + int GL_TEXTURE_CROP_RECT_OES = 0x8B9D; + int GL_WEIGHT_ARRAY_BUFFER_BINDING_OES = 0x889E; + int GL_WEIGHT_ARRAY_OES = 0x86AD; + int GL_WEIGHT_ARRAY_POINTER_OES = 0x86AC; + int GL_WEIGHT_ARRAY_SIZE_OES = 0x86AB; + int GL_WEIGHT_ARRAY_STRIDE_OES = 0x86AA; + int GL_WEIGHT_ARRAY_TYPE_OES = 0x86A9; + + void glTexParameterfv(int target, int pname, float[] param, int offset); + + void glCurrentPaletteMatrixOES( + int matrixpaletteindex + ); + + void glDrawTexfOES( + float x, + float y, + float z, + float width, + float height + ); + + void glDrawTexfvOES( + float[] coords, + int offset + ); + + void glDrawTexfvOES( + java.nio.FloatBuffer coords + ); + + void glDrawTexiOES( + int x, + int y, + int z, + int width, + int height + ); + + void glDrawTexivOES( + int[] coords, + int offset + ); + + void glDrawTexivOES( + java.nio.IntBuffer coords + ); + + void glDrawTexsOES( + short x, + short y, + short z, + short width, + short height + ); + + void glDrawTexsvOES( + short[] coords, + int offset + ); + + void glDrawTexsvOES( + java.nio.ShortBuffer coords + ); + + void glDrawTexxOES( + int x, + int y, + int z, + int width, + int height + ); + + void glDrawTexxvOES( + int[] coords, + int offset + ); + + void glDrawTexxvOES( + java.nio.IntBuffer coords + ); + + void glEnable( + int cap + ); + + void glEnableClientState( + int array + ); + + void glLoadPaletteFromModelViewMatrixOES( + ); + + void glMatrixIndexPointerOES( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + void glMatrixIndexPointerOES( + int size, + int type, + int stride, + int offset + ); + + void glWeightPointerOES( + int size, + int type, + int stride, + java.nio.Buffer pointer + ); + + void glWeightPointerOES( + int size, + int type, + int stride, + int offset + ); + +} diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java new file mode 100644 index 0000000..933c91e --- /dev/null +++ b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java @@ -0,0 +1,434 @@ +/* //device/java/android/javax/microedition/khronos/opengles/GL11ExtensionPack.java +** +** Copyright 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. +*/ + +// This source file is automatically generated + +package javax.microedition.khronos.opengles; + +public interface GL11ExtensionPack extends GL { + int GL_BLEND_DST_ALPHA = 0x80CA; + int GL_BLEND_DST_RGB = 0x80C8; + int GL_BLEND_EQUATION = 0x8009; + int GL_BLEND_EQUATION_ALPHA = 0x883D; + int GL_BLEND_EQUATION_RGB = 0x8009; + int GL_BLEND_SRC_ALPHA = 0x80CB; + int GL_BLEND_SRC_RGB = 0x80C9; + int GL_COLOR_ATTACHMENT0_OES = 0x8CE0; + int GL_COLOR_ATTACHMENT1_OES = 0x8CE1; + int GL_COLOR_ATTACHMENT2_OES = 0x8CE2; + int GL_COLOR_ATTACHMENT3_OES = 0x8CE3; + int GL_COLOR_ATTACHMENT4_OES = 0x8CE4; + int GL_COLOR_ATTACHMENT5_OES = 0x8CE5; + int GL_COLOR_ATTACHMENT6_OES = 0x8CE6; + int GL_COLOR_ATTACHMENT7_OES = 0x8CE7; + int GL_COLOR_ATTACHMENT8_OES = 0x8CE8; + int GL_COLOR_ATTACHMENT9_OES = 0x8CE9; + int GL_COLOR_ATTACHMENT10_OES = 0x8CEA; + int GL_COLOR_ATTACHMENT11_OES = 0x8CEB; + int GL_COLOR_ATTACHMENT12_OES = 0x8CEC; + int GL_COLOR_ATTACHMENT13_OES = 0x8CED; + int GL_COLOR_ATTACHMENT14_OES = 0x8CEE; + int GL_COLOR_ATTACHMENT15_OES = 0x8CEF; + int GL_DECR_WRAP = 0x8508; + int GL_DEPTH_ATTACHMENT_OES = 0x8D00; + int GL_DEPTH_COMPONENT = 0x1902; + int GL_DEPTH_COMPONENT16 = 0x81A5; + int GL_DEPTH_COMPONENT24 = 0x81A6; + int GL_DEPTH_COMPONENT32 = 0x81A7; + int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES = 0x8CD1; + int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES = 0x8CD0; + int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES = 0x8CD3; + int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES = 0x8CD2; + int GL_FRAMEBUFFER_BINDING_OES = 0x8CA6; + int GL_FRAMEBUFFER_COMPLETE_OES = 0x8CD5; + int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES = 0x8CD6; + int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES = 0x8CD9; + int GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES = 0x8CDB; + int GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES = 0x8CDA; + int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES = 0x8CD7; + int GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES = 0x8CDC; + int GL_FRAMEBUFFER_OES = 0x8D40; + int GL_FRAMEBUFFER_UNSUPPORTED_OES = 0x8CDD; + int GL_FUNC_ADD = 0x8006; + int GL_FUNC_REVERSE_SUBTRACT = 0x800B; + int GL_FUNC_SUBTRACT = 0x800A; + int GL_INCR_WRAP = 0x8507; + int GL_INVALID_FRAMEBUFFER_OPERATION_OES = 0x0506; + int GL_MAX_COLOR_ATTACHMENTS_OES = 0x8CDF; + int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; + int GL_MAX_RENDERBUFFER_SIZE_OES = 0x84E8; + int GL_MIRRORED_REPEAT = 0x8370; + int GL_NORMAL_MAP = 0x8511; + int GL_REFLECTION_MAP = 0x8512; + int GL_RENDERBUFFER_ALPHA_SIZE_OES = 0x8D53; + int GL_RENDERBUFFER_BINDING_OES = 0x8CA7; + int GL_RENDERBUFFER_BLUE_SIZE_OES = 0x8D52; + int GL_RENDERBUFFER_DEPTH_SIZE_OES = 0x8D54; + int GL_RENDERBUFFER_GREEN_SIZE_OES = 0x8D51; + int GL_RENDERBUFFER_HEIGHT_OES = 0x8D43; + int GL_RENDERBUFFER_INTERNAL_FORMAT_OES = 0x8D44; + int GL_RENDERBUFFER_OES = 0x8D41; + int GL_RENDERBUFFER_RED_SIZE_OES = 0x8D50; + int GL_RENDERBUFFER_STENCIL_SIZE_OES = 0x8D55; + int GL_RENDERBUFFER_WIDTH_OES = 0x8D42; + int GL_RGB5_A1 = 0x8057; + int GL_RGB565_OES = 0x8D62; + int GL_RGB8 = 0x8051; + int GL_RGBA4 = 0x8056; + int GL_RGBA8 = 0x8058; + int GL_STENCIL_ATTACHMENT_OES = 0x8D20; + int GL_STENCIL_INDEX = 0x1901; + int GL_STENCIL_INDEX1_OES = 0x8D46; + int GL_STENCIL_INDEX4_OES = 0x8D47; + int GL_STENCIL_INDEX8_OES = 0x8D48; + int GL_STR = -1; + int GL_TEXTURE_BINDING_CUBE_MAP = 0x8514; + int GL_TEXTURE_CUBE_MAP = 0x8513; + int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + int GL_TEXTURE_GEN_MODE = 0x2500; + int GL_TEXTURE_GEN_STR = 0x8D60; + + void glBindFramebufferOES( + int target, + int framebuffer + ); + + void glBindRenderbufferOES( + int target, + int renderbuffer + ); + + void glBindTexture( + int target, + int texture + ); + + void glBlendEquation( + int mode + ); + + void glBlendEquationSeparate( + int modeRGB, + int modeAlpha + ); + + void glBlendFuncSeparate( + int srcRGB, + int dstRGB, + int srcAlpha, + int dstAlpha + ); + + int glCheckFramebufferStatusOES( + int target + ); + + void glCompressedTexImage2D( + int target, + int level, + int internalformat, + int width, + int height, + int border, + int imageSize, + java.nio.Buffer data + ); + + void glCopyTexImage2D( + int target, + int level, + int internalformat, + int x, + int y, + int width, + int height, + int border + ); + + void glDeleteFramebuffersOES( + int n, + int[] framebuffers, + int offset + ); + + void glDeleteFramebuffersOES( + int n, + java.nio.IntBuffer framebuffers + ); + + void glDeleteRenderbuffersOES( + int n, + int[] renderbuffers, + int offset + ); + + void glDeleteRenderbuffersOES( + int n, + java.nio.IntBuffer renderbuffers + ); + + void glEnable( + int cap + ); + + void glFramebufferRenderbufferOES( + int target, + int attachment, + int renderbuffertarget, + int renderbuffer + ); + + void glFramebufferTexture2DOES( + int target, + int attachment, + int textarget, + int texture, + int level + ); + + void glGenerateMipmapOES( + int target + ); + + void glGenFramebuffersOES( + int n, + int[] framebuffers, + int offset + ); + + void glGenFramebuffersOES( + int n, + java.nio.IntBuffer framebuffers + ); + + void glGenRenderbuffersOES( + int n, + int[] renderbuffers, + int offset + ); + + void glGenRenderbuffersOES( + int n, + java.nio.IntBuffer renderbuffers + ); + + void glGetFramebufferAttachmentParameterivOES( + int target, + int attachment, + int pname, + int[] params, + int offset + ); + + void glGetFramebufferAttachmentParameterivOES( + int target, + int attachment, + int pname, + java.nio.IntBuffer params + ); + + void glGetIntegerv( + int pname, + int[] params, + int offset + ); + + void glGetIntegerv( + int pname, + java.nio.IntBuffer params + ); + + void glGetRenderbufferParameterivOES( + int target, + int pname, + int[] params, + int offset + ); + + void glGetRenderbufferParameterivOES( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glGetTexGenfv( + int coord, + int pname, + float[] params, + int offset + ); + + void glGetTexGenfv( + int coord, + int pname, + java.nio.FloatBuffer params + ); + + void glGetTexGeniv( + int coord, + int pname, + int[] params, + int offset + ); + + void glGetTexGeniv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + void glGetTexGenxv( + int coord, + int pname, + int[] params, + int offset + ); + + void glGetTexGenxv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + boolean glIsFramebufferOES( + int framebuffer + ); + + boolean glIsRenderbufferOES( + int renderbuffer + ); + + void glRenderbufferStorageOES( + int target, + int internalformat, + int width, + int height + ); + + void glStencilOp( + int fail, + int zfail, + int zpass + ); + + void glTexEnvf( + int target, + int pname, + float param + ); + + void glTexEnvfv( + int target, + int pname, + float[] params, + int offset + ); + + void glTexEnvfv( + int target, + int pname, + java.nio.FloatBuffer params + ); + + void glTexEnvx( + int target, + int pname, + int param + ); + + void glTexEnvxv( + int target, + int pname, + int[] params, + int offset + ); + + void glTexEnvxv( + int target, + int pname, + java.nio.IntBuffer params + ); + + void glTexGenf( + int coord, + int pname, + float param + ); + + void glTexGenfv( + int coord, + int pname, + float[] params, + int offset + ); + + void glTexGenfv( + int coord, + int pname, + java.nio.FloatBuffer params + ); + + void glTexGeni( + int coord, + int pname, + int param + ); + + void glTexGeniv( + int coord, + int pname, + int[] params, + int offset + ); + + void glTexGeniv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + void glTexGenx( + int coord, + int pname, + int param + ); + + void glTexGenxv( + int coord, + int pname, + int[] params, + int offset + ); + + void glTexGenxv( + int coord, + int pname, + java.nio.IntBuffer params + ); + + void glTexParameterf( + int target, + int pname, + float param + ); + +} diff --git a/opengl/libGLES_CM/Android.mk b/opengl/libGLES_CM/Android.mk new file mode 100644 index 0000000..a0081ef --- /dev/null +++ b/opengl/libGLES_CM/Android.mk @@ -0,0 +1,22 @@ +LOCAL_PATH:= $(call my-dir) + +# +# Build the wrapper OpenGL ES library +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= gl_wrapper.cpp.arm gl_logger.cpp + +LOCAL_SHARED_LIBRARIES += libcutils libutils libui +LOCAL_LDLIBS := -lpthread -ldl +LOCAL_MODULE:= libGLES_CM + +# needed on sim build because of weird logging issues +ifeq ($(TARGET_SIMULATOR),true) +else + LOCAL_SHARED_LIBRARIES += libdl +endif + +include $(BUILD_SHARED_LIBRARY) + diff --git a/opengl/libGLES_CM/egl_entries.cpp b/opengl/libGLES_CM/egl_entries.cpp new file mode 100644 index 0000000..ba46f40 --- /dev/null +++ b/opengl/libGLES_CM/egl_entries.cpp @@ -0,0 +1,46 @@ +EGL_ENTRY(EGLDisplay, eglGetDisplay, NativeDisplayType) +EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*) +EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay) +EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*) +EGL_ENTRY(EGLBoolean, eglChooseConfig, EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *) + +EGL_ENTRY(EGLBoolean, eglGetConfigAttrib, EGLDisplay, EGLConfig, EGLint, EGLint *) +EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint *) +EGL_ENTRY(EGLSurface, eglCreatePixmapSurface, EGLDisplay, EGLConfig, NativePixmapType, const EGLint *) +EGL_ENTRY(EGLSurface, eglCreatePbufferSurface, EGLDisplay, EGLConfig, const EGLint *) +EGL_ENTRY(EGLBoolean, eglDestroySurface, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLBoolean, eglQuerySurface, EGLDisplay, EGLSurface, EGLint, EGLint *) +EGL_ENTRY(EGLContext, eglCreateContext, EGLDisplay, EGLConfig, EGLContext, const EGLint *) +EGL_ENTRY(EGLBoolean, eglDestroyContext, EGLDisplay, EGLContext) +EGL_ENTRY(EGLBoolean, eglMakeCurrent, EGLDisplay, EGLSurface, EGLSurface, EGLContext) +EGL_ENTRY(EGLContext, eglGetCurrentContext, void) +EGL_ENTRY(EGLSurface, eglGetCurrentSurface, EGLint) +EGL_ENTRY(EGLDisplay, eglGetCurrentDisplay, void) +EGL_ENTRY(EGLBoolean, eglQueryContext, EGLDisplay, EGLContext, EGLint, EGLint *) +EGL_ENTRY(EGLBoolean, eglWaitGL, void) +EGL_ENTRY(EGLBoolean, eglWaitNative, EGLint) +EGL_ENTRY(EGLBoolean, eglSwapBuffers, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLBoolean, eglCopyBuffers, EGLDisplay, EGLSurface, NativePixmapType) +EGL_ENTRY(EGLint, eglGetError, void) +EGL_ENTRY(const char*, eglQueryString, EGLDisplay, EGLint) +EGL_ENTRY(proc_t, eglGetProcAddress, const char *) + +/* EGL 1.1 */ + +EGL_ENTRY(EGLBoolean, eglSurfaceAttrib, EGLDisplay, EGLSurface, EGLint, EGLint) +EGL_ENTRY(EGLBoolean, eglBindTexImage, EGLDisplay, EGLSurface, EGLint) +EGL_ENTRY(EGLBoolean, eglReleaseTexImage, EGLDisplay, EGLSurface, EGLint) +EGL_ENTRY(EGLBoolean, eglSwapInterval, EGLDisplay, EGLint) + +/* EGL 1.2 */ + +EGL_ENTRY(EGLBoolean, eglBindAPI, EGLenum) +EGL_ENTRY(EGLenum, eglQueryAPI, void) +EGL_ENTRY(EGLBoolean, eglWaitClient, void) +EGL_ENTRY(EGLBoolean, eglReleaseThread, void) +EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGLClientBuffer, EGLConfig, const EGLint *) + +/* Android extentions */ + +EGL_ENTRY(EGLBoolean, eglSwapRectangleANDROID, EGLDisplay, EGLSurface , EGLint, EGLint, EGLint, EGLint) +EGL_ENTRY(const char*, eglQueryStringConfigANDROID, EGLDisplay, EGLConfig, EGLint) diff --git a/opengl/libGLES_CM/enumextract.sh b/opengl/libGLES_CM/enumextract.sh new file mode 100644 index 0000000..5707302 --- /dev/null +++ b/opengl/libGLES_CM/enumextract.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +awk ' +/^#define GL_/ { + names[count] = $2; + values[count] = $3; + sort[count] = $3 + 0; + count++; +} +END { + for (i = 1; i < count; i++) { + for (j = 0; j < i; j++) { + if (sort[i] < sort[j]) { + tn = names[i]; + tv = values[i]; + ts = sort[i]; + names[i] = names[j]; + values[i] = values[j]; + sort[i] = sort[j]; + names[j] = tn; + values[j] = tv; + sort[j] = ts; + } + } + } + + for (i = 0; i < count; i++) { + printf("GLENUM(%s, %s)\n", names[i], values[i]); + } +} +' < $1 + diff --git a/opengl/libGLES_CM/gl_api.cpp b/opengl/libGLES_CM/gl_api.cpp new file mode 100644 index 0000000..ed3bdaa --- /dev/null +++ b/opengl/libGLES_CM/gl_api.cpp @@ -0,0 +1,606 @@ +void API_ENTRY(glActiveTexture)(GLenum texture) { + CALL_GL_API(glActiveTexture, texture); +} + +void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) { + CALL_GL_API(glAlphaFunc, func, ref); +} + +void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) { + CALL_GL_API(glAlphaFuncx, func, ref); +} + +void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) { + CALL_GL_API(glBindTexture, target, texture); +} + +void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) { + CALL_GL_API(glBlendFunc, sfactor, dfactor); +} + +void API_ENTRY(glClear)(GLbitfield mask) { + CALL_GL_API(glClear, mask); +} + +void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + CALL_GL_API(glClearColor, red, green, blue, alpha); +} + +void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { + CALL_GL_API(glClearColorx, red, green, blue, alpha); +} + +void API_ENTRY(glClearDepthf)(GLclampf depth) { + CALL_GL_API(glClearDepthf, depth); +} + +void API_ENTRY(glClearDepthx)(GLclampx depth) { + CALL_GL_API(glClearDepthx, depth); +} + +void API_ENTRY(glClearStencil)(GLint s) { + CALL_GL_API(glClearStencil, s); +} + +void API_ENTRY(glClientActiveTexture)(GLenum texture) { + CALL_GL_API(glClientActiveTexture, texture); +} + +void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + CALL_GL_API(glColor4f, red, green, blue, alpha); +} + +void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { + CALL_GL_API(glColor4x, red, green, blue, alpha); +} + +void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { + CALL_GL_API(glColorMask, r, g, b, a); +} + +void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) +{ + CALL_GL_API(glColorPointer, size, type, stride, ptr); +} + +void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLsizei imageSize, const GLvoid *data) { + CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, + width, height, border, imageSize, data); +} + +void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data) { + CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, + width, height, format, imageSize, data); +} + +void API_ENTRY(glCopyTexImage2D)( GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) { + CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, + width, height, border); +} + +void API_ENTRY(glCopyTexSubImage2D)( GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint x, GLint y, GLsizei width, + GLsizei height) { + CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, + width, height); +} + +void API_ENTRY(glCullFace)(GLenum mode) { + CALL_GL_API(glCullFace, mode); +} + +void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) { + CALL_GL_API(glDeleteTextures, n, textures); +} + +void API_ENTRY(glDepthFunc)(GLenum func) { + CALL_GL_API(glDepthFunc, func); +} + +void API_ENTRY(glDepthMask)(GLboolean flag) { + CALL_GL_API(glDepthMask, flag); +} + +void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { + CALL_GL_API(glDepthRangef, zNear, zFar); +} + +void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) { + CALL_GL_API(glDepthRangex, zNear, zFar); +} + +void API_ENTRY(glDisable)(GLenum cap) { + CALL_GL_API(glDisable, cap); +} + +void API_ENTRY(glDisableClientState)(GLenum array) { + CALL_GL_API(glDisableClientState, array); +} + +void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) { + CALL_GL_API(glDrawArrays, mode, first, count); +} + +void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices) { + CALL_GL_API(glDrawElements, mode, count, type, indices); +} + +void API_ENTRY(glEnable)(GLenum cap) { + CALL_GL_API(glEnable, cap); +} + +void API_ENTRY(glEnableClientState)(GLenum array) { + CALL_GL_API(glEnableClientState, array); +} + +void API_ENTRY(glFinish)(void) { + CALL_GL_API(glFinish); +} + +void API_ENTRY(glFlush)(void) { + CALL_GL_API(glFlush); +} + +void API_ENTRY(glFogf)(GLenum pname, GLfloat param) { + CALL_GL_API(glFogf, pname, param); +} + +void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glFogfv, pname, params); +} + +void API_ENTRY(glFogx)(GLenum pname, GLfixed param) { + CALL_GL_API(glFogx, pname, param); +} + +void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glFogxv, pname, params); +} + +void API_ENTRY(glFrontFace)(GLenum mode) { + CALL_GL_API(glFrontFace, mode); +} + +void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar); +} + +void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed zNear, GLfixed zFar) { + CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar); +} + +void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) { + CALL_GL_API(glGenTextures, n, textures); +} + +GLenum API_ENTRY(glGetError)(void) { + CALL_GL_API_RETURN(glGetError); +} + +void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) { + CALL_GL_API(glGetIntegerv, pname, params); +} + +const GLubyte * API_ENTRY(glGetString)(GLenum name) { + CALL_GL_API_RETURN(glGetString, name); +} + +void API_ENTRY(glHint)(GLenum target, GLenum mode) { + CALL_GL_API(glHint, target, mode); +} + +void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) { + CALL_GL_API(glLightModelf, pname, param); +} + +void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glLightModelfv, pname, params); +} + +void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) { + CALL_GL_API(glLightModelx, pname, param); +} + +void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glLightModelxv, pname, params); +} + +void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) { + CALL_GL_API(glLightf, light, pname, param); +} + +void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) { + CALL_GL_API(glLightfv, light, pname, params); +} + +void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) { + CALL_GL_API(glLightx, light, pname, param); +} + +void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) { + CALL_GL_API(glLightxv, light, pname, params); +} + +void API_ENTRY(glLineWidth)(GLfloat width) { + CALL_GL_API(glLineWidth, width); +} + +void API_ENTRY(glLineWidthx)(GLfixed width) { + CALL_GL_API(glLineWidthx, width); +} + +void API_ENTRY(glLoadIdentity)(void) { + CALL_GL_API(glLoadIdentity); +} + +void API_ENTRY(glLoadMatrixf)(const GLfloat *m) { + CALL_GL_API(glLoadMatrixf, m); +} + +void API_ENTRY(glLoadMatrixx)(const GLfixed *m) { + CALL_GL_API(glLoadMatrixx, m); +} + +void API_ENTRY(glLogicOp)(GLenum opcode) { + CALL_GL_API(glLogicOp, opcode); +} + +void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) { + CALL_GL_API(glMaterialf, face, pname, param); +} + +void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) { + CALL_GL_API(glMaterialfv, face, pname, params); +} + +void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) { + CALL_GL_API(glMaterialx, face, pname, param); +} + +void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) { + CALL_GL_API(glMaterialxv, face, pname, params); +} + +void API_ENTRY(glMatrixMode)(GLenum mode) { + CALL_GL_API(glMatrixMode, mode); +} + +void API_ENTRY(glMultMatrixf)(const GLfloat *m) { + CALL_GL_API(glMultMatrixf, m); +} + +void API_ENTRY(glMultMatrixx)(const GLfixed *m) { + CALL_GL_API(glMultMatrixx, m); +} + +void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { + CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q); +} + +void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { + CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q); +} + +void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) { + CALL_GL_API(glNormal3f, nx, ny, nz); +} + +void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) { + CALL_GL_API(glNormal3x, nx, ny, nz); +} + +void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glNormalPointer, type, stride, pointer); +} + +void API_ENTRY(glOrthof)( GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar); +} + +void API_ENTRY(glOrthox)( GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed zNear, GLfixed zFar) { + CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar); +} + +void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) { + CALL_GL_API(glPixelStorei, pname, param); +} + +void API_ENTRY(glPointSize)(GLfloat size) { + CALL_GL_API(glPointSize, size); +} + +void API_ENTRY(glPointSizex)(GLfixed size) { + CALL_GL_API(glPointSizex, size); +} + +void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { + CALL_GL_API(glPolygonOffset, factor, units); +} + +void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) { + CALL_GL_API(glPolygonOffsetx, factor, units); +} + +void API_ENTRY(glPopMatrix)(void) { + CALL_GL_API(glPopMatrix); +} + +void API_ENTRY(glPushMatrix)(void) { + CALL_GL_API(glPushMatrix); +} + +void API_ENTRY(glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels) { + CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels); +} + +void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glRotatef, angle, x, y, z); +} + +void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glRotatex, angle, x, y, z); +} + +void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) { + CALL_GL_API(glSampleCoverage, value, invert); +} + +void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) { + CALL_GL_API(glSampleCoveragex, value, invert); +} + +void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glScalef, x, y, z); +} + +void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glScalex, x, y, z); +} + +void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glScissor, x, y, width, height); +} + +void API_ENTRY(glShadeModel)(GLenum mode) { + CALL_GL_API(glShadeModel, mode); +} + +void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) { + CALL_GL_API(glStencilFunc, func, ref, mask); +} + +void API_ENTRY(glStencilMask)(GLuint mask) { + CALL_GL_API(glStencilMask, mask); +} + +void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) { + CALL_GL_API(glStencilOp, fail, zfail, zpass); +} + +void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glTexCoordPointer, size, type, stride, pointer); +} + +void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexEnvf, target, pname, param); +} + +void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexEnvfv, target, pname, params); +} + +void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) { + CALL_GL_API(glTexEnvx, target, pname, param); +} + +void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexEnvxv, target, pname, params); +} + +void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, GLenum format, + GLenum type, const GLvoid *pixels) { + CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, + border, format, type, pixels); +} + +void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexParameterf, target, pname, param); +} + +void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) { + CALL_GL_API(glTexParameterx, target, pname, param); +} + +void API_ENTRY(glTexSubImage2D)( GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels) { + CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, + width, height, format, type, pixels); +} + +void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glTranslatef, x, y, z); +} + +void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glTranslatex, x, y, z); +} + +void API_ENTRY(glVertexPointer)( GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glVertexPointer, size, type, stride, pointer); +} + +void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glViewport, x, y, width, height); +} + +// ES 1.1 +void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) { + CALL_GL_API(glClipPlanef, plane, equation); +} +void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) { + CALL_GL_API(glClipPlanex, plane, equation); +} +void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { + CALL_GL_API(glBindBuffer, target, buffer); +} +void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { + CALL_GL_API(glBufferData, target, size, data, usage); +} +void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { + CALL_GL_API(glBufferSubData, target, offset, size, data); +} +void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) { + CALL_GL_API(glDeleteBuffers, n, buffers); +} +void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) { + CALL_GL_API(glGenBuffers, n, buffers); +} +void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) { + CALL_GL_API(glGetBooleanv, pname, params); +} +void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) { + CALL_GL_API(glGetFixedv, pname, params); +} +void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) { + CALL_GL_API(glGetFloatv, pname, params); +} +void API_ENTRY(glGetPointerv)(GLenum pname, void **params) { + CALL_GL_API(glGetPointerv, pname, params); +} +void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) { + CALL_GL_API(glGetBufferParameteriv, target, pname, params); +} +void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) { + CALL_GL_API(glGetClipPlanef, pname, eqn); +} +void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) { + CALL_GL_API(glGetClipPlanex, pname, eqn); +} +void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetLightxv, light, pname, params); +} +void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetLightfv, light, pname, params); +} +void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetMaterialxv, face, pname, params); +} +void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetMaterialfv, face, pname, params); +} +void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexEnvfv, env, pname, params); +} +void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexEnviv, env, pname, params); +} +void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexEnvxv, env, pname, params); +} +void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexParameterfv, target, pname, params); +} +void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexParameteriv, target, pname, params); +} +void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexParameterxv, target, pname, params); +} +GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { + CALL_GL_API_RETURN(glIsBuffer, buffer); +} +GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { + CALL_GL_API_RETURN(glIsEnabled, cap); +} +GLboolean API_ENTRY(glIsTexture)(GLuint texture) { + CALL_GL_API_RETURN(glIsTexture, texture); +} +void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) { + CALL_GL_API(glPointParameterf, pname, param); +} +void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glPointParameterfv, pname, params); +} +void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) { + CALL_GL_API(glPointParameterx, pname, param); +} +void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glPointParameterxv, pname, params); +} +void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { + CALL_GL_API(glColor4ub, red, green, blue, alpha); +} +void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexEnvi, target, pname, param); +} +void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) { + CALL_GL_API(glTexEnviv, target, pname, params); +} + +void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexParameterfv, target, pname, params); +} + +void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) { + CALL_GL_API(glTexParameteriv, target, pname, params); +} + +void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexParameteri, target, pname, param); +} +void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexParameterxv, target, pname, params); +} +void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glPointSizePointerOES, type, stride, pointer); +} + +// Extensions +void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { + CALL_GL_API(glDrawTexsOES, x, y, z, w, h); +} +void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) { + CALL_GL_API(glDrawTexiOES, x, y, z, w, h); +} +void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) { + CALL_GL_API(glDrawTexfOES, x, y, z, w, h); +} +void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { + CALL_GL_API(glDrawTexxOES, x, y, z, w, h); +} +void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) { + CALL_GL_API(glDrawTexsvOES, coords); +} +void API_ENTRY(glDrawTexivOES)(const GLint* coords) { + CALL_GL_API(glDrawTexivOES, coords); +} +void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) { + CALL_GL_API(glDrawTexfvOES, coords); +} +void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) { + CALL_GL_API(glDrawTexxvOES, coords); +} +GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) { + CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); +} diff --git a/opengl/libGLES_CM/gl_entries.cpp b/opengl/libGLES_CM/gl_entries.cpp new file mode 100644 index 0000000..3279322 --- /dev/null +++ b/opengl/libGLES_CM/gl_entries.cpp @@ -0,0 +1,159 @@ +GL_ENTRY(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glColor4x, GLfixed, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glNormal3f, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glNormal3x, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glCullFace, GLenum) +GL_ENTRY(void, glFrontFace, GLenum) +GL_ENTRY(void, glDisable, GLenum) +GL_ENTRY(void, glEnable, GLenum) +GL_ENTRY(void, glFinish, void) +GL_ENTRY(void, glFlush, void) +GL_ENTRY(GLenum, glGetError, void) +GL_ENTRY(const GLubyte*, glGetString, GLenum) +GL_ENTRY(void, glGetIntegerv, GLenum, GLint *) +GL_ENTRY(void, glColorMask, GLboolean, GLboolean, GLboolean, GLboolean) +GL_ENTRY(void, glDepthMask, GLboolean) +GL_ENTRY(void, glStencilMask, GLuint) +GL_ENTRY(void, glDepthFunc, GLenum) +GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar) +GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar) +GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units) +GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units) +GL_ENTRY(void, glLogicOp, GLenum opcode) +GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref) +GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref) +GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor) +GL_ENTRY(void, glClear, GLbitfield mask) +GL_ENTRY(void, glClearColor, GLclampf r, GLclampf g, GLclampf b, GLclampf a) +GL_ENTRY(void, glClearColorx, GLclampx r, GLclampx g, GLclampx b, GLclampx a) +GL_ENTRY(void, glClearDepthf, GLclampf depth) +GL_ENTRY(void, glClearDepthx, GLclampx depth) +GL_ENTRY(void, glClearStencil, GLint s) +GL_ENTRY(void, glPointSize, GLfloat) +GL_ENTRY(void, glPointSizex, GLfixed) +GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert) +GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert) +GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask) +GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass) +GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glHint, GLenum, GLenum mode) +GL_ENTRY(void, glLineWidth, GLfloat width) +GL_ENTRY(void, glLineWidthx, GLfixed width) +GL_ENTRY(void, glShadeModel, GLenum) +GL_ENTRY(void, glLightModelf, GLenum, GLfloat) +GL_ENTRY(void, glLightModelfv, GLenum, const GLfloat *) +GL_ENTRY(void, glLightModelx, GLenum, GLfixed) +GL_ENTRY(void, glLightModelxv, GLenum, const GLfixed *) +GL_ENTRY(void, glLightf, GLenum, GLenum, GLfloat) +GL_ENTRY(void, glLightfv, GLenum, GLenum, const GLfloat *) +GL_ENTRY(void, glLightx, GLenum, GLenum, GLfixed) +GL_ENTRY(void, glLightxv, GLenum, GLenum, const GLfixed *) +GL_ENTRY(void, glMaterialf, GLenum, GLenum, GLfloat) +GL_ENTRY(void, glMaterialfv, GLenum, GLenum, const GLfloat *) +GL_ENTRY(void, glMaterialx, GLenum, GLenum, GLfixed) +GL_ENTRY(void, glMaterialxv, GLenum, GLenum, const GLfixed *) +GL_ENTRY(void, glFogf, GLenum, GLfloat) +GL_ENTRY(void, glFogfv, GLenum, const GLfloat *) +GL_ENTRY(void, glFogx, GLenum, GLfixed) +GL_ENTRY(void, glFogxv, GLenum, const GLfixed *) +GL_ENTRY(void, glVertexPointer, GLint, GLenum, GLsizei, const GLvoid *) +GL_ENTRY(void, glColorPointer, GLint, GLenum, GLsizei, const GLvoid *) +GL_ENTRY(void, glNormalPointer, GLenum, GLsizei, const GLvoid *) +GL_ENTRY(void, glTexCoordPointer, GLint, GLenum, GLsizei, const GLvoid *) +GL_ENTRY(void, glEnableClientState, GLenum) +GL_ENTRY(void, glDisableClientState, GLenum) +GL_ENTRY(void, glClientActiveTexture, GLenum) +GL_ENTRY(void, glDrawArrays, GLenum, GLint first, GLsizei) +GL_ENTRY(void, glDrawElements, GLenum, GLsizei, GLenum, const GLvoid *) +GL_ENTRY(void, glLoadIdentity, void) +GL_ENTRY(void, glLoadMatrixf, const GLfloat*) +GL_ENTRY(void, glLoadMatrixx, const GLfixed*) +GL_ENTRY(void, glMatrixMode, GLenum mode) +GL_ENTRY(void, glMultMatrixf, const GLfloat*) +GL_ENTRY(void, glMultMatrixx, const GLfixed*) +GL_ENTRY(void, glPopMatrix, void) +GL_ENTRY(void, glPushMatrix, void) +GL_ENTRY(void, glFrustumf, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glFrustumx, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glOrthof, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glOrthox, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glRotatef, GLfloat, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glRotatex, GLfixed, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glScalef, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glScalex, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glTranslatef, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glTranslatex, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glViewport, GLint, GLint, GLsizei, GLsizei) +GL_ENTRY(void, glActiveTexture, GLenum) +GL_ENTRY(void, glBindTexture, GLenum, GLuint) +GL_ENTRY(void, glGenTextures, GLsizei, GLuint*) +GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *) +GL_ENTRY(void, glMultiTexCoord4f, GLenum, GLfloat, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glMultiTexCoord4x, GLenum, GLfixed, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glPixelStorei, GLenum, GLint) +GL_ENTRY(void, glTexEnvf, GLenum, GLenum, GLfloat) +GL_ENTRY(void, glTexEnvfv, GLenum, GLenum, const GLfloat*) +GL_ENTRY(void, glTexEnvx, GLenum, GLenum, GLfixed) +GL_ENTRY(void, glTexEnvxv, GLenum, GLenum, const GLfixed*) +GL_ENTRY(void, glTexParameterf, GLenum, GLenum, GLfloat) +GL_ENTRY(void, glTexParameterx, GLenum, GLenum, GLfixed) +GL_ENTRY(void, glCompressedTexImage2D, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*) +GL_ENTRY(void, glCompressedTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*) +GL_ENTRY(void, glCopyTexImage2D, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint) +GL_ENTRY(void, glCopyTexSubImage2D, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei) +GL_ENTRY(void, glTexImage2D, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*) +GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*) +GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *) + +// 1.1 additions +GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat*) +GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed*) +GL_ENTRY(void, glBindBuffer, GLenum, GLuint) +GL_ENTRY(void, glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum) +GL_ENTRY(void, glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*) +GL_ENTRY(void, glDeleteBuffers, GLsizei, const GLuint*) +GL_ENTRY(void, glGenBuffers, GLsizei, GLuint*) +GL_ENTRY(void, glGetBooleanv, GLenum, GLboolean *) +GL_ENTRY(void, glGetFixedv, GLenum, GLfixed *) +GL_ENTRY(void, glGetFloatv, GLenum, GLfloat *) +GL_ENTRY(void, glGetPointerv, GLenum, void **) +GL_ENTRY(void, glGetBufferParameteriv, GLenum, GLenum, GLint *) +GL_ENTRY(void, glGetClipPlanef, GLenum, GLfloat[4]) +GL_ENTRY(void, glGetClipPlanex, GLenum, GLfixed[4]) +GL_ENTRY(void, glGetLightxv, GLenum, GLenum, GLfixed *) +GL_ENTRY(void, glGetLightfv, GLenum, GLenum, GLfloat *) +GL_ENTRY(void, glGetMaterialxv, GLenum, GLenum, GLfixed *) +GL_ENTRY(void, glGetMaterialfv, GLenum, GLenum, GLfloat *) +GL_ENTRY(void, glGetTexEnvfv, GLenum, GLenum, GLfloat *) +GL_ENTRY(void, glGetTexEnviv, GLenum, GLenum, GLint *) +GL_ENTRY(void, glGetTexEnvxv, GLenum, GLenum, GLfixed *) +GL_ENTRY(void, glGetTexParameterfv, GLenum, GLenum, GLfloat *) +GL_ENTRY(void, glGetTexParameteriv, GLenum, GLenum, GLint *) +GL_ENTRY(void, glGetTexParameterxv, GLenum, GLenum, GLfixed *) +GL_ENTRY(GLboolean, glIsBuffer, GLuint) +GL_ENTRY(GLboolean, glIsEnabled, GLenum) +GL_ENTRY(GLboolean, glIsTexture, GLuint) +GL_ENTRY(void, glPointParameterf, GLenum, GLfloat) +GL_ENTRY(void, glPointParameterfv, GLenum, const GLfloat *) +GL_ENTRY(void, glPointParameterx, GLenum, GLfixed) +GL_ENTRY(void, glPointParameterxv, GLenum, const GLfixed *) +GL_ENTRY(void, glColor4ub, GLubyte, GLubyte, GLubyte, GLubyte) +GL_ENTRY(void, glTexEnvi, GLenum, GLenum, GLint) +GL_ENTRY(void, glTexEnviv, GLenum, GLenum, const GLint *) +GL_ENTRY(void, glTexParameterfv, GLenum, GLenum, const GLfloat *) +GL_ENTRY(void, glTexParameteriv, GLenum, GLenum, const GLint *) +GL_ENTRY(void, glTexParameteri, GLenum, GLenum, GLint) +GL_ENTRY(void, glTexParameterxv, GLenum, GLenum, const GLfixed *) +GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid*) + +// Extensions +GL_ENTRY(void, glDrawTexsOES, GLshort, GLshort, GLshort, GLshort, GLshort) +GL_ENTRY(void, glDrawTexiOES, GLint, GLint, GLint, GLint, GLint) +GL_ENTRY(void, glDrawTexfOES, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) +GL_ENTRY(void, glDrawTexxOES, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed) +GL_ENTRY(void, glDrawTexsvOES, const GLshort*) +GL_ENTRY(void, glDrawTexivOES, const GLint*) +GL_ENTRY(void, glDrawTexfvOES, const GLfloat*) +GL_ENTRY(void, glDrawTexxvOES, const GLfixed*) +GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed* mantissa, GLint* exponent) + diff --git a/opengl/libGLES_CM/gl_enums.in b/opengl/libGLES_CM/gl_enums.in new file mode 100644 index 0000000..ffc2fad --- /dev/null +++ b/opengl/libGLES_CM/gl_enums.in @@ -0,0 +1,261 @@ +GLENUM(GL_POINTS, 0x0000) +GLENUM(GL_LINES, 0x0001) +GLENUM(GL_LINE_LOOP, 0x0002) +GLENUM(GL_LINE_STRIP, 0x0003) +GLENUM(GL_TRIANGLES, 0x0004) +GLENUM(GL_TRIANGLE_STRIP, 0x0005) +GLENUM(GL_TRIANGLE_FAN, 0x0006) +GLENUM(GL_ADD, 0x0104) +GLENUM(GL_NEVER, 0x0200) +GLENUM(GL_LESS, 0x0201) +GLENUM(GL_EQUAL, 0x0202) +GLENUM(GL_LEQUAL, 0x0203) +GLENUM(GL_GREATER, 0x0204) +GLENUM(GL_NOTEQUAL, 0x0205) +GLENUM(GL_GEQUAL, 0x0206) +GLENUM(GL_ALWAYS, 0x0207) +GLENUM(GL_SRC_COLOR, 0x0300) +GLENUM(GL_ONE_MINUS_SRC_COLOR, 0x0301) +GLENUM(GL_SRC_ALPHA, 0x0302) +GLENUM(GL_ONE_MINUS_SRC_ALPHA, 0x0303) +GLENUM(GL_DST_ALPHA, 0x0304) +GLENUM(GL_ONE_MINUS_DST_ALPHA, 0x0305) +GLENUM(GL_DST_COLOR, 0x0306) +GLENUM(GL_ONE_MINUS_DST_COLOR, 0x0307) +GLENUM(GL_SRC_ALPHA_SATURATE, 0x0308) +GLENUM(GL_FRONT, 0x0404) +GLENUM(GL_BACK, 0x0405) +GLENUM(GL_FRONT_AND_BACK, 0x0408) +GLENUM(GL_INVALID_ENUM, 0x0500) +GLENUM(GL_INVALID_VALUE, 0x0501) +GLENUM(GL_INVALID_OPERATION, 0x0502) +GLENUM(GL_STACK_OVERFLOW, 0x0503) +GLENUM(GL_STACK_UNDERFLOW, 0x0504) +GLENUM(GL_OUT_OF_MEMORY, 0x0505) +GLENUM(GL_EXP, 0x0800) +GLENUM(GL_EXP2, 0x0801) +GLENUM(GL_CW, 0x0900) +GLENUM(GL_CCW, 0x0901) +GLENUM(GL_POINT_SMOOTH, 0x0B10) +GLENUM(GL_SMOOTH_POINT_SIZE_RANGE, 0x0B12) +GLENUM(GL_LINE_SMOOTH, 0x0B20) +GLENUM(GL_SMOOTH_LINE_WIDTH_RANGE, 0x0B22) +GLENUM(GL_CULL_FACE, 0x0B44) +GLENUM(GL_LIGHTING, 0x0B50) +GLENUM(GL_LIGHT_MODEL_TWO_SIDE, 0x0B52) +GLENUM(GL_LIGHT_MODEL_AMBIENT, 0x0B53) +GLENUM(GL_COLOR_MATERIAL, 0x0B57) +GLENUM(GL_FOG, 0x0B60) +GLENUM(GL_FOG_DENSITY, 0x0B62) +GLENUM(GL_FOG_START, 0x0B63) +GLENUM(GL_FOG_END, 0x0B64) +GLENUM(GL_FOG_MODE, 0x0B65) +GLENUM(GL_FOG_COLOR, 0x0B66) +GLENUM(GL_DEPTH_TEST, 0x0B71) +GLENUM(GL_STENCIL_TEST, 0x0B90) +GLENUM(GL_NORMALIZE, 0x0BA1) +GLENUM(GL_ALPHA_TEST, 0x0BC0) +GLENUM(GL_DITHER, 0x0BD0) +GLENUM(GL_BLEND, 0x0BE2) +GLENUM(GL_COLOR_LOGIC_OP, 0x0BF2) +GLENUM(GL_SCISSOR_TEST, 0x0C11) +GLENUM(GL_PERSPECTIVE_CORRECTION_HINT, 0x0C50) +GLENUM(GL_POINT_SMOOTH_HINT, 0x0C51) +GLENUM(GL_LINE_SMOOTH_HINT, 0x0C52) +GLENUM(GL_POLYGON_SMOOTH_HINT, 0x0C53) +GLENUM(GL_FOG_HINT, 0x0C54) +GLENUM(GL_UNPACK_ALIGNMENT, 0x0CF5) +GLENUM(GL_PACK_ALIGNMENT, 0x0D05) +GLENUM(GL_MAX_LIGHTS, 0x0D31) +GLENUM(GL_MAX_CLIP_PLANES, 0x0D32) +GLENUM(GL_MAX_TEXTURE_SIZE, 0x0D33) +GLENUM(GL_MAX_MODELVIEW_STACK_DEPTH, 0x0D36) +GLENUM(GL_MAX_PROJECTION_STACK_DEPTH, 0x0D38) +GLENUM(GL_MAX_TEXTURE_STACK_DEPTH, 0x0D39) +GLENUM(GL_MAX_VIEWPORT_DIMS, 0x0D3A) +GLENUM(GL_RED_BITS, 0x0D52) +GLENUM(GL_GREEN_BITS, 0x0D53) +GLENUM(GL_BLUE_BITS, 0x0D54) +GLENUM(GL_ALPHA_BITS, 0x0D55) +GLENUM(GL_DEPTH_BITS, 0x0D56) +GLENUM(GL_STENCIL_BITS, 0x0D57) +GLENUM(GL_TEXTURE_2D, 0x0DE1) +GLENUM(GL_DONT_CARE, 0x1100) +GLENUM(GL_FASTEST, 0x1101) +GLENUM(GL_NICEST, 0x1102) +GLENUM(GL_AMBIENT, 0x1200) +GLENUM(GL_DIFFUSE, 0x1201) +GLENUM(GL_SPECULAR, 0x1202) +GLENUM(GL_POSITION, 0x1203) +GLENUM(GL_SPOT_DIRECTION, 0x1204) +GLENUM(GL_SPOT_EXPONENT, 0x1205) +GLENUM(GL_SPOT_CUTOFF, 0x1206) +GLENUM(GL_CONSTANT_ATTENUATION, 0x1207) +GLENUM(GL_LINEAR_ATTENUATION, 0x1208) +GLENUM(GL_QUADRATIC_ATTENUATION, 0x1209) +GLENUM(GL_BYTE, 0x1400) +GLENUM(GL_UNSIGNED_BYTE, 0x1401) +GLENUM(GL_SHORT, 0x1402) +GLENUM(GL_UNSIGNED_SHORT, 0x1403) +GLENUM(GL_FLOAT, 0x1406) +GLENUM(GL_FIXED, 0x140C) +GLENUM(GL_CLEAR, 0x1500) +GLENUM(GL_AND, 0x1501) +GLENUM(GL_AND_REVERSE, 0x1502) +GLENUM(GL_COPY, 0x1503) +GLENUM(GL_AND_INVERTED, 0x1504) +GLENUM(GL_NOOP, 0x1505) +GLENUM(GL_XOR, 0x1506) +GLENUM(GL_OR, 0x1507) +GLENUM(GL_NOR, 0x1508) +GLENUM(GL_EQUIV, 0x1509) +GLENUM(GL_INVERT, 0x150A) +GLENUM(GL_OR_REVERSE, 0x150B) +GLENUM(GL_COPY_INVERTED, 0x150C) +GLENUM(GL_OR_INVERTED, 0x150D) +GLENUM(GL_NAND, 0x150E) +GLENUM(GL_SET, 0x150F) +GLENUM(GL_EMISSION, 0x1600) +GLENUM(GL_SHININESS, 0x1601) +GLENUM(GL_AMBIENT_AND_DIFFUSE, 0x1602) +GLENUM(GL_MODELVIEW, 0x1700) +GLENUM(GL_PROJECTION, 0x1701) +GLENUM(GL_TEXTURE, 0x1702) +GLENUM(GL_ALPHA, 0x1906) +GLENUM(GL_RGB, 0x1907) +GLENUM(GL_RGBA, 0x1908) +GLENUM(GL_LUMINANCE, 0x1909) +GLENUM(GL_LUMINANCE_ALPHA, 0x190A) +GLENUM(GL_FLAT, 0x1D00) +GLENUM(GL_SMOOTH, 0x1D01) +GLENUM(GL_KEEP, 0x1E00) +GLENUM(GL_REPLACE, 0x1E01) +GLENUM(GL_REPLACE, 0x1E01) +GLENUM(GL_INCR, 0x1E02) +GLENUM(GL_DECR, 0x1E03) +GLENUM(GL_VENDOR, 0x1F00) +GLENUM(GL_RENDERER, 0x1F01) +GLENUM(GL_VERSION, 0x1F02) +GLENUM(GL_EXTENSIONS, 0x1F03) +GLENUM(GL_MODULATE, 0x2100) +GLENUM(GL_DECAL, 0x2101) +GLENUM(GL_TEXTURE_ENV_MODE, 0x2200) +GLENUM(GL_TEXTURE_ENV_COLOR, 0x2201) +GLENUM(GL_TEXTURE_ENV, 0x2300) +GLENUM(GL_NEAREST, 0x2600) +GLENUM(GL_LINEAR, 0x2601) +GLENUM(GL_NEAREST_MIPMAP_NEAREST, 0x2700) +GLENUM(GL_LINEAR_MIPMAP_NEAREST, 0x2701) +GLENUM(GL_NEAREST_MIPMAP_LINEAR, 0x2702) +GLENUM(GL_LINEAR_MIPMAP_LINEAR, 0x2703) +GLENUM(GL_TEXTURE_MAG_FILTER, 0x2800) +GLENUM(GL_TEXTURE_MIN_FILTER, 0x2801) +GLENUM(GL_TEXTURE_WRAP_S, 0x2802) +GLENUM(GL_TEXTURE_WRAP_T, 0x2803) +GLENUM(GL_CLAMP, 0x2900) +GLENUM(GL_REPEAT, 0x2901) +GLENUM(GL_CLIP_PLANE0, 0x3000) +GLENUM(GL_CLIP_PLANE1, 0x3001) +GLENUM(GL_CLIP_PLANE2, 0x3002) +GLENUM(GL_CLIP_PLANE3, 0x3003) +GLENUM(GL_CLIP_PLANE4, 0x3004) +GLENUM(GL_CLIP_PLANE5, 0x3005) +GLENUM(GL_LIGHT0, 0x4000) +GLENUM(GL_LIGHT1, 0x4001) +GLENUM(GL_LIGHT2, 0x4002) +GLENUM(GL_LIGHT3, 0x4003) +GLENUM(GL_LIGHT4, 0x4004) +GLENUM(GL_LIGHT5, 0x4005) +GLENUM(GL_LIGHT6, 0x4006) +GLENUM(GL_LIGHT7, 0x4007) +GLENUM(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0x7E80) +GLENUM(GL_UNSIGNED_SHORT_4_4_4_4, 0x8033) +GLENUM(GL_UNSIGNED_SHORT_5_5_5_1, 0x8034) +GLENUM(GL_POLYGON_OFFSET_FILL, 0x8037) +GLENUM(GL_RESCALE_NORMAL, 0x803A) +GLENUM(GL_VERTEX_ARRAY, 0x8074) +GLENUM(GL_NORMAL_ARRAY, 0x8075) +GLENUM(GL_COLOR_ARRAY, 0x8076) +GLENUM(GL_TEXTURE_COORD_ARRAY, 0x8078) +GLENUM(GL_MULTISAMPLE, 0x809D) +GLENUM(GL_SAMPLE_ALPHA_TO_COVERAGE, 0x809E) +GLENUM(GL_SAMPLE_ALPHA_TO_ONE, 0x809F) +GLENUM(GL_SAMPLE_COVERAGE, 0x80A0) +GLENUM(GL_MAX_ELEMENTS_VERTICES, 0x80E8) +GLENUM(GL_MAX_ELEMENTS_INDICES, 0x80E9) +GLENUM(GL_CLAMP_TO_EDGE, 0x812F) +GLENUM(GL_GENERATE_MIPMAP, 0x8191) +GLENUM(GL_GENERATE_MIPMAP_HINT, 0x8192) +GLENUM(GL_UNSIGNED_SHORT_5_6_5, 0x8363) +GLENUM(GL_ALIASED_POINT_SIZE_RANGE, 0x846D) +GLENUM(GL_ALIASED_LINE_WIDTH_RANGE, 0x846E) +GLENUM(GL_TEXTURE0, 0x84C0) +GLENUM(GL_TEXTURE1, 0x84C1) +GLENUM(GL_TEXTURE2, 0x84C2) +GLENUM(GL_TEXTURE3, 0x84C3) +GLENUM(GL_TEXTURE4, 0x84C4) +GLENUM(GL_TEXTURE5, 0x84C5) +GLENUM(GL_TEXTURE6, 0x84C6) +GLENUM(GL_TEXTURE7, 0x84C7) +GLENUM(GL_TEXTURE8, 0x84C8) +GLENUM(GL_TEXTURE9, 0x84C9) +GLENUM(GL_TEXTURE10, 0x84CA) +GLENUM(GL_TEXTURE11, 0x84CB) +GLENUM(GL_TEXTURE12, 0x84CC) +GLENUM(GL_TEXTURE13, 0x84CD) +GLENUM(GL_TEXTURE14, 0x84CE) +GLENUM(GL_TEXTURE15, 0x84CF) +GLENUM(GL_TEXTURE16, 0x84D0) +GLENUM(GL_TEXTURE17, 0x84D1) +GLENUM(GL_TEXTURE18, 0x84D2) +GLENUM(GL_TEXTURE19, 0x84D3) +GLENUM(GL_TEXTURE20, 0x84D4) +GLENUM(GL_TEXTURE21, 0x84D5) +GLENUM(GL_TEXTURE22, 0x84D6) +GLENUM(GL_TEXTURE23, 0x84D7) +GLENUM(GL_TEXTURE24, 0x84D8) +GLENUM(GL_TEXTURE25, 0x84D9) +GLENUM(GL_TEXTURE26, 0x84DA) +GLENUM(GL_TEXTURE27, 0x84DB) +GLENUM(GL_TEXTURE28, 0x84DC) +GLENUM(GL_TEXTURE29, 0x84DD) +GLENUM(GL_TEXTURE30, 0x84DE) +GLENUM(GL_TEXTURE31, 0x84DF) +GLENUM(GL_MAX_TEXTURE_UNITS, 0x84E2) +GLENUM(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 0x86A2) +GLENUM(GL_COMPRESSED_TEXTURE_FORMATS, 0x86A3) +GLENUM(GL_BUFFER_SIZE, 0x8764) +GLENUM(GL_BUFFER_USAGE, 0x8765) +GLENUM(GL_POINT_SPRITE_OES, 0x8861) +GLENUM(GL_COORD_REPLACE_OES, 0x8862) +GLENUM(GL_ARRAY_BUFFER, 0x8892) +GLENUM(GL_ELEMENT_ARRAY_BUFFER, 0x8893) +GLENUM(GL_ARRAY_BUFFER_BINDING, 0x8894) +GLENUM(GL_ELEMENT_ARRAY_BUFFER_BINDING, 0x8895) +GLENUM(GL_VERTEX_ARRAY_BUFFER_BINDING, 0x8896) +GLENUM(GL_NORMAL_ARRAY_BUFFER_BINDING, 0x8897) +GLENUM(GL_COLOR_ARRAY_BUFFER_BINDING, 0x8898) +GLENUM(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, 0x889A) +GLENUM(GL_STATIC_DRAW, 0x88E4) +GLENUM(GL_DYNAMIC_DRAW, 0x88E8) +GLENUM(GL_POINT_SIZE_ARRAY_TYPE_OES, 0x898A) +GLENUM(GL_POINT_SIZE_ARRAY_STRIDE_OES, 0x898B) +GLENUM(GL_POINT_SIZE_ARRAY_POINTER_OES, 0x898C) +GLENUM(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898D) +GLENUM(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898E) +GLENUM(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898F) +GLENUM(GL_PALETTE4_RGB8_OES, 0x8B90) +GLENUM(GL_PALETTE4_RGBA8_OES, 0x8B91) +GLENUM(GL_PALETTE4_R5_G6_B5_OES, 0x8B92) +GLENUM(GL_PALETTE4_RGBA4_OES, 0x8B93) +GLENUM(GL_PALETTE4_RGB5_A1_OES, 0x8B94) +GLENUM(GL_PALETTE8_RGB8_OES, 0x8B95) +GLENUM(GL_PALETTE8_RGBA8_OES, 0x8B96) +GLENUM(GL_PALETTE8_R5_G6_B5_OES, 0x8B97) +GLENUM(GL_PALETTE8_RGBA4_OES, 0x8B98) +GLENUM(GL_PALETTE8_RGB5_A1_OES, 0x8B99) +GLENUM(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, 0x8B9A) +GLENUM(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, 0x8B9B) +GLENUM(GL_POINT_SIZE_ARRAY_OES, 0x8B9C) +GLENUM(GL_TEXTURE_CROP_RECT_OES, 0x8B9D) +GLENUM(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES, 0x8B9F) diff --git a/opengl/libGLES_CM/gl_logger.cpp b/opengl/libGLES_CM/gl_logger.cpp new file mode 100644 index 0000000..14b5a39 --- /dev/null +++ b/opengl/libGLES_CM/gl_logger.cpp @@ -0,0 +1,1059 @@ +/* + ** Copyright 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. + */ + +#define LOG_TAG "GLLogger" + +#include <ctype.h> +#include <string.h> +#include <errno.h> +#include <dlfcn.h> + +#include <sys/ioctl.h> + +#include <GLES/egl.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <cutils/properties.h> + +#include <utils/String8.h> + +#include "gl_logger.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +#undef NELEM +#define NELEM(x) (sizeof(x)/sizeof(*(x))) + +template<typename T> +static int binarySearch(T const sortedArray[], int first, int last, EGLint key) +{ + while (first <= last) { + int mid = (first + last) / 2; + if (key > sortedArray[mid].key) { + first = mid + 1; + } else if (key < sortedArray[mid].key) { + last = mid - 1; + } else { + return mid; + } + } + return -1; +} + +struct pair_t { + const char* name; + int key; +}; + +static const pair_t gEnumMap[] = { + #define GLENUM(NAME, VALUE) { #NAME, VALUE }, + #include "gl_enums.in" + #undef GLENUM +}; + +// ---------------------------------------------------------------------------- + +template<typename TYPE> +class GLLogValue { +public: + GLLogValue(TYPE value) : mValue(value) { } + const TYPE& getValue() const { return mValue; } + String8 toString() const { + return convertToString(mValue); + } +private: + const TYPE& mValue; + String8 convertToString(unsigned int v) const { + char buf[16]; + snprintf(buf, 16, "%u", v); + return String8(buf); + } + String8 convertToString(unsigned long v) const { + char buf[16]; + snprintf(buf, 16, "%lu", v); + return String8(buf); + } + String8 convertToString(int v) const { + char buf[16]; + snprintf(buf, 16, "%d", v); + return String8(buf); + } + String8 convertToString(long v) const { + char buf[16]; + snprintf(buf, 16, "%ld", v); + return String8(buf); + } + String8 convertToString(float v) const { + char buf[16]; + snprintf(buf, 16, "%f", v); + return String8(buf); + } + String8 convertToString(void const* v) const { + char buf[16]; + snprintf(buf, 16, "%p", v); + return String8(buf); + } +}; + +class GLLogEnum : public GLLogValue<GLenum> { +public: + GLLogEnum(GLenum v) : GLLogValue<GLenum>(v) { } + String8 toString() const { + GLenum v = getValue(); + int i = binarySearch<pair_t>(gEnumMap, 0, NELEM(gEnumMap)-1, v); + if (i >= 0) { + return String8(gEnumMap[i].name); + } else { + char buf[16]; + snprintf(buf, 16, "0x%04x", v); + return String8(buf); + } + } +}; + +class GLLogClearBitfield : public GLLogValue<GLbitfield> { +public: + GLLogClearBitfield(GLbitfield v) : GLLogValue<GLbitfield>(v) { } + String8 toString() const { + char buf[16]; + snprintf(buf, 16, "0x%08x", getValue()); + return String8(buf); + } +}; + +class GLLogBool : public GLLogValue<GLboolean> { +public: + GLLogBool(GLboolean v) : GLLogValue<GLboolean>(v) { } + String8 toString() const { + GLboolean v = getValue(); + if (v == GL_TRUE) return String8("GL_TRUE"); + if (v == GL_FALSE) return String8("GL_FALSE"); + return GLLogValue<GLboolean>::toString(); + } +}; + +class GLLogFixed : public GLLogValue<GLfixed> { +public: + GLLogFixed(GLfixed v) : GLLogValue<GLfixed>(v) { } + String8 toString() const { + char buf[16]; + snprintf(buf, 16, "0x%08x", getValue()); + return String8(buf); + } +}; + + +template <typename TYPE> +class GLLogBuffer : public GLLogValue<TYPE *> { +public: + GLLogBuffer(TYPE* buffer, size_t count = -1) + : GLLogValue<TYPE*>(buffer) + { // output buffer + } + GLLogBuffer(TYPE const* buffer, size_t count = -1) + : GLLogValue<TYPE*>(const_cast<TYPE*>(buffer)) + { // input buffer + } +}; + +class GLLog +{ +public: + GLLog(const char* name) : mNumParams(0) { + mString.append(name); + mString.append("("); + } + + ~GLLog() { + LOGD("%s);", mString.string()); + } + + GLLog& operator << (unsigned char v) { + return *this << GLLogValue<unsigned int>(v); + } + GLLog& operator << (short v) { + return *this << GLLogValue<unsigned int>(v); + } + GLLog& operator << (unsigned int v) { + return *this << GLLogValue<unsigned int>(v); + } + GLLog& operator << (int v) { + return *this << GLLogValue<int>(v); + } + GLLog& operator << (long v) { + return *this << GLLogValue<long>(v); + } + GLLog& operator << (unsigned long v) { + return *this << GLLogValue<unsigned long>(v); + } + GLLog& operator << (float v) { + return *this << GLLogValue<float>(v); + } + GLLog& operator << (const void* v) { + return *this << GLLogValue<const void* >(v); + } + + template <typename TYPE> + GLLog& operator << (const TYPE& rhs) { + if (mNumParams > 0) + mString.append(", "); + mString.append(rhs.toString()); + mNumParams++; + return *this; + } + + const String8& string() const { return mString; } +private: + GLLog(const GLLog&); + + String8 mString; + int mNumParams; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + +#define API_ENTRY(api) log_##api +#define CALL_GL_API(_x, ...) +#define CALL_GL_API_RETURN(_x, ...) return(0); + +void API_ENTRY(glActiveTexture)(GLenum texture) { + CALL_GL_API(glActiveTexture, texture); + GLLog("glActiveTexture") << GLLogEnum(texture); +} + +void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) { + CALL_GL_API(glAlphaFunc, func, ref); + GLLog("glAlphaFunc") << GLLogEnum(func) << ref; +} + +void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) { + CALL_GL_API(glAlphaFuncx, func, ref); + GLLog("glAlphaFuncx") << GLLogEnum(func) << GLLogFixed(ref); +} + +void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) { + CALL_GL_API(glBindTexture, target, texture); + GLLog("glBindTexture") << GLLogEnum(target) << texture; +} + +void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) { + CALL_GL_API(glBlendFunc, sfactor, dfactor); + GLLog("glBlendFunc") << GLLogEnum(sfactor) << GLLogEnum(dfactor); +} + +void API_ENTRY(glClear)(GLbitfield mask) { + CALL_GL_API(glClear, mask); + GLLog("glClear") << GLLogClearBitfield(mask); +} + +void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + CALL_GL_API(glClearColor, red, green, blue, alpha); + GLLog("glClearColor") << red << green << blue << alpha; +} + +void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { + CALL_GL_API(glClearColorx, red, green, blue, alpha); + GLLog("glClearColorx") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha); +} + +void API_ENTRY(glClearDepthf)(GLclampf depth) { + CALL_GL_API(glClearDepthf, depth); + GLLog("glClearDepthf") << depth; +} + +void API_ENTRY(glClearDepthx)(GLclampx depth) { + CALL_GL_API(glClearDepthx, depth); + GLLog("glClearDepthx") << GLLogFixed(depth); +} + +void API_ENTRY(glClearStencil)(GLint s) { + CALL_GL_API(glClearStencil, s); + GLLog("glClearStencil") << s; +} + +void API_ENTRY(glClientActiveTexture)(GLenum texture) { + CALL_GL_API(glClientActiveTexture, texture); + GLLog("glClientActiveTexture") << GLLogEnum(texture); +} + +void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + CALL_GL_API(glColor4f, red, green, blue, alpha); + GLLog("glColor4f") << red << green << blue << alpha; +} + +void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { + CALL_GL_API(glColor4x, red, green, blue, alpha); + GLLog("glColor4x") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha); +} + +void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { + CALL_GL_API(glColorMask, r, g, b, a); + GLLog("glColorMask") << GLLogBool(r) << GLLogBool(g) << GLLogBool(b) << GLLogBool(a); +} + +void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) +{ + CALL_GL_API(glColorPointer, size, type, stride, ptr); + GLLog("glColorPointer") << size << GLLogEnum(type) << stride << ptr; +} + +void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLsizei imageSize, const GLvoid *data) { + CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, + width, height, border, imageSize, data); + GLLog("glCompressedTexImage2D") + << GLLogEnum(target) << level << GLLogEnum(internalformat) + << width << height << border << imageSize << data; +} + +void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data) { + CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, + width, height, format, imageSize, data); + GLLog("glCompressedTexSubImage2D") + << GLLogEnum(target) << level << xoffset << yoffset + << width << height << GLLogEnum(format) << imageSize << data; +} + +void API_ENTRY(glCopyTexImage2D)( GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) { + CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, + width, height, border); + GLLog("glCopyTexImage2D") + << GLLogEnum(target) << level << GLLogEnum(internalformat) + << x << y << width << height << border; +} + +void API_ENTRY(glCopyTexSubImage2D)( GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint x, GLint y, GLsizei width, + GLsizei height) { + CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, + width, height); + GLLog("glCopyTexSubImage2D") + << GLLogEnum(target) << level << xoffset << yoffset + << x << y << width << height; +} + +void API_ENTRY(glCullFace)(GLenum mode) { + CALL_GL_API(glCullFace, mode); + GLLog("glCullFace") << GLLogEnum(mode); +} + +void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) { + CALL_GL_API(glDeleteTextures, n, textures); + GLLog("glDeleteTextures") << n << GLLogBuffer<GLuint>(textures, n); +} + +void API_ENTRY(glDepthFunc)(GLenum func) { + CALL_GL_API(glDepthFunc, func); + GLLog("glDepthFunc") << GLLogEnum(func); +} + +void API_ENTRY(glDepthMask)(GLboolean flag) { + CALL_GL_API(glDepthMask, flag); + GLLog("glDepthMask") << GLLogBool(flag); +} + +void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { + CALL_GL_API(glDepthRangef, zNear, zFar); + GLLog("glDepthRangef") << zNear << zFar; +} + +void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) { + CALL_GL_API(glDepthRangex, zNear, zFar); + GLLog("glDepthRangex") << GLLogFixed(zNear) << GLLogFixed(zFar); +} + +void API_ENTRY(glDisable)(GLenum cap) { + CALL_GL_API(glDisable, cap); + GLLog("glDisable") << GLLogEnum(cap); +} + +void API_ENTRY(glDisableClientState)(GLenum array) { + CALL_GL_API(glDisableClientState, array); + GLLog("glDisableClientState") << GLLogEnum(array); +} + +void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) { + CALL_GL_API(glDrawArrays, mode, first, count); + GLLog("glDrawArrays") << GLLogEnum(mode) << first << count; +} + +void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices) { + CALL_GL_API(glDrawElements, mode, count, type, indices); + GLLog log("glDrawElements"); + log << GLLogEnum(mode) << count << GLLogEnum(type); + if (type == GL_UNSIGNED_BYTE) { + log << GLLogBuffer<GLubyte>(static_cast<const GLubyte*>(indices), count); + } else { + log << GLLogBuffer<GLushort>(static_cast<const GLushort*>(indices), count); + } + log; +} + +void API_ENTRY(glEnable)(GLenum cap) { + CALL_GL_API(glEnable, cap); + GLLog("glEnable") << GLLogEnum(cap); +} + +void API_ENTRY(glEnableClientState)(GLenum array) { + CALL_GL_API(glEnableClientState, array); + GLLog("glEnableClientState") << GLLogEnum(array); +} + +void API_ENTRY(glFinish)(void) { + CALL_GL_API(glFinish); + GLLog("glFinish"); +} + +void API_ENTRY(glFlush)(void) { + CALL_GL_API(glFlush); + GLLog("glFlush"); +} + +void API_ENTRY(glFogf)(GLenum pname, GLfloat param) { + CALL_GL_API(glFogf, pname, param); + GLLog("glFogf") << GLLogEnum(pname) << param; +} + +void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glFogfv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glFogfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} + +void API_ENTRY(glFogx)(GLenum pname, GLfixed param) { + CALL_GL_API(glFogx, pname, param); + GLLog("glFogx") << GLLogEnum(pname) << GLLogFixed(param); +} + +void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glFogxv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glFogfx") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} + +void API_ENTRY(glFrontFace)(GLenum mode) { + CALL_GL_API(glFrontFace, mode); + GLLog("glFrontFace") << GLLogEnum(mode); + } + +void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar); + GLLog("glFrustumf") << left << right << bottom << top << zNear << zFar; +} + +void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed zNear, GLfixed zFar) { + CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar); + GLLog("glFrustumx") + << GLLogFixed(left) << GLLogFixed(right) + << GLLogFixed(bottom) << GLLogFixed(top) + << GLLogFixed(zNear) << GLLogFixed(zFar); +} + +void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) { + CALL_GL_API(glGenTextures, n, textures); + GLLog("glGenTextures") << n << GLLogBuffer<GLuint>(textures, n); +} + +GLenum API_ENTRY(glGetError)(void) { + GLLog("glGetError"); + CALL_GL_API_RETURN(glGetError); +} + +void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) { + CALL_GL_API(glGetIntegerv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetIntegerv") << GLLogEnum(pname) << GLLogBuffer<GLint>(params); +} + +const GLubyte * API_ENTRY(glGetString)(GLenum name) { + GLLog("glGetString") << GLLogEnum(name); + CALL_GL_API_RETURN(glGetString, name); +} + +void API_ENTRY(glHint)(GLenum target, GLenum mode) { + CALL_GL_API(glHint, target, mode); + GLLog("GLenum") << GLLogEnum(target) << GLLogEnum(mode); +} + +void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) { + CALL_GL_API(glLightModelf, pname, param); + GLLog("glLightModelf") << GLLogEnum(pname) << param; +} + +void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glLightModelfv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glLightModelfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} + +void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) { + CALL_GL_API(glLightModelx, pname, param); + GLLog("glLightModelx") << GLLogEnum(pname) << GLLogFixed(param); +} + +void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glLightModelxv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glLightModelxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} + +void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) { + CALL_GL_API(glLightf, light, pname, param); + GLLog("glLightf") << GLLogEnum(light) << GLLogEnum(pname) << param; +} + +void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) { + CALL_GL_API(glLightfv, light, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} + +void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) { + CALL_GL_API(glLightx, light, pname, param); + GLLog("glLightx") << GLLogEnum(light) << GLLogEnum(pname) << GLLogFixed(param); +} + +void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) { + CALL_GL_API(glLightxv, light, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} + +void API_ENTRY(glLineWidth)(GLfloat width) { + CALL_GL_API(glLineWidth, width); + GLLog("glLineWidth") << width; +} + +void API_ENTRY(glLineWidthx)(GLfixed width) { + CALL_GL_API(glLineWidthx, width); + GLLog("glLineWidth") << GLLogFixed(width); +} + +void API_ENTRY(glLoadIdentity)(void) { + CALL_GL_API(glLoadIdentity); + GLLog("glLoadIdentity"); +} + +void API_ENTRY(glLoadMatrixf)(const GLfloat *m) { + CALL_GL_API(glLoadMatrixf, m); + GLLog("glLoadMatrixf") << GLLogBuffer<GLfloat>(m, 16); +} + +void API_ENTRY(glLoadMatrixx)(const GLfixed *m) { + CALL_GL_API(glLoadMatrixx, m); + GLLog("glLoadMatrixx") << GLLogBuffer<GLfixed>(m, 16); +} + +void API_ENTRY(glLogicOp)(GLenum opcode) { + CALL_GL_API(glLogicOp, opcode); + GLLog("glLogicOp") << GLLogEnum(opcode); +} + +void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) { + CALL_GL_API(glMaterialf, face, pname, param); + GLLog("glMaterialf") << GLLogEnum(face) << GLLogEnum(pname) << param; +} + +void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) { + CALL_GL_API(glMaterialfv, face, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} + +void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) { + CALL_GL_API(glMaterialx, face, pname, param); + GLLog("glMaterialx") << GLLogEnum(face) << GLLogEnum(pname) << GLLogFixed(param); +} + +void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) { + CALL_GL_API(glMaterialxv, face, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} + +void API_ENTRY(glMatrixMode)(GLenum mode) { + CALL_GL_API(glMatrixMode, mode); + GLLog("glMatrixMode") << GLLogEnum(mode); +} + +void API_ENTRY(glMultMatrixf)(const GLfloat *m) { + CALL_GL_API(glMultMatrixf, m); + GLLog("glMultMatrixf") << GLLogBuffer<GLfloat>(m, 16); +} + +void API_ENTRY(glMultMatrixx)(const GLfixed *m) { + CALL_GL_API(glMultMatrixx, m); + GLLog("glMultMatrixx") << GLLogBuffer<GLfixed>(m, 16); +} + +void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { + CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q); + GLLog("glMultiTexCoord4f") << GLLogEnum(target) << s << t << r << q; +} + +void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { + CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q); + GLLog("glMultiTexCoord4x") << GLLogEnum(target) + << GLLogFixed(s) << GLLogFixed(t) << GLLogFixed(r) << GLLogFixed(q); +} + +void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) { + CALL_GL_API(glNormal3f, nx, ny, nz); + GLLog("glNormal3f") << nx << ny << nz; +} + +void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) { + CALL_GL_API(glNormal3x, nx, ny, nz); + GLLog("glNormal3x") << GLLogFixed(nx) << GLLogFixed(ny) << GLLogFixed(nz); +} + +void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glNormalPointer, type, stride, pointer); + GLLog("glNormalPointer") << GLLogEnum(type) << stride << pointer; +} + +void API_ENTRY(glOrthof)( GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar); + GLLog("glOrthof") << left << right << bottom << top << zNear << zFar; +} + +void API_ENTRY(glOrthox)( GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed zNear, GLfixed zFar) { + CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar); + GLLog("glOrthox") << GLLogFixed(left) << GLLogFixed(right) + << GLLogFixed(bottom) << GLLogFixed(top) + << GLLogFixed(zNear) << GLLogFixed(zFar); +} + +void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) { + CALL_GL_API(glPixelStorei, pname, param); + GLLog("glPixelStorei") << GLLogEnum(pname) << param; +} + +void API_ENTRY(glPointSize)(GLfloat size) { + CALL_GL_API(glPointSize, size); + GLLog("glPointSize") << size; +} + +void API_ENTRY(glPointSizex)(GLfixed size) { + CALL_GL_API(glPointSizex, size); + GLLog("glPointSizex") << GLLogFixed(size); +} + +void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { + CALL_GL_API(glPolygonOffset, factor, units); + GLLog("glPolygonOffset") << factor << units; +} + +void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) { + CALL_GL_API(glPolygonOffsetx, factor, units); + GLLog("glPolygonOffsetx") << GLLogFixed(factor) << GLLogFixed(units); +} + +void API_ENTRY(glPopMatrix)(void) { + CALL_GL_API(glPopMatrix); + GLLog("glPopMatrix"); +} + +void API_ENTRY(glPushMatrix)(void) { + CALL_GL_API(glPushMatrix); + GLLog("glPushMatrix"); +} + +void API_ENTRY(glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels) { + CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels); + // XXX: we need to compute the size of this buffer + GLLog("glReadPixels") << x << y << width << height << GLLogEnum(format) << GLLogEnum(type) + << GLLogBuffer<unsigned char>(static_cast<unsigned char *>(pixels)); +} + +void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glRotatef, angle, x, y, z); + GLLog("glRotatef") << angle << x << y << z; +} + +void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glRotatex, angle, x, y, z); + GLLog("glRotatex") << GLLogFixed(angle) << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z); +} + +void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) { + CALL_GL_API(glSampleCoverage, value, invert); + GLLog("glSampleCoverage") << value << GLLogBool(invert); +} + +void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) { + CALL_GL_API(glSampleCoveragex, value, invert); + GLLog("glSampleCoveragex") << GLLogFixed(value) << GLLogBool(invert); +} + +void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glScalef, x, y, z); + GLLog("glScalef") << x << y << z; +} + +void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glScalex, x, y, z); + GLLog("glScalex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z); +} + +void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glScissor, x, y, width, height); + GLLog("glScissor") << x << y << width << height; +} + +void API_ENTRY(glShadeModel)(GLenum mode) { + CALL_GL_API(glShadeModel, mode); + GLLog("glShadeModel") << GLLogEnum(mode); +} + +void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) { + CALL_GL_API(glStencilFunc, func, ref, mask); + GLLog("glStencilFunc") << GLLogEnum(func) << ref << mask; +} + +void API_ENTRY(glStencilMask)(GLuint mask) { + CALL_GL_API(glStencilMask, mask); + GLLog("glStencilMask") << mask; +} + +void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) { + CALL_GL_API(glStencilOp, fail, zfail, zpass); + GLLog("glStencilOp") << GLLogEnum(fail) << GLLogEnum(zfail) << GLLogEnum(zpass); +} + +void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glTexCoordPointer, size, type, stride, pointer); + GLLog("glTexCoordPointer") << size << GLLogEnum(type) << stride << pointer; +} + +void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexEnvf, target, pname, param); + GLLog("glTexEnvf") << GLLogEnum(target) << GLLogEnum(pname) << param; +} + +void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexEnvfv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} + +void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) { + CALL_GL_API(glTexEnvx, target, pname, param); + GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param); +} + +void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexEnvxv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glTexEnvxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} + +void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, GLenum format, + GLenum type, const GLvoid *pixels) { + CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, + border, format, type, pixels); + GLLog("glTexImage2D") << GLLogEnum(target) << level << GLLogEnum(internalformat) + << width << height << border << GLLogEnum(format) << GLLogEnum(type) + << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels)); +} + +void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexParameterf, target, pname, param); + GLLog("glTexParameterf") << GLLogEnum(target) << GLLogEnum(pname) << param; +} + +void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) { + CALL_GL_API(glTexParameterx, target, pname, param); + GLLog("glTexParameterx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param); +} + +void API_ENTRY(glTexSubImage2D)( GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels) { + CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, + width, height, format, type, pixels); + GLLog("glTexSubImage2D") << GLLogEnum(target) << level << xoffset << yoffset + << width << height << GLLogEnum(format) << GLLogEnum(type) + << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels)); +} + +void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glTranslatef, x, y, z); + GLLog("glTranslatef") << x << y << z; +} + +void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glTranslatex, x, y, z); + GLLog("glTranslatex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z); +} + +void API_ENTRY(glVertexPointer)( GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glVertexPointer, size, type, stride, pointer); + GLLog("glVertexPointer") << size << GLLogEnum(type) << stride << pointer; +} + +void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glViewport, x, y, width, height); + GLLog("glViewport") << x << y << width << height; +} + +// ES 1.1 +void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) { + CALL_GL_API(glClipPlanef, plane, equation); + GLLog("glClipPlanef") << GLLogEnum(plane) << GLLogBuffer<GLfloat>(equation, 4); +} +void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) { + CALL_GL_API(glClipPlanex, plane, equation); + GLLog("glClipPlanex") << GLLogEnum(plane) << GLLogBuffer<GLfixed>(equation, 4); +} +void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { + CALL_GL_API(glBindBuffer, target, buffer); + GLLog("glBindBuffer") << GLLogEnum(target) << buffer; +} +void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { + CALL_GL_API(glBufferData, target, size, data, usage); + GLLog("glBufferData") << GLLogEnum(target) << size + << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size); +} +void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { + CALL_GL_API(glBufferSubData, target, offset, size, data); + GLLog("glBufferSubData") << GLLogEnum(target) << offset << size + << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size); +} +void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) { + CALL_GL_API(glDeleteBuffers, n, buffers); + GLLog("glDeleteBuffers") << n << GLLogBuffer<GLuint>(buffers, n); +} +void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) { + CALL_GL_API(glGenBuffers, n, buffers); + GLLog("glGenBuffers") << n << GLLogBuffer<GLuint>(buffers, n); +} +void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) { + CALL_GL_API(glGetBooleanv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetBooleanv") << GLLogEnum(pname) << GLLogBuffer<GLboolean>(params); +} +void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) { + CALL_GL_API(glGetFixedv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetFixedv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) { + CALL_GL_API(glGetFloatv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetFloatv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} +void API_ENTRY(glGetPointerv)(GLenum pname, void **params) { + CALL_GL_API(glGetPointerv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetPointerv") << GLLogEnum(pname) << GLLogBuffer<void*>(params); +} +void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) { + // XXX: we need to compute the size of this buffer + CALL_GL_API(glGetBufferParameteriv, target, pname, params); + GLLog("glGetBufferParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); +} +void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) { + CALL_GL_API(glGetClipPlanef, pname, eqn); + GLLog("glGetClipPlanef") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(eqn, 4); +} +void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) { + CALL_GL_API(glGetClipPlanex, pname, eqn); + GLLog("glGetClipPlanex") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(eqn, 4); +} +void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetLightxv, light, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetLightfv, light, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} +void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetMaterialxv, face, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetMaterialfv, face, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} +void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexEnvfv, env, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetTexEnvfv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} +void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexEnviv, env, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetTexEnviv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); +} +void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexEnvxv, env, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetTexEnvxv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexParameterfv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} +void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexParameteriv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); +} +void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexParameterxv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glGetTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { + GLLog("glIsBuffer") << buffer; + CALL_GL_API_RETURN(glIsBuffer, buffer); +} +GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { + GLLog("glIsEnabled") << GLLogEnum(cap); + CALL_GL_API_RETURN(glIsEnabled, cap); +} +GLboolean API_ENTRY(glIsTexture)(GLuint texture) { + GLLog("glIsTexture") << texture; + CALL_GL_API_RETURN(glIsTexture, texture); +} +void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) { + CALL_GL_API(glPointParameterf, pname, param); + GLLog("glPointParameterf") << GLLogEnum(pname) << param; +} +void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glPointParameterfv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glPointParameterfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} +void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) { + CALL_GL_API(glPointParameterx, pname, param); + GLLog("glPointParameterx") << GLLogEnum(pname) << GLLogFixed(param); +} +void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glPointParameterxv, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glPointParameterxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { + CALL_GL_API(glColor4ub, red, green, blue, alpha); + GLLog("glColor4ub") << red << green << blue << alpha; +} +void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexEnvi, target, pname, param); + GLLog("glTexEnvi") << GLLogEnum(target) << GLLogEnum(pname) << param; +} +void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) { + CALL_GL_API(glTexEnviv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glTexEnviv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); +} + +void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexParameterfv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); +} + +void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) { + CALL_GL_API(glTexParameteriv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); +} + +void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexParameteri, target, pname, param); + GLLog("glTexParameteri") << GLLogEnum(target) << GLLogEnum(pname) << param; +} +void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexParameterxv, target, pname, params); + // XXX: we need to compute the size of this buffer + GLLog("glTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); +} +void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glPointSizePointerOES, type, stride, pointer); + GLLog("glPointSizePointerOES") << GLLogEnum(type) << stride << pointer; +} + +// Extensions +void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { + CALL_GL_API(glDrawTexsOES, x, y, z, w, h); + GLLog("glDrawTexsOES") << x << y << z << w << h; +} +void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) { + CALL_GL_API(glDrawTexiOES, x, y, z, w, h); + GLLog("glDrawTexiOES") << x << y << z << w << h; +} +void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) { + CALL_GL_API(glDrawTexfOES, x, y, z, w, h); + GLLog("glDrawTexfOES") << x << y << z << w << h; +} +void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { + CALL_GL_API(glDrawTexxOES, x, y, z, w, h); + GLLog("glDrawTexfOES") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z) << GLLogFixed(w) << GLLogFixed(h); +} +void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) { + CALL_GL_API(glDrawTexsvOES, coords); + GLLog("glDrawTexsvOES") << GLLogBuffer<GLshort>(coords, 5); +} +void API_ENTRY(glDrawTexivOES)(const GLint* coords) { + CALL_GL_API(glDrawTexivOES, coords); + GLLog("glDrawTexivOES") << GLLogBuffer<GLint>(coords, 5); +} +void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) { + CALL_GL_API(glDrawTexfvOES, coords); + GLLog("glDrawTexfvOES") << GLLogBuffer<GLfloat>(coords, 5); +} +void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) { + CALL_GL_API(glDrawTexxvOES, coords); + GLLog("glDrawTexxvOES") << GLLogBuffer<GLfixed>(coords, 5); +} +GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) { + GLLog("glQueryMatrixxOES") << GLLogBuffer<GLfixed>(mantissa, 16) << GLLogBuffer<GLfixed>(exponent, 16); + CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); +} diff --git a/opengl/libGLES_CM/gl_logger.h b/opengl/libGLES_CM/gl_logger.h new file mode 100644 index 0000000..59e31c7 --- /dev/null +++ b/opengl/libGLES_CM/gl_logger.h @@ -0,0 +1,26 @@ +/* + ** Copyright 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. + */ + +#ifndef ANDROID_GL_LOGGER_H +#define ANDROID_GL_LOGGER_H + +extern "C" { +#define GL_ENTRY(r, api, ...) r log_##api(__VA_ARGS__); +#include "gl_entries.cpp" +#undef GL_ENTRY +}; + +#endif /* ANDROID_GL_LOGGER_H */ diff --git a/opengl/libGLES_CM/gl_wrapper.cpp b/opengl/libGLES_CM/gl_wrapper.cpp new file mode 100644 index 0000000..5da4f9a --- /dev/null +++ b/opengl/libGLES_CM/gl_wrapper.cpp @@ -0,0 +1,1663 @@ +/* + ** Copyright 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. + */ + +#define LOG_TAG "GLLogger" + +#include <ctype.h> +#include <string.h> +#include <errno.h> +#include <dlfcn.h> + +#include <sys/ioctl.h> + +#if HAVE_ANDROID_OS +#include <linux/android_pmem.h> +#endif + +#include <GLES/egl.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <cutils/properties.h> +#include <cutils/memory.h> + +#include <utils/IMemory.h> +#include <utils/KeyedVector.h> +#include <utils/threads.h> +#include <utils/IServiceManager.h> +#include <utils/IPCThreadState.h> +#include <utils/Parcel.h> + +#include <ui/EGLDisplaySurface.h> +#include <ui/ISurfaceComposer.h> + +#include "gl_logger.h" + +#undef NELEM + +#define GL_LOGGER 0 +#define USE_SLOW_BINDING 0 +#define NELEM(x) (sizeof(x)/sizeof(*(x))) +#define MAX_NUMBER_OF_GL_EXTENSIONS 32 +#define MAKE_CONFIG(_impl, _index) ((EGLConfig)(((_impl)<<24) | (_index))) +#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r) + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +// EGLDisplay are global, not attached to a given thread +static const unsigned int NUM_DISPLAYS = 1; +static const unsigned int IMPL_HARDWARE = 0; +static const unsigned int IMPL_SOFTWARE = 1; +static const unsigned int IMPL_HARDWARE_CONTEXT_LOST = 2; +static const unsigned int IMPL_SOFTWARE_CONTEXT_LOST = 3; +static const unsigned int IMPL_NO_CONTEXT = 4; + +// ---------------------------------------------------------------------------- + +struct gl_hooks_t; + +struct egl_connection_t +{ + void volatile * dso; + gl_hooks_t * hooks; + EGLint major; + EGLint minor; + int unavailable; +}; + +template <int MAGIC> +struct egl_object_t +{ + egl_object_t() : magic(MAGIC) { } + ~egl_object_t() { magic = 0; } + bool isValid() const { return magic == MAGIC; } +private: + uint32_t magic; +}; + +struct egl_display_t : public egl_object_t<'_dpy'> +{ + EGLDisplay dpys[2]; + EGLConfig* configs[2]; + EGLint numConfigs[2]; + EGLint numTotalConfigs; + char const* extensionsString; + volatile int32_t refs; + struct strings_t { + char const * vendor; + char const * version; + char const * clientApi; + char const * extensions; + char const * extensions_config; + }; + strings_t queryString[2]; +}; + +struct egl_surface_t : public egl_object_t<'_srf'> +{ + egl_surface_t(EGLDisplay dpy, EGLSurface surface, + NativeWindowType window, int impl, egl_connection_t const* cnx) + : dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx) + { + // NOTE: window must be incRef'ed and connected already + } + ~egl_surface_t() { + if (window) { + if (window->disconnect) + window->disconnect(window); + window->decRef(window); + } + } + EGLDisplay dpy; + EGLSurface surface; + NativeWindowType window; + int impl; + egl_connection_t const* cnx; +}; + +struct egl_context_t : public egl_object_t<'_ctx'> +{ + egl_context_t(EGLDisplay dpy, EGLContext context, + int impl, egl_connection_t const* cnx) + : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx) + { + } + EGLDisplay dpy; + EGLContext context; + EGLSurface read; + EGLSurface draw; + int impl; + egl_connection_t const* cnx; +}; + +struct tls_t +{ + tls_t() : error(EGL_SUCCESS), ctx(0) { } + EGLint error; + EGLContext ctx; +}; + + +// GL / EGL hooks + +typedef void(*proc_t)(); + +struct gl_hooks_t { + struct gl_t { + #define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); + #include "gl_entries.cpp" + #undef GL_ENTRY + } gl; + struct egl_t { + #define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); + #include "egl_entries.cpp" + #undef EGL_ENTRY + } egl; + struct gl_ext_t { + void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void); + } ext; +}; + +static char const * const gl_names[] = { + #define GL_ENTRY(_r, _api, ...) #_api, + #include "gl_entries.cpp" + #undef GL_ENTRY + NULL +}; + +static char const * const egl_names[] = { + #define EGL_ENTRY(_r, _api, ...) #_api, + #include "egl_entries.cpp" + #undef EGL_ENTRY + NULL +}; + +static void gl_unimplemented() { + LOGE("called unimplemented OpenGL ES API"); +} + +// ---------------------------------------------------------------------------- + +static egl_connection_t gEGLImpl[2]; +static egl_display_t gDisplay[NUM_DISPLAYS]; +static gl_hooks_t gHooks[5]; +static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t gEGLThreadLocalStorageKey = -1; + +// ---------------------------------------------------------------------------- + +#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER + +#include <sys/tls.h> +// We have a dedicated TLS slot in bionic +static inline void setGlThreadSpecific(gl_hooks_t const *value) { + ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL_API] = (uint32_t)value; +} +static gl_hooks_t const* getGlThreadSpecific() { + gl_hooks_t const* hooks = (gl_hooks_t const *)(((unsigned const *)__get_tls())[TLS_SLOT_OPENGL_API]); + if (hooks) return hooks; + return &gHooks[IMPL_NO_CONTEXT]; +} + +#else + +static pthread_key_t gGLWrapperKey = -1; +static inline void setGlThreadSpecific(gl_hooks_t const *value) { + pthread_setspecific(gGLWrapperKey, value); +} +static gl_hooks_t const* getGlThreadSpecific() { + gl_hooks_t const* hooks = static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey)); + if (hooks) return hooks; + return &gHooks[IMPL_NO_CONTEXT]; +} + +#endif + +static __attribute__((noinline)) +const char *egl_strerror(EGLint err) +{ + switch (err){ + 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 EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; + default: return "UNKNOWN"; + } +} + +static __attribute__((noinline)) +void clearTLS() { + if (gEGLThreadLocalStorageKey != -1) { + tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); + if (tls) { + delete tls; + pthread_setspecific(gEGLThreadLocalStorageKey, 0); + } + } +} + +static tls_t* getTLS() +{ + tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); + if (tls == 0) { + tls = new tls_t; + pthread_setspecific(gEGLThreadLocalStorageKey, tls); + } + return tls; +} + +template<typename T> +static __attribute__((noinline)) +T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) { + if (gEGLThreadLocalStorageKey == -1) { + pthread_mutex_lock(&gThreadLocalStorageKeyMutex); + if (gEGLThreadLocalStorageKey == -1) + pthread_key_create(&gEGLThreadLocalStorageKey, NULL); + pthread_mutex_unlock(&gThreadLocalStorageKeyMutex); + } + tls_t* tls = getTLS(); + if (tls->error != error) { + LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error)); + tls->error = error; + } + return returnValue; +} + +static __attribute__((noinline)) +GLint getError() { + if (gEGLThreadLocalStorageKey == -1) + return EGL_SUCCESS; + tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); + if (!tls) return EGL_SUCCESS; + GLint error = tls->error; + tls->error = EGL_SUCCESS; + return error; +} + +static __attribute__((noinline)) +void setContext(EGLContext ctx) { + if (gEGLThreadLocalStorageKey == -1) { + pthread_mutex_lock(&gThreadLocalStorageKeyMutex); + if (gEGLThreadLocalStorageKey == -1) + pthread_key_create(&gEGLThreadLocalStorageKey, NULL); + pthread_mutex_unlock(&gThreadLocalStorageKeyMutex); + } + tls_t* tls = getTLS(); + tls->ctx = ctx; +} + +static __attribute__((noinline)) +EGLContext getContext() { + if (gEGLThreadLocalStorageKey == -1) + return EGL_NO_CONTEXT; + tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); + if (!tls) return EGL_NO_CONTEXT; + return tls->ctx; +} + +/*****************************************************************************/ + +/* + * we provide our own allocators for the GPU regions, these + * allocators go through surfaceflinger + */ + +static Mutex gRegionsLock; +static request_gpu_t gRegions; +static sp<ISurfaceComposer> gSurfaceManager; +ISurfaceComposer* GLES_localSurfaceManager = 0; + +const sp<ISurfaceComposer>& getSurfaceFlinger() +{ + Mutex::Autolock _l(gRegionsLock); + + /* + * There is a little bit of voodoo magic here. We want to access + * surfaceflinger for allocating GPU regions, however, when we are + * running as part of surfaceflinger, we want to bypass the + * service manager because surfaceflinger might not be registered yet. + * SurfaceFlinger will populate "GLES_localSurfaceManager" with its + * own address, so we can just use that. + */ + if (gSurfaceManager == 0) { + if (GLES_localSurfaceManager) { + // we're running in SurfaceFlinger's context + gSurfaceManager = GLES_localSurfaceManager; + } else { + // we're a remote process or not part of surfaceflinger, + // go through the service manager + sp<IServiceManager> sm = defaultServiceManager(); + if (sm != NULL) { + sp<IBinder> binder = sm->getService(String16("SurfaceFlinger")); + gSurfaceManager = interface_cast<ISurfaceComposer>(binder); + } + } + } + return gSurfaceManager; +} + +class GPURevokeRequester : public BnGPUCallback +{ +public: + virtual void gpuLost() { + LOGD("CONTEXT_LOST: Releasing GPU upon request from SurfaceFlinger."); + gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_HARDWARE_CONTEXT_LOST]; + } +}; + +static sp<GPURevokeRequester> gRevokerCallback; + +static request_gpu_t* gpu_acquire(void* user) +{ + sp<ISurfaceComposer> server( getSurfaceFlinger() ); + + Mutex::Autolock _l(gRegionsLock); + if (server == NULL) { + return 0; + } + + ISurfaceComposer::gpu_info_t info; + gRevokerCallback = new GPURevokeRequester(); + status_t err = server->requestGPU(gRevokerCallback, &info); + if (err != NO_ERROR) { + LOGD("requestGPU returned %d", err); + return 0; + } + + bool failed = false; + request_gpu_t* gpu = &gRegions; + memset(gpu, 0, sizeof(*gpu)); + + if (info.regs != 0) { + sp<IMemoryHeap> heap(info.regs->getMemory()); + if (heap != 0) { + int fd = heap->heapID(); + gpu->regs.fd = fd; + gpu->regs.base = info.regs->pointer(); + gpu->regs.size = info.regs->size(); + gpu->regs.user = info.regs.get(); +#if HAVE_ANDROID_OS + struct pmem_region region; + if (ioctl(fd, PMEM_GET_PHYS, ®ion) >= 0) + gpu->regs.phys = (void*)region.offset; +#endif + info.regs->incStrong(gpu); + } else { + LOGE("GPU register handle %p is invalid!", info.regs.get()); + failed = true; + } + } + + for (size_t i=0 ; i<info.count && !failed ; i++) { + sp<IMemory>& region(info.regions[i].region); + if (region != 0) { + sp<IMemoryHeap> heap(region->getMemory()); + if (heap != 0) { + const int fd = heap->heapID(); + gpu->gpu[i].fd = fd; + gpu->gpu[i].base = region->pointer(); + gpu->gpu[i].size = region->size(); + gpu->gpu[i].user = region.get(); + gpu->gpu[i].offset = info.regions[i].reserved; +#if HAVE_ANDROID_OS + struct pmem_region reg; + if (ioctl(fd, PMEM_GET_PHYS, ®) >= 0) + gpu->gpu[i].phys = (void*)reg.offset; +#endif + region->incStrong(gpu); + } else { + LOGE("GPU region handle [%d, %p] is invalid!", i, region.get()); + failed = true; + } + } + } + + if (failed) { + // something went wrong, clean up everything! + if (gpu->regs.user) { + static_cast<IMemory*>(gpu->regs.user)->decStrong(gpu); + for (size_t i=0 ; i<info.count ; i++) { + if (gpu->gpu[i].user) { + static_cast<IMemory*>(gpu->gpu[i].user)->decStrong(gpu); + } + } + } + } + + gpu->count = info.count; + return gpu; +} + +static int gpu_release(void*, request_gpu_t* gpu) +{ + sp<IMemory> regs; + + { // scope for lock + Mutex::Autolock _l(gRegionsLock); + regs = static_cast<IMemory*>(gpu->regs.user); + gpu->regs.user = 0; + if (regs != 0) regs->decStrong(gpu); + + for (int i=0 ; i<gpu->count ; i++) { + sp<IMemory> r(static_cast<IMemory*>(gpu->gpu[i].user)); + gpu->gpu[i].user = 0; + if (r != 0) r->decStrong(gpu); + } + } + + // there is a special transaction to relinquish the GPU + // (it will happen automatically anyway if we don't do this) + Parcel data, reply; + // NOTE: this transaction does not require an interface token + regs->asBinder()->transact(1000, data, &reply); + return 1; +} + +/*****************************************************************************/ + +static __attribute__((noinline)) +void *load_driver(const char* driver, gl_hooks_t* hooks) +{ + void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); + LOGE_IF(!dso, + "couldn't load <%s> library (%s)", + driver, dlerror()); + + if (dso) { + void** curr; + char const * const * api; + gl_hooks_t::gl_t* gl = &hooks->gl; + curr = (void**)gl; + api = gl_names; + while (*api) { + void* f = dlsym(dso, *api); + //LOGD("<%s> @ 0x%p", *api, f); + if (f == NULL) { + //LOGW("<%s> not found in %s", *api, driver); + f = (void*)gl_unimplemented; + } + *curr++ = f; + api++; + } + gl_hooks_t::egl_t* egl = &hooks->egl; + curr = (void**)egl; + api = egl_names; + while (*api) { + void* f = dlsym(dso, *api); + if (f == NULL) { + //LOGW("<%s> not found in %s", *api, driver); + f = (void*)0; + } + *curr++ = f; + api++; + } + + // hook this driver up with surfaceflinger if needed + register_gpu_t register_gpu = + (register_gpu_t)dlsym(dso, "oem_register_gpu"); + + if (register_gpu != NULL) { + if (getSurfaceFlinger() != 0) { + register_gpu(dso, gpu_acquire, gpu_release); + } + } + } + return dso; +} + +template<typename T> +static __attribute__((noinline)) +int binarySearch( + T const sortedArray[], int first, int last, T key) +{ + while (first <= last) { + int mid = (first + last) / 2; + if (key > sortedArray[mid]) { + first = mid + 1; + } else if (key < sortedArray[mid]) { + last = mid - 1; + } else { + return mid; + } + } + return -1; +} + +static int cmp_configs(const void* a, const void *b) +{ + EGLConfig c0 = *(EGLConfig const *)a; + EGLConfig c1 = *(EGLConfig const *)b; + return c0<c1 ? -1 : (c0>c1 ? 1 : 0); +} + +static char const * const gVendorString = "Android"; +static char const * const gVersionString = "1.2 Android META-EGL"; +static char const * const gClientApiString = "OpenGL ES"; + +struct extention_map_t { + const char* name; + void (*address)(void); +}; + +static const extention_map_t gExtentionMap[] = { + { "eglSwapRectangleANDROID", (void(*)())&eglSwapRectangleANDROID }, + { "eglQueryStringConfigANDROID", (void(*)())&eglQueryStringConfigANDROID }, +}; + +static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS]; + +static void(*findProcAddress(const char* name, + const extention_map_t* map, size_t n))() +{ + for (uint32_t i=0 ; i<n ; i++) { + if (!strcmp(name, map[i].name)) { + return map[i].address; + } + } + return NULL; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + + +// ---------------------------------------------------------------------------- +// extensions for the framework +// ---------------------------------------------------------------------------- + +void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr, GLsizei count) { + glColorPointer(size, type, stride, ptr); +} +void glNormalPointerBounds(GLenum type, GLsizei stride, + const GLvoid *pointer, GLsizei count) { + glNormalPointer(type, stride, pointer); +} +void glTexCoordPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count) { + glTexCoordPointer(size, type, stride, pointer); +} +void glVertexPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count) { + glVertexPointer(size, type, stride, pointer); +} + + +// ---------------------------------------------------------------------------- +// Actual GL wrappers +// ---------------------------------------------------------------------------- + +#if __OPTIMIZE__ && defined(__arm__) && !defined(__thumb__) && !USE_SLOW_BINDING && !GL_LOGGER + + #define API_ENTRY(_api) __attribute__((naked)) _api + #define CALL_GL_API(_api, ...) \ + asm volatile( \ + "mov r12, #0xFFFF0FFF \n" \ + "ldr r12, [r12, #-15] \n" \ + "ldr r12, [r12, %[tls]] \n" \ + "cmp r12, #0 \n" \ + "ldrne pc, [r12, %[api]] \n" \ + "bx lr \n" \ + : \ + : [tls] "J"(TLS_SLOT_OPENGL_API*4), \ + [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \ + : \ + ); + + #define CALL_GL_API_RETURN(_api, ...) \ + CALL_GL_API(_api, __VA_ARGS__) \ + return 0; // placate gcc's warnings. never reached. + +#else + + #define API_ENTRY(_api) _api + #if GL_LOGGER + + #define CALL_GL_API(_api, ...) \ + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ + log_##_api(__VA_ARGS__); \ + _c->_api(__VA_ARGS__); + + #define CALL_GL_API_RETURN(_api, ...) \ + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ + log_##_api(__VA_ARGS__); \ + return _c->_api(__VA_ARGS__) + + #else + + #define CALL_GL_API(_api, ...) \ + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ + _c->_api(__VA_ARGS__); + + #define CALL_GL_API_RETURN(_api, ...) \ + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ + return _c->_api(__VA_ARGS__) + + #endif + +#endif + +#include "gl_api.cpp" + +#undef API_ENTRY +#undef CALL_GL_API +#undef CALL_GL_API_RETURN + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +static int gl_context_lost() { + setGlThreadSpecific(&gHooks[IMPL_HARDWARE_CONTEXT_LOST]); + return 0; +} +static int egl_context_lost() { + setGlThreadSpecific(&gHooks[IMPL_HARDWARE_CONTEXT_LOST]); + return EGL_FALSE; +} +static EGLBoolean egl_context_lost_swap_buffers(void*, void*) { + usleep(100000); // don't use all the CPU + setGlThreadSpecific(&gHooks[IMPL_HARDWARE_CONTEXT_LOST]); + return EGL_FALSE; +} +static GLint egl_context_lost_get_error() { + return EGL_CONTEXT_LOST; +} +static int ext_context_lost() { + return 0; +} + +static void gl_no_context() { + LOGE("call to OpenGL ES API with no current context"); +} +static void early_egl_init(void) +{ +#if !defined(HAVE_ANDROID_OS) || USE_SLOW_BINDING || GL_LOGGER + pthread_key_create(&gGLWrapperKey, NULL); +#endif + uint32_t addr = (uint32_t)((void*)gl_no_context); + android_memset32((uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], addr, sizeof(gHooks[IMPL_NO_CONTEXT])); + setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); +} + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; +static int sEarlyInitState = pthread_once(&once_control, &early_egl_init); + + +static inline +egl_display_t* get_display(EGLDisplay dpy) +{ + uintptr_t index = uintptr_t(dpy)-1U; + return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index]; +} + +static inline +egl_surface_t* get_surface(EGLSurface surface) +{ + egl_surface_t* s = (egl_surface_t *)surface; + return s; +} + +static inline +egl_context_t* get_context(EGLContext context) +{ + egl_context_t* c = (egl_context_t *)context; + return c; +} + +static egl_connection_t* validate_display_config( + EGLDisplay dpy, EGLConfig config, + egl_display_t const*& dp, int& impl, int& index) +{ + dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL); + + impl = uintptr_t(config)>>24; + if (uint32_t(impl) >= 2) { + return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); + } + index = uintptr_t(config) & 0xFFFFFF; + if (index >= dp->numConfigs[impl]) { + return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); + } + egl_connection_t* const cnx = &gEGLImpl[impl]; + if (cnx->dso == 0) { + return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); + } + return cnx; +} + +static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx) +{ + if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (!get_display(dpy)->isValid()) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (!ctx) // TODO: make sure context is a valid object + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (!get_context(ctx)->isValid()) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + return EGL_TRUE; +} + +static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) +{ + if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (!get_display(dpy)->isValid()) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (!surface) // TODO: make sure surface is a valid object + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!get_surface(surface)->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + return EGL_TRUE; +} + +static void add_extension(egl_display_t* dp, char const*& p, const char* ext) +{ + if (!strstr(p, ext)) { + p = (char const*)realloc((void*)p, strlen(p) + 1 + strlen(ext) + 1); + strcat((char*)p, " "); + strcat((char*)p, ext); + } + if (!strstr(dp->extensionsString, ext)) { + char const*& es = dp->extensionsString; + es = (char const*)realloc((void*)es, strlen(es) + 1 + strlen(ext) + 1); + strcat((char*)es, " "); + strcat((char*)es, ext); + } +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +EGLDisplay eglGetDisplay(NativeDisplayType display) +{ + if (sEarlyInitState) { + return EGL_NO_DISPLAY; + } + + uint32_t index = uint32_t(display); + if (index >= NUM_DISPLAYS) { + return EGL_NO_DISPLAY; + } + + EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); + egl_display_t* d = &gDisplay[index]; + + // dynamically load all our EGL implementations for that display + // and call into the real eglGetGisplay() + egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE]; + if (cnx->dso == 0) { + cnx->hooks = &gHooks[IMPL_SOFTWARE]; + cnx->dso = load_driver("libagl.so", cnx->hooks); + } + if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) { + d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display); + LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY, + "No EGLDisplay for software EGL!"); + } + + cnx = &gEGLImpl[IMPL_HARDWARE]; + if (cnx->dso == 0 && cnx->unavailable == 0) { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.egl.hw", value, "1"); + if (atoi(value) != 0) { + cnx->hooks = &gHooks[IMPL_HARDWARE]; + cnx->dso = load_driver("libhgl.so", cnx->hooks); + } else { + LOGD("3D hardware acceleration is disabled"); + } + } + if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) { + android_memset32( + (uint32_t*)(void*)&gHooks[IMPL_HARDWARE_CONTEXT_LOST].gl, + (uint32_t)((void*)gl_context_lost), + sizeof(gHooks[IMPL_HARDWARE_CONTEXT_LOST].gl)); + android_memset32( + (uint32_t*)(void*)&gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl, + (uint32_t)((void*)egl_context_lost), + sizeof(gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl)); + android_memset32( + (uint32_t*)(void*)&gHooks[IMPL_HARDWARE_CONTEXT_LOST].ext, + (uint32_t)((void*)ext_context_lost), + sizeof(gHooks[IMPL_HARDWARE_CONTEXT_LOST].ext)); + + gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl.eglSwapBuffers = + egl_context_lost_swap_buffers; + + gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl.eglGetError = + egl_context_lost_get_error; + + gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl.eglTerminate = + gHooks[IMPL_HARDWARE].egl.eglTerminate; + + d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display); + if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) { + dlclose((void*)cnx->dso); + cnx->dso = 0; + // in case of failure, we want to make sure we don't try again + // as it's expensive. + cnx->unavailable = 1; + } + } + + return dpy; +} + +// ---------------------------------------------------------------------------- +// Initialization +// ---------------------------------------------------------------------------- + +EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + egl_display_t * const dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + if (android_atomic_inc(&dp->refs) > 0) { + if (major != NULL) *major = 1; + if (minor != NULL) *minor = 2; + return EGL_TRUE; + } + + setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); + + // initialize each EGL and + // build our own extension string first, based on the extension we know + // and the extension supported by our client implementation + dp->extensionsString = strdup("EGL_ANDROID_query_string_config"); + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + cnx->major = -1; + cnx->minor = -1; + if (cnx->dso && cnx->hooks->egl.eglInitialize( + dp->dpys[i], &cnx->major, &cnx->minor)) { + + //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p", + // i, dp->dpys[i], cnx->major, cnx->minor, cnx); + + // get the query-strings for this display for each implementation + dp->queryString[i].vendor = + cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR); + dp->queryString[i].version = + cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION); + dp->queryString[i].extensions = strdup( + cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS)); + dp->queryString[i].clientApi = + cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS); + + // Dynamically insert extensions we know about + if (cnx->hooks->egl.eglSwapRectangleANDROID) + add_extension(dp, dp->queryString[i].extensions, + "EGL_ANDROID_swap_rectangle"); + + if (cnx->hooks->egl.eglQueryStringConfigANDROID) + add_extension(dp, dp->queryString[i].extensions, + "EGL_ANDROID_query_string_config"); + } + } + + // Build the extension list that depends on the current config. + // It is the intersection of our extension list and the + // underlaying EGL's extensions list + EGLBoolean res = EGL_FALSE; + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { + char const* const their_extensions = dp->queryString[i].extensions; + char* our_extensions = strdup(dp->extensionsString); + char* const our_extensions_org = our_extensions; + char* extensions_config = (char*)calloc(strlen(our_extensions)+2, 1); + char* p; + do { + p = strchr(our_extensions, ' '); + if (p) *p++ = 0; + else p = strchr(our_extensions, 0); + if (strstr(their_extensions, our_extensions)) { + strcat(extensions_config, our_extensions); + strcat(extensions_config, " "); + } + our_extensions = p; + } while (*p); + free((void*)our_extensions_org); + + // remove the trailling white space + if (extensions_config[0] != 0) { + size_t l = strlen(extensions_config) - 1; // new size + extensions_config[l] = 0; // remove the trailling white space + extensions_config = (char*)realloc(extensions_config, l+1); + } else { + extensions_config = (char*)realloc(extensions_config, 1); + } + dp->queryString[i].extensions_config = extensions_config; + + EGLint n; + if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) { + dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n); + if (dp->configs[i]) { + if (cnx->hooks->egl.eglGetConfigs( + dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i])) + { + // sort the configurations so we can do binary searches + qsort( dp->configs[i], + dp->numConfigs[i], + sizeof(EGLConfig), cmp_configs); + + dp->numTotalConfigs += n; + res = EGL_TRUE; + } + } + } + } + } + + if (res == EGL_TRUE) { + if (major != NULL) *major = 1; + if (minor != NULL) *minor = 2; + return EGL_TRUE; + } + return setError(EGL_NOT_INITIALIZED, EGL_FALSE); +} + +EGLBoolean eglTerminate(EGLDisplay dpy) +{ + egl_display_t* const dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (android_atomic_dec(&dp->refs) != 1) + return EGL_TRUE; + + EGLBoolean res = EGL_FALSE; + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + cnx->hooks->egl.eglTerminate(dp->dpys[i]); + + /* REVISIT: it's unclear what to do if eglTerminate() fails, + * on one end we shouldn't care, on the other end if it fails + * it might not be safe to call dlclose() (there could be some + * threads around). */ + + free(dp->configs[i]); + free((void*)dp->queryString[i].extensions_config); + free((void*)dp->queryString[i].extensions); + dp->numConfigs[i] = 0; + dp->dpys[i] = EGL_NO_DISPLAY; + dlclose((void*)cnx->dso); + cnx->dso = 0; + res = EGL_TRUE; + } + } + free((void*)dp->extensionsString); + dp->extensionsString = 0; + dp->numTotalConfigs = 0; + clearTLS(); + return res; +} + +// ---------------------------------------------------------------------------- +// configuration +// ---------------------------------------------------------------------------- + +EGLBoolean eglGetConfigs( EGLDisplay dpy, + EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + egl_display_t const * const dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + GLint numConfigs = dp->numTotalConfigs; + if (!configs) { + *num_config = numConfigs; + return EGL_TRUE; + } + GLint n = 0; + for (int j=0 ; j<2 ; j++) { + for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) { + *configs++ = MAKE_CONFIG(j, i); + config_size--; + n++; + } + } + + *num_config = n; + return EGL_TRUE; +} + +EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, + EGLint *num_config) +{ + egl_display_t const * const dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + if (configs == 0) { + *num_config = 0; + return EGL_TRUE; + } + + EGLBoolean res = EGL_FALSE; + *num_config = 0; + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + EGLint n; + if (cnx->hooks->egl.eglChooseConfig( + dp->dpys[i], attrib_list, configs, config_size, &n)) + { + // now we need to convert these client EGLConfig to our + // internal EGLConfig format. This is done in O(n log n). + for (int j=0 ; j<n ; j++) { + int index = binarySearch<EGLConfig>( + dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]); + if (index >= 0) { + configs[j] = MAKE_CONFIG(i, index); + } else { + return setError(EGL_BAD_CONFIG, EGL_FALSE); + } + } + configs += n; + config_size -= n; + *num_config += n; + res = EGL_TRUE; + } + } + } + return res; +} + +EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (!cnx) return EGL_FALSE; + return cnx->hooks->egl.eglGetConfigAttrib( + dp->dpys[i], dp->configs[i][index], attribute, value); +} + +// ---------------------------------------------------------------------------- +// surfaces +// ---------------------------------------------------------------------------- + +EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, + NativeWindowType window, + const EGLint *attrib_list) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (cnx) { + // window must be connected upon calling underlying + // eglCreateWindowSurface + if (window) { + window->incRef(window); + if (window->connect) + window->connect(window); + } + + EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface( + dp->dpys[i], dp->configs[i][index], window, attrib_list); + if (surface != EGL_NO_SURFACE) { + egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx); + return s; + } + + // something went wrong, disconnect and free window + // (will disconnect() automatically) + if (window) { + window->decRef(window); + } + } + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, + NativePixmapType pixmap, + const EGLint *attrib_list) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (cnx) { + EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface( + dp->dpys[i], dp->configs[i][index], pixmap, attrib_list); + if (surface != EGL_NO_SURFACE) { + egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); + return s; + } + } + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (cnx) { + EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface( + dp->dpys[i], dp->configs[i][index], attrib_list); + if (surface != EGL_NO_SURFACE) { + egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); + return s; + } + } + return EGL_NO_SURFACE; +} + +EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + if (!validate_display_surface(dpy, surface)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + + EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface( + dp->dpys[s->impl], s->surface); + + delete s; + return result; +} + +EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint *value) +{ + if (!validate_display_surface(dpy, surface)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + + return s->cnx->hooks->egl.eglQuerySurface( + dp->dpys[s->impl], s->surface, attribute, value); +} + +// ---------------------------------------------------------------------------- +// contextes +// ---------------------------------------------------------------------------- + +EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, + EGLContext share_list, const EGLint *attrib_list) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (cnx) { + EGLContext context = cnx->hooks->egl.eglCreateContext( + dp->dpys[i], dp->configs[i][index], share_list, attrib_list); + if (context != EGL_NO_CONTEXT) { + egl_context_t* c = new egl_context_t(dpy, context, i, cnx); + return c; + } + } + return EGL_NO_CONTEXT; +} + +EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + if (!validate_display_context(dpy, ctx)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_context_t * const c = get_context(ctx); + EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext( + dp->dpys[c->impl], c->context); + delete c; + return result; +} + +EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, + EGLSurface read, EGLContext ctx) +{ + egl_display_t const * const dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + if (read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE && + ctx == EGL_NO_CONTEXT) + { + EGLBoolean result = EGL_TRUE; + ctx = getContext(); + if (ctx) { + egl_context_t * const c = get_context(ctx); + result = c->cnx->hooks->egl.eglMakeCurrent(dp->dpys[c->impl], 0, 0, 0); + if (result == EGL_TRUE) { + setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); + setContext(EGL_NO_CONTEXT); + } + } + return result; + } + + if (!validate_display_context(dpy, ctx)) + return EGL_FALSE; + + egl_context_t * const c = get_context(ctx); + if (draw != EGL_NO_SURFACE) { + egl_surface_t const * d = get_surface(draw); + if (!d) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (d->impl != c->impl) + return setError(EGL_BAD_MATCH, EGL_FALSE); + draw = d->surface; + } + if (read != EGL_NO_SURFACE) { + egl_surface_t const * r = get_surface(read); + if (!r) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (r->impl != c->impl) + return setError(EGL_BAD_MATCH, EGL_FALSE); + read = r->surface; + } + EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent( + dp->dpys[c->impl], draw, read, c->context); + + if (result == EGL_TRUE) { + setGlThreadSpecific(c->cnx->hooks); + setContext(ctx); + c->read = read; + c->draw = draw; + } + return result; +} + + +EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint *value) +{ + if (!validate_display_context(dpy, ctx)) + return EGL_FALSE; + + egl_display_t const * const dp = get_display(dpy); + egl_context_t * const c = get_context(ctx); + + return c->cnx->hooks->egl.eglQueryContext( + dp->dpys[c->impl], c->context, attribute, value); +} + +EGLContext eglGetCurrentContext(void) +{ + EGLContext ctx = getContext(); + return ctx; +} + +EGLSurface eglGetCurrentSurface(EGLint readdraw) +{ + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); + switch (readdraw) { + case EGL_READ: return c->read; + case EGL_DRAW: return c->draw; + default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + } + return EGL_NO_SURFACE; +} + +EGLDisplay eglGetCurrentDisplay(void) +{ + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); + return c->dpy; + } + return EGL_NO_DISPLAY; +} + +EGLBoolean eglWaitGL(void) +{ + EGLBoolean res = EGL_TRUE; + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (uint32_t(c->impl)>=2) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl[c->impl]; + if (!cnx->dso) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + res = cnx->hooks->egl.eglWaitGL(); + } + return res; +} + +EGLBoolean eglWaitNative(EGLint engine) +{ + EGLBoolean res = EGL_TRUE; + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (uint32_t(c->impl)>=2) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl[c->impl]; + if (!cnx->dso) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + res = cnx->hooks->egl.eglWaitNative(engine); + } + return res; +} + +EGLint eglGetError(void) +{ + EGLint result = EGL_SUCCESS; + for (int i=0 ; i<2 ; i++) { + EGLint err = EGL_SUCCESS; + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) + err = cnx->hooks->egl.eglGetError(); + if (err!=EGL_SUCCESS && result==EGL_SUCCESS) + result = err; + } + if (result == EGL_SUCCESS) + result = getError(); + return result; +} + +void (*eglGetProcAddress(const char *procname))() +{ + void (*addr)(); + addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); + if (addr) return addr; + + return NULL; // TODO: finish implementation below + + addr = findProcAddress(procname, gGLExtentionMap, NELEM(gGLExtentionMap)); + if (addr) return addr; + + addr = 0; + int slot = -1; + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + if (cnx->hooks->egl.eglGetProcAddress) { + addr = cnx->hooks->egl.eglGetProcAddress(procname); + if (addr) { + if (slot == -1) { + slot = 0; // XXX: find free slot + if (slot == -1) { + addr = 0; + break; + } + } + cnx->hooks->ext.extensions[slot] = addr; + } + } + } + } + + if (slot >= 0) { + addr = 0; // XXX: address of stub 'slot' + gGLExtentionMap[slot].name = strdup(procname); + gGLExtentionMap[slot].address = addr; + } + + return addr; + + + /* + * TODO: For OpenGL ES extensions, we must generate a stub + * that looks like + * mov r12, #0xFFFF0FFF + * ldr r12, [r12, #-15] + * ldr r12, [r12, #TLS_SLOT_OPENGL_API*4] + * mov r12, [r12, #api_offset] + * ldrne pc, r12 + * mov pc, #unsupported_extension + * + * and write the address of the extension in *all* + * gl_hooks_t::gl_ext_t at offset "api_offset" from gl_hooks_t + * + */ +} + +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) +{ + if (!validate_display_surface(dpy, draw)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(draw); + return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface); +} + +EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, + NativePixmapType target) +{ + if (!validate_display_surface(dpy, surface)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + return s->cnx->hooks->egl.eglCopyBuffers( + dp->dpys[s->impl], s->surface, target); +} + +const char* eglQueryString(EGLDisplay dpy, EGLint name) +{ + egl_display_t const * const dp = get_display(dpy); + switch (name) { + case EGL_VENDOR: + return gVendorString; + case EGL_VERSION: + return gVersionString; + case EGL_EXTENSIONS: + return dp->extensionsString; + case EGL_CLIENT_APIS: + return gClientApiString; + } + return setError(EGL_BAD_PARAMETER, (const char *)0); +} + + +// ---------------------------------------------------------------------------- +// EGL 1.1 +// ---------------------------------------------------------------------------- + +EGLBoolean eglSurfaceAttrib( + EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + if (!validate_display_surface(dpy, surface)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->hooks->egl.eglSurfaceAttrib) { + return s->cnx->hooks->egl.eglSurfaceAttrib( + dp->dpys[s->impl], s->surface, attribute, value); + } + return setError(EGL_BAD_SURFACE, EGL_FALSE); +} + +EGLBoolean eglBindTexImage( + EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + if (!validate_display_surface(dpy, surface)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->hooks->egl.eglBindTexImage) { + return s->cnx->hooks->egl.eglBindTexImage( + dp->dpys[s->impl], s->surface, buffer); + } + return setError(EGL_BAD_SURFACE, EGL_FALSE); +} + +EGLBoolean eglReleaseTexImage( + EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + if (!validate_display_surface(dpy, surface)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->hooks->egl.eglReleaseTexImage) { + return s->cnx->hooks->egl.eglReleaseTexImage( + dp->dpys[s->impl], s->surface, buffer); + } + return setError(EGL_BAD_SURFACE, EGL_FALSE); +} + +EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) +{ + egl_display_t * const dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + EGLBoolean res = EGL_TRUE; + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + if (cnx->hooks->egl.eglSwapInterval) { + if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) { + res = EGL_FALSE; + } + } + } + } + return res; +} + + +// ---------------------------------------------------------------------------- +// EGL 1.2 +// ---------------------------------------------------------------------------- + +EGLBoolean eglWaitClient(void) +{ + EGLBoolean res = EGL_TRUE; + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (uint32_t(c->impl)>=2) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl[c->impl]; + if (!cnx->dso) + return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (cnx->hooks->egl.eglWaitClient) { + res = cnx->hooks->egl.eglWaitClient(); + } else { + res = cnx->hooks->egl.eglWaitGL(); + } + } + return res; +} + +EGLBoolean eglBindAPI(EGLenum api) +{ + // bind this API on all EGLs + EGLBoolean res = EGL_TRUE; + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + if (cnx->hooks->egl.eglBindAPI) { + if (cnx->hooks->egl.eglBindAPI(api) == EGL_FALSE) { + res = EGL_FALSE; + } + } + } + } + return res; +} + +EGLenum eglQueryAPI(void) +{ + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + if (cnx->hooks->egl.eglQueryAPI) { + // the first one we find is okay, because they all + // should be the same + return cnx->hooks->egl.eglQueryAPI(); + } + } + } + // or, it can only be OpenGL ES + return EGL_OPENGL_ES_API; +} + +EGLBoolean eglReleaseThread(void) +{ + for (int i=0 ; i<2 ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (cnx->dso) { + if (cnx->hooks->egl.eglReleaseThread) { + cnx->hooks->egl.eglReleaseThread(); + } + } + } + clearTLS(); + return EGL_TRUE; +} + +EGLSurface eglCreatePbufferFromClientBuffer( + EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint *attrib_list) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (!cnx) return EGL_FALSE; + if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) { + return cnx->hooks->egl.eglCreatePbufferFromClientBuffer( + dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list); + } + return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); +} + +// ---------------------------------------------------------------------------- +// Android extentions +// ---------------------------------------------------------------------------- + +EGLBoolean eglSwapRectangleANDROID( + EGLDisplay dpy, EGLSurface draw, + EGLint l, EGLint t, EGLint w, EGLint h) +{ + if (!validate_display_surface(dpy, draw)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(draw); + if (s->cnx->hooks->egl.eglSwapRectangleANDROID) { + return s->cnx->hooks->egl.eglSwapRectangleANDROID( + dp->dpys[s->impl], s->surface, l, t, w, h); + } + return setError(EGL_BAD_SURFACE, EGL_FALSE); +} + +const char* eglQueryStringConfigANDROID( + EGLDisplay dpy, EGLConfig config, EGLint name) +{ + egl_display_t const* dp = 0; + int i=0, index=0; + egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); + if (cnx) { + return dp->queryString[i].extensions_config; + } + return setError(EGL_BAD_PARAMETER, (const char *)0); +} diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk new file mode 100644 index 0000000..a3dff76 --- /dev/null +++ b/opengl/libagl/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH:= $(call my-dir) + +# +# Build the software OpenGL ES library +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + egl.cpp \ + state.cpp \ + texture.cpp \ + Tokenizer.cpp \ + TokenManager.cpp \ + TextureObjectManager.cpp \ + BufferObjectManager.cpp \ + array.cpp.arm \ + fp.cpp.arm \ + light.cpp.arm \ + matrix.cpp.arm \ + mipmap.cpp.arm \ + primitives.cpp.arm \ + vertex.cpp.arm + +ifeq ($(TARGET_ARCH),arm) + LOCAL_SRC_FILES += fixed_asm.S iterators.S + LOCAL_CFLAGS += -fstrict-aliasing +endif + +LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger +LOCAL_LDLIBS := -lpthread -ldl +LOCAL_MODULE:= libagl + +include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libagl/BufferObjectManager.cpp b/opengl/libagl/BufferObjectManager.cpp new file mode 100644 index 0000000..6bf28ee --- /dev/null +++ b/opengl/libagl/BufferObjectManager.cpp @@ -0,0 +1,103 @@ +/* + ** Copyright 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. + */ + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +#include <utils/Atomic.h> +#include <utils/RefBase.h> +#include <utils/KeyedVector.h> +#include <utils/Errors.h> + +#include <GLES/gl.h> + +#include "BufferObjectManager.h" + + +namespace android { + +using namespace gl; + +// ---------------------------------------------------------------------------- + +EGLBufferObjectManager::EGLBufferObjectManager() +: TokenManager(), mCount(0) +{ +} + +EGLBufferObjectManager::~EGLBufferObjectManager() +{ + // destroy all the buffer objects and their storage + GLsizei n = mBuffers.size(); + for (GLsizei i=0 ; i<n ; i++) { + buffer_t* bo = mBuffers.valueAt(i); + free(bo->data); + delete bo; + } +} + +buffer_t const* EGLBufferObjectManager::bind(GLuint buffer) +{ + Mutex::Autolock _l(mLock); + int32_t i = mBuffers.indexOfKey(buffer); + if (i >= 0) { + return mBuffers.valueAt(i); + } + buffer_t* bo = new buffer_t; + bo->data = 0; + bo->usage = GL_STATIC_DRAW; + bo->size = 0; + bo->name = buffer; + mBuffers.add(buffer, bo); + return bo; +} + +int EGLBufferObjectManager::allocateStore(buffer_t* bo, + GLsizeiptr size, GLenum usage) +{ + Mutex::Autolock _l(mLock); + if (size != bo->size) { + uint8_t* data = (uint8_t*)malloc(size); + if (data == 0) + return -1; + free(bo->data); + bo->data = data; + bo->size = size; + } + bo->usage = usage; + return 0; +} + +void EGLBufferObjectManager::deleteBuffers(GLsizei n, const GLuint* buffers) +{ + Mutex::Autolock _l(mLock); + while (n--) { + const GLuint t = *buffers++; + if (t) { + int32_t index = mBuffers.indexOfKey(t); + if (index >= 0) { + buffer_t* bo = mBuffers.valueAt(index); + free(bo->data); + mBuffers.removeItemsAt(index); + delete bo; + } + } + } +} + +// ---------------------------------------------------------------------------- +}; // namespace android diff --git a/opengl/libagl/BufferObjectManager.h b/opengl/libagl/BufferObjectManager.h new file mode 100644 index 0000000..9e9340a --- /dev/null +++ b/opengl/libagl/BufferObjectManager.h @@ -0,0 +1,85 @@ +/* + ** + ** Copyright 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. + */ + +#ifndef ANDROID_OPENGLES_BUFFER_OBJECT_MANAGER_H +#define ANDROID_OPENGLES_BUFFER_OBJECT_MANAGER_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +#include <utils/Atomic.h> +#include <utils/RefBase.h> +#include <utils/KeyedVector.h> +#include <utils/Errors.h> + +#include <GLES/gl.h> + +#include "Tokenizer.h" +#include "TokenManager.h" + + +namespace android { + +// ---------------------------------------------------------------------------- + +namespace gl { + +struct buffer_t { + GLsizeiptr size; + GLenum usage; + uint8_t* data; + uint32_t name; +}; + +}; + +class EGLBufferObjectManager : public TokenManager +{ +public: + EGLBufferObjectManager(); + ~EGLBufferObjectManager(); + + // protocol for sp<> + inline void incStrong(const void* id) const; + inline void decStrong(const void* id) const; + typedef void weakref_type; + + gl::buffer_t const* bind(GLuint buffer); + int allocateStore(gl::buffer_t* bo, GLsizeiptr size, GLenum usage); + void deleteBuffers(GLsizei n, const GLuint* buffers); + +private: + mutable volatile int32_t mCount; + mutable Mutex mLock; + KeyedVector<GLuint, gl::buffer_t*> mBuffers; +}; + +void EGLBufferObjectManager::incStrong(const void* id) const { + android_atomic_inc(&mCount); +} +void EGLBufferObjectManager::decStrong(const void* id) const { + if (android_atomic_dec(&mCount) == 1) { + delete this; + } +} + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_OPENGLES_BUFFER_OBJECT_MANAGER_H + diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp new file mode 100644 index 0000000..12fae63 --- /dev/null +++ b/opengl/libagl/TextureObjectManager.cpp @@ -0,0 +1,309 @@ +/* + ** Copyright 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "context.h" +#include "TextureObjectManager.h" + +namespace android { +// ---------------------------------------------------------------------------- + +EGLTextureObject::EGLTextureObject() + : mCount(0), mSize(0) +{ + init(); +} + +EGLTextureObject::~EGLTextureObject() +{ + if (!direct) { + if (mSize && surface.data) + free(surface.data); + if (mMipmaps) + freeMipmaps(); + } +} + +void EGLTextureObject::init() +{ + memset(&surface, 0, sizeof(surface)); + surface.version = sizeof(surface); + mMipmaps = 0; + mNumExtraLod = 0; + mIsComplete = false; + wraps = GL_REPEAT; + wrapt = GL_REPEAT; + min_filter = GL_LINEAR; + mag_filter = GL_LINEAR; + internalformat = 0; + memset(crop_rect, 0, sizeof(crop_rect)); + generate_mipmap = GL_FALSE; + direct = GL_FALSE; +} + +void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old) +{ + wraps = old->wraps; + wrapt = old->wrapt; + min_filter = old->min_filter; + mag_filter = old->mag_filter; + memcpy(crop_rect, old->crop_rect, sizeof(crop_rect)); + generate_mipmap = old->generate_mipmap; + direct = old->direct; +} + +status_t EGLTextureObject::allocateMipmaps() +{ + // here, by construction, mMipmaps=0 && mNumExtraLod=0 + + if (!surface.data) + return NO_INIT; + + int w = surface.width; + int h = surface.height; + const int numLods = 31 - gglClz(max(w,h)); + if (numLods <= 0) + return NO_ERROR; + + mMipmaps = (GGLSurface*)malloc(numLods * sizeof(GGLSurface)); + if (!mMipmaps) + return NO_MEMORY; + + memset(mMipmaps, 0, numLods * sizeof(GGLSurface)); + mNumExtraLod = numLods; + return NO_ERROR; +} + +void EGLTextureObject::freeMipmaps() +{ + if (mMipmaps) { + for (int i=0 ; i<mNumExtraLod ; i++) { + if (mMipmaps[i].data) { + free(mMipmaps[i].data); + } + } + free(mMipmaps); + mMipmaps = 0; + mNumExtraLod = 0; + } +} + +const GGLSurface& EGLTextureObject::mip(int lod) const +{ + if (lod<=0 || !mMipmaps) + return surface; + lod = min(lod-1, mNumExtraLod-1); + return mMipmaps[lod]; +} + +GGLSurface& EGLTextureObject::editMip(int lod) +{ + return const_cast<GGLSurface&>(mip(lod)); +} + +status_t EGLTextureObject::setSurface(GGLSurface const* s) +{ + // XXX: glFlush() on 's' + if (mSize && surface.data) { + free(surface.data); + } + surface = *s; + internalformat = 0; + + // we should keep the crop_rect, but it's delicate because + // the new size of the surface could make it invalid. + // so for now, we just loose it. + memset(crop_rect, 0, sizeof(crop_rect)); + + // it would be nice id we could keep the generate_mipmap flag + // we would have to generate them right now though. + generate_mipmap = GL_FALSE; + + direct = GL_TRUE; + mSize = 0; // we don't own this surface + if (mMipmaps) + freeMipmaps(); + mIsComplete = true; + return NO_ERROR; +} + +status_t EGLTextureObject::reallocate( + GLint level, int w, int h, int s, + int format, int compressedFormat, int bpr) +{ + const size_t size = h * bpr; + if (level == 0) + { + if (size!=mSize || !surface.data) { + if (mSize && surface.data) { + free(surface.data); + } + surface.data = (GGLubyte*)malloc(size); + if (!surface.data) { + mSize = 0; + mIsComplete = false; + return NO_MEMORY; + } + mSize = size; + } + surface.version = sizeof(GGLSurface); + surface.width = w; + surface.height = h; + surface.stride = s; + surface.format = format; + surface.compressedFormat = compressedFormat; + if (mMipmaps) + freeMipmaps(); + mIsComplete = true; + } + else + { + if (!mMipmaps) { + if (allocateMipmaps() != NO_ERROR) + return NO_MEMORY; + } + + LOGW_IF(level-1 >= mNumExtraLod, + "specifying mipmap level %d, but # of level is %d", + level, mNumExtraLod+1); + + GGLSurface& mipmap = editMip(level); + if (mipmap.data) + free(mipmap.data); + + mipmap.data = (GGLubyte*)malloc(size); + if (!mipmap.data) { + memset(&mipmap, 0, sizeof(GGLSurface)); + mIsComplete = false; + return NO_MEMORY; + } + + mipmap.version = sizeof(GGLSurface); + mipmap.width = w; + mipmap.height = h; + mipmap.stride = s; + mipmap.format = format; + mipmap.compressedFormat = compressedFormat; + + // check if the texture is complete + mIsComplete = true; + const GGLSurface* prev = &surface; + for (int i=0 ; i<mNumExtraLod ; i++) { + const GGLSurface* curr = mMipmaps + i; + if (curr->format != surface.format) { + mIsComplete = false; + break; + } + + uint32_t w = (prev->width >> 1) ? : 1; + uint32_t h = (prev->height >> 1) ? : 1; + if (w != curr->width || h != curr->height) { + mIsComplete = false; + break; + } + prev = curr; + } + } + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +EGLSurfaceManager::EGLSurfaceManager() + : TokenManager(), mCount(0) +{ +} + +EGLSurfaceManager::~EGLSurfaceManager() +{ + // everything gets freed automatically here... +} + +sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name) +{ + sp<EGLTextureObject> result; + + Mutex::Autolock _l(mLock); + if (mTextures.indexOfKey(name) >= 0) + return result; // already exists! + + result = new EGLTextureObject(); + + status_t err = mTextures.add(name, result); + if (err < 0) + result.clear(); + + return result; +} + +sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name) +{ + Mutex::Autolock _l(mLock); + const ssize_t index = mTextures.indexOfKey(name); + if (index >= 0) { + sp<EGLTextureObject> result(mTextures.valueAt(index)); + mTextures.removeItemsAt(index); + return result; + } + return 0; +} + +sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name) +{ + sp<EGLTextureObject> tex; + Mutex::Autolock _l(mLock); + const ssize_t index = mTextures.indexOfKey(name); + if (index >= 0) { + const sp<EGLTextureObject>& old = mTextures.valueAt(index); + const uint32_t refs = old->getStrongCount(); + if (ggl_likely(refs == 1)) { + // we're the only owner + tex = old; + } else { + // keep the texture's parameters + tex = new EGLTextureObject(); + tex->copyParameters(old); + mTextures.removeItemsAt(index); + mTextures.add(name, tex); + } + } + return tex; +} + +void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens) +{ + // free all texures + Mutex::Autolock _l(mLock); + for (GLsizei i=0 ; i<n ; i++) { + const GLuint t(*tokens++); + if (t) { + mTextures.removeItem(t); + } + } +} + +sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name) +{ + Mutex::Autolock _l(mLock); + const ssize_t index = mTextures.indexOfKey(name); + if (index >= 0) + return mTextures.valueAt(index); + return 0; +} + +// ---------------------------------------------------------------------------- +}; // namespace android diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h new file mode 100644 index 0000000..74ed1a4 --- /dev/null +++ b/opengl/libagl/TextureObjectManager.h @@ -0,0 +1,140 @@ +/* +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_SURFACE_H +#define ANDROID_OPENGLES_SURFACE_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +#include <utils/Atomic.h> +#include <utils/threads.h> +#include <utils/RefBase.h> +#include <utils/KeyedVector.h> +#include <utils/Errors.h> + +#include <private/pixelflinger/ggl_context.h> + +#include <GLES/gl.h> + +#include "Tokenizer.h" +#include "TokenManager.h" + + +namespace android { + +// ---------------------------------------------------------------------------- + +class EGLTextureObject +{ +public: + EGLTextureObject(); + ~EGLTextureObject(); + + // protocol for sp<> + inline void incStrong(const void* id) const; + inline void decStrong(const void* id) const; + inline uint32_t getStrongCount() const; + + status_t setSurface(GGLSurface const* s); + status_t reallocate(GLint level, + int w, int h, int s, + int format, int compressedFormat, int bpr); + inline size_t size() const; + const GGLSurface& mip(int lod) const; + GGLSurface& editMip(int lod); + bool hasMipmaps() const { return mMipmaps!=0; } + bool isComplete() const { return mIsComplete; } + void copyParameters(const sp<EGLTextureObject>& old); + +private: + status_t allocateMipmaps(); + void freeMipmaps(); + void init(); + mutable int32_t mCount; + size_t mSize; + GGLSurface *mMipmaps; + int mNumExtraLod; + bool mIsComplete; + +public: + GGLSurface surface; + GLenum wraps; + GLenum wrapt; + GLenum min_filter; + GLenum mag_filter; + GLenum internalformat; + GLint crop_rect[4]; + GLint generate_mipmap; + GLint direct; +}; + +void EGLTextureObject::incStrong(const void* id) const { + android_atomic_inc(&mCount); +} +void EGLTextureObject::decStrong(const void* id) const { + if (android_atomic_dec(&mCount) == 1) { + delete this; + } +} +uint32_t EGLTextureObject::getStrongCount() const { + return mCount; +} +size_t EGLTextureObject::size() const { + return mSize; +} + +// ---------------------------------------------------------------------------- + +class EGLSurfaceManager : public TokenManager +{ +public: + EGLSurfaceManager(); + ~EGLSurfaceManager(); + + // protocol for sp<> + inline void incStrong(const void* id) const; + inline void decStrong(const void* id) const; + typedef void weakref_type; + + sp<EGLTextureObject> createTexture(GLuint name); + sp<EGLTextureObject> removeTexture(GLuint name); + sp<EGLTextureObject> replaceTexture(GLuint name); + void deleteTextures(GLsizei n, const GLuint *tokens); + sp<EGLTextureObject> texture(GLuint name); + +private: + mutable int32_t mCount; + mutable Mutex mLock; + KeyedVector< GLuint, sp<EGLTextureObject> > mTextures; +}; + +void EGLSurfaceManager::incStrong(const void* id) const { + android_atomic_inc(&mCount); +} +void EGLSurfaceManager::decStrong(const void* id) const { + if (android_atomic_dec(&mCount) == 1) { + delete this; + } +} + + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_OPENGLES_SURFACE_H + diff --git a/opengl/libagl/TokenManager.cpp b/opengl/libagl/TokenManager.cpp new file mode 100644 index 0000000..eea6025 --- /dev/null +++ b/opengl/libagl/TokenManager.cpp @@ -0,0 +1,62 @@ +/* libs/opengles/surface.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "TokenManager.h" + +namespace android { +// ---------------------------------------------------------------------------- + +TokenManager::TokenManager() +{ + // token 0 is always reserved + mTokenizer.reserve(0); +} + +TokenManager::~TokenManager() +{ +} + +status_t TokenManager::getToken(GLsizei n, GLuint *tokens) +{ + Mutex::Autolock _l(mLock); + for (GLsizei i=0 ; i<n ; i++) + *tokens++ = mTokenizer.acquire(); + return NO_ERROR; +} + +void TokenManager::recycleTokens(GLsizei n, const GLuint *tokens) +{ + Mutex::Autolock _l(mLock); + for (int i=0 ; i<n ; i++) { + const GLuint token = *tokens++; + if (token) { + mTokenizer.release(token); + } + } +} + +bool TokenManager::isTokenValid(GLuint token) const +{ + Mutex::Autolock _l(mLock); + return mTokenizer.isAcquired(token); +} + +// ---------------------------------------------------------------------------- +}; // namespace android + diff --git a/opengl/libagl/TokenManager.h b/opengl/libagl/TokenManager.h new file mode 100644 index 0000000..49c1469 --- /dev/null +++ b/opengl/libagl/TokenManager.h @@ -0,0 +1,53 @@ +/* +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_TOKEN_MANAGER_H +#define ANDROID_OPENGLES_TOKEN_MANAGER_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +#include <utils/threads.h> + +#include <GLES/gl.h> + +#include "Tokenizer.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +class TokenManager +{ +public: + TokenManager(); + ~TokenManager(); + + status_t getToken(GLsizei n, GLuint *tokens); + void recycleTokens(GLsizei n, const GLuint *tokens); + bool isTokenValid(GLuint token) const; + +private: + mutable Mutex mLock; + Tokenizer mTokenizer; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_OPENGLES_TOKEN_MANAGER_H + diff --git a/opengl/libagl/Tokenizer.cpp b/opengl/libagl/Tokenizer.cpp new file mode 100644 index 0000000..9b3ea1a --- /dev/null +++ b/opengl/libagl/Tokenizer.cpp @@ -0,0 +1,173 @@ +/* libs/opengles/Tokenizer.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> + +#include "Tokenizer.h" + +// ---------------------------------------------------------------------------- + +namespace android { + +ANDROID_BASIC_TYPES_TRAITS(Tokenizer::run_t) + +Tokenizer::Tokenizer() +{ +} + +Tokenizer::Tokenizer(const Tokenizer& other) + : mRanges(other.mRanges) +{ +} + +Tokenizer::~Tokenizer() +{ +} + +uint32_t Tokenizer::acquire() +{ + if (!mRanges.size() || mRanges[0].first) { + _insertTokenAt(0,0); + return 0; + } + + // just extend the first run + const run_t& run = mRanges[0]; + uint32_t token = run.first + run.length; + _insertTokenAt(token, 1); + return token; +} + +bool Tokenizer::isAcquired(uint32_t token) const +{ + return (_indexOrderOf(token) >= 0); +} + +status_t Tokenizer::reserve(uint32_t token) +{ + size_t o; + const ssize_t i = _indexOrderOf(token, &o); + if (i >= 0) { + return BAD_VALUE; // this token is already taken + } + ssize_t err = _insertTokenAt(token, o); + return (err<0) ? err : status_t(NO_ERROR); +} + +status_t Tokenizer::release(uint32_t token) +{ + const ssize_t i = _indexOrderOf(token); + if (i >= 0) { + const run_t& run = mRanges[i]; + if ((token >= run.first) && (token < run.first+run.length)) { + // token in this range, we need to split + run_t& run = mRanges.editItemAt(i); + if ((token == run.first) || (token == run.first+run.length-1)) { + if (token == run.first) { + run.first += 1; + } + run.length -= 1; + if (run.length == 0) { + // XXX: should we systematically remove a run that's empty? + mRanges.removeItemsAt(i); + } + } else { + // split the run + run_t new_run; + new_run.first = token+1; + new_run.length = run.first+run.length - new_run.first; + run.length = token - run.first; + mRanges.insertAt(new_run, i+1); + } + return NO_ERROR; + } + } + return NAME_NOT_FOUND; +} + +ssize_t Tokenizer::_indexOrderOf(uint32_t token, size_t* order) const +{ + // binary search + ssize_t err = NAME_NOT_FOUND; + ssize_t l = 0; + ssize_t h = mRanges.size()-1; + ssize_t mid; + const run_t* a = mRanges.array(); + while (l <= h) { + mid = l + (h - l)/2; + const run_t* const curr = a + mid; + int c = 0; + if (token < curr->first) c = 1; + else if (token >= curr->first+curr->length) c = -1; + if (c == 0) { + err = l = mid; + break; + } else if (c < 0) { + l = mid + 1; + } else { + h = mid - 1; + } + } + if (order) *order = l; + return err; +} + +ssize_t Tokenizer::_insertTokenAt(uint32_t token, size_t index) +{ + const size_t c = mRanges.size(); + + if (index >= 1) { + // do we need to merge with the previous run? + run_t& p = mRanges.editItemAt(index-1); + if (p.first+p.length == token) { + p.length += 1; + if (index < c) { + const run_t& n = mRanges[index]; + if (token+1 == n.first) { + p.length += n.length; + mRanges.removeItemsAt(index); + } + } + return index; + } + } + + if (index < c) { + // do we need to merge with the next run? + run_t& n = mRanges.editItemAt(index); + if (token+1 == n.first) { + n.first -= 1; + n.length += 1; + return index; + } + } + + return mRanges.insertAt(run_t(token,1), index); +} + +void Tokenizer::dump() const +{ + const run_t* ranges = mRanges.array(); + const size_t c = mRanges.size(); + LOGD("Tokenizer (%p, size = %u)\n", this, c); + for (size_t i=0 ; i<c ; i++) { + LOGD("%u: (%u, %u)\n", i, ranges[i].first, ranges[i].length); + } +} + +}; // namespace android + diff --git a/opengl/libagl/Tokenizer.h b/opengl/libagl/Tokenizer.h new file mode 100644 index 0000000..ac555cb --- /dev/null +++ b/opengl/libagl/Tokenizer.h @@ -0,0 +1,59 @@ +/* libs/opengles/Tokenizer.h +** +** Copyright 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. +*/ + + +#ifndef ANDROID_OPENGLES_TOKENIZER_H +#define ANDROID_OPENGLES_TOKENIZER_H + +#include <utils/Vector.h> +#include <utils/Errors.h> + +// ---------------------------------------------------------------------------- + +namespace android { + +class Tokenizer +{ +public: + Tokenizer(); + Tokenizer(const Tokenizer& other); + ~Tokenizer(); + + uint32_t acquire(); + status_t reserve(uint32_t token); + status_t release(uint32_t token); + bool isAcquired(uint32_t token) const; + + void dump() const; + + struct run_t { + run_t() {}; + run_t(uint32_t f, uint32_t l) : first(f), length(l) {} + uint32_t first; + uint32_t length; + }; +private: + ssize_t _indexOrderOf(uint32_t token, size_t* order=0) const; + ssize_t _insertTokenAt(uint32_t token, size_t index); + Vector<run_t> mRanges; +}; + +}; // namespace android + +// ---------------------------------------------------------------------------- + +#endif // ANDROID_OPENGLES_TOKENIZER_H diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp new file mode 100644 index 0000000..1f6757d --- /dev/null +++ b/opengl/libagl/array.cpp @@ -0,0 +1,1557 @@ +/* +** Copyright 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. +*/ + +#include <stdlib.h> +#include <stdio.h> + +#include "context.h" +#include "fp.h" +#include "state.h" +#include "matrix.h" +#include "vertex.h" +#include "light.h" +#include "primitives.h" +#include "texture.h" +#include "BufferObjectManager.h" + +// ---------------------------------------------------------------------------- + +#define VC_CACHE_STATISTICS 0 +#define VC_CACHE_TYPE_NONE 0 +#define VC_CACHE_TYPE_INDEXED 1 +#define VC_CACHE_TYPE_LRU 2 +#define VC_CACHE_TYPE VC_CACHE_TYPE_INDEXED + +#if VC_CACHE_STATISTICS +#include <utils/Timers.h> +#endif + +// ---------------------------------------------------------------------------- + +namespace android { + +static void validate_arrays(ogles_context_t* c, GLenum mode); + +static void compileElements__generic(ogles_context_t*, + vertex_t*, GLint, GLsizei); +static void compileElement__generic(ogles_context_t*, + vertex_t*, GLint); + +static void drawPrimitivesPoints(ogles_context_t*, GLint, GLsizei); +static void drawPrimitivesLineStrip(ogles_context_t*, GLint, GLsizei); +static void drawPrimitivesLineLoop(ogles_context_t*, GLint, GLsizei); +static void drawPrimitivesLines(ogles_context_t*, GLint, GLsizei); +static void drawPrimitivesTriangleStrip(ogles_context_t*, GLint, GLsizei); +static void drawPrimitivesTriangleFan(ogles_context_t*, GLint, GLsizei); +static void drawPrimitivesTriangles(ogles_context_t*, GLint, GLsizei); + +static void drawIndexedPrimitivesPoints(ogles_context_t*, + GLsizei, const GLvoid*); +static void drawIndexedPrimitivesLineStrip(ogles_context_t*, + GLsizei, const GLvoid*); +static void drawIndexedPrimitivesLineLoop(ogles_context_t*, + GLsizei, const GLvoid*); +static void drawIndexedPrimitivesLines(ogles_context_t*, + GLsizei, const GLvoid*); +static void drawIndexedPrimitivesTriangleStrip(ogles_context_t*, + GLsizei, const GLvoid*); +static void drawIndexedPrimitivesTriangleFan(ogles_context_t*, + GLsizei, const GLvoid*); +static void drawIndexedPrimitivesTriangles(ogles_context_t*, + GLsizei, const GLvoid*); + +// ---------------------------------------------------------------------------- + +typedef void (*arrays_prims_fct_t)(ogles_context_t*, GLint, GLsizei); +static const arrays_prims_fct_t drawArraysPrims[] = { + drawPrimitivesPoints, + drawPrimitivesLines, + drawPrimitivesLineLoop, + drawPrimitivesLineStrip, + drawPrimitivesTriangles, + drawPrimitivesTriangleStrip, + drawPrimitivesTriangleFan +}; + +typedef void (*elements_prims_fct_t)(ogles_context_t*, GLsizei, const GLvoid*); +static const elements_prims_fct_t drawElementsPrims[] = { + drawIndexedPrimitivesPoints, + drawIndexedPrimitivesLines, + drawIndexedPrimitivesLineLoop, + drawIndexedPrimitivesLineStrip, + drawIndexedPrimitivesTriangles, + drawIndexedPrimitivesTriangleStrip, + drawIndexedPrimitivesTriangleFan +}; + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +void ogles_init_array(ogles_context_t* c) +{ + c->arrays.vertex.size = 4; + c->arrays.vertex.type = GL_FLOAT; + c->arrays.color.size = 4; + c->arrays.color.type = GL_FLOAT; + c->arrays.normal.size = 4; + c->arrays.normal.type = GL_FLOAT; + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + c->arrays.texture[i].size = 4; + c->arrays.texture[i].type = GL_FLOAT; + } + c->vc.init(); + + if (!c->vc.vBuffer) { + // this could have failed + ogles_error(c, GL_OUT_OF_MEMORY); + } +} + +void ogles_uninit_array(ogles_context_t* c) +{ + c->vc.uninit(); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Array fetchers +#endif + +static void currentColor(ogles_context_t* c, GLfixed* v, const GLvoid*) { + memcpy(v, c->current.color.v, sizeof(vec4_t)); +} +static void currentColor_clamp(ogles_context_t* c, GLfixed* v, const GLvoid*) { + memcpy(v, c->currentColorClamped.v, sizeof(vec4_t)); +} +static void currentNormal(ogles_context_t* c, GLfixed* v, const GLvoid*) { + memcpy(v, c->currentNormal.v, sizeof(vec3_t)); +} +static void currentTexCoord(ogles_context_t* c, GLfixed* v, const GLvoid*) { + memcpy(v, c->current.texture[c->arrays.tmu].v, sizeof(vec4_t)); +} + + +static void fetchNop(ogles_context_t*, GLfixed*, const GLvoid*) { +} +static void fetch2b(ogles_context_t*, GLfixed* v, const GLbyte* p) { + v[0] = gglIntToFixed(p[0]); + v[1] = gglIntToFixed(p[1]); +} +static void fetch2s(ogles_context_t*, GLfixed* v, const GLshort* p) { + v[0] = gglIntToFixed(p[0]); + v[1] = gglIntToFixed(p[1]); +} +static void fetch2x(ogles_context_t*, GLfixed* v, const GLfixed* p) { + memcpy(v, p, 2*sizeof(GLfixed)); +} +static void fetch2f(ogles_context_t*, GLfixed* v, const GLfloat* p) { + v[0] = gglFloatToFixed(p[0]); + v[1] = gglFloatToFixed(p[1]); +} +static void fetch3b(ogles_context_t*, GLfixed* v, const GLbyte* p) { + v[0] = gglIntToFixed(p[0]); + v[1] = gglIntToFixed(p[1]); + v[2] = gglIntToFixed(p[2]); +} +static void fetch3s(ogles_context_t*, GLfixed* v, const GLshort* p) { + v[0] = gglIntToFixed(p[0]); + v[1] = gglIntToFixed(p[1]); + v[2] = gglIntToFixed(p[2]); +} +static void fetch3x(ogles_context_t*, GLfixed* v, const GLfixed* p) { + memcpy(v, p, 3*sizeof(GLfixed)); +} +static void fetch3f(ogles_context_t*, GLfixed* v, const GLfloat* p) { + v[0] = gglFloatToFixed(p[0]); + v[1] = gglFloatToFixed(p[1]); + v[2] = gglFloatToFixed(p[2]); +} +static void fetch4b(ogles_context_t*, GLfixed* v, const GLbyte* p) { + v[0] = gglIntToFixed(p[0]); + v[1] = gglIntToFixed(p[1]); + v[2] = gglIntToFixed(p[2]); + v[3] = gglIntToFixed(p[3]); +} +static void fetch4s(ogles_context_t*, GLfixed* v, const GLshort* p) { + v[0] = gglIntToFixed(p[0]); + v[1] = gglIntToFixed(p[1]); + v[2] = gglIntToFixed(p[2]); + v[3] = gglIntToFixed(p[3]); +} +static void fetch4x(ogles_context_t*, GLfixed* v, const GLfixed* p) { + memcpy(v, p, 4*sizeof(GLfixed)); +} +static void fetch4f(ogles_context_t*, GLfixed* v, const GLfloat* p) { + v[0] = gglFloatToFixed(p[0]); + v[1] = gglFloatToFixed(p[1]); + v[2] = gglFloatToFixed(p[2]); + v[3] = gglFloatToFixed(p[3]); +} +static void fetchExpand4ub(ogles_context_t*, GLfixed* v, const GLubyte* p) { + v[0] = GGL_UB_TO_X(p[0]); + v[1] = GGL_UB_TO_X(p[1]); + v[2] = GGL_UB_TO_X(p[2]); + v[3] = GGL_UB_TO_X(p[3]); +} +static void fetchClamp4x(ogles_context_t*, GLfixed* v, const GLfixed* p) { + v[0] = gglClampx(p[0]); + v[1] = gglClampx(p[1]); + v[2] = gglClampx(p[2]); + v[3] = gglClampx(p[3]); +} +static void fetchClamp4f(ogles_context_t*, GLfixed* v, const GLfloat* p) { + v[0] = gglClampx(gglFloatToFixed(p[0])); + v[1] = gglClampx(gglFloatToFixed(p[1])); + v[2] = gglClampx(gglFloatToFixed(p[2])); + v[3] = gglClampx(gglFloatToFixed(p[3])); +} +static void fetchExpand3ub(ogles_context_t*, GLfixed* v, const GLubyte* p) { + v[0] = GGL_UB_TO_X(p[0]); + v[1] = GGL_UB_TO_X(p[1]); + v[2] = GGL_UB_TO_X(p[2]); + v[3] = 0x10000; +} +static void fetchClamp3x(ogles_context_t*, GLfixed* v, const GLfixed* p) { + v[0] = gglClampx(p[0]); + v[1] = gglClampx(p[1]); + v[2] = gglClampx(p[2]); + v[3] = 0x10000; +} +static void fetchClamp3f(ogles_context_t*, GLfixed* v, const GLfloat* p) { + v[0] = gglClampx(gglFloatToFixed(p[0])); + v[1] = gglClampx(gglFloatToFixed(p[1])); + v[2] = gglClampx(gglFloatToFixed(p[2])); + v[3] = 0x10000; +} +static void fetchExpand3b(ogles_context_t*, GLfixed* v, const GLbyte* p) { + v[0] = GGL_B_TO_X(p[0]); + v[1] = GGL_B_TO_X(p[1]); + v[2] = GGL_B_TO_X(p[2]); +} +static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) { + v[0] = GGL_S_TO_X(p[0]); + v[1] = GGL_S_TO_X(p[1]); + v[2] = GGL_S_TO_X(p[2]); +} + +typedef array_t::fetcher_t fn_t; + +static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x} + { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, + (fn_t)fetch3f, 0, 0, 0, 0, 0, + (fn_t)fetch3x }, + { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0, + (fn_t)fetch4f, 0, 0, 0, 0, 0, + (fn_t)fetch4x }, +}; +static const fn_t color_clamp_fct[2][16] = { // size={3,4}, type={ub,f,x} + { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, + (fn_t)fetchClamp3f, 0, 0, 0, 0, 0, + (fn_t)fetchClamp3x }, + { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0, + (fn_t)fetchClamp4f, 0, 0, 0, 0, 0, + (fn_t)fetchClamp4x }, +}; +static const fn_t normal_fct[1][16] = { // size={3}, type={b,s,f,x} + { (fn_t)fetchExpand3b, 0, + (fn_t)fetchExpand3s, 0, 0, 0, + (fn_t)fetch3f, 0, 0, 0, 0, 0, + (fn_t)fetch3x }, +}; +static const fn_t vertex_fct[3][16] = { // size={2,3,4}, type={b,s,f,x} + { (fn_t)fetch2b, 0, + (fn_t)fetch2s, 0, 0, 0, + (fn_t)fetch2f, 0, 0, 0, 0, 0, + (fn_t)fetch3x }, + { (fn_t)fetch3b, 0, + (fn_t)fetch3s, 0, 0, 0, + (fn_t)fetch3f, 0, 0, 0, 0, 0, + (fn_t)fetch3x }, + { (fn_t)fetch4b, 0, + (fn_t)fetch4s, 0, 0, 0, + (fn_t)fetch4f, 0, 0, 0, 0, 0, + (fn_t)fetch4x } +}; +static const fn_t texture_fct[3][16] = { // size={2,3,4}, type={b,s,f,x} + { (fn_t)fetch2b, 0, + (fn_t)fetch2s, 0, 0, 0, + (fn_t)fetch2f, 0, 0, 0, 0, 0, + (fn_t)fetch2x }, + { (fn_t)fetch3b, 0, + (fn_t)fetch3s, 0, 0, 0, + (fn_t)fetch3f, 0, 0, 0, 0, 0, + (fn_t)fetch3x }, + { (fn_t)fetch4b, 0, + (fn_t)fetch4s, 0, 0, 0, + (fn_t)fetch4f, 0, 0, 0, 0, 0, + (fn_t)fetch4x } +}; + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark array_t +#endif + +void array_t::init( + GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer, const buffer_t* bo, GLsizei count) +{ + if (!stride) { + stride = size; + switch (type) { + case GL_SHORT: + case GL_UNSIGNED_SHORT: + stride *= 2; + break; + case GL_FLOAT: + case GL_FIXED: + stride *= 4; + break; + } + } + this->size = size; + this->type = type; + this->stride = stride; + this->pointer = pointer; + this->bo = bo; + this->bounds = count; +} + +inline void array_t::resolve() +{ + physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer; +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark vertex_cache_t +#endif + +void vertex_cache_t::init() +{ + // make sure the size of vertex_t allows cache-line alignment + CTA<(sizeof(vertex_t) & 0x1F) == 0> assertAlignedSize; + + const int align = 32; + const size_t s = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE; + const size_t size = s*sizeof(vertex_t) + align; + base = malloc(size); + if (base) { + memset(base, 0, size); + vBuffer = (vertex_t*)((size_t(base) + align - 1) & ~(align-1)); + vCache = vBuffer + VERTEX_BUFFER_SIZE; + sequence = 0; + } +} + +void vertex_cache_t::uninit() +{ + free(base); + base = vBuffer = vCache = 0; +} + +void vertex_cache_t::clear() +{ +#if VC_CACHE_STATISTICS + startTime = systemTime(SYSTEM_TIME_THREAD); + total = 0; + misses = 0; +#endif + +#if VC_CACHE_TYPE == VC_CACHE_TYPE_LRU + vertex_t* v = vBuffer; + size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE; + do { + v->mru = 0; + v++; + } while (--count); +#endif + + sequence += INDEX_SEQ; + if (sequence >= 0x80000000LU) { + sequence = INDEX_SEQ; + vertex_t* v = vBuffer; + size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE; + do { + v->index = 0; + v++; + } while (--count); + } +} + +void vertex_cache_t::dump_stats(GLenum mode) +{ +#if VC_CACHE_STATISTICS + nsecs_t time = systemTime(SYSTEM_TIME_THREAD) - startTime; + uint32_t hits = total - misses; + uint32_t prim_count; + switch (mode) { + case GL_POINTS: prim_count = total; break; + case GL_LINE_STRIP: prim_count = total - 1; break; + case GL_LINE_LOOP: prim_count = total - 1; break; + case GL_LINES: prim_count = total / 2; break; + case GL_TRIANGLE_STRIP: prim_count = total - 2; break; + case GL_TRIANGLE_FAN: prim_count = total - 2; break; + case GL_TRIANGLES: prim_count = total / 3; break; + default: return; + } + printf( "total=%5u, hits=%5u, miss=%5u, hitrate=%3u%%," + " prims=%5u, time=%6u us, prims/s=%d, v/t=%f\n", + total, hits, misses, (hits*100)/total, + prim_count, int(ns2us(time)), int(prim_count*float(seconds(1))/time), + float(misses) / prim_count); +#endif +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +static __attribute__((noinline)) +void enableDisableClientState(ogles_context_t* c, GLenum array, bool enable) +{ + const int tmu = c->arrays.activeTexture; + array_t* a; + switch (array) { + case GL_COLOR_ARRAY: a = &c->arrays.color; break; + case GL_NORMAL_ARRAY: a = &c->arrays.normal; break; + case GL_TEXTURE_COORD_ARRAY: a = &c->arrays.texture[tmu]; break; + case GL_VERTEX_ARRAY: a = &c->arrays.vertex; break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + a->enable = enable ? GL_TRUE : GL_FALSE; +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Vertex Cache +#endif + +static __attribute__((noinline)) +vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index) +{ + #if VC_CACHE_STATISTICS + c->vc.misses++; + #endif + if (ggl_unlikely(v->locked)) { + // we're just looking for an entry in the cache that is not locked. + // and we know that there cannot be more than 2 locked entries + // because a triangle needs at most 3 vertices. + // We never use the first and second entries because they might be in + // use by the striper or faner. Any other entry will do as long as + // it's not locked. + // We compute directly the index of a "free" entry from the locked + // state of v[2] and v[3]. + v = c->vc.vBuffer + 2; + v += v[0].locked | (v[1].locked<<1); + } + // note: compileElement clears v->flags + c->arrays.compileElement(c, v, index); + v->locked = 1; + return v; +} + +static __attribute__((noinline)) +vertex_t* fetch_vertex(ogles_context_t* c, size_t index) +{ + index |= c->vc.sequence; + +#if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED + + vertex_t* const v = c->vc.vCache + + (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1)); + + if (ggl_likely(v->index == index)) { + v->locked = 1; + return v; + } + return cache_vertex(c, v, index); + +#elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU + + vertex_t* v = c->vc.vCache + + (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2; + + // always record LRU in v[0] + if (ggl_likely(v[0].index == index)) { + v[0].locked = 1; + v[0].mru = 0; + return &v[0]; + } + + if (ggl_likely(v[1].index == index)) { + v[1].locked = 1; + v[0].mru = 1; + return &v[1]; + } + + const int lru = 1 - v[0].mru; + v[0].mru = lru; + return cache_vertex(c, &v[lru], index); + +#elif VC_CACHE_TYPE == VC_CACHE_TYPE_NONE + + // just for debugging... + vertex_t* v = c->vc.vBuffer + 2; + return cache_vertex(c, v, index); + +#endif +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Primitive Assembly +#endif + +void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count) +{ + if (ggl_unlikely(count < 1)) + return; + + // vertex cache size must be multiple of 1 + const GLsizei vcs = + (vertex_cache_t::VERTEX_BUFFER_SIZE + + vertex_cache_t::VERTEX_CACHE_SIZE); + do { + vertex_t* v = c->vc.vBuffer; + GLsizei num = count > vcs ? vcs : count; + c->arrays.cull = vertex_t::CLIP_ALL; + c->arrays.compileElements(c, v, first, num); + first += num; + count -= num; + if (!c->arrays.cull) { + // quick/trivial reject of the whole batch + do { + const uint32_t cc = v[0].flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderPoint(c, v); + v++; + num--; + } while (num); + } + } while (count); +} + +// ---------------------------------------------------------------------------- + +void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count) +{ + if (ggl_unlikely(count < 2)) + return; + + vertex_t *v, *v0, *v1; + c->arrays.cull = vertex_t::CLIP_ALL; + c->arrays.compileElement(c, c->vc.vBuffer, first); + first += 1; + count -= 1; + + // vertex cache size must be multiple of 1 + const GLsizei vcs = + (vertex_cache_t::VERTEX_BUFFER_SIZE + + vertex_cache_t::VERTEX_CACHE_SIZE - 1); + do { + v0 = c->vc.vBuffer + 0; + v = c->vc.vBuffer + 1; + GLsizei num = count > vcs ? vcs : count; + c->arrays.compileElements(c, v, first, num); + first += num; + count -= num; + if (!c->arrays.cull) { + // quick/trivial reject of the whole batch + do { + v1 = v++; + const uint32_t cc = v0->flags & v1->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v0, v1); + v0 = v1; + num--; + } while (num); + } + // copy back the last processed vertex + c->vc.vBuffer[0] = *v0; + c->arrays.cull = v0->flags & vertex_t::CLIP_ALL; + } while (count); +} + +void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count) +{ + if (ggl_unlikely(count < 2)) + return; + drawPrimitivesLineStrip(c, first, count); + if (ggl_likely(count >= 3)) { + vertex_t* v0 = c->vc.vBuffer; + vertex_t* v1 = c->vc.vBuffer + 1; + c->arrays.compileElement(c, v1, first); + const uint32_t cc = v0->flags & v1->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v0, v1); + } +} + +void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count) +{ + if (ggl_unlikely(count < 2)) + return; + + // vertex cache size must be multiple of 2 + const GLsizei vcs = + ((vertex_cache_t::VERTEX_BUFFER_SIZE + + vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2; + do { + vertex_t* v = c->vc.vBuffer; + GLsizei num = count > vcs ? vcs : count; + c->arrays.cull = vertex_t::CLIP_ALL; + c->arrays.compileElements(c, v, first, num); + first += num; + count -= num; + if (!c->arrays.cull) { + // quick/trivial reject of the whole batch + num -= 2; + do { + const uint32_t cc = v[0].flags & v[1].flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v, v+1); + v += 2; + num -= 2; + } while (num >= 0); + } + } while (count >= 2); +} + +// ---------------------------------------------------------------------------- + +static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, + GLint first, GLsizei count, int winding) +{ + // winding == 2 : fan + // winding == 1 : strip + + if (ggl_unlikely(count < 3)) + return; + + vertex_t *v, *v0, *v1, *v2; + c->arrays.cull = vertex_t::CLIP_ALL; + c->arrays.compileElements(c, c->vc.vBuffer, first, 2); + first += 2; + count -= 2; + + // vertex cache size must be multiple of 2. This is extremely important + // because it allows us to preserve the same winding when the whole + // batch is culled. We also need 2 extra vertices in the array, because + // we always keep the two first ones. + const GLsizei vcs = + ((vertex_cache_t::VERTEX_BUFFER_SIZE + + vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2; + do { + v0 = c->vc.vBuffer + 0; + v1 = c->vc.vBuffer + 1; + v = c->vc.vBuffer + 2; + GLsizei num = count > vcs ? vcs : count; + c->arrays.compileElements(c, v, first, num); + first += num; + count -= num; + if (!c->arrays.cull) { + // quick/trivial reject of the whole batch + do { + v2 = v++; + const uint32_t cc = v0->flags & v1->flags & v2->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderTriangle(c, v0, v1, v2); + swap(((winding^=1) ? v1 : v0), v2); + num--; + } while (num); + } + if (count) { + v0 = c->vc.vBuffer + 2 + num - 2; + v1 = c->vc.vBuffer + 2 + num - 1; + if ((winding&2) == 0) { + // for strips copy back the two last compiled vertices + c->vc.vBuffer[0] = *v0; + } + c->vc.vBuffer[1] = *v1; + c->arrays.cull = v0->flags & v1->flags & vertex_t::CLIP_ALL; + } + } while (count > 0); +} + +void drawPrimitivesTriangleStrip(ogles_context_t* c, + GLint first, GLsizei count) { + drawPrimitivesTriangleFanOrStrip(c, first, count, 1); +} + +void drawPrimitivesTriangleFan(ogles_context_t* c, + GLint first, GLsizei count) { + drawPrimitivesTriangleFanOrStrip(c, first, count, 2); +} + +void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count) +{ + if (ggl_unlikely(count < 3)) + return; + + // vertex cache size must be multiple of 3 + const GLsizei vcs = + ((vertex_cache_t::VERTEX_BUFFER_SIZE + + vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3; + do { + vertex_t* v = c->vc.vBuffer; + GLsizei num = count > vcs ? vcs : count; + c->arrays.cull = vertex_t::CLIP_ALL; + c->arrays.compileElements(c, v, first, num); + first += num; + count -= num; + if (!c->arrays.cull) { + // quick/trivial reject of the whole batch + num -= 3; + do { + const uint32_t cc = v[0].flags & v[1].flags & v[2].flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderTriangle(c, v, v+1, v+2); + v += 3; + num -= 3; + } while (num >= 0); + } + } while (count >= 3); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +// this looks goofy, but gcc does a great job with this... +static inline unsigned int read_index(int type, const GLvoid*& p) { + unsigned int r; + if (type) { + r = *(const GLubyte*)p; + p = (const GLubyte*)p + 1; + } else { + r = *(const GLushort*)p; + p = (const GLushort*)p + 1; + } + return r; +} + +// ---------------------------------------------------------------------------- + +void drawIndexedPrimitivesPoints(ogles_context_t* c, + GLsizei count, const GLvoid *indices) +{ + if (ggl_unlikely(count < 1)) + return; + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); + do { + vertex_t * v = fetch_vertex(c, read_index(type, indices)); + if (ggl_likely(!(v->flags & vertex_t::CLIP_ALL))) + c->prims.renderPoint(c, v); + v->locked = 0; + count--; + } while(count); +} + +// ---------------------------------------------------------------------------- + +void drawIndexedPrimitivesLineStrip(ogles_context_t* c, + GLsizei count, const GLvoid *indices) +{ + if (ggl_unlikely(count < 2)) + return; + + vertex_t * const v = c->vc.vBuffer; + vertex_t* v0 = v; + vertex_t* v1; + + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); + c->arrays.compileElement(c, v0, read_index(type, indices)); + count -= 1; + do { + v1 = fetch_vertex(c, read_index(type, indices)); + const uint32_t cc = v0->flags & v1->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v0, v1); + v0->locked = 0; + v0 = v1; + count--; + } while (count); + v1->locked = 0; +} + +void drawIndexedPrimitivesLineLoop(ogles_context_t* c, + GLsizei count, const GLvoid *indices) +{ + if (ggl_unlikely(count <= 2)) { + drawIndexedPrimitivesLines(c, count, indices); + return; + } + + vertex_t * const v = c->vc.vBuffer; + vertex_t* v0 = v; + vertex_t* v1; + + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); + c->arrays.compileElement(c, v0, read_index(type, indices)); + count -= 1; + do { + v1 = fetch_vertex(c, read_index(type, indices)); + const uint32_t cc = v0->flags & v1->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v0, v1); + v0->locked = 0; + v0 = v1; + count--; + } while (count); + v1->locked = 0; + + v1 = c->vc.vBuffer; + const uint32_t cc = v0->flags & v1->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v0, v1); +} + +void drawIndexedPrimitivesLines(ogles_context_t* c, + GLsizei count, const GLvoid *indices) +{ + if (ggl_unlikely(count < 2)) + return; + + count -= 2; + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); + do { + vertex_t* const v0 = fetch_vertex(c, read_index(type, indices)); + vertex_t* const v1 = fetch_vertex(c, read_index(type, indices)); + const uint32_t cc = v0->flags & v1->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderLine(c, v0, v1); + v0->locked = 0; + v1->locked = 0; + count -= 2; + } while (count >= 0); +} + +// ---------------------------------------------------------------------------- + +static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c, + GLsizei count, const GLvoid *indices, int winding) +{ + // winding == 2 : fan + // winding == 1 : strip + + if (ggl_unlikely(count < 3)) + return; + + vertex_t * const v = c->vc.vBuffer; + vertex_t* v0 = v; + vertex_t* v1 = v+1; + vertex_t* v2; + + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); + c->arrays.compileElement(c, v0, read_index(type, indices)); + c->arrays.compileElement(c, v1, read_index(type, indices)); + count -= 2; + + // note: GCC 4.1.1 here makes a prety interesting optimization + // where it duplicates the loop below based on c->arrays.indicesType + + do { + v2 = fetch_vertex(c, read_index(type, indices)); + const uint32_t cc = v0->flags & v1->flags & v2->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderTriangle(c, v0, v1, v2); + vertex_t* & consumed = ((winding^=1) ? v1 : v0); + consumed->locked = 0; + consumed = v2; + count--; + } while (count); + v0->locked = v1->locked = 0; + v2->locked = 0; +} + +void drawIndexedPrimitivesTriangleStrip(ogles_context_t* c, + GLsizei count, const GLvoid *indices) { + drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 1); +} + +void drawIndexedPrimitivesTriangleFan(ogles_context_t* c, + GLsizei count, const GLvoid *indices) { + drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 2); +} + +void drawIndexedPrimitivesTriangles(ogles_context_t* c, + GLsizei count, const GLvoid *indices) +{ + if (ggl_unlikely(count < 3)) + return; + + count -= 3; + if (ggl_likely(c->arrays.indicesType == GL_UNSIGNED_SHORT)) { + // This case is probably our most common case... + uint16_t const * p = (uint16_t const *)indices; + do { + vertex_t* const v0 = fetch_vertex(c, *p++); + vertex_t* const v1 = fetch_vertex(c, *p++); + vertex_t* const v2 = fetch_vertex(c, *p++); + const uint32_t cc = v0->flags & v1->flags & v2->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderTriangle(c, v0, v1, v2); + v0->locked = 0; + v1->locked = 0; + v2->locked = 0; + count -= 3; + } while (count >= 0); + } else { + uint8_t const * p = (uint8_t const *)indices; + do { + vertex_t* const v0 = fetch_vertex(c, *p++); + vertex_t* const v1 = fetch_vertex(c, *p++); + vertex_t* const v2 = fetch_vertex(c, *p++); + const uint32_t cc = v0->flags & v1->flags & v2->flags; + if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) + c->prims.renderTriangle(c, v0, v1, v2); + v0->locked = 0; + v1->locked = 0; + v2->locked = 0; + count -= 3; + } while (count >= 0); + } +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Array compilers +#endif + +void compileElement__generic(ogles_context_t* c, + vertex_t* v, GLint first) +{ + v->flags = 0; + v->index = first; + first &= vertex_cache_t::INDEX_MASK; + const GLubyte* vp = c->arrays.vertex.element(first); + c->arrays.vertex.fetch(c, v->obj.v, vp); + c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj); + c->arrays.perspective(c, v); +} + +void compileElements__generic(ogles_context_t* c, + vertex_t* v, GLint first, GLsizei count) +{ + const GLubyte* vp = c->arrays.vertex.element( + first & vertex_cache_t::INDEX_MASK); + const size_t stride = c->arrays.vertex.stride; + transform_t const* const mvp = &c->transforms.mvp; + do { + v->flags = 0; + v->index = first++; + c->arrays.vertex.fetch(c, v->obj.v, vp); + c->arrays.mvp_transform(mvp, &v->clip, &v->obj); + c->arrays.perspective(c, v); + vp += stride; + v++; + } while (--count); +} + +/* +void compileElements__3x_full(ogles_context_t* c, + vertex_t* v, GLint first, GLsizei count) +{ + const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first); + const size_t stride = c->arrays.vertex.stride / 4; +// const GLfixed* const& m = c->transforms.mvp.matrix.m; + + GLfixed m[16]; + memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m)); + + do { + const GLfixed rx = vp[0]; + const GLfixed ry = vp[1]; + const GLfixed rz = vp[2]; + vp += stride; + v->index = first++; + v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); + v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); + v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); + v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); + + const GLfixed w = v->clip.w; + uint32_t clip = 0; + if (v->clip.x < -w) clip |= vertex_t::CLIP_L; + if (v->clip.x > w) clip |= vertex_t::CLIP_R; + if (v->clip.y < -w) clip |= vertex_t::CLIP_B; + if (v->clip.y > w) clip |= vertex_t::CLIP_T; + if (v->clip.z < -w) clip |= vertex_t::CLIP_N; + if (v->clip.z > w) clip |= vertex_t::CLIP_F; + v->flags = clip; + c->arrays.cull &= clip; + + //c->arrays.perspective(c, v); + v++; + } while (--count); +} +*/ + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark clippers +#endif + +static void clipVec4(vec4_t& nv, + GLfixed t, const vec4_t& s, const vec4_t& p) +{ + for (int i=0; i<4 ; i++) + nv.v[i] = gglMulAddx(t, s.v[i] - p.v[i], p.v[i], 28); +} + +static void clipVertex(ogles_context_t* c, vertex_t* nv, + GLfixed t, const vertex_t* s, const vertex_t* p) +{ + clipVec4(nv->clip, t, s->clip, p->clip); + nv->fog = gglMulAddx(t, s->fog - p->fog, p->fog, 28); + ogles_vertex_project(c, nv); + nv->flags |= vertex_t::LIT | vertex_t::EYE | vertex_t::TT; + nv->flags &= ~vertex_t::CLIP_ALL; +} + +static void clipVertexC(ogles_context_t* c, vertex_t* nv, + GLfixed t, const vertex_t* s, const vertex_t* p) +{ + clipVec4(nv->color, t, s->color, p->color); + clipVertex(c, nv, t, s, p); +} + +static void clipVertexT(ogles_context_t* c, vertex_t* nv, + GLfixed t, const vertex_t* s, const vertex_t* p) +{ + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (c->rasterizer.state.texture[i].enable) + clipVec4(nv->texture[i], t, s->texture[i], p->texture[i]); + } + clipVertex(c, nv, t, s, p); +} + +static void clipVertexAll(ogles_context_t* c, vertex_t* nv, + GLfixed t, const vertex_t* s, const vertex_t* p) +{ + clipVec4(nv->color, t, s->color, p->color); + clipVertexT(c, nv, t, s, p); +} + +static void clipEye(ogles_context_t* c, vertex_t* nv, + GLfixed t, const vertex_t* s, const vertex_t* p) +{ + nv->clear(); + c->arrays.clipVertex(c, nv, t, p, s); + clipVec4(nv->eye, t, s->eye, p->eye); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +void validate_arrays(ogles_context_t* c, GLenum mode) +{ + uint32_t enables = c->rasterizer.state.enables; + + // Perspective correction is not need if Ortho transform, but + // the user can still provide the w coordinate manually, so we can't + // automatically turn it off (in fact we could when the 4th coordinate + // is not spcified in the vertex array). + // W interpolation is never needed for points. + GLboolean perspective = + c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS); + c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective); + + // set anti-aliasing + GLboolean smooth = GL_FALSE; + switch (mode) { + case GL_POINTS: + smooth = c->point.smooth; + break; + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + smooth = c->line.smooth; + break; + } + if (((enables & GGL_ENABLE_AA)?1:0) != smooth) + c->rasterizer.procs.enableDisable(c, GGL_AA, smooth); + + // set the shade model for this primitive + c->rasterizer.procs.shadeModel(c, + (mode == GL_POINTS) ? GL_FLAT : c->lighting.shadeModel); + + // compute all the matrices we'll need... + uint32_t want = + transform_state_t::MVP | + transform_state_t::VIEWPORT; + if (c->lighting.enable) { // needs normal transforms and eye coords + want |= transform_state_t::MVUI; + want |= transform_state_t::MODELVIEW; + } + if (enables & GGL_ENABLE_TMUS) { // needs texture transforms + want |= transform_state_t::TEXTURE; + } + if (c->clipPlanes.enable) { // needs eye coords + want |= transform_state_t::MODELVIEW; + } + ogles_validate_transform(c, want); + + // textures... + if (enables & GGL_ENABLE_TMUS) + ogles_validate_texture(c); + + // vertex compilers + c->arrays.compileElement = compileElement__generic; + c->arrays.compileElements = compileElements__generic; + + // vertex transform + c->arrays.mvp_transform = + c->transforms.mvp.pointv[c->arrays.vertex.size - 2]; + + c->arrays.mv_transform = + c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2]; + + /* + * *********************************************************************** + * pick fetchers + * *********************************************************************** + */ + + array_machine_t& am = c->arrays; + am.vertex.fetch = fetchNop; + am.normal.fetch = currentNormal; + am.color.fetch = currentColor; + + if (am.vertex.enable) { + am.vertex.resolve(); + if (am.vertex.bo || am.vertex.pointer) { + am.vertex.fetch = vertex_fct[am.vertex.size-2][am.vertex.type & 0xF]; + } + } + + if (am.normal.enable) { + am.normal.resolve(); + if (am.normal.bo || am.normal.pointer) { + am.normal.fetch = normal_fct[am.normal.size-3][am.normal.type & 0xF]; + } + } + + if (am.color.enable) { + am.color.resolve(); + if (c->lighting.enable) { + if (am.color.bo || am.color.pointer) { + am.color.fetch = color_fct[am.color.size-3][am.color.type & 0xF]; + } + } else { + if (am.color.bo || am.color.pointer) { + am.color.fetch = color_clamp_fct[am.color.size-3][am.color.type & 0xF]; + } + } + } + + int activeTmuCount = 0; + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + am.texture[i].fetch = currentTexCoord; + if (c->rasterizer.state.texture[i].enable) { + + // texture fetchers... + if (am.texture[i].enable) { + am.texture[i].resolve(); + if (am.texture[i].bo || am.texture[i].pointer) { + am.texture[i].fetch = texture_fct[am.texture[i].size-2][am.texture[i].type & 0xF]; + } + } + + // texture transform... + const int index = c->arrays.texture[i].size - 2; + c->arrays.tex_transform[i] = + c->transforms.texture[i].transform.pointv[index]; + + am.tmu = i; + activeTmuCount++; + } + } + + // pick the vertex-clipper + uint32_t clipper = 0; + // we must reload 'enables' here + enables = c->rasterizer.state.enables; + if (enables & GGL_ENABLE_SMOOTH) + clipper |= 1; // we need to interpolate colors + if (enables & GGL_ENABLE_TMUS) + clipper |= 2; // we need to interpolate textures + switch (clipper) { + case 0: c->arrays.clipVertex = clipVertex; break; + case 1: c->arrays.clipVertex = clipVertexC; break; + case 2: c->arrays.clipVertex = clipVertexT; break; + case 3: c->arrays.clipVertex = clipVertexAll; break; + } + c->arrays.clipEye = clipEye; + + // pick the primitive rasterizer + ogles_validate_primitives(c); +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + +#if 0 +#pragma mark - +#pragma mark array API +#endif + +void glVertexPointer( + GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + ogles_context_t* c = ogles_context_t::get(); + if (size<2 || size>4 || stride<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + switch (type) { + case GL_BYTE: + case GL_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->arrays.vertex.init(size, type, stride, pointer, c->arrays.array_buffer, 0); +} + +void glColorPointer( + GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + ogles_context_t* c = ogles_context_t::get(); + // in theory ogles doesn't allow color arrays of size 3 + // but it is very useful to 'visualize' the normal array. + if (size<3 || size>4 || stride<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_FIXED: + case GL_FLOAT: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->arrays.color.init(size, type, stride, pointer, c->arrays.array_buffer, 0); +} + +void glNormalPointer( + GLenum type, GLsizei stride, const GLvoid *pointer) +{ + ogles_context_t* c = ogles_context_t::get(); + if (stride<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + switch (type) { + case GL_BYTE: + case GL_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->arrays.normal.init(3, type, stride, pointer, c->arrays.array_buffer, 0); +} + +void glTexCoordPointer( + GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + ogles_context_t* c = ogles_context_t::get(); + if (size<2 || size>4 || stride<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + switch (type) { + case GL_BYTE: + case GL_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + const int tmu = c->arrays.activeTexture; + c->arrays.texture[tmu].init(size, type, stride, pointer, + c->arrays.array_buffer, 0); +} + + +void glEnableClientState(GLenum array) { + ogles_context_t* c = ogles_context_t::get(); + enableDisableClientState(c, array, true); +} + +void glDisableClientState(GLenum array) { + ogles_context_t* c = ogles_context_t::get(); + enableDisableClientState(c, array, false); +} + +void glClientActiveTexture(GLenum texture) +{ + ogles_context_t* c = ogles_context_t::get(); + if (texture<GL_TEXTURE0 || texture>=GL_TEXTURE0+GGL_TEXTURE_UNIT_COUNT) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->arrays.activeTexture = texture - GL_TEXTURE0; +} + +void glDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + ogles_context_t* c = ogles_context_t::get(); + if (count<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + switch (mode) { + case GL_POINTS: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + case GL_LINES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + case GL_TRIANGLES: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + + if (count == 0 || !c->arrays.vertex.enable) + return; + if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK)) + return; // all triangles are culled + + validate_arrays(c, mode); + drawArraysPrims[mode](c, first, count); + +#if VC_CACHE_STATISTICS + c->vc.total = count; + c->vc.dump_stats(mode); +#endif +} + +void glDrawElements( + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) +{ + ogles_context_t* c = ogles_context_t::get(); + if (count<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + switch (mode) { + case GL_POINTS: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + case GL_LINES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + case GL_TRIANGLES: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + c->arrays.indicesType = type; + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (count == 0 || !c->arrays.vertex.enable) + return; + if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK)) + return; // all triangles are culled + + // clear the vertex-cache + c->vc.clear(); + validate_arrays(c, mode); + + // if indices are in a buffer object, the pointer is treated as an + // offset in that buffer. + if (c->arrays.element_array_buffer) { + indices = c->arrays.element_array_buffer->data + uintptr_t(indices); + } + + drawElementsPrims[mode](c, count, indices); + +#if VC_CACHE_STATISTICS + c->vc.total = count; + c->vc.dump_stats(mode); +#endif +} + +// ---------------------------------------------------------------------------- +// buffers +// ---------------------------------------------------------------------------- + +void glBindBuffer(GLenum target, GLuint buffer) +{ + ogles_context_t* c = ogles_context_t::get(); + if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + // create a buffer object, or bind an existing one + buffer_t const* bo = 0; + if (buffer) { + bo = c->bufferObjectManager->bind(buffer); + if (!bo) { + ogles_error(c, GL_OUT_OF_MEMORY); + return; + } + } + ((target == GL_ARRAY_BUFFER) ? + c->arrays.array_buffer : c->arrays.element_array_buffer) = bo; +} + +void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ + ogles_context_t* c = ogles_context_t::get(); + if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (size<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if ((usage!=GL_STATIC_DRAW) && (usage!=GL_DYNAMIC_DRAW)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + c->arrays.array_buffer : c->arrays.element_array_buffer); + + if (bo == 0) { + // can't modify buffer 0 + ogles_error(c, GL_INVALID_OPERATION); + return; + } + + buffer_t* edit_bo = const_cast<buffer_t*>(bo); + if (c->bufferObjectManager->allocateStore(edit_bo, size, usage) != 0) { + ogles_error(c, GL_OUT_OF_MEMORY); + return; + } + if (data) { + memcpy(bo->data, data, size); + } +} + +void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +{ + ogles_context_t* c = ogles_context_t::get(); + if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (offset<0 || size<0 || data==0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + c->arrays.array_buffer : c->arrays.element_array_buffer); + + if (bo == 0) { + // can't modify buffer 0 + ogles_error(c, GL_INVALID_OPERATION); + return; + } + if (offset+size > bo->size) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + memcpy(bo->data + offset, data, size); +} + +void glDeleteBuffers(GLsizei n, const GLuint* buffers) +{ + ogles_context_t* c = ogles_context_t::get(); + if (n<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + for (int i=0 ; i<n ; i++) { + GLuint name = buffers[i]; + if (name) { + // unbind bound deleted buffers... + if (c->arrays.element_array_buffer->name == name) { + c->arrays.element_array_buffer = 0; + } + if (c->arrays.array_buffer->name == name) { + c->arrays.array_buffer = 0; + } + if (c->arrays.vertex.bo->name == name) { + c->arrays.vertex.bo = 0; + } + if (c->arrays.normal.bo->name == name) { + c->arrays.normal.bo = 0; + } + if (c->arrays.color.bo->name == name) { + c->arrays.color.bo = 0; + } + for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) { + if (c->arrays.texture[t].bo->name == name) { + c->arrays.texture[t].bo = 0; + } + } + } + } + c->bufferObjectManager->deleteBuffers(n, buffers); + c->bufferObjectManager->recycleTokens(n, buffers); +} + +void glGenBuffers(GLsizei n, GLuint* buffers) +{ + ogles_context_t* c = ogles_context_t::get(); + if (n<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + c->bufferObjectManager->getToken(n, buffers); +} diff --git a/opengl/libagl/array.h b/opengl/libagl/array.h new file mode 100644 index 0000000..e156978 --- /dev/null +++ b/opengl/libagl/array.h @@ -0,0 +1,37 @@ +/* libs/opengles/array.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_ARRAY_H +#define ANDROID_OPENGLES_ARRAY_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +namespace android { + +namespace gl { +struct ogles_context_t; +}; + +void ogles_init_array(ogles_context_t* c); +void ogles_uninit_array(ogles_context_t* c); + +}; // namespace android + +#endif // ANDROID_OPENGLES_ARRAY_H + diff --git a/opengl/libagl/context.h b/opengl/libagl/context.h new file mode 100644 index 0000000..ef36b56 --- /dev/null +++ b/opengl/libagl/context.h @@ -0,0 +1,20 @@ +/* libs/opengles/context.h +** +** Copyright 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. +*/ + +#include <private/opengles/gl_context.h> + +using namespace android::gl; diff --git a/opengl/libagl/dxt.cpp b/opengl/libagl/dxt.cpp new file mode 100644 index 0000000..238c81f --- /dev/null +++ b/opengl/libagl/dxt.cpp @@ -0,0 +1,636 @@ +/* libs/opengles/dxt.cpp +** +** Copyright 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. +*/ + +#define TIMING 0 + +#if TIMING +#include <sys/time.h> // for optimization timing +#include <stdio.h> +#include <stdlib.h> +#endif + +#include <GLES/gl.h> +#include <utils/Endian.h> + +#include "context.h" + +#define TIMING 0 + +namespace android { + +static uint8_t avg23tab[64*64]; +static volatile int tables_initialized = 0; + +// Definitions below are equivalent to these over the valid range of arguments +// #define div5(x) ((x)/5) +// #define div7(x) ((x)/7) + +// Use fixed-point to divide by 5 and 7 +// 3277 = 2^14/5 + 1 +// 2341 = 2^14/7 + 1 +#define div5(x) (((x)*3277) >> 14) +#define div7(x) (((x)*2341) >> 14) + +// Table with entry [a << 6 | b] = (2*a + b)/3 for 0 <= a,b < 64 +#define avg23(x0,x1) avg23tab[((x0) << 6) | (x1)] + +// Extract 5/6/5 RGB +#define red(x) (((x) >> 11) & 0x1f) +#define green(x) (((x) >> 5) & 0x3f) +#define blue(x) ( (x) & 0x1f) + +/* + * Convert 5/6/5 RGB (as 3 ints) to 8/8/8 + * + * Operation count: 8 <<, 0 &, 5 | + */ +inline static int rgb565SepTo888(int r, int g, int b) + +{ + return ((((r << 3) | (r >> 2)) << 16) | + (((g << 2) | (g >> 4)) << 8) | + ((b << 3) | (b >> 2))); +} + +/* + * Convert 5/6/5 RGB (as a single 16-bit word) to 8/8/8 + * + * r4r3r2r1 r0g5g4g3 g2g1g0b4 b3b2b1b0 rgb + * r4r3r2 r1r0g5g4 g3g2g1g0 b4b3b2b1 b0 0 0 0 rgb << 3 + * r4r3r2r1 r0r4r3r2 g5g4g3g2 g1g0g5g4 b4b3b2b1 b0b4b3b2 desired result + * + * Construct the 24-bit RGB word as: + * + * r4r3r2r1 r0------ -------- -------- -------- -------- (rgb << 8) & 0xf80000 + * r4r3r2 -------- -------- -------- -------- (rgb << 3) & 0x070000 + * g5g4g3g2 g1g0---- -------- -------- (rgb << 5) & 0x00fc00 + * g5g4 -------- -------- (rgb >> 1) & 0x000300 + * b4b3b2b1 b0------ (rgb << 3) & 0x0000f8 + * b4b3b2 (rgb >> 2) & 0x000007 + * + * Operation count: 5 <<, 6 &, 5 | (n.b. rgb >> 3 is used twice) + */ +inline static int rgb565To888(int rgb) + +{ + int rgb3 = rgb >> 3; + return (((rgb << 8) & 0xf80000) | + ( rgb3 & 0x070000) | + ((rgb << 5) & 0x00fc00) | + ((rgb >> 1) & 0x000300) | + ( rgb3 & 0x0000f8) | + ((rgb >> 2) & 0x000007)); +} + +#if __BYTE_ORDER == __BIG_ENDIAN +static uint32_t swap(uint32_t x) { + int b0 = (x >> 24) & 0xff; + int b1 = (x >> 16) & 0xff; + int b2 = (x >> 8) & 0xff; + int b3 = (x ) & 0xff; + + return (uint32_t)((b3 << 24) | (b2 << 16) | (b1 << 8) | b0); +} +#endif + +static void +init_tables() +{ + if (tables_initialized) { + return; + } + + for (int i = 0; i < 64; i++) { + for (int j = 0; j < 64; j++) { + int avg = (2*i + j)/3; + avg23tab[(i << 6) | j] = avg; + } + } + + asm volatile ("" : : : "memory"); + tables_initialized = 1; +} + +/* + * Utility to scan a DXT1 compressed texture to determine whether it + * contains a transparent pixel (color0 < color1, code == 3). This + * may be useful if the application lacks information as to whether + * the true format is GL_COMPRESSED_RGB_S3TC_DXT1_EXT or + * GL_COMPRESSED_RGBA_S3TC_DXT1_EXT. + */ +bool +DXT1HasAlpha(const GLvoid *data, int width, int height) { +#if TIMING + struct timeval start_t, end_t; + struct timezone tz; + + gettimeofday(&start_t, &tz); +#endif + + bool hasAlpha = false; + + int xblocks = (width + 3)/4; + int yblocks = (height + 3)/4; + int numblocks = xblocks*yblocks; + + uint32_t const *d32 = (uint32_t *)data; + for (int b = 0; b < numblocks; b++) { + uint32_t colors = *d32++; + +#if __BYTE_ORDER == __BIG_ENDIAN + colors = swap(colors); +#endif + + uint16_t color0 = colors & 0xffff; + uint16_t color1 = colors >> 16; + + if (color0 < color1) { + // There's no need to endian-swap within 'bits' + // since we don't care which pixel is the transparent one + uint32_t bits = *d32++; + + // Detect if any (odd, even) pair of bits are '11' + // bits: b31 b30 b29 ... b3 b2 b1 b0 + // bits >> 1: b31 b31 b30 ... b4 b3 b2 b1 + // &: b31 (b31 & b30) (b29 & b28) ... (b2 & b1) (b1 & b0) + // & 0x55..: 0 (b31 & b30) 0 ... 0 (b1 & b0) + if (((bits & (bits >> 1)) & 0x55555555) != 0) { + hasAlpha = true; + goto done; + } + } else { + // Skip 4 bytes + ++d32; + } + } + + done: +#if TIMING + gettimeofday(&end_t, &tz); + long usec = (end_t.tv_sec - start_t.tv_sec)*1000000 + + (end_t.tv_usec - start_t.tv_usec); + + printf("Scanned w=%d h=%d in %ld usec\n", width, height, usec); +#endif + + return hasAlpha; +} + +static void +decodeDXT1(const GLvoid *data, int width, int height, + void *surface, int stride, + bool hasAlpha) + +{ + init_tables(); + + uint32_t const *d32 = (uint32_t *)data; + + // Color table for the current block + uint16_t c[4]; + c[0] = c[1] = c[2] = c[3] = 0; + + // Specified colors from the previous block + uint16_t prev_color0 = 0x0000; + uint16_t prev_color1 = 0x0000; + + uint16_t* rowPtr = (uint16_t*)surface; + for (int base_y = 0; base_y < height; base_y += 4, rowPtr += 4*stride) { + uint16_t *blockPtr = rowPtr; + for (int base_x = 0; base_x < width; base_x += 4, blockPtr += 4) { + uint32_t colors = *d32++; + uint32_t bits = *d32++; + +#if __BYTE_ORDER == __BIG_ENDIAN + colors = swap(colors); + bits = swap(bits); +#endif + + // Raw colors + uint16_t color0 = colors & 0xffff; + uint16_t color1 = colors >> 16; + + // If the new block has the same base colors as the + // previous one, we don't need to recompute the color + // table c[] + if (color0 != prev_color0 || color1 != prev_color1) { + // Store raw colors for comparison with next block + prev_color0 = color0; + prev_color1 = color1; + + int r0 = red(color0); + int g0 = green(color0); + int b0 = blue(color0); + + int r1 = red(color1); + int g1 = green(color1); + int b1 = blue(color1); + + if (hasAlpha) { + c[0] = (r0 << 11) | ((g0 >> 1) << 6) | (b0 << 1) | 0x1; + c[1] = (r1 << 11) | ((g1 >> 1) << 6) | (b1 << 1) | 0x1; + } else { + c[0] = color0; + c[1] = color1; + } + + int r2, g2, b2, r3, g3, b3, a3; + + int bbits = bits >> 1; + bool has2 = ((bbits & ~bits) & 0x55555555) != 0; + bool has3 = ((bbits & bits) & 0x55555555) != 0; + + if (has2 || has3) { + if (color0 > color1) { + r2 = avg23(r0, r1); + g2 = avg23(g0, g1); + b2 = avg23(b0, b1); + + r3 = avg23(r1, r0); + g3 = avg23(g1, g0); + b3 = avg23(b1, b0); + a3 = 1; + } else { + r2 = (r0 + r1) >> 1; + g2 = (g0 + g1) >> 1; + b2 = (b0 + b1) >> 1; + + r3 = g3 = b3 = a3 = 0; + } + if (hasAlpha) { + c[2] = (r2 << 11) | ((g2 >> 1) << 6) | + (b2 << 1) | 0x1; + c[3] = (r3 << 11) | ((g3 >> 1) << 6) | + (b3 << 1) | a3; + } else { + c[2] = (r2 << 11) | (g2 << 5) | b2; + c[3] = (r3 << 11) | (g3 << 5) | b3; + } + } + } + + uint16_t* blockRowPtr = blockPtr; + for (int y = 0; y < 4; y++, blockRowPtr += stride) { + // Don't process rows past the botom + if (base_y + y >= height) { + break; + } + + int w = min(width - base_x, 4); + for (int x = 0; x < w; x++) { + int code = bits & 0x3; + bits >>= 2; + + blockRowPtr[x] = c[code]; + } + } + } + } +} + +// Output data as internalformat=GL_RGBA, type=GL_UNSIGNED_BYTE +static void +decodeDXT3(const GLvoid *data, int width, int height, + void *surface, int stride) + +{ + init_tables(); + + uint32_t const *d32 = (uint32_t *)data; + + // Specified colors from the previous block + uint16_t prev_color0 = 0x0000; + uint16_t prev_color1 = 0x0000; + + // Color table for the current block + uint32_t c[4]; + c[0] = c[1] = c[2] = c[3] = 0; + + uint32_t* rowPtr = (uint32_t*)surface; + for (int base_y = 0; base_y < height; base_y += 4, rowPtr += 4*stride) { + uint32_t *blockPtr = rowPtr; + for (int base_x = 0; base_x < width; base_x += 4, blockPtr += 4) { + +#if __BYTE_ORDER == __BIG_ENDIAN + uint32_t alphahi = *d32++; + uint32_t alphalo = *d32++; + alphahi = swap(alphahi); + alphalo = swap(alphalo); +#else + uint32_t alphalo = *d32++; + uint32_t alphahi = *d32++; +#endif + + uint32_t colors = *d32++; + uint32_t bits = *d32++; + +#if __BYTE_ORDER == __BIG_ENDIAN + colors = swap(colors); + bits = swap(bits); +#endif + + uint64_t alpha = ((uint64_t)alphahi << 32) | alphalo; + + // Raw colors + uint16_t color0 = colors & 0xffff; + uint16_t color1 = colors >> 16; + + // If the new block has the same base colors as the + // previous one, we don't need to recompute the color + // table c[] + if (color0 != prev_color0 || color1 != prev_color1) { + // Store raw colors for comparison with next block + prev_color0 = color0; + prev_color1 = color1; + + int bbits = bits >> 1; + bool has2 = ((bbits & ~bits) & 0x55555555) != 0; + bool has3 = ((bbits & bits) & 0x55555555) != 0; + + if (has2 || has3) { + int r0 = red(color0); + int g0 = green(color0); + int b0 = blue(color0); + + int r1 = red(color1); + int g1 = green(color1); + int b1 = blue(color1); + + int r2 = avg23(r0, r1); + int g2 = avg23(g0, g1); + int b2 = avg23(b0, b1); + + int r3 = avg23(r1, r0); + int g3 = avg23(g1, g0); + int b3 = avg23(b1, b0); + + c[0] = rgb565SepTo888(r0, g0, b0); + c[1] = rgb565SepTo888(r1, g1, b1); + c[2] = rgb565SepTo888(r2, g2, b2); + c[3] = rgb565SepTo888(r3, g3, b3); + } else { + // Convert to 8 bits + c[0] = rgb565To888(color0); + c[1] = rgb565To888(color1); + } + } + + uint32_t* blockRowPtr = blockPtr; + for (int y = 0; y < 4; y++, blockRowPtr += stride) { + // Don't process rows past the botom + if (base_y + y >= height) { + break; + } + + int w = min(width - base_x, 4); + for (int x = 0; x < w; x++) { + int a = alpha & 0xf; + alpha >>= 4; + + int code = bits & 0x3; + bits >>= 2; + + blockRowPtr[x] = c[code] | (a << 28) | (a << 24); + } + } + } + } +} + +// Output data as internalformat=GL_RGBA, type=GL_UNSIGNED_BYTE +static void +decodeDXT5(const GLvoid *data, int width, int height, + void *surface, int stride) + +{ + init_tables(); + + uint32_t const *d32 = (uint32_t *)data; + + // Specified alphas from the previous block + uint8_t prev_alpha0 = 0x00; + uint8_t prev_alpha1 = 0x00; + + // Specified colors from the previous block + uint16_t prev_color0 = 0x0000; + uint16_t prev_color1 = 0x0000; + + // Alpha table for the current block + uint8_t a[8]; + a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = 0; + + // Color table for the current block + uint32_t c[4]; + c[0] = c[1] = c[2] = c[3] = 0; + + int good_a5 = 0; + int bad_a5 = 0; + int good_a6 = 0; + int bad_a6 = 0; + int good_a7 = 0; + int bad_a7 = 0; + + uint32_t* rowPtr = (uint32_t*)surface; + for (int base_y = 0; base_y < height; base_y += 4, rowPtr += 4*stride) { + uint32_t *blockPtr = rowPtr; + for (int base_x = 0; base_x < width; base_x += 4, blockPtr += 4) { + +#if __BYTE_ORDER == __BIG_ENDIAN + uint32_t alphahi = *d32++; + uint32_t alphalo = *d32++; + alphahi = swap(alphahi); + alphalo = swap(alphalo); +#else + uint32_t alphalo = *d32++; + uint32_t alphahi = *d32++; +#endif + + uint32_t colors = *d32++; + uint32_t bits = *d32++; + +#if __BYTE_ORDER == __BIG_ENDIANx + colors = swap(colors); + bits = swap(bits); +#endif + + uint64_t alpha = ((uint64_t)alphahi << 32) | alphalo; + uint64_t alpha0 = alpha & 0xff; + alpha >>= 8; + uint64_t alpha1 = alpha & 0xff; + alpha >>= 8; + + if (alpha0 != prev_alpha0 || alpha1 != prev_alpha1) { + prev_alpha0 = alpha0; + prev_alpha1 = alpha1; + + a[0] = alpha0; + a[1] = alpha1; + int a01 = alpha0 + alpha1 - 1; + if (alpha0 > alpha1) { + a[2] = div7(6*alpha0 + alpha1); + a[4] = div7(4*alpha0 + 3*alpha1); + a[6] = div7(2*alpha0 + 5*alpha1); + + // Use symmetry to derive half of the values + // A few values will be off by 1 (~.5%) + // Alternate which values are computed directly + // and which are derived to try to reduce bias + a[3] = a01 - a[6]; + a[5] = a01 - a[4]; + a[7] = a01 - a[2]; + } else { + a[2] = div5(4*alpha0 + alpha1); + a[4] = div5(2*alpha0 + 3*alpha1); + a[3] = a01 - a[4]; + a[5] = a01 - a[2]; + a[6] = 0x00; + a[7] = 0xff; + } + } + + // Raw colors + uint16_t color0 = colors & 0xffff; + uint16_t color1 = colors >> 16; + + // If the new block has the same base colors as the + // previous one, we don't need to recompute the color + // table c[] + if (color0 != prev_color0 || color1 != prev_color1) { + // Store raw colors for comparison with next block + prev_color0 = color0; + prev_color1 = color1; + + int bbits = bits >> 1; + bool has2 = ((bbits & ~bits) & 0x55555555) != 0; + bool has3 = ((bbits & bits) & 0x55555555) != 0; + + if (has2 || has3) { + int r0 = red(color0); + int g0 = green(color0); + int b0 = blue(color0); + + int r1 = red(color1); + int g1 = green(color1); + int b1 = blue(color1); + + int r2 = avg23(r0, r1); + int g2 = avg23(g0, g1); + int b2 = avg23(b0, b1); + + int r3 = avg23(r1, r0); + int g3 = avg23(g1, g0); + int b3 = avg23(b1, b0); + + c[0] = rgb565SepTo888(r0, g0, b0); + c[1] = rgb565SepTo888(r1, g1, b1); + c[2] = rgb565SepTo888(r2, g2, b2); + c[3] = rgb565SepTo888(r3, g3, b3); + } else { + // Convert to 8 bits + c[0] = rgb565To888(color0); + c[1] = rgb565To888(color1); + } + } + + uint32_t* blockRowPtr = blockPtr; + for (int y = 0; y < 4; y++, blockRowPtr += stride) { + // Don't process rows past the botom + if (base_y + y >= height) { + break; + } + + int w = min(width - base_x, 4); + for (int x = 0; x < w; x++) { + int acode = alpha & 0x7; + alpha >>= 3; + + int code = bits & 0x3; + bits >>= 2; + + blockRowPtr[x] = c[code] | (a[acode] << 24); + } + } + } + } +} + +/* + * Decode a DXT-compressed texture into memory. DXT textures consist of + * a series of 4x4 pixel blocks in left-to-right, top-down order. + * The number of blocks is given by ceil(width/4)*ceil(height/4). + * + * 'data' points to the texture data. 'width' and 'height' indicate the + * dimensions of the texture. We assume width and height are >= 0 but + * do not require them to be powers of 2 or divisible by any factor. + * + * The output is written to 'surface' with each scanline separated by + * 'stride' 2- or 4-byte words. + * + * 'format' indicates the type of compression and must be one of the following: + * + * GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + * The output is written as 5/6/5 opaque RGB (16 bit words). + * 8 bytes are read from 'data' for each block. + * + * GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + * The output is written as 5/5/5/1 RGBA (16 bit words) + * 8 bytes are read from 'data' for each block. + * + * GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + * GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + * The output is written as 8/8/8/8 ARGB (32 bit words) + * 16 bytes are read from 'data' for each block. + */ +void +decodeDXT(const GLvoid *data, int width, int height, + void *surface, int stride, int format) +{ +#if TIMING + struct timeval start_t, end_t; + struct timezone tz; + + gettimeofday(&start_t, &tz); +#endif + + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + decodeDXT1(data, width, height, surface, stride, false); + break; + + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + decodeDXT1(data, width, height, surface, stride, true); + break; + + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + decodeDXT3(data, width, height, surface, stride); + break; + + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + decodeDXT5(data, width, height, surface, stride); + break; + } + +#if TIMING + gettimeofday(&end_t, &tz); + long usec = (end_t.tv_sec - start_t.tv_sec)*1000000 + + (end_t.tv_usec - start_t.tv_usec); + + printf("Loaded w=%d h=%d in %ld usec\n", width, height, usec); +#endif +} + +} // namespace android diff --git a/opengl/libagl/dxt.h b/opengl/libagl/dxt.h new file mode 100644 index 0000000..d95a36c --- /dev/null +++ b/opengl/libagl/dxt.h @@ -0,0 +1,33 @@ +/* libs/opengles/dxt.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_TEXTURE_H +#define ANDROID_OPENGLES_TEXTURE_H + +#include <stdlib.h> + +#include <GLES/gl.h> + +namespace android { + + bool DXT1HasAlpha(const GLvoid *data, int width, int height); + void decodeDXT(const GLvoid *data, int width, int height, + void *surface, int stride, int format); + +} // namespace android + +#endif // ANDROID_OPENGLES_TEXTURE_H diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp new file mode 100644 index 0000000..854a49e --- /dev/null +++ b/opengl/libagl/egl.cpp @@ -0,0 +1,1513 @@ +/* +** +** Copyright 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. +*/ + +#define LOG_TAG "EGL" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/mman.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> + +#include <utils/threads.h> + +#include <GLES/egl.h> + +#include <pixelflinger/format.h> + +#include "context.h" +#include "state.h" +#include "texture.h" +#include "matrix.h" + +#undef NELEM +#define NELEM(x) (sizeof(x)/sizeof(*(x))) + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +const unsigned int NUM_DISPLAYS = 1; + +static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t gEGLErrorKey = -1; +#ifndef HAVE_ANDROID_OS +namespace gl { +pthread_key_t gGLKey = -1; +}; // namspace gl +#endif + +template<typename T> +static T setError(GLint error, T returnValue) { + if (ggl_unlikely(gEGLErrorKey == -1)) { + pthread_mutex_lock(&gErrorKeyMutex); + if (gEGLErrorKey == -1) + pthread_key_create(&gEGLErrorKey, NULL); + pthread_mutex_unlock(&gErrorKeyMutex); + } + pthread_setspecific(gEGLErrorKey, (void*)error); + return returnValue; +} + +static GLint getError() { + if (ggl_unlikely(gEGLErrorKey == -1)) + return EGL_SUCCESS; + GLint error = (GLint)pthread_getspecific(gEGLErrorKey); + pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS); + return error; +} + +// ---------------------------------------------------------------------------- + +struct egl_display_t +{ + egl_display_t() : type(0), initialized(0) { } + + static egl_display_t& get_display(EGLDisplay dpy); + + static EGLBoolean is_valid(EGLDisplay dpy) { + return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; + } + + NativeDisplayType type; + volatile int32_t initialized; +}; + +static egl_display_t gDisplays[NUM_DISPLAYS]; + +egl_display_t& egl_display_t::get_display(EGLDisplay dpy) { + return gDisplays[uintptr_t(dpy)-1U]; +} + +struct egl_context_t { + enum { + IS_CURRENT = 0x00010000, + NEVER_CURRENT = 0x00020000 + }; + uint32_t flags; + EGLDisplay dpy; + EGLConfig config; + EGLSurface read; + EGLSurface draw; + + static inline egl_context_t* context(EGLContext ctx) { + ogles_context_t* const gl = static_cast<ogles_context_t*>(ctx); + return static_cast<egl_context_t*>(gl->rasterizer.base); + } +}; + +// ---------------------------------------------------------------------------- + +struct egl_surface_t +{ + enum { + PAGE_FLIP = 0x00000001, + MAGIC = 0x31415265 + }; + + uint32_t magic; + EGLDisplay dpy; + EGLConfig config; + EGLContext ctx; + + egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); + virtual ~egl_surface_t(); + virtual bool isValid() const = 0; + + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; + virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; + virtual EGLint getWidth() const = 0; + virtual EGLint getHeight() const = 0; + virtual void* getBits() const = 0; + + virtual EGLint getHorizontalResolution() const; + virtual EGLint getVerticalResolution() const; + virtual EGLint getRefreshRate() const; + virtual EGLint getSwapBehavior() const; + virtual EGLBoolean swapBuffers(); + virtual EGLBoolean swapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); +protected: + GGLSurface depth; +}; + +egl_surface_t::egl_surface_t(EGLDisplay dpy, + EGLConfig config, + int32_t depthFormat) + : magic(0x31415265), dpy(dpy), config(config), ctx(0) +{ + depth.version = sizeof(GGLSurface); + depth.data = 0; + depth.format = depthFormat; +} +egl_surface_t::~egl_surface_t() +{ + magic = 0; + free(depth.data); +} +EGLBoolean egl_surface_t::swapBuffers() { + return EGL_FALSE; +} +EGLBoolean egl_surface_t::swapRectangle( + EGLint l, EGLint t, EGLint w, EGLint h) { + return EGL_FALSE; +} +EGLint egl_surface_t::getHorizontalResolution() const { + return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); +} +EGLint egl_surface_t::getVerticalResolution() const { + return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); +} +EGLint egl_surface_t::getRefreshRate() const { + return (60 * EGL_DISPLAY_SCALING); +} +EGLint egl_surface_t::getSwapBehavior() const { + return EGL_BUFFER_PRESERVED; +} + +// ---------------------------------------------------------------------------- + +struct egl_window_surface_t : public egl_surface_t +{ + egl_window_surface_t( + EGLDisplay dpy, EGLConfig config, + int32_t depthFormat, + egl_native_window_t* window); + + ~egl_window_surface_t(); + + virtual bool isValid() const { return nativeWindow->magic == 0x600913; } + virtual EGLBoolean swapBuffers(); + virtual EGLBoolean swapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); + virtual EGLBoolean bindReadSurface(ogles_context_t* gl); + virtual EGLint getWidth() const { return nativeWindow->width; } + virtual EGLint getHeight() const { return nativeWindow->height; } + virtual void* getBits() const; + virtual EGLint getHorizontalResolution() const; + virtual EGLint getVerticalResolution() const; + virtual EGLint getRefreshRate() const; + virtual EGLint getSwapBehavior() const; +private: + egl_native_window_t* nativeWindow; +}; + +egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, + EGLConfig config, + int32_t depthFormat, + egl_native_window_t* window) + : egl_surface_t(dpy, config, depthFormat), nativeWindow(window) +{ + if (depthFormat) { + depth.width = window->width; + depth.height = window->height; + depth.stride = depth.width; // use the width here + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return; + } + } + nativeWindow->incRef(nativeWindow); +} +egl_window_surface_t::~egl_window_surface_t() { + nativeWindow->decRef(nativeWindow); +} + +EGLBoolean egl_window_surface_t::swapBuffers() +{ + uint32_t flags = nativeWindow->swapBuffers(nativeWindow); + if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) { + // TODO: we probaly should reset the swap rect here + // if the window size has changed + // window->setSwapRectangle(Rect(info.w, info.h)); + if (depth.data) { + free(depth.data); + depth.width = nativeWindow->width; + depth.height = nativeWindow->height; + depth.stride = nativeWindow->stride; + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return EGL_FALSE; + } + } + } + return EGL_TRUE; +} + +EGLBoolean egl_window_surface_t::swapRectangle( + EGLint l, EGLint t, EGLint w, EGLint h) +{ + nativeWindow->setSwapRectangle(nativeWindow, l, t, w, h); + return EGL_TRUE; +} +EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl) +{ + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = nativeWindow->width; + buffer.height = nativeWindow->height; + buffer.stride = nativeWindow->stride; + buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; + buffer.format = nativeWindow->format; + gl->rasterizer.procs.colorBuffer(gl, &buffer); + if (depth.data != gl->rasterizer.state.buffers.depth.data) + gl->rasterizer.procs.depthBuffer(gl, &depth); + return EGL_TRUE; +} +EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl) +{ + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = nativeWindow->width; + buffer.height = nativeWindow->height; + buffer.stride = nativeWindow->stride; + buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; + buffer.format = nativeWindow->format; + gl->rasterizer.procs.readBuffer(gl, &buffer); + return EGL_TRUE; +} +void* egl_window_surface_t::getBits() const { + return (GGLubyte*)nativeWindow->base + nativeWindow->offset; +} +EGLint egl_window_surface_t::getHorizontalResolution() const { + return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); +} +EGLint egl_window_surface_t::getVerticalResolution() const { + return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); +} +EGLint egl_window_surface_t::getRefreshRate() const { + return (nativeWindow->fps * EGL_DISPLAY_SCALING); +} +EGLint egl_window_surface_t::getSwapBehavior() const { + uint32_t flags = nativeWindow->flags; + if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER) + return EGL_BUFFER_DESTROYED; + return EGL_BUFFER_PRESERVED; +} + +// ---------------------------------------------------------------------------- + +struct egl_pixmap_surface_t : public egl_surface_t +{ + egl_pixmap_surface_t( + EGLDisplay dpy, EGLConfig config, + int32_t depthFormat, + egl_native_pixmap_t const * pixmap); + + virtual ~egl_pixmap_surface_t() { } + + virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); + virtual EGLBoolean bindReadSurface(ogles_context_t* gl); + virtual EGLint getWidth() const { return nativePixmap.width; } + virtual EGLint getHeight() const { return nativePixmap.height; } + virtual void* getBits() const { return nativePixmap.data; } +private: + egl_native_pixmap_t nativePixmap; +}; + +egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy, + EGLConfig config, + int32_t depthFormat, + egl_native_pixmap_t const * pixmap) + : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap) +{ + if (depthFormat) { + depth.width = pixmap->width; + depth.height = pixmap->height; + depth.stride = depth.width; // use the width here + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return; + } + } +} +EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl) +{ + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = nativePixmap.width; + buffer.height = nativePixmap.height; + buffer.stride = nativePixmap.stride; + buffer.data = nativePixmap.data; + buffer.format = nativePixmap.format; + + gl->rasterizer.procs.colorBuffer(gl, &buffer); + if (depth.data != gl->rasterizer.state.buffers.depth.data) + gl->rasterizer.procs.depthBuffer(gl, &depth); + return EGL_TRUE; +} +EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl) +{ + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = nativePixmap.width; + buffer.height = nativePixmap.height; + buffer.stride = nativePixmap.stride; + buffer.data = nativePixmap.data; + buffer.format = nativePixmap.format; + gl->rasterizer.procs.readBuffer(gl, &buffer); + return EGL_TRUE; +} + +// ---------------------------------------------------------------------------- + +struct egl_pbuffer_surface_t : public egl_surface_t +{ + egl_pbuffer_surface_t( + EGLDisplay dpy, EGLConfig config, int32_t depthFormat, + int32_t w, int32_t h, int32_t f); + + virtual ~egl_pbuffer_surface_t(); + + virtual bool isValid() const { return pbuffer.data != 0; } + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); + virtual EGLBoolean bindReadSurface(ogles_context_t* gl); + virtual EGLint getWidth() const { return pbuffer.width; } + virtual EGLint getHeight() const { return pbuffer.height; } + virtual void* getBits() const { return pbuffer.data; } +private: + GGLSurface pbuffer; +}; + +egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, + EGLConfig config, int32_t depthFormat, + int32_t w, int32_t h, int32_t f) + : egl_surface_t(dpy, config, depthFormat) +{ + size_t size = w*h; + switch (f) { + case GGL_PIXEL_FORMAT_RGB_565: size *= 2; break; + case GGL_PIXEL_FORMAT_RGBA_8888: size *= 4; break; + default: + LOGE("incompatible pixel format for pbuffer (format=%d)", f); + pbuffer.data = 0; + break; + } + pbuffer.version = sizeof(GGLSurface); + pbuffer.width = w; + pbuffer.height = h; + pbuffer.stride = w; + pbuffer.data = (GGLubyte*)malloc(size); + pbuffer.format = f; + + if (depthFormat) { + depth.width = pbuffer.width; + depth.height = pbuffer.height; + depth.stride = depth.width; // use the width here + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return; + } + } +} +egl_pbuffer_surface_t::~egl_pbuffer_surface_t() { + free(pbuffer.data); +} +EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl) +{ + gl->rasterizer.procs.colorBuffer(gl, &pbuffer); + if (depth.data != gl->rasterizer.state.buffers.depth.data) + gl->rasterizer.procs.depthBuffer(gl, &depth); + return EGL_TRUE; +} +EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl) +{ + gl->rasterizer.procs.readBuffer(gl, &pbuffer); + return EGL_TRUE; +} + +// ---------------------------------------------------------------------------- + +struct config_pair_t { + GLint key; + GLint value; +}; + +struct configs_t { + const config_pair_t* array; + int size; +}; + +struct config_management_t { + GLint key; + bool (*match)(GLint reqValue, GLint confValue); + static bool atLeast(GLint reqValue, GLint confValue) { + return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue); + } + static bool exact(GLint reqValue, GLint confValue) { + return (reqValue == EGL_DONT_CARE) || (confValue == reqValue); + } + static bool mask(GLint reqValue, GLint confValue) { + return (confValue & reqValue) == reqValue; + } +}; + +// ---------------------------------------------------------------------------- + +static char const * const gVendorString = "Google Inc."; +static char const * const gVersionString = "1.2 Android Driver"; +static char const * const gClientApiString = "OpenGL ES"; +static char const * const gExtensionsString = + "EGL_ANDROID_swap_rectangle" " " + "EGL_ANDROID_copy_front_to_back" " " + "EGL_ANDROID_get_render_buffer_address" + ; + +// ---------------------------------------------------------------------------- + +struct extention_map_t { + const char * const name; + void (*address)(void); +}; + +static const extention_map_t gExtentionMap[] = { + { "eglSwapRectangleANDROID", (void(*)())&eglSwapRectangleANDROID }, + { "glDrawTexsOES", (void(*)())&glDrawTexsOES }, + { "glDrawTexiOES", (void(*)())&glDrawTexiOES }, + { "glDrawTexfOES", (void(*)())&glDrawTexfOES }, + { "glDrawTexxOES", (void(*)())&glDrawTexxOES }, + { "glDrawTexsvOES", (void(*)())&glDrawTexsvOES }, + { "glDrawTexivOES", (void(*)())&glDrawTexivOES }, + { "glDrawTexfvOES", (void(*)())&glDrawTexfvOES }, + { "glDrawTexxvOES", (void(*)())&glDrawTexxvOES }, + { "glQueryMatrixxOES", (void(*)())&glQueryMatrixxOES }, + { "glClipPlanef", (void(*)())&glClipPlanef }, + { "glClipPlanex", (void(*)())&glClipPlanex }, + { "glBindBuffer", (void(*)())&glBindBuffer }, + { "glBufferData", (void(*)())&glBufferData }, + { "glBufferSubData", (void(*)())&glBufferSubData }, + { "glDeleteBuffers", (void(*)())&glDeleteBuffers }, + { "glGenBuffers", (void(*)())&glGenBuffers }, +}; + +/* + * In the lists below, attributes names MUST be sorted. + * Additinnaly, all configs must be sorted according to + * the EGL specification. + */ + +static config_pair_t const config_base_attribute_list[] = { + { EGL_STENCIL_SIZE, 0 }, + { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, + { EGL_LEVEL, 0 }, + { EGL_MAX_PBUFFER_HEIGHT, 0 }, + { EGL_MAX_PBUFFER_PIXELS, 0 }, + { EGL_MAX_PBUFFER_WIDTH, 0 }, + { EGL_NATIVE_RENDERABLE, EGL_TRUE }, + { EGL_NATIVE_VISUAL_ID, 0 }, + { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGB_565 }, + { EGL_SAMPLES, 0 }, + { EGL_SAMPLE_BUFFERS, 0 }, + { EGL_TRANSPARENT_TYPE, EGL_NONE }, + { EGL_TRANSPARENT_BLUE_VALUE, 0 }, + { EGL_TRANSPARENT_GREEN_VALUE, 0 }, + { EGL_TRANSPARENT_RED_VALUE, 0 }, + { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE }, + { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE }, + { EGL_MIN_SWAP_INTERVAL, 1 }, + { EGL_MAX_SWAP_INTERVAL, 4 }, +}; + +// These configs can override the base attribute list + +static config_pair_t const config_0_attribute_list[] = { + { EGL_BUFFER_SIZE, 16 }, + { EGL_ALPHA_SIZE, 0 }, + { EGL_BLUE_SIZE, 5 }, + { EGL_GREEN_SIZE, 6 }, + { EGL_RED_SIZE, 5 }, + { EGL_DEPTH_SIZE, 0 }, + { EGL_CONFIG_ID, 0 }, + { EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT }, +}; + +static config_pair_t const config_1_attribute_list[] = { + { EGL_BUFFER_SIZE, 16 }, + { EGL_ALPHA_SIZE, 0 }, + { EGL_BLUE_SIZE, 5 }, + { EGL_GREEN_SIZE, 6 }, + { EGL_RED_SIZE, 5 }, + { EGL_DEPTH_SIZE, 16 }, + { EGL_CONFIG_ID, 1 }, + { EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT }, +}; + +static config_pair_t const config_2_attribute_list[] = { + { EGL_BUFFER_SIZE, 32 }, + { EGL_ALPHA_SIZE, 8 }, + { EGL_BLUE_SIZE, 8 }, + { EGL_GREEN_SIZE, 8 }, + { EGL_RED_SIZE, 8 }, + { EGL_DEPTH_SIZE, 0 }, + { EGL_CONFIG_ID, 2 }, + { EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT }, +}; + +static config_pair_t const config_3_attribute_list[] = { + { EGL_BUFFER_SIZE, 32 }, + { EGL_ALPHA_SIZE, 8 }, + { EGL_BLUE_SIZE, 8 }, + { EGL_GREEN_SIZE, 8 }, + { EGL_RED_SIZE, 8 }, + { EGL_DEPTH_SIZE, 16 }, + { EGL_CONFIG_ID, 3 }, + { EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT }, +}; + +static configs_t const gConfigs[] = { + { config_0_attribute_list, NELEM(config_0_attribute_list) }, + { config_1_attribute_list, NELEM(config_1_attribute_list) }, + { config_2_attribute_list, NELEM(config_2_attribute_list) }, + { config_3_attribute_list, NELEM(config_3_attribute_list) }, +}; + +static config_management_t const gConfigManagement[] = { + { EGL_BUFFER_SIZE, config_management_t::atLeast }, + { EGL_ALPHA_SIZE, config_management_t::atLeast }, + { EGL_BLUE_SIZE, config_management_t::atLeast }, + { EGL_GREEN_SIZE, config_management_t::atLeast }, + { EGL_RED_SIZE, config_management_t::atLeast }, + { EGL_DEPTH_SIZE, config_management_t::atLeast }, + { EGL_STENCIL_SIZE, config_management_t::atLeast }, + { EGL_CONFIG_CAVEAT, config_management_t::exact }, + { EGL_CONFIG_ID, config_management_t::exact }, + { EGL_LEVEL, config_management_t::exact }, + { EGL_MAX_PBUFFER_HEIGHT, config_management_t::exact }, + { EGL_MAX_PBUFFER_PIXELS, config_management_t::exact }, + { EGL_MAX_PBUFFER_WIDTH, config_management_t::exact }, + { EGL_NATIVE_RENDERABLE, config_management_t::exact }, + { EGL_NATIVE_VISUAL_ID, config_management_t::exact }, + { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact }, + { EGL_SAMPLES, config_management_t::exact }, + { EGL_SAMPLE_BUFFERS, config_management_t::exact }, + { EGL_SURFACE_TYPE, config_management_t::mask }, + { EGL_TRANSPARENT_TYPE, config_management_t::exact }, + { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact }, + { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact }, + { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact }, + { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact }, + { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact }, + { EGL_MIN_SWAP_INTERVAL, config_management_t::exact }, + { EGL_MAX_SWAP_INTERVAL, config_management_t::exact }, +}; + +static config_pair_t const config_defaults[] = { + { EGL_SURFACE_TYPE, EGL_WINDOW_BIT }, +}; + +// ---------------------------------------------------------------------------- + +template<typename T> +static int binarySearch(T const sortedArray[], int first, int last, EGLint key) +{ + while (first <= last) { + int mid = (first + last) / 2; + if (key > sortedArray[mid].key) { + first = mid + 1; + } else if (key < sortedArray[mid].key) { + last = mid - 1; + } else { + return mid; + } + } + return -1; +} + +static int isAttributeMatching(int i, EGLint attr, EGLint val) +{ + // look for the attribute in all of our configs + config_pair_t const* configFound = gConfigs[i].array; + int index = binarySearch<config_pair_t>( + gConfigs[i].array, + 0, gConfigs[i].size-1, + attr); + if (index < 0) { + configFound = config_base_attribute_list; + index = binarySearch<config_pair_t>( + config_base_attribute_list, + 0, NELEM(config_base_attribute_list)-1, + attr); + } + if (index >= 0) { + // attribute found, check if this config could match + int cfgMgtIndex = binarySearch<config_management_t>( + gConfigManagement, + 0, NELEM(gConfigManagement)-1, + attr); + if (index >= 0) { + bool match = gConfigManagement[cfgMgtIndex].match( + val, configFound[index].value); + if (match) { + // this config matches + return 1; + } + } else { + // attribute nont found. this should NEVER happen. + } + } else { + // error, this attribute doesn't exist + } + return 0; +} + +static int makeCurrent(ogles_context_t* gl) +{ + ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific(); + if (gl) { + egl_context_t* c = egl_context_t::context(gl); + if (c->flags & egl_context_t::IS_CURRENT) { + if (current != gl) { + // it is an error to set a context current, if it's already + // current to another thread + return -1; + } + } else { + if (current) { + // mark the current context as not current, and flush + glFlush(); + egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; + } + } + if (!(c->flags & egl_context_t::IS_CURRENT)) { + // The context is not current, make it current! + setGlThreadSpecific(gl); + c->flags |= egl_context_t::IS_CURRENT; + } + } else { + if (current) { + // mark the current context as not current, and flush + glFlush(); + egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; + } + // this thread has no context attached to it + setGlThreadSpecific(0); + } + return 0; +} + +static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value) +{ + size_t numConfigs = NELEM(gConfigs); + int index = (int)config; + if (uint32_t(index) >= numConfigs) + return setError(EGL_BAD_CONFIG, EGL_FALSE); + + int attrIndex; + attrIndex = binarySearch<config_pair_t>( + gConfigs[index].array, + 0, gConfigs[index].size-1, + attribute); + if (attrIndex>=0) { + *value = gConfigs[index].array[attrIndex].value; + return EGL_TRUE; + } + + attrIndex = binarySearch<config_pair_t>( + config_base_attribute_list, + 0, NELEM(config_base_attribute_list)-1, + attribute); + if (attrIndex>=0) { + *value = config_base_attribute_list[attrIndex].value; + return EGL_TRUE; + } + return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); +} + +static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, + NativeWindowType window, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + if (window == 0) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + EGLint surfaceType; + if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) + return EGL_FALSE; + + if (!(surfaceType & EGL_WINDOW_BIT)) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + EGLint configID; + if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) + return EGL_FALSE; + + int32_t depthFormat; + int32_t pixelFormat; + switch(configID) { + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = 0; + break; + case 1: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = GGL_PIXEL_FORMAT_Z_16; + break; + case 2: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = 0; + break; + case 3: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = GGL_PIXEL_FORMAT_Z_16; + break; + default: + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + // XXX: we don't have access to the pixelFormat here just yet. + // (it's possible that the surface is not fully initialized) + // maybe this should be done after the page-flip + //if (EGLint(info.format) != pixelFormat) + // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + egl_surface_t* surface = + new egl_window_surface_t(dpy, config, depthFormat, + static_cast<egl_native_window_t*>(window)); + + if (!surface->isValid()) { + // there was a problem in the ctor, the error + // flag has been set. + delete surface; + surface = 0; + } + return surface; +} + +static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, + NativePixmapType pixmap, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + if (pixmap == 0) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + EGLint surfaceType; + if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) + return EGL_FALSE; + + if (!(surfaceType & EGL_PIXMAP_BIT)) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + EGLint configID; + if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) + return EGL_FALSE; + + int32_t depthFormat; + int32_t pixelFormat; + switch(configID) { + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = 0; + break; + case 1: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = GGL_PIXEL_FORMAT_Z_16; + break; + case 2: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = 0; + break; + case 3: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = GGL_PIXEL_FORMAT_Z_16; + break; + default: + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + if (pixmap->format != pixelFormat) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + egl_surface_t* surface = + new egl_pixmap_surface_t(dpy, config, depthFormat, + static_cast<egl_native_pixmap_t*>(pixmap)); + + if (!surface->isValid()) { + // there was a problem in the ctor, the error + // flag has been set. + delete surface; + surface = 0; + } + return surface; +} + +static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + + EGLint surfaceType; + if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) + return EGL_FALSE; + + if (!(surfaceType & EGL_PBUFFER_BIT)) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + EGLint configID; + if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) + return EGL_FALSE; + + int32_t depthFormat; + int32_t pixelFormat; + switch(configID) { + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = 0; + break; + case 1: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = GGL_PIXEL_FORMAT_Z_16; + break; + case 2: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = 0; + break; + case 3: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = GGL_PIXEL_FORMAT_Z_16; + break; + default: + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + int32_t w = 0; + int32_t h = 0; + while (attrib_list[0]) { + if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1]; + if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1]; + attrib_list+=2; + } + + egl_surface_t* surface = + new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat); + + if (!surface->isValid()) { + // there was a problem in the ctor, the error + // flag has been set. + delete surface; + surface = 0; + } + return surface; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + +// ---------------------------------------------------------------------------- +// Initialization +// ---------------------------------------------------------------------------- + +EGLDisplay eglGetDisplay(NativeDisplayType display) +{ +#ifndef HAVE_ANDROID_OS + // this just needs to be done once + if (gGLKey == -1) { + pthread_mutex_lock(&gInitMutex); + if (gGLKey == -1) + pthread_key_create(&gGLKey, NULL); + pthread_mutex_unlock(&gInitMutex); + } +#endif + if (display == EGL_DEFAULT_DISPLAY) { + EGLDisplay dpy = (EGLDisplay)1; + egl_display_t& d = egl_display_t::get_display(dpy); + d.type = display; + return dpy; + } + return EGL_NO_DISPLAY; +} + +EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + EGLBoolean res = EGL_TRUE; + egl_display_t& d = egl_display_t::get_display(dpy); + + if (android_atomic_inc(&d.initialized) == 0) { + // initialize stuff here if needed + //pthread_mutex_lock(&gInitMutex); + //pthread_mutex_unlock(&gInitMutex); + } + + if (res == EGL_TRUE) { + if (major != NULL) *major = 1; + if (minor != NULL) *minor = 2; + } + return res; +} + +EGLBoolean eglTerminate(EGLDisplay dpy) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + EGLBoolean res = EGL_TRUE; + egl_display_t& d = egl_display_t::get_display(dpy); + if (android_atomic_dec(&d.initialized) == 1) { + // TODO: destroy all resources (surfaces, contextes, etc...) + //pthread_mutex_lock(&gInitMutex); + //pthread_mutex_unlock(&gInitMutex); + } + return res; +} + +// ---------------------------------------------------------------------------- +// configuration +// ---------------------------------------------------------------------------- + +EGLBoolean eglGetConfigs( EGLDisplay dpy, + EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + GLint numConfigs = NELEM(gConfigs); + if (!configs) { + *num_config = numConfigs; + return EGL_TRUE; + } + GLint i; + for (i=0 ; i<numConfigs && i<config_size ; i++) { + *configs++ = (EGLConfig)i; + } + *num_config = i; + return EGL_TRUE; +} + +EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, + EGLint *num_config) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + if (ggl_unlikely(configs==0 || attrib_list==0)) { + *num_config = 0; + return EGL_TRUE; + } + + int numAttributes = 0; + int numConfigs = NELEM(gConfigs); + uint32_t possibleMatch = (1<<numConfigs)-1; + while(possibleMatch && *attrib_list != EGL_NONE) { + numAttributes++; + EGLint attr = *attrib_list++; + EGLint val = *attrib_list++; + for (int i=0 ; i<numConfigs ; i++) { + if (!(possibleMatch & (1<<i))) + continue; + if (isAttributeMatching(i, attr, val) == 0) { + possibleMatch &= ~(1<<i); + } + } + } + + // now, handle the attributes which have a useful default value + for (size_t j=0 ; j<NELEM(config_defaults) ; j++) { + // see if this attribute was specified, if not apply its + // default value + if (binarySearch<config_pair_t>( + (config_pair_t const*)attrib_list, + 0, numAttributes, + config_defaults[j].key) < 0) + { + for (int i=0 ; i<numConfigs ; i++) { + if (!(possibleMatch & (1<<i))) + continue; + if (isAttributeMatching(i, + config_defaults[j].key, + config_defaults[j].value) == 0) + { + possibleMatch &= ~(1<<i); + } + } + } + } + + // return the configurations found + int n=0; + if (possibleMatch) { + for (int i=0 ; config_size && i<numConfigs ; i++) { + if (possibleMatch & (1<<i)) { + *configs++ = (EGLConfig)i; + config_size--; + n++; + } + } + } + *num_config = n; + return EGL_TRUE; +} + +EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + return getConfigAttrib(dpy, config, attribute, value); +} + +// ---------------------------------------------------------------------------- +// surfaces +// ---------------------------------------------------------------------------- + +EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, + NativeWindowType window, + const EGLint *attrib_list) +{ + return createWindowSurface(dpy, config, window, attrib_list); +} + +EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, + NativePixmapType pixmap, + const EGLint *attrib_list) +{ + return createPixmapSurface(dpy, config, pixmap, attrib_list); +} + +EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + // none of our configs support pbuffers + // (in fact it's working but since we can't use them as + // textures yet, it's not useful at all) + //createPbufferSurface(dpy, config, attrib_list); + return EGL_NO_SURFACE; +} + +EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (eglSurface != EGL_NO_SURFACE) { + egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); + if (surface->magic != egl_surface_t::MAGIC) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (surface->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + delete surface; + } + return EGL_TRUE; +} + +EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface, + EGLint attribute, EGLint *value) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface); + if (surface->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + EGLBoolean ret = EGL_TRUE; + switch (attribute) { + case EGL_CONFIG_ID: + ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value); + break; + case EGL_WIDTH: + *value = surface->getWidth(); + break; + case EGL_HEIGHT: + *value = surface->getHeight(); + break; + case EGL_LARGEST_PBUFFER: + // not modified for a window or pixmap surface + break; + case EGL_TEXTURE_FORMAT: + *value = EGL_NO_TEXTURE; + break; + case EGL_TEXTURE_TARGET: + *value = EGL_NO_TEXTURE; + break; + case EGL_MIPMAP_TEXTURE: + *value = EGL_FALSE; + break; + case EGL_MIPMAP_LEVEL: + *value = 0; + break; + case EGL_RENDER_BUFFER: + // TODO: return the real RENDER_BUFFER here + *value = EGL_BACK_BUFFER; + break; + case EGL_HORIZONTAL_RESOLUTION: + // pixel/mm * EGL_DISPLAY_SCALING + *value = surface->getHorizontalResolution(); + break; + case EGL_VERTICAL_RESOLUTION: + // pixel/mm * EGL_DISPLAY_SCALING + *value = surface->getVerticalResolution(); + break; + case EGL_PIXEL_ASPECT_RATIO: { + // w/h * EGL_DISPLAY_SCALING + int wr = surface->getHorizontalResolution(); + int hr = surface->getVerticalResolution(); + *value = (wr * EGL_DISPLAY_SCALING) / hr; + } break; + case EGL_SWAP_BEHAVIOR: + *value = surface->getSwapBehavior(); + break; + default: + ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + return ret; +} + +EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, + EGLContext share_list, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + + ogles_context_t* gl = ogles_init(sizeof(egl_context_t)); + if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + + egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base); + c->flags = egl_context_t::NEVER_CURRENT; + c->dpy = dpy; + c->config = config; + c->read = 0; + c->draw = 0; + return (EGLContext)gl; +} + +EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_context_t* c = egl_context_t::context(ctx); + if (c->flags & egl_context_t::IS_CURRENT) + setGlThreadSpecific(0); + ogles_uninit((ogles_context_t*)ctx); + return EGL_TRUE; +} + +EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, + EGLSurface read, EGLContext ctx) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (draw) { + egl_surface_t* s = (egl_surface_t*)draw; + if (s->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: check that draw and read are compatible with the context + } + + EGLContext current_ctx = EGL_NO_CONTEXT; + if (ctx == EGL_NO_CONTEXT) { + // if we're detaching, we need the current context + current_ctx = (EGLContext)getGlThreadSpecific(); + } else { + egl_context_t* c = egl_context_t::context(ctx); + egl_surface_t* d = (egl_surface_t*)draw; + egl_surface_t* r = (egl_surface_t*)read; + if ((d && d->ctx && d->ctx != ctx) || + (r && r->ctx && r->ctx != ctx)) { + // once of the surface is bound to a context in another thread + return setError(EGL_BAD_ACCESS, EGL_FALSE); + } + } + + ogles_context_t* gl = (ogles_context_t*)ctx; + if (makeCurrent(gl) == 0) { + if (ctx) { + egl_context_t* c = egl_context_t::context(ctx); + egl_surface_t* d = (egl_surface_t*)draw; + egl_surface_t* r = (egl_surface_t*)read; + c->read = read; + c->draw = draw; + if (c->flags & egl_context_t::NEVER_CURRENT) { + c->flags &= ~egl_context_t::NEVER_CURRENT; + GLint w = 0; + GLint h = 0; + if (draw) { + w = d->getWidth(); + h = d->getHeight(); + } + ogles_surfaceport(gl, 0, 0); + ogles_viewport(gl, 0, 0, w, h); + ogles_scissor(gl, 0, 0, w, h); + } + if (d) { + d->ctx = ctx; + d->bindDrawSurface(gl); + } + if (r) { + r->ctx = ctx; + r->bindReadSurface(gl); + } + } else { + // if surfaces were bound to the context bound to this thread + // mark then as unbound. + if (current_ctx) { + egl_context_t* c = egl_context_t::context(current_ctx); + egl_surface_t* d = (egl_surface_t*)c->draw; + egl_surface_t* r = (egl_surface_t*)c->read; + if (d) d->ctx = EGL_NO_CONTEXT; + if (r) r->ctx = EGL_NO_CONTEXT; + } + } + return EGL_TRUE; + } + return setError(EGL_BAD_ACCESS, EGL_FALSE); +} + +EGLContext eglGetCurrentContext(void) +{ + // eglGetCurrentContext returns the current EGL rendering context, + // as specified by eglMakeCurrent. If no context is current, + // EGL_NO_CONTEXT is returned. + return (EGLContext)getGlThreadSpecific(); +} + +EGLSurface eglGetCurrentSurface(EGLint readdraw) +{ + // eglGetCurrentSurface returns the read or draw surface attached + // to the current EGL rendering context, as specified by eglMakeCurrent. + // If no context is current, EGL_NO_SURFACE is returned. + EGLContext ctx = (EGLContext)getGlThreadSpecific(); + if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE; + egl_context_t* c = egl_context_t::context(ctx); + if (readdraw == EGL_READ) { + return c->read; + } else if (readdraw == EGL_DRAW) { + return c->draw; + } + return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); +} + +EGLDisplay eglGetCurrentDisplay(void) +{ + // eglGetCurrentDisplay returns the current EGL display connection + // for the current EGL rendering context, as specified by eglMakeCurrent. + // If no context is current, EGL_NO_DISPLAY is returned. + EGLContext ctx = (EGLContext)getGlThreadSpecific(); + if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY; + egl_context_t* c = egl_context_t::context(ctx); + return c->dpy; +} + +EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint *value) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_context_t* c = egl_context_t::context(ctx); + switch (attribute) { + case EGL_CONFIG_ID: + // Returns the ID of the EGL frame buffer configuration with + // respect to which the context was created + return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value); + } + return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); +} + +EGLBoolean eglWaitGL(void) +{ + return EGL_TRUE; +} + +EGLBoolean eglWaitNative(EGLint engine) +{ + return EGL_TRUE; +} + +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + egl_surface_t* d = static_cast<egl_surface_t*>(draw); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + // post the surface + d->swapBuffers(); + + // if it's bound to a context, update the buffer + if (d->ctx != EGL_NO_CONTEXT) { + d->bindDrawSurface((ogles_context_t*)d->ctx); + // if this surface is also the read surface of the context + // it is bound to, make sure to update the read buffer as well. + // The EGL spec is a little unclear about this. + egl_context_t* c = egl_context_t::context(d->ctx); + if (c->read == draw) { + d->bindReadSurface((ogles_context_t*)d->ctx); + } + } + + return EGL_TRUE; +} + +EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, + NativePixmapType target) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglCopyBuffers() + return EGL_FALSE; +} + +EGLint eglGetError(void) +{ + return getError(); +} + +const char* eglQueryString(EGLDisplay dpy, EGLint name) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, (const char*)0); + + switch (name) { + case EGL_VENDOR: + return gVendorString; + case EGL_VERSION: + return gVersionString; + case EGL_EXTENSIONS: + return gExtensionsString; + case EGL_CLIENT_APIS: + return gClientApiString; + } + return setError(EGL_BAD_PARAMETER, (const char *)0); +} + +// ---------------------------------------------------------------------------- +// EGL 1.1 +// ---------------------------------------------------------------------------- + +EGLBoolean eglSurfaceAttrib( + EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglSurfaceAttrib() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); +} + +EGLBoolean eglBindTexImage( + EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglBindTexImage() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); +} + +EGLBoolean eglReleaseTexImage( + EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglReleaseTexImage() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); +} + +EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglSwapInterval() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); +} + +// ---------------------------------------------------------------------------- +// EGL 1.2 +// ---------------------------------------------------------------------------- + +EGLBoolean eglBindAPI(EGLenum api) +{ + if (api != EGL_OPENGL_ES_API) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + return EGL_TRUE; +} + +EGLenum eglQueryAPI(void) +{ + return EGL_OPENGL_ES_API; +} + +EGLBoolean eglWaitClient(void) +{ + glFinish(); + return EGL_TRUE; +} + +EGLBoolean eglReleaseThread(void) +{ + // TODO: eglReleaseThread() + return EGL_TRUE; +} + +EGLSurface eglCreatePbufferFromClientBuffer( + EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + // TODO: eglCreatePbufferFromClientBuffer() + return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); +} + +// ---------------------------------------------------------------------------- +// Android extentions +// ---------------------------------------------------------------------------- + +void (*eglGetProcAddress (const char *procname))() +{ + extention_map_t const * const map = gExtentionMap; + for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) { + if (!strcmp(procname, map[i].name)) { + return map[i].address; + } + } + return NULL; +} + +EGLBoolean eglSwapRectangleANDROID( + EGLDisplay dpy, EGLSurface draw, + EGLint l, EGLint t, EGLint w, EGLint h) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_surface_t* surface = (egl_surface_t*)draw; + if (surface->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + return surface->swapRectangle(l, t, w, h); +} diff --git a/opengl/libagl/fixed_asm.S b/opengl/libagl/fixed_asm.S new file mode 100644 index 0000000..6cbc56f --- /dev/null +++ b/opengl/libagl/fixed_asm.S @@ -0,0 +1,65 @@ +/* libs/opengles/fixed_asm.S +** +** Copyright 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. +*/ + + + .text + .align + + .global gglFloatToFixed + .global gglFloatToFixedFast + + +/* + * Converts a float to a s15.16 fixed-point number. + * this doesn't handle floats out of the [-32768, +32768[ range + * and doesn't performs round-to-nearest. + * however, it's very fast :-) + */ + +gglFloatToFixedFast: + movs r1, r0, lsl #1 /* remove bit sign */ + mov r2, #0x8E /* 127 + 15 */ + sub r1, r2, r1, lsr #24 /* compute shift */ + mov r2, r0, lsl #8 /* mantissa<<8 */ + orr r2, r2, #0x80000000 /* add the missing 1 */ + mov r0, r2, lsr r1 /* scale to 16.16 */ + rsbcs r0, r0, #0 /* negate if needed */ + bx lr + +/* + * this version rounds-to-nearest and saturates numbers + * outside the range (but not NaNs). + */ + +gglFloatToFixed: + mov r1, r0, lsl #1 /* remove bit sign */ + mov r2, #0x8E /* 127 + 15 */ + subs r1, r2, r1, lsr #24 /* compute shift */ + bls 0f /* too big */ + mov r2, r0, lsl #8 /* mantissa<<8 */ + orr r2, r2, #0x80000000 /* add the missing 1 */ + mov r3, r0 + movs r0, r2, lsr r1 /* scale to 16.16 */ + addcs r0, r0, #1 /* round-to-nearest */ + tst r3, #0x80000000 /* negative? */ + rsbne r0, r0, #0 /* negate if needed */ + bx lr + +0: ands r0, r0, #0x80000000 /* keep only the sign bit */ + moveq r0, #0x7fffffff /* positive, maximum value */ + bx lr + diff --git a/opengl/libagl/fp.cpp b/opengl/libagl/fp.cpp new file mode 100644 index 0000000..ae5f1fe --- /dev/null +++ b/opengl/libagl/fp.cpp @@ -0,0 +1,87 @@ +/* libs/opengles/fp.cpp +** +** Copyright 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. +*/ + +#include "fp.h" + +// ---------------------------------------------------------------------------- + +#if !defined(__arm__) +GGLfixed gglFloatToFixed(float v) { + return GGLfixed(floorf(v * 65536.0f + 0.5f)); +} +#endif + +// ---------------------------------------------------------------------------- + +namespace android { + +namespace gl { + +GLfloat fixedToFloat(GLfixed x) +{ +#if DEBUG_USE_FLOATS + return x / 65536.0f; +#else + if (!x) return 0; + const uint32_t s = x & 0x80000000; + union { + uint32_t i; + float f; + }; + i = s ? -x : x; + const int c = gglClz(i) - 8; + i = (c>=0) ? (i<<c) : (i>>-c); + const uint32_t e = 134 - c; + i &= ~0x800000; + i |= e<<23; + i |= s; + return f; +#endif +} + +float sinef(float x) +{ + const float A = 1.0f / (2.0f*M_PI); + const float B = -16.0f; + const float C = 8.0f; + + // scale angle for easy argument reduction + x *= A; + + if (fabsf(x) >= 0.5f) { + // Argument reduction + x = x - ceilf(x + 0.5f) + 1.0f; + } + + const float y = B*x*fabsf(x) + C*x; + return 0.2215f * (y*fabsf(y) - y) + y; +} + +float cosinef(float x) +{ + return sinef(x + float(M_PI/2)); +} + +void sincosf(GLfloat angle, GLfloat* s, GLfloat* c) { + *s = sinef(angle); + *c = cosinef(angle); +} + +}; // namespace fp_utils + +// ---------------------------------------------------------------------------- +}; // namespace android diff --git a/opengl/libagl/fp.h b/opengl/libagl/fp.h new file mode 100644 index 0000000..6d0c183 --- /dev/null +++ b/opengl/libagl/fp.h @@ -0,0 +1,243 @@ +/* libs/opengles/fp.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_FP_H +#define ANDROID_OPENGLES_FP_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> +#include <math.h> + +#include <private/pixelflinger/ggl_context.h> + +#include <GLES/gl.h> + +#define DEBUG_USE_FLOATS 0 + +// ---------------------------------------------------------------------------- + +extern "C" GLfixed gglFloatToFixed(float f) __attribute__((const)); + +// ---------------------------------------------------------------------------- +namespace android { + +namespace gl { + + GLfloat fixedToFloat(GLfixed) CONST; + + void sincosf(GLfloat angle, GLfloat* s, GLfloat* c); + float sinef(GLfloat x) CONST; + float cosinef(GLfloat x) CONST; + +inline bool cmpf(GLfloat a, GLfloat b) CONST; +inline bool isZerof(GLfloat) CONST; +inline bool isOnef(GLfloat) CONST; + +inline int isZeroOrNegativef(GLfloat) CONST; + +inline int exponent(GLfloat) CONST; +inline int32_t mantissa(GLfloat) CONST; +inline GLfloat clampToZerof(GLfloat) CONST; +inline GLfloat reciprocalf(GLfloat) CONST; +inline GLfloat rsqrtf(GLfloat) CONST; +inline GLfloat sqrf(GLfloat) CONST; +inline GLfloat addExpf(GLfloat v, int e) CONST; +inline GLfloat mul2f(GLfloat v) CONST; +inline GLfloat div2f(GLfloat v) CONST; +inline GLfloat absf(GLfloat v) CONST; + + +/* + * float fastexpf(float) : a fast approximation of expf(x) + * give somewhat accurate results for -88 <= x <= 88 + * + * exp(x) = 2^(x/ln(2)) + * we use the properties of float encoding + * to get a fast 2^ and linear interpolation + * + */ + +inline float fastexpf(float y) __attribute__((const)); + +inline float fastexpf(float y) +{ + union { + float r; + int32_t i; + } u; + + // 127*ln(2) = 88 + if (y < -88.0f) { + u.r = 0.0f; + } else if (y > 88.0f) { + u.r = INFINITY; + } else { + const float kOneOverLogTwo = (1L<<23) / M_LN2; + const int32_t kExponentBias = 127L<<23; + const int32_t e = int32_t(y*kOneOverLogTwo); + u.i = e + kExponentBias; + } + + return u.r; +} + + +bool cmpf(GLfloat a, GLfloat b) { +#if DEBUG_USE_FLOATS + return a == b; +#else + union { + float f; + uint32_t i; + } ua, ub; + ua.f = a; + ub.f = b; + return ua.i == ub.i; +#endif +} + +bool isZerof(GLfloat v) { +#if DEBUG_USE_FLOATS + return v == 0; +#else + union { + float f; + int32_t i; + }; + f = v; + return (i<<1) == 0; +#endif +} + +bool isOnef(GLfloat v) { + return cmpf(v, 1.0f); +} + +int isZeroOrNegativef(GLfloat v) { +#if DEBUG_USE_FLOATS + return v <= 0; +#else + union { + float f; + int32_t i; + }; + f = v; + return isZerof(v) | (i>>31); +#endif +} + +int exponent(GLfloat v) { + union { + float f; + uint32_t i; + }; + f = v; + return ((i << 1) >> 24) - 127; +} + +int32_t mantissa(GLfloat v) { + union { + float f; + uint32_t i; + }; + f = v; + if (!(i&0x7F800000)) return 0; + const int s = i >> 31; + i |= (1L<<23); + i &= ~0xFF000000; + return s ? -i : i; +} + +GLfloat clampToZerof(GLfloat v) { +#if DEBUG_USE_FLOATS + return v<0 ? 0 : (v>1 ? 1 : v); +#else + union { + float f; + int32_t i; + }; + f = v; + i &= ~(i>>31); + return f; +#endif +} + +GLfloat reciprocalf(GLfloat v) { + // XXX: do better + return 1.0f / v; +} + +GLfloat rsqrtf(GLfloat v) { + // XXX: do better + return 1.0f / sqrtf(v); +} + +GLfloat sqrf(GLfloat v) { + // XXX: do better + return v*v; +} + +GLfloat addExpf(GLfloat v, int e) { + union { + float f; + int32_t i; + }; + f = v; + if (i<<1) { // XXX: deal with over/underflow + i += int32_t(e)<<23; + } + return f; +} + +GLfloat mul2f(GLfloat v) { +#if DEBUG_USE_FLOATS + return v*2; +#else + return addExpf(v, 1); +#endif +} + +GLfloat div2f(GLfloat v) { +#if DEBUG_USE_FLOATS + return v*0.5f; +#else + return addExpf(v, -1); +#endif +} + +GLfloat absf(GLfloat v) { +#if DEBUG_USE_FLOATS + return v<0 ? -v : v; +#else + union { + float f; + int32_t i; + }; + f = v; + i &= ~0x80000000; + return f; +#endif +} + +}; // namespace gl + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_OPENGLES_FP_H + diff --git a/opengl/libagl/iterators.S b/opengl/libagl/iterators.S new file mode 100644 index 0000000..daf2937 --- /dev/null +++ b/opengl/libagl/iterators.S @@ -0,0 +1,88 @@ +/* libs/opengles/iterators.S +** +** Copyright 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. +*/ + + + .text + .align + .arm + + .global iterators0032 + +/* + * iterators0032 + * + * MUST BE CALLED FROM ARM CODE + * + * r0: const compute_iterators_t* (this) + * r0 + 0: m_dx01 + * r0 + 4: m_dy10 + * r0 + 8: m_dx20 + * r0 +12: m_dy02 + * r0 +16: m_x0 + * r0 +20: m_y0 + * r0 +24: m_area + * r0 +28: m_scale + * r0 +29: m_area_scale; + * r1: int32_t* (out) + * r1 + 0: c + * r1 + 4: dcdx + * r1 + 8: dcdy + * r2: c0 + * r3: c1 + * [sp]: c2 + */ + +iterators0032: + stmfd sp!, {r4, r5, r6, r7, r8, lr} + ldr r4, [sp, #4*6] + + ldrb r12, [r0, #29] + sub r3, r3, r2 + sub r4, r4, r2 + sub r12, r12, #16 + mov r3, r3, asr r12 + mov r4, r4, asr r12 + + ldr r5, [r0, #0] + ldr r12, [r0, #4] + smull r8, lr, r4, r5 + ldr r5, [r0, #8] + smull r6, r7, r4, r12 + ldr r12, [r0, #12] + smlal r8, lr, r3, r5 + smlal r6, r7, r3, r12 + + ldr r3, [r0, #16] // m_x0 + ldr r4, [r0, #20] // m_x1 + + str r6, [r1, #4] + str r8, [r1, #8] + + umull r6, r5, r3, r6 + umull r8, r0, r4, r8 + mla r7, r3, r7, r5 + mla lr, r4, lr, r0 + adds r6, r6, r8 + adc r7, r7, lr + + movs r6, r6, lsr #4 + adc r6, r6, r7, lsl #28 + rsb r6, r6, r2, lsl #16 + str r6, [r1, #0] + + ldmfd sp!, {r4, r5, r6, r7, r8, pc} + diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp new file mode 100644 index 0000000..87725cb --- /dev/null +++ b/opengl/libagl/light.cpp @@ -0,0 +1,852 @@ +/* libs/opengles/light.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> +#include "context.h" +#include "fp.h" +#include "light.h" +#include "state.h" +#include "matrix.h" + + +#if defined(__arm__) && defined(__thumb__) +#warning "light.cpp should not be compiled in thumb on ARM." +#endif + +namespace android { + +// ---------------------------------------------------------------------------- + +static void invalidate_lighting(ogles_context_t* c); +static void lightVertexValidate(ogles_context_t* c, vertex_t* v); +static void lightVertexNop(ogles_context_t* c, vertex_t* v); +static void lightVertex(ogles_context_t* c, vertex_t* v); +static void lightVertexMaterial(ogles_context_t* c, vertex_t* v); + +static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s); +static inline void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b); + +static __attribute__((noinline)) +void vnorm3(GLfixed* d, const GLfixed* a); + +static inline void vsa3(GLfixed* d, + const GLfixed* m, GLfixed s, const GLfixed* a); +static inline void vmla3(GLfixed* d, + const GLfixed* m0, const GLfixed* m1, const GLfixed* a); +static inline void vmul3(GLfixed* d, + const GLfixed* m0, const GLfixed* m1); + +static GLfixed fog_linear(ogles_context_t* c, GLfixed z); +static GLfixed fog_exp(ogles_context_t* c, GLfixed z); +static GLfixed fog_exp2(ogles_context_t* c, GLfixed z); + + +// ---------------------------------------------------------------------------- + +static void init_white(vec4_t& c) { + c.r = c.g = c.b = c.a = 0x10000; +} + +void ogles_init_light(ogles_context_t* c) +{ + for (unsigned int i=0 ; i<OGLES_MAX_LIGHTS ; i++) { + c->lighting.lights[i].ambient.a = 0x10000; + c->lighting.lights[i].position.z = 0x10000; + c->lighting.lights[i].spotDir.z = -0x10000; + c->lighting.lights[i].spotCutoff = gglIntToFixed(180); + c->lighting.lights[i].attenuation[0] = 0x10000; + } + init_white(c->lighting.lights[0].diffuse); + init_white(c->lighting.lights[0].specular); + + c->lighting.front.ambient.r = + c->lighting.front.ambient.g = + c->lighting.front.ambient.b = gglFloatToFixed(0.2f); + c->lighting.front.ambient.a = 0x10000; + c->lighting.front.diffuse.r = + c->lighting.front.diffuse.g = + c->lighting.front.diffuse.b = gglFloatToFixed(0.8f); + c->lighting.front.diffuse.a = 0x10000; + c->lighting.front.specular.a = 0x10000; + c->lighting.front.emission.a = 0x10000; + + c->lighting.lightModel.ambient.r = + c->lighting.lightModel.ambient.g = + c->lighting.lightModel.ambient.b = gglFloatToFixed(0.2f); + c->lighting.lightModel.ambient.a = 0x10000; + + c->lighting.colorMaterial.face = GL_FRONT_AND_BACK; + c->lighting.colorMaterial.mode = GL_AMBIENT_AND_DIFFUSE; + + c->fog.mode = GL_EXP; + c->fog.fog = fog_exp; + c->fog.density = 0x10000; + c->fog.end = 0x10000; + c->fog.invEndMinusStart = 0x10000; + + invalidate_lighting(c); + + c->rasterizer.procs.shadeModel(c, GL_SMOOTH); + c->lighting.shadeModel = GL_SMOOTH; +} + +void ogles_uninit_light(ogles_context_t* c) +{ +} + +static inline int32_t clampF(GLfixed f) CONST; +int32_t clampF(GLfixed f) { + f = (f & ~(f>>31)); + if (f >= 0x10000) + f = 0x10000; + return f; +} + +static GLfixed fog_linear(ogles_context_t* c, GLfixed z) { + return clampF(gglMulx((c->fog.end - z), c->fog.invEndMinusStart)); +} + +static GLfixed fog_exp(ogles_context_t* c, GLfixed z) { + const float e = fixedToFloat(gglMulx(c->fog.density, z)); + return clampF(gglFloatToFixed(fastexpf(-e))); +} + +static GLfixed fog_exp2(ogles_context_t* c, GLfixed z) { + const float e = fixedToFloat(gglMulx(c->fog.density, z)); + return clampF(gglFloatToFixed(fastexpf(-e*e))); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark math helpers +#endif + +static inline +void vscale3(GLfixed* d, const GLfixed* m, GLfixed s) { + d[0] = gglMulx(m[0], s); + d[1] = gglMulx(m[1], s); + d[2] = gglMulx(m[2], s); +} + +static inline +void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) { + d[0] = gglMulAddx(m[0], s, a[0]); + d[1] = gglMulAddx(m[1], s, a[1]); + d[2] = gglMulAddx(m[2], s, a[2]); +} + +static inline +void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b) { + const GLfixed wa = a[3]; + const GLfixed wb = b[3]; + if (ggl_likely(wa == wb)) { + d[0] = a[0] - b[0]; + d[1] = a[1] - b[1]; + d[2] = a[2] - b[2]; + } else { + d[0] = gglMulSubx(a[0], wb, gglMulx(b[0], wa)); + d[1] = gglMulSubx(a[1], wb, gglMulx(b[1], wa)); + d[2] = gglMulSubx(a[2], wb, gglMulx(b[2], wa)); + } +} + +static inline +void vmla3(GLfixed* d, + const GLfixed* m0, const GLfixed* m1, const GLfixed* a) +{ + d[0] = gglMulAddx(m0[0], m1[0], a[0]); + d[1] = gglMulAddx(m0[1], m1[1], a[1]); + d[2] = gglMulAddx(m0[2], m1[2], a[2]); +} + +static inline +void vmul3(GLfixed* d, const GLfixed* m0, const GLfixed* m1) { + d[0] = gglMulx(m0[0], m1[0]); + d[1] = gglMulx(m0[1], m1[1]); + d[2] = gglMulx(m0[2], m1[2]); +} + +void vnorm3(GLfixed* d, const GLfixed* a) +{ + // we must take care of overflows when normalizing a vector + GLfixed n; + int32_t x = a[0]; x = x>=0 ? x : -x; + int32_t y = a[1]; y = y>=0 ? y : -y; + int32_t z = a[2]; z = z>=0 ? z : -z; + if (ggl_likely(x<=0x6800 && y<=0x6800 && z<= 0x6800)) { + // in this case this will all fit on 32 bits + n = x*x + y*y + z*z; + n = gglSqrtRecipx(n); + n <<= 8; + } else { + // here norm^2 is at least 0x7EC00000 (>>32 == 0.495117) + n = vsquare3(x, y, z); + n = gglSqrtRecipx(n); + } + vscale3(d, a, n); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark lighting equations +#endif + +static inline void light_picker(ogles_context_t* c) +{ + if (ggl_likely(!c->lighting.enable)) { + c->lighting.lightVertex = lightVertexNop; + return; + } + if (c->lighting.colorMaterial.enable) { + c->lighting.lightVertex = lightVertexMaterial; + } else { + c->lighting.lightVertex = lightVertex; + } +} + +static inline void validate_light_mvi(ogles_context_t* c) +{ + uint32_t en = c->lighting.enabledLights; + while (en) { + const int i = 31 - gglClz(en); + en &= ~(1<<i); + light_t& l = c->lighting.lights[i]; + c->transforms.mvui.point3(&c->transforms.mvui, + &l.objPosition, &l.position); + vnorm3(l.normalizedObjPosition.v, l.objPosition.v); + } +} + +static inline void validate_light(ogles_context_t* c) +{ + // if colorMaterial is enabled, we get the color from the vertex + if (!c->lighting.colorMaterial.enable) { + material_t& material = c->lighting.front; + uint32_t en = c->lighting.enabledLights; + while (en) { + const int i = 31 - gglClz(en); + en &= ~(1<<i); + light_t& l = c->lighting.lights[i]; + vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v); + vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v); + vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); + + // this is just a flag to tell if we have a specular component + l.implicitSpecular.v[3] = + l.implicitSpecular.r | + l.implicitSpecular.g | + l.implicitSpecular.b; + + l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0; + if (l.rConstAttenuation) + l.rConstAttenuation = gglRecipFast(l.attenuation[0]); + } + // emission and ambient for the whole scene + vmla3( c->lighting.implicitSceneEmissionAndAmbient.v, + c->lighting.lightModel.ambient.v, + material.ambient.v, + material.emission.v); + c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a; + } + validate_light_mvi(c); +} + +void invalidate_lighting(ogles_context_t* c) +{ + // TODO: pick lightVertexValidate or lightVertexValidateMVI + // instead of systematically the heavier lightVertexValidate() + c->lighting.lightVertex = lightVertexValidate; +} + +void ogles_invalidate_lighting_mvui(ogles_context_t* c) +{ + invalidate_lighting(c); +} + +void lightVertexNop(ogles_context_t*, vertex_t* v) +{ + // we should never end-up here +} + +void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v) +{ + validate_light_mvi(c); + light_picker(c); + c->lighting.lightVertex(c, v); +} + +void lightVertexValidate(ogles_context_t* c, vertex_t* v) +{ + validate_light(c); + light_picker(c); + c->lighting.lightVertex(c, v); +} + +void lightVertexMaterial(ogles_context_t* c, vertex_t* v) +{ + // fetch the material color + const GLvoid* cp = c->arrays.color.element( + v->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v->color.v, cp); + + // acquire the color-material from the vertex + material_t& material = c->lighting.front; + material.ambient = + material.diffuse = v->color; + // implicit arguments need to be computed per/vertex + uint32_t en = c->lighting.enabledLights; + while (en) { + const int i = 31 - gglClz(en); + en &= ~(1<<i); + light_t& l = c->lighting.lights[i]; + vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v); + vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v); + vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); + } + // emission and ambient for the whole scene + vmla3( c->lighting.implicitSceneEmissionAndAmbient.v, + c->lighting.lightModel.ambient.v, + material.ambient.v, + material.emission.v); + c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a; + + // now we can light our vertex as usual + lightVertex(c, v); +} + +void lightVertex(ogles_context_t* c, vertex_t* v) +{ + // emission and ambient for the whole scene + vec4_t r = c->lighting.implicitSceneEmissionAndAmbient; + + uint32_t en = c->lighting.enabledLights; + if (ggl_likely(en)) { + // since we do the lighting in object-space, we don't need to + // transform each normal. However, we might still have to normalize + // it if GL_NORMALIZE is enabled. + vec4_t n; + c->arrays.normal.fetch(c, n.v, + c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK)); + if (c->transforms.rescaleNormals == GL_NORMALIZE) + vnorm3(n.v, n.v); + + const material_t& material = c->lighting.front; + const int twoSide = c->lighting.lightModel.twoSide; + + while (en) { + const int i = 31 - gglClz(en); + en &= ~(1<<i); + const light_t& l = c->lighting.lights[i]; + + vec4_t d, t; + GLfixed s; + GLfixed sqDist = 0x10000; + + // compute vertex-to-light vector + if (ggl_unlikely(l.position.w)) { + vsub3w(d.v, l.objPosition.v, v->obj.v); + sqDist = dot3(d.v, d.v); + vscale3(d.v, d.v, gglSqrtRecipx(sqDist)); + } else { + // TODO: avoid copy here + d = l.normalizedObjPosition; + } + + // ambient & diffuse + s = dot3(n.v, d.v); + s = (s<0) ? (twoSide?(-s):0) : s; + vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v); + + // specular + if (ggl_unlikely(s && l.implicitSpecular.v[3])) { + vec4_t h; + h.x = d.x; + h.y = d.y; + h.z = d.z + 0x10000; + vnorm3(h.v, h.v); + s = dot3(n.v, h.v); + s = (s<0) ? (twoSide?(-s):0) : s; + if (s > 0) { + s = gglPowx(s, material.shininess); + vsa3(t.v, l.implicitSpecular.v, s, t.v); + } + } + + // spot + if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) { + GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v); + if (spotAtt >= l.spotCutoffCosine) { + vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp)); + } + } + + // attenuation + if (ggl_unlikely(l.position.w)) { + if (l.rConstAttenuation) { + s = l.rConstAttenuation; + } else { + s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]); + if (l.attenuation[1]) + s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s); + s = gglRecipFast(s); + } + vscale3(t.v, t.v, s); + } + + r.r += t.r; + r.g += t.g; + r.b += t.b; + } + } + v->color.r = gglClampx(r.r); + v->color.g = gglClampx(r.g); + v->color.b = gglClampx(r.b); + v->color.a = gglClampx(r.a); + v->flags |= vertex_t::LIT; +} + +static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c) +{ + if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE; + invalidate_lighting(c); +} + +static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c) +{ + if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + light_t& light = c->lighting.lights[i-GL_LIGHT0]; + const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f); + switch (pname) { + case GL_SPOT_EXPONENT: + if (GGLfixed(param) >= gglIntToFixed(128)) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + light.spotExp = param; + break; + case GL_SPOT_CUTOFF: + if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + light.spotCutoff = param; + light.spotCutoffCosine = + gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param)); + break; + case GL_CONSTANT_ATTENUATION: + if (param < 0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + light.attenuation[0] = param; + break; + case GL_LINEAR_ATTENUATION: + if (param < 0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + light.attenuation[1] = param; + break; + case GL_QUADRATIC_ATTENUATION: + if (param < 0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + light.attenuation[2] = param; + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + invalidate_lighting(c); +} + +static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c) +{ + if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + GLfixed* what; + light_t& light = c->lighting.lights[i-GL_LIGHT0]; + switch (pname) { + case GL_AMBIENT: + what = light.ambient.v; + break; + case GL_DIFFUSE: + what = light.diffuse.v; + break; + case GL_SPECULAR: + what = light.specular.v; + break; + case GL_POSITION: { + ogles_validate_transform(c, transform_state_t::MODELVIEW); + transform_t& mv = c->transforms.modelview.transform; + memcpy(light.position.v, params, sizeof(light.position.v)); + mv.point4(&mv, &light.position, &light.position); + invalidate_lighting(c); + return; + } + case GL_SPOT_DIRECTION: { + ogles_validate_transform(c, transform_state_t::MVUI); + transform_t& mvui = c->transforms.mvui; + mvui.point3(&mvui, &light.spotDir, (vec4_t*)params); + vnorm3(light.normalizedSpotDir.v, light.spotDir.v); + invalidate_lighting(c); + return; + } + default: + lightx(i, pname, params[0], c); + return; + } + what[0] = params[0]; + what[1] = params[1]; + what[2] = params[2]; + what[3] = params[3]; + invalidate_lighting(c); +} + +static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c) +{ + if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (ggl_unlikely(pname != GL_SHININESS)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->lighting.front.shininess = param; + invalidate_lighting(c); +} + +static void fogx(GLenum pname, GLfixed param, ogles_context_t* c) +{ + switch (pname) { + case GL_FOG_DENSITY: + if (param >= 0) { + c->fog.density = param; + break; + } + ogles_error(c, GL_INVALID_VALUE); + break; + case GL_FOG_START: + c->fog.start = gglClampx(param); + c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); + break; + case GL_FOG_END: + c->fog.end = gglClampx(param); + c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); + break; + case GL_FOG_MODE: + switch (param) { + case GL_LINEAR: + c->fog.mode = param; + c->fog.fog = fog_linear; + break; + case GL_EXP: + c->fog.mode = param; + c->fog.fog = fog_exp; + break; + case GL_EXP2: + c->fog.mode = param; + c->fog.fog = fog_exp2; + break; + default: + ogles_error(c, GL_INVALID_ENUM); + break; + } + break; + default: + ogles_error(c, GL_INVALID_ENUM); + break; + } +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + +#if 0 +#pragma mark - +#pragma mark lighting APIs +#endif + +void glShadeModel(GLenum mode) +{ + ogles_context_t* c = ogles_context_t::get(); + if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->lighting.shadeModel = mode; +} + +void glLightModelf(GLenum pname, GLfloat param) +{ + ogles_context_t* c = ogles_context_t::get(); + lightModelx(pname, gglFloatToFixed(param), c); +} + +void glLightModelx(GLenum pname, GLfixed param) +{ + ogles_context_t* c = ogles_context_t::get(); + lightModelx(pname, param, c); +} + +void glLightModelfv(GLenum pname, const GLfloat *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (pname == GL_LIGHT_MODEL_TWO_SIDE) { + lightModelx(pname, gglFloatToFixed(params[0]), c); + return; + } + + if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]); + c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]); + c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]); + c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]); + invalidate_lighting(c); +} + +void glLightModelxv(GLenum pname, const GLfixed *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (pname == GL_LIGHT_MODEL_TWO_SIDE) { + lightModelx(pname, params[0], c); + return; + } + + if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + c->lighting.lightModel.ambient.r = params[0]; + c->lighting.lightModel.ambient.g = params[1]; + c->lighting.lightModel.ambient.b = params[2]; + c->lighting.lightModel.ambient.a = params[3]; + invalidate_lighting(c); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +void glLightf(GLenum i, GLenum pname, GLfloat param) +{ + ogles_context_t* c = ogles_context_t::get(); + lightx(i, pname, gglFloatToFixed(param), c); +} + +void glLightx(GLenum i, GLenum pname, GLfixed param) +{ + ogles_context_t* c = ogles_context_t::get(); + lightx(i, pname, param, c); +} + +void glLightfv(GLenum i, GLenum pname, const GLfloat *params) +{ + ogles_context_t* c = ogles_context_t::get(); + switch (pname) { + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + lightx(i, pname, gglFloatToFixed(params[0]), c); + return; + } + + GLfixed paramsx[4]; + paramsx[0] = gglFloatToFixed(params[0]); + paramsx[1] = gglFloatToFixed(params[1]); + paramsx[2] = gglFloatToFixed(params[2]); + if (pname != GL_SPOT_DIRECTION) + paramsx[3] = gglFloatToFixed(params[3]); + + lightxv(i, pname, paramsx, c); +} + +void glLightxv(GLenum i, GLenum pname, const GLfixed *params) +{ + ogles_context_t* c = ogles_context_t::get(); + lightxv(i, pname, params, c); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +void glMaterialf(GLenum face, GLenum pname, GLfloat param) +{ + ogles_context_t* c = ogles_context_t::get(); + materialx(face, pname, gglFloatToFixed(param), c); +} + +void glMaterialx(GLenum face, GLenum pname, GLfixed param) +{ + ogles_context_t* c = ogles_context_t::get(); + materialx(face, pname, param, c); +} + +void glMaterialfv( + GLenum face, GLenum pname, const GLfloat *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + GLfixed* what=0; + GLfixed* other=0; + switch (pname) { + case GL_AMBIENT: what = c->lighting.front.ambient.v; break; + case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break; + case GL_SPECULAR: what = c->lighting.front.specular.v; break; + case GL_EMISSION: what = c->lighting.front.emission.v; break; + case GL_AMBIENT_AND_DIFFUSE: + what = c->lighting.front.ambient.v; break; + other = c->lighting.front.diffuse.v; break; + break; + case GL_SHININESS: + c->lighting.front.shininess = gglFloatToFixed(params[0]); + invalidate_lighting(c); + return; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + what[0] = gglFloatToFixed(params[0]); + what[1] = gglFloatToFixed(params[1]); + what[2] = gglFloatToFixed(params[2]); + what[3] = gglFloatToFixed(params[3]); + if (other) { + other[0] = what[0]; + other[1] = what[1]; + other[2] = what[2]; + other[3] = what[3]; + } + invalidate_lighting(c); +} + +void glMaterialxv( + GLenum face, GLenum pname, const GLfixed *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + GLfixed* what=0; + GLfixed* other=0; + switch (pname) { + case GL_AMBIENT: what = c->lighting.front.ambient.v; break; + case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break; + case GL_SPECULAR: what = c->lighting.front.specular.v; break; + case GL_EMISSION: what = c->lighting.front.emission.v; break; + case GL_AMBIENT_AND_DIFFUSE: + what = c->lighting.front.ambient.v; break; + other= c->lighting.front.diffuse.v; break; + break; + case GL_SHININESS: + c->lighting.front.shininess = gglFloatToFixed(params[0]); + invalidate_lighting(c); + return; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + what[0] = params[0]; + what[1] = params[1]; + what[2] = params[2]; + what[3] = params[3]; + if (other) { + other[0] = what[0]; + other[1] = what[1]; + other[2] = what[2]; + other[3] = what[3]; + } + invalidate_lighting(c); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark fog +#endif + +void glFogf(GLenum pname, GLfloat param) { + ogles_context_t* c = ogles_context_t::get(); + GLfixed paramx = (GLfixed)param; + if (pname != GL_FOG_MODE) + paramx = gglFloatToFixed(param); + fogx(pname, paramx, c); +} + +void glFogx(GLenum pname, GLfixed param) { + ogles_context_t* c = ogles_context_t::get(); + fogx(pname, param, c); +} + +void glFogfv(GLenum pname, const GLfloat *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (pname != GL_FOG_COLOR) { + GLfixed paramx = (GLfixed)params[0]; + if (pname != GL_FOG_MODE) + paramx = gglFloatToFixed(params[0]); + fogx(pname, paramx, c); + return; + } + GLfixed paramsx[4]; + paramsx[0] = gglFloatToFixed(params[0]); + paramsx[1] = gglFloatToFixed(params[1]); + paramsx[2] = gglFloatToFixed(params[2]); + paramsx[3] = gglFloatToFixed(params[3]); + c->rasterizer.procs.fogColor3xv(c, paramsx); +} + +void glFogxv(GLenum pname, const GLfixed *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (pname != GL_FOG_COLOR) { + fogx(pname, params[0], c); + return; + } + c->rasterizer.procs.fogColor3xv(c, params); +} diff --git a/opengl/libagl/light.h b/opengl/libagl/light.h new file mode 100644 index 0000000..6dae25f --- /dev/null +++ b/opengl/libagl/light.h @@ -0,0 +1,38 @@ +/* libs/opengles/light.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_LIGHT_H +#define ANDROID_OPENGLES_LIGHT_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +namespace android { + +namespace gl { +struct ogles_context_t; +}; + +void ogles_init_light(ogles_context_t* c); +void ogles_uninit_light(ogles_context_t* c); +void ogles_invalidate_lighting_mvui(ogles_context_t* c); + +}; // namespace android + +#endif // ANDROID_OPENGLES_LIGHT_H + diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp new file mode 100644 index 0000000..441da38 --- /dev/null +++ b/opengl/libagl/matrix.cpp @@ -0,0 +1,1144 @@ +/* libs/opengles/matrix.cpp +** +** Copyright 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. +*/ + +#include <stdlib.h> +#include <stdio.h> + +#include "context.h" +#include "fp.h" +#include "state.h" +#include "matrix.h" +#include "vertex.h" +#include "light.h" + +#if defined(__arm__) && defined(__thumb__) +#warning "matrix.cpp should not be compiled in thumb on ARM." +#endif + +#define I(_i, _j) ((_j)+ 4*(_i)) + +namespace android { + +// ---------------------------------------------------------------------------- + +static const GLfloat gIdentityf[16] = { 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1 }; + +static const matrixx_t gIdentityx = { + { 0x10000,0,0,0, + 0,0x10000,0,0, + 0,0,0x10000,0, + 0,0,0,0x10000 + } + }; + +static void point2__nop(transform_t const*, vec4_t* c, vec4_t const* o); +static void point3__nop(transform_t const*, vec4_t* c, vec4_t const* o); +static void point4__nop(transform_t const*, vec4_t* c, vec4_t const* o); +static void normal__nop(transform_t const*, vec4_t* c, vec4_t const* o); +static void point2__generic(transform_t const*, vec4_t* c, vec4_t const* o); +static void point3__generic(transform_t const*, vec4_t* c, vec4_t const* o); +static void point4__generic(transform_t const*, vec4_t* c, vec4_t const* o); +static void normal__generic(transform_t const*, vec4_t* c, vec4_t const* o); + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +void ogles_init_matrix(ogles_context_t* c) +{ + c->transforms.modelview.init(OGLES_MODELVIEW_STACK_DEPTH); + c->transforms.projection.init(OGLES_PROJECTION_STACK_DEPTH); + for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) + c->transforms.texture[i].init(OGLES_TEXTURE_STACK_DEPTH); + + c->transforms.current = &c->transforms.modelview; + c->transforms.matrixMode = GL_MODELVIEW; + c->transforms.dirty = transform_state_t::VIEWPORT | + transform_state_t::MVUI | + transform_state_t::MVIT | + transform_state_t::MVP; + c->transforms.mvp.loadIdentity(); + c->transforms.mvp4.loadIdentity(); + c->transforms.mvit4.loadIdentity(); + c->transforms.mvui.loadIdentity(); + c->transforms.vpt.loadIdentity(); + c->transforms.vpt.zNear = 0.0f; + c->transforms.vpt.zFar = 1.0f; +} + +void ogles_uninit_matrix(ogles_context_t* c) +{ + c->transforms.modelview.uninit(); + c->transforms.projection.uninit(); + for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) + c->transforms.texture[i].uninit(); +} + +static void validate_perspective(ogles_context_t* c, vertex_t* v) +{ + const uint32_t enables = c->rasterizer.state.enables; + c->arrays.perspective = (c->clipPlanes.enable) ? + ogles_vertex_clipAllPerspective3D : ogles_vertex_perspective3D; + if (enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) { + c->arrays.perspective = (c->clipPlanes.enable) ? + ogles_vertex_clipAllPerspective3DZ : ogles_vertex_perspective3DZ; + } + if ((c->arrays.vertex.size != 4) && + (c->transforms.mvp4.flags & transform_t::FLAGS_2D_PROJECTION)) { + c->arrays.perspective = ogles_vertex_perspective2D; + } + c->arrays.perspective(c, v); +} + +void ogles_invalidate_perspective(ogles_context_t* c) +{ + c->arrays.perspective = validate_perspective; +} + +void ogles_validate_transform_impl(ogles_context_t* c, uint32_t want) +{ + int dirty = c->transforms.dirty & want; + + // Validate the modelview + if (dirty & transform_state_t::MODELVIEW) { + c->transforms.modelview.validate(); + } + + // Validate the projection stack (in fact, it's never needed) + if (dirty & transform_state_t::PROJECTION) { + c->transforms.projection.validate(); + } + + // Validate the viewport transformation + if (dirty & transform_state_t::VIEWPORT) { + vp_transform_t& vpt = c->transforms.vpt; + vpt.transform.matrix.load(vpt.matrix); + vpt.transform.picker(); + } + + // We need to update the mvp (used to transform each vertex) + if (dirty & transform_state_t::MVP) { + c->transforms.update_mvp(); + // invalidate perspective (divide by W) and view volume clipping + ogles_invalidate_perspective(c); + } + + // Validate the mvui (for normal transformation) + if (dirty & transform_state_t::MVUI) { + c->transforms.update_mvui(); + ogles_invalidate_lighting_mvui(c); + } + + // Validate the texture stack + if (dirty & transform_state_t::TEXTURE) { + for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) + c->transforms.texture[i].validate(); + } + + // Validate the mvit4 (user-clip planes) + if (dirty & transform_state_t::MVIT) { + c->transforms.update_mvit(); + } + + c->transforms.dirty &= ~want; +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark transform_t +#endif + +void transform_t::loadIdentity() { + matrix = gIdentityx; + flags = 0; + ops = OP_IDENTITY; + point2 = point2__nop; + point3 = point3__nop; + point4 = point4__nop; +} + + +static inline +int notZero(GLfixed v) { + return abs(v) & ~0x3; +} + +static inline +int notOne(GLfixed v) { + return notZero(v - 0x10000); +} + +void transform_t::picker() +{ + const GLfixed* const m = matrix.m; + + // XXX: picker needs to be smarter + flags = 0; + ops = OP_ALL; + point2 = point2__generic; + point3 = point3__generic; + point4 = point4__generic; + + // find out if this is a 2D projection + if (!(notZero(m[3]) | notZero(m[7]) | notZero(m[11]) | notOne(m[15]))) { + flags |= FLAGS_2D_PROJECTION; + } +} + +void mvui_transform_t::picker() +{ + flags = 0; + ops = OP_ALL; + point3 = normal__generic; +} + +void transform_t::dump(const char* what) +{ + GLfixed const * const m = matrix.m; + LOGD("%s:", what); + for (int i=0 ; i<4 ; i++) + LOGD("[%08x %08x %08x %08x] [%f %f %f %f]\n", + m[I(0,i)], m[I(1,i)], m[I(2,i)], m[I(3,i)], + fixedToFloat(m[I(0,i)]), + fixedToFloat(m[I(1,i)]), + fixedToFloat(m[I(2,i)]), + fixedToFloat(m[I(3,i)])); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark matrixx_t +#endif + +void matrixx_t::load(const matrixf_t& rhs) { + GLfixed* xp = m; + GLfloat const* fp = rhs.elements(); + unsigned int i = 16; + do { + const GLfloat f = *fp++; + *xp++ = isZerof(f) ? 0 : gglFloatToFixed(f); + } while (--i); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark matrixf_t +#endif + +void matrixf_t::multiply(matrixf_t& r, const matrixf_t& lhs, const matrixf_t& rhs) +{ + GLfloat const* const m = lhs.m; + for (int i=0 ; i<4 ; i++) { + register const float rhs_i0 = rhs.m[ I(i,0) ]; + register float ri0 = m[ I(0,0) ] * rhs_i0; + register float ri1 = m[ I(0,1) ] * rhs_i0; + register float ri2 = m[ I(0,2) ] * rhs_i0; + register float ri3 = m[ I(0,3) ] * rhs_i0; + for (int j=1 ; j<4 ; j++) { + register const float rhs_ij = rhs.m[ I(i,j) ]; + ri0 += m[ I(j,0) ] * rhs_ij; + ri1 += m[ I(j,1) ] * rhs_ij; + ri2 += m[ I(j,2) ] * rhs_ij; + ri3 += m[ I(j,3) ] * rhs_ij; + } + r.m[ I(i,0) ] = ri0; + r.m[ I(i,1) ] = ri1; + r.m[ I(i,2) ] = ri2; + r.m[ I(i,3) ] = ri3; + } +} + +void matrixf_t::dump(const char* what) { + LOGD("%s", what); + LOGD("[ %9f %9f %9f %9f ]", m[I(0,0)], m[I(1,0)], m[I(2,0)], m[I(3,0)]); + LOGD("[ %9f %9f %9f %9f ]", m[I(0,1)], m[I(1,1)], m[I(2,1)], m[I(3,1)]); + LOGD("[ %9f %9f %9f %9f ]", m[I(0,2)], m[I(1,2)], m[I(2,2)], m[I(3,2)]); + LOGD("[ %9f %9f %9f %9f ]", m[I(0,3)], m[I(1,3)], m[I(2,3)], m[I(3,3)]); +} + +void matrixf_t::loadIdentity() { + memcpy(m, gIdentityf, sizeof(m)); +} + +void matrixf_t::set(const GLfixed* rhs) { + load(rhs); +} + +void matrixf_t::set(const GLfloat* rhs) { + load(rhs); +} + +void matrixf_t::load(const GLfixed* rhs) { + GLfloat* fp = m; + unsigned int i = 16; + do { + *fp++ = fixedToFloat(*rhs++); + } while (--i); +} + +void matrixf_t::load(const GLfloat* rhs) { + memcpy(m, rhs, sizeof(m)); +} + +void matrixf_t::load(const matrixf_t& rhs) { + operator = (rhs); +} + +void matrixf_t::multiply(const matrixf_t& rhs) { + matrixf_t r; + multiply(r, *this, rhs); + operator = (r); +} + +void matrixf_t::translate(GLfloat x, GLfloat y, GLfloat z) { + for (int i=0 ; i<4 ; i++) { + m[12+i] += m[i]*x + m[4+i]*y + m[8+i]*z; + } +} + +void matrixf_t::scale(GLfloat x, GLfloat y, GLfloat z) { + for (int i=0 ; i<4 ; i++) { + m[ i] *= x; + m[4+i] *= y; + m[8+i] *= z; + } +} + +void matrixf_t::rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z) +{ + matrixf_t rotation; + GLfloat* r = rotation.m; + GLfloat c, s; + r[3] = 0; r[7] = 0; r[11]= 0; + r[12]= 0; r[13]= 0; r[14]= 0; r[15]= 1; + a *= GLfloat(M_PI / 180.0f); + sincosf(a, &s, &c); + if (isOnef(x) && isZerof(y) && isZerof(z)) { + r[5] = c; r[10]= c; + r[6] = s; r[9] = -s; + r[1] = 0; r[2] = 0; + r[4] = 0; r[8] = 0; + r[0] = 1; + } else if (isZerof(x) && isOnef(y) && isZerof(z)) { + r[0] = c; r[10]= c; + r[8] = s; r[2] = -s; + r[1] = 0; r[4] = 0; + r[6] = 0; r[9] = 0; + r[5] = 1; + } else if (isZerof(x) && isZerof(y) && isOnef(z)) { + r[0] = c; r[5] = c; + r[1] = s; r[4] = -s; + r[2] = 0; r[6] = 0; + r[8] = 0; r[9] = 0; + r[10]= 1; + } else { + const GLfloat len = sqrtf(x*x + y*y + z*z); + if (!isOnef(len)) { + const GLfloat recipLen = reciprocalf(len); + x *= recipLen; + y *= recipLen; + z *= recipLen; + } + const GLfloat nc = 1.0f - c; + const GLfloat xy = x * y; + const GLfloat yz = y * z; + const GLfloat zx = z * x; + const GLfloat xs = x * s; + const GLfloat ys = y * s; + const GLfloat zs = z * s; + r[ 0] = x*x*nc + c; r[ 4] = xy*nc - zs; r[ 8] = zx*nc + ys; + r[ 1] = xy*nc + zs; r[ 5] = y*y*nc + c; r[ 9] = yz*nc - xs; + r[ 2] = zx*nc - ys; r[ 6] = yz*nc + xs; r[10] = z*z*nc + c; + } + multiply(rotation); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark matrix_stack_t +#endif + +void matrix_stack_t::init(int depth) { + stack = new matrixf_t[depth]; + ops = new uint8_t[depth]; + maxDepth = depth; + depth = 0; + dirty = 0; + loadIdentity(); +} + +void matrix_stack_t::uninit() { + delete [] stack; + delete [] ops; +} + +void matrix_stack_t::loadIdentity() { + transform.loadIdentity(); + stack[depth].loadIdentity(); + ops[depth] = OP_IDENTITY; +} + +void matrix_stack_t::load(const GLfixed* rhs) +{ + memcpy(transform.matrix.m, rhs, sizeof(transform.matrix.m)); + stack[depth].load(rhs); + ops[depth] = OP_ALL; // TODO: we should look at the matrix +} + +void matrix_stack_t::load(const GLfloat* rhs) +{ + stack[depth].load(rhs); + ops[depth] = OP_ALL; // TODO: we should look at the matrix +} + +void matrix_stack_t::multiply(const matrixf_t& rhs) +{ + stack[depth].multiply(rhs); + ops[depth] = OP_ALL; // TODO: we should look at the matrix +} + +void matrix_stack_t::translate(GLfloat x, GLfloat y, GLfloat z) +{ + stack[depth].translate(x,y,z); + ops[depth] |= OP_TRANSLATE; +} + +void matrix_stack_t::scale(GLfloat x, GLfloat y, GLfloat z) +{ + stack[depth].scale(x,y,z); + if (x==y && y==z) { + ops[depth] |= OP_UNIFORM_SCALE; + } else { + ops[depth] |= OP_SCALE; + } +} + +void matrix_stack_t::rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z) +{ + stack[depth].rotate(a,x,y,z); + ops[depth] |= OP_ROTATE; +} + +void matrix_stack_t::validate() +{ + if (dirty & DO_FLOAT_TO_FIXED) { + transform.matrix.load(top()); + } + if (dirty & DO_PICKER) { + transform.picker(); + } + dirty = 0; +} + +GLint matrix_stack_t::push() +{ + if (depth >= (maxDepth-1)) { + return GL_STACK_OVERFLOW; + } + stack[depth+1] = stack[depth]; + ops[depth+1] = ops[depth]; + depth++; + return 0; +} + +GLint matrix_stack_t::pop() +{ + if (depth == 0) { + return GL_STACK_UNDERFLOW; + } + depth--; + return 0; +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark vp_transform_t +#endif + +void vp_transform_t::loadIdentity() { + transform.loadIdentity(); + matrix.loadIdentity(); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark transform_state_t +#endif + +void transform_state_t::invalidate() +{ + switch (matrixMode) { + case GL_MODELVIEW: dirty |= MODELVIEW | MVP | MVUI | MVIT; break; + case GL_PROJECTION: dirty |= PROJECTION | MVP; break; + case GL_TEXTURE: dirty |= TEXTURE | MVP; break; + } + current->dirty = matrix_stack_t::DO_PICKER | + matrix_stack_t::DO_FLOAT_TO_FIXED; +} + +void transform_state_t::update_mvp() +{ + matrixf_t temp_mvp; + matrixf_t::multiply(temp_mvp, projection.top(), modelview.top()); + mvp4.matrix.load(temp_mvp); + mvp4.picker(); + + if (mvp4.flags & transform_t::FLAGS_2D_PROJECTION) { + // the mvp matrix doesn't transform W, in this case we can + // premultiply it with the viewport transformation. In addition to + // being more efficient, this is also much more accurate and in fact + // is needed for 2D drawing with a resulting 1:1 mapping. + matrixf_t mvpv; + matrixf_t::multiply(mvpv, vpt.matrix, temp_mvp); + mvp.matrix.load(mvpv); + mvp.picker(); + } else { + mvp = mvp4; + } +} + +static inline +GLfloat det22(GLfloat a, GLfloat b, GLfloat c, GLfloat d) { + return a*d - b*c; +} + +static inline +GLfloat ndet22(GLfloat a, GLfloat b, GLfloat c, GLfloat d) { + return b*c - a*d; +} + +static __attribute__((noinline)) +void invert(GLfloat* inverse, const GLfloat* src) +{ + double t; + int i, j, k, swap; + GLfloat tmp[4][4]; + + memcpy(inverse, gIdentityf, sizeof(gIdentityf)); + memcpy(tmp, src, sizeof(GLfloat)*16); + + for (i = 0; i < 4; i++) { + // look for largest element in column + swap = i; + for (j = i + 1; j < 4; j++) { + if (fabs(tmp[j][i]) > fabs(tmp[i][i])) { + swap = j; + } + } + + if (swap != i) { + /* swap rows. */ + for (k = 0; k < 4; k++) { + t = tmp[i][k]; + tmp[i][k] = tmp[swap][k]; + tmp[swap][k] = t; + + t = inverse[i*4+k]; + inverse[i*4+k] = inverse[swap*4+k]; + inverse[swap*4+k] = t; + } + } + + t = 1.0f / tmp[i][i]; + for (k = 0; k < 4; k++) { + tmp[i][k] *= t; + inverse[i*4+k] *= t; + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = tmp[j][i]; + for (k = 0; k < 4; k++) { + tmp[j][k] -= tmp[i][k]*t; + inverse[j*4+k] -= inverse[i*4+k]*t; + } + } + } + } +} + +void transform_state_t::update_mvit() +{ + GLfloat r[16]; + const GLfloat* const mv = modelview.top().elements(); + invert(r, mv); + // convert to fixed-point and transpose + GLfixed* const x = mvit4.matrix.m; + for (int i=0 ; i<4 ; i++) + for (int j=0 ; j<4 ; j++) + x[I(i,j)] = gglFloatToFixed(r[I(j,i)]); + mvit4.picker(); +} + +void transform_state_t::update_mvui() +{ + const GLfloat* const mv = modelview.top().elements(); + + /* + When transforming normals, we can use the upper 3x3 matrix, see: + http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node26.html + */ + + // Also note that: + // l(obj) = tr(M).l(eye) for infinite light + // l(obj) = inv(M).l(eye) for local light + + const uint32_t ops = modelview.top_ops() & ~OP_TRANSLATE; + if (ggl_likely((!(ops & ~OP_ROTATE)) || + (rescaleNormals && modelview.isRigidBody()))) { + // if the modelview matrix is a rigid body transformation + // (translation, rotation, uniform scaling), then we can bypass + // the inverse by transposing the matrix. + GLfloat rescale = 1.0f; + if (rescaleNormals == GL_RESCALE_NORMAL) { + if (!(ops & ~OP_UNIFORM_SCALE)) { + rescale = reciprocalf(mv[I(0,0)]); + } else { + rescale = rsqrtf( + sqrf(mv[I(2,0)]) + sqrf(mv[I(2,1)]) + sqrf(mv[I(2,2)])); + } + } + GLfixed* const x = mvui.matrix.m; + for (int i=0 ; i<3 ; i++) { + x[I(i,0)] = gglFloatToFixed(mv[I(0,i)] * rescale); + x[I(i,1)] = gglFloatToFixed(mv[I(1,i)] * rescale); + x[I(i,2)] = gglFloatToFixed(mv[I(2,i)] * rescale); + } + mvui.picker(); + return; + } + + GLfloat r[3][3]; + r[0][0] = det22(mv[I(1,1)], mv[I(2,1)], mv[I(1,2)], mv[I(2,2)]); + r[0][1] =ndet22(mv[I(0,1)], mv[I(2,1)], mv[I(0,2)], mv[I(2,2)]); + r[0][2] = det22(mv[I(0,1)], mv[I(1,1)], mv[I(0,2)], mv[I(1,2)]); + r[1][0] =ndet22(mv[I(1,0)], mv[I(2,0)], mv[I(1,2)], mv[I(2,2)]); + r[1][1] = det22(mv[I(0,0)], mv[I(2,0)], mv[I(0,2)], mv[I(2,2)]); + r[1][2] =ndet22(mv[I(0,0)], mv[I(1,0)], mv[I(0,2)], mv[I(1,2)]); + r[2][0] = det22(mv[I(1,0)], mv[I(2,0)], mv[I(1,1)], mv[I(2,1)]); + r[2][1] =ndet22(mv[I(0,0)], mv[I(2,0)], mv[I(0,1)], mv[I(2,1)]); + r[2][2] = det22(mv[I(0,0)], mv[I(1,0)], mv[I(0,1)], mv[I(1,1)]); + + GLfloat rdet; + if (rescaleNormals == GL_RESCALE_NORMAL) { + rdet = rsqrtf(sqrf(r[0][2]) + sqrf(r[1][2]) + sqrf(r[2][2])); + } else { + rdet = reciprocalf( + r[0][0]*mv[I(0,0)] + r[0][1]*mv[I(1,0)] + r[0][2]*mv[I(2,0)]); + } + + GLfixed* const x = mvui.matrix.m; + for (int i=0 ; i<3 ; i++) { + x[I(i,0)] = gglFloatToFixed(r[i][0] * rdet); + x[I(i,1)] = gglFloatToFixed(r[i][1] * rdet); + x[I(i,2)] = gglFloatToFixed(r[i][2] * rdet); + } + mvui.picker(); +} + + +// ---------------------------------------------------------------------------- +// transformation and matrices API +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark transformation and matrices API +#endif + +int ogles_surfaceport(ogles_context_t* c, GLint x, GLint y) +{ + c->viewport.surfaceport.x = x; + c->viewport.surfaceport.y = y; + + ogles_viewport(c, + c->viewport.x, + c->viewport.y, + c->viewport.w, + c->viewport.h); + + ogles_scissor(c, + c->viewport.scissor.x, + c->viewport.scissor.y, + c->viewport.scissor.w, + c->viewport.scissor.h); + + return 0; +} + +void ogles_scissor(ogles_context_t* c, + GLint x, GLint y, GLsizei w, GLsizei h) +{ + if ((w|h) < 0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + c->viewport.scissor.x = x; + c->viewport.scissor.y = y; + c->viewport.scissor.w = w; + c->viewport.scissor.h = h; + + x += c->viewport.surfaceport.x; + y += c->viewport.surfaceport.y; + + y = c->rasterizer.state.buffers.color.height - (y + h); + c->rasterizer.procs.scissor(c, x, y, w, h); +} + +void ogles_viewport(ogles_context_t* c, + GLint x, GLint y, GLsizei w, GLsizei h) +{ + if ((w|h)<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + c->viewport.x = x; + c->viewport.y = y; + c->viewport.w = w; + c->viewport.h = h; + + x += c->viewport.surfaceport.x; + y += c->viewport.surfaceport.y; + + GLint H = c->rasterizer.state.buffers.color.height; + GLfloat sx = div2f(w); + GLfloat ox = sx + x; + GLfloat sy = div2f(h); + GLfloat oy = sy - y + (H - h); + + GLfloat near = c->transforms.vpt.zNear; + GLfloat far = c->transforms.vpt.zFar; + GLfloat A = div2f(far - near); + GLfloat B = div2f(far + near); + + // compute viewport matrix + GLfloat* const f = c->transforms.vpt.matrix.editElements(); + f[0] = sx; f[4] = 0; f[ 8] = 0; f[12] = ox; + f[1] = 0; f[5] =-sy; f[ 9] = 0; f[13] = oy; + f[2] = 0; f[6] = 0; f[10] = A; f[14] = B; + f[3] = 0; f[7] = 0; f[11] = 0; f[15] = 1; + c->transforms.dirty |= transform_state_t::VIEWPORT; +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark matrix * vertex +#endif + +void point2__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { + const GLfixed* const m = mx->matrix.m; + const GLfixed rx = rhs->x; + const GLfixed ry = rhs->y; + lhs->x = mla2a(rx, m[ 0], ry, m[ 4], m[12]); + lhs->y = mla2a(rx, m[ 1], ry, m[ 5], m[13]); + lhs->z = mla2a(rx, m[ 2], ry, m[ 6], m[14]); + lhs->w = mla2a(rx, m[ 3], ry, m[ 7], m[15]); +} + +void point3__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { + const GLfixed* const m = mx->matrix.m; + const GLfixed rx = rhs->x; + const GLfixed ry = rhs->y; + const GLfixed rz = rhs->z; + lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); + lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); + lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); + lhs->w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); +} + +void point4__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { + const GLfixed* const m = mx->matrix.m; + const GLfixed rx = rhs->x; + const GLfixed ry = rhs->y; + const GLfixed rz = rhs->z; + const GLfixed rw = rhs->w; + lhs->x = mla4(rx, m[ 0], ry, m[ 4], rz, m[ 8], rw, m[12]); + lhs->y = mla4(rx, m[ 1], ry, m[ 5], rz, m[ 9], rw, m[13]); + lhs->z = mla4(rx, m[ 2], ry, m[ 6], rz, m[10], rw, m[14]); + lhs->w = mla4(rx, m[ 3], ry, m[ 7], rz, m[11], rw, m[15]); +} + +void normal__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { + const GLfixed* const m = mx->matrix.m; + const GLfixed rx = rhs->x; + const GLfixed ry = rhs->y; + const GLfixed rz = rhs->z; + lhs->x = mla3(rx, m[ 0], ry, m[ 4], rz, m[ 8]); + lhs->y = mla3(rx, m[ 1], ry, m[ 5], rz, m[ 9]); + lhs->z = mla3(rx, m[ 2], ry, m[ 6], rz, m[10]); +} + + +void point2__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) { + lhs->z = 0; + lhs->w = 0x10000; + if (lhs != rhs) { + lhs->x = rhs->x; + lhs->y = rhs->y; + } +} + +void point3__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) { + lhs->w = 0x10000; + if (lhs != rhs) { + lhs->x = rhs->x; + lhs->y = rhs->y; + lhs->z = rhs->z; + } +} + +void point4__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) { + if (lhs != rhs) + *lhs = *rhs; +} + + +static void frustumf( + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar, + ogles_context_t* c) + { + if (cmpf(left,right) || + cmpf(top, bottom) || + cmpf(zNear, zFar) || + isZeroOrNegativef(zNear) || + isZeroOrNegativef(zFar)) + { + ogles_error(c, GL_INVALID_VALUE); + return; + } + const GLfloat r_width = reciprocalf(right - left); + const GLfloat r_height = reciprocalf(top - bottom); + const GLfloat r_depth = reciprocalf(zNear - zFar); + const GLfloat x = mul2f(zNear * r_width); + const GLfloat y = mul2f(zNear * r_height); + const GLfloat A = mul2f((right + left) * r_width); + const GLfloat B = (top + bottom) * r_height; + const GLfloat C = (zFar + zNear) * r_depth; + const GLfloat D = mul2f(zFar * zNear * r_depth); + GLfloat f[16]; + f[ 0] = x; + f[ 5] = y; + f[ 8] = A; + f[ 9] = B; + f[10] = C; + f[14] = D; + f[11] = -1.0f; + f[ 1] = f[ 2] = f[ 3] = + f[ 4] = f[ 6] = f[ 7] = + f[12] = f[13] = f[15] = 0.0f; + + matrixf_t rhs; + rhs.set(f); + c->transforms.current->multiply(rhs); + c->transforms.invalidate(); +} + +static void orthof( + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar, + ogles_context_t* c) +{ + if (cmpf(left,right) || + cmpf(top, bottom) || + cmpf(zNear, zFar)) + { + ogles_error(c, GL_INVALID_VALUE); + return; + } + const GLfloat r_width = reciprocalf(right - left); + const GLfloat r_height = reciprocalf(top - bottom); + const GLfloat r_depth = reciprocalf(zFar - zNear); + const GLfloat x = mul2f(r_width); + const GLfloat y = mul2f(r_height); + const GLfloat z = -mul2f(r_depth); + const GLfloat tx = -(right + left) * r_width; + const GLfloat ty = -(top + bottom) * r_height; + const GLfloat tz = -(zFar + zNear) * r_depth; + GLfloat f[16]; + f[ 0] = x; + f[ 5] = y; + f[10] = z; + f[12] = tx; + f[13] = ty; + f[14] = tz; + f[15] = 1.0f; + f[ 1] = f[ 2] = f[ 3] = + f[ 4] = f[ 6] = f[ 7] = + f[ 8] = f[ 9] = f[11] = 0.0f; + matrixf_t rhs; + rhs.set(f); + c->transforms.current->multiply(rhs); + c->transforms.invalidate(); +} + +static void depthRangef(GLclampf zNear, GLclampf zFar, ogles_context_t* c) +{ + zNear = clampToZerof(zNear > 1 ? 1 : zNear); + zFar = clampToZerof(zFar > 1 ? 1 : zFar); + GLfloat* const f = c->transforms.vpt.matrix.editElements(); + f[10] = div2f(zFar - zNear); + f[14] = div2f(zFar + zNear); + c->transforms.dirty |= transform_state_t::VIEWPORT; + c->transforms.vpt.zNear = zNear; + c->transforms.vpt.zFar = zFar; +} + + +// ---------------------------------------------------------------------------- +}; // namespace android + +using namespace android; + +void glMatrixMode(GLenum mode) +{ + ogles_context_t* c = ogles_context_t::get(); + matrix_stack_t* stack = 0; + switch (mode) { + case GL_MODELVIEW: + stack = &c->transforms.modelview; + break; + case GL_PROJECTION: + stack = &c->transforms.projection; + break; + case GL_TEXTURE: + stack = &c->transforms.texture[c->textures.active]; + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->transforms.matrixMode = mode; + c->transforms.current = stack; +} + +void glLoadIdentity() +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->loadIdentity(); // also loads the GLfixed transform + c->transforms.invalidate(); + c->transforms.current->dirty = 0; +} + +void glLoadMatrixf(const GLfloat* m) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->load(m); + c->transforms.invalidate(); +} + +void glLoadMatrixx(const GLfixed* m) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->load(m); // also loads the GLfixed transform + c->transforms.invalidate(); + c->transforms.current->dirty &= ~matrix_stack_t::DO_FLOAT_TO_FIXED; +} + +void glMultMatrixf(const GLfloat* m) +{ + ogles_context_t* c = ogles_context_t::get(); + matrixf_t rhs; + rhs.set(m); + c->transforms.current->multiply(rhs); + c->transforms.invalidate(); +} + +void glMultMatrixx(const GLfixed* m) +{ + ogles_context_t* c = ogles_context_t::get(); + matrixf_t rhs; + rhs.set(m); + c->transforms.current->multiply(rhs); + c->transforms.invalidate(); +} + +void glPopMatrix() +{ + ogles_context_t* c = ogles_context_t::get(); + GLint err = c->transforms.current->pop(); + if (ggl_unlikely(err)) { + ogles_error(c, err); + return; + } + c->transforms.invalidate(); +} + +void glPushMatrix() +{ + ogles_context_t* c = ogles_context_t::get(); + GLint err = c->transforms.current->push(); + if (ggl_unlikely(err)) { + ogles_error(c, err); + return; + } + c->transforms.invalidate(); +} + +void glFrustumf( + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar) +{ + ogles_context_t* c = ogles_context_t::get(); + frustumf(left, right, bottom, top, zNear, zFar, c); +} + +void glFrustumx( + GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed zNear, GLfixed zFar) +{ + ogles_context_t* c = ogles_context_t::get(); + frustumf( fixedToFloat(left), fixedToFloat(right), + fixedToFloat(bottom), fixedToFloat(top), + fixedToFloat(zNear), fixedToFloat(zFar), + c); +} + +void glOrthof( + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat zNear, GLfloat zFar) +{ + ogles_context_t* c = ogles_context_t::get(); + orthof(left, right, bottom, top, zNear, zFar, c); +} + +void glOrthox( + GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed zNear, GLfixed zFar) +{ + ogles_context_t* c = ogles_context_t::get(); + orthof( fixedToFloat(left), fixedToFloat(right), + fixedToFloat(bottom), fixedToFloat(top), + fixedToFloat(zNear), fixedToFloat(zFar), + c); +} + +void glRotatef(GLfloat a, GLfloat x, GLfloat y, GLfloat z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->rotate(a, x, y, z); + c->transforms.invalidate(); +} + +void glRotatex(GLfixed a, GLfixed x, GLfixed y, GLfixed z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->rotate( + fixedToFloat(a), fixedToFloat(x), + fixedToFloat(y), fixedToFloat(z)); + c->transforms.invalidate(); +} + +void glScalef(GLfloat x, GLfloat y, GLfloat z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->scale(x, y, z); + c->transforms.invalidate(); +} + +void glScalex(GLfixed x, GLfixed y, GLfixed z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->scale( + fixedToFloat(x), fixedToFloat(y), fixedToFloat(z)); + c->transforms.invalidate(); +} + +void glTranslatef(GLfloat x, GLfloat y, GLfloat z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->translate(x, y, z); + c->transforms.invalidate(); +} + +void glTranslatex(GLfixed x, GLfixed y, GLfixed z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->transforms.current->translate( + fixedToFloat(x), fixedToFloat(y), fixedToFloat(z)); + c->transforms.invalidate(); +} + +void glScissor(GLint x, GLint y, GLsizei w, GLsizei h) +{ + ogles_context_t* c = ogles_context_t::get(); + ogles_scissor(c, x, y, w, h); +} + +void glViewport(GLint x, GLint y, GLsizei w, GLsizei h) +{ + ogles_context_t* c = ogles_context_t::get(); + ogles_viewport(c, x, y, w, h); +} + +void glDepthRangef(GLclampf zNear, GLclampf zFar) +{ + ogles_context_t* c = ogles_context_t::get(); + depthRangef(zNear, zFar, c); +} + +void glDepthRangex(GLclampx zNear, GLclampx zFar) +{ + ogles_context_t* c = ogles_context_t::get(); + depthRangef(fixedToFloat(zNear), fixedToFloat(zFar), c); +} + +void glPolygonOffsetx(GLfixed factor, GLfixed units) +{ + ogles_context_t* c = ogles_context_t::get(); + c->polygonOffset.factor = factor; + c->polygonOffset.units = units; +} + +void glPolygonOffset(GLfloat factor, GLfloat units) +{ + ogles_context_t* c = ogles_context_t::get(); + c->polygonOffset.factor = gglFloatToFixed(factor); + c->polygonOffset.units = gglFloatToFixed(units); +} + +GLbitfield glQueryMatrixxOES(GLfixed* m, GLint* e) +{ + ogles_context_t* c = ogles_context_t::get(); + GLbitfield status = 0; + GLfloat const* f = c->transforms.current->top().elements(); + for (int i=0 ; i<16 ; i++) { + if (isnan(f[i]) || isinf(f[i])) { + status |= 1<<i; + continue; + } + e[i] = exponent(f[i]) - 7; + m[i] = mantissa(f[i]); + } + return status; +} diff --git a/opengl/libagl/matrix.h b/opengl/libagl/matrix.h new file mode 100644 index 0000000..c9a38a9 --- /dev/null +++ b/opengl/libagl/matrix.h @@ -0,0 +1,355 @@ +/* libs/opengles/matrix.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_MATRIX_H +#define ANDROID_OPENGLES_MATRIX_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> +#include <utils/Log.h> + +#include <private/pixelflinger/ggl_context.h> + +#include <GLES/gl.h> + +namespace android { + +const int OGLES_MODELVIEW_STACK_DEPTH = 16; +const int OGLES_PROJECTION_STACK_DEPTH = 2; +const int OGLES_TEXTURE_STACK_DEPTH = 2; + +void ogles_init_matrix(ogles_context_t*); +void ogles_uninit_matrix(ogles_context_t*); +void ogles_invalidate_perspective(ogles_context_t* c); +void ogles_validate_transform_impl(ogles_context_t* c, uint32_t want); + +int ogles_surfaceport(ogles_context_t* c, GLint x, GLint y); + +void ogles_scissor(ogles_context_t* c, + GLint x, GLint y, GLsizei w, GLsizei h); + +void ogles_viewport(ogles_context_t* c, + GLint x, GLint y, GLsizei w, GLsizei h); + +inline void ogles_validate_transform( + ogles_context_t* c, uint32_t want) +{ + if (c->transforms.dirty & want) + ogles_validate_transform_impl(c, want); +} + +// ---------------------------------------------------------------------------- + +inline +GLfixed vsquare3(GLfixed a, GLfixed b, GLfixed c) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + int32_t t; + asm( + "smull %0, %1, %2, %2 \n" + "smlal %0, %1, %3, %3 \n" + "smlal %0, %1, %4, %4 \n" + "movs %0, %0, lsr #16 \n" + "adc %0, %0, %1, lsl #16 \n" + : "=&r"(r), "=&r"(t) + : "%r"(a), "r"(b), "r"(c) + : "cc" + ); + return r; + +#else + + return (( int64_t(a)*a + + int64_t(b)*b + + int64_t(c)*c + 0x8000)>>16); + +#endif +} + +static inline GLfixed mla2a( GLfixed a0, GLfixed b0, + GLfixed a1, GLfixed b1, + GLfixed c) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + int32_t t; + asm( + "smull %0, %1, %2, %3 \n" + "smlal %0, %1, %4, %5 \n" + "add %0, %6, %0, lsr #16 \n" + "add %0, %0, %1, lsl #16 \n" + : "=&r"(r), "=&r"(t) + : "%r"(a0), "r"(b0), + "%r"(a1), "r"(b1), + "r"(c) + : + ); + return r; + +#else + + return (( int64_t(a0)*b0 + + int64_t(a1)*b1)>>16) + c; + +#endif +} + +static inline GLfixed mla3a( GLfixed a0, GLfixed b0, + GLfixed a1, GLfixed b1, + GLfixed a2, GLfixed b2, + GLfixed c) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + int32_t t; + asm( + "smull %0, %1, %2, %3 \n" + "smlal %0, %1, %4, %5 \n" + "smlal %0, %1, %6, %7 \n" + "add %0, %8, %0, lsr #16 \n" + "add %0, %0, %1, lsl #16 \n" + : "=&r"(r), "=&r"(t) + : "%r"(a0), "r"(b0), + "%r"(a1), "r"(b1), + "%r"(a2), "r"(b2), + "r"(c) + : + ); + return r; + +#else + + return (( int64_t(a0)*b0 + + int64_t(a1)*b1 + + int64_t(a2)*b2)>>16) + c; + +#endif +} + +// b0, b1, b2 are signed 16-bit quanities +// that have been shifted right by 'shift' bits relative to normal +// S16.16 fixed point +static inline GLfixed mla3a16( GLfixed a0, int32_t b1b0, + GLfixed a1, + GLfixed a2, int32_t b2, + GLint shift, + GLfixed c) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + asm( + "smulwb %0, %1, %2 \n" + "smlawt %0, %3, %2, %0 \n" + "smlawb %0, %4, %5, %0 \n" + "add %0, %7, %0, lsl %6 \n" + : "=&r"(r) + : "r"(a0), "r"(b1b0), + "r"(a1), + "r"(a2), "r"(b2), + "r"(shift), + "r"(c) + : + ); + return r; + +#else + + int32_t accum; + int16_t b0 = b1b0 & 0xffff; + int16_t b1 = (b1b0 >> 16) & 0xffff; + accum = int64_t(a0)*int16_t(b0) >> 16; + accum += int64_t(a1)*int16_t(b1) >> 16; + accum += int64_t(a2)*int16_t(b2) >> 16; + accum = (accum << shift) + c; + return accum; + +#endif +} + + +static inline GLfixed mla3a16_btb( GLfixed a0, + GLfixed a1, + GLfixed a2, + int32_t b1b0, int32_t xxb2, + GLint shift, + GLfixed c) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + asm( + "smulwb %0, %1, %4 \n" + "smlawt %0, %2, %4, %0 \n" + "smlawb %0, %3, %5, %0 \n" + "add %0, %7, %0, lsl %6 \n" + : "=&r"(r) + : "r"(a0), + "r"(a1), + "r"(a2), + "r"(b1b0), "r"(xxb2), + "r"(shift), + "r"(c) + : + ); + return r; + +#else + + int32_t accum; + int16_t b0 = b1b0 & 0xffff; + int16_t b1 = (b1b0 >> 16) & 0xffff; + int16_t b2 = xxb2 & 0xffff; + accum = int64_t(a0)*int16_t(b0) >> 16; + accum += int64_t(a1)*int16_t(b1) >> 16; + accum += int64_t(a2)*int16_t(b2) >> 16; + accum = (accum << shift) + c; + return accum; + +#endif +} + +static inline GLfixed mla3a16_btt( GLfixed a0, + GLfixed a1, + GLfixed a2, + int32_t b1b0, int32_t b2xx, + GLint shift, + GLfixed c) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + asm( + "smulwb %0, %1, %4 \n" + "smlawt %0, %2, %4, %0 \n" + "smlawt %0, %3, %5, %0 \n" + "add %0, %7, %0, lsl %6 \n" + : "=&r"(r) + : "r"(a0), + "r"(a1), + "r"(a2), + "r"(b1b0), "r"(b2xx), + "r"(shift), + "r"(c) + : + ); + return r; + +#else + + int32_t accum; + int16_t b0 = b1b0 & 0xffff; + int16_t b1 = (b1b0 >> 16) & 0xffff; + int16_t b2 = (b2xx >> 16) & 0xffff; + accum = int64_t(a0)*int16_t(b0) >> 16; + accum += int64_t(a1)*int16_t(b1) >> 16; + accum += int64_t(a2)*int16_t(b2) >> 16; + accum = (accum << shift) + c; + return accum; + +#endif +} + +static inline GLfixed mla3( GLfixed a0, GLfixed b0, + GLfixed a1, GLfixed b1, + GLfixed a2, GLfixed b2) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + int32_t t; + asm( + "smull %0, %1, %2, %3 \n" + "smlal %0, %1, %4, %5 \n" + "smlal %0, %1, %6, %7 \n" + "movs %0, %0, lsr #16 \n" + "adc %0, %0, %1, lsl #16 \n" + : "=&r"(r), "=&r"(t) + : "%r"(a0), "r"(b0), + "%r"(a1), "r"(b1), + "%r"(a2), "r"(b2) + : "cc" + ); + return r; + +#else + + return (( int64_t(a0)*b0 + + int64_t(a1)*b1 + + int64_t(a2)*b2 + 0x8000)>>16); + +#endif +} + +static inline GLfixed mla4( GLfixed a0, GLfixed b0, + GLfixed a1, GLfixed b1, + GLfixed a2, GLfixed b2, + GLfixed a3, GLfixed b3) +{ +#if defined(__arm__) && !defined(__thumb__) + + GLfixed r; + int32_t t; + asm( + "smull %0, %1, %2, %3 \n" + "smlal %0, %1, %4, %5 \n" + "smlal %0, %1, %6, %7 \n" + "smlal %0, %1, %8, %9 \n" + "movs %0, %0, lsr #16 \n" + "adc %0, %0, %1, lsl #16 \n" + : "=&r"(r), "=&r"(t) + : "%r"(a0), "r"(b0), + "%r"(a1), "r"(b1), + "%r"(a2), "r"(b2), + "%r"(a3), "r"(b3) + : "cc" + ); + return r; + +#else + + return (( int64_t(a0)*b0 + + int64_t(a1)*b1 + + int64_t(a2)*b2 + + int64_t(a3)*b3 + 0x8000)>>16); + +#endif +} + +inline +GLfixed dot4(const GLfixed* a, const GLfixed* b) +{ + return mla4(a[0], b[0], a[1], b[1], a[2], b[2], a[3], b[3]); +} + + +inline +GLfixed dot3(const GLfixed* a, const GLfixed* b) +{ + return mla3(a[0], b[0], a[1], b[1], a[2], b[2]); +} + + +}; // namespace android + +#endif // ANDROID_OPENGLES_MATRIX_H + diff --git a/opengl/libagl/mipmap.cpp b/opengl/libagl/mipmap.cpp new file mode 100644 index 0000000..ccd77b7 --- /dev/null +++ b/opengl/libagl/mipmap.cpp @@ -0,0 +1,192 @@ +/* libs/opengles/mipmap.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> +#include <stdlib.h> + +#include "context.h" +#include "state.h" +#include "texture.h" +#include "TextureObjectManager.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +status_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex) +{ + int level = 0; + const GGLSurface* base = &tex->surface; + const GGLFormat& pixelFormat(c->rasterizer.formats[base->format]); + + int w = base->width; + int h = base->height; + if ((w&h) == 1) + return NO_ERROR; + + w = (w>>1) ? : 1; + h = (h>>1) ? : 1; + + while(true) { + ++level; + const int bpr = w * pixelFormat.size; + if (tex->reallocate(level, w, h, w, + base->format, base->compressedFormat, bpr) != NO_ERROR) { + return NO_MEMORY; + } + + int stride = w; + int bs = base->stride; + GGLSurface& cur = tex->editMip(level); + + if (base->format == GGL_PIXEL_FORMAT_RGB_565) + { + uint16_t const * src = (uint16_t const *)base->data; + uint16_t* dst = (uint16_t*)cur.data; + const uint32_t mask = 0x07E0F81F; + for (int y=0 ; y<h ; y++) { + size_t offset = (y*2) * bs; + for (int x=0 ; x<w ; x++) { + uint32_t p00 = src[offset]; + uint32_t p10 = src[offset+1]; + uint32_t p01 = src[offset+bs]; + uint32_t p11 = src[offset+bs+1]; + p00 = (p00 | (p00 << 16)) & mask; + p01 = (p01 | (p01 << 16)) & mask; + p10 = (p10 | (p10 << 16)) & mask; + p11 = (p11 | (p11 << 16)) & mask; + uint32_t grb = ((p00 + p10 + p01 + p11) >> 2) & mask; + uint32_t rgb = (grb & 0xFFFF) | (grb >> 16); + dst[x + y*stride] = rgb; + offset += 2; + } + } + } + else if (base->format == GGL_PIXEL_FORMAT_RGBA_5551) + { + uint16_t const * src = (uint16_t const *)base->data; + uint16_t* dst = (uint16_t*)cur.data; + for (int y=0 ; y<h ; y++) { + size_t offset = (y*2) * bs; + for (int x=0 ; x<w ; x++) { + uint32_t p00 = src[offset]; + uint32_t p10 = src[offset+1]; + uint32_t p01 = src[offset+bs]; + uint32_t p11 = src[offset+bs+1]; + uint32_t r = ((p00>>11)+(p10>>11)+(p01>>11)+(p11>>11)+2)>>2; + uint32_t g = (((p00>>6)+(p10>>6)+(p01>>6)+(p11>>6)+2)>>2)&0x3F; + uint32_t b = ((p00&0x3E)+(p10&0x3E)+(p01&0x3E)+(p11&0x3E)+4)>>3; + uint32_t a = ((p00&1)+(p10&1)+(p01&1)+(p11&1)+2)>>2; + dst[x + y*stride] = (r<<11)|(g<<6)|(b<<1)|a; + offset += 2; + } + } + } + else if (base->format == GGL_PIXEL_FORMAT_RGBA_8888) + { + uint32_t const * src = (uint32_t const *)base->data; + uint32_t* dst = (uint32_t*)cur.data; + for (int y=0 ; y<h ; y++) { + size_t offset = (y*2) * bs; + for (int x=0 ; x<w ; x++) { + uint32_t p00 = src[offset]; + uint32_t p10 = src[offset+1]; + uint32_t p01 = src[offset+bs]; + uint32_t p11 = src[offset+bs+1]; + uint32_t rb00 = p00 & 0x00FF00FF; + uint32_t rb01 = p01 & 0x00FF00FF; + uint32_t rb10 = p10 & 0x00FF00FF; + uint32_t rb11 = p11 & 0x00FF00FF; + uint32_t ga00 = (p00 >> 8) & 0x00FF00FF; + uint32_t ga01 = (p01 >> 8) & 0x00FF00FF; + uint32_t ga10 = (p10 >> 8) & 0x00FF00FF; + uint32_t ga11 = (p11 >> 8) & 0x00FF00FF; + uint32_t rb = (rb00 + rb01 + rb10 + rb11)>>2; + uint32_t ga = (ga00 + ga01 + ga10 + ga11)>>2; + uint32_t rgba = (rb & 0x00FF00FF) | ((ga & 0x00FF00FF)<<8); + dst[x + y*stride] = rgba; + offset += 2; + } + } + } + else if ((base->format == GGL_PIXEL_FORMAT_RGB_888) || + (base->format == GGL_PIXEL_FORMAT_LA_88) || + (base->format == GGL_PIXEL_FORMAT_A_8) || + (base->format == GGL_PIXEL_FORMAT_L_8)) + { + int skip; + switch (base->format) { + case GGL_PIXEL_FORMAT_RGB_888: skip = 3; break; + case GGL_PIXEL_FORMAT_LA_88: skip = 2; break; + default: skip = 1; break; + } + uint8_t const * src = (uint8_t const *)base->data; + uint8_t* dst = (uint8_t*)cur.data; + bs *= skip; + stride *= skip; + for (int y=0 ; y<h ; y++) { + size_t offset = (y*2) * bs; + for (int x=0 ; x<w ; x++) { + for (int c=0 ; c<skip ; c++) { + uint32_t p00 = src[c+offset]; + uint32_t p10 = src[c+offset+skip]; + uint32_t p01 = src[c+offset+bs]; + uint32_t p11 = src[c+offset+bs+skip]; + dst[x + y*stride + c] = (p00 + p10 + p01 + p11) >> 2; + } + offset += 2*skip; + } + } + } + else if (base->format == GGL_PIXEL_FORMAT_RGBA_4444) + { + uint16_t const * src = (uint16_t const *)base->data; + uint16_t* dst = (uint16_t*)cur.data; + for (int y=0 ; y<h ; y++) { + size_t offset = (y*2) * bs; + for (int x=0 ; x<w ; x++) { + uint32_t p00 = src[offset]; + uint32_t p10 = src[offset+1]; + uint32_t p01 = src[offset+bs]; + uint32_t p11 = src[offset+bs+1]; + p00 = ((p00 << 12) & 0x0F0F0000) | (p00 & 0x0F0F); + p10 = ((p10 << 12) & 0x0F0F0000) | (p10 & 0x0F0F); + p01 = ((p01 << 12) & 0x0F0F0000) | (p01 & 0x0F0F); + p11 = ((p11 << 12) & 0x0F0F0000) | (p11 & 0x0F0F); + uint32_t rbga = (p00 + p10 + p01 + p11) >> 2; + uint32_t rgba = (rbga & 0x0F0F) | ((rbga>>12) & 0xF0F0); + dst[x + y*stride] = rgba; + offset += 2; + } + } + } else { + LOGE("Unsupported format (%d)", base->format); + return BAD_TYPE; + } + + // exit condition: we just processed the 1x1 LODs + if ((w&h) == 1) + break; + + base = &cur; + w = (w>>1) ? : 1; + h = (h>>1) ? : 1; + } + return NO_ERROR; +} + +}; // namespace android diff --git a/opengl/libagl/primitives.cpp b/opengl/libagl/primitives.cpp new file mode 100644 index 0000000..20e8d37 --- /dev/null +++ b/opengl/libagl/primitives.cpp @@ -0,0 +1,1095 @@ +/* libs/opengles/primitives.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "context.h" +#include "primitives.h" +#include "light.h" +#include "matrix.h" +#include "vertex.h" +#include "fp.h" +#include "TextureObjectManager.h" + +extern "C" void iterators0032(const void* that, + int32_t* it, int32_t c0, int32_t c1, int32_t c2); + +namespace android { + +// ---------------------------------------------------------------------------- + +static void primitive_point(ogles_context_t* c, vertex_t* v); +static void primitive_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1); +static void primitive_clip_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static void primitive_nop_point(ogles_context_t* c, vertex_t* v); +static void primitive_nop_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1); +static void primitive_nop_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static inline bool cull_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static void lerp_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static void lerp_texcoords(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static void lerp_texcoords_w(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static void triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static void clip_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2); + +static unsigned int clip_line(ogles_context_t* c, + vertex_t* s, vertex_t* p); + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +static void lightTriangleDarkSmooth(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + if (!(v0->flags & vertex_t::LIT)) { + v0->flags |= vertex_t::LIT; + const GLvoid* cp = c->arrays.color.element( + v0->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v0->color.v, cp); + } + if (!(v1->flags & vertex_t::LIT)) { + v1->flags |= vertex_t::LIT; + const GLvoid* cp = c->arrays.color.element( + v1->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v1->color.v, cp); + } + if(!(v2->flags & vertex_t::LIT)) { + v2->flags |= vertex_t::LIT; + const GLvoid* cp = c->arrays.color.element( + v2->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v2->color.v, cp); + } +} + +static void lightTriangleDarkFlat(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + if (!(v2->flags & vertex_t::LIT)) { + v2->flags |= vertex_t::LIT; + const GLvoid* cp = c->arrays.color.element( + v2->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v2->color.v, cp); + } + // configure the rasterizer here, before we clip + c->rasterizer.procs.color4xv(c, v2->color.v); +} + +static void lightTriangleSmooth(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + if (!(v0->flags & vertex_t::LIT)) + c->lighting.lightVertex(c, v0); + if (!(v1->flags & vertex_t::LIT)) + c->lighting.lightVertex(c, v1); + if(!(v2->flags & vertex_t::LIT)) + c->lighting.lightVertex(c, v2); +} + +static void lightTriangleFlat(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + if (!(v2->flags & vertex_t::LIT)) + c->lighting.lightVertex(c, v2); + // configure the rasterizer here, before we clip + c->rasterizer.procs.color4xv(c, v2->color.v); +} + +// The fog versions... + +static inline +void lightVertexDarkSmoothFog(ogles_context_t* c, vertex_t* v) +{ + if (!(v->flags & vertex_t::LIT)) { + v->flags |= vertex_t::LIT; + v->fog = c->fog.fog(c, v->window.z); + const GLvoid* cp = c->arrays.color.element( + v->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v->color.v, cp); + } +} +static inline +void lightVertexDarkFlatFog(ogles_context_t* c, vertex_t* v) +{ + if (!(v->flags & vertex_t::LIT)) { + v->flags |= vertex_t::LIT; + v->fog = c->fog.fog(c, v->window.z); + } +} +static inline +void lightVertexSmoothFog(ogles_context_t* c, vertex_t* v) +{ + if (!(v->flags & vertex_t::LIT)) { + v->fog = c->fog.fog(c, v->window.z); + c->lighting.lightVertex(c, v); + } +} + +static void lightTriangleDarkSmoothFog(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + lightVertexDarkSmoothFog(c, v0); + lightVertexDarkSmoothFog(c, v1); + lightVertexDarkSmoothFog(c, v2); +} + +static void lightTriangleDarkFlatFog(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + lightVertexDarkFlatFog(c, v0); + lightVertexDarkFlatFog(c, v1); + lightVertexDarkSmoothFog(c, v2); + // configure the rasterizer here, before we clip + c->rasterizer.procs.color4xv(c, v2->color.v); +} + +static void lightTriangleSmoothFog(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + lightVertexSmoothFog(c, v0); + lightVertexSmoothFog(c, v1); + lightVertexSmoothFog(c, v2); +} + +static void lightTriangleFlatFog(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + lightVertexDarkFlatFog(c, v0); + lightVertexDarkFlatFog(c, v1); + lightVertexSmoothFog(c, v2); + // configure the rasterizer here, before we clip + c->rasterizer.procs.color4xv(c, v2->color.v); +} + + + +typedef void (*light_primitive_t)(ogles_context_t*, + vertex_t*, vertex_t*, vertex_t*); + +// fog 0x4, light 0x2, smooth 0x1 +static const light_primitive_t lightPrimitive[8] = { + lightTriangleDarkFlat, // no fog | dark | flat + lightTriangleDarkSmooth, // no fog | dark | smooth + lightTriangleFlat, // no fog | light | flat + lightTriangleSmooth, // no fog | light | smooth + lightTriangleDarkFlatFog, // fog | dark | flat + lightTriangleDarkSmoothFog, // fog | dark | smooth + lightTriangleFlatFog, // fog | light | flat + lightTriangleSmoothFog // fog | light | smooth +}; + +void ogles_validate_primitives(ogles_context_t* c) +{ + const uint32_t enables = c->rasterizer.state.enables; + + // set up the lighting/shading/smoothing/fogging function + int index = enables & GGL_ENABLE_SMOOTH ? 0x1 : 0; + index |= c->lighting.enable ? 0x2 : 0; + index |= enables & GGL_ENABLE_FOG ? 0x4 : 0; + c->lighting.lightTriangle = lightPrimitive[index]; + + // set up the primitive renderers + if (ggl_likely(c->arrays.vertex.enable)) { + c->prims.renderPoint = primitive_point; + c->prims.renderLine = primitive_line; + c->prims.renderTriangle = primitive_clip_triangle; + } else { + c->prims.renderPoint = primitive_nop_point; + c->prims.renderLine = primitive_nop_line; + c->prims.renderTriangle = primitive_nop_triangle; + } +} + +// ---------------------------------------------------------------------------- + +void compute_iterators_t::initTriangle( + vertex_t const* v0, vertex_t const* v1, vertex_t const* v2) +{ + m_dx01 = v1->window.x - v0->window.x; + m_dy10 = v0->window.y - v1->window.y; + m_dx20 = v0->window.x - v2->window.x; + m_dy02 = v2->window.y - v0->window.y; + m_area = m_dx01*m_dy02 + (-m_dy10)*m_dx20; +} + +void compute_iterators_t::initLerp(vertex_t const* v0, uint32_t enables) +{ + m_x0 = v0->window.x; + m_y0 = v0->window.y; + const GGLcoord area = (m_area + TRI_HALF) >> TRI_FRACTION_BITS; + const GGLcoord minArea = 2; // cannot be inversed + // triangles with an area smaller than 1.0 are not smooth-shaded + + int q=0, s=0, d=0; + if (abs(area) >= minArea) { + // Here we do some voodoo magic, to compute a suitable scale + // factor for deltas/area: + + // First compute the 1/area with full 32-bits precision, + // gglRecipQNormalized returns a number [-0.5, 0.5[ and an exponent. + d = gglRecipQNormalized(area, &q); + + // Then compute the minimum left-shift to not overflow the muls + // below. + s = 32 - gglClz(abs(m_dy02)|abs(m_dy10)|abs(m_dx01)|abs(m_dx20)); + + // We'll keep 16-bits of precision for deltas/area. So we need + // to shift everything left an extra 15 bits. + s += 15; + + // make sure all final shifts are not > 32, because gglMulx + // can't handle it. + if (s < q) s = q; + if (s > 32) { + d >>= 32-s; + s = 32; + } + } + + m_dx01 = gglMulx(m_dx01, d, s); + m_dy10 = gglMulx(m_dy10, d, s); + m_dx20 = gglMulx(m_dx20, d, s); + m_dy02 = gglMulx(m_dy02, d, s); + m_area_scale = 32 + q - s; + m_scale = 0; + + if (enables & GGL_ENABLE_TMUS) { + const int A = gglClz(abs(m_dy02)|abs(m_dy10)|abs(m_dx01)|abs(m_dx20)); + const int B = gglClz(abs(m_x0)|abs(m_y0)); + m_scale = max(0, 32 - (A + 16)) + + max(0, 32 - (B + TRI_FRACTION_BITS)) + 1; + } +} + +int compute_iterators_t::iteratorsScale(GGLfixed* it, + int32_t c0, int32_t c1, int32_t c2) const +{ + int32_t dc01 = c1 - c0; + int32_t dc02 = c2 - c0; + const int A = gglClz(abs(c0)); + const int B = gglClz(abs(dc01)|abs(dc02)); + const int scale = min(A, B - m_scale) - 2; + if (scale >= 0) { + c0 <<= scale; + dc01 <<= scale; + dc02 <<= scale; + } else { + c0 >>= -scale; + dc01 >>= -scale; + dc02 >>= -scale; + } + const int s = m_area_scale; + int32_t dcdx = gglMulAddx(dc01, m_dy02, gglMulx(dc02, m_dy10, s), s); + int32_t dcdy = gglMulAddx(dc02, m_dx01, gglMulx(dc01, m_dx20, s), s); + int32_t c = c0 - (gglMulAddx(dcdx, m_x0, + gglMulx(dcdy, m_y0, TRI_FRACTION_BITS), TRI_FRACTION_BITS)); + it[0] = c; + it[1] = dcdx; + it[2] = dcdy; + return scale; +} + +void compute_iterators_t::iterators1616(GGLfixed* it, + GGLfixed c0, GGLfixed c1, GGLfixed c2) const +{ + const GGLfixed dc01 = c1 - c0; + const GGLfixed dc02 = c2 - c0; + // 16.16 x 16.16 == 32.32 --> 16.16 + const int s = m_area_scale; + int32_t dcdx = gglMulAddx(dc01, m_dy02, gglMulx(dc02, m_dy10, s), s); + int32_t dcdy = gglMulAddx(dc02, m_dx01, gglMulx(dc01, m_dx20, s), s); + int32_t c = c0 - (gglMulAddx(dcdx, m_x0, + gglMulx(dcdy, m_y0, TRI_FRACTION_BITS), TRI_FRACTION_BITS)); + it[0] = c; + it[1] = dcdx; + it[2] = dcdy; +} + +#if defined(__arm__) && !defined(__thumb__) +inline void compute_iterators_t::iterators0032(int32_t* it, + int32_t c0, int32_t c1, int32_t c2) const +{ + ::iterators0032(this, it, c0, c1, c2); +} +#else +void compute_iterators_t::iterators0032(int32_t* it, + int32_t c0, int32_t c1, int32_t c2) const +{ + const int s = m_area_scale - 16; + int32_t dc01 = (c1 - c0)>>s; + int32_t dc02 = (c2 - c0)>>s; + // 16.16 x 16.16 == 32.32 + int64_t dcdx = gglMulii(dc01, m_dy02) + gglMulii(dc02, m_dy10); + int64_t dcdy = gglMulii(dc02, m_dx01) + gglMulii(dc01, m_dx20); + int32_t c = (c0<<16) - ((dcdx*m_x0 + dcdy*m_y0)>>4); + it[ 0] = c; + it[ 1] = dcdx; + it[ 2] = dcdy; +} +#endif + +// ---------------------------------------------------------------------------- + +static inline int32_t clampZ(GLfixed z) CONST; +int32_t clampZ(GLfixed z) { + z = (z & ~(z>>31)); + if (z >= 0x10000) + z = 0xFFFF; + return z; +} + +static __attribute__((noinline)) +void fetch_texcoord_impl(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + vertex_t* const vtx[3] = { v0, v1, v2 }; + array_t const * const texcoordArray = c->arrays.texture; + + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (!(c->rasterizer.state.texture[i].enable)) + continue; + + for (int j=0 ; j<3 ; j++) { + vertex_t* const v = vtx[j]; + if (v->flags & vertex_t::TT) + continue; + + // NOTE: here we could compute automatic texgen + // such as sphere/cube maps, instead of fetching them + // from the textcoord array. + + vec4_t& coords = v->texture[i]; + const GLubyte* tp = texcoordArray[i].element( + v->index & vertex_cache_t::INDEX_MASK); + texcoordArray[i].fetch(c, coords.v, tp); + + // transform texture coordinates... + coords.Q = 0x10000; + const transform_t& tr = c->transforms.texture[i].transform; + if (ggl_unlikely(tr.ops)) { + c->arrays.tex_transform[i](&tr, &coords, &coords); + } + + // divide by Q + const GGLfixed q = coords.Q; + if (ggl_unlikely(q != 0x10000)) { + const int32_t qinv = gglRecip28(q); + coords.S = gglMulx(coords.S, qinv, 28); + coords.T = gglMulx(coords.T, qinv, 28); + } + } + } + v0->flags |= vertex_t::TT; + v1->flags |= vertex_t::TT; + v2->flags |= vertex_t::TT; +} + +inline void fetch_texcoord(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + const uint32_t enables = c->rasterizer.state.enables; + if (!(enables & GGL_ENABLE_TMUS)) + return; + + // Fetch & transform texture coordinates... + if (ggl_likely(v0->flags & v1->flags & v2->flags & vertex_t::TT)) { + // already done for all three vertices, bail... + return; + } + fetch_texcoord_impl(c, v0, v1, v2); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Point +#endif + +void primitive_nop_point(ogles_context_t*, vertex_t*) { +} + +void primitive_point(ogles_context_t* c, vertex_t* v) +{ + // lighting & clamping... + const uint32_t enables = c->rasterizer.state.enables; + + if (ggl_unlikely(!(v->flags & vertex_t::LIT))) { + if (c->lighting.enable) { + c->lighting.lightVertex(c, v); + } else { + v->flags |= vertex_t::LIT; + const GLvoid* cp = c->arrays.color.element( + v->index & vertex_cache_t::INDEX_MASK); + c->arrays.color.fetch(c, v->color.v, cp); + } + if (enables & GGL_ENABLE_FOG) { + v->fog = c->fog.fog(c, v->window.z); + } + } + + // XXX: we don't need to do that each-time + // if color array and lighting not enabled + c->rasterizer.procs.color4xv(c, v->color.v); + + // XXX: look into ES point-sprite extension + if (enables & GGL_ENABLE_TMUS) { + fetch_texcoord(c, v,v,v); + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (!c->rasterizer.state.texture[i].enable) + continue; + int32_t itt[8]; + itt[1] = itt[2] = itt[4] = itt[5] = 0; + itt[6] = itt[7] = 16; // XXX: check that + if (c->rasterizer.state.texture[i].s_wrap == GGL_CLAMP) { + int width = c->textures.tmu[i].texture->surface.width; + itt[0] = v->texture[i].S * width; + itt[6] = 0; + } + if (c->rasterizer.state.texture[i].t_wrap == GGL_CLAMP) { + int height = c->textures.tmu[i].texture->surface.height; + itt[3] = v->texture[i].T * height; + itt[7] = 0; + } + c->rasterizer.procs.texCoordGradScale8xv(c, i, itt); + } + } + + if (enables & GGL_ENABLE_DEPTH_TEST) { + int32_t itz[3]; + itz[0] = clampZ(v->window.z) * 0x00010001; + itz[1] = itz[2] = 0; + c->rasterizer.procs.zGrad3xv(c, itz); + } + + if (enables & GGL_ENABLE_FOG) { + GLfixed itf[3]; + itf[0] = v->fog; + itf[1] = itf[2] = 0; + c->rasterizer.procs.fogGrad3xv(c, itf); + } + + // Render our point... + c->rasterizer.procs.pointx(c, v->window.v, c->point.size); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Line +#endif + +void primitive_nop_line(ogles_context_t*, vertex_t*, vertex_t*) { +} + +void primitive_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1) +{ + // This is a cheezy implementation of line drawing that + // uses 2 triangles per line. + // That said, how often line drawing is used? + + // get texture coordinates + fetch_texcoord(c, v0, v1, v1); + + // light/shade the vertices first (they're copied below) + c->lighting.lightTriangle(c, v0, v1, v1); + + vertex_t v[4]; + v[0] = *v0; + v[1] = *v1; + v0 = &v[0]; + v1 = &v[1]; + + // clip the line if needed + if (ggl_unlikely((v0->flags | v1->flags) & vertex_t::CLIP_ALL)) { + unsigned int count = clip_line(c, v0, v1); + if (ggl_unlikely(count == 0)) + return; + } + + // compute iterators... + const uint32_t enables = c->rasterizer.state.enables; + const uint32_t mask = GGL_ENABLE_TMUS | + GGL_ENABLE_SMOOTH | + GGL_ENABLE_W | + GGL_ENABLE_FOG | + GGL_ENABLE_DEPTH_TEST; + + if (ggl_unlikely(enables & mask)) { + c->lerp.initTriangle(v0, v1, v1); + lerp_triangle(c, v0, v1, v1); + } + + // render our line + c->rasterizer.procs.linex(c, v0->window.v, v1->window.v, c->line.width); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Triangle +#endif + +void primitive_nop_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) { +} + +void primitive_clip_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + uint32_t cc = (v0->flags | v1->flags | v2->flags) & vertex_t::CLIP_ALL; + if (ggl_likely(!cc)) { + // code below must be as optimized as possible, this is the + // common code path. + + // This triangle is not clipped, test if it's culled + // unclipped triangle... + c->lerp.initTriangle(v0, v1, v2); + if (cull_triangle(c, v0, v1, v2)) + return; // culled! + + // Fetch all texture coordinates if needed + fetch_texcoord(c, v0, v1, v2); + + // light (or shade) our triangle! + c->lighting.lightTriangle(c, v0, v1, v2); + + triangle(c, v0, v1, v2); + return; + } + + // The assumption here is that we're not going to clip very often, + // and even more rarely will we clip a triangle that ends up + // being culled out. So it's okay to light the vertices here, even though + // in a few cases we won't render the triangle (if culled). + + // Fetch texture coordinates... + fetch_texcoord(c, v0, v1, v2); + + // light (or shade) our triangle! + c->lighting.lightTriangle(c, v0, v1, v2); + + clip_triangle(c, v0, v1, v2); +} + +// ----------------------------------------------------------------------- + +void triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + // compute iterators... + const uint32_t enables = c->rasterizer.state.enables; + const uint32_t mask = GGL_ENABLE_TMUS | + GGL_ENABLE_SMOOTH | + GGL_ENABLE_W | + GGL_ENABLE_FOG | + GGL_ENABLE_DEPTH_TEST; + + if (ggl_likely(enables & mask)) + lerp_triangle(c, v0, v1, v2); + + c->rasterizer.procs.trianglex(c, v0->window.v, v1->window.v, v2->window.v); +} + +void lerp_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + const uint32_t enables = c->rasterizer.state.enables; + c->lerp.initLerp(v0, enables); + + // set up texture iterators + if (enables & GGL_ENABLE_TMUS) { + if (enables & GGL_ENABLE_W) { + lerp_texcoords_w(c, v0, v1, v2); + } else { + lerp_texcoords(c, v0, v1, v2); + } + } + + // set up the color iterators + const compute_iterators_t& lerp = c->lerp; + if (enables & GGL_ENABLE_SMOOTH) { + GLfixed itc[12]; + for (int i=0 ; i<4 ; i++) { + const GGLcolor c0 = v0->color.v[i] * 255; + const GGLcolor c1 = v1->color.v[i] * 255; + const GGLcolor c2 = v2->color.v[i] * 255; + lerp.iterators1616(&itc[i*3], c0, c1, c2); + } + c->rasterizer.procs.colorGrad12xv(c, itc); + } + + if (enables & GGL_ENABLE_DEPTH_TEST) { + int32_t itz[3]; + const int32_t v0z = clampZ(v0->window.z); + const int32_t v1z = clampZ(v1->window.z); + const int32_t v2z = clampZ(v2->window.z); + lerp.iterators0032(itz, v0z, v1z, v2z); + if (ggl_unlikely(c->polygonOffset.enable)) { + const GLfixed factor = c->polygonOffset.factor; + const GLfixed units = c->polygonOffset.units; + int32_t maxDepthSlope = max(abs(itz[1]), abs(itz[2])); + int32_t offset = (int64_t(maxDepthSlope)*factor + + (int64_t(units) << 16)) >> 16; + itz[0] += offset; // XXX: this can cause overflows + } + c->rasterizer.procs.zGrad3xv(c, itz); + } + + if (ggl_unlikely(enables & GGL_ENABLE_FOG)) { + GLfixed itf[3]; + lerp.iterators1616(itf, v0->fog, v1->fog, v2->fog); + c->rasterizer.procs.fogGrad3xv(c, itf); + } +} + + +static inline +int compute_lod(ogles_context_t* c, int i, + int32_t s0, int32_t t0, int32_t s1, int32_t t1, int32_t s2, int32_t t2) +{ + // Compute mipmap level / primitive + // rho = sqrt( texelArea / area ) + // lod = log2( rho ) + // lod = log2( texelArea / area ) / 2 + // lod = (log2( texelArea ) - log2( area )) / 2 + const compute_iterators_t& lerp = c->lerp; + const GGLcoord area = abs(lerp.area()); + const int w = c->textures.tmu[i].texture->surface.width; + const int h = c->textures.tmu[i].texture->surface.height; + const int shift = 16 + (16 - TRI_FRACTION_BITS); + int32_t texelArea = abs( gglMulx(s1-s0, t2-t0, shift) - + gglMulx(s2-s0, t1-t0, shift) )*w*h; + int log2TArea = (32-TRI_FRACTION_BITS -1) - gglClz(texelArea); + int log2Area = (32-TRI_FRACTION_BITS*2-1) - gglClz(area); + int lod = (log2TArea - log2Area + 1) >> 1; + return lod; +} + +void lerp_texcoords(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + const compute_iterators_t& lerp = c->lerp; + int32_t itt[8] __attribute__((aligned(16))); + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + const texture_t& tmu = c->rasterizer.state.texture[i]; + if (!tmu.enable) + continue; + + // compute the jacobians using block floating-point + int32_t s0 = v0->texture[i].S; + int32_t t0 = v0->texture[i].T; + int32_t s1 = v1->texture[i].S; + int32_t t1 = v1->texture[i].T; + int32_t s2 = v2->texture[i].S; + int32_t t2 = v2->texture[i].T; + + const GLenum min_filter = c->textures.tmu[i].texture->min_filter; + if (ggl_unlikely(min_filter >= GL_NEAREST_MIPMAP_NEAREST)) { + int lod = compute_lod(c, i, s0, t0, s1, t1, s2, t2); + c->rasterizer.procs.bindTextureLod(c, i, + &c->textures.tmu[i].texture->mip(lod)); + } + + // premultiply (s,t) when clampling + if (tmu.s_wrap == GGL_CLAMP) { + const int width = tmu.surface.width; + s0 *= width; + s1 *= width; + s2 *= width; + } + if (tmu.t_wrap == GGL_CLAMP) { + const int height = tmu.surface.height; + t0 *= height; + t1 *= height; + t2 *= height; + } + itt[6] = -lerp.iteratorsScale(itt+0, s0, s1, s2); + itt[7] = -lerp.iteratorsScale(itt+3, t0, t1, t2); + c->rasterizer.procs.texCoordGradScale8xv(c, i, itt); + } +} + +void lerp_texcoords_w(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + const compute_iterators_t& lerp = c->lerp; + int32_t itt[8] __attribute__((aligned(16))); + int32_t itw[3]; + + // compute W's scale to 2.30 + int32_t w0 = v0->window.w; + int32_t w1 = v1->window.w; + int32_t w2 = v2->window.w; + int wscale = 32 - gglClz(w0|w1|w2); + + // compute the jacobian using block floating-point + int sc = lerp.iteratorsScale(itw, w0, w1, w2); + sc += wscale - 16; + c->rasterizer.procs.wGrad3xv(c, itw); + + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + const texture_t& tmu = c->rasterizer.state.texture[i]; + if (!tmu.enable) + continue; + + // compute the jacobians using block floating-point + int32_t s0 = v0->texture[i].S; + int32_t t0 = v0->texture[i].T; + int32_t s1 = v1->texture[i].S; + int32_t t1 = v1->texture[i].T; + int32_t s2 = v2->texture[i].S; + int32_t t2 = v2->texture[i].T; + + const GLenum min_filter = c->textures.tmu[i].texture->min_filter; + if (ggl_unlikely(min_filter >= GL_NEAREST_MIPMAP_NEAREST)) { + int lod = compute_lod(c, i, s0, t0, s1, t1, s2, t2); + c->rasterizer.procs.bindTextureLod(c, i, + &c->textures.tmu[i].texture->mip(lod)); + } + + // premultiply (s,t) when clampling + if (tmu.s_wrap == GGL_CLAMP) { + const int width = tmu.surface.width; + s0 *= width; + s1 *= width; + s2 *= width; + } + if (tmu.t_wrap == GGL_CLAMP) { + const int height = tmu.surface.height; + t0 *= height; + t1 *= height; + t2 *= height; + } + + s0 = gglMulx(s0, w0, wscale); + t0 = gglMulx(t0, w0, wscale); + s1 = gglMulx(s1, w1, wscale); + t1 = gglMulx(t1, w1, wscale); + s2 = gglMulx(s2, w2, wscale); + t2 = gglMulx(t2, w2, wscale); + + itt[6] = sc - lerp.iteratorsScale(itt+0, s0, s1, s2); + itt[7] = sc - lerp.iteratorsScale(itt+3, t0, t1, t2); + c->rasterizer.procs.texCoordGradScale8xv(c, i, itt); + } +} + + +static inline +bool cull_triangle(ogles_context_t* c, vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + if (ggl_likely(c->cull.enable)) { + const GLenum winding = (c->lerp.area() > 0) ? GL_CW : GL_CCW; + const GLenum face = (winding == c->cull.frontFace) ? GL_FRONT : GL_BACK; + if (face == c->cull.cullFace) + return true; // culled! + } + return false; +} + +static inline +GLfixed frustumPlaneDist(int plane, const vec4_t& s) +{ + const GLfixed d = s.v[ plane >> 1 ]; + return ((plane & 1) ? (s.w - d) : (s.w + d)); +} + +static inline +int32_t clipDivide(GLfixed a, GLfixed b) { + // returns a 4.28 fixed-point + return gglMulDivi(1LU<<28, a, b); +} + +void clip_triangle(ogles_context_t* c, + vertex_t* v0, vertex_t* v1, vertex_t* v2) +{ + uint32_t all_cc = (v0->flags | v1->flags | v2->flags) & vertex_t::CLIP_ALL; + + vertex_t *p0, *p1, *p2; + const int MAX_CLIPPING_PLANES = 6 + OGLES_MAX_CLIP_PLANES; + const int MAX_VERTICES = 3; + + // Temporary buffer to hold the new vertices. Each plane can add up to + // two new vertices (because the polygon is convex). + // We need one extra element, to handle an overflow case when + // the polygon degenerates into something non convex. + vertex_t buffer[MAX_CLIPPING_PLANES * 2 + 1]; // ~3KB + vertex_t* buf = buffer; + + // original list of vertices (polygon to clip, in fact this + // function works with an arbitrary polygon). + vertex_t* in[3] = { v0, v1, v2 }; + + // output lists (we need 2, which we use back and forth) + // (maximum outpout list's size is MAX_CLIPPING_PLANES + MAX_VERTICES) + // 2 more elements for overflow when non convex polygons. + vertex_t* out[2][MAX_CLIPPING_PLANES + MAX_VERTICES + 2]; + unsigned int outi = 0; + + // current input list + vertex_t** ivl = in; + + // 3 input vertices, 0 in the output list, first plane + unsigned int ic = 3; + + // User clip-planes first, the clipping is always done in eye-coordinate + // this is basically the same algorithm than for the view-volume + // clipping, except for the computation of the distance (vertex, plane) + // and the fact that we need to compute the eye-coordinates of each + // new vertex we create. + + if (ggl_unlikely(all_cc & vertex_t::USER_CLIP_ALL)) + { + unsigned int plane = 0; + uint32_t cc = (all_cc & vertex_t::USER_CLIP_ALL) >> 8; + do { + if (cc & 1) { + // pointers to our output list (head and current) + vertex_t** const ovl = &out[outi][0]; + vertex_t** output = ovl; + unsigned int oc = 0; + unsigned int sentinel = 0; + // previous vertice, compute distance to the plane + vertex_t* s = ivl[ic-1]; + const vec4_t& equation = c->clipPlanes.plane[plane].equation; + GLfixed sd = dot4(equation.v, s->eye.v); + // clip each vertice against this plane... + for (unsigned int i=0 ; i<ic ; i++) { + vertex_t* p = ivl[i]; + const GLfixed pd = dot4(equation.v, p->eye.v); + if (sd >= 0) { + if (pd >= 0) { + // both inside + *output++ = p; + oc++; + } else { + // s inside, p outside (exiting) + const GLfixed t = clipDivide(sd, sd-pd); + c->arrays.clipEye(c, buf, t, p, s); + *output++ = buf++; + oc++; + if (++sentinel >= 3) + return; // non-convex polygon! + } + } else { + if (pd >= 0) { + // s outside (entering) + if (pd) { + const GLfixed t = clipDivide(pd, pd-sd); + c->arrays.clipEye(c, buf, t, s, p); + *output++ = buf++; + oc++; + if (++sentinel >= 3) + return; // non-convex polygon! + } + *output++ = p; + oc++; + } else { + // both outside + } + } + s = p; + sd = pd; + } + // output list become the new input list + if (oc<3) + return; // less than 3 vertices left? we're done! + ivl = ovl; + ic = oc; + outi = 1-outi; + } + cc >>= 1; + plane++; + } while (cc); + } + + // frustum clip-planes + if (all_cc & vertex_t::FRUSTUM_CLIP_ALL) + { + unsigned int plane = 0; + uint32_t cc = all_cc & vertex_t::FRUSTUM_CLIP_ALL; + do { + if (cc & 1) { + // pointers to our output list (head and current) + vertex_t** const ovl = &out[outi][0]; + vertex_t** output = ovl; + unsigned int oc = 0; + unsigned int sentinel = 0; + // previous vertice, compute distance to the plane + vertex_t* s = ivl[ic-1]; + GLfixed sd = frustumPlaneDist(plane, s->clip); + // clip each vertice against this plane... + for (unsigned int i=0 ; i<ic ; i++) { + vertex_t* p = ivl[i]; + const GLfixed pd = frustumPlaneDist(plane, p->clip); + if (sd >= 0) { + if (pd >= 0) { + // both inside + *output++ = p; + oc++; + } else { + // s inside, p outside (exiting) + const GLfixed t = clipDivide(sd, sd-pd); + c->arrays.clipVertex(c, buf, t, p, s); + *output++ = buf++; + oc++; + if (++sentinel >= 3) + return; // non-convex polygon! + } + } else { + if (pd >= 0) { + // s outside (entering) + if (pd) { + const GLfixed t = clipDivide(pd, pd-sd); + c->arrays.clipVertex(c, buf, t, s, p); + *output++ = buf++; + oc++; + if (++sentinel >= 3) + return; // non-convex polygon! + } + *output++ = p; + oc++; + } else { + // both outside + } + } + s = p; + sd = pd; + } + // output list become the new input list + if (oc<3) + return; // less than 3 vertices left? we're done! + ivl = ovl; + ic = oc; + outi = 1-outi; + } + cc >>= 1; + plane++; + } while (cc); + } + + // finally we can render our triangles... + p0 = ivl[0]; + p1 = ivl[1]; + for (unsigned int i=2 ; i<ic ; i++) { + p2 = ivl[i]; + c->lerp.initTriangle(p0, p1, p2); + if (cull_triangle(c, p0, p1, p2)) { + p1 = p2; + continue; // culled! + } + triangle(c, p0, p1, p2); + p1 = p2; + } +} + +unsigned int clip_line(ogles_context_t* c, vertex_t* s, vertex_t* p) +{ + const uint32_t all_cc = (s->flags | p->flags) & vertex_t::CLIP_ALL; + + if (ggl_unlikely(all_cc & vertex_t::USER_CLIP_ALL)) + { + unsigned int plane = 0; + uint32_t cc = (all_cc & vertex_t::USER_CLIP_ALL) >> 8; + do { + if (cc & 1) { + const vec4_t& equation = c->clipPlanes.plane[plane].equation; + const GLfixed sd = dot4(equation.v, s->eye.v); + const GLfixed pd = dot4(equation.v, p->eye.v); + if (sd >= 0) { + if (pd >= 0) { + // both inside + } else { + // s inside, p outside (exiting) + const GLfixed t = clipDivide(sd, sd-pd); + c->arrays.clipEye(c, p, t, p, s); + } + } else { + if (pd >= 0) { + // s outside (entering) + if (pd) { + const GLfixed t = clipDivide(pd, pd-sd); + c->arrays.clipEye(c, s, t, s, p); + } + } else { + // both outside + return 0; + } + } + } + cc >>= 1; + plane++; + } while (cc); + } + + // frustum clip-planes + if (all_cc & vertex_t::FRUSTUM_CLIP_ALL) + { + unsigned int plane = 0; + uint32_t cc = all_cc & vertex_t::FRUSTUM_CLIP_ALL; + do { + if (cc & 1) { + const GLfixed sd = frustumPlaneDist(plane, s->clip); + const GLfixed pd = frustumPlaneDist(plane, p->clip); + if (sd >= 0) { + if (pd >= 0) { + // both inside + } else { + // s inside, p outside (exiting) + const GLfixed t = clipDivide(sd, sd-pd); + c->arrays.clipVertex(c, p, t, p, s); + } + } else { + if (pd >= 0) { + // s outside (entering) + if (pd) { + const GLfixed t = clipDivide(pd, pd-sd); + c->arrays.clipVertex(c, s, t, s, p); + } + } else { + // both outside + return 0; + } + } + } + cc >>= 1; + plane++; + } while (cc); + } + + return 2; +} + + +}; // namespace android diff --git a/opengl/libagl/primitives.h b/opengl/libagl/primitives.h new file mode 100644 index 0000000..1bef604 --- /dev/null +++ b/opengl/libagl/primitives.h @@ -0,0 +1,37 @@ +/* libs/opengles/primitives.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_PRIMITIVES_H +#define ANDROID_OPENGLES_PRIMITIVES_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + + +namespace android { + +namespace gl { +struct ogles_context_t; +}; + +void ogles_validate_primitives(ogles_context_t* c); + +}; // namespace android + +#endif // ANDROID_OPENGLES_PRIMITIVES_H + diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp new file mode 100644 index 0000000..c2f9f12 --- /dev/null +++ b/opengl/libagl/state.cpp @@ -0,0 +1,592 @@ +/* libs/opengles/state.cpp +** +** Copyright 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. +*/ + +#include <stdlib.h> + +#include "context.h" +#include "fp.h" +#include "state.h" +#include "array.h" +#include "matrix.h" +#include "vertex.h" +#include "light.h" +#include "texture.h" +#include "BufferObjectManager.h" +#include "TextureObjectManager.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +static char const * const gVendorString = "Android"; +static char const * const gRendererString = "Android PixelFlinger 1.0"; +static char const * const gVersionString = "OpenGL ES-CM 1.0"; +static char const * const gExtensionsString = + "GL_OES_byte_coordinates " // OK + "GL_OES_fixed_point " // OK + "GL_OES_single_precision " // OK + "GL_OES_read_format " // OK + "GL_OES_compressed_paletted_texture " // OK + "GL_OES_draw_texture " // OK + "GL_OES_matrix_get " // OK + "GL_OES_query_matrix " // OK + // "GL_OES_point_size_array " // TODO + // "GL_OES_point_sprite " // TODO + "GL_ARB_texture_compression " // OK + "GL_ARB_texture_non_power_of_two " // OK + "GL_ANDROID_direct_texture " // OK + "GL_ANDROID_user_clip_plane " // OK + "GL_ANDROID_vertex_buffer_object " // OK + "GL_ANDROID_generate_mipmap " // OK + ; + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +ogles_context_t *ogles_init(size_t extra) +{ + void* const base = malloc(extra + sizeof(ogles_context_t) + 32); + if (!base) return 0; + + ogles_context_t *c = + (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL); + memset(c, 0, sizeof(ogles_context_t)); + ggl_init_context(&(c->rasterizer)); + + // XXX: this should be passed as an argument + sp<EGLSurfaceManager> smgr(new EGLSurfaceManager()); + c->surfaceManager = smgr.get(); + c->surfaceManager->incStrong(c); + + sp<EGLBufferObjectManager> bomgr(new EGLBufferObjectManager()); + c->bufferObjectManager = bomgr.get(); + c->bufferObjectManager->incStrong(c); + + ogles_init_array(c); + ogles_init_matrix(c); + ogles_init_vertex(c); + ogles_init_light(c); + ogles_init_texture(c); + + c->rasterizer.base = base; + c->point.size = TRI_ONE; + c->line.width = TRI_ONE; + + // in OpenGL, writing to the depth buffer is enabled by default. + c->rasterizer.procs.depthMask(c, 1); + + // OpenGL enables dithering by default + c->rasterizer.procs.enable(c, GL_DITHER); + + return c; +} + +void ogles_uninit(ogles_context_t* c) +{ + ogles_uninit_array(c); + ogles_uninit_matrix(c); + ogles_uninit_vertex(c); + ogles_uninit_light(c); + ogles_uninit_texture(c); + c->surfaceManager->decStrong(c); + c->bufferObjectManager->decStrong(c); + ggl_uninit_context(&(c->rasterizer)); + free(c->rasterizer.base); +} + +void _ogles_error(ogles_context_t* c, GLenum error) +{ + if (c->error == GL_NO_ERROR) + c->error = error; +} + +static bool stencilop_valid(GLenum op) { + switch (op) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + return true; + } + return false; +} + +static void enable_disable(ogles_context_t* c, GLenum cap, int enabled) +{ + if ((cap >= GL_LIGHT0) && (cap<GL_LIGHT0+OGLES_MAX_LIGHTS)) { + c->lighting.lights[cap-GL_LIGHT0].enable = enabled; + c->lighting.enabledLights &= ~(1<<(cap-GL_LIGHT0)); + c->lighting.enabledLights |= (enabled<<(cap-GL_LIGHT0)); + return; + } + + switch (cap) { + case GL_POINT_SMOOTH: + c->point.smooth = enabled; + break; + case GL_LINE_SMOOTH: + c->line.smooth = enabled; + break; + case GL_POLYGON_OFFSET_FILL: + c->polygonOffset.enable = enabled; + break; + case GL_CULL_FACE: + c->cull.enable = enabled; + break; + case GL_LIGHTING: + c->lighting.enable = enabled; + break; + case GL_COLOR_MATERIAL: + c->lighting.colorMaterial.enable = enabled; + break; + case GL_NORMALIZE: + case GL_RESCALE_NORMAL: + c->transforms.rescaleNormals = enabled ? cap : 0; + // XXX: invalidate mvit + break; + + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + c->clipPlanes.enable &= ~(1<<(cap-GL_CLIP_PLANE0)); + c->clipPlanes.enable |= (enabled<<(cap-GL_CLIP_PLANE0)); + ogles_invalidate_perspective(c); + break; + + case GL_FOG: + case GL_DEPTH_TEST: + ogles_invalidate_perspective(c); + // fall-through... + case GL_BLEND: + case GL_SCISSOR_TEST: + case GL_ALPHA_TEST: + case GL_COLOR_LOGIC_OP: + case GL_DITHER: + case GL_STENCIL_TEST: + case GL_TEXTURE_2D: + // these need to fall through into the rasterizer + c->rasterizer.procs.enableDisable(c, cap, enabled); + break; + + case GL_MULTISAMPLE: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_ALPHA_TO_ONE: + case GL_SAMPLE_COVERAGE: + // not supported in this implementation + break; + + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- +using namespace android; + +#if 0 +#pragma mark - +#endif + +// These ones are super-easy, we're not supporting those features! +void glSampleCoverage(GLclampf value, GLboolean invert) { +} +void glSampleCoveragex(GLclampx value, GLboolean invert) { +} +void glStencilFunc(GLenum func, GLint ref, GLuint mask) { + ogles_context_t* c = ogles_context_t::get(); + if (func < GL_NEVER || func > GL_ALWAYS) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + // from OpenGL|ES 1.0 sepcification: + // If there is no stencil buffer, no stencil modification can occur + // and it is as if the stencil test always passes. +} + +void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) { + ogles_context_t* c = ogles_context_t::get(); + if ((stencilop_valid(fail) & + stencilop_valid(zfail) & + stencilop_valid(zpass)) == 0) { + ogles_error(c, GL_INVALID_ENUM); + return; + } +} + +// ---------------------------------------------------------------------------- + +void glAlphaFunc(GLenum func, GLclampf ref) +{ + glAlphaFuncx(func, gglFloatToFixed(ref)); +} + +void glCullFace(GLenum mode) +{ + ogles_context_t* c = ogles_context_t::get(); + switch (mode) { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + } + c->cull.cullFace = mode; +} + +void glFrontFace(GLenum mode) +{ + ogles_context_t* c = ogles_context_t::get(); + switch (mode) { + case GL_CW: + case GL_CCW: + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->cull.frontFace = mode; +} + +void glHint(GLenum target, GLenum mode) +{ + ogles_context_t* c = ogles_context_t::get(); + switch (target) { + case GL_FOG_HINT: + case GL_GENERATE_MIPMAP_HINT: + case GL_LINE_SMOOTH_HINT: + break; + case GL_POINT_SMOOTH_HINT: + c->rasterizer.procs.enableDisable(c, + GGL_POINT_SMOOTH_NICE, mode==GL_NICEST); + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + c->perspective = (mode == GL_NICEST) ? 1 : 0; + break; + default: + ogles_error(c, GL_INVALID_ENUM); + } +} + +void glEnable(GLenum cap) { + ogles_context_t* c = ogles_context_t::get(); + enable_disable(c, cap, 1); +} +void glDisable(GLenum cap) { + ogles_context_t* c = ogles_context_t::get(); + enable_disable(c, cap, 0); +} + +void glFinish() +{ // nothing to do for our software implementation +} + +void glFlush() +{ // nothing to do for our software implementation +} + +GLenum glGetError() +{ + // From OpenGL|ES 1.0 specification: + // If more than one flag has recorded an error, glGetError returns + // and clears an arbitrary error flag value. Thus, glGetError should + // always be called in a loop, until it returns GL_NO_ERROR, + // if all error flags are to be reset. + + ogles_context_t* c = ogles_context_t::get(); + if (c->error) { + const GLenum ret(c->error); + c->error = 0; + return ret; + } + + if (c->rasterizer.error) { + const GLenum ret(c->rasterizer.error); + c->rasterizer.error = 0; + return ret; + } + + return GL_NO_ERROR; +} + +const GLubyte* glGetString(GLenum string) +{ + switch (string) { + case GL_VENDOR: return (const GLubyte*)gVendorString; + case GL_RENDERER: return (const GLubyte*)gRendererString; + case GL_VERSION: return (const GLubyte*)gVersionString; + case GL_EXTENSIONS: return (const GLubyte*)gExtensionsString; + } + ogles_context_t* c = ogles_context_t::get(); + ogles_error(c, GL_INVALID_ENUM); + return 0; +} + +void glGetIntegerv(GLenum pname, GLint *params) +{ + ogles_context_t* c = ogles_context_t::get(); + switch (pname) { + case GL_ALIASED_POINT_SIZE_RANGE: + params[0] = 0; + params[1] = GGL_MAX_ALIASED_POINT_SIZE; + break; + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = 0; + params[1] = GGL_MAX_ALIASED_POINT_SIZE; + break; + case GL_ALPHA_BITS: { + int index = c->rasterizer.state.buffers.color.format; + GGLFormat const * formats = gglGetPixelFormatTable(); + params[0] = formats[index].ah - formats[index].al; + break; + } + case GL_RED_BITS: { + int index = c->rasterizer.state.buffers.color.format; + GGLFormat const * formats = gglGetPixelFormatTable(); + params[0] = formats[index].rh - formats[index].rl; + break; + } + case GL_GREEN_BITS: { + int index = c->rasterizer.state.buffers.color.format; + GGLFormat const * formats = gglGetPixelFormatTable(); + params[0] = formats[index].gh - formats[index].gl; + break; + } + case GL_BLUE_BITS: { + int index = c->rasterizer.state.buffers.color.format; + GGLFormat const * formats = gglGetPixelFormatTable(); + params[0] = formats[index].bh - formats[index].bl; + break; + } + case GL_COMPRESSED_TEXTURE_FORMATS: + params[ 0] = GL_PALETTE4_RGB8_OES; + params[ 1] = GL_PALETTE4_RGBA8_OES; + params[ 2] = GL_PALETTE4_R5_G6_B5_OES; + params[ 3] = GL_PALETTE4_RGBA4_OES; + params[ 4] = GL_PALETTE4_RGB5_A1_OES; + params[ 5] = GL_PALETTE8_RGB8_OES; + params[ 6] = GL_PALETTE8_RGBA8_OES; + params[ 7] = GL_PALETTE8_R5_G6_B5_OES; + params[ 8] = GL_PALETTE8_RGBA4_OES; + params[ 9] = GL_PALETTE8_RGB5_A1_OES; + break; + case GL_DEPTH_BITS: + params[0] = c->rasterizer.state.buffers.depth.format ? 0 : 16; + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + params[0] = GL_RGB; + break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + params[0] = GL_UNSIGNED_SHORT_5_6_5; + break; + case GL_MAX_ELEMENTS_INDICES: + params[0] = 65536; + break; + case GL_MAX_ELEMENTS_VERTICES: + params[0] = 0x7FFFFFFF; + break; + case GL_MAX_LIGHTS: + params[0] = OGLES_MAX_LIGHTS; + break; + case GL_MAX_CLIP_PLANES: + params[0] = OGLES_MAX_CLIP_PLANES; + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + params[0] = OGLES_MODELVIEW_STACK_DEPTH; + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + params[0] = OGLES_PROJECTION_STACK_DEPTH; + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + params[0] = OGLES_TEXTURE_STACK_DEPTH; + break; + case GL_MAX_TEXTURE_SIZE: + params[0] = GGL_MAX_TEXTURE_SIZE; + break; + case GL_MAX_TEXTURE_UNITS: + params[0] = GGL_TEXTURE_UNIT_COUNT; + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = GGL_MAX_VIEWPORT_DIMS; + params[1] = GGL_MAX_VIEWPORT_DIMS; + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + params[0] = OGLES_NUM_COMPRESSED_TEXTURE_FORMATS; + break; + case GL_SMOOTH_LINE_WIDTH_RANGE: + params[0] = 0; + params[1] = GGL_MAX_SMOOTH_LINE_WIDTH; + break; + case GL_SMOOTH_POINT_SIZE_RANGE: + params[0] = 0; + params[1] = GGL_MAX_SMOOTH_POINT_SIZE; + break; + case GL_STENCIL_BITS: + params[0] = 0; + break; + case GL_SUBPIXEL_BITS: + params[0] = GGL_SUBPIXEL_BITS; + break; + + case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES: + memcpy( params, + c->transforms.modelview.top().elements(), + 16*sizeof(GLint)); + break; + case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES: + memcpy( params, + c->transforms.projection.top().elements(), + 16*sizeof(GLint)); + break; + case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES: + memcpy( params, + c->transforms.texture[c->textures.active].top().elements(), + 16*sizeof(GLint)); + break; + + default: + ogles_error(c, GL_INVALID_ENUM); + break; + } +} + +// ---------------------------------------------------------------------------- + +void glPointSize(GLfloat size) +{ + ogles_context_t* c = ogles_context_t::get(); + if (size <= 0) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->point.size = TRI_FROM_FIXED(gglFloatToFixed(size)); +} + +void glPointSizex(GLfixed size) +{ + ogles_context_t* c = ogles_context_t::get(); + if (size <= 0) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->point.size = TRI_FROM_FIXED(size); +} + +// ---------------------------------------------------------------------------- + +void glLineWidth(GLfloat width) +{ + ogles_context_t* c = ogles_context_t::get(); + if (width <= 0) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->line.width = TRI_FROM_FIXED(gglFloatToFixed(width)); +} + +void glLineWidthx(GLfixed width) +{ + ogles_context_t* c = ogles_context_t::get(); + if (width <= 0) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->line.width = TRI_FROM_FIXED(width); +} + +// ---------------------------------------------------------------------------- + +void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.colorMask(c, r, g, b, a); +} + +void glDepthMask(GLboolean flag) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.depthMask(c, flag); +} + +void glStencilMask(GLuint mask) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.stencilMask(c, mask); +} + +void glDepthFunc(GLenum func) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.depthFunc(c, func); +} + +void glLogicOp(GLenum opcode) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.logicOp(c, opcode); +} + +void glAlphaFuncx(GLenum func, GLclampx ref) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.alphaFuncx(c, func, ref); +} + +void glBlendFunc(GLenum sfactor, GLenum dfactor) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.blendFunc(c, sfactor, dfactor); +} + +void glClear(GLbitfield mask) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.clear(c, mask); +} + +void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.clearColorx(c, red, green, blue, alpha); +} + +void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) +{ + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.clearColorx(c, + gglFloatToFixed(r), + gglFloatToFixed(g), + gglFloatToFixed(b), + gglFloatToFixed(a)); +} + +void glClearDepthx(GLclampx depth) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.clearDepthx(c, depth); +} + +void glClearDepthf(GLclampf depth) +{ + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth)); +} + +void glClearStencil(GLint s) { + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.clearStencil(c, s); +} diff --git a/opengl/libagl/state.h b/opengl/libagl/state.h new file mode 100644 index 0000000..55a5ccb --- /dev/null +++ b/opengl/libagl/state.h @@ -0,0 +1,54 @@ +/* libs/opengles/state.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_STATE_H +#define ANDROID_OPENGLES_STATE_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +#include <private/pixelflinger/ggl_context.h> + +#include <GLES/gl.h> + +#include <stdio.h> + +namespace android { + +ogles_context_t *ogles_init(size_t extra); +void ogles_uninit(ogles_context_t* c); +void _ogles_error(ogles_context_t* c, GLenum error); + +#ifndef TRACE_GL_ERRORS +#define TRACE_GL_ERRORS 0 +#endif + +#if TRACE_GL_ERRORS +#define ogles_error(c, error) \ +do { \ + printf("ogles_error at file %s line %d\n", __FILE__, __LINE__); \ + _ogles_error(c, error); \ +} while (0) +#else /* !TRACE_GL_ERRORS */ +#define ogles_error(c, error) _ogles_error((c), (error)) +#endif + +}; // namespace android + +#endif // ANDROID_OPENGLES_STATE_H + diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp new file mode 100644 index 0000000..6b2640a --- /dev/null +++ b/opengl/libagl/texture.cpp @@ -0,0 +1,1423 @@ +/* libs/opengles/texture.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "context.h" +#include "fp.h" +#include "state.h" +#include "texture.h" +#include "TextureObjectManager.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +static void bindTextureTmu( + ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex); + +static __attribute__((noinline)) +void generateMipmap(ogles_context_t* c, GLint level); + +// ---------------------------------------------------------------------------- + +#if 0 +#pragma mark - +#pragma mark Init +#endif + +void ogles_init_texture(ogles_context_t* c) +{ + c->textures.packAlignment = 4; + c->textures.unpackAlignment = 4; + + // each context has a default named (0) texture (not shared) + c->textures.defaultTexture = new EGLTextureObject(); + c->textures.defaultTexture->incStrong(c); + + // bind the default texture to each texture unit + for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + bindTextureTmu(c, i, 0, c->textures.defaultTexture); + memset(c->current.texture[i].v, 0, sizeof(vec4_t)); + c->current.texture[i].Q = 0x10000; + } +} + +void ogles_uninit_texture(ogles_context_t* c) +{ + if (c->textures.ggl) + gglUninit(c->textures.ggl); + c->textures.defaultTexture->decStrong(c); + for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (c->textures.tmu[i].texture) + c->textures.tmu[i].texture->decStrong(c); + } +} + +static __attribute__((noinline)) +void validate_tmu(ogles_context_t* c, int i) +{ + texture_unit_t& u(c->textures.tmu[i]); + if (u.dirty) { + u.dirty = 0; + c->rasterizer.procs.activeTexture(c, i); + c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); + c->rasterizer.procs.texGeni(c, GGL_S, + GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); + c->rasterizer.procs.texGeni(c, GGL_T, + GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); + c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, + GGL_TEXTURE_WRAP_S, u.texture->wraps); + c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, + GGL_TEXTURE_WRAP_T, u.texture->wrapt); + c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, + GGL_TEXTURE_MIN_FILTER, u.texture->min_filter); + c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, + GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter); + + // disable this texture unit if it's not complete + if (!u.texture->isComplete()) { + c->rasterizer.procs.disable(c, GGL_TEXTURE_2D); + } + } +} + +void ogles_validate_texture_impl(ogles_context_t* c) +{ + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (c->rasterizer.state.texture[i].enable) + validate_tmu(c, i); + } + c->rasterizer.procs.activeTexture(c, c->textures.active); +} + +static +void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) { + c->textures.tmu[tmu].dirty = flags; +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Format conversion +#endif + +static uint32_t gl2format_table[6][4] = { + // BYTE, 565, 4444, 5551 + { GGL_PIXEL_FORMAT_A_8, + 0, 0, 0 }, // GL_ALPHA + { GGL_PIXEL_FORMAT_RGB_888, + GGL_PIXEL_FORMAT_RGB_565, + 0, 0 }, // GL_RGB + { GGL_PIXEL_FORMAT_RGBA_8888, + 0, + GGL_PIXEL_FORMAT_RGBA_4444, + GGL_PIXEL_FORMAT_RGBA_5551 }, // GL_RGBA + { GGL_PIXEL_FORMAT_L_8, + 0, 0, 0 }, // GL_LUMINANCE + { GGL_PIXEL_FORMAT_LA_88, + 0, 0, 0 }, // GL_LUMINANCE_ALPHA +}; + +static int32_t convertGLPixelFormat(GLint format, GLenum type) +{ + int32_t fi = -1; + int32_t ti = -1; + switch (format) { + case GL_ALPHA: fi = 0; break; + case GL_RGB: fi = 1; break; + case GL_RGBA: fi = 2; break; + case GL_LUMINANCE: fi = 3; break; + case GL_LUMINANCE_ALPHA: fi = 4; break; + } + switch (type) { + case GL_UNSIGNED_BYTE: ti = 0; break; + case GL_UNSIGNED_SHORT_5_6_5: ti = 1; break; + case GL_UNSIGNED_SHORT_4_4_4_4: ti = 2; break; + case GL_UNSIGNED_SHORT_5_5_5_1: ti = 3; break; + } + if (fi==-1 || ti==-1) + return 0; + return gl2format_table[fi][ti]; +} + +// ---------------------------------------------------------------------------- + +static GLenum validFormatType(ogles_context_t* c, GLenum format, GLenum type) +{ + GLenum error = 0; + if (format<GL_ALPHA || format>GL_LUMINANCE_ALPHA) { + error = GL_INVALID_ENUM; + } + if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT_4_4_4_4 && + type != GL_UNSIGNED_SHORT_5_5_5_1 && type != GL_UNSIGNED_SHORT_5_6_5) { + error = GL_INVALID_ENUM; + } + if (type == GL_UNSIGNED_SHORT_5_6_5 && format != GL_RGB) { + error = GL_INVALID_OPERATION; + } + if ((type == GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL_UNSIGNED_SHORT_5_5_5_1) && format != GL_RGBA) { + error = GL_INVALID_OPERATION; + } + if (error) { + ogles_error(c, error); + } + return error; +} + +// ---------------------------------------------------------------------------- + +GGLContext* getRasterizer(ogles_context_t* c) +{ + GGLContext* ggl = c->textures.ggl; + if (ggl_unlikely(!ggl)) { + // this is quite heavy the first time... + gglInit(&ggl); + if (!ggl) { + return 0; + } + GGLfixed colors[4] = { 0, 0, 0, 0x10000 }; + c->textures.ggl = ggl; + ggl->activeTexture(ggl, 0); + ggl->enable(ggl, GGL_TEXTURE_2D); + ggl->texEnvi(ggl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); + ggl->disable(ggl, GGL_DITHER); + ggl->shadeModel(ggl, GGL_FLAT); + ggl->color4xv(ggl, colors); + } + return ggl; +} + +static __attribute__((noinline)) +int copyPixels( + ogles_context_t* c, + const GGLSurface& dst, + GLint xoffset, GLint yoffset, + const GGLSurface& src, + GLint x, GLint y, GLsizei w, GLsizei h) +{ + if ((dst.format == src.format) && + (dst.stride == src.stride) && + (dst.width == src.width) && + (dst.height == src.height) && + (dst.stride > 0) && + ((x|y) == 0) && + ((xoffset|yoffset) == 0)) + { + // this is a common case... + const GGLFormat& pixelFormat(c->rasterizer.formats[src.format]); + const size_t size = src.height * src.stride * pixelFormat.size; + memcpy(dst.data, src.data, size); + return 0; + } + + // use pixel-flinger to handle all the conversions + GGLContext* ggl = getRasterizer(c); + if (!ggl) { + // the only reason this would fail is because we ran out of memory + return GL_OUT_OF_MEMORY; + } + + ggl->colorBuffer(ggl, &dst); + ggl->bindTexture(ggl, &src); + ggl->texCoord2i(ggl, x-xoffset, y-yoffset); + ggl->recti(ggl, xoffset, yoffset, xoffset+w, yoffset+h); + return 0; +} + +// ---------------------------------------------------------------------------- + +static __attribute__((noinline)) +sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) +{ + sp<EGLTextureObject> tex; + const int active = c->textures.active; + const GLuint name = c->textures.tmu[active].name; + + // free the reference to the previously bound object + texture_unit_t& u(c->textures.tmu[active]); + if (u.texture) + u.texture->decStrong(c); + + if (name == 0) { + // 0 is our local texture object, not shared with anyone. + // But it affects all bound TMUs immediately. + // (we need to invalidate all units bound to this texture object) + tex = c->textures.defaultTexture; + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (c->textures.tmu[i].texture == tex.get()) + invalidate_texture(c, i); + } + } else { + // get a new texture object for that name + tex = c->surfaceManager->replaceTexture(name); + } + + // bind this texture to the current active texture unit + // and add a reference to this texture object + u.texture = tex.get(); + u.texture->incStrong(c); + u.name = name; + invalidate_texture(c, active); + return tex; +} + +void bindTextureTmu( + ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex) +{ + if (tex.get() == c->textures.tmu[tmu].texture) + return; + + // free the reference to the previously bound object + texture_unit_t& u(c->textures.tmu[tmu]); + if (u.texture) + u.texture->decStrong(c); + + // bind this texture to the current active texture unit + // and add a reference to this texture object + u.texture = tex.get(); + u.texture->incStrong(c); + u.name = texture; + invalidate_texture(c, tmu); +} + +int createTextureSurface(ogles_context_t* c, + GGLSurface** outSurface, int32_t* outSize, GLint level, + GLenum format, GLenum type, GLsizei width, GLsizei height, + GLenum compressedFormat = 0) +{ + // find out which texture is bound to the current unit + const int active = c->textures.active; + const GLuint name = c->textures.tmu[active].name; + + // convert the pixelformat to one we can handle + const int32_t formatIdx = convertGLPixelFormat(format, type); + if (formatIdx == 0) { // we don't know what to do with this + return GL_INVALID_OPERATION; + } + + // figure out the size we need as well as the stride + const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); + const int32_t align = c->textures.unpackAlignment-1; + const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; + const size_t size = bpr * height; + const int32_t stride = bpr / pixelFormat.size; + + if (level > 0) { + const int active = c->textures.active; + EGLTextureObject* tex = c->textures.tmu[active].texture; + status_t err = tex->reallocate(level, + width, height, stride, formatIdx, compressedFormat, bpr); + if (err != NO_ERROR) + return GL_OUT_OF_MEMORY; + GGLSurface& surface = tex->editMip(level); + *outSurface = &surface; + *outSize = size; + return 0; + } + + sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); + status_t err = tex->reallocate(level, + width, height, stride, formatIdx, compressedFormat, bpr); + if (err != NO_ERROR) + return GL_OUT_OF_MEMORY; + + tex->internalformat = format; + *outSurface = &tex->surface; + *outSize = size; + return 0; +} + +static void decodePalette4(const GLvoid *data, int level, int width, int height, + void *surface, int stride, int format) + +{ + int indexBits = 8; + int entrySize = 0; + switch (format) { + case GL_PALETTE4_RGB8_OES: + indexBits = 4; + /* FALLTHROUGH */ + case GL_PALETTE8_RGB8_OES: + entrySize = 3; + break; + + case GL_PALETTE4_RGBA8_OES: + indexBits = 4; + /* FALLTHROUGH */ + case GL_PALETTE8_RGBA8_OES: + entrySize = 4; + break; + + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + indexBits = 4; + /* FALLTHROUGH */ + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + entrySize = 2; + break; + } + + const int paletteSize = (1 << indexBits) * entrySize; + uint8_t const* pixels = (uint8_t *)data + paletteSize; + for (int i=0 ; i<level ; i++) { + int w = (width >> i) ? : 1; + int h = (height >> i) ? : 1; + pixels += h * ((w * indexBits) / 8); + } + width = (width >> level) ? : 1; + height = (height >> level) ? : 1; + + if (entrySize == 2) { + uint8_t const* const palette = (uint8_t*)data; + for (int y=0 ; y<height ; y++) { + uint8_t* p = (uint8_t*)surface + y*stride*2; + if (indexBits == 8) { + for (int x=0 ; x<width ; x++) { + int index = 2 * (*pixels++); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + } + } else { + for (int x=0 ; x<width ; x+=2) { + int v = *pixels++; + int index = 2 * (v >> 4); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + if (x+1 < width) { + index = 2 * (v & 0xF); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + } + } + } + } + } else if (entrySize == 3) { + uint8_t const* const palette = (uint8_t*)data; + for (int y=0 ; y<height ; y++) { + uint8_t* p = (uint8_t*)surface + y*stride*3; + if (indexBits == 8) { + for (int x=0 ; x<width ; x++) { + int index = 3 * (*pixels++); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + *p++ = palette[index + 2]; + } + } else { + for (int x=0 ; x<width ; x+=2) { + int v = *pixels++; + int index = 3 * (v >> 4); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + *p++ = palette[index + 2]; + if (x+1 < width) { + index = 3 * (v & 0xF); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + *p++ = palette[index + 2]; + } + } + } + } + } else if (entrySize == 4) { + uint8_t const* const palette = (uint8_t*)data; + for (int y=0 ; y<height ; y++) { + uint8_t* p = (uint8_t*)surface + y*stride*4; + if (indexBits == 8) { + for (int x=0 ; x<width ; x++) { + int index = 4 * (*pixels++); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + *p++ = palette[index + 2]; + *p++ = palette[index + 3]; + } + } else { + for (int x=0 ; x<width ; x+=2) { + int v = *pixels++; + int index = 4 * (v >> 4); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + *p++ = palette[index + 2]; + *p++ = palette[index + 3]; + if (x+1 < width) { + index = 4 * (v & 0xF); + *p++ = palette[index + 0]; + *p++ = palette[index + 1]; + *p++ = palette[index + 2]; + *p++ = palette[index + 3]; + } + } + } + } + } +} + + + +static __attribute__((noinline)) +void set_depth_and_fog(ogles_context_t* c, GLint z) +{ + const uint32_t enables = c->rasterizer.state.enables; + // we need to compute Zw + int32_t iterators[3]; + iterators[1] = iterators[2] = 0; + GGLfixed Zw; + GGLfixed n = gglFloatToFixed(c->transforms.vpt.zNear); + GGLfixed f = gglFloatToFixed(c->transforms.vpt.zFar); + if (z<=0) Zw = n; + else if (z>=1) Zw = f; + else Zw = gglMulAddx(z, (f-n), n); + if (enables & GGL_ENABLE_FOG) { + // set up fog if needed... + iterators[0] = c->fog.fog(c, Zw); + c->rasterizer.procs.fogGrad3xv(c, iterators); + } + if (enables & GGL_ENABLE_DEPTH_TEST) { + // set up z-test if needed... + int32_t z = (Zw & ~(Zw>>31)); + if (z >= 0x10000) + z = 0xFFFF; + iterators[0] = (z << 16) | z; + c->rasterizer.procs.zGrad3xv(c, iterators); + } +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark Generate mimaps +#endif + +extern status_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex); + +void generateMipmap(ogles_context_t* c, GLint level) +{ + if (level == 0) { + const int active = c->textures.active; + EGLTextureObject* tex = c->textures.tmu[active].texture; + if (tex->generate_mipmap) { + if (buildAPyramid(c, tex) != NO_ERROR) { + ogles_error(c, GL_OUT_OF_MEMORY); + return; + } + } + } +} + + +static void texParameterx( + GLenum target, GLenum pname, GLfixed param, ogles_context_t* c) +{ + if (target != GGL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; + switch (pname) { + case GL_TEXTURE_WRAP_S: + if ((param == GL_CLAMP) || + (param == GL_REPEAT) || + (param == GL_CLAMP_TO_EDGE)) { + textureObject->wraps = param; + } else { + goto invalid_enum; + } + break; + case GL_TEXTURE_WRAP_T: + if ((param == GGL_CLAMP) || + (param == GGL_REPEAT) || + (param == GGL_CLAMP_TO_EDGE)) { + textureObject->wrapt = param; + } else { + goto invalid_enum; + } + break; + case GL_TEXTURE_MIN_FILTER: + if ((param == GL_NEAREST) || + (param == GL_LINEAR) || + (param == GL_NEAREST_MIPMAP_NEAREST) || + (param == GL_LINEAR_MIPMAP_NEAREST) || + (param == GL_NEAREST_MIPMAP_LINEAR) || + (param == GL_LINEAR_MIPMAP_LINEAR)) { + textureObject->min_filter = param; + } else { + goto invalid_enum; + } + break; + case GL_TEXTURE_MAG_FILTER: + if ((param == GL_NEAREST) || + (param == GL_LINEAR)) { + textureObject->mag_filter = param; + } else { + goto invalid_enum; + } + break; + case GL_GENERATE_MIPMAP: + textureObject->generate_mipmap = param; + break; + default: +invalid_enum: + ogles_error(c, GL_INVALID_ENUM); + return; + } + invalidate_texture(c, c->textures.active); +} + + +static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, + ogles_context_t* c) +{ + // quickly reject empty rects + if ((w|h) <= 0) + return; + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + y = gglIntToFixed(cbSurface.height) - (y + h); + w >>= FIXED_BITS; + h >>= FIXED_BITS; + + // set up all texture units + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (!c->rasterizer.state.texture[i].enable) + continue; + + int32_t texcoords[8]; + texture_unit_t& u(c->textures.tmu[i]); + + // validate this tmu (bind, wrap, filter) + validate_tmu(c, i); + // we CLAMP here, which works with premultiplied (s,t) + c->rasterizer.procs.texParameteri(c, + GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP); + c->rasterizer.procs.texParameteri(c, + GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); + u.dirty = 0xFF; // XXX: should be more subtle + + EGLTextureObject* textureObject = u.texture; + const GLint Ucr = textureObject->crop_rect[0] << 16; + const GLint Vcr = textureObject->crop_rect[1] << 16; + const GLint Wcr = textureObject->crop_rect[2] << 16; + const GLint Hcr = textureObject->crop_rect[3] << 16; + + // computes texture coordinates (pre-multiplied) + int32_t dsdx = Wcr / w; // dsdx = ((Wcr/w)/Wt)*Wt + int32_t dtdy =-Hcr / h; // dtdy = -((Hcr/h)/Ht)*Ht + int32_t s0 = Ucr - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx + int32_t t0 = (Vcr+Hcr) - gglMulx(dtdy, y); // t0 = (Vcr+Hcr) - y*dtdy + texcoords[0] = s0; + texcoords[1] = dsdx; + texcoords[2] = 0; + texcoords[3] = t0; + texcoords[4] = 0; + texcoords[5] = dtdy; + texcoords[6] = 0; + texcoords[7] = 0; + c->rasterizer.procs.texCoordGradScale8xv(c, i, texcoords); + } + + const uint32_t enables = c->rasterizer.state.enables; + if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) + set_depth_and_fog(c, z); + + c->rasterizer.procs.activeTexture(c, c->textures.active); + c->rasterizer.procs.color4xv(c, c->currentColorClamped.v); + c->rasterizer.procs.disable(c, GGL_W_LERP); + c->rasterizer.procs.disable(c, GGL_AA); + c->rasterizer.procs.shadeModel(c, GL_FLAT); + c->rasterizer.procs.recti(c, + gglFixedToIntRound(x), + gglFixedToIntRound(y), + gglFixedToIntRound(x)+w, + gglFixedToIntRound(y)+h); +} + +static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c) +{ + // All coordinates are integer, so if we have only one + // texture unit active and no scaling is required + // THEN, we can use our special 1:1 mapping + // which is a lot faster. + + if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) { + const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + const GLint Wcr = textureObject->crop_rect[2]; + const GLint Hcr = textureObject->crop_rect[3]; + + if ((w == Wcr) && (h == -Hcr)) { + if ((w|h) <= 0) return; // quickly reject empty rects + + if (u.dirty) { + c->rasterizer.procs.activeTexture(c, tmu); + c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); + c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, + GGL_TEXTURE_MIN_FILTER, u.texture->min_filter); + c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, + GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter); + } + c->rasterizer.procs.texGeni(c, GGL_S, + GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); + c->rasterizer.procs.texGeni(c, GGL_T, + GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); + u.dirty = 0xFF; // XXX: should be more subtle + c->rasterizer.procs.activeTexture(c, c->textures.active); + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + y = cbSurface.height - (y + h); + const GLint Ucr = textureObject->crop_rect[0]; + const GLint Vcr = textureObject->crop_rect[1]; + const GLint s0 = Ucr - x; + const GLint t0 = (Vcr + Hcr) - y; + + const GLuint tw = textureObject->surface.width; + const GLuint th = textureObject->surface.height; + if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) { + // The GL spec is unclear about what should happen + // in this case, so we just use the slow case, which + // at least won't crash + goto slow_case; + } + + c->rasterizer.procs.texCoord2i(c, s0, t0); + const uint32_t enables = c->rasterizer.state.enables; + if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) + set_depth_and_fog(c, z); + + c->rasterizer.procs.color4xv(c, c->currentColorClamped.v); + c->rasterizer.procs.disable(c, GGL_W_LERP); + c->rasterizer.procs.disable(c, GGL_AA); + c->rasterizer.procs.shadeModel(c, GL_FLAT); + c->rasterizer.procs.recti(c, x, y, x+w, y+h); + return; + } + } + +slow_case: + drawTexxOES( + gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z), + gglIntToFixed(w), gglIntToFixed(h), + c); +} + + +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + + +#if 0 +#pragma mark - +#pragma mark Texture API +#endif + +void glActiveTexture(GLenum texture) +{ + ogles_context_t* c = ogles_context_t::get(); + if (uint32_t(texture-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + c->textures.active = texture - GL_TEXTURE0; + c->rasterizer.procs.activeTexture(c, c->textures.active); +} + +void glBindTexture(GLenum target, GLuint texture) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + // Bind or create a texture + sp<EGLTextureObject> tex; + if (texture == 0) { + // 0 is our local texture object + tex = c->textures.defaultTexture; + } else { + tex = c->surfaceManager->texture(texture); + if (ggl_unlikely(tex == 0)) { + tex = c->surfaceManager->createTexture(texture); + if (tex == 0) { + ogles_error(c, GL_OUT_OF_MEMORY); + return; + } + } + } + bindTextureTmu(c, c->textures.active, texture, tex); +} + +void glGenTextures(GLsizei n, GLuint *textures) +{ + ogles_context_t* c = ogles_context_t::get(); + if (n<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + // generate unique (shared) texture names + c->surfaceManager->getToken(n, textures); +} + +void glDeleteTextures(GLsizei n, const GLuint *textures) +{ + ogles_context_t* c = ogles_context_t::get(); + if (n<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + // If deleting a bound texture, bind this unit to 0 + for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) { + if (c->textures.tmu[t].name == 0) + continue; + for (int i=0 ; i<n ; i++) { + if (textures[i] && (textures[i] == c->textures.tmu[t].name)) { + // bind this tmu to texture 0 + sp<EGLTextureObject> tex(c->textures.defaultTexture); + bindTextureTmu(c, t, 0, tex); + } + } + } + c->surfaceManager->deleteTextures(n, textures); + c->surfaceManager->recycleTokens(n, textures); +} + +void glMultiTexCoord4f( + GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + ogles_context_t* c = ogles_context_t::get(); + if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + const int tmu = target-GL_TEXTURE0; + c->current.texture[tmu].S = gglFloatToFixed(s); + c->current.texture[tmu].T = gglFloatToFixed(t); + c->current.texture[tmu].R = gglFloatToFixed(r); + c->current.texture[tmu].Q = gglFloatToFixed(q); +} + +void glMultiTexCoord4x( + GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +{ + ogles_context_t* c = ogles_context_t::get(); + if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + const int tmu = target-GL_TEXTURE0; + c->current.texture[tmu].S = s; + c->current.texture[tmu].T = t; + c->current.texture[tmu].R = r; + c->current.texture[tmu].Q = q; +} + +void glPixelStorei(GLenum pname, GLint param) +{ + ogles_context_t* c = ogles_context_t::get(); + if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if ((param<=0 || param>8) || (param & (param-1))) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (pname == GL_PACK_ALIGNMENT) + c->textures.packAlignment = param; + if (pname == GL_UNPACK_ALIGNMENT) + c->textures.unpackAlignment = param; +} + +void glTexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.texEnvi(c, target, pname, GLint(param)); +} + +void glTexEnvfv( + GLenum target, GLenum pname, const GLfloat *params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (pname == GL_TEXTURE_ENV_MODE) { + c->rasterizer.procs.texEnvi(c, target, pname, GLint(*params)); + return; + } + if (pname == GL_TEXTURE_ENV_COLOR) { + GGLfixed fixed[4]; + for (int i=0 ; i<4 ; i++) + fixed[i] = gglFloatToFixed(params[i]); + c->rasterizer.procs.texEnvxv(c, target, pname, fixed); + return; + } + ogles_error(c, GL_INVALID_ENUM); +} + +void glTexEnvx(GLenum target, GLenum pname, GLfixed param) +{ + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.texEnvi(c, target, pname, param); +} + +void glTexEnvxv( + GLenum target, GLenum pname, const GLfixed *params) +{ + ogles_context_t* c = ogles_context_t::get(); + c->rasterizer.procs.texEnvxv(c, target, pname, params); +} + +void glTexParameteriv( + GLenum target, GLenum pname, const GLint* params) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GGL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; + switch (pname) { + case GL_TEXTURE_CROP_RECT_OES: + memcpy(textureObject->crop_rect, params, 4*sizeof(GLint)); + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } +} + +void glTexParameterf( + GLenum target, GLenum pname, GLfloat param) +{ + ogles_context_t* c = ogles_context_t::get(); + texParameterx(target, pname, GLfixed(param), c); +} + +void glTexParameterx( + GLenum target, GLenum pname, GLfixed param) +{ + ogles_context_t* c = ogles_context_t::get(); + texParameterx(target, pname, param, c); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#endif + +void glCompressedTexImage2D( + GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLsizei imageSize, const GLvoid *data) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if ((internalformat < GL_PALETTE4_RGB8_OES || + internalformat > GL_PALETTE8_RGB5_A1_OES)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (width<0 || height<0 || border!=0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + // "uncompress" the texture since pixelflinger doesn't support + // any compressed texture format natively. + GLenum format; + GLenum type; + switch (internalformat) { + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE4_RGB8_OES: + format = GL_RGB; + type = GL_UNSIGNED_BYTE; + break; + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE4_RGBA8_OES: + format = GL_RGBA; + type = GL_UNSIGNED_BYTE; + break; + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE4_R5_G6_B5_OES: + format = GL_RGB; + type = GL_UNSIGNED_SHORT_5_6_5; + break; + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE4_RGBA4_OES: + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case GL_PALETTE8_RGB5_A1_OES: + case GL_PALETTE4_RGB5_A1_OES: + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_5_5_5_1; + break; + default: + ogles_error(c, GL_INVALID_ENUM); + return; + } + + if (!data || !width || !height) { + // unclear if this is an error or not... + return; + } + + int32_t size; + GGLSurface* surface; + // all mipmap levels are specified at once. + const int numLevels = level<0 ? -level : 1; + for (int i=0 ; i<numLevels ; i++) { + int lod_w = (width >> i) ? : 1; + int lod_h = (height >> i) ? : 1; + int error = createTextureSurface(c, &surface, &size, + i, format, type, lod_w, lod_h); + if (error) { + ogles_error(c, error); + return; + } + decodePalette4(data, i, width, height, + surface->data, surface->stride, internalformat); + } +} + + +void glTexImage2D( + GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (width<0 || height<0 || border!=0 || level < 0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (format != internalformat) { + ogles_error(c, GL_INVALID_OPERATION); + return; + } + if (validFormatType(c, format, type)) { + return; + } + + int32_t size = 0; + GGLSurface* surface = 0; + if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { + int error = createTextureSurface(c, &surface, &size, + level, format, type, width, height); + if (error) { + ogles_error(c, error); + return; + } + } else if (pixels == 0 || level != 0) { + // pixel can't be null for direct texture + ogles_error(c, GL_INVALID_OPERATION); + return; + } + + if (pixels) { + const int32_t formatIdx = convertGLPixelFormat(format, type); + const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); + const int32_t align = c->textures.unpackAlignment-1; + const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; + const size_t size = bpr * height; + const int32_t stride = bpr / pixelFormat.size; + + GGLSurface userSurface; + userSurface.version = sizeof(userSurface); + userSurface.width = width; + userSurface.height = height; + userSurface.stride = stride; + userSurface.format = formatIdx; + userSurface.compressedFormat = 0; + userSurface.data = (GLubyte*)pixels; + + if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { + int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); + if (err) { + ogles_error(c, err); + return; + } + generateMipmap(c, level); + } else { + // bind it to the texture unit + sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); + tex->setSurface(&userSurface); + } + } +} + +// ---------------------------------------------------------------------------- + +void glCompressedTexSubImage2D( + GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data) +{ + ogles_context_t* c = ogles_context_t::get(); + ogles_error(c, GL_INVALID_ENUM); +} + +void glTexSubImage2D( + GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (validFormatType(c, format, type)) { + return; + } + + // find out which texture is bound to the current unit + const int active = c->textures.active; + EGLTextureObject* tex = c->textures.tmu[active].texture; + const GGLSurface& surface(tex->mip(level)); + + if (!tex->internalformat || tex->direct) { + ogles_error(c, GL_INVALID_OPERATION); + return; + } + if ((xoffset + width > GLsizei(surface.width)) || + (yoffset + height > GLsizei(surface.height))) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (!width || !height) { + return; // okay, but no-op. + } + + // figure out the size we need as well as the stride + const int32_t formatIdx = convertGLPixelFormat(format, type); + if (formatIdx == 0) { // we don't know what to do with this + ogles_error(c, GL_INVALID_OPERATION); + return; + } + + const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); + const int32_t align = c->textures.unpackAlignment-1; + const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; + const size_t size = bpr * height; + const int32_t stride = bpr / pixelFormat.size; + GGLSurface userSurface; + userSurface.version = sizeof(userSurface); + userSurface.width = width; + userSurface.height = height; + userSurface.stride = stride; + userSurface.format = formatIdx; + userSurface.compressedFormat = 0; + userSurface.data = (GLubyte*)pixels; + + int err = copyPixels(c, + surface, xoffset, yoffset, + userSurface, 0, 0, width, height); + if (err) { + ogles_error(c, err); + return; + } + + generateMipmap(c, level); + + // since we only changed the content of the texture, we don't need + // to call bindTexture on the main rasterizer. +} + +// ---------------------------------------------------------------------------- + +void glCopyTexImage2D( + GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (internalformat<GL_ALPHA || internalformat>GL_LUMINANCE_ALPHA) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (width<0 || height<0 || border!=0 || level<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + GLenum format = 0; + GLenum type = GL_UNSIGNED_BYTE; + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + const int cbFormatIdx = cbSurface.format; + switch (cbFormatIdx) { + case GGL_PIXEL_FORMAT_RGB_565: + type = GL_UNSIGNED_SHORT_5_6_5; + break; + case GGL_PIXEL_FORMAT_RGBA_5551: + type = GL_UNSIGNED_SHORT_5_5_5_1; + break; + case GGL_PIXEL_FORMAT_RGBA_4444: + type = GL_UNSIGNED_SHORT_4_4_4_4; + break; + } + switch (internalformat) { + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE: + type = GL_UNSIGNED_BYTE; + break; + } + + // figure out the format to use for the new texture + switch (cbFormatIdx) { + case GGL_PIXEL_FORMAT_RGBA_8888: + case GGL_PIXEL_FORMAT_A_8: + case GGL_PIXEL_FORMAT_RGBA_5551: + case GGL_PIXEL_FORMAT_RGBA_4444: + format = internalformat; + break; + case GGL_PIXEL_FORMAT_RGBX_8888: + case GGL_PIXEL_FORMAT_RGB_888: + case GGL_PIXEL_FORMAT_RGB_565: + case GGL_PIXEL_FORMAT_L_8: + switch (internalformat) { + case GL_LUMINANCE: + case GL_RGB: + format = internalformat; + break; + } + break; + } + + if (format == 0) { + // invalid combination + ogles_error(c, GL_INVALID_ENUM); + return; + } + + // create the new texture... + int32_t size; + GGLSurface* surface; + int error = createTextureSurface(c, &surface, &size, + level, format, type, width, height); + if (error) { + ogles_error(c, error); + return; + } + + // The bottom row is stored first in textures + GGLSurface txSurface(*surface); + txSurface.stride = -txSurface.stride; + + // (x,y) is the lower-left corner of colorBuffer + y = cbSurface.height - (y + height); + + int err = copyPixels(c, + txSurface, 0, 0, + cbSurface, x, y, cbSurface.width, cbSurface.height); + if (err) { + ogles_error(c, err); + } + + generateMipmap(c, level); +} + +void glCopyTexSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (!width || !height) { + return; // okay, but no-op. + } + + // find out which texture is bound to the current unit + const int active = c->textures.active; + EGLTextureObject* tex = c->textures.tmu[active].texture; + const GGLSurface& surface(tex->mip(level)); + + if (!tex->internalformat) { + ogles_error(c, GL_INVALID_OPERATION); + return; + } + if ((xoffset + width > GLsizei(surface.width)) || + (yoffset + height > GLsizei(surface.height))) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + // The bottom row is stored first in textures + GGLSurface txSurface(surface); + txSurface.stride = -txSurface.stride; + + // (x,y) is the lower-left corner of colorBuffer + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + y = cbSurface.height - (y + height); + + int err = copyPixels(c, + surface, xoffset, yoffset, + cbSurface, x, y, width, height); + if (err) { + ogles_error(c, err); + return; + } + + generateMipmap(c, level); +} + +void glReadPixels( + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels) +{ + ogles_context_t* c = ogles_context_t::get(); + if ((format != GL_RGBA) && (format != GL_RGB)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if ((type != GL_UNSIGNED_BYTE) && (type != GL_UNSIGNED_SHORT_5_6_5)) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + if (width<0 || height<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (x<0 || x<0) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + int32_t formatIdx = GGL_PIXEL_FORMAT_NONE; + if ((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)) { + formatIdx = GGL_PIXEL_FORMAT_RGBA_8888; + } else if ((format == GL_RGB) && (type == GL_UNSIGNED_SHORT_5_6_5)) { + formatIdx = GGL_PIXEL_FORMAT_RGB_565; + } else { + ogles_error(c, GL_INVALID_OPERATION); + return; + } + + const GGLSurface& readSurface = c->rasterizer.state.buffers.read.s; + if ((x+width > GLint(readSurface.width)) || + (y+height > GLint(readSurface.height))) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); + const int32_t align = c->textures.packAlignment-1; + const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; + const int32_t stride = bpr / pixelFormat.size; + + GGLSurface userSurface; + userSurface.version = sizeof(userSurface); + userSurface.width = width; + userSurface.height = height; + userSurface.stride = -stride; // bottom row is transfered first + userSurface.format = formatIdx; + userSurface.compressedFormat = 0; + userSurface.data = (GLubyte*)pixels; + + // use pixel-flinger to handle all the conversions + GGLContext* ggl = getRasterizer(c); + if (!ggl) { + // the only reason this would fail is because we ran out of memory + ogles_error(c, GL_OUT_OF_MEMORY); + return; + } + + ggl->colorBuffer(ggl, &userSurface); // destination is user buffer + ggl->bindTexture(ggl, &readSurface); // source is read-buffer + ggl->texCoord2i(ggl, x, readSurface.height - (y + height)); + ggl->recti(ggl, 0, 0, width, height); +} + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark DrawTexture Extension +#endif + +void glDrawTexsvOES(const GLshort* coords) { + ogles_context_t* c = ogles_context_t::get(); + drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); +} +void glDrawTexivOES(const GLint* coords) { + ogles_context_t* c = ogles_context_t::get(); + drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); +} +void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { + ogles_context_t* c = ogles_context_t::get(); + drawTexiOES(x, y, z, w, h, c); +} +void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h) { + ogles_context_t* c = ogles_context_t::get(); + drawTexiOES(x, y, z, w, h, c); +} + +void glDrawTexfvOES(const GLfloat* coords) { + ogles_context_t* c = ogles_context_t::get(); + drawTexxOES( + gglFloatToFixed(coords[0]), + gglFloatToFixed(coords[1]), + gglFloatToFixed(coords[2]), + gglFloatToFixed(coords[3]), + gglFloatToFixed(coords[4]), + c); +} +void glDrawTexxvOES(const GLfixed* coords) { + ogles_context_t* c = ogles_context_t::get(); + drawTexxOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); +} +void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h){ + ogles_context_t* c = ogles_context_t::get(); + drawTexxOES( + gglFloatToFixed(x), gglFloatToFixed(y), gglFloatToFixed(z), + gglFloatToFixed(w), gglFloatToFixed(h), + c); +} +void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { + ogles_context_t* c = ogles_context_t::get(); + drawTexxOES(x, y, z, w, h, c); +} diff --git a/opengl/libagl/texture.h b/opengl/libagl/texture.h new file mode 100644 index 0000000..5c57948 --- /dev/null +++ b/opengl/libagl/texture.h @@ -0,0 +1,45 @@ +/* libs/opengles/texture.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_TEXTURE_H +#define ANDROID_OPENGLES_TEXTURE_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +#include <private/pixelflinger/ggl_context.h> + +#include <GLES/gl.h> + +#include "context.h" + +namespace android { + +void ogles_init_texture(ogles_context_t* c); +void ogles_uninit_texture(ogles_context_t* c); +void ogles_validate_texture_impl(ogles_context_t* c); + +inline void ogles_validate_texture(ogles_context_t* c) { + if (c->rasterizer.state.enables & GGL_ENABLE_TMUS) + ogles_validate_texture_impl(c); +} + + +}; // namespace android + +#endif // ANDROID_OPENGLES_TEXTURE_H diff --git a/opengl/libagl/vertex.cpp b/opengl/libagl/vertex.cpp new file mode 100644 index 0000000..5bcc9dc --- /dev/null +++ b/opengl/libagl/vertex.cpp @@ -0,0 +1,247 @@ +/* libs/opengles/vertex.cpp +** +** Copyright 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. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "context.h" +#include "fp.h" +#include "vertex.h" +#include "state.h" +#include "matrix.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +void ogles_init_vertex(ogles_context_t* c) +{ + c->cull.enable = GL_FALSE; + c->cull.cullFace = GL_BACK; + c->cull.frontFace = GL_CCW; + + c->current.color.r = 0x10000; + c->current.color.g = 0x10000; + c->current.color.b = 0x10000; + c->current.color.a = 0x10000; + + c->currentNormal.z = 0x10000; +} + +void ogles_uninit_vertex(ogles_context_t* c) +{ +} + +// ---------------------------------------------------------------------------- +// vertex processing +// ---------------------------------------------------------------------------- + +// Divides a vertex clip coordinates by W +static inline +void perspective(ogles_context_t* c, vertex_t* v, uint32_t enables) +{ + // [x,y,z]window = vpt * ([x,y,z]clip / clip.w) + // [w]window = 1/w + + // With a regular projection generated by glFrustum(), + // we have w=-z, therefore, w is in [zNear, zFar]. + // Also, zNear and zFar are stricly positive, + // and 1/w (window.w) is in [1/zFar, 1/zNear], usually this + // means ]0, +inf[ -- however, it is always recommended + // to use as large values as possible for zNear. + // All in all, w is usually smaller than 1.0 (assuming + // zNear is at least 1.0); and even if zNear is smaller than 1.0 + // values of w won't be too big. + + const int32_t rw = gglRecip28(v->clip.w); + const GLfixed* const m = c->transforms.vpt.transform.matrix.m; + v->window.w = rw; + v->window.x = gglMulAddx(gglMulx(v->clip.x, rw, 16), m[ 0], m[12], 28); + v->window.y = gglMulAddx(gglMulx(v->clip.y, rw, 16), m[ 5], m[13], 28); + v->window.x = TRI_FROM_FIXED(v->window.x); + v->window.y = TRI_FROM_FIXED(v->window.y); + if (enables & GGL_ENABLE_DEPTH_TEST) { + v->window.z = gglMulAddx(gglMulx(v->clip.z, rw, 16), m[10], m[14], 28); + } +} + +// frustum clipping and W-divide +static inline +void clipFrustumPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables) +{ + // ndc = clip / W + // window = ncd * viewport + + // clip to the view-volume + uint32_t clip = v->flags & vertex_t::CLIP_ALL; + const GLfixed w = v->clip.w; + if (v->clip.x < -w) clip |= vertex_t::CLIP_L; + if (v->clip.x > w) clip |= vertex_t::CLIP_R; + if (v->clip.y < -w) clip |= vertex_t::CLIP_B; + if (v->clip.y > w) clip |= vertex_t::CLIP_T; + if (v->clip.z < -w) clip |= vertex_t::CLIP_N; + if (v->clip.z > w) clip |= vertex_t::CLIP_F; + + v->flags |= clip; + c->arrays.cull &= clip; + + if (ggl_likely(!clip)) { + // if the vertice is clipped, we don't do the perspective + // divide, since we don't need its window coordinates. + perspective(c, v, enables); + } +} + +// frustum clipping, user clipping and W-divide +static inline +void clipAllPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables) +{ + // compute eye coordinates + c->arrays.mv_transform( + &c->transforms.modelview.transform, &v->eye, &v->obj); + v->flags |= vertex_t::EYE; + + // clip this vertex against each user clip plane + uint32_t clip = 0; + int planes = c->clipPlanes.enable; + while (planes) { + const int i = 31 - gglClz(planes); + planes &= ~(1<<i); + // XXX: we should have a special dot() for 2,3,4 coords vertices + GLfixed d = dot4(c->clipPlanes.plane[i].equation.v, v->eye.v); + if (d < 0) { + clip |= 0x100<<i; + } + } + v->flags |= clip; + + clipFrustumPerspective(c, v, enables); +} + +// ---------------------------------------------------------------------------- + +void ogles_vertex_project(ogles_context_t* c, vertex_t* v) { + perspective(c, v, c->rasterizer.state.enables); +} + +void ogles_vertex_perspective2D(ogles_context_t* c, vertex_t* v) +{ + // here we assume w=1.0 and the viewport transformation + // has been applied already. + c->arrays.cull = 0; + v->window.x = TRI_FROM_FIXED(v->clip.x); + v->window.y = TRI_FROM_FIXED(v->clip.y); + v->window.z = v->clip.z; + v->window.w = v->clip.w << 12; +} + +void ogles_vertex_perspective3DZ(ogles_context_t* c, vertex_t* v) { + clipFrustumPerspective(c, v, GGL_ENABLE_DEPTH_TEST); +} +void ogles_vertex_perspective3D(ogles_context_t* c, vertex_t* v) { + clipFrustumPerspective(c, v, 0); +} +void ogles_vertex_clipAllPerspective3DZ(ogles_context_t* c, vertex_t* v) { + clipAllPerspective(c, v, GGL_ENABLE_DEPTH_TEST); +} +void ogles_vertex_clipAllPerspective3D(ogles_context_t* c, vertex_t* v) { + clipAllPerspective(c, v, 0); +} + +static void clipPlanex(GLenum plane, const GLfixed* equ, ogles_context_t* c) +{ + const int p = plane - GL_CLIP_PLANE0; + if (ggl_unlikely(uint32_t(p) > (GL_CLIP_PLANE5 - GL_CLIP_PLANE0))) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + vec4_t& equation = c->clipPlanes.plane[p].equation; + memcpy(equation.v, equ, sizeof(vec4_t)); + + ogles_validate_transform(c, transform_state_t::MVIT); + transform_t& mvit = c->transforms.mvit4; + mvit.point4(&mvit, &equation, &equation); +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + + +void glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) +{ + ogles_context_t* c = ogles_context_t::get(); + c->current.color.r = gglFloatToFixed(r); + c->currentColorClamped.r = gglClampx(c->current.color.r); + c->current.color.g = gglFloatToFixed(g); + c->currentColorClamped.g = gglClampx(c->current.color.g); + c->current.color.b = gglFloatToFixed(b); + c->currentColorClamped.b = gglClampx(c->current.color.b); + c->current.color.a = gglFloatToFixed(a); + c->currentColorClamped.a = gglClampx(c->current.color.a); +} + +void glColor4x(GLfixed r, GLfixed g, GLfixed b, GLfixed a) +{ + ogles_context_t* c = ogles_context_t::get(); + c->current.color.r = r; + c->current.color.g = g; + c->current.color.b = b; + c->current.color.a = a; + c->currentColorClamped.r = gglClampx(r); + c->currentColorClamped.g = gglClampx(g); + c->currentColorClamped.b = gglClampx(b); + c->currentColorClamped.a = gglClampx(a); +} + +void glNormal3f(GLfloat x, GLfloat y, GLfloat z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->currentNormal.x = gglFloatToFixed(x); + c->currentNormal.y = gglFloatToFixed(y); + c->currentNormal.z = gglFloatToFixed(z); +} + +void glNormal3x(GLfixed x, GLfixed y, GLfixed z) +{ + ogles_context_t* c = ogles_context_t::get(); + c->currentNormal.x = x; + c->currentNormal.y = y; + c->currentNormal.z = z; +} + +// ---------------------------------------------------------------------------- + +void glClipPlanef(GLenum plane, const GLfloat* equ) +{ + const GLfixed equx[4] = { + gglFloatToFixed(equ[0]), + gglFloatToFixed(equ[1]), + gglFloatToFixed(equ[2]), + gglFloatToFixed(equ[3]) + }; + ogles_context_t* c = ogles_context_t::get(); + clipPlanex(plane, equx, c); +} + +void glClipPlanex(GLenum plane, const GLfixed* equ) +{ + ogles_context_t* c = ogles_context_t::get(); + clipPlanex(plane, equ, c); +} diff --git a/opengl/libagl/vertex.h b/opengl/libagl/vertex.h new file mode 100644 index 0000000..55e6213 --- /dev/null +++ b/opengl/libagl/vertex.h @@ -0,0 +1,48 @@ +/* libs/opengles/vertex.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_OPENGLES_VERTEX_H +#define ANDROID_OPENGLES_VERTEX_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> + +namespace android { + +namespace gl { +struct vertex_t; +struct ogles_context_t; +}; + +void ogles_init_vertex(ogles_context_t* c); +void ogles_uninit_vertex(ogles_context_t* c); + +void ogles_vertex_perspective2D(ogles_context_t*, vertex_t*); + +void ogles_vertex_perspective3D(ogles_context_t*, vertex_t*); +void ogles_vertex_perspective3DZ(ogles_context_t*, vertex_t*); +void ogles_vertex_clipAllPerspective3D(ogles_context_t*, vertex_t*); +void ogles_vertex_clipAllPerspective3DZ(ogles_context_t*, vertex_t*); + + +void ogles_vertex_project(ogles_context_t* c, vertex_t*); + +}; // namespace android + +#endif // ANDROID_OPENGLES_VERTEX_H + |