From bfcdb3b51ea88028b63f3f2d9577659e4119d20a Mon Sep 17 00:00:00 2001 From: lecoanet Date: Tue, 23 Mar 2004 14:53:46 +0000 Subject: Changes related to OpenGL context handling (only one context per display) and patches to avoid using widget structure in image cache */ --- generic/Image.c | 128 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 58 deletions(-) (limited to 'generic/Image.c') diff --git a/generic/Image.c b/generic/Image.c index 09ecdd3..fd0bb60 100644 --- a/generic/Image.c +++ b/generic/Image.c @@ -26,6 +26,7 @@ #include "Types.h" +#include "tkZinc.h" #include "Image.h" #include "WidgetInfo.h" #include "Geo.h" @@ -63,7 +64,8 @@ typedef struct _ImageStruct { GLuint texobj; #endif } i; - struct _ZnWInfo *wi; + Display *dpy; + Screen *screen; struct _ImageBits *bits; /* Bookkeeping */ @@ -89,13 +91,14 @@ typedef struct _ImageBits { #endif /* Bookeeping */ - struct _ZnWInfo *wi; /* The widget that created the tkimage below (the first - * to use this image). */ + Display *dpy; /* The tkimage below comes from this display. */ + Tcl_Interp *interp; /* The interp that created the tkimage below. */ Tk_Image tkimage; /* Keep this handle to be informed of changes */ Tk_PhotoHandle tkphoto; TkRegion valid_region; int width; int height; + int depth; Tcl_HashEntry *hash; /* From this it is easy to get the image/bitmap * name. */ Image images; /* Linked list of widget/display dependant @@ -171,7 +174,7 @@ InvalidateImage(ClientData client_data, * the same name as an old. The image is first deleted then re-instantiated. * As a side effect we also rely on it for telling if an image is a photo. */ - bits->tkphoto = Tk_FindPhoto(bits->wi->interp, image_name); + bits->tkphoto = Tk_FindPhoto(bits->interp, image_name); count = 0; this = bits->images; @@ -179,16 +182,16 @@ InvalidateImage(ClientData client_data, #ifdef GL if (this->for_gl) { if (this->i.texobj) { - ZnGLMakeCurrent(this->wi); + ZnGLMakeCurrent(this->dpy, 0); glDeleteTextures(1, &this->i.texobj); - ZnGLRelease(this->wi); + /*ZnGLRelease(this->wi);*/ this->i.texobj = 0; } } else { #endif if (this->i.pixmap != None) { - Tk_FreePixmap(this->wi->dpy, this->i.pixmap); + Tk_FreePixmap(this->dpy, this->i.pixmap); this->i.pixmap = None; } #ifdef GL @@ -241,7 +244,6 @@ ZnGetImage(ZnWInfo *wi, } bits = ZnMalloc(sizeof(ImageBits)); - bits->wi = wi; #ifdef GL bits->t_bits = NULL; #endif @@ -250,6 +252,8 @@ ZnGetImage(ZnWInfo *wi, bits->valid_region = NULL; bits->tkimage = NULL; bits->tkphoto = NULL; + bits->interp = wi->interp; + bits->dpy = wi->dpy; if (!Tk_GetImageMasterData(wi->interp, image_name, &type)) { /* @@ -270,6 +274,7 @@ ZnGetImage(ZnWInfo *wi, Tk_SizeOfBitmap(wi->dpy, pmap, &bits->width, &bits->height); mask = XGetImage(wi->dpy, pmap, 0, 0, (unsigned int) bits->width, (unsigned int) bits->height, 1L, XYPixmap); + bits->depth = 1; bits->rowstride = mask->bytes_per_line; bits->bpixels = ZnMalloc((unsigned int) (bits->height * bits->rowstride)); memset(bits->bpixels, 0, (unsigned int) (bits->height * bits->rowstride)); @@ -294,10 +299,12 @@ ZnGetImage(ZnWInfo *wi, ZnWarning("bogus photo image \""); goto im_error; } + bits->depth = Tk_Depth(wi->win); bits->tkimage = Tk_GetImage(wi->interp, wi->win, image_name, InvalidateImage, (ClientData) bits); } else { /* Other image types */ + bits->depth = Tk_Depth(wi->win); bits->tkimage = Tk_GetImage(wi->interp, wi->win, image_name, InvalidateImage, (ClientData) bits); Tk_SizeOfImage(bits->tkimage, &bits->width, &bits->height); @@ -323,8 +330,8 @@ ZnGetImage(ZnWInfo *wi, */ for (image = bits->images; image != NULL; image = image->next) { if (image->for_gl == for_gl) { - if ((for_gl && (image->wi->dpy == wi->dpy)) || - (!for_gl && (image->wi->screen == wi->screen))) { + if ((for_gl && (image->dpy == wi->dpy)) || + (!for_gl && (image->screen == wi->screen))) { if (!ZnImageIsBitmap(image)) { cs_ptr = ZnListArray(image->clients); num_cs = ZnListSize(image->clients); @@ -357,7 +364,8 @@ ZnGetImage(ZnWInfo *wi, image->bits = bits; image->refcount = 0; image->for_gl = for_gl; - image->wi = wi; + image->dpy = wi->dpy; + image->screen = wi->screen; if (!ZnImageIsBitmap(image)) { image->clients = ZnListNew(1, sizeof(ClientStruct)); @@ -503,14 +511,13 @@ ZnFreeImage(ZnImage image, } if (this->for_gl) { #ifdef GL - ZnWInfo *wi = this->wi; if (this->i.texobj) { - ZnGLMakeCurrent(wi); + ZnGLMakeCurrent(this->dpy, 0); /* printf("%d Libération de la texture %d pour l'image %s\n", wi, this->i.texobj, ZnNameOfImage(image));*/ glDeleteTextures(1, &this->i.texobj); this->i.texobj = 0; - ZnGLRelease(wi); + /*ZnGLRelease(wi);*/ } #endif } @@ -519,7 +526,7 @@ ZnFreeImage(ZnImage image, * This is an image, we need to free the instances. */ if (this->i.pixmap != None) { - Tk_FreePixmap(this->wi->dpy, this->i.pixmap); + Tk_FreePixmap(this->dpy, this->i.pixmap); } } else { @@ -527,7 +534,7 @@ ZnFreeImage(ZnImage image, * This is a bitmap ask Tk to free the resource. */ if (this->i.pixmap != None) { - Tk_FreeBitmap(this->wi->dpy, this->i.pixmap); + Tk_FreeBitmap(this->dpy, this->i.pixmap); } } ZnFree(this); @@ -598,11 +605,11 @@ ZnSizeOfImage(ZnImage image, ********************************************************************************** */ Pixmap -ZnImagePixmap(ZnImage image) +ZnImagePixmap(ZnImage image, + Tk_Window win) { Image this = (Image) image; ImageBits *bits = this->bits; - ZnWInfo *wi = bits->wi; /*printf("ZnImagePixmap: %s\n", ZnNameOfImage(image));*/ if (this->for_gl) { @@ -613,21 +620,27 @@ ZnImagePixmap(ZnImage image) if (this->i.pixmap == None) { if (ZnImageIsBitmap(image)) { - this->i.pixmap = Tk_GetBitmap(wi->interp, wi->win, Tk_GetUid(ZnNameOfImage(image))); + this->i.pixmap = Tk_GetBitmap(bits->interp, win, Tk_GetUid(ZnNameOfImage(image))); } else { Tk_Image tkimage; - if (bits->wi == wi) { + /* + * If the original image was created on the same display + * as the required display, we can get the pixmap from it. + * On the other hand we need first to obtain an image + * instance on the right display. + */ + if (bits->dpy == this->dpy) { tkimage = bits->tkimage; } else { /* Create a temporary tkimage to draw the pixmap. */ - tkimage = Tk_GetImage(wi->interp, wi->win, ZnNameOfImage(image), NULL, NULL); + tkimage = Tk_GetImage(bits->interp, win, ZnNameOfImage(image), NULL, NULL); } - this->i.pixmap = Tk_GetPixmap(wi->dpy, Tk_WindowId(wi->win), - bits->width, bits->height, Tk_Depth(wi->win)); + this->i.pixmap = Tk_GetPixmap(this->dpy, Tk_WindowId(win), + bits->width, bits->height, bits->depth); Tk_RedrawImage(tkimage, 0, 0, bits->width, bits->height, this->i.pixmap, 0, 0); if (tkimage != bits->tkimage) { @@ -678,9 +691,9 @@ ZnPointInImage(ZnImage image, ********************************************************************************** */ static void -BuildImageRegion(ImageBits *bits) +BuildImageRegion(Display *dpy, + ImageBits *bits) { - ZnWInfo *wi = bits->wi; Pixmap pmap; int x, y, end; GC gc; @@ -688,20 +701,19 @@ BuildImageRegion(ImageBits *bits) XRectangle rect; /*printf("BuildImageRegion: %s\n", ZnNameOfImage(bits->images));*/ - pmap = Tk_GetPixmap(wi->dpy, Tk_WindowId(wi->win), - bits->width, bits->height, Tk_Depth(wi->win)); - gc = XCreateGC(wi->dpy, pmap, 0, NULL); - XSetForeground(wi->dpy, gc, 0); - XFillRectangle(wi->dpy, pmap, gc, 0, 0, bits->width, bits->height); + pmap = Tk_GetPixmap(dpy, DefaultRootWindow(dpy), bits->width, bits->height, bits->depth); + gc = XCreateGC(dpy, pmap, 0, NULL); + XSetForeground(dpy, gc, 0); + XFillRectangle(dpy, pmap, gc, 0, 0, bits->width, bits->height); Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0); - im1 = XGetImage(wi->dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap); + im1 = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap); - XSetForeground(wi->dpy, gc, 1); - XFillRectangle(wi->dpy, pmap, gc, 0, 0, bits->width, bits->height); + XSetForeground(dpy, gc, 1); + XFillRectangle(dpy, pmap, gc, 0, 0, bits->width, bits->height); Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0); - im2 = XGetImage(wi->dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap); - Tk_FreePixmap(wi->dpy, pmap); - XFreeGC(wi->dpy, gc); + im2 = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap); + Tk_FreePixmap(dpy, pmap); + XFreeGC(dpy, gc); bits->valid_region = TkCreateRegion(); @@ -741,10 +753,11 @@ ZnImageRegion(ZnImage image) return NULL; } else { - ImageBits *bits = ((Image) image)->bits; + Image this = (Image) image; + ImageBits *bits = this->bits; #ifdef PTK if (!bits->valid_region) { - BuildImageRegion(bits); + BuildImageRegion(this->dpy, bits); } return bits->valid_region; #else @@ -753,7 +766,7 @@ ZnImageRegion(ZnImage image) } else { if (!bits->valid_region) { - BuildImageRegion(bits); + BuildImageRegion(this->dpy, bits); } return bits->valid_region; } @@ -894,32 +907,31 @@ From8r8g8b(unsigned char *data, } static void -GatherImageTexels(ImageBits *bits) +GatherImageTexels(Display *dpy, + ImageBits *bits) { Pixmap pmap; XImage *im; TkRegion valid_region; - int t_size, depth; - ZnWInfo *wi = bits->wi; + int t_size; /*printf("GatherImageTexels: %s\n", ZnNameOfImage(bits->images));*/ valid_region = ZnImageRegion(bits->images); t_size = bits->t_width * 4 * bits->t_height; bits->t_bits = ZnMalloc(t_size); - depth = Tk_Depth(wi->win); - pmap = Tk_GetPixmap(wi->dpy, Tk_WindowId(wi->win), - bits->width, bits->height, depth); + pmap = Tk_GetPixmap(dpy, DefaultRootWindow(dpy), + bits->width, bits->height, bits->depth); Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0); - im = XGetImage(wi->dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap); - Tk_FreePixmap(wi->dpy, pmap); + im = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap); + Tk_FreePixmap(dpy, pmap); - if (depth == 16) { + if (bits->depth == 16) { From5r6g5b(im->data, bits->width, bits->height, im->bytes_per_line, bits->t_bits, bits->t_width, bits->t_height, valid_region); } - else if ((depth == 24) || (depth == 32)) { + else if ((bits->depth == 24) || (bits->depth == 32)) { From8r8g8b(im->data, bits->width, bits->height, im->bytes_per_line, bits->t_bits, bits->t_width, bits->t_height, valid_region); } @@ -1030,7 +1042,7 @@ ZnImageTex(ZnImage image, * from a locally drawn pixmap. */ else { - GatherImageTexels(bits); + GatherImageTexels(bits->dpy, bits); } } @@ -1487,7 +1499,7 @@ ZnGetTexFont(ZnWInfo *wi, int width, height; unsigned int texw, texh; GLfloat xstep, ystep; - TkFont *tft = (TkFont *) font; + ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy); if (!inited) { Tcl_InitHashTable(&font_textures, TCL_ONE_WORD_KEYS); @@ -1540,18 +1552,18 @@ ZnGetTexFont(ZnWInfo *wi, /* * Initial size of texture. */ - texw = wi->max_tex_size; + texw = ce->max_tex_size; texh = 64; while (texh < (unsigned int) (txf->ascent+txf->descent)) { texh *= 2; } - /*printf("Taille réelle de texture utilisée: %d\n", wi->max_tex_size);*/ + /*printf("Taille réelle de texture utilisée: %d\n", ce->max_tex_size);*/ /* * This is temporarily disabled until we find out * how to reliably get max_tex_size up front without * waiting for the window mapping. */ - if (texh > wi->max_tex_size) { + if (texh > ce->max_tex_size) { goto error; } xstep = 0/*0.5 / texw*/; @@ -1640,14 +1652,14 @@ ZnGetTexFont(ZnWInfo *wi, px = gap; maxheight = height; if ((unsigned int) (py + height + gap) >= texh) { - if (texh*2 < wi->max_tex_size) { + if (texh*2 < ce->max_tex_size) { texh *= 2; ZnFree(txf->teximage); txf->teximage = ZnMalloc(texw * texh * sizeof(unsigned char)); strcpy(glist, glist2); goto restart; } - else if (texw*2 < wi->max_tex_size) { + else if (texw*2 < ce->max_tex_size) { texw *= 2; ZnFree(txf->teximage); txf->teximage = ZnMalloc(texw * texh * sizeof(unsigned char)); @@ -1899,9 +1911,9 @@ ZnFreeTexFont(ZnTexFontInfo tfi) if (this->texobj) { /*printf("%d Libération de la texture %d pour la fonte %s\n", wi, this->texobj, ZnNameOfTexFont(tfi));*/ - ZnGLMakeCurrent(wi); + ZnGLMakeCurrent(wi->dpy, 0); glDeleteTextures(1, &this->texobj); - ZnGLRelease(wi); + /*ZnGLRelease(wi);*/ } /* -- cgit v1.1