diff options
author | John Hawthorn <jhawthor@uvic.ca> | 2008-09-13 00:02:38 -0700 |
---|---|---|
committer | John Hawthorn <jhawthor@uvic.ca> | 2008-09-13 00:02:38 -0700 |
commit | d9e9f33c3210b71c07c4268415ff9b1555819b3f (patch) | |
tree | 1574715591b8ae6cb08771ff19670b56a5c887a9 /src/xlib.c | |
parent | 219d3d9d9c17db046755327054be8061bdb2bb7a (diff) | |
download | mirror-meh-d9e9f33c3210b71c07c4268415ff9b1555819b3f.tar.gz mirror-meh-d9e9f33c3210b71c07c4268415ff9b1555819b3f.tar.bz2 mirror-meh-d9e9f33c3210b71c07c4268415ff9b1555819b3f.zip |
Major changes. Optional XShm support, bilinear scaling, caching WIP
Diffstat (limited to 'src/xlib.c')
-rw-r--r-- | src/xlib.c | 182 |
1 files changed, 130 insertions, 52 deletions
@@ -7,6 +7,9 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h> +#include <X11/extensions/XShm.h> +#include <sys/ipc.h> +#include <sys/shm.h> #include "meh.h" @@ -16,80 +19,139 @@ int screen; Window window; GC gc; -static unsigned int getshift(unsigned int mask){ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - return __builtin_ctz(mask); -#else - int i = 0; - while((mask & 1) == 0){ - i++; - mask >>= 1; +int xshm = 0; + +#define GETVAL(x, c) (ibuf[(x) * 3 + (c)]) +#define GETLVAL(x, y, u, v, c) (( \ + (GETVAL((x), (c)) * (1023^(u)) + GETVAL((x)+1, (c)) * (u)) * (1023^(v)) + \ + (GETVAL((x)+img->bufwidth, (c)) * (1023^(u)) + GETVAL((x)+img->bufwidth+1, (c)) * (u)) * (v)) >> 20) + +void scale(struct image *img, XImage *ximg){ + int x, y; + unsigned char * __restrict__ ibuf; + char* __restrict__ newBuf = ximg->data; + unsigned int jdy = ximg->bytes_per_line / 4 - ximg->width; + unsigned int dx = (img->bufwidth << 10) / ximg->width; + + struct timeval t0; + struct timeval t1; + gettimeofday(&t0, NULL); + + for(y = 0; y < ximg->height; y++){ + unsigned int bufy = (y << 10) * img->bufheight / ximg->height; + unsigned int v_ratio = (bufy & 1023); + unsigned int bufx = img->bufwidth / ximg->width; + unsigned char *ibuf = &img->buf[y * img->bufheight / ximg->height * img->bufwidth * 3]; + for(x = ximg->width; x; x--){ + unsigned int u_ratio = (bufx & 1023); + + *newBuf++ = GETLVAL(bufx >> 10, bufy >> 10, u_ratio, v_ratio, 2); + *newBuf++ = GETLVAL(bufx >> 10, bufy >> 10, u_ratio, v_ratio, 1); + *newBuf++ = GETLVAL(bufx >> 10, bufy >> 10, u_ratio, v_ratio, 0); + newBuf++; + + bufx += dx; + } + newBuf += jdy; } - return i; -#endif + + gettimeofday(&t1, NULL); + printf("%i ms\n", ((t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec) / 1000); } + +void linearscale(struct image *img, XImage *ximg){ + unsigned int i; + int x, y; + unsigned int dx; + unsigned char * __restrict__ ibuf; + char* __restrict__ newBuf = ximg->data; + unsigned int jdy = ximg->bytes_per_line / 4 - ximg->width; + dx = (img->bufwidth << 10) / ximg->width; + + struct timeval t0; + struct timeval t1; + gettimeofday(&t0, NULL); + + for(y = 0; y < ximg->height; y++){ + i = 0; + ibuf = &img->buf[y * img->bufheight / ximg->height * img->bufwidth * 3]; + for(x = 0; x < ximg->width; x++){ + *newBuf++ = (ibuf[(i >> 10)*3+2]); + *newBuf++ = (ibuf[(i >> 10)*3+1]); + *newBuf++ = (ibuf[(i >> 10)*3]); + newBuf++; + + i += dx; + } + newBuf += jdy; + } + + gettimeofday(&t1, NULL); + printf("%i ms\n", ((t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec) / 1000); +} + +XShmSegmentInfo *shminfo; XImage *ximage(struct image *img, unsigned int width, unsigned int height) { int depth; XImage *ximg = NULL; Visual *vis; - unsigned int rshift, gshift, bshift; - unsigned int i; - unsigned int x,y; - unsigned int j = 0; depth = DefaultDepth(display, screen); vis = DefaultVisual(display, screen); - rshift = getshift(vis->red_mask); - gshift = getshift(vis->green_mask); - bshift = getshift(vis->blue_mask); - - if (depth >= 24) { - unsigned char *ibuf; - unsigned int dx; - size_t numNewBufBytes = ((sizeof(u_int32_t)) * (width) * (height)); - u_int32_t *newBuf = malloc(numNewBufBytes); - - dx = 1024 * img->width / width; - for(y = 0; y < height; y++){ - i = 0; - ibuf = &img->buf[y * img->height / height * img->width * 3]; - for(x = 0; x < width; x++){ - unsigned int r, g, b; - r = (ibuf[(i >> 10)*3] << rshift) & vis->red_mask; - g = (ibuf[(i >> 10)*3+1] << gshift) & vis->green_mask; - b = (ibuf[(i >> 10)*3+2] << bshift) & vis->blue_mask; - - newBuf[j++] = r | g | b; - i += dx; + if(depth >= 24){ + if(xshm){ + shminfo = malloc(sizeof(XShmSegmentInfo)); + if(!(ximg = XShmCreateImage(display, + CopyFromParent, depth, + ZPixmap, + NULL, + shminfo, + width, height + ))){ + } + if((shminfo->shmid = shmget(IPC_PRIVATE, ximg->bytes_per_line * ximg->height, IPC_CREAT|0777)) == -1){ + fprintf(stderr, "XShm problems\n"); + exit(1); + } + if((shminfo->shmaddr = ximg->data = shmat(shminfo->shmid, 0, 0)) == (void *)-1){ + fprintf(stderr, "XShm problems\n"); + exit(1); + } + shminfo->readOnly = False; + if(!XShmAttach(display, shminfo)){ + fprintf(stderr, "XShm problems, falling back to to XImage\n"); + xshm = 0; } } - - ximg = XCreateImage (display, - CopyFromParent, depth, - ZPixmap, 0, - (char *) newBuf, - width, height, - 32, 0 - ); + if(!xshm){ + ximg = XCreateImage(display, + CopyFromParent, depth, + ZPixmap, 0, + NULL, + width, height, + 32, 0 + ); + ximg->data = malloc(ximg->bytes_per_line * ximg->height + /*HACK*/(ximg->bytes_per_line+1)); + XInitImage(ximg); + } + scale(img, ximg); }else{ /* TODO other depths */ - fprintf(stderr, "This program does not support display depths less than 24.\n"); + fprintf(stderr, "This program does not yet support display depths <24.\n"); exit(1); return NULL; } - XInitImage(ximg); - return ximg; } XImage *getimage(struct image *img, unsigned int width, unsigned int height){ - if(width * img->height > height * img->width){ - return ximage(img, img->width * height / img->height, height); + if(width * img->bufheight > height * img->bufwidth){ + return ximage(img, img->bufwidth * height / img->bufheight, height); }else{ - return ximage(img, width, img->height * width / img->width); + return ximage(img, width, img->bufheight * width / img->bufwidth); } } @@ -103,7 +165,7 @@ void drawimage(XImage *ximg, unsigned int width, unsigned int height){ if(xoffset){ rects[0].width = rects[1].width = xoffset; rects[0].height = rects[1].height = height; - rects[1].x = width-xoffset; + rects[1].x = width - xoffset; rects[1].y = 0; }else if(yoffset){ rects[0].width = rects[1].width = width; @@ -113,10 +175,26 @@ void drawimage(XImage *ximg, unsigned int width, unsigned int height){ } XFillRectangles(display, window, gc, rects, 2); } - XPutImage(display, window, gc, ximg, 0, 0, xoffset, yoffset, ximg->width, ximg->height); + if(xshm){ + XShmPutImage(display, window, gc, ximg, 0, 0, xoffset, yoffset, ximg->width, ximg->height, False); + }else{ + XPutImage(display, window, gc, ximg, 0, 0, xoffset, yoffset, ximg->width, ximg->height); + } XFlush(display); } +void freeXImg(XImage *ximg){ + if(xshm){ + XShmDetach(display, shminfo); + XDestroyImage(ximg); + shmdt(shminfo->shmaddr); + shmctl(shminfo->shmid, IPC_RMID, 0); + free(shminfo); + }else{ + XDestroyImage(ximg); + } +} + void setaspect(unsigned int w, unsigned int h){ XSizeHints *hints = XAllocSizeHints(); |