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