Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / all-hosted / hidd / x11 / bitmap_common.c
blob4866245c22a4ece9956a3426fa31c93b0183f7d1
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "x11_debug.h"
8 #include <X11/Xlib.h>
9 #include <X11/Xutil.h>
10 #include <X11/cursorfont.h>
11 #include <X11/keysym.h>
13 #include <aros/macros.h>
14 #include <exec/memory.h>
15 #include <exec/lists.h>
16 #include <graphics/rastport.h>
17 #include <graphics/gfx.h>
18 #include <hidd/graphics.h>
19 #include <oop/oop.h>
21 #include <proto/oop.h>
22 #include <proto/utility.h>
24 #include "x11.h"
25 #include "bitmap.h"
26 #include "x11gfx_intern.h"
28 /****************************************************************************************/
30 #define DO_ENDIAN_FIX 1 /* fix if X11 server running on remote server with different endianess */
32 /****************************************************************************************/
34 #define MNAME(x) X11BM__ ## x
36 #if DO_ENDIAN_FIX
38 #if AROS_BIG_ENDIAN
39 #define NEEDS_ENDIAN_FIX(image) (((image)->bits_per_pixel >= 15) && ((image)->byte_order != MSBFirst))
40 #define SWAP16(x) AROS_WORD2LE(x)
41 #define SWAP32(x) AROS_LONG2LE(x)
42 #define AROS_BYTEORDER MSBFirst
43 #else
44 #define NEEDS_ENDIAN_FIX(image) (((image)->bits_per_pixel >= 15) && ((image)->byte_order != LSBFirst))
45 #define SWAP16(x) AROS_WORD2BE(x)
46 #define SWAP32(x) AROS_LONG2BE(x)
47 #define AROS_BYTEORDER LSBFirst
48 #endif
50 #if 0 /* stegerg: to test above stuff*/
51 #define NEEDS_ENDIAN_FIX(image) ((image)->bits_per_pixel >= 15)
52 #define AROS_BYTEORDER MSBFirst
53 #define SWAP16(x) AROS_WORD2BE(x)
54 #define SWAP32(x) AROS_LONG2BE(x)
55 #endif
57 /****************************************************************************************/
59 OOP_Object *X11BM__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
61 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
63 o = (OOP_Object *) OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
64 if (o)
66 struct bitmap_data *data = OOP_INST_DATA(cl, o);
67 BOOL ok = TRUE;
68 BOOL framebuffer;
70 /* Get some info passed to us by the x11gfxhidd class */
71 data->display = (Display *) GetTagData(aHidd_X11BitMap_SysDisplay, 0, msg->attrList);
72 data->screen = GetTagData(aHidd_X11BitMap_SysScreen, 0, msg->attrList);
73 data->cursor = (Cursor) GetTagData(aHidd_X11BitMap_SysCursor, 0, msg->attrList);
74 data->colmap = (Colormap) GetTagData(aHidd_X11BitMap_ColorMap, 0, msg->attrList);
75 framebuffer = GetTagData(aHidd_BitMap_FrameBuffer, FALSE, msg->attrList);
78 bug("[X11Bm] %s: display @ 0x%p, screen #%d\n", __PRETTY_FUNCTION__, data->display, data->screen);
79 bug("[X11Bm] %s: cursor @ 0x%p, colormap @ 0x%p\n", __PRETTY_FUNCTION__, data->cursor, data->colmap);
82 if (framebuffer)
84 /* Framebuffer is X11 window */
85 data->flags |= BMDF_FRAMEBUFFER;
86 ok = X11BM_InitFB(cl, o, msg->attrList);
88 else
90 /* Anything else is a pixmap */
91 ok = X11BM_InitPM(cl, o, msg->attrList);
94 if (ok)
96 /* Create an X11 GC. All objects need it. */
97 XGCValues gcval;
99 gcval.plane_mask = AllPlanes;
100 gcval.graphics_exposures = False;
102 HostLib_Lock();
104 data->gc = XCALL(XCreateGC, data->display, DRAWABLE(data),
105 GCPlaneMask | GCGraphicsExposures, &gcval);
106 HostLib_Unlock();
108 if (!data->gc)
109 ok = FALSE;
110 #if X11SOFTMOUSE
111 else if (framebuffer)
112 X11BM_InitEmptyCursor(data);
113 #endif
116 if (!ok)
118 OOP_MethodID disp_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
120 OOP_CoerceMethod(cl, o, (OOP_Msg) &disp_mid);
121 o = NULL;
123 } /* if (object allocated by superclass) */
125 D(bug("[X11Bm] %s: returning object @ 0x%p\n", __PRETTY_FUNCTION__, o));
126 return o;
129 /****************************************************************************************/
131 VOID X11BM__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
133 struct bitmap_data *data = OOP_INST_DATA(cl, o);
135 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
137 if (data->gc)
139 HostLib_Lock();
140 XCALL(XFreeGC, data->display, data->gc);
141 HostLib_Unlock();
144 if (data->flags & BMDF_FRAMEBUFFER)
145 X11BM_DisposeFB(data, XSD(cl));
146 else
147 X11BM_DisposePM(data);
149 OOP_DoSuperMethod(cl, o, msg);
152 /****************************************************************************************/
154 VOID X11BM__Hidd_BitMap__Clear(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_Clear *msg)
156 struct bitmap_data *data = OOP_INST_DATA(cl, o);
158 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
160 HostLib_Lock();
162 if (data->flags & BMDF_FRAMEBUFFER)
163 X11BM_ClearFB(data, GC_BG(msg->gc));
164 else
165 X11BM_ClearPM(data, GC_BG(msg->gc));
167 HostLib_Unlock();
170 /****************************************************************************************/
172 static void SwapImageEndianess(XImage *image)
174 LONG x, y, height, width, bpp;
175 UBYTE *imdata = (UBYTE *) image->data;
177 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
179 width = image->width;
180 height = image->height;
181 bpp = (image->bits_per_pixel + 7) / 8;
183 for (y = 0; y < height; y++)
185 switch (bpp)
187 case 2:
188 for (x = 0; x < width; x++, imdata += 2)
190 UWORD pix = *(UWORD *) imdata;
192 pix = SWAP16(pix);
194 *(UWORD *) imdata = pix;
196 imdata += (image->bytes_per_line - width * 2);
197 break;
199 case 3:
200 for (x = 0; x < width; x++, imdata += 3)
202 UBYTE pix1 = imdata[0];
203 UBYTE pix3 = imdata[2];
205 imdata[0] = pix3;
206 imdata[2] = pix1;
208 imdata += (image->bytes_per_line - width * 3);
209 break;
211 case 4:
212 for (x = 0; x < width; x++, imdata += 4)
214 ULONG pix = *(ULONG *) imdata;
216 pix = SWAP32(pix);
218 *(ULONG *) imdata = pix;
220 imdata += (image->bytes_per_line - width * 4);
221 break;
223 } /* switch(bpp) */
225 } /* for (y = 0; y < height; y ++) */
227 image->byte_order = AROS_BYTEORDER;
230 /****************************************************************************************/
232 #endif /* DO_ENDIAN_FIX */
234 /****************************************************************************************/
236 BOOL MNAME(Hidd_BitMap__SetColors)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_SetColors *msg)
238 struct bitmap_data *data = OOP_INST_DATA(cl, o);
239 HIDDT_PixelFormat *pf;
240 ULONG xc_i, col_i;
242 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
244 if (!OOP_DoSuperMethod(cl, o, &msg->mID))
245 return FALSE;
247 pf = BM_PIXFMT(o);
249 if (vHidd_ColorModel_StaticPalette == HIDD_PF_COLMODEL(pf) || vHidd_ColorModel_TrueColor == HIDD_PF_COLMODEL(pf))
251 /* Superclass has taken care of this case */
252 return TRUE;
255 /* Ve have a vHidd_GT_Palette bitmap */
257 if (data->flags & BMDF_COLORMAP_ALLOCED)
259 LOCK_X11
261 for (xc_i = msg->firstColor, col_i = 0; col_i < msg->numColors; xc_i++, col_i++)
263 XColor xcol;
265 xcol.red = msg->colors[col_i].red;
266 xcol.green = msg->colors[col_i].green;
267 xcol.blue = msg->colors[col_i].blue;
268 xcol.pad = 0;
269 xcol.pixel = xc_i;
270 xcol.flags = DoRed | DoGreen | DoBlue;
272 XCALL(XStoreColor, data->display, data->colmap, &xcol);
276 UNLOCK_X11
278 } /* if (data->flags & BMDF_COLORMAP_ALLOCED) */
280 return TRUE;
283 /****************************************************************************************/
285 VOID MNAME(Hidd_BitMap__PutPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
287 struct bitmap_data *data = OOP_INST_DATA(cl, o);
289 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
291 LOCK_X11
293 XCALL(XSetForeground, data->display, data->gc, msg->pixel);
294 XCALL(XSetFunction, data->display, data->gc, GXcopy);
295 XCALL(XDrawPoint, data->display, DRAWABLE(data), data->gc, msg->x, msg->y);
297 UNLOCK_X11
300 /****************************************************************************************/
302 HIDDT_Pixel MNAME(Hidd_BitMap__GetPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetPixel *msg)
304 struct bitmap_data *data = OOP_INST_DATA(cl, o);
305 HIDDT_Pixel pixel = -1;
306 XImage *image;
308 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
310 LOCK_X11
312 XCALL(XSync, data->display, False);
314 image = XCALL(XGetImage, data->display, DRAWABLE(data), msg->x, msg->y, 1, 1, AllPlanes, ZPixmap);
316 if (image)
318 pixel = XGetPixel(image, 0, 0);
319 XDestroyImage(image);
322 UNLOCK_X11
324 return pixel;
328 /****************************************************************************************/
330 ULONG MNAME(Hidd_BitMap__DrawPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPixel *msg)
332 struct bitmap_data *data = OOP_INST_DATA(cl, o);
333 XGCValues gcval;
335 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
337 gcval.function = GC_DRMD(msg->gc);
338 gcval.foreground = GC_FG(msg->gc);
339 gcval.background = GC_BG(msg->gc);
341 LOCK_X11
342 XCALL(XChangeGC, data->display, data->gc, GCFunction | GCForeground | GCBackground, &gcval);
343 XCALL(XDrawPoint, data->display, DRAWABLE(data), data->gc, msg->x, msg->y);
344 UNLOCK_X11
346 return 0;
349 /****************************************************************************************/
351 VOID MNAME(Hidd_BitMap__FillRect)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
353 struct bitmap_data *data = OOP_INST_DATA(cl, o);
354 XGCValues gcval;
356 D(bug("[X11Bm] %s(%d,%d,%d,%d)\n", __PRETTY_FUNCTION__, msg->minX, msg->minY, msg->maxX, msg->maxY));
357 D(bug("[X11Bm] %s: Drawmode = %d\n", __PRETTY_FUNCTION__, GC_DRMD(msg->gc)));
359 gcval.function = GC_DRMD(msg->gc);
360 gcval.foreground = GC_FG(msg->gc);
361 gcval.background = GC_BG(msg->gc);
363 LOCK_X11
364 XCALL(XChangeGC, data->display, data->gc, GCFunction | GCForeground | GCBackground, &gcval);
366 XCALL(XFillRectangle, data->display, DRAWABLE(data), data->gc, msg->minX, msg->minY, msg->maxX - msg->minX + 1, msg->maxY - msg->minY + 1);
368 UNLOCK_X11
371 /****************************************************************************************/
373 static ULONG *ximage_to_buf(OOP_Class *cl, OOP_Object *bm, HIDDT_Pixel *buf, XImage *image, ULONG width, ULONG height,
374 ULONG depth, struct pHidd_BitMap_GetImage *msg)
376 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
378 switch (msg->pixFmt)
380 case vHidd_StdPixFmt_Native:
382 UBYTE *imdata = image->data;
383 LONG y;
385 for (y = 0; y < height; y++)
387 memcpy(buf, imdata, msg->width * image->bits_per_pixel / 8);
389 imdata += image->bytes_per_line;
390 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
393 break;
395 case vHidd_StdPixFmt_Native32:
396 switch (image->bits_per_pixel)
398 case 8:
400 UBYTE *imdata = (UBYTE *) image->data;
401 LONG x, y;
403 for (y = 0; y < height; y++)
405 HIDDT_Pixel *p = buf;
407 for (x = 0; x < width; x++)
409 *p++ = *imdata++;
411 imdata += (image->bytes_per_line - width);
412 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
414 break;
417 case 16:
419 UWORD *imdata = (UWORD *) image->data;
420 LONG x, y;
422 for (y = 0; y < height; y++)
424 HIDDT_Pixel *p = buf;
426 for (x = 0; x < width; x++)
428 *p++ = *imdata++;
430 imdata += image->bytes_per_line / 2 - width;
431 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
433 break;
436 case 32:
438 ULONG *imdata = (ULONG *) image->data;
439 LONG x, y;
441 for (y = 0; y < height; y++)
443 HIDDT_Pixel *p = buf;
445 for (x = 0; x < width; x++)
447 *p++ = *imdata++;
449 imdata += image->bytes_per_line / 4 - width;
450 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
452 break;
455 default:
457 LONG x, y;
459 LOCK_X11
460 for (y = 0; y < height; y++)
462 HIDDT_Pixel *p;
464 p = buf;
465 for (x = 0; x < width; x++)
467 *p++ = XGetPixel(image, x, y);
469 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
471 UNLOCK_X11
472 break;
475 } /* switch (image->bits_per_pixel) */
477 break;
479 default:
482 OOP_Object *srcpf, *dstpf, *gfxhidd;
483 APTR srcPixels = image->data, dstBuf = buf;
485 //bug("DEFAULT PIXEL CONVERSION\n");
487 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, (IPTR *) &gfxhidd);
488 dstpf = HIDD_Gfx_GetPixFmt(gfxhidd, msg->pixFmt);
490 OOP_GetAttr(bm, aHidd_BitMap_PixFmt, (IPTR *) &srcpf);
492 //bug("CALLING ConvertPixels()\n");
494 HIDD_BM_ConvertPixels(bm, &srcPixels, (HIDDT_PixelFormat *) srcpf, image->bytes_per_line, &dstBuf,
495 (HIDDT_PixelFormat *) dstpf, msg->modulo, width, height, NULL /* We have no CLUT */
498 //bug("CONVERTPIXELS DONE\n");
500 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo * height);
501 break;
504 } /* switch (msg->pixFmt) */
506 return buf;
509 /****************************************************************************************/
511 #define ABS(a) ((a) < 0 ? -(a) : a)
513 /****************************************************************************************/
515 static inline UBYTE pix_to_lut(HIDDT_Pixel pixel, HIDDT_PixelLUT *plut, HIDDT_PixelFormat *pf)
517 HIDDT_ColComp red, green, blue;
518 ULONG i, best_match = 0;
519 ULONG diff, lowest_diff = 0xFFFFFFFF;
521 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
523 red = RED_COMP(pixel, pf);
524 green = GREEN_COMP(pixel, pf);
525 blue = BLUE_COMP(pixel, pf);
527 for (i = 0; i < plut->entries; i++)
529 register HIDDT_Pixel cur_lut = plut->pixels[i];
531 if (pixel == cur_lut)
532 return i; /* Exact match found */
534 /* How well does these pixels match ? */
535 diff = ABS(red - RED_COMP(cur_lut, pf)) + ABS(green - GREEN_COMP(cur_lut, pf))
536 + ABS(blue - BLUE_COMP(cur_lut, pf));
538 if (diff < lowest_diff)
540 best_match = i;
541 lowest_diff = diff;
546 return best_match;
549 /****************************************************************************************/
551 static UBYTE *ximage_to_buf_lut(OOP_Class *cl, OOP_Object *bm, UBYTE *buf, XImage *image, ULONG width, ULONG height,
552 ULONG depth, struct pHidd_BitMap_GetImageLUT *msg)
554 /* This one is trickier, as we have to reverse-lookup the lut.
555 This costs CPU ! Maybe one could do some kind of caching here ?
556 Ie. one stores the most often used RGB combinations
557 in a trie and looks up this first to see if whe can find an exact match
560 HIDDT_PixelFormat *pf = BM_PIXFMT(bm);
561 UBYTE *pixarray = msg->pixels;
563 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
565 if (image->bits_per_pixel == 16)
567 UWORD *imdata = (UWORD *) image->data;
568 LONG x, y;
570 for (y = 0; y < height; y++)
572 UBYTE *buf = pixarray;
574 for (x = 0; x < width; x++)
576 *buf++ = pix_to_lut((HIDDT_Pixel) *imdata, msg->pixlut, pf);
578 imdata++;
580 imdata += ((image->bytes_per_line / 2) - width); /*sg*/
582 pixarray += msg->modulo;
586 else
588 LONG x, y;
590 LOCK_X11
591 for (y = 0; y < height; y++)
593 UBYTE *buf = pixarray;
594 for (x = 0; x < width; x++)
596 *buf++ = pix_to_lut((HIDDT_Pixel) XGetPixel(image, x, y), msg->pixlut, pf);
599 pixarray += msg->modulo;
602 UNLOCK_X11
606 return pixarray;
610 /****************************************************************************************/
612 #if USE_XSHM
614 /****************************************************************************************/
616 static void getimage_xshm(OOP_Class *cl, OOP_Object *o, LONG x, LONG y,
617 ULONG width, ULONG height, APTR pixarray,
618 APTR (*fromimage_func)(), APTR fromimage_data)
620 struct bitmap_data *data;
621 XImage *image;
622 IPTR depth;
623 ULONG lines_to_copy;
624 LONG ysize;
625 LONG current_y;
626 LONG maxlines;
627 OOP_Object *pf;
628 Pixmap temp_pixmap = 0;
630 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
632 ASSERT(width > 0 && height > 0);
634 data = OOP_INST_DATA(cl, o);
636 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *)&pf);
637 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
639 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
641 LOCK_X11
642 image = create_xshm_ximage(data->display,
643 DefaultVisual(data->display, data->screen),
644 depth,
645 ZPixmap,
646 width,
647 height,
648 XSD(cl)->xshm_info);
649 UNLOCK_X11
651 if (!image)
652 return;
654 ASSERT(image->bytes_per_line > 0);
656 /* Calculate how many scanline can be stored in the buffer */
657 maxlines = XSHM_MEMSIZE / image->bytes_per_line;
659 if (0 == maxlines)
661 bug("ALERT !!! NOT ENOUGH MEMORY TO READ A COMPLETE SCANLINE\n");
662 bug("THROUGH XSHM IN X11GF X HIDD !!!\n");
663 Alert(AT_DeadEnd);
666 current_y = 0;
667 ysize = image->height;
669 ObtainSemaphore(&XSD(cl)->shm_sema);
671 LOCK_X11
673 while (ysize)
675 /* Get some more pixels from the Ximage */
677 lines_to_copy = MIN(maxlines, ysize);
679 ysize -= lines_to_copy;
680 image->height = lines_to_copy;
682 if (!temp_pixmap)
684 if (!(get_xshm_ximage(data->display, DRAWABLE(data), image,
685 x, y + current_y)))
687 /* XGetImage fails if done on a part of a X window which is off
688 screen (OTOH, it's no problem if it is hidden by another window).
689 If get_xshm_image() failed, we assume that this has happened and
690 thefore copy the area to a temp pixmap, and then get the ximage
691 from there. */
693 temp_pixmap = XCALL(XCreatePixmap, data->display, DRAWABLE(data),
694 width, height - current_y, DefaultDepth(data->display, data->screen));
696 if (temp_pixmap)
698 XCALL(XSetFunction, data->display, data->gc, GXcopy);
700 XCALL(XCopyArea, data->display, DRAWABLE(data), temp_pixmap, data->gc,
701 x, y + current_y, width, height - current_y, 0, 0);
703 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(data->gc));
705 x = 0; y = 0; current_y = 0;
710 if (temp_pixmap)
712 get_xshm_ximage(data->display, temp_pixmap, image,
713 x, y + current_y);
716 current_y += lines_to_copy;
718 pixarray = fromimage_func(cl, o, pixarray, image, image->width,
719 lines_to_copy, depth, fromimage_data);
721 } /* while (pixels left to copy) */
723 if (temp_pixmap)
725 XCALL(XFreePixmap,data->display, temp_pixmap);
728 UNLOCK_X11
730 ReleaseSemaphore(&XSD(cl)->shm_sema);
732 LOCK_X11
733 destroy_xshm_ximage(image);
734 UNLOCK_X11
736 return;
740 /****************************************************************************************/
742 #endif
744 /****************************************************************************************/
746 static void getimage_xlib(OOP_Class *cl, OOP_Object *o, LONG x, LONG y, ULONG width, ULONG height, APTR pixels,
747 APTR(*fromimage_func)(), APTR fromimage_data)
749 struct bitmap_data *data;
750 XImage *image;
751 ULONG *pixarray = (ULONG *) pixels;
752 OOP_Object *pf;
753 IPTR depth;
755 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
757 data = OOP_INST_DATA(cl, o);
759 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *) &pf);
760 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
762 LOCK_X11
763 image = XCALL(XGetImage, data->display, DRAWABLE(data), x, y,
764 width, height, AllPlanes, ZPixmap);
765 UNLOCK_X11
767 if (!image)
768 return;
770 #if DO_ENDIAN_FIX
771 if (NEEDS_ENDIAN_FIX(image))
773 SwapImageEndianess(image);
775 LOCK_X11
776 XCALL(XInitImage, image);
777 UNLOCK_X11
779 #endif
781 fromimage_func(cl, o, pixarray, image, width, height, depth, fromimage_data);
783 LOCK_X11
784 XDestroyImage(image);
785 UNLOCK_X11
787 return;
790 /****************************************************************************************/
792 VOID MNAME(Hidd_BitMap__GetImage)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImage *msg)
794 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
796 ASSERT(msg->width > 0 && msg->height > 0);
798 #if USE_XSHM
799 if (XSD(cl)->use_xshm)
801 getimage_xshm(cl, o, msg->x, msg->y, msg->width, msg->height,
802 msg->pixels, (APTR (*)())ximage_to_buf, msg);
804 else
805 #endif
807 getimage_xlib(cl, o, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) ximage_to_buf, msg);
811 /****************************************************************************************/
813 VOID MNAME(Hidd_BitMap__GetImageLUT)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImageLUT *msg)
815 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
817 ASSERT(msg->width != 0 && msg->height != 0);
818 #if USE_XSHM
819 if (XSD(cl)->use_xshm)
821 getimage_xshm(cl, o, msg->x, msg->y, msg->width, msg->height,
822 msg->pixels, (APTR (*)())ximage_to_buf_lut, msg);
824 else
825 #endif
827 getimage_xlib(cl, o, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) ximage_to_buf_lut, msg);
831 /****************************************************************************************/
833 #undef DEBUG
834 #define DEBUG 0
835 #include <aros/debug.h>
837 /****************************************************************************************/
839 static ULONG *buf_to_ximage(OOP_Class *cl, OOP_Object *bm, HIDDT_Pixel *buf, XImage *image, ULONG width, ULONG height,
840 ULONG depth, struct pHidd_BitMap_PutImage *msg)
842 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
844 switch (msg->pixFmt)
846 case vHidd_StdPixFmt_Native:
848 UBYTE *imdata = image->data;
849 LONG y;
851 for (y = 0; y < height; y++)
853 memcpy(imdata, buf, msg->width * image->bits_per_pixel / 8);
855 imdata += image->bytes_per_line;
856 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
859 break;
861 case vHidd_StdPixFmt_Native32:
862 switch (image->bits_per_pixel)
864 case 8:
866 UBYTE *imdata = (UBYTE *) image->data;
867 LONG x, y;
869 for (y = 0; y < height; y++)
871 HIDDT_Pixel *p = buf;
873 for (x = 0; x < width; x++)
875 *imdata++ = (UBYTE) *p++;
877 imdata += image->bytes_per_line - width;
878 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
880 break;
883 case 16:
885 UWORD *imdata = (UWORD *) image->data;
886 LONG x, y;
888 for (y = 0; y < height; y++)
890 HIDDT_Pixel *p = buf;
892 for (x = 0; x < width; x++)
894 *imdata++ = (UWORD) *p++;
896 imdata += image->bytes_per_line / 2 - width;
897 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
899 break;
902 case 24:
904 HIDDT_PixelFormat *pf;
905 UBYTE *imdata = image->data;
906 LONG x, y;
908 pf = BM_PIXFMT(bm);
910 for (y = 0; y < height; y++)
913 HIDDT_Pixel *p = buf;
915 for (x = 0; x < width; x++)
917 register HIDDT_Pixel pix;
919 pix = *p++;
920 #if (AROS_BIG_ENDIAN == 1)
921 *imdata ++ = pix >> 16;
922 *imdata ++ = (pix & pf->green_mask) >> 8;
923 *imdata ++ = (pix & pf->blue_mask);
924 #else
925 *imdata++ = (pix & pf->blue_mask);
926 *imdata++ = (pix & pf->green_mask) >> 8;
927 *imdata++ = pix >> 16;
928 #endif
930 imdata += image->bytes_per_line - width * 3;
931 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
933 break;
936 case 32:
938 ULONG *imdata = (ULONG *) image->data;
939 LONG x, y;
941 for (y = 0; y < height; y++)
943 HIDDT_Pixel *p = buf;
945 for (x = 0; x < width; x++)
947 *imdata++ = (ULONG) *p++;
949 imdata += image->bytes_per_line / 4 - width;
950 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
952 break;
955 default:
957 LONG x, y;
959 LOCK_X11
960 for (y = 0; y < height; y++)
962 HIDDT_Pixel *p;
964 p = buf;
965 for (x = 0; x < width; x++)
967 XPutPixel(image, x, y, *p++);
969 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo);
971 UNLOCK_X11
972 break;
975 } /* switch (image->bits_per_pixel) */
977 break;
979 default:
981 OOP_Object *srcpf, *dstpf, *gfxhidd;
982 APTR srcPixels = buf, dstBuf = image->data;
984 //bug("DEFAULT PIXEL CONVERSION\n");
986 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, (IPTR *) &gfxhidd);
987 srcpf = HIDD_Gfx_GetPixFmt(gfxhidd, msg->pixFmt);
989 OOP_GetAttr(bm, aHidd_BitMap_PixFmt, (IPTR *) &dstpf);
991 //bug("CALLING ConvertPixels()\n");
993 HIDD_BM_ConvertPixels(bm, &srcPixels, (HIDDT_PixelFormat *) srcpf, msg->modulo, &dstBuf,
994 (HIDDT_PixelFormat *) dstpf, image->bytes_per_line, width, height, NULL); /* We have no CLUT */
996 //bug("CONVERTPIXELS DONE\n");
998 buf = (HIDDT_Pixel *) ((UBYTE *) buf + msg->modulo * height);
999 break;
1002 } /* switch (msg->pixFmt) */
1004 return buf;
1007 /****************************************************************************************/
1009 static UBYTE *buf_to_ximage_lut(OOP_Class *cl, OOP_Object *bm, UBYTE *pixarray, XImage *image, ULONG width,
1010 ULONG height, ULONG depth, struct pHidd_BitMap_PutImageLUT *msg)
1012 HIDDT_Pixel *lut = msg->pixlut->pixels;
1014 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1016 switch (image->bits_per_pixel)
1018 case 8:
1020 UBYTE *imdata = (UBYTE *) image->data;
1021 LONG x, y;
1023 for (y = 0; y < height; y++)
1025 UBYTE *buf = pixarray;
1027 for (x = 0; x < width; x++)
1029 *imdata++ = (UBYTE) lut[*buf++];
1031 pixarray += msg->modulo;
1032 imdata += (image->bytes_per_line - width); /*sg*/
1034 break;
1037 case 16:
1039 UWORD *imdata = (UWORD *) image->data;
1040 LONG x, y;
1042 for (y = 0; y < height; y++)
1044 UBYTE *buf = pixarray;
1046 for (x = 0; x < width; x++)
1048 *imdata++ = (UWORD) lut[*buf++];
1050 pixarray += msg->modulo;
1051 imdata += ((image->bytes_per_line / 2) - width); /*sg*/
1053 break;
1056 case 32:
1058 ULONG *imdata = (ULONG *) image->data;
1059 LONG x, y;
1061 for (y = 0; y < height; y++)
1063 UBYTE *buf = pixarray;
1065 for (x = 0; x < width; x++)
1067 *imdata++ = (ULONG) lut[*buf++];
1070 pixarray += msg->modulo;
1071 imdata += ((image->bytes_per_line / 4) - width); /*sg*/
1073 break;
1076 default:
1078 LONG x, y;
1080 for (y = 0; y < height; y++)
1082 UBYTE *buf = pixarray;
1084 for (x = 0; x < width; x++)
1086 XPutPixel(image, x, y, lut[*buf++]);
1089 pixarray += msg->modulo;
1092 break;
1096 } /* switch(image->bits_per_pixel) */
1098 return pixarray;
1101 /****************************************************************************************/
1103 #if USE_XSHM
1105 /****************************************************************************************/
1107 static void putimage_xshm(OOP_Class *cl, OOP_Object *o, OOP_Object *gc,
1108 LONG x, LONG y, ULONG width, ULONG height,
1109 APTR pixarray, APTR (*toimage_func)(), APTR toimage_data)
1112 struct bitmap_data *data;
1113 XImage *image;
1114 IPTR depth;
1115 ULONG lines_to_copy;
1116 LONG ysize;
1117 LONG current_y;
1118 LONG maxlines;
1119 OOP_Object *pf;
1121 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1123 data = OOP_INST_DATA(cl, o);
1125 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1126 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
1128 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
1130 LOCK_X11
1131 image = create_xshm_ximage(data->display,
1132 DefaultVisual(data->display, data->screen),
1133 depth,
1134 ZPixmap,
1135 width,
1136 height,
1137 XSD(cl)->xshm_info);
1138 UNLOCK_X11
1140 if (!image)
1141 return;
1143 /* Calculate how many scanline can be stored in the buffer */
1144 maxlines = XSHM_MEMSIZE / image->bytes_per_line;
1146 if (0 == maxlines)
1148 bug("ALERT !!! NOT ENOUGH MEMORY TO WRITE A COMPLETE SCANLINE\n");
1149 bug("THROUGH XSHM IN X11GF X HIDD !!!\n");
1150 Alert(AT_DeadEnd);
1153 current_y = 0;
1154 ysize = image->height;
1156 ObtainSemaphore(&XSD(cl)->shm_sema);
1158 while (ysize)
1160 /* Get some more pixels from the HIDD */
1162 lines_to_copy = MIN(maxlines, ysize);
1164 ysize -= lines_to_copy;
1165 image->height = lines_to_copy;
1167 pixarray = toimage_func(cl, o, pixarray, image, image->width,
1168 lines_to_copy, depth, toimage_data);
1170 LOCK_X11
1171 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1173 put_xshm_ximage(data->display,
1174 DRAWABLE(data),
1175 data->gc,
1176 image,
1177 0, 0,
1178 x, y + current_y,
1179 image->width, lines_to_copy,
1180 FALSE);
1182 UNLOCK_X11
1184 current_y += lines_to_copy;
1186 } /* while (pixels left to copy) */
1188 ReleaseSemaphore(&XSD(cl)->shm_sema);
1190 LOCK_X11
1191 destroy_xshm_ximage(image);
1192 UNLOCK_X11
1194 return;
1198 /****************************************************************************************/
1200 #endif
1202 /****************************************************************************************/
1204 static void putimage_xlib(OOP_Class *cl, OOP_Object *o, OOP_Object *gc, LONG x, LONG y, ULONG width, ULONG height,
1205 APTR pixarray, APTR(*toimage_func)(), APTR toimage_data)
1208 struct bitmap_data *data;
1209 XImage *image;
1210 ULONG bperline;
1211 IPTR depth;
1212 OOP_Object *pf;
1214 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1216 data = OOP_INST_DATA(cl, o);
1218 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (IPTR *) &pf);
1219 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
1221 LOCK_X11
1222 image = XCALL(XCreateImage, data->display,
1223 DefaultVisual(data->display, data->screen),
1224 depth,
1225 ZPixmap,
1227 NULL,
1228 width,
1229 height,
1232 UNLOCK_X11
1234 if (!image)
1235 return;
1237 #if DO_ENDIAN_FIX
1238 if (NEEDS_ENDIAN_FIX(image))
1240 image->byte_order = AROS_BYTEORDER;
1242 LOCK_X11
1243 XCALL(XInitImage, image);
1244 UNLOCK_X11
1246 #endif
1248 bperline = image->bytes_per_line;
1249 image->data = (char *) AllocVec((size_t) height * bperline, MEMF_PUBLIC);
1251 if (!image->data)
1253 LOCK_X11
1254 XCALL(XFree, image);
1255 UNLOCK_X11
1257 return;
1260 toimage_func(cl, o, pixarray, image, width, height, depth, toimage_data);
1262 LOCK_X11
1263 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1264 XCALL( XPutImage, data->display, DRAWABLE(data), data->gc, image, 0, 0, x, y, width, height);
1265 UNLOCK_X11
1267 FreeVec(image->data);
1269 LOCK_X11
1270 XCALL(XFree, image);
1271 UNLOCK_X11
1275 /****************************************************************************************/
1277 VOID MNAME(Hidd_BitMap__PutImage)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImage *msg)
1279 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,
1280 msg->height));
1282 #if USE_XSHM
1283 if (XSD(cl)->use_xshm)
1285 putimage_xshm(cl, o, msg->gc, msg->x, msg->y,
1286 msg->width, msg->height, msg->pixels,
1287 (APTR (*)()) buf_to_ximage, msg);
1289 else
1290 #endif
1292 putimage_xlib(cl, o, msg->gc, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) buf_to_ximage, msg);
1296 /****************************************************************************************/
1298 VOID MNAME(Hidd_BitMap__PutImageLUT)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg)
1300 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,
1301 msg->height));
1303 #if USE_XSHM
1304 if (XSD(cl)->use_xshm)
1306 putimage_xshm(cl, o, msg->gc, msg->x, msg->y,
1307 msg->width, msg->height, msg->pixels,
1308 (APTR (*)())buf_to_ximage_lut, msg);
1310 else
1311 #endif
1313 putimage_xlib(cl, o, msg->gc, msg->x, msg->y, msg->width, msg->height, msg->pixels, (APTR(*)()) buf_to_ximage_lut, msg);
1317 /****************************************************************************************/
1319 VOID MNAME(Root__Get)(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
1321 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1322 ULONG idx;
1324 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1326 if (IS_X11BM_ATTR(msg->attrID, idx))
1328 switch (idx)
1330 case aoHidd_X11BitMap_Drawable:
1331 *msg->storage = (IPTR) DRAWABLE(data);
1332 return;
1334 case aoHidd_X11BitMap_GC:
1335 *msg->storage = (IPTR) data->gc;
1336 return;
1340 OOP_DoSuperMethod(cl, o, &msg->mID);
1343 /****************************************************************************************/
1345 BOOL X11BM__Root__Set(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
1347 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1349 #if ADJUST_XWIN_SIZE
1350 /* This provides support for framebuffer display mode switching */
1351 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1353 if (data->flags & BMDF_FRAMEBUFFER)
1355 struct TagItem *tag = FindTagItem(aHidd_BitMap_ModeID, msg->attrList);
1357 if (tag)
1359 if (!X11BM_SetMode(data, tag->ti_Data, XSD(cl)))
1361 /* Bail out if error happened, see aoHidd_BitMap_ModeID documentation */
1362 return FALSE;
1366 #endif
1367 return OOP_DoSuperMethod(cl, o, &msg->mID);
1370 /****************************************************************************************/
1372 VOID MNAME(Hidd_BitMap__DrawLine)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawLine *msg)
1374 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1375 OOP_Object *gc = msg->gc;
1377 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1379 if (GC_LINEPAT(gc) != (UWORD) ~0)
1381 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1383 return;
1386 LOCK_X11
1388 if (GC_DOCLIP(gc))
1390 XRectangle cr;
1392 cr.x = GC_CLIPX1(gc);
1393 cr.y = GC_CLIPY1(gc);
1394 cr.width = GC_CLIPX2(gc) - cr.x + 1;
1395 cr.height = GC_CLIPY2(gc) - cr.y + 1;
1397 XCALL(XSetClipRectangles, data->display, data->gc, 0, 0, &cr, 1, Unsorted);
1400 XCALL(XSetForeground, data->display, data->gc, GC_FG(gc));
1401 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1403 XCALL( XDrawLine, data->display, DRAWABLE(data), data->gc, msg->x1, msg->y1, msg->x2, msg->y2);
1405 if (GC_DOCLIP(gc))
1407 XCALL(XSetClipMask, data->display, data->gc, None);
1410 UNLOCK_X11
1413 /****************************************************************************************/
1415 VOID MNAME(Hidd_BitMap__DrawEllipse)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1417 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1418 OOP_Object *gc = msg->gc;
1420 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1422 LOCK_X11
1424 if (GC_DOCLIP(gc))
1426 XRectangle cr;
1428 /* bug("X11::Drawllipse: clip %d %d %d %d\n"
1429 , GC_CLIPX1(gc), GC_CLIPY1(gc), GC_CLIPX2(gc), GC_CLIPY2(gc));
1432 cr.x = GC_CLIPX1(gc);
1433 cr.y = GC_CLIPY1(gc);
1434 cr.width = GC_CLIPX2(gc) - cr.x + 1;
1435 cr.height = GC_CLIPY2(gc) - cr.y + 1;
1437 XCALL(XSetClipRectangles, data->display, data->gc, 0, 0, &cr, 1, Unsorted);
1440 XCALL(XSetForeground, data->display, data->gc, GC_FG(gc));
1441 XCALL(XSetFunction, data->display, data->gc, GC_DRMD(gc));
1443 /* bug("X11::Drawllipse: coord %d %d %d %d\n"
1444 , msg->x, msg->y, msg->rx, msg->ry);
1448 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);
1450 if (GC_DOCLIP(gc))
1452 XCALL(XSetClipMask, data->display, data->gc, None);
1455 UNLOCK_X11
1458 /****************************************************************************************/
1460 VOID MNAME(Hidd_BitMap__UpdateRect)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_UpdateRect *msg)
1462 struct bitmap_data *data = OOP_INST_DATA(cl, o);
1464 D(bug("[X11Bm] %s()\n", __PRETTY_FUNCTION__));
1466 LOCK_X11
1468 if (data->flags & BMDF_FRAMEBUFFER)
1469 X11BM_ExposeFB(data, msg->x, msg->y, msg->width, msg->height);
1471 XCALL(XFlush, data->display);
1473 UNLOCK_X11