2003/10/16 05:39:20
[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 dx1, jint dy1, jint dx2, jint dy2,jint sx1, jint sy1, jint sx2, jint sy2) { 
180         glEnable(GL_TEXTURE_RECTANGLE_EXT);
181         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);    
182         glBegin(GL_QUADS); 
183         glTexCoord2i (sx1, sy1   );
184         glVertex3i   (dx1, dy1, 0);   
185         glTexCoord2i (sx2, sy1   ); 
186         glVertex3i   (dx2, dy1, 0);
187         glTexCoord2i (sx2, sy2   ); 
188         glVertex3i   (dx2, dy2, 0);
189         glTexCoord2i (sx1, sy2   );
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 dx1, jint dy1, jint dx2, jint dy2,jint sx1, jint sy1, jint sx2, jint sy2) {
271     float tx1,ty1,tx2,ty2; // normalized texture coords
272     tx1 = (float) sx1 / (float) texWidth;
273     ty1 = (float) sy1 / (float) texHeight;
274     tx2 = (float) sx2 / (float) texWidth;
275     ty2 = (float) sy2 / (float) texHeight;
276
277     glEnable(GL_TEXTURE_2D);
278     glBindTexture(GL_TEXTURE_2D, textureName);    
279     checkGLError();
280     glBegin(GL_QUADS); 
281         glTexCoord2f (tx1, ty1   );
282         glVertex3i   (dx1, dy1, 0);
283         glTexCoord2f (tx2, ty1   ); 
284         glVertex3i   (dx2, dy1, 0);
285         glTexCoord2f (tx2, ty2   ); 
286         glVertex3i   (dx2, dy2, 0);
287         glTexCoord2f (tx1, ty2   );
288         glVertex3i   (dx1, dy2, 0);
289     glEnd();
290     glDisable(GL_TEXTURE_2D);
291     checkGLError();
292 }
293
294 } } } // end org::xwt::plat