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