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