X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fdevices%2Fopengl.c;h=fd1b745681eac6872bf10836f1b110649a15d7c1;hb=e4687b3aa2aed49fb16ba9e9561344d808750297;hp=a9459a147ac035ce54aad16ef8bcc39c5e77e524;hpb=7dc8b2115c007958d3054233901ba8dd9eb56ba0;p=swftools.git diff --git a/lib/devices/opengl.c b/lib/devices/opengl.c index a9459a1..fd1b745 100644 --- a/lib/devices/opengl.c +++ b/lib/devices/opengl.c @@ -1,17 +1,23 @@ #include #include #include +#include #include "../gfxdevice.h" #include "../gfxtools.h" +#include "../MD5.h" +#include "../types.h" +#include #include #include #include #include -#define ZSTEP (1/65536.0) +//#define ZSTEP (1/65536.0) +#define ZSTEP (1/32.0) +//#define ZSTEP (1/4.0) typedef struct _fontlist { gfxfont_t*font; @@ -25,11 +31,14 @@ typedef struct _internal { int width, height; int currentz; + int config_polygonoutlines; + GLUtesselator *tesselator; + GLUtesselator *tesselator_line; GLUtesselator *tesselator_tex; } internal_t; -static int verbose = 1; +static int verbose = 0; static void dbg(char*format, ...) { char buf[1024]; @@ -38,7 +47,7 @@ static void dbg(char*format, ...) if(!verbose) return; va_start(arglist, format); - vsprintf(buf, format, arglist); + vsnprintf(buf, sizeof(buf)-1, format, arglist); va_end(arglist); l = strlen(buf); while(l && buf[l-1]=='\n') { @@ -59,16 +68,16 @@ void CALLBACK errorCallback(GLenum errorCode) { const GLubyte *estring; estring = gluErrorString(errorCode); - dbg("Tessellation Error: %s\n", estring); + printf("Tessellation Error: %s\n", estring); exit(0); } void CALLBACK beginCallback(GLenum which) { - glBegin(which); + glBegin(which); } void CALLBACK endCallback(void) { - glEnd(); + glEnd(); } void CALLBACK vertexCallback(GLvoid *vertex) { @@ -92,20 +101,28 @@ void CALLBACK vertexCallbackTex(GLvoid *vertex) } void CALLBACK combineCallbackTex(GLdouble coords[3], GLdouble *data[4], GLfloat w[4], GLdouble **out) { - GLdouble *vertex, *texCoord; + GLdouble *vertex; vertex = (GLdouble *) malloc(5 * sizeof(GLdouble)); vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; - texCoord = &vertex[3]; - vertex[3] = w[0]*data[0][3] + w[1]*data[1][3] + w[2]*data[2][3] + w[3]*data[3][3]; - vertex[4] = w[0]*data[0][4] + w[1]*data[1][4] + w[2]*data[2][4] + w[3]*data[3][4]; + if(data[2] && data[3]) { + vertex[3] = w[0]*data[0][3] + w[1]*data[1][3] + w[2]*data[2][3] + w[3]*data[3][3]; + vertex[4] = w[0]*data[0][4] + w[1]*data[1][4] + w[2]*data[2][4] + w[3]*data[3][4]; + } else { + vertex[3] = w[0]*data[0][3] + w[1]*data[1][3]; + vertex[4] = w[0]*data[0][4] + w[1]*data[1][4]; + } *out = vertex; } int opengl_setparameter(struct _gfxdevice*dev, const char*key, const char*value) { + internal_t*i = (internal_t*)dev->internal; dbg("setparameter %s=%s", key, value); + if(!strcmp(key, "polygonoutlines")) { + i->config_polygonoutlines = atoi(value); + } return 0; } @@ -132,11 +149,20 @@ void opengl_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxc { dbg("stroke"); internal_t*i = (internal_t*)dev->internal; + i->currentz++; char running = 0; gfxline_t*l=0; - dbg("stroke"); + glColor4f(color->r/255.0, color->g/255.0, color->b/255.0, color->a/255.0); + + //glLineWidth(width*64); + if(width <= 0) { + width = 1.0; + } glLineWidth(width); + double z = i->currentz*ZSTEP; + + glPolygonOffset(0.0, 500.0); l = line; while(l) { @@ -150,34 +176,31 @@ void opengl_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxc running = 1; glBegin(GL_LINE_STRIP); } - glVertex3d(l->x, l->y, (i->currentz*ZSTEP)); + glVertex3d(l->x, l->y, z); l=l->next; } if(running) { running = 0; glEnd(); } - i->currentz ++; + glLineWidth(1.0); } -void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) +#define SPLINE_SUBDIVISION 2 + +void tesselatePolygon(GLUtesselator*tesselator, double z, gfxline_t*line) { - dbg("fill"); - internal_t*i = (internal_t*)dev->internal; - char running = 0; int len = 0; - double*xyz=0; - double lastx=0,lasty=0; gfxline_t*l=0; - dbg("fill"); - glColor4f(color->r/255.0, color->g/255.0, color->b/255.0, color->a/255.0); - - gluTessBeginPolygon(i->tesselator, NULL); + double lastx=0,lasty=0; + double*xyz=0; + char running = 0; + gluTessBeginPolygon(tesselator, NULL); l = line; len = 0; while(l) { if(l->type == gfx_splineTo) { - double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))/2; + double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))*SPLINE_SUBDIVISION; int steps = (int)c; if(steps<1) steps = 1; len += steps; @@ -187,7 +210,6 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) l = l->next; } //printf("full len:%d\n", len); - double z = (i->currentz*ZSTEP); xyz = malloc(sizeof(double)*3*len); l = line; len = 0; @@ -195,17 +217,17 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) if(l->type == gfx_moveTo) { if(running) { running = 0; - gluTessEndContour(i->tesselator); + gluTessEndContour(tesselator); } } if(!running) { running = 1; - gluTessBeginContour(i->tesselator); + gluTessBeginContour(tesselator); } if(l->type == gfx_splineTo) { int j; - double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))/2; + double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))*SPLINE_SUBDIVISION; int steps = (int)c; if(steps<1) steps = 1; //printf("c=%f d1=%f (%f/%f) d2=%f (%f/%f)\n", c,d1,l->x-l->sx,l->y-l->sy,d2,lastx-l->sx,lasty-l->sy); @@ -217,7 +239,7 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) xyz[len*3+0] = lastx*(1-t)*(1-t) + 2*l->sx*(1-t)*t + l->x*t*t; xyz[len*3+1] = lasty*(1-t)*(1-t) + 2*l->sy*(1-t)*t + l->y*t*t; xyz[len*3+2] = z; - gluTessVertex(i->tesselator, &xyz[len*3], &xyz[len*3]); + gluTessVertex(tesselator, &xyz[len*3], &xyz[len*3]); len++; } //printf("%d\n", len); @@ -225,7 +247,7 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) xyz[len*3+0] = l->x; xyz[len*3+1] = l->y; xyz[len*3+2] = z; - gluTessVertex(i->tesselator, &xyz[len*3], &xyz[len*3]); + gluTessVertex(tesselator, &xyz[len*3], &xyz[len*3]); len++; } lastx = l->x; @@ -235,26 +257,79 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) } if(running) { running = 0; - gluTessEndContour(i->tesselator); + gluTessEndContour(tesselator); } - gluTessEndPolygon(i->tesselator); - i->currentz ++; + gluTessEndPolygon(tesselator); free(xyz); } -void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) +void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) { - dbg("fillbitmap"); + double z; + dbg("fill %02x%02x%02x%02x", color->a, color->r, color->g, color->b); internal_t*i = (internal_t*)dev->internal; - char running = 0; - int len = 0; - double*xyz=0; - gfxline_t*l=0; - glColor4f(1.0,0,0,1.0); + + glDisable(GL_TEXTURE_2D); + glColor4f(color->r/255.0, color->g/255.0, color->b/255.0, color->a/255.0); - GLuint texIDs[1]; - glGenTextures(1, texIDs); + i->currentz ++; + z = (i->currentz*ZSTEP); + tesselatePolygon(i->tesselator, z, line); + + //tesselatePolygon(i->tesselator_line, z, line); +} + +typedef struct _gfxhash +{ + unsigned char d[16]; +} gfxhash_t; +char gfxhash_compare(gfxhash_t*h1, gfxhash_t*h2) +{ + return !memcmp(h1->d, h2->d, 16); +} + +typedef struct _imgopengl +{ + gfxhash_t hash; + GLuint texID; + int width, height; + unsigned char*data; + struct _imgopengl*next; +} imgopengl_t; + +static imgopengl_t*img2texid = 0; + +static gfxhash_t gfximage_hash(gfximage_t*img) +{ + int t; + int size = img->width*img->height*4; + U8*data = (U8*)img->data; + gfxhash_t hash; + hash_md5(data, size, hash.d); + return hash; +} + +static void delTextures() +{ + imgopengl_t*i = img2texid; + while(i) { + imgopengl_t*next = i->next; + if(i->data) { + glDeleteTextures(1, &i->texID); + free(i->data); + } + memset(i, 0, sizeof(imgopengl_t)); + free(i); + i = next; + } +} + +static imgopengl_t*addTexture(gfximage_t*img) +{ + gfxhash_t hash = gfximage_hash(img); + imgopengl_t*i = img2texid; + int width_bits = 0; int height_bits = 0; while(1<width) @@ -264,7 +339,27 @@ void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gf int newwidth = 1<hash) && newwidth==i->width && newheight==i->height) { + return i; + } + i = i->next; + } + + GLuint texIDs[1]; + glGenTextures(1, texIDs); + + i = malloc(sizeof(imgopengl_t)); + i->hash = hash; + i->texID = texIDs[0]; + i->next = img2texid; + img2texid = i; + + i->width = newwidth; + i->height = newheight; + unsigned char*data = malloc(newwidth*newheight*4); + i->data = data; int x,y; for(y=0;yheight;y++) { for(x=0;xwidth;x++) { @@ -273,29 +368,62 @@ void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gf data[(y*newwidth+x)*4+2] = img->data[y*img->width+x].b; data[(y*newwidth+x)*4+3] = img->data[y*img->width+x].a; } + int lastx = img->width - 1; + for(;xdata[y*img->width+lastx].r; + data[(y*newwidth+x)*4+1] = img->data[y*img->width+lastx].g; + data[(y*newwidth+x)*4+2] = img->data[y*img->width+lastx].b; + data[(y*newwidth+x)*4+3] = img->data[y*img->width+lastx].a; + } } + int lasty = img->height - 1; + for(;ydata[lasty*img->width+x].r; + data[(y*newwidth+x)*4+1] = img->data[lasty*img->width+x].g; + data[(y*newwidth+x)*4+2] = img->data[lasty*img->width+x].b; + data[(y*newwidth+x)*4+3] = img->data[lasty*img->width+x].a; + } + } + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, i->texID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, i->width, i->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + return i; +}; + +void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) +{ + dbg("fillbitmap"); + internal_t*i = (internal_t*)dev->internal; + char running = 0; + int len = 0; + double*xyz=0; + gfxline_t*l=0; + glColor4f(1.0,0,0.7,1.0); + + i->currentz ++; + + imgopengl_t* txt = addTexture(img); gfxmatrix_t m2; gfxmatrix_invert(matrix, &m2); - m2.m00 /= newwidth; - m2.m10 /= newwidth; - m2.tx /= newwidth; - m2.m01 /= newheight; - m2.m11 /= newheight; - m2.ty /= newheight; + m2.m00 /= txt->width; + m2.m10 /= txt->width; + m2.tx /= txt->width; + m2.m01 /= txt->height; + m2.m11 /= txt->height; + m2.ty /= txt->height; glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texIDs[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newwidth, newheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - - glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, txt->texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - gluTessBeginPolygon(i->tesselator_tex, NULL); l = line; len = 0; @@ -336,7 +464,6 @@ void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gf gluTessEndContour(i->tesselator_tex); } gluTessEndPolygon(i->tesselator_tex); - i->currentz ++; free(xyz); glDisable(GL_TEXTURE_2D); @@ -372,6 +499,8 @@ void opengl_addfont(gfxdevice_t*dev, gfxfont_t*font) void opengl_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix) { internal_t*i = (internal_t*)dev->internal; + if(!font) + return; if(i->font && i->font->id && !strcmp(font->id, i->font->id)) { // current font is correct @@ -386,8 +515,10 @@ void opengl_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*co l = l->next; } if(i->font == 0) { - fprintf(stderr, "Unknown font id: %s", font->id); - return; + opengl_addfont(dev, font); + i->font = font; + //fprintf(stderr, "Unknown font id: %s", font->id); + //return; } } @@ -398,12 +529,14 @@ void opengl_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*co opengl_fill(dev, line2, color); gfxline_free(line2); + i->currentz --; + return; } -void opengl_drawlink(struct _gfxdevice*dev, gfxline_t*line, char*action) +void opengl_drawlink(struct _gfxdevice*dev, gfxline_t*line, const char*action) { dbg("link"); } @@ -413,12 +546,12 @@ void opengl_endpage(struct _gfxdevice*dev) dbg("endpage"); } -int opengl_result_save(struct _gfxresult*gfx, char*filename) +int opengl_result_save(struct _gfxresult*gfx, const char*filename) { dbg("result:save"); return 0; } -void* opengl_result_get(struct _gfxresult*gfx, char*name) +void* opengl_result_get(struct _gfxresult*gfx, const char*name) { dbg("result:get"); return 0; @@ -427,6 +560,7 @@ void opengl_result_destroy(struct _gfxresult*gfx) { dbg("result:destroy"); free(gfx); + delTextures(); } gfxresult_t*opengl_finish(struct _gfxdevice*dev) @@ -448,6 +582,8 @@ void gfxdevice_opengl_init(gfxdevice_t*dev) dbg("init"); internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t)); memset(dev, 0, sizeof(gfxdevice_t)); + + dev->name = "opengl"; dev->internal = i; @@ -470,7 +606,14 @@ void gfxdevice_opengl_init(gfxdevice_t*dev) gluTessCallback(i->tesselator, GLU_TESS_VERTEX, (callbackfunction_t)vertexCallback); gluTessCallback(i->tesselator, GLU_TESS_BEGIN, (callbackfunction_t)beginCallback); gluTessCallback(i->tesselator, GLU_TESS_END, (callbackfunction_t)endCallback); - //gluTessCallback(i->tesselator, GLU_TESS_END, (callbackfunction_t)combineCallback); + gluTessCallback(i->tesselator, GLU_TESS_COMBINE, (callbackfunction_t)combineCallback); + + i->tesselator_line = gluNewTess(); + gluTessCallback(i->tesselator_line, GLU_TESS_ERROR, (callbackfunction_t)errorCallback); + gluTessCallback(i->tesselator_line, GLU_TESS_VERTEX, (callbackfunction_t)vertexCallback); + gluTessCallback(i->tesselator_line, GLU_TESS_BEGIN, (callbackfunction_t)beginCallback); + gluTessCallback(i->tesselator_line, GLU_TESS_END, (callbackfunction_t)endCallback); + gluTessProperty(i->tesselator_line, GLU_TESS_BOUNDARY_ONLY, 1.0); i->tesselator_tex = gluNewTess(); gluTessCallback(i->tesselator_tex, GLU_TESS_ERROR, (callbackfunction_t)errorCallback);