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