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