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