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