licensing cleanup (GPLv2)
[org.ibex.core.git] / src / org / ibex / plat / OpenGL.cc
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the GNU General Public License version 2 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 // Author: Brian Alliet
6
7 // IMPROVMENT: use alpha testing? might be faster
8
9 #include <org/ibex/plat/OpenGL.h>
10 #include <org/ibex/plat/OpenGL$GLPixelBuffer.h>
11 #include <org/ibex/plat/OpenGL$GLPicture.h>
12 #include <org/ibex/plat/OpenGL$RectGLPicture.h>
13 #include <org/ibex/plat/OpenGL$SquareGLPicture.h>
14 #include <org/ibex/plat/OpenGL$MosaicGLPicture.h>
15
16 #include <java/lang/Error.h>
17
18 #ifdef __APPLE__
19 #include <OpenGL/gl.h>
20 #include <OpenGL/glu.h>
21 #include <OpenGL/glext.h>
22 #else
23 #warning I am not sure if these are correct
24 #include <gl/gl.h>
25 #include <gl/glu.h>
26 #include <gl/glext.h>
27 #endif
28
29 #include <stdio.h>
30
31 #define min(a,b) ((a)<(b)?(a):(b)) 
32 #define max(a,b) ((a)>(b)?(a):(b)) 
33
34 namespace org { namespace ibex { namespace plat {
35
36 #define checkGLError() checkGLError2(__FILE__,__LINE__)
37 static void checkGLError2(const char *file,int line) {
38     GLenum err = glGetError();
39     if(err == GL_NO_ERROR) return;
40
41     fprintf(stderr,"%s:%d: GL Error: %s",file,line,(char *) gluErrorString(err));
42     exit(EXIT_FAILURE);
43 }
44
45 void OpenGL::natInit() {
46     GLint i;
47     const GLubyte *s;
48     activateSharedContext();
49     s = glGetString(GL_EXTENSIONS);
50     rectangularTextures = (jboolean) gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle",s);
51     glGetIntegerv(GL_MAX_TEXTURE_SIZE,&i);
52     maxTexSize = (jint) i;
53     if(rectangularTextures) {
54         glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT,&i);
55         maxRectTexSize = (jint) i;
56     }
57     s = glGetString(GL_VENDOR);
58     vendor = JvNewStringLatin1(s==0 ? "" : (char*)s);
59     s = glGetString(GL_RENDERER);
60     renderer = JvNewStringLatin1(s==0 ? "" : (char*)s);
61     s = glGetString(GL_VERSION);
62     version = JvNewStringLatin1(s==0 ? "" : (char*)s);
63 }
64
65 void OpenGL$GLPixelBuffer::drawableInit(jint width, jint height) {
66     glClearColor (0.3f, 0.7f, 1.0f, 1.0f);
67     glClearDepth( 0.0f );
68     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
69     glShadeModel(GL_SMOOTH);
70     glEnable(GL_BLEND);
71     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
72
73     glViewport(0,0,width,height);
74     glMatrixMode(GL_PROJECTION);
75     glLoadIdentity(); 
76     glOrtho(0,width,height,0,-1,1);
77     // CHECKME: This causes textures to be blurry, but something like this
78     // (but not this) might be required to draw straight lines   
79     //glMatrixMode(GL_MODELVIEW);
80     //glLoadIdentity(); 
81     //glTranslatef(0.375, 0.375, 0.0);    
82     
83     checkGLError();
84 }
85
86 void OpenGL$GLPixelBuffer::setColor(jint argb) {
87     float alpha = ((argb >> 24) & 0xff) / 255.0;
88     float red   = ((argb >> 16) & 0xff) / 255.0;
89     float green = ((argb >>  8) & 0xff) / 255.0;
90     float blue  = ((argb >>  0) & 0xff) / 255.0;
91     glColor4f(red,green,blue,alpha);
92 }
93
94 void OpenGL$GLPixelBuffer::fillTrapezoid(jint x1, jint x2, jint y1, jint x3, jint x4, jint y2, jint color) {
95     activateContext();
96     setColor(color);
97     glBegin(GL_QUADS); {
98         glVertex3f(x1,y1,0.0f );   
99         glVertex3f(x3,y2,0.0f );  
100         glVertex3f(x4,y2,0.0f ); 
101         glVertex3f(x2,y1,0.0f ); 
102     } glEnd();
103 }
104
105 void OpenGL$GLPixelBuffer::setClip(jint x1, jint y1, jint x2, jint y2) {
106     //fprintf(stderr,"setClip: %d %d %d %d\n",x1,y1,x2,y2);
107     if(x1==0 && y1==0 && x2==width && y2==height) {
108         if(glScissorEnabled) {
109             activateContext();
110             glDisable(GL_SCISSOR_TEST);
111             glScissorEnabled = false;
112         }
113         return;
114     }
115     activateContext();
116     if(!glScissorEnabled) {
117         glEnable(GL_SCISSOR_TEST);
118         glScissorEnabled = true;
119     }
120     if((x1 >= x2) || (y1 >= y2))
121         glScissor(0,0,0,0);
122     else
123         glScissor(x1,height-y2,x2-x1,y2-y1);
124     checkGLError();
125 }
126
127 void OpenGL$GLPixelBuffer::resetClip() {
128     activateContext();
129     if(glScissorEnabled) {
130         glDisable(GL_SCISSOR_TEST);
131         glScissorEnabled = false;
132     }    
133 }
134
135 // FEATURE: Eliminate duplicate code in RectGLPicture and SquareGLPicture
136 void OpenGL$RectGLPicture::natInit(Object *data_, jboolean alphaOnly) {
137     unsigned char *buf;
138     int i,j;
139     int size = width*height;
140     GLuint tex;
141
142     if(alphaOnly) {
143         jbyte *data = elements((JArray<jbyte> *)data_);
144         buf = (unsigned char *) data;
145     } else {
146         jint *data = elements((JArray<jint> *)data_);
147         buf = new unsigned char[size*4];
148         for(i=0,j=0;i<size;i++,j+=4) {
149             jint pixel = data[i];
150             buf[j+0] = (pixel >> 16) & 0xff;
151             buf[j+1] = (pixel >>  8) & 0xff;
152             buf[j+2] = (pixel >>  0) & 0xff;
153             buf[j+3] = (pixel >> 24) & 0xff;
154         }
155     }
156     
157     gl->activateSharedContext();
158     glEnable(GL_TEXTURE_RECTANGLE_EXT);
159     glGenTextures(1,&tex);
160     glBindTexture(GL_TEXTURE_RECTANGLE_EXT,tex);
161     glPixelStorei(GL_PACK_ALIGNMENT,1);
162     glTexImage2D(
163         GL_TEXTURE_RECTANGLE_EXT,0,
164         alphaOnly ? GL_ALPHA : GL_RGBA,width,height,0,
165         alphaOnly ? GL_ALPHA : GL_RGBA,GL_UNSIGNED_BYTE,buf);
166     if(!alphaOnly)
167         delete buf;
168
169     if(gl->glVersion >= 1.2) {
170         glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
171         glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
172         glTexParameterf(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
173         glTexParameterf(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
174     } else {
175         glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
176         glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
177     }
178     
179     glDisable(GL_TEXTURE_RECTANGLE_EXT);
180     checkGLError();
181   
182     textureName = (jint)tex;
183 }
184
185 void OpenGL$RectGLPicture::draw(jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) { 
186     cx1 = max(dx, cx1);
187     cy1 = max(dy, cy1);
188     cx2 = min(cx2, dx + width);
189     cy2 = min(cy2, dy + height);
190     if (cy2 <= cy1 || cx2 <= cx1) return;
191     glEnable(GL_TEXTURE_RECTANGLE_EXT);
192     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);    
193     glBegin(GL_QUADS); {
194       glTexCoord2i (cx1 - dx, cy1 - dy   );
195       glVertex3i   (cx1,      cy1,      0);
196       glTexCoord2i (cx2 - dx, cy1 - dy   );
197       glVertex3i   (cx2,      cy1,      0);
198       glTexCoord2i (cx2 - dx, cy2 - dy   );
199       glVertex3i   (cx2,      cy2,      0);
200       glTexCoord2i (cx1 - dx, cy2 - dy   );
201       glVertex3i   (cx1,      cy2,      0);
202     } glEnd();
203     glDisable(GL_TEXTURE_RECTANGLE_EXT);
204     checkGLError();
205 }
206
207 void OpenGL::natDeleteTexture(jint tex_) {
208     activateSharedContext();
209     GLuint tex = (GLuint) tex_;
210     glDeleteTextures(1,&tex);
211 }
212
213 void OpenGL$SquareGLPicture::natInit(Object *data_, jboolean alphaOnly) {
214     unsigned char *buf;
215     int row,col,p;
216     GLuint tex;
217
218     if(alphaOnly) {
219         jbyte *data = elements((JArray<jbyte>*) data_);
220         if(texWidth == width && texHeight == height) {
221             buf = (unsigned char*) data;
222         } else {
223             buf = new unsigned char[texWidth*texHeight];
224             p=0;
225             for(row=0;row<height;row++) {
226                 for(col=0;col<width;col++)
227                     buf[p++] = data[row*width+col];
228                 for(;col<texWidth;col++)
229                     buf[p++] = 0;
230             }
231             for(;row<texHeight;row++)
232                 for(col=0;col<texWidth;col++)
233                     buf[p++] = 0;
234         }
235     } else {
236         jint *data = elements((JArray<jint>*) data_);
237         buf = new unsigned char[texWidth*texHeight*4];
238         p=0;
239         for(row=0;row<height;row++) {
240             for(col=0;col<width;col++) {
241                 jint pixel = data[row*width+col];
242                 buf[p+0] = (pixel >> 16) & 0xff;
243                 buf[p+1] = (pixel >>  8) & 0xff;
244                 buf[p+2] = (pixel >>  0) & 0xff;
245                 buf[p+3] = (pixel >> 24) & 0xff;
246                 p+=4;
247             }
248             for(;col < texWidth;col++,p+=4)
249                 buf[p+0] = buf[p+1] = buf[p+2] = buf[p+3] = 0;
250         }
251         for(;row < texHeight;row++) 
252             for(col=0;col<texWidth;col++,p+=4)
253                 buf[p+0] = buf[p+1] = buf[p+2] = buf[p+3] = 0;
254     }
255     
256     gl->activateSharedContext();
257     glEnable(GL_TEXTURE_2D);
258     glGenTextures(1,&tex);
259     glBindTexture(GL_TEXTURE_2D,tex);
260     glPixelStorei(GL_PACK_ALIGNMENT,1);
261     glTexImage2D(GL_TEXTURE_2D,0,alphaOnly ? GL_ALPHA : GL_RGBA,texWidth,texHeight,0,alphaOnly ? GL_ALPHA : GL_RGBA,GL_UNSIGNED_BYTE,buf);
262     checkGLError();    
263     if(!alphaOnly || width != texWidth || height != texHeight) delete buf;
264
265     if(gl->glVersion >= 1.2) {
266         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
267         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
268         glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
269         glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
270     } else {
271         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
272         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
273     }
274
275     glDisable(GL_TEXTURE_2D);
276     checkGLError();
277   
278     textureName = (jint)tex;
279 }
280
281 void OpenGL$SquareGLPicture::draw(jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
282     cx1 = max(dx, cx1);
283     cy1 = max(dy, cy1);
284     cx2 = min(cx2, dx + width);
285     cy2 = min(cy2, dy + height);
286     if (cy2 <= cy1 || cx2 <= cx1) return;
287     float tx1 = (float) (cx1 - dx) / (float) texWidth;
288     float ty1 = (float) (cy1 - dy) / (float) texHeight;
289     float tx2 = (float) (cx2 - dx) / (float) texWidth;
290     float ty2 = (float) (cy2 - dy) / (float) texHeight;
291     glEnable(GL_TEXTURE_2D);
292     glBindTexture(GL_TEXTURE_2D, textureName);    
293     checkGLError();
294     glBegin(GL_QUADS); {
295         glTexCoord2f (tx1,      ty1        );    
296         glVertex3i   (cx1,      cy1,      0);
297         glTexCoord2f (tx2,      ty1        );    
298         glVertex3i   (cx2,      cy1,      0);
299         glTexCoord2f (tx2,      ty2        );    
300         glVertex3i   (cx2,      cy2,      0);
301         glTexCoord2f (tx1,      ty2        );    
302         glVertex3i   (cx1,      cy2,      0);
303     } glEnd();
304     glDisable(GL_TEXTURE_2D);
305     checkGLError();
306 }
307
308 } } } // end org::ibex::plat