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