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