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