1 namespace gfx::drivers;
3 // Enable to work around some Linux drivers not supporting PictStandardA8 format properly
4 #define ENABLE_XRENDER_WORK_AROUND
8 #if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
12 #define property _property
17 #define Window X11Window
18 #define Cursor X11Cursor
20 #define Display X11Display
22 #define KeyCode X11KeyCode
23 #define Picture X11Picture
24 #define Glyph X11Glyph
27 #include <X11/Xutil.h>
28 #include <X11/extensions/shape.h>
29 #include <X11/extensions/Xrender.h>
30 #include <X11/extensions/XShm.h>
54 static byte defaultRGBLookup[32768];
55 bool rgbLookupSet = false;
57 class XDisplay : LFBDisplay //struct
65 X11Picture shapePicture;
66 XShmSegmentInfo shminfo;
68 XShmSegmentInfo shminfoShape;
72 class XSurface : struct
80 ColorAlpha foreground, background;
85 X11Picture colorPicture;
89 class XBitmap : struct
94 X11Picture maskPicture;
95 #ifdef ENABLE_XRENDER_WORK_AROUND
100 XRenderPictFormat * GetXRenderFormat(PixelFormat pixelFormat, bool alphaBlend)
102 XRenderPictFormat * format = null;
105 case pixelFormatAlpha:
106 format = XRenderFindStandardFormat(xGlobalDisplay, PictStandardA8);
109 format = XRenderFindStandardFormat(xGlobalDisplay, alphaBlend ? PictStandardARGB32 : PictStandardRGB24);
110 // printf("R: %d G: %d B: %d\n", format->direct.red, format->direct.green, format->direct.blue);
114 XRenderPictFormat info = { 0 };
117 info.type = PictTypeDirect;
118 info.direct.red = 10;
119 info.direct.green = 5;
120 info.direct.blue = 0;
121 info.direct.redMask = 0x1F;
122 info.direct.greenMask = 0x1F;
123 info.direct.blueMask = 0x1F;
125 format = XRenderFindFormat(xGlobalDisplay,
126 /*PictFormatDepth|*/PictFormatType| PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
127 PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
132 XRenderPictFormat info = { 0 };
135 info.type = PictTypeDirect;
136 info.direct.alpha = 0;
137 info.direct.red = 11;
138 info.direct.green = 5;
139 info.direct.blue = 0;
140 info.direct.redMask = 0x1F;
141 info.direct.greenMask = 0x3F;
142 info.direct.blueMask = 0x1F;
143 info.direct.alphaMask = 0;
146 format = XRenderFindFormat(xGlobalDisplay,
147 /*PictFormatDepth|*/PictFormatType|PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
148 PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
155 static bool ClipBlitCoords(Surface surface, Bitmap src, int *dx, int *dy, int *sx, int *sy, int *w, int *h, bool * flip)
159 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top) return false;
161 if(*w < 0) { *w = -*w; *flip = true; }
163 //Clip against the edges of the source
176 if(*sx+*w>src.width-1)
177 *w-=*sx+*w-(src.width-1)-1;
178 if(*sy+*h>src.height-1)
179 *h-=*sy+*h-(src.height-1)-1;
180 //Clip against the edges of the destination
181 if(*dx<surface.box.left)
183 if(!*flip) *sx+=surface.box.left-*dx;
184 *w-=surface.box.left-*dx;
185 *dx=surface.box.left;
187 if(*dy<surface.box.top)
189 *sy+=surface.box.top-*dy;
190 *h-=surface.box.top-*dy;
193 if((*dx+*w)>surface.box.right)
195 if(*flip) *sx+=(uint)(*dx+*w)-surface.box.right-1;
196 *w-=((uint)(*dx+*w)-surface.box.right-1);
198 if((*dy+*h)>surface.box.bottom)
199 *h-=((*dy+*h)-surface.box.bottom-1);
205 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)
207 float s2dw,s2dh,d2sw,d2sh;
210 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return false;
212 if(Sgn(*w) != Sgn(*sw))
219 s2dw=(float)*w / *sw;
220 s2dh=(float)*h / *sh;
221 d2sw=(float)*sw / *w;
222 d2sh=(float)*sh / *h;
224 //Clip against the edges of the source
227 *dx += (int)((0-*sx) * s2dw);
228 *w -= (int)((0-*sx) * s2dw);
234 *dy += (int)((0-*sy) * s2dh);
235 *h -= (int)((0-*sy) * s2dh);
240 if(*sx+*sw>src.width-1)
242 *w-=(int)((*sx+*sw-(src.width-1)-1)*s2dw);
243 *sw-=*sx+*sw-(src.width-1)-1;
245 if(*sy+*sh>(src.height-1))
247 *h-=(int)((*sy+*sh-(src.height-1)-1)*s2dh);
248 *sh-=*sy+*sh-(src.height-1)-1;
250 //Clip against the edges of the destination
251 if(*dx < surface.box.left)
253 if(!*flip) *sx += (int)((surface.box.left-*dx)*d2sw);
254 *sw-=(int)((surface.box.left-*dx)*d2sw);
255 *w-=surface.box.left-*dx;
256 *dx=surface.box.left;
258 if(*dy < surface.box.top)
260 *sy += (int)((surface.box.top-*dy)*d2sh);
261 *sh -= (int)((surface.box.top-*dy)*d2sh);
262 *h -= surface.box.top-*dy;
263 *dy =surface.box.top;
265 if((*dx+*w)>surface.box.right)
267 if(*flip) *sx+=(int)(((*dx+*w)-surface.box.right-1)*d2sw);
268 *sw-=(int)(((*dx + *w)-surface.box.right-1)*d2sw);
269 *w-=((*dx+*w)-surface.box.right-1);
271 if((*dy+*h)>surface.box.bottom)
273 *sh-=(int)(((*dy+*h)-surface.box.bottom-1)*d2sh);
274 *h-=((*dy+*h)-surface.box.bottom-1);
276 if((*w<=0)||(*h<=0)||(*sw<=0)||(*sh<=0))
281 static void PutBitmapMask(Pixmap mask, Bitmap bitmap) {
283 GC maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
284 uint wordWidth = (bitmap.width+31) >> 5;
287 uint32 *b = new0 uint32[wordWidth * bitmap.height];
290 XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
292 image.width = bitmap.width;
293 image.height = bitmap.height;
295 image.format = XYBitmap;
296 #ifdef __BIG_ENDIAN__
297 image.byte_order = MSBFirst;
299 image.byte_order = LSBFirst;
301 image.bitmap_unit = 32;
302 image.bitmap_bit_order = LSBFirst;
303 image.bitmap_pad = 32;
305 image.bytes_per_line = wordWidth << 2;
307 image.data = (char*)b;
311 switch(bitmap.pixelFormat) {
316 byte *p = (byte*)bitmap.picture;
318 for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
319 for(x = 0; x<bitmap.width; x++) {
321 *b |= f; //XPutPixel(&image, x,y, 1);
331 case pixelFormat565: {
332 uint16 *p = (uint16*)bitmap.picture;
334 PrintLn(bitmap.pixelFormat);
336 for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
337 for(x = 0; x<bitmap.width; x++) {
339 *b |= f; //XPutPixel(&image, x,y, 1);
347 case pixelFormat888: {
348 ColorAlpha *p = (ColorAlpha*)bitmap.picture;
349 for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
350 for(x = 0; x<bitmap.width; x++) {
352 *b |= f; //XPutPixel(&image, x,y, 1);
360 case pixelFormatAlpha: {
363 case pixelFormatText: {
366 case pixelFormatRGBA: {
371 XSetForeground(xGlobalDisplay, maskGC, 1);
372 XSetBackground(xGlobalDisplay, maskGC, 0);
374 XPutImage(xGlobalDisplay, mask, maskGC, &image,
375 0, 0, 0, 0, //coordinates
376 bitmap.width, bitmap.height);
378 XFreeGC(xGlobalDisplay, maskGC);
382 class XDisplayDriver : DisplayDriver
384 class_property(name) = "X";
386 bool CreateDisplaySystem(DisplaySystem displaySystem)
388 //displaySystem.driverData = calloc(1, sizeof(LFBSystem));
389 displaySystem.flags.memBackBuffer = true;
390 displaySystem.pixelFormat = xSystemPixelFormat;
394 void DestroyDisplaySystem(DisplaySystem displaySystem)
396 // delete displaySystem.driverData;
399 void DestroyDisplay(Display display)
401 XDisplay xDisplay = display.driverData;
403 // Free Shared Memory Pixmap
404 if(xDisplay.shapePixmap)
405 XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
407 XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
410 if(xDisplay.shminfoShape.shmid != -1)
412 XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
413 if(xDisplay.shminfo.shmaddr != (void *)-1)
414 shmdt(xDisplay.shminfo.shmaddr);
415 shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
418 if(xDisplay.shapeImage)
420 if(xDisplay.shminfoShape.shmid != -1)
422 XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
423 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
424 shmdt(xDisplay.shminfoShape.shmaddr);
425 shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
427 XDestroyImage(xDisplay.shapeImage);
428 xDisplay.shapeImage = None;
431 XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
432 if(xDisplay.shapePicture)
433 XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
434 if(xDisplay.windowGC)
435 XFreeGC(xGlobalDisplay, xDisplay.windowGC);
437 XFreeGC(xGlobalDisplay, xDisplay.gc);
439 display.driverData = null;
442 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
448 bool CreateDisplay(Display display)
451 XDisplay xDisplay = display.driverData = XDisplay { };
455 xDisplay.windowGC = XCreateGC(xGlobalDisplay, (X11Window)display.window, 0, null);
456 XSetGraphicsExposures(xGlobalDisplay, xDisplay.windowGC, False);
462 bool DisplaySize(Display display, int width, int height)
464 XDisplay xDisplay = display.driverData;
467 if(width > display.width || height > display.height)
469 display.width = width;
470 display.height = height;
473 XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
476 XRenderPictureAttributes attributes = { 0 };
477 XRenderPictFormat * format = GetXRenderFormat(xSystemPixelFormat, display.alphaBlend);
478 attributes.component_alpha = 1;
479 attributes.poly_mode = PolyModeImprecise;
480 attributes.poly_edge = PolyEdgeSmooth;
484 XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
485 xDisplay.pixmap = None;
487 if(xDisplay.shapePixmap)
489 XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
490 xDisplay.shapePixmap = None;
493 // Free Shared Memory Pixmap
496 if(xDisplay.shminfoShape.shmid != -1)
498 XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
499 if(xDisplay.shminfo.shmaddr != (void *)-1)
500 shmdt(xDisplay.shminfo.shmaddr);
501 shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
503 XDestroyImage(xDisplay.image);
504 xDisplay.image = None;
506 if(xDisplay.shapeImage)
508 if(xDisplay.shminfoShape.shmid != -1)
510 XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
511 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
512 shmdt(xDisplay.shminfoShape.shmaddr);
513 shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
515 XDestroyImage(xDisplay.shapeImage);
516 xDisplay.shapeImage = None;
519 // Initialize Shared Memory Pixmap
521 if(xSharedMemory && display.useSharedMemory && format)
524 printf("Using shared memory!\n");
526 xDisplay.image = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
527 format->depth, ZPixmap, null, &xDisplay.shminfo, width, height);
529 else if(display.useSharedMemory && !xSharedMemory)
530 printf("%s", $"Error: Requested shared memory but shared memory pixmaps are not supported by X server.\n");
534 memset(&xDisplay.shminfo, 0, sizeof(XShmSegmentInfo));
535 // printf("shmget: %d\n", xDisplay.image->bytes_per_line * xDisplay.image->height);
536 xDisplay.shminfo.shmid = shmget(IPC_PRIVATE, xDisplay.image->bytes_per_line * xDisplay.image->height, IPC_CREAT|0777);
537 if(xDisplay.shminfo.shmid != -1)
539 xDisplay.shminfo.shmaddr = shmat(xDisplay.shminfo.shmid, 0, 0);
540 if(xDisplay.shminfo.shmaddr != (void *)-1)
542 // printf("%d, %d\n", xDisplay.shminfo.shmid, xDisplay.shminfo.shmaddr);
543 xDisplay.shminfo.readOnly = False;
544 if(XShmAttach(xGlobalDisplay, &xDisplay.shminfo))
546 xDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfo.shmaddr, &xDisplay.shminfo, width, height, format->depth);
548 xDisplay.bitmap.width = width;
549 xDisplay.bitmap.height = height;
550 xDisplay.bitmap.stride = xDisplay.image->bytes_per_line >> GetColorDepthShifts(display.pixelFormat);
551 xDisplay.bitmap.pixelFormat = display.pixelFormat;
552 xDisplay.bitmap.picture = (byte *)xDisplay.shminfo.shmaddr;
553 xDisplay.bitmap.size = width * height;
554 xDisplay.bitmap.sizeBytes = (uint)xDisplay.bitmap.size << GetColorDepthShifts(display.pixelFormat);
560 if(xDisplay.shminfo.shmid != -1)
562 XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
563 if(xDisplay.shminfo.shmaddr != (void *)-1)
564 shmdt(xDisplay.shminfo.shmaddr);
565 shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
567 XDestroyImage(xDisplay.image);
568 xDisplay.image = None;
573 // Initialize Shared Memory Shape Pixmap
574 if(xSharedMemory && display.useSharedMemory && display.alphaBlend)
575 xDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
576 1, ZPixmap, null, &xDisplay.shminfoShape, width, height);
578 if(xDisplay.shapeImage)
580 xDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE, xDisplay.shapeImage->bytes_per_line * xDisplay.shapeImage->height, IPC_CREAT|0777);
581 if(xDisplay.shminfoShape.shmid != -1)
583 xDisplay.shminfoShape.shmaddr = shmat(xDisplay.shminfoShape.shmid, 0, 0);
584 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
586 xDisplay.shminfoShape.readOnly = False;
587 if(XShmAttach(xGlobalDisplay, &xDisplay.shminfoShape))
589 xDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfoShape.shmaddr, &xDisplay.shminfoShape, width, height, 1);
593 if(!xDisplay.shapePixmap)
595 if(xDisplay.shminfoShape.shmid != -1)
597 XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
598 if(xDisplay.shminfoShape.shmaddr != (void *)-1)
599 shmdt(xDisplay.shminfoShape.shmaddr);
600 shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
602 XDestroyImage(xDisplay.shapeImage);
603 xDisplay.shapeImage = None;
607 if(!xDisplay.pixmap && format)
608 xDisplay.pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, format->depth);
609 if(display.alphaBlend && !xDisplay.shapePixmap)
610 xDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
613 xDisplay.gc = XCreateGC(xGlobalDisplay, (Pixmap)xDisplay.pixmap, 0, null);
614 XSetGraphicsExposures(xGlobalDisplay, xDisplay.gc, False);
618 xDisplay.picture = XRenderCreatePicture(xGlobalDisplay, xDisplay.pixmap, format, CPComponentAlpha, &attributes);
620 if(display.alphaBlend)
621 xDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, xDisplay.shapePixmap, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
624 xDisplay.updateBox.left = display.width;
625 xDisplay.updateBox.top = display.height;
626 xDisplay.updateBox.right = 0;
627 xDisplay.updateBox.bottom = 0;
633 void DisplayPosition(Display display, int x, int y)
635 XDisplay xDisplay = display.driverData;
636 xDisplay.offset.x = x;
637 xDisplay.offset.y = y;
640 void RestorePalette(Display display)
645 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
647 XBitmap xBitmap = bitmap.driverData;
651 XFreePixmap(xGlobalDisplay, xBitmap.pixmap);
653 XFreePixmap(xGlobalDisplay, xBitmap.mask);
655 XRenderFreePicture(xGlobalDisplay, xBitmap.picture);
656 if(xBitmap.maskPicture)
657 XRenderFreePicture(xGlobalDisplay, xBitmap.maskPicture);
659 bitmap.driverData = null;
661 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
664 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps, int cubeMapFace)
666 //XDisplay xDisplay = display.driverData;
668 XImage image = { 0 };
671 #ifdef ENABLE_XRENDER_WORK_AROUND
672 if(bitmap.pixelFormat == pixelFormatAlpha)
674 xBitmap.alphaTweak = true;
675 bitmap.alphaBlend = true;
678 if(bitmap.pixelFormat != pixelFormatAlpha)
680 bitmap.Convert(null, bitmap.alphaBlend ? pixelFormat888 : xSystemPixelFormat, null);
682 //bitmap.Convert(null, pixelFormatRGBA, null);
683 //bitmap.Convert(null, pixelFormat888, null);
685 XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height,
686 (bitmap.pixelFormat == pixelFormatAlpha) ? 8 : (bitmap.alphaBlend ? 32 : ((bitmap.pixelFormat == pixelFormat888) ? 24 : xSystemDepth)));
687 if(bitmap.transparent)
689 XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height, 1);
692 XRenderPictureAttributes attributes = { 0 };
693 XRenderPictFormat * format = GetXRenderFormat(bitmap.pixelFormat, bitmap.alphaBlend);
694 attributes.component_alpha = 1;
697 xBitmap.picture = XRenderCreatePicture(xGlobalDisplay, xBitmap.pixmap, format, CPComponentAlpha, &attributes);
698 if(bitmap.transparent && bitmap.pixelFormat != pixelFormatAlpha)
699 xBitmap.maskPicture = XRenderCreatePicture(xGlobalDisplay, xBitmap.mask, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), CPComponentAlpha, &attributes);
702 gc = XCreateGC(xGlobalDisplay, (Pixmap)xBitmap.pixmap, 0, null);
704 XSetGraphicsExposures(xGlobalDisplay, gc, False);
706 image.width = bitmap.width;
707 image.height = bitmap.height;
709 if(bitmap.pixelFormat == pixelFormatAlpha)
712 image.bitmap_pad = 8;
713 image.bytes_per_line = bitmap.stride;
714 image.bits_per_pixel = 8;
718 image.depth = bitmap.alphaBlend ? 32 : ((bitmap.pixelFormat == pixelFormat888) ? 24 : xSystemDepth);
719 image.bitmap_pad = (bitmap.pixelFormat == pixelFormat888) ? 32 : 16;
720 image.bytes_per_line = ((bitmap.pixelFormat == pixelFormat888) ? 4 : 2) * bitmap.stride;
721 image.bits_per_pixel = (bitmap.pixelFormat == pixelFormat888) ? 32 : 16;
724 image.format = ZPixmap;
725 //image.bitmap_bit_order = MSBFirst;
726 #ifdef __BIG_ENDIAN__
727 image.byte_order = MSBFirst;
729 image.bitmap_unit = 8;
731 image.red_mask = 0xF800;
732 image.green_mask = 0x7E0;
733 image.blue_mask = 0x1F;
737 image.red_mask = 0x0000FF;
738 image.green_mask = 0x00FF00;
739 image.blue_mask = 0xFF0000;
741 // image.red_mask = 0xFFFF0000;
743 image.data = (char *)bitmap.picture;
746 if(bitmap.pixelFormat != pixelFormatAlpha && bitmap.alphaBlend)
749 for(y = 0; y<bitmap.height; y++)
751 for(x = 0; x<bitmap.width; x++)
753 ColorAlpha * p = ((ColorAlpha *)bitmap.picture) + y * bitmap.stride + x;
755 p->color.r = (byte)(p->color.r * alpha / 255);
756 p->color.g = (byte)(p->color.g * alpha / 255);
757 p->color.b = (byte)(p->color.b * alpha / 255);
762 XPutImage(xGlobalDisplay, (Pixmap)xBitmap.pixmap, gc, &image,
763 0, 0, 0, 0, bitmap.width,bitmap.height);
765 if(bitmap.transparent && !bitmap.alphaBlend && bitmap.pixelFormat != pixelFormatAlpha)
766 PutBitmapMask(xBitmap.mask, bitmap);
768 XFreeGC(xGlobalDisplay, gc);
771 delete bitmap.picture;
773 bitmap.driverData = xBitmap;
774 bitmap.driver = displaySystem.driver;
778 void ReleaseSurface(Display display, Surface surface)
780 XSurface xSurface = surface.driverData;
781 XDisplay xDisplay = display ? display.driverData : null;
782 XRectangle rectangle;
784 if(xSurface.colorPicture)
785 XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
791 rectangle.width = (uint16)display.width;
792 rectangle.height = (uint16)display.height;
793 XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
796 if(xSurface.colorPixmap)
797 XFreePixmap(xGlobalDisplay, xSurface.colorPixmap);
802 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
805 XBitmap xBitmap = bitmap.driverData;
808 if((surface.driverData = xSurface = XSurface { }))
810 surface.offset.x = x;
811 surface.offset.y = y;
812 surface.unclippedBox = surface.box = clip;
814 xSurface.pixmap = xBitmap.pixmap;
821 bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
824 XDisplay xDisplay = display.driverData;
826 if((surface.driverData = xSurface = XSurface { }))
828 XRectangle rectangle;
830 surface.offset.x = x;
831 surface.offset.y = y;
832 surface.unclippedBox = surface.box = clip;
833 xSurface.pixmap = xDisplay.pixmap;
834 xSurface.picture = xDisplay.picture;
836 xSurface.colorPixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, 1, 1, /*(xSystemDepth == 16) ? 16 : */32);
838 rectangle.x = (short)(clip.left + x);
839 rectangle.y = (short)(clip.top + y);
840 rectangle.width = (short)(clip.right - clip.left + 1);
841 rectangle.height = (short)(clip.bottom - clip.top + 1);
843 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
844 XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
846 xDisplay.updateBox.left = Min(x + clip.left, xDisplay.updateBox.left);
847 xDisplay.updateBox.top = Min(y + clip.top, xDisplay.updateBox.top);
848 xDisplay.updateBox.right = Max(x + clip.right, xDisplay.updateBox.right);
849 xDisplay.updateBox.bottom = Max(y + clip.bottom, xDisplay.updateBox.bottom);
856 void Clip(Display display, Surface surface, Box clip)
858 XSurface xSurface = surface.driverData;
859 XDisplay xDisplay = display.driverData;
860 bool changed = false;
865 box.Clip(surface.unclippedBox);
869 xSurface.clipped = true;
872 else if(xSurface.clipped)
874 surface.box = surface.unclippedBox;
875 xSurface.clipped = false;
880 XRectangle rectangle =
882 (short)(surface.box.left + surface.offset.x),
883 (short)(surface.box.top + surface.offset.y),
884 (short)(surface.box.right - surface.box.left + 1),
885 (short)(surface.box.bottom - surface.box.top + 1)
887 XSetClipRectangles(xGlobalDisplay, xDisplay.gc,
888 0,0, &rectangle, 1, YXBanded);
892 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
895 XDisplay xDisplay = display ? display.driverData : null;
897 PixelFormat format = pixelFormat888;
917 if(sx+sw>display.width-1)
918 sw-=sx+sw-(display.width-1)-1;
919 if(sy+sh>display.height-1)
920 sh-=sy+sh-(display.height-1)-1;
924 xImage = XGetImage(xGlobalDisplay, xDisplay.pixmap, sx, sy, sw, sh, MAXDWORD, ZPixmap);
926 xImage = XGetImage(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), sx, sy, sw, sh, MAXDWORD, ZPixmap);
928 source.pixelFormat = format;
929 source.picture = (byte *)xImage->data;
932 source.stride = xImage->bytes_per_line / 4;
934 if(!bitmap || bitmap.pixelFormat != format || bitmap.width < w || bitmap.height < h)
937 bitmap.Allocate(null, w,h,w, format, (format == pixelFormat8)?true:false);
941 Surface surface = bitmap.GetSurface(0, 0, null);
942 surface.Blit(source, dx,dy,0,0,sw,sh);
946 source.picture = null;
949 XDestroyImage(xImage);
953 void SetForeground(Display display, Surface surface, ColorAlpha color)
955 XSurface xSurface = surface.driverData;
956 XDisplay xDisplay = display ? display.driverData : null;
957 XRenderColor renderColor = { (uint16)(color.color.r * color.a), (uint16)(color.color.g * color.a), (uint16)(color.color.b * color.a), (uint16)(color.a * 255) };
959 if(xSurface.colorPicture)
960 XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
961 // xSurface.colorPicture = XRenderCreateSolidFill(xGlobalDisplay, &renderColor);
964 XRenderPictureAttributes attributes = { 0 };
965 // XRenderPictFormat * format = myXRenderFindStandardFormat(xGlobalDisplay, PictStandardARGB32 /*PictStandardRGB24 /*PictStandardARGB32*/, 1);
966 XRenderPictFormat * format = /*(xSystemPixelFormat != pixelFormat888) ? GetXRenderFormat(xSystemPixelFormat, false) : */XRenderFindStandardFormat(xGlobalDisplay, PictStandardARGB32);
967 #if !defined(__APPLE__) && !defined(__OLDX__)
968 attributes.repeat = RepeatNormal;
970 attributes.repeat = 1;
972 ///attributes.component_alpha = 0;
974 xSurface.colorPicture = XRenderCreatePicture(xGlobalDisplay, xSurface.colorPixmap, format, /*CPComponentAlpha | */CPRepeat, &attributes);
975 XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.colorPicture, &renderColor, 0, 0, 1, 1);
978 // xSurface.foreground = ARGB(A(color),B(color),G(color),R(color));
979 xSurface.foreground = color;
982 XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
983 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
986 void SetBackground(Display display, Surface surface, ColorAlpha color)
988 XSurface xSurface = surface.driverData;
989 XDisplay xDisplay = display ? display.driverData : null;
990 // xSurface.background = ARGB(A(color),B(color),G(color),R(color));
991 xSurface.background = color;
994 XSetBackground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
995 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
998 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1003 void PutPixel(Display display, Surface surface,int x,int y)
1005 XSurface xSurface = surface.driverData;
1006 XDisplay xDisplay = display.driverData;
1008 if(xSurface.foreground.a < 255)
1009 DrawLine(display, surface, x,y,x,y);
1011 XDrawPoint(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1012 x + surface.offset.x,
1013 y + surface.offset.y);
1016 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1018 XDisplay xDisplay = display ? display.driverData : null;
1019 XSurface xSurface = surface.driverData;
1020 if(!xDisplay || xSurface.foreground.a < 255)
1022 XTrapezoid traps[3];
1024 double offset = 0.5;
1027 x1 += surface.offset.x;
1028 y1 += surface.offset.y;
1029 x2 += surface.offset.x;
1030 y2 += surface.offset.y;
1039 XDoubleToFixed(y1 - width + offset), XDoubleToFixed(y1 + width + offset),
1040 { { XDoubleToFixed(Min(x1, x2) - 0 + offset), XDoubleToFixed(y1 - width + offset) }, { XDoubleToFixed(Min(x1, x2) + 0.0 + offset), XDoubleToFixed(y1 + width+ offset) } },
1041 { { XDoubleToFixed(Max(x1, x2) - 0 + offset), XDoubleToFixed(y1 - width + offset) }, { XDoubleToFixed(Max(x1, x2) + 0.0 + offset), XDoubleToFixed(y1 + width+ offset) } }
1054 XDoubleToFixed(Min(y1, y2) - 0.0 + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset),
1055 { { XDoubleToFixed(x1 - width + offset), XDoubleToFixed(Min(y1, y2) - 0.0 + offset) }, { XDoubleToFixed(x1 - width + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset) } },
1056 { { XDoubleToFixed(x1 + width + offset), XDoubleToFixed(Min(y1, y2) - 0.0 + offset) }, { XDoubleToFixed(x1 + width + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset) } }
1065 Pointf A, B, C, D, E, F;
1078 l = sqrt(dx * dx + dy * dy);
1084 A = { (float)(x1 + dy * width), (float)(y1 - dx * width) };
1085 B = { (float)(x1 - dy * width), (float)(y1 + dx * width) };
1086 C = { (float)(A.x + ((B.y - A.y) * dx / dy)), B.y };
1087 E = { (float)(x2 + dy * width), (float)(y2 - dx * width) };
1088 F = { (float)(x2 - dy * width), (float)(y2 + dx * width) };
1089 D = { (float)(F.x + ((E.y - F.y) * dx / dy)), E.y };
1094 XDoubleToFixed(A.y + offset), XDoubleToFixed(B.y + offset),
1095 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) } },
1096 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) } }
1100 XDoubleToFixed(B.y + offset), XDoubleToFixed(D.y + offset),
1101 { { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) }, { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) } },
1102 { { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) }, { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) } }
1106 XDoubleToFixed(D.y + offset), XDoubleToFixed(F.y + offset),
1107 { { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } },
1108 { { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } }
1118 A = { (float)(x1 - dy * width), (float)(y1 + dx * width) };
1119 B = { (float)(x1 + dy * width), (float)(y1 - dx * width) };
1120 C = { (float)(A.x + ((B.y - A.y) * dx / dy)), B.y };
1121 E = { (float)(x2 - dy * width), (float)(y2 + dx * width) };
1122 F = { (float)(x2 + dy * width), (float)(y2 - dx * width) };
1123 D = { (float)(F.x + ((E.y - F.y) * dx / dy)), E.y };
1128 XDoubleToFixed(A.y + offset), XDoubleToFixed(B.y + offset),
1129 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) } },
1130 { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) } }
1134 XDoubleToFixed(B.y + offset), XDoubleToFixed(D.y + offset),
1135 { { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) }, { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) } },
1136 { { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) }, { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) } }
1140 XDoubleToFixed(D.y + offset), XDoubleToFixed(F.y + offset),
1141 { { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } },
1142 { { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } }
1151 printf("Line: (%d, %d)-(%d, %d)\n", x1,y1, x2,y2);
1152 printf("Line: A = (%.2f, %.2f), B = (%.2f, %.2f), C = (%.2f, %.2f)\n", A.x,A.y, B.x,B.y, C.x,C.y);
1153 printf("Line: D = (%.2f, %.2f), E = (%.2f, %.2f), F = (%.2f, %.2f)\n", D.x,D.y, E.x,E.y, F.x,F.y);
1154 printf("Trap1: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1155 traps[0].top / 65536.0, traps[0].bottom / 65536.0,
1156 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,
1157 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);
1158 printf("Trap2: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1159 traps[1].top / 65536.0, traps[1].bottom / 65536.0,
1160 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,
1161 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);
1162 printf("Trap3: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1163 traps[2].top / 65536.0, traps[2].bottom / 65536.0,
1164 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,
1165 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);
1169 XRenderCompositeTrapezoids(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xSurface.picture, None, 0, 0, traps, nTraps);
1172 XDrawLine(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1173 x1 + surface.offset.x,
1174 y1 + surface.offset.y,
1175 x2 + surface.offset.x,
1176 y2 + surface.offset.y);
1179 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1181 XDisplay xDisplay = display ? display.driverData : null;
1182 XSurface xSurface = surface.driverData;
1184 if(!xDisplay || xSurface.foreground.a < 255)
1186 DrawLine(display, surface,x1,y1,x2-1,y1);
1187 DrawLine(display, surface,x2,y1,x2,y2-1);
1188 DrawLine(display, surface,x1,y2,x2-1,y2);
1189 DrawLine(display, surface,x1,y1+1,x1,y2-1);
1192 XDrawRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1193 x1 + surface.offset.x,
1194 y1 + surface.offset.y,
1198 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1200 XDisplay xDisplay = display ? display.driverData : null;
1201 XSurface xSurface = surface.driverData;
1202 if(!xDisplay || xSurface.background.a < 255)
1204 XRenderColor renderColor =
1206 (uint16)(xSurface.background.color.r * xSurface.background.a),
1207 (uint16)(xSurface.background.color.g * xSurface.background.a),
1208 (uint16)(xSurface.background.color.b * xSurface.background.a),
1209 (uint16)(xSurface.background.a * 255)
1211 x1 += surface.offset.x;
1212 y1 += surface.offset.y;
1213 x2 += surface.offset.x;
1214 y2 += surface.offset.y;
1215 XRenderFillRectangle(xGlobalDisplay, PictOpOver, xSurface.picture, &renderColor, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1);
1219 XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
1220 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
1221 XFillRectangle(xGlobalDisplay, (Pixmap) xDisplay.pixmap, xDisplay.gc,
1222 x1 + surface.offset.x,
1223 y1 + surface.offset.y,
1224 x2 - x1 + 1, y2 - y1 + 1);
1225 XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
1226 ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
1230 void Clear(Display display, Surface surface, ClearType flags)
1232 if(flags != depthBuffer)
1234 // XDisplay xDisplay = display.driverData;
1235 XSurface xSurface = surface.driverData;
1236 if(xSurface.background.a < 255)
1238 int x1 = surface.box.left;
1239 int y1 = surface.box.top;
1240 int x2 = surface.box.right;
1241 int y2 = surface.box.bottom;
1242 XRenderColor renderColor =
1244 (uint16)(xSurface.background.color.r * xSurface.background.a),
1245 (uint16)(xSurface.background.color.g * xSurface.background.a),
1246 (uint16)(xSurface.background.color.b * xSurface.background.a),
1247 (uint16)(xSurface.background.a * 255)
1249 x1 += surface.offset.x;
1250 y1 += surface.offset.y;
1251 x2 += surface.offset.x;
1252 y2 += surface.offset.y;
1253 XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.picture, &renderColor, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1);
1256 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1260 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
1265 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1267 bool result = false;
1268 XBitmap xBitmap = bitmap.driverData = XBitmap { };
1273 switch(GetColorDepthShifts(format))
1275 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
1276 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
1277 case 2: stride = width; break;
1281 bitmap.stride = stride;
1282 bitmap.width = width;
1283 bitmap.height = height;
1284 bitmap.size = (uint)stride * (uint)height;
1285 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
1286 bitmap.pixelFormat = format;
1287 bitmap.transparent = false;
1288 bitmap.allocatePalette = allocatePalette;
1291 bitmap.palette = new ColorAlpha[256];
1293 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
1296 bitmap.palette = GetDefaultPalette();
1301 FreeBitmap(displaySystem, bitmap);
1307 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1309 XDisplay xDisplay = display.driverData;
1310 XSurface xSurface = surface.driverData;
1311 XBitmap xBitmap = src.driverData;
1315 if(!ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1318 dx += surface.offset.x;
1319 dy += surface.offset.y;
1321 if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1323 XSetClipMask(xGlobalDisplay, xDisplay.gc, xBitmap.mask);
1324 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx - sx, dy - sy);
1326 if(xSurface.xOffset)
1328 XTransform transform =
1331 { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), -(xSurface.xOffset << 10) },
1332 { (int)(0.0f), (int)(-1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1333 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1336 // printf("XOffset: %d\n", xSurface.xOffset);
1337 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1340 if(src.alphaBlend || display.alphaBlend)
1342 if(src.pixelFormat == pixelFormatAlpha
1343 #ifdef ENABLE_XRENDER_WORK_AROUND
1344 || xBitmap.alphaTweak
1348 XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w + (xSurface.xOffset ? 1 : 1), h);
1350 else if(src.alphaBlend)
1351 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1353 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1356 XCopyArea(xGlobalDisplay, (Pixmap)xBitmap.pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc,
1357 sx, sy, w, h, dx, dy);
1359 if(xSurface.xOffset)
1361 XTransform identity =
1364 { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1365 { (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1366 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1369 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1371 if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1373 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1375 XRectangle rectangle;
1377 rectangle.x = (short)(surface.unclippedBox.left + surface.offset.x);
1378 rectangle.y = (short)(surface.unclippedBox.top + surface.offset.y);
1379 rectangle.width = (short)(surface.unclippedBox.right - surface.unclippedBox.left + 1);
1380 rectangle.height = (short)(surface.unclippedBox.bottom - surface.unclippedBox.top + 1);
1382 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1388 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1390 XSurface xSurface = surface.driverData;
1391 XBitmap xBitmap = src.driverData;
1394 XTransform transform =
1397 { (int)((float)sw / w * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1398 { (int)(0.0f * (1<<16)), (int)((float)sh / h * (1<<16)), (int)(0.0f * (1<<16)) },
1399 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1402 XTransform identity =
1405 { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1406 { (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1407 { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1410 dx += surface.offset.x;
1411 dy += surface.offset.y;
1413 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1415 if(src.pixelFormat == pixelFormatAlpha
1416 #ifdef ENABLE_XRENDER_WORK_AROUND
1417 || xBitmap.alphaTweak
1420 XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w, h);
1421 else if(src.alphaBlend)
1422 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1425 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.maskPicture, &transform);
1426 XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1427 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.maskPicture, &identity);
1429 XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1433 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1435 XBitmap xBitmap = src.driverData;
1438 XRenderSetPictureFilter(xGlobalDisplay, xBitmap.picture, "bilinear", null, 0);
1439 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
1440 XRenderSetPictureFilter(xGlobalDisplay, xBitmap.picture, "nearest", null, 0);
1444 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1446 XImage image = { 0 };
1447 XDisplay xDisplay = display ? display.driverData : null;
1448 XSurface xSurface = surface.driverData;
1451 if(!xDisplay || !src.picture || !ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1454 if(src.pixelFormat == display.pixelFormat)
1456 image.width = src.width;
1457 image.height = src.height;
1458 image.depth = (src.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1459 image.bitmap_pad = (src.pixelFormat == pixelFormat888) ? 32 : 16;
1460 image.format = ZPixmap;
1461 image.bitmap_unit = 8;
1462 image.bytes_per_line = ((src.pixelFormat == pixelFormat888) ? 4 : 2) * src.stride;
1463 image.bits_per_pixel = (src.pixelFormat == pixelFormat888) ? 32 : 16;
1465 image.data = (char *)src.picture;
1468 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1469 sx, sy, dx + surface.offset.x, dy + surface.offset.y, w,h);
1475 temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1476 s = temp.GetSurface(0,0,null);
1477 s.Blit(src, 0,0, sx,sy, flip ? -w : w, h);
1481 image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1482 image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1483 image.format = ZPixmap;
1484 image.bitmap_unit = 8;
1485 image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1486 image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1488 image.data = (char *)temp.picture;
1491 if(!src.transparent)
1493 // 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);
1494 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1495 0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1500 GC maskGC = 0, gc = 0;
1501 Pixmap pixmap, mask;
1503 pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1504 mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1506 gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1507 maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
1508 XSetGraphicsExposures(xGlobalDisplay, gc, False);
1509 XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
1511 XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1512 XSetForeground(xGlobalDisplay, maskGC, 0);
1513 XFillRectangle(xGlobalDisplay, mask, maskGC, 0, 0, w, h);
1514 XSetForeground(xGlobalDisplay, maskGC, 1);
1515 if(temp.pixelFormat == pixelFormat888)
1518 for(y = 0; y<h; y++)
1520 for(x = 0; x<w; x++)
1522 if(((ColorAlpha *)temp.picture)[y * temp.stride + x].a)
1523 XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1527 else if(src.pixelFormat == pixelFormat8)
1530 for(y = 0; y<h; y++)
1532 for(x = 0; x<w; x++)
1534 if(src.picture[(y + sy) * src.stride + (flip ? (w-1-(sx + x)) : (sx + x)])
1535 XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1542 for(y = 0; y<h; y++)
1544 for(x = 0; x<w; x++)
1546 if(((uint16 *)temp.picture)[y * temp.stride + x])
1547 XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1552 XFreeGC(xGlobalDisplay, maskGC);
1555 Pixmap pixmap, mask;
1557 pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1558 mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1560 gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1561 XSetGraphicsExposures(xGlobalDisplay, gc, False);
1563 XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1565 PutBitmapMask(mask, temp);
1568 XSetClipMask(xGlobalDisplay, xDisplay.gc, mask);
1569 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx + surface.offset.x, dy + surface.offset.y);
1570 XCopyArea(xGlobalDisplay, pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc, 0, 0, w, h, dx + surface.offset.x, dy + surface.offset.y);
1571 XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1573 XRectangle rectangle;
1575 rectangle.x = (short)(surface.unclippedBox.left + surface.offset.x);
1576 rectangle.y = (short)(surface.unclippedBox.top + surface.offset.y);
1577 rectangle.width = (short)(surface.unclippedBox.right - surface.unclippedBox.left + 1);
1578 rectangle.height = (short)(surface.unclippedBox.bottom - surface.unclippedBox.top + 1);
1580 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1583 XFreeGC(xGlobalDisplay, gc);
1584 XFreePixmap(xGlobalDisplay, pixmap);
1585 XFreePixmap(xGlobalDisplay, mask);
1592 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1595 if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1597 XImage image = { 0 };
1598 XDisplay xDisplay = display.driverData;
1599 XSurface xSurface = surface.driverData;
1602 temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1603 s = temp.GetSurface(0,0,null);
1604 s.Stretch(src, 0,0, sx,sy, w, h, sw, sh);
1608 image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1609 image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1610 image.format = ZPixmap;
1611 image.bitmap_unit = 8;
1612 image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1613 image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1615 image.data = (char *)temp.picture;
1618 // printf("Blitting DI\n");
1619 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1620 0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1627 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1630 if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1632 XImage image = { 0 };
1633 XDisplay xDisplay = display.driverData;
1634 XSurface xSurface = surface.driverData;
1637 temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1638 s = temp.GetSurface(0,0,null);
1639 s.Filter(src, 0,0, sx,sy, w, h, sw, sh);
1643 image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1644 image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1645 image.format = ZPixmap;
1646 image.bitmap_unit = 8;
1647 image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1648 image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;;
1650 image.data = (char *)temp.picture;
1653 // printf("Blitting DI\n");
1654 XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1655 0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1662 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
1665 font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
1669 void UnloadFont(DisplaySystem displaySystem, Font font)
1671 ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
1674 void TextFont(Display display, Surface surface, Font font)
1676 // XSurface xSurface = surface.driverData;
1677 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
1680 void TextOpacity(Display display, Surface surface, bool opaque)
1682 XSurface xSurface = surface.driverData;
1683 xSurface.opaque = opaque;
1686 #define CHAR_WIDTH 6
1687 #define CHAR_HEIGHT 14
1689 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
1691 XSurface xSurface = surface.driverData;
1692 //XDisplay xDisplay = display.driverData;
1695 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, &tw, &th, prevGlyph, rPrevGlyph, &adv);
1700 XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.background);
1702 XFillRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1703 x + surface.offset.x, y + surface.offset.y,
1704 tw /*len * CHAR_WIDTH*/, th /*CHAR_HEIGHT*/);
1706 XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.foreground);
1709 XRenderColor renderColor =
1711 (uint16)(xSurface.background.color.r * xSurface.background.a),
1712 (uint16)(xSurface.background.color.g * xSurface.background.a),
1713 (uint16)(xSurface.background.color.b * xSurface.background.a),
1714 (uint16)xSurface.background.a
1716 //printf("Filling rectangle\n");
1717 XRenderFillRectangle(xGlobalDisplay, PictOpSrc /*PictOpOver*/, xSurface.picture, &renderColor,
1718 x + surface.offset.x, y + surface.offset.y, tw, th);
1721 XDrawString(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1722 x + surface.offset.x, y + surface.offset.y + 12, text, len);
1725 ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
1728 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
1730 XSurface xSurface = surface.driverData;
1733 for(realLen = 0; realLen<len && text[realLen]; realLen++);
1734 if(width) *width = len * CHAR_WIDTH;
1735 if(height) *height = CHAR_HEIGHT;
1738 FontExtent(display.displaySystem, xSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
1741 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
1744 if(width) *width = len * CHAR_WIDTH;
1745 if(height) *height = CHAR_HEIGHT;
1747 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
1750 void DrawingChar(Display display, Surface surface, byte character)
1755 void LineStipple(Display display, Surface surface, uint stipple)
1757 XDisplay xDisplay = display.driverData;
1758 char list[32] = { 0 };
1767 for(c = 0; c<32; c++)
1769 if((stipple & 0x8000) == on)
1784 XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineOnOffDash, CapButt, JoinMiter);
1785 XSetDashes(xGlobalDisplay, xDisplay.gc, offset, list, count);
1791 XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineSolid, CapButt, JoinMiter);
1792 XSetDashes(xGlobalDisplay, xDisplay.gc, 0, list, count);
1796 bool Lock(Display display)
1798 //XLockDisplay(xGlobalDisplay);
1802 void Unlock(Display display)
1804 //XUnlockDisplay(xGlobalDisplay);
1807 void StartUpdate(Display display)
1812 void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1817 void Update(Display display, Box updateBox)
1819 XDisplay xDisplay = display.driverData;
1820 Box * box = (updateBox != null) ? updateBox : &xDisplay.updateBox;
1823 XRectangle rectangle;
1826 rectangle.width = (uint16)display.width;
1827 rectangle.height = (uint16)display.height;
1828 XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1830 /*if(display.alphaBlend)
1831 XRenderComposite(xGlobalDisplay, PictOpSrc, xDisplay.picture, None, xDisplay.windowPicture, box->left, box->top, 0, 0, box->left, box->top,
1832 box->right - box->left + 1, box->bottom - box->top + 1);
1834 XCopyArea(xGlobalDisplay, (Pixmap)xDisplay.pixmap, (X11Window)display.window, xDisplay.gc /*windowGC*/,
1835 box->left, box->top,
1836 box->right - box->left + 1,
1837 box->bottom - box->top + 1,
1838 box->left, box->top);
1840 if(display.alphaBlend)
1842 Box * box = &xDisplay.updateBox;
1843 XRenderComposite(xGlobalDisplay, PictOpSrc, xDisplay.picture, None, xDisplay.shapePicture, box->left, box->top, 0, 0, box->left, box->top,
1844 box->right - box->left + 1, box->bottom - box->top + 1);
1845 #if !defined(__APPLE__) && !defined(__OLDX__)
1846 XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, xDisplay.shapePixmap, ShapeSet);
1848 XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, 2, 0, 0, xDisplay.shapePixmap, ShapeSet);
1852 XFlush(xGlobalDisplay);
1853 if(updateBox == null)
1855 xDisplay.updateBox.left = display.width;
1856 xDisplay.updateBox.top = display.height;
1857 xDisplay.updateBox.right = 0;
1858 xDisplay.updateBox.bottom = 0;
1862 void EndUpdate(Display display)
1868 default dllexport long IS_XGetPixmap(Bitmap bitmap)
1870 XBitmap xBitmap = bitmap.driverData;
1871 return xBitmap.pixmap;
1874 default dllexport void IS_XGetSurfaceInfo(Surface surface, Pixmap * pixmap, GC * gc, int *x, int * y)
1876 Display display = surface.display;
1877 XDisplay xDisplay = display.driverData;
1879 *pixmap = xDisplay.pixmap;
1881 *x = surface.offset.x;
1882 *y = surface.offset.y;