Use a different magic for memory DCs and get rid of the DC_MEMORY
[wine] / graphics / 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 "ts_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 <stdlib.h>
35 #include <string.h>
36 #include "windef.h"
37 #include "bitmap.h"
38 #include "x11drv.h"
39 #include "wine/debug.h"
40 #include "gdi.h"
41 #include "palette.h"
42 #include "global.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
45 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
46
47 static int ximageDepthTable[32];
48
49 /* This structure holds the arguments for DIB_SetImageBits() */
50 typedef struct
51 {
52     X11DRV_PDEVICE *physDev;
53     LPCVOID         bits;
54     XImage         *image;
55     PALETTEENTRY   *palentry;
56     int             lines;
57     DWORD           infoWidth;
58     WORD            depth;
59     WORD            infoBpp;
60     WORD            compression;
61     RGBQUAD        *colorMap;
62     int             nColorMap;
63     Drawable        drawable;
64     GC              gc;
65     int             xSrc;
66     int             ySrc;
67     int             xDest;
68     int             yDest;
69     int             width;
70     int             height;
71     DWORD           rMask;
72     DWORD           gMask;
73     DWORD           bMask;
74     BOOL            useShm;
75     int             dibpitch;
76 } X11DRV_DIB_IMAGEBITS_DESCR;
77
78
79 enum Rle_EscapeCodes
80 {
81   RLE_EOL   = 0, /* End of line */
82   RLE_END   = 1, /* End of bitmap */
83   RLE_DELTA = 2  /* Delta */
84 };
85
86 /***********************************************************************
87  *           X11DRV_DIB_GetXImageWidthBytes
88  *
89  * Return the width of an X image in bytes
90  */
91 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
92 {
93     if (!depth || depth > 32) goto error;
94
95     if (!ximageDepthTable[depth-1])
96     {
97         XImage *testimage = XCreateImage( gdi_display, visual, depth,
98                                           ZPixmap, 0, NULL, 1, 1, 32, 20 );
99         if (testimage)
100         {
101             ximageDepthTable[depth-1] = testimage->bits_per_pixel;
102             XDestroyImage( testimage );
103         }
104         else ximageDepthTable[depth-1] = -1;
105     }
106     if (ximageDepthTable[depth-1] != -1)
107         return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
108
109  error:
110     WARN( "(%d): Unsupported depth\n", depth );
111     return 4 * width;
112 }
113
114
115 /***********************************************************************
116  *           X11DRV_DIB_CreateXImage
117  *
118  * Create an X image.
119  */
120 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
121 {
122     int width_bytes;
123     XImage *image;
124
125     wine_tsx11_lock();
126     width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
127     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
128                           calloc( height, width_bytes ),
129                           width, height, 32, width_bytes );
130     wine_tsx11_unlock();
131     return image;
132 }
133
134
135 /***********************************************************************
136  *           DIB_GetBitmapInfo
137  *
138  * Get the info from a bitmap header.
139  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
140  */
141 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
142                               int *height, WORD *bpp, WORD *compr )
143 {
144     if (header->biSize == sizeof(BITMAPCOREHEADER))
145     {
146         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
147         *width  = core->bcWidth;
148         *height = core->bcHeight;
149         *bpp    = core->bcBitCount;
150         *compr  = 0;
151         return 0;
152     }
153     if (header->biSize >= sizeof(BITMAPINFOHEADER))
154     {
155         *width  = header->biWidth;
156         *height = header->biHeight;
157         *bpp    = header->biBitCount;
158         *compr  = header->biCompression;
159         return 1;
160     }
161     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
162     return -1;
163 }
164
165
166 /***********************************************************************
167  *           X11DRV_DIB_GenColorMap
168  *
169  * Fills the color map of a bitmap palette. Should not be called
170  * for a >8-bit deep bitmap.
171  */
172 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
173                              WORD coloruse, WORD depth, BOOL quads,
174                              const void *colorPtr, int start, int end )
175 {
176     int i;
177
178     if (coloruse == DIB_RGB_COLORS)
179     {
180         int max = 1 << depth;
181
182         if (end > max) end = max;
183
184         if (quads)
185         {
186             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
187
188             if (depth == 1)  /* Monochrome */
189                 for (i = start; i < end; i++, rgb++)
190                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
191                                        rgb->rgbBlue > 255*3/2);
192             else
193                 for (i = start; i < end; i++, rgb++)
194                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
195                                                                 rgb->rgbGreen,
196                                                                 rgb->rgbBlue));
197         }
198         else
199         {
200             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
201
202             if (depth == 1)  /* Monochrome */
203                 for (i = start; i < end; i++, rgb++)
204                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
205                                        rgb->rgbtBlue > 255*3/2);
206             else
207                 for (i = start; i < end; i++, rgb++)
208                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
209                                                                rgb->rgbtGreen,
210                                                                rgb->rgbtBlue));
211         }
212     }
213     else  /* DIB_PAL_COLORS */
214     {
215         if (colorPtr) {
216             WORD * index = (WORD *)colorPtr;
217
218             for (i = start; i < end; i++, index++)
219                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
220         } else {
221             for (i = start; i < end; i++)
222                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
223         }
224     }
225
226     return colorMapping;
227 }
228
229 /***********************************************************************
230  *           X11DRV_DIB_BuildColorMap
231  *
232  * Build the color map from the bitmap palette. Should not be called
233  * for a >8-bit deep bitmap.
234  */
235 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
236                                const BITMAPINFO *info, int *nColors )
237 {
238     int colors;
239     BOOL isInfo;
240     const void *colorPtr;
241     int *colorMapping;
242
243     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
244     {
245         colors = info->bmiHeader.biClrUsed;
246         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
247         colorPtr = info->bmiColors;
248     }
249     else  /* assume BITMAPCOREINFO */
250     {
251         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
252         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
253     }
254
255     if (colors > 256)
256     {
257         ERR("called with >256 colors!\n");
258         return NULL;
259     }
260
261     /* just so CopyDIBSection doesn't have to create an identity palette */
262     if (coloruse == (WORD)-1) colorPtr = NULL;
263
264     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
265                                           colors * sizeof(int) )))
266         return NULL;
267
268     *nColors = colors;
269     return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
270                                    isInfo, colorPtr, 0, colors);
271 }
272
273
274 /***********************************************************************
275  *           X11DRV_DIB_MapColor
276  */
277 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
278 {
279     int color;
280
281     if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
282         return oldcol;
283
284     for (color = 0; color < nPhysMap; color++)
285         if (physMap[color] == phys)
286             return color;
287
288     WARN("Strange color %08x\n", phys);
289     return 0;
290 }
291
292
293 /*********************************************************************
294  *         X11DRV_DIB_GetNearestIndex
295  *
296  * Helper for X11DRV_DIB_GetDIBits.
297  * Returns the nearest colour table index for a given RGB.
298  * Nearest is defined by minimizing the sum of the squares.
299  */
300 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
301 {
302     INT i, best = -1, diff, bestdiff = -1;
303     RGBQUAD *color;
304
305     for(color = colormap, i = 0; i < numColors; color++, i++) {
306         diff = (r - color->rgbRed) * (r - color->rgbRed) +
307                (g - color->rgbGreen) * (g - color->rgbGreen) +
308                (b - color->rgbBlue) * (b - color->rgbBlue);
309         if(diff == 0)
310             return i;
311         if(best == -1 || diff < bestdiff) {
312             best = i;
313             bestdiff = diff;
314         }
315     }
316     return best;
317 }
318 /*********************************************************************
319  *         X11DRV_DIB_MaskToShift
320  *
321  * Helper for X11DRV_DIB_GetDIBits.
322  * Returns the by how many bits to shift a given color so that it is
323  * in the proper position.
324  */
325 static INT X11DRV_DIB_MaskToShift(DWORD mask)
326 {
327     int shift;
328
329     if (mask==0)
330         return 0;
331
332     shift=0;
333     while ((mask&1)==0) {
334         mask>>=1;
335         shift++;
336     }
337     return shift;
338 }
339
340 /***********************************************************************
341  *           X11DRV_DIB_Convert_any_asis
342  *
343  * All X11DRV_DIB_Convert_Xxx functions take at least the following
344  * parameters:
345  * - width
346  *   This is the width in pixel of the surface to copy. This may be less
347  *   than the full width of the image.
348  * - height
349  *   The number of lines to copy. This may be less than the full height
350  *   of the image. This is always >0.
351  * - srcbits
352  *   Points to the first byte containing data to be copied. If the source
353  *   surface starts are coordinates (x,y) then this is:
354  *   image_ptr+x*bytes_pre_pixel+y*bytes_per_line
355  *   (with further adjustments for top-down/bottom-up images)
356  * - srclinebytes
357  *   This is the number of bytes per line. It may be >0 or <0 depending on
358  *   whether this is a top-down or bottom-up image.
359  * - dstbits
360  *   Same as srcbits but for the destination
361  * - dstlinebytes
362  *   Same as srclinebytes but for the destination.
363  *
364  * Notes:
365  * - The supported Dib formats are: pal1, pal4, pal8, rgb555, bgr555,
366  *   rgb565, bgr565, rgb888 and any 32bit (0888) format.
367  *   The supported XImage (Bmp) formats are: pal1, pal4, pal8,
368  *   rgb555, bgr555, rgb565, bgr565, rgb888, bgr888, rgb0888, bgr0888.
369  * - Rgb formats are those for which the masks are such that:
370  *   red_mask > green_mask > blue_mask
371  * - Bgr formats are those for which the masks sort in the other direction.
372  * - Many conversion functions handle both rgb->bgr and bgr->rgb conversions
373  *   so the comments use h, g, l to mean respectively the source color in the
374  *   high bits, the green, and the source color in the low bits.
375  */
376 static void X11DRV_DIB_Convert_any_asis(int width, int height,
377                                     int bytes_per_pixel,
378                                     const void* srcbits, int srclinebytes,
379                                     void* dstbits, int dstlinebytes)
380 {
381     int y;
382
383     width*=bytes_per_pixel;
384     for (y=0; y<height; y++) {
385         memcpy(dstbits, srcbits, width);
386         srcbits = (char*)srcbits + srclinebytes;
387         dstbits = (char*)dstbits + dstlinebytes;
388     }
389 }
390
391 /*
392  * 15 bit conversions
393  */
394
395 static void X11DRV_DIB_Convert_555_reverse(int width, int height,
396                                     const void* srcbits, int srclinebytes,
397                                     void* dstbits, int dstlinebytes)
398 {
399     const DWORD* srcpixel;
400     DWORD* dstpixel;
401     int x,y;
402
403     for (y=0; y<height; y++) {
404         srcpixel=srcbits;
405         dstpixel=dstbits;
406         for (x=0; x<width/2; x++) {
407             /* Do 2 pixels at a time */
408             DWORD srcval;
409             srcval=*srcpixel++;
410             *dstpixel++=((srcval << 10) & 0x7c007c00) | /* h */
411                         ( srcval        & 0x03e003e0) | /* g */
412                         ((srcval >> 10) & 0x001f001f);  /* l */
413         }
414         if (width&1) {
415             /* And the the odd pixel */
416             WORD srcval;
417             srcval=*((WORD*)srcpixel);
418             *((WORD*)dstpixel)=((srcval << 10) & 0x7c00) | /* h */
419                                ( srcval        & 0x03e0) | /* g */
420                                ((srcval >> 10) & 0x001f);  /* l */
421         }
422         srcbits = (char*)srcbits + srclinebytes;
423         dstbits = (char*)dstbits + dstlinebytes;
424     }
425 }
426
427 static void X11DRV_DIB_Convert_555_to_565_asis(int width, int height,
428                                     const void* srcbits, int srclinebytes,
429                                     void* dstbits, int dstlinebytes)
430 {
431     const DWORD* srcpixel;
432     DWORD* dstpixel;
433     int x,y;
434
435     for (y=0; y<height; y++) {
436         srcpixel=srcbits;
437         dstpixel=dstbits;
438         for (x=0; x<width/2; x++) {
439             /* Do 2 pixels at a time */
440             DWORD srcval;
441             srcval=*srcpixel++;
442             *dstpixel++=((srcval << 1) & 0xffc0ffc0) | /* h, g */
443                         ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
444                         ( srcval       & 0x001f001f);  /* l */
445         }
446         if (width&1) {
447             /* And the the odd pixel */
448             WORD srcval;
449             srcval=*((WORD*)srcpixel);
450             *((WORD*)dstpixel)=((srcval << 1) & 0xffc0) | /* h, g */
451                                ((srcval >> 4) & 0x0020) | /* g - 1 bit */
452                                 (srcval       & 0x001f);  /* l */
453         }
454         srcbits = (char*)srcbits + srclinebytes;
455         dstbits = (char*)dstbits + dstlinebytes;
456     }
457 }
458
459 static void X11DRV_DIB_Convert_555_to_565_reverse(int width, int height,
460                                     const void* srcbits, int srclinebytes,
461                                     void* dstbits, int dstlinebytes)
462 {
463     const DWORD* srcpixel;
464     DWORD* dstpixel;
465     int x,y;
466
467     for (y=0; y<height; y++) {
468         srcpixel=srcbits;
469         dstpixel=dstbits;
470         for (x=0; x<width/2; x++) {
471             /* Do 2 pixels at a time */
472             DWORD srcval;
473             srcval=*srcpixel++;
474             *dstpixel++=((srcval >> 10) & 0x001f001f) | /* h */
475                         ((srcval <<  1) & 0x07c007c0) | /* g */
476                         ((srcval >>  4) & 0x00200020) | /* g - 1 bit */
477                         ((srcval << 11) & 0xf800f800);  /* l */
478         }
479         if (width&1) {
480             /* And the the odd pixel */
481             WORD srcval;
482             srcval=*((WORD*)srcpixel);
483             *((WORD*)dstpixel)=((srcval >> 10) & 0x001f) | /* h */
484                                ((srcval <<  1) & 0x07c0) | /* g */
485                                ((srcval >>  4) & 0x0020) | /* g - 1 bit */
486                                ((srcval << 11) & 0xf800);  /* l */
487         }
488         srcbits = (char*)srcbits + srclinebytes;
489         dstbits = (char*)dstbits + dstlinebytes;
490     }
491 }
492
493 static void X11DRV_DIB_Convert_555_to_888_asis(int width, int height,
494                                     const void* srcbits, int srclinebytes,
495                                     void* dstbits, int dstlinebytes)
496 {
497     const WORD* srcpixel;
498     BYTE* dstpixel;
499     int x,y;
500
501     for (y=0; y<height; y++) {
502         srcpixel=srcbits;
503         dstpixel=dstbits;
504         for (x=0; x<width; x++) {
505             WORD srcval;
506             srcval=*srcpixel++;
507             dstpixel[0]=((srcval <<  3) & 0xf8) | /* l */
508                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
509             dstpixel[1]=((srcval >>  2) & 0xf8) | /* g */
510                         ((srcval >>  7) & 0x07);  /* g - 3 bits */
511             dstpixel[2]=((srcval >>  7) & 0xf8) | /* h */
512                         ((srcval >> 12) & 0x07);  /* h - 3 bits */
513             dstpixel+=3;
514         }
515         srcbits = (char*)srcbits + srclinebytes;
516         dstbits = (char*)dstbits + dstlinebytes;
517     }
518 }
519
520 static void X11DRV_DIB_Convert_555_to_888_reverse(int width, int height,
521                                     const void* srcbits, int srclinebytes,
522                                     void* dstbits, int dstlinebytes)
523 {
524     const WORD* srcpixel;
525     BYTE* dstpixel;
526     int x,y;
527
528     for (y=0; y<height; y++) {
529         srcpixel=srcbits;
530         dstpixel=dstbits;
531         for (x=0; x<width; x++) {
532             WORD srcval;
533             srcval=*srcpixel++;
534             dstpixel[0]=((srcval >>  7) & 0xf8) | /* h */
535                         ((srcval >> 12) & 0x07);  /* h - 3 bits */
536             dstpixel[1]=((srcval >>  2) & 0xf8) | /* g */
537                         ((srcval >>  7) & 0x07);  /* g - 3 bits */
538             dstpixel[2]=((srcval <<  3) & 0xf8) | /* l */
539                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
540             dstpixel+=3;
541         }
542         srcbits = (char*)srcbits + srclinebytes;
543         dstbits = (char*)dstbits + dstlinebytes;
544     }
545 }
546
547 static void X11DRV_DIB_Convert_555_to_0888_asis(int width, int height,
548                                     const void* srcbits, int srclinebytes,
549                                     void* dstbits, int dstlinebytes)
550 {
551     const WORD* srcpixel;
552     DWORD* dstpixel;
553     int x,y;
554
555     for (y=0; y<height; y++) {
556         srcpixel=srcbits;
557         dstpixel=dstbits;
558         for (x=0; x<width; x++) {
559             WORD srcval;
560             srcval=*srcpixel++;
561             *dstpixel++=((srcval << 9) & 0xf80000) | /* h */
562                         ((srcval << 4) & 0x070000) | /* h - 3 bits */
563                         ((srcval << 6) & 0x00f800) | /* g */
564                         ((srcval << 1) & 0x000700) | /* g - 3 bits */
565                         ((srcval << 3) & 0x0000f8) | /* l */
566                         ((srcval >> 2) & 0x000007);  /* l - 3 bits */
567         }
568         srcbits = (char*)srcbits + srclinebytes;
569         dstbits = (char*)dstbits + dstlinebytes;
570     }
571 }
572
573 static void X11DRV_DIB_Convert_555_to_0888_reverse(int width, int height,
574                                     const void* srcbits, int srclinebytes,
575                                     void* dstbits, int dstlinebytes)
576 {
577     const WORD* srcpixel;
578     DWORD* dstpixel;
579     int x,y;
580
581     for (y=0; y<height; y++) {
582         srcpixel=srcbits;
583         dstpixel=dstbits;
584         for (x=0; x<width; x++) {
585             WORD srcval;
586             srcval=*srcpixel++;
587             *dstpixel++=((srcval >>  7) & 0x0000f8) | /* h */
588                         ((srcval >> 12) & 0x000007) | /* h - 3 bits */
589                         ((srcval <<  6) & 0x00f800) | /* g */
590                         ((srcval <<  1) & 0x000700) | /* g - 3 bits */
591                         ((srcval << 19) & 0xf80000) | /* l */
592                         ((srcval << 14) & 0x070000);  /* l - 3 bits */
593         }
594         srcbits = (char*)srcbits + srclinebytes;
595         dstbits = (char*)dstbits + dstlinebytes;
596     }
597 }
598
599 static void X11DRV_DIB_Convert_5x5_to_any0888(int width, int height,
600                                     const void* srcbits, int srclinebytes,
601                                     WORD rsrc, WORD gsrc, WORD bsrc,
602                                     void* dstbits, int dstlinebytes,
603                                     DWORD rdst, DWORD gdst, DWORD bdst)
604 {
605     int rRightShift1,gRightShift1,bRightShift1;
606     int rRightShift2,gRightShift2,bRightShift2;
607     BYTE gMask1,gMask2;
608     int rLeftShift,gLeftShift,bLeftShift;
609     const WORD* srcpixel;
610     DWORD* dstpixel;
611     int x,y;
612
613     /* Note, the source pixel value is shifted left by 16 bits so that
614      * we know we will always have to shift right to extract the components.
615      */
616     rRightShift1=16+X11DRV_DIB_MaskToShift(rsrc)-3;
617     gRightShift1=16+X11DRV_DIB_MaskToShift(gsrc)-3;
618     bRightShift1=16+X11DRV_DIB_MaskToShift(bsrc)-3;
619     rRightShift2=rRightShift1+5;
620     gRightShift2=gRightShift1+5;
621     bRightShift2=bRightShift1+5;
622     if (gsrc==0x03e0) {
623         /* Green has 5 bits, like the others */
624         gMask1=0xf8;
625         gMask2=0x07;
626     } else {
627         /* Green has 6 bits, not 5. Compensate. */
628         gRightShift1++;
629         gRightShift2+=2;
630         gMask1=0xfc;
631         gMask2=0x03;
632     }
633
634     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
635     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
636     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
637
638     for (y=0; y<height; y++) {
639         srcpixel=srcbits;
640         dstpixel=dstbits;
641         for (x=0; x<width; x++) {
642             DWORD srcval;
643             BYTE red,green,blue;
644             srcval=*srcpixel++ << 16;
645             red=  ((srcval >> rRightShift1) & 0xf8) |
646                   ((srcval >> rRightShift2) & 0x07);
647             green=((srcval >> gRightShift1) & gMask1) |
648                   ((srcval >> gRightShift2) & gMask2);
649             blue= ((srcval >> bRightShift1) & 0xf8) |
650                   ((srcval >> bRightShift2) & 0x07);
651             *dstpixel++=(red   << rLeftShift) |
652                         (green << gLeftShift) |
653                         (blue  << bLeftShift);
654         }
655         srcbits = (char*)srcbits + srclinebytes;
656         dstbits = (char*)dstbits + dstlinebytes;
657     }
658 }
659
660 /*
661  * 16 bits conversions
662  */
663
664 static void X11DRV_DIB_Convert_565_reverse(int width, int height,
665                                     const void* srcbits, int srclinebytes,
666                                     void* dstbits, int dstlinebytes)
667 {
668     const DWORD* srcpixel;
669     DWORD* dstpixel;
670     int x,y;
671
672     for (y=0; y<height; y++) {
673         srcpixel=srcbits;
674         dstpixel=dstbits;
675         for (x=0; x<width/2; x++) {
676             /* Do 2 pixels at a time */
677             DWORD srcval;
678             srcval=*srcpixel++;
679             *dstpixel++=((srcval << 11) & 0xf800f800) | /* h */
680                         ( srcval        & 0x07e007e0) | /* g */
681                         ((srcval >> 11) & 0x001f001f);  /* l */
682         }
683         if (width&1) {
684             /* And the the odd pixel */
685             WORD srcval;
686             srcval=*((WORD*)srcpixel);
687             *((WORD*)dstpixel)=((srcval << 11) & 0xf800) | /* h */
688                                ( srcval        & 0x07e0) | /* g */
689                                ((srcval >> 11) & 0x001f);  /* l */
690         }
691         srcbits = (char*)srcbits + srclinebytes;
692         dstbits = (char*)dstbits + dstlinebytes;
693     }
694 }
695
696 static void X11DRV_DIB_Convert_565_to_555_asis(int width, int height,
697                                     const void* srcbits, int srclinebytes,
698                                     void* dstbits, int dstlinebytes)
699 {
700     const DWORD* srcpixel;
701     DWORD* dstpixel;
702     int x,y;
703
704     for (y=0; y<height; y++) {
705         srcpixel=srcbits;
706         dstpixel=dstbits;
707         for (x=0; x<width/2; x++) {
708             /* Do 2 pixels at a time */
709             DWORD srcval;
710             srcval=*srcpixel++;
711             *dstpixel++=((srcval >> 1) & 0x7fe07fe0) | /* h, g */
712                         ( srcval       & 0x001f001f);  /* l */
713         }
714         if (width&1) {
715             /* And the the odd pixel */
716             WORD srcval;
717             srcval=*((WORD*)srcpixel);
718             *((WORD*)dstpixel)=((srcval >> 1) & 0x7fe0) | /* h, g */
719                                ( srcval       & 0x001f);  /* l */
720         }
721         srcbits = (char*)srcbits + srclinebytes;
722         dstbits = (char*)dstbits + dstlinebytes;
723     }
724 }
725
726 static void X11DRV_DIB_Convert_565_to_555_reverse(int width, int height,
727                                     const void* srcbits, int srclinebytes,
728                                     void* dstbits, int dstlinebytes)
729 {
730     const DWORD* srcpixel;
731     DWORD* dstpixel;
732     int x,y;
733
734     for (y=0; y<height; y++) {
735         srcpixel=srcbits;
736         dstpixel=dstbits;
737         for (x=0; x<width/2; x++) {
738             /* Do 2 pixels at a time */
739             DWORD srcval;
740             srcval=*srcpixel++;
741             *dstpixel++=((srcval >> 11) & 0x001f001f) | /* h */
742                         ((srcval >>  1) & 0x03e003e0) | /* g */
743                         ((srcval << 10) & 0x7c007c00);  /* l */
744         }
745         if (width&1) {
746             /* And the the odd pixel */
747             WORD srcval;
748             srcval=*((WORD*)srcpixel);
749             *((WORD*)dstpixel)=((srcval >> 11) & 0x001f) | /* h */
750                                ((srcval >>  1) & 0x03e0) | /* g */
751                                ((srcval << 10) & 0x7c00);  /* l */
752         }
753         srcbits = (char*)srcbits + srclinebytes;
754         dstbits = (char*)dstbits + dstlinebytes;
755     }
756 }
757
758 static void X11DRV_DIB_Convert_565_to_888_asis(int width, int height,
759                                     const void* srcbits, int srclinebytes,
760                                     void* dstbits, int dstlinebytes)
761 {
762     const WORD* srcpixel;
763     BYTE* dstpixel;
764     int x,y;
765
766     for (y=0; y<height; y++) {
767         srcpixel=srcbits;
768         dstpixel=dstbits;
769         for (x=0; x<width; x++) {
770             WORD srcval;
771             srcval=*srcpixel++;
772             dstpixel[0]=((srcval <<  3) & 0xf8) | /* l */
773                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
774             dstpixel[1]=((srcval >>  3) & 0xfc) | /* g */
775                         ((srcval >>  9) & 0x03);  /* g - 2 bits */
776             dstpixel[2]=((srcval >>  8) & 0xf8) | /* h */
777                         ((srcval >> 13) & 0x07);  /* h - 3 bits */
778             dstpixel+=3;
779         }
780         srcbits = (char*)srcbits + srclinebytes;
781         dstbits = (char*)dstbits + dstlinebytes;
782     }
783 }
784
785 static void X11DRV_DIB_Convert_565_to_888_reverse(int width, int height,
786                                     const void* srcbits, int srclinebytes,
787                                     void* dstbits, int dstlinebytes)
788 {
789     const WORD* srcpixel;
790     BYTE* dstpixel;
791     int x,y;
792
793     for (y=0; y<height; y++) {
794         srcpixel=srcbits;
795         dstpixel=dstbits;
796         for (x=0; x<width; x++) {
797             WORD srcval;
798             srcval=*srcpixel++;
799             dstpixel[0]=((srcval >>  8) & 0xf8) | /* h */
800                         ((srcval >> 13) & 0x07);  /* h - 3 bits */
801             dstpixel[1]=((srcval >>  3) & 0xfc) | /* g */
802                         ((srcval >>  9) & 0x03);  /* g - 2 bits */
803             dstpixel[2]=((srcval <<  3) & 0xf8) | /* l */
804                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
805             dstpixel+=3;
806         }
807         srcbits = (char*)srcbits + srclinebytes;
808         dstbits = (char*)dstbits + dstlinebytes;
809     }
810 }
811
812 static void X11DRV_DIB_Convert_565_to_0888_asis(int width, int height,
813                                     const void* srcbits, int srclinebytes,
814                                     void* dstbits, int dstlinebytes)
815 {
816     const WORD* srcpixel;
817     DWORD* dstpixel;
818     int x,y;
819
820     for (y=0; y<height; y++) {
821         srcpixel=srcbits;
822         dstpixel=dstbits;
823         for (x=0; x<width; x++) {
824             WORD srcval;
825             srcval=*srcpixel++;
826             *dstpixel++=((srcval << 8) & 0xf80000) | /* h */
827                         ((srcval << 3) & 0x070000) | /* h - 3 bits */
828                         ((srcval << 5) & 0x00fc00) | /* g */
829                         ((srcval >> 1) & 0x000300) | /* g - 2 bits */
830                         ((srcval << 3) & 0x0000f8) | /* l */
831                         ((srcval >> 2) & 0x000007);  /* l - 3 bits */
832         }
833         srcbits = (char*)srcbits + srclinebytes;
834         dstbits = (char*)dstbits + dstlinebytes;
835     }
836 }
837
838 static void X11DRV_DIB_Convert_565_to_0888_reverse(int width, int height,
839                                     const void* srcbits, int srclinebytes,
840                                     void* dstbits, int dstlinebytes)
841 {
842     const WORD* srcpixel;
843     DWORD* dstpixel;
844     int x,y;
845
846     for (y=0; y<height; y++) {
847         srcpixel=srcbits;
848         dstpixel=dstbits;
849         for (x=0; x<width; x++) {
850             WORD srcval;
851             srcval=*srcpixel++;
852             *dstpixel++=((srcval >>  8) & 0x0000f8) | /* h */
853                         ((srcval >> 13) & 0x000007) | /* h - 3 bits */
854                         ((srcval <<  5) & 0x00fc00) | /* g */
855                         ((srcval >>  1) & 0x000300) | /* g - 2 bits */
856                         ((srcval << 19) & 0xf80000) | /* l */
857                         ((srcval << 14) & 0x070000);  /* l - 3 bits */
858         }
859         srcbits = (char*)srcbits + srclinebytes;
860         dstbits = (char*)dstbits + dstlinebytes;
861     }
862 }
863
864 /*
865  * 24 bit conversions
866  */
867
868 static void X11DRV_DIB_Convert_888_reverse(int width, int height,
869                                     const void* srcbits, int srclinebytes,
870                                     void* dstbits, int dstlinebytes)
871 {
872     const BYTE* srcpixel;
873     BYTE* dstpixel;
874     int x,y;
875
876     for (y=0; y<height; y++) {
877         srcpixel=srcbits;
878         dstpixel=dstbits;
879         for (x=0; x<width; x++) {
880             dstpixel[0]=srcpixel[2];
881             dstpixel[1]=srcpixel[1];
882             dstpixel[2]=srcpixel[0];
883             srcpixel+=3;
884             dstpixel+=3;
885         }
886         srcbits = (char*)srcbits + srclinebytes;
887         dstbits = (char*)dstbits + dstlinebytes;
888     }
889 }
890
891 static void X11DRV_DIB_Convert_888_to_555_asis(int width, int height,
892                                     const void* srcbits, int srclinebytes,
893                                     void* dstbits, int dstlinebytes)
894 {
895     const DWORD* srcpixel;
896     const BYTE* srcbyte;
897     WORD* dstpixel;
898     int x,y;
899     int oddwidth;
900
901     oddwidth=width & 3;
902     width=width/4;
903     for (y=0; y<height; y++) {
904         srcpixel=srcbits;
905         dstpixel=dstbits;
906         for (x=0; x<width; x++) {
907             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
908             DWORD srcval1,srcval2;
909             srcval1=srcpixel[0];
910             dstpixel[0]=((srcval1 >>  3) & 0x001f) | /* l1 */
911                         ((srcval1 >>  6) & 0x03e0) | /* g1 */
912                         ((srcval1 >>  9) & 0x7c00);  /* h1 */
913             srcval2=srcpixel[1];
914             dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
915                         ((srcval2 <<  2) & 0x03e0) | /* g2 */
916                         ((srcval2 >>  1) & 0x7c00);  /* h2 */
917             srcval1=srcpixel[2];
918             dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
919                         ((srcval2 >> 22) & 0x03e0) | /* g3 */
920                         ((srcval1 <<  7) & 0x7c00);  /* h3 */
921             dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
922                         ((srcval1 >> 14) & 0x03e0) | /* g4 */
923                         ((srcval1 >> 17) & 0x7c00);  /* h4 */
924             srcpixel+=3;
925             dstpixel+=4;
926         }
927         /* And now up to 3 odd pixels */
928         srcbyte=(LPBYTE)srcpixel;
929         for (x=0; x<oddwidth; x++) {
930             WORD dstval;
931             dstval =((srcbyte[0] >> 3) & 0x001f);    /* l */
932             dstval|=((srcbyte[1] << 2) & 0x03e0);    /* g */
933             dstval|=((srcbyte[2] << 7) & 0x7c00);    /* h */
934             *dstpixel++=dstval;
935             srcbyte+=3;
936         }
937         srcbits = (char*)srcbits + srclinebytes;
938         dstbits = (char*)dstbits + dstlinebytes;
939     }
940 }
941
942 static void X11DRV_DIB_Convert_888_to_555_reverse(int width, int height,
943                                     const void* srcbits, int srclinebytes,
944                                     void* dstbits, int dstlinebytes)
945 {
946     const DWORD* srcpixel;
947     const BYTE* srcbyte;
948     WORD* dstpixel;
949     int x,y;
950     int oddwidth;
951
952     oddwidth=width & 3;
953     width=width/4;
954     for (y=0; y<height; y++) {
955         srcpixel=srcbits;
956         dstpixel=dstbits;
957         for (x=0; x<width; x++) {
958             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
959             DWORD srcval1,srcval2;
960             srcval1=srcpixel[0];
961             dstpixel[0]=((srcval1 <<  7) & 0x7c00) | /* l1 */
962                         ((srcval1 >>  6) & 0x03e0) | /* g1 */
963                         ((srcval1 >> 19) & 0x001f);  /* h1 */
964             srcval2=srcpixel[1];
965             dstpixel[1]=((srcval1 >> 17) & 0x7c00) | /* l2 */
966                         ((srcval2 <<  2) & 0x03e0) | /* g2 */
967                         ((srcval2 >> 11) & 0x001f);  /* h2 */
968             srcval1=srcpixel[2];
969             dstpixel[2]=((srcval2 >>  9) & 0x7c00) | /* l3 */
970                         ((srcval2 >> 22) & 0x03e0) | /* g3 */
971                         ((srcval1 >>  3) & 0x001f);  /* h3 */
972             dstpixel[3]=((srcval1 >>  1) & 0x7c00) | /* l4 */
973                         ((srcval1 >> 14) & 0x03e0) | /* g4 */
974                         ((srcval1 >> 27) & 0x001f);  /* h4 */
975             srcpixel+=3;
976             dstpixel+=4;
977         }
978         /* And now up to 3 odd pixels */
979         srcbyte=(LPBYTE)srcpixel;
980         for (x=0; x<oddwidth; x++) {
981             WORD dstval;
982             dstval =((srcbyte[0] << 7) & 0x7c00);    /* l */
983             dstval|=((srcbyte[1] << 2) & 0x03e0);    /* g */
984             dstval|=((srcbyte[2] >> 3) & 0x001f);    /* h */
985             *dstpixel++=dstval;
986             srcbyte+=3;
987         }
988         srcbits = (char*)srcbits + srclinebytes;
989         dstbits = (char*)dstbits + dstlinebytes;
990     }
991 }
992
993 static void X11DRV_DIB_Convert_888_to_565_asis(int width, int height,
994                                     const void* srcbits, int srclinebytes,
995                                     void* dstbits, int dstlinebytes)
996 {
997     const DWORD* srcpixel;
998     const BYTE* srcbyte;
999     WORD* dstpixel;
1000     int x,y;
1001     int oddwidth;
1002
1003     oddwidth=width & 3;
1004     width=width/4;
1005     for (y=0; y<height; y++) {
1006         srcpixel=srcbits;
1007         dstpixel=dstbits;
1008         for (x=0; x<width; x++) {
1009             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1010             DWORD srcval1,srcval2;
1011             srcval1=srcpixel[0];
1012             dstpixel[0]=((srcval1 >>  3) & 0x001f) | /* l1 */
1013                         ((srcval1 >>  5) & 0x07e0) | /* g1 */
1014                         ((srcval1 >>  8) & 0xf800);  /* h1 */
1015             srcval2=srcpixel[1];
1016             dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
1017                         ((srcval2 <<  3) & 0x07e0) | /* g2 */
1018                         ( srcval2        & 0xf800);  /* h2 */
1019             srcval1=srcpixel[2];
1020             dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
1021                         ((srcval2 >> 21) & 0x07e0) | /* g3 */
1022                         ((srcval1 <<  8) & 0xf800);  /* h3 */
1023             dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
1024                         ((srcval1 >> 13) & 0x07e0) | /* g4 */
1025                         ((srcval1 >> 16) & 0xf800);  /* h4 */
1026             srcpixel+=3;
1027             dstpixel+=4;
1028         }
1029         /* And now up to 3 odd pixels */
1030         srcbyte=(LPBYTE)srcpixel;
1031         for (x=0; x<oddwidth; x++) {
1032             WORD dstval;
1033             dstval =((srcbyte[0] >> 3) & 0x001f);    /* l */
1034             dstval|=((srcbyte[1] << 3) & 0x07e0);    /* g */
1035             dstval|=((srcbyte[2] << 8) & 0xf800);    /* h */
1036             *dstpixel++=dstval;
1037             srcbyte+=3;
1038         }
1039         srcbits = (char*)srcbits + srclinebytes;
1040         dstbits = (char*)dstbits + dstlinebytes;
1041     }
1042 }
1043
1044 static void X11DRV_DIB_Convert_888_to_565_reverse(int width, int height,
1045                                     const void* srcbits, int srclinebytes,
1046                                     void* dstbits, int dstlinebytes)
1047 {
1048     const DWORD* srcpixel;
1049     const BYTE* srcbyte;
1050     WORD* dstpixel;
1051     int x,y;
1052     int oddwidth;
1053
1054     oddwidth=width & 3;
1055     width=width/4;
1056     for (y=0; y<height; y++) {
1057         srcpixel=srcbits;
1058         dstpixel=dstbits;
1059         for (x=0; x<width; x++) {
1060             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1061             DWORD srcval1,srcval2;
1062             srcval1=srcpixel[0];
1063             dstpixel[0]=((srcval1 <<  8) & 0xf800) | /* l1 */
1064                         ((srcval1 >>  5) & 0x07e0) | /* g1 */
1065                         ((srcval1 >> 19) & 0x001f);  /* h1 */
1066             srcval2=srcpixel[1];
1067             dstpixel[1]=((srcval1 >> 16) & 0xf800) | /* l2 */
1068                         ((srcval2 <<  3) & 0x07e0) | /* g2 */
1069                         ((srcval2 >> 11) & 0x001f);  /* h2 */
1070             srcval1=srcpixel[2];
1071             dstpixel[2]=((srcval2 >>  8) & 0xf800) | /* l3 */
1072                         ((srcval2 >> 21) & 0x07e0) | /* g3 */
1073                         ((srcval1 >>  3) & 0x001f);  /* h3 */
1074             dstpixel[3]=(srcval1         & 0xf800) | /* l4 */
1075                         ((srcval1 >> 13) & 0x07e0) | /* g4 */
1076                         ((srcval1 >> 27) & 0x001f);  /* h4 */
1077             srcpixel+=3;
1078             dstpixel+=4;
1079         }
1080         /* And now up to 3 odd pixels */
1081         srcbyte=(LPBYTE)srcpixel;
1082         for (x=0; x<oddwidth; x++) {
1083             WORD dstval;
1084             dstval =((srcbyte[0] << 8) & 0xf800);    /* l */
1085             dstval|=((srcbyte[1] << 3) & 0x07e0);    /* g */
1086             dstval|=((srcbyte[2] >> 3) & 0x001f);    /* h */
1087             *dstpixel++=dstval;
1088             srcbyte+=3;
1089         }
1090         srcbits = (char*)srcbits + srclinebytes;
1091         dstbits = (char*)dstbits + dstlinebytes;
1092     }
1093 }
1094
1095 static void X11DRV_DIB_Convert_888_to_0888_asis(int width, int height,
1096                                     const void* srcbits, int srclinebytes,
1097                                     void* dstbits, int dstlinebytes)
1098 {
1099     const DWORD* srcpixel;
1100     DWORD* dstpixel;
1101     int x,y;
1102     int oddwidth;
1103
1104     oddwidth=width & 3;
1105     width=width/4;
1106     for (y=0; y<height; y++) {
1107         srcpixel=srcbits;
1108         dstpixel=dstbits;
1109         for (x=0; x<width; x++) {
1110             /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1111             DWORD srcval1,srcval2;
1112             srcval1=srcpixel[0];
1113             dstpixel[0]=( srcval1        & 0x00ffffff);  /* h1, g1, l1 */
1114             srcval2=srcpixel[1];
1115             dstpixel[1]=( srcval1 >> 24) |              /* l2 */
1116                         ((srcval2 <<  8) & 0x00ffff00); /* h2, g2 */
1117             srcval1=srcpixel[2];
1118             dstpixel[2]=( srcval2 >> 16) |              /* g3, l3 */
1119                         ((srcval1 << 16) & 0x00ff0000); /* h3 */
1120             dstpixel[3]=( srcval1 >>  8);               /* h4, g4, l4 */
1121             srcpixel+=3;
1122             dstpixel+=4;
1123         }
1124         /* And now up to 3 odd pixels */
1125         for (x=0; x<oddwidth; x++) {
1126             DWORD srcval;
1127             srcval=*srcpixel;
1128             srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1129             *dstpixel++=( srcval         & 0x00ffffff); /* h, g, l */
1130         }
1131         srcbits = (char*)srcbits + srclinebytes;
1132         dstbits = (char*)dstbits + dstlinebytes;
1133     }
1134 }
1135
1136 static void X11DRV_DIB_Convert_888_to_0888_reverse(int width, int height,
1137                                     const void* srcbits, int srclinebytes,
1138                                     void* dstbits, int dstlinebytes)
1139 {
1140     const DWORD* srcpixel;
1141     DWORD* dstpixel;
1142     int x,y;
1143     int oddwidth;
1144
1145     oddwidth=width & 3;
1146     width=width/4;
1147     for (y=0; y<height; y++) {
1148         srcpixel=srcbits;
1149         dstpixel=dstbits;
1150         for (x=0; x<width; x++) {
1151             /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1152             DWORD srcval1,srcval2;
1153
1154             srcval1=srcpixel[0];
1155             dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */
1156                         ( srcval1        & 0x00ff00) | /* g1 */
1157                         ((srcval1 << 16) & 0xff0000);  /* l1 */
1158             srcval2=srcpixel[1];
1159             dstpixel[1]=((srcval1 >>  8) & 0xff0000) | /* l2 */
1160                         ((srcval2 <<  8) & 0x00ff00) | /* g2 */
1161                         ((srcval2 >>  8) & 0x0000ff);  /* h2 */
1162             srcval1=srcpixel[2];
1163             dstpixel[2]=( srcval2        & 0xff0000) | /* l3 */
1164                         ((srcval2 >> 16) & 0x00ff00) | /* g3 */
1165                         ( srcval1        & 0x0000ff);  /* h3 */
1166             dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */
1167                         ((srcval1 >>  8) & 0x00ff00) | /* g4 */
1168                         ((srcval1 <<  8) & 0xff0000);  /* l4 */
1169             srcpixel+=3;
1170             dstpixel+=4;
1171         }
1172         /* And now up to 3 odd pixels */
1173         for (x=0; x<oddwidth; x++) {
1174             DWORD srcval;
1175             srcval=*srcpixel;
1176             srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1177             *dstpixel++=((srcval  >> 16) & 0x0000ff) | /* h */
1178                         ( srcval         & 0x00ff00) | /* g */
1179                         ((srcval  << 16) & 0xff0000);  /* l */
1180         }
1181         srcbits = (char*)srcbits + srclinebytes;
1182         dstbits = (char*)dstbits + dstlinebytes;
1183     }
1184 }
1185
1186 static void X11DRV_DIB_Convert_rgb888_to_any0888(int width, int height,
1187                                     const void* srcbits, int srclinebytes,
1188                                     void* dstbits, int dstlinebytes,
1189                                     DWORD rdst, DWORD gdst, DWORD bdst)
1190 {
1191     int rLeftShift,gLeftShift,bLeftShift;
1192     const BYTE* srcpixel;
1193     DWORD* dstpixel;
1194     int x,y;
1195
1196     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1197     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1198     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1199     for (y=0; y<height; y++) {
1200         srcpixel=srcbits;
1201         dstpixel=dstbits;
1202         for (x=0; x<width; x++) {
1203             *dstpixel++=(srcpixel[0] << bLeftShift) | /* b */
1204                         (srcpixel[1] << gLeftShift) | /* g */
1205                         (srcpixel[2] << rLeftShift);  /* r */
1206             srcpixel+=3;
1207         }
1208         srcbits = (char*)srcbits + srclinebytes;
1209         dstbits = (char*)dstbits + dstlinebytes;
1210     }
1211 }
1212
1213 static void X11DRV_DIB_Convert_bgr888_to_any0888(int width, int height,
1214                                     const void* srcbits, int srclinebytes,
1215                                     void* dstbits, int dstlinebytes,
1216                                     DWORD rdst, DWORD gdst, DWORD bdst)
1217 {
1218     int rLeftShift,gLeftShift,bLeftShift;
1219     const BYTE* srcpixel;
1220     DWORD* dstpixel;
1221     int x,y;
1222
1223     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1224     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1225     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1226     for (y=0; y<height; y++) {
1227         srcpixel=srcbits;
1228         dstpixel=dstbits;
1229         for (x=0; x<width; x++) {
1230             *dstpixel++=(srcpixel[0] << rLeftShift) | /* r */
1231                         (srcpixel[1] << gLeftShift) | /* g */
1232                         (srcpixel[2] << bLeftShift);  /* b */
1233             srcpixel+=3;
1234         }
1235         srcbits = (char*)srcbits + srclinebytes;
1236         dstbits = (char*)dstbits + dstlinebytes;
1237     }
1238 }
1239
1240 /*
1241  * 32 bit conversions
1242  */
1243
1244 static void X11DRV_DIB_Convert_0888_reverse(int width, int height,
1245                                     const void* srcbits, int srclinebytes,
1246                                     void* dstbits, int dstlinebytes)
1247 {
1248     const DWORD* srcpixel;
1249     DWORD* dstpixel;
1250     int x,y;
1251
1252     for (y=0; y<height; y++) {
1253         srcpixel=srcbits;
1254         dstpixel=dstbits;
1255         for (x=0; x<width; x++) {
1256             DWORD srcval;
1257             srcval=*srcpixel++;
1258             *dstpixel++=((srcval << 16) & 0x00ff0000) | /* h */
1259                         ( srcval        & 0x0000ff00) | /* g */
1260                         ((srcval >> 16) & 0x000000ff);  /* l */
1261         }
1262         srcbits = (char*)srcbits + srclinebytes;
1263         dstbits = (char*)dstbits + dstlinebytes;
1264     }
1265 }
1266
1267 static void X11DRV_DIB_Convert_0888_any(int width, int height,
1268                                     const void* srcbits, int srclinebytes,
1269                                     DWORD rsrc, DWORD gsrc, DWORD bsrc,
1270                                     void* dstbits, int dstlinebytes,
1271                                     DWORD rdst, DWORD gdst, DWORD bdst)
1272 {
1273     int rRightShift,gRightShift,bRightShift;
1274     int rLeftShift,gLeftShift,bLeftShift;
1275     const DWORD* srcpixel;
1276     DWORD* dstpixel;
1277     int x,y;
1278
1279     rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1280     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1281     bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1282     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1283     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1284     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1285     for (y=0; y<height; y++) {
1286         srcpixel=srcbits;
1287         dstpixel=dstbits;
1288         for (x=0; x<width; x++) {
1289             DWORD srcval;
1290             srcval=*srcpixel++;
1291             *dstpixel++=(((srcval >> rRightShift) & 0xff) << rLeftShift) |
1292                         (((srcval >> gRightShift) & 0xff) << gLeftShift) |
1293                         (((srcval >> bRightShift) & 0xff) << bLeftShift);
1294         }
1295         srcbits = (char*)srcbits + srclinebytes;
1296         dstbits = (char*)dstbits + dstlinebytes;
1297     }
1298 }
1299
1300 static void X11DRV_DIB_Convert_0888_to_555_asis(int width, int height,
1301                                     const void* srcbits, int srclinebytes,
1302                                     void* dstbits, int dstlinebytes)
1303 {
1304     const DWORD* srcpixel;
1305     WORD* dstpixel;
1306     int x,y;
1307
1308     for (y=0; y<height; y++) {
1309         srcpixel=srcbits;
1310         dstpixel=dstbits;
1311         for (x=0; x<width; x++) {
1312             DWORD srcval;
1313             srcval=*srcpixel++;
1314             *dstpixel++=((srcval >> 9) & 0x7c00) | /* h */
1315                         ((srcval >> 6) & 0x03e0) | /* g */
1316                         ((srcval >> 3) & 0x001f);  /* l */
1317         }
1318         srcbits = (char*)srcbits + srclinebytes;
1319         dstbits = (char*)dstbits + dstlinebytes;
1320     }
1321 }
1322
1323 static void X11DRV_DIB_Convert_0888_to_555_reverse(int width, int height,
1324                                     const void* srcbits, int srclinebytes,
1325                                     void* dstbits, int dstlinebytes)
1326 {
1327     const DWORD* srcpixel;
1328     WORD* dstpixel;
1329     int x,y;
1330
1331     for (y=0; y<height; y++) {
1332         srcpixel=srcbits;
1333         dstpixel=dstbits;
1334         for (x=0; x<width; x++) {
1335             DWORD srcval;
1336             srcval=*srcpixel++;
1337             *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1338                         ((srcval >>  6) & 0x03e0) | /* g */
1339                         ((srcval <<  7) & 0x7c00);  /* l */
1340         }
1341         srcbits = (char*)srcbits + srclinebytes;
1342         dstbits = (char*)dstbits + dstlinebytes;
1343     }
1344 }
1345
1346 static void X11DRV_DIB_Convert_0888_to_565_asis(int width, int height,
1347                                     const void* srcbits, int srclinebytes,
1348                                     void* dstbits, int dstlinebytes)
1349 {
1350     const DWORD* srcpixel;
1351     WORD* dstpixel;
1352     int x,y;
1353
1354     for (y=0; y<height; y++) {
1355         srcpixel=srcbits;
1356         dstpixel=dstbits;
1357         for (x=0; x<width; x++) {
1358             DWORD srcval;
1359             srcval=*srcpixel++;
1360             *dstpixel++=((srcval >> 8) & 0xf800) | /* h */
1361                         ((srcval >> 5) & 0x07e0) | /* g */
1362                         ((srcval >> 3) & 0x001f);  /* l */
1363         }
1364         srcbits = (char*)srcbits + srclinebytes;
1365         dstbits = (char*)dstbits + dstlinebytes;
1366     }
1367 }
1368
1369 static void X11DRV_DIB_Convert_0888_to_565_reverse(int width, int height,
1370                                     const void* srcbits, int srclinebytes,
1371                                     void* dstbits, int dstlinebytes)
1372 {
1373     const DWORD* srcpixel;
1374     WORD* dstpixel;
1375     int x,y;
1376
1377     for (y=0; y<height; y++) {
1378         srcpixel=srcbits;
1379         dstpixel=dstbits;
1380         for (x=0; x<width; x++) {
1381             DWORD srcval;
1382             srcval=*srcpixel++;
1383             *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1384                         ((srcval >>  5) & 0x07e0) | /* g */
1385                         ((srcval <<  8) & 0xf800);  /* l */
1386         }
1387         srcbits = (char*)srcbits + srclinebytes;
1388         dstbits = (char*)dstbits + dstlinebytes;
1389     }
1390 }
1391
1392 static void X11DRV_DIB_Convert_any0888_to_5x5(int width, int height,
1393                                     const void* srcbits, int srclinebytes,
1394                                     DWORD rsrc, DWORD gsrc, DWORD bsrc,
1395                                     void* dstbits, int dstlinebytes,
1396                                     WORD rdst, WORD gdst, WORD bdst)
1397 {
1398     int rRightShift,gRightShift,bRightShift;
1399     int rLeftShift,gLeftShift,bLeftShift;
1400     const DWORD* srcpixel;
1401     WORD* dstpixel;
1402     int x,y;
1403
1404     /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel
1405      * contains 0x11223344.
1406      * - first we shift 0x11223344 right by rRightShift to bring the most
1407      *   significant bits of the red components in the bottom 5 (or 6) bits
1408      *   -> 0x4488c
1409      * - then we remove non red bits by anding with the modified rdst (0x1f)
1410      *   -> 0x0c
1411      * - finally shift these bits left by rLeftShift so that they end up in
1412      *   the right place
1413      *   -> 0x3000
1414      */
1415     rRightShift=X11DRV_DIB_MaskToShift(rsrc)+3;
1416     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1417     gRightShift+=(gdst==0x07e0?2:3);
1418     bRightShift=X11DRV_DIB_MaskToShift(bsrc)+3;
1419
1420     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1421     rdst=rdst >> rLeftShift;
1422     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1423     gdst=gdst >> gLeftShift;
1424     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1425     bdst=bdst >> bLeftShift;
1426
1427     for (y=0; y<height; y++) {
1428         srcpixel=srcbits;
1429         dstpixel=dstbits;
1430         for (x=0; x<width; x++) {
1431             DWORD srcval;
1432             srcval=*srcpixel++;
1433             *dstpixel++=(((srcval >> rRightShift) & rdst) << rLeftShift) |
1434                         (((srcval >> gRightShift) & gdst) << gLeftShift) |
1435                         (((srcval >> bRightShift) & bdst) << bLeftShift);
1436         }
1437         srcbits = (char*)srcbits + srclinebytes;
1438         dstbits = (char*)dstbits + dstlinebytes;
1439     }
1440 }
1441
1442 static void X11DRV_DIB_Convert_0888_to_888_asis(int width, int height,
1443                                     const void* srcbits, int srclinebytes,
1444                                     void* dstbits, int dstlinebytes)
1445 {
1446     const DWORD* srcpixel;
1447     DWORD* dstpixel;
1448     BYTE* dstbyte;
1449     int x,y;
1450     int oddwidth;
1451
1452     oddwidth=width & 3;
1453     width=width/4;
1454     for (y=0; y<height; y++) {
1455         srcpixel=srcbits;
1456         dstpixel=dstbits;
1457         for (x=0; x<width; x++) {
1458             /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1459             DWORD srcval;
1460             srcval=((*srcpixel++)       & 0x00ffffff);  /* h1, g1, l1*/
1461             *dstpixel++=srcval | ((*srcpixel)   << 24); /* h2 */
1462             srcval=((*srcpixel++ >> 8 ) & 0x0000ffff);  /* g2, l2 */
1463             *dstpixel++=srcval | ((*srcpixel)   << 16); /* h3, g3 */
1464             srcval=((*srcpixel++ >> 16) & 0x000000ff);  /* l3 */
1465             *dstpixel++=srcval | ((*srcpixel++) << 8);  /* h4, g4, l4 */
1466         }
1467         /* And now up to 3 odd pixels */
1468         dstbyte=(BYTE*)dstpixel;
1469         for (x=0; x<oddwidth; x++) {
1470             DWORD srcval;
1471             srcval=*srcpixel++;
1472             *((WORD*)dstbyte)++=srcval;                 /* h, g */
1473             *dstbyte++=srcval >> 16;                    /* l */
1474         }
1475         srcbits = (char*)srcbits + srclinebytes;
1476         dstbits = (char*)dstbits + dstlinebytes;
1477     }
1478 }
1479
1480 static void X11DRV_DIB_Convert_0888_to_888_reverse(int width, int height,
1481                                     const void* srcbits, int srclinebytes,
1482                                     void* dstbits, int dstlinebytes)
1483 {
1484     const DWORD* srcpixel;
1485     DWORD* dstpixel;
1486     BYTE* dstbyte;
1487     int x,y;
1488     int oddwidth;
1489
1490     oddwidth=width & 3;
1491     width=width/4;
1492     for (y=0; y<height; y++) {
1493         srcpixel=srcbits;
1494         dstpixel=dstbits;
1495         for (x=0; x<width; x++) {
1496             /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1497             DWORD srcval1,srcval2;
1498             srcval1=*srcpixel++;
1499             srcval2=    ((srcval1 >> 16) & 0x000000ff) | /* h1 */
1500                         ( srcval1        & 0x0000ff00) | /* g1 */
1501                         ((srcval1 << 16) & 0x00ff0000);  /* l1 */
1502             srcval1=*srcpixel++;
1503             *dstpixel++=srcval2 |
1504                         ((srcval1 <<  8) & 0xff000000);  /* h2 */
1505             srcval2=    ((srcval1 >>  8) & 0x000000ff) | /* g2 */
1506                         ((srcval1 <<  8) & 0x0000ff00);  /* l2 */
1507             srcval1=*srcpixel++;
1508             *dstpixel++=srcval2 |
1509                         ( srcval1        & 0x00ff0000) | /* h3 */
1510                         ((srcval1 << 16) & 0xff000000);  /* g3 */
1511             srcval2=    ( srcval1        & 0x000000ff);  /* l3 */
1512             srcval1=*srcpixel++;
1513             *dstpixel++=srcval2 |
1514                         ((srcval1 >>  8) & 0x0000ff00) | /* h4 */
1515                         ((srcval1 <<  8) & 0x00ff0000) | /* g4 */
1516                         ( srcval1 << 24);                /* l4 */
1517         }
1518         /* And now up to 3 odd pixels */
1519         dstbyte=(BYTE*)dstpixel;
1520         for (x=0; x<oddwidth; x++) {
1521             DWORD srcval;
1522             srcval=*srcpixel++;
1523             *((WORD*)dstbyte)++=((srcval >> 16) & 0x00ff) | /* h */
1524                                 (srcval         & 0xff00);  /* g */
1525             *dstbyte++=srcval;                              /* l */
1526         }
1527         srcbits = (char*)srcbits + srclinebytes;
1528         dstbits = (char*)dstbits + dstlinebytes;
1529     }
1530 }
1531
1532 static void X11DRV_DIB_Convert_any0888_to_rgb888(int width, int height,
1533                                     const void* srcbits, int srclinebytes,
1534                                     DWORD rsrc, DWORD gsrc, DWORD bsrc,
1535                                     void* dstbits, int dstlinebytes)
1536 {
1537     int rRightShift,gRightShift,bRightShift;
1538     const DWORD* srcpixel;
1539     BYTE* dstpixel;
1540     int x,y;
1541
1542     rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1543     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1544     bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1545     for (y=0; y<height; y++) {
1546         srcpixel=srcbits;
1547         dstpixel=dstbits;
1548         for (x=0; x<width; x++) {
1549             DWORD srcval;
1550             srcval=*srcpixel++;
1551             dstpixel[0]=(srcval >> bRightShift); /* b */
1552             dstpixel[1]=(srcval >> gRightShift); /* g */
1553             dstpixel[2]=(srcval >> rRightShift); /* r */
1554             dstpixel+=3;
1555         }
1556         srcbits = (char*)srcbits + srclinebytes;
1557         dstbits = (char*)dstbits + dstlinebytes;
1558     }
1559 }
1560
1561 static void X11DRV_DIB_Convert_any0888_to_bgr888(int width, int height,
1562                                     const void* srcbits, int srclinebytes,
1563                                     DWORD rsrc, DWORD gsrc, DWORD bsrc,
1564                                     void* dstbits, int dstlinebytes)
1565 {
1566     int rRightShift,gRightShift,bRightShift;
1567     const DWORD* srcpixel;
1568     BYTE* dstpixel;
1569     int x,y;
1570
1571     rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1572     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1573     bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1574     for (y=0; y<height; y++) {
1575         srcpixel=srcbits;
1576         dstpixel=dstbits;
1577         for (x=0; x<width; x++) {
1578             DWORD srcval;
1579             srcval=*srcpixel++;
1580             dstpixel[0]=(srcval >> rRightShift); /* r */
1581             dstpixel[1]=(srcval >> gRightShift); /* g */
1582             dstpixel[2]=(srcval >> bRightShift); /* b */
1583             dstpixel+=3;
1584         }
1585         srcbits = (char*)srcbits + srclinebytes;
1586         dstbits = (char*)dstbits + dstlinebytes;
1587     }
1588 }
1589
1590 /***********************************************************************
1591  *           X11DRV_DIB_SetImageBits_1
1592  *
1593  * SetDIBits for a 1-bit deep DIB.
1594  */
1595 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
1596                                 DWORD srcwidth, DWORD dstwidth, int left,
1597                                 int *colors, XImage *bmpImage, DWORD linebytes)
1598 {
1599     int h;
1600     const BYTE* srcbyte;
1601     BYTE srcval, extra;
1602     DWORD i, x;
1603
1604     if (lines < 0 ) {
1605         lines = -lines;
1606         srcbits = srcbits + linebytes * (lines - 1);
1607         linebytes = -linebytes;
1608     }
1609
1610     if ((extra = (left & 7)) != 0) {
1611         left &= ~7;
1612         dstwidth += extra;
1613     }
1614     srcbits += left >> 3;
1615
1616     /* ==== pal 1 dib -> any bmp format ==== */
1617     for (h = lines-1; h >=0; h--) {
1618         srcbyte=srcbits;
1619         /* FIXME: should avoid putting x<left pixels (minor speed issue) */
1620         for (i = dstwidth/8, x = left; i > 0; i--) {
1621             srcval=*srcbyte++;
1622             XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
1623             XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
1624             XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
1625             XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
1626             XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
1627             XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
1628             XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
1629             XPutPixel( bmpImage, x++, h, colors[ srcval       & 1] );
1630         }
1631         if (dstwidth % 8){
1632             srcval=*srcbyte;
1633             switch (dstwidth & 7)
1634             {
1635             case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1636             case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1637             case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1638             case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1639             case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1640             case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1641             case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1642             }
1643         }
1644         srcbits += linebytes;
1645     }
1646 }
1647
1648 /***********************************************************************
1649  *           X11DRV_DIB_GetImageBits_1
1650  *
1651  * GetDIBits for a 1-bit deep DIB.
1652  */
1653 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1654                                        DWORD dstwidth, DWORD srcwidth,
1655                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
1656                                 XImage *bmpImage, DWORD linebytes )
1657 {
1658     DWORD x;
1659     int h;
1660
1661     if (lines < 0 ) {
1662         lines = -lines;
1663         dstbits = dstbits + linebytes * (lines - 1);
1664         linebytes = -linebytes;
1665     }
1666
1667     switch (bmpImage->depth)
1668     {
1669     case 1:
1670     case 4:
1671         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1672             /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1673             BYTE* dstbyte;
1674
1675             for (h=lines-1; h>=0; h--) {
1676                 BYTE dstval;
1677                 dstbyte=dstbits;
1678                 dstval=0;
1679                 for (x=0; x<dstwidth; x++) {
1680                     PALETTEENTRY srcval;
1681                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
1682                     dstval|=(X11DRV_DIB_GetNearestIndex
1683                              (colors, 2,
1684                               srcval.peRed,
1685                               srcval.peGreen,
1686                               srcval.peBlue) << (7 - (x & 7)));
1687                     if ((x&7)==7) {
1688                         *dstbyte++=dstval;
1689                         dstval=0;
1690                     }
1691                 }
1692                 if ((dstwidth&7)!=0) {
1693                     *dstbyte=dstval;
1694                 }
1695                 dstbits += linebytes;
1696             }
1697         } else {
1698             goto notsupported;
1699         }
1700         break;
1701
1702     case 8:
1703         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1704             /* ==== pal 8 bmp -> pal 1 dib ==== */
1705             const void* srcbits;
1706             const BYTE* srcpixel;
1707             BYTE* dstbyte;
1708
1709             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1710
1711             for (h=0; h<lines; h++) {
1712                 BYTE dstval;
1713                 srcpixel=srcbits;
1714                 dstbyte=dstbits;
1715                 dstval=0;
1716                 for (x=0; x<dstwidth; x++) {
1717                     PALETTEENTRY srcval;
1718                     srcval=srccolors[(int)*srcpixel++];
1719                     dstval|=(X11DRV_DIB_GetNearestIndex
1720                              (colors, 2,
1721                               srcval.peRed,
1722                               srcval.peGreen,
1723                               srcval.peBlue) << (7-(x&7)) );
1724                     if ((x&7)==7) {
1725                         *dstbyte++=dstval;
1726                         dstval=0;
1727                     }
1728                 }
1729                 if ((dstwidth&7)!=0) {
1730                     *dstbyte=dstval;
1731                 }
1732                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1733                 dstbits += linebytes;
1734             }
1735         } else {
1736             goto notsupported;
1737         }
1738         break;
1739
1740     case 15:
1741     case 16:
1742         {
1743             const void* srcbits;
1744             const WORD* srcpixel;
1745             BYTE* dstbyte;
1746
1747             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1748
1749             if (bmpImage->green_mask==0x03e0) {
1750                 if (bmpImage->red_mask==0x7c00) {
1751                     /* ==== rgb 555 bmp -> pal 1 dib ==== */
1752                     for (h=0; h<lines; h++) {
1753                         BYTE dstval;
1754                         srcpixel=srcbits;
1755                         dstbyte=dstbits;
1756                         dstval=0;
1757                         for (x=0; x<dstwidth; x++) {
1758                             WORD srcval;
1759                             srcval=*srcpixel++;
1760                             dstval|=(X11DRV_DIB_GetNearestIndex
1761                                      (colors, 2,
1762                                       ((srcval >>  7) & 0xf8) | /* r */
1763                                       ((srcval >> 12) & 0x07),
1764                                       ((srcval >>  2) & 0xf8) | /* g */
1765                                       ((srcval >>  7) & 0x07),
1766                                       ((srcval <<  3) & 0xf8) | /* b */
1767                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
1768                             if ((x&7)==7) {
1769                                 *dstbyte++=dstval;
1770                                 dstval=0;
1771                             }
1772                         }
1773                         if ((dstwidth&7)!=0) {
1774                             *dstbyte=dstval;
1775                         }
1776                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1777                         dstbits += linebytes;
1778                     }
1779                 } else if (bmpImage->blue_mask==0x7c00) {
1780                     /* ==== bgr 555 bmp -> pal 1 dib ==== */
1781                     for (h=0; h<lines; h++) {
1782                         WORD dstval;
1783                         srcpixel=srcbits;
1784                         dstbyte=dstbits;
1785                         dstval=0;
1786                         for (x=0; x<dstwidth; x++) {
1787                             BYTE srcval;
1788                             srcval=*srcpixel++;
1789                             dstval|=(X11DRV_DIB_GetNearestIndex
1790                                      (colors, 2,
1791                                       ((srcval <<  3) & 0xf8) | /* r */
1792                                       ((srcval >>  2) & 0x07),
1793                                       ((srcval >>  2) & 0xf8) | /* g */
1794                                       ((srcval >>  7) & 0x07),
1795                                       ((srcval >>  7) & 0xf8) | /* b */
1796                                       ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1797                             if ((x&7)==7) {
1798                                 *dstbyte++=dstval;
1799                                 dstval=0;
1800                             }
1801                         }
1802                         if ((dstwidth&7)!=0) {
1803                             *dstbyte=dstval;
1804                         }
1805                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1806                         dstbits += linebytes;
1807                     }
1808                 } else {
1809                     goto notsupported;
1810                 }
1811             } else if (bmpImage->green_mask==0x07e0) {
1812                 if (bmpImage->red_mask==0xf800) {
1813                     /* ==== rgb 565 bmp -> pal 1 dib ==== */
1814                     for (h=0; h<lines; h++) {
1815                         BYTE dstval;
1816                         srcpixel=srcbits;
1817                         dstbyte=dstbits;
1818                         dstval=0;
1819                         for (x=0; x<dstwidth; x++) {
1820                             WORD srcval;
1821                             srcval=*srcpixel++;
1822                             dstval|=(X11DRV_DIB_GetNearestIndex
1823                                      (colors, 2,
1824                                       ((srcval >>  8) & 0xf8) | /* r */
1825                                       ((srcval >> 13) & 0x07),
1826                                       ((srcval >>  3) & 0xfc) | /* g */
1827                                       ((srcval >>  9) & 0x03),
1828                                       ((srcval <<  3) & 0xf8) | /* b */
1829                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
1830                             if ((x&7)==7) {
1831                                 *dstbyte++=dstval;
1832                                 dstval=0;
1833                             }
1834                         }
1835                         if ((dstwidth&7)!=0) {
1836                             *dstbyte=dstval;
1837                         }
1838                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1839                         dstbits += linebytes;
1840                     }
1841                 } else if (bmpImage->blue_mask==0xf800) {
1842                     /* ==== bgr 565 bmp -> pal 1 dib ==== */
1843                     for (h=0; h<lines; h++) {
1844                         BYTE dstval;
1845                         srcpixel=srcbits;
1846                         dstbyte=dstbits;
1847                         dstval=0;
1848                         for (x=0; x<dstwidth; x++) {
1849                             WORD srcval;
1850                             srcval=*srcpixel++;
1851                             dstval|=(X11DRV_DIB_GetNearestIndex
1852                                      (colors, 2,
1853                                       ((srcval <<  3) & 0xf8) | /* r */
1854                                       ((srcval >>  2) & 0x07),
1855                                       ((srcval >>  3) & 0xfc) | /* g */
1856                                       ((srcval >>  9) & 0x03),
1857                                       ((srcval >>  8) & 0xf8) | /* b */
1858                                       ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1859                             if ((x&7)==7) {
1860                                 *dstbyte++=dstval;
1861                                 dstval=0;
1862                             }
1863                         }
1864                         if ((dstwidth&7)!=0) {
1865                             *dstbyte=dstval;
1866                         }
1867                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1868                         dstbits += linebytes;
1869                     }
1870                 } else {
1871                     goto notsupported;
1872                 }
1873             } else {
1874                 goto notsupported;
1875             }
1876         }
1877         break;
1878
1879     case 24:
1880     case 32:
1881         {
1882             const void* srcbits;
1883             const BYTE *srcbyte;
1884             BYTE* dstbyte;
1885             int bytes_per_pixel;
1886
1887             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1888             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1889
1890             if (bmpImage->green_mask!=0x00ff00 ||
1891                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1892                 goto notsupported;
1893             } else if (bmpImage->blue_mask==0xff) {
1894                 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1895                 for (h=0; h<lines; h++) {
1896                     BYTE dstval;
1897                     srcbyte=srcbits;
1898                     dstbyte=dstbits;
1899                     dstval=0;
1900                     for (x=0; x<dstwidth; x++) {
1901                         dstval|=(X11DRV_DIB_GetNearestIndex
1902                                  (colors, 2,
1903                                   srcbyte[2],
1904                                   srcbyte[1],
1905                                   srcbyte[0]) << (7-(x&7)) );
1906                         srcbyte+=bytes_per_pixel;
1907                         if ((x&7)==7) {
1908                             *dstbyte++=dstval;
1909                             dstval=0;
1910                         }
1911                     }
1912                     if ((dstwidth&7)!=0) {
1913                         *dstbyte=dstval;
1914                     }
1915                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1916                     dstbits += linebytes;
1917                 }
1918             } else {
1919                 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1920                 for (h=0; h<lines; h++) {
1921                     BYTE dstval;
1922                     srcbyte=srcbits;
1923                     dstbyte=dstbits;
1924                     dstval=0;
1925                     for (x=0; x<dstwidth; x++) {
1926                         dstval|=(X11DRV_DIB_GetNearestIndex
1927                                  (colors, 2,
1928                                   srcbyte[0],
1929                                   srcbyte[1],
1930                                   srcbyte[2]) << (7-(x&7)) );
1931                         srcbyte+=bytes_per_pixel;
1932                         if ((x&7)==7) {
1933                             *dstbyte++=dstval;
1934                             dstval=0;
1935                         }
1936                     }
1937                     if ((dstwidth&7)!=0) {
1938                         *dstbyte=dstval;
1939                     }
1940                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1941                     dstbits += linebytes;
1942                 }
1943             }
1944         }
1945         break;
1946
1947     default:
1948     notsupported:
1949         {
1950             BYTE* dstbyte;
1951             unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1952
1953             /* ==== any bmp format -> pal 1 dib ==== */
1954             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1955                   bmpImage->bits_per_pixel, bmpImage->red_mask,
1956                   bmpImage->green_mask, bmpImage->blue_mask );
1957
1958             for (h=lines-1; h>=0; h--) {
1959                 BYTE dstval;
1960                 dstbyte=dstbits;
1961                 dstval=0;
1962                 for (x=0; x<dstwidth; x++) {
1963                     dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1964                     if ((x&7)==7) {
1965                         *dstbyte++=dstval;
1966                         dstval=0;
1967                     }
1968                 }
1969                 if ((dstwidth&7)!=0) {
1970                     *dstbyte=dstval;
1971                 }
1972                 dstbits += linebytes;
1973             }
1974         }
1975         break;
1976     }
1977 }
1978
1979 /***********************************************************************
1980  *           X11DRV_DIB_SetImageBits_4
1981  *
1982  * SetDIBits for a 4-bit deep DIB.
1983  */
1984 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1985                                 DWORD srcwidth, DWORD dstwidth, int left,
1986                                 int *colors, XImage *bmpImage, DWORD linebytes)
1987 {
1988     int h;
1989     const BYTE* srcbyte;
1990     DWORD i, x;
1991
1992     if (lines < 0 ) {
1993         lines = -lines;
1994         srcbits = srcbits + linebytes * (lines - 1);
1995         linebytes = -linebytes;
1996     }
1997
1998     if (left & 1) {
1999         left--;
2000         dstwidth++;
2001     }
2002     srcbits += left >> 1;
2003
2004     /* ==== pal 4 dib -> any bmp format ==== */
2005     for (h = lines-1; h >= 0; h--) {
2006         srcbyte=srcbits;
2007         for (i = dstwidth/2, x = left; i > 0; i--) {
2008             BYTE srcval=*srcbyte++;
2009             XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
2010             XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
2011         }
2012         if (dstwidth & 1)
2013             XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
2014         srcbits += linebytes;
2015     }
2016 }
2017
2018
2019
2020 /***********************************************************************
2021  *           X11DRV_DIB_GetImageBits_4
2022  *
2023  * GetDIBits for a 4-bit deep DIB.
2024  */
2025 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
2026                                        DWORD srcwidth, DWORD dstwidth,
2027                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
2028                                        XImage *bmpImage, DWORD linebytes )
2029 {
2030     DWORD x;
2031     int h;
2032     BYTE *bits;
2033
2034     if (lines < 0 )
2035     {
2036        lines = -lines;
2037        dstbits = dstbits + ( linebytes * (lines-1) );
2038        linebytes = -linebytes;
2039     }
2040
2041     bits = dstbits;
2042
2043     switch (bmpImage->depth) {
2044     case 1:
2045     case 4:
2046         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2047             /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2048             BYTE* dstbyte;
2049
2050             for (h = lines-1; h >= 0; h--) {
2051                 BYTE dstval;
2052                 dstbyte=dstbits;
2053                 dstval=0;
2054                 for (x = 0; x < dstwidth; x++) {
2055                     PALETTEENTRY srcval;
2056                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2057                     dstval|=(X11DRV_DIB_GetNearestIndex
2058                              (colors, 16,
2059                               srcval.peRed,
2060                               srcval.peGreen,
2061                               srcval.peBlue) << (4-((x&1)<<2)));
2062                     if ((x&1)==1) {
2063                         *dstbyte++=dstval;
2064                         dstval=0;
2065                     }
2066                 }
2067                 if ((dstwidth&1)!=0) {
2068                     *dstbyte=dstval;
2069                 }
2070                 dstbits += linebytes;
2071             }
2072         } else {
2073             goto notsupported;
2074         }
2075         break;
2076
2077     case 8:
2078         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2079             /* ==== pal 8 bmp -> pal 4 dib ==== */
2080             const void* srcbits;
2081             const BYTE *srcpixel;
2082             BYTE* dstbyte;
2083
2084             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2085             for (h=0; h<lines; h++) {
2086                 BYTE dstval;
2087                 srcpixel=srcbits;
2088                 dstbyte=dstbits;
2089                 dstval=0;
2090                 for (x=0; x<dstwidth; x++) {
2091                     PALETTEENTRY srcval;
2092                     srcval = srccolors[(int)*srcpixel++];
2093                     dstval|=(X11DRV_DIB_GetNearestIndex
2094                              (colors, 16,
2095                               srcval.peRed,
2096                               srcval.peGreen,
2097                               srcval.peBlue) << (4*(1-(x&1))) );
2098                     if ((x&1)==1) {
2099                         *dstbyte++=dstval;
2100                         dstval=0;
2101                     }
2102                 }
2103                 if ((dstwidth&1)!=0) {
2104                     *dstbyte=dstval;
2105                 }
2106                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2107                 dstbits += linebytes;
2108             }
2109         } else {
2110             goto notsupported;
2111         }
2112         break;
2113
2114     case 15:
2115     case 16:
2116         {
2117             const void* srcbits;
2118             const WORD* srcpixel;
2119             BYTE* dstbyte;
2120
2121             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2122
2123             if (bmpImage->green_mask==0x03e0) {
2124                 if (bmpImage->red_mask==0x7c00) {
2125                     /* ==== rgb 555 bmp -> pal 4 dib ==== */
2126                     for (h=0; h<lines; h++) {
2127                         BYTE dstval;
2128                         srcpixel=srcbits;
2129                         dstbyte=dstbits;
2130                         dstval=0;
2131                         for (x=0; x<dstwidth; x++) {
2132                             WORD srcval;
2133                             srcval=*srcpixel++;
2134                             dstval|=(X11DRV_DIB_GetNearestIndex
2135                                      (colors, 16,
2136                                       ((srcval >>  7) & 0xf8) | /* r */
2137                                       ((srcval >> 12) & 0x07),
2138                                       ((srcval >>  2) & 0xf8) | /* g */
2139                                       ((srcval >>  7) & 0x07),
2140                                       ((srcval <<  3) & 0xf8) | /* b */
2141                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
2142                             if ((x&1)==1) {
2143                                 *dstbyte++=dstval;
2144                                 dstval=0;
2145                             }
2146                         }
2147                         if ((dstwidth&1)!=0) {
2148                             *dstbyte=dstval;
2149                         }
2150                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2151                         dstbits += linebytes;
2152                     }
2153                 } else if (bmpImage->blue_mask==0x7c00) {
2154                     /* ==== bgr 555 bmp -> pal 4 dib ==== */
2155                     for (h=0; h<lines; h++) {
2156                         WORD dstval;
2157                         srcpixel=srcbits;
2158                         dstbyte=dstbits;
2159                         dstval=0;
2160                         for (x=0; x<dstwidth; x++) {
2161                             WORD srcval;
2162                             srcval=*srcpixel++;
2163                             dstval|=(X11DRV_DIB_GetNearestIndex
2164                                      (colors, 16,
2165                                       ((srcval <<  3) & 0xf8) | /* r */
2166                                       ((srcval >>  2) & 0x07),
2167                                       ((srcval >>  2) & 0xf8) | /* g */
2168                                       ((srcval >>  7) & 0x07),
2169                                       ((srcval >>  7) & 0xf8) | /* b */
2170                                       ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2171                             if ((x&1)==1) {
2172                                 *dstbyte++=dstval;
2173                                 dstval=0;
2174                             }
2175                         }
2176                         if ((dstwidth&1)!=0) {
2177                             *dstbyte=dstval;
2178                         }
2179                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2180                         dstbits += linebytes;
2181                     }
2182                 } else {
2183                     goto notsupported;
2184                 }
2185             } else if (bmpImage->green_mask==0x07e0) {
2186                 if (bmpImage->red_mask==0xf800) {
2187                     /* ==== rgb 565 bmp -> pal 4 dib ==== */
2188                     for (h=0; h<lines; h++) {
2189                         BYTE dstval;
2190                         srcpixel=srcbits;
2191                         dstbyte=dstbits;
2192                         dstval=0;
2193                         for (x=0; x<dstwidth; x++) {
2194                             WORD srcval;
2195                             srcval=*srcpixel++;
2196                             dstval|=(X11DRV_DIB_GetNearestIndex
2197                                      (colors, 16,
2198                                       ((srcval >>  8) & 0xf8) | /* r */
2199                                       ((srcval >> 13) & 0x07),
2200                                       ((srcval >>  3) & 0xfc) | /* g */
2201                                       ((srcval >>  9) & 0x03),
2202                                       ((srcval <<  3) & 0xf8) | /* b */
2203                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
2204                             if ((x&1)==1) {
2205                                 *dstbyte++=dstval;
2206                                 dstval=0;
2207                             }
2208                         }
2209                         if ((dstwidth&1)!=0) {
2210                             *dstbyte=dstval;
2211                         }
2212                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2213                         dstbits += linebytes;
2214                     }
2215                 } else if (bmpImage->blue_mask==0xf800) {
2216                     /* ==== bgr 565 bmp -> pal 4 dib ==== */
2217                     for (h=0; h<lines; h++) {
2218                         WORD dstval;
2219                         srcpixel=srcbits;
2220                         dstbyte=dstbits;
2221                         dstval=0;
2222                         for (x=0; x<dstwidth; x++) {
2223                             WORD srcval;
2224                             srcval=*srcpixel++;
2225                             dstval|=(X11DRV_DIB_GetNearestIndex
2226                                      (colors, 16,
2227                                       ((srcval <<  3) & 0xf8) | /* r */
2228                                       ((srcval >>  2) & 0x07),
2229                                       ((srcval >>  3) & 0xfc) | /* g */
2230                                       ((srcval >>  9) & 0x03),
2231                                       ((srcval >>  8) & 0xf8) | /* b */
2232                                       ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2233                             if ((x&1)==1) {
2234                                 *dstbyte++=dstval;
2235                                 dstval=0;
2236                             }
2237                         }
2238                         if ((dstwidth&1)!=0) {
2239                             *dstbyte=dstval;
2240                         }
2241                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2242                         dstbits += linebytes;
2243                     }
2244                 } else {
2245                     goto notsupported;
2246                 }
2247             } else {
2248                 goto notsupported;
2249             }
2250         }
2251         break;
2252
2253     case 24:
2254         if (bmpImage->bits_per_pixel==24) {
2255             const void* srcbits;
2256             const BYTE *srcbyte;
2257             BYTE* dstbyte;
2258
2259             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2260
2261             if (bmpImage->green_mask!=0x00ff00 ||
2262                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2263                 goto notsupported;
2264             } else if (bmpImage->blue_mask==0xff) {
2265                 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2266                 for (h=0; h<lines; h++) {
2267                     srcbyte=srcbits;
2268                     dstbyte=dstbits;
2269                     for (x=0; x<dstwidth/2; x++) {
2270                         /* Do 2 pixels at a time */
2271                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2272                                     (colors, 16,
2273                                      srcbyte[2],
2274                                      srcbyte[1],
2275                                      srcbyte[0]) << 4) |
2276                                     X11DRV_DIB_GetNearestIndex
2277                                     (colors, 16,
2278                                      srcbyte[5],
2279                                      srcbyte[4],
2280                                      srcbyte[3]);
2281                         srcbyte+=6;
2282                     }
2283                     if (dstwidth&1) {
2284                         /* And the the odd pixel */
2285                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2286                                     (colors, 16,
2287                                      srcbyte[2],
2288                                      srcbyte[1],
2289                                      srcbyte[0]) << 4);
2290                     }
2291                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2292                     dstbits += linebytes;
2293                 }
2294             } else {
2295                 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2296                 for (h=0; h<lines; h++) {
2297                     srcbyte=srcbits;
2298                     dstbyte=dstbits;
2299                     for (x=0; x<dstwidth/2; x++) {
2300                         /* Do 2 pixels at a time */
2301                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2302                                     (colors, 16,
2303                                      srcbyte[0],
2304                                      srcbyte[1],
2305                                      srcbyte[2]) << 4) |
2306                                     X11DRV_DIB_GetNearestIndex
2307                                     (colors, 16,
2308                                      srcbyte[3],
2309                                      srcbyte[4],
2310                                      srcbyte[5]);
2311                         srcbyte+=6;
2312                     }
2313                     if (dstwidth&1) {
2314                         /* And the the odd pixel */
2315                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2316                                     (colors, 16,
2317                                      srcbyte[0],
2318                                      srcbyte[1],
2319                                      srcbyte[2]) << 4);
2320                     }
2321                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2322                     dstbits += linebytes;
2323                 }
2324             }
2325             break;
2326         }
2327         /* Fall through */
2328
2329     case 32:
2330         {
2331             const void* srcbits;
2332             const BYTE *srcbyte;
2333             BYTE* dstbyte;
2334
2335             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2336
2337             if (bmpImage->green_mask!=0x00ff00 ||
2338                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2339                 goto notsupported;
2340             } else if (bmpImage->blue_mask==0xff) {
2341                 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2342                 for (h=0; h<lines; h++) {
2343                     srcbyte=srcbits;
2344                     dstbyte=dstbits;
2345                     for (x=0; x<dstwidth/2; x++) {
2346                         /* Do 2 pixels at a time */
2347                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2348                                     (colors, 16,
2349                                      srcbyte[2],
2350                                      srcbyte[1],
2351                                      srcbyte[0]) << 4) |
2352                                     X11DRV_DIB_GetNearestIndex
2353                                     (colors, 16,
2354                                      srcbyte[6],
2355                                      srcbyte[5],
2356                                      srcbyte[4]);
2357                         srcbyte+=8;
2358                     }
2359                     if (dstwidth&1) {
2360                         /* And the the odd pixel */
2361                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2362                                     (colors, 16,
2363                                      srcbyte[2],
2364                                      srcbyte[1],
2365                                      srcbyte[0]) << 4);
2366                     }
2367                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2368                     dstbits += linebytes;
2369                 }
2370             } else {
2371                 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2372                 for (h=0; h<lines; h++) {
2373                     srcbyte=srcbits;
2374                     dstbyte=dstbits;
2375                     for (x=0; x<dstwidth/2; x++) {
2376                         /* Do 2 pixels at a time */
2377                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2378                                     (colors, 16,
2379                                      srcbyte[0],
2380                                      srcbyte[1],
2381                                      srcbyte[2]) << 4) |
2382                                     X11DRV_DIB_GetNearestIndex
2383                                     (colors, 16,
2384                                      srcbyte[4],
2385                                      srcbyte[5],
2386                                      srcbyte[6]);
2387                         srcbyte+=8;
2388                     }
2389                     if (dstwidth&1) {
2390                         /* And the the odd pixel */
2391                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2392                                     (colors, 16,
2393                                      srcbyte[0],
2394                                      srcbyte[1],
2395                                      srcbyte[2]) << 4);
2396                     }
2397                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2398                     dstbits += linebytes;
2399                 }
2400             }
2401         }
2402         break;
2403
2404     default:
2405     notsupported:
2406         {
2407             BYTE* dstbyte;
2408
2409             /* ==== any bmp format -> pal 4 dib ==== */
2410             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2411                   bmpImage->bits_per_pixel, bmpImage->red_mask,
2412                   bmpImage->green_mask, bmpImage->blue_mask );
2413             for (h=lines-1; h>=0; h--) {
2414                 dstbyte=dstbits;
2415                 for (x=0; x<(dstwidth & ~1); x+=2) {
2416                     *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2417                         X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2418                 }
2419                 if (dstwidth & 1) {
2420                     *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2421                 }
2422                 dstbits += linebytes;
2423             }
2424         }
2425         break;
2426     }
2427 }
2428
2429 /***********************************************************************
2430  *           X11DRV_DIB_SetImageBits_RLE4
2431  *
2432  * SetDIBits for a 4-bit deep compressed DIB.
2433  */
2434 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2435                                           DWORD width, DWORD dstwidth,
2436                                           int left, int *colors,
2437                                           XImage *bmpImage )
2438 {
2439     int x = 0, y = lines - 1, c, length;
2440     const BYTE *begin = bits;
2441
2442     while (y >= 0)
2443     {
2444         length = *bits++;
2445         if (length) {   /* encoded */
2446             c = *bits++;
2447             while (length--) {
2448                 if (x >= width) break;
2449                 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2450                 if (!length--) break;
2451                 if (x >= width) break;
2452                 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2453             }
2454         } else {
2455             length = *bits++;
2456             switch (length)
2457             {
2458             case RLE_EOL:
2459                 x = 0;
2460                 y--;
2461                 break;
2462
2463             case RLE_END:
2464                 return;
2465
2466             case RLE_DELTA:
2467                 x += *bits++;
2468                 y -= *bits++;
2469                 break;
2470
2471             default: /* absolute */
2472                 while (length--) {
2473                     c = *bits++;
2474                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2475                     if (!length--) break;
2476                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2477                 }
2478                 if ((bits - begin) & 1)
2479                     bits++;
2480             }
2481         }
2482     }
2483 }
2484
2485
2486
2487 /***********************************************************************
2488  *           X11DRV_DIB_SetImageBits_8
2489  *
2490  * SetDIBits for an 8-bit deep DIB.
2491  */
2492 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2493                                 DWORD srcwidth, DWORD dstwidth, int left,
2494                                 const int *colors, XImage *bmpImage,
2495                                 DWORD linebytes )
2496 {
2497     DWORD x;
2498     int h;
2499     const BYTE* srcbyte;
2500     BYTE* dstbits;
2501
2502     if (lines < 0 )
2503     {
2504         lines = -lines;
2505         srcbits = srcbits + linebytes * (lines-1);
2506         linebytes = -linebytes;
2507     }
2508     srcbits += left;
2509     srcbyte = srcbits;
2510
2511     switch (bmpImage->depth) {
2512     case 15:
2513     case 16:
2514 #if defined(__i386__) && defined(__GNUC__)
2515         /* Some X servers might have 32 bit/ 16bit deep pixel */
2516         if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
2517             (ImageByteOrder(gdi_display)==LSBFirst) )
2518         {
2519             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2520             /* FIXME: Does this really handle all these cases correctly? */
2521             /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2522             for (h = lines ; h--; ) {
2523                 int _cl1,_cl2; /* temp outputs for asm below */
2524                 /* Borrowed from DirectDraw */
2525                 __asm__ __volatile__(
2526                 "xor %%eax,%%eax\n"
2527                 "cld\n"
2528                 "1:\n"
2529                 "    lodsb\n"
2530                 "    movw (%%edx,%%eax,4),%%ax\n"
2531                 "    stosw\n"
2532                 "      xor %%eax,%%eax\n"
2533                 "    loop 1b\n"
2534                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2535                 :"S" (srcbyte),
2536                  "D" (dstbits),
2537                  "c" (dstwidth),
2538                  "d" (colors)
2539                 :"eax", "cc", "memory"
2540                 );
2541                 srcbyte = (srcbits += linebytes);
2542                 dstbits -= bmpImage->bytes_per_line;
2543             }
2544             return;
2545         }
2546         break;
2547 #endif
2548     case 24:
2549     case 32:
2550 #if defined(__i386__) && defined(__GNUC__)
2551         if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
2552             (ImageByteOrder(gdi_display)==LSBFirst) )
2553         {
2554             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2555             /* FIXME: Does this really handle both cases correctly? */
2556             /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2557             for (h = lines ; h--; ) {
2558                 int _cl1,_cl2; /* temp outputs for asm below */
2559                 /* Borrowed from DirectDraw */
2560                 __asm__ __volatile__(
2561                 "xor %%eax,%%eax\n"
2562                 "cld\n"
2563                 "1:\n"
2564                 "    lodsb\n"
2565                 "    movl (%%edx,%%eax,4),%%eax\n"
2566                 "    stosl\n"
2567                 "      xor %%eax,%%eax\n"
2568                 "    loop 1b\n"
2569                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2570                 :"S" (srcbyte),
2571                  "D" (dstbits),
2572                  "c" (dstwidth),
2573                  "d" (colors)
2574                 :"eax", "cc", "memory"
2575                 );
2576                 srcbyte = (srcbits += linebytes);
2577                 dstbits -= bmpImage->bytes_per_line;
2578             }
2579             return;
2580         }
2581         break;
2582 #endif
2583     default:
2584         break; /* use slow generic case below */
2585     }
2586
2587     /* ==== pal 8 dib -> any bmp format ==== */
2588     for (h=lines-1; h>=0; h--) {
2589         for (x=left; x<dstwidth+left; x++) {
2590             XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2591         }
2592         srcbyte = (srcbits += linebytes);
2593     }
2594 }
2595
2596 /***********************************************************************
2597  *           X11DRV_DIB_GetImageBits_8
2598  *
2599  * GetDIBits for an 8-bit deep DIB.
2600  */
2601 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2602                                        DWORD srcwidth, DWORD dstwidth,
2603                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
2604                                        XImage *bmpImage, DWORD linebytes )
2605 {
2606     DWORD x;
2607     int h;
2608     BYTE* dstbyte;
2609
2610     if (lines < 0 )
2611     {
2612        lines = -lines;
2613        dstbits = dstbits + ( linebytes * (lines-1) );
2614        linebytes = -linebytes;
2615     }
2616
2617     /*
2618      * Hack for now
2619      * This condition is true when GetImageBits has been called by
2620      * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2621      * 256 colormaps, so we'll just use for for GetDIBits calls.
2622      * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2623      */
2624     if (!srccolors) goto updatesection;
2625
2626     switch (bmpImage->depth) {
2627     case 1:
2628     case 4:
2629         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2630
2631             /* ==== pal 1 bmp -> pal 8 dib ==== */
2632             /* ==== pal 4 bmp -> pal 8 dib ==== */
2633             for (h=lines-1; h>=0; h--) {
2634                 dstbyte=dstbits;
2635                 for (x=0; x<dstwidth; x++) {
2636                     PALETTEENTRY srcval;
2637                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2638                     *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2639                                                           srcval.peRed,
2640                                                           srcval.peGreen,
2641                                                           srcval.peBlue);
2642                 }
2643                 dstbits += linebytes;
2644             }
2645         } else {
2646             goto notsupported;
2647         }
2648         break;
2649
2650     case 8:
2651        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2652             /* ==== pal 8 bmp -> pal 8 dib ==== */
2653            const void* srcbits;
2654            const BYTE* srcpixel;
2655
2656            srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2657            for (h=0; h<lines; h++) {
2658                srcpixel=srcbits;
2659                dstbyte=dstbits;
2660                for (x = 0; x < dstwidth; x++) {
2661                    PALETTEENTRY srcval;
2662                    srcval=srccolors[(int)*srcpixel++];
2663                    *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2664                                                          srcval.peRed,
2665                                                          srcval.peGreen,
2666                                                          srcval.peBlue);
2667                }
2668                srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2669                dstbits += linebytes;
2670            }
2671        } else {
2672            goto notsupported;
2673        }
2674        break;
2675
2676     case 15:
2677     case 16:
2678         {
2679             const void* srcbits;
2680             const WORD* srcpixel;
2681             BYTE* dstbyte;
2682
2683             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2684
2685             if (bmpImage->green_mask==0x03e0) {
2686                 if (bmpImage->red_mask==0x7c00) {
2687                     /* ==== rgb 555 bmp -> pal 8 dib ==== */
2688                     for (h=0; h<lines; h++) {
2689                         srcpixel=srcbits;
2690                         dstbyte=dstbits;
2691                         for (x=0; x<dstwidth; x++) {
2692                             WORD srcval;
2693                             srcval=*srcpixel++;
2694                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2695                                 (colors, 256,
2696                                  ((srcval >>  7) & 0xf8) | /* r */
2697                                  ((srcval >> 12) & 0x07),
2698                                  ((srcval >>  2) & 0xf8) | /* g */
2699                                  ((srcval >>  7) & 0x07),
2700                                  ((srcval <<  3) & 0xf8) | /* b */
2701                                  ((srcval >>  2) & 0x07) );
2702                         }
2703                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2704                         dstbits += linebytes;
2705                     }
2706                 } else if (bmpImage->blue_mask==0x7c00) {
2707                     /* ==== bgr 555 bmp -> pal 8 dib ==== */
2708                     for (h=0; h<lines; h++) {
2709                         srcpixel=srcbits;
2710                         dstbyte=dstbits;
2711                         for (x=0; x<dstwidth; x++) {
2712                             WORD srcval;
2713                             srcval=*srcpixel++;
2714                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2715                                 (colors, 256,
2716                                  ((srcval <<  3) & 0xf8) | /* r */
2717                                  ((srcval >>  2) & 0x07),
2718                                  ((srcval >>  2) & 0xf8) | /* g */
2719                                  ((srcval >>  7) & 0x07),
2720                                  ((srcval >>  7) & 0xf8) | /* b */
2721                                  ((srcval >> 12) & 0x07) );
2722                         }
2723                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2724                         dstbits += linebytes;
2725                     }
2726                 } else {
2727                     goto notsupported;
2728                 }
2729             } else if (bmpImage->green_mask==0x07e0) {
2730                 if (bmpImage->red_mask==0xf800) {
2731                     /* ==== rgb 565 bmp -> pal 8 dib ==== */
2732                     for (h=0; h<lines; h++) {
2733                         srcpixel=srcbits;
2734                         dstbyte=dstbits;
2735                         for (x=0; x<dstwidth; x++) {
2736                             WORD srcval;
2737                             srcval=*srcpixel++;
2738                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2739                                 (colors, 256,
2740                                  ((srcval >>  8) & 0xf8) | /* r */
2741                                  ((srcval >> 13) & 0x07),
2742                                  ((srcval >>  3) & 0xfc) | /* g */
2743                                  ((srcval >>  9) & 0x03),
2744                                  ((srcval <<  3) & 0xf8) | /* b */
2745                                  ((srcval >>  2) & 0x07) );
2746                         }
2747                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2748                         dstbits += linebytes;
2749                     }
2750                 } else if (bmpImage->blue_mask==0xf800) {
2751                     /* ==== bgr 565 bmp -> pal 8 dib ==== */
2752                     for (h=0; h<lines; h++) {
2753                         srcpixel=srcbits;
2754                         dstbyte=dstbits;
2755                         for (x=0; x<dstwidth; x++) {
2756                             WORD srcval;
2757                             srcval=*srcpixel++;
2758                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2759                                 (colors, 256,
2760                                  ((srcval <<  3) & 0xf8) | /* r */
2761                                  ((srcval >>  2) & 0x07),
2762                                  ((srcval >>  3) & 0xfc) | /* g */
2763                                  ((srcval >>  9) & 0x03),
2764                                  ((srcval >>  8) & 0xf8) | /* b */
2765                                  ((srcval >> 13) & 0x07) );
2766                         }
2767                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2768                         dstbits += linebytes;
2769                     }
2770                 } else {
2771                     goto notsupported;
2772                 }
2773             } else {
2774                 goto notsupported;
2775             }
2776         }
2777         break;
2778
2779     case 24:
2780     case 32:
2781         {
2782             const void* srcbits;
2783             const BYTE *srcbyte;
2784             BYTE* dstbyte;
2785             int bytes_per_pixel;
2786
2787             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2788             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2789
2790             if (bmpImage->green_mask!=0x00ff00 ||
2791                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2792                 goto notsupported;
2793             } else if (bmpImage->blue_mask==0xff) {
2794                 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2795                 for (h=0; h<lines; h++) {
2796                     srcbyte=srcbits;
2797                     dstbyte=dstbits;
2798                     for (x=0; x<dstwidth; x++) {
2799                         *dstbyte++=X11DRV_DIB_GetNearestIndex
2800                             (colors, 256,
2801                              srcbyte[2],
2802                              srcbyte[1],
2803                              srcbyte[0]);
2804                         srcbyte+=bytes_per_pixel;
2805                     }
2806                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2807                     dstbits += linebytes;
2808                 }
2809             } else {
2810                 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2811                 for (h=0; h<lines; h++) {
2812                     srcbyte=srcbits;
2813                     dstbyte=dstbits;
2814                     for (x=0; x<dstwidth; x++) {
2815                         *dstbyte++=X11DRV_DIB_GetNearestIndex
2816                             (colors, 256,
2817                              srcbyte[0],
2818                              srcbyte[1],
2819                              srcbyte[2]);
2820                         srcbyte+=bytes_per_pixel;
2821                     }
2822                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2823                     dstbits += linebytes;
2824                 }
2825             }
2826         }
2827         break;
2828
2829     default:
2830     notsupported:
2831         WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2832               bmpImage->depth, bmpImage->red_mask,
2833               bmpImage->green_mask, bmpImage->blue_mask );
2834     updatesection:
2835         /* ==== any bmp format -> pal 8 dib ==== */
2836         for (h=lines-1; h>=0; h--) {
2837             dstbyte=dstbits;
2838             for (x=0; x<dstwidth; x++) {
2839                 *dstbyte=X11DRV_DIB_MapColor
2840                     ((int*)colors, 256,
2841                      XGetPixel(bmpImage, x, h), *dstbyte);
2842                 dstbyte++;
2843             }
2844             dstbits += linebytes;
2845         }
2846         break;
2847     }
2848 }
2849
2850 /***********************************************************************
2851  *            X11DRV_DIB_SetImageBits_RLE8
2852  *
2853  * SetDIBits for an 8-bit deep compressed DIB.
2854  *
2855  * This function rewritten 941113 by James Youngman.  WINE blew out when I
2856  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2857  *
2858  * This was because the algorithm assumed that all RLE8 bitmaps end with the
2859  * 'End of bitmap' escape code.  This code is very much laxer in what it
2860  * allows to end the expansion.  Possibly too lax.  See the note by
2861  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
2862  * bitmap should end with RleEnd, but on the other hand, software exists
2863  * that produces ones that don't and Windows 3.1 doesn't complain a bit
2864  * about it.
2865  *
2866  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
2867  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
2868  *                                              [JAY]
2869  */
2870 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2871                                           DWORD width, DWORD dstwidth,
2872                                           int left, int *colors,
2873                                           XImage *bmpImage )
2874 {
2875     int x;                      /* X-positon on each line.  Increases. */
2876     int y;                      /* Line #.  Starts at lines-1, decreases */
2877     const BYTE *pIn = bits;     /* Pointer to current position in bits */
2878     BYTE length;                /* The length pf a run */
2879     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
2880
2881     /*
2882      * Note that the bitmap data is stored by Windows starting at the
2883      * bottom line of the bitmap and going upwards.  Within each line,
2884      * the data is stored left-to-right.  That's the reason why line
2885      * goes from lines-1 to 0.                  [JAY]
2886      */
2887
2888     x = 0;
2889     y = lines - 1;
2890     while (y >= 0)
2891     {
2892         length = *pIn++;
2893
2894         /*
2895          * If the length byte is not zero (which is the escape value),
2896          * We have a run of length pixels all the same colour.  The colour
2897          * index is stored next.
2898          *
2899          * If the length byte is zero, we need to read the next byte to
2900          * know what to do.                     [JAY]
2901          */
2902         if (length != 0)
2903         {
2904             /*
2905              * [Run-Length] Encoded mode
2906              */
2907             int color = colors[*pIn++];
2908             while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2909         }
2910         else
2911         {
2912             /*
2913              * Escape codes (may be an absolute sequence though)
2914              */
2915             escape_code = (*pIn++);
2916             switch(escape_code)
2917             {
2918             case RLE_EOL:
2919                 x = 0;
2920                 y--;
2921                 break;
2922
2923             case RLE_END:
2924                 /* Not all RLE8 bitmaps end with this code.  For
2925                  * example, Paint Shop Pro produces some that don't.
2926                  * That's (I think) what caused the previous
2927                  * implementation to fail.  [JAY]
2928                  */
2929                 return;
2930
2931             case RLE_DELTA:
2932                 x += (*pIn++);
2933                 y -= (*pIn++);
2934                 break;
2935
2936             default:  /* switch to absolute mode */
2937                 length = escape_code;
2938                 while (length--)
2939                 {
2940                     int color = colors[*pIn++];
2941                     if (x >= dstwidth)
2942                     {
2943                         pIn += length;
2944                         break;
2945                     }
2946                     XPutPixel(bmpImage, x++, y, color);
2947                 }
2948                 /*
2949                  * If you think for a moment you'll realise that the
2950                  * only time we could ever possibly read an odd
2951                  * number of bytes is when there is a 0x00 (escape),
2952                  * a value >0x02 (absolute mode) and then an odd-
2953                  * length run.  Therefore this is the only place we
2954                  * need to worry about it.  Everywhere else the
2955                  * bytes are always read in pairs.  [JAY]
2956                  */
2957                 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2958                 break;
2959             } /* switch (escape_code) : Escape sequence */
2960         }
2961     }
2962 }
2963
2964
2965 /***********************************************************************
2966  *           X11DRV_DIB_SetImageBits_16
2967  *
2968  * SetDIBits for a 16-bit deep DIB.
2969  */
2970 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2971                                  DWORD srcwidth, DWORD dstwidth, int left,
2972                                        X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2973                                        XImage *bmpImage, DWORD linebytes )
2974 {
2975     DWORD x;
2976     int h;
2977
2978     if (lines < 0 )
2979     {
2980         lines = -lines;
2981         srcbits = srcbits + ( linebytes * (lines-1));
2982         linebytes = -linebytes;
2983     }
2984
2985     switch (bmpImage->depth)
2986     {
2987     case 15:
2988     case 16:
2989         {
2990             char* dstbits;
2991
2992             srcbits=srcbits+left*2;
2993             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2994
2995             if (bmpImage->green_mask==0x03e0) {
2996                 if (gSrc==bmpImage->green_mask) {
2997                     if (rSrc==bmpImage->red_mask) {
2998                         /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2999                         /* ==== bgr 555 dib -> bgr 555 bmp ==== */
3000                         X11DRV_DIB_Convert_any_asis
3001                             (dstwidth,lines,2,
3002                              srcbits,linebytes,
3003                              dstbits,-bmpImage->bytes_per_line);
3004                     } else if (rSrc==bmpImage->blue_mask) {
3005                         /* ==== rgb 555 dib -> bgr 555 bmp ==== */
3006                         /* ==== bgr 555 dib -> rgb 555 bmp ==== */
3007                         X11DRV_DIB_Convert_555_reverse
3008                             (dstwidth,lines,
3009                              srcbits,linebytes,
3010                              dstbits,-bmpImage->bytes_per_line);
3011                     }
3012                 } else {
3013                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3014                         /* ==== rgb 565 dib -> rgb 555 bmp ==== */
3015                         /* ==== bgr 565 dib -> bgr 555 bmp ==== */
3016                         X11DRV_DIB_Convert_565_to_555_asis
3017                             (dstwidth,lines,
3018                              srcbits,linebytes,
3019                              dstbits,-bmpImage->bytes_per_line);
3020                     } else {
3021                         /* ==== rgb 565 dib -> bgr 555 bmp ==== */
3022                         /* ==== bgr 565 dib -> rgb 555 bmp ==== */
3023                         X11DRV_DIB_Convert_565_to_555_reverse
3024                             (dstwidth,lines,
3025                              srcbits,linebytes,
3026                              dstbits,-bmpImage->bytes_per_line);
3027                     }
3028                 }
3029             } else if (bmpImage->green_mask==0x07e0) {
3030                 if (gSrc==bmpImage->green_mask) {
3031                     if (rSrc==bmpImage->red_mask) {
3032                         /* ==== rgb 565 dib -> rgb 565 bmp ==== */
3033                         /* ==== bgr 565 dib -> bgr 565 bmp ==== */
3034                         X11DRV_DIB_Convert_any_asis
3035                             (dstwidth,lines,2,
3036                              srcbits,linebytes,
3037                              dstbits,-bmpImage->bytes_per_line);
3038                     } else {
3039                         /* ==== rgb 565 dib -> bgr 565 bmp ==== */
3040                         /* ==== bgr 565 dib -> rgb 565 bmp ==== */
3041                         X11DRV_DIB_Convert_565_reverse
3042                             (dstwidth,lines,
3043                              srcbits,linebytes,
3044                              dstbits,-bmpImage->bytes_per_line);
3045                     }
3046                 } else {
3047                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3048                         /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3049                         /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3050                         X11DRV_DIB_Convert_555_to_565_asis
3051                             (dstwidth,lines,
3052                              srcbits,linebytes,
3053                              dstbits,-bmpImage->bytes_per_line);
3054                     } else {
3055                         /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3056                         /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3057                         X11DRV_DIB_Convert_555_to_565_reverse
3058                             (dstwidth,lines,
3059                              srcbits,linebytes,
3060                              dstbits,-bmpImage->bytes_per_line);
3061                     }
3062                 }
3063             } else {
3064                 goto notsupported;
3065             }
3066         }
3067         break;
3068
3069     case 24:
3070         if (bmpImage->bits_per_pixel==24) {
3071             char* dstbits;
3072
3073             srcbits=srcbits+left*2;
3074             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3075
3076             if (bmpImage->green_mask!=0x00ff00 ||
3077                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3078                 goto notsupported;
3079             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3080                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3081                 if (gSrc==0x03e0) {
3082                     /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3083                     /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3084                     X11DRV_DIB_Convert_555_to_888_asis
3085                         (dstwidth,lines,
3086                          srcbits,linebytes,
3087                          dstbits,-bmpImage->bytes_per_line);
3088                 } else {
3089                     /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3090                     /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3091                     X11DRV_DIB_Convert_565_to_888_asis
3092                         (dstwidth,lines,
3093                          srcbits,linebytes,
3094                          dstbits,-bmpImage->bytes_per_line);
3095                 }
3096             } else {
3097                 if (gSrc==0x03e0) {
3098                     /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3099                     /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3100                     X11DRV_DIB_Convert_555_to_888_reverse
3101                         (dstwidth,lines,
3102                          srcbits,linebytes,
3103                          dstbits,-bmpImage->bytes_per_line);
3104                 } else {
3105                     /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3106                     /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3107                     X11DRV_DIB_Convert_565_to_888_reverse
3108                         (dstwidth,lines,
3109                          srcbits,linebytes,
3110                          dstbits,-bmpImage->bytes_per_line);
3111                 }
3112             }
3113             break;
3114         }
3115         /* Fall through */
3116
3117     case 32:
3118         {
3119             char* dstbits;
3120
3121             srcbits=srcbits+left*2;
3122             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3123
3124             if (bmpImage->green_mask!=0x00ff00 ||
3125                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3126                 goto notsupported;
3127             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3128                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3129                 if (gSrc==0x03e0) {
3130                     /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3131                     /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3132                     X11DRV_DIB_Convert_555_to_0888_asis
3133                         (dstwidth,lines,
3134                          srcbits,linebytes,
3135                          dstbits,-bmpImage->bytes_per_line);
3136                 } else {
3137                     /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3138                     /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3139                     X11DRV_DIB_Convert_565_to_0888_asis
3140                         (dstwidth,lines,
3141                          srcbits,linebytes,
3142                          dstbits,-bmpImage->bytes_per_line);
3143                 }
3144             } else {
3145                 if (gSrc==0x03e0) {
3146                     /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3147                     /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3148                     X11DRV_DIB_Convert_555_to_0888_reverse
3149                         (dstwidth,lines,
3150                          srcbits,linebytes,
3151                          dstbits,-bmpImage->bytes_per_line);
3152                 } else {
3153                     /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3154                     /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3155                     X11DRV_DIB_Convert_565_to_0888_reverse
3156                         (dstwidth,lines,
3157                          srcbits,linebytes,
3158                          dstbits,-bmpImage->bytes_per_line);
3159                 }
3160             }
3161         }
3162         break;
3163
3164     default:
3165     notsupported:
3166         WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3167               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3168               bmpImage->green_mask, bmpImage->blue_mask );
3169         /* fall through */
3170     case 1:
3171     case 4:
3172     case 8:
3173         {
3174             /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3175             const WORD* srcpixel;
3176             int rShift1,gShift1,bShift1;
3177             int rShift2,gShift2,bShift2;
3178             BYTE gMask1,gMask2;
3179
3180             /* Set color scaling values */
3181             rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3182             gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3183             bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3184             rShift2=rShift1+5;
3185             gShift2=gShift1+5;
3186             bShift2=bShift1+5;
3187             if (gSrc==0x03e0) {
3188                 /* Green has 5 bits, like the others */
3189                 gMask1=0xf8;
3190                 gMask2=0x07;
3191             } else {
3192                 /* Green has 6 bits, not 5. Compensate. */
3193                 gShift1++;
3194                 gShift2+=2;
3195                 gMask1=0xfc;
3196                 gMask2=0x03;
3197             }
3198
3199             srcbits+=2*left;
3200
3201             /* We could split it into four separate cases to optimize
3202              * but it is probably not worth it.
3203              */
3204             for (h=lines-1; h>=0; h--) {
3205                 srcpixel=(const WORD*)srcbits;
3206                 for (x=left; x<dstwidth+left; x++) {
3207                     DWORD srcval;
3208                     BYTE red,green,blue;
3209                     srcval=*srcpixel++ << 16;
3210                     red=  ((srcval >> rShift1) & 0xf8) |
3211                         ((srcval >> rShift2) & 0x07);
3212                     green=((srcval >> gShift1) & gMask1) |
3213                         ((srcval >> gShift2) & gMask2);
3214                     blue= ((srcval >> bShift1) & 0xf8) |
3215                         ((srcval >> bShift2) & 0x07);
3216                     XPutPixel(bmpImage, x, h,
3217                               X11DRV_PALETTE_ToPhysical
3218                               (physDev, RGB(red,green,blue)));
3219                 }
3220                 srcbits += linebytes;
3221             }
3222         }
3223         break;
3224     }
3225 }
3226
3227
3228 /***********************************************************************
3229  *           X11DRV_DIB_GetImageBits_16
3230  *
3231  * GetDIBits for an 16-bit deep DIB.
3232  */
3233 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3234                                         DWORD dstwidth, DWORD srcwidth,
3235                                         PALETTEENTRY *srccolors,
3236                                         DWORD rDst, DWORD gDst, DWORD bDst,
3237                                         XImage *bmpImage, DWORD dibpitch )
3238 {
3239     DWORD x;
3240     int h;
3241
3242     DWORD linebytes = dibpitch;
3243
3244     if (lines < 0 )
3245     {
3246         lines = -lines;
3247         dstbits = dstbits + ( linebytes * (lines-1));
3248         linebytes = -linebytes;
3249     }
3250
3251     switch (bmpImage->depth)
3252     {
3253     case 15:
3254     case 16:
3255         {
3256             const char* srcbits;
3257
3258             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3259
3260             if (bmpImage->green_mask==0x03e0) {
3261                 if (gDst==bmpImage->green_mask) {
3262                     if (rDst==bmpImage->red_mask) {
3263                         /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3264                         /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3265                         X11DRV_DIB_Convert_any_asis
3266                             (dstwidth,lines,2,
3267                              srcbits,-bmpImage->bytes_per_line,
3268                              dstbits,linebytes);
3269                     } else {
3270                         /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3271                         /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3272                         X11DRV_DIB_Convert_555_reverse
3273                             (dstwidth,lines,
3274                              srcbits,-bmpImage->bytes_per_line,
3275                              dstbits,linebytes);
3276                     }
3277                 } else {
3278                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3279                         /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3280                         /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3281                         X11DRV_DIB_Convert_555_to_565_asis
3282                             (dstwidth,lines,
3283                              srcbits,-bmpImage->bytes_per_line,
3284                              dstbits,linebytes);
3285                     } else {
3286                         /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3287                         /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3288                         X11DRV_DIB_Convert_555_to_565_reverse
3289                             (dstwidth,lines,
3290                              srcbits,-bmpImage->bytes_per_line,
3291                              dstbits,linebytes);
3292                     }
3293                 }
3294             } else if (bmpImage->green_mask==0x07e0) {
3295                 if (gDst==bmpImage->green_mask) {
3296                     if (rDst == bmpImage->red_mask) {
3297                         /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3298                         /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3299                         X11DRV_DIB_Convert_any_asis
3300                             (dstwidth,lines,2,
3301                              srcbits,-bmpImage->bytes_per_line,
3302                              dstbits,linebytes);
3303                     } else {
3304                         /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3305                         /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3306                         X11DRV_DIB_Convert_565_reverse
3307                             (dstwidth,lines,
3308                              srcbits,-bmpImage->bytes_per_line,
3309                              dstbits,linebytes);
3310                     }
3311                 } else {
3312                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3313                         /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3314                         /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3315                         X11DRV_DIB_Convert_565_to_555_asis
3316                             (dstwidth,lines,
3317                              srcbits,-bmpImage->bytes_per_line,
3318                              dstbits,linebytes);
3319                     } else {
3320                         /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3321                         /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3322                         X11DRV_DIB_Convert_565_to_555_reverse
3323                             (dstwidth,lines,
3324                              srcbits,-bmpImage->bytes_per_line,
3325                              dstbits,linebytes);
3326                     }
3327                 }
3328             } else {
3329                 goto notsupported;
3330             }
3331         }
3332         break;
3333
3334     case 24:
3335         if (bmpImage->bits_per_pixel == 24) {
3336             const char* srcbits;
3337
3338             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3339
3340             if (bmpImage->green_mask!=0x00ff00 ||
3341                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3342                 goto notsupported;
3343             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3344                     (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3345                 if (gDst==0x03e0) {
3346                     /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3347                     /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3348                     X11DRV_DIB_Convert_888_to_555_asis
3349                         (dstwidth,lines,
3350                          srcbits,-bmpImage->bytes_per_line,
3351                          dstbits,linebytes);
3352                 } else {
3353                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3354                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3355                     X11DRV_DIB_Convert_888_to_565_asis
3356                         (dstwidth,lines,
3357                          srcbits,-bmpImage->bytes_per_line,
3358                          dstbits,linebytes);
3359                 }
3360             } else {
3361                 if (gDst==0x03e0) {
3362                     /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3363                     /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3364                     X11DRV_DIB_Convert_888_to_555_reverse
3365                         (dstwidth,lines,
3366                          srcbits,-bmpImage->bytes_per_line,
3367                          dstbits,linebytes);
3368                 } else {
3369                     /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3370                     /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3371                     X11DRV_DIB_Convert_888_to_565_reverse
3372                         (dstwidth,lines,
3373                          srcbits,-bmpImage->bytes_per_line,
3374                          dstbits,linebytes);
3375                 }
3376             }
3377             break;
3378         }
3379         /* Fall through */
3380
3381     case 32:
3382         {
3383             const char* srcbits;
3384
3385             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3386
3387             if (bmpImage->green_mask!=0x00ff00 ||
3388                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3389                 goto notsupported;
3390             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3391                        (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3392                 if (gDst==0x03e0) {
3393                     /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3394                     /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3395                     X11DRV_DIB_Convert_0888_to_555_asis
3396                         (dstwidth,lines,
3397                          srcbits,-bmpImage->bytes_per_line,
3398                          dstbits,linebytes);
3399                 } else {
3400                     /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3401                     /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3402                     X11DRV_DIB_Convert_0888_to_565_asis
3403                         (dstwidth,lines,
3404                          srcbits,-bmpImage->bytes_per_line,
3405                          dstbits,linebytes);
3406                 }
3407             } else {
3408                 if (gDst==0x03e0) {
3409                     /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3410                     /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3411                     X11DRV_DIB_Convert_0888_to_555_reverse
3412                         (dstwidth,lines,
3413                          srcbits,-bmpImage->bytes_per_line,
3414                          dstbits,linebytes);
3415                 } else {
3416                     /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3417                     /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3418                     X11DRV_DIB_Convert_0888_to_565_reverse
3419                         (dstwidth,lines,
3420                          srcbits,-bmpImage->bytes_per_line,
3421                          dstbits,linebytes);
3422                 }
3423             }
3424         }
3425         break;
3426
3427     case 1:
3428     case 4:
3429         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3430             /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3431             int rShift,gShift,bShift;
3432             WORD* dstpixel;
3433
3434             /* Shift everything 16 bits left so that all shifts are >0,
3435              * even for BGR DIBs. Then a single >> 16 will bring everything
3436              * back into place.
3437              */
3438             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3439             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3440             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3441             if (gDst==0x07e0) {
3442                 /* 6 bits for the green */
3443                 gShift++;
3444             }
3445             rDst=rDst << 16;
3446             gDst=gDst << 16;
3447             bDst=bDst << 16;
3448             for (h = lines - 1; h >= 0; h--) {
3449                 dstpixel=(LPWORD)dstbits;
3450                 for (x = 0; x < dstwidth; x++) {
3451                     PALETTEENTRY srcval;
3452                     DWORD dstval;
3453                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
3454                     dstval=((srcval.peRed   << rShift) & rDst) |
3455                            ((srcval.peGreen << gShift) & gDst) |
3456                            ((srcval.peBlue  << bShift) & bDst);
3457                     *dstpixel++=dstval >> 16;
3458                 }
3459                 dstbits += linebytes;
3460             }
3461         } else {
3462             goto notsupported;
3463         }
3464         break;
3465
3466     case 8:
3467         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3468             /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3469             int rShift,gShift,bShift;
3470             const BYTE* srcbits;
3471             const BYTE* srcpixel;
3472             WORD* dstpixel;
3473
3474             /* Shift everything 16 bits left so that all shifts are >0,
3475              * even for BGR DIBs. Then a single >> 16 will bring everything
3476              * back into place.
3477              */
3478             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3479             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3480             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3481             if (gDst==0x07e0) {
3482                 /* 6 bits for the green */
3483                 gShift++;
3484             }
3485             rDst=rDst << 16;
3486             gDst=gDst << 16;
3487             bDst=bDst << 16;
3488             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3489             for (h=0; h<lines; h++) {
3490                 srcpixel=srcbits;
3491                 dstpixel=(LPWORD)dstbits;
3492                 for (x = 0; x < dstwidth; x++) {
3493                     PALETTEENTRY srcval;
3494                     DWORD dstval;
3495                     srcval=srccolors[(int)*srcpixel++];
3496                     dstval=((srcval.peRed   << rShift) & rDst) |
3497                            ((srcval.peGreen << gShift) & gDst) |
3498                            ((srcval.peBlue  << bShift) & bDst);
3499                     *dstpixel++=dstval >> 16;
3500                 }
3501                 srcbits -= bmpImage->bytes_per_line;
3502                 dstbits += linebytes;
3503             }
3504         } else {
3505             goto notsupported;
3506         }
3507         break;
3508
3509     default:
3510     notsupported:
3511         {
3512             /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3513             int rShift,gShift,bShift;
3514             WORD* dstpixel;
3515
3516             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3517                   bmpImage->depth, bmpImage->red_mask,
3518                   bmpImage->green_mask, bmpImage->blue_mask,
3519                   rDst, gDst, bDst);
3520
3521             /* Shift everything 16 bits left so that all shifts are >0,
3522              * even for BGR DIBs. Then a single >> 16 will bring everything
3523              * back into place.
3524              */
3525             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3526             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3527             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3528             if (gDst==0x07e0) {
3529                 /* 6 bits for the green */
3530                 gShift++;
3531             }
3532             rDst=rDst << 16;
3533             gDst=gDst << 16;
3534             bDst=bDst << 16;
3535             for (h = lines - 1; h >= 0; h--) {
3536                 dstpixel=(LPWORD)dstbits;
3537                 for (x = 0; x < dstwidth; x++) {
3538                     COLORREF srcval;
3539                     DWORD dstval;
3540                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3541                     dstval=((GetRValue(srcval) << rShift) & rDst) |
3542                            ((GetGValue(srcval) << gShift) & gDst) |
3543                            ((GetBValue(srcval) << bShift) & bDst);
3544                     *dstpixel++=dstval >> 16;
3545                 }
3546                 dstbits += linebytes;
3547             }
3548         }
3549         break;
3550     }
3551 }
3552
3553
3554 /***********************************************************************
3555  *           X11DRV_DIB_SetImageBits_24
3556  *
3557  * SetDIBits for a 24-bit deep DIB.
3558  */
3559 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3560                                  DWORD srcwidth, DWORD dstwidth, int left,
3561                                  X11DRV_PDEVICE *physDev,
3562                                  DWORD rSrc, DWORD gSrc, DWORD bSrc,
3563                                  XImage *bmpImage, DWORD linebytes )
3564 {
3565     DWORD x;
3566     int h;
3567
3568     if (lines < 0 )
3569     {
3570         lines = -lines;
3571         srcbits = srcbits + linebytes * (lines - 1);
3572         linebytes = -linebytes;
3573     }
3574
3575     switch (bmpImage->depth)
3576     {
3577     case 24:
3578         if (bmpImage->bits_per_pixel==24) {
3579             char* dstbits;
3580
3581             srcbits=srcbits+left*3;
3582             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3583
3584             if (bmpImage->green_mask!=0x00ff00 ||
3585                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3586                 goto notsupported;
3587             } else if (rSrc==bmpImage->red_mask) {
3588                 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3589                 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3590                 X11DRV_DIB_Convert_any_asis
3591                     (dstwidth,lines,3,
3592                      srcbits,linebytes,
3593                      dstbits,-bmpImage->bytes_per_line);
3594             } else {
3595                 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3596                 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3597                 X11DRV_DIB_Convert_888_reverse
3598                     (dstwidth,lines,
3599                      srcbits,linebytes,
3600                      dstbits,-bmpImage->bytes_per_line);
3601             }
3602             break;
3603         }
3604         /* fall through */
3605
3606     case 32:
3607         {
3608             char* dstbits;
3609
3610             srcbits=srcbits+left*3;
3611             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3612
3613             if (bmpImage->green_mask!=0x00ff00 ||
3614                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3615                 goto notsupported;
3616             } else if (rSrc==bmpImage->red_mask) {
3617                 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3618                 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3619                 X11DRV_DIB_Convert_888_to_0888_asis
3620                     (dstwidth,lines,
3621                      srcbits,linebytes,
3622                      dstbits,-bmpImage->bytes_per_line);
3623             } else {
3624                 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3625                 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3626                 X11DRV_DIB_Convert_888_to_0888_reverse
3627                     (dstwidth,lines,
3628                      srcbits,linebytes,
3629                      dstbits,-bmpImage->bytes_per_line);
3630             }
3631             break;
3632         }
3633
3634     case 15:
3635     case 16:
3636         {
3637             char* dstbits;
3638
3639             srcbits=srcbits+left*3;
3640             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3641
3642             if (bmpImage->green_mask==0x03e0) {
3643                 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3644                     (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3645                     /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3646                     /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3647                     X11DRV_DIB_Convert_888_to_555_asis
3648                         (dstwidth,lines,
3649                          srcbits,linebytes,
3650                          dstbits,-bmpImage->bytes_per_line);
3651                 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3652                            (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3653                     /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3654                     /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3655                     X11DRV_DIB_Convert_888_to_555_reverse
3656                         (dstwidth,lines,
3657                          srcbits,linebytes,
3658                          dstbits,-bmpImage->bytes_per_line);
3659                 } else {
3660                     goto notsupported;
3661                 }
3662             } else if (bmpImage->green_mask==0x07e0) {
3663                 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3664                     (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3665                     /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3666                     /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3667                     X11DRV_DIB_Convert_888_to_565_asis
3668                         (dstwidth,lines,
3669                          srcbits,linebytes,
3670                          dstbits,-bmpImage->bytes_per_line);
3671                 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3672                            (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3673                     /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3674                     /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3675                     X11DRV_DIB_Convert_888_to_565_reverse
3676                         (dstwidth,lines,
3677                          srcbits,linebytes,
3678                          dstbits,-bmpImage->bytes_per_line);
3679                 } else {
3680                     goto notsupported;
3681                 }
3682             } else {
3683                 goto notsupported;
3684             }
3685         }
3686         break;
3687
3688     default:
3689     notsupported:
3690         WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3691               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3692               bmpImage->green_mask, bmpImage->blue_mask );
3693         /* fall through */
3694     case 1:
3695     case 4:
3696     case 8:
3697         {
3698             /* ==== rgb 888 dib -> any bmp bormat ==== */
3699             const BYTE* srcbyte;
3700
3701             /* Windows only supports one 24bpp DIB format: RGB888 */
3702             srcbits+=left*3;
3703             for (h = lines - 1; h >= 0; h--) {
3704                 srcbyte=(const BYTE*)srcbits;
3705                 for (x = left; x < dstwidth+left; x++) {
3706                     XPutPixel(bmpImage, x, h,
3707                               X11DRV_PALETTE_ToPhysical
3708                               (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3709                     srcbyte+=3;
3710                 }
3711                 srcbits += linebytes;
3712             }
3713         }
3714         break;
3715     }
3716 }
3717
3718
3719 /***********************************************************************
3720  *           X11DRV_DIB_GetImageBits_24
3721  *
3722  * GetDIBits for an 24-bit deep DIB.
3723  */
3724 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3725                                         DWORD dstwidth, DWORD srcwidth,
3726                                         PALETTEENTRY *srccolors,
3727                                         DWORD rDst, DWORD gDst, DWORD bDst,
3728                                         XImage *bmpImage, DWORD linebytes )
3729 {
3730     DWORD x;
3731     int h;
3732
3733     if (lines < 0 )
3734     {
3735         lines = -lines;
3736         dstbits = dstbits + ( linebytes * (lines-1) );
3737         linebytes = -linebytes;
3738     }
3739
3740     switch (bmpImage->depth)
3741     {
3742     case 24:
3743         if (bmpImage->bits_per_pixel==24) {
3744             const char* srcbits;
3745
3746             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3747
3748             if (bmpImage->green_mask!=0x00ff00 ||
3749                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3750                 goto notsupported;
3751             } else if (rDst==bmpImage->red_mask) {
3752                 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3753                 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3754                 X11DRV_DIB_Convert_any_asis
3755                     (dstwidth,lines,3,
3756                      srcbits,-bmpImage->bytes_per_line,
3757                      dstbits,linebytes);
3758             } else {
3759                 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3760                 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3761                 X11DRV_DIB_Convert_888_reverse
3762                     (dstwidth,lines,
3763                      srcbits,-bmpImage->bytes_per_line,
3764                      dstbits,linebytes);
3765             }
3766             break;
3767         }
3768         /* fall through */
3769
3770     case 32:
3771         {
3772             const char* srcbits;
3773
3774             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3775
3776             if (bmpImage->green_mask!=0x00ff00 ||
3777                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3778                 goto notsupported;
3779             } else if (rDst==bmpImage->red_mask) {
3780                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3781                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3782                 X11DRV_DIB_Convert_0888_to_888_asis
3783                     (dstwidth,lines,
3784                      srcbits,-bmpImage->bytes_per_line,
3785                      dstbits,linebytes);
3786             } else {
3787                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3788                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3789                 X11DRV_DIB_Convert_0888_to_888_reverse
3790                     (dstwidth,lines,
3791                      srcbits,-bmpImage->bytes_per_line,
3792                      dstbits,linebytes);
3793             }
3794             break;
3795         }
3796
3797     case 15:
3798     case 16:
3799         {
3800             const char* srcbits;
3801
3802             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3803
3804             if (bmpImage->green_mask==0x03e0) {
3805                 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3806                     (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3807                     /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3808                     /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3809                     X11DRV_DIB_Convert_555_to_888_asis
3810                         (dstwidth,lines,
3811                          srcbits,-bmpImage->bytes_per_line,
3812                          dstbits,linebytes);
3813                 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3814                            (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3815                     /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3816                     /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3817                     X11DRV_DIB_Convert_555_to_888_reverse
3818                         (dstwidth,lines,
3819                          srcbits,-bmpImage->bytes_per_line,
3820                          dstbits,linebytes);
3821                 } else {
3822                     goto notsupported;
3823                 }
3824             } else if (bmpImage->green_mask==0x07e0) {
3825                 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3826                     (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3827                     /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3828                     /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3829                     X11DRV_DIB_Convert_565_to_888_asis
3830                         (dstwidth,lines,
3831                          srcbits,-bmpImage->bytes_per_line,
3832                          dstbits,linebytes);
3833                 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3834                            (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3835                     /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3836                     /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3837                     X11DRV_DIB_Convert_565_to_888_reverse
3838                         (dstwidth,lines,
3839                          srcbits,-bmpImage->bytes_per_line,
3840                          dstbits,linebytes);
3841                 } else {
3842                     goto notsupported;
3843                 }
3844             } else {
3845                 goto notsupported;
3846             }
3847         }
3848         break;
3849
3850     case 1:
3851     case 4:
3852         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3853             /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3854             BYTE* dstbyte;
3855
3856             /* Windows only supports one 24bpp DIB format: rgb 888 */
3857             for (h = lines - 1; h >= 0; h--) {
3858                 dstbyte=dstbits;
3859                 for (x = 0; x < dstwidth; x++) {
3860                     PALETTEENTRY srcval;
3861                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
3862                     dstbyte[0]=srcval.peBlue;
3863                     dstbyte[1]=srcval.peGreen;
3864                     dstbyte[2]=srcval.peRed;
3865                     dstbyte+=3;
3866                 }
3867                 dstbits += linebytes;
3868             }
3869         } else {
3870             goto notsupported;
3871         }
3872         break;
3873
3874     case 8:
3875         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3876             /* ==== pal 8 bmp -> rgb 888 dib ==== */
3877             const void* srcbits;
3878             const BYTE* srcpixel;
3879             BYTE* dstbyte;
3880
3881             /* Windows only supports one 24bpp DIB format: rgb 888 */
3882             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3883             for (h = lines - 1; h >= 0; h--) {
3884                 srcpixel=srcbits;
3885                 dstbyte=dstbits;
3886                 for (x = 0; x < dstwidth; x++ ) {
3887                     PALETTEENTRY srcval;
3888                     srcval=srccolors[(int)*srcpixel++];
3889                     dstbyte[0]=srcval.peBlue;
3890                     dstbyte[1]=srcval.peGreen;
3891                     dstbyte[2]=srcval.peRed;
3892                     dstbyte+=3;
3893                 }
3894                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3895                 dstbits += linebytes;
3896             }
3897         } else {
3898             goto notsupported;
3899         }
3900         break;
3901
3902     default:
3903     notsupported:
3904         {
3905             /* ==== any bmp format -> 888 dib ==== */
3906             BYTE* dstbyte;
3907
3908             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3909                   bmpImage->depth, bmpImage->red_mask,
3910                   bmpImage->green_mask, bmpImage->blue_mask,
3911                   rDst, gDst, bDst );
3912
3913             /* Windows only supports one 24bpp DIB format: rgb 888 */
3914             for (h = lines - 1; h >= 0; h--) {
3915                 dstbyte=dstbits;
3916                 for (x = 0; x < dstwidth; x++) {
3917                     COLORREF srcval=X11DRV_PALETTE_ToLogical
3918                         (XGetPixel( bmpImage, x, h ));
3919                     dstbyte[0]=GetBValue(srcval);
3920                     dstbyte[1]=GetGValue(srcval);
3921                     dstbyte[2]=GetRValue(srcval);
3922                     dstbyte+=3;
3923                 }
3924                 dstbits += linebytes;
3925             }
3926         }
3927         break;
3928     }
3929 }
3930
3931
3932 /***********************************************************************
3933  *           X11DRV_DIB_SetImageBits_32
3934  *
3935  * SetDIBits for a 32-bit deep DIB.
3936  */
3937 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3938                                        DWORD srcwidth, DWORD dstwidth, int left,
3939                                        X11DRV_PDEVICE *physDev,
3940                                        DWORD rSrc, DWORD gSrc, DWORD bSrc,
3941                                        XImage *bmpImage,
3942                                        DWORD linebytes)
3943 {
3944     DWORD x, *ptr;
3945     int h;
3946
3947     if (lines < 0 )
3948     {
3949        lines = -lines;
3950        srcbits = srcbits + ( linebytes * (lines-1) );
3951        linebytes = -linebytes;
3952     }
3953
3954     ptr = (DWORD *) srcbits + left;
3955
3956     switch (bmpImage->depth)
3957     {
3958     case 24:
3959         if (bmpImage->bits_per_pixel==24) {
3960             char* dstbits;
3961
3962             srcbits=srcbits+left*4;
3963             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3964
3965             if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3966                 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3967                 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3968                 X11DRV_DIB_Convert_0888_to_888_asis
3969                     (dstwidth,lines,
3970                      srcbits,linebytes,
3971                      dstbits,-bmpImage->bytes_per_line);
3972             } else if (bmpImage->green_mask!=0x00ff00 ||
3973                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3974                 goto notsupported;
3975                 /* the tests below assume sane bmpImage masks */
3976             } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3977                 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3978                 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3979                 X11DRV_DIB_Convert_0888_to_888_reverse
3980                     (dstwidth,lines,
3981                      srcbits,linebytes,
3982                      dstbits,-bmpImage->bytes_per_line);
3983             } else if (bmpImage->blue_mask==0xff) {
3984                 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3985                 X11DRV_DIB_Convert_any0888_to_rgb888
3986                     (dstwidth,lines,
3987                      srcbits,linebytes,
3988                      rSrc,gSrc,bSrc,
3989                      dstbits,-bmpImage->bytes_per_line);
3990             } else {
3991                 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3992                 X11DRV_DIB_Convert_any0888_to_bgr888
3993                     (dstwidth,lines,
3994                      srcbits,linebytes,
3995                      rSrc,gSrc,bSrc,
3996                      dstbits,-bmpImage->bytes_per_line);
3997             }
3998             break;
3999         }
4000         /* fall through */
4001
4002     case 32:
4003         {
4004             char* dstbits;
4005
4006             srcbits=srcbits+left*4;
4007             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
4008
4009             if (gSrc==bmpImage->green_mask) {
4010                 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
4011                     /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
4012                     /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
4013                     X11DRV_DIB_Convert_any_asis
4014                         (dstwidth,lines,4,
4015                          srcbits,linebytes,
4016                          dstbits,-bmpImage->bytes_per_line);
4017                 } else if (bmpImage->green_mask!=0x00ff00 ||
4018                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4019                     goto notsupported;
4020                     /* the tests below assume sane bmpImage masks */
4021                 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
4022                     /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
4023                     /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
4024                     X11DRV_DIB_Convert_0888_reverse
4025                         (dstwidth,lines,
4026                          srcbits,linebytes,
4027                          dstbits,-bmpImage->bytes_per_line);
4028                 } else {
4029                     /* ==== any 0888 dib -> any 0888 bmp ==== */
4030                     X11DRV_DIB_Convert_0888_any
4031                         (dstwidth,lines,
4032                          srcbits,linebytes,
4033                          rSrc,gSrc,bSrc,
4034                          dstbits,-bmpImage->bytes_per_line,
4035                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4036                 }
4037             } else if (bmpImage->green_mask!=0x00ff00 ||
4038                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4039                 goto notsupported;
4040                 /* the tests below assume sane bmpImage masks */
4041             } else {
4042                 /* ==== any 0888 dib -> any 0888 bmp ==== */
4043                 X11DRV_DIB_Convert_0888_any
4044                     (dstwidth,lines,
4045                      srcbits,linebytes,
4046                      rSrc,gSrc,bSrc,
4047                      dstbits,-bmpImage->bytes_per_line,
4048                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4049             }
4050         }
4051         break;
4052
4053     case 15:
4054     case 16:
4055         {
4056             char* dstbits;
4057
4058             srcbits=srcbits+left*4;
4059             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4060
4061             if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4062                 if (bmpImage->green_mask==0x03e0) {
4063                     if (bmpImage->red_mask==0x7f00) {
4064                         /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4065                         X11DRV_DIB_Convert_0888_to_555_asis
4066                             (dstwidth,lines,
4067                              srcbits,linebytes,
4068                              dstbits,-bmpImage->bytes_per_line);
4069                     } else if (bmpImage->blue_mask==0x7f00) {
4070                         /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4071                         X11DRV_DIB_Convert_0888_to_555_reverse
4072                             (dstwidth,lines,
4073                              srcbits,linebytes,
4074                              dstbits,-bmpImage->bytes_per_line);
4075                     } else {
4076                         goto notsupported;
4077                     }
4078                 } else if (bmpImage->green_mask==0x07e0) {
4079                     if (bmpImage->red_mask==0xf800) {
4080                         /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4081                         X11DRV_DIB_Convert_0888_to_565_asis
4082                             (dstwidth,lines,
4083                              srcbits,linebytes,
4084                              dstbits,-bmpImage->bytes_per_line);
4085                     } else if (bmpImage->blue_mask==0xf800) {
4086                         /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4087                         X11DRV_DIB_Convert_0888_to_565_reverse
4088                             (dstwidth,lines,
4089                              srcbits,linebytes,
4090                              dstbits,-bmpImage->bytes_per_line);
4091                     } else {
4092                         goto notsupported;
4093                     }
4094                 } else {
4095                     goto notsupported;
4096                 }
4097             } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4098                 if (bmpImage->green_mask==0x03e0) {
4099                     if (bmpImage->blue_mask==0x7f00) {
4100                         /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4101                         X11DRV_DIB_Convert_0888_to_555_asis
4102                             (dstwidth,lines,
4103                              srcbits,linebytes,
4104                              dstbits,-bmpImage->bytes_per_line);
4105                     } else if (bmpImage->red_mask==0x7f00) {
4106                         /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4107                         X11DRV_DIB_Convert_0888_to_555_reverse
4108                             (dstwidth,lines,
4109                              srcbits,linebytes,
4110                              dstbits,-bmpImage->bytes_per_line);
4111                     } else {
4112                         goto notsupported;
4113                     }
4114                 } else if (bmpImage->green_mask==0x07e0) {
4115                     if (bmpImage->blue_mask==0xf800) {
4116                         /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4117                         X11DRV_DIB_Convert_0888_to_565_asis
4118                             (dstwidth,lines,
4119                              srcbits,linebytes,
4120                              dstbits,-bmpImage->bytes_per_line);
4121                     } else if (bmpImage->red_mask==0xf800) {
4122                         /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4123                         X11DRV_DIB_Convert_0888_to_565_reverse
4124                             (dstwidth,lines,
4125                              srcbits,linebytes,
4126                              dstbits,-bmpImage->bytes_per_line);
4127                     } else {
4128                         goto notsupported;
4129                     }
4130                 } else {
4131                     goto notsupported;
4132                 }
4133             } else {
4134                 if (bmpImage->green_mask==0x03e0 &&
4135                     (bmpImage->red_mask==0x7f00 ||
4136                      bmpImage->blue_mask==0x7f00)) {
4137                     /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4138                     X11DRV_DIB_Convert_any0888_to_5x5
4139                         (dstwidth,lines,
4140                          srcbits,linebytes,
4141                          rSrc,gSrc,bSrc,
4142                          dstbits,-bmpImage->bytes_per_line,
4143                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4144                 } else if (bmpImage->green_mask==0x07e0 &&
4145                            (bmpImage->red_mask==0xf800 ||
4146                             bmpImage->blue_mask==0xf800)) {
4147                     /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4148                     X11DRV_DIB_Convert_any0888_to_5x5
4149                         (dstwidth,lines,
4150                          srcbits,linebytes,
4151                          rSrc,gSrc,bSrc,
4152                          dstbits,-bmpImage->bytes_per_line,
4153                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4154                 } else {
4155                     goto notsupported;
4156                 }
4157             }
4158         }
4159         break;
4160
4161     default:
4162     notsupported:
4163         WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4164               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4165               bmpImage->green_mask, bmpImage->blue_mask );
4166         /* fall through */
4167     case 1:
4168     case 4:
4169     case 8:
4170         {
4171             /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4172             const DWORD* srcpixel;
4173             int rShift,gShift,bShift;
4174
4175             rShift=X11DRV_DIB_MaskToShift(rSrc);
4176             gShift=X11DRV_DIB_MaskToShift(gSrc);
4177             bShift=X11DRV_DIB_MaskToShift(bSrc);
4178             srcbits+=left*4;
4179             for (h = lines - 1; h >= 0; h--) {
4180                 srcpixel=(const DWORD*)srcbits;
4181                 for (x = left; x < dstwidth+left; x++) {
4182                     DWORD srcvalue;
4183                     BYTE red,green,blue;
4184                     srcvalue=*srcpixel++;
4185                     red=  (srcvalue >> rShift) & 0xff;
4186                     green=(srcvalue >> gShift) & 0xff;
4187                     blue= (srcvalue >> bShift) & 0xff;
4188                     XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4189                               (physDev, RGB(red,green,blue)));
4190                 }
4191                 srcbits += linebytes;
4192             }
4193         }
4194         break;
4195     }
4196
4197 }
4198
4199 /***********************************************************************
4200  *           X11DRV_DIB_GetImageBits_32
4201  *
4202  * GetDIBits for an 32-bit deep DIB.
4203  */
4204 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4205                                         DWORD dstwidth, DWORD srcwidth,
4206                                         PALETTEENTRY *srccolors,
4207                                         DWORD rDst, DWORD gDst, DWORD bDst,
4208                                         XImage *bmpImage, DWORD linebytes )
4209 {
4210     DWORD x;
4211     int h;
4212     BYTE *bits;
4213
4214     if (lines < 0 )
4215     {
4216         lines = -lines;
4217         dstbits = dstbits + ( linebytes * (lines-1) );
4218         linebytes = -linebytes;
4219     }
4220
4221     bits = dstbits;
4222
4223     switch (bmpImage->depth)
4224     {
4225     case 24:
4226         if (bmpImage->bits_per_pixel==24) {
4227             const void* srcbits;
4228
4229             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4230
4231             if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4232                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4233                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4234                 X11DRV_DIB_Convert_888_to_0888_asis
4235                     (dstwidth,lines,
4236                      srcbits,-bmpImage->bytes_per_line,
4237                      dstbits,linebytes);
4238             } else if (bmpImage->green_mask!=0x00ff00 ||
4239                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4240                 goto notsupported;
4241                 /* the tests below assume sane bmpImage masks */
4242             } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4243                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4244                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4245                 X11DRV_DIB_Convert_888_to_0888_reverse
4246                     (dstwidth,lines,
4247                      srcbits,-bmpImage->bytes_per_line,
4248                      dstbits,linebytes);
4249             } else if (bmpImage->blue_mask==0xff) {
4250                 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4251                 X11DRV_DIB_Convert_rgb888_to_any0888
4252                     (dstwidth,lines,
4253                      srcbits,-bmpImage->bytes_per_line,
4254                      dstbits,linebytes,
4255                      rDst,gDst,bDst);
4256             } else {
4257                 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4258                 X11DRV_DIB_Convert_bgr888_to_any0888
4259                     (dstwidth,lines,
4260                      srcbits,-bmpImage->bytes_per_line,
4261                      dstbits,linebytes,
4262                      rDst,gDst,bDst);
4263             }
4264             break;
4265         }
4266         /* fall through */
4267
4268     case 32:
4269         {
4270             const char* srcbits;
4271
4272             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4273
4274             if (gDst==bmpImage->green_mask) {
4275                 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4276                     /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4277                     /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4278                     X11DRV_DIB_Convert_any_asis
4279                         (dstwidth,lines,4,
4280                          srcbits,-bmpImage->bytes_per_line,
4281                          dstbits,linebytes);
4282                 } else if (bmpImage->green_mask!=0x00ff00 ||
4283                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4284                     goto notsupported;
4285                     /* the tests below assume sane bmpImage masks */
4286                 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
4287                     /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4288                     /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4289                     X11DRV_DIB_Convert_0888_reverse
4290                         (dstwidth,lines,
4291                          srcbits,-bmpImage->bytes_per_line,
4292                          dstbits,linebytes);
4293                 } else {
4294                     /* ==== any 0888 bmp -> any 0888 dib ==== */
4295                     X11DRV_DIB_Convert_0888_any
4296                         (dstwidth,lines,
4297                          srcbits,-bmpImage->bytes_per_line,
4298                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4299                          dstbits,linebytes,
4300                          rDst,gDst,bDst);
4301                 }
4302             } else if (bmpImage->green_mask!=0x00ff00 ||
4303                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4304                 goto notsupported;
4305                 /* the tests below assume sane bmpImage masks */
4306             } else {
4307                 /* ==== any 0888 bmp -> any 0888 dib ==== */
4308                 X11DRV_DIB_Convert_0888_any
4309                     (dstwidth,lines,
4310                      srcbits,-bmpImage->bytes_per_line,
4311                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4312                      dstbits,linebytes,
4313                      rDst,gDst,bDst);
4314             }
4315         }
4316         break;
4317
4318     case 15:
4319     case 16:
4320         {
4321             const char* srcbits;
4322
4323             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4324
4325             if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4326                 if (bmpImage->green_mask==0x03e0) {
4327                     if (bmpImage->red_mask==0x7f00) {
4328                         /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4329                         X11DRV_DIB_Convert_555_to_0888_asis
4330                             (dstwidth,lines,
4331                              srcbits,-bmpImage->bytes_per_line,
4332                              dstbits,linebytes);
4333                     } else if (bmpImage->blue_mask==0x7f00) {
4334                         /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4335                         X11DRV_DIB_Convert_555_to_0888_reverse
4336                             (dstwidth,lines,
4337                              srcbits,-bmpImage->bytes_per_line,
4338                              dstbits,linebytes);
4339                     } else {
4340                         goto notsupported;
4341                     }
4342                 } else if (bmpImage->green_mask==0x07e0) {
4343                     if (bmpImage->red_mask==0xf800) {
4344                         /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4345                         X11DRV_DIB_Convert_565_to_0888_asis
4346                             (dstwidth,lines,
4347                              srcbits,-bmpImage->bytes_per_line,
4348                              dstbits,linebytes);
4349                     } else if (bmpImage->blue_mask==0xf800) {
4350                         /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4351                         X11DRV_DIB_Convert_565_to_0888_reverse
4352                             (dstwidth,lines,
4353                              srcbits,-bmpImage->bytes_per_line,
4354                              dstbits,linebytes);
4355                     } else {
4356                         goto notsupported;
4357                     }
4358                 } else {
4359                     goto notsupported;
4360                 }
4361             } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4362                 if (bmpImage->green_mask==0x03e0) {
4363                     if (bmpImage->blue_mask==0x7f00) {
4364                         /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4365                         X11DRV_DIB_Convert_555_to_0888_asis
4366                             (dstwidth,lines,
4367                              srcbits,-bmpImage->bytes_per_line,
4368                              dstbits,linebytes);
4369                     } else if (bmpImage->red_mask==0x7f00) {
4370                         /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4371                         X11DRV_DIB_Convert_555_to_0888_reverse
4372                             (dstwidth,lines,
4373                              srcbits,-bmpImage->bytes_per_line,
4374                              dstbits,linebytes);
4375                     } else {
4376                         goto notsupported;
4377                     }
4378                 } else if (bmpImage->green_mask==0x07e0) {
4379                     if (bmpImage->blue_mask==0xf800) {
4380                         /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4381                         X11DRV_DIB_Convert_565_to_0888_asis
4382                             (dstwidth,lines,
4383                              srcbits,-bmpImage->bytes_per_line,
4384                              dstbits,linebytes);
4385                     } else if (bmpImage->red_mask==0xf800) {
4386                         /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4387                         X11DRV_DIB_Convert_565_to_0888_reverse
4388                             (dstwidth,lines,
4389                              srcbits,-bmpImage->bytes_per_line,
4390                              dstbits,linebytes);
4391                     } else {
4392                         goto notsupported;
4393                     }
4394                 } else {
4395                     goto notsupported;
4396                 }
4397             } else {
4398                 if (bmpImage->green_mask==0x03e0 &&
4399                     (bmpImage->red_mask==0x7f00 ||
4400                      bmpImage->blue_mask==0x7f00)) {
4401                     /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4402                     X11DRV_DIB_Convert_5x5_to_any0888
4403                         (dstwidth,lines,
4404                          srcbits,-bmpImage->bytes_per_line,
4405                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4406                          dstbits,linebytes,
4407                          rDst,gDst,bDst);
4408                 } else if (bmpImage->green_mask==0x07e0 &&
4409                            (bmpImage->red_mask==0xf800 ||
4410                             bmpImage->blue_mask==0xf800)) {
4411                     /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4412                     X11DRV_DIB_Convert_5x5_to_any0888
4413                         (dstwidth,lines,
4414                          srcbits,-bmpImage->bytes_per_line,
4415                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4416                          dstbits,linebytes,
4417                          rDst,gDst,bDst);
4418                 } else {
4419                     goto notsupported;
4420                 }
4421             }
4422         }
4423         break;
4424
4425     case 1:
4426     case 4:
4427         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4428             /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4429             int rShift,gShift,bShift;
4430             DWORD* dstpixel;
4431
4432             rShift=X11DRV_DIB_MaskToShift(rDst);
4433             gShift=X11DRV_DIB_MaskToShift(gDst);
4434             bShift=X11DRV_DIB_MaskToShift(bDst);
4435             for (h = lines - 1; h >= 0; h--) {
4436                 dstpixel=(DWORD*)dstbits;
4437                 for (x = 0; x < dstwidth; x++) {
4438                     PALETTEENTRY srcval;
4439                     srcval = srccolors[XGetPixel(bmpImage, x, h)];
4440                     *dstpixel++=(srcval.peRed   << rShift) |
4441                                 (srcval.peGreen << gShift) |
4442                                 (srcval.peBlue  << bShift);
4443                 }
4444                 dstbits += linebytes;
4445             }
4446         } else {
4447             goto notsupported;
4448         }
4449         break;
4450
4451     case 8:
4452         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4453             /* ==== pal 8 bmp -> any 0888 dib ==== */
4454             int rShift,gShift,bShift;
4455             const void* srcbits;
4456             const BYTE* srcpixel;
4457             DWORD* dstpixel;
4458
4459             rShift=X11DRV_DIB_MaskToShift(rDst);
4460             gShift=X11DRV_DIB_MaskToShift(gDst);
4461             bShift=X11DRV_DIB_MaskToShift(bDst);
4462             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4463             for (h = lines - 1; h >= 0; h--) {
4464                 srcpixel=srcbits;
4465                 dstpixel=(DWORD*)dstbits;
4466                 for (x = 0; x < dstwidth; x++) {
4467                     PALETTEENTRY srcval;
4468                     srcval=srccolors[(int)*srcpixel++];
4469                     *dstpixel++=(srcval.peRed   << rShift) |
4470                                 (srcval.peGreen << gShift) |
4471                                 (srcval.peBlue  << bShift);
4472                 }
4473                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
4474                 dstbits += linebytes;
4475             }
4476         } else {
4477             goto notsupported;
4478         }
4479         break;
4480
4481     default:
4482     notsupported:
4483         {
4484             /* ==== any bmp format -> any 0888 dib ==== */
4485             int rShift,gShift,bShift;
4486             DWORD* dstpixel;
4487
4488             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4489                   bmpImage->depth, bmpImage->red_mask,
4490                   bmpImage->green_mask, bmpImage->blue_mask,
4491                   rDst,gDst,bDst);
4492
4493             rShift=X11DRV_DIB_MaskToShift(rDst);
4494             gShift=X11DRV_DIB_MaskToShift(gDst);
4495             bShift=X11DRV_DIB_MaskToShift(bDst);
4496             for (h = lines - 1; h >= 0; h--) {
4497                 dstpixel=(DWORD*)dstbits;
4498                 for (x = 0; x < dstwidth; x++) {
4499                     COLORREF srcval;
4500                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4501                     *dstpixel++=(GetRValue(srcval) << rShift) |
4502                                 (GetGValue(srcval) << gShift) |
4503                                 (GetBValue(srcval) << bShift);
4504                 }
4505                 dstbits += linebytes;
4506             }
4507         }
4508         break;
4509     }
4510 }
4511
4512 /***********************************************************************
4513  *           X11DRV_DIB_SetImageBits
4514  *
4515  * Transfer the bits to an X image.
4516  * Helper function for SetDIBits() and SetDIBitsToDevice().
4517  */
4518 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4519 {
4520     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4521     XImage *bmpImage;
4522
4523     wine_tsx11_lock();
4524     if (descr->image)
4525         bmpImage = descr->image;
4526     else {
4527         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4528                                  descr->infoWidth, lines, 32, 0 );
4529         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4530         if(bmpImage->data == NULL) {
4531             ERR("Out of memory!\n");
4532             XDestroyImage( bmpImage );
4533             wine_tsx11_unlock();
4534             return lines;
4535         }
4536     }
4537
4538     TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4539           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4540     TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4541           bmpImage->depth,bmpImage->bits_per_pixel,
4542           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4543
4544       /* Transfer the pixels */
4545     switch(descr->infoBpp)
4546     {
4547     case 1:
4548         X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4549                                    descr->width, descr->xSrc, (int *)(descr->colorMap),
4550                                    bmpImage, descr->dibpitch );
4551         break;
4552     case 4:
4553         if (descr->compression) {
4554             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4555                           descr->width, descr->height, AllPlanes, ZPixmap,
4556                           bmpImage, descr->xSrc, descr->ySrc );
4557
4558             X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4559                                           descr->infoWidth, descr->width,
4560                                           descr->xSrc, (int *)(descr->colorMap),
4561                                           bmpImage );
4562         } else
4563             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4564                                        descr->infoWidth, descr->width,
4565                                        descr->xSrc, (int*)(descr->colorMap),
4566                                        bmpImage, descr->dibpitch );
4567         break;
4568     case 8:
4569         if (descr->compression) {
4570             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4571                           descr->width, descr->height, AllPlanes, ZPixmap,
4572                           bmpImage, descr->xSrc, descr->ySrc );
4573             X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4574                                           descr->infoWidth, descr->width,
4575                                           descr->xSrc, (int *)(descr->colorMap),
4576                                           bmpImage );
4577         } else
4578             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4579                                        descr->infoWidth, descr->width,
4580                                        descr->xSrc, (int *)(descr->colorMap),
4581                                        bmpImage, descr->dibpitch );
4582         break;
4583     case 15:
4584     case 16:
4585         X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4586                                     descr->infoWidth, descr->width,
4587                                    descr->xSrc, descr->physDev,
4588                                    descr->rMask, descr->gMask, descr->bMask,
4589                                    bmpImage, descr->dibpitch);
4590         break;
4591     case 24:
4592         X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4593                                     descr->infoWidth, descr->width,
4594                                     descr->xSrc, descr->physDev,
4595                                     descr->rMask, descr->gMask, descr->bMask,
4596                                     bmpImage, descr->dibpitch);
4597         break;
4598     case 32:
4599         X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4600                                     descr->infoWidth, descr->width,
4601                                    descr->xSrc, descr->physDev,
4602                                    descr->rMask, descr->gMask, descr->bMask,
4603                                    bmpImage, descr->dibpitch);
4604         break;
4605     default:
4606         WARN("(%d): Invalid depth\n", descr->infoBpp );
4607         break;
4608     }
4609
4610     TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4611      descr->drawable, descr->gc, bmpImage,
4612      descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4613      descr->width, descr->height);
4614 #ifdef HAVE_LIBXXSHM
4615     if (descr->useShm)
4616     {
4617         XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4618                       descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4619                       descr->width, descr->height, FALSE );
4620         XSync( gdi_display, 0 );
4621     }
4622     else
4623 #endif
4624         XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4625                    descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4626                    descr->width, descr->height );
4627
4628     if (!descr->image) XDestroyImage( bmpImage );
4629     wine_tsx11_unlock();
4630     return lines;
4631 }
4632
4633 /***********************************************************************
4634  *           X11DRV_DIB_GetImageBits
4635  *
4636  * Transfer the bits from an X image.
4637  */
4638 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4639 {
4640     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4641     XImage *bmpImage;
4642
4643     wine_tsx11_lock();
4644    if (descr->image)
4645         bmpImage = descr->image;
4646     else {
4647         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4648                                  descr->infoWidth, lines, 32, 0 );
4649         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4650         if(bmpImage->data == NULL) {
4651             ERR("Out of memory!\n");
4652             XDestroyImage( bmpImage );
4653             wine_tsx11_unlock();
4654             return lines;
4655         }
4656     }
4657
4658 #ifdef HAVE_LIBXXSHM
4659     if (descr->useShm)
4660     {
4661         int saveRed, saveGreen, saveBlue;
4662
4663         TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4664                             gdi_display, descr->drawable, bmpImage,
4665                             descr->xSrc, descr->ySrc, AllPlanes);
4666
4667         /* We must save and restore the bmpImage's masks in order
4668          * to preserve them across the call to XShmGetImage, which
4669          * decides to eleminate them since it doesn't happen to know
4670          * what the format of the image is supposed to be, even though
4671          * we do. */
4672         saveRed = bmpImage->red_mask;
4673         saveBlue= bmpImage->blue_mask;
4674         saveGreen = bmpImage->green_mask;
4675
4676         XShmGetImage( gdi_display, descr->drawable, bmpImage,
4677                       descr->xSrc, descr->ySrc, AllPlanes);
4678
4679         bmpImage->red_mask = saveRed;
4680         bmpImage->blue_mask = saveBlue;
4681         bmpImage->green_mask = saveGreen;
4682     }
4683     else
4684 #endif /* HAVE_LIBXXSHM */
4685     {
4686         TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4687               gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4688               lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4689         XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4690                       descr->width, lines, AllPlanes, ZPixmap,
4691                       bmpImage, descr->xDest, descr->yDest );
4692     }
4693
4694     TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4695           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4696     TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4697           bmpImage->depth,bmpImage->bits_per_pixel,
4698           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4699       /* Transfer the pixels */
4700     switch(descr->infoBpp)
4701     {
4702     case 1:
4703           X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4704                                      descr->infoWidth, descr->width,
4705                                      descr->colorMap, descr->palentry,
4706                                      bmpImage, descr->dibpitch );
4707        break;
4708
4709     case 4:
4710        if (descr->compression)
4711            FIXME("Compression not yet supported!\n");
4712        else
4713            X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4714                                       descr->infoWidth, descr->width,
4715                                       descr->colorMap, descr->palentry,
4716                                       bmpImage, descr->dibpitch );
4717        break;
4718
4719     case 8:
4720        if (descr->compression)
4721            FIXME("Compression not yet supported!\n");
4722        else
4723            X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4724                                       descr->infoWidth, descr->width,
4725                                       descr->colorMap, descr->palentry,
4726                                       bmpImage, descr->dibpitch );
4727        break;
4728     case 15:
4729     case 16:
4730        X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4731                                    descr->infoWidth,descr->width,
4732                                    descr->palentry,
4733                                    descr->rMask, descr->gMask, descr->bMask,
4734                                    bmpImage, descr->dibpitch );
4735        break;
4736
4737     case 24:
4738        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4739                                    descr->infoWidth,descr->width,
4740                                    descr->palentry,
4741                                    descr->rMask, descr->gMask, descr->bMask,
4742                                    bmpImage, descr->dibpitch);
4743        break;
4744
4745     case 32:
4746        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4747                                    descr->infoWidth, descr->width,
4748                                    descr->palentry,
4749                                    descr->rMask, descr->gMask, descr->bMask,
4750                                    bmpImage, descr->dibpitch);
4751        break;
4752
4753     default:
4754         WARN("(%d): Invalid depth\n", descr->infoBpp );
4755         break;
4756     }
4757
4758     if (!descr->image) XDestroyImage( bmpImage );
4759     wine_tsx11_unlock();
4760     return lines;
4761 }
4762
4763 /*************************************************************************
4764  *              X11DRV_SetDIBitsToDevice
4765  *
4766  */
4767 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
4768                                 DWORD cy, INT xSrc, INT ySrc,
4769                                 UINT startscan, UINT lines, LPCVOID bits,
4770                                 const BITMAPINFO *info, UINT coloruse )
4771 {
4772     X11DRV_DIB_IMAGEBITS_DESCR descr;
4773     DWORD width;
4774     INT result;
4775     int height;
4776     BOOL top_down;
4777     POINT pt;
4778     DC *dc = physDev->dc;
4779
4780     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4781                            &descr.infoBpp, &descr.compression ) == -1)
4782         return 0;
4783     top_down = (height < 0);
4784     if (top_down) height = -height;
4785
4786     pt.x = xDest;
4787     pt.y = yDest;
4788     LPtoDP(physDev->hdc, &pt, 1);
4789
4790     if (!lines || (startscan >= height)) return 0;
4791     if (!top_down && startscan + lines > height) lines = height - startscan;
4792
4793     /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
4794      * and clamp all values to fit inside [startscan,startscan+lines]
4795      */
4796     if (ySrc + cy <= startscan + lines)
4797     {
4798         INT y = startscan + lines - (ySrc + cy);
4799         if (ySrc < startscan) cy -= (startscan - ySrc);
4800         if (!top_down)
4801         {
4802             /* avoid getting unnecessary lines */
4803             ySrc = 0;
4804             if (y >= lines) return 0;
4805             lines -= y;
4806         }
4807         else
4808         {
4809             if (y >= lines) return lines;
4810             ySrc = y;  /* need to get all lines in top down mode */
4811         }
4812     }
4813     else
4814     {
4815         if (ySrc >= startscan + lines) return lines;
4816         pt.y += ySrc + cy - (startscan + lines);
4817         cy = startscan + lines - ySrc;
4818         ySrc = 0;
4819         if (cy > lines) cy = lines;
4820     }
4821     if (xSrc >= width) return lines;
4822     if (xSrc + cx >= width) cx = width - xSrc;
4823     if (!cx || !cy) return lines;
4824
4825     X11DRV_SetupGCForText( physDev );  /* To have the correct colors */
4826     TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4827
4828     switch (descr.infoBpp)
4829     {
4830        case 1:
4831        case 4:
4832        case 8:
4833                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4834                                             coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
4835                                             dc->bitsPerPixel, info, &descr.nColorMap );
4836                if (!descr.colorMap) return 0;
4837                descr.rMask = descr.gMask = descr.bMask = 0;
4838                break;
4839        case 15:
4840        case 16:
4841                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4842                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
4843                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
4844                descr.colorMap = 0;
4845                break;
4846
4847        case 24:
4848        case 32:
4849                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
4850                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4851                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4852                descr.colorMap = 0;
4853                break;
4854     }
4855
4856     descr.physDev   = physDev;
4857     descr.bits      = bits;
4858     descr.image     = NULL;
4859     descr.palentry  = NULL;
4860     descr.lines     = top_down ? -lines : lines;
4861     descr.infoWidth = width;
4862     descr.depth     = dc->bitsPerPixel;
4863     descr.drawable  = physDev->drawable;
4864     descr.gc        = physDev->gc;
4865     descr.xSrc      = xSrc;
4866     descr.ySrc      = ySrc;
4867     descr.xDest     = physDev->org.x + pt.x;
4868     descr.yDest     = physDev->org.y + pt.y;
4869     descr.width     = cx;
4870     descr.height    = cy;
4871     descr.useShm    = FALSE;
4872     descr.dibpitch  = ((width * descr.infoBpp + 31) &~31) / 8;
4873
4874     result = X11DRV_DIB_SetImageBits( &descr );
4875
4876     if (descr.infoBpp <= 8)
4877        HeapFree(GetProcessHeap(), 0, descr.colorMap);
4878     return result;
4879 }
4880
4881 /***********************************************************************
4882  *           SetDIBits   (X11DRV.@)
4883  */
4884 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
4885                       UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
4886 {
4887   X11DRV_DIB_IMAGEBITS_DESCR descr;
4888   BITMAPOBJ *bmp;
4889   int height, tmpheight;
4890   INT result;
4891
4892   descr.physDev = physDev;
4893
4894   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4895                          &descr.infoBpp, &descr.compression ) == -1)
4896       return 0;
4897
4898   tmpheight = height;
4899   if (height < 0) height = -height;
4900   if (!lines || (startscan >= height))
4901       return 0;
4902
4903   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
4904
4905   if (startscan + lines > height) lines = height - startscan;
4906
4907   switch (descr.infoBpp)
4908   {
4909        case 1:
4910        case 4:
4911        case 8:
4912                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4913                         coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
4914                                                           bmp->bitmap.bmBitsPixel,
4915                                                           info, &descr.nColorMap );
4916                if (!descr.colorMap)
4917                {
4918                    GDI_ReleaseObj( hbitmap );
4919                    return 0;
4920                }
4921                descr.rMask = descr.gMask = descr.bMask = 0;
4922                break;
4923        case 15:
4924        case 16:
4925                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4926                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4927                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4928                descr.colorMap = 0;
4929                break;
4930
4931        case 24:
4932        case 32:
4933                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
4934                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4935                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4936                descr.colorMap = 0;
4937                break;
4938
4939        default: break;
4940   }
4941
4942   descr.bits      = bits;
4943   descr.image     = NULL;
4944   descr.palentry  = NULL;
4945   descr.lines     = tmpheight >= 0 ? lines : -lines;
4946   descr.depth     = bmp->bitmap.bmBitsPixel;
4947   descr.drawable  = (Pixmap)bmp->physBitmap;
4948   descr.gc        = BITMAP_GC(bmp);
4949   descr.xSrc      = 0;
4950   descr.ySrc      = 0;
4951   descr.xDest     = 0;
4952   descr.yDest     = height - startscan - lines;
4953   descr.width     = bmp->bitmap.bmWidth;
4954   descr.height    = lines;
4955   descr.useShm    = FALSE;
4956   descr.dibpitch  = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4957   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
4958   result = X11DRV_DIB_SetImageBits( &descr );
4959   X11DRV_DIB_Unlock(bmp, TRUE);
4960
4961   if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4962
4963   GDI_ReleaseObj( hbitmap );
4964   return result;
4965 }
4966
4967 /***********************************************************************
4968  *           GetDIBits   (X11DRV.@)
4969  */
4970 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
4971                       LPVOID bits, BITMAPINFO *info, UINT coloruse )
4972 {
4973   X11DRV_DIBSECTION *dib;
4974   X11DRV_DIB_IMAGEBITS_DESCR descr;
4975   PALETTEOBJ * palette;
4976   BITMAPOBJ *bmp;
4977   int height;
4978   DC *dc = physDev->dc;
4979
4980   if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4981       return 0;
4982   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
4983   {
4984       GDI_ReleaseObj( dc->hPalette );
4985       return 0;
4986   }
4987   dib = (X11DRV_DIBSECTION *) bmp->dib;
4988
4989   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4990         lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4991         (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4992         startscan );
4993
4994   if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4995
4996   height = info->bmiHeader.biHeight;
4997   if (height < 0) height = -height;
4998   if( lines > height ) lines = height;
4999   /* Top-down images have a negative biHeight, the scanlines of theses images
5000    * were inverted in X11DRV_DIB_GetImageBits_xx
5001    * To prevent this we simply change the sign of lines
5002    * (the number of scan lines to copy).
5003    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
5004    */
5005   if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
5006
5007   if( startscan >= bmp->bitmap.bmHeight )
5008   {
5009       lines = 0;
5010       goto done;
5011   }
5012
5013   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
5014                         &descr.infoBpp, &descr.compression ) == -1)
5015   {
5016       lines = 0;
5017       goto done;
5018   }
5019
5020   switch (descr.infoBpp)
5021   {
5022       case 1:
5023       case 4:
5024       case 8:
5025           descr.rMask= descr.gMask = descr.bMask = 0;
5026           break;
5027       case 15:
5028       case 16:
5029           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
5030           descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
5031           descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
5032           break;
5033       case 24:
5034       case 32:
5035           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
5036           descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x00ff00;
5037           descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x0000ff;
5038           break;
5039   }
5040
5041   descr.physDev   = physDev;
5042   descr.palentry  = palette->logpalette.palPalEntry;
5043   descr.bits      = bits;
5044   descr.image     = NULL;
5045   descr.lines     = lines;
5046   descr.depth     = bmp->bitmap.bmBitsPixel;
5047   descr.drawable  = (Pixmap)bmp->physBitmap;
5048   descr.gc        = BITMAP_GC(bmp);
5049   descr.width     = bmp->bitmap.bmWidth;
5050   descr.height    = bmp->bitmap.bmHeight;
5051   descr.colorMap  = info->bmiColors;
5052   descr.xDest     = 0;
5053   descr.yDest     = 0;
5054   descr.xSrc      = 0;
5055
5056   if (descr.lines > 0)
5057   {
5058      descr.ySrc = (descr.height-1) - (startscan + (lines-1));
5059   }
5060   else
5061   {
5062      descr.ySrc = startscan;
5063   }
5064 #ifdef HAVE_LIBXXSHM
5065   descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
5066 #else
5067   descr.useShm = FALSE;
5068 #endif
5069   descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
5070                        : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
5071
5072   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
5073   X11DRV_DIB_GetImageBits( &descr );
5074   X11DRV_DIB_Unlock(bmp, TRUE);
5075
5076   if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
5077       info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
5078                                          info->bmiHeader.biWidth,
5079                                          info->bmiHeader.biHeight,
5080                                          info->bmiHeader.biBitCount );
5081
5082   if (descr.compression == BI_BITFIELDS)
5083   {
5084     *(DWORD *)info->bmiColors = descr.rMask;
5085     *((DWORD *)info->bmiColors+1) = descr.gMask;
5086     *((DWORD *)info->bmiColors+2) = descr.bMask;
5087   }
5088   else
5089   {
5090     /* if RLE or JPEG compression were supported,
5091      * this line would be invalid. */
5092     info->bmiHeader.biCompression = 0;
5093   }
5094
5095 done:
5096   GDI_ReleaseObj( dc->hPalette );
5097   GDI_ReleaseObj( hbitmap );
5098   return lines;
5099 }
5100
5101 /***********************************************************************
5102  *           DIB_DoProtectDIBSection
5103  */
5104 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5105 {
5106     DIBSECTION *dib = bmp->dib;
5107     INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5108                                              : -dib->dsBm.bmHeight;
5109     /* use the biSizeImage data as the memory size only if we're dealing with a
5110        compressed image where the value is set.  Otherwise, calculate based on
5111        width * height */
5112     INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5113                          ? dib->dsBmih.biSizeImage
5114                          : dib->dsBm.bmWidthBytes * effHeight;
5115     DWORD old_prot;
5116
5117     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5118     TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5119 }
5120
5121 /***********************************************************************
5122  *           X11DRV_DIB_DoUpdateDIBSection
5123  */
5124 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5125                                         void *colorMap, int nColorMap,
5126                                         Drawable dest,
5127                                         DWORD xSrc, DWORD ySrc,
5128                                         DWORD xDest, DWORD yDest,
5129                                         DWORD width, DWORD height)
5130 {
5131   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5132   X11DRV_DIB_IMAGEBITS_DESCR descr;
5133
5134   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5135                          &descr.infoBpp, &descr.compression ) == -1)
5136     return;
5137
5138   descr.physDev   = NULL;
5139   descr.palentry  = NULL;
5140   descr.image     = dib->image;
5141   descr.colorMap  = colorMap;
5142   descr.nColorMap = nColorMap;
5143   descr.bits      = dib->dibSection.dsBm.bmBits;
5144   descr.depth     = bmp->bitmap.bmBitsPixel;
5145
5146   switch (descr.infoBpp)
5147   {
5148     case 1:
5149     case 4:
5150     case 8:
5151       descr.rMask = descr.gMask = descr.bMask = 0;
5152       break;
5153     case 15:
5154     case 16:
5155       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5156       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5157       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5158       break;
5159
5160     case 24:
5161     case 32:
5162       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5163       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5164       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5165       break;
5166   }
5167
5168   /* Hack for now */
5169   descr.drawable  = dest;
5170   descr.gc        = BITMAP_GC(bmp);
5171   descr.xSrc      = xSrc;
5172   descr.ySrc      = ySrc;
5173   descr.xDest     = xDest;
5174   descr.yDest     = yDest;
5175   descr.width     = width;
5176   descr.height    = height;
5177 #ifdef HAVE_LIBXXSHM
5178   descr.useShm = (dib->shminfo.shmid != -1);
5179 #else
5180   descr.useShm = FALSE;
5181 #endif
5182   descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5183
5184   if (toDIB)
5185     {
5186       TRACE("Copying from Pixmap to DIB bits\n");
5187       X11DRV_DIB_GetImageBits( &descr );
5188     }
5189   else
5190     {
5191       TRACE("Copying from DIB bits to Pixmap\n");
5192       X11DRV_DIB_SetImageBits( &descr );
5193     }
5194 }
5195
5196 /***********************************************************************
5197  *           X11DRV_DIB_CopyDIBSection
5198  */
5199 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
5200                                DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
5201                                DWORD width, DWORD height)
5202 {
5203   BITMAPOBJ *bmp;
5204   DC *dcSrc = physDevSrc->dc;
5205   DC *dcDst = physDevDst->dc;
5206   int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5207
5208   TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5209     xSrc, ySrc, xDest, yDest, width, height);
5210   /* this function is meant as an optimization for BitBlt,
5211    * not to be called otherwise */
5212   if (GetObjectType( physDevSrc->hdc ) != OBJ_MEMDC) {
5213     ERR("called for non-memory source DC!?\n");
5214     return;
5215   }
5216
5217   bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5218   if (!(bmp && bmp->dib)) {
5219     ERR("called for non-DIBSection!?\n");
5220     GDI_ReleaseObj( dcSrc->hBitmap );
5221     return;
5222   }
5223   /* while BitBlt should already have made sure we only get
5224    * positive values, we should check for oversize values */
5225   if ((xSrc < bmp->bitmap.bmWidth) &&
5226       (ySrc < bmp->bitmap.bmHeight)) {
5227     if (xSrc + width > bmp->bitmap.bmWidth)
5228       width = bmp->bitmap.bmWidth - xSrc;
5229     if (ySrc + height > bmp->bitmap.bmHeight)
5230       height = bmp->bitmap.bmHeight - ySrc;
5231     /* if the source bitmap is 8bpp or less, we're supposed to use the
5232      * DC's palette for color conversion (not the DIB color table) */
5233     if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5234       X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5235       if ((!dcSrc->hPalette) ||
5236           (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5237         /* HACK: no palette has been set in the source DC,
5238          * use the DIB colormap instead - this is necessary in some
5239          * cases since we need to do depth conversion in some places
5240          * where real Windows can just copy data straight over */
5241         colorMap = dib->colorMap;
5242         nColorMap = dib->nColorMap;
5243       } else {
5244         colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
5245                                              bmp->dib->dsBm.bmBitsPixel,
5246                                              (BITMAPINFO*)&(bmp->dib->dsBmih),
5247                                              &nColorMap );
5248         if (colorMap) aColorMap = TRUE;
5249       }
5250     }
5251     /* perform the copy */
5252     X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5253                                 physDevDst->drawable, xSrc, ySrc,
5254                                 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
5255                                 width, height);
5256     /* free color mapping */
5257     if (aColorMap)
5258       HeapFree(GetProcessHeap(), 0, colorMap);
5259   }
5260   GDI_ReleaseObj( dcSrc->hBitmap );
5261 }
5262
5263 /***********************************************************************
5264  *           X11DRV_DIB_DoUpdateDIBSection
5265  */
5266 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5267 {
5268   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5269   X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5270                               (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5271                               bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5272 }
5273
5274 /***********************************************************************
5275  *           X11DRV_DIB_FaultHandler
5276  */
5277 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5278 {
5279   BITMAPOBJ *bmp;
5280   INT state;
5281
5282   bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5283   if (!bmp) return FALSE;
5284
5285   state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5286   if (state != DIB_Status_InSync) {
5287     /* no way to tell whether app needs read or write yet,
5288      * try read first */
5289     X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5290   } else {
5291     /* hm, apparently the app must have write access */
5292     X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5293   }
5294   X11DRV_DIB_Unlock(bmp, TRUE);
5295
5296   GDI_ReleaseObj( (HBITMAP)res );
5297   return TRUE;
5298 }
5299
5300 /***********************************************************************
5301  *           X11DRV_DIB_Coerce
5302  */
5303 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5304 {
5305   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5306   INT ret = DIB_Status_None;
5307
5308   if (dib) {
5309     EnterCriticalSection(&(dib->lock));
5310     ret = dib->status;
5311     switch (req) {
5312     case DIB_Status_GdiMod:
5313       /* GDI access - request to draw on pixmap */
5314       switch (dib->status)
5315       {
5316         default:
5317         case DIB_Status_None:
5318           dib->p_status = DIB_Status_GdiMod;
5319           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5320           break;
5321
5322         case DIB_Status_GdiMod:
5323           TRACE("GdiMod requested in status GdiMod\n" );
5324           break;
5325
5326         case DIB_Status_InSync:
5327           TRACE("GdiMod requested in status InSync\n" );
5328           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5329           dib->status = DIB_Status_GdiMod;
5330           dib->p_status = DIB_Status_InSync;
5331           break;
5332
5333         case DIB_Status_AuxMod:
5334           TRACE("GdiMod requested in status AuxMod\n" );
5335           if (lossy) dib->status = DIB_Status_GdiMod;
5336           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5337           dib->p_status = DIB_Status_AuxMod;
5338           if (dib->status != DIB_Status_AppMod) {
5339             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5340             break;
5341           }
5342           /* fall through if copy_aux() had to change to AppMod state */
5343
5344         case DIB_Status_AppMod:
5345           TRACE("GdiMod requested in status AppMod\n" );
5346           if (!lossy) {
5347             /* make it readonly to avoid app changing data while we copy */
5348             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5349             X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5350           }
5351           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5352           dib->p_status = DIB_Status_AppMod;
5353           dib->status = DIB_Status_GdiMod;
5354           break;
5355       }
5356       break;
5357
5358     case DIB_Status_InSync:
5359       /* App access - request access to read DIB surface */
5360       /* (typically called from signal handler) */
5361       switch (dib->status)
5362       {
5363         default:
5364         case DIB_Status_None:
5365           /* shouldn't happen from signal handler */
5366           break;
5367
5368         case DIB_Status_AuxMod:
5369           TRACE("InSync requested in status AuxMod\n" );
5370           if (lossy) dib->status = DIB_Status_InSync;
5371           else {
5372             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5373             (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5374           }
5375           if (dib->status != DIB_Status_GdiMod) {
5376             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5377             break;
5378           }
5379           /* fall through if copy_aux() had to change to GdiMod state */
5380
5381         case DIB_Status_GdiMod:
5382           TRACE("InSync requested in status GdiMod\n" );
5383           if (!lossy) {
5384             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5385             X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5386           }
5387           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5388           dib->status = DIB_Status_InSync;
5389           break;
5390
5391         case DIB_Status_InSync:
5392           TRACE("InSync requested in status InSync\n" );
5393           /* shouldn't happen from signal handler */
5394           break;
5395
5396         case DIB_Status_AppMod:
5397           TRACE("InSync requested in status AppMod\n" );
5398           /* no reason to do anything here, and this
5399            * shouldn't happen from signal handler */
5400           break;
5401       }
5402       break;
5403
5404     case DIB_Status_AppMod:
5405       /* App access - request access to write DIB surface */
5406       /* (typically called from signal handler) */
5407       switch (dib->status)
5408       {
5409         default:
5410         case DIB_Status_None:
5411           /* shouldn't happen from signal handler */
5412           break;
5413
5414         case DIB_Status_AuxMod:
5415           TRACE("AppMod requested in status AuxMod\n" );
5416           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5417           if (lossy) dib->status = DIB_Status_AppMod;
5418           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5419           if (dib->status != DIB_Status_GdiMod)
5420             break;
5421           /* fall through if copy_aux() had to change to GdiMod state */
5422
5423         case DIB_Status_GdiMod:
5424           TRACE("AppMod requested in status GdiMod\n" );
5425           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5426           if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5427           dib->status = DIB_Status_AppMod;
5428           break;
5429
5430         case DIB_Status_InSync:
5431           TRACE("AppMod requested in status InSync\n" );
5432           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5433           dib->status = DIB_Status_AppMod;
5434           break;
5435
5436         case DIB_Status_AppMod:
5437           TRACE("AppMod requested in status AppMod\n" );
5438           /* shouldn't happen from signal handler */
5439           break;
5440       }
5441       break;
5442
5443     case DIB_Status_AuxMod:
5444       if (dib->status == DIB_Status_None) {
5445         dib->p_status = req;
5446       } else {
5447         if (dib->status != DIB_Status_AuxMod)
5448           dib->p_status = dib->status;
5449         dib->status = DIB_Status_AuxMod;
5450       }
5451       break;
5452       /* it is up to the caller to do the copy/conversion, probably
5453        * using the return value to decide where to copy from */
5454     }
5455     LeaveCriticalSection(&(dib->lock));
5456   }
5457   return ret;
5458 }
5459
5460 /***********************************************************************
5461  *           X11DRV_DIB_Lock
5462  */
5463 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5464 {
5465   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5466   INT ret = DIB_Status_None;
5467
5468   if (dib) {
5469     TRACE("Locking %p from thread %04lx\n", bmp, GetCurrentThreadId());
5470     EnterCriticalSection(&(dib->lock));
5471     ret = dib->status;
5472     if (req != DIB_Status_None)
5473       X11DRV_DIB_Coerce(bmp, req, lossy);
5474   }
5475   return ret;
5476 }
5477
5478 /***********************************************************************
5479  *           X11DRV_DIB_Unlock
5480  */
5481 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5482 {
5483   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5484
5485   if (dib) {
5486     switch (dib->status)
5487     {
5488       default:
5489       case DIB_Status_None:
5490         /* in case anyone is wondering, this is the "signal handler doesn't
5491          * work" case, where we always have to be ready for app access */
5492         if (commit) {
5493           switch (dib->p_status)
5494           {
5495             case DIB_Status_AuxMod:
5496               TRACE("Unlocking and syncing from AuxMod\n" );
5497               (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5498               if (dib->status != DIB_Status_None) {
5499                 dib->p_status = dib->status;
5500                 dib->status = DIB_Status_None;
5501               }
5502               if (dib->p_status != DIB_Status_GdiMod)
5503                 break;
5504               /* fall through if copy_aux() had to change to GdiMod state */
5505
5506             case DIB_Status_GdiMod:
5507               TRACE("Unlocking and syncing from GdiMod\n" );
5508               X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5509               break;
5510
5511             default:
5512               TRACE("Unlocking without needing to sync\n" );
5513               break;
5514           }
5515         }
5516         else TRACE("Unlocking with no changes\n");
5517         dib->p_status = DIB_Status_None;
5518         break;
5519
5520       case DIB_Status_GdiMod:
5521         TRACE("Unlocking in status GdiMod\n" );
5522         /* DIB was protected in Coerce */
5523         if (!commit) {
5524           /* no commit, revert to InSync if applicable */
5525           if ((dib->p_status == DIB_Status_InSync) ||
5526               (dib->p_status == DIB_Status_AppMod)) {
5527             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5528             dib->status = DIB_Status_InSync;
5529           }
5530         }
5531         break;
5532
5533       case DIB_Status_InSync:
5534         TRACE("Unlocking in status InSync\n" );
5535         /* DIB was already protected in Coerce */
5536         break;
5537
5538       case DIB_Status_AppMod:
5539         TRACE("Unlocking in status AppMod\n" );
5540         /* DIB was already protected in Coerce */
5541         /* this case is ordinary only called from the signal handler,
5542          * so we don't bother to check for !commit */
5543         break;
5544
5545       case DIB_Status_AuxMod:
5546         TRACE("Unlocking in status AuxMod\n" );
5547         if (commit) {
5548           /* DIB may need protection now */
5549           if ((dib->p_status == DIB_Status_InSync) ||
5550               (dib->p_status == DIB_Status_AppMod))
5551             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5552         } else {
5553           /* no commit, revert to previous state */
5554           if (dib->p_status != DIB_Status_None)
5555             dib->status = dib->p_status;
5556           /* no protections changed */
5557         }
5558         dib->p_status = DIB_Status_None;
5559         break;
5560     }
5561     LeaveCriticalSection(&(dib->lock));
5562     TRACE("Unlocked %p\n", bmp);
5563   }
5564 }
5565
5566 /***********************************************************************
5567  *           X11DRV_CoerceDIBSection2
5568  */
5569 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5570 {
5571   BITMAPOBJ *bmp;
5572   INT ret;
5573
5574   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5575   if (!bmp) return DIB_Status_None;
5576   ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5577   GDI_ReleaseObj( hBmp );
5578   return ret;
5579 }
5580
5581 /***********************************************************************
5582  *           X11DRV_LockDIBSection2
5583  */
5584 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5585 {
5586   BITMAPOBJ *bmp;
5587   INT ret;
5588
5589   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5590   if (!bmp) return DIB_Status_None;
5591   ret = X11DRV_DIB_Lock(bmp, req, lossy);
5592   GDI_ReleaseObj( hBmp );
5593   return ret;
5594 }
5595
5596 /***********************************************************************
5597  *           X11DRV_UnlockDIBSection2
5598  */
5599 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5600 {
5601   BITMAPOBJ *bmp;
5602
5603   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5604   if (!bmp) return;
5605   X11DRV_DIB_Unlock(bmp, commit);
5606   GDI_ReleaseObj( hBmp );
5607 }
5608
5609 /***********************************************************************
5610  *           X11DRV_CoerceDIBSection
5611  */
5612 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5613 {
5614   if (!physDev) return DIB_Status_None;
5615   return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
5616 }
5617
5618 /***********************************************************************
5619  *           X11DRV_LockDIBSection
5620  */
5621 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5622 {
5623   if (!physDev) return DIB_Status_None;
5624   if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return DIB_Status_None;
5625
5626   return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
5627 }
5628
5629 /***********************************************************************
5630  *           X11DRV_UnlockDIBSection
5631  */
5632 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
5633 {
5634   if (!physDev) return;
5635   if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return;
5636
5637   X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
5638 }
5639
5640
5641 #ifdef HAVE_LIBXXSHM
5642 /***********************************************************************
5643  *           X11DRV_XShmErrorHandler
5644  *
5645  */
5646 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
5647 {
5648     return 1;  /* FIXME: should check event contents */
5649 }
5650
5651 /***********************************************************************
5652  *           X11DRV_XShmCreateImage
5653  *
5654  */
5655 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5656                                        XShmSegmentInfo* shminfo)
5657 {
5658     XImage *image;
5659
5660     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5661     if (image)
5662     {
5663         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5664                                   IPC_CREAT|0700);
5665         if( shminfo->shmid != -1 )
5666         {
5667             shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5668             if( shminfo->shmaddr != (char*)-1 )
5669             {
5670                 BOOL ok;
5671
5672                 shminfo->readOnly = FALSE;
5673                 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
5674                 ok = (XShmAttach( gdi_display, shminfo ) != 0);
5675                 if (X11DRV_check_error()) ok = FALSE;
5676                 if (ok)
5677                 {
5678                     shmctl(shminfo->shmid, IPC_RMID, 0);
5679                     return image; /* Success! */
5680                 }
5681                 /* An error occured */
5682                 shmdt(shminfo->shmaddr);
5683             }
5684             shmctl(shminfo->shmid, IPC_RMID, 0);
5685         }
5686         XFlush(gdi_display);
5687         XDestroyImage(image);
5688         image = NULL;
5689     }
5690     return image;
5691 }
5692 #endif /* HAVE_LIBXXSHM */
5693
5694
5695 /***********************************************************************
5696  *           X11DRV_DIB_CreateDIBSection
5697  */
5698 HBITMAP X11DRV_DIB_CreateDIBSection(
5699   X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
5700   LPVOID *bits, HANDLE section,
5701   DWORD offset, DWORD ovr_pitch)
5702 {
5703   HBITMAP res = 0;
5704   BITMAPOBJ *bmp = NULL;
5705   X11DRV_DIBSECTION *dib = NULL;
5706   int *colorMap = NULL;
5707   int nColorMap;
5708
5709   /* Fill BITMAP32 structure with DIB data */
5710   BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5711   INT effHeight, totalSize;
5712   BITMAP bm;
5713   LPVOID mapBits = NULL;
5714
5715   TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5716         bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5717         bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5718
5719   effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5720   bm.bmType = 0;
5721   bm.bmWidth = bi->biWidth;
5722   bm.bmHeight = effHeight;
5723   bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5724                               : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5725   bm.bmPlanes = bi->biPlanes;
5726   bm.bmBitsPixel = bi->biBitCount;
5727   bm.bmBits = NULL;
5728
5729   /* Get storage location for DIB bits.  Only use biSizeImage if it's valid and
5730      we're dealing with a compressed bitmap.  Otherwise, use width * height. */
5731   totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5732     ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5733
5734   if (section)
5735   {
5736       SYSTEM_INFO SystemInfo;
5737       DWORD mapOffset;
5738       INT mapSize;
5739
5740       GetSystemInfo( &SystemInfo );
5741       mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5742       mapSize = totalSize + (offset - mapOffset);
5743       mapBits = MapViewOfFile( section,
5744                                FILE_MAP_ALL_ACCESS,
5745                                0L,
5746                                mapOffset,
5747                                mapSize );
5748       bm.bmBits = (char *)mapBits + (offset - mapOffset);
5749   }
5750   else if (ovr_pitch && offset)
5751     bm.bmBits = (LPVOID) offset;
5752   else {
5753     offset = 0;
5754     bm.bmBits = VirtualAlloc(NULL, totalSize,
5755                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5756   }
5757
5758   /* Create Color Map */
5759   if (bm.bmBits && bm.bmBitsPixel <= 8)
5760       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
5761                                            usage, bm.bmBitsPixel, bmi, &nColorMap );
5762
5763   /* Allocate Memory for DIB and fill structure */
5764   if (bm.bmBits)
5765     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5766   if (dib)
5767     {
5768       dib->dibSection.dsBm = bm;
5769       dib->dibSection.dsBmih = *bi;
5770       dib->dibSection.dsBmih.biSizeImage = totalSize;
5771
5772       /* Set dsBitfields values */
5773        if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5774        {
5775            dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5776        }
5777        else switch( bi->biBitCount )
5778        {
5779            case 15:
5780            case 16:
5781                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5782                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5783                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5784                break;
5785
5786            case 24:
5787            case 32:
5788                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors       : 0xff0000;
5789                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5790                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5791                break;
5792        }
5793       dib->dibSection.dshSection = section;
5794       dib->dibSection.dsOffset = offset;
5795
5796       dib->status    = DIB_Status_None;
5797       dib->nColorMap = nColorMap;
5798       dib->colorMap  = colorMap;
5799     }
5800
5801   /* Create Device Dependent Bitmap and add DIB pointer */
5802   if (dib)
5803     {
5804       res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
5805       if (res)
5806         {
5807           bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5808           if (bmp) bmp->dib = (DIBSECTION *) dib;
5809         }
5810     }
5811
5812   /* Create XImage */
5813   if (dib && bmp)
5814   {
5815       wine_tsx11_lock();
5816 #ifdef HAVE_LIBXXSHM
5817       if (XShmQueryExtension(gdi_display) &&
5818           (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5819                                                 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5820       {
5821         ; /* Created Image */
5822       } else {
5823           dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5824           dib->shminfo.shmid = -1;
5825       }
5826 #else
5827       dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5828 #endif
5829       wine_tsx11_unlock();
5830   }
5831
5832   /* Clean up in case of errors */
5833   if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5834     {
5835       TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
5836             res, bmp, dib, bm.bmBits);
5837       if (bm.bmBits)
5838         {
5839           if (section)
5840             UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5841           else if (!offset)
5842             VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5843         }
5844
5845       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5846       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5847       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5848       if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5849       if (res) { DeleteObject(res); res = 0; }
5850     }
5851   else if (bm.bmBits)
5852     {
5853       /* Install fault handler, if possible */
5854       InitializeCriticalSection(&(dib->lock));
5855       if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5856         {
5857           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5858           if (dib) dib->status = DIB_Status_AppMod;
5859         }
5860     }
5861
5862   /* Return BITMAP handle and storage location */
5863   if (bmp) GDI_ReleaseObj(res);
5864   if (bm.bmBits && bits) *bits = bm.bmBits;
5865   return res;
5866 }
5867
5868 /***********************************************************************
5869  *           X11DRV_DIB_DeleteDIBSection
5870  */
5871 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5872 {
5873   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5874
5875   if (dib->image)
5876   {
5877       wine_tsx11_lock();
5878 #ifdef HAVE_LIBXXSHM
5879       if (dib->shminfo.shmid != -1)
5880       {
5881           XShmDetach (gdi_display, &(dib->shminfo));
5882           XDestroyImage (dib->image);
5883           shmdt (dib->shminfo.shmaddr);
5884           dib->shminfo.shmid = -1;
5885       }
5886       else
5887 #endif
5888           XDestroyImage( dib->image );
5889       wine_tsx11_unlock();
5890   }
5891
5892   if (dib->colorMap)
5893     HeapFree(GetProcessHeap(), 0, dib->colorMap);
5894
5895   DeleteCriticalSection(&(dib->lock));
5896 }
5897
5898 /***********************************************************************
5899  *           SetDIBColorTable   (X11DRV.@)
5900  */
5901 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
5902 {
5903     BITMAPOBJ * bmp;
5904     X11DRV_DIBSECTION *dib;
5905     UINT ret = 0;
5906
5907     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5908     dib = (X11DRV_DIBSECTION *) bmp->dib;
5909
5910     if (dib && dib->colorMap) {
5911         UINT end = count + start;
5912         if (end > dib->nColorMap) end = dib->nColorMap;
5913         /*
5914          * Changing color table might change the mapping between
5915          * DIB colors and X11 colors and thus alter the visible state
5916          * of the bitmap object.
5917          */
5918         X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5919         X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
5920                                 dib->dibSection.dsBm.bmBitsPixel,
5921                                 TRUE, colors, start, end );
5922         X11DRV_DIB_Unlock(bmp, TRUE);
5923         ret = end - start;
5924     }
5925     GDI_ReleaseObj( physDev->dc->hBitmap );
5926     return ret;
5927 }
5928
5929 /***********************************************************************
5930  *           GetDIBColorTable   (X11DRV.@)
5931  */
5932 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
5933 {
5934     BITMAPOBJ * bmp;
5935     X11DRV_DIBSECTION *dib;
5936     UINT ret = 0;
5937
5938     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5939     dib = (X11DRV_DIBSECTION *) bmp->dib;
5940
5941     if (dib && dib->colorMap) {
5942         UINT i, end = count + start;
5943         if (end > dib->nColorMap) end = dib->nColorMap;
5944         for (i = start; i < end; i++,colors++) {
5945             COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5946             colors->rgbBlue  = GetBValue(col);
5947             colors->rgbGreen = GetGValue(col);
5948             colors->rgbRed   = GetRValue(col);
5949             colors->rgbReserved = 0;
5950         }
5951         ret = end-start;
5952     }
5953     GDI_ReleaseObj( physDev->dc->hBitmap );
5954     return ret;
5955 }
5956
5957
5958 /**************************************************************************
5959  *              X11DRV_DIB_CreateDIBFromPixmap
5960  *
5961  *  Allocates a packed DIB and copies the Pixmap data into it.
5962  *  If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5963  */
5964 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5965 {
5966     HBITMAP hBmp = 0;
5967     BITMAPOBJ *pBmp = NULL;
5968     HGLOBAL hPackedDIB = 0;
5969
5970     /* Allocates an HBITMAP which references the Pixmap passed to us */
5971     hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5972     if (!hBmp)
5973     {
5974         TRACE("\tCould not create bitmap header for Pixmap\n");
5975         goto END;
5976     }
5977
5978     /*
5979      * Create a packed DIB from the Pixmap wrapper bitmap created above.
5980      * A packed DIB contains a BITMAPINFO structure followed immediately by
5981      * an optional color palette and the pixel data.
5982      */
5983     hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5984
5985     /* Get a pointer to the BITMAPOBJ structure */
5986     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5987
5988     /* We can now get rid of the HBITMAP wrapper we created earlier.
5989      * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5990      */
5991     if (!bDeletePixmap)
5992     {
5993         /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5994         pBmp->physBitmap = NULL;
5995         pBmp->funcs = NULL;
5996     }
5997     GDI_ReleaseObj( hBmp );
5998     DeleteObject(hBmp);
5999
6000 END:
6001     TRACE("\tReturning packed DIB %p\n", hPackedDIB);
6002     return hPackedDIB;
6003 }
6004
6005
6006 /**************************************************************************
6007  *                 X11DRV_DIB_CreatePixmapFromDIB
6008  *
6009  *    Creates a Pixmap from a packed DIB
6010  */
6011 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
6012 {
6013     Pixmap pixmap = None;
6014     HBITMAP hBmp = 0;
6015     BITMAPOBJ *pBmp = NULL;
6016     LPBYTE pPackedDIB = NULL;
6017     LPBITMAPINFO pbmi = NULL;
6018     LPBITMAPINFOHEADER pbmiHeader = NULL;
6019     LPBYTE pbits = NULL;
6020
6021     /* Get a pointer to the packed DIB's data  */
6022     pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
6023     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
6024     pbmi = (LPBITMAPINFO)pPackedDIB;
6025     pbits = (LPBYTE)(pPackedDIB
6026                      + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
6027
6028     /* Create a DDB from the DIB */
6029
6030     hBmp = CreateDIBitmap(hdc,
6031                           pbmiHeader,
6032                           CBM_INIT,
6033                           (LPVOID)pbits,
6034                           pbmi,
6035                           DIB_RGB_COLORS);
6036
6037     GlobalUnlock(hPackedDIB);
6038
6039     TRACE("CreateDIBitmap returned %p\n", hBmp);
6040
6041     /* Retrieve the internal Pixmap from the DDB */
6042
6043     pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
6044
6045     pixmap = (Pixmap)pBmp->physBitmap;
6046     /* clear the physBitmap so that we can steal its pixmap */
6047     pBmp->physBitmap = NULL;
6048     pBmp->funcs = NULL;
6049
6050     /* Delete the DDB we created earlier now that we have stolen its pixmap */
6051     GDI_ReleaseObj( hBmp );
6052     DeleteObject(hBmp);
6053
6054     TRACE("\tReturning Pixmap %ld\n", pixmap);
6055     return pixmap;
6056 }