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