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