winex11.drv: Remove remaining pixmap prefix to fix compilation without libxrender.
[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     ColorShifts            *shifts;
75     RGBQUAD                *colorMap;
76     int                     nColorMap;
77     Drawable                drawable;
78     GC                      gc;
79     int                     xSrc;
80     int                     ySrc;
81     int                     xDest;
82     int                     yDest;
83     int                     width;
84     int                     height;
85     DWORD                   rMask;
86     DWORD                   gMask;
87     DWORD                   bMask;
88     enum x11drv_shm_mode    shm_mode;
89     int                     dibpitch;
90     DWORD                   sizeImage;
91     X_PHYSBITMAP           *physBitmap;
92 } X11DRV_DIB_IMAGEBITS_DESCR;
93
94
95 enum Rle_EscapeCodes
96 {
97   RLE_EOL   = 0, /* End of line */
98   RLE_END   = 1, /* End of bitmap */
99   RLE_DELTA = 2  /* Delta */
100 };
101
102
103 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *,INT);
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     return ((width * depth + 31) / 8) & ~3;
158 }
159
160
161 /***********************************************************************
162  *           bitmap_info_size
163  *
164  * Return the size of the bitmap info structure including color table.
165  */
166 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
167 {
168     unsigned int colors, size, masks = 0;
169
170     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
171     {
172         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
173         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
174         return sizeof(BITMAPCOREHEADER) + colors *
175              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
176     }
177     else  /* assume BITMAPINFOHEADER */
178     {
179         colors = info->bmiHeader.biClrUsed;
180         if (!colors && (info->bmiHeader.biBitCount <= 8))
181             colors = 1 << info->bmiHeader.biBitCount;
182         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
183         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
184         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
185     }
186 }
187
188
189 /***********************************************************************
190  *           X11DRV_DIB_CreateXImage
191  *
192  * Create an X image.
193  */
194 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
195 {
196     int width_bytes;
197     XImage *image = NULL;
198     void *data;
199
200     wine_tsx11_lock();
201     width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
202     data = HeapAlloc( GetProcessHeap(), 0, height * width_bytes );
203     if (data) image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
204                                     data, width, height, 32, width_bytes );
205     if (!image) HeapFree( GetProcessHeap(), 0, data );
206     wine_tsx11_unlock();
207     return image;
208 }
209
210
211 /***********************************************************************
212  *           X11DRV_DIB_DestroyXImage
213  *
214  * Destroy an X image created with X11DRV_DIB_CreateXImage.
215  */
216 void X11DRV_DIB_DestroyXImage( XImage *image )
217 {
218     HeapFree( GetProcessHeap(), 0, image->data );
219     image->data = NULL;
220     wine_tsx11_lock();
221     XDestroyImage( image );
222     wine_tsx11_unlock();
223 }
224
225
226 /***********************************************************************
227  *           X11DRV_DIB_GetColorCount
228  *
229  * Computes the number of colors for the bitmap palette.
230  * Should not be called for a >8-bit deep bitmap.
231  */
232 static unsigned int X11DRV_DIB_GetColorCount(const BITMAPINFO *info)
233 {
234     unsigned int colors = min( info->bmiHeader.biClrUsed, 256 );
235     if (!colors) colors = 1 << info->bmiHeader.biBitCount;
236     return colors;
237 }
238
239
240 static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
241 {
242     return (c1.rgbRed * c1.rgbRed + c1.rgbGreen * c1.rgbGreen + c1.rgbBlue * c1.rgbBlue) > 
243         (c2.rgbRed * c2.rgbRed + c2.rgbGreen * c2.rgbGreen + c2.rgbBlue * c2.rgbBlue);
244 }
245
246 /***********************************************************************
247  *           X11DRV_DIB_GenColorMap
248  *
249  * Fills the color map of a bitmap palette. Should not be called
250  * for a >8-bit deep bitmap.
251  */
252 static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
253                                     WORD coloruse, WORD depth, const void *colorPtr, int start, int end )
254 {
255     int i;
256
257     if (coloruse == DIB_RGB_COLORS)
258     {
259         const RGBQUAD * rgb = colorPtr;
260
261         if (depth == 1)  /* Monochrome */
262         {
263             BOOL invert = FALSE;
264             RGBQUAD table[2];
265
266             if (GetDIBColorTable( physDev->dev.hdc, 0, 2, table ) == 2)
267                 invert = !colour_is_brighter(table[1], table[0]);
268
269             for (i = start; i < end; i++, rgb++)
270                 colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
271                                     rgb->rgbBlue > 255*3/2 && !invert) ||
272                                    (rgb->rgbRed + rgb->rgbGreen +
273                                     rgb->rgbBlue <= 255*3/2 && invert));
274         }
275         else
276             for (i = start; i < end; i++, rgb++)
277                 colorMapping[i] = X11DRV_PALETTE_LookupPixel(physDev->color_shifts, RGB(rgb->rgbRed,
278                                                                                         rgb->rgbGreen,
279                                                                                         rgb->rgbBlue));
280     }
281     else  /* DIB_PAL_COLORS */
282     {
283         const WORD * index = colorPtr;
284
285         for (i = start; i < end; i++, index++)
286             colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
287     }
288
289     return colorMapping;
290 }
291
292 /***********************************************************************
293  *           X11DRV_DIB_BuildColorMap
294  *
295  * Build the color map from the bitmap palette. Should not be called
296  * for a >8-bit deep bitmap.
297  */
298 static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
299                                       const BITMAPINFO *info, int *nColors )
300 {
301     const void *colorPtr;
302     int *colorMapping;
303
304
305     *nColors = X11DRV_DIB_GetColorCount(info);
306     if (!*nColors) return NULL;
307
308     colorPtr = (const BYTE*)info + (WORD)info->bmiHeader.biSize;
309     if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, *nColors * sizeof(int) )))
310         return NULL;
311
312     return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
313                                    colorPtr, 0, *nColors);
314 }
315
316 /***********************************************************************
317  *           X11DRV_DIB_MapColor
318  */
319 static int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
320 {
321     int color;
322
323     if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
324         return oldcol;
325
326     for (color = 0; color < nPhysMap; color++)
327         if (physMap[color] == phys)
328             return color;
329
330     WARN("Strange color %08x\n", phys);
331     return 0;
332 }
333
334
335 /*********************************************************************
336  *         X11DRV_DIB_GetNearestIndex
337  *
338  * Helper for X11DRV_DIB_GetDIBits.
339  * Returns the nearest colour table index for a given RGB.
340  * Nearest is defined by minimizing the sum of the squares.
341  */
342 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
343 {
344     INT i, best = -1, diff, bestdiff = -1;
345     RGBQUAD *color;
346
347     for(color = colormap, i = 0; i < numColors; color++, i++) {
348         diff = (r - color->rgbRed) * (r - color->rgbRed) +
349                (g - color->rgbGreen) * (g - color->rgbGreen) +
350                (b - color->rgbBlue) * (b - color->rgbBlue);
351         if(diff == 0)
352             return i;
353         if(best == -1 || diff < bestdiff) {
354             best = i;
355             bestdiff = diff;
356         }
357     }
358     return best;
359 }
360 /*********************************************************************
361  *         X11DRV_DIB_MaskToShift
362  *
363  * Helper for X11DRV_DIB_GetDIBits.
364  * Returns the by how many bits to shift a given color so that it is
365  * in the proper position.
366  */
367 INT X11DRV_DIB_MaskToShift(DWORD mask)
368 {
369     int shift;
370
371     if (mask==0)
372         return 0;
373
374     shift=0;
375     while ((mask&1)==0) {
376         mask>>=1;
377         shift++;
378     }
379     return shift;
380 }
381
382 /***********************************************************************
383  *           X11DRV_DIB_CheckMask
384  *
385  * Check RGB mask if it is either 0 or matches visual's mask.
386  */
387 static inline int X11DRV_DIB_CheckMask(int red_mask, int green_mask, int blue_mask)
388 {
389     return ( red_mask == 0 && green_mask == 0 && blue_mask == 0 ) ||
390            ( red_mask == visual->red_mask && green_mask == visual->green_mask &&
391              blue_mask == visual->blue_mask );
392 }
393
394 /***********************************************************************
395  *           X11DRV_DIB_SetImageBits_1
396  *
397  * SetDIBits for a 1-bit deep DIB.
398  */
399 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
400                                 DWORD srcwidth, DWORD dstwidth, int left,
401                                 int *colors, XImage *bmpImage, int linebytes)
402 {
403     int h, width;
404     const BYTE* srcbyte;
405     BYTE srcval, extra;
406     DWORD i, x;
407
408     if (lines < 0 ) {
409         lines = -lines;
410         srcbits = srcbits + linebytes * (lines - 1);
411         linebytes = -linebytes;
412     }
413
414     if ((extra = (left & 7)) != 0) {
415         left &= ~7;
416         dstwidth += extra;
417     }
418     srcbits += left >> 3;
419     width = min(srcwidth, dstwidth);
420
421     /* ==== pal 1 dib -> any bmp format ==== */
422     for (h = lines-1; h >=0; h--) {
423         srcbyte=srcbits;
424         for (i = width/8, x = left; i > 0; i--) {
425             srcval=*srcbyte++;
426             XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
427             XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
428             XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
429             XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
430             XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
431             XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
432             XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
433             XPutPixel( bmpImage, x++, h, colors[ srcval       & 1] );
434         }
435         if (width % 8){
436             srcval=*srcbyte;
437             switch (width & 7)
438             {
439             case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
440                 /* fall through */
441             case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
442                 /* fall through */
443             case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
444                 /* fall through */
445             case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
446                 /* fall through */
447             case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
448                 /* fall through */
449             case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
450                 /* fall through */
451             case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
452             }
453         }
454         srcbits += linebytes;
455     }
456 }
457
458 /***********************************************************************
459  *           X11DRV_DIB_GetImageBits_1
460  *
461  * GetDIBits for a 1-bit deep DIB.
462  */
463 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
464                                        DWORD dstwidth, DWORD srcwidth,
465                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
466                                        XImage *bmpImage, int linebytes )
467 {
468     DWORD x;
469     int h, width = min(dstwidth, srcwidth);
470
471     if (lines < 0 ) {
472         lines = -lines;
473         dstbits = dstbits + linebytes * (lines - 1);
474         linebytes = -linebytes;
475     }
476
477     switch (bmpImage->depth)
478     {
479     case 1:
480     case 4:
481         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
482             && srccolors) {
483             /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
484             BYTE* dstbyte;
485
486             for (h=lines-1; h>=0; h--) {
487                 BYTE dstval;
488                 dstbyte=dstbits;
489                 dstval=0;
490                 for (x=0; x<width; x++) {
491                     PALETTEENTRY srcval;
492                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
493                     dstval|=(X11DRV_DIB_GetNearestIndex
494                              (colors, 2,
495                               srcval.peRed,
496                               srcval.peGreen,
497                               srcval.peBlue) << (7 - (x & 7)));
498                     if ((x&7)==7) {
499                         *dstbyte++=dstval;
500                         dstval=0;
501                     }
502                 }
503                 if ((width&7)!=0) {
504                     *dstbyte++=dstval;
505                 }
506                 /* pad with 0 to DWORD alignment */
507                 for (x = (x+7)&~7; x < ((width + 31) & ~31); x+=8)
508                     *dstbyte++ = 0;
509                 dstbits += linebytes;
510             }
511         } else {
512             goto notsupported;
513         }
514         break;
515
516     case 8:
517         if (X11DRV_DIB_CheckMask(bmpImage->red_mask, bmpImage->green_mask, bmpImage->blue_mask)
518             && srccolors) {
519             /* ==== pal 8 bmp -> pal 1 dib ==== */
520             const void* srcbits;
521             const BYTE* srcpixel;
522             BYTE* dstbyte;
523
524             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
525
526             for (h=0; h<lines; h++) {
527                 BYTE dstval;
528                 srcpixel=srcbits;
529                 dstbyte=dstbits;
530                 dstval=0;
531                 for (x=0; x<width; x++) {
532                     PALETTEENTRY srcval;
533                     srcval=srccolors[*srcpixel++];
534                     dstval|=(X11DRV_DIB_GetNearestIndex
535                              (colors, 2,
536                               srcval.peRed,
537                               srcval.peGreen,
538                               srcval.peBlue) << (7-(x&7)) );
539                     if ((x&7)==7) {
540                         *dstbyte++=dstval;
541                         dstval=0;
542                     }
543                 }
544                 if ((width&7)!=0) {
545                     *dstbyte=dstval;
546                 }
547                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
548                 dstbits += linebytes;
549             }
550         } else {
551             goto notsupported;
552         }
553         break;
554
555     case 15:
556     case 16:
557         {
558             const void* srcbits;
559             const WORD* srcpixel;
560             BYTE* dstbyte;
561
562             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
563
564             if (bmpImage->green_mask==0x03e0) {
565                 if (bmpImage->red_mask==0x7c00) {
566                     /* ==== rgb 555 bmp -> pal 1 dib ==== */
567                     for (h=0; h<lines; h++) {
568                         BYTE dstval;
569                         srcpixel=srcbits;
570                         dstbyte=dstbits;
571                         dstval=0;
572                         for (x=0; x<width; x++) {
573                             WORD srcval;
574                             srcval=*srcpixel++;
575                             dstval|=(X11DRV_DIB_GetNearestIndex
576                                      (colors, 2,
577                                       ((srcval >>  7) & 0xf8) | /* r */
578                                       ((srcval >> 12) & 0x07),
579                                       ((srcval >>  2) & 0xf8) | /* g */
580                                       ((srcval >>  7) & 0x07),
581                                       ((srcval <<  3) & 0xf8) | /* b */
582                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
583                             if ((x&7)==7) {
584                                 *dstbyte++=dstval;
585                                 dstval=0;
586                             }
587                         }
588                         if ((width&7)!=0) {
589                             *dstbyte=dstval;
590                         }
591                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
592                         dstbits += linebytes;
593                     }
594                 } else if (bmpImage->blue_mask==0x7c00) {
595                     /* ==== bgr 555 bmp -> pal 1 dib ==== */
596                     for (h=0; h<lines; h++) {
597                         BYTE dstval;
598                         srcpixel=srcbits;
599                         dstbyte=dstbits;
600                         dstval=0;
601                         for (x=0; x<width; x++) {
602                             WORD srcval;
603
604                             srcval=*srcpixel++;
605                             dstval|=(X11DRV_DIB_GetNearestIndex
606                                      (colors, 2,
607                                       ((srcval <<  3) & 0xf8) | /* r */
608                                       ((srcval >>  2) & 0x07),
609                                       ((srcval >>  2) & 0xf8) | /* g */
610                                       ((srcval >>  7) & 0x07),
611                                       ((srcval >>  7) & 0xf8) | /* b */
612                                       ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
613                             if ((x&7)==7) {
614                                 *dstbyte++=dstval;
615                                 dstval=0;
616                             }
617                         }
618                         if ((width&7)!=0) {
619                             *dstbyte=dstval;
620                         }
621                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
622                         dstbits += linebytes;
623                     }
624                 } else {
625                     goto notsupported;
626                 }
627             } else if (bmpImage->green_mask==0x07e0) {
628                 if (bmpImage->red_mask==0xf800) {
629                     /* ==== rgb 565 bmp -> pal 1 dib ==== */
630                     for (h=0; h<lines; h++) {
631                         BYTE dstval;
632                         srcpixel=srcbits;
633                         dstbyte=dstbits;
634                         dstval=0;
635                         for (x=0; x<width; x++) {
636                             WORD srcval;
637                             srcval=*srcpixel++;
638                             dstval|=(X11DRV_DIB_GetNearestIndex
639                                      (colors, 2,
640                                       ((srcval >>  8) & 0xf8) | /* r */
641                                       ((srcval >> 13) & 0x07),
642                                       ((srcval >>  3) & 0xfc) | /* g */
643                                       ((srcval >>  9) & 0x03),
644                                       ((srcval <<  3) & 0xf8) | /* b */
645                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
646                             if ((x&7)==7) {
647                                 *dstbyte++=dstval;
648                                 dstval=0;
649                             }
650                         }
651                         if ((width&7)!=0) {
652                             *dstbyte=dstval;
653                         }
654                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
655                         dstbits += linebytes;
656                     }
657                 } else if (bmpImage->blue_mask==0xf800) {
658                     /* ==== bgr 565 bmp -> pal 1 dib ==== */
659                     for (h=0; h<lines; h++) {
660                         BYTE dstval;
661                         srcpixel=srcbits;
662                         dstbyte=dstbits;
663                         dstval=0;
664                         for (x=0; x<width; x++) {
665                             WORD srcval;
666                             srcval=*srcpixel++;
667                             dstval|=(X11DRV_DIB_GetNearestIndex
668                                      (colors, 2,
669                                       ((srcval <<  3) & 0xf8) | /* r */
670                                       ((srcval >>  2) & 0x07),
671                                       ((srcval >>  3) & 0xfc) | /* g */
672                                       ((srcval >>  9) & 0x03),
673                                       ((srcval >>  8) & 0xf8) | /* b */
674                                       ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
675                             if ((x&7)==7) {
676                                 *dstbyte++=dstval;
677                                 dstval=0;
678                             }
679                         }
680                         if ((width&7)!=0) {
681                             *dstbyte=dstval;
682                         }
683                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
684                         dstbits += linebytes;
685                     }
686                 } else {
687                     goto notsupported;
688                 }
689             } else {
690                 goto notsupported;
691             }
692         }
693         break;
694
695     case 24:
696     case 32:
697         {
698             const void* srcbits;
699             const BYTE *srcbyte;
700             BYTE* dstbyte;
701             int bytes_per_pixel;
702
703             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
704             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
705
706             if (bmpImage->green_mask!=0x00ff00 ||
707                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
708                 goto notsupported;
709             } else if (bmpImage->blue_mask==0xff) {
710                 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
711                 for (h=0; h<lines; h++) {
712                     BYTE dstval;
713                     srcbyte=srcbits;
714                     dstbyte=dstbits;
715                     dstval=0;
716                     for (x=0; x<width; x++) {
717                         dstval|=(X11DRV_DIB_GetNearestIndex
718                                  (colors, 2,
719                                   srcbyte[2],
720                                   srcbyte[1],
721                                   srcbyte[0]) << (7-(x&7)) );
722                         srcbyte+=bytes_per_pixel;
723                         if ((x&7)==7) {
724                             *dstbyte++=dstval;
725                             dstval=0;
726                         }
727                     }
728                     if ((width&7)!=0) {
729                         *dstbyte=dstval;
730                     }
731                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
732                     dstbits += linebytes;
733                 }
734             } else {
735                 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
736                 for (h=0; h<lines; h++) {
737                     BYTE dstval;
738                     srcbyte=srcbits;
739                     dstbyte=dstbits;
740                     dstval=0;
741                     for (x=0; x<width; x++) {
742                         dstval|=(X11DRV_DIB_GetNearestIndex
743                                  (colors, 2,
744                                   srcbyte[0],
745                                   srcbyte[1],
746                                   srcbyte[2]) << (7-(x&7)) );
747                         srcbyte+=bytes_per_pixel;
748                         if ((x&7)==7) {
749                             *dstbyte++=dstval;
750                             dstval=0;
751                         }
752                     }
753                     if ((width&7)!=0) {
754                         *dstbyte=dstval;
755                     }
756                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
757                     dstbits += linebytes;
758                 }
759             }
760         }
761         break;
762
763     default:
764     notsupported:
765         {
766             BYTE* dstbyte;
767             BYTE neg = 0;
768             unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
769
770             /* ==== any bmp format -> pal 1 dib ==== */
771             if ((unsigned)colors[0].rgbRed+colors[0].rgbGreen+colors[0].rgbBlue >=
772                 (unsigned)colors[1].rgbRed+colors[1].rgbGreen+colors[1].rgbBlue )
773                 neg = 1;
774
775             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB, "
776                  "%s color mapping\n",
777                   bmpImage->bits_per_pixel, bmpImage->red_mask,
778                   bmpImage->green_mask, bmpImage->blue_mask,
779                   neg?"negative":"direct" );
780
781             for (h=lines-1; h>=0; h--) {
782                 BYTE dstval;
783                 dstbyte=dstbits;
784                 dstval=0;
785                 for (x=0; x<width; x++) {
786                     dstval|=((XGetPixel( bmpImage, x, h) >= white) ^ neg) << (7 - (x&7));
787                     if ((x&7)==7) {
788                         *dstbyte++=dstval;
789                         dstval=0;
790                     }
791                 }
792                 if ((width&7)!=0) {
793                     *dstbyte=dstval;
794                 }
795                 dstbits += linebytes;
796             }
797         }
798         break;
799     }
800 }
801
802 /***********************************************************************
803  *           X11DRV_DIB_SetImageBits_4
804  *
805  * SetDIBits for a 4-bit deep DIB.
806  */
807 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
808                                 DWORD srcwidth, DWORD dstwidth, int left,
809                                 int *colors, XImage *bmpImage, int linebytes)
810 {
811     int h, width;
812     const BYTE* srcbyte;
813     DWORD i, x;
814
815     if (lines < 0 ) {
816         lines = -lines;
817         srcbits = srcbits + linebytes * (lines - 1);
818         linebytes = -linebytes;
819     }
820
821     if (left & 1) {
822         left--;
823         dstwidth++;
824     }
825     srcbits += left >> 1;
826     width = min(srcwidth, dstwidth);
827
828     /* ==== pal 4 dib -> any bmp format ==== */
829     for (h = lines-1; h >= 0; h--) {
830         srcbyte=srcbits;
831         for (i = width/2, x = left; i > 0; i--) {
832             BYTE srcval=*srcbyte++;
833             XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
834             XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
835         }
836         if (width & 1)
837             XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
838         srcbits += linebytes;
839     }
840 }
841
842
843
844 /***********************************************************************
845  *           X11DRV_DIB_GetImageBits_4
846  *
847  * GetDIBits for a 4-bit deep DIB.
848  */
849 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
850                                        DWORD srcwidth, DWORD dstwidth,
851                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
852                                        XImage *bmpImage, int linebytes )
853 {
854     DWORD x;
855     int h, width = min(srcwidth, dstwidth);
856
857     if (lines < 0 )
858     {
859        lines = -lines;
860        dstbits = dstbits + ( linebytes * (lines-1) );
861        linebytes = -linebytes;
862     }
863
864     switch (bmpImage->depth) {
865     case 1:
866     case 4:
867         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
868             && srccolors) {
869             /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
870             BYTE* dstbyte;
871
872             for (h = lines-1; h >= 0; h--) {
873                 BYTE dstval;
874                 dstbyte=dstbits;
875                 dstval=0;
876                 for (x = 0; x < width; x++) {
877                     PALETTEENTRY srcval;
878                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
879                     dstval|=(X11DRV_DIB_GetNearestIndex
880                              (colors, 16,
881                               srcval.peRed,
882                               srcval.peGreen,
883                               srcval.peBlue) << (4-((x&1)<<2)));
884                     if ((x&1)==1) {
885                         *dstbyte++=dstval;
886                         dstval=0;
887                     }
888                 }
889                 if ((width&1)!=0) {
890                     *dstbyte=dstval;
891                 }
892                 dstbits += linebytes;
893             }
894         } else {
895             goto notsupported;
896         }
897         break;
898
899     case 8:
900         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
901             && srccolors) {
902             /* ==== pal 8 bmp -> pal 4 dib ==== */
903             const void* srcbits;
904             const BYTE *srcpixel;
905             BYTE* dstbyte;
906
907             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
908             for (h=0; h<lines; h++) {
909                 BYTE dstval;
910                 srcpixel=srcbits;
911                 dstbyte=dstbits;
912                 dstval=0;
913                 for (x=0; x<width; x++) {
914                     PALETTEENTRY srcval;
915                     srcval = srccolors[*srcpixel++];
916                     dstval|=(X11DRV_DIB_GetNearestIndex
917                              (colors, 16,
918                               srcval.peRed,
919                               srcval.peGreen,
920                               srcval.peBlue) << (4*(1-(x&1))) );
921                     if ((x&1)==1) {
922                         *dstbyte++=dstval;
923                         dstval=0;
924                     }
925                 }
926                 if ((width&1)!=0) {
927                     *dstbyte=dstval;
928                 }
929                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
930                 dstbits += linebytes;
931             }
932         } else {
933             goto notsupported;
934         }
935         break;
936
937     case 15:
938     case 16:
939         {
940             const void* srcbits;
941             const WORD* srcpixel;
942             BYTE* dstbyte;
943
944             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
945
946             if (bmpImage->green_mask==0x03e0) {
947                 if (bmpImage->red_mask==0x7c00) {
948                     /* ==== rgb 555 bmp -> pal 4 dib ==== */
949                     for (h=0; h<lines; h++) {
950                         BYTE dstval;
951                         srcpixel=srcbits;
952                         dstbyte=dstbits;
953                         dstval=0;
954                         for (x=0; x<width; x++) {
955                             WORD srcval;
956                             srcval=*srcpixel++;
957                             dstval|=(X11DRV_DIB_GetNearestIndex
958                                      (colors, 16,
959                                       ((srcval >>  7) & 0xf8) | /* r */
960                                       ((srcval >> 12) & 0x07),
961                                       ((srcval >>  2) & 0xf8) | /* g */
962                                       ((srcval >>  7) & 0x07),
963                                       ((srcval <<  3) & 0xf8) | /* b */
964                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
965                             if ((x&1)==1) {
966                                 *dstbyte++=dstval;
967                                 dstval=0;
968                             }
969                         }
970                         if ((width&1)!=0) {
971                             *dstbyte=dstval;
972                         }
973                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
974                         dstbits += linebytes;
975                     }
976                 } else if (bmpImage->blue_mask==0x7c00) {
977                     /* ==== bgr 555 bmp -> pal 4 dib ==== */
978                     for (h=0; h<lines; h++) {
979                         WORD dstval;
980                         srcpixel=srcbits;
981                         dstbyte=dstbits;
982                         dstval=0;
983                         for (x=0; x<width; x++) {
984                             WORD srcval;
985                             srcval=*srcpixel++;
986                             dstval|=(X11DRV_DIB_GetNearestIndex
987                                      (colors, 16,
988                                       ((srcval <<  3) & 0xf8) | /* r */
989                                       ((srcval >>  2) & 0x07),
990                                       ((srcval >>  2) & 0xf8) | /* g */
991                                       ((srcval >>  7) & 0x07),
992                                       ((srcval >>  7) & 0xf8) | /* b */
993                                       ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
994                             if ((x&1)==1) {
995                                 *dstbyte++=dstval;
996                                 dstval=0;
997                             }
998                         }
999                         if ((width&1)!=0) {
1000                             *dstbyte=dstval;
1001                         }
1002                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1003                         dstbits += linebytes;
1004                     }
1005                 } else {
1006                     goto notsupported;
1007                 }
1008             } else if (bmpImage->green_mask==0x07e0) {
1009                 if (bmpImage->red_mask==0xf800) {
1010                     /* ==== rgb 565 bmp -> pal 4 dib ==== */
1011                     for (h=0; h<lines; h++) {
1012                         BYTE dstval;
1013                         srcpixel=srcbits;
1014                         dstbyte=dstbits;
1015                         dstval=0;
1016                         for (x=0; x<width; x++) {
1017                             WORD srcval;
1018                             srcval=*srcpixel++;
1019                             dstval|=(X11DRV_DIB_GetNearestIndex
1020                                      (colors, 16,
1021                                       ((srcval >>  8) & 0xf8) | /* r */
1022                                       ((srcval >> 13) & 0x07),
1023                                       ((srcval >>  3) & 0xfc) | /* g */
1024                                       ((srcval >>  9) & 0x03),
1025                                       ((srcval <<  3) & 0xf8) | /* b */
1026                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
1027                             if ((x&1)==1) {
1028                                 *dstbyte++=dstval;
1029                                 dstval=0;
1030                             }
1031                         }
1032                         if ((width&1)!=0) {
1033                             *dstbyte=dstval;
1034                         }
1035                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1036                         dstbits += linebytes;
1037                     }
1038                 } else if (bmpImage->blue_mask==0xf800) {
1039                     /* ==== bgr 565 bmp -> pal 4 dib ==== */
1040                     for (h=0; h<lines; h++) {
1041                         WORD dstval;
1042                         srcpixel=srcbits;
1043                         dstbyte=dstbits;
1044                         dstval=0;
1045                         for (x=0; x<width; x++) {
1046                             WORD srcval;
1047                             srcval=*srcpixel++;
1048                             dstval|=(X11DRV_DIB_GetNearestIndex
1049                                      (colors, 16,
1050                                       ((srcval <<  3) & 0xf8) | /* r */
1051                                       ((srcval >>  2) & 0x07),
1052                                       ((srcval >>  3) & 0xfc) | /* g */
1053                                       ((srcval >>  9) & 0x03),
1054                                       ((srcval >>  8) & 0xf8) | /* b */
1055                                       ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1056                             if ((x&1)==1) {
1057                                 *dstbyte++=dstval;
1058                                 dstval=0;
1059                             }
1060                         }
1061                         if ((width&1)!=0) {
1062                             *dstbyte=dstval;
1063                         }
1064                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1065                         dstbits += linebytes;
1066                     }
1067                 } else {
1068                     goto notsupported;
1069                 }
1070             } else {
1071                 goto notsupported;
1072             }
1073         }
1074         break;
1075
1076     case 24:
1077         if (bmpImage->bits_per_pixel==24) {
1078             const void* srcbits;
1079             const BYTE *srcbyte;
1080             BYTE* dstbyte;
1081
1082             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1083
1084             if (bmpImage->green_mask!=0x00ff00 ||
1085                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1086                 goto notsupported;
1087             } else if (bmpImage->blue_mask==0xff) {
1088                 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1089                 for (h=0; h<lines; h++) {
1090                     srcbyte=srcbits;
1091                     dstbyte=dstbits;
1092                     for (x=0; x<width/2; x++) {
1093                         /* Do 2 pixels at a time */
1094                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1095                                     (colors, 16,
1096                                      srcbyte[2],
1097                                      srcbyte[1],
1098                                      srcbyte[0]) << 4) |
1099                                     X11DRV_DIB_GetNearestIndex
1100                                     (colors, 16,
1101                                      srcbyte[5],
1102                                      srcbyte[4],
1103                                      srcbyte[3]);
1104                         srcbyte+=6;
1105                     }
1106                     if (width&1) {
1107                         /* And then the odd pixel */
1108                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1109                                     (colors, 16,
1110                                      srcbyte[2],
1111                                      srcbyte[1],
1112                                      srcbyte[0]) << 4);
1113                     }
1114                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1115                     dstbits += linebytes;
1116                 }
1117             } else {
1118                 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1119                 for (h=0; h<lines; h++) {
1120                     srcbyte=srcbits;
1121                     dstbyte=dstbits;
1122                     for (x=0; x<width/2; x++) {
1123                         /* Do 2 pixels at a time */
1124                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1125                                     (colors, 16,
1126                                      srcbyte[0],
1127                                      srcbyte[1],
1128                                      srcbyte[2]) << 4) |
1129                                     X11DRV_DIB_GetNearestIndex
1130                                     (colors, 16,
1131                                      srcbyte[3],
1132                                      srcbyte[4],
1133                                      srcbyte[5]);
1134                         srcbyte+=6;
1135                     }
1136                     if (width&1) {
1137                         /* And then the odd pixel */
1138                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1139                                     (colors, 16,
1140                                      srcbyte[0],
1141                                      srcbyte[1],
1142                                      srcbyte[2]) << 4);
1143                     }
1144                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1145                     dstbits += linebytes;
1146                 }
1147             }
1148             break;
1149         }
1150         /* Fall through */
1151
1152     case 32:
1153         {
1154             const void* srcbits;
1155             const BYTE *srcbyte;
1156             BYTE* dstbyte;
1157
1158             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1159
1160             if (bmpImage->green_mask!=0x00ff00 ||
1161                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1162                 goto notsupported;
1163             } else if (bmpImage->blue_mask==0xff) {
1164                 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1165                 for (h=0; h<lines; h++) {
1166                     srcbyte=srcbits;
1167                     dstbyte=dstbits;
1168                     for (x=0; x<width/2; x++) {
1169                         /* Do 2 pixels at a time */
1170                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1171                                     (colors, 16,
1172                                      srcbyte[2],
1173                                      srcbyte[1],
1174                                      srcbyte[0]) << 4) |
1175                                     X11DRV_DIB_GetNearestIndex
1176                                     (colors, 16,
1177                                      srcbyte[6],
1178                                      srcbyte[5],
1179                                      srcbyte[4]);
1180                         srcbyte+=8;
1181                     }
1182                     if (width&1) {
1183                         /* And then the odd pixel */
1184                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1185                                     (colors, 16,
1186                                      srcbyte[2],
1187                                      srcbyte[1],
1188                                      srcbyte[0]) << 4);
1189                     }
1190                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1191                     dstbits += linebytes;
1192                 }
1193             } else {
1194                 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1195                 for (h=0; h<lines; h++) {
1196                     srcbyte=srcbits;
1197                     dstbyte=dstbits;
1198                     for (x=0; x<width/2; x++) {
1199                         /* Do 2 pixels at a time */
1200                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1201                                     (colors, 16,
1202                                      srcbyte[0],
1203                                      srcbyte[1],
1204                                      srcbyte[2]) << 4) |
1205                                     X11DRV_DIB_GetNearestIndex
1206                                     (colors, 16,
1207                                      srcbyte[4],
1208                                      srcbyte[5],
1209                                      srcbyte[6]);
1210                         srcbyte+=8;
1211                     }
1212                     if (width&1) {
1213                         /* And then the odd pixel */
1214                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1215                                     (colors, 16,
1216                                      srcbyte[0],
1217                                      srcbyte[1],
1218                                      srcbyte[2]) << 4);
1219                     }
1220                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1221                     dstbits += linebytes;
1222                 }
1223             }
1224         }
1225         break;
1226
1227     default:
1228     notsupported:
1229         {
1230             BYTE* dstbyte;
1231
1232             /* ==== any bmp format -> pal 4 dib ==== */
1233             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1234                   bmpImage->bits_per_pixel, bmpImage->red_mask,
1235                   bmpImage->green_mask, bmpImage->blue_mask );
1236             for (h=lines-1; h>=0; h--) {
1237                 dstbyte=dstbits;
1238                 for (x=0; x<(width & ~1); x+=2) {
1239                     *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1240                         X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1241                 }
1242                 if (width & 1) {
1243                     *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1244                 }
1245                 dstbits += linebytes;
1246             }
1247         }
1248         break;
1249     }
1250 }
1251
1252 /***********************************************************************
1253  *           X11DRV_DIB_SetImageBits_8
1254  *
1255  * SetDIBits for an 8-bit deep DIB.
1256  */
1257 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1258                                 DWORD srcwidth, DWORD dstwidth, int left,
1259                                 const int *colors, XImage *bmpImage,
1260                                 int linebytes )
1261 {
1262     DWORD x;
1263     int h, width = min(srcwidth, dstwidth);
1264     const BYTE* srcbyte;
1265     BYTE* dstbits;
1266
1267     if (lines < 0 )
1268     {
1269         lines = -lines;
1270         srcbits = srcbits + linebytes * (lines-1);
1271         linebytes = -linebytes;
1272     }
1273     srcbits += left;
1274     srcbyte = srcbits;
1275
1276     switch (bmpImage->depth) {
1277     case 15:
1278     case 16:
1279         /* Some X servers might have 32 bit/ 16bit deep pixel */
1280         if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1281             (ImageByteOrder(gdi_display)==LSBFirst) )
1282         {
1283             /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1284             dstbits=(BYTE*)bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1285             for (h = lines ; h--; ) {
1286                 DWORD* dstpixel=(DWORD*)dstbits;
1287                 for (x=0; x<width/2; x++) {
1288                     /* Do 2 pixels at a time */
1289                     *dstpixel++=(colors[srcbyte[1]] << 16) | colors[srcbyte[0]];
1290                     srcbyte+=2;
1291                 }
1292                 if (width&1) {
1293                     /* And then the odd pixel */
1294                     *((WORD*)dstpixel)=colors[srcbyte[0]];
1295                 }
1296                 srcbyte = (srcbits += linebytes);
1297                 dstbits -= bmpImage->bytes_per_line;
1298             }
1299             return;
1300         }
1301         break;
1302     case 24:
1303     case 32:
1304         if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1305             (ImageByteOrder(gdi_display)==LSBFirst) )
1306         {
1307             dstbits=(BYTE*)bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1308             /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1309             for (h = lines ; h--; ) {
1310                 DWORD* dstpixel=(DWORD*)dstbits;
1311                 for (x=0; x<width; x++) {
1312                     *dstpixel++=colors[*srcbyte++];
1313                 }
1314                 srcbyte = (srcbits += linebytes);
1315                 dstbits -= bmpImage->bytes_per_line;
1316             }
1317             return;
1318         }
1319         break;
1320     default:
1321         break; /* use slow generic case below */
1322     }
1323
1324     /* ==== pal 8 dib -> any bmp format ==== */
1325     for (h=lines-1; h>=0; h--) {
1326         for (x=left; x<width+left; x++) {
1327             XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1328         }
1329         srcbyte = (srcbits += linebytes);
1330     }
1331 }
1332
1333 /***********************************************************************
1334  *           X11DRV_DIB_GetImageBits_8
1335  *
1336  * GetDIBits for an 8-bit deep DIB.
1337  */
1338 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1339                                        DWORD srcwidth, DWORD dstwidth,
1340                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
1341                                        XImage *bmpImage, int linebytes )
1342 {
1343     DWORD x;
1344     int h, width = min(srcwidth, dstwidth);
1345     BYTE* dstbyte;
1346
1347     if (lines < 0 )
1348     {
1349        lines = -lines;
1350        dstbits = dstbits + ( linebytes * (lines-1) );
1351        linebytes = -linebytes;
1352     }
1353
1354     /*
1355      * Hack for now
1356      * This condition is true when GetImageBits has been called by
1357      * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1358      * 256 colormaps, so we'll just use it for GetDIBits calls.
1359      * (In some cases, in an updateDIBSection, the returned colors are bad too)
1360      */
1361     if (!srccolors) goto updatesection;
1362
1363     switch (bmpImage->depth) {
1364     case 1:
1365     case 4:
1366         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1367             && srccolors) {
1368
1369             /* ==== pal 1 bmp -> pal 8 dib ==== */
1370             /* ==== pal 4 bmp -> pal 8 dib ==== */
1371             for (h=lines-1; h>=0; h--) {
1372                 dstbyte=dstbits;
1373                 for (x=0; x<width; x++) {
1374                     PALETTEENTRY srcval;
1375                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
1376                     *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1377                                                           srcval.peRed,
1378                                                           srcval.peGreen,
1379                                                           srcval.peBlue);
1380                 }
1381                 dstbits += linebytes;
1382             }
1383         } else {
1384             goto notsupported;
1385         }
1386         break;
1387
1388     case 8:
1389        if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1390            && srccolors) {
1391             /* ==== pal 8 bmp -> pal 8 dib ==== */
1392            const void* srcbits;
1393            const BYTE* srcpixel;
1394
1395            srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1396            for (h=0; h<lines; h++) {
1397                srcpixel=srcbits;
1398                dstbyte=dstbits;
1399                for (x = 0; x < width; x++) {
1400                    PALETTEENTRY srcval;
1401                    srcval=srccolors[*srcpixel++];
1402                    *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1403                                                          srcval.peRed,
1404                                                          srcval.peGreen,
1405                                                          srcval.peBlue);
1406                }
1407                srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1408                dstbits += linebytes;
1409            }
1410        } else {
1411            goto notsupported;
1412        }
1413        break;
1414
1415     case 15:
1416     case 16:
1417         {
1418             const void* srcbits;
1419             const WORD* srcpixel;
1420             BYTE* dstbyte;
1421
1422             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1423
1424             if (bmpImage->green_mask==0x03e0) {
1425                 if (bmpImage->red_mask==0x7c00) {
1426                     /* ==== rgb 555 bmp -> pal 8 dib ==== */
1427                     for (h=0; h<lines; h++) {
1428                         srcpixel=srcbits;
1429                         dstbyte=dstbits;
1430                         for (x=0; x<width; x++) {
1431                             WORD srcval;
1432                             srcval=*srcpixel++;
1433                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1434                                 (colors, 256,
1435                                  ((srcval >>  7) & 0xf8) | /* r */
1436                                  ((srcval >> 12) & 0x07),
1437                                  ((srcval >>  2) & 0xf8) | /* g */
1438                                  ((srcval >>  7) & 0x07),
1439                                  ((srcval <<  3) & 0xf8) | /* b */
1440                                  ((srcval >>  2) & 0x07) );
1441                         }
1442                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1443                         dstbits += linebytes;
1444                     }
1445                 } else if (bmpImage->blue_mask==0x7c00) {
1446                     /* ==== bgr 555 bmp -> pal 8 dib ==== */
1447                     for (h=0; h<lines; h++) {
1448                         srcpixel=srcbits;
1449                         dstbyte=dstbits;
1450                         for (x=0; x<width; x++) {
1451                             WORD srcval;
1452                             srcval=*srcpixel++;
1453                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1454                                 (colors, 256,
1455                                  ((srcval <<  3) & 0xf8) | /* r */
1456                                  ((srcval >>  2) & 0x07),
1457                                  ((srcval >>  2) & 0xf8) | /* g */
1458                                  ((srcval >>  7) & 0x07),
1459                                  ((srcval >>  7) & 0xf8) | /* b */
1460                                  ((srcval >> 12) & 0x07) );
1461                         }
1462                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1463                         dstbits += linebytes;
1464                     }
1465                 } else {
1466                     goto notsupported;
1467                 }
1468             } else if (bmpImage->green_mask==0x07e0) {
1469                 if (bmpImage->red_mask==0xf800) {
1470                     /* ==== rgb 565 bmp -> pal 8 dib ==== */
1471                     for (h=0; h<lines; h++) {
1472                         srcpixel=srcbits;
1473                         dstbyte=dstbits;
1474                         for (x=0; x<width; x++) {
1475                             WORD srcval;
1476                             srcval=*srcpixel++;
1477                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1478                                 (colors, 256,
1479                                  ((srcval >>  8) & 0xf8) | /* r */
1480                                  ((srcval >> 13) & 0x07),
1481                                  ((srcval >>  3) & 0xfc) | /* g */
1482                                  ((srcval >>  9) & 0x03),
1483                                  ((srcval <<  3) & 0xf8) | /* b */
1484                                  ((srcval >>  2) & 0x07) );
1485                         }
1486                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1487                         dstbits += linebytes;
1488                     }
1489                 } else if (bmpImage->blue_mask==0xf800) {
1490                     /* ==== bgr 565 bmp -> pal 8 dib ==== */
1491                     for (h=0; h<lines; h++) {
1492                         srcpixel=srcbits;
1493                         dstbyte=dstbits;
1494                         for (x=0; x<width; x++) {
1495                             WORD srcval;
1496                             srcval=*srcpixel++;
1497                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1498                                 (colors, 256,
1499                                  ((srcval <<  3) & 0xf8) | /* r */
1500                                  ((srcval >>  2) & 0x07),
1501                                  ((srcval >>  3) & 0xfc) | /* g */
1502                                  ((srcval >>  9) & 0x03),
1503                                  ((srcval >>  8) & 0xf8) | /* b */
1504                                  ((srcval >> 13) & 0x07) );
1505                         }
1506                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1507                         dstbits += linebytes;
1508                     }
1509                 } else {
1510                     goto notsupported;
1511                 }
1512             } else {
1513                 goto notsupported;
1514             }
1515         }
1516         break;
1517
1518     case 24:
1519     case 32:
1520         {
1521             const void* srcbits;
1522             const BYTE *srcbyte;
1523             BYTE* dstbyte;
1524             int bytes_per_pixel;
1525
1526             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1527             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1528
1529             if (bmpImage->green_mask!=0x00ff00 ||
1530                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1531                 goto notsupported;
1532             } else if (bmpImage->blue_mask==0xff) {
1533                 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1534                 for (h=0; h<lines; h++) {
1535                     srcbyte=srcbits;
1536                     dstbyte=dstbits;
1537                     for (x=0; x<width; x++) {
1538                         *dstbyte++=X11DRV_DIB_GetNearestIndex
1539                             (colors, 256,
1540                              srcbyte[2],
1541                              srcbyte[1],
1542                              srcbyte[0]);
1543                         srcbyte+=bytes_per_pixel;
1544                     }
1545                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1546                     dstbits += linebytes;
1547                 }
1548             } else {
1549                 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1550                 for (h=0; h<lines; h++) {
1551                     srcbyte=srcbits;
1552                     dstbyte=dstbits;
1553                     for (x=0; x<width; x++) {
1554                         *dstbyte++=X11DRV_DIB_GetNearestIndex
1555                             (colors, 256,
1556                              srcbyte[0],
1557                              srcbyte[1],
1558                              srcbyte[2]);
1559                         srcbyte+=bytes_per_pixel;
1560                     }
1561                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1562                     dstbits += linebytes;
1563                 }
1564             }
1565         }
1566         break;
1567
1568     default:
1569     notsupported:
1570         WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1571               bmpImage->depth, bmpImage->red_mask,
1572               bmpImage->green_mask, bmpImage->blue_mask );
1573     updatesection:
1574         /* ==== any bmp format -> pal 8 dib ==== */
1575         for (h=lines-1; h>=0; h--) {
1576             dstbyte=dstbits;
1577             for (x=0; x<width; x++) {
1578                 *dstbyte=X11DRV_DIB_MapColor
1579                     ((int*)colors, 256,
1580                      XGetPixel(bmpImage, x, h), *dstbyte);
1581                 dstbyte++;
1582             }
1583             dstbits += linebytes;
1584         }
1585         break;
1586     }
1587 }
1588
1589 /***********************************************************************
1590  *           X11DRV_DIB_SetImageBits_16
1591  *
1592  * SetDIBits for a 16-bit deep DIB.
1593  */
1594 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1595                                         DWORD srcwidth, DWORD dstwidth, int left,
1596                                         X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1597                                         XImage *bmpImage, int linebytes )
1598 {
1599     DWORD x;
1600     int h, width = min(srcwidth, dstwidth);
1601     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1602
1603     if (lines < 0 )
1604     {
1605         lines = -lines;
1606         srcbits = srcbits + ( linebytes * (lines-1));
1607         linebytes = -linebytes;
1608     }
1609
1610     switch (bmpImage->depth)
1611     {
1612     case 15:
1613     case 16:
1614         {
1615             char* dstbits;
1616
1617             srcbits=srcbits+left*2;
1618             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1619
1620             if (bmpImage->green_mask==0x03e0) {
1621                 if (gSrc==bmpImage->green_mask) {
1622                     if (rSrc==bmpImage->red_mask) {
1623                         /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1624                         /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1625                         convs->Convert_5x5_asis
1626                             (width,lines,
1627                              srcbits,linebytes,
1628                              dstbits,-bmpImage->bytes_per_line);
1629                     } else if (rSrc==bmpImage->blue_mask) {
1630                         /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1631                         /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1632                         convs->Convert_555_reverse
1633                             (width,lines,
1634                              srcbits,linebytes,
1635                              dstbits,-bmpImage->bytes_per_line);
1636                     }
1637                 } else {
1638                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1639                         /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1640                         /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1641                         convs->Convert_565_to_555_asis
1642                             (width,lines,
1643                              srcbits,linebytes,
1644                              dstbits,-bmpImage->bytes_per_line);
1645                     } else {
1646                         /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1647                         /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1648                         convs->Convert_565_to_555_reverse
1649                             (width,lines,
1650                              srcbits,linebytes,
1651                              dstbits,-bmpImage->bytes_per_line);
1652                     }
1653                 }
1654             } else if (bmpImage->green_mask==0x07e0) {
1655                 if (gSrc==bmpImage->green_mask) {
1656                     if (rSrc==bmpImage->red_mask) {
1657                         /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1658                         /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1659                         convs->Convert_5x5_asis
1660                             (width,lines,
1661                              srcbits,linebytes,
1662                              dstbits,-bmpImage->bytes_per_line);
1663                     } else {
1664                         /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1665                         /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1666                         convs->Convert_565_reverse
1667                             (width,lines,
1668                              srcbits,linebytes,
1669                              dstbits,-bmpImage->bytes_per_line);
1670                     }
1671                 } else {
1672                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1673                         /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1674                         /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1675                         convs->Convert_555_to_565_asis
1676                             (width,lines,
1677                              srcbits,linebytes,
1678                              dstbits,-bmpImage->bytes_per_line);
1679                     } else {
1680                         /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1681                         /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1682                         convs->Convert_555_to_565_reverse
1683                             (width,lines,
1684                              srcbits,linebytes,
1685                              dstbits,-bmpImage->bytes_per_line);
1686                     }
1687                 }
1688             } else {
1689                 goto notsupported;
1690             }
1691         }
1692         break;
1693
1694     case 24:
1695         if (bmpImage->bits_per_pixel==24) {
1696             char* dstbits;
1697
1698             srcbits=srcbits+left*2;
1699             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1700
1701             if (bmpImage->green_mask!=0x00ff00 ||
1702                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1703                 goto notsupported;
1704             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1705                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1706                 if (gSrc==0x03e0) {
1707                     /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1708                     /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1709                     convs->Convert_555_to_888_asis
1710                         (width,lines,
1711                          srcbits,linebytes,
1712                          dstbits,-bmpImage->bytes_per_line);
1713                 } else {
1714                     /* ==== rgb 565 dib -> rgb 888 bmp ==== */
1715                     /* ==== bgr 565 dib -> bgr 888 bmp ==== */
1716                     convs->Convert_565_to_888_asis
1717                         (width,lines,
1718                          srcbits,linebytes,
1719                          dstbits,-bmpImage->bytes_per_line);
1720                 }
1721             } else {
1722                 if (gSrc==0x03e0) {
1723                     /* ==== rgb 555 dib -> bgr 888 bmp ==== */
1724                     /* ==== bgr 555 dib -> rgb 888 bmp ==== */
1725                     convs->Convert_555_to_888_reverse
1726                         (width,lines,
1727                          srcbits,linebytes,
1728                          dstbits,-bmpImage->bytes_per_line);
1729                 } else {
1730                     /* ==== rgb 565 dib -> bgr 888 bmp ==== */
1731                     /* ==== bgr 565 dib -> rgb 888 bmp ==== */
1732                     convs->Convert_565_to_888_reverse
1733                         (width,lines,
1734                          srcbits,linebytes,
1735                          dstbits,-bmpImage->bytes_per_line);
1736                 }
1737             }
1738             break;
1739         }
1740         /* Fall through */
1741
1742     case 32:
1743         {
1744             char* dstbits;
1745
1746             srcbits=srcbits+left*2;
1747             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1748
1749             if (bmpImage->green_mask!=0x00ff00 ||
1750                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1751                 goto notsupported;
1752             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1753                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1754                 if (gSrc==0x03e0) {
1755                     /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
1756                     /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
1757                     convs->Convert_555_to_0888_asis
1758                         (width,lines,
1759                          srcbits,linebytes,
1760                          dstbits,-bmpImage->bytes_per_line);
1761                 } else {
1762                     /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
1763                     /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
1764                     convs->Convert_565_to_0888_asis
1765                         (width,lines,
1766                          srcbits,linebytes,
1767                          dstbits,-bmpImage->bytes_per_line);
1768                 }
1769             } else {
1770                 if (gSrc==0x03e0) {
1771                     /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
1772                     /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
1773                     convs->Convert_555_to_0888_reverse
1774                         (width,lines,
1775                          srcbits,linebytes,
1776                          dstbits,-bmpImage->bytes_per_line);
1777                 } else {
1778                     /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
1779                     /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
1780                     convs->Convert_565_to_0888_reverse
1781                         (width,lines,
1782                          srcbits,linebytes,
1783                          dstbits,-bmpImage->bytes_per_line);
1784                 }
1785             }
1786         }
1787         break;
1788
1789     default:
1790     notsupported:
1791         WARN("from 16 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
1792               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
1793               bmpImage->green_mask, bmpImage->blue_mask );
1794         /* fall through */
1795     case 1:
1796     case 4:
1797     case 8:
1798         {
1799             /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
1800             const WORD* srcpixel;
1801             int rShift1,gShift1,bShift1;
1802             int rShift2,gShift2,bShift2;
1803             BYTE gMask1,gMask2;
1804
1805             /* Set color scaling values */
1806             rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
1807             gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
1808             bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
1809             rShift2=rShift1+5;
1810             gShift2=gShift1+5;
1811             bShift2=bShift1+5;
1812             if (gSrc==0x03e0) {
1813                 /* Green has 5 bits, like the others */
1814                 gMask1=0xf8;
1815                 gMask2=0x07;
1816             } else {
1817                 /* Green has 6 bits, not 5. Compensate. */
1818                 gShift1++;
1819                 gShift2+=2;
1820                 gMask1=0xfc;
1821                 gMask2=0x03;
1822             }
1823
1824             srcbits+=2*left;
1825
1826             /* We could split it into four separate cases to optimize
1827              * but it is probably not worth it.
1828              */
1829             for (h=lines-1; h>=0; h--) {
1830                 srcpixel=(const WORD*)srcbits;
1831                 for (x=left; x<width+left; x++) {
1832                     DWORD srcval;
1833                     BYTE red,green,blue;
1834                     srcval=*srcpixel++ << 16;
1835                     red=  ((srcval >> rShift1) & 0xf8) |
1836                         ((srcval >> rShift2) & 0x07);
1837                     green=((srcval >> gShift1) & gMask1) |
1838                         ((srcval >> gShift2) & gMask2);
1839                     blue= ((srcval >> bShift1) & 0xf8) |
1840                         ((srcval >> bShift2) & 0x07);
1841                     XPutPixel(bmpImage, x, h,
1842                               X11DRV_PALETTE_ToPhysical
1843                               (physDev, RGB(red,green,blue)));
1844                 }
1845                 srcbits += linebytes;
1846             }
1847         }
1848         break;
1849     }
1850 }
1851
1852
1853 /***********************************************************************
1854  *           X11DRV_DIB_GetImageBits_16
1855  *
1856  * GetDIBits for an 16-bit deep DIB.
1857  */
1858 static void X11DRV_DIB_GetImageBits_16( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
1859                                         DWORD dstwidth, DWORD srcwidth,
1860                                         PALETTEENTRY *srccolors,
1861                                         DWORD rDst, DWORD gDst, DWORD bDst,
1862                                         XImage *bmpImage, int linebytes )
1863 {
1864     DWORD x;
1865     int h, width = min(srcwidth, dstwidth);
1866     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
1867
1868     if (lines < 0 )
1869     {
1870         lines = -lines;
1871         dstbits = dstbits + ( linebytes * (lines-1));
1872         linebytes = -linebytes;
1873     }
1874
1875     switch (bmpImage->depth)
1876     {
1877     case 15:
1878     case 16:
1879         {
1880             const char* srcbits;
1881
1882             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1883
1884             if (bmpImage->green_mask==0x03e0) {
1885                 if (gDst==bmpImage->green_mask) {
1886                     if (rDst==bmpImage->red_mask) {
1887                         /* ==== rgb 555 bmp -> rgb 555 dib ==== */
1888                         /* ==== bgr 555 bmp -> bgr 555 dib ==== */
1889                         convs->Convert_5x5_asis
1890                             (width,lines,
1891                              srcbits,-bmpImage->bytes_per_line,
1892                              dstbits,linebytes);
1893                     } else {
1894                         /* ==== rgb 555 bmp -> bgr 555 dib ==== */
1895                         /* ==== bgr 555 bmp -> rgb 555 dib ==== */
1896                         convs->Convert_555_reverse
1897                             (width,lines,
1898                              srcbits,-bmpImage->bytes_per_line,
1899                              dstbits,linebytes);
1900                     }
1901                 } else {
1902                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
1903                         /* ==== rgb 555 bmp -> rgb 565 dib ==== */
1904                         /* ==== bgr 555 bmp -> bgr 565 dib ==== */
1905                         convs->Convert_555_to_565_asis
1906                             (width,lines,
1907                              srcbits,-bmpImage->bytes_per_line,
1908                              dstbits,linebytes);
1909                     } else {
1910                         /* ==== rgb 555 bmp -> bgr 565 dib ==== */
1911                         /* ==== bgr 555 bmp -> rgb 565 dib ==== */
1912                         convs->Convert_555_to_565_reverse
1913                             (width,lines,
1914                              srcbits,-bmpImage->bytes_per_line,
1915                              dstbits,linebytes);
1916                     }
1917                 }
1918             } else if (bmpImage->green_mask==0x07e0) {
1919                 if (gDst==bmpImage->green_mask) {
1920                     if (rDst == bmpImage->red_mask) {
1921                         /* ==== rgb 565 bmp -> rgb 565 dib ==== */
1922                         /* ==== bgr 565 bmp -> bgr 565 dib ==== */
1923                         convs->Convert_5x5_asis
1924                             (width,lines,
1925                              srcbits,-bmpImage->bytes_per_line,
1926                              dstbits,linebytes);
1927                     } else {
1928                         /* ==== rgb 565 bmp -> bgr 565 dib ==== */
1929                         /* ==== bgr 565 bmp -> rgb 565 dib ==== */
1930                         convs->Convert_565_reverse
1931                             (width,lines,
1932                              srcbits,-bmpImage->bytes_per_line,
1933                              dstbits,linebytes);
1934                     }
1935                 } else {
1936                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
1937                         /* ==== rgb 565 bmp -> rgb 555 dib ==== */
1938                         /* ==== bgr 565 bmp -> bgr 555 dib ==== */
1939                         convs->Convert_565_to_555_asis
1940                             (width,lines,
1941                              srcbits,-bmpImage->bytes_per_line,
1942                              dstbits,linebytes);
1943                     } else {
1944                         /* ==== rgb 565 bmp -> bgr 555 dib ==== */
1945                         /* ==== bgr 565 bmp -> rgb 555 dib ==== */
1946                         convs->Convert_565_to_555_reverse
1947                             (width,lines,
1948                              srcbits,-bmpImage->bytes_per_line,
1949                              dstbits,linebytes);
1950                     }
1951                 }
1952             } else {
1953                 goto notsupported;
1954             }
1955         }
1956         break;
1957
1958     case 24:
1959         if (bmpImage->bits_per_pixel == 24) {
1960             const char* srcbits;
1961
1962             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1963
1964             if (bmpImage->green_mask!=0x00ff00 ||
1965                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1966                 goto notsupported;
1967             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
1968                     (bDst==0x1f && bmpImage->blue_mask==0xff)) {
1969                 if (gDst==0x03e0) {
1970                     /* ==== rgb 888 bmp -> rgb 555 dib ==== */
1971                     /* ==== bgr 888 bmp -> bgr 555 dib ==== */
1972                     convs->Convert_888_to_555_asis
1973                         (width,lines,
1974                          srcbits,-bmpImage->bytes_per_line,
1975                          dstbits,linebytes);
1976                 } else {
1977                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
1978                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
1979                     convs->Convert_888_to_565_asis
1980                         (width,lines,
1981                          srcbits,-bmpImage->bytes_per_line,
1982                          dstbits,linebytes);
1983                 }
1984             } else {
1985                 if (gDst==0x03e0) {
1986                     /* ==== rgb 888 bmp -> bgr 555 dib ==== */
1987                     /* ==== bgr 888 bmp -> rgb 555 dib ==== */
1988                     convs->Convert_888_to_555_reverse
1989                         (width,lines,
1990                          srcbits,-bmpImage->bytes_per_line,
1991                          dstbits,linebytes);
1992                 } else {
1993                     /* ==== rgb 888 bmp -> bgr 565 dib ==== */
1994                     /* ==== bgr 888 bmp -> rgb 565 dib ==== */
1995                     convs->Convert_888_to_565_reverse
1996                         (width,lines,
1997                          srcbits,-bmpImage->bytes_per_line,
1998                          dstbits,linebytes);
1999                 }
2000             }
2001             break;
2002         }
2003         /* Fall through */
2004
2005     case 32:
2006         {
2007             const char* srcbits;
2008
2009             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2010
2011             if (bmpImage->green_mask!=0x00ff00 ||
2012                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2013                 goto notsupported;
2014             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2015                        (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2016                 if (gDst==0x03e0) {
2017                     /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2018                     /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2019                     convs->Convert_0888_to_555_asis
2020                         (width,lines,
2021                          srcbits,-bmpImage->bytes_per_line,
2022                          dstbits,linebytes);
2023                 } else {
2024                     /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2025                     /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2026                     convs->Convert_0888_to_565_asis
2027                         (width,lines,
2028                          srcbits,-bmpImage->bytes_per_line,
2029                          dstbits,linebytes);
2030                 }
2031             } else {
2032                 if (gDst==0x03e0) {
2033                     /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2034                     /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2035                     convs->Convert_0888_to_555_reverse
2036                         (width,lines,
2037                          srcbits,-bmpImage->bytes_per_line,
2038                          dstbits,linebytes);
2039                 } else {
2040                     /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2041                     /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2042                     convs->Convert_0888_to_565_reverse
2043                         (width,lines,
2044                          srcbits,-bmpImage->bytes_per_line,
2045                          dstbits,linebytes);
2046                 }
2047             }
2048         }
2049         break;
2050
2051     case 1:
2052     case 4:
2053         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2054             && srccolors) {
2055             /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2056             int rShift,gShift,bShift;
2057             WORD* dstpixel;
2058
2059             /* Shift everything 16 bits left so that all shifts are >0,
2060              * even for BGR DIBs. Then a single >> 16 will bring everything
2061              * back into place.
2062              */
2063             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2064             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2065             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2066             if (gDst==0x07e0) {
2067                 /* 6 bits for the green */
2068                 gShift++;
2069             }
2070             rDst=rDst << 16;
2071             gDst=gDst << 16;
2072             bDst=bDst << 16;
2073             for (h = lines - 1; h >= 0; h--) {
2074                 dstpixel=(LPWORD)dstbits;
2075                 for (x = 0; x < width; x++) {
2076                     PALETTEENTRY srcval;
2077                     DWORD dstval;
2078                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2079                     dstval=((srcval.peRed   << rShift) & rDst) |
2080                            ((srcval.peGreen << gShift) & gDst) |
2081                            ((srcval.peBlue  << bShift) & bDst);
2082                     *dstpixel++=dstval >> 16;
2083                 }
2084                 dstbits += linebytes;
2085             }
2086         } else {
2087             goto notsupported;
2088         }
2089         break;
2090
2091     case 8:
2092         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2093             && srccolors) {
2094             /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2095             int rShift,gShift,bShift;
2096             const BYTE* srcbits;
2097             const BYTE* srcpixel;
2098             WORD* dstpixel;
2099
2100             /* Shift everything 16 bits left so that all shifts are >0,
2101              * even for BGR DIBs. Then a single >> 16 will bring everything
2102              * back into place.
2103              */
2104             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2105             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2106             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2107             if (gDst==0x07e0) {
2108                 /* 6 bits for the green */
2109                 gShift++;
2110             }
2111             rDst=rDst << 16;
2112             gDst=gDst << 16;
2113             bDst=bDst << 16;
2114             srcbits=(BYTE*)bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2115             for (h=0; h<lines; h++) {
2116                 srcpixel=srcbits;
2117                 dstpixel=(LPWORD)dstbits;
2118                 for (x = 0; x < width; x++) {
2119                     PALETTEENTRY srcval;
2120                     DWORD dstval;
2121                     srcval=srccolors[*srcpixel++];
2122                     dstval=((srcval.peRed   << rShift) & rDst) |
2123                            ((srcval.peGreen << gShift) & gDst) |
2124                            ((srcval.peBlue  << bShift) & bDst);
2125                     *dstpixel++=dstval >> 16;
2126                 }
2127                 srcbits -= bmpImage->bytes_per_line;
2128                 dstbits += linebytes;
2129             }
2130         } else {
2131             goto notsupported;
2132         }
2133         break;
2134
2135     default:
2136     notsupported:
2137         {
2138             /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2139             int rShift,gShift,bShift;
2140             WORD* dstpixel;
2141
2142             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%x,%x,%x)\n",
2143                   bmpImage->depth, bmpImage->red_mask,
2144                   bmpImage->green_mask, bmpImage->blue_mask,
2145                   rDst, gDst, bDst);
2146
2147             /* Shift everything 16 bits left so that all shifts are >0,
2148              * even for BGR DIBs. Then a single >> 16 will bring everything
2149              * back into place.
2150              */
2151             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2152             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2153             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2154             if (gDst==0x07e0) {
2155                 /* 6 bits for the green */
2156                 gShift++;
2157             }
2158             rDst=rDst << 16;
2159             gDst=gDst << 16;
2160             bDst=bDst << 16;
2161             for (h = lines - 1; h >= 0; h--) {
2162                 dstpixel=(LPWORD)dstbits;
2163                 for (x = 0; x < width; x++) {
2164                     COLORREF srcval;
2165                     DWORD dstval;
2166                     srcval=X11DRV_PALETTE_ToLogical(physDev, XGetPixel(bmpImage, x, h));
2167                     dstval=((GetRValue(srcval) << rShift) & rDst) |
2168                            ((GetGValue(srcval) << gShift) & gDst) |
2169                            ((GetBValue(srcval) << bShift) & bDst);
2170                     *dstpixel++=dstval >> 16;
2171                 }
2172                 dstbits += linebytes;
2173             }
2174         }
2175         break;
2176     }
2177 }
2178
2179
2180 /***********************************************************************
2181  *           X11DRV_DIB_SetImageBits_24
2182  *
2183  * SetDIBits for a 24-bit deep DIB.
2184  */
2185 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2186                                  DWORD srcwidth, DWORD dstwidth, int left,
2187                                  X11DRV_PDEVICE *physDev,
2188                                  DWORD rSrc, DWORD gSrc, DWORD bSrc,
2189                                  XImage *bmpImage, DWORD linebytes )
2190 {
2191     DWORD x;
2192     int h, width = min(srcwidth, dstwidth);
2193     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2194
2195     if (lines < 0 )
2196     {
2197         lines = -lines;
2198         srcbits = srcbits + linebytes * (lines - 1);
2199         linebytes = -linebytes;
2200     }
2201
2202     switch (bmpImage->depth)
2203     {
2204     case 24:
2205         if (bmpImage->bits_per_pixel==24) {
2206             char* dstbits;
2207
2208             srcbits=srcbits+left*3;
2209             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2210
2211             if (bmpImage->green_mask!=0x00ff00 ||
2212                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2213                 goto notsupported;
2214             } else if (rSrc==bmpImage->red_mask) {
2215                 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2216                 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2217                 convs->Convert_888_asis
2218                     (width,lines,
2219                      srcbits,linebytes,
2220                      dstbits,-bmpImage->bytes_per_line);
2221             } else {
2222                 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2223                 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2224                 convs->Convert_888_reverse
2225                     (width,lines,
2226                      srcbits,linebytes,
2227                      dstbits,-bmpImage->bytes_per_line);
2228             }
2229             break;
2230         }
2231         /* fall through */
2232
2233     case 32:
2234         {
2235             char* dstbits;
2236
2237             srcbits=srcbits+left*3;
2238             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2239
2240             if (bmpImage->green_mask!=0x00ff00 ||
2241                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2242                 goto notsupported;
2243             } else if (rSrc==bmpImage->red_mask) {
2244                 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2245                 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2246                 convs->Convert_888_to_0888_asis
2247                     (width,lines,
2248                      srcbits,linebytes,
2249                      dstbits,-bmpImage->bytes_per_line);
2250             } else {
2251                 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2252                 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2253                 convs->Convert_888_to_0888_reverse
2254                     (width,lines,
2255                      srcbits,linebytes,
2256                      dstbits,-bmpImage->bytes_per_line);
2257             }
2258             break;
2259         }
2260
2261     case 15:
2262     case 16:
2263         {
2264             char* dstbits;
2265
2266             srcbits=srcbits+left*3;
2267             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2268
2269             if (bmpImage->green_mask==0x03e0) {
2270                 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2271                     (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2272                     /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2273                     /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2274                     convs->Convert_888_to_555_asis
2275                         (width,lines,
2276                          srcbits,linebytes,
2277                          dstbits,-bmpImage->bytes_per_line);
2278                 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2279                            (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2280                     /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2281                     /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2282                     convs->Convert_888_to_555_reverse
2283                         (width,lines,
2284                          srcbits,linebytes,
2285                          dstbits,-bmpImage->bytes_per_line);
2286                 } else {
2287                     goto notsupported;
2288                 }
2289             } else if (bmpImage->green_mask==0x07e0) {
2290                 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2291                     (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2292                     /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2293                     /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2294                     convs->Convert_888_to_565_asis
2295                         (width,lines,
2296                          srcbits,linebytes,
2297                          dstbits,-bmpImage->bytes_per_line);
2298                 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2299                            (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2300                     /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2301                     /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2302                     convs->Convert_888_to_565_reverse
2303                         (width,lines,
2304                          srcbits,linebytes,
2305                          dstbits,-bmpImage->bytes_per_line);
2306                 } else {
2307                     goto notsupported;
2308                 }
2309             } else {
2310                 goto notsupported;
2311             }
2312         }
2313         break;
2314
2315     default:
2316     notsupported:
2317         WARN("from 24 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2318               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2319               bmpImage->green_mask, bmpImage->blue_mask );
2320         /* fall through */
2321     case 1:
2322     case 4:
2323     case 8:
2324         {
2325             /* ==== rgb 888 dib -> any bmp format ==== */
2326             const BYTE* srcbyte;
2327
2328             /* Windows only supports one 24bpp DIB format: RGB888 */
2329             srcbits+=left*3;
2330             for (h = lines - 1; h >= 0; h--) {
2331                 srcbyte = srcbits;
2332                 for (x = left; x < width+left; x++) {
2333                     XPutPixel(bmpImage, x, h,
2334                               X11DRV_PALETTE_ToPhysical
2335                               (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2336                     srcbyte+=3;
2337                 }
2338                 srcbits += linebytes;
2339             }
2340         }
2341         break;
2342     }
2343 }
2344
2345
2346 /***********************************************************************
2347  *           X11DRV_DIB_GetImageBits_24
2348  *
2349  * GetDIBits for an 24-bit deep DIB.
2350  */
2351 static void X11DRV_DIB_GetImageBits_24( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
2352                                         DWORD dstwidth, DWORD srcwidth,
2353                                         PALETTEENTRY *srccolors,
2354                                         DWORD rDst, DWORD gDst, DWORD bDst,
2355                                         XImage *bmpImage, DWORD linebytes )
2356 {
2357     DWORD x;
2358     int h, width = min(srcwidth, dstwidth);
2359     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2360
2361     if (lines < 0 )
2362     {
2363         lines = -lines;
2364         dstbits = dstbits + ( linebytes * (lines-1) );
2365         linebytes = -linebytes;
2366     }
2367
2368     switch (bmpImage->depth)
2369     {
2370     case 24:
2371         if (bmpImage->bits_per_pixel==24) {
2372             const char* srcbits;
2373
2374             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2375
2376             if (bmpImage->green_mask!=0x00ff00 ||
2377                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2378                 goto notsupported;
2379             } else if (rDst==bmpImage->red_mask) {
2380                 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2381                 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2382                 convs->Convert_888_asis
2383                     (width,lines,
2384                      srcbits,-bmpImage->bytes_per_line,
2385                      dstbits,linebytes);
2386             } else {
2387                 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2388                 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2389                 convs->Convert_888_reverse
2390                     (width,lines,
2391                      srcbits,-bmpImage->bytes_per_line,
2392                      dstbits,linebytes);
2393             }
2394             break;
2395         }
2396         /* fall through */
2397
2398     case 32:
2399         {
2400             const char* srcbits;
2401
2402             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2403
2404             if (bmpImage->green_mask!=0x00ff00 ||
2405                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2406                 goto notsupported;
2407             } else if (rDst==bmpImage->red_mask) {
2408                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2409                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2410                 convs->Convert_0888_to_888_asis
2411                     (width,lines,
2412                      srcbits,-bmpImage->bytes_per_line,
2413                      dstbits,linebytes);
2414             } else {
2415                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2416                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2417                 convs->Convert_0888_to_888_reverse
2418                     (width,lines,
2419                      srcbits,-bmpImage->bytes_per_line,
2420                      dstbits,linebytes);
2421             }
2422             break;
2423         }
2424
2425     case 15:
2426     case 16:
2427         {
2428             const char* srcbits;
2429
2430             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2431
2432             if (bmpImage->green_mask==0x03e0) {
2433                 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2434                     (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2435                     /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2436                     /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2437                     convs->Convert_555_to_888_asis
2438                         (width,lines,
2439                          srcbits,-bmpImage->bytes_per_line,
2440                          dstbits,linebytes);
2441                 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2442                            (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2443                     /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2444                     /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2445                     convs->Convert_555_to_888_reverse
2446                         (width,lines,
2447                          srcbits,-bmpImage->bytes_per_line,
2448                          dstbits,linebytes);
2449                 } else {
2450                     goto notsupported;
2451                 }
2452             } else if (bmpImage->green_mask==0x07e0) {
2453                 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2454                     (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2455                     /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2456                     /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2457                     convs->Convert_565_to_888_asis
2458                         (width,lines,
2459                          srcbits,-bmpImage->bytes_per_line,
2460                          dstbits,linebytes);
2461                 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2462                            (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2463                     /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2464                     /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2465                     convs->Convert_565_to_888_reverse
2466                         (width,lines,
2467                          srcbits,-bmpImage->bytes_per_line,
2468                          dstbits,linebytes);
2469                 } else {
2470                     goto notsupported;
2471                 }
2472             } else {
2473                 goto notsupported;
2474             }
2475         }
2476         break;
2477
2478     case 1:
2479     case 4:
2480         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2481             && srccolors) {
2482             /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2483             BYTE* dstbyte;
2484
2485             /* Windows only supports one 24bpp DIB format: rgb 888 */
2486             for (h = lines - 1; h >= 0; h--) {
2487                 dstbyte=dstbits;
2488                 for (x = 0; x < width; x++) {
2489                     PALETTEENTRY srcval;
2490                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2491                     dstbyte[0]=srcval.peBlue;
2492                     dstbyte[1]=srcval.peGreen;
2493                     dstbyte[2]=srcval.peRed;
2494                     dstbyte+=3;
2495                 }
2496                 dstbits += linebytes;
2497             }
2498         } else {
2499             goto notsupported;
2500         }
2501         break;
2502
2503     case 8:
2504         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2505             && srccolors) {
2506             /* ==== pal 8 bmp -> rgb 888 dib ==== */
2507             const void* srcbits;
2508             const BYTE* srcpixel;
2509             BYTE* dstbyte;
2510
2511             /* Windows only supports one 24bpp DIB format: rgb 888 */
2512             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2513             for (h = lines - 1; h >= 0; h--) {
2514                 srcpixel=srcbits;
2515                 dstbyte=dstbits;
2516                 for (x = 0; x < width; x++ ) {
2517                     PALETTEENTRY srcval;
2518                     srcval=srccolors[*srcpixel++];
2519                     dstbyte[0]=srcval.peBlue;
2520                     dstbyte[1]=srcval.peGreen;
2521                     dstbyte[2]=srcval.peRed;
2522                     dstbyte+=3;
2523                 }
2524                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
2525                 dstbits += linebytes;
2526             }
2527         } else {
2528             goto notsupported;
2529         }
2530         break;
2531
2532     default:
2533     notsupported:
2534         {
2535             /* ==== any bmp format -> 888 dib ==== */
2536             BYTE* dstbyte;
2537
2538             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%x,%x,%x)\n",
2539                   bmpImage->depth, bmpImage->red_mask,
2540                   bmpImage->green_mask, bmpImage->blue_mask,
2541                   rDst, gDst, bDst );
2542
2543             /* Windows only supports one 24bpp DIB format: rgb 888 */
2544             for (h = lines - 1; h >= 0; h--) {
2545                 dstbyte=dstbits;
2546                 for (x = 0; x < width; x++) {
2547                     COLORREF srcval=X11DRV_PALETTE_ToLogical
2548                         (physDev, XGetPixel( bmpImage, x, h ));
2549                     dstbyte[0]=GetBValue(srcval);
2550                     dstbyte[1]=GetGValue(srcval);
2551                     dstbyte[2]=GetRValue(srcval);
2552                     dstbyte+=3;
2553                 }
2554                 dstbits += linebytes;
2555             }
2556         }
2557         break;
2558     }
2559 }
2560
2561
2562 /***********************************************************************
2563  *           X11DRV_DIB_SetImageBits_32
2564  *
2565  * SetDIBits for a 32-bit deep DIB.
2566  */
2567 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2568                                        DWORD srcwidth, DWORD dstwidth, int left,
2569                                        X11DRV_PDEVICE *physDev,
2570                                        DWORD rSrc, DWORD gSrc, DWORD bSrc,
2571                                        XImage *bmpImage,
2572                                        DWORD linebytes)
2573 {
2574     DWORD x;
2575     int h, width = min(srcwidth, dstwidth);
2576     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2577
2578     if (lines < 0 )
2579     {
2580        lines = -lines;
2581        srcbits = srcbits + ( linebytes * (lines-1) );
2582        linebytes = -linebytes;
2583     }
2584
2585     switch (bmpImage->depth)
2586     {
2587     case 24:
2588         if (bmpImage->bits_per_pixel==24) {
2589             char* dstbits;
2590
2591             srcbits=srcbits+left*4;
2592             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2593
2594             if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2595                 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2596                 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2597                 convs->Convert_0888_to_888_asis
2598                     (width,lines,
2599                      srcbits,linebytes,
2600                      dstbits,-bmpImage->bytes_per_line);
2601             } else if (bmpImage->green_mask!=0x00ff00 ||
2602                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2603                 goto notsupported;
2604                 /* the tests below assume sane bmpImage masks */
2605             } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2606                 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2607                 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2608                 convs->Convert_0888_to_888_reverse
2609                     (width,lines,
2610                      srcbits,linebytes,
2611                      dstbits,-bmpImage->bytes_per_line);
2612             } else if (bmpImage->blue_mask==0xff) {
2613                 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2614                 convs->Convert_any0888_to_rgb888
2615                     (width,lines,
2616                      srcbits,linebytes,
2617                      rSrc,gSrc,bSrc,
2618                      dstbits,-bmpImage->bytes_per_line);
2619             } else {
2620                 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2621                 convs->Convert_any0888_to_bgr888
2622                     (width,lines,
2623                      srcbits,linebytes,
2624                      rSrc,gSrc,bSrc,
2625                      dstbits,-bmpImage->bytes_per_line);
2626             }
2627             break;
2628         }
2629         /* fall through */
2630
2631     case 32:
2632         {
2633             char* dstbits;
2634
2635             srcbits=srcbits+left*4;
2636             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2637
2638             if (gSrc==bmpImage->green_mask) {
2639                 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2640                     /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2641                     /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2642                     convs->Convert_0888_asis
2643                         (width,lines,
2644                          srcbits,linebytes,
2645                          dstbits,-bmpImage->bytes_per_line);
2646                 } else if (bmpImage->green_mask!=0x00ff00 ||
2647                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2648                     goto notsupported;
2649                     /* the tests below assume sane bmpImage masks */
2650                 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2651                     /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2652                     /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2653                     convs->Convert_0888_reverse
2654                         (width,lines,
2655                          srcbits,linebytes,
2656                          dstbits,-bmpImage->bytes_per_line);
2657                 } else {
2658                     /* ==== any 0888 dib -> any 0888 bmp ==== */
2659                     convs->Convert_0888_any
2660                         (width,lines,
2661                          srcbits,linebytes,
2662                          rSrc,gSrc,bSrc,
2663                          dstbits,-bmpImage->bytes_per_line,
2664                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2665                 }
2666             } else if (bmpImage->green_mask!=0x00ff00 ||
2667                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2668                 goto notsupported;
2669                 /* the tests below assume sane bmpImage masks */
2670             } else {
2671                 /* ==== any 0888 dib -> any 0888 bmp ==== */
2672                 convs->Convert_0888_any
2673                     (width,lines,
2674                      srcbits,linebytes,
2675                      rSrc,gSrc,bSrc,
2676                      dstbits,-bmpImage->bytes_per_line,
2677                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2678             }
2679         }
2680         break;
2681
2682     case 15:
2683     case 16:
2684         {
2685             char* dstbits;
2686
2687             srcbits=srcbits+left*4;
2688             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2689
2690             if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2691                 if (bmpImage->green_mask==0x03e0) {
2692                     if (bmpImage->red_mask==0x7f00) {
2693                         /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2694                         convs->Convert_0888_to_555_asis
2695                             (width,lines,
2696                              srcbits,linebytes,
2697                              dstbits,-bmpImage->bytes_per_line);
2698                     } else if (bmpImage->blue_mask==0x7f00) {
2699                         /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2700                         convs->Convert_0888_to_555_reverse
2701                             (width,lines,
2702                              srcbits,linebytes,
2703                              dstbits,-bmpImage->bytes_per_line);
2704                     } else {
2705                         goto notsupported;
2706                     }
2707                 } else if (bmpImage->green_mask==0x07e0) {
2708                     if (bmpImage->red_mask==0xf800) {
2709                         /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
2710                         convs->Convert_0888_to_565_asis
2711                             (width,lines,
2712                              srcbits,linebytes,
2713                              dstbits,-bmpImage->bytes_per_line);
2714                     } else if (bmpImage->blue_mask==0xf800) {
2715                         /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
2716                         convs->Convert_0888_to_565_reverse
2717                             (width,lines,
2718                              srcbits,linebytes,
2719                              dstbits,-bmpImage->bytes_per_line);
2720                     } else {
2721                         goto notsupported;
2722                     }
2723                 } else {
2724                     goto notsupported;
2725                 }
2726             } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
2727                 if (bmpImage->green_mask==0x03e0) {
2728                     if (bmpImage->blue_mask==0x7f00) {
2729                         /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
2730                         convs->Convert_0888_to_555_asis
2731                             (width,lines,
2732                              srcbits,linebytes,
2733                              dstbits,-bmpImage->bytes_per_line);
2734                     } else if (bmpImage->red_mask==0x7f00) {
2735                         /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
2736                         convs->Convert_0888_to_555_reverse
2737                             (width,lines,
2738                              srcbits,linebytes,
2739                              dstbits,-bmpImage->bytes_per_line);
2740                     } else {
2741                         goto notsupported;
2742                     }
2743                 } else if (bmpImage->green_mask==0x07e0) {
2744                     if (bmpImage->blue_mask==0xf800) {
2745                         /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
2746                         convs->Convert_0888_to_565_asis
2747                             (width,lines,
2748                              srcbits,linebytes,
2749                              dstbits,-bmpImage->bytes_per_line);
2750                     } else if (bmpImage->red_mask==0xf800) {
2751                         /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
2752                         convs->Convert_0888_to_565_reverse
2753                             (width,lines,
2754                              srcbits,linebytes,
2755                              dstbits,-bmpImage->bytes_per_line);
2756                     } else {
2757                         goto notsupported;
2758                     }
2759                 } else {
2760                     goto notsupported;
2761                 }
2762             } else {
2763                 if (bmpImage->green_mask==0x03e0 &&
2764                     (bmpImage->red_mask==0x7f00 ||
2765                      bmpImage->blue_mask==0x7f00)) {
2766                     /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
2767                     convs->Convert_any0888_to_5x5
2768                         (width,lines,
2769                          srcbits,linebytes,
2770                          rSrc,gSrc,bSrc,
2771                          dstbits,-bmpImage->bytes_per_line,
2772                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2773                 } else if (bmpImage->green_mask==0x07e0 &&
2774                            (bmpImage->red_mask==0xf800 ||
2775                             bmpImage->blue_mask==0xf800)) {
2776                     /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
2777                     convs->Convert_any0888_to_5x5
2778                         (width,lines,
2779                          srcbits,linebytes,
2780                          rSrc,gSrc,bSrc,
2781                          dstbits,-bmpImage->bytes_per_line,
2782                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2783                 } else {
2784                     goto notsupported;
2785                 }
2786             }
2787         }
2788         break;
2789
2790     default:
2791     notsupported:
2792         WARN("from 32 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2793               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2794               bmpImage->green_mask, bmpImage->blue_mask );
2795         /* fall through */
2796     case 1:
2797     case 4:
2798     case 8:
2799         {
2800             /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
2801             const DWORD* srcpixel;
2802             int rShift,gShift,bShift;
2803
2804             rShift=X11DRV_DIB_MaskToShift(rSrc);
2805             gShift=X11DRV_DIB_MaskToShift(gSrc);
2806             bShift=X11DRV_DIB_MaskToShift(bSrc);
2807             srcbits+=left*4;
2808             for (h = lines - 1; h >= 0; h--) {
2809                 srcpixel=(const DWORD*)srcbits;
2810                 for (x = left; x < width+left; x++) {
2811                     DWORD srcvalue;
2812                     BYTE red,green,blue;
2813                     srcvalue=*srcpixel++;
2814                     red=  (srcvalue >> rShift) & 0xff;
2815                     green=(srcvalue >> gShift) & 0xff;
2816                     blue= (srcvalue >> bShift) & 0xff;
2817                     XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
2818                               (physDev, RGB(red,green,blue)));
2819                 }
2820                 srcbits += linebytes;
2821             }
2822         }
2823         break;
2824     }
2825
2826 }
2827
2828 /***********************************************************************
2829  *           X11DRV_DIB_GetImageBits_32
2830  *
2831  * GetDIBits for an 32-bit deep DIB.
2832  */
2833 static void X11DRV_DIB_GetImageBits_32( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
2834                                         DWORD dstwidth, DWORD srcwidth,
2835                                         PALETTEENTRY *srccolors,
2836                                         DWORD rDst, DWORD gDst, DWORD bDst,
2837                                         XImage *bmpImage, int linebytes )
2838 {
2839     DWORD x;
2840     int h, width = min(srcwidth, dstwidth);
2841     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2842
2843     if (lines < 0 )
2844     {
2845         lines = -lines;
2846         dstbits = dstbits + ( linebytes * (lines-1) );
2847         linebytes = -linebytes;
2848     }
2849
2850     switch (bmpImage->depth)
2851     {
2852     case 24:
2853         if (bmpImage->bits_per_pixel==24) {
2854             const void* srcbits;
2855
2856             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2857
2858             if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
2859                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2860                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2861                 convs->Convert_888_to_0888_asis
2862                     (width,lines,
2863                      srcbits,-bmpImage->bytes_per_line,
2864                      dstbits,linebytes);
2865             } else if (bmpImage->green_mask!=0x00ff00 ||
2866                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2867                 goto notsupported;
2868                 /* the tests below assume sane bmpImage masks */
2869             } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
2870                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2871                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2872                 convs->Convert_888_to_0888_reverse
2873                     (width,lines,
2874                      srcbits,-bmpImage->bytes_per_line,
2875                      dstbits,linebytes);
2876             } else if (bmpImage->blue_mask==0xff) {
2877                 /* ==== rgb 888 bmp -> any 0888 dib ==== */
2878                 convs->Convert_rgb888_to_any0888
2879                     (width,lines,
2880                      srcbits,-bmpImage->bytes_per_line,
2881                      dstbits,linebytes,
2882                      rDst,gDst,bDst);
2883             } else {
2884                 /* ==== bgr 888 bmp -> any 0888 dib ==== */
2885                 convs->Convert_bgr888_to_any0888
2886                     (width,lines,
2887                      srcbits,-bmpImage->bytes_per_line,
2888                      dstbits,linebytes,
2889                      rDst,gDst,bDst);
2890             }
2891             break;
2892         }
2893         /* fall through */
2894
2895     case 32:
2896         {
2897             const char* srcbits;
2898
2899             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2900
2901             if (gDst==bmpImage->green_mask) {
2902                 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
2903                     /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
2904                     /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
2905                     convs->Convert_0888_asis
2906                         (width,lines,
2907                          srcbits,-bmpImage->bytes_per_line,
2908                          dstbits,linebytes);
2909                 } else if (bmpImage->green_mask!=0x00ff00 ||
2910                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2911                     goto notsupported;
2912                     /* the tests below assume sane bmpImage masks */
2913                 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
2914                     /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
2915                     /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
2916                     convs->Convert_0888_reverse
2917                         (width,lines,
2918                          srcbits,-bmpImage->bytes_per_line,
2919                          dstbits,linebytes);
2920                 } else {
2921                     /* ==== any 0888 bmp -> any 0888 dib ==== */
2922                     convs->Convert_0888_any
2923                         (width,lines,
2924                          srcbits,-bmpImage->bytes_per_line,
2925                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
2926                          dstbits,linebytes,
2927                          rDst,gDst,bDst);
2928                 }
2929             } else if (bmpImage->green_mask!=0x00ff00 ||
2930                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2931                 goto notsupported;
2932                 /* the tests below assume sane bmpImage masks */
2933             } else {
2934                 /* ==== any 0888 bmp -> any 0888 dib ==== */
2935                 convs->Convert_0888_any
2936                     (width,lines,
2937                      srcbits,-bmpImage->bytes_per_line,
2938                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
2939                      dstbits,linebytes,
2940                      rDst,gDst,bDst);
2941             }
2942         }
2943         break;
2944
2945     case 15:
2946     case 16:
2947         {
2948             const char* srcbits;
2949
2950             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2951
2952             if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
2953                 if (bmpImage->green_mask==0x03e0) {
2954                     if (bmpImage->red_mask==0x7f00) {
2955                         /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
2956                         convs->Convert_555_to_0888_asis
2957                             (width,lines,
2958                              srcbits,-bmpImage->bytes_per_line,
2959                              dstbits,linebytes);
2960                     } else if (bmpImage->blue_mask==0x7f00) {
2961                         /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
2962                         convs->Convert_555_to_0888_reverse
2963                             (width,lines,
2964                              srcbits,-bmpImage->bytes_per_line,
2965                              dstbits,linebytes);
2966                     } else {
2967                         goto notsupported;
2968                     }
2969                 } else if (bmpImage->green_mask==0x07e0) {
2970                     if (bmpImage->red_mask==0xf800) {
2971                         /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
2972                         convs->Convert_565_to_0888_asis
2973                             (width,lines,
2974                              srcbits,-bmpImage->bytes_per_line,
2975                              dstbits,linebytes);
2976                     } else if (bmpImage->blue_mask==0xf800) {
2977                         /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
2978                         convs->Convert_565_to_0888_reverse
2979                             (width,lines,
2980                              srcbits,-bmpImage->bytes_per_line,
2981                              dstbits,linebytes);
2982                     } else {
2983                         goto notsupported;
2984                     }
2985                 } else {
2986                     goto notsupported;
2987                 }
2988             } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
2989                 if (bmpImage->green_mask==0x03e0) {
2990                     if (bmpImage->blue_mask==0x7f00) {
2991                         /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
2992                         convs->Convert_555_to_0888_asis
2993                             (width,lines,
2994                              srcbits,-bmpImage->bytes_per_line,
2995                              dstbits,linebytes);
2996                     } else if (bmpImage->red_mask==0x7f00) {
2997                         /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
2998                         convs->Convert_555_to_0888_reverse
2999                             (width,lines,
3000                              srcbits,-bmpImage->bytes_per_line,
3001                              dstbits,linebytes);
3002                     } else {
3003                         goto notsupported;
3004                     }
3005                 } else if (bmpImage->green_mask==0x07e0) {
3006                     if (bmpImage->blue_mask==0xf800) {
3007                         /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3008                         convs->Convert_565_to_0888_asis
3009                             (width,lines,
3010                              srcbits,-bmpImage->bytes_per_line,
3011                              dstbits,linebytes);
3012                     } else if (bmpImage->red_mask==0xf800) {
3013                         /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3014                         convs->Convert_565_to_0888_reverse
3015                             (width,lines,
3016                              srcbits,-bmpImage->bytes_per_line,
3017                              dstbits,linebytes);
3018                     } else {
3019                         goto notsupported;
3020                     }
3021                 } else {
3022                     goto notsupported;
3023                 }
3024             } else {
3025                 if (bmpImage->green_mask==0x03e0 &&
3026                     (bmpImage->red_mask==0x7f00 ||
3027                      bmpImage->blue_mask==0x7f00)) {
3028                     /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3029                     convs->Convert_5x5_to_any0888
3030                         (width,lines,
3031                          srcbits,-bmpImage->bytes_per_line,
3032                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3033                          dstbits,linebytes,
3034                          rDst,gDst,bDst);
3035                 } else if (bmpImage->green_mask==0x07e0 &&
3036                            (bmpImage->red_mask==0xf800 ||
3037                             bmpImage->blue_mask==0xf800)) {
3038                     /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3039                     convs->Convert_5x5_to_any0888
3040                         (width,lines,
3041                          srcbits,-bmpImage->bytes_per_line,
3042                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3043                          dstbits,linebytes,
3044                          rDst,gDst,bDst);
3045                 } else {
3046                     goto notsupported;
3047                 }
3048             }
3049         }
3050         break;
3051
3052     case 1:
3053     case 4:
3054         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3055             && srccolors) {
3056             /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3057             int rShift,gShift,bShift;
3058             DWORD* dstpixel;
3059
3060             rShift=X11DRV_DIB_MaskToShift(rDst);
3061             gShift=X11DRV_DIB_MaskToShift(gDst);
3062             bShift=X11DRV_DIB_MaskToShift(bDst);
3063             for (h = lines - 1; h >= 0; h--) {
3064                 dstpixel=(DWORD*)dstbits;
3065                 for (x = 0; x < width; x++) {
3066                     PALETTEENTRY srcval;
3067                     srcval = srccolors[XGetPixel(bmpImage, x, h)];
3068                     *dstpixel++=(srcval.peRed   << rShift) |
3069                                 (srcval.peGreen << gShift) |
3070                                 (srcval.peBlue  << bShift);
3071                 }
3072                 dstbits += linebytes;
3073             }
3074         } else {
3075             goto notsupported;
3076         }
3077         break;
3078
3079     case 8:
3080         if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3081             && srccolors) {
3082             /* ==== pal 8 bmp -> any 0888 dib ==== */
3083             int rShift,gShift,bShift;
3084             const void* srcbits;
3085             const BYTE* srcpixel;
3086             DWORD* dstpixel;
3087
3088             rShift=X11DRV_DIB_MaskToShift(rDst);
3089             gShift=X11DRV_DIB_MaskToShift(gDst);
3090             bShift=X11DRV_DIB_MaskToShift(bDst);
3091             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3092             for (h = lines - 1; h >= 0; h--) {
3093                 srcpixel=srcbits;
3094                 dstpixel=(DWORD*)dstbits;
3095                 for (x = 0; x < width; x++) {
3096                     PALETTEENTRY srcval;
3097                     srcval=srccolors[*srcpixel++];
3098                     *dstpixel++=(srcval.peRed   << rShift) |
3099                                 (srcval.peGreen << gShift) |
3100                                 (srcval.peBlue  << bShift);
3101                 }
3102                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
3103                 dstbits += linebytes;
3104             }
3105         } else {
3106             goto notsupported;
3107         }
3108         break;
3109
3110     default:
3111     notsupported:
3112         {
3113             /* ==== any bmp format -> any 0888 dib ==== */
3114             int rShift,gShift,bShift;
3115             DWORD* dstpixel;
3116
3117             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%x,%x,%x)\n",
3118                   bmpImage->depth, bmpImage->red_mask,
3119                   bmpImage->green_mask, bmpImage->blue_mask,
3120                   rDst,gDst,bDst);
3121
3122             rShift=X11DRV_DIB_MaskToShift(rDst);
3123             gShift=X11DRV_DIB_MaskToShift(gDst);
3124             bShift=X11DRV_DIB_MaskToShift(bDst);
3125             for (h = lines - 1; h >= 0; h--) {
3126                 dstpixel=(DWORD*)dstbits;
3127                 for (x = 0; x < width; x++) {
3128                     COLORREF srcval;
3129                     srcval=X11DRV_PALETTE_ToLogical(physDev, XGetPixel(bmpImage, x, h));
3130                     *dstpixel++=(GetRValue(srcval) << rShift) |
3131                                 (GetGValue(srcval) << gShift) |
3132                                 (GetBValue(srcval) << bShift);
3133                 }
3134                 dstbits += linebytes;
3135             }
3136         }
3137         break;
3138     }
3139 }
3140
3141 /***********************************************************************
3142  *           X11DRV_DIB_SetImageBits
3143  *
3144  * Transfer the bits to an X image.
3145  * Helper function for SetDIBits() and SetDIBitsToDevice().
3146  */
3147 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3148 {
3149     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3150     void *old_data = NULL;
3151     XImage *bmpImage;
3152
3153     wine_tsx11_lock();
3154     if (descr->image)
3155         bmpImage = descr->image;
3156     else {
3157         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3158                                  descr->infoWidth, lines, 32, 0 );
3159         bmpImage->data = HeapAlloc( GetProcessHeap(), 0, lines * bmpImage->bytes_per_line );
3160         if(bmpImage->data == NULL) {
3161             ERR("Out of memory!\n");
3162             XDestroyImage( bmpImage );
3163             wine_tsx11_unlock();
3164             return 0;
3165         }
3166         if (descr->shifts)
3167         {
3168             bmpImage->red_mask = descr->shifts->physicalRed.max << descr->shifts->physicalRed.shift;
3169             bmpImage->green_mask = descr->shifts->physicalGreen.max << descr->shifts->physicalGreen.shift;
3170             bmpImage->blue_mask = descr->shifts->physicalBlue.max << descr->shifts->physicalBlue.shift;
3171         }
3172     }
3173     wine_tsx11_unlock();
3174
3175     TRACE("Dib: depth=%d r=%x g=%x b=%x\n",
3176           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3177     TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3178           bmpImage->depth,bmpImage->bits_per_pixel,
3179           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3180
3181 #ifdef HAVE_LIBXXSHM
3182     if (descr->shm_mode == X11DRV_SHM_PIXMAP
3183             && descr->xSrc == 0 && descr->ySrc == 0
3184             && descr->xDest == 0 && descr->yDest == 0)
3185     {
3186         TRACE("Using the shared pixmap data.\n");
3187
3188         wine_tsx11_lock();
3189         XSync( gdi_display, False );
3190         wine_tsx11_unlock();
3191
3192         old_data = descr->image->data;
3193         descr->image->data = descr->physBitmap->shminfo.shmaddr;
3194     }
3195 #endif
3196
3197       /* Transfer the pixels */
3198     __TRY
3199     {
3200         switch(descr->infoBpp)
3201         {
3202         case 1:
3203             X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3204                                        descr->width, descr->xSrc, (int *)(descr->colorMap),
3205                                        bmpImage, descr->dibpitch );
3206             break;
3207         case 4:
3208             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3209                                        descr->infoWidth, descr->width,
3210                                        descr->xSrc, (int*)(descr->colorMap),
3211                                        bmpImage, descr->dibpitch );
3212             break;
3213         case 8:
3214             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3215                                        descr->infoWidth, descr->width,
3216                                        descr->xSrc, (int *)(descr->colorMap),
3217                                        bmpImage, descr->dibpitch );
3218             break;
3219         case 16:
3220             X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3221                                         descr->infoWidth, descr->width,
3222                                         descr->xSrc, descr->physDev,
3223                                         descr->rMask, descr->gMask, descr->bMask,
3224                                         bmpImage, descr->dibpitch);
3225             break;
3226         case 24:
3227             X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3228                                         descr->infoWidth, descr->width,
3229                                         descr->xSrc, descr->physDev,
3230                                         descr->rMask, descr->gMask, descr->bMask,
3231                                         bmpImage, descr->dibpitch);
3232             break;
3233         case 32:
3234             X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3235                                         descr->infoWidth, descr->width,
3236                                         descr->xSrc, descr->physDev,
3237                                         descr->rMask, descr->gMask, descr->bMask,
3238                                         bmpImage, descr->dibpitch);
3239             break;
3240         default:
3241             WARN("(%d): Invalid depth\n", descr->infoBpp );
3242             break;
3243         }
3244     }
3245     __EXCEPT_PAGE_FAULT
3246     {
3247         WARN( "invalid bits pointer %p\n", descr->bits );
3248         lines = 0;
3249     }
3250     __ENDTRY
3251
3252     TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3253      descr->drawable, descr->gc, bmpImage,
3254      descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3255      descr->width, descr->height);
3256
3257     wine_tsx11_lock();
3258     if (lines)
3259     {
3260 #ifdef HAVE_LIBXXSHM
3261         if (descr->shm_mode == X11DRV_SHM_PIXMAP
3262                 && descr->xSrc == 0 && descr->ySrc == 0
3263                 && descr->xDest == 0 && descr->yDest == 0)
3264         {
3265             XSync( gdi_display, False );
3266         }
3267         else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image)
3268         {
3269             XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3270                           descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3271                           descr->width, descr->height, FALSE );
3272             XSync( gdi_display, 0 );
3273         }
3274         else
3275 #endif
3276         {
3277             XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3278                        descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3279                        descr->width, descr->height );
3280         }
3281     }
3282
3283     if (old_data) descr->image->data = old_data;
3284
3285     if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
3286     wine_tsx11_unlock();
3287     return lines;
3288 }
3289
3290 /***********************************************************************
3291  *           X11DRV_DIB_GetImageBits
3292  *
3293  * Transfer the bits from an X image.
3294  */
3295 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3296 {
3297     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3298     void *old_data = NULL;
3299     XImage *bmpImage;
3300
3301     wine_tsx11_lock();
3302    if (descr->image)
3303         bmpImage = descr->image;
3304     else {
3305         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3306                                  descr->infoWidth, lines, 32, 0 );
3307         bmpImage->data = HeapAlloc( GetProcessHeap(), 0, lines * bmpImage->bytes_per_line );
3308         if(bmpImage->data == NULL) {
3309             ERR("Out of memory!\n");
3310             XDestroyImage( bmpImage );
3311             wine_tsx11_unlock();
3312             return 0;
3313         }
3314         if (descr->shifts)
3315         {
3316             bmpImage->red_mask = descr->shifts->physicalRed.max << descr->shifts->physicalRed.shift;
3317             bmpImage->green_mask = descr->shifts->physicalGreen.max << descr->shifts->physicalGreen.shift;
3318             bmpImage->blue_mask = descr->shifts->physicalBlue.max << descr->shifts->physicalBlue.shift;
3319         }
3320     }
3321
3322 #ifdef HAVE_LIBXXSHM
3323
3324     /* We must not call XShmGetImage() with a bitmap which is bigger than the available area.
3325        If we do, XShmGetImage() will fail (X exception), as it checks for this internally. */
3326     if (descr->shm_mode == X11DRV_SHM_PIXMAP && descr->image
3327             && descr->xSrc == 0 && descr->ySrc == 0
3328             && descr->xDest == 0 && descr->yDest == 0
3329             && bmpImage->width <= (descr->width - descr->xSrc)
3330             && bmpImage->height <= (descr->height - descr->ySrc))
3331     {
3332         XSync( gdi_display, False );
3333         old_data = bmpImage->data;
3334         bmpImage->data = descr->physBitmap->shminfo.shmaddr;
3335         TRACE("Using shared pixmap data.\n");
3336     }
3337     else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image
3338             && bmpImage->width <= (descr->width - descr->xSrc)
3339             && bmpImage->height <= (descr->height - descr->ySrc))
3340     {
3341         int saveRed, saveGreen, saveBlue;
3342
3343         TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3344                             gdi_display, descr->drawable, bmpImage,
3345                             descr->xSrc, descr->ySrc, AllPlanes);
3346
3347         /* We must save and restore the bmpImage's masks in order
3348          * to preserve them across the call to XShmGetImage, which
3349          * decides to eliminate them since it doesn't happen to know
3350          * what the format of the image is supposed to be, even though
3351          * we do. */
3352         saveRed = bmpImage->red_mask;
3353         saveBlue= bmpImage->blue_mask;
3354         saveGreen = bmpImage->green_mask;
3355
3356         XShmGetImage( gdi_display, descr->drawable, bmpImage,
3357                       descr->xSrc, descr->ySrc, AllPlanes);
3358
3359         bmpImage->red_mask = saveRed;
3360         bmpImage->blue_mask = saveBlue;
3361         bmpImage->green_mask = saveGreen;
3362     }
3363     else
3364 #endif /* HAVE_LIBXXSHM */
3365     {
3366         TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3367               gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3368               lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3369         XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3370                       descr->width, lines, AllPlanes, ZPixmap,
3371                       bmpImage, descr->xDest, descr->yDest );
3372     }
3373     wine_tsx11_unlock();
3374
3375     TRACE("Dib: depth=%2d r=%x g=%x b=%x\n",
3376           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3377     TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3378           bmpImage->depth,bmpImage->bits_per_pixel,
3379           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3380       /* Transfer the pixels */
3381     switch(descr->infoBpp)
3382     {
3383     case 1:
3384           X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3385                                      descr->infoWidth, descr->width,
3386                                      descr->colorMap, descr->palentry,
3387                                      bmpImage, descr->dibpitch );
3388        break;
3389
3390     case 4:
3391         X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3392                                    descr->infoWidth, descr->width,
3393                                    descr->colorMap, descr->palentry,
3394                                    bmpImage, descr->dibpitch );
3395         break;
3396     case 8:
3397         X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3398                                    descr->infoWidth, descr->width,
3399                                    descr->colorMap, descr->palentry,
3400                                    bmpImage, descr->dibpitch );
3401         break;
3402     case 16:
3403        X11DRV_DIB_GetImageBits_16( descr->physDev, descr->lines, (LPVOID)descr->bits,
3404                                    descr->infoWidth,descr->width,
3405                                    descr->palentry,
3406                                    descr->rMask, descr->gMask, descr->bMask,
3407                                    bmpImage, descr->dibpitch );
3408        break;
3409
3410     case 24:
3411        X11DRV_DIB_GetImageBits_24( descr->physDev, descr->lines, (LPVOID)descr->bits,
3412                                    descr->infoWidth,descr->width,
3413                                    descr->palentry,
3414                                    descr->rMask, descr->gMask, descr->bMask,
3415                                    bmpImage, descr->dibpitch);
3416        break;
3417
3418     case 32:
3419        X11DRV_DIB_GetImageBits_32( descr->physDev, descr->lines, (LPVOID)descr->bits,
3420                                    descr->infoWidth, descr->width,
3421                                    descr->palentry,
3422                                    descr->rMask, descr->gMask, descr->bMask,
3423                                    bmpImage, descr->dibpitch);
3424        break;
3425
3426     default:
3427         WARN("(%d): Invalid depth\n", descr->infoBpp );
3428         break;
3429     }
3430
3431     if (old_data) bmpImage->data = old_data;
3432     if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
3433     return lines;
3434 }
3435
3436 /***********************************************************************
3437  *           X11DRV_DIB_DoCopyDIBSection
3438  */
3439 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
3440                                         void *colorMap, int nColorMap,
3441                                         Drawable dest, GC gc,
3442                                         DWORD xSrc, DWORD ySrc,
3443                                         DWORD xDest, DWORD yDest,
3444                                         DWORD width, DWORD height)
3445 {
3446   DIBSECTION dibSection;
3447   X11DRV_DIB_IMAGEBITS_DESCR descr;
3448   int identity[2] = {0,1};
3449
3450   if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
3451
3452   descr.physDev     = NULL;
3453   descr.palentry    = NULL;
3454   descr.infoWidth   = dibSection.dsBmih.biWidth;
3455   descr.infoBpp     = dibSection.dsBmih.biBitCount;
3456   descr.lines       = physBitmap->topdown ? -dibSection.dsBmih.biHeight : dibSection.dsBmih.biHeight;
3457   descr.image       = physBitmap->image;
3458   descr.colorMap    = colorMap;
3459   descr.nColorMap   = nColorMap;
3460   descr.bits        = dibSection.dsBm.bmBits;
3461   descr.depth       = physBitmap->depth;
3462   descr.shifts      = physBitmap->trueColor ? &physBitmap->color_shifts : NULL;
3463   descr.compression = dibSection.dsBmih.biCompression;
3464   descr.physBitmap  = physBitmap;
3465
3466   if(descr.infoBpp == 1)
3467       descr.colorMap = (void*)identity;
3468
3469   switch (descr.infoBpp)
3470   {
3471     case 1:
3472     case 4:
3473     case 8:
3474       descr.rMask = descr.gMask = descr.bMask = 0;
3475       break;
3476     case 15:
3477     case 16:
3478       descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0x7c00;
3479       descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x03e0;
3480       descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x001f;
3481       break;
3482
3483     case 24:
3484     case 32:
3485       descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0xff0000;
3486       descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x00ff00;
3487       descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x0000ff;
3488       break;
3489   }
3490
3491   /* Hack for now */
3492   descr.drawable  = dest;
3493   descr.gc        = gc;
3494   descr.xSrc      = xSrc;
3495   descr.ySrc      = ySrc;
3496   descr.xDest     = xDest;
3497   descr.yDest     = yDest;
3498   descr.width     = width;
3499   descr.height    = height;
3500   descr.sizeImage = 0;
3501
3502   descr.shm_mode = physBitmap->shm_mode;
3503 #ifdef HAVE_LIBXXSHM
3504   if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP && physBitmap->pixmap != dest)
3505   {
3506     descr.shm_mode = X11DRV_SHM_NONE;
3507   }
3508 #endif
3509   descr.dibpitch = dibSection.dsBm.bmWidthBytes;
3510
3511   if (toDIB)
3512     {
3513       TRACE("Copying from Pixmap to DIB bits\n");
3514       X11DRV_DIB_GetImageBits( &descr );
3515     }
3516   else
3517     {
3518       TRACE("Copying from DIB bits to Pixmap\n");
3519       X11DRV_DIB_SetImageBits( &descr );
3520     }
3521 }
3522
3523 /***********************************************************************
3524  *           X11DRV_DIB_DoUpdateDIBSection
3525  */
3526 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
3527 {
3528     BITMAP bitmap;
3529
3530     GetObjectW( physBitmap->hbitmap, sizeof(bitmap), &bitmap );
3531     X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
3532                                 physBitmap->colorMap, physBitmap->nColorMap,
3533                                 physBitmap->pixmap, get_bitmap_gc(physBitmap->depth),
3534                                 0, 0, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
3535 }
3536
3537 /***********************************************************************
3538  *           X11DRV_DIB_FaultHandler
3539  */
3540 static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep )
3541 {
3542     X_PHYSBITMAP *physBitmap = NULL;
3543     BOOL found = FALSE;
3544     BYTE *addr;
3545     struct list *ptr;
3546     const size_t pagemask = getpagesize() - 1;
3547
3548     if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
3549         return EXCEPTION_CONTINUE_SEARCH;
3550
3551     addr = (BYTE *)ep->ExceptionRecord->ExceptionInformation[1];
3552
3553     EnterCriticalSection(&dibs_cs);
3554     LIST_FOR_EACH( ptr, &dibs_list )
3555     {
3556         physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry );
3557         if ((physBitmap->base <= addr) &&
3558             (addr < physBitmap->base + ((physBitmap->size + pagemask) & ~pagemask)))
3559         {
3560             found = TRUE;
3561             break;
3562         }
3563     }
3564     LeaveCriticalSection(&dibs_cs);
3565
3566     if (!found) return EXCEPTION_CONTINUE_SEARCH;
3567
3568     if (addr >= physBitmap->base + physBitmap->size)
3569         WARN( "%p: access to %p beyond the end of the DIB\n", physBitmap->hbitmap, addr );
3570
3571     X11DRV_DIB_Lock( physBitmap, DIB_Status_None );
3572     if (ep->ExceptionRecord->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT) {
3573         /* the app tried to write the DIB bits */
3574         X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod);
3575     } else {
3576         /* the app tried to read the DIB bits */
3577         X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync);
3578     }
3579     X11DRV_DIB_Unlock( physBitmap, TRUE );
3580
3581     return EXCEPTION_CONTINUE_EXECUTION;
3582 }
3583
3584 /***********************************************************************
3585  *           X11DRV_DIB_Coerce
3586  */
3587 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *physBitmap, INT req)
3588 {
3589     INT ret = DIB_Status_None;
3590
3591     if (!physBitmap->image) return ret;  /* not a DIB section */
3592     EnterCriticalSection(&physBitmap->lock);
3593     ret = physBitmap->status;
3594     switch (req) {
3595     case DIB_Status_GdiMod:
3596       /* GDI access - request to draw on pixmap */
3597       switch (physBitmap->status)
3598       {
3599         default:
3600         case DIB_Status_None:
3601           physBitmap->p_status = DIB_Status_GdiMod;
3602           X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
3603           break;
3604
3605         case DIB_Status_GdiMod:
3606           TRACE("GdiMod requested in status GdiMod\n" );
3607           physBitmap->p_status = DIB_Status_GdiMod;
3608           break;
3609
3610         case DIB_Status_InSync:
3611           TRACE("GdiMod requested in status InSync\n" );
3612           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
3613           physBitmap->status = DIB_Status_GdiMod;
3614           physBitmap->p_status = DIB_Status_InSync;
3615           break;
3616
3617         case DIB_Status_AppMod:
3618           TRACE("GdiMod requested in status AppMod\n" );
3619           /* make it readonly to avoid app changing data while we copy */
3620           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
3621           X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
3622           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
3623           physBitmap->p_status = DIB_Status_AppMod;
3624           physBitmap->status = DIB_Status_GdiMod;
3625           break;
3626       }
3627       break;
3628
3629     case DIB_Status_InSync:
3630       /* App access - request access to read DIB surface */
3631       /* (typically called from signal handler) */
3632       switch (physBitmap->status)
3633       {
3634         default:
3635         case DIB_Status_None:
3636           /* shouldn't happen from signal handler */
3637           break;
3638
3639         case DIB_Status_GdiMod:
3640           TRACE("InSync requested in status GdiMod\n" );
3641           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3642           X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
3643           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
3644           physBitmap->status = DIB_Status_InSync;
3645           break;
3646
3647         case DIB_Status_InSync:
3648           TRACE("InSync requested in status InSync\n" );
3649           /* shouldn't happen from signal handler */
3650           break;
3651
3652         case DIB_Status_AppMod:
3653           TRACE("InSync requested in status AppMod\n" );
3654           /* no reason to do anything here, and this
3655            * shouldn't happen from signal handler */
3656           break;
3657       }
3658       break;
3659
3660     case DIB_Status_AppMod:
3661       /* App access - request access to write DIB surface */
3662       /* (typically called from signal handler) */
3663       switch (physBitmap->status)
3664       {
3665         default:
3666         case DIB_Status_None:
3667           /* shouldn't happen from signal handler */
3668           break;
3669
3670         case DIB_Status_GdiMod:
3671           TRACE("AppMod requested in status GdiMod\n" );
3672           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3673           X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
3674           physBitmap->status = DIB_Status_AppMod;
3675           break;
3676
3677         case DIB_Status_InSync:
3678           TRACE("AppMod requested in status InSync\n" );
3679           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3680           physBitmap->status = DIB_Status_AppMod;
3681           break;
3682
3683         case DIB_Status_AppMod:
3684           TRACE("AppMod requested in status AppMod\n" );
3685           /* shouldn't happen from signal handler */
3686           break;
3687       }
3688       break;
3689
3690       /* it is up to the caller to do the copy/conversion, probably
3691        * using the return value to decide where to copy from */
3692     }
3693     LeaveCriticalSection(&physBitmap->lock);
3694     return ret;
3695 }
3696
3697 /***********************************************************************
3698  *           X11DRV_DIB_Lock
3699  */
3700 INT X11DRV_DIB_Lock(X_PHYSBITMAP *physBitmap, INT req)
3701 {
3702     INT ret = DIB_Status_None;
3703
3704     if (!physBitmap->image) return ret;  /* not a DIB section */
3705     TRACE("Locking %p from thread %04x\n", physBitmap->hbitmap, GetCurrentThreadId());
3706     EnterCriticalSection(&physBitmap->lock);
3707     ret = physBitmap->status;
3708     if (req != DIB_Status_None)
3709       X11DRV_DIB_Coerce(physBitmap, req);
3710     return ret;
3711 }
3712
3713 /***********************************************************************
3714  *           X11DRV_DIB_Unlock
3715  */
3716 void X11DRV_DIB_Unlock(X_PHYSBITMAP *physBitmap, BOOL commit)
3717 {
3718     if (!physBitmap->image) return;  /* not a DIB section */
3719     switch (physBitmap->status)
3720     {
3721       default:
3722       case DIB_Status_None:
3723         /* in case anyone is wondering, this is the "signal handler doesn't
3724          * work" case, where we always have to be ready for app access */
3725         if (commit) {
3726           switch (physBitmap->p_status)
3727           {
3728             case DIB_Status_GdiMod:
3729               TRACE("Unlocking and syncing from GdiMod\n" );
3730               X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
3731               break;
3732
3733             default:
3734               TRACE("Unlocking without needing to sync\n" );
3735               break;
3736           }
3737         }
3738         else TRACE("Unlocking with no changes\n");
3739         physBitmap->p_status = DIB_Status_None;
3740         break;
3741
3742       case DIB_Status_GdiMod:
3743         TRACE("Unlocking in status GdiMod\n" );
3744         /* DIB was protected in Coerce */
3745         if (!commit) {
3746           /* no commit, revert to InSync if applicable */
3747           if ((physBitmap->p_status == DIB_Status_InSync) ||
3748               (physBitmap->p_status == DIB_Status_AppMod)) {
3749             X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
3750             physBitmap->status = DIB_Status_InSync;
3751           }
3752         }
3753         break;
3754
3755       case DIB_Status_InSync:
3756         TRACE("Unlocking in status InSync\n" );
3757         /* DIB was already protected in Coerce */
3758         break;
3759
3760       case DIB_Status_AppMod:
3761         TRACE("Unlocking in status AppMod\n" );
3762         /* DIB was already protected in Coerce */
3763         /* this case is ordinary only called from the signal handler,
3764          * so we don't bother to check for !commit */
3765         break;
3766     }
3767     LeaveCriticalSection(&physBitmap->lock);
3768     TRACE("Unlocked %p\n", physBitmap->hbitmap);
3769 }
3770
3771 /***********************************************************************
3772  *           X11DRV_CoerceDIBSection
3773  */
3774 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req)
3775 {
3776     if (!physDev || !physDev->bitmap) return DIB_Status_None;
3777     return X11DRV_DIB_Coerce(physDev->bitmap, req);
3778 }
3779
3780 /***********************************************************************
3781  *           X11DRV_LockDIBSection
3782  */
3783 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req)
3784 {
3785     if (!physDev || !physDev->bitmap) return DIB_Status_None;
3786     return X11DRV_DIB_Lock(physDev->bitmap, req);
3787 }
3788
3789 /***********************************************************************
3790  *           X11DRV_UnlockDIBSection
3791  */
3792 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
3793 {
3794     if (!physDev || !physDev->bitmap) return;
3795     X11DRV_DIB_Unlock(physDev->bitmap, commit);
3796 }
3797
3798
3799 #ifdef HAVE_LIBXXSHM
3800 /***********************************************************************
3801  *           X11DRV_XShmErrorHandler
3802  *
3803  */
3804 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
3805 {
3806     return 1;  /* FIXME: should check event contents */
3807 }
3808
3809 /***********************************************************************
3810  *           X11DRV_XShmCreateImage
3811  *
3812  */
3813 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
3814                                        XShmSegmentInfo* shminfo)
3815 {
3816     XImage *image;
3817
3818     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
3819     if (image)
3820     {
3821         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
3822                                   IPC_CREAT|0700);
3823         if( shminfo->shmid != -1 )
3824         {
3825             shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 );
3826             if( shminfo->shmaddr != (char*)-1 )
3827             {
3828                 BOOL ok;
3829
3830                 shminfo->readOnly = FALSE;
3831                 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
3832                 ok = (XShmAttach( gdi_display, shminfo ) != 0);
3833                 XSync( gdi_display, False );
3834                 if (X11DRV_check_error()) ok = FALSE;
3835                 if (ok)
3836                 {
3837                     shmctl(shminfo->shmid, IPC_RMID, 0);
3838                     return image; /* Success! */
3839                 }
3840                 /* An error occurred */
3841                 shmdt(shminfo->shmaddr);
3842             }
3843             shmctl(shminfo->shmid, IPC_RMID, 0);
3844             shminfo->shmid = -1;
3845         }
3846         XFlush(gdi_display);
3847         XDestroyImage(image);
3848         image = NULL;
3849     }
3850     return image;
3851 }
3852 #endif /* HAVE_LIBXXSHM */
3853
3854 static Bool X11DRV_DIB_QueryXShm( Bool *pixmaps )
3855 {
3856     static Bool have_xshm, have_xshm_pixmaps;
3857     static BOOL initialized;
3858
3859     if (!initialized)
3860     {
3861 #ifdef HAVE_LIBXXSHM
3862         int major, minor;
3863
3864         have_xshm = XShmQueryVersion( gdi_display, &major, &minor, &have_xshm_pixmaps );
3865 #endif
3866         initialized = TRUE;
3867     }
3868
3869     *pixmaps = have_xshm_pixmaps;
3870     return have_xshm;
3871 }
3872
3873 /***********************************************************************
3874  *           X11DRV_CreateDIBSection   (X11DRV.@)
3875  */
3876 HBITMAP X11DRV_CreateDIBSection( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *bmi, UINT usage )
3877 {
3878     X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
3879     X_PHYSBITMAP *physBitmap;
3880     DIBSECTION dib;
3881 #ifdef HAVE_LIBXXSHM
3882     Bool pixmaps;
3883 #endif
3884
3885     if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
3886     physBitmap->topdown = bmi->bmiHeader.biHeight < 0;
3887     physBitmap->status = DIB_Status_None;
3888
3889     GetObjectW( hbitmap, sizeof(dib), &dib );
3890
3891     /* create color map */
3892     if (dib.dsBm.bmBitsPixel <= 8)
3893     {
3894         physBitmap->colorMap = X11DRV_DIB_BuildColorMap( physDev,
3895                                                          usage, dib.dsBm.bmBitsPixel, bmi,
3896                                                          &physBitmap->nColorMap );
3897     }
3898
3899     if (!X11DRV_XRender_SetPhysBitmapDepth( physBitmap, dib.dsBm.bmBitsPixel, &dib ))
3900     {
3901         if (dib.dsBm.bmBitsPixel == 1)
3902         {
3903             physBitmap->depth = 1;
3904             physBitmap->trueColor = FALSE;
3905         }
3906         else
3907         {
3908             physBitmap->depth = screen_depth;
3909             physBitmap->color_shifts = X11DRV_PALETTE_default_shifts;
3910             physBitmap->trueColor = (visual->class == TrueColor || visual->class == DirectColor);
3911         }
3912     }
3913
3914     /* create pixmap and X image */
3915     wine_tsx11_lock();
3916 #ifdef HAVE_LIBXXSHM
3917     physBitmap->shminfo.shmid = -1;
3918
3919     if (X11DRV_DIB_QueryXShm( &pixmaps )
3920             && (physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
3921                                                             physBitmap->depth, &physBitmap->shminfo )))
3922     {
3923         if (pixmaps)
3924         {
3925             physBitmap->shm_mode = X11DRV_SHM_PIXMAP;
3926             physBitmap->image->data = HeapAlloc( GetProcessHeap(), 0,
3927                     dib.dsBm.bmHeight * physBitmap->image->bytes_per_line );
3928         }
3929         else
3930         {
3931             physBitmap->shm_mode = X11DRV_SHM_IMAGE;
3932             physBitmap->image->data = physBitmap->shminfo.shmaddr;
3933         }
3934     }
3935     else
3936 #endif
3937     {
3938         physBitmap->shm_mode = X11DRV_SHM_NONE;
3939         physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
3940                                                      physBitmap->depth );
3941     }
3942
3943 #ifdef HAVE_LIBXXSHM
3944     if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP)
3945     {
3946         TRACE("Creating shared pixmap for bmp %p.\n", physBitmap->hbitmap);
3947         physBitmap->pixmap = XShmCreatePixmap( gdi_display, root_window,
3948                                                physBitmap->shminfo.shmaddr, &physBitmap->shminfo,
3949                                                dib.dsBm.bmWidth, dib.dsBm.bmHeight,
3950                                                physBitmap->depth );
3951     }
3952     else
3953 #endif
3954     {
3955         physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
3956                                             dib.dsBm.bmHeight, physBitmap->depth );
3957     }
3958
3959     wine_tsx11_unlock();
3960     if (!physBitmap->pixmap || !physBitmap->image) return 0;
3961
3962     if (physBitmap->trueColor)
3963     {
3964         ColorShifts *shifts = &physBitmap->color_shifts;
3965
3966         /* When XRender is around and used, we also support dibsections in other formats like 16-bit. In these
3967          * cases we need to override the mask of XImages. The reason is that during XImage creation the masks are
3968          * derived from a 24-bit visual (no 16-bit ones are around when X runs at 24-bit). SetImageBits and other
3969          * functions rely on the color masks for proper color conversion, so we need to override the masks here. */
3970         physBitmap->image->red_mask = shifts->physicalRed.max << shifts->physicalRed.shift;
3971         physBitmap->image->green_mask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
3972         physBitmap->image->blue_mask = shifts->physicalBlue.max << shifts->physicalBlue.shift;
3973     }
3974
3975       /* install fault handler */
3976     InitializeCriticalSection( &physBitmap->lock );
3977     physBitmap->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": X_PHYSBITMAP.lock");
3978
3979     physBitmap->base   = dib.dsBm.bmBits;
3980     physBitmap->size   = dib.dsBmih.biSizeImage;
3981     physBitmap->status = DIB_Status_AppMod;
3982
3983     if (!dibs_handler)
3984         dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler );
3985     EnterCriticalSection( &dibs_cs );
3986     list_add_head( &dibs_list, &physBitmap->entry );
3987     LeaveCriticalSection( &dibs_cs );
3988
3989     X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3990
3991     return hbitmap;
3992 }
3993
3994 /***********************************************************************
3995  *           X11DRV_DIB_DeleteDIBSection
3996  */
3997 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
3998 {
3999   BOOL last;
4000
4001   EnterCriticalSection( &dibs_cs );
4002   list_remove( &physBitmap->entry );
4003   last = list_empty( &dibs_list );
4004   LeaveCriticalSection( &dibs_cs );
4005
4006   if (last)
4007   {
4008       RemoveVectoredExceptionHandler( dibs_handler );
4009       dibs_handler = NULL;
4010   }
4011
4012   if (dib->dshSection)
4013       X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync);
4014
4015   if (physBitmap->image)
4016   {
4017       wine_tsx11_lock();
4018 #ifdef HAVE_LIBXXSHM
4019       if (physBitmap->shminfo.shmid != -1)
4020       {
4021           XShmDetach( gdi_display, &(physBitmap->shminfo) );
4022           if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP) X11DRV_DIB_DestroyXImage( physBitmap->image );
4023           else XDestroyImage( physBitmap->image );
4024           shmdt( physBitmap->shminfo.shmaddr );
4025           physBitmap->shminfo.shmid = -1;
4026           physBitmap->shm_mode = X11DRV_SHM_NONE;
4027       }
4028       else
4029 #endif
4030           X11DRV_DIB_DestroyXImage( physBitmap->image );
4031       wine_tsx11_unlock();
4032   }
4033
4034   HeapFree(GetProcessHeap(), 0, physBitmap->colorMap);
4035   physBitmap->lock.DebugInfo->Spare[0] = 0;
4036   DeleteCriticalSection(&physBitmap->lock);
4037 }
4038
4039 /***********************************************************************
4040  *           SetDIBColorTable   (X11DRV.@)
4041  */
4042 UINT X11DRV_SetDIBColorTable( PHYSDEV dev, UINT start, UINT count, const RGBQUAD *colors )
4043 {
4044     X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
4045     DIBSECTION dib;
4046     UINT ret = 0;
4047     X_PHYSBITMAP *physBitmap = physDev->bitmap;
4048
4049     if (!physBitmap) return 0;
4050     GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4051
4052     if (physBitmap->colorMap && start < physBitmap->nColorMap) {
4053         UINT end = count + start;
4054         if (end > physBitmap->nColorMap) end = physBitmap->nColorMap;
4055         /*
4056          * Changing color table might change the mapping between
4057          * DIB colors and X11 colors and thus alter the visible state
4058          * of the bitmap object.
4059          */
4060         /*
4061          * FIXME we need to recalculate the pen, brush, text and bkgnd pixels here,
4062          * at least for a 1 bpp dibsection
4063          */
4064         X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod );
4065         X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
4066                                 dib.dsBm.bmBitsPixel, colors, start, end );
4067         X11DRV_DIB_Unlock( physBitmap, TRUE );
4068         ret = end - start;
4069     }
4070     return ret;
4071 }
4072
4073
4074 /***********************************************************************
4075  *           X11DRV_DIB_CreateDIBFromBitmap
4076  *
4077  *  Allocates a packed DIB and copies the bitmap data into it.
4078  */
4079 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4080 {
4081     BITMAP bmp;
4082     HGLOBAL hPackedDIB;
4083     LPBYTE pPackedDIB;
4084     LPBITMAPINFOHEADER pbmiHeader;
4085     unsigned int cDataSize, cPackedSize, OffsetBits;
4086     int nLinesCopied;
4087
4088     if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4089
4090     /*
4091      * A packed DIB contains a BITMAPINFO structure followed immediately by
4092      * an optional color palette and the pixel data.
4093      */
4094
4095     /* Calculate the size of the packed DIB */
4096     cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4097     cPackedSize = sizeof(BITMAPINFOHEADER)
4098                   + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4099                   + cDataSize;
4100     /* Get the offset to the bits */
4101     OffsetBits = cPackedSize - cDataSize;
4102
4103     /* Allocate the packed DIB */
4104     TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4105     hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4106                              cPackedSize );
4107     if ( !hPackedDIB )
4108     {
4109         WARN("Could not allocate packed DIB!\n");
4110         return 0;
4111     }
4112
4113     /* A packed DIB starts with a BITMAPINFOHEADER */
4114     pPackedDIB = GlobalLock(hPackedDIB);
4115     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4116
4117     /* Init the BITMAPINFOHEADER */
4118     pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4119     pbmiHeader->biWidth = bmp.bmWidth;
4120     pbmiHeader->biHeight = bmp.bmHeight;
4121     pbmiHeader->biPlanes = 1;
4122     pbmiHeader->biBitCount = bmp.bmBitsPixel;
4123     pbmiHeader->biCompression = BI_RGB;
4124     pbmiHeader->biSizeImage = 0;
4125     pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4126     pbmiHeader->biClrUsed = 0;
4127     pbmiHeader->biClrImportant = 0;
4128
4129     /* Retrieve the DIB bits from the bitmap and fill in the
4130      * DIB color table if present */
4131
4132     nLinesCopied = GetDIBits(hdc,                       /* Handle to device context */
4133                              hBmp,                      /* Handle to bitmap */
4134                              0,                         /* First scan line to set in dest bitmap */
4135                              bmp.bmHeight,              /* Number of scan lines to copy */
4136                              pPackedDIB + OffsetBits,   /* [out] Address of array for bitmap bits */
4137                              (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4138                              0);                        /* RGB or palette index */
4139     GlobalUnlock(hPackedDIB);
4140
4141     /* Cleanup if GetDIBits failed */
4142     if (nLinesCopied != bmp.bmHeight)
4143     {
4144         TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4145         GlobalFree(hPackedDIB);
4146         hPackedDIB = 0;
4147     }
4148     return hPackedDIB;
4149 }
4150
4151
4152 /**************************************************************************
4153  *              X11DRV_DIB_CreateDIBFromPixmap
4154  *
4155  *  Allocates a packed DIB and copies the Pixmap data into it.
4156  *  The Pixmap passed in is deleted after the conversion.
4157  */
4158 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc)
4159 {
4160     HDC hdcMem;
4161     X_PHYSBITMAP *physBitmap;
4162     Pixmap orig_pixmap;
4163     HBITMAP hBmp = 0;
4164     HGLOBAL hPackedDIB = 0;
4165     Window root;
4166     int x,y;               /* Unused */
4167     unsigned border_width; /* Unused */
4168     unsigned int depth, width, height;
4169
4170     /* Get the Pixmap dimensions and bit depth */
4171     wine_tsx11_lock();
4172     if (!XGetGeometry(gdi_display, pixmap, &root, &x, &y, &width, &height,
4173                       &border_width, &depth)) depth = 0;
4174     wine_tsx11_unlock();
4175     if (!pixmap_formats[depth]) return 0;
4176
4177     TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4178           width, height, depth);
4179
4180     /*
4181      * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4182      * and make it a container for the pixmap passed.
4183      */
4184     if (!(hBmp = CreateBitmap( width, height, 1, pixmap_formats[depth]->bits_per_pixel, NULL ))) return 0;
4185
4186     /* force bitmap to be owned by a screen DC */
4187     hdcMem = CreateCompatibleDC( hdc );
4188     SelectObject( hdcMem, SelectObject( hdcMem, hBmp ));
4189     DeleteDC( hdcMem );
4190
4191     physBitmap = X11DRV_get_phys_bitmap( hBmp );
4192
4193     /* swap the new pixmap in */
4194     orig_pixmap = physBitmap->pixmap;
4195     physBitmap->pixmap = pixmap;
4196
4197     /*
4198      * Create a packed DIB from the Pixmap wrapper bitmap created above.
4199      * A packed DIB contains a BITMAPINFO structure followed immediately by
4200      * an optional color palette and the pixel data.
4201      */
4202     hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4203
4204     /* we can now get rid of the HBITMAP and its original pixmap */
4205     physBitmap->pixmap = orig_pixmap;
4206     DeleteObject(hBmp);
4207
4208     TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4209     return hPackedDIB;
4210 }
4211
4212
4213 /**************************************************************************
4214  *                 X11DRV_DIB_CreatePixmapFromDIB
4215  *
4216  *    Creates a Pixmap from a packed DIB
4217  */
4218 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4219 {
4220     Pixmap pixmap = 0;
4221     X_PHYSBITMAP *physBitmap;
4222     HBITMAP hBmp;
4223     LPBITMAPINFO pbmi;
4224     HDC memdc;
4225
4226     /* Create a DDB from the DIB */
4227
4228     pbmi = GlobalLock(hPackedDIB);
4229     hBmp = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
4230                           (LPBYTE)pbmi + bitmap_info_size( pbmi, DIB_RGB_COLORS ),
4231                           pbmi, DIB_RGB_COLORS);
4232     GlobalUnlock(hPackedDIB);
4233
4234     /* make sure it's owned by x11drv */
4235     memdc = CreateCompatibleDC( hdc );
4236     SelectObject( memdc, hBmp );
4237     DeleteDC( memdc );
4238
4239     /* clear the physBitmap so that we can steal its pixmap */
4240     if ((physBitmap = X11DRV_get_phys_bitmap( hBmp )))
4241     {
4242         pixmap = physBitmap->pixmap;
4243         physBitmap->pixmap = 0;
4244     }
4245
4246     /* Delete the DDB we created earlier now that we have stolen its pixmap */
4247     DeleteObject(hBmp);
4248
4249     TRACE("Returning Pixmap %lx\n", pixmap);
4250     return pixmap;
4251 }