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