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