Implemented OleLoadPictureEx.
[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         srcval=*srcbyte;
1632         switch (dstwidth & 7)
1633         {
1634         case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1635         case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1636         case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1637         case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1638         case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1639         case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1640         case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1641         }
1642         srcbits += linebytes;
1643     }
1644 }
1645
1646 /***********************************************************************
1647  *           X11DRV_DIB_GetImageBits_1
1648  *
1649  * GetDIBits for a 1-bit deep DIB.
1650  */
1651 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1652                                        DWORD dstwidth, DWORD srcwidth,
1653                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
1654                                 XImage *bmpImage, DWORD linebytes )
1655 {
1656     DWORD x;
1657     int h;
1658
1659     if (lines < 0 ) {
1660         lines = -lines;
1661         dstbits = dstbits + linebytes * (lines - 1);
1662         linebytes = -linebytes;
1663     }
1664
1665     switch (bmpImage->depth)
1666     {
1667     case 1:
1668     case 4:
1669         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1670             /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1671             BYTE* dstbyte;
1672
1673             for (h=lines-1; h>=0; h--) {
1674                 BYTE dstval;
1675                 dstbyte=dstbits;
1676                 dstval=0;
1677                 for (x=0; x<dstwidth; x++) {
1678                     PALETTEENTRY srcval;
1679                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
1680                     dstval|=(X11DRV_DIB_GetNearestIndex
1681                              (colors, 2,
1682                               srcval.peRed,
1683                               srcval.peGreen,
1684                               srcval.peBlue) << (7 - (x & 7)));
1685                     if ((x&7)==7) {
1686                         *dstbyte++=dstval;
1687                         dstval=0;
1688                     }
1689                 }
1690                 if ((dstwidth&7)!=0) {
1691                     *dstbyte=dstval;
1692                 }
1693                 dstbits += linebytes;
1694             }
1695         } else {
1696             goto notsupported;
1697         }
1698         break;
1699
1700     case 8:
1701         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1702             /* ==== pal 8 bmp -> pal 1 dib ==== */
1703             const void* srcbits;
1704             const BYTE* srcpixel;
1705             BYTE* dstbyte;
1706
1707             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1708
1709             for (h=0; h<lines; h++) {
1710                 BYTE dstval;
1711                 srcpixel=srcbits;
1712                 dstbyte=dstbits;
1713                 dstval=0;
1714                 for (x=0; x<dstwidth; x++) {
1715                     PALETTEENTRY srcval;
1716                     srcval=srccolors[(int)*srcpixel++];
1717                     dstval|=(X11DRV_DIB_GetNearestIndex
1718                              (colors, 2,
1719                               srcval.peRed,
1720                               srcval.peGreen,
1721                               srcval.peBlue) << (7-(x&7)) );
1722                     if ((x&7)==7) {
1723                         *dstbyte++=dstval;
1724                         dstval=0;
1725                     }
1726                 }
1727                 if ((dstwidth&7)!=0) {
1728                     *dstbyte=dstval;
1729                 }
1730                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1731                 dstbits += linebytes;
1732             }
1733         } else {
1734             goto notsupported;
1735         }
1736         break;
1737
1738     case 15:
1739     case 16:
1740         {
1741             const void* srcbits;
1742             const WORD* srcpixel;
1743             BYTE* dstbyte;
1744
1745             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1746
1747             if (bmpImage->green_mask==0x03e0) {
1748                 if (bmpImage->red_mask==0x7c00) {
1749                     /* ==== rgb 555 bmp -> pal 1 dib ==== */
1750                     for (h=0; h<lines; h++) {
1751                         BYTE dstval;
1752                         srcpixel=srcbits;
1753                         dstbyte=dstbits;
1754                         dstval=0;
1755                         for (x=0; x<dstwidth; x++) {
1756                             WORD srcval;
1757                             srcval=*srcpixel++;
1758                             dstval|=(X11DRV_DIB_GetNearestIndex
1759                                      (colors, 2,
1760                                       ((srcval >>  7) & 0xf8) | /* r */
1761                                       ((srcval >> 12) & 0x07),
1762                                       ((srcval >>  2) & 0xf8) | /* g */
1763                                       ((srcval >>  7) & 0x07),
1764                                       ((srcval <<  3) & 0xf8) | /* b */
1765                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
1766                             if ((x&7)==7) {
1767                                 *dstbyte++=dstval;
1768                                 dstval=0;
1769                             }
1770                         }
1771                         if ((dstwidth&7)!=0) {
1772                             *dstbyte=dstval;
1773                         }
1774                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1775                         dstbits += linebytes;
1776                     }
1777                 } else if (bmpImage->blue_mask==0x7c00) {
1778                     /* ==== bgr 555 bmp -> pal 1 dib ==== */
1779                     for (h=0; h<lines; h++) {
1780                         WORD dstval;
1781                         srcpixel=srcbits;
1782                         dstbyte=dstbits;
1783                         dstval=0;
1784                         for (x=0; x<dstwidth; x++) {
1785                             BYTE srcval;
1786                             srcval=*srcpixel++;
1787                             dstval|=(X11DRV_DIB_GetNearestIndex
1788                                      (colors, 2,
1789                                       ((srcval <<  3) & 0xf8) | /* r */
1790                                       ((srcval >>  2) & 0x07),
1791                                       ((srcval >>  2) & 0xf8) | /* g */
1792                                       ((srcval >>  7) & 0x07),
1793                                       ((srcval >>  7) & 0xf8) | /* b */
1794                                       ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1795                             if ((x&7)==7) {
1796                                 *dstbyte++=dstval;
1797                                 dstval=0;
1798                             }
1799                         }
1800                         if ((dstwidth&7)!=0) {
1801                             *dstbyte=dstval;
1802                         }
1803                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1804                         dstbits += linebytes;
1805                     }
1806                 } else {
1807                     goto notsupported;
1808                 }
1809             } else if (bmpImage->green_mask==0x07e0) {
1810                 if (bmpImage->red_mask==0xf800) {
1811                     /* ==== rgb 565 bmp -> pal 1 dib ==== */
1812                     for (h=0; h<lines; h++) {
1813                         BYTE dstval;
1814                         srcpixel=srcbits;
1815                         dstbyte=dstbits;
1816                         dstval=0;
1817                         for (x=0; x<dstwidth; x++) {
1818                             WORD srcval;
1819                             srcval=*srcpixel++;
1820                             dstval|=(X11DRV_DIB_GetNearestIndex
1821                                      (colors, 2,
1822                                       ((srcval >>  8) & 0xf8) | /* r */
1823                                       ((srcval >> 13) & 0x07),
1824                                       ((srcval >>  3) & 0xfc) | /* g */
1825                                       ((srcval >>  9) & 0x03),
1826                                       ((srcval <<  3) & 0xf8) | /* b */
1827                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
1828                             if ((x&7)==7) {
1829                                 *dstbyte++=dstval;
1830                                 dstval=0;
1831                             }
1832                         }
1833                         if ((dstwidth&7)!=0) {
1834                             *dstbyte=dstval;
1835                         }
1836                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1837                         dstbits += linebytes;
1838                     }
1839                 } else if (bmpImage->blue_mask==0xf800) {
1840                     /* ==== bgr 565 bmp -> pal 1 dib ==== */
1841                     for (h=0; h<lines; h++) {
1842                         BYTE dstval;
1843                         srcpixel=srcbits;
1844                         dstbyte=dstbits;
1845                         dstval=0;
1846                         for (x=0; x<dstwidth; x++) {
1847                             WORD srcval;
1848                             srcval=*srcpixel++;
1849                             dstval|=(X11DRV_DIB_GetNearestIndex
1850                                      (colors, 2,
1851                                       ((srcval <<  3) & 0xf8) | /* r */
1852                                       ((srcval >>  2) & 0x07),
1853                                       ((srcval >>  3) & 0xfc) | /* g */
1854                                       ((srcval >>  9) & 0x03),
1855                                       ((srcval >>  8) & 0xf8) | /* b */
1856                                       ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1857                             if ((x&7)==7) {
1858                                 *dstbyte++=dstval;
1859                                 dstval=0;
1860                             }
1861                         }
1862                         if ((dstwidth&7)!=0) {
1863                             *dstbyte=dstval;
1864                         }
1865                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1866                         dstbits += linebytes;
1867                     }
1868                 } else {
1869                     goto notsupported;
1870                 }
1871             } else {
1872                 goto notsupported;
1873             }
1874         }
1875         break;
1876
1877     case 24:
1878     case 32:
1879         {
1880             const void* srcbits;
1881             const BYTE *srcbyte;
1882             BYTE* dstbyte;
1883             int bytes_per_pixel;
1884
1885             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1886             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1887
1888             if (bmpImage->green_mask!=0x00ff00 ||
1889                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1890                 goto notsupported;
1891             } else if (bmpImage->blue_mask==0xff) {
1892                 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1893                 for (h=0; h<lines; h++) {
1894                     BYTE dstval;
1895                     srcbyte=srcbits;
1896                     dstbyte=dstbits;
1897                     dstval=0;
1898                     for (x=0; x<dstwidth; x++) {
1899                         dstval|=(X11DRV_DIB_GetNearestIndex
1900                                  (colors, 2,
1901                                   srcbyte[2],
1902                                   srcbyte[1],
1903                                   srcbyte[0]) << (7-(x&7)) );
1904                         srcbyte+=bytes_per_pixel;
1905                         if ((x&7)==7) {
1906                             *dstbyte++=dstval;
1907                             dstval=0;
1908                         }
1909                     }
1910                     if ((dstwidth&7)!=0) {
1911                         *dstbyte=dstval;
1912                     }
1913                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1914                     dstbits += linebytes;
1915                 }
1916             } else {
1917                 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1918                 for (h=0; h<lines; h++) {
1919                     BYTE dstval;
1920                     srcbyte=srcbits;
1921                     dstbyte=dstbits;
1922                     dstval=0;
1923                     for (x=0; x<dstwidth; x++) {
1924                         dstval|=(X11DRV_DIB_GetNearestIndex
1925                                  (colors, 2,
1926                                   srcbyte[0],
1927                                   srcbyte[1],
1928                                   srcbyte[2]) << (7-(x&7)) );
1929                         srcbyte+=bytes_per_pixel;
1930                         if ((x&7)==7) {
1931                             *dstbyte++=dstval;
1932                             dstval=0;
1933                         }
1934                     }
1935                     if ((dstwidth&7)!=0) {
1936                         *dstbyte=dstval;
1937                     }
1938                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1939                     dstbits += linebytes;
1940                 }
1941             }
1942         }
1943         break;
1944
1945     default:
1946     notsupported:
1947         {
1948             BYTE* dstbyte;
1949             unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1950
1951             /* ==== any bmp format -> pal 1 dib ==== */
1952             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1953                   bmpImage->bits_per_pixel, bmpImage->red_mask,
1954                   bmpImage->green_mask, bmpImage->blue_mask );
1955
1956             for (h=lines-1; h>=0; h--) {
1957                 BYTE dstval;
1958                 dstbyte=dstbits;
1959                 dstval=0;
1960                 for (x=0; x<dstwidth; x++) {
1961                     dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1962                     if ((x&7)==7) {
1963                         *dstbyte++=dstval;
1964                         dstval=0;
1965                     }
1966                 }
1967                 if ((dstwidth&7)!=0) {
1968                     *dstbyte=dstval;
1969                 }
1970                 dstbits += linebytes;
1971             }
1972         }
1973         break;
1974     }
1975 }
1976
1977 /***********************************************************************
1978  *           X11DRV_DIB_SetImageBits_4
1979  *
1980  * SetDIBits for a 4-bit deep DIB.
1981  */
1982 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1983                                 DWORD srcwidth, DWORD dstwidth, int left,
1984                                 int *colors, XImage *bmpImage, DWORD linebytes)
1985 {
1986     int h;
1987     const BYTE* srcbyte;
1988     DWORD i, x;
1989
1990     if (lines < 0 ) {
1991         lines = -lines;
1992         srcbits = srcbits + linebytes * (lines - 1);
1993         linebytes = -linebytes;
1994     }
1995
1996     if (left & 1) {
1997         left--;
1998         dstwidth++;
1999     }
2000     srcbits += left >> 1;
2001
2002     /* ==== pal 4 dib -> any bmp format ==== */
2003     for (h = lines-1; h >= 0; h--) {
2004         srcbyte=srcbits;
2005         for (i = dstwidth/2, x = left; i > 0; i--) {
2006             BYTE srcval=*srcbyte++;
2007             XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
2008             XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
2009         }
2010         if (dstwidth & 1)
2011             XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
2012         srcbits += linebytes;
2013     }
2014 }
2015
2016
2017
2018 /***********************************************************************
2019  *           X11DRV_DIB_GetImageBits_4
2020  *
2021  * GetDIBits for a 4-bit deep DIB.
2022  */
2023 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
2024                                        DWORD srcwidth, DWORD dstwidth,
2025                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
2026                                        XImage *bmpImage, DWORD linebytes )
2027 {
2028     DWORD x;
2029     int h;
2030     BYTE *bits;
2031
2032     if (lines < 0 )
2033     {
2034        lines = -lines;
2035        dstbits = dstbits + ( linebytes * (lines-1) );
2036        linebytes = -linebytes;
2037     }
2038
2039     bits = dstbits;
2040
2041     switch (bmpImage->depth) {
2042     case 1:
2043     case 4:
2044         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2045             /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2046             BYTE* dstbyte;
2047
2048             for (h = lines-1; h >= 0; h--) {
2049                 BYTE dstval;
2050                 dstbyte=dstbits;
2051                 dstval=0;
2052                 for (x = 0; x < dstwidth; x++) {
2053                     PALETTEENTRY srcval;
2054                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2055                     dstval|=(X11DRV_DIB_GetNearestIndex
2056                              (colors, 16,
2057                               srcval.peRed,
2058                               srcval.peGreen,
2059                               srcval.peBlue) << (4-((x&1)<<2)));
2060                     if ((x&1)==1) {
2061                         *dstbyte++=dstval;
2062                         dstval=0;
2063                     }
2064                 }
2065                 if ((dstwidth&1)!=0) {
2066                     *dstbyte=dstval;
2067                 }
2068                 dstbits += linebytes;
2069             }
2070         } else {
2071             goto notsupported;
2072         }
2073         break;
2074
2075     case 8:
2076         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2077             /* ==== pal 8 bmp -> pal 4 dib ==== */
2078             const void* srcbits;
2079             const BYTE *srcpixel;
2080             BYTE* dstbyte;
2081
2082             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2083             for (h=0; h<lines; h++) {
2084                 BYTE dstval;
2085                 srcpixel=srcbits;
2086                 dstbyte=dstbits;
2087                 dstval=0;
2088                 for (x=0; x<dstwidth; x++) {
2089                     PALETTEENTRY srcval;
2090                     srcval = srccolors[(int)*srcpixel++];
2091                     dstval|=(X11DRV_DIB_GetNearestIndex
2092                              (colors, 16,
2093                               srcval.peRed,
2094                               srcval.peGreen,
2095                               srcval.peBlue) << (4*(1-(x&1))) );
2096                     if ((x&1)==1) {
2097                         *dstbyte++=dstval;
2098                         dstval=0;
2099                     }
2100                 }
2101                 if ((dstwidth&1)!=0) {
2102                     *dstbyte=dstval;
2103                 }
2104                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2105                 dstbits += linebytes;
2106             }
2107         } else {
2108             goto notsupported;
2109         }
2110         break;
2111
2112     case 15:
2113     case 16:
2114         {
2115             const void* srcbits;
2116             const WORD* srcpixel;
2117             BYTE* dstbyte;
2118
2119             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2120
2121             if (bmpImage->green_mask==0x03e0) {
2122                 if (bmpImage->red_mask==0x7c00) {
2123                     /* ==== rgb 555 bmp -> pal 4 dib ==== */
2124                     for (h=0; h<lines; h++) {
2125                         BYTE dstval;
2126                         srcpixel=srcbits;
2127                         dstbyte=dstbits;
2128                         dstval=0;
2129                         for (x=0; x<dstwidth; x++) {
2130                             WORD srcval;
2131                             srcval=*srcpixel++;
2132                             dstval|=(X11DRV_DIB_GetNearestIndex
2133                                      (colors, 16,
2134                                       ((srcval >>  7) & 0xf8) | /* r */
2135                                       ((srcval >> 12) & 0x07),
2136                                       ((srcval >>  2) & 0xf8) | /* g */
2137                                       ((srcval >>  7) & 0x07),
2138                                       ((srcval <<  3) & 0xf8) | /* b */
2139                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
2140                             if ((x&1)==1) {
2141                                 *dstbyte++=dstval;
2142                                 dstval=0;
2143                             }
2144                         }
2145                         if ((dstwidth&1)!=0) {
2146                             *dstbyte=dstval;
2147                         }
2148                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2149                         dstbits += linebytes;
2150                     }
2151                 } else if (bmpImage->blue_mask==0x7c00) {
2152                     /* ==== bgr 555 bmp -> pal 4 dib ==== */
2153                     for (h=0; h<lines; h++) {
2154                         WORD dstval;
2155                         srcpixel=srcbits;
2156                         dstbyte=dstbits;
2157                         dstval=0;
2158                         for (x=0; x<dstwidth; x++) {
2159                             WORD srcval;
2160                             srcval=*srcpixel++;
2161                             dstval|=(X11DRV_DIB_GetNearestIndex
2162                                      (colors, 16,
2163                                       ((srcval <<  3) & 0xf8) | /* r */
2164                                       ((srcval >>  2) & 0x07),
2165                                       ((srcval >>  2) & 0xf8) | /* g */
2166                                       ((srcval >>  7) & 0x07),
2167                                       ((srcval >>  7) & 0xf8) | /* b */
2168                                       ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2169                             if ((x&1)==1) {
2170                                 *dstbyte++=dstval;
2171                                 dstval=0;
2172                             }
2173                         }
2174                         if ((dstwidth&1)!=0) {
2175                             *dstbyte=dstval;
2176                         }
2177                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2178                         dstbits += linebytes;
2179                     }
2180                 } else {
2181                     goto notsupported;
2182                 }
2183             } else if (bmpImage->green_mask==0x07e0) {
2184                 if (bmpImage->red_mask==0xf800) {
2185                     /* ==== rgb 565 bmp -> pal 4 dib ==== */
2186                     for (h=0; h<lines; h++) {
2187                         BYTE dstval;
2188                         srcpixel=srcbits;
2189                         dstbyte=dstbits;
2190                         dstval=0;
2191                         for (x=0; x<dstwidth; x++) {
2192                             WORD srcval;
2193                             srcval=*srcpixel++;
2194                             dstval|=(X11DRV_DIB_GetNearestIndex
2195                                      (colors, 16,
2196                                       ((srcval >>  8) & 0xf8) | /* r */
2197                                       ((srcval >> 13) & 0x07),
2198                                       ((srcval >>  3) & 0xfc) | /* g */
2199                                       ((srcval >>  9) & 0x03),
2200                                       ((srcval <<  3) & 0xf8) | /* b */
2201                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
2202                             if ((x&1)==1) {
2203                                 *dstbyte++=dstval;
2204                                 dstval=0;
2205                             }
2206                         }
2207                         if ((dstwidth&1)!=0) {
2208                             *dstbyte=dstval;
2209                         }
2210                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2211                         dstbits += linebytes;
2212                     }
2213                 } else if (bmpImage->blue_mask==0xf800) {
2214                     /* ==== bgr 565 bmp -> pal 4 dib ==== */
2215                     for (h=0; h<lines; h++) {
2216                         WORD dstval;
2217                         srcpixel=srcbits;
2218                         dstbyte=dstbits;
2219                         dstval=0;
2220                         for (x=0; x<dstwidth; x++) {
2221                             WORD srcval;
2222                             srcval=*srcpixel++;
2223                             dstval|=(X11DRV_DIB_GetNearestIndex
2224                                      (colors, 16,
2225                                       ((srcval <<  3) & 0xf8) | /* r */
2226                                       ((srcval >>  2) & 0x07),
2227                                       ((srcval >>  3) & 0xfc) | /* g */
2228                                       ((srcval >>  9) & 0x03),
2229                                       ((srcval >>  8) & 0xf8) | /* b */
2230                                       ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2231                             if ((x&1)==1) {
2232                                 *dstbyte++=dstval;
2233                                 dstval=0;
2234                             }
2235                         }
2236                         if ((dstwidth&1)!=0) {
2237                             *dstbyte=dstval;
2238                         }
2239                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2240                         dstbits += linebytes;
2241                     }
2242                 } else {
2243                     goto notsupported;
2244                 }
2245             } else {
2246                 goto notsupported;
2247             }
2248         }
2249         break;
2250
2251     case 24:
2252         if (bmpImage->bits_per_pixel==24) {
2253             const void* srcbits;
2254             const BYTE *srcbyte;
2255             BYTE* dstbyte;
2256
2257             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2258
2259             if (bmpImage->green_mask!=0x00ff00 ||
2260                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2261                 goto notsupported;
2262             } else if (bmpImage->blue_mask==0xff) {
2263                 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2264                 for (h=0; h<lines; h++) {
2265                     srcbyte=srcbits;
2266                     dstbyte=dstbits;
2267                     for (x=0; x<dstwidth/2; x++) {
2268                         /* Do 2 pixels at a time */
2269                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2270                                     (colors, 16,
2271                                      srcbyte[2],
2272                                      srcbyte[1],
2273                                      srcbyte[0]) << 4) |
2274                                     X11DRV_DIB_GetNearestIndex
2275                                     (colors, 16,
2276                                      srcbyte[5],
2277                                      srcbyte[4],
2278                                      srcbyte[3]);
2279                         srcbyte+=6;
2280                     }
2281                     if (dstwidth&1) {
2282                         /* And the the odd pixel */
2283                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2284                                     (colors, 16,
2285                                      srcbyte[2],
2286                                      srcbyte[1],
2287                                      srcbyte[0]) << 4);
2288                     }
2289                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2290                     dstbits += linebytes;
2291                 }
2292             } else {
2293                 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2294                 for (h=0; h<lines; h++) {
2295                     srcbyte=srcbits;
2296                     dstbyte=dstbits;
2297                     for (x=0; x<dstwidth/2; x++) {
2298                         /* Do 2 pixels at a time */
2299                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2300                                     (colors, 16,
2301                                      srcbyte[0],
2302                                      srcbyte[1],
2303                                      srcbyte[2]) << 4) |
2304                                     X11DRV_DIB_GetNearestIndex
2305                                     (colors, 16,
2306                                      srcbyte[3],
2307                                      srcbyte[4],
2308                                      srcbyte[5]);
2309                         srcbyte+=6;
2310                     }
2311                     if (dstwidth&1) {
2312                         /* And the the odd pixel */
2313                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2314                                     (colors, 16,
2315                                      srcbyte[0],
2316                                      srcbyte[1],
2317                                      srcbyte[2]) << 4);
2318                     }
2319                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2320                     dstbits += linebytes;
2321                 }
2322             }
2323             break;
2324         }
2325         /* Fall through */
2326
2327     case 32:
2328         {
2329             const void* srcbits;
2330             const BYTE *srcbyte;
2331             BYTE* dstbyte;
2332
2333             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2334
2335             if (bmpImage->green_mask!=0x00ff00 ||
2336                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2337                 goto notsupported;
2338             } else if (bmpImage->blue_mask==0xff) {
2339                 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2340                 for (h=0; h<lines; h++) {
2341                     srcbyte=srcbits;
2342                     dstbyte=dstbits;
2343                     for (x=0; x<dstwidth/2; x++) {
2344                         /* Do 2 pixels at a time */
2345                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2346                                     (colors, 16,
2347                                      srcbyte[2],
2348                                      srcbyte[1],
2349                                      srcbyte[0]) << 4) |
2350                                     X11DRV_DIB_GetNearestIndex
2351                                     (colors, 16,
2352                                      srcbyte[6],
2353                                      srcbyte[5],
2354                                      srcbyte[4]);
2355                         srcbyte+=8;
2356                     }
2357                     if (dstwidth&1) {
2358                         /* And the the odd pixel */
2359                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2360                                     (colors, 16,
2361                                      srcbyte[2],
2362                                      srcbyte[1],
2363                                      srcbyte[0]) << 4);
2364                     }
2365                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2366                     dstbits += linebytes;
2367                 }
2368             } else {
2369                 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2370                 for (h=0; h<lines; h++) {
2371                     srcbyte=srcbits;
2372                     dstbyte=dstbits;
2373                     for (x=0; x<dstwidth/2; x++) {
2374                         /* Do 2 pixels at a time */
2375                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2376                                     (colors, 16,
2377                                      srcbyte[0],
2378                                      srcbyte[1],
2379                                      srcbyte[2]) << 4) |
2380                                     X11DRV_DIB_GetNearestIndex
2381                                     (colors, 16,
2382                                      srcbyte[4],
2383                                      srcbyte[5],
2384                                      srcbyte[6]);
2385                         srcbyte+=8;
2386                     }
2387                     if (dstwidth&1) {
2388                         /* And the the odd pixel */
2389                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
2390                                     (colors, 16,
2391                                      srcbyte[0],
2392                                      srcbyte[1],
2393                                      srcbyte[2]) << 4);
2394                     }
2395                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2396                     dstbits += linebytes;
2397                 }
2398             }
2399         }
2400         break;
2401
2402     default:
2403     notsupported:
2404         {
2405             BYTE* dstbyte;
2406
2407             /* ==== any bmp format -> pal 4 dib ==== */
2408             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2409                   bmpImage->bits_per_pixel, bmpImage->red_mask,
2410                   bmpImage->green_mask, bmpImage->blue_mask );
2411             for (h=lines-1; h>=0; h--) {
2412                 dstbyte=dstbits;
2413                 for (x=0; x<(dstwidth & ~1); x+=2) {
2414                     *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2415                         X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2416                 }
2417                 if (dstwidth & 1) {
2418                     *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2419                 }
2420                 dstbits += linebytes;
2421             }
2422         }
2423         break;
2424     }
2425 }
2426
2427 /***********************************************************************
2428  *           X11DRV_DIB_SetImageBits_RLE4
2429  *
2430  * SetDIBits for a 4-bit deep compressed DIB.
2431  */
2432 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2433                                           DWORD width, DWORD dstwidth,
2434                                           int left, int *colors,
2435                                           XImage *bmpImage )
2436 {
2437     int x = 0, y = lines - 1, c, length;
2438     const BYTE *begin = bits;
2439
2440     while (y >= 0)
2441     {
2442         length = *bits++;
2443         if (length) {   /* encoded */
2444             c = *bits++;
2445             while (length--) {
2446                 if (x >= width) break;
2447                 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2448                 if (!length--) break;
2449                 if (x >= width) break;
2450                 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2451             }
2452         } else {
2453             length = *bits++;
2454             switch (length)
2455             {
2456             case RLE_EOL:
2457                 x = 0;
2458                 y--;
2459                 break;
2460
2461             case RLE_END:
2462                 return;
2463
2464             case RLE_DELTA:
2465                 x += *bits++;
2466                 y -= *bits++;
2467                 break;
2468
2469             default: /* absolute */
2470                 while (length--) {
2471                     c = *bits++;
2472                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2473                     if (!length--) break;
2474                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2475                 }
2476                 if ((bits - begin) & 1)
2477                     bits++;
2478             }
2479         }
2480     }
2481 }
2482
2483
2484
2485 /***********************************************************************
2486  *           X11DRV_DIB_SetImageBits_8
2487  *
2488  * SetDIBits for an 8-bit deep DIB.
2489  */
2490 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2491                                 DWORD srcwidth, DWORD dstwidth, int left,
2492                                 const int *colors, XImage *bmpImage,
2493                                 DWORD linebytes )
2494 {
2495     DWORD x;
2496     int h;
2497     const BYTE* srcbyte;
2498     BYTE* dstbits;
2499
2500     if (lines < 0 )
2501     {
2502         lines = -lines;
2503         srcbits = srcbits + linebytes * (lines-1);
2504         linebytes = -linebytes;
2505     }
2506     srcbits += left;
2507     srcbyte = srcbits;
2508
2509     switch (bmpImage->depth) {
2510     case 15:
2511     case 16:
2512 #if defined(__i386__) && defined(__GNUC__)
2513         /* Some X servers might have 32 bit/ 16bit deep pixel */
2514         if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
2515             (ImageByteOrder(gdi_display)==LSBFirst) )
2516         {
2517             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2518             /* FIXME: Does this really handle all these cases correctly? */
2519             /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2520             for (h = lines ; h--; ) {
2521                 int _cl1,_cl2; /* temp outputs for asm below */
2522                 /* Borrowed from DirectDraw */
2523                 __asm__ __volatile__(
2524                 "xor %%eax,%%eax\n"
2525                 "cld\n"
2526                 "1:\n"
2527                 "    lodsb\n"
2528                 "    movw (%%edx,%%eax,4),%%ax\n"
2529                 "    stosw\n"
2530                 "      xor %%eax,%%eax\n"
2531                 "    loop 1b\n"
2532                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2533                 :"S" (srcbyte),
2534                  "D" (dstbits),
2535                  "c" (dstwidth),
2536                  "d" (colors)
2537                 :"eax", "cc", "memory"
2538                 );
2539                 srcbyte = (srcbits += linebytes);
2540                 dstbits -= bmpImage->bytes_per_line;
2541             }
2542             return;
2543         }
2544         break;
2545 #endif
2546     case 24:
2547     case 32:
2548 #if defined(__i386__) && defined(__GNUC__)
2549         if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
2550             (ImageByteOrder(gdi_display)==LSBFirst) )
2551         {
2552             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2553             /* FIXME: Does this really handle both cases correctly? */
2554             /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2555             for (h = lines ; h--; ) {
2556                 int _cl1,_cl2; /* temp outputs for asm below */
2557                 /* Borrowed from DirectDraw */
2558                 __asm__ __volatile__(
2559                 "xor %%eax,%%eax\n"
2560                 "cld\n"
2561                 "1:\n"
2562                 "    lodsb\n"
2563                 "    movl (%%edx,%%eax,4),%%eax\n"
2564                 "    stosl\n"
2565                 "      xor %%eax,%%eax\n"
2566                 "    loop 1b\n"
2567                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2568                 :"S" (srcbyte),
2569                  "D" (dstbits),
2570                  "c" (dstwidth),
2571                  "d" (colors)
2572                 :"eax", "cc", "memory"
2573                 );
2574                 srcbyte = (srcbits += linebytes);
2575                 dstbits -= bmpImage->bytes_per_line;
2576             }
2577             return;
2578         }
2579         break;
2580 #endif
2581     default:
2582         break; /* use slow generic case below */
2583     }
2584
2585     /* ==== pal 8 dib -> any bmp format ==== */
2586     for (h=lines-1; h>=0; h--) {
2587         for (x=left; x<dstwidth+left; x++) {
2588             XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2589         }
2590         srcbyte = (srcbits += linebytes);
2591     }
2592 }
2593
2594 /***********************************************************************
2595  *           X11DRV_DIB_GetImageBits_8
2596  *
2597  * GetDIBits for an 8-bit deep DIB.
2598  */
2599 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2600                                        DWORD srcwidth, DWORD dstwidth,
2601                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
2602                                        XImage *bmpImage, DWORD linebytes )
2603 {
2604     DWORD x;
2605     int h;
2606     BYTE* dstbyte;
2607
2608     if (lines < 0 )
2609     {
2610        lines = -lines;
2611        dstbits = dstbits + ( linebytes * (lines-1) );
2612        linebytes = -linebytes;
2613     }
2614
2615     /*
2616      * Hack for now
2617      * This condition is true when GetImageBits has been called by
2618      * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2619      * 256 colormaps, so we'll just use for for GetDIBits calls.
2620      * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2621      */
2622     if (!srccolors) goto updatesection;
2623
2624     switch (bmpImage->depth) {
2625     case 1:
2626     case 4:
2627         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2628
2629             /* ==== pal 1 bmp -> pal 8 dib ==== */
2630             /* ==== pal 4 bmp -> pal 8 dib ==== */
2631             for (h=lines-1; h>=0; h--) {
2632                 dstbyte=dstbits;
2633                 for (x=0; x<dstwidth; x++) {
2634                     PALETTEENTRY srcval;
2635                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2636                     *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2637                                                           srcval.peRed,
2638                                                           srcval.peGreen,
2639                                                           srcval.peBlue);
2640                 }
2641                 dstbits += linebytes;
2642             }
2643         } else {
2644             goto notsupported;
2645         }
2646         break;
2647
2648     case 8:
2649        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2650             /* ==== pal 8 bmp -> pal 8 dib ==== */
2651            const void* srcbits;
2652            const BYTE* srcpixel;
2653
2654            srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2655            for (h=0; h<lines; h++) {
2656                srcpixel=srcbits;
2657                dstbyte=dstbits;
2658                for (x = 0; x < dstwidth; x++) {
2659                    PALETTEENTRY srcval;
2660                    srcval=srccolors[(int)*srcpixel++];
2661                    *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2662                                                          srcval.peRed,
2663                                                          srcval.peGreen,
2664                                                          srcval.peBlue);
2665                }
2666                srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2667                dstbits += linebytes;
2668            }
2669        } else {
2670            goto notsupported;
2671        }
2672        break;
2673
2674     case 15:
2675     case 16:
2676         {
2677             const void* srcbits;
2678             const WORD* srcpixel;
2679             BYTE* dstbyte;
2680
2681             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2682
2683             if (bmpImage->green_mask==0x03e0) {
2684                 if (bmpImage->red_mask==0x7c00) {
2685                     /* ==== rgb 555 bmp -> pal 8 dib ==== */
2686                     for (h=0; h<lines; h++) {
2687                         srcpixel=srcbits;
2688                         dstbyte=dstbits;
2689                         for (x=0; x<dstwidth; x++) {
2690                             WORD srcval;
2691                             srcval=*srcpixel++;
2692                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2693                                 (colors, 256,
2694                                  ((srcval >>  7) & 0xf8) | /* r */
2695                                  ((srcval >> 12) & 0x07),
2696                                  ((srcval >>  2) & 0xf8) | /* g */
2697                                  ((srcval >>  7) & 0x07),
2698                                  ((srcval <<  3) & 0xf8) | /* b */
2699                                  ((srcval >>  2) & 0x07) );
2700                         }
2701                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2702                         dstbits += linebytes;
2703                     }
2704                 } else if (bmpImage->blue_mask==0x7c00) {
2705                     /* ==== bgr 555 bmp -> pal 8 dib ==== */
2706                     for (h=0; h<lines; h++) {
2707                         srcpixel=srcbits;
2708                         dstbyte=dstbits;
2709                         for (x=0; x<dstwidth; x++) {
2710                             WORD srcval;
2711                             srcval=*srcpixel++;
2712                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2713                                 (colors, 256,
2714                                  ((srcval <<  3) & 0xf8) | /* r */
2715                                  ((srcval >>  2) & 0x07),
2716                                  ((srcval >>  2) & 0xf8) | /* g */
2717                                  ((srcval >>  7) & 0x07),
2718                                  ((srcval >>  7) & 0xf8) | /* b */
2719                                  ((srcval >> 12) & 0x07) );
2720                         }
2721                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2722                         dstbits += linebytes;
2723                     }
2724                 } else {
2725                     goto notsupported;
2726                 }
2727             } else if (bmpImage->green_mask==0x07e0) {
2728                 if (bmpImage->red_mask==0xf800) {
2729                     /* ==== rgb 565 bmp -> pal 8 dib ==== */
2730                     for (h=0; h<lines; h++) {
2731                         srcpixel=srcbits;
2732                         dstbyte=dstbits;
2733                         for (x=0; x<dstwidth; x++) {
2734                             WORD srcval;
2735                             srcval=*srcpixel++;
2736                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2737                                 (colors, 256,
2738                                  ((srcval >>  8) & 0xf8) | /* r */
2739                                  ((srcval >> 13) & 0x07),
2740                                  ((srcval >>  3) & 0xfc) | /* g */
2741                                  ((srcval >>  9) & 0x03),
2742                                  ((srcval <<  3) & 0xf8) | /* b */
2743                                  ((srcval >>  2) & 0x07) );
2744                         }
2745                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2746                         dstbits += linebytes;
2747                     }
2748                 } else if (bmpImage->blue_mask==0xf800) {
2749                     /* ==== bgr 565 bmp -> pal 8 dib ==== */
2750                     for (h=0; h<lines; h++) {
2751                         srcpixel=srcbits;
2752                         dstbyte=dstbits;
2753                         for (x=0; x<dstwidth; x++) {
2754                             WORD srcval;
2755                             srcval=*srcpixel++;
2756                             *dstbyte++=X11DRV_DIB_GetNearestIndex
2757                                 (colors, 256,
2758                                  ((srcval <<  3) & 0xf8) | /* r */
2759                                  ((srcval >>  2) & 0x07),
2760                                  ((srcval >>  3) & 0xfc) | /* g */
2761                                  ((srcval >>  9) & 0x03),
2762                                  ((srcval >>  8) & 0xf8) | /* b */
2763                                  ((srcval >> 13) & 0x07) );
2764                         }
2765                         srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2766                         dstbits += linebytes;
2767                     }
2768                 } else {
2769                     goto notsupported;
2770                 }
2771             } else {
2772                 goto notsupported;
2773             }
2774         }
2775         break;
2776
2777     case 24:
2778     case 32:
2779         {
2780             const void* srcbits;
2781             const BYTE *srcbyte;
2782             BYTE* dstbyte;
2783             int bytes_per_pixel;
2784
2785             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2786             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2787
2788             if (bmpImage->green_mask!=0x00ff00 ||
2789                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2790                 goto notsupported;
2791             } else if (bmpImage->blue_mask==0xff) {
2792                 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2793                 for (h=0; h<lines; h++) {
2794                     srcbyte=srcbits;
2795                     dstbyte=dstbits;
2796                     for (x=0; x<dstwidth; x++) {
2797                         *dstbyte++=X11DRV_DIB_GetNearestIndex
2798                             (colors, 256,
2799                              srcbyte[2],
2800                              srcbyte[1],
2801                              srcbyte[0]);
2802                         srcbyte+=bytes_per_pixel;
2803                     }
2804                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2805                     dstbits += linebytes;
2806                 }
2807             } else {
2808                 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2809                 for (h=0; h<lines; h++) {
2810                     srcbyte=srcbits;
2811                     dstbyte=dstbits;
2812                     for (x=0; x<dstwidth; x++) {
2813                         *dstbyte++=X11DRV_DIB_GetNearestIndex
2814                             (colors, 256,
2815                              srcbyte[0],
2816                              srcbyte[1],
2817                              srcbyte[2]);
2818                         srcbyte+=bytes_per_pixel;
2819                     }
2820                     srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2821                     dstbits += linebytes;
2822                 }
2823             }
2824         }
2825         break;
2826
2827     default:
2828     notsupported:
2829         WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2830               bmpImage->depth, bmpImage->red_mask,
2831               bmpImage->green_mask, bmpImage->blue_mask );
2832     updatesection:
2833         /* ==== any bmp format -> pal 8 dib ==== */
2834         for (h=lines-1; h>=0; h--) {
2835             dstbyte=dstbits;
2836             for (x=0; x<dstwidth; x++) {
2837                 *dstbyte=X11DRV_DIB_MapColor
2838                     ((int*)colors, 256,
2839                      XGetPixel(bmpImage, x, h), *dstbyte);
2840                 dstbyte++;
2841             }
2842             dstbits += linebytes;
2843         }
2844         break;
2845     }
2846 }
2847
2848 /***********************************************************************
2849  *            X11DRV_DIB_SetImageBits_RLE8
2850  *
2851  * SetDIBits for an 8-bit deep compressed DIB.
2852  *
2853  * This function rewritten 941113 by James Youngman.  WINE blew out when I
2854  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2855  *
2856  * This was because the algorithm assumed that all RLE8 bitmaps end with the
2857  * 'End of bitmap' escape code.  This code is very much laxer in what it
2858  * allows to end the expansion.  Possibly too lax.  See the note by
2859  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
2860  * bitmap should end with RleEnd, but on the other hand, software exists
2861  * that produces ones that don't and Windows 3.1 doesn't complain a bit
2862  * about it.
2863  *
2864  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
2865  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
2866  *                                              [JAY]
2867  */
2868 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2869                                           DWORD width, DWORD dstwidth,
2870                                           int left, int *colors,
2871                                           XImage *bmpImage )
2872 {
2873     int x;                      /* X-positon on each line.  Increases. */
2874     int y;                      /* Line #.  Starts at lines-1, decreases */
2875     const BYTE *pIn = bits;     /* Pointer to current position in bits */
2876     BYTE length;                /* The length pf a run */
2877     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
2878
2879     /*
2880      * Note that the bitmap data is stored by Windows starting at the
2881      * bottom line of the bitmap and going upwards.  Within each line,
2882      * the data is stored left-to-right.  That's the reason why line
2883      * goes from lines-1 to 0.                  [JAY]
2884      */
2885
2886     x = 0;
2887     y = lines - 1;
2888     while (y >= 0)
2889     {
2890         length = *pIn++;
2891
2892         /*
2893          * If the length byte is not zero (which is the escape value),
2894          * We have a run of length pixels all the same colour.  The colour
2895          * index is stored next.
2896          *
2897          * If the length byte is zero, we need to read the next byte to
2898          * know what to do.                     [JAY]
2899          */
2900         if (length != 0)
2901         {
2902             /*
2903              * [Run-Length] Encoded mode
2904              */
2905             int color = colors[*pIn++];
2906             while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2907         }
2908         else
2909         {
2910             /*
2911              * Escape codes (may be an absolute sequence though)
2912              */
2913             escape_code = (*pIn++);
2914             switch(escape_code)
2915             {
2916             case RLE_EOL:
2917                 x = 0;
2918                 y--;
2919                 break;
2920
2921             case RLE_END:
2922                 /* Not all RLE8 bitmaps end with this code.  For
2923                  * example, Paint Shop Pro produces some that don't.
2924                  * That's (I think) what caused the previous
2925                  * implementation to fail.  [JAY]
2926                  */
2927                 return;
2928
2929             case RLE_DELTA:
2930                 x += (*pIn++);
2931                 y -= (*pIn++);
2932                 break;
2933
2934             default:  /* switch to absolute mode */
2935                 length = escape_code;
2936                 while (length--)
2937                 {
2938                     int color = colors[*pIn++];
2939                     if (x >= dstwidth)
2940                     {
2941                         pIn += length;
2942                         break;
2943                     }
2944                     XPutPixel(bmpImage, x++, y, color);
2945                 }
2946                 /*
2947                  * If you think for a moment you'll realise that the
2948                  * only time we could ever possibly read an odd
2949                  * number of bytes is when there is a 0x00 (escape),
2950                  * a value >0x02 (absolute mode) and then an odd-
2951                  * length run.  Therefore this is the only place we
2952                  * need to worry about it.  Everywhere else the
2953                  * bytes are always read in pairs.  [JAY]
2954                  */
2955                 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2956                 break;
2957             } /* switch (escape_code) : Escape sequence */
2958         }
2959     }
2960 }
2961
2962
2963 /***********************************************************************
2964  *           X11DRV_DIB_SetImageBits_16
2965  *
2966  * SetDIBits for a 16-bit deep DIB.
2967  */
2968 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2969                                  DWORD srcwidth, DWORD dstwidth, int left,
2970                                        X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2971                                        XImage *bmpImage, DWORD linebytes )
2972 {
2973     DWORD x;
2974     int h;
2975
2976     if (lines < 0 )
2977     {
2978         lines = -lines;
2979         srcbits = srcbits + ( linebytes * (lines-1));
2980         linebytes = -linebytes;
2981     }
2982
2983     switch (bmpImage->depth)
2984     {
2985     case 15:
2986     case 16:
2987         {
2988             char* dstbits;
2989
2990             srcbits=srcbits+left*2;
2991             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2992
2993             if (bmpImage->green_mask==0x03e0) {
2994                 if (gSrc==bmpImage->green_mask) {
2995                     if (rSrc==bmpImage->red_mask) {
2996                         /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2997                         /* ==== bgr 555 dib -> bgr 555 bmp ==== */
2998                         X11DRV_DIB_Convert_any_asis
2999                             (dstwidth,lines,2,
3000                              srcbits,linebytes,
3001                              dstbits,-bmpImage->bytes_per_line);
3002                     } else if (rSrc==bmpImage->blue_mask) {
3003                         /* ==== rgb 555 dib -> bgr 555 bmp ==== */
3004                         /* ==== bgr 555 dib -> rgb 555 bmp ==== */
3005                         X11DRV_DIB_Convert_555_reverse
3006                             (dstwidth,lines,
3007                              srcbits,linebytes,
3008                              dstbits,-bmpImage->bytes_per_line);
3009                     }
3010                 } else {
3011                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3012                         /* ==== rgb 565 dib -> rgb 555 bmp ==== */
3013                         /* ==== bgr 565 dib -> bgr 555 bmp ==== */
3014                         X11DRV_DIB_Convert_565_to_555_asis
3015                             (dstwidth,lines,
3016                              srcbits,linebytes,
3017                              dstbits,-bmpImage->bytes_per_line);
3018                     } else {
3019                         /* ==== rgb 565 dib -> bgr 555 bmp ==== */
3020                         /* ==== bgr 565 dib -> rgb 555 bmp ==== */
3021                         X11DRV_DIB_Convert_565_to_555_reverse
3022                             (dstwidth,lines,
3023                              srcbits,linebytes,
3024                              dstbits,-bmpImage->bytes_per_line);
3025                     }
3026                 }
3027             } else if (bmpImage->green_mask==0x07e0) {
3028                 if (gSrc==bmpImage->green_mask) {
3029                     if (rSrc==bmpImage->red_mask) {
3030                         /* ==== rgb 565 dib -> rgb 565 bmp ==== */
3031                         /* ==== bgr 565 dib -> bgr 565 bmp ==== */
3032                         X11DRV_DIB_Convert_any_asis
3033                             (dstwidth,lines,2,
3034                              srcbits,linebytes,
3035                              dstbits,-bmpImage->bytes_per_line);
3036                     } else {
3037                         /* ==== rgb 565 dib -> bgr 565 bmp ==== */
3038                         /* ==== bgr 565 dib -> rgb 565 bmp ==== */
3039                         X11DRV_DIB_Convert_565_reverse
3040                             (dstwidth,lines,
3041                              srcbits,linebytes,
3042                              dstbits,-bmpImage->bytes_per_line);
3043                     }
3044                 } else {
3045                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3046                         /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3047                         /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3048                         X11DRV_DIB_Convert_555_to_565_asis
3049                             (dstwidth,lines,
3050                              srcbits,linebytes,
3051                              dstbits,-bmpImage->bytes_per_line);
3052                     } else {
3053                         /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3054                         /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3055                         X11DRV_DIB_Convert_555_to_565_reverse
3056                             (dstwidth,lines,
3057                              srcbits,linebytes,
3058                              dstbits,-bmpImage->bytes_per_line);
3059                     }
3060                 }
3061             } else {
3062                 goto notsupported;
3063             }
3064         }
3065         break;
3066
3067     case 24:
3068         if (bmpImage->bits_per_pixel==24) {
3069             char* dstbits;
3070
3071             srcbits=srcbits+left*2;
3072             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3073
3074             if (bmpImage->green_mask!=0x00ff00 ||
3075                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3076                 goto notsupported;
3077             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3078                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3079                 if (gSrc==0x03e0) {
3080                     /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3081                     /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3082                     X11DRV_DIB_Convert_555_to_888_asis
3083                         (dstwidth,lines,
3084                          srcbits,linebytes,
3085                          dstbits,-bmpImage->bytes_per_line);
3086                 } else {
3087                     /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3088                     /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3089                     X11DRV_DIB_Convert_565_to_888_asis
3090                         (dstwidth,lines,
3091                          srcbits,linebytes,
3092                          dstbits,-bmpImage->bytes_per_line);
3093                 }
3094             } else {
3095                 if (gSrc==0x03e0) {
3096                     /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3097                     /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3098                     X11DRV_DIB_Convert_555_to_888_reverse
3099                         (dstwidth,lines,
3100                          srcbits,linebytes,
3101                          dstbits,-bmpImage->bytes_per_line);
3102                 } else {
3103                     /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3104                     /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3105                     X11DRV_DIB_Convert_565_to_888_reverse
3106                         (dstwidth,lines,
3107                          srcbits,linebytes,
3108                          dstbits,-bmpImage->bytes_per_line);
3109                 }
3110             }
3111             break;
3112         }
3113         /* Fall through */
3114
3115     case 32:
3116         {
3117             char* dstbits;
3118
3119             srcbits=srcbits+left*2;
3120             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3121
3122             if (bmpImage->green_mask!=0x00ff00 ||
3123                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3124                 goto notsupported;
3125             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3126                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3127                 if (gSrc==0x03e0) {
3128                     /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3129                     /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3130                     X11DRV_DIB_Convert_555_to_0888_asis
3131                         (dstwidth,lines,
3132                          srcbits,linebytes,
3133                          dstbits,-bmpImage->bytes_per_line);
3134                 } else {
3135                     /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3136                     /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3137                     X11DRV_DIB_Convert_565_to_0888_asis
3138                         (dstwidth,lines,
3139                          srcbits,linebytes,
3140                          dstbits,-bmpImage->bytes_per_line);
3141                 }
3142             } else {
3143                 if (gSrc==0x03e0) {
3144                     /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3145                     /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3146                     X11DRV_DIB_Convert_555_to_0888_reverse
3147                         (dstwidth,lines,
3148                          srcbits,linebytes,
3149                          dstbits,-bmpImage->bytes_per_line);
3150                 } else {
3151                     /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3152                     /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3153                     X11DRV_DIB_Convert_565_to_0888_reverse
3154                         (dstwidth,lines,
3155                          srcbits,linebytes,
3156                          dstbits,-bmpImage->bytes_per_line);
3157                 }
3158             }
3159         }
3160         break;
3161
3162     default:
3163     notsupported:
3164         WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3165               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3166               bmpImage->green_mask, bmpImage->blue_mask );
3167         /* fall through */
3168     case 1:
3169     case 4:
3170     case 8:
3171         {
3172             /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3173             const WORD* srcpixel;
3174             int rShift1,gShift1,bShift1;
3175             int rShift2,gShift2,bShift2;
3176             BYTE gMask1,gMask2;
3177
3178             /* Set color scaling values */
3179             rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3180             gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3181             bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3182             rShift2=rShift1+5;
3183             gShift2=gShift1+5;
3184             bShift2=bShift1+5;
3185             if (gSrc==0x03e0) {
3186                 /* Green has 5 bits, like the others */
3187                 gMask1=0xf8;
3188                 gMask2=0x07;
3189             } else {
3190                 /* Green has 6 bits, not 5. Compensate. */
3191                 gShift1++;
3192                 gShift2+=2;
3193                 gMask1=0xfc;
3194                 gMask2=0x03;
3195             }
3196
3197             srcbits+=2*left;
3198
3199             /* We could split it into four separate cases to optimize
3200              * but it is probably not worth it.
3201              */
3202             for (h=lines-1; h>=0; h--) {
3203                 srcpixel=(const WORD*)srcbits;
3204                 for (x=left; x<dstwidth+left; x++) {
3205                     DWORD srcval;
3206                     BYTE red,green,blue;
3207                     srcval=*srcpixel++ << 16;
3208                     red=  ((srcval >> rShift1) & 0xf8) |
3209                         ((srcval >> rShift2) & 0x07);
3210                     green=((srcval >> gShift1) & gMask1) |
3211                         ((srcval >> gShift2) & gMask2);
3212                     blue= ((srcval >> bShift1) & 0xf8) |
3213                         ((srcval >> bShift2) & 0x07);
3214                     XPutPixel(bmpImage, x, h,
3215                               X11DRV_PALETTE_ToPhysical
3216                               (physDev, RGB(red,green,blue)));
3217                 }
3218                 srcbits += linebytes;
3219             }
3220         }
3221         break;
3222     }
3223 }
3224
3225
3226 /***********************************************************************
3227  *           X11DRV_DIB_GetImageBits_16
3228  *
3229  * GetDIBits for an 16-bit deep DIB.
3230  */
3231 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3232                                         DWORD dstwidth, DWORD srcwidth,
3233                                         PALETTEENTRY *srccolors,
3234                                         DWORD rDst, DWORD gDst, DWORD bDst,
3235                                         XImage *bmpImage, DWORD dibpitch )
3236 {
3237     DWORD x;
3238     int h;
3239
3240     DWORD linebytes = dibpitch;
3241
3242     if (lines < 0 )
3243     {
3244         lines = -lines;
3245         dstbits = dstbits + ( linebytes * (lines-1));
3246         linebytes = -linebytes;
3247     }
3248
3249     switch (bmpImage->depth)
3250     {
3251     case 15:
3252     case 16:
3253         {
3254             const char* srcbits;
3255
3256             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3257
3258             if (bmpImage->green_mask==0x03e0) {
3259                 if (gDst==bmpImage->green_mask) {
3260                     if (rDst==bmpImage->red_mask) {
3261                         /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3262                         /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3263                         X11DRV_DIB_Convert_any_asis
3264                             (dstwidth,lines,2,
3265                              srcbits,-bmpImage->bytes_per_line,
3266                              dstbits,linebytes);
3267                     } else {
3268                         /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3269                         /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3270                         X11DRV_DIB_Convert_555_reverse
3271                             (dstwidth,lines,
3272                              srcbits,-bmpImage->bytes_per_line,
3273                              dstbits,linebytes);
3274                     }
3275                 } else {
3276                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3277                         /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3278                         /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3279                         X11DRV_DIB_Convert_555_to_565_asis
3280                             (dstwidth,lines,
3281                              srcbits,-bmpImage->bytes_per_line,
3282                              dstbits,linebytes);
3283                     } else {
3284                         /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3285                         /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3286                         X11DRV_DIB_Convert_555_to_565_reverse
3287                             (dstwidth,lines,
3288                              srcbits,-bmpImage->bytes_per_line,
3289                              dstbits,linebytes);
3290                     }
3291                 }
3292             } else if (bmpImage->green_mask==0x07e0) {
3293                 if (gDst==bmpImage->green_mask) {
3294                     if (rDst == bmpImage->red_mask) {
3295                         /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3296                         /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3297                         X11DRV_DIB_Convert_any_asis
3298                             (dstwidth,lines,2,
3299                              srcbits,-bmpImage->bytes_per_line,
3300                              dstbits,linebytes);
3301                     } else {
3302                         /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3303                         /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3304                         X11DRV_DIB_Convert_565_reverse
3305                             (dstwidth,lines,
3306                              srcbits,-bmpImage->bytes_per_line,
3307                              dstbits,linebytes);
3308                     }
3309                 } else {
3310                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3311                         /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3312                         /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3313                         X11DRV_DIB_Convert_565_to_555_asis
3314                             (dstwidth,lines,
3315                              srcbits,-bmpImage->bytes_per_line,
3316                              dstbits,linebytes);
3317                     } else {
3318                         /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3319                         /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3320                         X11DRV_DIB_Convert_565_to_555_reverse
3321                             (dstwidth,lines,
3322                              srcbits,-bmpImage->bytes_per_line,
3323                              dstbits,linebytes);
3324                     }
3325                 }
3326             } else {
3327                 goto notsupported;
3328             }
3329         }
3330         break;
3331
3332     case 24:
3333         if (bmpImage->bits_per_pixel == 24) {
3334             const char* srcbits;
3335
3336             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3337
3338             if (bmpImage->green_mask!=0x00ff00 ||
3339                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3340                 goto notsupported;
3341             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3342                     (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3343                 if (gDst==0x03e0) {
3344                     /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3345                     /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3346                     X11DRV_DIB_Convert_888_to_555_asis
3347                         (dstwidth,lines,
3348                          srcbits,-bmpImage->bytes_per_line,
3349                          dstbits,linebytes);
3350                 } else {
3351                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3352                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3353                     X11DRV_DIB_Convert_888_to_565_asis
3354                         (dstwidth,lines,
3355                          srcbits,-bmpImage->bytes_per_line,
3356                          dstbits,linebytes);
3357                 }
3358             } else {
3359                 if (gDst==0x03e0) {
3360                     /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3361                     /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3362                     X11DRV_DIB_Convert_888_to_555_reverse
3363                         (dstwidth,lines,
3364                          srcbits,-bmpImage->bytes_per_line,
3365                          dstbits,linebytes);
3366                 } else {
3367                     /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3368                     /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3369                     X11DRV_DIB_Convert_888_to_565_reverse
3370                         (dstwidth,lines,
3371                          srcbits,-bmpImage->bytes_per_line,
3372                          dstbits,linebytes);
3373                 }
3374             }
3375             break;
3376         }
3377         /* Fall through */
3378
3379     case 32:
3380         {
3381             const char* srcbits;
3382
3383             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3384
3385             if (bmpImage->green_mask!=0x00ff00 ||
3386                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3387                 goto notsupported;
3388             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3389                        (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3390                 if (gDst==0x03e0) {
3391                     /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3392                     /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3393                     X11DRV_DIB_Convert_0888_to_555_asis
3394                         (dstwidth,lines,
3395                          srcbits,-bmpImage->bytes_per_line,
3396                          dstbits,linebytes);
3397                 } else {
3398                     /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3399                     /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3400                     X11DRV_DIB_Convert_0888_to_565_asis
3401                         (dstwidth,lines,
3402                          srcbits,-bmpImage->bytes_per_line,
3403                          dstbits,linebytes);
3404                 }
3405             } else {
3406                 if (gDst==0x03e0) {
3407                     /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3408                     /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3409                     X11DRV_DIB_Convert_0888_to_555_reverse
3410                         (dstwidth,lines,
3411                          srcbits,-bmpImage->bytes_per_line,
3412                          dstbits,linebytes);
3413                 } else {
3414                     /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3415                     /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3416                     X11DRV_DIB_Convert_0888_to_565_reverse
3417                         (dstwidth,lines,
3418                          srcbits,-bmpImage->bytes_per_line,
3419                          dstbits,linebytes);
3420                 }
3421             }
3422         }
3423         break;
3424
3425     case 1:
3426     case 4:
3427         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3428             /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3429             int rShift,gShift,bShift;
3430             WORD* dstpixel;
3431
3432             /* Shift everything 16 bits left so that all shifts are >0,
3433              * even for BGR DIBs. Then a single >> 16 will bring everything
3434              * back into place.
3435              */
3436             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3437             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3438             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3439             if (gDst==0x07e0) {
3440                 /* 6 bits for the green */
3441                 gShift++;
3442             }
3443             rDst=rDst << 16;
3444             gDst=gDst << 16;
3445             bDst=bDst << 16;
3446             for (h = lines - 1; h >= 0; h--) {
3447                 dstpixel=(LPWORD)dstbits;
3448                 for (x = 0; x < dstwidth; x++) {
3449                     PALETTEENTRY srcval;
3450                     DWORD dstval;
3451                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
3452                     dstval=((srcval.peRed   << rShift) & rDst) |
3453                            ((srcval.peGreen << gShift) & gDst) |
3454                            ((srcval.peBlue  << bShift) & bDst);
3455                     *dstpixel++=dstval >> 16;
3456                 }
3457                 dstbits += linebytes;
3458             }
3459         } else {
3460             goto notsupported;
3461         }
3462         break;
3463
3464     case 8:
3465         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3466             /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3467             int rShift,gShift,bShift;
3468             const BYTE* srcbits;
3469             const BYTE* srcpixel;
3470             WORD* dstpixel;
3471
3472             /* Shift everything 16 bits left so that all shifts are >0,
3473              * even for BGR DIBs. Then a single >> 16 will bring everything
3474              * back into place.
3475              */
3476             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3477             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3478             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3479             if (gDst==0x07e0) {
3480                 /* 6 bits for the green */
3481                 gShift++;
3482             }
3483             rDst=rDst << 16;
3484             gDst=gDst << 16;
3485             bDst=bDst << 16;
3486             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3487             for (h=0; h<lines; h++) {
3488                 srcpixel=srcbits;
3489                 dstpixel=(LPWORD)dstbits;
3490                 for (x = 0; x < dstwidth; x++) {
3491                     PALETTEENTRY srcval;
3492                     DWORD dstval;
3493                     srcval=srccolors[(int)*srcpixel++];
3494                     dstval=((srcval.peRed   << rShift) & rDst) |
3495                            ((srcval.peGreen << gShift) & gDst) |
3496                            ((srcval.peBlue  << bShift) & bDst);
3497                     *dstpixel++=dstval >> 16;
3498                 }
3499                 srcbits -= bmpImage->bytes_per_line;
3500                 dstbits += linebytes;
3501             }
3502         } else {
3503             goto notsupported;
3504         }
3505         break;
3506
3507     default:
3508     notsupported:
3509         {
3510             /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3511             int rShift,gShift,bShift;
3512             WORD* dstpixel;
3513
3514             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3515                   bmpImage->depth, bmpImage->red_mask,
3516                   bmpImage->green_mask, bmpImage->blue_mask,
3517                   rDst, gDst, bDst);
3518
3519             /* Shift everything 16 bits left so that all shifts are >0,
3520              * even for BGR DIBs. Then a single >> 16 will bring everything
3521              * back into place.
3522              */
3523             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3524             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3525             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3526             if (gDst==0x07e0) {
3527                 /* 6 bits for the green */
3528                 gShift++;
3529             }
3530             rDst=rDst << 16;
3531             gDst=gDst << 16;
3532             bDst=bDst << 16;
3533             for (h = lines - 1; h >= 0; h--) {
3534                 dstpixel=(LPWORD)dstbits;
3535                 for (x = 0; x < dstwidth; x++) {
3536                     COLORREF srcval;
3537                     DWORD dstval;
3538                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3539                     dstval=((GetRValue(srcval) << rShift) & rDst) |
3540                            ((GetGValue(srcval) << gShift) & gDst) |
3541                            ((GetBValue(srcval) << bShift) & bDst);
3542                     *dstpixel++=dstval >> 16;
3543                 }
3544                 dstbits += linebytes;
3545             }
3546         }
3547         break;
3548     }
3549 }
3550
3551
3552 /***********************************************************************
3553  *           X11DRV_DIB_SetImageBits_24
3554  *
3555  * SetDIBits for a 24-bit deep DIB.
3556  */
3557 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3558                                  DWORD srcwidth, DWORD dstwidth, int left,
3559                                  X11DRV_PDEVICE *physDev,
3560                                  DWORD rSrc, DWORD gSrc, DWORD bSrc,
3561                                  XImage *bmpImage, DWORD linebytes )
3562 {
3563     DWORD x;
3564     int h;
3565
3566     if (lines < 0 )
3567     {
3568         lines = -lines;
3569         srcbits = srcbits + linebytes * (lines - 1);
3570         linebytes = -linebytes;
3571     }
3572
3573     switch (bmpImage->depth)
3574     {
3575     case 24:
3576         if (bmpImage->bits_per_pixel==24) {
3577             char* dstbits;
3578
3579             srcbits=srcbits+left*3;
3580             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3581
3582             if (bmpImage->green_mask!=0x00ff00 ||
3583                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3584                 goto notsupported;
3585             } else if (rSrc==bmpImage->red_mask) {
3586                 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3587                 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3588                 X11DRV_DIB_Convert_any_asis
3589                     (dstwidth,lines,3,
3590                      srcbits,linebytes,
3591                      dstbits,-bmpImage->bytes_per_line);
3592             } else {
3593                 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3594                 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3595                 X11DRV_DIB_Convert_888_reverse
3596                     (dstwidth,lines,
3597                      srcbits,linebytes,
3598                      dstbits,-bmpImage->bytes_per_line);
3599             }
3600             break;
3601         }
3602         /* fall through */
3603
3604     case 32:
3605         {
3606             char* dstbits;
3607
3608             srcbits=srcbits+left*3;
3609             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3610
3611             if (bmpImage->green_mask!=0x00ff00 ||
3612                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3613                 goto notsupported;
3614             } else if (rSrc==bmpImage->red_mask) {
3615                 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3616                 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3617                 X11DRV_DIB_Convert_888_to_0888_asis
3618                     (dstwidth,lines,
3619                      srcbits,linebytes,
3620                      dstbits,-bmpImage->bytes_per_line);
3621             } else {
3622                 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3623                 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3624                 X11DRV_DIB_Convert_888_to_0888_reverse
3625                     (dstwidth,lines,
3626                      srcbits,linebytes,
3627                      dstbits,-bmpImage->bytes_per_line);
3628             }
3629             break;
3630         }
3631
3632     case 15:
3633     case 16:
3634         {
3635             char* dstbits;
3636
3637             srcbits=srcbits+left*3;
3638             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3639
3640             if (bmpImage->green_mask==0x03e0) {
3641                 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3642                     (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3643                     /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3644                     /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3645                     X11DRV_DIB_Convert_888_to_555_asis
3646                         (dstwidth,lines,
3647                          srcbits,linebytes,
3648                          dstbits,-bmpImage->bytes_per_line);
3649                 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3650                            (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3651                     /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3652                     /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3653                     X11DRV_DIB_Convert_888_to_555_reverse
3654                         (dstwidth,lines,
3655                          srcbits,linebytes,
3656                          dstbits,-bmpImage->bytes_per_line);
3657                 } else {
3658                     goto notsupported;
3659                 }
3660             } else if (bmpImage->green_mask==0x07e0) {
3661                 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3662                     (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3663                     /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3664                     /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3665                     X11DRV_DIB_Convert_888_to_565_asis
3666                         (dstwidth,lines,
3667                          srcbits,linebytes,
3668                          dstbits,-bmpImage->bytes_per_line);
3669                 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3670                            (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3671                     /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3672                     /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3673                     X11DRV_DIB_Convert_888_to_565_reverse
3674                         (dstwidth,lines,
3675                          srcbits,linebytes,
3676                          dstbits,-bmpImage->bytes_per_line);
3677                 } else {
3678                     goto notsupported;
3679                 }
3680             } else {
3681                 goto notsupported;
3682             }
3683         }
3684         break;
3685
3686     default:
3687     notsupported:
3688         WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3689               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3690               bmpImage->green_mask, bmpImage->blue_mask );
3691         /* fall through */
3692     case 1:
3693     case 4:
3694     case 8:
3695         {
3696             /* ==== rgb 888 dib -> any bmp bormat ==== */
3697             const BYTE* srcbyte;
3698
3699             /* Windows only supports one 24bpp DIB format: RGB888 */
3700             srcbits+=left*3;
3701             for (h = lines - 1; h >= 0; h--) {
3702                 srcbyte=(const BYTE*)srcbits;
3703                 for (x = left; x < dstwidth+left; x++) {
3704                     XPutPixel(bmpImage, x, h,
3705                               X11DRV_PALETTE_ToPhysical
3706                               (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3707                     srcbyte+=3;
3708                 }
3709                 srcbits += linebytes;
3710             }
3711         }
3712         break;
3713     }
3714 }
3715
3716
3717 /***********************************************************************
3718  *           X11DRV_DIB_GetImageBits_24
3719  *
3720  * GetDIBits for an 24-bit deep DIB.
3721  */
3722 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3723                                         DWORD dstwidth, DWORD srcwidth,
3724                                         PALETTEENTRY *srccolors,
3725                                         DWORD rDst, DWORD gDst, DWORD bDst,
3726                                         XImage *bmpImage, DWORD linebytes )
3727 {
3728     DWORD x;
3729     int h;
3730
3731     if (lines < 0 )
3732     {
3733         lines = -lines;
3734         dstbits = dstbits + ( linebytes * (lines-1) );
3735         linebytes = -linebytes;
3736     }
3737
3738     switch (bmpImage->depth)
3739     {
3740     case 24:
3741         if (bmpImage->bits_per_pixel==24) {
3742             const char* srcbits;
3743
3744             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3745
3746             if (bmpImage->green_mask!=0x00ff00 ||
3747                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3748                 goto notsupported;
3749             } else if (rDst==bmpImage->red_mask) {
3750                 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3751                 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3752                 X11DRV_DIB_Convert_any_asis
3753                     (dstwidth,lines,3,
3754                      srcbits,-bmpImage->bytes_per_line,
3755                      dstbits,linebytes);
3756             } else {
3757                 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3758                 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3759                 X11DRV_DIB_Convert_888_reverse
3760                     (dstwidth,lines,
3761                      srcbits,-bmpImage->bytes_per_line,
3762                      dstbits,linebytes);
3763             }
3764             break;
3765         }
3766         /* fall through */
3767
3768     case 32:
3769         {
3770             const char* srcbits;
3771
3772             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3773
3774             if (bmpImage->green_mask!=0x00ff00 ||
3775                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3776                 goto notsupported;
3777             } else if (rDst==bmpImage->red_mask) {
3778                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3779                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3780                 X11DRV_DIB_Convert_0888_to_888_asis
3781                     (dstwidth,lines,
3782                      srcbits,-bmpImage->bytes_per_line,
3783                      dstbits,linebytes);
3784             } else {
3785                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3786                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3787                 X11DRV_DIB_Convert_0888_to_888_reverse
3788                     (dstwidth,lines,
3789                      srcbits,-bmpImage->bytes_per_line,
3790                      dstbits,linebytes);
3791             }
3792             break;
3793         }
3794
3795     case 15:
3796     case 16:
3797         {
3798             const char* srcbits;
3799
3800             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3801
3802             if (bmpImage->green_mask==0x03e0) {
3803                 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3804                     (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3805                     /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3806                     /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3807                     X11DRV_DIB_Convert_555_to_888_asis
3808                         (dstwidth,lines,
3809                          srcbits,-bmpImage->bytes_per_line,
3810                          dstbits,linebytes);
3811                 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3812                            (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3813                     /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3814                     /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3815                     X11DRV_DIB_Convert_555_to_888_reverse
3816                         (dstwidth,lines,
3817                          srcbits,-bmpImage->bytes_per_line,
3818                          dstbits,linebytes);
3819                 } else {
3820                     goto notsupported;
3821                 }
3822             } else if (bmpImage->green_mask==0x07e0) {
3823                 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3824                     (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3825                     /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3826                     /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3827                     X11DRV_DIB_Convert_565_to_888_asis
3828                         (dstwidth,lines,
3829                          srcbits,-bmpImage->bytes_per_line,
3830                          dstbits,linebytes);
3831                 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3832                            (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3833                     /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3834                     /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3835                     X11DRV_DIB_Convert_565_to_888_reverse
3836                         (dstwidth,lines,
3837                          srcbits,-bmpImage->bytes_per_line,
3838                          dstbits,linebytes);
3839                 } else {
3840                     goto notsupported;
3841                 }
3842             } else {
3843                 goto notsupported;
3844             }
3845         }
3846         break;
3847
3848     case 1:
3849     case 4:
3850         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3851             /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3852             BYTE* dstbyte;
3853
3854             /* Windows only supports one 24bpp DIB format: rgb 888 */
3855             for (h = lines - 1; h >= 0; h--) {
3856                 dstbyte=dstbits;
3857                 for (x = 0; x < dstwidth; x++) {
3858                     PALETTEENTRY srcval;
3859                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
3860                     dstbyte[0]=srcval.peBlue;
3861                     dstbyte[1]=srcval.peGreen;
3862                     dstbyte[2]=srcval.peRed;
3863                     dstbyte+=3;
3864                 }
3865                 dstbits += linebytes;
3866             }
3867         } else {
3868             goto notsupported;
3869         }
3870         break;
3871
3872     case 8:
3873         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3874             /* ==== pal 8 bmp -> rgb 888 dib ==== */
3875             const void* srcbits;
3876             const BYTE* srcpixel;
3877             BYTE* dstbyte;
3878
3879             /* Windows only supports one 24bpp DIB format: rgb 888 */
3880             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3881             for (h = lines - 1; h >= 0; h--) {
3882                 srcpixel=srcbits;
3883                 dstbyte=dstbits;
3884                 for (x = 0; x < dstwidth; x++ ) {
3885                     PALETTEENTRY srcval;
3886                     srcval=srccolors[(int)*srcpixel++];
3887                     dstbyte[0]=srcval.peBlue;
3888                     dstbyte[1]=srcval.peGreen;
3889                     dstbyte[2]=srcval.peRed;
3890                     dstbyte+=3;
3891                 }
3892                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3893                 dstbits += linebytes;
3894             }
3895         } else {
3896             goto notsupported;
3897         }
3898         break;
3899
3900     default:
3901     notsupported:
3902         {
3903             /* ==== any bmp format -> 888 dib ==== */
3904             BYTE* dstbyte;
3905
3906             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3907                   bmpImage->depth, bmpImage->red_mask,
3908                   bmpImage->green_mask, bmpImage->blue_mask,
3909                   rDst, gDst, bDst );
3910
3911             /* Windows only supports one 24bpp DIB format: rgb 888 */
3912             for (h = lines - 1; h >= 0; h--) {
3913                 dstbyte=dstbits;
3914                 for (x = 0; x < dstwidth; x++) {
3915                     COLORREF srcval=X11DRV_PALETTE_ToLogical
3916                         (XGetPixel( bmpImage, x, h ));
3917                     dstbyte[0]=GetBValue(srcval);
3918                     dstbyte[1]=GetGValue(srcval);
3919                     dstbyte[2]=GetRValue(srcval);
3920                     dstbyte+=3;
3921                 }
3922                 dstbits += linebytes;
3923             }
3924         }
3925         break;
3926     }
3927 }
3928
3929
3930 /***********************************************************************
3931  *           X11DRV_DIB_SetImageBits_32
3932  *
3933  * SetDIBits for a 32-bit deep DIB.
3934  */
3935 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3936                                        DWORD srcwidth, DWORD dstwidth, int left,
3937                                        X11DRV_PDEVICE *physDev,
3938                                        DWORD rSrc, DWORD gSrc, DWORD bSrc,
3939                                        XImage *bmpImage,
3940                                        DWORD linebytes)
3941 {
3942     DWORD x, *ptr;
3943     int h;
3944
3945     if (lines < 0 )
3946     {
3947        lines = -lines;
3948        srcbits = srcbits + ( linebytes * (lines-1) );
3949        linebytes = -linebytes;
3950     }
3951
3952     ptr = (DWORD *) srcbits + left;
3953
3954     switch (bmpImage->depth)
3955     {
3956     case 24:
3957         if (bmpImage->bits_per_pixel==24) {
3958             char* dstbits;
3959
3960             srcbits=srcbits+left*4;
3961             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3962
3963             if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3964                 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3965                 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3966                 X11DRV_DIB_Convert_0888_to_888_asis
3967                     (dstwidth,lines,
3968                      srcbits,linebytes,
3969                      dstbits,-bmpImage->bytes_per_line);
3970             } else if (bmpImage->green_mask!=0x00ff00 ||
3971                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3972                 goto notsupported;
3973                 /* the tests below assume sane bmpImage masks */
3974             } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3975                 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3976                 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3977                 X11DRV_DIB_Convert_0888_to_888_reverse
3978                     (dstwidth,lines,
3979                      srcbits,linebytes,
3980                      dstbits,-bmpImage->bytes_per_line);
3981             } else if (bmpImage->blue_mask==0xff) {
3982                 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3983                 X11DRV_DIB_Convert_any0888_to_rgb888
3984                     (dstwidth,lines,
3985                      srcbits,linebytes,
3986                      rSrc,gSrc,bSrc,
3987                      dstbits,-bmpImage->bytes_per_line);
3988             } else {
3989                 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3990                 X11DRV_DIB_Convert_any0888_to_bgr888
3991                     (dstwidth,lines,
3992                      srcbits,linebytes,
3993                      rSrc,gSrc,bSrc,
3994                      dstbits,-bmpImage->bytes_per_line);
3995             }
3996             break;
3997         }
3998         /* fall through */
3999
4000     case 32:
4001         {
4002             char* dstbits;
4003
4004             srcbits=srcbits+left*4;
4005             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
4006
4007             if (gSrc==bmpImage->green_mask) {
4008                 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
4009                     /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
4010                     /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
4011                     X11DRV_DIB_Convert_any_asis
4012                         (dstwidth,lines,4,
4013                          srcbits,linebytes,
4014                          dstbits,-bmpImage->bytes_per_line);
4015                 } else if (bmpImage->green_mask!=0x00ff00 ||
4016                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4017                     goto notsupported;
4018                     /* the tests below assume sane bmpImage masks */
4019                 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
4020                     /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
4021                     /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
4022                     X11DRV_DIB_Convert_0888_reverse
4023                         (dstwidth,lines,
4024                          srcbits,linebytes,
4025                          dstbits,-bmpImage->bytes_per_line);
4026                 } else {
4027                     /* ==== any 0888 dib -> any 0888 bmp ==== */
4028                     X11DRV_DIB_Convert_0888_any
4029                         (dstwidth,lines,
4030                          srcbits,linebytes,
4031                          rSrc,gSrc,bSrc,
4032                          dstbits,-bmpImage->bytes_per_line,
4033                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4034                 }
4035             } else if (bmpImage->green_mask!=0x00ff00 ||
4036                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4037                 goto notsupported;
4038                 /* the tests below assume sane bmpImage masks */
4039             } else {
4040                 /* ==== any 0888 dib -> any 0888 bmp ==== */
4041                 X11DRV_DIB_Convert_0888_any
4042                     (dstwidth,lines,
4043                      srcbits,linebytes,
4044                      rSrc,gSrc,bSrc,
4045                      dstbits,-bmpImage->bytes_per_line,
4046                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4047             }
4048         }
4049         break;
4050
4051     case 15:
4052     case 16:
4053         {
4054             char* dstbits;
4055
4056             srcbits=srcbits+left*4;
4057             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4058
4059             if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4060                 if (bmpImage->green_mask==0x03e0) {
4061                     if (bmpImage->red_mask==0x7f00) {
4062                         /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4063                         X11DRV_DIB_Convert_0888_to_555_asis
4064                             (dstwidth,lines,
4065                              srcbits,linebytes,
4066                              dstbits,-bmpImage->bytes_per_line);
4067                     } else if (bmpImage->blue_mask==0x7f00) {
4068                         /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4069                         X11DRV_DIB_Convert_0888_to_555_reverse
4070                             (dstwidth,lines,
4071                              srcbits,linebytes,
4072                              dstbits,-bmpImage->bytes_per_line);
4073                     } else {
4074                         goto notsupported;
4075                     }
4076                 } else if (bmpImage->green_mask==0x07e0) {
4077                     if (bmpImage->red_mask==0xf800) {
4078                         /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4079                         X11DRV_DIB_Convert_0888_to_565_asis
4080                             (dstwidth,lines,
4081                              srcbits,linebytes,
4082                              dstbits,-bmpImage->bytes_per_line);
4083                     } else if (bmpImage->blue_mask==0xf800) {
4084                         /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4085                         X11DRV_DIB_Convert_0888_to_565_reverse
4086                             (dstwidth,lines,
4087                              srcbits,linebytes,
4088                              dstbits,-bmpImage->bytes_per_line);
4089                     } else {
4090                         goto notsupported;
4091                     }
4092                 } else {
4093                     goto notsupported;
4094                 }
4095             } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4096                 if (bmpImage->green_mask==0x03e0) {
4097                     if (bmpImage->blue_mask==0x7f00) {
4098                         /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4099                         X11DRV_DIB_Convert_0888_to_555_asis
4100                             (dstwidth,lines,
4101                              srcbits,linebytes,
4102                              dstbits,-bmpImage->bytes_per_line);
4103                     } else if (bmpImage->red_mask==0x7f00) {
4104                         /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4105                         X11DRV_DIB_Convert_0888_to_555_reverse
4106                             (dstwidth,lines,
4107                              srcbits,linebytes,
4108                              dstbits,-bmpImage->bytes_per_line);
4109                     } else {
4110                         goto notsupported;
4111                     }
4112                 } else if (bmpImage->green_mask==0x07e0) {
4113                     if (bmpImage->blue_mask==0xf800) {
4114                         /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4115                         X11DRV_DIB_Convert_0888_to_565_asis
4116                             (dstwidth,lines,
4117                              srcbits,linebytes,
4118                              dstbits,-bmpImage->bytes_per_line);
4119                     } else if (bmpImage->red_mask==0xf800) {
4120                         /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4121                         X11DRV_DIB_Convert_0888_to_565_reverse
4122                             (dstwidth,lines,
4123                              srcbits,linebytes,
4124                              dstbits,-bmpImage->bytes_per_line);
4125                     } else {
4126                         goto notsupported;
4127                     }
4128                 } else {
4129                     goto notsupported;
4130                 }
4131             } else {
4132                 if (bmpImage->green_mask==0x03e0 &&
4133                     (bmpImage->red_mask==0x7f00 ||
4134                      bmpImage->blue_mask==0x7f00)) {
4135                     /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4136                     X11DRV_DIB_Convert_any0888_to_5x5
4137                         (dstwidth,lines,
4138                          srcbits,linebytes,
4139                          rSrc,gSrc,bSrc,
4140                          dstbits,-bmpImage->bytes_per_line,
4141                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4142                 } else if (bmpImage->green_mask==0x07e0 &&
4143                            (bmpImage->red_mask==0xf800 ||
4144                             bmpImage->blue_mask==0xf800)) {
4145                     /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4146                     X11DRV_DIB_Convert_any0888_to_5x5
4147                         (dstwidth,lines,
4148                          srcbits,linebytes,
4149                          rSrc,gSrc,bSrc,
4150                          dstbits,-bmpImage->bytes_per_line,
4151                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4152                 } else {
4153                     goto notsupported;
4154                 }
4155             }
4156         }
4157         break;
4158
4159     default:
4160     notsupported:
4161         WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4162               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4163               bmpImage->green_mask, bmpImage->blue_mask );
4164         /* fall through */
4165     case 1:
4166     case 4:
4167     case 8:
4168         {
4169             /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4170             const DWORD* srcpixel;
4171             int rShift,gShift,bShift;
4172
4173             rShift=X11DRV_DIB_MaskToShift(rSrc);
4174             gShift=X11DRV_DIB_MaskToShift(gSrc);
4175             bShift=X11DRV_DIB_MaskToShift(bSrc);
4176             srcbits+=left*4;
4177             for (h = lines - 1; h >= 0; h--) {
4178                 srcpixel=(const DWORD*)srcbits;
4179                 for (x = left; x < dstwidth+left; x++) {
4180                     DWORD srcvalue;
4181                     BYTE red,green,blue;
4182                     srcvalue=*srcpixel++;
4183                     red=  (srcvalue >> rShift) & 0xff;
4184                     green=(srcvalue >> gShift) & 0xff;
4185                     blue= (srcvalue >> bShift) & 0xff;
4186                     XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4187                               (physDev, RGB(red,green,blue)));
4188                 }
4189                 srcbits += linebytes;
4190             }
4191         }
4192         break;
4193     }
4194
4195 }
4196
4197 /***********************************************************************
4198  *           X11DRV_DIB_GetImageBits_32
4199  *
4200  * GetDIBits for an 32-bit deep DIB.
4201  */
4202 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4203                                         DWORD dstwidth, DWORD srcwidth,
4204                                         PALETTEENTRY *srccolors,
4205                                         DWORD rDst, DWORD gDst, DWORD bDst,
4206                                         XImage *bmpImage, DWORD linebytes )
4207 {
4208     DWORD x;
4209     int h;
4210     BYTE *bits;
4211
4212     if (lines < 0 )
4213     {
4214         lines = -lines;
4215         dstbits = dstbits + ( linebytes * (lines-1) );
4216         linebytes = -linebytes;
4217     }
4218
4219     bits = dstbits;
4220
4221     switch (bmpImage->depth)
4222     {
4223     case 24:
4224         if (bmpImage->bits_per_pixel==24) {
4225             const void* srcbits;
4226
4227             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4228
4229             if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4230                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4231                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4232                 X11DRV_DIB_Convert_888_to_0888_asis
4233                     (dstwidth,lines,
4234                      srcbits,-bmpImage->bytes_per_line,
4235                      dstbits,linebytes);
4236             } else if (bmpImage->green_mask!=0x00ff00 ||
4237                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4238                 goto notsupported;
4239                 /* the tests below assume sane bmpImage masks */
4240             } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4241                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4242                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4243                 X11DRV_DIB_Convert_888_to_0888_reverse
4244                     (dstwidth,lines,
4245                      srcbits,-bmpImage->bytes_per_line,
4246                      dstbits,linebytes);
4247             } else if (bmpImage->blue_mask==0xff) {
4248                 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4249                 X11DRV_DIB_Convert_rgb888_to_any0888
4250                     (dstwidth,lines,
4251                      srcbits,-bmpImage->bytes_per_line,
4252                      dstbits,linebytes,
4253                      rDst,gDst,bDst);
4254             } else {
4255                 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4256                 X11DRV_DIB_Convert_bgr888_to_any0888
4257                     (dstwidth,lines,
4258                      srcbits,-bmpImage->bytes_per_line,
4259                      dstbits,linebytes,
4260                      rDst,gDst,bDst);
4261             }
4262             break;
4263         }
4264         /* fall through */
4265
4266     case 32:
4267         {
4268             const char* srcbits;
4269
4270             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4271
4272             if (gDst==bmpImage->green_mask) {
4273                 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4274                     /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4275                     /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4276                     X11DRV_DIB_Convert_any_asis
4277                         (dstwidth,lines,4,
4278                          srcbits,-bmpImage->bytes_per_line,
4279                          dstbits,linebytes);
4280                 } else if (bmpImage->green_mask!=0x00ff00 ||
4281                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4282                     goto notsupported;
4283                     /* the tests below assume sane bmpImage masks */
4284                 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
4285                     /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4286                     /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4287                     X11DRV_DIB_Convert_0888_reverse
4288                         (dstwidth,lines,
4289                          srcbits,-bmpImage->bytes_per_line,
4290                          dstbits,linebytes);
4291                 } else {
4292                     /* ==== any 0888 bmp -> any 0888 dib ==== */
4293                     X11DRV_DIB_Convert_0888_any
4294                         (dstwidth,lines,
4295                          srcbits,-bmpImage->bytes_per_line,
4296                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4297                          dstbits,linebytes,
4298                          rDst,gDst,bDst);
4299                 }
4300             } else if (bmpImage->green_mask!=0x00ff00 ||
4301                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4302                 goto notsupported;
4303                 /* the tests below assume sane bmpImage masks */
4304             } else {
4305                 /* ==== any 0888 bmp -> any 0888 dib ==== */
4306                 X11DRV_DIB_Convert_0888_any
4307                     (dstwidth,lines,
4308                      srcbits,-bmpImage->bytes_per_line,
4309                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4310                      dstbits,linebytes,
4311                      rDst,gDst,bDst);
4312             }
4313         }
4314         break;
4315
4316     case 15:
4317     case 16:
4318         {
4319             const char* srcbits;
4320
4321             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4322
4323             if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4324                 if (bmpImage->green_mask==0x03e0) {
4325                     if (bmpImage->red_mask==0x7f00) {
4326                         /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4327                         X11DRV_DIB_Convert_555_to_0888_asis
4328                             (dstwidth,lines,
4329                              srcbits,-bmpImage->bytes_per_line,
4330                              dstbits,linebytes);
4331                     } else if (bmpImage->blue_mask==0x7f00) {
4332                         /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4333                         X11DRV_DIB_Convert_555_to_0888_reverse
4334                             (dstwidth,lines,
4335                              srcbits,-bmpImage->bytes_per_line,
4336                              dstbits,linebytes);
4337                     } else {
4338                         goto notsupported;
4339                     }
4340                 } else if (bmpImage->green_mask==0x07e0) {
4341                     if (bmpImage->red_mask==0xf800) {
4342                         /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4343                         X11DRV_DIB_Convert_565_to_0888_asis
4344                             (dstwidth,lines,
4345                              srcbits,-bmpImage->bytes_per_line,
4346                              dstbits,linebytes);
4347                     } else if (bmpImage->blue_mask==0xf800) {
4348                         /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4349                         X11DRV_DIB_Convert_565_to_0888_reverse
4350                             (dstwidth,lines,
4351                              srcbits,-bmpImage->bytes_per_line,
4352                              dstbits,linebytes);
4353                     } else {
4354                         goto notsupported;
4355                     }
4356                 } else {
4357                     goto notsupported;
4358                 }
4359             } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4360                 if (bmpImage->green_mask==0x03e0) {
4361                     if (bmpImage->blue_mask==0x7f00) {
4362                         /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4363                         X11DRV_DIB_Convert_555_to_0888_asis
4364                             (dstwidth,lines,
4365                              srcbits,-bmpImage->bytes_per_line,
4366                              dstbits,linebytes);
4367                     } else if (bmpImage->red_mask==0x7f00) {
4368                         /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4369                         X11DRV_DIB_Convert_555_to_0888_reverse
4370                             (dstwidth,lines,
4371                              srcbits,-bmpImage->bytes_per_line,
4372                              dstbits,linebytes);
4373                     } else {
4374                         goto notsupported;
4375                     }
4376                 } else if (bmpImage->green_mask==0x07e0) {
4377                     if (bmpImage->blue_mask==0xf800) {
4378                         /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4379                         X11DRV_DIB_Convert_565_to_0888_asis
4380                             (dstwidth,lines,
4381                              srcbits,-bmpImage->bytes_per_line,
4382                              dstbits,linebytes);
4383                     } else if (bmpImage->red_mask==0xf800) {
4384                         /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4385                         X11DRV_DIB_Convert_565_to_0888_reverse
4386                             (dstwidth,lines,
4387                              srcbits,-bmpImage->bytes_per_line,
4388                              dstbits,linebytes);
4389                     } else {
4390                         goto notsupported;
4391                     }
4392                 } else {
4393                     goto notsupported;
4394                 }
4395             } else {
4396                 if (bmpImage->green_mask==0x03e0 &&
4397                     (bmpImage->red_mask==0x7f00 ||
4398                      bmpImage->blue_mask==0x7f00)) {
4399                     /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4400                     X11DRV_DIB_Convert_5x5_to_any0888
4401                         (dstwidth,lines,
4402                          srcbits,-bmpImage->bytes_per_line,
4403                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4404                          dstbits,linebytes,
4405                          rDst,gDst,bDst);
4406                 } else if (bmpImage->green_mask==0x07e0 &&
4407                            (bmpImage->red_mask==0xf800 ||
4408                             bmpImage->blue_mask==0xf800)) {
4409                     /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4410                     X11DRV_DIB_Convert_5x5_to_any0888
4411                         (dstwidth,lines,
4412                          srcbits,-bmpImage->bytes_per_line,
4413                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4414                          dstbits,linebytes,
4415                          rDst,gDst,bDst);
4416                 } else {
4417                     goto notsupported;
4418                 }
4419             }
4420         }
4421         break;
4422
4423     case 1:
4424     case 4:
4425         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4426             /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4427             int rShift,gShift,bShift;
4428             DWORD* dstpixel;
4429
4430             rShift=X11DRV_DIB_MaskToShift(rDst);
4431             gShift=X11DRV_DIB_MaskToShift(gDst);
4432             bShift=X11DRV_DIB_MaskToShift(bDst);
4433             for (h = lines - 1; h >= 0; h--) {
4434                 dstpixel=(DWORD*)dstbits;
4435                 for (x = 0; x < dstwidth; x++) {
4436                     PALETTEENTRY srcval;
4437                     srcval = srccolors[XGetPixel(bmpImage, x, h)];
4438                     *dstpixel++=(srcval.peRed   << rShift) |
4439                                 (srcval.peGreen << gShift) |
4440                                 (srcval.peBlue  << bShift);
4441                 }
4442                 dstbits += linebytes;
4443             }
4444         } else {
4445             goto notsupported;
4446         }
4447         break;
4448
4449     case 8:
4450         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4451             /* ==== pal 8 bmp -> any 0888 dib ==== */
4452             int rShift,gShift,bShift;
4453             const void* srcbits;
4454             const BYTE* srcpixel;
4455             DWORD* dstpixel;
4456
4457             rShift=X11DRV_DIB_MaskToShift(rDst);
4458             gShift=X11DRV_DIB_MaskToShift(gDst);
4459             bShift=X11DRV_DIB_MaskToShift(bDst);
4460             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4461             for (h = lines - 1; h >= 0; h--) {
4462                 srcpixel=srcbits;
4463                 dstpixel=(DWORD*)dstbits;
4464                 for (x = 0; x < dstwidth; x++) {
4465                     PALETTEENTRY srcval;
4466                     srcval=srccolors[(int)*srcpixel++];
4467                     *dstpixel++=(srcval.peRed   << rShift) |
4468                                 (srcval.peGreen << gShift) |
4469                                 (srcval.peBlue  << bShift);
4470                 }
4471                 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
4472                 dstbits += linebytes;
4473             }
4474         } else {
4475             goto notsupported;
4476         }
4477         break;
4478
4479     default:
4480     notsupported:
4481         {
4482             /* ==== any bmp format -> any 0888 dib ==== */
4483             int rShift,gShift,bShift;
4484             DWORD* dstpixel;
4485
4486             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4487                   bmpImage->depth, bmpImage->red_mask,
4488                   bmpImage->green_mask, bmpImage->blue_mask,
4489                   rDst,gDst,bDst);
4490
4491             rShift=X11DRV_DIB_MaskToShift(rDst);
4492             gShift=X11DRV_DIB_MaskToShift(gDst);
4493             bShift=X11DRV_DIB_MaskToShift(bDst);
4494             for (h = lines - 1; h >= 0; h--) {
4495                 dstpixel=(DWORD*)dstbits;
4496                 for (x = 0; x < dstwidth; x++) {
4497                     COLORREF srcval;
4498                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4499                     *dstpixel++=(GetRValue(srcval) << rShift) |
4500                                 (GetGValue(srcval) << gShift) |
4501                                 (GetBValue(srcval) << bShift);
4502                 }
4503                 dstbits += linebytes;
4504             }
4505         }
4506         break;
4507     }
4508 }
4509
4510 /***********************************************************************
4511  *           X11DRV_DIB_SetImageBits
4512  *
4513  * Transfer the bits to an X image.
4514  * Helper function for SetDIBits() and SetDIBitsToDevice().
4515  */
4516 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4517 {
4518     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4519     XImage *bmpImage;
4520
4521     wine_tsx11_lock();
4522     if (descr->image)
4523         bmpImage = descr->image;
4524     else {
4525         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4526                                  descr->infoWidth, lines, 32, 0 );
4527         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4528         if(bmpImage->data == NULL) {
4529             ERR("Out of memory!\n");
4530             XDestroyImage( bmpImage );
4531             wine_tsx11_unlock();
4532             return lines;
4533         }
4534     }
4535
4536     TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4537           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4538     TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4539           bmpImage->depth,bmpImage->bits_per_pixel,
4540           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4541
4542       /* Transfer the pixels */
4543     switch(descr->infoBpp)
4544     {
4545     case 1:
4546         X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4547                                    descr->width, descr->xSrc, (int *)(descr->colorMap),
4548                                    bmpImage, descr->dibpitch );
4549         break;
4550     case 4:
4551         if (descr->compression) {
4552             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4553                           descr->width, descr->height, AllPlanes, ZPixmap,
4554                           bmpImage, descr->xSrc, descr->ySrc );
4555
4556             X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4557                                           descr->infoWidth, descr->width,
4558                                           descr->xSrc, (int *)(descr->colorMap),
4559                                           bmpImage );
4560         } else
4561             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4562                                        descr->infoWidth, descr->width,
4563                                        descr->xSrc, (int*)(descr->colorMap),
4564                                        bmpImage, descr->dibpitch );
4565         break;
4566     case 8:
4567         if (descr->compression) {
4568             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4569                           descr->width, descr->height, AllPlanes, ZPixmap,
4570                           bmpImage, descr->xSrc, descr->ySrc );
4571             X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4572                                           descr->infoWidth, descr->width,
4573                                           descr->xSrc, (int *)(descr->colorMap),
4574                                           bmpImage );
4575         } else
4576             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4577                                        descr->infoWidth, descr->width,
4578                                        descr->xSrc, (int *)(descr->colorMap),
4579                                        bmpImage, descr->dibpitch );
4580         break;
4581     case 15:
4582     case 16:
4583         X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4584                                     descr->infoWidth, descr->width,
4585                                    descr->xSrc, descr->physDev,
4586                                    descr->rMask, descr->gMask, descr->bMask,
4587                                    bmpImage, descr->dibpitch);
4588         break;
4589     case 24:
4590         X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4591                                     descr->infoWidth, descr->width,
4592                                     descr->xSrc, descr->physDev,
4593                                     descr->rMask, descr->gMask, descr->bMask,
4594                                     bmpImage, descr->dibpitch);
4595         break;
4596     case 32:
4597         X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4598                                     descr->infoWidth, descr->width,
4599                                    descr->xSrc, descr->physDev,
4600                                    descr->rMask, descr->gMask, descr->bMask,
4601                                    bmpImage, descr->dibpitch);
4602         break;
4603     default:
4604         WARN("(%d): Invalid depth\n", descr->infoBpp );
4605         break;
4606     }
4607
4608     TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4609      descr->drawable, descr->gc, bmpImage,
4610      descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4611      descr->width, descr->height);
4612 #ifdef HAVE_LIBXXSHM
4613     if (descr->useShm)
4614     {
4615         XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4616                       descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4617                       descr->width, descr->height, FALSE );
4618         XSync( gdi_display, 0 );
4619     }
4620     else
4621 #endif
4622         XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4623                    descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4624                    descr->width, descr->height );
4625
4626     if (!descr->image) XDestroyImage( bmpImage );
4627     wine_tsx11_unlock();
4628     return lines;
4629 }
4630
4631 /***********************************************************************
4632  *           X11DRV_DIB_GetImageBits
4633  *
4634  * Transfer the bits from an X image.
4635  */
4636 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4637 {
4638     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4639     XImage *bmpImage;
4640
4641     wine_tsx11_lock();
4642    if (descr->image)
4643         bmpImage = descr->image;
4644     else {
4645         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4646                                  descr->infoWidth, lines, 32, 0 );
4647         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4648         if(bmpImage->data == NULL) {
4649             ERR("Out of memory!\n");
4650             XDestroyImage( bmpImage );
4651             wine_tsx11_unlock();
4652             return lines;
4653         }
4654     }
4655
4656     if (descr->useShm)
4657     {
4658         int saveRed, saveGreen, saveBlue;
4659
4660         TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4661                             gdi_display, descr->drawable, bmpImage,
4662                             descr->xSrc, descr->ySrc, AllPlanes);
4663
4664         /* We must save and restore the bmpImage's masks in order
4665          * to preserve them across the call to XShmGetImage, which
4666          * decides to eleminate them since it doesn't happen to know
4667          * what the format of the image is supposed to be, even though
4668          * we do. */
4669         saveRed = bmpImage->red_mask;
4670         saveBlue= bmpImage->blue_mask;
4671         saveGreen = bmpImage->green_mask;
4672
4673         XShmGetImage( gdi_display, descr->drawable, bmpImage,
4674                       descr->xSrc, descr->ySrc, AllPlanes);
4675
4676         bmpImage->red_mask = saveRed;
4677         bmpImage->blue_mask = saveBlue;
4678         bmpImage->green_mask = saveGreen;
4679     }
4680     else
4681     {
4682         TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4683               gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4684               lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4685         XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4686                       descr->width, lines, AllPlanes, ZPixmap,
4687                       bmpImage, descr->xDest, descr->yDest );
4688     }
4689
4690     TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4691           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4692     TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4693           bmpImage->depth,bmpImage->bits_per_pixel,
4694           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4695       /* Transfer the pixels */
4696     switch(descr->infoBpp)
4697     {
4698     case 1:
4699           X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4700                                      descr->infoWidth, descr->width,
4701                                      descr->colorMap, descr->palentry,
4702                                      bmpImage, descr->dibpitch );
4703        break;
4704
4705     case 4:
4706        if (descr->compression)
4707            FIXME("Compression not yet supported!\n");
4708        else
4709            X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4710                                       descr->infoWidth, descr->width,
4711                                       descr->colorMap, descr->palentry,
4712                                       bmpImage, descr->dibpitch );
4713        break;
4714
4715     case 8:
4716        if (descr->compression)
4717            FIXME("Compression not yet supported!\n");
4718        else
4719            X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4720                                       descr->infoWidth, descr->width,
4721                                       descr->colorMap, descr->palentry,
4722                                       bmpImage, descr->dibpitch );
4723        break;
4724     case 15:
4725     case 16:
4726        X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4727                                    descr->infoWidth,descr->width,
4728                                    descr->palentry,
4729                                    descr->rMask, descr->gMask, descr->bMask,
4730                                    bmpImage, descr->dibpitch );
4731        break;
4732
4733     case 24:
4734        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4735                                    descr->infoWidth,descr->width,
4736                                    descr->palentry,
4737                                    descr->rMask, descr->gMask, descr->bMask,
4738                                    bmpImage, descr->dibpitch);
4739        break;
4740
4741     case 32:
4742        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4743                                    descr->infoWidth, descr->width,
4744                                    descr->palentry,
4745                                    descr->rMask, descr->gMask, descr->bMask,
4746                                    bmpImage, descr->dibpitch);
4747        break;
4748
4749     default:
4750         WARN("(%d): Invalid depth\n", descr->infoBpp );
4751         break;
4752     }
4753
4754     if (!descr->image) XDestroyImage( bmpImage );
4755     wine_tsx11_unlock();
4756     return lines;
4757 }
4758
4759 /*************************************************************************
4760  *              X11DRV_SetDIBitsToDevice
4761  *
4762  */
4763 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
4764                                 DWORD cy, INT xSrc, INT ySrc,
4765                                 UINT startscan, UINT lines, LPCVOID bits,
4766                                 const BITMAPINFO *info, UINT coloruse )
4767 {
4768     X11DRV_DIB_IMAGEBITS_DESCR descr;
4769     DWORD width;
4770     INT result;
4771     int height;
4772     BOOL top_down;
4773     POINT pt;
4774     DC *dc = physDev->dc;
4775
4776     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4777                            &descr.infoBpp, &descr.compression ) == -1)
4778         return 0;
4779     top_down = (height < 0);
4780     if (top_down) height = -height;
4781
4782     pt.x = xDest;
4783     pt.y = yDest;
4784     LPtoDP(physDev->hdc, &pt, 1);
4785
4786     if (!lines || (startscan >= height)) return 0;
4787     if (!top_down && startscan + lines > height) lines = height - startscan;
4788
4789     /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
4790      * and clamp all values to fit inside [startscan,startscan+lines]
4791      */
4792     if (ySrc + cy <= startscan + lines)
4793     {
4794         INT y = startscan + lines - (ySrc + cy);
4795         if (ySrc < startscan) cy -= (startscan - ySrc);
4796         if (!top_down)
4797         {
4798             /* avoid getting unnecessary lines */
4799             ySrc = 0;
4800             if (y >= lines) return 0;
4801             lines -= y;
4802         }
4803         else
4804         {
4805             if (y >= lines) return lines;
4806             ySrc = y;  /* need to get all lines in top down mode */
4807         }
4808     }
4809     else
4810     {
4811         if (ySrc >= startscan + lines) return lines;
4812         pt.y += ySrc + cy - (startscan + lines);
4813         cy = startscan + lines - ySrc;
4814         ySrc = 0;
4815         if (cy > lines) cy = lines;
4816     }
4817     if (xSrc >= width) return lines;
4818     if (xSrc + cx >= width) cx = width - xSrc;
4819     if (!cx || !cy) return lines;
4820
4821     X11DRV_SetupGCForText( physDev );  /* To have the correct colors */
4822     TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4823
4824     switch (descr.infoBpp)
4825     {
4826        case 1:
4827        case 4:
4828        case 8:
4829                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4830                                             coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
4831                                             dc->bitsPerPixel, info, &descr.nColorMap );
4832                if (!descr.colorMap) return 0;
4833                descr.rMask = descr.gMask = descr.bMask = 0;
4834                break;
4835        case 15:
4836        case 16:
4837                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4838                descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
4839                descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
4840                descr.colorMap = 0;
4841                break;
4842
4843        case 24:
4844        case 32:
4845                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
4846                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4847                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4848                descr.colorMap = 0;
4849                break;
4850     }
4851
4852     descr.physDev   = physDev;
4853     descr.bits      = bits;
4854     descr.image     = NULL;
4855     descr.palentry  = NULL;
4856     descr.lines     = top_down ? -lines : lines;
4857     descr.infoWidth = width;
4858     descr.depth     = dc->bitsPerPixel;
4859     descr.drawable  = physDev->drawable;
4860     descr.gc        = physDev->gc;
4861     descr.xSrc      = xSrc;
4862     descr.ySrc      = ySrc;
4863     descr.xDest     = physDev->org.x + pt.x;
4864     descr.yDest     = physDev->org.y + pt.y;
4865     descr.width     = cx;
4866     descr.height    = cy;
4867     descr.useShm    = FALSE;
4868     descr.dibpitch  = ((width * descr.infoBpp + 31) &~31) / 8;
4869
4870     result = X11DRV_DIB_SetImageBits( &descr );
4871
4872     if (descr.infoBpp <= 8)
4873        HeapFree(GetProcessHeap(), 0, descr.colorMap);
4874     return result;
4875 }
4876
4877 /***********************************************************************
4878  *           SetDIBits   (X11DRV.@)
4879  */
4880 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
4881                       UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
4882 {
4883   X11DRV_DIB_IMAGEBITS_DESCR descr;
4884   BITMAPOBJ *bmp;
4885   int height, tmpheight;
4886   INT result;
4887
4888   descr.physDev = physDev;
4889
4890   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4891                          &descr.infoBpp, &descr.compression ) == -1)
4892       return 0;
4893
4894   tmpheight = height;
4895   if (height < 0) height = -height;
4896   if (!lines || (startscan >= height))
4897       return 0;
4898
4899   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
4900
4901   if (startscan + lines > height) lines = height - startscan;
4902
4903   switch (descr.infoBpp)
4904   {
4905        case 1:
4906        case 4:
4907        case 8:
4908                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4909                         coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
4910                                                           bmp->bitmap.bmBitsPixel,
4911                                                           info, &descr.nColorMap );
4912                if (!descr.colorMap)
4913                {
4914                    GDI_ReleaseObj( hbitmap );
4915                    return 0;
4916                }
4917                descr.rMask = descr.gMask = descr.bMask = 0;
4918                break;
4919        case 15:
4920        case 16:
4921                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4922                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4923                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4924                descr.colorMap = 0;
4925                break;
4926
4927        case 24:
4928        case 32:
4929                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
4930                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4931                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4932                descr.colorMap = 0;
4933                break;
4934
4935        default: break;
4936   }
4937
4938   descr.bits      = bits;
4939   descr.image     = NULL;
4940   descr.palentry  = NULL;
4941   descr.lines     = tmpheight >= 0 ? lines : -lines;
4942   descr.depth     = bmp->bitmap.bmBitsPixel;
4943   descr.drawable  = (Pixmap)bmp->physBitmap;
4944   descr.gc        = BITMAP_GC(bmp);
4945   descr.xSrc      = 0;
4946   descr.ySrc      = 0;
4947   descr.xDest     = 0;
4948   descr.yDest     = height - startscan - lines;
4949   descr.width     = bmp->bitmap.bmWidth;
4950   descr.height    = lines;
4951   descr.useShm    = FALSE;
4952   descr.dibpitch  = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4953   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
4954   result = X11DRV_DIB_SetImageBits( &descr );
4955   X11DRV_DIB_Unlock(bmp, TRUE);
4956
4957   if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4958
4959   GDI_ReleaseObj( hbitmap );
4960   return result;
4961 }
4962
4963 /***********************************************************************
4964  *           GetDIBits   (X11DRV.@)
4965  */
4966 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
4967                       LPVOID bits, BITMAPINFO *info, UINT coloruse )
4968 {
4969   X11DRV_DIBSECTION *dib;
4970   X11DRV_DIB_IMAGEBITS_DESCR descr;
4971   PALETTEOBJ * palette;
4972   BITMAPOBJ *bmp;
4973   int height;
4974   DC *dc = physDev->dc;
4975
4976   if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4977       return 0;
4978   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
4979   {
4980       GDI_ReleaseObj( dc->hPalette );
4981       return 0;
4982   }
4983   dib = (X11DRV_DIBSECTION *) bmp->dib;
4984
4985   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4986         lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4987         (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4988         startscan );
4989
4990   if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4991
4992   height = info->bmiHeader.biHeight;
4993   if (height < 0) height = -height;
4994   if( lines > height ) lines = height;
4995   /* Top-down images have a negative biHeight, the scanlines of theses images
4996    * were inverted in X11DRV_DIB_GetImageBits_xx
4997    * To prevent this we simply change the sign of lines
4998    * (the number of scan lines to copy).
4999    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
5000    */
5001   if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
5002
5003   if( startscan >= bmp->bitmap.bmHeight )
5004   {
5005       lines = 0;
5006       goto done;
5007   }
5008
5009   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
5010                         &descr.infoBpp, &descr.compression ) == -1)
5011   {
5012       lines = 0;
5013       goto done;
5014   }
5015
5016   switch (descr.infoBpp)
5017   {
5018       case 1:
5019       case 4:
5020       case 8:
5021           descr.rMask= descr.gMask = descr.bMask = 0;
5022           break;
5023       case 15:
5024       case 16:
5025           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
5026           descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
5027           descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
5028           break;
5029       case 24:
5030       case 32:
5031           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
5032           descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x00ff00;
5033           descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x0000ff;
5034           break;
5035   }
5036
5037   descr.physDev   = physDev;
5038   descr.palentry  = palette->logpalette.palPalEntry;
5039   descr.bits      = bits;
5040   descr.image     = NULL;
5041   descr.lines     = lines;
5042   descr.depth     = bmp->bitmap.bmBitsPixel;
5043   descr.drawable  = (Pixmap)bmp->physBitmap;
5044   descr.gc        = BITMAP_GC(bmp);
5045   descr.width     = bmp->bitmap.bmWidth;
5046   descr.height    = bmp->bitmap.bmHeight;
5047   descr.colorMap  = info->bmiColors;
5048   descr.xDest     = 0;
5049   descr.yDest     = 0;
5050   descr.xSrc      = 0;
5051
5052   if (descr.lines > 0)
5053   {
5054      descr.ySrc = (descr.height-1) - (startscan + (lines-1));
5055   }
5056   else
5057   {
5058      descr.ySrc = startscan;
5059   }
5060 #ifdef HAVE_LIBXXSHM
5061   descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
5062 #else
5063   descr.useShm = FALSE;
5064 #endif
5065   descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
5066                        : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
5067
5068   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
5069   X11DRV_DIB_GetImageBits( &descr );
5070   X11DRV_DIB_Unlock(bmp, TRUE);
5071
5072   if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
5073       info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
5074                                          info->bmiHeader.biWidth,
5075                                          info->bmiHeader.biHeight,
5076                                          info->bmiHeader.biBitCount );
5077
5078   if (descr.compression == BI_BITFIELDS)
5079   {
5080     *(DWORD *)info->bmiColors = descr.rMask;
5081     *((DWORD *)info->bmiColors+1) = descr.gMask;
5082     *((DWORD *)info->bmiColors+2) = descr.bMask;
5083   }
5084   else
5085   {
5086     /* if RLE or JPEG compression were supported,
5087      * this line would be invalid. */
5088     info->bmiHeader.biCompression = 0;
5089   }
5090
5091 done:
5092   GDI_ReleaseObj( dc->hPalette );
5093   GDI_ReleaseObj( hbitmap );
5094   return lines;
5095 }
5096
5097 /***********************************************************************
5098  *           DIB_DoProtectDIBSection
5099  */
5100 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5101 {
5102     DIBSECTION *dib = bmp->dib;
5103     INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5104                                              : -dib->dsBm.bmHeight;
5105     /* use the biSizeImage data as the memory size only if we're dealing with a
5106        compressed image where the value is set.  Otherwise, calculate based on
5107        width * height */
5108     INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5109                          ? dib->dsBmih.biSizeImage
5110                          : dib->dsBm.bmWidthBytes * effHeight;
5111     DWORD old_prot;
5112
5113     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5114     TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5115 }
5116
5117 /***********************************************************************
5118  *           X11DRV_DIB_DoUpdateDIBSection
5119  */
5120 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5121                                         void *colorMap, int nColorMap,
5122                                         Drawable dest,
5123                                         DWORD xSrc, DWORD ySrc,
5124                                         DWORD xDest, DWORD yDest,
5125                                         DWORD width, DWORD height)
5126 {
5127   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5128   X11DRV_DIB_IMAGEBITS_DESCR descr;
5129
5130   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5131                          &descr.infoBpp, &descr.compression ) == -1)
5132     return;
5133
5134   descr.physDev   = NULL;
5135   descr.palentry  = NULL;
5136   descr.image     = dib->image;
5137   descr.colorMap  = colorMap;
5138   descr.nColorMap = nColorMap;
5139   descr.bits      = dib->dibSection.dsBm.bmBits;
5140   descr.depth     = bmp->bitmap.bmBitsPixel;
5141
5142   switch (descr.infoBpp)
5143   {
5144     case 1:
5145     case 4:
5146     case 8:
5147       descr.rMask = descr.gMask = descr.bMask = 0;
5148       break;
5149     case 15:
5150     case 16:
5151       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5152       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5153       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5154       break;
5155
5156     case 24:
5157     case 32:
5158       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5159       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5160       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5161       break;
5162   }
5163
5164   /* Hack for now */
5165   descr.drawable  = dest;
5166   descr.gc        = BITMAP_GC(bmp);
5167   descr.xSrc      = xSrc;
5168   descr.ySrc      = ySrc;
5169   descr.xDest     = xDest;
5170   descr.yDest     = yDest;
5171   descr.width     = width;
5172   descr.height    = height;
5173 #ifdef HAVE_LIBXXSHM
5174   descr.useShm = (dib->shminfo.shmid != -1);
5175 #else
5176   descr.useShm = FALSE;
5177 #endif
5178   descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5179
5180   if (toDIB)
5181     {
5182       TRACE("Copying from Pixmap to DIB bits\n");
5183       X11DRV_DIB_GetImageBits( &descr );
5184     }
5185   else
5186     {
5187       TRACE("Copying from DIB bits to Pixmap\n");
5188       X11DRV_DIB_SetImageBits( &descr );
5189     }
5190 }
5191
5192 /***********************************************************************
5193  *           X11DRV_DIB_CopyDIBSection
5194  */
5195 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
5196                                DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
5197                                DWORD width, DWORD height)
5198 {
5199   BITMAPOBJ *bmp;
5200   DC *dcSrc = physDevSrc->dc;
5201   DC *dcDst = physDevDst->dc;
5202   int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5203
5204   TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5205     xSrc, ySrc, xDest, yDest, width, height);
5206   /* this function is meant as an optimization for BitBlt,
5207    * not to be called otherwise */
5208   if (!(dcSrc->flags & DC_MEMORY)) {
5209     ERR("called for non-memory source DC!?\n");
5210     return;
5211   }
5212
5213   bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5214   if (!(bmp && bmp->dib)) {
5215     ERR("called for non-DIBSection!?\n");
5216     GDI_ReleaseObj( dcSrc->hBitmap );
5217     return;
5218   }
5219   /* while BitBlt should already have made sure we only get
5220    * positive values, we should check for oversize values */
5221   if ((xSrc < bmp->bitmap.bmWidth) &&
5222       (ySrc < bmp->bitmap.bmHeight)) {
5223     if (xSrc + width > bmp->bitmap.bmWidth)
5224       width = bmp->bitmap.bmWidth - xSrc;
5225     if (ySrc + height > bmp->bitmap.bmHeight)
5226       height = bmp->bitmap.bmHeight - ySrc;
5227     /* if the source bitmap is 8bpp or less, we're supposed to use the
5228      * DC's palette for color conversion (not the DIB color table) */
5229     if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5230       X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5231       if ((!dcSrc->hPalette) ||
5232           (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5233         /* HACK: no palette has been set in the source DC,
5234          * use the DIB colormap instead - this is necessary in some
5235          * cases since we need to do depth conversion in some places
5236          * where real Windows can just copy data straight over */
5237         colorMap = dib->colorMap;
5238         nColorMap = dib->nColorMap;
5239       } else {
5240         colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
5241                                              bmp->dib->dsBm.bmBitsPixel,
5242                                              (BITMAPINFO*)&(bmp->dib->dsBmih),
5243                                              &nColorMap );
5244         if (colorMap) aColorMap = TRUE;
5245       }
5246     }
5247     /* perform the copy */
5248     X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5249                                 physDevDst->drawable, xSrc, ySrc,
5250                                 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
5251                                 width, height);
5252     /* free color mapping */
5253     if (aColorMap)
5254       HeapFree(GetProcessHeap(), 0, colorMap);
5255   }
5256   GDI_ReleaseObj( dcSrc->hBitmap );
5257 }
5258
5259 /***********************************************************************
5260  *           X11DRV_DIB_DoUpdateDIBSection
5261  */
5262 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5263 {
5264   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5265   X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5266                               (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5267                               bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5268 }
5269
5270 /***********************************************************************
5271  *           X11DRV_DIB_FaultHandler
5272  */
5273 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5274 {
5275   BITMAPOBJ *bmp;
5276   INT state;
5277
5278   bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5279   if (!bmp) return FALSE;
5280
5281   state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5282   if (state != DIB_Status_InSync) {
5283     /* no way to tell whether app needs read or write yet,
5284      * try read first */
5285     X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5286   } else {
5287     /* hm, apparently the app must have write access */
5288     X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5289   }
5290   X11DRV_DIB_Unlock(bmp, TRUE);
5291
5292   GDI_ReleaseObj( (HBITMAP)res );
5293   return TRUE;
5294 }
5295
5296 /***********************************************************************
5297  *           X11DRV_DIB_Coerce
5298  */
5299 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5300 {
5301   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5302   INT ret = DIB_Status_None;
5303
5304   if (dib) {
5305     EnterCriticalSection(&(dib->lock));
5306     ret = dib->status;
5307     switch (req) {
5308     case DIB_Status_GdiMod:
5309       /* GDI access - request to draw on pixmap */
5310       switch (dib->status)
5311       {
5312         default:
5313         case DIB_Status_None:
5314           dib->p_status = DIB_Status_GdiMod;
5315           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5316           break;
5317
5318         case DIB_Status_GdiMod:
5319           TRACE("GdiMod requested in status GdiMod\n" );
5320           break;
5321
5322         case DIB_Status_InSync:
5323           TRACE("GdiMod requested in status InSync\n" );
5324           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5325           dib->status = DIB_Status_GdiMod;
5326           dib->p_status = DIB_Status_InSync;
5327           break;
5328
5329         case DIB_Status_AuxMod:
5330           TRACE("GdiMod requested in status AuxMod\n" );
5331           if (lossy) dib->status = DIB_Status_GdiMod;
5332           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5333           dib->p_status = DIB_Status_AuxMod;
5334           if (dib->status != DIB_Status_AppMod) {
5335             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5336             break;
5337           }
5338           /* fall through if copy_aux() had to change to AppMod state */
5339
5340         case DIB_Status_AppMod:
5341           TRACE("GdiMod requested in status AppMod\n" );
5342           if (!lossy) {
5343             /* make it readonly to avoid app changing data while we copy */
5344             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5345             X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5346           }
5347           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5348           dib->p_status = DIB_Status_AppMod;
5349           dib->status = DIB_Status_GdiMod;
5350           break;
5351       }
5352       break;
5353
5354     case DIB_Status_InSync:
5355       /* App access - request access to read DIB surface */
5356       /* (typically called from signal handler) */
5357       switch (dib->status)
5358       {
5359         default:
5360         case DIB_Status_None:
5361           /* shouldn't happen from signal handler */
5362           break;
5363
5364         case DIB_Status_AuxMod:
5365           TRACE("InSync requested in status AuxMod\n" );
5366           if (lossy) dib->status = DIB_Status_InSync;
5367           else {
5368             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5369             (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5370           }
5371           if (dib->status != DIB_Status_GdiMod) {
5372             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5373             break;
5374           }
5375           /* fall through if copy_aux() had to change to GdiMod state */
5376
5377         case DIB_Status_GdiMod:
5378           TRACE("InSync requested in status GdiMod\n" );
5379           if (!lossy) {
5380             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5381             X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5382           }
5383           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5384           dib->status = DIB_Status_InSync;
5385           break;
5386
5387         case DIB_Status_InSync:
5388           TRACE("InSync requested in status InSync\n" );
5389           /* shouldn't happen from signal handler */
5390           break;
5391
5392         case DIB_Status_AppMod:
5393           TRACE("InSync requested in status AppMod\n" );
5394           /* no reason to do anything here, and this
5395            * shouldn't happen from signal handler */
5396           break;
5397       }
5398       break;
5399
5400     case DIB_Status_AppMod:
5401       /* App access - request access to write DIB surface */
5402       /* (typically called from signal handler) */
5403       switch (dib->status)
5404       {
5405         default:
5406         case DIB_Status_None:
5407           /* shouldn't happen from signal handler */
5408           break;
5409
5410         case DIB_Status_AuxMod:
5411           TRACE("AppMod requested in status AuxMod\n" );
5412           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5413           if (lossy) dib->status = DIB_Status_AppMod;
5414           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5415           if (dib->status != DIB_Status_GdiMod)
5416             break;
5417           /* fall through if copy_aux() had to change to GdiMod state */
5418
5419         case DIB_Status_GdiMod:
5420           TRACE("AppMod requested in status GdiMod\n" );
5421           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5422           if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5423           dib->status = DIB_Status_AppMod;
5424           break;
5425
5426         case DIB_Status_InSync:
5427           TRACE("AppMod requested in status InSync\n" );
5428           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5429           dib->status = DIB_Status_AppMod;
5430           break;
5431
5432         case DIB_Status_AppMod:
5433           TRACE("AppMod requested in status AppMod\n" );
5434           /* shouldn't happen from signal handler */
5435           break;
5436       }
5437       break;
5438
5439     case DIB_Status_AuxMod:
5440       if (dib->status == DIB_Status_None) {
5441         dib->p_status = req;
5442       } else {
5443         if (dib->status != DIB_Status_AuxMod)
5444           dib->p_status = dib->status;
5445         dib->status = DIB_Status_AuxMod;
5446       }
5447       break;
5448       /* it is up to the caller to do the copy/conversion, probably
5449        * using the return value to decide where to copy from */
5450     }
5451     LeaveCriticalSection(&(dib->lock));
5452   }
5453   return ret;
5454 }
5455
5456 /***********************************************************************
5457  *           X11DRV_DIB_Lock
5458  */
5459 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5460 {
5461   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5462   INT ret = DIB_Status_None;
5463
5464   if (dib) {
5465     TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
5466     EnterCriticalSection(&(dib->lock));
5467     ret = dib->status;
5468     if (req != DIB_Status_None)
5469       X11DRV_DIB_Coerce(bmp, req, lossy);
5470   }
5471   return ret;
5472 }
5473
5474 /***********************************************************************
5475  *           X11DRV_DIB_Unlock
5476  */
5477 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5478 {
5479   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5480
5481   if (dib) {
5482     switch (dib->status)
5483     {
5484       default:
5485       case DIB_Status_None:
5486         /* in case anyone is wondering, this is the "signal handler doesn't
5487          * work" case, where we always have to be ready for app access */
5488         if (commit) {
5489           switch (dib->p_status)
5490           {
5491             case DIB_Status_AuxMod:
5492               TRACE("Unlocking and syncing from AuxMod\n" );
5493               (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5494               if (dib->status != DIB_Status_None) {
5495                 dib->p_status = dib->status;
5496                 dib->status = DIB_Status_None;
5497               }
5498               if (dib->p_status != DIB_Status_GdiMod)
5499                 break;
5500               /* fall through if copy_aux() had to change to GdiMod state */
5501
5502             case DIB_Status_GdiMod:
5503               TRACE("Unlocking and syncing from GdiMod\n" );
5504               X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5505               break;
5506
5507             default:
5508               TRACE("Unlocking without needing to sync\n" );
5509               break;
5510           }
5511         }
5512         else TRACE("Unlocking with no changes\n");
5513         dib->p_status = DIB_Status_None;
5514         break;
5515
5516       case DIB_Status_GdiMod:
5517         TRACE("Unlocking in status GdiMod\n" );
5518         /* DIB was protected in Coerce */
5519         if (!commit) {
5520           /* no commit, revert to InSync if applicable */
5521           if ((dib->p_status == DIB_Status_InSync) ||
5522               (dib->p_status == DIB_Status_AppMod)) {
5523             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5524             dib->status = DIB_Status_InSync;
5525           }
5526         }
5527         break;
5528
5529       case DIB_Status_InSync:
5530         TRACE("Unlocking in status InSync\n" );
5531         /* DIB was already protected in Coerce */
5532         break;
5533
5534       case DIB_Status_AppMod:
5535         TRACE("Unlocking in status AppMod\n" );
5536         /* DIB was already protected in Coerce */
5537         /* this case is ordinary only called from the signal handler,
5538          * so we don't bother to check for !commit */
5539         break;
5540
5541       case DIB_Status_AuxMod:
5542         TRACE("Unlocking in status AuxMod\n" );
5543         if (commit) {
5544           /* DIB may need protection now */
5545           if ((dib->p_status == DIB_Status_InSync) ||
5546               (dib->p_status == DIB_Status_AppMod))
5547             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5548         } else {
5549           /* no commit, revert to previous state */
5550           if (dib->p_status != DIB_Status_None)
5551             dib->status = dib->p_status;
5552           /* no protections changed */
5553         }
5554         dib->p_status = DIB_Status_None;
5555         break;
5556     }
5557     LeaveCriticalSection(&(dib->lock));
5558     TRACE("Unlocked %p\n", bmp);
5559   }
5560 }
5561
5562 /***********************************************************************
5563  *           X11DRV_CoerceDIBSection2
5564  */
5565 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5566 {
5567   BITMAPOBJ *bmp;
5568   INT ret;
5569
5570   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5571   if (!bmp) return DIB_Status_None;
5572   ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5573   GDI_ReleaseObj( hBmp );
5574   return ret;
5575 }
5576
5577 /***********************************************************************
5578  *           X11DRV_LockDIBSection2
5579  */
5580 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5581 {
5582   BITMAPOBJ *bmp;
5583   INT ret;
5584
5585   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5586   if (!bmp) return DIB_Status_None;
5587   ret = X11DRV_DIB_Lock(bmp, req, lossy);
5588   GDI_ReleaseObj( hBmp );
5589   return ret;
5590 }
5591
5592 /***********************************************************************
5593  *           X11DRV_UnlockDIBSection2
5594  */
5595 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5596 {
5597   BITMAPOBJ *bmp;
5598
5599   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5600   if (!bmp) return;
5601   X11DRV_DIB_Unlock(bmp, commit);
5602   GDI_ReleaseObj( hBmp );
5603 }
5604
5605 /***********************************************************************
5606  *           X11DRV_CoerceDIBSection
5607  */
5608 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5609 {
5610   if (!physDev) return DIB_Status_None;
5611   return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
5612 }
5613
5614 /***********************************************************************
5615  *           X11DRV_LockDIBSection
5616  */
5617 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5618 {
5619   if (!physDev) return DIB_Status_None;
5620   if (!(physDev->dc->flags & DC_MEMORY)) return DIB_Status_None;
5621
5622   return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
5623 }
5624
5625 /***********************************************************************
5626  *           X11DRV_UnlockDIBSection
5627  */
5628 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
5629 {
5630   if (!physDev) return;
5631   if (!(physDev->dc->flags & DC_MEMORY)) return;
5632
5633   X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
5634 }
5635
5636
5637 #ifdef HAVE_LIBXXSHM
5638 /***********************************************************************
5639  *           X11DRV_XShmErrorHandler
5640  *
5641  */
5642 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
5643 {
5644     return 1;  /* FIXME: should check event contents */
5645 }
5646
5647 /***********************************************************************
5648  *           X11DRV_XShmCreateImage
5649  *
5650  */
5651 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5652                                        XShmSegmentInfo* shminfo)
5653 {
5654     XImage *image;
5655
5656     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5657     if (image)
5658     {
5659         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5660                                   IPC_CREAT|0700);
5661         if( shminfo->shmid != -1 )
5662         {
5663             shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5664             if( shminfo->shmaddr != (char*)-1 )
5665             {
5666                 BOOL ok;
5667
5668                 shminfo->readOnly = FALSE;
5669                 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
5670                 ok = (XShmAttach( gdi_display, shminfo ) != 0);
5671                 if (X11DRV_check_error()) ok = FALSE;
5672                 if (ok)
5673                 {
5674                     shmctl(shminfo->shmid, IPC_RMID, 0);
5675                     return image; /* Success! */
5676                 }
5677                 /* An error occured */
5678                 shmdt(shminfo->shmaddr);
5679             }
5680             shmctl(shminfo->shmid, IPC_RMID, 0);
5681         }
5682         XFlush(gdi_display);
5683         XDestroyImage(image);
5684         image = NULL;
5685     }
5686     return image;
5687 }
5688 #endif /* HAVE_LIBXXSHM */
5689
5690
5691 /***********************************************************************
5692  *           X11DRV_DIB_CreateDIBSection
5693  */
5694 HBITMAP X11DRV_DIB_CreateDIBSection(
5695   X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
5696   LPVOID *bits, HANDLE section,
5697   DWORD offset, DWORD ovr_pitch)
5698 {
5699   HBITMAP res = 0;
5700   BITMAPOBJ *bmp = NULL;
5701   X11DRV_DIBSECTION *dib = NULL;
5702   int *colorMap = NULL;
5703   int nColorMap;
5704
5705   /* Fill BITMAP32 structure with DIB data */
5706   BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5707   INT effHeight, totalSize;
5708   BITMAP bm;
5709   LPVOID mapBits = NULL;
5710
5711   TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5712         bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5713         bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5714
5715   effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5716   bm.bmType = 0;
5717   bm.bmWidth = bi->biWidth;
5718   bm.bmHeight = effHeight;
5719   bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5720                               : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5721   bm.bmPlanes = bi->biPlanes;
5722   bm.bmBitsPixel = bi->biBitCount;
5723   bm.bmBits = NULL;
5724
5725   /* Get storage location for DIB bits.  Only use biSizeImage if it's valid and
5726      we're dealing with a compressed bitmap.  Otherwise, use width * height. */
5727   totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5728     ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5729
5730   if (section)
5731   {
5732       SYSTEM_INFO SystemInfo;
5733       DWORD mapOffset;
5734       INT mapSize;
5735
5736       GetSystemInfo( &SystemInfo );
5737       mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5738       mapSize = totalSize + (offset - mapOffset);
5739       mapBits = MapViewOfFile( section,
5740                                FILE_MAP_ALL_ACCESS,
5741                                0L,
5742                                mapOffset,
5743                                mapSize );
5744       bm.bmBits = (char *)mapBits + (offset - mapOffset);
5745   }
5746   else if (ovr_pitch && offset)
5747     bm.bmBits = (LPVOID) offset;
5748   else {
5749     offset = 0;
5750     bm.bmBits = VirtualAlloc(NULL, totalSize,
5751                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5752   }
5753
5754   /* Create Color Map */
5755   if (bm.bmBits && bm.bmBitsPixel <= 8)
5756       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
5757                                            usage, bm.bmBitsPixel, bmi, &nColorMap );
5758
5759   /* Allocate Memory for DIB and fill structure */
5760   if (bm.bmBits)
5761     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5762   if (dib)
5763     {
5764       dib->dibSection.dsBm = bm;
5765       dib->dibSection.dsBmih = *bi;
5766       dib->dibSection.dsBmih.biSizeImage = totalSize;
5767
5768       /* Set dsBitfields values */
5769        if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5770        {
5771            dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5772        }
5773        else switch( bi->biBitCount )
5774        {
5775            case 15:
5776            case 16:
5777                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5778                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5779                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5780                break;
5781
5782            case 24:
5783            case 32:
5784                dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors       : 0xff0000;
5785                dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5786                dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5787                break;
5788        }
5789       dib->dibSection.dshSection = section;
5790       dib->dibSection.dsOffset = offset;
5791
5792       dib->status    = DIB_Status_None;
5793       dib->nColorMap = nColorMap;
5794       dib->colorMap  = colorMap;
5795     }
5796
5797   /* Create Device Dependent Bitmap and add DIB pointer */
5798   if (dib)
5799     {
5800       res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
5801       if (res)
5802         {
5803           bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5804           if (bmp) bmp->dib = (DIBSECTION *) dib;
5805         }
5806     }
5807
5808   /* Create XImage */
5809   if (dib && bmp)
5810   {
5811       wine_tsx11_lock();
5812 #ifdef HAVE_LIBXXSHM
5813       if (XShmQueryExtension(gdi_display) &&
5814           (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5815                                                 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5816       {
5817         ; /* Created Image */
5818       } else {
5819           dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5820           dib->shminfo.shmid = -1;
5821       }
5822 #else
5823       dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5824 #endif
5825       wine_tsx11_unlock();
5826   }
5827
5828   /* Clean up in case of errors */
5829   if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5830     {
5831       TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
5832             res, bmp, dib, bm.bmBits);
5833       if (bm.bmBits)
5834         {
5835           if (section)
5836             UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5837           else if (!offset)
5838             VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5839         }
5840
5841       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5842       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5843       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5844       if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5845       if (res) { DeleteObject(res); res = 0; }
5846     }
5847   else if (bm.bmBits)
5848     {
5849       /* Install fault handler, if possible */
5850       InitializeCriticalSection(&(dib->lock));
5851       if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5852         {
5853           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5854           if (dib) dib->status = DIB_Status_AppMod;
5855         }
5856     }
5857
5858   /* Return BITMAP handle and storage location */
5859   if (bmp) GDI_ReleaseObj(res);
5860   if (bm.bmBits && bits) *bits = bm.bmBits;
5861   return res;
5862 }
5863
5864 /***********************************************************************
5865  *           X11DRV_DIB_DeleteDIBSection
5866  */
5867 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5868 {
5869   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5870
5871   if (dib->image)
5872   {
5873       wine_tsx11_lock();
5874 #ifdef HAVE_LIBXXSHM
5875       if (dib->shminfo.shmid != -1)
5876       {
5877           XShmDetach (gdi_display, &(dib->shminfo));
5878           XDestroyImage (dib->image);
5879           shmdt (dib->shminfo.shmaddr);
5880           dib->shminfo.shmid = -1;
5881       }
5882       else
5883 #endif
5884           XDestroyImage( dib->image );
5885       wine_tsx11_unlock();
5886   }
5887
5888   if (dib->colorMap)
5889     HeapFree(GetProcessHeap(), 0, dib->colorMap);
5890
5891   DeleteCriticalSection(&(dib->lock));
5892 }
5893
5894 /***********************************************************************
5895  *           SetDIBColorTable   (X11DRV.@)
5896  */
5897 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
5898 {
5899     BITMAPOBJ * bmp;
5900     X11DRV_DIBSECTION *dib;
5901     UINT ret = 0;
5902
5903     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5904     dib = (X11DRV_DIBSECTION *) bmp->dib;
5905
5906     if (dib && dib->colorMap) {
5907         UINT end = count + start;
5908         if (end > dib->nColorMap) end = dib->nColorMap;
5909         /*
5910          * Changing color table might change the mapping between
5911          * DIB colors and X11 colors and thus alter the visible state
5912          * of the bitmap object.
5913          */
5914         X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5915         X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
5916                                 dib->dibSection.dsBm.bmBitsPixel,
5917                                 TRUE, colors, start, end );
5918         X11DRV_DIB_Unlock(bmp, TRUE);
5919         ret = end - start;
5920     }
5921     GDI_ReleaseObj( physDev->dc->hBitmap );
5922     return ret;
5923 }
5924
5925 /***********************************************************************
5926  *           GetDIBColorTable   (X11DRV.@)
5927  */
5928 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
5929 {
5930     BITMAPOBJ * bmp;
5931     X11DRV_DIBSECTION *dib;
5932     UINT ret = 0;
5933
5934     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5935     dib = (X11DRV_DIBSECTION *) bmp->dib;
5936
5937     if (dib && dib->colorMap) {
5938         UINT i, end = count + start;
5939         if (end > dib->nColorMap) end = dib->nColorMap;
5940         for (i = start; i < end; i++,colors++) {
5941             COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5942             colors->rgbBlue  = GetBValue(col);
5943             colors->rgbGreen = GetGValue(col);
5944             colors->rgbRed   = GetRValue(col);
5945             colors->rgbReserved = 0;
5946         }
5947         ret = end-start;
5948     }
5949     GDI_ReleaseObj( physDev->dc->hBitmap );
5950     return ret;
5951 }
5952
5953
5954 /**************************************************************************
5955  *              X11DRV_DIB_CreateDIBFromPixmap
5956  *
5957  *  Allocates a packed DIB and copies the Pixmap data into it.
5958  *  If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5959  */
5960 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5961 {
5962     HBITMAP hBmp = 0;
5963     BITMAPOBJ *pBmp = NULL;
5964     HGLOBAL hPackedDIB = 0;
5965
5966     /* Allocates an HBITMAP which references the Pixmap passed to us */
5967     hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5968     if (!hBmp)
5969     {
5970         TRACE("\tCould not create bitmap header for Pixmap\n");
5971         goto END;
5972     }
5973
5974     /*
5975      * Create a packed DIB from the Pixmap wrapper bitmap created above.
5976      * A packed DIB contains a BITMAPINFO structure followed immediately by
5977      * an optional color palette and the pixel data.
5978      */
5979     hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5980
5981     /* Get a pointer to the BITMAPOBJ structure */
5982     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5983
5984     /* We can now get rid of the HBITMAP wrapper we created earlier.
5985      * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5986      */
5987     if (!bDeletePixmap)
5988     {
5989         /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5990         pBmp->physBitmap = NULL;
5991         pBmp->funcs = NULL;
5992     }
5993     GDI_ReleaseObj( hBmp );
5994     DeleteObject(hBmp);
5995
5996 END:
5997     TRACE("\tReturning packed DIB %p\n", hPackedDIB);
5998     return hPackedDIB;
5999 }
6000
6001
6002 /**************************************************************************
6003  *                 X11DRV_DIB_CreatePixmapFromDIB
6004  *
6005  *    Creates a Pixmap from a packed DIB
6006  */
6007 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
6008 {
6009     Pixmap pixmap = None;
6010     HBITMAP hBmp = 0;
6011     BITMAPOBJ *pBmp = NULL;
6012     LPBYTE pPackedDIB = NULL;
6013     LPBITMAPINFO pbmi = NULL;
6014     LPBITMAPINFOHEADER pbmiHeader = NULL;
6015     LPBYTE pbits = NULL;
6016
6017     /* Get a pointer to the packed DIB's data  */
6018     pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
6019     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
6020     pbmi = (LPBITMAPINFO)pPackedDIB;
6021     pbits = (LPBYTE)(pPackedDIB
6022                      + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
6023
6024     /* Create a DDB from the DIB */
6025
6026     hBmp = CreateDIBitmap(hdc,
6027                           pbmiHeader,
6028                           CBM_INIT,
6029                           (LPVOID)pbits,
6030                           pbmi,
6031                           DIB_RGB_COLORS);
6032
6033     GlobalUnlock(hPackedDIB);
6034
6035     TRACE("CreateDIBitmap returned %p\n", hBmp);
6036
6037     /* Retrieve the internal Pixmap from the DDB */
6038
6039     pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
6040
6041     pixmap = (Pixmap)pBmp->physBitmap;
6042     /* clear the physBitmap so that we can steal its pixmap */
6043     pBmp->physBitmap = NULL;
6044     pBmp->funcs = NULL;
6045
6046     /* Delete the DDB we created earlier now that we have stolen its pixmap */
6047     GDI_ReleaseObj( hBmp );
6048     DeleteObject(hBmp);
6049
6050     TRACE("\tReturning Pixmap %ld\n", pixmap);
6051     return pixmap;
6052 }