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