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