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