I got my build working well enough that I was able to play around with
some of the Baloon3D code. (Ask Ian why you are having problems building B3D on unix... it's his fault!) Attached is a new version of the cross-platform code. Changes: 1. Removed many error tests... OpenGL is a safe protocol so extra error checking is not required. Any sanity checks should be accomplished in the gererated portion of the code, before it reaches the OpenGL interface anyway. This will allow the code to run smoother, especially through deep pipelines. 2. I massacred glSetTransform. It was being overly cautious about setting up the matricies, (setting them to identity before doing anything), and it was manually transposing the input matrices... The version of OpenGL on my system has its own transpose function which, presumably, is better tuned for the implementation's internal representation format. It also makes the code alot cleaner on the client side. The version provided does run both the 3D demos in 3.7 and the teapot stuff in Croquet. -- the build can' t find the croquet sources though I don't know why that is... In the B3D demos of 3.7, it gets around 21-26 FPS in software rendering, and around 48fps in hardware acceleration mode. There are some minor glitches with the grass color but otherwise it's a good driver... /**************************************************************************** * PROJECT: Squeak 3D accelerator * FILE: sqOpenGLRenderer.c * CONTENT: Generic (cross-platform) bindings for OpenGL * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: [hidden email] * RCSID: $Id: sqOpenGLRenderer.c 909 2004-08-31 21:13:51Z bertf $ * * NOTES: * * *****************************************************************************/ #ifdef WIN32 # include <windows.h> # include <winerror.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqVirtualMachine.h" #include "sqConfig.h" #include "sqPlatformSpecific.h" #include "B3DAcceleratorPlugin.h" #if defined (B3DX_GL) #include "sqOpenGLRenderer.h" #if !defined(GL_VERSION_1_1) #warning "This system does not support OpenGL 1.1" #endif // not really used yet, but this is my hardware and I intend to add GL 1.2 features #if !defined(GL_VERSION_1_2) #warning "This system does not support OpenGL 1.2" #endif static float blackLight[4] = { 0.0, 0.0, 0.0, 0.0 }; /*****************************************************************************/ /* Pbuffers are maintained by the next layer down from OpenGL, in the case of X11, it's the GLX interface. Therefore we need to send these calls down to our platform code to get our Inf0z. */ int glGetRendererSurfaceHandle(int handle) { /* If we were to use p-buffers, this would be the place to return a surface handle for the p-buffer so Squeak can blt directly to it. Note that this is a ZILLION times faster when it comes to compositing; so it is definitely a good idea when supported. However, I don't have the time to figure it out so I'll just leave this as an exercise for the interested reader :-) */ /* struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } */ return -1; /* e.g., fail */ } int glGetRendererColorMasks(int handle, int *masks) { /* If a surface is provided, this is the place to fill in the color masks for the surface. Since we don't provide any, we just bail out. */ /* struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } */ return 0; /* e.g., fail */ } int glGetRendererSurfaceWidth(int handle) { /* If a surface is provided return the width of it */ /* struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } */ return -1; /* e.g., fail */ } int glGetRendererSurfaceHeight(int handle) { /* If a surface is provided return the height of it */ /* struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } */ return -1; /* e.g., fail */ } int glGetRendererSurfaceDepth(int handle) { /* If a surface is provided return the depth of it */ /* struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } */ return -1; /* e.g., fail */ } /*****************************************************************************/ /* texture support */ int glAllocateTexture(int handle, int w, int h, int d) /* return handle or -1 on error */ { GLuint texture; char *errMsg = ""; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(w & (w-1)) return -1; /* not power of two */ if(h & (h-1)) return -1; /* not power of two */ DPRINTF(5, (fp, "### Allocating new texture (w = %d, h = %d, d = %d)\n", w, h, d)); glGenTextures(1, &texture); DPRINTF(5, (fp, "Allocated texture id = %d\n", texture)); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); errMsg = "glTexImage2D() failed"; glTexImage2D(GL_TEXTURE_2D, /* target */ 0, /* mipmap level */ 4, /* components */ w, /* width */ h, /* height */ 0, /* border */ GL_RGBA, /* format */ GL_UNSIGNED_BYTE, /* type */ NULL /* image data - if NULL contents is unspecified */); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; DPRINTF(5, (fp,"\tid = %d\n", texture)); return texture; FAILED: DPRINTF(1, (fp, "ERROR (glAllocateTexture): %s -- %s\n", errMsg, glErrString())); glDeleteTextures(1, &texture); return -1; } int glDestroyTexture(int rendererHandle, int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(!glIsTexture(handle)) { return 0; } DPRINTF(5, (fp, "### Destroying texture (id = %d)\n", handle)); glDeleteTextures(1, (GLuint*) &handle); ERROR_CHECK; return 1; } int glActualTextureDepth(int rendererHandle, int handle) /* return depth or <0 on error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer) return -1; return 32; } int glTextureColorMasks(int rendererHandle, int handle, int masks[4]) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer) return 0; #ifdef LSB_FIRST masks[3] = 0xFF000000; masks[2] = 0x00FF0000; masks[1] = 0x0000FF00; masks[0] = 0x000000FF; #else masks[0] = 0xFF000000; masks[1] = 0x00FF0000; masks[2] = 0x0000FF00; masks[3] = 0x000000FF; #endif return 1; } int glTextureByteSex(int rendererHandle, int handle) /* return > 0 if MSB, = 0 if LSB, < 0 if error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer) return -1; #ifdef LSB_FIRST return 0; #else return 1; #endif } int glTextureSurfaceHandle(int rendererHandle, int handle) { /* GL textures are not directly accessible */ return -1; } int glUploadTexture(int rendererHandle, int handle, int w, int h, int d, void* bits) { int y; struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if((d != 32 ) || (!glIsTexture(handle))) return 0; DPRINTF(5, (fp, "### Uploading texture (w = %d, h = %d, d = %d, id = %d)\n", w, h, d, handle)); glBindTexture(GL_TEXTURE_2D, handle); ERROR_CHECK; for(y = 0; y < h; y++) { glTexSubImage2D(GL_TEXTURE_2D, /* target */ 0, /* level */ 0, /* xoffset */ y, /* yoffset */ w, /* width */ 1, /* height */ GL_RGBA, /* format */ GL_UNSIGNED_BYTE, /* type */ ((char*)bits) + (y*w*4)); ERROR_CHECK; } return 1; } int glCompositeTexture(int rendererHandle, int handle, int x, int y, int w, int h, int translucent) { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(!glIsTexture(handle)) return 0; DPRINTF(7, (fp, "glCompositeTexture(%d, %d, %d, %d)\n", x, y, w, h)); { /* setup a transformation so that we're dealing with pixel x/y coordinate systems */ glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); ERROR_CHECK; /* matrix backup complete - now install new mapping */ { int width = renderer->bufferRect[2]; int height = renderer->bufferRect[3]; glViewport(0, 0, width, height); /* now remap from lower left origin to upper left origin while scaling from (-width,+width) to (-1, +1) */ glScaled(2.0/width, -2.0/height, 1.0); /* offset origin to start at 0,0 rather than -width/2,-height/2 */ glTranslated(width*-0.5, height*-0.5, 0.0); ERROR_CHECK; } /* setup the right shading rules */ glPushAttrib(GL_ALL_ATTRIB_BITS); { glShadeModel(GL_FLAT); glEnable(GL_TEXTURE_2D); glDisable(GL_COLOR_MATERIAL); glDisable(GL_DITHER); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDepthMask(GL_FALSE); glColor4d(1.0, 1.0, 1.0, 1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); } ERROR_CHECK; /* prepare for translucency */ if(translucent) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } ERROR_CHECK; } { /* and *THAT* is the hard work ;-))) */ glBindTexture(GL_TEXTURE_2D, handle); ERROR_CHECK; x -= renderer->bufferRect[0]; y -= renderer->bufferRect[1]; DPRINTF(7, (fp, "glRecti(%d, %d, %d, %d)\n", x, y, w, h)); glBegin(GL_QUADS); glTexCoord2d(0.0, 0.0); glVertex2i(x, y); glTexCoord2d(1.0, 0.0); glVertex2i(x+w, y); glTexCoord2d(1.0, 1.0); glVertex2i(x+w, y+h); glTexCoord2d(0.0, 1.0); glVertex2i(x, y+h); glEnd(); ERROR_CHECK; } /* and restore everything back to normal */ { glPopAttrib(); /* BUG BUG BUG - Mac OpenGL has a problem with glPushAttrib/glShadeModel/glPopAttrib - BUG BUG BUG */ glShadeModel(GL_SMOOTH); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } ERROR_CHECK; /* done */ return 1; } /*****************************************************************************/ int glSetViewport(int handle, int x, int y, int w, int h) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### New Viewport\n")); renderer->viewport[0] = x; renderer->viewport[1] = y; renderer->viewport[2] = w; renderer->viewport[3] = h; x -= renderer->bufferRect[0]; y -= renderer->bufferRect[1]; DPRINTF(5, (fp, "\tx: %d\n\ty: %d\n\tw: %d\n\th: %d\n", x, y, w, h)); glViewport(x, renderer->bufferRect[3] - (y+h), w, h); return 1; } int glClearDepthBuffer(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### Clearing depth buffer\n")); glClear(GL_DEPTH_BUFFER_BIT); return 1; } int glClearViewport(int handle, unsigned int bgra, unsigned int pv) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### Clearing viewport buffer\n")); // this looks much less wrong than it used to but that doesn't mean it's right... =( glClearColor( ((bgra >> 16) & 0xff) / 255.0, ((bgra >> 8) & 0xff) / 255.0, (bgra & 0xff) / 255.0, (bgra >> 24) / 255.0); glClear(GL_COLOR_BUFFER_BIT); return 1; } int glFinishRenderer(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### Finishing renderer\n")); glFinish(); return 1; } int glFlushRenderer(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### Flushing renderer\n")); glFlush(); return 1; } int glSwapRendererBuffers(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### Swapping renderer buffers\n")); glSwapBuffers(renderer); ERROR_CHECK; return 1; } int glSetTransform(int handle, float *modelViewMatrix, float *projectionMatrix) { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF(5, (fp, "### Installing new transformations\n")); glMatrixMode(GL_PROJECTION); if(projectionMatrix) glLoadTransposeMatrixf(projectionMatrix); glMatrixMode(GL_MODELVIEW); if(modelViewMatrix) glLoadTransposeMatrixf(modelViewMatrix); return 1; } int glDisableLights(int handle) { int i; GLint max; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF(5, (fp, "### Disabling all lights\n")); glGetIntegerv(GL_MAX_LIGHTS, &max); for(i = 0; i < max; i++) { glDisable(GL_LIGHT0+i); if( (glErr = glGetError()) != GL_NO_ERROR) DPRINTF(1, (fp,"ERROR (glDisableLights): glDisable(GL_LIGHT%d) failed -- %s\n", i, glErrString())); } return 1; } int glLoadMaterial(int handle, B3DPrimitiveMaterial *mat) { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF(5, (fp, "### New Material\n")); if(!mat) { DPRINTF(5, (fp, "\tOFF (material == nil)\n")); glDisable(GL_LIGHTING); return 1; } DPRINTF(5, (fp, "\tambient : %g, %g, %g, %g\n",mat->ambient[0], mat->ambient[1], mat->ambient[2], mat->ambient[3])); DPRINTF(5, (fp, "\tdiffuse : %g, %g, %g, %g\n",mat->diffuse[0], mat->diffuse[1], mat->diffuse[2], mat->diffuse[3])); DPRINTF(5, (fp, "\tspecular : %g, %g, %g, %g\n",mat->specular[0], mat->specular[1], mat->specular[2], mat->specular[3])); DPRINTF(5, (fp, "\temission : %g, %g, %g, %g\n",mat->emission[0], mat->emission[1], mat->emission[2], mat->emission[3])); DPRINTF(5, (fp, "\tshininess: %g\n", mat->shininess)); glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat->ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat->emission); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat->shininess); return 1; } int glLoadLight(int handle, int idx, B3DPrimitiveLight *light) { float pos[4]; int index = GL_LIGHT0 + idx; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF(5, (fp, "### New Light (%d)\n", idx)); if(!light) { DPRINTF(5, (fp, "\tDISABLED\n")); glDisable(index); ERROR_CHECK; return 1; } glEnable(index); ERROR_CHECK; /* DPRINTF(5, (fp, "\tambient : %g, %g, %g, %g\n",light->ambient[0], light->ambient[1], light->ambient[2], light->ambient[3])); DPRINTF(5, (fp, "\tdiffuse : %g, %g, %g, %g\n",light->diffuse[0], light->diffuse[1], light->diffuse[2], light->diffuse[3])); DPRINTF(5, (fp, "\tspecular : %g, %g, %g, %g\n",light->specular[0], light->specular[1], light->specular[2], light->specular[3])); DPRINTF(5, (fp, "\tposition : %g, %g, %g\n",light->position[0], light->position[1], light->position[2])); DPRINTF(5, (fp, "\tdirection : %g, %g, %g\n",light->direction[0], light->direction[1], light->direction[2])); DPRINTF(5, (fp, "\tattenuation : %g, %g, %g\n",light->attenuation[0], light->attenuation[1], light->attenuation[2])); DPRINTF(5, (fp, "\tflags [%d]:", light->flags)); if(light->flags & B3D_LIGHT_AMBIENT) DPRINTF(5,(fp," B3D_LIGHT_AMBIENT")); if(light->flags & B3D_LIGHT_DIFFUSE) DPRINTF(5,(fp," B3D_LIGHT_DIFFUSE")); if(light->flags & B3D_LIGHT_SPECULAR) DPRINTF(5,(fp," B3D_LIGHT_SPECULAR")); if(light->flags & B3D_LIGHT_POSITIONAL) DPRINTF(5,(fp," B3D_LIGHT_POSITIONAL")); if(light->flags & B3D_LIGHT_DIRECTIONAL) DPRINTF(5,(fp," B3D_LIGHT_DIRECTIONAL")); if(light->flags & B3D_LIGHT_ATTENUATED) DPRINTF(5,(fp," B3D_LIGHT_ATTENUATED")); if(light->flags & B3D_LIGHT_HAS_SPOT) DPRINTF(5,(fp," B3D_LIGHT_HAS_SPOT")); DPRINTF(5, (fp, "\n")); DPRINTF(5, (fp, "\tspot exponent : %g\n", light->spotExponent)); DPRINTF(5, (fp, "### Installing Light (%d)\n", idx)); */ if(light->flags & B3D_LIGHT_AMBIENT) { DPRINTF(5, (fp, "\tambient : %g, %g, %g, %g\n",light->ambient[0], light->ambient[1], light->ambient[2], light->ambient[3])); glLightfv(index, GL_AMBIENT, light->ambient); } else { DPRINTF(5, (fp, "\tambient : OFF (0, 0, 0, 1)\n")); glLightfv(index, GL_AMBIENT, blackLight); } if(light->flags & B3D_LIGHT_DIFFUSE) { DPRINTF(5, (fp, "\tdiffuse : %g, %g, %g, %g\n",light->diffuse[0], light->diffuse[1], light->diffuse[2], light->diffuse[3])); glLightfv(index, GL_DIFFUSE, light->diffuse); } else { DPRINTF(5, (fp, "\tdiffuse : OFF (0, 0, 0, 1)\n")); glLightfv(index, GL_DIFFUSE, blackLight); } if(light->flags & B3D_LIGHT_SPECULAR) { DPRINTF(5, (fp, "\tspecular : %g, %g, %g, %g\n",light->specular[0], light->specular[1], light->specular[2], light->specular[3])); glLightfv(index, GL_SPECULAR, light->specular); } else { DPRINTF(5, (fp, "\tspecular : OFF (0, 0, 0, 1)\n")); glLightfv(index, GL_SPECULAR, blackLight); } if(light->flags & B3D_LIGHT_POSITIONAL) { DPRINTF(5, (fp, "\tposition : %g, %g, %g\n",light->position[0], light->position[1], light->position[2])); pos[0] = light->position[0]; pos[1] = light->position[1]; pos[2] = light->position[2]; pos[3] = 1.0; /* @@@ FIXME: Squeak pre-transforms the light @@@ */ glPushMatrix(); glLoadIdentity(); glLightfv(index, GL_POSITION, pos); glPopMatrix(); } else { if(light->flags & B3D_LIGHT_DIRECTIONAL) { DPRINTF(5, (fp, "\tdirection: %g, %g, %g\n",light->direction[0], light->direction[1], light->direction[2])); pos[0] = light->direction[0]; pos[1] = light->direction[1]; pos[2] = light->direction[2]; pos[3] = 0.0; /* @@@ FIXME: Squeak pre-transforms the light @@@ */ glPushMatrix(); glLoadIdentity(); glLightfv(index, GL_POSITION, pos); glPopMatrix(); } } if(light->flags & B3D_LIGHT_ATTENUATED) { DPRINTF(5, (fp, "\tattenuation: %g, %g, %g\n",light->attenuation[0], light->attenuation[1], light->attenuation[2])); glLightf(index, GL_CONSTANT_ATTENUATION, light->attenuation[0]); glLightf(index, GL_LINEAR_ATTENUATION, light->attenuation[1]); glLightf(index, GL_QUADRATIC_ATTENUATION, light->attenuation[2]); } else { DPRINTF(5, (fp, "\tattenuation: OFF (1, 0, 0)\n")); glLightf(index, GL_CONSTANT_ATTENUATION, 1.0); glLightf(index, GL_LINEAR_ATTENUATION, 0.0); glLightf(index, GL_QUADRATIC_ATTENUATION, 0.0); } if(light->flags & B3D_LIGHT_HAS_SPOT) { DPRINTF(5, (fp, "\tspot exponent : %g\n", light->spotExponent)); DPRINTF(5, (fp, "\tspot cutoff : ???\n")); DPRINTF(5, (fp, "\tspot direction: %g, %g, %g\n",light->direction[0], light->direction[1], light->direction[2])); glLightf(index, GL_SPOT_EXPONENT, light->spotExponent); glLightf(index, GL_SPOT_CUTOFF, light->spotExponent); glLightfv(index, GL_SPOT_DIRECTION, light->direction); } else { glLightf(index, GL_SPOT_EXPONENT, 0.0); glLightf(index, GL_SPOT_CUTOFF, 180.0); } return 1; } int glSetFog(int handle, int fogType, double density, double fogRangeStart, double fogRangeEnd, int rgba) { GLfloat fogColor[4]; glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(fogType == 0) { glDisable(GL_FOG); ERROR_CHECK; return 1; } glEnable(GL_FOG); if(fogType == 1) glFogi(GL_FOG_MODE, GL_LINEAR); if(fogType == 2) glFogi(GL_FOG_MODE, GL_EXP); if(fogType == 3) glFogi(GL_FOG_MODE, GL_EXP2); glFogf(GL_FOG_DENSITY, (GLfloat)density); glFogf(GL_FOG_START, (GLfloat)fogRangeStart); glFogf(GL_FOG_END, (GLfloat)fogRangeEnd); fogColor[0] = ((rgba >> 16) & 255) / 255.0; fogColor[1] = ((rgba >> 8) & 255) / 255.0; fogColor[2] = (rgba & 255) / 255.0; fogColor[3] = (rgba >> 24) / 255.0; glFogfv(GL_FOG_COLOR, fogColor); /* enable pixel fog */ glHint(GL_FOG_HINT, GL_NICEST); return 1; } int glGetIntProperty(int handle, int prop) { GLint v; glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(prop < 0) return glGetIntPropertyOS(handle, prop); switch(prop) { case 1: /* backface culling */ if(!glIsEnabled(GL_CULL_FACE)) return 0; glGetIntegerv(GL_FRONT_FACE, &v); if(v == GL_CW) return 1; if(v == GL_CCW) return -1; return 0; case 2: /* polygon mode */ glGetIntegerv(GL_POLYGON_MODE, &v); return v; case 3: /* point size */ glGetIntegerv(GL_POINT_SIZE, &v); return v; case 4: /* line width */ glGetIntegerv(GL_LINE_WIDTH, &v); return v; case 5: /* blend enable */ return glIsEnabled(GL_BLEND); case 6: /* blend source factor */ case 7: /* blend dest factor */ if(prop == 6) glGetIntegerv(GL_BLEND_SRC, &v); else glGetIntegerv(GL_BLEND_DST, &v); switch(v) { case GL_ZERO: return 0; case GL_ONE: return 1; case GL_SRC_COLOR: return 2; case GL_ONE_MINUS_SRC_COLOR: return 3; case GL_DST_COLOR: return 4; case GL_ONE_MINUS_DST_COLOR: return 5; case GL_SRC_ALPHA: return 6; case GL_ONE_MINUS_SRC_ALPHA: return 7; case GL_DST_ALPHA: return 8; case GL_ONE_MINUS_DST_ALPHA: return 9; case GL_SRC_ALPHA_SATURATE: return 10; default: return -1; } } return 0; } int glSetIntProperty(int handle, int prop, int value) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(prop < 0) return glSetIntPropertyOS(handle, prop, value); switch(prop) { case 1: /* backface culling */ if(!value) { glDisable(GL_CULL_FACE); ERROR_CHECK; return 1; } glEnable(GL_CULL_FACE); glFrontFace(value == 1 ? GL_CCW : GL_CW); ERROR_CHECK; return 1; case 2: /* polygon mode */ if(value == 0) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else if(value == 1) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else if(value == 2) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); else return 0; return 1; case 3: /* point size */ glPointSize(value); ERROR_CHECK; return 1; case 4: /* line width */ glLineWidth(value); ERROR_CHECK; return 1; case 5: /* blend enable */ if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND); return 1; case 6: /* blend source factor */ case 7: /* blend dest factor */ { int factor; GLint src, dst; switch(value) { case 0: factor = GL_ZERO; break; case 1: factor = GL_ONE; break; case 2: factor = GL_SRC_COLOR; break; case 3: factor = GL_ONE_MINUS_SRC_COLOR; break; case 4: factor = GL_DST_COLOR; break; case 5: factor = GL_ONE_MINUS_DST_COLOR; break; case 6: factor = GL_SRC_ALPHA; break; case 7: factor = GL_ONE_MINUS_SRC_ALPHA; break; case 8: factor = GL_DST_ALPHA; break; case 9: factor = GL_ONE_MINUS_DST_ALPHA; break; case 10: factor = GL_SRC_ALPHA_SATURATE; break; default: return 0; } glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); if(prop == 6) src = factor; else dst = factor; glBlendFunc(src,dst); return 1; } } return 0; } #ifndef GL_VERSION_1_1 static void glRenderVertex(B3DPrimitiveVertex *vtx, int flags) { DPRINTF(10, (fp, "[")); if(flags & 1) { unsigned int vv = vtx->pixelValue32; DPRINTF(10, (fp, "C(%d, %d, %d, %d)",(vv >> 16) & 255, (vv >> 8) & 255, vv & 255, vv >> 24)); glColor4ub( (vv >> 16) & 255, (vv >> 8) & 255, vv & 255, vv >> 24 ); } if(flags & 2) { DPRINTF(10, (fp, "N(%g, %g, %g)", vtx->normal[0], vtx->normal[1], vtx->normal[2])); glNormal3fv(vtx->normal); } if(flags & 4) { DPRINTF(10, (fp, "T(%g, %g)", vtx->texCoord[0], vtx->texCoord[1])); glTexCoord2fv(vtx->texCoord); } DPRINTF(10, (fp, "V(%g, %g, %g)]\n", vtx->position[0], vtx->position[1], vtx->position[2])); glVertex3fv(vtx->position); } #endif /* General dummy for Squeak's primitive faces */ typedef int B3DInputFace; int glRenderVertexBuffer(int handle, int primType, int flags, int texHandle, float *vtxArray, int vtxSize, int *idxArray, int idxSize) { B3DPrimitiveVertex *vtxPointer = (B3DPrimitiveVertex*) vtxArray; B3DInputFace *facePtr = (B3DInputFace*) idxArray; GLuint tracking; int nVertices = vtxSize; int i, vtxFlags; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } /* DPRINTF(5, (fp,"### Primitive : %d\n", primType)); DPRINTF(5, (fp,"\ttexHandle : %d\n", texHandle)); DPRINTF(5, (fp,"\tcolor flags :")); if(flags & B3D_VB_TRACK_AMBIENT) DPRINTF(5,(fp," B3D_VB_TRACK_AMBIENT")); if(flags & B3D_VB_TRACK_DIFFUSE) DPRINTF(5,(fp," B3D_VB_TRACK_DIFFUSE")); if(flags & B3D_VB_TRACK_SPECULAR) DPRINTF(5,(fp," B3D_VB_TRACK_SPECULAR")); if(flags & B3D_VB_TRACK_EMISSION) DPRINTF(5,(fp," B3D_VB_TRACK_EMISSION")); DPRINTF(5, (fp,"\n\tlight flags :")); if(flags & B3D_VB_LOCAL_VIEWER) DPRINTF(5,(fp," B3D_VB_LOCAL_VIEWER")); if(flags & B3D_VB_TWO_SIDED) DPRINTF(5,(fp," B3D_VB_TWO_SIDED")); DPRINTF(5, (fp,"\n\tvertex flags:")); if(flags & B3D_VB_HAS_NORMALS) DPRINTF(5,(fp," B3D_VB_HAS_NORMALS")); if(flags & B3D_VB_HAS_TEXTURES) DPRINTF(5,(fp," B3D_VB_HAS_TEXTURES")); DPRINTF(5, (fp, "\n")); */ /* process VB flags */ tracking = 0; if(flags & B3D_VB_TRACK_AMBIENT) tracking |= GL_AMBIENT; if(flags & B3D_VB_TRACK_DIFFUSE) tracking |= GL_DIFFUSE; if(flags & B3D_VB_TRACK_SPECULAR) tracking |= GL_SPECULAR; if(flags & B3D_VB_TRACK_EMISSION) tracking |= GL_EMISSION; if(tracking) { /* in accordance with glColorMaterial man page noting: Call glColorMaterial before enabling GL_COLOR_MATERIAL. */ glColorMaterial(GL_FRONT_AND_BACK, tracking); glEnable(GL_COLOR_MATERIAL); } glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (flags & B3D_VB_LOCAL_VIEWER) ? 1 : 0); ERROR_CHECK; glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (flags & B3D_VB_TWO_SIDED) ? 1 : 0); ERROR_CHECK; if(texHandle > 0) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texHandle); } else glDisable(GL_TEXTURE_2D); vtxFlags = 0; if(tracking) vtxFlags |= 1; if(flags & B3D_VB_HAS_NORMALS) vtxFlags |= 2; if(flags & B3D_VB_HAS_TEXTURES) vtxFlags |= 4; #ifdef GL_VERSION_1_1 /* use glDrawElements() etc */ /* @@@ HACK!!! */ vtxPointer -= 1; /* that way we can submit all vertices at once */ if(vtxFlags & 1) { /* harumph... we need to rotate all the colors as we're getting ARGB here but GL expects RGBA... */ for(i=1;i<=nVertices;i++) { unsigned int argb = vtxPointer[i].pixelValue32; unsigned int rgba = (argb << 8) | (argb >> 24); vtxPointer[i].pixelValue32 = rgba; } glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(B3DPrimitiveVertex), &(vtxPointer->pixelValue32)); glEnableClientState(GL_COLOR_ARRAY); } if(vtxFlags & 2) { glNormalPointer(GL_FLOAT, sizeof(B3DPrimitiveVertex), vtxPointer->normal); glEnableClientState(GL_NORMAL_ARRAY); } if(vtxFlags & 4) { glTexCoordPointer(2, GL_FLOAT, sizeof(B3DPrimitiveVertex), vtxPointer->texCoord); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } glVertexPointer(3, GL_FLOAT, sizeof(B3DPrimitiveVertex), vtxPointer->position); glEnableClientState(GL_VERTEX_ARRAY); ERROR_CHECK; /* @@@ HACK!!! */ vtxPointer += 1; /* that way we can submit all vertices at once */ #endif /* GL_VERSION_1_1 */ switch(primType) { case 1: /* points */ #ifdef GL_VERSION_1_1 glDrawArrays(GL_POINTS, 1, nVertices); #else /* !GL_VERSION_1_1 */ glBegin(GL_POINTS); for(i=0; i < nVertices; i++) glRenderVertex(vtxPointer + i, vtxFlags); glEnd(); #endif /* GL_VERSION_1_1 */ break; case 2: /* lines */ #ifdef GL_VERSION_1_1 glDrawArrays(GL_LINES, 1, nVertices); #else /* !GL_VERSION_1_1 */ glBegin(GL_LINES); for(i=0; i < nVertices; i++) glRenderVertex(vtxPointer + i, vtxFlags); glEnd(); #endif /* GL_VERSION_1_1 */ break; case 3: /* polygon */ #ifdef GL_VERSION_1_1 glDrawArrays(GL_POLYGON, 1, nVertices); #else /* !GL_VERSION_1_1 */ glBegin(GL_POLYGON); for(i=0; i < nVertices; i++) glRenderVertex(vtxPointer + i, vtxFlags); glEnd(); #endif /* GL_VERSION_1_1 */ break; case 4: /* indexed lines */ #ifdef GL_VERSION_1_1 glDrawElements(GL_LINES, idxSize, GL_UNSIGNED_INT, facePtr); #else /* !GL_VERSION_1_1 */ nFaces = idxSize / 2; glBegin(GL_LINES); for(i = 0; i < nFaces; i++) { B3DInputFace *face = facePtr + (2*i); if(face[0] && face[1]) { DPRINTF(10, (fp,"\n")); glRenderVertex(vtxPointer + face[0] - 1, vtxFlags); glRenderVertex(vtxPointer + face[1] - 1, vtxFlags); } } glEnd(); #endif /* GL_VERSION_1_1 */ break; case 5: /* indexed triangles */ #ifdef GL_VERSION_1_1 glDrawElements(GL_TRIANGLES, idxSize, GL_UNSIGNED_INT, facePtr); #else /* !GL_VERSION_1_1 */ nFaces = idxSize / 3; glBegin(GL_TRIANGLES); for(i = 0; i < nFaces; i++) { B3DInputFace *face = facePtr + (3*i); if(face[0] && face[1] && face[2]) { DPRINTF(10, (fp,"\n")); glRenderVertex(vtxPointer + face[0] - 1, vtxFlags); glRenderVertex(vtxPointer + face[1] - 1, vtxFlags); glRenderVertex(vtxPointer + face[2] - 1, vtxFlags); } } glEnd(); #endif /* GL_VERSION_1_1 */ break; case 6: /* indexed quads */ #ifdef GL_VERSION_1_1 glDrawElements(GL_QUADS, idxSize, GL_UNSIGNED_INT, facePtr); #else /* !GL_VERSION_1_1 */ nFaces = idxSize / 4; glBegin(GL_QUADS); for(i = 0; i < nFaces; i++) { B3DInputFace *face = facePtr + (4*i); if(face[0] && face[1] && face[2] && face[3]) { DPRINTF(10, (fp,"\n")); glRenderVertex(vtxPointer + face[0] - 1, vtxFlags); glRenderVertex(vtxPointer + face[1] - 1, vtxFlags); glRenderVertex(vtxPointer + face[2] - 1, vtxFlags); glRenderVertex(vtxPointer + face[3] - 1, vtxFlags); } } glEnd(); #endif /* GL_VERSION_1_1 */ break; } ERROR_CHECK; DPRINTF(5, (fp,"\n")); glDisable(GL_COLOR_MATERIAL); ERROR_CHECK; #ifdef GL_VERSION_1_1 if(vtxFlags & 1) glDisableClientState(GL_COLOR_ARRAY); if(vtxFlags & 2) glDisableClientState(GL_NORMAL_ARRAY); if(vtxFlags & 4) glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); ERROR_CHECK; #endif /* GL_VERSION_1_1 */ return 1; } #endif /* defined B3DX_GL */ |
Am 09.03.2005 um 15:26 schrieb Alan Grimes:
> I got my build working well enough that I was able to play around with > some of the Baloon3D code. (Ask Ian why you are having problems > building B3D on unix... it's his fault!) Didn't know I had problems ... but blaming Ian is always a good bet. Ian, you're guilty! > Attached is a new version of the cross-platform code. 1. Please try setting your mail client to not inline attachments. This is what you sent: Content-Type: text/plain; name="sqOpenGLRenderer.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sqOpenGLRenderer.c" 2. Please send diffs in context or unified format. It makes reading your changes much more efficient for others. I have attached one. > Changes: > > 1. Removed many error tests... OpenGL is a safe protocol so extra > error checking is not required. Any sanity checks should be > accomplished in the gererated portion of the code, before it reaches > the OpenGL interface anyway. This will allow the code to run smoother, > especially through deep pipelines. glGetError() is very cheap if no error happened. If there was one it is very nice for debugging to see exactly which call caused it. So unless you can demonstrate this is indeed hurting performance, I'd leave them in place. > 2. I massacred glSetTransform. It was being overly cautious about > setting up the matricies, (setting them to identity before doing > anything), and it was manually transposing the input matrices... The > version of OpenGL on my system has its own transpose function which, > presumably, is better tuned for the implementation's internal > representation format. It also makes the code alot cleaner on the > client side. You would need to check for the existence of ARB_transpose_matrix before using glLoadTransposeMatrix(). I guess this will not even compile on Windows. Mind, if you touch anything in the platforms/Cross directory you better make sure it works everywhere. > The version provided does run both the 3D demos in 3.7 and the teapot > stuff in Croquet. Croquet doesn't actually use any of the OpenGL stuff in this file, but only the GLX code. > -- the build can't find the croquet sources though I don't know why > that is... Did you read the error message thoroughly? I bet it said where it was looking for which sources file. Make sure it's there. > In the B3D demos of 3.7, it gets around 21-26 FPS in software > rendering, and around 48fps in hardware acceleration mode. There are > some minor glitches with the grass color but otherwise it's a good > driver... Did your changes yield any measurable performance improvement? If so, on what hardware? - Bert - sqOpenGLRenderer.c.diff (18K) Download Attachment |
In reply to this post by Alan Grimes
Hi Alan,
[Note that the disney email address is no longer valid] > I got my build working well enough that I was able to play around with > some of the Baloon3D code. (Ask Ian why you are having problems building > B3D on unix... it's his fault!) Can you say something more specifically about what the problem is? I have been recompiling Unix VMs on my share of obscure platforms and never had a problem. Something more specific than "ask Ian" would be greatly appreciated. > 1. Removed many error tests... OpenGL is a safe protocol so extra error > checking is not required. Any sanity checks should be accomplished in > the gererated portion of the code, before it reaches the OpenGL > interface anyway. This will allow the code to run smoother, especially > through deep pipelines. That was a mistake. Assuming that OpenGL is a "safe protocol" is fine as long as you are dealing with the specs - when it comes to the ugly reality of dealing with the drivers these checks can be live-saving (see glCompositeTransform for a rather obscure Mac driver bug we had to work around). Removing the checks was in particular a mistake because you can just #define them away, e.g., adding a #undefine ERRORCHECK #define ERRORCHECK will make all of the tests dissappear so there is absolutely no reason to remove them from the sources. > 2. I massacred glSetTransform. It was being overly cautious about > setting up the matricies, (setting them to identity before doing > anything), and it was manually transposing the input matrices... The > version of OpenGL on my system has its own transpose function which, > presumably, is better tuned for the implementation's internal > representation format. It also makes the code alot cleaner on the client > side. Again, the caution you see is the result of a workaround for some obscure driver bug (I don't recall the details but it had to do with the fact that on some driver there was a bug in analyzing the transform and resetting the matrix did reset those flags to work properly... so much for the safety of OpenGL ;-) About glLoadTransposeMatrixf - this would require OpenGL 1.3 support and the sources can (and should, I think) be capable of getting away with 1.1 support - largely because this is still the latest version support by various Microsoft header files so people who'd want to compile Squeak using the MS libs would have a very hard time to figure this out. So thanks for the proposed changes but I think we shouldn't adopt them. Both the error checks and being able to compile with 1.1 seem too important to me to commit any of the changes. > In the B3D demos of 3.7, it gets around 21-26 FPS in software rendering, > and around 48fps in hardware acceleration mode. There are some minor > glitches with the grass color but otherwise it's a good driver... Just out of curiosity: Is there any difference when you turn on the error checks? I wouldn't expect any but then I've never really tried... Cheers, - Andreas |
> ...the caution you see is the result of a workaround for some > obscure driver bug (I don't recall the details but it had to do > with... Hmm, it'd be nice if stuff like this were noted in a comment at the time. -C -- Craig Latta improvisational musical informaticist craig@{netjam.org, weather-dimensions.com, appliedminds.com} www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)] |
Free forum by Nabble | Edit this page |