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