1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // Author: Brian Alliet
4 // IMPROVMENT: use alpha testing? might be faster
6 #include <org/ibex/plat/OpenGL.h>
7 #include <org/ibex/graphics/PixelBuffer.h>
8 #include <org/ibex/graphics/Polygon.h>
9 #include <org/ibex/plat/OpenGL$GLPixelBuffer.h>
10 #include <org/ibex/plat/OpenGL$GLPicture.h>
11 #include <org/ibex/plat/OpenGL$RectGLPicture.h>
12 #include <org/ibex/plat/OpenGL$SquareGLPicture.h>
13 #include <org/ibex/plat/OpenGL$MosaicGLPicture.h>
15 #include <java/lang/Error.h>
18 #include <OpenGL/gl.h>
19 #include <OpenGL/glu.h>
20 #include <OpenGL/glext.h>
22 #warning I am not sure if these are correct
30 #define min(a,b) ((a)<(b)?(a):(b))
31 #define max(a,b) ((a)>(b)?(a):(b))
33 namespace org { namespace ibex { namespace plat {
35 #define checkGLError() checkGLError2(__FILE__,__LINE__)
36 static void checkGLError2(const char *file,int line) {
37 GLenum err = glGetError();
38 if(err == GL_NO_ERROR) return;
40 fprintf(stderr,"%s:%d: GL Error: %s",file,line,(char *) gluErrorString(err));
44 void OpenGL::natInit() {
47 activateSharedContext();
48 s = glGetString(GL_EXTENSIONS);
49 rectangularTextures = (jboolean) gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle",s);
50 glGetIntegerv(GL_MAX_TEXTURE_SIZE,&i);
51 maxTexSize = (jint) i;
52 if(rectangularTextures) {
53 glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT,&i);
54 maxRectTexSize = (jint) i;
56 s = glGetString(GL_VENDOR);
57 vendor = JvNewStringLatin1(s==0 ? "" : (char*)s);
58 s = glGetString(GL_RENDERER);
59 renderer = JvNewStringLatin1(s==0 ? "" : (char*)s);
60 s = glGetString(GL_VERSION);
61 version = JvNewStringLatin1(s==0 ? "" : (char*)s);
64 void OpenGL$GLPixelBuffer::drawableInit(jint width, jint height) {
65 glClearColor (0.3f, 0.7f, 1.0f, 1.0f);
67 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
68 glShadeModel(GL_SMOOTH);
70 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
72 glViewport(0,0,width,height);
73 glMatrixMode(GL_PROJECTION);
75 glOrtho(0,width,height,0,-1,1);
76 // CHECKME: This causes textures to be blurry, but something like this
77 // (but not this) might be required to draw straight lines
78 //glMatrixMode(GL_MODELVIEW);
80 //glTranslatef(0.375, 0.375, 0.0);
85 void OpenGL$GLPixelBuffer::setColor(jint argb) {
86 float alpha = ((argb >> 24) & 0xff) / 255.0;
87 float red = ((argb >> 16) & 0xff) / 255.0;
88 float green = ((argb >> 8) & 0xff) / 255.0;
89 float blue = ((argb >> 0) & 0xff) / 255.0;
90 glColor4f(red,green,blue,alpha);
93 void OpenGL$GLPixelBuffer::fillTrapezoid(jint x1, jint x2, jint y1, jint x3, jint x4, jint y2, jint color) {
97 glVertex3f(x1,y1,0.0f );
98 glVertex3f(x3,y2,0.0f );
99 glVertex3f(x4,y2,0.0f );
100 glVertex3f(x2,y1,0.0f );
104 void OpenGL$GLPixelBuffer::natFill(org::ibex::graphics::Polygon* p, jint argb) {
107 for(jint contour=0; contour < p->numcontours; contour++) {
108 glBegin(GL_POLYGON); {
109 for(jint i = elements(p->contours)[contour]; i < elements(p->contours)[contour+1]; i++) {
110 glVertex3f(elements(p->x)[i], elements(p->y)[i], 0.0f );
116 void OpenGL$GLPixelBuffer::setClip(jint x1, jint y1, jint x2, jint y2) {
117 //fprintf(stderr,"setClip: %d %d %d %d\n",x1,y1,x2,y2);
118 if(x1==0 && y1==0 && x2==width && y2==height) {
119 if(glScissorEnabled) {
121 glDisable(GL_SCISSOR_TEST);
122 glScissorEnabled = false;
127 if(!glScissorEnabled) {
128 glEnable(GL_SCISSOR_TEST);
129 glScissorEnabled = true;
131 if((x1 >= x2) || (y1 >= y2))
134 glScissor(x1,height-y2,x2-x1,y2-y1);
138 void OpenGL$GLPixelBuffer::resetClip() {
140 if(glScissorEnabled) {
141 glDisable(GL_SCISSOR_TEST);
142 glScissorEnabled = false;
146 // FEATURE: Eliminate duplicate code in RectGLPicture and SquareGLPicture
147 void OpenGL$RectGLPicture::natInit(Object *data_, jboolean alphaOnly) {
150 int size = width*height;
154 jbyte *data = elements((JArray<jbyte> *)data_);
155 buf = (unsigned char *) data;
157 jint *data = elements((JArray<jint> *)data_);
158 buf = new unsigned char[size*4];
159 for(i=0,j=0;i<size;i++,j+=4) {
160 jint pixel = data[i];
161 buf[j+0] = (pixel >> 16) & 0xff;
162 buf[j+1] = (pixel >> 8) & 0xff;
163 buf[j+2] = (pixel >> 0) & 0xff;
164 buf[j+3] = (pixel >> 24) & 0xff;
168 gl->activateSharedContext();
169 glEnable(GL_TEXTURE_RECTANGLE_EXT);
170 glGenTextures(1,&tex);
171 glBindTexture(GL_TEXTURE_RECTANGLE_EXT,tex);
172 glPixelStorei(GL_PACK_ALIGNMENT,1);
174 GL_TEXTURE_RECTANGLE_EXT,0,
175 alphaOnly ? GL_ALPHA : GL_RGBA,width,height,0,
176 alphaOnly ? GL_ALPHA : GL_RGBA,GL_UNSIGNED_BYTE,buf);
180 if(gl->glVersion >= 1.2) {
181 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
182 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
183 glTexParameterf(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
184 glTexParameterf(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
186 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
187 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
190 glDisable(GL_TEXTURE_RECTANGLE_EXT);
193 textureName = (jint)tex;
196 void OpenGL$RectGLPicture::draw(jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
199 cx2 = min(cx2, dx + width);
200 cy2 = min(cy2, dy + height);
201 if (cy2 <= cy1 || cx2 <= cx1) return;
202 glEnable(GL_TEXTURE_RECTANGLE_EXT);
203 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);
205 glTexCoord2i (cx1 - dx, cy1 - dy );
206 glVertex3i (cx1, cy1, 0);
207 glTexCoord2i (cx2 - dx, cy1 - dy );
208 glVertex3i (cx2, cy1, 0);
209 glTexCoord2i (cx2 - dx, cy2 - dy );
210 glVertex3i (cx2, cy2, 0);
211 glTexCoord2i (cx1 - dx, cy2 - dy );
212 glVertex3i (cx1, cy2, 0);
214 glDisable(GL_TEXTURE_RECTANGLE_EXT);
218 void OpenGL::natDeleteTexture(jint tex_) {
219 activateSharedContext();
220 GLuint tex = (GLuint) tex_;
221 glDeleteTextures(1,&tex);
224 void OpenGL$SquareGLPicture::natInit(Object *data_, jboolean alphaOnly) {
230 jbyte *data = elements((JArray<jbyte>*) data_);
231 if(texWidth == width && texHeight == height) {
232 buf = (unsigned char*) data;
234 buf = new unsigned char[texWidth*texHeight];
236 for(row=0;row<height;row++) {
237 for(col=0;col<width;col++)
238 buf[p++] = data[row*width+col];
239 for(;col<texWidth;col++)
242 for(;row<texHeight;row++)
243 for(col=0;col<texWidth;col++)
247 jint *data = elements((JArray<jint>*) data_);
248 buf = new unsigned char[texWidth*texHeight*4];
250 for(row=0;row<height;row++) {
251 for(col=0;col<width;col++) {
252 jint pixel = data[row*width+col];
253 buf[p+0] = (pixel >> 16) & 0xff;
254 buf[p+1] = (pixel >> 8) & 0xff;
255 buf[p+2] = (pixel >> 0) & 0xff;
256 buf[p+3] = (pixel >> 24) & 0xff;
259 for(;col < texWidth;col++,p+=4)
260 buf[p+0] = buf[p+1] = buf[p+2] = buf[p+3] = 0;
262 for(;row < texHeight;row++)
263 for(col=0;col<texWidth;col++,p+=4)
264 buf[p+0] = buf[p+1] = buf[p+2] = buf[p+3] = 0;
267 gl->activateSharedContext();
268 glEnable(GL_TEXTURE_2D);
269 glGenTextures(1,&tex);
270 glBindTexture(GL_TEXTURE_2D,tex);
271 glPixelStorei(GL_PACK_ALIGNMENT,1);
272 glTexImage2D(GL_TEXTURE_2D,0,alphaOnly ? GL_ALPHA : GL_RGBA,texWidth,texHeight,0,alphaOnly ? GL_ALPHA : GL_RGBA,GL_UNSIGNED_BYTE,buf);
274 if(!alphaOnly || width != texWidth || height != texHeight) delete buf;
276 if(gl->glVersion >= 1.2) {
277 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
278 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
279 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
280 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
282 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
283 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
286 glDisable(GL_TEXTURE_2D);
289 textureName = (jint)tex;
292 void OpenGL$SquareGLPicture::draw(jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
295 cx2 = min(cx2, dx + width);
296 cy2 = min(cy2, dy + height);
297 if (cy2 <= cy1 || cx2 <= cx1) return;
298 float tx1 = (float) (cx1 - dx) / (float) texWidth;
299 float ty1 = (float) (cy1 - dy) / (float) texHeight;
300 float tx2 = (float) (cx2 - dx) / (float) texWidth;
301 float ty2 = (float) (cy2 - dy) / (float) texHeight;
302 glEnable(GL_TEXTURE_2D);
303 glBindTexture(GL_TEXTURE_2D, textureName);
306 glTexCoord2f (tx1, ty1 );
307 glVertex3i (cx1, cy1, 0);
308 glTexCoord2f (tx2, ty1 );
309 glVertex3i (cx2, cy1, 0);
310 glTexCoord2f (tx2, ty2 );
311 glVertex3i (cx2, cy2, 0);
312 glTexCoord2f (tx1, ty2 );
313 glVertex3i (cx1, cy2, 0);
315 glDisable(GL_TEXTURE_2D);
319 } } } // end org::ibex::plat