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