81a6d8f6d1ba592e1baef08285624b70f7212db6
[sdk] / ecere / src / gfx / drivers / XDisplayDriver.ec
1 namespace gfx::drivers;
2
3 import "instance"
4
5 #if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
6
7 default:
8
9 #define property _property
10 #define new _new
11 #define class _class
12 #define uint _uint
13
14 #define Window    X11Window
15 #define Cursor    X11Cursor
16 #define Font      X11Font
17 #define Display   X11Display
18 #define Time      X11Time
19 #define KeyCode   X11KeyCode
20 #define Picture   X11Picture
21
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24 #if !defined(__EMSCRIPTEN__)
25 #include <X11/extensions/shape.h>
26 #include <X11/extensions/Xrender.h>
27 #endif
28 #include <X11/extensions/XShm.h>
29 #include <sys/ipc.h>
30 #include <sys/shm.h>
31
32 #undef Window
33 #undef Cursor
34 #undef Font
35 #undef Display
36 #undef Time
37 #undef KeyCode
38 #undef Picture
39
40 #undef uint
41 #undef new
42 #undef property
43 #undef class
44
45 private:
46
47 import "Display"
48 import "XInterface"
49
50 /*
51 static byte defaultRGBLookup[32768];
52 bool rgbLookupSet = false;
53 */
54 class XDisplay : LFBDisplay //struct
55 {
56    Pixmap pixmap;
57    Pixmap shapePixmap;
58    GC windowGC, gc;
59    Point offset;
60    Box updateBox;
61    X11Picture picture;
62    X11Picture shapePicture;
63    XShmSegmentInfo shminfo;
64    XImage * image;
65    XShmSegmentInfo shminfoShape;
66    XImage * shapeImage;
67 };
68
69 class XSurface : struct
70 {
71    Font font;
72    bool opaqueText;
73    int xOffset;
74    bool writingText;
75    bool writingOutline;
76
77    ColorAlpha foreground, background;
78    bool opaque;
79    bool clipped;
80    Pixmap pixmap;
81    X11Picture picture;
82    X11Picture colorPicture;
83    Pixmap colorPixmap;
84 };
85
86 class XBitmap : struct
87 {
88    Pixmap pixmap;
89    Pixmap mask;
90    X11Picture picture;
91    X11Picture maskPicture;
92 };
93
94 XRenderPictFormat * GetXRenderFormat(PixelFormat pixelFormat, bool alphaBlend)
95 {
96    XRenderPictFormat * format = null;
97    switch(pixelFormat)
98    {
99       case pixelFormatAlpha:
100          format = XRenderFindStandardFormat(xGlobalDisplay, PictStandardA8);
101          break;
102       case pixelFormat888:
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);
105          break;
106       case pixelFormat555:
107       {
108          XRenderPictFormat info = { 0 };
109
110          info.depth = 16;
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;
118
119          format = XRenderFindFormat(xGlobalDisplay,
120             /*PictFormatDepth|*/PictFormatType| PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
121             PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
122          break;
123       }
124       case pixelFormat565:
125       {
126          XRenderPictFormat info = { 0 };
127
128          info.depth = 16;
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;
138          info.id = 0xba;
139
140          format = XRenderFindFormat(xGlobalDisplay,
141             /*PictFormatDepth|*/PictFormatType|PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
142             PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
143          break;
144       }
145    }
146    return format;
147 }
148
149 static bool ClipBlitCoords(Surface surface, Bitmap src, int *dx, int *dy, int *sx, int *sy, int *w, int *h, bool * flip)
150 {
151    *flip = false;
152
153    if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top) return false;
154
155    if(*w < 0) { *w = -*w; *flip = true; }
156
157    //Clip against the edges of the source
158    if(*sx<0)
159    {
160       *dx+=-*sx;
161       *w-=-*sx;
162       *sx=0;
163    }
164    if(*sy<0)
165    {
166       *dy+=0-*sy;
167       *h-=0-*sy;
168       *sy=0;
169    }
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)
176    {
177       if(!*flip) *sx+=surface.box.left-*dx;
178       *w-=surface.box.left-*dx;
179       *dx=surface.box.left;
180    }
181    if(*dy<surface.box.top)
182    {
183       *sy+=surface.box.top-*dy;
184       *h-=surface.box.top-*dy;
185       *dy=surface.box.top;
186    }
187    if((*dx+*w)>surface.box.right)
188    {
189       if(*flip) *sx+=(uint)(*dx+*w)-surface.box.right-1;
190       *w-=((uint)(*dx+*w)-surface.box.right-1);
191    }
192    if((*dy+*h)>surface.box.bottom)
193       *h-=((*dy+*h)-surface.box.bottom-1);
194    if((*w<=0)||(*h<=0))
195       return false;
196    return true;
197 }
198
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)
200 {
201    float s2dw,s2dh,d2sw,d2sh;
202    *flip = false;
203
204    if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return false;
205
206    if(Sgn(*w) != Sgn(*sw))
207    {
208       *w = Abs(*w);
209       *sw = Abs(*sw);
210       *flip = true;
211    }
212
213    s2dw=(float)*w / *sw;
214    s2dh=(float)*h / *sh;
215    d2sw=(float)*sw / *w;
216    d2sh=(float)*sh / *h;
217
218    //Clip against the edges of the source
219    if(*sx < 0)
220    {
221       *dx += (int)((0-*sx) * s2dw);
222       *w -= (int)((0-*sx) * s2dw);
223       *sw -= 0-*sx;
224       *sx=0;
225    }
226    if(*sy < 0)
227    {
228       *dy += (int)((0-*sy) * s2dh);
229       *h -= (int)((0-*sy) * s2dh);
230
231       *sh -= 0-*sy;
232       *sy=0;
233    }
234    if(*sx+*sw>src.width-1)
235    {
236       *w-=(int)((*sx+*sw-(src.width-1)-1)*s2dw);
237       *sw-=*sx+*sw-(src.width-1)-1;
238    }
239    if(*sy+*sh>(src.height-1))
240    {
241       *h-=(int)((*sy+*sh-(src.height-1)-1)*s2dh);
242       *sh-=*sy+*sh-(src.height-1)-1;
243    }
244    //Clip against the edges of the destination
245    if(*dx < surface.box.left)
246    {
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;
251    }
252    if(*dy < surface.box.top)
253    {
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;
258    }
259    if((*dx+*w)>surface.box.right)
260    {
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);
264    }
265    if((*dy+*h)>surface.box.bottom)
266    {
267       *sh-=(int)(((*dy+*h)-surface.box.bottom-1)*d2sh);
268       *h-=((*dy+*h)-surface.box.bottom-1);
269    }
270    if((*w<=0)||(*h<=0)||(*sw<=0)||(*sh<=0))
271       return false;
272    return true;
273 }
274
275 static void PutBitmapMask(Pixmap mask, Bitmap bitmap) {
276    XImage image = {0};
277    GC maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
278    uint wordWidth = (bitmap.width+31) >> 5;
279
280    uint x,y;
281    uint32 *b = new0 uint32[wordWidth * bitmap.height];
282    uint32 f = 1;
283
284    XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
285
286    image.width = bitmap.width;
287    image.height = bitmap.height;
288
289    image.format = XYBitmap;
290    #ifdef __BIG_ENDIAN__
291    image.byte_order = MSBFirst;
292    #else
293    image.byte_order = LSBFirst;
294    #endif
295    image.bitmap_unit = 32;
296    image.bitmap_bit_order = LSBFirst;
297    image.bitmap_pad = 32;
298    image.depth = 1;
299    image.bytes_per_line = wordWidth << 2;
300
301    image.data = (char*)b;
302
303    XInitImage(&image);
304
305    switch(bitmap.pixelFormat) {
306       case pixelFormat4: {
307
308       } break;
309       case pixelFormat8: {
310          byte *p = (byte*)bitmap.picture;
311
312          for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
313             for(x = 0; x<bitmap.width; x++) {
314                if(p[x])
315                   *b |= f; //XPutPixel(&image, x,y, 1);
316                if (!(f<<=1))
317                   b++, f=1;
318             }
319             if (f != 1)
320                b++, f=1;
321          }
322       } break;
323       case pixelFormat444:
324       case pixelFormat555:
325       case pixelFormat565: {
326          uint16 *p = (uint16*)bitmap.picture;
327 #ifdef _DEBUG
328          PrintLn(bitmap.pixelFormat);
329 #endif
330          for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
331             for(x = 0; x<bitmap.width; x++) {
332                if(p[x])
333                   *b |= f; //XPutPixel(&image, x,y, 1);
334                if (!(f<<=1))
335                   b++, f=1;
336             }
337             if (f != 1)
338                b++, f=1;
339          }
340       } break;
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++) {
345                if(p[x].a)
346                   *b |= f; //XPutPixel(&image, x,y, 1);
347                if (!(f<<=1))
348                   b++, f=1;
349             }
350             if (f != 1)
351                b++, f=1;
352          }
353       } break;
354       case pixelFormatAlpha: {
355
356       } break;
357       case pixelFormatText: {
358
359       } break;
360       case pixelFormatRGBA: {
361
362       } break;
363    }
364
365    XSetForeground(xGlobalDisplay, maskGC, 1);
366    XSetBackground(xGlobalDisplay, maskGC, 0);
367
368    XPutImage(xGlobalDisplay, mask, maskGC, &image,
369       0, 0, 0, 0, //coordinates
370       bitmap.width, bitmap.height);
371
372    XFreeGC(xGlobalDisplay, maskGC);
373    delete image.data;
374 }
375
376 class XDisplayDriver : DisplayDriver
377 {
378    class_property(name) = "X";
379
380    bool CreateDisplaySystem(DisplaySystem displaySystem)
381    {
382       //displaySystem.driverData = calloc(1, sizeof(LFBSystem));
383       displaySystem.flags.memBackBuffer = true;
384       displaySystem.pixelFormat = xSystemPixelFormat;
385       return true;
386    }
387
388    void DestroyDisplaySystem(DisplaySystem displaySystem)
389    {
390       // delete displaySystem.driverData;
391    }
392
393    void DestroyDisplay(Display display)
394    {
395       XDisplay xDisplay = display.driverData;
396
397       // Free Shared Memory Pixmap
398       if(xDisplay.shapePixmap)
399          XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
400       if(xDisplay.pixmap)
401          XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
402       if(xDisplay.image)
403       {
404          if(xDisplay.shminfoShape.shmid != -1)
405          {
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);
410          }
411       }
412       if(xDisplay.shapeImage)
413       {
414          if(xDisplay.shminfoShape.shmid != -1)
415          {
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);
420          }
421          XDestroyImage(xDisplay.shapeImage);
422          xDisplay.shapeImage = None;
423       }
424       if(xDisplay.picture)
425          XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
426       if(xDisplay.shapePicture)
427          XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
428       if(xDisplay.windowGC)
429          XFreeGC(xGlobalDisplay, xDisplay.windowGC);
430       if(xDisplay.gc)
431          XFreeGC(xGlobalDisplay, xDisplay.gc);
432       delete xDisplay;
433       display.driverData = null;
434    }
435
436    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
437    {
438
439
440    }
441
442    bool CreateDisplay(Display display)
443    {
444       bool result = false;
445       XDisplay xDisplay = display.driverData = XDisplay { };
446
447       if(display)
448       {
449          xDisplay.windowGC = XCreateGC(xGlobalDisplay, (X11Window)display.window, 0, null);
450          XSetGraphicsExposures(xGlobalDisplay, xDisplay.windowGC, False);
451          result = true;
452       }
453       return result;
454    }
455
456    bool DisplaySize(Display display, int width, int height)
457    {
458       XDisplay xDisplay = display.driverData;
459       bool result = false;
460
461       if(width > display.width || height > display.height)
462       {
463          display.width = width;
464          display.height = height;
465
466          if(xDisplay.picture)
467             XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
468
469          {
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;
475
476             if(xDisplay.pixmap)
477             {
478                XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
479                xDisplay.pixmap = None;
480             }
481             if(xDisplay.shapePixmap)
482             {
483                XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
484                xDisplay.shapePixmap = None;
485             }
486
487             // Free Shared Memory Pixmap
488             if(xDisplay.image)
489             {
490                if(xDisplay.shminfoShape.shmid != -1)
491                {
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);
496                }
497                XDestroyImage(xDisplay.image);
498                xDisplay.image = None;
499             }
500             if(xDisplay.shapeImage)
501             {
502                if(xDisplay.shminfoShape.shmid != -1)
503                {
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);
508                }
509                XDestroyImage(xDisplay.shapeImage);
510                xDisplay.shapeImage = None;
511             }
512
513             // Initialize Shared Memory Pixmap
514 #ifdef __linux__
515             if(xSharedMemory && display.useSharedMemory && format)
516             {
517 #ifdef _DEBUG
518                printf("Using shared memory!\n");
519 #endif
520                xDisplay.image = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
521                   format->depth, ZPixmap, null, &xDisplay.shminfo, width, height);
522             }
523             else if(display.useSharedMemory && !xSharedMemory)
524                printf("%s", $"Error: Requested shared memory but shared memory pixmaps are not supported by X server.\n");
525 #endif
526             if(xDisplay.image)
527             {
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)
532                {
533                   xDisplay.shminfo.shmaddr = shmat(xDisplay.shminfo.shmid, 0, 0);
534                   if(xDisplay.shminfo.shmaddr != (void *)-1)
535                   {
536                      // printf("%d,  %d\n", xDisplay.shminfo.shmid, xDisplay.shminfo.shmaddr);
537                      xDisplay.shminfo.readOnly = False;
538                      if(XShmAttach(xGlobalDisplay, &xDisplay.shminfo))
539                      {
540                         xDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfo.shmaddr, &xDisplay.shminfo, width, height, format->depth);
541
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);
549                      }
550                   }
551                }
552                if(!xDisplay.pixmap)
553                {
554                   if(xDisplay.shminfo.shmid != -1)
555                   {
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);
560                   }
561                   XDestroyImage(xDisplay.image);
562                   xDisplay.image = None;
563                }
564             }
565
566 #ifdef __linux__
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);
571 #endif
572             if(xDisplay.shapeImage)
573             {
574                xDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE, xDisplay.shapeImage->bytes_per_line * xDisplay.shapeImage->height, IPC_CREAT|0777);
575                if(xDisplay.shminfoShape.shmid != -1)
576                {
577                   xDisplay.shminfoShape.shmaddr = shmat(xDisplay.shminfoShape.shmid, 0, 0);
578                   if(xDisplay.shminfoShape.shmaddr != (void *)-1)
579                   {
580                      xDisplay.shminfoShape.readOnly = False;
581                      if(XShmAttach(xGlobalDisplay, &xDisplay.shminfoShape))
582                      {
583                         xDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfoShape.shmaddr, &xDisplay.shminfoShape, width, height, 1);
584                      }
585                   }
586                }
587                if(!xDisplay.shapePixmap)
588                {
589                   if(xDisplay.shminfoShape.shmid != -1)
590                   {
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);
595                   }
596                   XDestroyImage(xDisplay.shapeImage);
597                   xDisplay.shapeImage = None;
598                }
599             }
600
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);
605             if(!xDisplay.gc)
606             {
607                xDisplay.gc = XCreateGC(xGlobalDisplay, (Pixmap)xDisplay.pixmap, 0, null);
608                XSetGraphicsExposures(xGlobalDisplay, xDisplay.gc, False);
609             }
610
611             if(format)
612                xDisplay.picture = XRenderCreatePicture(xGlobalDisplay, xDisplay.pixmap, format, CPComponentAlpha, &attributes);
613
614             if(display.alphaBlend)
615                xDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, xDisplay.shapePixmap, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
616          }
617       }
618       xDisplay.updateBox.left = display.width;
619       xDisplay.updateBox.top = display.height;
620       xDisplay.updateBox.right = 0;
621       xDisplay.updateBox.bottom = 0;
622
623       result = true;
624       return result;
625    }
626
627    void DisplayPosition(Display display, int x, int y)
628    {
629       XDisplay xDisplay = display.driverData;
630       xDisplay.offset.x = x;
631       xDisplay.offset.y = y;
632    }
633
634    void RestorePalette(Display display)
635    {
636
637    }
638
639    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
640    {
641       XBitmap xBitmap = bitmap.driverData;
642       if(xBitmap)
643       {
644          if(xBitmap.pixmap)
645             XFreePixmap(xGlobalDisplay, xBitmap.pixmap);
646          if(xBitmap.mask)
647             XFreePixmap(xGlobalDisplay, xBitmap.mask);
648          if(xBitmap.picture)
649             XRenderFreePicture(xGlobalDisplay, xBitmap.picture);
650          if(xBitmap.maskPicture)
651             XRenderFreePicture(xGlobalDisplay, xBitmap.maskPicture);
652          delete xBitmap;
653          bitmap.driverData = null;
654       }
655       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
656    }
657
658    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
659    {
660       //XDisplay xDisplay = display.driverData;
661       XBitmap xBitmap { };
662       XImage image = { 0 };
663       GC gc = 0;
664
665       if(bitmap.pixelFormat != pixelFormatAlpha)
666          bitmap.Convert(null, bitmap.alphaBlend ? pixelFormat888 : xSystemPixelFormat, null);
667
668       //bitmap.Convert(null, pixelFormatRGBA, null);
669       //bitmap.Convert(null, pixelFormat888, null);
670       xBitmap.pixmap =
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)
674          xBitmap.mask =
675             XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height, 1);
676
677       {
678          XRenderPictureAttributes attributes = { 0 };
679          XRenderPictFormat * format = GetXRenderFormat(bitmap.pixelFormat, bitmap.alphaBlend);
680          attributes.component_alpha = 1;
681
682          if(format)
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);
686       }
687
688       gc = XCreateGC(xGlobalDisplay, (Pixmap)xBitmap.pixmap, 0, null);
689
690       XSetGraphicsExposures(xGlobalDisplay, gc, False);
691
692       image.width = bitmap.width;
693       image.height = bitmap.height;
694
695       if(bitmap.pixelFormat == pixelFormatAlpha)
696       {
697          image.depth = 8;
698          image.bitmap_pad = 8;
699          image.bytes_per_line = bitmap.stride;
700          image.bits_per_pixel = 8;
701       }
702       else
703       {
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;
708       }
709
710       image.format = ZPixmap;
711       //image.bitmap_bit_order = MSBFirst;
712       #ifdef __BIG_ENDIAN__
713       image.byte_order = MSBFirst;
714       #endif
715       image.bitmap_unit = 8;
716       /*
717       image.red_mask   = 0xF800;
718       image.green_mask = 0x7E0;
719       image.blue_mask  = 0x1F;
720       */
721
722       /*
723       image.red_mask   = 0x0000FF;
724       image.green_mask = 0x00FF00;
725       image.blue_mask  = 0xFF0000;
726       */
727       // image.red_mask  = 0xFFFF0000;
728
729       image.data = (char *)bitmap.picture;
730       XInitImage(&image);
731
732       if(bitmap.pixelFormat != pixelFormatAlpha && bitmap.alphaBlend)
733       {
734          int x,y;
735          for(y = 0; y<bitmap.height; y++)
736          {
737             for(x = 0; x<bitmap.width; x++)
738             {
739                ColorAlpha * p = ((ColorAlpha *)bitmap.picture) + y * bitmap.stride + x;
740                int alpha = p->a;
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);
744             }
745          }
746       }
747
748       XPutImage(xGlobalDisplay, (Pixmap)xBitmap.pixmap, gc, &image,
749          0, 0, 0, 0, bitmap.width,bitmap.height);
750
751       if(bitmap.transparent && !bitmap.alphaBlend && bitmap.pixelFormat != pixelFormatAlpha)
752          PutBitmapMask(xBitmap.mask, bitmap);
753
754       XFreeGC(xGlobalDisplay, gc);
755
756       if(!bitmap.keepData)
757          delete bitmap.picture;
758
759       bitmap.driverData = xBitmap;
760       bitmap.driver = displaySystem.driver;
761       return true;
762    }
763
764    void ReleaseSurface(Display display, Surface surface)
765    {
766       XSurface xSurface = surface.driverData;
767       XDisplay xDisplay = display ? display.driverData : null;
768       XRectangle rectangle;
769
770       if(xSurface.colorPicture)
771          XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
772
773       rectangle.x = 0;
774       rectangle.y = 0;
775       if(display)
776       {
777          rectangle.width = (uint16)display.width;
778          rectangle.height = (uint16)display.height;
779          XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
780       }
781
782       if(xSurface.colorPixmap)
783          XFreePixmap(xGlobalDisplay, xSurface.colorPixmap);
784
785       delete xSurface;
786    }
787
788    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
789    {
790       bool result = false;
791       XBitmap xBitmap = bitmap.driverData;
792       XSurface xSurface;
793
794       if((surface.driverData = xSurface = XSurface { }))
795       {
796          surface.offset.x = x;
797          surface.offset.y = y;
798          surface.unclippedBox = surface.box = clip;
799
800          xSurface.pixmap = xBitmap.pixmap;
801
802          result = true;
803       }
804       return result;
805    }
806
807    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
808    {
809       bool result = false;
810       XDisplay xDisplay = display.driverData;
811       XSurface xSurface;
812       if((surface.driverData = xSurface = XSurface { }))
813       {
814          XRectangle rectangle;
815
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;
821
822          xSurface.colorPixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, 1, 1, /*(xSystemDepth == 16) ? 16 : */32);
823
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);
828
829          XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
830          XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
831
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);
836
837          result = true;
838       }
839       return result;
840    }
841
842    void Clip(Display display, Surface surface, Box clip)
843    {
844       XSurface xSurface = surface.driverData;
845       XDisplay xDisplay = display.driverData;
846       bool changed = false;
847       if(clip != null)
848       {
849          Box box = clip;
850
851          box.Clip(surface.unclippedBox);
852
853          surface.box = box;
854
855          xSurface.clipped = true;
856          changed = true;
857       }
858       else if(xSurface.clipped)
859       {
860          surface.box = surface.unclippedBox;
861          xSurface.clipped = false;
862          changed = true;
863       }
864       if(changed)
865       {
866          XRectangle rectangle =
867          {
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)
872          };
873          XSetClipRectangles(xGlobalDisplay, xDisplay.gc,
874             0,0, &rectangle, 1, YXBanded);
875       }
876    }
877
878    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
879    {
880       bool result = false;
881       XDisplay xDisplay = display ? display.driverData : null;
882       XImage * xImage;
883       PixelFormat format = pixelFormat888;
884       Bitmap source { };
885       int sx = x, sy = y;
886       int dx = 0, dy = 0;
887       int sw = w, sh = h;
888
889       if(sx<0)
890       {
891          dx+=-sx;
892          sw-=-sx;
893          sx=0;
894       }
895       if(sy<0)
896       {
897          dy+=0-sy;
898          sh-=0-sy;
899          sy=0;
900       }
901       if(display)
902       {
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;
907       }
908
909       if(display)
910          xImage = XGetImage(xGlobalDisplay, xDisplay.pixmap, sx, sy, sw, sh, MAXDWORD, ZPixmap);
911       else
912          xImage = XGetImage(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), sx, sy, sw, sh, MAXDWORD, ZPixmap);
913
914       source.pixelFormat = format;
915       source.picture = (byte *)xImage->data;
916       source.width = sw;
917       source.height = sh;
918       source.stride = xImage->bytes_per_line / 4;
919
920       if(!bitmap || bitmap.pixelFormat != format || bitmap.width < w || bitmap.height < h)
921       {
922          bitmap.Free();
923          bitmap.Allocate(null, w,h,w, format, (format == pixelFormat8)?true:false);
924       }
925       if(bitmap)
926       {
927          Surface surface = bitmap.GetSurface(0, 0, null);
928          surface.Blit(source, dx,dy,0,0,sw,sh);
929          delete surface;
930          result = true;
931       }
932       source.picture = null;
933       delete source;
934
935       XDestroyImage(xImage);
936       return result;
937    }
938
939    void SetForeground(Display display, Surface surface, ColorAlpha color)
940    {
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) };
944
945       if(xSurface.colorPicture)
946          XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
947       // xSurface.colorPicture = XRenderCreateSolidFill(xGlobalDisplay, &renderColor);
948
949       {
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;
955          #else
956          attributes.repeat = 1;
957          #endif
958          ///attributes.component_alpha = 0;
959          if(format)
960             xSurface.colorPicture = XRenderCreatePicture(xGlobalDisplay, xSurface.colorPixmap, format, /*CPComponentAlpha | */CPRepeat, &attributes);
961          XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.colorPicture, &renderColor, 0, 0, 1, 1);
962       }
963
964       // xSurface.foreground = ARGB(A(color),B(color),G(color),R(color));
965       xSurface.foreground = color;
966
967       if(xDisplay)
968          XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
969             ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
970    }
971
972    void SetBackground(Display display, Surface surface, ColorAlpha color)
973    {
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;
978
979       if(xDisplay)
980          XSetBackground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
981             ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
982    }
983
984    ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
985    {
986       return 0;
987    }
988
989    void PutPixel(Display display, Surface surface,int x,int y)
990    {
991       XSurface xSurface = surface.driverData;
992       XDisplay xDisplay = display.driverData;
993
994       if(xSurface.foreground.a < 255)
995          DrawLine(display, surface, x,y,x,y);
996       else
997          XDrawPoint(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
998             x + surface.offset.x,
999             y + surface.offset.y);
1000    }
1001
1002    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1003    {
1004       XDisplay xDisplay = display ? display.driverData : null;
1005       XSurface xSurface = surface.driverData;
1006       if(!xDisplay || xSurface.foreground.a < 255)
1007       {
1008          XTrapezoid traps[3];
1009          int nTraps = 0;
1010          double offset = 0.5;
1011          double width = 0.5;
1012
1013          x1 += surface.offset.x;
1014          y1 += surface.offset.y;
1015          x2 += surface.offset.x;
1016          y2 += surface.offset.y;
1017
1018          if(y1 == y2)
1019          {
1020             x2++;
1021             x1--;
1022             {
1023                XTrapezoid trap1 =
1024                {
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) } }
1028                };
1029                traps[0] = trap1;
1030                nTraps = 1;
1031             }
1032          }
1033          else if(x1 == x2)
1034          {
1035             y2++;
1036             y1--;
1037             {
1038                XTrapezoid trap1 =
1039                {
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) } }
1043                };
1044                traps[0] = trap1;
1045                nTraps = 1;
1046             }
1047          }
1048          else
1049          {
1050             double dx, dy, l;
1051             Pointf A, B, C, D, E, F;
1052             if(y1 > y2)
1053             {
1054                int tmp = y2;
1055                y2 = y1;
1056                y1 = tmp;
1057                tmp = x2;
1058                x2 = x1;
1059                x1 = tmp;
1060             }
1061
1062             dx = x2 - x1;
1063             dy = y2 - y1;
1064             l = sqrt(dx * dx + dy * dy);
1065             dx /= l;
1066             dy /= l;
1067
1068             if(x2 > x1)
1069             {
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 };
1076
1077                {
1078                   XTrapezoid trap1 =
1079                   {
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) } }
1083                   };
1084                   XTrapezoid trap2 =
1085                   {
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) } }
1089                   };
1090                   XTrapezoid trap3 =
1091                   {
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) } }
1095                   };
1096                   traps[0] = trap1;
1097                   traps[1] = trap2;
1098                   traps[2] = trap3;
1099                   nTraps = 3;
1100                }
1101             }
1102             else
1103             {
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 };
1110
1111                {
1112                   XTrapezoid trap1 =
1113                   {
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) } }
1117                   };
1118                   XTrapezoid trap2 =
1119                   {
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) } }
1123                   };
1124                   XTrapezoid trap3 =
1125                   {
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) } }
1129                   };
1130                   traps[0] = trap1;
1131                   traps[1] = trap2;
1132                   traps[2] = trap3;
1133                   nTraps = 3;
1134                }
1135             }
1136             /*
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);
1152             printf("\n");
1153             */
1154          }
1155          XRenderCompositeTrapezoids(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xSurface.picture, None, 0, 0, traps, nTraps);
1156       }
1157       else
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);
1163    }
1164
1165    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1166    {
1167       XDisplay xDisplay = display ? display.driverData : null;
1168       XSurface xSurface = surface.driverData;
1169
1170       if(!xDisplay || xSurface.foreground.a < 255)
1171       {
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);
1176       }
1177       else
1178          XDrawRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1179             x1 + surface.offset.x,
1180             y1 + surface.offset.y,
1181             x2 - x1, y2 - y1);
1182    }
1183
1184    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1185    {
1186       XDisplay xDisplay = display ? display.driverData : null;
1187       XSurface xSurface = surface.driverData;
1188       if(!xDisplay || xSurface.background.a < 255)
1189       {
1190          XRenderColor renderColor =
1191          {
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)
1196          };
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);
1202       }
1203       else
1204       {
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)));
1213       }
1214    }
1215
1216    void Clear(Display display, Surface surface, ClearType flags)
1217    {
1218       if(flags != depthBuffer)
1219       {
1220          // XDisplay xDisplay = display.driverData;
1221          XSurface xSurface = surface.driverData;
1222          if(xSurface.background.a < 255)
1223          {
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 =
1229             {
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)
1234             };
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);
1240          }
1241          else
1242             Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1243       }
1244    }
1245
1246    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
1247    {
1248       return true;
1249    }
1250
1251    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1252    {
1253       bool result = false;
1254       XBitmap xBitmap = bitmap.driverData = XBitmap { };
1255       if(xBitmap)
1256       {
1257          if(!stride)
1258          {
1259             switch(GetColorDepthShifts(format))
1260             {
1261                case 0: stride = (width + 3) & 0xFFFFFFFC; break;
1262                case 1: stride = (width + 1) & 0xFFFFFFFE; break;
1263                case 2: stride = width;                    break;
1264             }
1265          }
1266
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;
1275          if(allocatePalette)
1276          {
1277             bitmap.palette = new ColorAlpha[256];
1278             if(bitmap.palette)
1279                CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
1280          }
1281          else
1282             bitmap.palette = GetDefaultPalette();
1283
1284          result = true;
1285
1286          if(!result)
1287             FreeBitmap(displaySystem, bitmap);
1288       }
1289
1290       return result;
1291    }
1292
1293    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1294    {
1295       XDisplay xDisplay = display.driverData;
1296       XSurface xSurface = surface.driverData;
1297       XBitmap xBitmap = src.driverData;
1298       if(xBitmap)
1299       {
1300          bool flip;
1301          if(!ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1302             return;
1303
1304          dx += surface.offset.x;
1305          dy += surface.offset.y;
1306
1307          if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1308          {
1309             XSetClipMask(xGlobalDisplay, xDisplay.gc, xBitmap.mask);
1310             XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx - sx, dy - sy);
1311          }
1312          if(xSurface.xOffset)
1313          {
1314             XTransform transform =
1315             {
1316                {
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)) }
1320                }
1321             };
1322             // printf("XOffset: %d\n", xSurface.xOffset);
1323             XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1324          }
1325
1326          if(src.alphaBlend || display.alphaBlend)
1327          {
1328             if(src.pixelFormat == pixelFormatAlpha)
1329             {
1330                XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w + (xSurface.xOffset ? 1 : 1), h);
1331             }
1332             else if(src.alphaBlend)
1333                XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1334             else
1335                XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1336          }
1337          else
1338             XCopyArea(xGlobalDisplay, (Pixmap)xBitmap.pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc,
1339                sx, sy, w, h, dx, dy);
1340
1341          if(xSurface.xOffset)
1342          {
1343             XTransform identity =
1344             {
1345                {
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)) }
1349                }
1350             };
1351             XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1352          }
1353          if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1354          {
1355             XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1356             {
1357                XRectangle rectangle;
1358
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);
1363
1364                XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1365             }
1366          }
1367       }
1368    }
1369
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)
1371    {
1372       XSurface xSurface = surface.driverData;
1373       XBitmap xBitmap = src.driverData;
1374       if(xBitmap)
1375       {
1376          XTransform transform =
1377          {
1378             {
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)) }
1382             }
1383          };
1384          XTransform identity =
1385          {
1386             {
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)) }
1390             }
1391          };
1392          dx += surface.offset.x;
1393          dy += surface.offset.y;
1394
1395          XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1396
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);
1401          else
1402          {
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);
1406          }
1407          XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1408       }
1409    }
1410
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)
1412    {
1413       XBitmap xBitmap = src.driverData;
1414       if(xBitmap)
1415       {
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);
1419       }
1420    }
1421
1422    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1423    {
1424       XImage image = { 0 };
1425       XDisplay xDisplay = display ? display.driverData : null;
1426       XSurface xSurface = surface.driverData;
1427       bool flip;
1428
1429       if(!xDisplay || !src.picture || !ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1430          return;
1431
1432       if(src.pixelFormat == display.pixelFormat)
1433       {
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;
1442
1443          image.data = (char *)src.picture;
1444          XInitImage(&image);
1445
1446          XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1447             sx, sy, dx + surface.offset.x, dy + surface.offset.y, w,h);
1448       }
1449       else
1450       {
1451          Bitmap temp { };
1452          Surface s;
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);
1456
1457          image.width = w;
1458          image.height = 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;
1465
1466          image.data = (char *)temp.picture;
1467
1468          XInitImage(&image);
1469          if(!src.transparent)
1470          {
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);
1474          }
1475          else
1476          {
1477          #if 0
1478             GC maskGC = 0, gc = 0;
1479             Pixmap pixmap, mask;
1480
1481             pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1482             mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1483
1484             gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1485             maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
1486             XSetGraphicsExposures(xGlobalDisplay, gc, False);
1487             XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
1488
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)
1494             {
1495                int x,y;
1496                for(y = 0; y<h; y++)
1497                {
1498                   for(x = 0; x<w; x++)
1499                   {
1500                      if(((ColorAlpha *)temp.picture)[y * temp.stride + x].a)
1501                         XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1502                   }
1503                }
1504             }
1505             else if(src.pixelFormat == pixelFormat8)
1506             {
1507                int x,y;
1508                for(y = 0; y<h; y++)
1509                {
1510                   for(x = 0; x<w; x++)
1511                   {
1512                      if(src.picture[(y + sy) * src.stride + (flip ? (w-1-(sx + x)) : (sx + x)])
1513                         XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1514                   }
1515                }
1516             }
1517             else
1518             {
1519                int x,y;
1520                for(y = 0; y<h; y++)
1521                {
1522                   for(x = 0; x<w; x++)
1523                   {
1524                      if(((uint16 *)temp.picture)[y * temp.stride + x])
1525                         XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1526                   }
1527                }
1528             }
1529
1530             XFreeGC(xGlobalDisplay, maskGC);
1531          #else
1532          GC gc = 0;
1533             Pixmap pixmap, mask;
1534
1535             pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1536             mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1537
1538             gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1539             XSetGraphicsExposures(xGlobalDisplay, gc, False);
1540
1541             XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1542
1543          PutBitmapMask(mask, temp);
1544          #endif
1545
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);
1550             {
1551                XRectangle rectangle;
1552
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);
1557
1558                XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1559             }
1560
1561             XFreeGC(xGlobalDisplay, gc);
1562             XFreePixmap(xGlobalDisplay, pixmap);
1563             XFreePixmap(xGlobalDisplay, mask);
1564          }
1565          delete s;
1566          delete temp;
1567       }
1568    }
1569
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)
1571    {
1572       bool flip;
1573       if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1574       {
1575          XImage image = { 0 };
1576          XDisplay xDisplay = display.driverData;
1577          XSurface xSurface = surface.driverData;
1578          Bitmap temp { };
1579          Surface s;
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);
1583
1584          image.width = w;
1585          image.height = h;
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;
1592
1593          image.data = (char *)temp.picture;
1594          XInitImage(&image);
1595
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);
1599
1600          delete s;
1601          delete temp;
1602       }
1603    }
1604
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)
1606    {
1607       bool flip;
1608       if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1609       {
1610          XImage image = { 0 };
1611          XDisplay xDisplay = display.driverData;
1612          XSurface xSurface = surface.driverData;
1613          Bitmap temp { };
1614          Surface s;
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);
1618
1619          image.width = w;
1620          image.height = h;
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;;
1627
1628          image.data = (char *)temp.picture;
1629          XInitImage(&image);
1630
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);
1634
1635          delete s;
1636          delete temp;
1637       }
1638    }
1639
1640    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
1641    {
1642       Font font;
1643       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
1644       return font;
1645    }
1646
1647    void UnloadFont(DisplaySystem displaySystem, Font font)
1648    {
1649       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
1650    }
1651
1652    void TextFont(Display display, Surface surface, Font font)
1653    {
1654       // XSurface xSurface = surface.driverData;
1655       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
1656    }
1657
1658    void TextOpacity(Display display, Surface surface, bool opaque)
1659    {
1660       XSurface xSurface = surface.driverData;
1661       xSurface.opaque = opaque;
1662    }
1663
1664    #define CHAR_WIDTH   6
1665    #define CHAR_HEIGHT  14
1666
1667    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
1668    {
1669       XSurface xSurface = surface.driverData;
1670       //XDisplay xDisplay = display.driverData;
1671       int tw, th;
1672
1673       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, &tw, &th);
1674       if(xSurface.opaque)
1675       {
1676 #if 0
1677          XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.background);
1678
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*/);
1682
1683          XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.foreground);
1684 #endif
1685
1686          XRenderColor renderColor =
1687          {
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
1692          };
1693          //printf("Filling rectangle\n");
1694          XRenderFillRectangle(xGlobalDisplay, PictOpSrc /*PictOpOver*/, xSurface.picture, &renderColor,
1695             x + surface.offset.x, y + surface.offset.y, tw, th);
1696       }
1697       /*
1698       XDrawString(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1699          x + surface.offset.x, y + surface.offset.y + 12, text, len);
1700       */
1701
1702       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
1703    }
1704
1705    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
1706    {
1707       XSurface xSurface = surface.driverData;
1708       /*
1709       uint realLen;
1710       for(realLen = 0; realLen<len && text[realLen]; realLen++);
1711       if(width) *width = len * CHAR_WIDTH;
1712       if(height) *height = CHAR_HEIGHT;
1713       */
1714
1715       FontExtent(display.displaySystem, xSurface.font, text, len, width, height);
1716    }
1717
1718    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
1719    {
1720       /*
1721       if(width) *width = len * CHAR_WIDTH;
1722       if(height) *height = CHAR_HEIGHT;
1723       */
1724       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height);
1725    }
1726
1727    void DrawingChar(Display display, Surface surface, byte character)
1728    {
1729
1730    }
1731
1732    void LineStipple(Display display, Surface surface, uint stipple)
1733    {
1734       XDisplay xDisplay = display.driverData;
1735       char list[32] = { 0 };
1736       int count = 0;
1737
1738       if(stipple)
1739       {
1740          int c;
1741          int offset = 0;
1742          uint16 on = 0x8000;
1743
1744          for(c = 0; c<32; c++)
1745          {
1746             if((stipple & 0x8000) == on)
1747                list[count]++;
1748             else
1749             {
1750                if(!list[count])
1751                   offset = 1;
1752                else
1753                {
1754                   count++;
1755                   list[count]++;
1756                   on ^= 0x8000;
1757                }
1758             }
1759             stipple <<= 1;
1760          }
1761          XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineOnOffDash, CapButt, JoinMiter);
1762          XSetDashes(xGlobalDisplay, xDisplay.gc, offset, list, count);
1763       }
1764       else
1765       {
1766          list[0] = 4;
1767          count = 1;
1768          XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineSolid, CapButt, JoinMiter);
1769          XSetDashes(xGlobalDisplay, xDisplay.gc, 0, list, count);
1770       }
1771    }
1772
1773    bool Lock(Display display)
1774    {
1775       //XLockDisplay(xGlobalDisplay);
1776       return true;
1777    }
1778
1779    void Unlock(Display display)
1780    {
1781       //XUnlockDisplay(xGlobalDisplay);
1782    }
1783
1784    void StartUpdate(Display display)
1785    {
1786
1787    }
1788
1789    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1790    {
1791
1792    }
1793
1794    void Update(Display display, Box updateBox)
1795    {
1796       XDisplay xDisplay = display.driverData;
1797       Box * box = (updateBox != null) ? updateBox : &xDisplay.updateBox;
1798
1799       {
1800          XRectangle rectangle;
1801          rectangle.x = 0;
1802          rectangle.y = 0;
1803          rectangle.width = (uint16)display.width;
1804          rectangle.height = (uint16)display.height;
1805          XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1806       }
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);
1810       else*/
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);
1816
1817       if(display.alphaBlend)
1818       {
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);
1824          #else
1825          XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, 2, 0, 0, xDisplay.shapePixmap, ShapeSet);
1826          #endif
1827       }
1828
1829       XFlush(xGlobalDisplay);
1830       if(updateBox == null)
1831       {
1832          xDisplay.updateBox.left = display.width;
1833          xDisplay.updateBox.top = display.height;
1834          xDisplay.updateBox.right = 0;
1835          xDisplay.updateBox.bottom = 0;
1836       }
1837    }
1838
1839    void EndUpdate(Display display)
1840    {
1841
1842    }
1843 }
1844
1845 default dllexport long IS_XGetPixmap(Bitmap bitmap)
1846 {
1847    XBitmap xBitmap = bitmap.driverData;
1848    return xBitmap.pixmap;
1849 }
1850
1851 default dllexport void IS_XGetSurfaceInfo(Surface surface, Pixmap * pixmap, GC * gc, int *x, int * y)
1852 {
1853    Display display = surface.display;
1854    XDisplay xDisplay = display.driverData;
1855
1856    *pixmap = xDisplay.pixmap;
1857    *gc = xDisplay.gc;
1858    *x = surface.offset.x;
1859    *y = surface.offset.y;
1860 }
1861
1862 #endif