mass rename and rebranding from xwt to ibex - fixed to use ixt files
[org.ibex.core.git] / src / org / ibex / plat / OpenGL.cc
diff --git a/src/org/ibex/plat/OpenGL.cc b/src/org/ibex/plat/OpenGL.cc
new file mode 100644 (file)
index 0000000..1f79649
--- /dev/null
@@ -0,0 +1,305 @@
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
+// Author: Brian Alliet
+
+// IMPROVMENT: use alpha testing? might be faster
+
+#include <org/ibex/plat/OpenGL.h>
+#include <org/ibex/plat/OpenGL$GLPixelBuffer.h>
+#include <org/ibex/plat/OpenGL$GLPicture.h>
+#include <org/ibex/plat/OpenGL$RectGLPicture.h>
+#include <org/ibex/plat/OpenGL$SquareGLPicture.h>
+#include <org/ibex/plat/OpenGL$MosaicGLPicture.h>
+
+#include <java/lang/Error.h>
+
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#include <OpenGL/glext.h>
+#else
+#warning I am not sure if these are correct
+#include <gl/gl.h>
+#include <gl/glu.h>
+#include <gl/glext.h>
+#endif
+
+#include <stdio.h>
+
+#define min(a,b) ((a)<(b)?(a):(b)) 
+#define max(a,b) ((a)>(b)?(a):(b)) 
+
+namespace org { namespace ibex { namespace plat {
+
+#define checkGLError() checkGLError2(__FILE__,__LINE__)
+static void checkGLError2(const char *file,int line) {
+    GLenum err = glGetError();
+    if(err == GL_NO_ERROR) return;
+
+    fprintf(stderr,"%s:%d: GL Error: %s",file,line,(char *) gluErrorString(err));
+    exit(EXIT_FAILURE);
+}
+
+void OpenGL::natInit() {
+    GLint i;
+    const GLubyte *s;
+    activateSharedContext();
+    s = glGetString(GL_EXTENSIONS);
+    rectangularTextures = (jboolean) gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle",s);
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE,&i);
+    maxTexSize = (jint) i;
+    if(rectangularTextures) {
+        glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT,&i);
+        maxRectTexSize = (jint) i;
+    }
+    s = glGetString(GL_VENDOR);
+    vendor = JvNewStringLatin1(s==0 ? "" : (char*)s);
+    s = glGetString(GL_RENDERER);
+    renderer = JvNewStringLatin1(s==0 ? "" : (char*)s);
+    s = glGetString(GL_VERSION);
+    version = JvNewStringLatin1(s==0 ? "" : (char*)s);
+}
+
+void OpenGL$GLPixelBuffer::drawableInit(jint width, jint height) {
+    glClearColor (0.3f, 0.7f, 1.0f, 1.0f);
+    glClearDepth( 0.0f );
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+    glShadeModel(GL_SMOOTH);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    glViewport(0,0,width,height);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity(); 
+    glOrtho(0,width,height,0,-1,1);
+    // CHECKME: This causes textures to be blurry, but something like this
+    // (but not this) might be required to draw straight lines   
+    //glMatrixMode(GL_MODELVIEW);
+    //glLoadIdentity(); 
+    //glTranslatef(0.375, 0.375, 0.0);    
+    
+    checkGLError();
+}
+
+void OpenGL$GLPixelBuffer::setColor(jint argb) {
+    float alpha = ((argb >> 24) & 0xff) / 255.0;
+    float red   = ((argb >> 16) & 0xff) / 255.0;
+    float green = ((argb >>  8) & 0xff) / 255.0;
+    float blue  = ((argb >>  0) & 0xff) / 255.0;
+    glColor4f(red,green,blue,alpha);
+}
+
+void OpenGL$GLPixelBuffer::fillTrapezoid(jint x1, jint x2, jint y1, jint x3, jint x4, jint y2, jint color) {
+    activateContext();
+    setColor(color);
+    glBegin(GL_QUADS); {
+        glVertex3f(x1,y1,0.0f );   
+        glVertex3f(x3,y2,0.0f );  
+        glVertex3f(x4,y2,0.0f ); 
+        glVertex3f(x2,y1,0.0f ); 
+    } glEnd();
+}
+
+void OpenGL$GLPixelBuffer::setClip(jint x1, jint y1, jint x2, jint y2) {
+    //fprintf(stderr,"setClip: %d %d %d %d\n",x1,y1,x2,y2);
+    if(x1==0 && y1==0 && x2==width && y2==height) {
+        if(glScissorEnabled) {
+            activateContext();
+            glDisable(GL_SCISSOR_TEST);
+            glScissorEnabled = false;
+        }
+        return;
+    }
+    activateContext();
+    if(!glScissorEnabled) {
+        glEnable(GL_SCISSOR_TEST);
+        glScissorEnabled = true;
+    }
+    if((x1 >= x2) || (y1 >= y2))
+        glScissor(0,0,0,0);
+    else
+        glScissor(x1,height-y2,x2-x1,y2-y1);
+    checkGLError();
+}
+
+void OpenGL$GLPixelBuffer::resetClip() {
+    activateContext();
+    if(glScissorEnabled) {
+        glDisable(GL_SCISSOR_TEST);
+        glScissorEnabled = false;
+    }    
+}
+
+// FEATURE: Eliminate duplicate code in RectGLPicture and SquareGLPicture
+void OpenGL$RectGLPicture::natInit(Object *data_, jboolean alphaOnly) {
+    unsigned char *buf;
+    int i,j;
+    int size = width*height;
+    GLuint tex;
+
+    if(alphaOnly) {
+        jbyte *data = elements((JArray<jbyte> *)data_);
+        buf = (unsigned char *) data;
+    } else {
+        jint *data = elements((JArray<jint> *)data_);
+        buf = new unsigned char[size*4];
+        for(i=0,j=0;i<size;i++,j+=4) {
+            jint pixel = data[i];
+            buf[j+0] = (pixel >> 16) & 0xff;
+            buf[j+1] = (pixel >>  8) & 0xff;
+            buf[j+2] = (pixel >>  0) & 0xff;
+            buf[j+3] = (pixel >> 24) & 0xff;
+        }
+    }
+    
+    gl->activateSharedContext();
+    glEnable(GL_TEXTURE_RECTANGLE_EXT);
+    glGenTextures(1,&tex);
+    glBindTexture(GL_TEXTURE_RECTANGLE_EXT,tex);
+    glPixelStorei(GL_PACK_ALIGNMENT,1);
+    glTexImage2D(
+        GL_TEXTURE_RECTANGLE_EXT,0,
+        alphaOnly ? GL_ALPHA : GL_RGBA,width,height,0,
+        alphaOnly ? GL_ALPHA : GL_RGBA,GL_UNSIGNED_BYTE,buf);
+    if(!alphaOnly)
+        delete buf;
+
+    if(gl->glVersion >= 1.2) {
+        glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+        glTexParameterf(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameterf(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    } else {
+        glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+    }
+    
+    glDisable(GL_TEXTURE_RECTANGLE_EXT);
+    checkGLError();
+  
+    textureName = (jint)tex;
+}
+
+void OpenGL$RectGLPicture::draw(jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) { 
+    cx1 = max(dx, cx1);
+    cy1 = max(dy, cy1);
+    cx2 = min(cx2, dx + width);
+    cy2 = min(cy2, dy + height);
+    if (cy2 <= cy1 || cx2 <= cx1) return;
+    glEnable(GL_TEXTURE_RECTANGLE_EXT);
+    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);    
+    glBegin(GL_QUADS); {
+      glTexCoord2i (cx1 - dx, cy1 - dy   );
+      glVertex3i   (cx1,      cy1,      0);
+      glTexCoord2i (cx2 - dx, cy1 - dy   );
+      glVertex3i   (cx2,      cy1,      0);
+      glTexCoord2i (cx2 - dx, cy2 - dy   );
+      glVertex3i   (cx2,      cy2,      0);
+      glTexCoord2i (cx1 - dx, cy2 - dy   );
+      glVertex3i   (cx1,      cy2,      0);
+    } glEnd();
+    glDisable(GL_TEXTURE_RECTANGLE_EXT);
+    checkGLError();
+}
+
+void OpenGL::natDeleteTexture(jint tex_) {
+    activateSharedContext();
+    GLuint tex = (GLuint) tex_;
+    glDeleteTextures(1,&tex);
+}
+
+void OpenGL$SquareGLPicture::natInit(Object *data_, jboolean alphaOnly) {
+    unsigned char *buf;
+    int row,col,p;
+    GLuint tex;
+
+    if(alphaOnly) {
+        jbyte *data = elements((JArray<jbyte>*) data_);
+        if(texWidth == width && texHeight == height) {
+            buf = (unsigned char*) data;
+        } else {
+            buf = new unsigned char[texWidth*texHeight];
+            p=0;
+            for(row=0;row<height;row++) {
+                for(col=0;col<width;col++)
+                    buf[p++] = data[row*width+col];
+                for(;col<texWidth;col++)
+                    buf[p++] = 0;
+            }
+            for(;row<texHeight;row++)
+                for(col=0;col<texWidth;col++)
+                    buf[p++] = 0;
+        }
+    } else {
+        jint *data = elements((JArray<jint>*) data_);
+        buf = new unsigned char[texWidth*texHeight*4];
+        p=0;
+        for(row=0;row<height;row++) {
+            for(col=0;col<width;col++) {
+                jint pixel = data[row*width+col];
+                buf[p+0] = (pixel >> 16) & 0xff;
+                buf[p+1] = (pixel >>  8) & 0xff;
+                buf[p+2] = (pixel >>  0) & 0xff;
+                buf[p+3] = (pixel >> 24) & 0xff;
+                p+=4;
+            }
+            for(;col < texWidth;col++,p+=4)
+                buf[p+0] = buf[p+1] = buf[p+2] = buf[p+3] = 0;
+        }
+        for(;row < texHeight;row++) 
+            for(col=0;col<texWidth;col++,p+=4)
+                buf[p+0] = buf[p+1] = buf[p+2] = buf[p+3] = 0;
+    }
+    
+    gl->activateSharedContext();
+    glEnable(GL_TEXTURE_2D);
+    glGenTextures(1,&tex);
+    glBindTexture(GL_TEXTURE_2D,tex);
+    glPixelStorei(GL_PACK_ALIGNMENT,1);
+    glTexImage2D(GL_TEXTURE_2D,0,alphaOnly ? GL_ALPHA : GL_RGBA,texWidth,texHeight,0,alphaOnly ? GL_ALPHA : GL_RGBA,GL_UNSIGNED_BYTE,buf);
+    checkGLError();    
+    if(!alphaOnly || width != texWidth || height != texHeight) delete buf;
+
+    if(gl->glVersion >= 1.2) {
+        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+        glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    } else {
+        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+    }
+
+    glDisable(GL_TEXTURE_2D);
+    checkGLError();
+  
+    textureName = (jint)tex;
+}
+
+void OpenGL$SquareGLPicture::draw(jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
+    cx1 = max(dx, cx1);
+    cy1 = max(dy, cy1);
+    cx2 = min(cx2, dx + width);
+    cy2 = min(cy2, dy + height);
+    if (cy2 <= cy1 || cx2 <= cx1) return;
+    float tx1 = (float) (cx1 - dx) / (float) texWidth;
+    float ty1 = (float) (cy1 - dy) / (float) texHeight;
+    float tx2 = (float) (cx2 - dx) / (float) texWidth;
+    float ty2 = (float) (cy2 - dy) / (float) texHeight;
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, textureName);    
+    checkGLError();
+    glBegin(GL_QUADS); {
+       glTexCoord2f (tx1,      ty1        );    
+        glVertex3i   (cx1,      cy1,      0);
+       glTexCoord2f (tx2,      ty1        );    
+        glVertex3i   (cx2,      cy1,      0);
+       glTexCoord2f (tx2,      ty2        );    
+        glVertex3i   (cx2,      cy2,      0);
+       glTexCoord2f (tx1,      ty2        );    
+        glVertex3i   (cx1,      cy2,      0);
+    } glEnd();
+    glDisable(GL_TEXTURE_2D);
+    checkGLError();
+}
+
+} } } // end org::ibex::plat