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