1 namespace gfx::drivers;
5 #if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
9 #define property _property
14 #define Window X11Window
15 #define Cursor X11Cursor
17 #define Display X11Display
19 #define KeyCode X11KeyCode
20 #define Picture X11Picture
23 #include <X11/Xutil.h>
24 #if !defined(__EMSCRIPTEN__)
25 #include <X11/extensions/shape.h>
26 #include <X11/extensions/Xrender.h>
28 #include <X11/extensions/XShm.h>
51 static byte defaultRGBLookup[32768];
52 bool rgbLookupSet = false;
54 class XDisplay : LFBDisplay //struct
62 X11Picture shapePicture;
63 XShmSegmentInfo shminfo;
65 XShmSegmentInfo shminfoShape;
69 class XSurface : struct
77 ColorAlpha foreground, background;
82 X11Picture colorPicture;
86 class XBitmap : struct
91 X11Picture maskPicture;
94 XRenderPictFormat * GetXRenderFormat(PixelFormat pixelFormat, bool alphaBlend)
96 XRenderPictFormat * format = null;
99 case pixelFormatAlpha:
100 format = XRenderFindStandardFormat(xGlobalDisplay, PictStandardA8);
103 format = XRenderFindStandardFormat(xGlobalDisplay, alphaBlend ? PictStandardARGB32 : PictStandardRGB24);
104 // printf("R: %d G: %d B: %d\n", format->direct.red, format->direct.green, format->direct.blue);
108 XRenderPictFormat info = { 0 };
111 info.type = PictTypeDirect;
112 info.direct.red = 10;
113 info.direct.green = 5;
114 info.direct.blue = 0;
115 info.direct.redMask = 0x1F;
116 info.direct.greenMask = 0x1F;
117 info.direct.blueMask = 0x1F;
119 format = XRenderFindFormat(xGlobalDisplay,
120 /*PictFormatDepth|*/PictFormatType| PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
121 PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
126 XRenderPictFormat info = { 0 };
129 info.type = PictTypeDirect;
130 info.direct.alpha = 0;
131 info.direct.red = 11;
132 info.direct.green = 5;
133 info.direct.blue = 0;
134 info.direct.redMask = 0x1F;
135 info.direct.greenMask = 0x3F;
136 info.direct.blueMask = 0x1F;
137 info.direct.alphaMask = 0;
140 format = XRenderFindFormat(xGlobalDisplay,
141 /*PictFormatDepth|*/PictFormatType|PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
142 PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
149 static bool ClipBlitCoords(Surface surface, Bitmap src, int *dx, int *dy, int *sx, int *sy, int *w, int *h, bool * flip)
153 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top) return false;
155 if(*w < 0) { *w = -*w; *flip = true; }
157 //Clip against the edges of the source
170 if(*sx+*w>src.width-1)
171 *w-=*sx+*w-(src.width-1)-1;
172 if(*sy+*h>src.height-1)
173 *h-=*sy+*h-(src.height-1)-1;
174 //Clip against the edges of the destination
175 if(*dx<surface.box.left)
177 if(!*flip) *sx+=surface.box.left-*dx;
178 *w-=surface.box.left-*dx;
179 *dx=surface.box.left;
181 if(*dy<surface.box.top)
183 *sy+=surface.box.top-*dy;
184 *h-=surface.box.top-*dy;
187 if((*dx+*w)>surface.box.right)
189 if(*flip) *sx+=(uint)(*dx+*w)-surface.box.right-1;
190 *w-=((uint)(*dx+*w)-surface.box.right-1);
192 if((*dy+*h)>surface.box.bottom)
193 *h-=((*dy+*h)-surface.box.bottom-1);
199 static bool ClipStretchCoords(Surface surface, Bitmap src, int *dx, int *dy, int *sx, int *sy, int *w, int *h, int *sw, int *sh, bool * flip)
201 float s2dw,s2dh,d2sw,d2sh;
204 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return false;
206 if(Sgn(*w) != Sgn(*sw))
213 s2dw=(float)*w / *sw;
214 s2dh=(float)*h / *sh;
215 d2sw=(float)*sw / *w;
216 d2sh=(float)*sh / *h;
218 //Clip against the edges of the source
221 *dx += (int)((0-*sx) * s2dw);
222 *w -= (int)((0-*sx) * s2dw);
228 *dy += (int)((0-*sy) * s2dh);
229 *h -= (int)((0-*sy) * s2dh);
234 if(*sx+*sw>src.width-1)
236 *w-=(int)((*sx+*sw-(src.width-1)-1)*s2dw);
237 *sw-=*sx+*sw-(src.width-1)-1;
239 if(*sy+*sh>(src.height-1))
241 *h-=(int)((*sy+*sh-(src.height-1)-1)*s2dh);
242 *sh-=*sy+*sh-(src.height-1)-1;
244 //Clip against the edges of the destination
245 if(*dx < surface.box.left)
247 if(!*flip) *sx += (int)((surface.box.left-*dx)*d2sw);
248 *sw-=(int)((surface.box.left-*dx)*d2sw);
249 *w-=surface.box.left-*dx;
250 *dx=surface.box.left;
252 if(*dy < surface.box.top)
254 *sy += (int)((surface.box.top-*dy)*d2sh);
255 *sh -= (int)((surface.box.top-*dy)*d2sh);
256 *h -= surface.box.top-*dy;
257 *dy =surface.box.top;
259 if((*dx+*w)>surface.box.right)
261 if(*flip) *sx+=(int)(((*dx+*w)-surface.box.right-1)*d2sw);
262 *sw-=(int)(((*dx + *w)-surface.box.right-1)*d2sw);
263 *w-=((*dx+*w)-surface.box.right-1);
265 if((*dy+*h)>surface.box.bottom)
267 *sh-=(int)(((*dy+*h)-surface.box.bottom-1)*d2sh);
268 *h-=((*dy+*h)-surface.box.bottom-1);
270 if((*w<=0)||(*h<=0)||(*sw<=0)||(*sh<=0))
275 static void PutBitmapMask(Pixmap mask, Bitmap bitmap) {
277 GC maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
278 uint wordWidth = (bitmap.width+31) >> 5;
281 uint32 *b = new0 uint32[wordWidth * bitmap.height];
284 XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
286 image.width = bitmap.width;
287 image.height = bitmap.height;
289 image.format = XYBitmap;
290 #ifdef __BIG_ENDIAN__
291 image.byte_order = MSBFirst;
293 image.byte_order = LSBFirst;
295 image.bitmap_unit = 32;
296 image.bitmap_bit_order = LSBFirst;
297 image.bitmap_pad = 32;
299 image.bytes_per_line = wordWidth << 2;
301 image.data = (char*)b;
305 switch(bitmap.pixelFormat) {
310 byte *p = (byte*)bitmap.picture;
312 for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
313 for(x = 0; x<bitmap.width; x++) {
315 *b |= f; //XPutPixel(&image, x,y, 1);
325 case pixelFormat565: {
326 uint16 *p = (uint16*)bitmap.picture;
328 PrintLn(bitmap.pixelFormat);
330 for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
331 for(x = 0; x<bitmap.width; x++) {
333 *b |= f; //XPutPixel(&image, x,y, 1);
341 case pixelFormat888: {
342 ColorAlpha *p = (ColorAlpha*)bitmap.picture;
343 for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
344 for(x = 0; x<bitmap.width; x++) {
346 *b |= f; //XPutPixel(&image, x,y, 1);
354 case pixelFormatAlpha: {
357 case pixelFormatText: {
360 case pixelFormatRGBA: {
365 XSetForeground(xGlobalDisplay, maskGC, 1);
366 XSetBackground(xGlobalDisplay, maskGC, 0);
368 XPutImage(xGlobalDisplay, mask, maskGC, &image,
369 0, 0, 0, 0, //coordinates
370 bitmap.width, bitmap.height);
372 XFreeGC(xGlobalDisplay, maskGC);
376 class XDisplayDriver : DisplayDriver
378 class_property(name) = "X";
380 bool CreateDisplaySystem(DisplaySystem displaySystem)
382 //displaySystem.driverData = calloc(1, sizeof(LFBSystem));
383 displaySystem.flags.memBackBuffer = true;
384 displaySystem.pixelFormat = xSystemPixelFormat;
388 void DestroyDisplaySystem(DisplaySystem displaySystem)
390 // delete displaySystem.driverData;
393 void DestroyDisplay(Display display)
395 XDisplay xDisplay = display.driverData;
397 // Free Shared Memory Pixmap
398 if(xDisplay.shapePixmap)
399 XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
401 XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
404 if(xDisplay.shminfoShape.shmid != -1)
406 XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
407 if(xDisplay.shminfo.shmaddr != (void *)-1)
408 shmdt(xDisplay.shminfo.shmaddr);
409 shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
412 if(xDisplay.shapeImage)
414 if(xDisplay.shminfoShape.shmid != -1)
416 XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
417 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
418 shmdt(xDisplay.shminfoShape.shmaddr);
419 shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
421 XDestroyImage(xDisplay.shapeImage);
422 xDisplay.shapeImage = None;
425 XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
426 if(xDisplay.shapePicture)
427 XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
428 if(xDisplay.windowGC)
429 XFreeGC(xGlobalDisplay, xDisplay.windowGC);
431 XFreeGC(xGlobalDisplay, xDisplay.gc);
433 display.driverData = null;
436 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
442 bool CreateDisplay(Display display)
445 XDisplay xDisplay = display.driverData = XDisplay { };
449 xDisplay.windowGC = XCreateGC(xGlobalDisplay, (X11Window)display.window, 0, null);
450 XSetGraphicsExposures(xGlobalDisplay, xDisplay.windowGC, False);
456 bool DisplaySize(Display display, int width, int height)
458 XDisplay xDisplay = display.driverData;
461 if(width > display.width || height > display.height)
463 display.width = width;
464 display.height = height;
467 XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
470 XRenderPictureAttributes attributes = { 0 };
471 XRenderPictFormat * format = GetXRenderFormat(xSystemPixelFormat, display.alphaBlend);
472 attributes.component_alpha = 1;
473 attributes.poly_mode = PolyModeImprecise;
474 attributes.poly_edge = PolyEdgeSmooth;
478 XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
479 xDisplay.pixmap = None;
481 if(xDisplay.shapePixmap)
483 XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
484 xDisplay.shapePixmap = None;
487 // Free Shared Memory Pixmap
490 if(xDisplay.shminfoShape.shmid != -1)
492 XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
493 if(xDisplay.shminfo.shmaddr != (void *)-1)
494 shmdt(xDisplay.shminfo.shmaddr);
495 shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
497 XDestroyImage(xDisplay.image);
498 xDisplay.image = None;
500 if(xDisplay.shapeImage)
502 if(xDisplay.shminfoShape.shmid != -1)
504 XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
505 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
506 shmdt(xDisplay.shminfoShape.shmaddr);
507 shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
509 XDestroyImage(xDisplay.shapeImage);
510 xDisplay.shapeImage = None;
513 // Initialize Shared Memory Pixmap
515 if(xSharedMemory && display.useSharedMemory && format)
518 printf("Using shared memory!\n");
520 xDisplay.image = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
521 format->depth, ZPixmap, null, &xDisplay.shminfo, width, height);
523 else if(display.useSharedMemory && !xSharedMemory)
524 printf("%s", $"Error: Requested shared memory but shared memory pixmaps are not supported by X server.\n");
528 memset(&xDisplay.shminfo, 0, sizeof(XShmSegmentInfo));
529 // printf("shmget: %d\n", xDisplay.image->bytes_per_line * xDisplay.image->height);
530 xDisplay.shminfo.shmid = shmget(IPC_PRIVATE, xDisplay.image->bytes_per_line * xDisplay.image->height, IPC_CREAT|0777);
531 if(xDisplay.shminfo.shmid != -1)
533 xDisplay.shminfo.shmaddr = shmat(xDisplay.shminfo.shmid, 0, 0);
534 if(xDisplay.shminfo.shmaddr != (void *)-1)
536 // printf("%d, %d\n", xDisplay.shminfo.shmid, xDisplay.shminfo.shmaddr);
537 xDisplay.shminfo.readOnly = False;
538 if(XShmAttach(xGlobalDisplay, &xDisplay.shminfo))
540 xDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfo.shmaddr, &xDisplay.shminfo, width, height, format->depth);
542 xDisplay.bitmap.width = width;
543 xDisplay.bitmap.height = height;
544 xDisplay.bitmap.stride = xDisplay.image->bytes_per_line >> GetColorDepthShifts(display.pixelFormat);
545 xDisplay.bitmap.pixelFormat = display.pixelFormat;
546 xDisplay.bitmap.picture = (byte *)xDisplay.shminfo.shmaddr;
547 xDisplay.bitmap.size = width * height;
548 xDisplay.bitmap.sizeBytes = (uint)xDisplay.bitmap.size << GetColorDepthShifts(display.pixelFormat);
554 if(xDisplay.shminfo.shmid != -1)
556 XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
557 if(xDisplay.shminfo.shmaddr != (void *)-1)
558 shmdt(xDisplay.shminfo.shmaddr);
559 shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
561 XDestroyImage(xDisplay.image);
562 xDisplay.image = None;
567 // Initialize Shared Memory Shape Pixmap
568 if(xSharedMemory && display.useSharedMemory && display.alphaBlend)
569 xDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
570 1, ZPixmap, null, &xDisplay.shminfoShape, width, height);
572 if(xDisplay.shapeImage)
574 xDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE, xDisplay.shapeImage->bytes_per_line * xDisplay.shapeImage->height, IPC_CREAT|0777);
575 if(xDisplay.shminfoShape.shmid != -1)
577 xDisplay.shminfoShape.shmaddr = shmat(xDisplay.shminfoShape.shmid, 0, 0);
578 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
580 xDisplay.shminfoShape.readOnly = False;
581 if(XShmAttach(xGlobalDisplay, &xDisplay.shminfoShape))
583 xDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfoShape.shmaddr, &xDisplay.shminfoShape, width, height, 1);
587 if(!xDisplay.shapePixmap)
589 if(xDisplay.shminfoShape.shmid != -1)
591 XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
592 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
593 shmdt(xDisplay.shminfoShape.shmaddr);
594 shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
596 XDestroyImage(xDisplay.shapeImage);
597 xDisplay.shapeImage = None;
601 if(!xDisplay.pixmap && format)
602 xDisplay.pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, format->depth);
603 if(display.alphaBlend && !xDisplay.shapePixmap)
604 xDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
607 xDisplay.gc = XCreateGC(xGlobalDisplay, (Pixmap)xDisplay.pixmap, 0, null);
608 XSetGraphicsExposures(xGlobalDisplay, xDisplay.gc, False);
612 xDisplay.picture = XRenderCreatePicture(xGlobalDisplay, xDisplay.pixmap, format, CPComponentAlpha, &attributes);
614 if(display.alphaBlend)
615 xDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, xDisplay.shapePixmap, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
618 xDisplay.updateBox.left = display.width;
619 xDisplay.updateBox.top = display.height;
620 xDisplay.updateBox.right = 0;
621 xDisplay.updateBox.bottom = 0;
627 void DisplayPosition(Display display, int x, int y)
629 XDisplay xDisplay = display.driverData;
630 xDisplay.offset.x = x;
631 xDisplay.offset.y = y;
634 void RestorePalette(Display display)
639 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
641 XBitmap xBitmap = bitmap.driverData;
645 XFreePixmap(xGlobalDisplay, xBitmap.pixmap);
647 XFreePixmap(xGlobalDisplay, xBitmap.mask);
649 XRenderFreePicture(xGlobalDisplay, xBitmap.picture);
650 if(xBitmap.maskPicture)
651 XRenderFreePicture(xGlobalDisplay, xBitmap.maskPicture);
653 bitmap.driverData = null;
655 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
658 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
660 //XDisplay xDisplay = display.driverData;
662 XImage image = { 0 };
665 if(bitmap.pixelFormat != pixelFormatAlpha)
666 bitmap.Convert(null, bitmap.alphaBlend ? pixelFormat888 : xSystemPixelFormat, null);
668 //bitmap.Convert(null, pixelFormatRGBA, null);
669 //bitmap.Convert(null, pixelFormat888, null);
671 XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height,
672 (bitmap.pixelFormat == pixelFormatAlpha) ? 8 : (bitmap.alphaBlend ? 32 : ((bitmap.pixelFormat == pixelFormat888) ? 24 : xSystemDepth)));
673 if(bitmap.transparent)
675 XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height, 1);
678 XRenderPictureAttributes attributes = { 0 };
679 XRenderPictFormat * format = GetXRenderFormat(bitmap.pixelFormat, bitmap.alphaBlend);
680 attributes.component_alpha = 1;
683 xBitmap.picture = XRenderCreatePicture(xGlobalDisplay, xBitmap.pixmap, format, CPComponentAlpha, &attributes);
684 if(bitmap.transparent && bitmap.pixelFormat != pixelFormatAlpha)
685 xBitmap.maskPicture = XRenderCreatePicture(xGlobalDisplay, xBitmap.mask, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), CPComponentAlpha, &attributes);
688 gc = XCreateGC(xGlobalDisplay, (Pixmap)xBitmap.pixmap, 0, null);
690 XSetGraphicsExposures(xGlobalDisplay, gc, False);
692 image.width = bitmap.width;
693 image.height = bitmap.height;
695 if(bitmap.pixelFormat == pixelFormatAlpha)
698 image.bitmap_pad = 8;
699 image.bytes_per_line = bitmap.stride;
700 image.bits_per_pixel = 8;
704 image.depth = bitmap.alphaBlend ? 32 : ((bitmap.pixelFormat == pixelFormat888) ? 24 : xSystemDepth);
705 image.bitmap_pad = (bitmap.pixelFormat == pixelFormat888) ? 32 : 16;
706 image.bytes_per_line = ((bitmap.pixelFormat == pixelFormat888) ? 4 : 2) * bitmap.stride;
707 image.bits_per_pixel = (bitmap.pixelFormat == pixelFormat888) ? 32 : 16;
710 image.format = ZPixmap;
711 //image.bitmap_bit_order = MSBFirst;
712 #ifdef __BIG_ENDIAN__
713 image.byte_order = MSBFirst;
715 image.bitmap_unit = 8;
717 image.red_mask = 0xF800;
718 image.green_mask = 0x7E0;
719 image.blue_mask = 0x1F;
723 image.red_mask = 0x0000FF;
724 image.green_mask = 0x00FF00;
725 image.blue_mask = 0xFF0000;
727 // image.red_mask = 0xFFFF0000;
729 image.data = (char *)bitmap.picture;
732 if(bitmap.pixelFormat != pixelFormatAlpha && bitmap.alphaBlend)
735 for(y = 0; y<bitmap.height; y++)
737 for(x = 0; x<bitmap.width; x++)
739 ColorAlpha * p = ((ColorAlpha *)bitmap.picture) + y * bitmap.stride + x;
741 p->color.r = (byte)(p->color.r * alpha / 255);
742 p->color.g = (byte)(p->color.g * alpha / 255);
743 p->color.b = (byte)(p->color.b * alpha / 255);
748 XPutImage(xGlobalDisplay, (Pixmap)xBitmap.pixmap, gc, &image,
749 0, 0, 0, 0, bitmap.width,bitmap.height);
751 if(bitmap.transparent && !bitmap.alphaBlend && bitmap.pixelFormat != pixelFormatAlpha)
752 PutBitmapMask(xBitmap.mask, bitmap);
754 XFreeGC(xGlobalDisplay, gc);
757 delete bitmap.picture;
759 bitmap.driverData = xBitmap;
760 bitmap.driver = displaySystem.driver;
764 void ReleaseSurface(Display display, Surface surface)
766 XSurface xSurface = surface.driverData;
767 XDisplay xDisplay = display ? display.driverData : null;
768 XRectangle rectangle;
770 if(xSurface.colorPicture)
771 XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
777 rectangle.width = (uint16)display.width;
778 rectangle.height = (uint16)display.height;
779 XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
782 if(xSurface.colorPixmap)
783 XFreePixmap(xGlobalDisplay, xSurface.colorPixmap);
788 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
791 XBitmap xBitmap = bitmap.driverData;
794 if((surface.driverData = xSurface = XSurface { }))
796 surface.offset.x = x;
797 surface.offset.y = y;
798 surface.unclippedBox = surface.box = clip;
800 xSurface.pixmap = xBitmap.pixmap;
807 bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
810 XDisplay xDisplay = display.driverData;
812 if((surface.driverData = xSurface = XSurface { }))
814 XRectangle rectangle;
816 surface.offset.x = x;
817 surface.offset.y = y;
818 surface.unclippedBox = surface.box = clip;
819 xSurface.pixmap = xDisplay.pixmap;
820 xSurface.picture = xDisplay.picture;
822 xSurface.colorPixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, 1, 1, /*(xSystemDepth == 16) ? 16 : */32);
824 rectangle.x = (short)(clip.left + x);
825 rectangle.y = (short)(clip.top + y);
826 rectangle.width = (short)(clip.right - clip.left + 1);
827 rectangle.height = (short)(clip.bottom - clip.top + 1);
829 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
830 XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
832 xDisplay.updateBox.left = Min(x + clip.left, xDisplay.updateBox.left);
833 xDisplay.updateBox.top = Min(y + clip.top, xDisplay.updateBox.top);
834 xDisplay.updateBox.right = Max(x + clip.right, xDisplay.updateBox.right);
835 xDisplay.updateBox.bottom = Max(y + clip.bottom, xDisplay.updateBox.bottom);
842 void Clip(Display display, Surface surface, Box clip)
844 XSurface xSurface = surface.driverData;
845 XDisplay xDisplay = display.driverData;
846 bool changed = false;
851 box.Clip(surface.unclippedBox);
855 xSurface.clipped = true;
858 else if(xSurface.clipped)
860 surface.box = surface.unclippedBox;
861 xSurface.clipped = false;
866 XRectangle rectangle =
868 (short)(surface.box.left + surface.offset.x),
869 (short)(surface.box.top + surface.offset.y),
870 (short)(surface.box.right - surface.box.left + 1),
871 (short)(surface.box.bottom - surface.box.top + 1)
873 XSetClipRectangles(xGlobalDisplay, xDisplay.gc,
874 0,0, &rectangle, 1, YXBanded);
878 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
881 XDisplay xDisplay = display ? display.driverData : null;
883 PixelFormat format = pixelFormat888;
903 if(sx+sw>display.width-1)
904 sw-=sx+sw-(display.width-1)-1;
905 if(sy+sh>display.height-1)
906 sh-=sy+sh-(display.height-1)-1;
910 xImage = XGetImage(xGlobalDisplay, xDisplay.pixmap, sx, sy, sw, sh, MAXDWORD, ZPixmap);
912 xImage = XGetImage(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), sx, sy, sw, sh, MAXDWORD, ZPixmap);
914 source.pixelFormat = format;
915 source.picture = (byte *)xImage->data;
918 source.stride = xImage->bytes_per_line / 4;
920 if(!bitmap || bitmap.pixelFormat != format || bitmap.width < w || bitmap.height < h)
923 bitmap.Allocate(null, w,h,w, format, (format == pixelFormat8)?true:false);
927 Surface surface = bitmap.GetSurface(0, 0, null);
928 surface.Blit(source, dx,dy,0,0,sw,sh);
932 source.picture = null;
935 XDestroyImage(xImage);
939 void SetForeground(Display display, Surface surface, ColorAlpha color)
941 XSurface xSurface = surface.driverData;
942 XDisplay xDisplay = display ? display.driverData : null;
943 XRenderColor renderColor = { (uint16)(color.color.r * color.a), (uint16)(color.color.g * color.a), (uint16)(color.color.b * color.a), (uint16)(color.a * 255) };
945 if(xSurface.colorPicture)
946 XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
947 // xSurface.colorPicture = XRenderCreateSolidFill(xGlobalDisplay, &renderColor);
950 XRenderPictureAttributes attributes = { 0 };
951 // XRenderPictFormat * format = myXRenderFindStandardFormat(xGlobalDisplay, PictStandardARGB32 /*PictStandardRGB24 /*PictStandardARGB32*/, 1);
952 XRenderPictFormat * format = /*(xSystemPixelFormat != pixelFormat888) ? GetXRenderFormat(xSystemPixelFormat, false) : */XRenderFindStandardFormat(xGlobalDisplay, PictStandardARGB32);
953 #if !defined(__APPLE__) && !defined(__OLDX__)
954 attributes.repeat = RepeatNormal;
956 attributes.repeat = 1;
958 ///attributes.component_alpha = 0;
960 xSurface.colorPicture = XRenderCreatePicture(xGlobalDisplay, xSurface.colorPixmap, format, /*CPComponentAlpha | */CPRepeat, &attributes);
961 XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.colorPicture, &renderColor, 0, 0, 1, 1);
964 // xSurface.foreground = ARGB(A(color),B(color),G(color),R(color));
965 xSurface.foreground = color;
968 XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
969 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
972 void SetBackground(Display display, Surface surface, ColorAlpha color)
974 XSurface xSurface = surface.driverData;
975 XDisplay xDisplay = display ? display.driverData : null;
976 // xSurface.background = ARGB(A(color),B(color),G(color),R(color));
977 xSurface.background = color;
980 XSetBackground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
981 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
984 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
989 void PutPixel(Display display, Surface surface,int x,int y)
991 XSurface xSurface = surface.driverData;
992 XDisplay xDisplay = display.driverData;
994 if(xSurface.foreground.a < 255)
995 DrawLine(display, surface, x,y,x,y);
997 XDrawPoint(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
998 x + surface.offset.x,
999 y + surface.offset.y);
1002 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1004 XDisplay xDisplay = display ? display.driverData : null;
1005 XSurface xSurface = surface.driverData;
1006 if(!xDisplay || xSurface.foreground.a < 255)
1008 XTrapezoid traps[3];
1010 double offset = 0.5;
1013 x1 += surface.offset.x;
1014 y1 += surface.offset.y;
1015 x2 += surface.offset.x;
1016 y2 += surface.offset.y;
1025 XDoubleToFixed(y1 - width + offset), XDoubleToFixed(y1 + width + offset),
1026 { { XDoubleToFixed(Min(x1, x2) - 0 + offset), XDoubleToFixed(y1 - width + offset) }, { XDoubleToFixed(Min(x1, x2) + 0.0 + offset), XDoubleToFixed(y1 + width+ offset) } },
1027 { { XDoubleToFixed(Max(x1, x2) - 0 + offset), XDoubleToFixed(y1 - width + offset) }, { XDoubleToFixed(Max(x1, x2) + 0.0 + offset), XDoubleToFixed(y1 + width+ offset) } }
1040 XDoubleToFixed(Min(y1, y2) - 0.0 + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset),
1041 { { XDoubleToFixed(x1 - width + offset), XDoubleToFixed(Min(y1, y2) - 0.0 + offset) }, { XDoubleToFixed(x1 - width + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset) } },
1042 { { XDoubleToFixed(x1 + width + offset), XDoubleToFixed(Min(y1, y2) - 0.0 + offset) }, { XDoubleToFixed(x1 + width + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset) } }
1051 Pointf A, B, C, D, E, F;
1064 l = sqrt(dx * dx + dy * dy);
1070 A = { (float)(x1 + dy * width), (float)(y1 - dx * width) };
1071 B = { (float)(x1 - dy * width), (float)(y1 + dx * width) };
1072 C = { (float)(A.x + ((B.y - A.y) * dx / dy)), B.y };
1073 E = { (float)(x2 + dy * width), (float)(y2 - dx * width) };
1074 F = { (float)(x2 - dy * width), (float)(y2 + dx * width) };
1075 D = { (float)(F.x + ((E.y - F.y) * dx / dy)), E.y };
1080 XDoubleToFixed(A.y + offset), XDoubleToFixed(B.y + offset),
1081 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) } },
1082 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) } }
1086 XDoubleToFixed(B.y + offset), XDoubleToFixed(D.y + offset),
1087 { { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) }, { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) } },
1088 { { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) }, { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) } }
1092 XDoubleToFixed(D.y + offset), XDoubleToFixed(F.y + offset),
1093 { { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } },
1094 { { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } }
1104 A = { (float)(x1 - dy * width), (float)(y1 + dx * width) };
1105 B = { (float)(x1 + dy * width), (float)(y1 - dx * width) };
1106 C = { (float)(A.x + ((B.y - A.y) * dx / dy)), B.y };
1107 E = { (float)(x2 - dy * width), (float)(y2 + dx * width) };
1108 F = { (float)(x2 + dy * width), (float)(y2 - dx * width) };
1109 D = { (float)(F.x + ((E.y - F.y) * dx / dy)), E.y };
1114 XDoubleToFixed(A.y + offset), XDoubleToFixed(B.y + offset),
1115 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) } },
1116 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) } }
1120 XDoubleToFixed(B.y + offset), XDoubleToFixed(D.y + offset),
1121 { { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) }, { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) } },
1122 { { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) }, { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) } }
1126 XDoubleToFixed(D.y + offset), XDoubleToFixed(F.y + offset),
1127 { { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } },
1128 { { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } }
1137 printf("Line: (%d, %d)-(%d, %d)\n", x1,y1, x2,y2);
1138 printf("Line: A = (%.2f, %.2f), B = (%.2f, %.2f), C = (%.2f, %.2f)\n", A.x,A.y, B.x,B.y, C.x,C.y);
1139 printf("Line: D = (%.2f, %.2f), E = (%.2f, %.2f), F = (%.2f, %.2f)\n", D.x,D.y, E.x,E.y, F.x,F.y);
1140 printf("Trap1: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1141 traps[0].top / 65536.0, traps[0].bottom / 65536.0,
1142 traps[0].left.p1.x / 65536.0, traps[0].left.p1.y / 65536.0, traps[0].left.p2.x / 65536.0, traps[0].left.p2.y / 65536.0,
1143 traps[0].right.p1.x / 65536.0, traps[0].right.p1.y / 65536.0, traps[0].right.p2.x / 65536.0, traps[0].right.p2.y / 65536.0);
1144 printf("Trap2: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1145 traps[1].top / 65536.0, traps[1].bottom / 65536.0,
1146 traps[1].left.p1.x / 65536.0, traps[1].left.p1.y / 65536.0, traps[1].left.p2.x / 65536.0, traps[1].left.p2.y / 65536.0,
1147 traps[1].right.p1.x / 65536.0, traps[1].right.p1.y / 65536.0, traps[1].right.p2.x / 65536.0, traps[1].right.p2.y / 65536.0);
1148 printf("Trap3: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1149 traps[2].top / 65536.0, traps[2].bottom / 65536.0,
1150 traps[2].left.p1.x / 65536.0, traps[2].left.p1.y / 65536.0, traps[2].left.p2.x / 65536.0, traps[2].left.p2.y / 65536.0,
1151 traps[2].right.p1.x / 65536.0, traps[2].right.p1.y / 65536.0, traps[2].right.p2.x / 65536.0, traps[2].right.p2.y / 65536.0);
1155 XRenderCompositeTrapezoids(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xSurface.picture, None, 0, 0, traps, nTraps);
1158 XDrawLine(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1159 x1 + surface.offset.x,
1160 y1 + surface.offset.y,
1161 x2 + surface.offset.x,
1162 y2 + surface.offset.y);
1165 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1167 XDisplay xDisplay = display ? display.driverData : null;
1168 XSurface xSurface = surface.driverData;
1170 if(!xDisplay || xSurface.foreground.a < 255)
1172 DrawLine(display, surface,x1,y1,x2-1,y1);
1173 DrawLine(display, surface,x2,y1,x2,y2-1);
1174 DrawLine(display, surface,x1,y2,x2-1,y2);
1175 DrawLine(display, surface,x1,y1+1,x1,y2-1);
1178 XDrawRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1179 x1 + surface.offset.x,
1180 y1 + surface.offset.y,
1184 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1186 XDisplay xDisplay = display ? display.driverData : null;
1187 XSurface xSurface = surface.driverData;
1188 if(!xDisplay || xSurface.background.a < 255)
1190 XRenderColor renderColor =
1192 (uint16)(xSurface.background.color.r * xSurface.background.a),
1193 (uint16)(xSurface.background.color.g * xSurface.background.a),
1194 (uint16)(xSurface.background.color.b * xSurface.background.a),
1195 (uint16)(xSurface.background.a * 255)
1197 x1 += surface.offset.x;
1198 y1 += surface.offset.y;
1199 x2 += surface.offset.x;
1200 y2 += surface.offset.y;
1201 XRenderFillRectangle(xGlobalDisplay, PictOpOver, xSurface.picture, &renderColor, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1);
1205 XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
1206 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
1207 XFillRectangle(xGlobalDisplay, (Pixmap) xDisplay.pixmap, xDisplay.gc,
1208 x1 + surface.offset.x,
1209 y1 + surface.offset.y,
1210 x2 - x1 + 1, y2 - y1 + 1);
1211 XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
1212 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
1216 void Clear(Display display, Surface surface, ClearType flags)
1218 if(flags != depthBuffer)
1220 // XDisplay xDisplay = display.driverData;
1221 XSurface xSurface = surface.driverData;
1222 if(xSurface.background.a < 255)
1224 int x1 = surface.box.left;
1225 int y1 = surface.box.top;
1226 int x2 = surface.box.right;
1227 int y2 = surface.box.bottom;
1228 XRenderColor renderColor =
1230 (uint16)(xSurface.background.color.r * xSurface.background.a),
1231 (uint16)(xSurface.background.color.g * xSurface.background.a),
1232 (uint16)(xSurface.background.color.b * xSurface.background.a),
1233 (uint16)(xSurface.background.a * 255)
1235 x1 += surface.offset.x;
1236 y1 += surface.offset.y;
1237 x2 += surface.offset.x;
1238 y2 += surface.offset.y;
1239 XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.picture, &renderColor, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1);
1242 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1246 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
1251 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1253 bool result = false;
1254 XBitmap xBitmap = bitmap.driverData = XBitmap { };
1259 switch(GetColorDepthShifts(format))
1261 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
1262 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
1263 case 2: stride = width; break;
1267 bitmap.stride = stride;
1268 bitmap.width = width;
1269 bitmap.height = height;
1270 bitmap.size = (uint)stride * (uint)height;
1271 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
1272 bitmap.pixelFormat = format;
1273 bitmap.transparent = false;
1274 bitmap.allocatePalette = allocatePalette;
1277 bitmap.palette = new ColorAlpha[256];
1279 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
1282 bitmap.palette = GetDefaultPalette();
1287 FreeBitmap(displaySystem, bitmap);
1293 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1295 XDisplay xDisplay = display.driverData;
1296 XSurface xSurface = surface.driverData;
1297 XBitmap xBitmap = src.driverData;
1301 if(!ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1304 dx += surface.offset.x;
1305 dy += surface.offset.y;
1307 if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1309 XSetClipMask(xGlobalDisplay, xDisplay.gc, xBitmap.mask);
1310 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx - sx, dy - sy);
1312 if(xSurface.xOffset)
1314 XTransform transform =
1317 { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), -(xSurface.xOffset << 10) },
1318 { (int)(0.0f), (int)(-1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1319 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1322 // printf("XOffset: %d\n", xSurface.xOffset);
1323 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1326 if(src.alphaBlend || display.alphaBlend)
1328 if(src.pixelFormat == pixelFormatAlpha)
1330 XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w + (xSurface.xOffset ? 1 : 1), h);
1332 else if(src.alphaBlend)
1333 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1335 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1338 XCopyArea(xGlobalDisplay, (Pixmap)xBitmap.pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc,
1339 sx, sy, w, h, dx, dy);
1341 if(xSurface.xOffset)
1343 XTransform identity =
1346 { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1347 { (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1348 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1351 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1353 if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1355 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1357 XRectangle rectangle;
1359 rectangle.x = (short)(surface.unclippedBox.left + surface.offset.x);
1360 rectangle.y = (short)(surface.unclippedBox.top + surface.offset.y);
1361 rectangle.width = (short)(surface.unclippedBox.right - surface.unclippedBox.left + 1);
1362 rectangle.height = (short)(surface.unclippedBox.bottom - surface.unclippedBox.top + 1);
1364 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1370 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1372 XSurface xSurface = surface.driverData;
1373 XBitmap xBitmap = src.driverData;
1376 XTransform transform =
1379 { (int)((float)sw / w * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1380 { (int)(0.0f * (1<<16)), (int)((float)sh / h * (1<<16)), (int)(0.0f * (1<<16)) },
1381 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1384 XTransform identity =
1387 { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1388 { (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1389 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1392 dx += surface.offset.x;
1393 dy += surface.offset.y;
1395 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1397 if(src.pixelFormat == pixelFormatAlpha)
1398 XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w, h);
1399 else if(src.alphaBlend)
1400 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1403 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.maskPicture, &transform);
1404 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1405 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.maskPicture, &identity);
1407 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1411 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1413 XBitmap xBitmap = src.driverData;
1416 XRenderSetPictureFilter(xGlobalDisplay, xBitmap.picture, "bilinear", null, 0);
1417 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
1418 XRenderSetPictureFilter(xGlobalDisplay, xBitmap.picture, "nearest", null, 0);
1422 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1424 XImage image = { 0 };
1425 XDisplay xDisplay = display ? display.driverData : null;
1426 XSurface xSurface = surface.driverData;
1429 if(!xDisplay || !src.picture || !ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1432 if(src.pixelFormat == display.pixelFormat)
1434 image.width = src.width;
1435 image.height = src.height;
1436 image.depth = (src.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1437 image.bitmap_pad = (src.pixelFormat == pixelFormat888) ? 32 : 16;
1438 image.format = ZPixmap;
1439 image.bitmap_unit = 8;
1440 image.bytes_per_line = ((src.pixelFormat == pixelFormat888) ? 4 : 2) * src.stride;
1441 image.bits_per_pixel = (src.pixelFormat == pixelFormat888) ? 32 : 16;
1443 image.data = (char *)src.picture;
1446 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1447 sx, sy, dx + surface.offset.x, dy + surface.offset.y, w,h);
1453 temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1454 s = temp.GetSurface(0,0,null);
1455 s.Blit(src, 0,0, sx,sy, flip ? -w : w, h);
1459 image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1460 image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1461 image.format = ZPixmap;
1462 image.bitmap_unit = 8;
1463 image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1464 image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1466 image.data = (char *)temp.picture;
1469 if(!src.transparent)
1471 // printf("Stride: %d, dx: %d, dy: %d, w: %d, h: %d, %d\n", temp.stride, dx + surface.offset.x, dy + surface.offset.y, w,h, xSystemDepth);
1472 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1473 0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1478 GC maskGC = 0, gc = 0;
1479 Pixmap pixmap, mask;
1481 pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1482 mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1484 gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1485 maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
1486 XSetGraphicsExposures(xGlobalDisplay, gc, False);
1487 XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
1489 XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1490 XSetForeground(xGlobalDisplay, maskGC, 0);
1491 XFillRectangle(xGlobalDisplay, mask, maskGC, 0, 0, w, h);
1492 XSetForeground(xGlobalDisplay, maskGC, 1);
1493 if(temp.pixelFormat == pixelFormat888)
1496 for(y = 0; y<h; y++)
1498 for(x = 0; x<w; x++)
1500 if(((ColorAlpha *)temp.picture)[y * temp.stride + x].a)
1501 XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1505 else if(src.pixelFormat == pixelFormat8)
1508 for(y = 0; y<h; y++)
1510 for(x = 0; x<w; x++)
1512 if(src.picture[(y + sy) * src.stride + (flip ? (w-1-(sx + x)) : (sx + x)])
1513 XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1520 for(y = 0; y<h; y++)
1522 for(x = 0; x<w; x++)
1524 if(((uint16 *)temp.picture)[y * temp.stride + x])
1525 XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1530 XFreeGC(xGlobalDisplay, maskGC);
1533 Pixmap pixmap, mask;
1535 pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1536 mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1538 gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1539 XSetGraphicsExposures(xGlobalDisplay, gc, False);
1541 XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1543 PutBitmapMask(mask, temp);
1546 XSetClipMask(xGlobalDisplay, xDisplay.gc, mask);
1547 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx + surface.offset.x, dy + surface.offset.y);
1548 XCopyArea(xGlobalDisplay, pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc, 0, 0, w, h, dx + surface.offset.x, dy + surface.offset.y);
1549 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1551 XRectangle rectangle;
1553 rectangle.x = (short)(surface.unclippedBox.left + surface.offset.x);
1554 rectangle.y = (short)(surface.unclippedBox.top + surface.offset.y);
1555 rectangle.width = (short)(surface.unclippedBox.right - surface.unclippedBox.left + 1);
1556 rectangle.height = (short)(surface.unclippedBox.bottom - surface.unclippedBox.top + 1);
1558 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1561 XFreeGC(xGlobalDisplay, gc);
1562 XFreePixmap(xGlobalDisplay, pixmap);
1563 XFreePixmap(xGlobalDisplay, mask);
1570 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1573 if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1575 XImage image = { 0 };
1576 XDisplay xDisplay = display.driverData;
1577 XSurface xSurface = surface.driverData;
1580 temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1581 s = temp.GetSurface(0,0,null);
1582 s.Stretch(src, 0,0, sx,sy, w, h, sw, sh);
1586 image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1587 image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1588 image.format = ZPixmap;
1589 image.bitmap_unit = 8;
1590 image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1591 image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1593 image.data = (char *)temp.picture;
1596 // printf("Blitting DI\n");
1597 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1598 0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1605 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1608 if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1610 XImage image = { 0 };
1611 XDisplay xDisplay = display.driverData;
1612 XSurface xSurface = surface.driverData;
1615 temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1616 s = temp.GetSurface(0,0,null);
1617 s.Filter(src, 0,0, sx,sy, w, h, sw, sh);
1621 image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1622 image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1623 image.format = ZPixmap;
1624 image.bitmap_unit = 8;
1625 image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1626 image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;;
1628 image.data = (char *)temp.picture;
1631 // printf("Blitting DI\n");
1632 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1633 0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1640 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
1643 font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
1647 void UnloadFont(DisplaySystem displaySystem, Font font)
1649 ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
1652 void TextFont(Display display, Surface surface, Font font)
1654 // XSurface xSurface = surface.driverData;
1655 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
1658 void TextOpacity(Display display, Surface surface, bool opaque)
1660 XSurface xSurface = surface.driverData;
1661 xSurface.opaque = opaque;
1664 #define CHAR_WIDTH 6
1665 #define CHAR_HEIGHT 14
1667 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
1669 XSurface xSurface = surface.driverData;
1670 //XDisplay xDisplay = display.driverData;
1673 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, &tw, &th);
1677 XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.background);
1679 XFillRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1680 x + surface.offset.x, y + surface.offset.y,
1681 tw /*len * CHAR_WIDTH*/, th /*CHAR_HEIGHT*/);
1683 XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.foreground);
1686 XRenderColor renderColor =
1688 (uint16)(xSurface.background.color.r * xSurface.background.a),
1689 (uint16)(xSurface.background.color.g * xSurface.background.a),
1690 (uint16)(xSurface.background.color.b * xSurface.background.a),
1691 (uint16)xSurface.background.a
1693 //printf("Filling rectangle\n");
1694 XRenderFillRectangle(xGlobalDisplay, PictOpSrc /*PictOpOver*/, xSurface.picture, &renderColor,
1695 x + surface.offset.x, y + surface.offset.y, tw, th);
1698 XDrawString(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1699 x + surface.offset.x, y + surface.offset.y + 12, text, len);
1702 ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
1705 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
1707 XSurface xSurface = surface.driverData;
1710 for(realLen = 0; realLen<len && text[realLen]; realLen++);
1711 if(width) *width = len * CHAR_WIDTH;
1712 if(height) *height = CHAR_HEIGHT;
1715 FontExtent(display.displaySystem, xSurface.font, text, len, width, height);
1718 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
1721 if(width) *width = len * CHAR_WIDTH;
1722 if(height) *height = CHAR_HEIGHT;
1724 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height);
1727 void DrawingChar(Display display, Surface surface, byte character)
1732 void LineStipple(Display display, Surface surface, uint stipple)
1734 XDisplay xDisplay = display.driverData;
1735 char list[32] = { 0 };
1744 for(c = 0; c<32; c++)
1746 if((stipple & 0x8000) == on)
1761 XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineOnOffDash, CapButt, JoinMiter);
1762 XSetDashes(xGlobalDisplay, xDisplay.gc, offset, list, count);
1768 XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineSolid, CapButt, JoinMiter);
1769 XSetDashes(xGlobalDisplay, xDisplay.gc, 0, list, count);
1773 bool Lock(Display display)
1775 //XLockDisplay(xGlobalDisplay);
1779 void Unlock(Display display)
1781 //XUnlockDisplay(xGlobalDisplay);
1784 void StartUpdate(Display display)
1789 void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1794 void Update(Display display, Box updateBox)
1796 XDisplay xDisplay = display.driverData;
1797 Box * box = (updateBox != null) ? updateBox : &xDisplay.updateBox;
1800 XRectangle rectangle;
1803 rectangle.width = (uint16)display.width;
1804 rectangle.height = (uint16)display.height;
1805 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1807 /*if(display.alphaBlend)
1808 XRenderComposite(xGlobalDisplay, PictOpSrc, xDisplay.picture, None, xDisplay.windowPicture, box->left, box->top, 0, 0, box->left, box->top,
1809 box->right - box->left + 1, box->bottom - box->top + 1);
1811 XCopyArea(xGlobalDisplay, (Pixmap)xDisplay.pixmap, (X11Window)display.window, xDisplay.gc /*windowGC*/,
1812 box->left, box->top,
1813 box->right - box->left + 1,
1814 box->bottom - box->top + 1,
1815 box->left, box->top);
1817 if(display.alphaBlend)
1819 Box * box = &xDisplay.updateBox;
1820 XRenderComposite(xGlobalDisplay, PictOpSrc, xDisplay.picture, None, xDisplay.shapePicture, box->left, box->top, 0, 0, box->left, box->top,
1821 box->right - box->left + 1, box->bottom - box->top + 1);
1822 #if !defined(__APPLE__) && !defined(__OLDX__)
1823 XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, xDisplay.shapePixmap, ShapeSet);
1825 XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, 2, 0, 0, xDisplay.shapePixmap, ShapeSet);
1829 XFlush(xGlobalDisplay);
1830 if(updateBox == null)
1832 xDisplay.updateBox.left = display.width;
1833 xDisplay.updateBox.top = display.height;
1834 xDisplay.updateBox.right = 0;
1835 xDisplay.updateBox.bottom = 0;
1839 void EndUpdate(Display display)
1845 default dllexport long IS_XGetPixmap(Bitmap bitmap)
1847 XBitmap xBitmap = bitmap.driverData;
1848 return xBitmap.pixmap;
1851 default dllexport void IS_XGetSurfaceInfo(Surface surface, Pixmap * pixmap, GC * gc, int *x, int * y)
1853 Display display = surface.display;
1854 XDisplay xDisplay = display.driverData;
1856 *pixmap = xDisplay.pixmap;
1858 *x = surface.offset.x;
1859 *y = surface.offset.y;