Fixed drive mapping in GET ALLOCATION.
[wine] / dlls / x11drv / dib.c
1 /*
2  * X11DRV device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <X11/Xlib.h>
24 #ifdef HAVE_LIBXXSHM
25 #include <X11/extensions/XShm.h>
26 # ifdef HAVE_SYS_SHM_H
27 #  include <sys/shm.h>
28 # endif
29 # ifdef HAVE_SYS_IPC_H
30 #  include <sys/ipc.h>
31 # endif
32 #endif /* defined(HAVE_LIBXXSHM) */
33
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "gdi.h"
40 #include "x11drv.h"
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
44 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
45
46 static int ximageDepthTable[32];
47
48 /* This structure holds the arguments for DIB_SetImageBits() */
49 typedef struct
50 {
51     X11DRV_PDEVICE *physDev;
52     LPCVOID         bits;
53     XImage         *image;
54     PALETTEENTRY   *palentry;
55     int             lines;
56     DWORD           infoWidth;
57     WORD            depth;
58     WORD            infoBpp;
59     WORD            compression;
60     RGBQUAD        *colorMap;
61     int             nColorMap;
62     Drawable        drawable;
63     GC              gc;
64     int             xSrc;
65     int             ySrc;
66     int             xDest;
67     int             yDest;
68     int             width;
69     int             height;
70     DWORD           rMask;
71     DWORD           gMask;
72     DWORD           bMask;
73     BOOL            useShm;
74     int             dibpitch;
75     DWORD           sizeImage;  
76 } X11DRV_DIB_IMAGEBITS_DESCR;
77
78
79 enum Rle_EscapeCodes
80 {
81   RLE_EOL   = 0, /* End of line */
82   RLE_END   = 1, /* End of bitmap */
83   RLE_DELTA = 2  /* Delta */
84 };
85
86 /***********************************************************************
87  *           X11DRV_DIB_GetXImageWidthBytes
88  *
89  * Return the width of an X image in bytes
90  */
91 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
92 {
93     if (!depth || depth > 32) goto error;
94
95     if (!ximageDepthTable[depth-1])
96     {
97         XImage *testimage = XCreateImage( gdi_display, visual, depth,
98                                           ZPixmap, 0, NULL, 1, 1, 32, 20 );
99         if (testimage)
100         {
101             ximageDepthTable[depth-1] = testimage->bits_per_pixel;
102             XDestroyImage( testimage );
103         }
104         else ximageDepthTable[depth-1] = -1;
105     }
106     if (ximageDepthTable[depth-1] != -1)
107         return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
108
109  error:
110     WARN( "(%d): Unsupported depth\n", depth );
111     return 4 * width;
112 }
113
114
115 /***********************************************************************
116  *           X11DRV_DIB_GetDIBWidthBytes
117  *
118  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
119  */
120 static int X11DRV_DIB_GetDIBWidthBytes( int width, int depth )
121 {
122     int words;
123
124     switch(depth)
125     {
126     case 1:  words = (width + 31) / 32; break;
127     case 4:  words = (width + 7) / 8; break;
128     case 8:  words = (width + 3) / 4; break;
129     case 15:
130     case 16: words = (width + 1) / 2; break;
131     case 24: words = (width * 3 + 3) / 4; break;
132     default:
133         WARN("(%d): Unsupported depth\n", depth );
134         /* fall through */
135     case 32:
136         words = width;
137     }
138     return 4 * words;
139 }
140
141
142 /***********************************************************************
143  *           X11DRV_DIB_BitmapInfoSize
144  *
145  * Return the size of the bitmap info structure including color table.
146  */
147 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
148 {
149     int colors;
150
151     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
152     {
153         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
154         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
155         return sizeof(BITMAPCOREHEADER) + colors *
156              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
157     }
158     else  /* assume BITMAPINFOHEADER */
159     {
160         colors = info->bmiHeader.biClrUsed;
161         if (!colors && (info->bmiHeader.biBitCount <= 8))
162             colors = 1 << info->bmiHeader.biBitCount;
163         return sizeof(BITMAPINFOHEADER) + colors *
164                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
165     }
166 }
167
168
169 /***********************************************************************
170  *           X11DRV_DIB_CreateXImage
171  *
172  * Create an X image.
173  */
174 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
175 {
176     int width_bytes;
177     XImage *image;
178
179     wine_tsx11_lock();
180     width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
181     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
182                           calloc( height, width_bytes ),
183                           width, height, 32, width_bytes );
184     wine_tsx11_unlock();
185     return image;
186 }
187
188
189 /***********************************************************************
190  *           DIB_GetBitmapInfo
191  *
192  * Get the info from a bitmap header.
193  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
194  */
195 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
196                               int *height, WORD *bpp, WORD *compr )
197 {
198     if (header->biSize == sizeof(BITMAPCOREHEADER))
199     {
200         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
201         *width  = core->bcWidth;
202         *height = core->bcHeight;
203         *bpp    = core->bcBitCount;
204         *compr  = 0;
205         return 0;
206     }
207     if (header->biSize >= sizeof(BITMAPINFOHEADER))
208     {
209         *width  = header->biWidth;
210         *height = header->biHeight;
211         *bpp    = header->biBitCount;
212         *compr  = header->biCompression;
213         return 1;
214     }
215     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
216     return -1;
217 }
218
219
220 /***********************************************************************
221  *           X11DRV_DIB_GenColorMap
222  *
223  * Fills the color map of a bitmap palette. Should not be called
224  * for a >8-bit deep bitmap.
225  */
226 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
227                              WORD coloruse, WORD depth, BOOL quads,
228                              const void *colorPtr, int start, int end )
229 {
230     int i;
231
232     if (coloruse == DIB_RGB_COLORS)
233     {
234         int max = 1 << depth;
235
236         if (end > max) end = max;
237
238         if (quads)
239         {
240             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
241
242             if (depth == 1)  /* Monochrome */
243                 for (i = start; i < end; i++, rgb++)
244                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
245                                        rgb->rgbBlue > 255*3/2);
246             else
247                 for (i = start; i < end; i++, rgb++)
248                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
249                                                                 rgb->rgbGreen,
250                                                                 rgb->rgbBlue));
251         }
252         else
253         {
254             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
255
256             if (depth == 1)  /* Monochrome */
257                 for (i = start; i < end; i++, rgb++)
258                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
259                                        rgb->rgbtBlue > 255*3/2);
260             else
261                 for (i = start; i < end; i++, rgb++)
262                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
263                                                                rgb->rgbtGreen,
264                                                                rgb->rgbtBlue));
265         }
266     }
267     else  /* DIB_PAL_COLORS */
268     {
269         if (colorPtr) {
270             WORD * index = (WORD *)colorPtr;
271
272             for (i = start; i < end; i++, index++)
273                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
274         } else {
275             for (i = start; i < end; i++)
276                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
277         }
278     }
279
280     return colorMapping;
281 }
282
283 /***********************************************************************
284  *           X11DRV_DIB_BuildColorMap
285  *
286  * Build the color map from the bitmap palette. Should not be called
287  * for a >8-bit deep bitmap.
288  */
289 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
290                                const BITMAPINFO *info, int *nColors )
291 {
292     int colors;
293     BOOL isInfo;
294     const void *colorPtr;
295     int *colorMapping;
296
297     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
298     {
299         colors = info->bmiHeader.biClrUsed;
300         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
301         colorPtr = info->bmiColors;
302     }
303     else  /* assume BITMAPCOREINFO */
304     {
305         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
306         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
307     }
308
309     if (colors > 256)
310     {
311         ERR("called with >256 colors!\n");
312         return NULL;
313     }
314
315     /* just so CopyDIBSection doesn't have to create an identity palette */
316     if (coloruse == (WORD)-1) colorPtr = NULL;
317
318     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
319                                           colors * sizeof(int) )))
320         return NULL;
321
322     *nColors = colors;
323     return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
324                                    isInfo, colorPtr, 0, colors);
325 }
326
327
328 /***********************************************************************
329  *           X11DRV_DIB_MapColor
330  */
331 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
332 {
333     int color;
334
335     if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
336         return oldcol;
337
338     for (color = 0; color < nPhysMap; color++)
339         if (physMap[color] == phys)
340             return color;
341
342     WARN("Strange color %08x\n", phys);
343     return 0;
344 }
345
346
347 /*********************************************************************
348  *         X11DRV_DIB_GetNearestIndex
349  *
350  * Helper for X11DRV_DIB_GetDIBits.
351  * Returns the nearest colour table index for a given RGB.
352  * Nearest is defined by minimizing the sum of the squares.
353  */
354 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
355 {
356     INT i, best = -1, diff, bestdiff = -1;
357     RGBQUAD *color;
358
359     for(color = colormap, i = 0; i < numColors; color++, i++) {
360         diff = (r - color->rgbRed) * (r - color->rgbRed) +
361                (g - color->rgbGreen) * (g - color->rgbGreen) +
362                (b - color->rgbBlue) * (b - color->rgbBlue);
363         if(diff == 0)
364             return i;
365         if(best == -1 || diff < bestdiff) {
366             best = i;
367             bestdiff = diff;
368         }
369     }
370     return best;
371 }
372 /*********************************************************************
373  *         X11DRV_DIB_MaskToShift
374  *
375  * Helper for X11DRV_DIB_GetDIBits.
376  * Returns the by how many bits to shift a given color so that it is
377  * in the proper position.
378  */
379 INT X11DRV_DIB_MaskToShift(DWORD mask)
380 {
381     int shift;
382
383     if (mask==0)
384         return 0;
385
386     shift=0;
387     while ((mask&1)==0) {
388         mask>>=1;
389         shift++;
390     }
391     return shift;
392 }
393
394 /***********************************************************************
395  *           X11DRV_DIB_SetImageBits_1
396  *
397  * SetDIBits for a 1-bit deep DIB.
398  */
399 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
400                                 DWORD srcwidth, DWORD dstwidth, int left,
401                                 int *colors, XImage *bmpImage, DWORD linebytes)
402 {
403     int h;
404     const BYTE* srcbyte;
405     BYTE srcval, extra;
406     DWORD i, x;
407
408     if (lines < 0 ) {
409         lines = -lines;
410         srcbits = srcbits + linebytes * (lines - 1);
411         linebytes = -linebytes;
412     }
413
414     if ((extra = (left & 7)) != 0) {
415         left &= ~7;
416         dstwidth += extra;
417     }
418     srcbits += left >> 3;
419
420     /* ==== pal 1 dib -> any bmp format ==== */
421     for (h = lines-1; h >=0; h--) {
422         srcbyte=srcbits;
423         /* FIXME: should avoid putting x<left pixels (minor speed issue) */
424         for (i = dstwidth/8, x = left; i > 0; i--) {
425             srcval=*srcbyte++;
426             XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
427             XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
428             XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
429             XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
430             XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
431             XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
432             XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
433             XPutPixel( bmpImage, x++, h, colors[ srcval       & 1] );
434         }
435         if (dstwidth % 8){
436             srcval=*srcbyte;
437             switch (dstwidth & 7)
438             {
439             case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
440             case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
441             case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
442             case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
443             case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
444             case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
445             case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
446             }
447         }
448         srcbits += linebytes;
449     }
450 }
451
452 /***********************************************************************
453  *           X11DRV_DIB_GetImageBits_1
454  *
455  * GetDIBits for a 1-bit deep DIB.
456  */
457 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
458                                        DWORD dstwidth, DWORD srcwidth,
459                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
460                                 XImage *bmpImage, DWORD linebytes )
461 {
462     DWORD x;
463     int h;
464
465     if (lines < 0 ) {
466         lines = -lines;
467         dstbits = dstbits + linebytes * (lines - 1);
468         linebytes = -linebytes;
469     }
470
471     switch (bmpImage->depth)
472     {
473     case 1:
474     case 4:
475         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
476             /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
477             BYTE* dstbyte;
478
479             for (h=lines-1; h>=0; h--) {
480                 BYTE dstval;
481                 dstbyte=dstbits;
482                 dstval=0;
483                 for (x=0; x<dstwidth; x++) {
484                     PALETTEENTRY srcval;
485                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
486                     dstval|=(X11DRV_DIB_GetNearestIndex
487                              (colors, 2,
488                               srcval.peRed,
489                               srcval.peGreen,
490                               srcval.peBlue) << (7 - (x & 7)));
491                     if ((x&7)==7) {
492                         *dstbyte++=dstval;
493                         dstval=0;
494                     }
495                 }
496                 if ((dstwidth&7)!=0) {
497                     *dstbyte=dstval;
498                 }
499                 dstbits += linebytes;
500             }
501         } else {
502             goto notsupported;
503         }
504         break;
505
506     case 8:
507         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
508             /* ==== pal 8 bmp -> pal 1 dib ==== */
509             const void* srcbits;
510             const BYTE* srcpixel;
511             BYTE* dstbyte;
512
513             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
514
515             for (h=0; h<lines; h++) {
516                 BYTE dstval;
517                 srcpixel=srcbits;
518                 dstbyte=dstbits;
519                 dstval=0;
520                 for (x=0; x<dstwidth; x++) {
521                     PALETTEENTRY srcval;
522                     srcval=srccolors[(int)*srcpixel++];
523                     dstval|=(X11DRV_DIB_GetNearestIndex
524                              (colors, 2,
525                               srcval.peRed,
526                               srcval.peGreen,
527                               srcval.peBlue) << (7-(x&7)) );
528                     if ((x&7)==7) {
529                         *dstbyte++=dstval;
530                         dstval=0;
531                     }
532                 }
533                 if ((dstwidth&7)!=0) {
534                     *dstbyte=dstval;
535                 }
536                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
537                 dstbits += linebytes;
538             }
539         } else {
540             goto notsupported;
541         }
542         break;
543
544     case 15:
545     case 16:
546         {
547             const void* srcbits;
548             const WORD* srcpixel;
549             BYTE* dstbyte;
550
551             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
552
553             if (bmpImage->green_mask==0x03e0) {
554                 if (bmpImage->red_mask==0x7c00) {
555                     /* ==== rgb 555 bmp -> pal 1 dib ==== */
556                     for (h=0; h<lines; h++) {
557                         BYTE dstval;
558                         srcpixel=srcbits;
559                         dstbyte=dstbits;
560                         dstval=0;
561                         for (x=0; x<dstwidth; x++) {
562                             WORD srcval;
563                             srcval=*srcpixel++;
564                             dstval|=(X11DRV_DIB_GetNearestIndex
565                                      (colors, 2,
566                                       ((srcval >>  7) & 0xf8) | /* r */
567                                       ((srcval >> 12) & 0x07),
568                                       ((srcval >>  2) & 0xf8) | /* g */
569                                       ((srcval >>  7) & 0x07),
570                                       ((srcval <<  3) & 0xf8) | /* b */
571                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
572                             if ((x&7)==7) {
573                                 *dstbyte++=dstval;
574                                 dstval=0;
575                             }
576                         }
577                         if ((dstwidth&7)!=0) {
578                             *dstbyte=dstval;
579                         }
580                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
581                         dstbits += linebytes;
582                     }
583                 } else if (bmpImage->blue_mask==0x7c00) {
584                     /* ==== bgr 555 bmp -> pal 1 dib ==== */
585                     for (h=0; h<lines; h++) {
586                         WORD dstval;
587                         srcpixel=srcbits;
588                         dstbyte=dstbits;
589                         dstval=0;
590                         for (x=0; x<dstwidth; x++) {
591                             BYTE srcval;
592                             srcval=*srcpixel++;
593                             dstval|=(X11DRV_DIB_GetNearestIndex
594                                      (colors, 2,
595                                       ((srcval <<  3) & 0xf8) | /* r */
596                                       ((srcval >>  2) & 0x07),
597                                       ((srcval >>  2) & 0xf8) | /* g */
598                                       ((srcval >>  7) & 0x07),
599                                       ((srcval >>  7) & 0xf8) | /* b */
600                                       ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
601                             if ((x&7)==7) {
602                                 *dstbyte++=dstval;
603                                 dstval=0;
604                             }
605                         }
606                         if ((dstwidth&7)!=0) {
607                             *dstbyte=dstval;
608                         }
609                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
610                         dstbits += linebytes;
611                     }
612                 } else {
613                     goto notsupported;
614                 }
615             } else if (bmpImage->green_mask==0x07e0) {
616                 if (bmpImage->red_mask==0xf800) {
617                     /* ==== rgb 565 bmp -> pal 1 dib ==== */
618                     for (h=0; h<lines; h++) {
619                         BYTE dstval;
620                         srcpixel=srcbits;
621                         dstbyte=dstbits;
622                         dstval=0;
623                         for (x=0; x<dstwidth; x++) {
624                             WORD srcval;
625                             srcval=*srcpixel++;
626                             dstval|=(X11DRV_DIB_GetNearestIndex
627                                      (colors, 2,
628                                       ((srcval >>  8) & 0xf8) | /* r */
629                                       ((srcval >> 13) & 0x07),
630                                       ((srcval >>  3) & 0xfc) | /* g */
631                                       ((srcval >>  9) & 0x03),
632                                       ((srcval <<  3) & 0xf8) | /* b */
633                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
634                             if ((x&7)==7) {
635                                 *dstbyte++=dstval;
636                                 dstval=0;
637                             }
638                         }
639                         if ((dstwidth&7)!=0) {
640                             *dstbyte=dstval;
641                         }
642                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
643                         dstbits += linebytes;
644                     }
645                 } else if (bmpImage->blue_mask==0xf800) {
646                     /* ==== bgr 565 bmp -> pal 1 dib ==== */
647                     for (h=0; h<lines; h++) {
648                         BYTE dstval;
649                         srcpixel=srcbits;
650                         dstbyte=dstbits;
651                         dstval=0;
652                         for (x=0; x<dstwidth; x++) {
653                             WORD srcval;
654                             srcval=*srcpixel++;
655                             dstval|=(X11DRV_DIB_GetNearestIndex
656                                      (colors, 2,
657                                       ((srcval <<  3) & 0xf8) | /* r */
658                                       ((srcval >>  2) & 0x07),
659                                       ((srcval >>  3) & 0xfc) | /* g */
660                                       ((srcval >>  9) & 0x03),
661                                       ((srcval >>  8) & 0xf8) | /* b */
662                                       ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
663                             if ((x&7)==7) {
664                                 *dstbyte++=dstval;
665                                 dstval=0;
666                             }
667                         }
668                         if ((dstwidth&7)!=0) {
669                             *dstbyte=dstval;
670                         }
671                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
672                         dstbits += linebytes;
673                     }
674                 } else {
675                     goto notsupported;
676                 }
677             } else {
678                 goto notsupported;
679             }
680         }
681         break;
682
683     case 24:
684     case 32:
685         {
686             const void* srcbits;
687             const BYTE *srcbyte;
688             BYTE* dstbyte;
689             int bytes_per_pixel;
690
691             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
692             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
693
694             if (bmpImage->green_mask!=0x00ff00 ||
695                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
696                 goto notsupported;
697             } else if (bmpImage->blue_mask==0xff) {
698                 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
699                 for (h=0; h<lines; h++) {
700                     BYTE dstval;
701                     srcbyte=srcbits;
702                     dstbyte=dstbits;
703                     dstval=0;
704                     for (x=0; x<dstwidth; x++) {
705                         dstval|=(X11DRV_DIB_GetNearestIndex
706                                  (colors, 2,
707                                   srcbyte[2],
708                                   srcbyte[1],
709                                   srcbyte[0]) << (7-(x&7)) );
710                         srcbyte+=bytes_per_pixel;
711                         if ((x&7)==7) {
712                             *dstbyte++=dstval;
713                             dstval=0;
714                         }
715                     }
716                     if ((dstwidth&7)!=0) {
717                         *dstbyte=dstval;
718                     }
719                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
720                     dstbits += linebytes;
721                 }
722             } else {
723                 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
724                 for (h=0; h<lines; h++) {
725                     BYTE dstval;
726                     srcbyte=srcbits;
727                     dstbyte=dstbits;
728                     dstval=0;
729                     for (x=0; x<dstwidth; x++) {
730                         dstval|=(X11DRV_DIB_GetNearestIndex
731                                  (colors, 2,
732                                   srcbyte[0],
733                                   srcbyte[1],
734                                   srcbyte[2]) << (7-(x&7)) );
735                         srcbyte+=bytes_per_pixel;
736                         if ((x&7)==7) {
737                             *dstbyte++=dstval;
738                             dstval=0;
739                         }
740                     }
741                     if ((dstwidth&7)!=0) {
742                         *dstbyte=dstval;
743                     }
744                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
745                     dstbits += linebytes;
746                 }
747             }
748         }
749         break;
750
751     default:
752     notsupported:
753         {
754             BYTE* dstbyte;
755             unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
756
757             /* ==== any bmp format -> pal 1 dib ==== */
758             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
759                   bmpImage->bits_per_pixel, bmpImage->red_mask,
760                   bmpImage->green_mask, bmpImage->blue_mask );
761
762             for (h=lines-1; h>=0; h--) {
763                 BYTE dstval;
764                 dstbyte=dstbits;
765                 dstval=0;
766                 for (x=0; x<dstwidth; x++) {
767                     dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
768                     if ((x&7)==7) {
769                         *dstbyte++=dstval;
770                         dstval=0;
771                     }
772                 }
773                 if ((dstwidth&7)!=0) {
774                     *dstbyte=dstval;
775                 }
776                 dstbits += linebytes;
777             }
778         }
779         break;
780     }
781 }
782
783 /***********************************************************************
784  *           X11DRV_DIB_SetImageBits_4
785  *
786  * SetDIBits for a 4-bit deep DIB.
787  */
788 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
789                                 DWORD srcwidth, DWORD dstwidth, int left,
790                                 int *colors, XImage *bmpImage, DWORD linebytes)
791 {
792     int h;
793     const BYTE* srcbyte;
794     DWORD i, x;
795
796     if (lines < 0 ) {
797         lines = -lines;
798         srcbits = srcbits + linebytes * (lines - 1);
799         linebytes = -linebytes;
800     }
801
802     if (left & 1) {
803         left--;
804         dstwidth++;
805     }
806     srcbits += left >> 1;
807
808     /* ==== pal 4 dib -> any bmp format ==== */
809     for (h = lines-1; h >= 0; h--) {
810         srcbyte=srcbits;
811         for (i = dstwidth/2, x = left; i > 0; i--) {
812             BYTE srcval=*srcbyte++;
813             XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
814             XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
815         }
816         if (dstwidth & 1)
817             XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
818         srcbits += linebytes;
819     }
820 }
821
822
823
824 /***********************************************************************
825  *           X11DRV_DIB_GetImageBits_4
826  *
827  * GetDIBits for a 4-bit deep DIB.
828  */
829 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
830                                        DWORD srcwidth, DWORD dstwidth,
831                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
832                                        XImage *bmpImage, DWORD linebytes )
833 {
834     DWORD x;
835     int h;
836     BYTE *bits;
837
838     if (lines < 0 )
839     {
840        lines = -lines;
841        dstbits = dstbits + ( linebytes * (lines-1) );
842        linebytes = -linebytes;
843     }
844
845     bits = dstbits;
846
847     switch (bmpImage->depth) {
848     case 1:
849     case 4:
850         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
851             /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
852             BYTE* dstbyte;
853
854             for (h = lines-1; h >= 0; h--) {
855                 BYTE dstval;
856                 dstbyte=dstbits;
857                 dstval=0;
858                 for (x = 0; x < dstwidth; x++) {
859                     PALETTEENTRY srcval;
860                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
861                     dstval|=(X11DRV_DIB_GetNearestIndex
862                              (colors, 16,
863                               srcval.peRed,
864                               srcval.peGreen,
865                               srcval.peBlue) << (4-((x&1)<<2)));
866                     if ((x&1)==1) {
867                         *dstbyte++=dstval;
868                         dstval=0;
869                     }
870                 }
871                 if ((dstwidth&1)!=0) {
872                     *dstbyte=dstval;
873                 }
874                 dstbits += linebytes;
875             }
876         } else {
877             goto notsupported;
878         }
879         break;
880
881     case 8:
882         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
883             /* ==== pal 8 bmp -> pal 4 dib ==== */
884             const void* srcbits;
885             const BYTE *srcpixel;
886             BYTE* dstbyte;
887
888             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
889             for (h=0; h<lines; h++) {
890                 BYTE dstval;
891                 srcpixel=srcbits;
892                 dstbyte=dstbits;
893                 dstval=0;
894                 for (x=0; x<dstwidth; x++) {
895                     PALETTEENTRY srcval;
896                     srcval = srccolors[(int)*srcpixel++];
897                     dstval|=(X11DRV_DIB_GetNearestIndex
898                              (colors, 16,
899                               srcval.peRed,
900                               srcval.peGreen,
901                               srcval.peBlue) << (4*(1-(x&1))) );
902                     if ((x&1)==1) {
903                         *dstbyte++=dstval;
904                         dstval=0;
905                     }
906                 }
907                 if ((dstwidth&1)!=0) {
908                     *dstbyte=dstval;
909                 }
910                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
911                 dstbits += linebytes;
912             }
913         } else {
914             goto notsupported;
915         }
916         break;
917
918     case 15:
919     case 16:
920         {
921             const void* srcbits;
922             const WORD* srcpixel;
923             BYTE* dstbyte;
924
925             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
926
927             if (bmpImage->green_mask==0x03e0) {
928                 if (bmpImage->red_mask==0x7c00) {
929                     /* ==== rgb 555 bmp -> pal 4 dib ==== */
930                     for (h=0; h<lines; h++) {
931                         BYTE dstval;
932                         srcpixel=srcbits;
933                         dstbyte=dstbits;
934                         dstval=0;
935                         for (x=0; x<dstwidth; x++) {
936                             WORD srcval;
937                             srcval=*srcpixel++;
938                             dstval|=(X11DRV_DIB_GetNearestIndex
939                                      (colors, 16,
940                                       ((srcval >>  7) & 0xf8) | /* r */
941                                       ((srcval >> 12) & 0x07),
942                                       ((srcval >>  2) & 0xf8) | /* g */
943                                       ((srcval >>  7) & 0x07),
944                                       ((srcval <<  3) & 0xf8) | /* b */
945                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
946                             if ((x&1)==1) {
947                                 *dstbyte++=dstval;
948                                 dstval=0;
949                             }
950                         }
951                         if ((dstwidth&1)!=0) {
952                             *dstbyte=dstval;
953                         }
954                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
955                         dstbits += linebytes;
956                     }
957                 } else if (bmpImage->blue_mask==0x7c00) {
958                     /* ==== bgr 555 bmp -> pal 4 dib ==== */
959                     for (h=0; h<lines; h++) {
960                         WORD dstval;
961                         srcpixel=srcbits;
962                         dstbyte=dstbits;
963                         dstval=0;
964                         for (x=0; x<dstwidth; x++) {
965                             WORD srcval;
966                             srcval=*srcpixel++;
967                             dstval|=(X11DRV_DIB_GetNearestIndex
968                                      (colors, 16,
969                                       ((srcval <<  3) & 0xf8) | /* r */
970                                       ((srcval >>  2) & 0x07),
971                                       ((srcval >>  2) & 0xf8) | /* g */
972                                       ((srcval >>  7) & 0x07),
973                                       ((srcval >>  7) & 0xf8) | /* b */
974                                       ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
975                             if ((x&1)==1) {
976                                 *dstbyte++=dstval;
977                                 dstval=0;
978                             }
979                         }
980                         if ((dstwidth&1)!=0) {
981                             *dstbyte=dstval;
982                         }
983                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
984                         dstbits += linebytes;
985                     }
986                 } else {
987                     goto notsupported;
988                 }
989             } else if (bmpImage->green_mask==0x07e0) {
990                 if (bmpImage->red_mask==0xf800) {
991                     /* ==== rgb 565 bmp -> pal 4 dib ==== */
992                     for (h=0; h<lines; h++) {
993                         BYTE dstval;
994                         srcpixel=srcbits;
995                         dstbyte=dstbits;
996                         dstval=0;
997                         for (x=0; x<dstwidth; x++) {
998                             WORD srcval;
999                             srcval=*srcpixel++;
1000                             dstval|=(X11DRV_DIB_GetNearestIndex
1001                                      (colors, 16,
1002                                       ((srcval >>  8) & 0xf8) | /* r */
1003                                       ((srcval >> 13) & 0x07),
1004                                       ((srcval >>  3) & 0xfc) | /* g */
1005                                       ((srcval >>  9) & 0x03),
1006                                       ((srcval <<  3) & 0xf8) | /* b */
1007                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
1008                             if ((x&1)==1) {
1009                                 *dstbyte++=dstval;
1010                                 dstval=0;
1011                             }
1012                         }
1013                         if ((dstwidth&1)!=0) {
1014                             *dstbyte=dstval;
1015                         }
1016                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1017                         dstbits += linebytes;
1018                     }
1019                 } else if (bmpImage->blue_mask==0xf800) {
1020                     /* ==== bgr 565 bmp -> pal 4 dib ==== */
1021                     for (h=0; h<lines; h++) {
1022                         WORD dstval;
1023                         srcpixel=srcbits;
1024                         dstbyte=dstbits;
1025                         dstval=0;
1026                         for (x=0; x<dstwidth; x++) {
1027                             WORD srcval;
1028                             srcval=*srcpixel++;
1029                             dstval|=(X11DRV_DIB_GetNearestIndex
1030                                      (colors, 16,
1031                                       ((srcval <<  3) & 0xf8) | /* r */
1032                                       ((srcval >>  2) & 0x07),
1033                                       ((srcval >>  3) & 0xfc) | /* g */
1034                                       ((srcval >>  9) & 0x03),
1035                                       ((srcval >>  8) & 0xf8) | /* b */
1036                                       ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1037                             if ((x&1)==1) {
1038                                 *dstbyte++=dstval;
1039                                 dstval=0;
1040                             }
1041                         }
1042                         if ((dstwidth&1)!=0) {
1043                             *dstbyte=dstval;
1044                         }
1045                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1046                         dstbits += linebytes;
1047                     }
1048                 } else {
1049                     goto notsupported;
1050                 }
1051             } else {
1052                 goto notsupported;
1053             }
1054         }
1055         break;
1056
1057     case 24:
1058         if (bmpImage->bits_per_pixel==24) {
1059             const void* srcbits;
1060             const BYTE *srcbyte;
1061             BYTE* dstbyte;
1062
1063             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1064
1065             if (bmpImage->green_mask!=0x00ff00 ||
1066                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1067                 goto notsupported;
1068             } else if (bmpImage->blue_mask==0xff) {
1069                 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1070                 for (h=0; h<lines; h++) {
1071                     srcbyte=srcbits;
1072                     dstbyte=dstbits;
1073                     for (x=0; x<dstwidth/2; x++) {
1074                         /* Do 2 pixels at a time */
1075                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1076                                     (colors, 16,
1077                                      srcbyte[2],
1078                                      srcbyte[1],
1079                                      srcbyte[0]) << 4) |
1080                                     X11DRV_DIB_GetNearestIndex
1081                                     (colors, 16,
1082                                      srcbyte[5],
1083                                      srcbyte[4],
1084                                      srcbyte[3]);
1085                         srcbyte+=6;
1086                     }
1087                     if (dstwidth&1) {
1088                         /* And the the odd pixel */
1089                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1090                                     (colors, 16,
1091                                      srcbyte[2],
1092                                      srcbyte[1],
1093                                      srcbyte[0]) << 4);
1094                     }
1095                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1096                     dstbits += linebytes;
1097                 }
1098             } else {
1099                 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1100                 for (h=0; h<lines; h++) {
1101                     srcbyte=srcbits;
1102                     dstbyte=dstbits;
1103                     for (x=0; x<dstwidth/2; x++) {
1104                         /* Do 2 pixels at a time */
1105                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1106                                     (colors, 16,
1107                                      srcbyte[0],
1108                                      srcbyte[1],
1109                                      srcbyte[2]) << 4) |
1110                                     X11DRV_DIB_GetNearestIndex
1111                                     (colors, 16,
1112                                      srcbyte[3],
1113                                      srcbyte[4],
1114                                      srcbyte[5]);
1115                         srcbyte+=6;
1116                     }
1117                     if (dstwidth&1) {
1118                         /* And the the odd pixel */
1119                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1120                                     (colors, 16,
1121                                      srcbyte[0],
1122                                      srcbyte[1],
1123                                      srcbyte[2]) << 4);
1124                     }
1125                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1126                     dstbits += linebytes;
1127                 }
1128             }
1129             break;
1130         }
1131         /* Fall through */
1132
1133     case 32:
1134         {
1135             const void* srcbits;
1136             const BYTE *srcbyte;
1137             BYTE* dstbyte;
1138
1139             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1140
1141             if (bmpImage->green_mask!=0x00ff00 ||
1142                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1143                 goto notsupported;
1144             } else if (bmpImage->blue_mask==0xff) {
1145                 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1146                 for (h=0; h<lines; h++) {
1147                     srcbyte=srcbits;
1148                     dstbyte=dstbits;
1149                     for (x=0; x<dstwidth/2; x++) {
1150                         /* Do 2 pixels at a time */
1151                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1152                                     (colors, 16,
1153                                      srcbyte[2],
1154                                      srcbyte[1],
1155                                      srcbyte[0]) << 4) |
1156                                     X11DRV_DIB_GetNearestIndex
1157                                     (colors, 16,
1158                                      srcbyte[6],
1159                                      srcbyte[5],
1160                                      srcbyte[4]);
1161                         srcbyte+=8;
1162                     }
1163                     if (dstwidth&1) {
1164                         /* And the the odd pixel */
1165                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1166                                     (colors, 16,
1167                                      srcbyte[2],
1168                                      srcbyte[1],
1169                                      srcbyte[0]) << 4);
1170                     }
1171                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1172                     dstbits += linebytes;
1173                 }
1174             } else {
1175                 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1176                 for (h=0; h<lines; h++) {
1177                     srcbyte=srcbits;
1178                     dstbyte=dstbits;
1179                     for (x=0; x<dstwidth/2; x++) {
1180                         /* Do 2 pixels at a time */
1181                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1182                                     (colors, 16,
1183                                      srcbyte[0],
1184                                      srcbyte[1],
1185                                      srcbyte[2]) << 4) |
1186                                     X11DRV_DIB_GetNearestIndex
1187                                     (colors, 16,
1188                                      srcbyte[4],
1189                                      srcbyte[5],
1190                                      srcbyte[6]);
1191                         srcbyte+=8;
1192                     }
1193                     if (dstwidth&1) {
1194                         /* And the the odd pixel */
1195                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1196                                     (colors, 16,
1197                                      srcbyte[0],
1198                                      srcbyte[1],
1199                                      srcbyte[2]) << 4);
1200                     }
1201                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1202                     dstbits += linebytes;
1203                 }
1204             }
1205         }
1206         break;
1207
1208     default:
1209     notsupported:
1210         {
1211             BYTE* dstbyte;
1212
1213             /* ==== any bmp format -> pal 4 dib ==== */
1214             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1215                   bmpImage->bits_per_pixel, bmpImage->red_mask,
1216                   bmpImage->green_mask, bmpImage->blue_mask );
1217             for (h=lines-1; h>=0; h--) {
1218                 dstbyte=dstbits;
1219                 for (x=0; x<(dstwidth & ~1); x+=2) {
1220                     *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1221                         X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1222                 }
1223                 if (dstwidth & 1) {
1224                     *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1225                 }
1226                 dstbits += linebytes;
1227             }
1228         }
1229         break;
1230     }
1231 }
1232
1233 /***********************************************************************
1234  *           X11DRV_DIB_SetImageBits_RLE4
1235  *
1236  * SetDIBits for a 4-bit deep compressed DIB.
1237  */
1238 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1239                                           DWORD width, DWORD dstwidth,
1240                                           int left, int *colors,
1241                                           XImage *bmpImage )
1242 {
1243     int x = 0, y = lines - 1, c, length;
1244     const BYTE *begin = bits;
1245
1246     while (y >= 0)
1247     {
1248         length = *bits++;
1249         if (length) {   /* encoded */
1250             c = *bits++;
1251             while (length--) {
1252                 if (x >= width) break;
1253                 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1254                 if (!length--) break;
1255                 if (x >= width) break;
1256                 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1257             }
1258         } else {
1259             length = *bits++;
1260             switch (length)
1261             {
1262             case RLE_EOL:
1263                 x = 0;
1264                 y--;
1265                 break;
1266
1267             case RLE_END:
1268                 return;
1269
1270             case RLE_DELTA:
1271                 x += *bits++;
1272                 y -= *bits++;
1273                 break;
1274
1275             default: /* absolute */
1276                 while (length--) {
1277                     c = *bits++;
1278                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1279                     if (!length--) break;
1280                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1281                 }
1282                 if ((bits - begin) & 1)
1283                     bits++;
1284             }
1285         }
1286     }
1287 }
1288
1289
1290
1291 /***********************************************************************
1292  *           X11DRV_DIB_SetImageBits_8
1293  *
1294  * SetDIBits for an 8-bit deep DIB.
1295  */
1296 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1297                                 DWORD srcwidth, DWORD dstwidth, int left,
1298                                 const int *colors, XImage *bmpImage,
1299                                 DWORD linebytes )
1300 {
1301     DWORD x;
1302     int h;
1303     const BYTE* srcbyte;
1304     BYTE* dstbits;
1305
1306     if (lines < 0 )
1307     {
1308         lines = -lines;
1309         srcbits = srcbits + linebytes * (lines-1);
1310         linebytes = -linebytes;
1311     }
1312     srcbits += left;
1313     srcbyte = srcbits;
1314
1315     switch (bmpImage->depth) {
1316     case 15:
1317     case 16:
1318 #if defined(__i386__) && defined(__GNUC__)
1319         /* Some X servers might have 32 bit/ 16bit deep pixel */
1320         if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
1321             (ImageByteOrder(gdi_display)==LSBFirst) )
1322         {
1323             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1324             /* FIXME: Does this really handle all these cases correctly? */
1325             /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1326             for (h = lines ; h--; ) {
1327                 int _cl1,_cl2; /* temp outputs for asm below */
1328                 /* Borrowed from DirectDraw */
1329                 __asm__ __volatile__(
1330                 "xor %%eax,%%eax\n"
1331                 "cld\n"
1332                 "1:\n"
1333                 "    lodsb\n"
1334                 "    movw (%%edx,%%eax,4),%%ax\n"
1335                 "    stosw\n"
1336                 "      xor %%eax,%%eax\n"
1337                 "    loop 1b\n"
1338                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1339                 :"S" (srcbyte),
1340                  "D" (dstbits),
1341                  "c" (dstwidth),
1342                  "d" (colors)
1343                 :"eax", "cc", "memory"
1344                 );
1345                 srcbyte = (srcbits += linebytes);
1346                 dstbits -= bmpImage->bytes_per_line;
1347             }
1348             return;
1349         }
1350         break;
1351 #endif
1352     case 24:
1353     case 32:
1354 #if defined(__i386__) && defined(__GNUC__)
1355         if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
1356             (ImageByteOrder(gdi_display)==LSBFirst) )
1357         {
1358             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1359             /* FIXME: Does this really handle both cases correctly? */
1360             /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1361             for (h = lines ; h--; ) {
1362                 int _cl1,_cl2; /* temp outputs for asm below */
1363                 /* Borrowed from DirectDraw */
1364                 __asm__ __volatile__(
1365                 "xor %%eax,%%eax\n"
1366                 "cld\n"
1367                 "1:\n"
1368                 "    lodsb\n"
1369                 "    movl (%%edx,%%eax,4),%%eax\n"
1370                 "    stosl\n"
1371                 "      xor %%eax,%%eax\n"
1372                 "    loop 1b\n"
1373                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1374                 :"S" (srcbyte),
1375                  "D" (dstbits),
1376                  "c" (dstwidth),
1377                  "d" (colors)
1378                 :"eax", "cc", "memory"
1379                 );
1380                 srcbyte = (srcbits += linebytes);
1381                 dstbits -= bmpImage->bytes_per_line;
1382             }
1383             return;
1384         }
1385         break;
1386 #endif
1387     default:
1388         break; /* use slow generic case below */
1389     }
1390
1391     /* ==== pal 8 dib -> any bmp format ==== */
1392     for (h=lines-1; h>=0; h--) {
1393         for (x=left; x<dstwidth+left; x++) {
1394             XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1395         }
1396         srcbyte = (srcbits += linebytes);
1397     }
1398 }
1399
1400 /***********************************************************************
1401  *           X11DRV_DIB_GetImageBits_8
1402  *
1403  * GetDIBits for an 8-bit deep DIB.
1404  */
1405 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1406                                        DWORD srcwidth, DWORD dstwidth,
1407                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
1408                                        XImage *bmpImage, DWORD linebytes )
1409 {
1410     DWORD x;
1411     int h;
1412     BYTE* dstbyte;
1413
1414     if (lines < 0 )
1415     {
1416        lines = -lines;
1417        dstbits = dstbits + ( linebytes * (lines-1) );
1418        linebytes = -linebytes;
1419     }
1420
1421     /*
1422      * Hack for now
1423      * This condition is true when GetImageBits has been called by
1424      * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1425      * 256 colormaps, so we'll just use for for GetDIBits calls.
1426      * (In somes cases, in a updateDIBSection, the returned colors are bad too)
1427      */
1428     if (!srccolors) goto updatesection;
1429
1430     switch (bmpImage->depth) {
1431     case 1:
1432     case 4:
1433         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1434
1435             /* ==== pal 1 bmp -> pal 8 dib ==== */
1436             /* ==== pal 4 bmp -> pal 8 dib ==== */
1437             for (h=lines-1; h>=0; h--) {
1438                 dstbyte=dstbits;
1439                 for (x=0; x<dstwidth; x++) {
1440                     PALETTEENTRY srcval;
1441                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
1442                     *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1443                                                           srcval.peRed,
1444                                                           srcval.peGreen,
1445                                                           srcval.peBlue);
1446                 }
1447                 dstbits += linebytes;
1448             }
1449         } else {
1450             goto notsupported;
1451         }
1452         break;
1453
1454     case 8:
1455        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1456             /* ==== pal 8 bmp -> pal 8 dib ==== */
1457            const void* srcbits;
1458            const BYTE* srcpixel;
1459
1460            srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1461            for (h=0; h<lines; h++) {
1462                srcpixel=srcbits;
1463                dstbyte=dstbits;
1464                for (x = 0; x < dstwidth; x++) {
1465                    PALETTEENTRY srcval;
1466                    srcval=srccolors[(int)*srcpixel++];
1467                    *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1468                                                          srcval.peRed,
1469                                                          srcval.peGreen,
1470                                                          srcval.peBlue);
1471                }
1472                srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1473                dstbits += linebytes;
1474            }
1475        } else {
1476            goto notsupported;
1477        }
1478        break;
1479
1480     case 15:
1481     case 16:
1482         {
1483             const void* srcbits;
1484             const WORD* srcpixel;
1485             BYTE* dstbyte;
1486
1487             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1488
1489             if (bmpImage->green_mask==0x03e0) {
1490                 if (bmpImage->red_mask==0x7c00) {
1491                     /* ==== rgb 555 bmp -> pal 8 dib ==== */
1492                     for (h=0; h<lines; h++) {
1493                         srcpixel=srcbits;
1494                         dstbyte=dstbits;
1495                         for (x=0; x<dstwidth; x++) {
1496                             WORD srcval;
1497                             srcval=*srcpixel++;
1498                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1499                                 (colors, 256,
1500                                  ((srcval >>  7) & 0xf8) | /* r */
1501                                  ((srcval >> 12) & 0x07),
1502                                  ((srcval >>  2) & 0xf8) | /* g */
1503                                  ((srcval >>  7) & 0x07),
1504                                  ((srcval <<  3) & 0xf8) | /* b */
1505                                  ((srcval >>  2) & 0x07) );
1506                         }
1507                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1508                         dstbits += linebytes;
1509                     }
1510                 } else if (bmpImage->blue_mask==0x7c00) {
1511                     /* ==== bgr 555 bmp -> pal 8 dib ==== */
1512                     for (h=0; h<lines; h++) {
1513                         srcpixel=srcbits;
1514                         dstbyte=dstbits;
1515                         for (x=0; x<dstwidth; x++) {
1516                             WORD srcval;
1517                             srcval=*srcpixel++;
1518                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1519                                 (colors, 256,
1520                                  ((srcval <<  3) & 0xf8) | /* r */
1521                                  ((srcval >>  2) & 0x07),
1522                                  ((srcval >>  2) & 0xf8) | /* g */
1523                                  ((srcval >>  7) & 0x07),
1524                                  ((srcval >>  7) & 0xf8) | /* b */
1525                                  ((srcval >> 12) & 0x07) );
1526                         }
1527                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1528                         dstbits += linebytes;
1529                     }
1530                 } else {
1531                     goto notsupported;
1532                 }
1533             } else if (bmpImage->green_mask==0x07e0) {
1534                 if (bmpImage->red_mask==0xf800) {
1535                     /* ==== rgb 565 bmp -> pal 8 dib ==== */
1536                     for (h=0; h<lines; h++) {
1537                         srcpixel=srcbits;
1538                         dstbyte=dstbits;
1539                         for (x=0; x<dstwidth; x++) {
1540                             WORD srcval;
1541                             srcval=*srcpixel++;
1542                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1543                                 (colors, 256,
1544                                  ((srcval >>  8) & 0xf8) | /* r */
1545                                  ((srcval >> 13) & 0x07),
1546                                  ((srcval >>  3) & 0xfc) | /* g */
1547                                  ((srcval >>  9) & 0x03),
1548                                  ((srcval <<  3) & 0xf8) | /* b */
1549                                  ((srcval >>  2) & 0x07) );
1550                         }
1551                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1552                         dstbits += linebytes;
1553                     }
1554                 } else if (bmpImage->blue_mask==0xf800) {
1555                     /* ==== bgr 565 bmp -> pal 8 dib ==== */
1556                     for (h=0; h<lines; h++) {
1557                         srcpixel=srcbits;
1558                         dstbyte=dstbits;
1559                         for (x=0; x<dstwidth; x++) {
1560                             WORD srcval;
1561                             srcval=*srcpixel++;
1562                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1563                                 (colors, 256,
1564                                  ((srcval <<  3) & 0xf8) | /* r */
1565                                  ((srcval >>  2) & 0x07),
1566                                  ((srcval >>  3) & 0xfc) | /* g */
1567                                  ((srcval >>  9) & 0x03),
1568                                  ((srcval >>  8) & 0xf8) | /* b */
1569                                  ((srcval >> 13) & 0x07) );
1570                         }
1571                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1572                         dstbits += linebytes;
1573                     }
1574                 } else {
1575                     goto notsupported;
1576                 }
1577             } else {
1578                 goto notsupported;
1579             }
1580         }
1581         break;
1582
1583     case 24:
1584     case 32:
1585         {
1586             const void* srcbits;
1587             const BYTE *srcbyte;
1588             BYTE* dstbyte;
1589             int bytes_per_pixel;
1590
1591             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1592             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1593
1594             if (bmpImage->green_mask!=0x00ff00 ||
1595                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1596                 goto notsupported;
1597             } else if (bmpImage->blue_mask==0xff) {
1598                 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1599                 for (h=0; h<lines; h++) {
1600                     srcbyte=srcbits;
1601                     dstbyte=dstbits;
1602                     for (x=0; x<dstwidth; x++) {
1603                         *dstbyte++=X11DRV_DIB_GetNearestIndex
1604                             (colors, 256,
1605                              srcbyte[2],
1606                              srcbyte[1],
1607                              srcbyte[0]);
1608                         srcbyte+=bytes_per_pixel;
1609                     }
1610                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1611                     dstbits += linebytes;
1612                 }
1613             } else {
1614                 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1615                 for (h=0; h<lines; h++) {
1616                     srcbyte=srcbits;
1617                     dstbyte=dstbits;
1618                     for (x=0; x<dstwidth; x++) {
1619                         *dstbyte++=X11DRV_DIB_GetNearestIndex
1620                             (colors, 256,
1621                              srcbyte[0],
1622                              srcbyte[1],
1623                              srcbyte[2]);
1624                         srcbyte+=bytes_per_pixel;
1625                     }
1626                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1627                     dstbits += linebytes;
1628                 }
1629             }
1630         }
1631         break;
1632
1633     default:
1634     notsupported:
1635         WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1636               bmpImage->depth, bmpImage->red_mask,
1637               bmpImage->green_mask, bmpImage->blue_mask );
1638     updatesection:
1639         /* ==== any bmp format -> pal 8 dib ==== */
1640         for (h=lines-1; h>=0; h--) {
1641             dstbyte=dstbits;
1642             for (x=0; x<dstwidth; x++) {
1643                 *dstbyte=X11DRV_DIB_MapColor
1644                     ((int*)colors, 256,
1645                      XGetPixel(bmpImage, x, h), *dstbyte);
1646                 dstbyte++;
1647             }
1648             dstbits += linebytes;
1649         }
1650         break;
1651     }
1652 }
1653
1654 /***********************************************************************
1655  *            X11DRV_DIB_SetImageBits_RLE8
1656  *
1657  * SetDIBits for an 8-bit deep compressed DIB.
1658  *
1659  * This function rewritten 941113 by James Youngman.  WINE blew out when I
1660  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1661  *
1662  * This was because the algorithm assumed that all RLE8 bitmaps end with the
1663  * 'End of bitmap' escape code.  This code is very much laxer in what it
1664  * allows to end the expansion.  Possibly too lax.  See the note by
1665  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
1666  * bitmap should end with RleEnd, but on the other hand, software exists
1667  * that produces ones that don't and Windows 3.1 doesn't complain a bit
1668  * about it.
1669  *
1670  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
1671  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
1672  *                                              [JAY]
1673  */
1674 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1675                                           DWORD width, DWORD dstwidth,
1676                                           int left, int *colors,
1677                                           XImage *bmpImage )
1678 {
1679     int x;                      /* X-positon on each line.  Increases. */
1680     int y;                      /* Line #.  Starts at lines-1, decreases */
1681     const BYTE *pIn = bits;     /* Pointer to current position in bits */
1682     BYTE length;                /* The length pf a run */
1683     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
1684
1685     /*
1686      * Note that the bitmap data is stored by Windows starting at the
1687      * bottom line of the bitmap and going upwards.  Within each line,
1688      * the data is stored left-to-right.  That's the reason why line
1689      * goes from lines-1 to 0.                  [JAY]
1690      */
1691
1692     x = 0;
1693     y = lines - 1;
1694     while (y >= 0)
1695     {
1696         length = *pIn++;
1697
1698         /*
1699          * If the length byte is not zero (which is the escape value),
1700          * We have a run of length pixels all the same colour.  The colour
1701          * index is stored next.
1702          *
1703          * If the length byte is zero, we need to read the next byte to
1704          * know what to do.                     [JAY]
1705          */
1706         if (length != 0)
1707         {
1708             /*
1709              * [Run-Length] Encoded mode
1710              */
1711             int color = colors[*pIn++];
1712             while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
1713         }
1714         else
1715         {
1716             /*
1717              * Escape codes (may be an absolute sequence though)
1718              */
1719             escape_code = (*pIn++);
1720             switch(escape_code)
1721             {
1722             case RLE_EOL:
1723                 x = 0;
1724                 y--;
1725                 break;
1726
1727             case RLE_END:
1728                 /* Not all RLE8 bitmaps end with this code.  For
1729                  * example, Paint Shop Pro produces some that don't.
1730                  * That's (I think) what caused the previous
1731                  * implementation to fail.  [JAY]
1732                  */
1733                 return;
1734
1735             case RLE_DELTA:
1736                 x += (*pIn++);
1737                 y -= (*pIn++);
1738                 break;
1739
1740             default:  /* switch to absolute mode */
1741                 length = escape_code;
1742                 while (length--)
1743                 {
1744                     int color = colors[*pIn++];
1745                     if (x >= dstwidth)
1746                     {
1747                         pIn += length;
1748                         break;
1749                     }
1750                     XPutPixel(bmpImage, x++, y, color);
1751                 }
1752                 /*
1753                  * If you think for a moment you'll realise that the
1754                  * only time we could ever possibly read an odd
1755                  * number of bytes is when there is a 0x00 (escape),
1756                  * a value >0x02 (absolute mode) and then an odd-
1757                  * length run.  Therefore this is the only place we
1758                  * need to worry about it.  Everywhere else the
1759                  * bytes are always read in pairs.  [JAY]
1760                  */
1761                 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1762                 break;
1763             } /* switch (escape_code) : Escape sequence */
1764         }
1765     }
1766 }
1767
1768
1769 /***********************************************************************
1770  *           X11DRV_DIB_SetImageBits_16
1771  *
1772  * SetDIBits for a 16-bit deep DIB.
1773  */
1774 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1775                                  DWORD srcwidth, DWORD dstwidth, int left,
1776                                        X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1777                                        XImage *bmpImage, DWORD linebytes )
1778 {
1779     DWORD x;
1780     int h;
1781     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1782
1783     if (lines < 0 )
1784     {
1785         lines = -lines;
1786         srcbits = srcbits + ( linebytes * (lines-1));
1787         linebytes = -linebytes;
1788     }
1789
1790     switch (bmpImage->depth)
1791     {
1792     case 15:
1793     case 16:
1794         {
1795             char* dstbits;
1796
1797             srcbits=srcbits+left*2;
1798             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1799
1800             if (bmpImage->green_mask==0x03e0) {
1801                 if (gSrc==bmpImage->green_mask) {
1802                     if (rSrc==bmpImage->red_mask) {
1803                         /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1804                         /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1805                         convs->Convert_5x5_asis
1806                             (dstwidth,lines,
1807                              srcbits,linebytes,
1808                              dstbits,-bmpImage->bytes_per_line);
1809                     } else if (rSrc==bmpImage->blue_mask) {
1810                         /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1811                         /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1812                         convs->Convert_555_reverse
1813                             (dstwidth,lines,
1814                              srcbits,linebytes,
1815                              dstbits,-bmpImage->bytes_per_line);
1816                     }
1817                 } else {
1818                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1819                         /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1820                         /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1821                         convs->Convert_565_to_555_asis
1822                             (dstwidth,lines,
1823                              srcbits,linebytes,
1824                              dstbits,-bmpImage->bytes_per_line);
1825                     } else {
1826                         /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1827                         /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1828                         convs->Convert_565_to_555_reverse
1829                             (dstwidth,lines,
1830                              srcbits,linebytes,
1831                              dstbits,-bmpImage->bytes_per_line);
1832                     }
1833                 }
1834             } else if (bmpImage->green_mask==0x07e0) {
1835                 if (gSrc==bmpImage->green_mask) {
1836                     if (rSrc==bmpImage->red_mask) {
1837                         /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1838                         /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1839                         convs->Convert_5x5_asis
1840                             (dstwidth,lines,
1841                              srcbits,linebytes,
1842                              dstbits,-bmpImage->bytes_per_line);
1843                     } else {
1844                         /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1845                         /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1846                         convs->Convert_565_reverse
1847                             (dstwidth,lines,
1848                              srcbits,linebytes,
1849                              dstbits,-bmpImage->bytes_per_line);
1850                     }
1851                 } else {
1852                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1853                         /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1854                         /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1855                         convs->Convert_555_to_565_asis
1856                             (dstwidth,lines,
1857                              srcbits,linebytes,
1858                              dstbits,-bmpImage->bytes_per_line);
1859                     } else {
1860                         /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1861                         /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1862                         convs->Convert_555_to_565_reverse
1863                             (dstwidth,lines,
1864                              srcbits,linebytes,
1865                              dstbits,-bmpImage->bytes_per_line);
1866                     }
1867                 }
1868             } else {
1869                 goto notsupported;
1870             }
1871         }
1872         break;
1873
1874     case 24:
1875         if (bmpImage->bits_per_pixel==24) {
1876             char* dstbits;
1877
1878             srcbits=srcbits+left*2;
1879             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1880
1881             if (bmpImage->green_mask!=0x00ff00 ||
1882                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1883                 goto notsupported;
1884             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1885                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1886                 if (gSrc==0x03e0) {
1887                     /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1888                     /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1889                     convs->Convert_555_to_888_asis
1890                         (dstwidth,lines,
1891                          srcbits,linebytes,
1892                          dstbits,-bmpImage->bytes_per_line);
1893                 } else {
1894                     /* ==== rgb 565 dib -> rgb 888 bmp ==== */
1895                     /* ==== bgr 565 dib -> bgr 888 bmp ==== */
1896                     convs->Convert_565_to_888_asis
1897                         (dstwidth,lines,
1898                          srcbits,linebytes,
1899                          dstbits,-bmpImage->bytes_per_line);
1900                 }
1901             } else {
1902                 if (gSrc==0x03e0) {
1903                     /* ==== rgb 555 dib -> bgr 888 bmp ==== */
1904                     /* ==== bgr 555 dib -> rgb 888 bmp ==== */
1905                     convs->Convert_555_to_888_reverse
1906                         (dstwidth,lines,
1907                          srcbits,linebytes,
1908                          dstbits,-bmpImage->bytes_per_line);
1909                 } else {
1910                     /* ==== rgb 565 dib -> bgr 888 bmp ==== */
1911                     /* ==== bgr 565 dib -> rgb 888 bmp ==== */
1912                     convs->Convert_565_to_888_reverse
1913                         (dstwidth,lines,
1914                          srcbits,linebytes,
1915                          dstbits,-bmpImage->bytes_per_line);
1916                 }
1917             }
1918             break;
1919         }
1920         /* Fall through */
1921
1922     case 32:
1923         {
1924             char* dstbits;
1925
1926             srcbits=srcbits+left*2;
1927             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1928
1929             if (bmpImage->green_mask!=0x00ff00 ||
1930                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1931                 goto notsupported;
1932             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1933                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1934                 if (gSrc==0x03e0) {
1935                     /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
1936                     /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
1937                     convs->Convert_555_to_0888_asis
1938                         (dstwidth,lines,
1939                          srcbits,linebytes,
1940                          dstbits,-bmpImage->bytes_per_line);
1941                 } else {
1942                     /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
1943                     /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
1944                     convs->Convert_565_to_0888_asis
1945                         (dstwidth,lines,
1946                          srcbits,linebytes,
1947                          dstbits,-bmpImage->bytes_per_line);
1948                 }
1949             } else {
1950                 if (gSrc==0x03e0) {
1951                     /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
1952                     /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
1953                     convs->Convert_555_to_0888_reverse
1954                         (dstwidth,lines,
1955                          srcbits,linebytes,
1956                          dstbits,-bmpImage->bytes_per_line);
1957                 } else {
1958                     /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
1959                     /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
1960                     convs->Convert_565_to_0888_reverse
1961                         (dstwidth,lines,
1962                          srcbits,linebytes,
1963                          dstbits,-bmpImage->bytes_per_line);
1964                 }
1965             }
1966         }
1967         break;
1968
1969     default:
1970     notsupported:
1971         WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
1972               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
1973               bmpImage->green_mask, bmpImage->blue_mask );
1974         /* fall through */
1975     case 1:
1976     case 4:
1977     case 8:
1978         {
1979             /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
1980             const WORD* srcpixel;
1981             int rShift1,gShift1,bShift1;
1982             int rShift2,gShift2,bShift2;
1983             BYTE gMask1,gMask2;
1984
1985             /* Set color scaling values */
1986             rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
1987             gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
1988             bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
1989             rShift2=rShift1+5;
1990             gShift2=gShift1+5;
1991             bShift2=bShift1+5;
1992             if (gSrc==0x03e0) {
1993                 /* Green has 5 bits, like the others */
1994                 gMask1=0xf8;
1995                 gMask2=0x07;
1996             } else {
1997                 /* Green has 6 bits, not 5. Compensate. */
1998                 gShift1++;
1999                 gShift2+=2;
2000                 gMask1=0xfc;
2001                 gMask2=0x03;
2002             }
2003
2004             srcbits+=2*left;
2005
2006             /* We could split it into four separate cases to optimize
2007              * but it is probably not worth it.
2008              */
2009             for (h=lines-1; h>=0; h--) {
2010                 srcpixel=(const WORD*)srcbits;
2011                 for (x=left; x<dstwidth+left; x++) {
2012                     DWORD srcval;
2013                     BYTE red,green,blue;
2014                     srcval=*srcpixel++ << 16;
2015                     red=  ((srcval >> rShift1) & 0xf8) |
2016                         ((srcval >> rShift2) & 0x07);
2017                     green=((srcval >> gShift1) & gMask1) |
2018                         ((srcval >> gShift2) & gMask2);
2019                     blue= ((srcval >> bShift1) & 0xf8) |
2020                         ((srcval >> bShift2) & 0x07);
2021                     XPutPixel(bmpImage, x, h,
2022                               X11DRV_PALETTE_ToPhysical
2023                               (physDev, RGB(red,green,blue)));
2024                 }
2025                 srcbits += linebytes;
2026             }
2027         }
2028         break;
2029     }
2030 }
2031
2032
2033 /***********************************************************************
2034  *           X11DRV_DIB_GetImageBits_16
2035  *
2036  * GetDIBits for an 16-bit deep DIB.
2037  */
2038 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
2039                                         DWORD dstwidth, DWORD srcwidth,
2040                                         PALETTEENTRY *srccolors,
2041                                         DWORD rDst, DWORD gDst, DWORD bDst,
2042                                         XImage *bmpImage, DWORD dibpitch )
2043 {
2044     DWORD x;
2045     int h;
2046     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2047
2048     DWORD linebytes = dibpitch;
2049
2050     if (lines < 0 )
2051     {
2052         lines = -lines;
2053         dstbits = dstbits + ( linebytes * (lines-1));
2054         linebytes = -linebytes;
2055     }
2056
2057     switch (bmpImage->depth)
2058     {
2059     case 15:
2060     case 16:
2061         {
2062             const char* srcbits;
2063
2064             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2065
2066             if (bmpImage->green_mask==0x03e0) {
2067                 if (gDst==bmpImage->green_mask) {
2068                     if (rDst==bmpImage->red_mask) {
2069                         /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2070                         /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2071                         convs->Convert_5x5_asis
2072                             (dstwidth,lines,
2073                              srcbits,-bmpImage->bytes_per_line,
2074                              dstbits,linebytes);
2075                     } else {
2076                         /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2077                         /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2078                         convs->Convert_555_reverse
2079                             (dstwidth,lines,
2080                              srcbits,-bmpImage->bytes_per_line,
2081                              dstbits,linebytes);
2082                     }
2083                 } else {
2084                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2085                         /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2086                         /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2087                         convs->Convert_555_to_565_asis
2088                             (dstwidth,lines,
2089                              srcbits,-bmpImage->bytes_per_line,
2090                              dstbits,linebytes);
2091                     } else {
2092                         /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2093                         /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2094                         convs->Convert_555_to_565_reverse
2095                             (dstwidth,lines,
2096                              srcbits,-bmpImage->bytes_per_line,
2097                              dstbits,linebytes);
2098                     }
2099                 }
2100             } else if (bmpImage->green_mask==0x07e0) {
2101                 if (gDst==bmpImage->green_mask) {
2102                     if (rDst == bmpImage->red_mask) {
2103                         /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2104                         /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2105                         convs->Convert_5x5_asis
2106                             (dstwidth,lines,
2107                              srcbits,-bmpImage->bytes_per_line,
2108                              dstbits,linebytes);
2109                     } else {
2110                         /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2111                         /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2112                         convs->Convert_565_reverse
2113                             (dstwidth,lines,
2114                              srcbits,-bmpImage->bytes_per_line,
2115                              dstbits,linebytes);
2116                     }
2117                 } else {
2118                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2119                         /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2120                         /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2121                         convs->Convert_565_to_555_asis
2122                             (dstwidth,lines,
2123                              srcbits,-bmpImage->bytes_per_line,
2124                              dstbits,linebytes);
2125                     } else {
2126                         /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2127                         /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2128                         convs->Convert_565_to_555_reverse
2129                             (dstwidth,lines,
2130                              srcbits,-bmpImage->bytes_per_line,
2131                              dstbits,linebytes);
2132                     }
2133                 }
2134             } else {
2135                 goto notsupported;
2136             }
2137         }
2138         break;
2139
2140     case 24:
2141         if (bmpImage->bits_per_pixel == 24) {
2142             const char* srcbits;
2143
2144             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2145
2146             if (bmpImage->green_mask!=0x00ff00 ||
2147                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2148                 goto notsupported;
2149             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2150                     (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2151                 if (gDst==0x03e0) {
2152                     /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2153                     /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2154                     convs->Convert_888_to_555_asis
2155                         (dstwidth,lines,
2156                          srcbits,-bmpImage->bytes_per_line,
2157                          dstbits,linebytes);
2158                 } else {
2159                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2160                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2161                     convs->Convert_888_to_565_asis
2162                         (dstwidth,lines,
2163                          srcbits,-bmpImage->bytes_per_line,
2164                          dstbits,linebytes);
2165                 }
2166             } else {
2167                 if (gDst==0x03e0) {
2168                     /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2169                     /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2170                     convs->Convert_888_to_555_reverse
2171                         (dstwidth,lines,
2172                          srcbits,-bmpImage->bytes_per_line,
2173                          dstbits,linebytes);
2174                 } else {
2175                     /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2176                     /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2177                     convs->Convert_888_to_565_reverse
2178                         (dstwidth,lines,
2179                          srcbits,-bmpImage->bytes_per_line,
2180                          dstbits,linebytes);
2181                 }
2182             }
2183             break;
2184         }
2185         /* Fall through */
2186
2187     case 32:
2188         {
2189             const char* srcbits;
2190
2191             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2192
2193             if (bmpImage->green_mask!=0x00ff00 ||
2194                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2195                 goto notsupported;
2196             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2197                        (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2198                 if (gDst==0x03e0) {
2199                     /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2200                     /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2201                     convs->Convert_0888_to_555_asis
2202                         (dstwidth,lines,
2203                          srcbits,-bmpImage->bytes_per_line,
2204                          dstbits,linebytes);
2205                 } else {
2206                     /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2207                     /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2208                     convs->Convert_0888_to_565_asis
2209                         (dstwidth,lines,
2210                          srcbits,-bmpImage->bytes_per_line,
2211                          dstbits,linebytes);
2212                 }
2213             } else {
2214                 if (gDst==0x03e0) {
2215                     /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2216                     /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2217                     convs->Convert_0888_to_555_reverse
2218                         (dstwidth,lines,
2219                          srcbits,-bmpImage->bytes_per_line,
2220                          dstbits,linebytes);
2221                 } else {
2222                     /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2223                     /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2224                     convs->Convert_0888_to_565_reverse
2225                         (dstwidth,lines,
2226                          srcbits,-bmpImage->bytes_per_line,
2227                          dstbits,linebytes);
2228                 }
2229             }
2230         }
2231         break;
2232
2233     case 1:
2234     case 4:
2235         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2236             /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2237             int rShift,gShift,bShift;
2238             WORD* dstpixel;
2239
2240             /* Shift everything 16 bits left so that all shifts are >0,
2241              * even for BGR DIBs. Then a single >> 16 will bring everything
2242              * back into place.
2243              */
2244             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2245             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2246             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2247             if (gDst==0x07e0) {
2248                 /* 6 bits for the green */
2249                 gShift++;
2250             }
2251             rDst=rDst << 16;
2252             gDst=gDst << 16;
2253             bDst=bDst << 16;
2254             for (h = lines - 1; h >= 0; h--) {
2255                 dstpixel=(LPWORD)dstbits;
2256                 for (x = 0; x < dstwidth; x++) {
2257                     PALETTEENTRY srcval;
2258                     DWORD dstval;
2259                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2260                     dstval=((srcval.peRed   << rShift) & rDst) |
2261                            ((srcval.peGreen << gShift) & gDst) |
2262                            ((srcval.peBlue  << bShift) & bDst);
2263                     *dstpixel++=dstval >> 16;
2264                 }
2265                 dstbits += linebytes;
2266             }
2267         } else {
2268             goto notsupported;
2269         }
2270         break;
2271
2272     case 8:
2273         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2274             /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2275             int rShift,gShift,bShift;
2276             const BYTE* srcbits;
2277             const BYTE* srcpixel;
2278             WORD* dstpixel;
2279
2280             /* Shift everything 16 bits left so that all shifts are >0,
2281              * even for BGR DIBs. Then a single >> 16 will bring everything
2282              * back into place.
2283              */
2284             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2285             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2286             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2287             if (gDst==0x07e0) {
2288                 /* 6 bits for the green */
2289                 gShift++;
2290             }
2291             rDst=rDst << 16;
2292             gDst=gDst << 16;
2293             bDst=bDst << 16;
2294             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2295             for (h=0; h<lines; h++) {
2296                 srcpixel=srcbits;
2297                 dstpixel=(LPWORD)dstbits;
2298                 for (x = 0; x < dstwidth; x++) {
2299                     PALETTEENTRY srcval;
2300                     DWORD dstval;
2301                     srcval=srccolors[(int)*srcpixel++];
2302                     dstval=((srcval.peRed   << rShift) & rDst) |
2303                            ((srcval.peGreen << gShift) & gDst) |
2304                            ((srcval.peBlue  << bShift) & bDst);
2305                     *dstpixel++=dstval >> 16;
2306                 }
2307                 srcbits -= bmpImage->bytes_per_line;
2308                 dstbits += linebytes;
2309             }
2310         } else {
2311             goto notsupported;
2312         }
2313         break;
2314
2315     default:
2316     notsupported:
2317         {
2318             /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2319             int rShift,gShift,bShift;
2320             WORD* dstpixel;
2321
2322             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
2323                   bmpImage->depth, bmpImage->red_mask,
2324                   bmpImage->green_mask, bmpImage->blue_mask,
2325                   rDst, gDst, bDst);
2326
2327             /* Shift everything 16 bits left so that all shifts are >0,
2328              * even for BGR DIBs. Then a single >> 16 will bring everything
2329              * back into place.
2330              */
2331             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2332             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2333             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2334             if (gDst==0x07e0) {
2335                 /* 6 bits for the green */
2336                 gShift++;
2337             }
2338             rDst=rDst << 16;
2339             gDst=gDst << 16;
2340             bDst=bDst << 16;
2341             for (h = lines - 1; h >= 0; h--) {
2342                 dstpixel=(LPWORD)dstbits;
2343                 for (x = 0; x < dstwidth; x++) {
2344                     COLORREF srcval;
2345                     DWORD dstval;
2346                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
2347                     dstval=((GetRValue(srcval) << rShift) & rDst) |
2348                            ((GetGValue(srcval) << gShift) & gDst) |
2349                            ((GetBValue(srcval) << bShift) & bDst);
2350                     *dstpixel++=dstval >> 16;
2351                 }
2352                 dstbits += linebytes;
2353             }
2354         }
2355         break;
2356     }
2357 }
2358
2359
2360 /***********************************************************************
2361  *           X11DRV_DIB_SetImageBits_24
2362  *
2363  * SetDIBits for a 24-bit deep DIB.
2364  */
2365 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2366                                  DWORD srcwidth, DWORD dstwidth, int left,
2367                                  X11DRV_PDEVICE *physDev,
2368                                  DWORD rSrc, DWORD gSrc, DWORD bSrc,
2369                                  XImage *bmpImage, DWORD linebytes )
2370 {
2371     DWORD x;
2372     int h;
2373     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2374
2375     if (lines < 0 )
2376     {
2377         lines = -lines;
2378         srcbits = srcbits + linebytes * (lines - 1);
2379         linebytes = -linebytes;
2380     }
2381
2382     switch (bmpImage->depth)
2383     {
2384     case 24:
2385         if (bmpImage->bits_per_pixel==24) {
2386             char* dstbits;
2387
2388             srcbits=srcbits+left*3;
2389             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2390
2391             if (bmpImage->green_mask!=0x00ff00 ||
2392                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2393                 goto notsupported;
2394             } else if (rSrc==bmpImage->red_mask) {
2395                 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2396                 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2397                 convs->Convert_888_asis
2398                     (dstwidth,lines,
2399                      srcbits,linebytes,
2400                      dstbits,-bmpImage->bytes_per_line);
2401             } else {
2402                 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2403                 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2404                 convs->Convert_888_reverse
2405                     (dstwidth,lines,
2406                      srcbits,linebytes,
2407                      dstbits,-bmpImage->bytes_per_line);
2408             }
2409             break;
2410         }
2411         /* fall through */
2412
2413     case 32:
2414         {
2415             char* dstbits;
2416
2417             srcbits=srcbits+left*3;
2418             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2419
2420             if (bmpImage->green_mask!=0x00ff00 ||
2421                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2422                 goto notsupported;
2423             } else if (rSrc==bmpImage->red_mask) {
2424                 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2425                 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2426                 convs->Convert_888_to_0888_asis
2427                     (dstwidth,lines,
2428                      srcbits,linebytes,
2429                      dstbits,-bmpImage->bytes_per_line);
2430             } else {
2431                 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2432                 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2433                 convs->Convert_888_to_0888_reverse
2434                     (dstwidth,lines,
2435                      srcbits,linebytes,
2436                      dstbits,-bmpImage->bytes_per_line);
2437             }
2438             break;
2439         }
2440
2441     case 15:
2442     case 16:
2443         {
2444             char* dstbits;
2445
2446             srcbits=srcbits+left*3;
2447             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2448
2449             if (bmpImage->green_mask==0x03e0) {
2450                 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2451                     (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2452                     /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2453                     /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2454                     convs->Convert_888_to_555_asis
2455                         (dstwidth,lines,
2456                          srcbits,linebytes,
2457                          dstbits,-bmpImage->bytes_per_line);
2458                 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2459                            (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2460                     /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2461                     /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2462                     convs->Convert_888_to_555_reverse
2463                         (dstwidth,lines,
2464                          srcbits,linebytes,
2465                          dstbits,-bmpImage->bytes_per_line);
2466                 } else {
2467                     goto notsupported;
2468                 }
2469             } else if (bmpImage->green_mask==0x07e0) {
2470                 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2471                     (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2472                     /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2473                     /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2474                     convs->Convert_888_to_565_asis
2475                         (dstwidth,lines,
2476                          srcbits,linebytes,
2477                          dstbits,-bmpImage->bytes_per_line);
2478                 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2479                            (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2480                     /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2481                     /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2482                     convs->Convert_888_to_565_reverse
2483                         (dstwidth,lines,
2484                          srcbits,linebytes,
2485                          dstbits,-bmpImage->bytes_per_line);
2486                 } else {
2487                     goto notsupported;
2488                 }
2489             } else {
2490                 goto notsupported;
2491             }
2492         }
2493         break;
2494
2495     default:
2496     notsupported:
2497         WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2498               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2499               bmpImage->green_mask, bmpImage->blue_mask );
2500         /* fall through */
2501     case 1:
2502     case 4:
2503     case 8:
2504         {
2505             /* ==== rgb 888 dib -> any bmp bormat ==== */
2506             const BYTE* srcbyte;
2507
2508             /* Windows only supports one 24bpp DIB format: RGB888 */
2509             srcbits+=left*3;
2510             for (h = lines - 1; h >= 0; h--) {
2511                 srcbyte=(const BYTE*)srcbits;
2512                 for (x = left; x < dstwidth+left; x++) {
2513                     XPutPixel(bmpImage, x, h,
2514                               X11DRV_PALETTE_ToPhysical
2515                               (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2516                     srcbyte+=3;
2517                 }
2518                 srcbits += linebytes;
2519             }
2520         }
2521         break;
2522     }
2523 }
2524
2525
2526 /***********************************************************************
2527  *           X11DRV_DIB_GetImageBits_24
2528  *
2529  * GetDIBits for an 24-bit deep DIB.
2530  */
2531 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2532                                         DWORD dstwidth, DWORD srcwidth,
2533                                         PALETTEENTRY *srccolors,
2534                                         DWORD rDst, DWORD gDst, DWORD bDst,
2535                                         XImage *bmpImage, DWORD linebytes )
2536 {
2537     DWORD x;
2538     int h;
2539     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2540
2541     if (lines < 0 )
2542     {
2543         lines = -lines;
2544         dstbits = dstbits + ( linebytes * (lines-1) );
2545         linebytes = -linebytes;
2546     }
2547
2548     switch (bmpImage->depth)
2549     {
2550     case 24:
2551         if (bmpImage->bits_per_pixel==24) {
2552             const char* srcbits;
2553
2554             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2555
2556             if (bmpImage->green_mask!=0x00ff00 ||
2557                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2558                 goto notsupported;
2559             } else if (rDst==bmpImage->red_mask) {
2560                 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2561                 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2562                 convs->Convert_888_asis
2563                     (dstwidth,lines,
2564                      srcbits,-bmpImage->bytes_per_line,
2565                      dstbits,linebytes);
2566             } else {
2567                 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2568                 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2569                 convs->Convert_888_reverse
2570                     (dstwidth,lines,
2571                      srcbits,-bmpImage->bytes_per_line,
2572                      dstbits,linebytes);
2573             }
2574             break;
2575         }
2576         /* fall through */
2577
2578     case 32:
2579         {
2580             const char* srcbits;
2581
2582             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2583
2584             if (bmpImage->green_mask!=0x00ff00 ||
2585                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2586                 goto notsupported;
2587             } else if (rDst==bmpImage->red_mask) {
2588                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2589                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2590                 convs->Convert_0888_to_888_asis
2591                     (dstwidth,lines,
2592                      srcbits,-bmpImage->bytes_per_line,
2593                      dstbits,linebytes);
2594             } else {
2595                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2596                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2597                 convs->Convert_0888_to_888_reverse
2598                     (dstwidth,lines,
2599                      srcbits,-bmpImage->bytes_per_line,
2600                      dstbits,linebytes);
2601             }
2602             break;
2603         }
2604
2605     case 15:
2606     case 16:
2607         {
2608             const char* srcbits;
2609
2610             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2611
2612             if (bmpImage->green_mask==0x03e0) {
2613                 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2614                     (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2615                     /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2616                     /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2617                     convs->Convert_555_to_888_asis
2618                         (dstwidth,lines,
2619                          srcbits,-bmpImage->bytes_per_line,
2620                          dstbits,linebytes);
2621                 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2622                            (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2623                     /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2624                     /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2625                     convs->Convert_555_to_888_reverse
2626                         (dstwidth,lines,
2627                          srcbits,-bmpImage->bytes_per_line,
2628                          dstbits,linebytes);
2629                 } else {
2630                     goto notsupported;
2631                 }
2632             } else if (bmpImage->green_mask==0x07e0) {
2633                 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2634                     (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2635                     /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2636                     /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2637                     convs->Convert_565_to_888_asis
2638                         (dstwidth,lines,
2639                          srcbits,-bmpImage->bytes_per_line,
2640                          dstbits,linebytes);
2641                 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2642                            (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2643                     /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2644                     /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2645                     convs->Convert_565_to_888_reverse
2646                         (dstwidth,lines,
2647                          srcbits,-bmpImage->bytes_per_line,
2648                          dstbits,linebytes);
2649                 } else {
2650                     goto notsupported;
2651                 }
2652             } else {
2653                 goto notsupported;
2654             }
2655         }
2656         break;
2657
2658     case 1:
2659     case 4:
2660         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2661             /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2662             BYTE* dstbyte;
2663
2664             /* Windows only supports one 24bpp DIB format: rgb 888 */
2665             for (h = lines - 1; h >= 0; h--) {
2666                 dstbyte=dstbits;
2667                 for (x = 0; x < dstwidth; x++) {
2668                     PALETTEENTRY srcval;
2669                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2670                     dstbyte[0]=srcval.peBlue;
2671                     dstbyte[1]=srcval.peGreen;
2672                     dstbyte[2]=srcval.peRed;
2673                     dstbyte+=3;
2674                 }
2675                 dstbits += linebytes;
2676             }
2677         } else {
2678             goto notsupported;
2679         }
2680         break;
2681
2682     case 8:
2683         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
2684             /* ==== pal 8 bmp -> rgb 888 dib ==== */
2685             const void* srcbits;
2686             const BYTE* srcpixel;
2687             BYTE* dstbyte;
2688
2689             /* Windows only supports one 24bpp DIB format: rgb 888 */
2690             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2691             for (h = lines - 1; h >= 0; h--) {
2692                 srcpixel=srcbits;
2693                 dstbyte=dstbits;
2694                 for (x = 0; x < dstwidth; x++ ) {
2695                     PALETTEENTRY srcval;
2696                     srcval=srccolors[(int)*srcpixel++];
2697                     dstbyte[0]=srcval.peBlue;
2698                     dstbyte[1]=srcval.peGreen;
2699                     dstbyte[2]=srcval.peRed;
2700                     dstbyte+=3;
2701                 }
2702                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2703                 dstbits += linebytes;
2704             }
2705         } else {
2706             goto notsupported;
2707         }
2708         break;
2709
2710     default:
2711     notsupported:
2712         {
2713             /* ==== any bmp format -> 888 dib ==== */
2714             BYTE* dstbyte;
2715
2716             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
2717                   bmpImage->depth, bmpImage->red_mask,
2718                   bmpImage->green_mask, bmpImage->blue_mask,
2719                   rDst, gDst, bDst );
2720
2721             /* Windows only supports one 24bpp DIB format: rgb 888 */
2722             for (h = lines - 1; h >= 0; h--) {
2723                 dstbyte=dstbits;
2724                 for (x = 0; x < dstwidth; x++) {
2725                     COLORREF srcval=X11DRV_PALETTE_ToLogical
2726                         (XGetPixel( bmpImage, x, h ));
2727                     dstbyte[0]=GetBValue(srcval);
2728                     dstbyte[1]=GetGValue(srcval);
2729                     dstbyte[2]=GetRValue(srcval);
2730                     dstbyte+=3;
2731                 }
2732                 dstbits += linebytes;
2733             }
2734         }
2735         break;
2736     }
2737 }
2738
2739
2740 /***********************************************************************
2741  *           X11DRV_DIB_SetImageBits_32
2742  *
2743  * SetDIBits for a 32-bit deep DIB.
2744  */
2745 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2746                                        DWORD srcwidth, DWORD dstwidth, int left,
2747                                        X11DRV_PDEVICE *physDev,
2748                                        DWORD rSrc, DWORD gSrc, DWORD bSrc,
2749                                        XImage *bmpImage,
2750                                        DWORD linebytes)
2751 {
2752     DWORD x, *ptr;
2753     int h;
2754     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2755
2756     if (lines < 0 )
2757     {
2758        lines = -lines;
2759        srcbits = srcbits + ( linebytes * (lines-1) );
2760        linebytes = -linebytes;
2761     }
2762
2763     ptr = (DWORD *) srcbits + left;
2764
2765     switch (bmpImage->depth)
2766     {
2767     case 24:
2768         if (bmpImage->bits_per_pixel==24) {
2769             char* dstbits;
2770
2771             srcbits=srcbits+left*4;
2772             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2773
2774             if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2775                 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2776                 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2777                 convs->Convert_0888_to_888_asis
2778                     (dstwidth,lines,
2779                      srcbits,linebytes,
2780                      dstbits,-bmpImage->bytes_per_line);
2781             } else if (bmpImage->green_mask!=0x00ff00 ||
2782                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2783                 goto notsupported;
2784                 /* the tests below assume sane bmpImage masks */
2785             } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2786                 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2787                 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2788                 convs->Convert_0888_to_888_reverse
2789                     (dstwidth,lines,
2790                      srcbits,linebytes,
2791                      dstbits,-bmpImage->bytes_per_line);
2792             } else if (bmpImage->blue_mask==0xff) {
2793                 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2794                 convs->Convert_any0888_to_rgb888
2795                     (dstwidth,lines,
2796                      srcbits,linebytes,
2797                      rSrc,gSrc,bSrc,
2798                      dstbits,-bmpImage->bytes_per_line);
2799             } else {
2800                 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2801                 convs->Convert_any0888_to_bgr888
2802                     (dstwidth,lines,
2803                      srcbits,linebytes,
2804                      rSrc,gSrc,bSrc,
2805                      dstbits,-bmpImage->bytes_per_line);
2806             }
2807             break;
2808         }
2809         /* fall through */
2810
2811     case 32:
2812         {
2813             char* dstbits;
2814
2815             srcbits=srcbits+left*4;
2816             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2817
2818             if (gSrc==bmpImage->green_mask) {
2819                 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2820                     /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2821                     /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2822                     convs->Convert_0888_asis
2823                         (dstwidth,lines,
2824                          srcbits,linebytes,
2825                          dstbits,-bmpImage->bytes_per_line);
2826                 } else if (bmpImage->green_mask!=0x00ff00 ||
2827                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2828                     goto notsupported;
2829                     /* the tests below assume sane bmpImage masks */
2830                 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2831                     /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2832                     /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2833                     convs->Convert_0888_reverse
2834                         (dstwidth,lines,
2835                          srcbits,linebytes,
2836                          dstbits,-bmpImage->bytes_per_line);
2837                 } else {
2838                     /* ==== any 0888 dib -> any 0888 bmp ==== */
2839                     convs->Convert_0888_any
2840                         (dstwidth,lines,
2841                          srcbits,linebytes,
2842                          rSrc,gSrc,bSrc,
2843                          dstbits,-bmpImage->bytes_per_line,
2844                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2845                 }
2846             } else if (bmpImage->green_mask!=0x00ff00 ||
2847                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2848                 goto notsupported;
2849                 /* the tests below assume sane bmpImage masks */
2850             } else {
2851                 /* ==== any 0888 dib -> any 0888 bmp ==== */
2852                 convs->Convert_0888_any
2853                     (dstwidth,lines,
2854                      srcbits,linebytes,
2855                      rSrc,gSrc,bSrc,
2856                      dstbits,-bmpImage->bytes_per_line,
2857                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2858             }
2859         }
2860         break;
2861
2862     case 15:
2863     case 16:
2864         {
2865             char* dstbits;
2866
2867             srcbits=srcbits+left*4;
2868             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2869
2870             if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2871                 if (bmpImage->green_mask==0x03e0) {
2872                     if (bmpImage->red_mask==0x7f00) {
2873                         /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2874                         convs->Convert_0888_to_555_asis
2875                             (dstwidth,lines,
2876                              srcbits,linebytes,
2877                              dstbits,-bmpImage->bytes_per_line);
2878                     } else if (bmpImage->blue_mask==0x7f00) {
2879                         /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2880                         convs->Convert_0888_to_555_reverse
2881                             (dstwidth,lines,
2882                              srcbits,linebytes,
2883                              dstbits,-bmpImage->bytes_per_line);
2884                     } else {
2885                         goto notsupported;
2886                     }
2887                 } else if (bmpImage->green_mask==0x07e0) {
2888                     if (bmpImage->red_mask==0xf800) {
2889                         /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
2890                         convs->Convert_0888_to_565_asis
2891                             (dstwidth,lines,
2892                              srcbits,linebytes,
2893                              dstbits,-bmpImage->bytes_per_line);
2894                     } else if (bmpImage->blue_mask==0xf800) {
2895                         /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
2896                         convs->Convert_0888_to_565_reverse
2897                             (dstwidth,lines,
2898                              srcbits,linebytes,
2899                              dstbits,-bmpImage->bytes_per_line);
2900                     } else {
2901                         goto notsupported;
2902                     }
2903                 } else {
2904                     goto notsupported;
2905                 }
2906             } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
2907                 if (bmpImage->green_mask==0x03e0) {
2908                     if (bmpImage->blue_mask==0x7f00) {
2909                         /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
2910                         convs->Convert_0888_to_555_asis
2911                             (dstwidth,lines,
2912                              srcbits,linebytes,
2913                              dstbits,-bmpImage->bytes_per_line);
2914                     } else if (bmpImage->red_mask==0x7f00) {
2915                         /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
2916                         convs->Convert_0888_to_555_reverse
2917                             (dstwidth,lines,
2918                              srcbits,linebytes,
2919                              dstbits,-bmpImage->bytes_per_line);
2920                     } else {
2921                         goto notsupported;
2922                     }
2923                 } else if (bmpImage->green_mask==0x07e0) {
2924                     if (bmpImage->blue_mask==0xf800) {
2925                         /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
2926                         convs->Convert_0888_to_565_asis
2927                             (dstwidth,lines,
2928                              srcbits,linebytes,
2929                              dstbits,-bmpImage->bytes_per_line);
2930                     } else if (bmpImage->red_mask==0xf800) {
2931                         /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
2932                         convs->Convert_0888_to_565_reverse
2933                             (dstwidth,lines,
2934                              srcbits,linebytes,
2935                              dstbits,-bmpImage->bytes_per_line);
2936                     } else {
2937                         goto notsupported;
2938                     }
2939                 } else {
2940                     goto notsupported;
2941                 }
2942             } else {
2943                 if (bmpImage->green_mask==0x03e0 &&
2944                     (bmpImage->red_mask==0x7f00 ||
2945                      bmpImage->blue_mask==0x7f00)) {
2946                     /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
2947                     convs->Convert_any0888_to_5x5
2948                         (dstwidth,lines,
2949                          srcbits,linebytes,
2950                          rSrc,gSrc,bSrc,
2951                          dstbits,-bmpImage->bytes_per_line,
2952                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2953                 } else if (bmpImage->green_mask==0x07e0 &&
2954                            (bmpImage->red_mask==0xf800 ||
2955                             bmpImage->blue_mask==0xf800)) {
2956                     /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
2957                     convs->Convert_any0888_to_5x5
2958                         (dstwidth,lines,
2959                          srcbits,linebytes,
2960                          rSrc,gSrc,bSrc,
2961                          dstbits,-bmpImage->bytes_per_line,
2962                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2963                 } else {
2964                     goto notsupported;
2965                 }
2966             }
2967         }
2968         break;
2969
2970     default:
2971     notsupported:
2972         WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2973               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2974               bmpImage->green_mask, bmpImage->blue_mask );
2975         /* fall through */
2976     case 1:
2977     case 4:
2978     case 8:
2979         {
2980             /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
2981             const DWORD* srcpixel;
2982             int rShift,gShift,bShift;
2983
2984             rShift=X11DRV_DIB_MaskToShift(rSrc);
2985             gShift=X11DRV_DIB_MaskToShift(gSrc);
2986             bShift=X11DRV_DIB_MaskToShift(bSrc);
2987             srcbits+=left*4;
2988             for (h = lines - 1; h >= 0; h--) {
2989                 srcpixel=(const DWORD*)srcbits;
2990                 for (x = left; x < dstwidth+left; x++) {
2991                     DWORD srcvalue;
2992                     BYTE red,green,blue;
2993                     srcvalue=*srcpixel++;
2994                     red=  (srcvalue >> rShift) & 0xff;
2995                     green=(srcvalue >> gShift) & 0xff;
2996                     blue= (srcvalue >> bShift) & 0xff;
2997                     XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
2998                               (physDev, RGB(red,green,blue)));
2999                 }
3000                 srcbits += linebytes;
3001             }
3002         }
3003         break;
3004     }
3005
3006 }
3007
3008 /***********************************************************************
3009  *           X11DRV_DIB_GetImageBits_32
3010  *
3011  * GetDIBits for an 32-bit deep DIB.
3012  */
3013 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
3014                                         DWORD dstwidth, DWORD srcwidth,
3015                                         PALETTEENTRY *srccolors,
3016                                         DWORD rDst, DWORD gDst, DWORD bDst,
3017                                         XImage *bmpImage, DWORD linebytes )
3018 {
3019     DWORD x;
3020     int h;
3021     BYTE *bits;
3022     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
3023
3024     if (lines < 0 )
3025     {
3026         lines = -lines;
3027         dstbits = dstbits + ( linebytes * (lines-1) );
3028         linebytes = -linebytes;
3029     }
3030
3031     bits = dstbits;
3032
3033     switch (bmpImage->depth)
3034     {
3035     case 24:
3036         if (bmpImage->bits_per_pixel==24) {
3037             const void* srcbits;
3038
3039             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3040
3041             if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
3042                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3043                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3044                 convs->Convert_888_to_0888_asis
3045                     (dstwidth,lines,
3046                      srcbits,-bmpImage->bytes_per_line,
3047                      dstbits,linebytes);
3048             } else if (bmpImage->green_mask!=0x00ff00 ||
3049                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3050                 goto notsupported;
3051                 /* the tests below assume sane bmpImage masks */
3052             } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3053                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3054                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3055                 convs->Convert_888_to_0888_reverse
3056                     (dstwidth,lines,
3057                      srcbits,-bmpImage->bytes_per_line,
3058                      dstbits,linebytes);
3059             } else if (bmpImage->blue_mask==0xff) {
3060                 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3061                 convs->Convert_rgb888_to_any0888
3062                     (dstwidth,lines,
3063                      srcbits,-bmpImage->bytes_per_line,
3064                      dstbits,linebytes,
3065                      rDst,gDst,bDst);
3066             } else {
3067                 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3068                 convs->Convert_bgr888_to_any0888
3069                     (dstwidth,lines,
3070                      srcbits,-bmpImage->bytes_per_line,
3071                      dstbits,linebytes,
3072                      rDst,gDst,bDst);
3073             }
3074             break;
3075         }
3076         /* fall through */
3077
3078     case 32:
3079         {
3080             const char* srcbits;
3081
3082             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3083
3084             if (gDst==bmpImage->green_mask) {
3085                 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3086                     /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3087                     /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3088                     convs->Convert_0888_asis
3089                         (dstwidth,lines,
3090                          srcbits,-bmpImage->bytes_per_line,
3091                          dstbits,linebytes);
3092                 } else if (bmpImage->green_mask!=0x00ff00 ||
3093                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3094                     goto notsupported;
3095                     /* the tests below assume sane bmpImage masks */
3096                 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3097                     /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3098                     /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3099                     convs->Convert_0888_reverse
3100                         (dstwidth,lines,
3101                          srcbits,-bmpImage->bytes_per_line,
3102                          dstbits,linebytes);
3103                 } else {
3104                     /* ==== any 0888 bmp -> any 0888 dib ==== */
3105                     convs->Convert_0888_any
3106                         (dstwidth,lines,
3107                          srcbits,-bmpImage->bytes_per_line,
3108                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3109                          dstbits,linebytes,
3110                          rDst,gDst,bDst);
3111                 }
3112             } else if (bmpImage->green_mask!=0x00ff00 ||
3113                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3114                 goto notsupported;
3115                 /* the tests below assume sane bmpImage masks */
3116             } else {
3117                 /* ==== any 0888 bmp -> any 0888 dib ==== */
3118                 convs->Convert_0888_any
3119                     (dstwidth,lines,
3120                      srcbits,-bmpImage->bytes_per_line,
3121                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3122                      dstbits,linebytes,
3123                      rDst,gDst,bDst);
3124             }
3125         }
3126         break;
3127
3128     case 15:
3129     case 16:
3130         {
3131             const char* srcbits;
3132
3133             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3134
3135             if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3136                 if (bmpImage->green_mask==0x03e0) {
3137                     if (bmpImage->red_mask==0x7f00) {
3138                         /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3139                         convs->Convert_555_to_0888_asis
3140                             (dstwidth,lines,
3141                              srcbits,-bmpImage->bytes_per_line,
3142                              dstbits,linebytes);
3143                     } else if (bmpImage->blue_mask==0x7f00) {
3144                         /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3145                         convs->Convert_555_to_0888_reverse
3146                             (dstwidth,lines,
3147                              srcbits,-bmpImage->bytes_per_line,
3148                              dstbits,linebytes);
3149                     } else {
3150                         goto notsupported;
3151                     }
3152                 } else if (bmpImage->green_mask==0x07e0) {
3153                     if (bmpImage->red_mask==0xf800) {
3154                         /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3155                         convs->Convert_565_to_0888_asis
3156                             (dstwidth,lines,
3157                              srcbits,-bmpImage->bytes_per_line,
3158                              dstbits,linebytes);
3159                     } else if (bmpImage->blue_mask==0xf800) {
3160                         /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3161                         convs->Convert_565_to_0888_reverse
3162                             (dstwidth,lines,
3163                              srcbits,-bmpImage->bytes_per_line,
3164                              dstbits,linebytes);
3165                     } else {
3166                         goto notsupported;
3167                     }
3168                 } else {
3169                     goto notsupported;
3170                 }
3171             } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3172                 if (bmpImage->green_mask==0x03e0) {
3173                     if (bmpImage->blue_mask==0x7f00) {
3174                         /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3175                         convs->Convert_555_to_0888_asis
3176                             (dstwidth,lines,
3177                              srcbits,-bmpImage->bytes_per_line,
3178                              dstbits,linebytes);
3179                     } else if (bmpImage->red_mask==0x7f00) {
3180                         /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3181                         convs->Convert_555_to_0888_reverse
3182                             (dstwidth,lines,
3183                              srcbits,-bmpImage->bytes_per_line,
3184                              dstbits,linebytes);
3185                     } else {
3186                         goto notsupported;
3187                     }
3188                 } else if (bmpImage->green_mask==0x07e0) {
3189                     if (bmpImage->blue_mask==0xf800) {
3190                         /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3191                         convs->Convert_565_to_0888_asis
3192                             (dstwidth,lines,
3193                              srcbits,-bmpImage->bytes_per_line,
3194                              dstbits,linebytes);
3195                     } else if (bmpImage->red_mask==0xf800) {
3196                         /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3197                         convs->Convert_565_to_0888_reverse
3198                             (dstwidth,lines,
3199                              srcbits,-bmpImage->bytes_per_line,
3200                              dstbits,linebytes);
3201                     } else {
3202                         goto notsupported;
3203                     }
3204                 } else {
3205                     goto notsupported;
3206                 }
3207             } else {
3208                 if (bmpImage->green_mask==0x03e0 &&
3209                     (bmpImage->red_mask==0x7f00 ||
3210                      bmpImage->blue_mask==0x7f00)) {
3211                     /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3212                     convs->Convert_5x5_to_any0888
3213                         (dstwidth,lines,
3214                          srcbits,-bmpImage->bytes_per_line,
3215                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3216                          dstbits,linebytes,
3217                          rDst,gDst,bDst);
3218                 } else if (bmpImage->green_mask==0x07e0 &&
3219                            (bmpImage->red_mask==0xf800 ||
3220                             bmpImage->blue_mask==0xf800)) {
3221                     /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3222                     convs->Convert_5x5_to_any0888
3223                         (dstwidth,lines,
3224                          srcbits,-bmpImage->bytes_per_line,
3225                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3226                          dstbits,linebytes,
3227                          rDst,gDst,bDst);
3228                 } else {
3229                     goto notsupported;
3230                 }
3231             }
3232         }
3233         break;
3234
3235     case 1:
3236     case 4:
3237         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3238             /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3239             int rShift,gShift,bShift;
3240             DWORD* dstpixel;
3241
3242             rShift=X11DRV_DIB_MaskToShift(rDst);
3243             gShift=X11DRV_DIB_MaskToShift(gDst);
3244             bShift=X11DRV_DIB_MaskToShift(bDst);
3245             for (h = lines - 1; h >= 0; h--) {
3246                 dstpixel=(DWORD*)dstbits;
3247                 for (x = 0; x < dstwidth; x++) {
3248                     PALETTEENTRY srcval;
3249                     srcval = srccolors[XGetPixel(bmpImage, x, h)];
3250                     *dstpixel++=(srcval.peRed   << rShift) |
3251                                 (srcval.peGreen << gShift) |
3252                                 (srcval.peBlue  << bShift);
3253                 }
3254                 dstbits += linebytes;
3255             }
3256         } else {
3257             goto notsupported;
3258         }
3259         break;
3260
3261     case 8:
3262         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3263             /* ==== pal 8 bmp -> any 0888 dib ==== */
3264             int rShift,gShift,bShift;
3265             const void* srcbits;
3266             const BYTE* srcpixel;
3267             DWORD* dstpixel;
3268
3269             rShift=X11DRV_DIB_MaskToShift(rDst);
3270             gShift=X11DRV_DIB_MaskToShift(gDst);
3271             bShift=X11DRV_DIB_MaskToShift(bDst);
3272             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3273             for (h = lines - 1; h >= 0; h--) {
3274                 srcpixel=srcbits;
3275                 dstpixel=(DWORD*)dstbits;
3276                 for (x = 0; x < dstwidth; x++) {
3277                     PALETTEENTRY srcval;
3278                     srcval=srccolors[(int)*srcpixel++];
3279                     *dstpixel++=(srcval.peRed   << rShift) |
3280                                 (srcval.peGreen << gShift) |
3281                                 (srcval.peBlue  << bShift);
3282                 }
3283                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3284                 dstbits += linebytes;
3285             }
3286         } else {
3287             goto notsupported;
3288         }
3289         break;
3290
3291     default:
3292     notsupported:
3293         {
3294             /* ==== any bmp format -> any 0888 dib ==== */
3295             int rShift,gShift,bShift;
3296             DWORD* dstpixel;
3297
3298             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
3299                   bmpImage->depth, bmpImage->red_mask,
3300                   bmpImage->green_mask, bmpImage->blue_mask,
3301                   rDst,gDst,bDst);
3302
3303             rShift=X11DRV_DIB_MaskToShift(rDst);
3304             gShift=X11DRV_DIB_MaskToShift(gDst);
3305             bShift=X11DRV_DIB_MaskToShift(bDst);
3306             for (h = lines - 1; h >= 0; h--) {
3307                 dstpixel=(DWORD*)dstbits;
3308                 for (x = 0; x < dstwidth; x++) {
3309                     COLORREF srcval;
3310                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3311                     *dstpixel++=(GetRValue(srcval) << rShift) |
3312                                 (GetGValue(srcval) << gShift) |
3313                                 (GetBValue(srcval) << bShift);
3314                 }
3315                 dstbits += linebytes;
3316             }
3317         }
3318         break;
3319     }
3320 }
3321
3322 /***********************************************************************
3323  *           X11DRV_DIB_SetImageBits
3324  *
3325  * Transfer the bits to an X image.
3326  * Helper function for SetDIBits() and SetDIBitsToDevice().
3327  */
3328 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3329 {
3330     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3331     XImage *bmpImage;
3332
3333     wine_tsx11_lock();
3334     if (descr->image)
3335         bmpImage = descr->image;
3336     else {
3337         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3338                                  descr->infoWidth, lines, 32, 0 );
3339         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3340         if(bmpImage->data == NULL) {
3341             ERR("Out of memory!\n");
3342             XDestroyImage( bmpImage );
3343             wine_tsx11_unlock();
3344             return lines;
3345         }
3346     }
3347
3348     TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
3349           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3350     TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3351           bmpImage->depth,bmpImage->bits_per_pixel,
3352           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3353
3354       /* Transfer the pixels */
3355     switch(descr->infoBpp)
3356     {
3357     case 1:
3358         X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3359                                    descr->width, descr->xSrc, (int *)(descr->colorMap),
3360                                    bmpImage, descr->dibpitch );
3361         break;
3362     case 4:
3363         if (descr->compression) {
3364             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3365                           descr->width, descr->height, AllPlanes, ZPixmap,
3366                           bmpImage, descr->xSrc, descr->ySrc );
3367
3368             X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3369                                           descr->infoWidth, descr->width,
3370                                           descr->xSrc, (int *)(descr->colorMap),
3371                                           bmpImage );
3372         } else
3373             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3374                                        descr->infoWidth, descr->width,
3375                                        descr->xSrc, (int*)(descr->colorMap),
3376                                        bmpImage, descr->dibpitch );
3377         break;
3378     case 8:
3379         if (descr->compression) {
3380             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3381                           descr->width, descr->height, AllPlanes, ZPixmap,
3382                           bmpImage, descr->xSrc, descr->ySrc );
3383             X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3384                                           descr->infoWidth, descr->width,
3385                                           descr->xSrc, (int *)(descr->colorMap),
3386                                           bmpImage );
3387         } else
3388             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3389                                        descr->infoWidth, descr->width,
3390                                        descr->xSrc, (int *)(descr->colorMap),
3391                                        bmpImage, descr->dibpitch );
3392         break;
3393     case 15:
3394     case 16:
3395         X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3396                                     descr->infoWidth, descr->width,
3397                                    descr->xSrc, descr->physDev,
3398                                    descr->rMask, descr->gMask, descr->bMask,
3399                                    bmpImage, descr->dibpitch);
3400         break;
3401     case 24:
3402         X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3403                                     descr->infoWidth, descr->width,
3404                                     descr->xSrc, descr->physDev,
3405                                     descr->rMask, descr->gMask, descr->bMask,
3406                                     bmpImage, descr->dibpitch);
3407         break;
3408     case 32:
3409         X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3410                                     descr->infoWidth, descr->width,
3411                                    descr->xSrc, descr->physDev,
3412                                    descr->rMask, descr->gMask, descr->bMask,
3413                                    bmpImage, descr->dibpitch);
3414         break;
3415     default:
3416         WARN("(%d): Invalid depth\n", descr->infoBpp );
3417         break;
3418     }
3419
3420     TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3421      descr->drawable, descr->gc, bmpImage,
3422      descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3423      descr->width, descr->height);
3424 #ifdef HAVE_LIBXXSHM
3425     if (descr->useShm)
3426     {
3427         XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3428                       descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3429                       descr->width, descr->height, FALSE );
3430         XSync( gdi_display, 0 );
3431     }
3432     else
3433 #endif
3434         XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3435                    descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3436                    descr->width, descr->height );
3437
3438     if (!descr->image) XDestroyImage( bmpImage );
3439     wine_tsx11_unlock();
3440     return lines;
3441 }
3442
3443 /***********************************************************************
3444  *           X11DRV_DIB_GetImageBits
3445  *
3446  * Transfer the bits from an X image.
3447  */
3448 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3449 {
3450     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3451     XImage *bmpImage;
3452
3453     wine_tsx11_lock();
3454    if (descr->image)
3455         bmpImage = descr->image;
3456     else {
3457         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3458                                  descr->infoWidth, lines, 32, 0 );
3459         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3460         if(bmpImage->data == NULL) {
3461             ERR("Out of memory!\n");
3462             XDestroyImage( bmpImage );
3463             wine_tsx11_unlock();
3464             return lines;
3465         }
3466     }
3467
3468 #ifdef HAVE_LIBXXSHM
3469     if (descr->useShm)
3470     {
3471         int saveRed, saveGreen, saveBlue;
3472
3473         TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3474                             gdi_display, descr->drawable, bmpImage,
3475                             descr->xSrc, descr->ySrc, AllPlanes);
3476
3477         /* We must save and restore the bmpImage's masks in order
3478          * to preserve them across the call to XShmGetImage, which
3479          * decides to eleminate them since it doesn't happen to know
3480          * what the format of the image is supposed to be, even though
3481          * we do. */
3482         saveRed = bmpImage->red_mask;
3483         saveBlue= bmpImage->blue_mask;
3484         saveGreen = bmpImage->green_mask;
3485
3486         XShmGetImage( gdi_display, descr->drawable, bmpImage,
3487                       descr->xSrc, descr->ySrc, AllPlanes);
3488
3489         bmpImage->red_mask = saveRed;
3490         bmpImage->blue_mask = saveBlue;
3491         bmpImage->green_mask = saveGreen;
3492     }
3493     else
3494 #endif /* HAVE_LIBXXSHM */
3495     {
3496         TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3497               gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3498               lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3499         XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3500                       descr->width, lines, AllPlanes, ZPixmap,
3501                       bmpImage, descr->xDest, descr->yDest );
3502     }
3503
3504     TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
3505           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3506     TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3507           bmpImage->depth,bmpImage->bits_per_pixel,
3508           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3509       /* Transfer the pixels */
3510     switch(descr->infoBpp)
3511     {
3512     case 1:
3513           X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3514                                      descr->infoWidth, descr->width,
3515                                      descr->colorMap, descr->palentry,
3516                                      bmpImage, descr->dibpitch );
3517        break;
3518
3519     case 4:
3520         if (descr->compression) {
3521            FIXME("Compression not yet supported!\n");
3522            if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 4 ) * abs(descr->lines))
3523                break;
3524         }
3525         X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3526                                    descr->infoWidth, descr->width,
3527                                    descr->colorMap, descr->palentry,
3528                                    bmpImage, descr->dibpitch );
3529         break;
3530     case 8:
3531         if (descr->compression) {
3532            FIXME("Compression not yet supported!\n");
3533            if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 8 ) * abs(descr->lines))
3534                break;
3535         }
3536         X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3537                                    descr->infoWidth, descr->width,
3538                                    descr->colorMap, descr->palentry,
3539                                    bmpImage, descr->dibpitch );
3540         break;
3541     case 15:
3542     case 16:
3543        X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
3544                                    descr->infoWidth,descr->width,
3545                                    descr->palentry,
3546                                    descr->rMask, descr->gMask, descr->bMask,
3547                                    bmpImage, descr->dibpitch );
3548        break;
3549
3550     case 24:
3551        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
3552                                    descr->infoWidth,descr->width,
3553                                    descr->palentry,
3554                                    descr->rMask, descr->gMask, descr->bMask,
3555                                    bmpImage, descr->dibpitch);
3556        break;
3557
3558     case 32:
3559        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
3560                                    descr->infoWidth, descr->width,
3561                                    descr->palentry,
3562                                    descr->rMask, descr->gMask, descr->bMask,
3563                                    bmpImage, descr->dibpitch);
3564        break;
3565
3566     default:
3567         WARN("(%d): Invalid depth\n", descr->infoBpp );
3568         break;
3569     }
3570
3571     if (!descr->image) XDestroyImage( bmpImage );
3572     wine_tsx11_unlock();
3573     return lines;
3574 }
3575
3576 /*************************************************************************
3577  *              X11DRV_SetDIBitsToDevice
3578  *
3579  */
3580 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
3581                                 DWORD cy, INT xSrc, INT ySrc,
3582                                 UINT startscan, UINT lines, LPCVOID bits,
3583                                 const BITMAPINFO *info, UINT coloruse )
3584 {
3585     X11DRV_DIB_IMAGEBITS_DESCR descr;
3586     DWORD width;
3587     INT result;
3588     int height;
3589     BOOL top_down;
3590     POINT pt;
3591
3592     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3593                            &descr.infoBpp, &descr.compression ) == -1)
3594         return 0;
3595     top_down = (height < 0);
3596     if (top_down) height = -height;
3597
3598     pt.x = xDest;
3599     pt.y = yDest;
3600     LPtoDP(physDev->hdc, &pt, 1);
3601
3602     if (!lines || (startscan >= height)) return 0;
3603     if (!top_down && startscan + lines > height) lines = height - startscan;
3604
3605     /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3606      * and clamp all values to fit inside [startscan,startscan+lines]
3607      */
3608     if (ySrc + cy <= startscan + lines)
3609     {
3610         INT y = startscan + lines - (ySrc + cy);
3611         if (ySrc < startscan) cy -= (startscan - ySrc);
3612         if (!top_down)
3613         {
3614             /* avoid getting unnecessary lines */
3615             ySrc = 0;
3616             if (y >= lines) return 0;
3617             lines -= y;
3618         }
3619         else
3620         {
3621             if (y >= lines) return lines;
3622             ySrc = y;  /* need to get all lines in top down mode */
3623         }
3624     }
3625     else
3626     {
3627         if (ySrc >= startscan + lines) return lines;
3628         pt.y += ySrc + cy - (startscan + lines);
3629         cy = startscan + lines - ySrc;
3630         ySrc = 0;
3631         if (cy > lines) cy = lines;
3632     }
3633     if (xSrc >= width) return lines;
3634     if (xSrc + cx >= width) cx = width - xSrc;
3635     if (!cx || !cy) return lines;
3636
3637     X11DRV_SetupGCForText( physDev );  /* To have the correct colors */
3638     wine_tsx11_lock();
3639     XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
3640     wine_tsx11_unlock();
3641
3642     switch (descr.infoBpp)
3643     {
3644        case 1:
3645        case 4:
3646        case 8:
3647                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3648                                             coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
3649                                             physDev->depth, info, &descr.nColorMap );
3650                if (!descr.colorMap) return 0;
3651                descr.rMask = descr.gMask = descr.bMask = 0;
3652                break;
3653        case 15:
3654        case 16:
3655                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3656                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
3657                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
3658                descr.colorMap = 0;
3659                break;
3660
3661        case 24:
3662        case 32:
3663                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
3664                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3665                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3666                descr.colorMap = 0;
3667                break;
3668     }
3669
3670     descr.physDev   = physDev;
3671     descr.bits      = bits;
3672     descr.image     = NULL;
3673     descr.palentry  = NULL;
3674     descr.lines     = top_down ? -lines : lines;
3675     descr.infoWidth = width;
3676     descr.depth     = physDev->depth;
3677     descr.drawable  = physDev->drawable;
3678     descr.gc        = physDev->gc;
3679     descr.xSrc      = xSrc;
3680     descr.ySrc      = ySrc;
3681     descr.xDest     = physDev->org.x + pt.x;
3682     descr.yDest     = physDev->org.y + pt.y;
3683     descr.width     = cx;
3684     descr.height    = cy;
3685     descr.useShm    = FALSE;
3686     descr.dibpitch  = ((width * descr.infoBpp + 31) &~31) / 8;
3687
3688     result = X11DRV_DIB_SetImageBits( &descr );
3689
3690     if (descr.infoBpp <= 8)
3691        HeapFree(GetProcessHeap(), 0, descr.colorMap);
3692     return result;
3693 }
3694
3695 /***********************************************************************
3696  *           SetDIBits   (X11DRV.@)
3697  */
3698 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3699                       UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3700 {
3701   X11DRV_DIB_IMAGEBITS_DESCR descr;
3702   BITMAPOBJ *bmp;
3703   int height, tmpheight;
3704   INT result;
3705
3706   descr.physDev = physDev;
3707
3708   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
3709                          &descr.infoBpp, &descr.compression ) == -1)
3710       return 0;
3711
3712   tmpheight = height;
3713   if (height < 0) height = -height;
3714   if (!lines || (startscan >= height))
3715       return 0;
3716
3717   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3718
3719   if (startscan + lines > height) lines = height - startscan;
3720
3721   switch (descr.infoBpp)
3722   {
3723        case 1:
3724        case 4:
3725        case 8:
3726                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3727                         coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
3728                                                           bmp->bitmap.bmBitsPixel,
3729                                                           info, &descr.nColorMap );
3730                if (!descr.colorMap)
3731                {
3732                    GDI_ReleaseObj( hbitmap );
3733                    return 0;
3734                }
3735                descr.rMask = descr.gMask = descr.bMask = 0;
3736                break;
3737        case 15:
3738        case 16:
3739                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3740                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3741                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3742                descr.colorMap = 0;
3743                break;
3744
3745        case 24:
3746        case 32:
3747                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
3748                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3749                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3750                descr.colorMap = 0;
3751                break;
3752
3753        default: break;
3754   }
3755
3756   descr.bits      = bits;
3757   descr.image     = NULL;
3758   descr.palentry  = NULL;
3759   descr.lines     = tmpheight >= 0 ? lines : -lines;
3760   descr.depth     = bmp->bitmap.bmBitsPixel;
3761   descr.drawable  = (Pixmap)bmp->physBitmap;
3762   descr.gc        = BITMAP_GC(bmp);
3763   descr.xSrc      = 0;
3764   descr.ySrc      = 0;
3765   descr.xDest     = 0;
3766   descr.yDest     = height - startscan - lines;
3767   descr.width     = bmp->bitmap.bmWidth;
3768   descr.height    = lines;
3769   descr.useShm    = FALSE;
3770   descr.dibpitch  = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3771   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3772   result = X11DRV_DIB_SetImageBits( &descr );
3773   X11DRV_DIB_Unlock(bmp, TRUE);
3774
3775   if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
3776
3777   GDI_ReleaseObj( hbitmap );
3778   return result;
3779 }
3780
3781 /***********************************************************************
3782  *           GetDIBits   (X11DRV.@)
3783  */
3784 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3785                       LPVOID bits, BITMAPINFO *info, UINT coloruse )
3786 {
3787   X11DRV_DIBSECTION *dib;
3788   X11DRV_DIB_IMAGEBITS_DESCR descr;
3789   PALETTEENTRY palette[256];
3790   BITMAPOBJ *bmp;
3791   int height;
3792
3793   GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
3794
3795   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3796
3797   dib = (X11DRV_DIBSECTION *) bmp->dib;
3798
3799   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3800         lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3801         (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
3802         startscan );
3803
3804   if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3805
3806   height = info->bmiHeader.biHeight;
3807   if (height < 0) height = -height;
3808   if( lines > height ) lines = height;
3809   /* Top-down images have a negative biHeight, the scanlines of theses images
3810    * were inverted in X11DRV_DIB_GetImageBits_xx
3811    * To prevent this we simply change the sign of lines
3812    * (the number of scan lines to copy).
3813    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3814    */
3815   if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3816
3817   if( startscan >= bmp->bitmap.bmHeight )
3818   {
3819       lines = 0;
3820       goto done;
3821   }
3822
3823   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3824                         &descr.infoBpp, &descr.compression ) == -1)
3825   {
3826       lines = 0;
3827       goto done;
3828   }
3829
3830   descr.colorMap = NULL;
3831
3832   switch (descr.infoBpp)
3833   {
3834       case 1:
3835       case 4:
3836       case 8:
3837           descr.rMask= descr.gMask = descr.bMask = 0;
3838           if(coloruse == DIB_RGB_COLORS)
3839               descr.colorMap = info->bmiColors;
3840           else {
3841               int num_colors = 1 << descr.infoBpp, i;
3842               RGBQUAD *rgb;
3843               COLORREF colref;
3844               WORD *index = (WORD*)info->bmiColors;
3845               descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
3846               for(i = 0; i < num_colors; i++, rgb++, index++) {
3847                   colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
3848                   rgb->rgbRed = GetRValue(colref);
3849                   rgb->rgbGreen = GetGValue(colref);
3850                   rgb->rgbBlue = GetBValue(colref);
3851                   rgb->rgbReserved = 0;
3852               }
3853           }
3854           break;
3855       case 15:
3856       case 16:
3857           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3858           descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
3859           descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
3860           break;
3861       case 24:
3862       case 32:
3863           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3864           descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3865           descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3866           break;
3867   }
3868
3869   descr.physDev   = physDev;
3870   descr.palentry  = palette;
3871   descr.bits      = bits;
3872   descr.image     = NULL;
3873   descr.lines     = lines;
3874   descr.depth     = bmp->bitmap.bmBitsPixel;
3875   descr.drawable  = (Pixmap)bmp->physBitmap;
3876   descr.gc        = BITMAP_GC(bmp);
3877   descr.width     = bmp->bitmap.bmWidth;
3878   descr.height    = bmp->bitmap.bmHeight;
3879   descr.xDest     = 0;
3880   descr.yDest     = 0;
3881   descr.xSrc      = 0;
3882   descr.sizeImage = info->bmiHeader.biSizeImage;
3883
3884   if (descr.lines > 0)
3885   {
3886      descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3887   }
3888   else
3889   {
3890      descr.ySrc = startscan;
3891   }
3892 #ifdef HAVE_LIBXXSHM
3893   descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3894 #else
3895   descr.useShm = FALSE;
3896 #endif
3897   descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3898                        : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3899
3900   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3901   X11DRV_DIB_GetImageBits( &descr );
3902   X11DRV_DIB_Unlock(bmp, TRUE);
3903
3904   if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3905       info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBWidthBytes( info->bmiHeader.biWidth,
3906                                                                  info->bmiHeader.biBitCount )
3907                                     * abs( info->bmiHeader.biHeight );
3908
3909   if (descr.compression == BI_BITFIELDS)
3910   {
3911     *(DWORD *)info->bmiColors = descr.rMask;
3912     *((DWORD *)info->bmiColors+1) = descr.gMask;
3913     *((DWORD *)info->bmiColors+2) = descr.bMask;
3914   }
3915   else
3916   {
3917     /* if RLE or JPEG compression were supported,
3918      * this line would be invalid. */
3919     info->bmiHeader.biCompression = 0;
3920   }
3921
3922   if(descr.colorMap && descr.colorMap != info->bmiColors)
3923       HeapFree(GetProcessHeap(), 0, descr.colorMap);
3924 done:
3925   GDI_ReleaseObj( hbitmap );
3926   return lines;
3927 }
3928
3929 /***********************************************************************
3930  *           DIB_DoProtectDIBSection
3931  */
3932 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3933 {
3934     DWORD old_prot;
3935     INT totalSize;
3936     DIBSECTION *dib = bmp->dib;
3937     INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3938                                              : -dib->dsBm.bmHeight;
3939
3940     /* use the biSizeImage data as the memory size only if we're dealing with a
3941        compressed image where the value is set.  Otherwise, calculate based on
3942        width * height */
3943     if (dib->dsBmih.biSizeImage &&
3944         (dib->dsBmih.biCompression == BI_RLE4 || dib->dsBmih.biCompression == BI_RLE8))
3945         totalSize = dib->dsBmih.biSizeImage;
3946     else
3947         totalSize = dib->dsBm.bmWidthBytes * effHeight;
3948
3949     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3950     TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3951 }
3952
3953 /***********************************************************************
3954  *           X11DRV_DIB_DoUpdateDIBSection
3955  */
3956 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
3957                                         void *colorMap, int nColorMap,
3958                                         Drawable dest,
3959                                         DWORD xSrc, DWORD ySrc,
3960                                         DWORD xDest, DWORD yDest,
3961                                         DWORD width, DWORD height)
3962 {
3963   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3964   X11DRV_DIB_IMAGEBITS_DESCR descr;
3965
3966   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3967                          &descr.infoBpp, &descr.compression ) == -1)
3968     return;
3969
3970   descr.physDev   = NULL;
3971   descr.palentry  = NULL;
3972   descr.image     = dib->image;
3973   descr.colorMap  = colorMap;
3974   descr.nColorMap = nColorMap;
3975   descr.bits      = dib->dibSection.dsBm.bmBits;
3976   descr.depth     = bmp->bitmap.bmBitsPixel;
3977
3978   switch (descr.infoBpp)
3979   {
3980     case 1:
3981     case 4:
3982     case 8:
3983       descr.rMask = descr.gMask = descr.bMask = 0;
3984       break;
3985     case 15:
3986     case 16:
3987       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3988       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3989       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3990       break;
3991
3992     case 24:
3993     case 32:
3994       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
3995       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
3996       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
3997       break;
3998   }
3999
4000   /* Hack for now */
4001   descr.drawable  = dest;
4002   descr.gc        = BITMAP_GC(bmp);
4003   descr.xSrc      = xSrc;
4004   descr.ySrc      = ySrc;
4005   descr.xDest     = xDest;
4006   descr.yDest     = yDest;
4007   descr.width     = width;
4008   descr.height    = height;
4009   descr.sizeImage = 0;
4010
4011 #ifdef HAVE_LIBXXSHM
4012   descr.useShm = (dib->shminfo.shmid != -1);
4013 #else
4014   descr.useShm = FALSE;
4015 #endif
4016   descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
4017
4018   if (toDIB)
4019     {
4020       TRACE("Copying from Pixmap to DIB bits\n");
4021       X11DRV_DIB_GetImageBits( &descr );
4022     }
4023   else
4024     {
4025       TRACE("Copying from DIB bits to Pixmap\n");
4026       X11DRV_DIB_SetImageBits( &descr );
4027     }
4028 }
4029
4030 /***********************************************************************
4031  *           X11DRV_DIB_CopyDIBSection
4032  */
4033 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
4034                                DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
4035                                DWORD width, DWORD height)
4036 {
4037   BITMAPOBJ *bmp;
4038   HBITMAP hBitmap;
4039   int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
4040
4041   TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", physDevSrc->hdc, physDevDst->hdc,
4042     xSrc, ySrc, xDest, yDest, width, height);
4043   /* this function is meant as an optimization for BitBlt,
4044    * not to be called otherwise */
4045   if (GetObjectType( physDevSrc->hdc ) != OBJ_MEMDC) {
4046     ERR("called for non-memory source DC!?\n");
4047     return;
4048   }
4049
4050   hBitmap = GetCurrentObject( physDevSrc->hdc, OBJ_BITMAP );
4051   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC );
4052   if (!(bmp && bmp->dib)) {
4053     ERR("called for non-DIBSection!?\n");
4054     GDI_ReleaseObj( hBitmap );
4055     return;
4056   }
4057   /* while BitBlt should already have made sure we only get
4058    * positive values, we should check for oversize values */
4059   if ((xSrc < bmp->bitmap.bmWidth) &&
4060       (ySrc < bmp->bitmap.bmHeight)) {
4061     if (xSrc + width > bmp->bitmap.bmWidth)
4062       width = bmp->bitmap.bmWidth - xSrc;
4063     if (ySrc + height > bmp->bitmap.bmHeight)
4064       height = bmp->bitmap.bmHeight - ySrc;
4065     /* if the source bitmap is 8bpp or less, we're supposed to use the
4066      * DC's palette for color conversion (not the DIB color table) */
4067     if (bmp->dib->dsBm.bmBitsPixel <= 8) {
4068       X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4069       HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL );
4070       if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
4071         /* HACK: no palette has been set in the source DC,
4072          * use the DIB colormap instead - this is necessary in some
4073          * cases since we need to do depth conversion in some places
4074          * where real Windows can just copy data straight over */
4075         colorMap = dib->colorMap;
4076         nColorMap = dib->nColorMap;
4077       } else {
4078         colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4079                                              bmp->dib->dsBm.bmBitsPixel,
4080                                              (BITMAPINFO*)&(bmp->dib->dsBmih),
4081                                              &nColorMap );
4082         if (colorMap) aColorMap = TRUE;
4083       }
4084     }
4085     /* perform the copy */
4086     X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
4087                                 physDevDst->drawable, xSrc, ySrc,
4088                                 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
4089                                 width, height);
4090     /* free color mapping */
4091     if (aColorMap)
4092       HeapFree(GetProcessHeap(), 0, colorMap);
4093   }
4094   GDI_ReleaseObj( hBitmap );
4095 }
4096
4097 /***********************************************************************
4098  *           X11DRV_DIB_DoUpdateDIBSection
4099  */
4100 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
4101 {
4102   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4103   X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
4104                               (Drawable)bmp->physBitmap, 0, 0, 0, 0,
4105                               bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
4106 }
4107
4108 /***********************************************************************
4109  *           X11DRV_DIB_FaultHandler
4110  */
4111 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
4112 {
4113   BITMAPOBJ *bmp;
4114   INT state;
4115
4116   bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
4117   if (!bmp) return FALSE;
4118
4119   state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
4120   if (state != DIB_Status_InSync) {
4121     /* no way to tell whether app needs read or write yet,
4122      * try read first */
4123     X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
4124   } else {
4125     /* hm, apparently the app must have write access */
4126     X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
4127   }
4128   X11DRV_DIB_Unlock(bmp, TRUE);
4129
4130   GDI_ReleaseObj( (HBITMAP)res );
4131   return TRUE;
4132 }
4133
4134 /***********************************************************************
4135  *           X11DRV_DIB_Coerce
4136  */
4137 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
4138 {
4139   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4140   INT ret = DIB_Status_None;
4141
4142   if (dib) {
4143     EnterCriticalSection(&(dib->lock));
4144     ret = dib->status;
4145     switch (req) {
4146     case DIB_Status_GdiMod:
4147       /* GDI access - request to draw on pixmap */
4148       switch (dib->status)
4149       {
4150         default:
4151         case DIB_Status_None:
4152           dib->p_status = DIB_Status_GdiMod;
4153           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4154           break;
4155
4156         case DIB_Status_GdiMod:
4157           TRACE("GdiMod requested in status GdiMod\n" );
4158           break;
4159
4160         case DIB_Status_InSync:
4161           TRACE("GdiMod requested in status InSync\n" );
4162           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4163           dib->status = DIB_Status_GdiMod;
4164           dib->p_status = DIB_Status_InSync;
4165           break;
4166
4167         case DIB_Status_AuxMod:
4168           TRACE("GdiMod requested in status AuxMod\n" );
4169           if (lossy) dib->status = DIB_Status_GdiMod;
4170           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
4171           dib->p_status = DIB_Status_AuxMod;
4172           if (dib->status != DIB_Status_AppMod) {
4173             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4174             break;
4175           }
4176           /* fall through if copy_aux() had to change to AppMod state */
4177
4178         case DIB_Status_AppMod:
4179           TRACE("GdiMod requested in status AppMod\n" );
4180           if (!lossy) {
4181             /* make it readonly to avoid app changing data while we copy */
4182             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4183             X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4184           }
4185           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4186           dib->p_status = DIB_Status_AppMod;
4187           dib->status = DIB_Status_GdiMod;
4188           break;
4189       }
4190       break;
4191
4192     case DIB_Status_InSync:
4193       /* App access - request access to read DIB surface */
4194       /* (typically called from signal handler) */
4195       switch (dib->status)
4196       {
4197         default:
4198         case DIB_Status_None:
4199           /* shouldn't happen from signal handler */
4200           break;
4201
4202         case DIB_Status_AuxMod:
4203           TRACE("InSync requested in status AuxMod\n" );
4204           if (lossy) dib->status = DIB_Status_InSync;
4205           else {
4206             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4207             (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
4208           }
4209           if (dib->status != DIB_Status_GdiMod) {
4210             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4211             break;
4212           }
4213           /* fall through if copy_aux() had to change to GdiMod state */
4214
4215         case DIB_Status_GdiMod:
4216           TRACE("InSync requested in status GdiMod\n" );
4217           if (!lossy) {
4218             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4219             X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4220           }
4221           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4222           dib->status = DIB_Status_InSync;
4223           break;
4224
4225         case DIB_Status_InSync:
4226           TRACE("InSync requested in status InSync\n" );
4227           /* shouldn't happen from signal handler */
4228           break;
4229
4230         case DIB_Status_AppMod:
4231           TRACE("InSync requested in status AppMod\n" );
4232           /* no reason to do anything here, and this
4233            * shouldn't happen from signal handler */
4234           break;
4235       }
4236       break;
4237
4238     case DIB_Status_AppMod:
4239       /* App access - request access to write DIB surface */
4240       /* (typically called from signal handler) */
4241       switch (dib->status)
4242       {
4243         default:
4244         case DIB_Status_None:
4245           /* shouldn't happen from signal handler */
4246           break;
4247
4248         case DIB_Status_AuxMod:
4249           TRACE("AppMod requested in status AuxMod\n" );
4250           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4251           if (lossy) dib->status = DIB_Status_AppMod;
4252           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4253           if (dib->status != DIB_Status_GdiMod)
4254             break;
4255           /* fall through if copy_aux() had to change to GdiMod state */
4256
4257         case DIB_Status_GdiMod:
4258           TRACE("AppMod requested in status GdiMod\n" );
4259           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4260           if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4261           dib->status = DIB_Status_AppMod;
4262           break;
4263
4264         case DIB_Status_InSync:
4265           TRACE("AppMod requested in status InSync\n" );
4266           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4267           dib->status = DIB_Status_AppMod;
4268           break;
4269
4270         case DIB_Status_AppMod:
4271           TRACE("AppMod requested in status AppMod\n" );
4272           /* shouldn't happen from signal handler */
4273           break;
4274       }
4275       break;
4276
4277     case DIB_Status_AuxMod:
4278       if (dib->status == DIB_Status_None) {
4279         dib->p_status = req;
4280       } else {
4281         if (dib->status != DIB_Status_AuxMod)
4282           dib->p_status = dib->status;
4283         dib->status = DIB_Status_AuxMod;
4284       }
4285       break;
4286       /* it is up to the caller to do the copy/conversion, probably
4287        * using the return value to decide where to copy from */
4288     }
4289     LeaveCriticalSection(&(dib->lock));
4290   }
4291   return ret;
4292 }
4293
4294 /***********************************************************************
4295  *           X11DRV_DIB_Lock
4296  */
4297 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
4298 {
4299   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4300   INT ret = DIB_Status_None;
4301
4302   if (dib) {
4303     TRACE("Locking %p from thread %04lx\n", bmp, GetCurrentThreadId());
4304     EnterCriticalSection(&(dib->lock));
4305     ret = dib->status;
4306     if (req != DIB_Status_None)
4307       X11DRV_DIB_Coerce(bmp, req, lossy);
4308   }
4309   return ret;
4310 }
4311
4312 /***********************************************************************
4313  *           X11DRV_DIB_Unlock
4314  */
4315 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
4316 {
4317   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4318
4319   if (dib) {
4320     switch (dib->status)
4321     {
4322       default:
4323       case DIB_Status_None:
4324         /* in case anyone is wondering, this is the "signal handler doesn't
4325          * work" case, where we always have to be ready for app access */
4326         if (commit) {
4327           switch (dib->p_status)
4328           {
4329             case DIB_Status_AuxMod:
4330               TRACE("Unlocking and syncing from AuxMod\n" );
4331               (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4332               if (dib->status != DIB_Status_None) {
4333                 dib->p_status = dib->status;
4334                 dib->status = DIB_Status_None;
4335               }
4336               if (dib->p_status != DIB_Status_GdiMod)
4337                 break;
4338               /* fall through if copy_aux() had to change to GdiMod state */
4339
4340             case DIB_Status_GdiMod:
4341               TRACE("Unlocking and syncing from GdiMod\n" );
4342               X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4343               break;
4344
4345             default:
4346               TRACE("Unlocking without needing to sync\n" );
4347               break;
4348           }
4349         }
4350         else TRACE("Unlocking with no changes\n");
4351         dib->p_status = DIB_Status_None;
4352         break;
4353
4354       case DIB_Status_GdiMod:
4355         TRACE("Unlocking in status GdiMod\n" );
4356         /* DIB was protected in Coerce */
4357         if (!commit) {
4358           /* no commit, revert to InSync if applicable */
4359           if ((dib->p_status == DIB_Status_InSync) ||
4360               (dib->p_status == DIB_Status_AppMod)) {
4361             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4362             dib->status = DIB_Status_InSync;
4363           }
4364         }
4365         break;
4366
4367       case DIB_Status_InSync:
4368         TRACE("Unlocking in status InSync\n" );
4369         /* DIB was already protected in Coerce */
4370         break;
4371
4372       case DIB_Status_AppMod:
4373         TRACE("Unlocking in status AppMod\n" );
4374         /* DIB was already protected in Coerce */
4375         /* this case is ordinary only called from the signal handler,
4376          * so we don't bother to check for !commit */
4377         break;
4378
4379       case DIB_Status_AuxMod:
4380         TRACE("Unlocking in status AuxMod\n" );
4381         if (commit) {
4382           /* DIB may need protection now */
4383           if ((dib->p_status == DIB_Status_InSync) ||
4384               (dib->p_status == DIB_Status_AppMod))
4385             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4386         } else {
4387           /* no commit, revert to previous state */
4388           if (dib->p_status != DIB_Status_None)
4389             dib->status = dib->p_status;
4390           /* no protections changed */
4391         }
4392         dib->p_status = DIB_Status_None;
4393         break;
4394     }
4395     LeaveCriticalSection(&(dib->lock));
4396     TRACE("Unlocked %p\n", bmp);
4397   }
4398 }
4399
4400 /***********************************************************************
4401  *           X11DRV_CoerceDIBSection2
4402  */
4403 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4404 {
4405   BITMAPOBJ *bmp;
4406   INT ret;
4407
4408   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4409   if (!bmp) return DIB_Status_None;
4410   ret = X11DRV_DIB_Coerce(bmp, req, lossy);
4411   GDI_ReleaseObj( hBmp );
4412   return ret;
4413 }
4414
4415 /***********************************************************************
4416  *           X11DRV_LockDIBSection2
4417  */
4418 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4419 {
4420   BITMAPOBJ *bmp;
4421   INT ret;
4422
4423   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4424   if (!bmp) return DIB_Status_None;
4425   ret = X11DRV_DIB_Lock(bmp, req, lossy);
4426   GDI_ReleaseObj( hBmp );
4427   return ret;
4428 }
4429
4430 /***********************************************************************
4431  *           X11DRV_UnlockDIBSection2
4432  */
4433 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
4434 {
4435   BITMAPOBJ *bmp;
4436
4437   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4438   if (!bmp) return;
4439   X11DRV_DIB_Unlock(bmp, commit);
4440   GDI_ReleaseObj( hBmp );
4441 }
4442
4443 /***********************************************************************
4444  *           X11DRV_CoerceDIBSection
4445  */
4446 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4447 {
4448   if (!physDev) return DIB_Status_None;
4449   return X11DRV_CoerceDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), req, lossy );
4450 }
4451
4452 /***********************************************************************
4453  *           X11DRV_LockDIBSection
4454  */
4455 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4456 {
4457   if (!physDev) return DIB_Status_None;
4458   if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return DIB_Status_None;
4459
4460   return X11DRV_LockDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), req, lossy );
4461 }
4462
4463 /***********************************************************************
4464  *           X11DRV_UnlockDIBSection
4465  */
4466 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4467 {
4468   if (!physDev) return;
4469   if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return;
4470
4471   X11DRV_UnlockDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), commit );
4472 }
4473
4474
4475 #ifdef HAVE_LIBXXSHM
4476 /***********************************************************************
4477  *           X11DRV_XShmErrorHandler
4478  *
4479  */
4480 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4481 {
4482     return 1;  /* FIXME: should check event contents */
4483 }
4484
4485 /***********************************************************************
4486  *           X11DRV_XShmCreateImage
4487  *
4488  */
4489 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4490                                        XShmSegmentInfo* shminfo)
4491 {
4492     XImage *image;
4493
4494     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4495     if (image)
4496     {
4497         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4498                                   IPC_CREAT|0700);
4499         if( shminfo->shmid != -1 )
4500         {
4501             shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
4502             if( shminfo->shmaddr != (char*)-1 )
4503             {
4504                 BOOL ok;
4505
4506                 shminfo->readOnly = FALSE;
4507                 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4508                 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4509                 XSync( gdi_display, False );
4510                 if (X11DRV_check_error()) ok = FALSE;
4511                 if (ok)
4512                 {
4513                     shmctl(shminfo->shmid, IPC_RMID, 0);
4514                     return image; /* Success! */
4515                 }
4516                 /* An error occurred */
4517                 shmdt(shminfo->shmaddr);
4518             }
4519             shmctl(shminfo->shmid, IPC_RMID, 0);
4520         }
4521         XFlush(gdi_display);
4522         XDestroyImage(image);
4523         image = NULL;
4524     }
4525     return image;
4526 }
4527 #endif /* HAVE_LIBXXSHM */
4528
4529
4530 /***********************************************************************
4531  *           X11DRV_DIB_CreateDIBSection
4532  */
4533 HBITMAP X11DRV_DIB_CreateDIBSection(
4534   X11DRV_PDEVICE *physDev, const BITMAPINFO *bmi, UINT usage,
4535   VOID **bits, HANDLE section,
4536   DWORD offset, DWORD ovr_pitch)
4537 {
4538   HBITMAP res = 0;
4539   BITMAPOBJ *bmp = NULL;
4540   X11DRV_DIBSECTION *dib = NULL;
4541   int *colorMap = NULL;
4542   int nColorMap;
4543
4544   /* Fill BITMAP32 structure with DIB data */
4545   const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
4546   INT effHeight, totalSize;
4547   BITMAP bm;
4548   LPVOID mapBits = NULL;
4549
4550   TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
4551         bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
4552         bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
4553
4554   effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
4555   bm.bmType = 0;
4556   bm.bmWidth = bi->biWidth;
4557   bm.bmHeight = effHeight;
4558   bm.bmWidthBytes = ovr_pitch ? ovr_pitch : X11DRV_DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
4559   bm.bmPlanes = bi->biPlanes;
4560   bm.bmBitsPixel = bi->biBitCount;
4561   bm.bmBits = NULL;
4562
4563   /* Get storage location for DIB bits.  Only use biSizeImage if it's valid and
4564      we're dealing with a compressed bitmap.  Otherwise, use width * height. */
4565   if (bi->biSizeImage && (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8))
4566       totalSize = bi->biSizeImage;
4567   else
4568       totalSize = bm.bmWidthBytes * effHeight;
4569
4570   if (section)
4571   {
4572       SYSTEM_INFO SystemInfo;
4573       DWORD mapOffset;
4574       INT mapSize;
4575
4576       GetSystemInfo( &SystemInfo );
4577       mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
4578       mapSize = totalSize + (offset - mapOffset);
4579       mapBits = MapViewOfFile( section,
4580                                FILE_MAP_ALL_ACCESS,
4581                                0L,
4582                                mapOffset,
4583                                mapSize );
4584       bm.bmBits = (char *)mapBits + (offset - mapOffset);
4585   }
4586   else if (ovr_pitch && offset)
4587     bm.bmBits = (LPVOID) offset;
4588   else {
4589     offset = 0;
4590     bm.bmBits = VirtualAlloc(NULL, totalSize,
4591                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
4592   }
4593
4594   /* Create Color Map */
4595   if (bm.bmBits && bm.bmBitsPixel <= 8)
4596       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
4597                                            usage, bm.bmBitsPixel, bmi, &nColorMap );
4598
4599   /* Allocate Memory for DIB and fill structure */
4600   if (bm.bmBits)
4601     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
4602   if (dib)
4603     {
4604       dib->dibSection.dsBm = bm;
4605       dib->dibSection.dsBmih = *bi;
4606       dib->dibSection.dsBmih.biSizeImage = totalSize;
4607
4608       /* Set dsBitfields values */
4609        if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
4610        {
4611            dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
4612        }
4613        else switch( bi->biBitCount )
4614        {
4615            case 15:
4616            case 16:
4617                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
4618                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
4619                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
4620                break;
4621
4622            case 24:
4623            case 32:
4624                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors       : 0xff0000;
4625                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
4626                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
4627                break;
4628        }
4629       dib->dibSection.dshSection = section;
4630       dib->dibSection.dsOffset = offset;
4631
4632       dib->status    = DIB_Status_None;
4633       dib->nColorMap = nColorMap;
4634       dib->colorMap  = colorMap;
4635     }
4636
4637   /* Create Device Dependent Bitmap and add DIB pointer */
4638   if (dib)
4639     {
4640       res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
4641       if (res)
4642         {
4643           bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
4644           if (bmp) bmp->dib = (DIBSECTION *) dib;
4645         }
4646     }
4647
4648   /* Create XImage */
4649   if (dib && bmp)
4650   {
4651       wine_tsx11_lock();
4652 #ifdef HAVE_LIBXXSHM
4653       if (XShmQueryExtension(gdi_display) &&
4654           (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
4655                                                 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
4656       {
4657         ; /* Created Image */
4658       } else {
4659           dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4660           dib->shminfo.shmid = -1;
4661       }
4662 #else
4663       dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4664 #endif
4665       wine_tsx11_unlock();
4666   }
4667
4668   /* Clean up in case of errors */
4669   if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
4670     {
4671       TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
4672             res, bmp, dib, bm.bmBits);
4673       if (bm.bmBits)
4674         {
4675           if (section)
4676             UnmapViewOfFile(mapBits), bm.bmBits = NULL;
4677           else if (!offset)
4678             VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
4679         }
4680
4681       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
4682       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
4683       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
4684       if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
4685       if (res) { DeleteObject(res); res = 0; }
4686     }
4687   else if (bm.bmBits)
4688     {
4689       extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg);
4690       /* Install fault handler, if possible */
4691       InitializeCriticalSection(&(dib->lock));
4692       if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
4693         {
4694           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4695           if (dib) dib->status = DIB_Status_AppMod;
4696         }
4697     }
4698
4699   /* Return BITMAP handle and storage location */
4700   if (bmp) GDI_ReleaseObj(res);
4701   if (bm.bmBits && bits) *bits = bm.bmBits;
4702   return res;
4703 }
4704
4705 /***********************************************************************
4706  *           X11DRV_DIB_DeleteDIBSection
4707  */
4708 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
4709 {
4710   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4711
4712   if (dib->image)
4713   {
4714       wine_tsx11_lock();
4715 #ifdef HAVE_LIBXXSHM
4716       if (dib->shminfo.shmid != -1)
4717       {
4718           XShmDetach (gdi_display, &(dib->shminfo));
4719           XDestroyImage (dib->image);
4720           shmdt (dib->shminfo.shmaddr);
4721           dib->shminfo.shmid = -1;
4722       }
4723       else
4724 #endif
4725           XDestroyImage( dib->image );
4726       wine_tsx11_unlock();
4727   }
4728
4729   if (dib->colorMap)
4730     HeapFree(GetProcessHeap(), 0, dib->colorMap);
4731
4732   DeleteCriticalSection(&(dib->lock));
4733 }
4734
4735 /***********************************************************************
4736  *           SetDIBColorTable   (X11DRV.@)
4737  */
4738 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4739 {
4740     BITMAPOBJ * bmp;
4741     X11DRV_DIBSECTION *dib;
4742     UINT ret = 0;
4743     HBITMAP hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
4744
4745     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
4746     dib = (X11DRV_DIBSECTION *) bmp->dib;
4747
4748     if (dib && dib->colorMap) {
4749         UINT end = count + start;
4750         if (end > dib->nColorMap) end = dib->nColorMap;
4751         /*
4752          * Changing color table might change the mapping between
4753          * DIB colors and X11 colors and thus alter the visible state
4754          * of the bitmap object.
4755          */
4756         X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
4757         X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
4758                                 dib->dibSection.dsBm.bmBitsPixel,
4759                                 TRUE, colors, start, end );
4760         X11DRV_DIB_Unlock(bmp, TRUE);
4761         ret = end - start;
4762     }
4763     GDI_ReleaseObj( hBitmap );
4764     return ret;
4765 }
4766
4767 /***********************************************************************
4768  *           GetDIBColorTable   (X11DRV.@)
4769  */
4770 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
4771 {
4772     BITMAPOBJ * bmp;
4773     X11DRV_DIBSECTION *dib;
4774     UINT ret = 0;
4775     HBITMAP hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
4776
4777     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
4778     dib = (X11DRV_DIBSECTION *) bmp->dib;
4779
4780     if (dib && dib->colorMap) {
4781         UINT i, end = count + start;
4782         if (end > dib->nColorMap) end = dib->nColorMap;
4783         for (i = start; i < end; i++,colors++) {
4784             COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
4785             colors->rgbBlue  = GetBValue(col);
4786             colors->rgbGreen = GetGValue(col);
4787             colors->rgbRed   = GetRValue(col);
4788             colors->rgbReserved = 0;
4789         }
4790         ret = end-start;
4791     }
4792     GDI_ReleaseObj( hBitmap );
4793     return ret;
4794 }
4795
4796
4797
4798 /***********************************************************************
4799  *           X11DRV_DIB_CreateDIBFromBitmap
4800  *
4801  *  Allocates a packed DIB and copies the bitmap data into it.
4802  */
4803 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4804 {
4805     BITMAP bmp;
4806     HGLOBAL hPackedDIB;
4807     LPBYTE pPackedDIB;
4808     LPBITMAPINFOHEADER pbmiHeader;
4809     unsigned int cDataSize, cPackedSize, OffsetBits, nLinesCopied;
4810
4811     if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4812
4813     /*
4814      * A packed DIB contains a BITMAPINFO structure followed immediately by
4815      * an optional color palette and the pixel data.
4816      */
4817
4818     /* Calculate the size of the packed DIB */
4819     cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4820     cPackedSize = sizeof(BITMAPINFOHEADER)
4821                   + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4822                   + cDataSize;
4823     /* Get the offset to the bits */
4824     OffsetBits = cPackedSize - cDataSize;
4825
4826     /* Allocate the packed DIB */
4827     TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4828     hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4829                              cPackedSize );
4830     if ( !hPackedDIB )
4831     {
4832         WARN("Could not allocate packed DIB!\n");
4833         return 0;
4834     }
4835
4836     /* A packed DIB starts with a BITMAPINFOHEADER */
4837     pPackedDIB = GlobalLock(hPackedDIB);
4838     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4839
4840     /* Init the BITMAPINFOHEADER */
4841     pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4842     pbmiHeader->biWidth = bmp.bmWidth;
4843     pbmiHeader->biHeight = bmp.bmHeight;
4844     pbmiHeader->biPlanes = 1;
4845     pbmiHeader->biBitCount = bmp.bmBitsPixel;
4846     pbmiHeader->biCompression = BI_RGB;
4847     pbmiHeader->biSizeImage = 0;
4848     pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4849     pbmiHeader->biClrUsed = 0;
4850     pbmiHeader->biClrImportant = 0;
4851
4852     /* Retrieve the DIB bits from the bitmap and fill in the
4853      * DIB color table if present */
4854
4855     nLinesCopied = GetDIBits(hdc,                       /* Handle to device context */
4856                              hBmp,                      /* Handle to bitmap */
4857                              0,                         /* First scan line to set in dest bitmap */
4858                              bmp.bmHeight,              /* Number of scan lines to copy */
4859                              pPackedDIB + OffsetBits,   /* [out] Address of array for bitmap bits */
4860                              (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4861                              0);                        /* RGB or palette index */
4862     GlobalUnlock(hPackedDIB);
4863
4864     /* Cleanup if GetDIBits failed */
4865     if (nLinesCopied != bmp.bmHeight)
4866     {
4867         TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4868         GlobalFree(hPackedDIB);
4869         hPackedDIB = 0;
4870     }
4871     return hPackedDIB;
4872 }
4873
4874
4875 /**************************************************************************
4876  *              X11DRV_DIB_CreateDIBFromPixmap
4877  *
4878  *  Allocates a packed DIB and copies the Pixmap data into it.
4879  *  If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
4880  */
4881 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
4882 {
4883     HBITMAP hBmp = 0;
4884     BITMAPOBJ *pBmp = NULL;
4885     HGLOBAL hPackedDIB = 0;
4886
4887     /* Allocates an HBITMAP which references the Pixmap passed to us */
4888     hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(hdc, pixmap);
4889     if (!hBmp)
4890     {
4891         TRACE("\tCould not create bitmap header for Pixmap\n");
4892         goto END;
4893     }
4894
4895     /*
4896      * Create a packed DIB from the Pixmap wrapper bitmap created above.
4897      * A packed DIB contains a BITMAPINFO structure followed immediately by
4898      * an optional color palette and the pixel data.
4899      */
4900     hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4901
4902     /* Get a pointer to the BITMAPOBJ structure */
4903     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4904
4905     /* We can now get rid of the HBITMAP wrapper we created earlier.
4906      * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4907      */
4908     if (!bDeletePixmap)
4909     {
4910         /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
4911         pBmp->physBitmap = NULL;
4912         pBmp->funcs = NULL;
4913     }
4914     GDI_ReleaseObj( hBmp );
4915     DeleteObject(hBmp);
4916
4917 END:
4918     TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4919     return hPackedDIB;
4920 }
4921
4922
4923 /**************************************************************************
4924  *                 X11DRV_DIB_CreatePixmapFromDIB
4925  *
4926  *    Creates a Pixmap from a packed DIB
4927  */
4928 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4929 {
4930     Pixmap pixmap = None;
4931     HBITMAP hBmp = 0;
4932     BITMAPOBJ *pBmp = NULL;
4933     LPBYTE pPackedDIB = NULL;
4934     LPBITMAPINFO pbmi = NULL;
4935     LPBITMAPINFOHEADER pbmiHeader = NULL;
4936     LPBYTE pbits = NULL;
4937
4938     /* Get a pointer to the packed DIB's data  */
4939     pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
4940     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4941     pbmi = (LPBITMAPINFO)pPackedDIB;
4942     pbits = (LPBYTE)(pPackedDIB
4943                      + X11DRV_DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
4944
4945     /* Create a DDB from the DIB */
4946
4947     hBmp = CreateDIBitmap(hdc,
4948                           pbmiHeader,
4949                           CBM_INIT,
4950                           (LPVOID)pbits,
4951                           pbmi,
4952                           DIB_RGB_COLORS);
4953
4954     GlobalUnlock(hPackedDIB);
4955
4956     TRACE("CreateDIBitmap returned %p\n", hBmp);
4957
4958     /* Retrieve the internal Pixmap from the DDB */
4959
4960     pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4961
4962     pixmap = (Pixmap)pBmp->physBitmap;
4963     /* clear the physBitmap so that we can steal its pixmap */
4964     pBmp->physBitmap = NULL;
4965     pBmp->funcs = NULL;
4966
4967     /* Delete the DDB we created earlier now that we have stolen its pixmap */
4968     GDI_ReleaseObj( hBmp );
4969     DeleteObject(hBmp);
4970
4971     TRACE("\tReturning Pixmap %ld\n", pixmap);
4972     return pixmap;
4973 }