revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-hosted / hidd / x11 / x11gfx_bitmapclass.c
blob58732d7c40a5fd29c52dc1556a59002190f0b860
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "x11_debug.h"
8 #include <hidd/gfx.h>
9 #include <proto/utility.h>
11 #include "x11_types.h"
12 #include "x11.h"
13 #include "x11_hostlib.h"
14 #include "x11gfx_bitmap.h"
15 #include "x11_xshm.h"
17 /****************************************************************************************/
19 #define DO_ENDIAN_FIX 1 /* fix if X11 server running on remote server with different endianess */
21 /****************************************************************************************/
23 #define MNAME(x) X11BM__ ## x
25 #if DO_ENDIAN_FIX
27 #if AROS_BIG_ENDIAN
28 #define NEEDS_ENDIAN_FIX(image) (((image)->bits_per_pixel >= 15) && ((image)->byte_order != MSBFirst))
29 #define SWAP16(x) AROS_WORD2LE(x)
30 #define SWAP32(x) AROS_LONG2LE(x)
31 #define AROS_BYTEORDER MSBFirst
32 #else
33 #define NEEDS_ENDIAN_FIX(image) (((image)->bits_per_pixel >= 15) && ((image)->byte_order != LSBFirst))
34 #define SWAP16(x) AROS_WORD2BE(x)
35 #define SWAP32(x) AROS_LONG2BE(x)
36 #define AROS_BYTEORDER LSBFirst
37 #endif
39 #if 0 /* stegerg: to test above stuff*/
40 #define NEEDS_ENDIAN_FIX(image) ((image)->bits_per_pixel >= 15)
41 #define AROS_BYTEORDER MSBFirst
42 #define SWAP16(x) AROS_WORD2BE(x)
43 #define SWAP32(x) AROS_LONG2BE(x)
44 #endif
46 /****************************************************************************************/
48 OOP_Object *X11BM__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
50 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
52 o = (OOP_Object *) OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
53 if (o)
55 struct bitmap_data *data = OOP_INST_DATA(cl, o);
56 BOOL ok = TRUE;
57 BOOL framebuffer;
59 /* Get some info passed to us by the x11gfxhidd class */
60 data->display = (Display *) GetTagData(aHidd_BitMap_X11_SysDisplay, 0, msg->attrList);
61 data->screen = GetTagData(aHidd_BitMap_X11_SysScreen, 0, msg->attrList);
62 data->cursor = (Cursor) GetTagData(aHidd_BitMap_X11_SysCursor, 0, msg->attrList);
63 data->colmap = (Colormap) GetTagData(aHidd_BitMap_X11_ColorMap, 0, msg->attrList);
64 framebuffer = GetTagData(aHidd_BitMap_FrameBuffer, FALSE, msg->attrList);
67 bug("[X11Bm] %s: display @ 0x%p, screen #%d\n", __PRETTY_FUNCTION__, data->display, data->screen);
68 bug("[X11Bm] %s: cursor @ 0x%p, colormap @ 0x%p\n", __PRETTY_FUNCTION__, data->cursor, data->colmap);
71 if (framebuffer)
73 /* Framebuffer is X11 window */
74 data->flags |= BMDF_FRAMEBUFFER;
75 ok = X11BM_InitFB(cl, o, msg->attrList);
77 else
79 /* Anything else is a pixmap */
80 ok = X11BM_InitPM(cl, o, msg->attrList);
83 if (ok)
85 /* Create an X11 GC. All objects need it. */
86 XGCValues gcval;
88 gcval.plane_mask = AllPlanes;
89 gcval.graphics_exposures = False;
91 HostLib_Lock();
93 data->gc = XCALL(XCreateGC, data->display, DRAWABLE(data),
94 GCPlaneMask | GCGraphicsExposures, &gcval);
95 HostLib_Unlock();
97 if (!data->gc)
98 ok = FALSE;
99 #if X11SOFTMOUSE
100 else if (framebuffer)
101 X11BM_InitEmptyCursor(data);
102 #endif
105 if (ok && (data->flags & BMDF_FRAMEBUFFER) != 0)
107 ok = X11BM_NotifyFB(cl, o);
110 if (!ok)
112 OOP_MethodID disp_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
114 OOP_CoerceMethod(cl, o, (OOP_Msg) &disp_mid);
115 o = NULL;
117 } /* if (object allocated by superclass) */
119 D(bug("[X11Bm] %s: returning object @ 0x%p\n", __PRETTY_FUNCTION__, o));
120 return o;
123 /****************************************************************************************/
125 VOID X11BM__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
127 struct bitmap_data *data = OOP_INST_DATA(cl, o);
129 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
131 if (data->gc)
133 HostLib_Lock();
134 XCALL(XFreeGC, data->display, data->gc);
135 HostLib_Unlock();
138 if (data->flags & BMDF_FRAMEBUFFER)
139 X11BM_DisposeFB(data, XSD(cl));
140 else
141 X11BM_DisposePM(data);
143 OOP_DoSuperMethod(cl, o, msg);
146 /****************************************************************************************/
148 VOID X11BM__Hidd_BitMap__Clear(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_Clear *msg)
150 struct bitmap_data *data = OOP_INST_DATA(cl, o);
152 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
154 HostLib_Lock();
156 if (data->flags & BMDF_FRAMEBUFFER)
157 X11BM_ClearFB(data, GC_BG(msg->gc));
158 else
159 X11BM_ClearPM(data, GC_BG(msg->gc));
161 HostLib_Unlock();
164 /****************************************************************************************/
166 static void SwapImageEndianess(XImage *image)
168 LONG x, y, height, width, bpp;
169 UBYTE *imdata = (UBYTE *) image->data;
171 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
173 width = image->width;
174 height = image->height;
175 bpp = (image->bits_per_pixel + 7) / 8;
177 for (y = 0; y < height; y++)
179 switch (bpp)
181 case 2:
182 for (x = 0; x < width; x++, imdata += 2)
184 UWORD pix = *(UWORD *) imdata;
186 pix = SWAP16(pix);
188 *(UWORD *) imdata = pix;
190 imdata += (image->bytes_per_line - width * 2);
191 break;
193 case 3:
194 for (x = 0; x < width; x++, imdata += 3)
196 UBYTE pix1 = imdata[0];
197 UBYTE pix3 = imdata[2];
199 imdata[0] = pix3;
200 imdata[2] = pix1;
202 imdata += (image->bytes_per_line - width * 3);
203 break;
205 case 4:
206 for (x = 0; x < width; x++, imdata += 4)
208 ULONG pix = *(ULONG *) imdata;
210 pix = SWAP32(pix);
212 *(ULONG *) imdata = pix;
214 imdata += (image->bytes_per_line - width * 4);
215 break;
217 } /* switch(bpp) */
219 } /* for (y = 0; y < height; y ++) */
221 image->byte_order = AROS_BYTEORDER;
224 /****************************************************************************************/
226 #endif /* DO_ENDIAN_FIX */
228 /****************************************************************************************/
230 BOOL MNAME(Hidd_BitMap__SetColors)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_SetColors *msg)
232 struct bitmap_data *data = OOP_INST_DATA(cl, o);
233 HIDDT_PixelFormat *pf;
234 ULONG xc_i, col_i;
236 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
238 if (!OOP_DoSuperMethod(cl, o, &msg->mID))
239 return FALSE;
241 pf = BM_PIXFMT(o);
243 if (vHidd_ColorModel_StaticPalette == HIDD_PF_COLMODEL(pf) || vHidd_ColorModel_TrueColor == HIDD_PF_COLMODEL(pf))
245 /* Superclass has taken care of this case */
246 return TRUE;
249 /* Ve have a vHidd_GT_Palette bitmap */
251 if (data->flags & BMDF_COLORMAP_ALLOCED)
253 LOCK_X11
255 for (xc_i = msg->firstColor, col_i = 0; col_i < msg->numColors; xc_i++, col_i++)
257 XColor xcol;
259 xcol.red = msg->colors[col_i].red;
260 xcol.green = msg->colors[col_i].green;
261 xcol.blue = msg->colors[col_i].blue;
262 xcol.pad = 0;
263 xcol.pixel = xc_i;
264 xcol.flags = DoRed | DoGreen | DoBlue;
266 XCALL(XStoreColor, data->display, data->colmap, &xcol);
270 UNLOCK_X11
272 } /* if (data->flags & BMDF_COLORMAP_ALLOCED) */
274 return TRUE;
277 /****************************************************************************************/
279 VOID MNAME(Hidd_BitMap__PutPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
281 struct bitmap_data *data = OOP_INST_DATA(cl, o);
283 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
285 LOCK_X11
287 XCALL(XSetForeground, data->display, data->gc, msg->pixel);
288 XCALL(XSetFunction, data->display, data->gc, GXcopy);
289 XCALL(XDrawPoint, data->display, DRAWABLE(data), data->gc, msg->x, msg->y);
291 UNLOCK_X11
294 /****************************************************************************************/
296 HIDDT_Pixel MNAME(Hidd_BitMap__GetPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetPixel *msg)
298 struct bitmap_data *data = OOP_INST_DATA(cl, o);
299 HIDDT_Pixel pixel = -1;
300 XImage *image;
302 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
304 LOCK_X11
306 XCALL(XSync, data->display, False);
308 image = XCALL(XGetImage, data->display, DRAWABLE(data), msg->x, msg->y, 1, 1, AllPlanes, ZPixmap);
310 if (image)
312 pixel = XGetPixel(image, 0, 0);
313 XDestroyImage(image);
316 UNLOCK_X11
318 return pixel;
322 /****************************************************************************************/
324 ULONG MNAME(Hidd_BitMap__DrawPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPixel *msg)
326 struct bitmap_data *data = OOP_INST_DATA(cl, o);
327 XGCValues gcval;
329 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
331 gcval.function = GC_DRMD(msg->gc);
332 gcval.foreground = GC_FG(msg->gc);
333 gcval.background = GC_BG(msg->gc);
335 LOCK_X11
336 XCALL(XChangeGC, data->display, data->gc, GCFunction | GCForeground | GCBackground, &gcval);
337 XCALL(XDrawPoint, data->display, DRAWABLE(data), data->gc, msg->x, msg->y);
338 UNLOCK_X11
340 return 0;
343 /****************************************************************************************/
345 VOID MNAME(Hidd_BitMap__FillRect)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
347 struct bitmap_data *data = OOP_INST_DATA(cl, o);
348 XGCValues gcval;
350 D(bug("[X11Bm] %s(%d,%d,%d,%d)\n", __PRETTY_FUNCTION__, msg->minX, msg->minY, msg->maxX, msg->maxY));
351 D(bug("[X11Bm] %s: Drawmode = %d\n", __PRETTY_FUNCTION__, GC_DRMD(msg->gc)));
353 gcval.function = GC_DRMD(msg->gc);
354 gcval.foreground = GC_FG(msg->gc);
355 gcval.background = GC_BG(msg->gc);
357 LOCK_X11
358 XCALL(XChangeGC, data->display, data->gc, GCFunction | GCForeground | GCBackground, &gcval);
360 XCALL(XFillRectangle, data->display, DRAWABLE(data), data->gc, msg->minX, msg->minY, msg->maxX - msg->minX + 1, msg->maxY - msg->minY + 1);
362 UNLOCK_X11
365 /****************************************************************************************/
367 static ULONG *ximage_to_buf(OOP_Class *cl, OOP_Object *bm, HIDDT_Pixel *buf, XImage *image, ULONG width, ULONG height,
368 ULONG depth, struct pHidd_BitMap_GetImage *msg)
370 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
372 switch (msg->pixFmt)
374 case vHidd_StdPixFmt_Native:
376 UBYTE *imdata = image->data;
377 LONG y;
379 for (y = 0; y < height; y++)
381 memcpy(buf, imdata, msg->width * image->bits_per_pixel / 8);
383 imdata += image->bytes_per_line;
384 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
387 break;
389 case vHidd_StdPixFmt_Native32:
390 switch (image->bits_per_pixel)
392 case 8:
394 UBYTE *imdata = (UBYTE *) image->data;
395 LONG x, y;
397 for (y = 0; y < height; y++)
399 HIDDT_Pixel *p = buf;
401 for (x = 0; x < width; x++)
403 *p++ = *imdata++;
405 imdata += (image->bytes_per_line - width);
406 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
408 break;
411 case 16:
413 UWORD *imdata = (UWORD *) image->data;
414 LONG x, y;
416 for (y = 0; y < height; y++)
418 HIDDT_Pixel *p = buf;
420 for (x = 0; x < width; x++)
422 *p++ = *imdata++;
424 imdata += image->bytes_per_line / 2 - width;
425 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
427 break;
430 case 32:
432 ULONG *imdata = (ULONG *) image->data;
433 LONG x, y;
435 for (y = 0; y < height; y++)
437 HIDDT_Pixel *p = buf;
439 for (x = 0; x < width; x++)
441 *p++ = *imdata++;
443 imdata += image->bytes_per_line / 4 - width;
444 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
446 break;
449 default:
451 LONG x, y;
453 LOCK_X11
454 for (y = 0; y < height; y++)
456 HIDDT_Pixel *p;
458 p = buf;
459 for (x = 0; x < width; x++)
461 *p++ = XGetPixel(image, x, y);
463 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
465 UNLOCK_X11
466 break;
469 } /* switch (image->bits_per_pixel) */
471 break;
473 default:
476 OOP_Object *srcpf, *dstpf, *gfxhidd;
477 APTR srcPixels = image->data, dstBuf = buf;
479 //bug("DEFAULT PIXEL CONVERSION\n");
481 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, (IPTR *) &gfxhidd);
482 dstpf = HIDD_Gfx_GetPixFmt(gfxhidd, msg->pixFmt);
484 OOP_GetAttr(bm, aHidd_BitMap_PixFmt, (IPTR *) &srcpf);
486 //bug("CALLING ConvertPixels()\n");
488 HIDD_BM_ConvertPixels(bm, &srcPixels, (HIDDT_PixelFormat *) srcpf, image->bytes_per_line, &dstBuf,
489 (HIDDT_PixelFormat *) dstpf, msg->modulo, width, height, NULL /* We have no CLUT */
492 //bug("CONVERTPIXELS DONE\n");
494 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo * height);
495 break;
498 } /* switch (msg->pixFmt) */
500 return buf;
503 /****************************************************************************************/
505 #define ABS(a) ((a) < 0 ? -(a) : a)
507 /****************************************************************************************/
509 static inline UBYTE pix_to_lut(HIDDT_Pixel pixel, HIDDT_PixelLUT *plut, HIDDT_PixelFormat *pf)
511 HIDDT_ColComp red, green, blue;
512 ULONG i, best_match = 0;
513 ULONG diff, lowest_diff = 0xFFFFFFFF;
515 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
517 red = RED_COMP(pixel, pf);
518 green = GREEN_COMP(pixel, pf);
519 blue = BLUE_COMP(pixel, pf);
521 for (i = 0; i < plut->entries; i++)
523 register HIDDT_Pixel cur_lut = plut->pixels[i];
525 if (pixel == cur_lut)
526 return i; /* Exact match found */
528 /* How well does these pixels match ? */
529 diff = ABS(red - RED_COMP(cur_lut, pf)) + ABS(green - GREEN_COMP(cur_lut, pf))
530 + ABS(blue - BLUE_COMP(cur_lut, pf));
532 if (diff < lowest_diff)
534 best_match = i;
535 lowest_diff = diff;
540 return best_match;
543 /****************************************************************************************/
545 static UBYTE *ximage_to_buf_lut(OOP_Class *cl, OOP_Object *bm, UBYTE *buf, XImage *image, ULONG width, ULONG height,
546 ULONG depth, struct pHidd_BitMap_GetImageLUT *msg)
548 /* This one is trickier, as we have to reverse-lookup the lut.
549 This costs CPU ! Maybe one could do some kind of caching here ?
550 Ie. one stores the most often used RGB combinations
551 in a trie and looks up this first to see if whe can find an exact match
554 HIDDT_PixelFormat *pf = BM_PIXFMT(bm);
555 UBYTE *pixarray = msg->pixels;
557 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
559 if (image->bits_per_pixel == 16)
561 UWORD *imdata = (UWORD *) image->data;
562 LONG x, y;
564 for (y = 0; y < height; y++)
566 UBYTE *buf = pixarray;
568 for (x = 0; x < width; x++)
570 *buf++ = pix_to_lut((HIDDT_Pixel) *imdata, msg->pixlut, pf);
572 imdata++;
574 imdata += ((image->bytes_per_line / 2) - width); /*sg*/
576 pixarray += msg->modulo;
580 else
582 LONG x, y;
584 LOCK_X11
585 for (y = 0; y < height; y++)
587 UBYTE *buf = pixarray;
588 for (x = 0; x < width; x++)
590 *buf++ = pix_to_lut((HIDDT_Pixel) XGetPixel(image, x, y), msg->pixlut, pf);
593 pixarray += msg->modulo;
596 UNLOCK_X11
600 return pixarray;
604 /****************************************************************************************/
606 #if USE_XSHM
608 /****************************************************************************************/
610 static void getimage_xshm(OOP_Class *cl, OOP_Object *o, LONG x, LONG y,
611 ULONG width, ULONG height, APTR pixarray,
612 APTR (*fromimage_func)(), APTR fromimage_data)
614 struct bitmap_data *data;
615 XImage *image;
616 IPTR depth;
617 ULONG lines_to_copy;
618 LONG ysize;
619 LONG current_y;
620 LONG maxlines;
621 OOP_Object *pf;
622 Pixmap temp_pixmap = 0;
624 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
626 ASSERT(width > 0 && height > 0);
628 data = OOP_INST_DATA(cl, o);
630 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *)&pf);
631 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
633 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
635 LOCK_X11
636 image = create_xshm_ximage(data->display,
637 DefaultVisual(data->display, data->screen),
638 depth,
639 ZPixmap,
640 width,
641 height,
642 XSD(cl)->xshm_info);
643 UNLOCK_X11
645 if (!image)
646 return;
648 ASSERT(image->bytes_per_line > 0);
650 /* Calculate how many scanline can be stored in the buffer */
651 maxlines = XSHM_MEMSIZE / image->bytes_per_line;
653 if (0 == maxlines)
655 bug("ALERT !!! NOT ENOUGH MEMORY TO READ A COMPLETE SCANLINE\n");
656 bug("THROUGH XSHM IN X11GF X HIDD !!!\n");
657 Alert(AT_DeadEnd);
660 current_y = 0;
661 ysize = image->height;
663 ObtainSemaphore(&XSD(cl)->shm_sema);
665 LOCK_X11
667 while (ysize)
669 /* Get some more pixels from the Ximage */
671 lines_to_copy = MIN(maxlines, ysize);
673 ysize -= lines_to_copy;
674 image->height = lines_to_copy;
676 if (!temp_pixmap)
678 if (!(get_xshm_ximage(data->display, DRAWABLE(data), image,
679 x, y + current_y)))
681 /* XGetImage fails if done on a part of a X window which is off
682 screen (OTOH, it's no problem if it is hidden by another window).
683 If get_xshm_image() failed, we assume that this has happened and
684 thefore copy the area to a temp pixmap, and then get the ximage
685 from there. */
687 temp_pixmap = XCALL(XCreatePixmap, data->display, DRAWABLE(data),
688 width, height - current_y, DefaultDepth(data->display, data->screen));
690 if (temp_pixmap)
692 XCALL(XSetFunction, data->display, data->gc, GXcopy);
694 XCALL(XCopyArea, data->display, DRAWABLE(data), temp_pixmap, data->gc,
695 x, y + current_y, width, height - current_y, 0, 0);
697 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(data->gc));
699 x = 0; y = 0; current_y = 0;
704 if (temp_pixmap)
706 get_xshm_ximage(data->display, temp_pixmap, image,
707 x, y + current_y);
710 current_y += lines_to_copy;
712 pixarray = fromimage_func(cl, o, pixarray, image, image->width,
713 lines_to_copy, depth, fromimage_data);
715 } /* while (pixels left to copy) */
717 if (temp_pixmap)
719 XCALL(XFreePixmap,data->display, temp_pixmap);
722 UNLOCK_X11
724 ReleaseSemaphore(&XSD(cl)->shm_sema);
726 LOCK_X11
727 destroy_xshm_ximage(image);
728 UNLOCK_X11
730 return;
734 /****************************************************************************************/
736 #endif
738 /****************************************************************************************/
740 static void getimage_xlib(OOP_Class *cl, OOP_Object *o, LONG x, LONG y, ULONG width, ULONG height, APTR pixels,
741 APTR(*fromimage_func)(), APTR fromimage_data)
743 struct bitmap_data *data;
744 XImage *image;
745 ULONG *pixarray = (ULONG *) pixels;
746 OOP_Object *pf;
747 IPTR depth;
749 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
751 data = OOP_INST_DATA(cl, o);
753 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *) &pf);
754 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
756 LOCK_X11
757 image = XCALL(XGetImage, data->display, DRAWABLE(data), x, y,
758 width, height, AllPlanes, ZPixmap);
759 UNLOCK_X11
761 if (!image)
762 return;
764 #if DO_ENDIAN_FIX
765 if (NEEDS_ENDIAN_FIX(image))
767 SwapImageEndianess(image);
769 LOCK_X11
770 XCALL(XInitImage, image);
771 UNLOCK_X11
773 #endif
775 fromimage_func(cl, o, pixarray, image, width, height, depth, fromimage_data);
777 LOCK_X11
778 XDestroyImage(image);
779 UNLOCK_X11
781 return;
784 /****************************************************************************************/
786 VOID MNAME(Hidd_BitMap__GetImage)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImage *msg)
788 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
790 ASSERT(msg->width > 0 && msg->height > 0);
792 #if USE_XSHM
793 if (XSD(cl)->use_xshm)
795 getimage_xshm(cl, o, msg->x, msg->y, msg->width, msg->height,
796 msg->pixels, (APTR (*)())ximage_to_buf, msg);
798 else
799 #endif
801 getimage_xlib(cl, o, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) ximage_to_buf, msg);
805 /****************************************************************************************/
807 VOID MNAME(Hidd_BitMap__GetImageLUT)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImageLUT *msg)
809 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
811 ASSERT(msg->width != 0 && msg->height != 0);
812 #if USE_XSHM
813 if (XSD(cl)->use_xshm)
815 getimage_xshm(cl, o, msg->x, msg->y, msg->width, msg->height,
816 msg->pixels, (APTR (*)())ximage_to_buf_lut, msg);
818 else
819 #endif
821 getimage_xlib(cl, o, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) ximage_to_buf_lut, msg);
825 /****************************************************************************************/
827 #undef DEBUG
828 #define DEBUG 0
829 #include <aros/debug.h>
831 /****************************************************************************************/
833 static ULONG *buf_to_ximage(OOP_Class *cl, OOP_Object *bm, HIDDT_Pixel *buf, XImage *image, ULONG width, ULONG height,
834 ULONG depth, struct pHidd_BitMap_PutImage *msg)
836 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
838 switch (msg->pixFmt)
840 case vHidd_StdPixFmt_Native:
842 UBYTE *imdata = image->data;
843 LONG y;
845 for (y = 0; y < height; y++)
847 memcpy(imdata, buf, msg->width * image->bits_per_pixel / 8);
849 imdata += image->bytes_per_line;
850 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
853 break;
855 case vHidd_StdPixFmt_Native32:
856 switch (image->bits_per_pixel)
858 case 8:
860 UBYTE *imdata = (UBYTE *) image->data;
861 LONG x, y;
863 for (y = 0; y < height; y++)
865 HIDDT_Pixel *p = buf;
867 for (x = 0; x < width; x++)
869 *imdata++ = (UBYTE) *p++;
871 imdata += image->bytes_per_line - width;
872 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
874 break;
877 case 16:
879 UWORD *imdata = (UWORD *) image->data;
880 LONG x, y;
882 for (y = 0; y < height; y++)
884 HIDDT_Pixel *p = buf;
886 for (x = 0; x < width; x++)
888 *imdata++ = (UWORD) *p++;
890 imdata += image->bytes_per_line / 2 - width;
891 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
893 break;
896 case 24:
898 HIDDT_PixelFormat *pf;
899 UBYTE *imdata = image->data;
900 LONG x, y;
902 pf = BM_PIXFMT(bm);
904 for (y = 0; y < height; y++)
907 HIDDT_Pixel *p = buf;
909 for (x = 0; x < width; x++)
911 register HIDDT_Pixel pix;
913 pix = *p++;
914 #if (AROS_BIG_ENDIAN == 1)
915 *imdata ++ = pix >> 16;
916 *imdata ++ = (pix & pf->green_mask) >> 8;
917 *imdata ++ = (pix & pf->blue_mask);
918 #else
919 *imdata++ = (pix & pf->blue_mask);
920 *imdata++ = (pix & pf->green_mask) >> 8;
921 *imdata++ = pix >> 16;
922 #endif
924 imdata += image->bytes_per_line - width * 3;
925 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
927 break;
930 case 32:
932 ULONG *imdata = (ULONG *) image->data;
933 LONG x, y;
935 for (y = 0; y < height; y++)
937 HIDDT_Pixel *p = buf;
939 for (x = 0; x < width; x++)
941 *imdata++ = (ULONG) *p++;
943 imdata += image->bytes_per_line / 4 - width;
944 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
946 break;
949 default:
951 LONG x, y;
953 LOCK_X11
954 for (y = 0; y < height; y++)
956 HIDDT_Pixel *p;
958 p = buf;
959 for (x = 0; x < width; x++)
961 XPutPixel(image, x, y, *p++);
963 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
965 UNLOCK_X11
966 break;
969 } /* switch (image->bits_per_pixel) */
971 break;
973 default:
975 OOP_Object *srcpf, *dstpf, *gfxhidd;
976 APTR srcPixels = buf, dstBuf = image->data;
978 //bug("DEFAULT PIXEL CONVERSION\n");
980 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, (IPTR *) &gfxhidd);
981 srcpf = HIDD_Gfx_GetPixFmt(gfxhidd, msg->pixFmt);
983 OOP_GetAttr(bm, aHidd_BitMap_PixFmt, (IPTR *) &dstpf);
985 //bug("CALLING ConvertPixels()\n");
987 HIDD_BM_ConvertPixels(bm, &srcPixels, (HIDDT_PixelFormat *) srcpf, msg->modulo, &dstBuf,
988 (HIDDT_PixelFormat *) dstpf, image->bytes_per_line, width, height, NULL); /* We have no CLUT */
990 //bug("CONVERTPIXELS DONE\n");
992 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo * height);
993 break;
996 } /* switch (msg->pixFmt) */
998 return buf;
1001 /****************************************************************************************/
1003 static UBYTE *buf_to_ximage_lut(OOP_Class *cl, OOP_Object *bm, UBYTE *pixarray, XImage *image, ULONG width,
1004 ULONG height, ULONG depth, struct pHidd_BitMap_PutImageLUT *msg)
1006 HIDDT_Pixel *lut = msg->pixlut->pixels;
1008 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1010 switch (image->bits_per_pixel)
1012 case 8:
1014 UBYTE *imdata = (UBYTE *) image->data;
1015 LONG x, y;
1017 for (y = 0; y < height; y++)
1019 UBYTE *buf = pixarray;
1021 for (x = 0; x < width; x++)
1023 *imdata++ = (UBYTE) lut[*buf++];
1025 pixarray += msg->modulo;
1026 imdata += (image->bytes_per_line - width); /*sg*/
1028 break;
1031 case 16:
1033 UWORD *imdata = (UWORD *) image->data;
1034 LONG x, y;
1036 for (y = 0; y < height; y++)
1038 UBYTE *buf = pixarray;
1040 for (x = 0; x < width; x++)
1042 *imdata++ = (UWORD) lut[*buf++];
1044 pixarray += msg->modulo;
1045 imdata += ((image->bytes_per_line / 2) - width); /*sg*/
1047 break;
1050 case 32:
1052 ULONG *imdata = (ULONG *) image->data;
1053 LONG x, y;
1055 for (y = 0; y < height; y++)
1057 UBYTE *buf = pixarray;
1059 for (x = 0; x < width; x++)
1061 *imdata++ = (ULONG) lut[*buf++];
1064 pixarray += msg->modulo;
1065 imdata += ((image->bytes_per_line / 4) - width); /*sg*/
1067 break;
1070 default:
1072 LONG x, y;
1074 for (y = 0; y < height; y++)
1076 UBYTE *buf = pixarray;
1078 for (x = 0; x < width; x++)
1080 XPutPixel(image, x, y, lut[*buf++]);
1083 pixarray += msg->modulo;
1086 break;
1090 } /* switch(image->bits_per_pixel) */
1092 return pixarray;
1095 /****************************************************************************************/
1097 #if USE_XSHM
1099 /****************************************************************************************/
1101 static void putimage_xshm(OOP_Class *cl, OOP_Object *o, OOP_Object *gc,
1102 LONG x, LONG y, ULONG width, ULONG height,
1103 APTR pixarray, APTR (*toimage_func)(), APTR toimage_data)
1106 struct bitmap_data *data;
1107 XImage *image;
1108 IPTR depth;
1109 ULONG lines_to_copy;
1110 LONG ysize;
1111 LONG current_y;
1112 LONG maxlines;
1113 OOP_Object *pf;
1115 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1117 data = OOP_INST_DATA(cl, o);
1119 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1120 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
1122 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
1124 LOCK_X11
1125 image = create_xshm_ximage(data->display,
1126 DefaultVisual(data->display, data->screen),
1127 depth,
1128 ZPixmap,
1129 width,
1130 height,
1131 XSD(cl)->xshm_info);
1132 UNLOCK_X11
1134 if (!image)
1135 return;
1137 /* Calculate how many scanline can be stored in the buffer */
1138 maxlines = XSHM_MEMSIZE / image->bytes_per_line;
1140 if (0 == maxlines)
1142 bug("ALERT !!! NOT ENOUGH MEMORY TO WRITE A COMPLETE SCANLINE\n");
1143 bug("THROUGH XSHM IN X11GF X HIDD !!!\n");
1144 Alert(AT_DeadEnd);
1147 current_y = 0;
1148 ysize = image->height;
1150 ObtainSemaphore(&XSD(cl)->shm_sema);
1152 while (ysize)
1154 /* Get some more pixels from the HIDD */
1156 lines_to_copy = MIN(maxlines, ysize);
1158 ysize -= lines_to_copy;
1159 image->height = lines_to_copy;
1161 pixarray = toimage_func(cl, o, pixarray, image, image->width,
1162 lines_to_copy, depth, toimage_data);
1164 LOCK_X11
1165 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1167 put_xshm_ximage(data->display,
1168 DRAWABLE(data),
1169 data->gc,
1170 image,
1171 0, 0,
1172 x, y + current_y,
1173 image->width, lines_to_copy,
1174 FALSE);
1176 UNLOCK_X11
1178 current_y += lines_to_copy;
1180 } /* while (pixels left to copy) */
1182 ReleaseSemaphore(&XSD(cl)->shm_sema);
1184 LOCK_X11
1185 destroy_xshm_ximage(image);
1186 UNLOCK_X11
1188 return;
1192 /****************************************************************************************/
1194 #endif
1196 /****************************************************************************************/
1198 static void putimage_xlib(OOP_Class *cl, OOP_Object *o, OOP_Object *gc, LONG x, LONG y, ULONG width, ULONG height,
1199 APTR pixarray, APTR(*toimage_func)(), APTR toimage_data)
1202 struct bitmap_data *data;
1203 XImage *image;
1204 ULONG bperline;
1205 IPTR depth;
1206 OOP_Object *pf;
1208 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1210 data = OOP_INST_DATA(cl, o);
1212 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *) &pf);
1213 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
1215 LOCK_X11
1216 image = XCALL(XCreateImage, data->display,
1217 DefaultVisual(data->display, data->screen),
1218 depth,
1219 ZPixmap,
1221 NULL,
1222 width,
1223 height,
1226 UNLOCK_X11
1228 if (!image)
1229 return;
1231 #if DO_ENDIAN_FIX
1232 if (NEEDS_ENDIAN_FIX(image))
1234 image->byte_order = AROS_BYTEORDER;
1236 LOCK_X11
1237 XCALL(XInitImage, image);
1238 UNLOCK_X11
1240 #endif
1242 bperline = image->bytes_per_line;
1243 image->data = (char *) AllocVec((size_t) height * bperline, MEMF_PUBLIC);
1245 if (!image->data)
1247 LOCK_X11
1248 XCALL(XFree, image);
1249 UNLOCK_X11
1251 return;
1254 toimage_func(cl, o, pixarray, image, width, height, depth, toimage_data);
1256 LOCK_X11
1257 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1258 XCALL( XPutImage, data->display, DRAWABLE(data), data->gc, image, 0, 0, x, y, width, height);
1259 UNLOCK_X11
1261 FreeVec(image->data);
1263 LOCK_X11
1264 XCALL(XFree, image);
1265 UNLOCK_X11
1269 /****************************************************************************************/
1271 VOID MNAME(Hidd_BitMap__PutImage)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImage *msg)
1273 D(bug("[X11Bm] %s(pa=%p, x=%d, y=%d, w=%d, h=%d)\n", __PRETTY_FUNCTION__, msg->pixels, msg->x, msg->y, msg->width,
1274 msg->height));
1276 #if USE_XSHM
1277 if (XSD(cl)->use_xshm)
1279 putimage_xshm(cl, o, msg->gc, msg->x, msg->y,
1280 msg->width, msg->height, msg->pixels,
1281 (APTR (*)()) buf_to_ximage, msg);
1283 else
1284 #endif
1286 putimage_xlib(cl, o, msg->gc, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) buf_to_ximage, msg);
1290 /****************************************************************************************/
1292 VOID MNAME(Hidd_BitMap__PutImageLUT)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg)
1294 D(bug("[X11Bm] %s(pa=%p, x=%d, y=%d, w=%d, h=%d)\n", __PRETTY_FUNCTION__, msg->pixels, msg->x, msg->y, msg->width,
1295 msg->height));
1297 #if USE_XSHM
1298 if (XSD(cl)->use_xshm)
1300 putimage_xshm(cl, o, msg->gc, msg->x, msg->y,
1301 msg->width, msg->height, msg->pixels,
1302 (APTR (*)())buf_to_ximage_lut, msg);
1304 else
1305 #endif
1307 putimage_xlib(cl, o, msg->gc, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) buf_to_ximage_lut, msg);
1311 /****************************************************************************************/
1313 VOID MNAME(Root__Get)(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
1315 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1316 ULONG idx;
1318 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1320 if (IS_X11BM_ATTR(msg->attrID, idx))
1322 switch (idx)
1324 case aoHidd_BitMap_X11_Drawable:
1325 *msg->storage = (IPTR) DRAWABLE(data);
1326 return;
1328 case aoHidd_BitMap_X11_GC:
1329 *msg->storage = (IPTR) data->gc;
1330 return;
1334 OOP_DoSuperMethod(cl, o, &msg->mID);
1337 /****************************************************************************************/
1339 BOOL X11BM__Root__Set(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
1341 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1343 #if ADJUST_XWIN_SIZE
1344 /* This provides support for framebuffer display mode switching */
1345 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1347 if (data->flags & BMDF_FRAMEBUFFER)
1349 struct TagItem *tag = FindTagItem(aHidd_BitMap_ModeID, msg->attrList);
1351 if (tag)
1353 if (!X11BM_SetMode(data, tag->ti_Data, XSD(cl)))
1355 /* Bail out if error happened, see aoHidd_BitMap_ModeID documentation */
1356 return FALSE;
1360 #endif
1361 return OOP_DoSuperMethod(cl, o, &msg->mID);
1364 /****************************************************************************************/
1366 VOID MNAME(Hidd_BitMap__DrawLine)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawLine *msg)
1368 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1369 OOP_Object *gc = msg->gc;
1371 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1373 if (GC_LINEPAT(gc) != (UWORD) ~0)
1375 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1377 return;
1380 LOCK_X11
1382 if (GC_DOCLIP(gc))
1384 XRectangle cr;
1386 cr.x = GC_CLIPX1(gc);
1387 cr.y = GC_CLIPY1(gc);
1388 cr.width = GC_CLIPX2(gc) - cr.x + 1;
1389 cr.height = GC_CLIPY2(gc) - cr.y + 1;
1391 XCALL(XSetClipRectangles, data->display, data->gc, 0, 0, &cr, 1, Unsorted);
1394 XCALL(XSetForeground, data->display, data->gc, GC_FG(gc));
1395 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1397 XCALL( XDrawLine, data->display, DRAWABLE(data), data->gc, msg->x1, msg->y1, msg->x2, msg->y2);
1399 if (GC_DOCLIP(gc))
1401 XCALL(XSetClipMask, data->display, data->gc, None);
1404 UNLOCK_X11
1407 /****************************************************************************************/
1409 VOID MNAME(Hidd_BitMap__DrawEllipse)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1411 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1412 OOP_Object *gc = msg->gc;
1414 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1416 LOCK_X11
1418 if (GC_DOCLIP(gc))
1420 XRectangle cr;
1422 /* bug("X11::Drawllipse: clip %d %d %d %d\n"
1423 , GC_CLIPX1(gc), GC_CLIPY1(gc), GC_CLIPX2(gc), GC_CLIPY2(gc));
1426 cr.x = GC_CLIPX1(gc);
1427 cr.y = GC_CLIPY1(gc);
1428 cr.width = GC_CLIPX2(gc) - cr.x + 1;
1429 cr.height = GC_CLIPY2(gc) - cr.y + 1;
1431 XCALL(XSetClipRectangles, data->display, data->gc, 0, 0, &cr, 1, Unsorted);
1434 XCALL(XSetForeground, data->display, data->gc, GC_FG(gc));
1435 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1437 /* bug("X11::Drawllipse: coord %d %d %d %d\n"
1438 , msg->x, msg->y, msg->rx, msg->ry);
1442 XCALL(XDrawArc, data->display, DRAWABLE(data), data->gc, msg->x - msg->rx, msg->y - msg->ry, msg->rx * 2, msg->ry * 2, 0, 360 * 64);
1444 if (GC_DOCLIP(gc))
1446 XCALL(XSetClipMask, data->display, data->gc, None);
1449 UNLOCK_X11
1452 /****************************************************************************************/
1454 VOID MNAME(Hidd_BitMap__UpdateRect)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_UpdateRect *msg)
1456 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1458 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1460 LOCK_X11
1462 if (data->flags & BMDF_FRAMEBUFFER)
1463 X11BM_ExposeFB(data, msg->x, msg->y, msg->width, msg->height);
1465 XCALL(XFlush, data->display);
1467 UNLOCK_X11