2 * Blit ARGB images to X with X(Shm)Images
11 #include <X11/extensions/XShm.h>
15 typedef void (*ximage_convert_func_t
)
17 const unsigned char *src
,
44 static char *modename
[] = {
59 extern ximage_convert_func_t ximage_convert_funcs
[];
73 ximage_convert_func_t convert_func
;
76 XImage
*pool
[POOLSIZE
];
77 /* MUST exist during the lifetime of the shared ximage according to the
78 xc/doc/hardcopy/Xext/mit-shm.PS.gz */
79 XShmSegmentInfo shminfo
[POOLSIZE
];
84 createximage(Display
*dpy
, Visual
*vis
, XShmSegmentInfo
*xsi
, int depth
, int w
, int h
)
89 if (!XShmQueryExtension(dpy
)) goto fallback
;
91 img
= XShmCreateImage(dpy
, vis
, depth
, ZPixmap
, nil
, xsi
, w
, h
);
94 fprintf(stderr
, "warn: could not XShmCreateImage\n");
98 xsi
->shmid
= shmget(IPC_PRIVATE
,
99 img
->bytes_per_line
* img
->height
,
104 fprintf(stderr
, "warn: could not shmget\n");
108 img
->data
= xsi
->shmaddr
= shmat(xsi
->shmid
, 0, 0);
109 if (img
->data
== (char*)-1)
112 fprintf(stderr
, "warn: could not shmat\n");
116 xsi
->readOnly
= False
;
117 status
= XShmAttach(dpy
, xsi
);
122 fprintf(stderr
, "warn: could not XShmAttach\n");
128 shmctl(xsi
->shmid
, IPC_RMID
, 0);
135 img
= XCreateImage(dpy
, vis
, depth
, ZPixmap
, 0, 0, w
, h
, 32, 0);
138 fprintf(stderr
, "fail: could not XCreateImage");
142 img
->data
= malloc(h
* img
->bytes_per_line
);
145 fprintf(stderr
, "fail: could not malloc");
155 if (info
.visual
.class == PseudoColor
&& info
.visual
.depth
== 8)
159 for (b
= 0; b
< 4; b
++) {
160 for (g
= 0; g
< 8; g
++) {
161 for (r
= 0; r
< 8; r
++) {
162 info
.rgbcube
[i
].pixel
= i
;
163 info
.rgbcube
[i
].red
= (r
* 36) << 8;
164 info
.rgbcube
[i
].green
= (g
* 36) << 8;
165 info
.rgbcube
[i
].blue
= (b
* 85) << 8;
166 info
.rgbcube
[i
].flags
=
167 DoRed
| DoGreen
| DoBlue
;
172 info
.colormap
= XCreateColormap(info
.display
,
173 RootWindow(info
.display
, info
.screen
),
176 XStoreColors(info
.display
, info
.colormap
, info
.rgbcube
, 256);
179 else if (info
.visual
.class == TrueColor
)
184 fprintf(stderr
, "Cannot handle visual class %d with depth: %d\n",
185 info
.visual
.class, info
.visual
.depth
);
195 unsigned long rm
, gm
, bm
;
196 unsigned long rs
, gs
, bs
;
198 byteorder
= ImageByteOrder(info
.display
);
199 #if BYTE_ORDER == BIG_ENDIAN
200 byterev
= byteorder
!= MSBFirst
;
202 byterev
= byteorder
!= LSBFirst
;
205 rm
= info
.visual
.red_mask
;
206 gm
= info
.visual
.green_mask
;
207 bm
= info
.visual
.blue_mask
;
213 printf("ximage: mode %d/%d %08lx %08lx %08lx (%ld,%ld,%ld) %s%s\n",
216 rm
, gm
, bm
, rs
, gs
, bs
,
217 byteorder
== MSBFirst
? "msb" : "lsb",
218 byterev
? " <swap>":"");
221 if (info
.bitsperpixel
== 8) {
222 /* Either PseudoColor with BGR233 colormap, or TrueColor */
225 else if (info
.bitsperpixel
== 16) {
226 if (rm
== 0xF800 && gm
== 0x07E0 && bm
== 0x001F)
227 info
.mode
= !byterev
? RGB565
: RGB565_BR
;
228 if (rm
== 0x7C00 && gm
== 0x03E0 && bm
== 0x001F)
229 info
.mode
= !byterev
? RGB555
: RGB555_BR
;
231 else if (info
.bitsperpixel
== 24) {
232 if (rs
== 0 && gs
== 8 && bs
== 16)
233 info
.mode
= byteorder
== MSBFirst
? RGB888
: BGR888
;
234 if (rs
== 16 && gs
== 8 && bs
== 0)
235 info
.mode
= byteorder
== MSBFirst
? BGR888
: RGB888
;
237 else if (info
.bitsperpixel
== 32) {
238 if (rs
== 0 && gs
== 8 && bs
== 16)
239 info
.mode
= byteorder
== MSBFirst
? ABGR8888
: RGBA8888
;
240 if (rs
== 8 && gs
== 16 && bs
== 24)
241 info
.mode
= byteorder
== MSBFirst
? BGRA8888
: ARGB8888
;
242 if (rs
== 16 && gs
== 8 && bs
== 0)
243 info
.mode
= byteorder
== MSBFirst
? ARGB8888
: BGRA8888
;
244 if (rs
== 24 && gs
== 16 && bs
== 8)
245 info
.mode
= byteorder
== MSBFirst
? RGBA8888
: ABGR8888
;
248 printf("ximage: ARGB8888 to %s\n", modename
[info
.mode
]);
250 /* select conversion function */
251 info
.convert_func
= ximage_convert_funcs
[info
.mode
];
261 for (i
= 0; i
< POOLSIZE
; i
++) {
265 for (i
= 0; i
< POOLSIZE
; i
++) {
266 info
.pool
[i
] = createximage(info
.display
,
267 info
.visual
.visual
, &info
.shminfo
[i
], info
.visual
.depth
,
269 if (info
.pool
[i
] == nil
) {
278 next_pool_image(void)
280 if (info
.lastused
+ 1 >= POOLSIZE
) {
282 XSync(info
.display
, False
);
284 XFlush(info
.display
);
287 return info
.pool
[info
.lastused
++];
291 ximage_init(Display
*display
, int screen
, Visual
*visual
)
293 XVisualInfo
template;
294 XVisualInfo
*visuals
;
296 XPixmapFormatValues
*formats
;
301 info
.display
= display
;
302 info
.screen
= screen
;
305 /* Get XVisualInfo for this visual */
306 template.visualid
= XVisualIDFromVisual(visual
);
307 visuals
= XGetVisualInfo(display
, VisualIDMask
, &template, &nvisuals
);
309 fprintf(stderr
, "Visual not found!\n");
313 memcpy(&info
.visual
, visuals
, sizeof (XVisualInfo
));
316 /* Get appropriate PixmapFormat for this visual */
317 formats
= XListPixmapFormats(info
.display
, &nformats
);
318 for (i
= 0; i
< nformats
; i
++) {
319 if (formats
[i
].depth
== info
.visual
.depth
) {
320 info
.bitsperpixel
= formats
[i
].bits_per_pixel
;
326 fprintf(stderr
, "PixmapFormat not found!\n");
333 /* prepare colormap */
336 /* prepare pool of XImages */
342 printf("ximage: %sPutImage\n", info
.useshm
? "XShm" : "X");
348 ximage_get_depth(void)
350 return info
.visual
.depth
;
354 ximage_get_visual(void)
356 return info
.visual
.visual
;
360 ximage_get_colormap(void)
362 return info
.colormap
;
366 ximage_blit(Drawable d
, GC gc
,
368 unsigned char *srcdata
,
376 unsigned char *srcptr
;
378 for (ay
= 0; ay
< srch
; ay
+= HEIGHT
)
380 h
= MIN(srch
- ay
, HEIGHT
);
381 for (ax
= 0; ax
< srcw
; ax
+= WIDTH
)
383 w
= MIN(srcw
- ax
, WIDTH
);
385 image
= next_pool_image();
388 (ay
+ srcy
) * srcstride
+
391 info
.convert_func(srcptr
, srcstride
,
393 image
->bytes_per_line
, w
, h
);
397 XShmPutImage(info
.display
, d
, gc
, image
,
398 0, 0, dstx
+ ax
, dsty
+ ay
,
403 XPutImage(info
.display
, d
, gc
, image
,
414 * Primitive conversion functions
420 #define restrict __restrict__
428 const unsigned char * restrict src, \
430 unsigned char * restrict dst, \
436 * Convert byte:ARGB8888 to various formats
440 ximage_convert_argb8888(PARAMS
)
443 unsigned * restrict s
= (unsigned * restrict
)src
;
444 unsigned * restrict d
= (unsigned * restrict
)dst
;
445 for (y
= 0; y
< h
; y
++) {
446 for (x
= 0; x
< w
; x
++) {
455 ximage_convert_bgra8888(PARAMS
)
458 unsigned *s
= (unsigned *)src
;
459 unsigned *d
= (unsigned *)dst
;
461 for (y
= 0; y
< h
; y
++) {
462 for (x
= 0; x
< w
; x
++) {
466 ((val
>> 8) & 0xff00) |
468 ((val
<< 8) & 0xff0000);
471 (((val >> 24) & 0xff) << 0) |
472 (((val >> 16) & 0xff) << 8) |
473 (((val >> 8) & 0xff) << 16) |
474 (((val >> 0) & 0xff) << 24);
482 /* following have yet to recieve some MMX love ;-) */
485 ximage_convert_abgr8888(PARAMS
)
488 unsigned *s
= (unsigned *)src
;
489 unsigned *d
= (unsigned *)dst
;
492 for (y
= 0; y
< h
; y
++) {
493 for (x
= 0; x
< w
; x
++) {
496 d
[x
] = (val
& 0xff00ff00) |
497 (((val
<< 16) | (val
>> 16)) & 0x00ff00ff);
499 d
[x
] = (val
<< 24) | ((val
>> 8) & 0xff);
508 ximage_convert_rgba8888(PARAMS
)
511 for (y
= 0; y
< h
; y
++) {
512 for (x
= 0; x
< w
; x
++) {
513 dst
[x
* 4 + 0] = src
[x
* 4 + 1];
514 dst
[x
* 4 + 1] = src
[x
* 4 + 2];
515 dst
[x
* 4 + 2] = src
[x
* 4 + 3];
516 dst
[x
* 4 + 3] = src
[x
* 4 + 0];
524 ximage_convert_bgr888(PARAMS
)
527 for (y
= 0; y
< h
; y
++) {
528 for (x
= 0; x
< w
; x
++) {
529 dst
[3*x
+ 0] = src
[4*x
+ 3];
530 dst
[3*x
+ 1] = src
[4*x
+ 2];
531 dst
[3*x
+ 2] = src
[4*x
+ 1];
539 ximage_convert_rgb888(PARAMS
)
542 for (y
= 0; y
< h
; y
++) {
543 for (x
= 0; x
< w
; x
++) {
544 dst
[3*x
+ 0] = src
[4*x
+ 1];
545 dst
[3*x
+ 1] = src
[4*x
+ 2];
546 dst
[3*x
+ 2] = src
[4*x
+ 3];
554 ximage_convert_rgb565(PARAMS
)
556 unsigned char r
, g
, b
;
558 for (y
= 0; y
< h
; y
++) {
559 for (x
= 0; x
< w
; x
++) {
563 ((unsigned short *)dst
)[x
] =
574 ximage_convert_rgb565_br(PARAMS
)
576 unsigned char r
, g
, b
;
578 for (y
= 0; y
< h
; y
++) {
579 for (x
= 0; x
< w
; x
++) {
584 g4 g3 g2 b7 b6 b5 b4 b3 r7 r6 r5 r4 r3 g7 g6 g5
586 ((unsigned short *)dst
)[x
] =
598 ximage_convert_rgb555(PARAMS
)
600 unsigned char r
, g
, b
;
602 for (y
= 0; y
< h
; y
++) {
603 for (x
= 0; x
< w
; x
++) {
607 ((unsigned short *)dst
)[x
] =
618 ximage_convert_rgb555_br(PARAMS
)
620 unsigned char r
, g
, b
;
622 for (y
= 0; y
< h
; y
++) {
623 for (x
= 0; x
< w
; x
++) {
628 g5 g4 g3 b7 b6 b5 b4 b3 0 r7 r6 r5 r4 r3 g7 g6
630 ((unsigned short *)dst
)[x
] =
642 ximage_convert_bgr233(PARAMS
)
644 unsigned char r
, g
, b
;
646 for(y
= 0; y
< h
; y
++) {
647 for(x
= 0; x
< w
; x
++) {
651 /* format: b7 b6 g7 g6 g5 r7 r6 r5 */
652 dst
[x
] = (b
&0xC0) | ((g
>>2)&0x38) | ((r
>>5)&0x7);
659 ximage_convert_func_t ximage_convert_funcs
[] = {
660 ximage_convert_argb8888
,
661 ximage_convert_bgra8888
,
662 ximage_convert_rgba8888
,
663 ximage_convert_abgr8888
,
664 ximage_convert_rgb888
,
665 ximage_convert_bgr888
,
666 ximage_convert_rgb565
,
667 ximage_convert_rgb565_br
,
668 ximage_convert_rgb555
,
669 ximage_convert_rgb555_br
,
670 ximage_convert_bgr233
,