Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / winex11.drv / dib.c
blobab3fdfb36843866d3793f6ae8f68459f4eafeff1
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
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.
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.
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
21 #include "config.h"
23 #include <X11/Xlib.h>
24 #ifdef HAVE_LIBXXSHM
25 #include <X11/extensions/XShm.h>
26 # ifdef HAVE_SYS_SHM_H
27 # include <sys/shm.h>
28 # endif
29 # ifdef HAVE_SYS_IPC_H
30 # include <sys/ipc.h>
31 # endif
32 #endif /* defined(HAVE_LIBXXSHM) */
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "x11drv.h"
41 #include "excpt.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
46 #ifdef HAVE_XSHMEMULATEDSHMGET
47 #define shmget XShmEmulatedShmget
48 #define shmat XShmEmulatedShmat
49 #define shmdt XShmEmulatedShmdt
50 #define shmctl XShmEmulatedShmctl
51 #endif
53 static struct list dibs_list = LIST_INIT(dibs_list);
55 static CRITICAL_SECTION dibs_cs;
56 static CRITICAL_SECTION_DEBUG dibs_cs_debug =
58 0, 0, &dibs_cs,
59 { &dibs_cs_debug.ProcessLocksList, &dibs_cs_debug.ProcessLocksList },
60 0, 0, { (DWORD_PTR)(__FILE__ ": dibs_cs") }
62 static CRITICAL_SECTION dibs_cs = { &dibs_cs_debug, -1, 0, 0, 0, 0 };
64 static PVOID dibs_handler;
66 static int ximageDepthTable[32];
68 /* This structure holds the arguments for DIB_SetImageBits() */
69 typedef struct
71 X11DRV_PDEVICE *physDev;
72 LPCVOID bits;
73 XImage *image;
74 PALETTEENTRY *palentry;
75 int lines;
76 DWORD infoWidth;
77 WORD depth;
78 WORD infoBpp;
79 WORD compression;
80 RGBQUAD *colorMap;
81 int nColorMap;
82 Drawable drawable;
83 GC gc;
84 int xSrc;
85 int ySrc;
86 int xDest;
87 int yDest;
88 int width;
89 int height;
90 DWORD rMask;
91 DWORD gMask;
92 DWORD bMask;
93 BOOL useShm;
94 int dibpitch;
95 DWORD sizeImage;
96 X_PHYSBITMAP *physBitmap;
97 } X11DRV_DIB_IMAGEBITS_DESCR;
100 enum Rle_EscapeCodes
102 RLE_EOL = 0, /* End of line */
103 RLE_END = 1, /* End of bitmap */
104 RLE_DELTA = 2 /* Delta */
108 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *,INT,BOOL);
109 static INT X11DRV_DIB_Lock(X_PHYSBITMAP *,INT,BOOL);
110 static void X11DRV_DIB_Unlock(X_PHYSBITMAP *,BOOL);
113 Some of the following helper functions are duplicated in
114 dlls/gdi/dib.c
117 /***********************************************************************
118 * X11DRV_DIB_GetXImageWidthBytes
120 * Return the width of an X image in bytes
122 static inline int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
124 if (!depth || depth > 32) goto error;
126 if (!ximageDepthTable[depth-1])
128 XImage *testimage = XCreateImage( gdi_display, visual, depth,
129 ZPixmap, 0, NULL, 1, 1, 32, 20 );
130 if (testimage)
132 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
133 XDestroyImage( testimage );
135 else ximageDepthTable[depth-1] = -1;
137 if (ximageDepthTable[depth-1] != -1)
138 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
140 error:
141 WARN( "(%d): Unsupported depth\n", depth );
142 return 4 * width;
146 /***********************************************************************
147 * X11DRV_DIB_GetDIBWidthBytes
149 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
151 static int X11DRV_DIB_GetDIBWidthBytes( int width, int depth )
153 int words;
155 switch(depth)
157 case 1: words = (width + 31) / 32; break;
158 case 4: words = (width + 7) / 8; break;
159 case 8: words = (width + 3) / 4; break;
160 case 15:
161 case 16: words = (width + 1) / 2; break;
162 case 24: words = (width * 3 + 3) / 4; break;
163 default:
164 WARN("(%d): Unsupported depth\n", depth );
165 /* fall through */
166 case 32:
167 words = width;
169 return 4 * words;
173 /***********************************************************************
174 * X11DRV_DIB_GetDIBImageBytes
176 * Return the number of bytes used to hold the image in a DIB bitmap.
178 static int X11DRV_DIB_GetDIBImageBytes( int width, int height, int depth )
180 return X11DRV_DIB_GetDIBWidthBytes( width, depth ) * abs( height );
184 /***********************************************************************
185 * X11DRV_DIB_BitmapInfoSize
187 * Return the size of the bitmap info structure including color table.
189 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
191 unsigned int colors;
193 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
195 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
196 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
197 return sizeof(BITMAPCOREHEADER) + colors *
198 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
200 else /* assume BITMAPINFOHEADER */
202 colors = info->bmiHeader.biClrUsed;
203 if (!colors && (info->bmiHeader.biBitCount <= 8))
204 colors = 1 << info->bmiHeader.biBitCount;
205 return sizeof(BITMAPINFOHEADER) + colors *
206 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
211 /***********************************************************************
212 * X11DRV_DIB_CreateXImage
214 * Create an X image.
216 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
218 int width_bytes;
219 XImage *image;
221 wine_tsx11_lock();
222 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
223 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
224 calloc( height, width_bytes ),
225 width, height, 32, width_bytes );
226 wine_tsx11_unlock();
227 return image;
231 /***********************************************************************
232 * DIB_GetBitmapInfoEx
234 * Get the info from a bitmap header.
235 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
237 static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER *header, LONG *width,
238 LONG *height, WORD *planes, WORD *bpp,
239 WORD *compr, DWORD *size )
241 if (header->biSize == sizeof(BITMAPCOREHEADER))
243 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
244 *width = core->bcWidth;
245 *height = core->bcHeight;
246 *planes = core->bcPlanes;
247 *bpp = core->bcBitCount;
248 *compr = 0;
249 *size = 0;
250 return 0;
252 if (header->biSize >= sizeof(BITMAPINFOHEADER))
254 *width = header->biWidth;
255 *height = header->biHeight;
256 *planes = header->biPlanes;
257 *bpp = header->biBitCount;
258 *compr = header->biCompression;
259 *size = header->biSizeImage;
260 return 1;
262 ERR("(%d): unknown/wrong size for header\n", header->biSize );
263 return -1;
267 /***********************************************************************
268 * DIB_GetBitmapInfo
270 * Get the info from a bitmap header.
271 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
273 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
274 LONG *height, WORD *bpp, WORD *compr )
276 WORD planes;
277 DWORD size;
279 return DIB_GetBitmapInfoEx( header, width, height, &planes, bpp, compr, &size);
283 static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
285 return (c1.rgbRed * c1.rgbRed + c1.rgbGreen * c1.rgbGreen + c1.rgbBlue * c1.rgbBlue) >
286 (c2.rgbRed * c2.rgbRed + c2.rgbGreen * c2.rgbGreen + c2.rgbBlue * c2.rgbBlue);
289 /***********************************************************************
290 * X11DRV_DIB_GenColorMap
292 * Fills the color map of a bitmap palette. Should not be called
293 * for a >8-bit deep bitmap.
295 static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
296 WORD coloruse, WORD depth, BOOL quads,
297 const void *colorPtr, int start, int end )
299 int i;
301 if (coloruse == DIB_RGB_COLORS)
303 if (quads)
305 const RGBQUAD * rgb = (const RGBQUAD *)colorPtr;
307 if (depth == 1) /* Monochrome */
309 BOOL invert = FALSE;
310 RGBQUAD table[2];
312 if (GetDIBColorTable( physDev->hdc, 0, 2, table ) == 2)
313 invert = !colour_is_brighter(table[1], table[0]);
315 for (i = start; i < end; i++, rgb++)
316 colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
317 rgb->rgbBlue > 255*3/2 && !invert) ||
318 (rgb->rgbRed + rgb->rgbGreen +
319 rgb->rgbBlue <= 255*3/2 && invert));
321 else
322 for (i = start; i < end; i++, rgb++)
323 colorMapping[i] = X11DRV_PALETTE_ToPhysical( NULL, RGB(rgb->rgbRed,
324 rgb->rgbGreen,
325 rgb->rgbBlue));
327 else
329 const RGBTRIPLE * rgb = (const RGBTRIPLE *)colorPtr;
331 if (depth == 1) /* Monochrome */
333 BOOL invert = FALSE;
334 RGBQUAD table[2];
336 if (GetDIBColorTable( physDev->hdc, 0, 2, table ) == 2)
337 invert = !colour_is_brighter(table[1], table[0]);
339 for (i = start; i < end; i++, rgb++)
340 colorMapping[i] = ((rgb->rgbtRed + rgb->rgbtGreen +
341 rgb->rgbtBlue > 255*3/2 && !invert) ||
342 (rgb->rgbtRed + rgb->rgbtGreen +
343 rgb->rgbtBlue <= 255*3/2 && invert));
345 else
346 for (i = start; i < end; i++, rgb++)
347 colorMapping[i] = X11DRV_PALETTE_ToPhysical( NULL, RGB(rgb->rgbtRed,
348 rgb->rgbtGreen,
349 rgb->rgbtBlue));
352 else /* DIB_PAL_COLORS */
354 if (colorPtr) {
355 const WORD * index = (const WORD *)colorPtr;
357 for (i = start; i < end; i++, index++)
358 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
359 } else {
360 for (i = start; i < end; i++)
361 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
365 return colorMapping;
368 /***********************************************************************
369 * X11DRV_DIB_BuildColorMap
371 * Build the color map from the bitmap palette. Should not be called
372 * for a >8-bit deep bitmap.
374 static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
375 const BITMAPINFO *info, int *nColors )
377 unsigned int colors;
378 BOOL isInfo;
379 const void *colorPtr;
380 int *colorMapping;
382 isInfo = info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER);
384 if (isInfo)
386 colors = info->bmiHeader.biClrUsed;
387 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
389 else
391 colors = 1 << ((const BITMAPCOREHEADER *)info)->bcBitCount;
394 colorPtr = (const BYTE*) info + (WORD) info->bmiHeader.biSize;
396 if (colors > 256)
398 ERR("called with >256 colors!\n");
399 return NULL;
402 /* just so CopyDIBSection doesn't have to create an identity palette */
403 if (coloruse == (WORD)-1) colorPtr = NULL;
405 if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(int) )))
406 return NULL;
408 *nColors = colors;
409 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
410 isInfo, colorPtr, 0, colors);
413 /***********************************************************************
414 * X11DRV_DIB_MapColor
416 static int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
418 unsigned int color;
420 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
421 return oldcol;
423 for (color = 0; color < nPhysMap; color++)
424 if (physMap[color] == phys)
425 return color;
427 WARN("Strange color %08x\n", phys);
428 return 0;
432 /*********************************************************************
433 * X11DRV_DIB_GetNearestIndex
435 * Helper for X11DRV_DIB_GetDIBits.
436 * Returns the nearest colour table index for a given RGB.
437 * Nearest is defined by minimizing the sum of the squares.
439 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
441 INT i, best = -1, diff, bestdiff = -1;
442 RGBQUAD *color;
444 for(color = colormap, i = 0; i < numColors; color++, i++) {
445 diff = (r - color->rgbRed) * (r - color->rgbRed) +
446 (g - color->rgbGreen) * (g - color->rgbGreen) +
447 (b - color->rgbBlue) * (b - color->rgbBlue);
448 if(diff == 0)
449 return i;
450 if(best == -1 || diff < bestdiff) {
451 best = i;
452 bestdiff = diff;
455 return best;
457 /*********************************************************************
458 * X11DRV_DIB_MaskToShift
460 * Helper for X11DRV_DIB_GetDIBits.
461 * Returns the by how many bits to shift a given color so that it is
462 * in the proper position.
464 INT X11DRV_DIB_MaskToShift(DWORD mask)
466 int shift;
468 if (mask==0)
469 return 0;
471 shift=0;
472 while ((mask&1)==0) {
473 mask>>=1;
474 shift++;
476 return shift;
479 /***********************************************************************
480 * X11DRV_DIB_CheckMask
482 * Check RGB mask if it is either 0 or matches visual's mask.
484 static inline int X11DRV_DIB_CheckMask(int red_mask, int green_mask, int blue_mask)
486 return ( red_mask == 0 && green_mask == 0 && blue_mask == 0 ) ||
487 ( red_mask == visual->red_mask && green_mask == visual->green_mask &&
488 blue_mask == visual->blue_mask );
491 /***********************************************************************
492 * X11DRV_DIB_SetImageBits_1
494 * SetDIBits for a 1-bit deep DIB.
496 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
497 DWORD srcwidth, DWORD dstwidth, int left,
498 int *colors, XImage *bmpImage, DWORD linebytes)
500 int h, width;
501 const BYTE* srcbyte;
502 BYTE srcval, extra;
503 DWORD i, x;
505 if (lines < 0 ) {
506 lines = -lines;
507 srcbits = srcbits + linebytes * (lines - 1);
508 linebytes = -linebytes;
511 if ((extra = (left & 7)) != 0) {
512 left &= ~7;
513 dstwidth += extra;
515 srcbits += left >> 3;
516 width = min(srcwidth, dstwidth);
518 /* ==== pal 1 dib -> any bmp format ==== */
519 for (h = lines-1; h >=0; h--) {
520 srcbyte=srcbits;
521 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
522 for (i = width/8, x = left; i > 0; i--) {
523 srcval=*srcbyte++;
524 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
525 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
526 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
527 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
528 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
529 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
530 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
531 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
533 if (width % 8){
534 srcval=*srcbyte;
535 switch (width & 7)
537 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
538 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
539 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
540 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
541 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
542 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
543 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
546 srcbits += linebytes;
550 /***********************************************************************
551 * X11DRV_DIB_GetImageBits_1
553 * GetDIBits for a 1-bit deep DIB.
555 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
556 DWORD dstwidth, DWORD srcwidth,
557 RGBQUAD *colors, PALETTEENTRY *srccolors,
558 XImage *bmpImage, DWORD linebytes )
560 DWORD x;
561 int h, width = min(dstwidth, srcwidth);
563 if (lines < 0 ) {
564 lines = -lines;
565 dstbits = dstbits + linebytes * (lines - 1);
566 linebytes = -linebytes;
569 switch (bmpImage->depth)
571 case 1:
572 case 4:
573 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
574 && srccolors) {
575 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
576 BYTE* dstbyte;
578 for (h=lines-1; h>=0; h--) {
579 BYTE dstval;
580 dstbyte=dstbits;
581 dstval=0;
582 for (x=0; x<width; x++) {
583 PALETTEENTRY srcval;
584 srcval=srccolors[XGetPixel(bmpImage, x, h)];
585 dstval|=(X11DRV_DIB_GetNearestIndex
586 (colors, 2,
587 srcval.peRed,
588 srcval.peGreen,
589 srcval.peBlue) << (7 - (x & 7)));
590 if ((x&7)==7) {
591 *dstbyte++=dstval;
592 dstval=0;
595 if ((width&7)!=0) {
596 *dstbyte=dstval;
598 dstbits += linebytes;
600 } else {
601 goto notsupported;
603 break;
605 case 8:
606 if (X11DRV_DIB_CheckMask(bmpImage->red_mask, bmpImage->green_mask, bmpImage->blue_mask)
607 && srccolors) {
608 /* ==== pal 8 bmp -> pal 1 dib ==== */
609 const void* srcbits;
610 const BYTE* srcpixel;
611 BYTE* dstbyte;
613 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
615 for (h=0; h<lines; h++) {
616 BYTE dstval;
617 srcpixel=srcbits;
618 dstbyte=dstbits;
619 dstval=0;
620 for (x=0; x<width; x++) {
621 PALETTEENTRY srcval;
622 srcval=srccolors[(int)*srcpixel++];
623 dstval|=(X11DRV_DIB_GetNearestIndex
624 (colors, 2,
625 srcval.peRed,
626 srcval.peGreen,
627 srcval.peBlue) << (7-(x&7)) );
628 if ((x&7)==7) {
629 *dstbyte++=dstval;
630 dstval=0;
633 if ((width&7)!=0) {
634 *dstbyte=dstval;
636 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
637 dstbits += linebytes;
639 } else {
640 goto notsupported;
642 break;
644 case 15:
645 case 16:
647 const void* srcbits;
648 const WORD* srcpixel;
649 BYTE* dstbyte;
651 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
653 if (bmpImage->green_mask==0x03e0) {
654 if (bmpImage->red_mask==0x7c00) {
655 /* ==== rgb 555 bmp -> pal 1 dib ==== */
656 for (h=0; h<lines; h++) {
657 BYTE dstval;
658 srcpixel=srcbits;
659 dstbyte=dstbits;
660 dstval=0;
661 for (x=0; x<width; x++) {
662 WORD srcval;
663 srcval=*srcpixel++;
664 dstval|=(X11DRV_DIB_GetNearestIndex
665 (colors, 2,
666 ((srcval >> 7) & 0xf8) | /* r */
667 ((srcval >> 12) & 0x07),
668 ((srcval >> 2) & 0xf8) | /* g */
669 ((srcval >> 7) & 0x07),
670 ((srcval << 3) & 0xf8) | /* b */
671 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
672 if ((x&7)==7) {
673 *dstbyte++=dstval;
674 dstval=0;
677 if ((width&7)!=0) {
678 *dstbyte=dstval;
680 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
681 dstbits += linebytes;
683 } else if (bmpImage->blue_mask==0x7c00) {
684 /* ==== bgr 555 bmp -> pal 1 dib ==== */
685 for (h=0; h<lines; h++) {
686 WORD dstval;
687 srcpixel=srcbits;
688 dstbyte=dstbits;
689 dstval=0;
690 for (x=0; x<width; x++) {
691 BYTE srcval;
692 srcval=*srcpixel++;
693 dstval|=(X11DRV_DIB_GetNearestIndex
694 (colors, 2,
695 ((srcval << 3) & 0xf8) | /* r */
696 ((srcval >> 2) & 0x07),
697 ((srcval >> 2) & 0xf8) | /* g */
698 ((srcval >> 7) & 0x07),
699 ((srcval >> 7) & 0xf8) | /* b */
700 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
701 if ((x&7)==7) {
702 *dstbyte++=dstval;
703 dstval=0;
706 if ((width&7)!=0) {
707 *dstbyte=dstval;
709 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
710 dstbits += linebytes;
712 } else {
713 goto notsupported;
715 } else if (bmpImage->green_mask==0x07e0) {
716 if (bmpImage->red_mask==0xf800) {
717 /* ==== rgb 565 bmp -> pal 1 dib ==== */
718 for (h=0; h<lines; h++) {
719 BYTE dstval;
720 srcpixel=srcbits;
721 dstbyte=dstbits;
722 dstval=0;
723 for (x=0; x<width; x++) {
724 WORD srcval;
725 srcval=*srcpixel++;
726 dstval|=(X11DRV_DIB_GetNearestIndex
727 (colors, 2,
728 ((srcval >> 8) & 0xf8) | /* r */
729 ((srcval >> 13) & 0x07),
730 ((srcval >> 3) & 0xfc) | /* g */
731 ((srcval >> 9) & 0x03),
732 ((srcval << 3) & 0xf8) | /* b */
733 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
734 if ((x&7)==7) {
735 *dstbyte++=dstval;
736 dstval=0;
739 if ((width&7)!=0) {
740 *dstbyte=dstval;
742 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
743 dstbits += linebytes;
745 } else if (bmpImage->blue_mask==0xf800) {
746 /* ==== bgr 565 bmp -> pal 1 dib ==== */
747 for (h=0; h<lines; h++) {
748 BYTE dstval;
749 srcpixel=srcbits;
750 dstbyte=dstbits;
751 dstval=0;
752 for (x=0; x<width; x++) {
753 WORD srcval;
754 srcval=*srcpixel++;
755 dstval|=(X11DRV_DIB_GetNearestIndex
756 (colors, 2,
757 ((srcval << 3) & 0xf8) | /* r */
758 ((srcval >> 2) & 0x07),
759 ((srcval >> 3) & 0xfc) | /* g */
760 ((srcval >> 9) & 0x03),
761 ((srcval >> 8) & 0xf8) | /* b */
762 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
763 if ((x&7)==7) {
764 *dstbyte++=dstval;
765 dstval=0;
768 if ((width&7)!=0) {
769 *dstbyte=dstval;
771 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
772 dstbits += linebytes;
774 } else {
775 goto notsupported;
777 } else {
778 goto notsupported;
781 break;
783 case 24:
784 case 32:
786 const void* srcbits;
787 const BYTE *srcbyte;
788 BYTE* dstbyte;
789 int bytes_per_pixel;
791 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
792 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
794 if (bmpImage->green_mask!=0x00ff00 ||
795 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
796 goto notsupported;
797 } else if (bmpImage->blue_mask==0xff) {
798 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
799 for (h=0; h<lines; h++) {
800 BYTE dstval;
801 srcbyte=srcbits;
802 dstbyte=dstbits;
803 dstval=0;
804 for (x=0; x<width; x++) {
805 dstval|=(X11DRV_DIB_GetNearestIndex
806 (colors, 2,
807 srcbyte[2],
808 srcbyte[1],
809 srcbyte[0]) << (7-(x&7)) );
810 srcbyte+=bytes_per_pixel;
811 if ((x&7)==7) {
812 *dstbyte++=dstval;
813 dstval=0;
816 if ((width&7)!=0) {
817 *dstbyte=dstval;
819 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
820 dstbits += linebytes;
822 } else {
823 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
824 for (h=0; h<lines; h++) {
825 BYTE dstval;
826 srcbyte=srcbits;
827 dstbyte=dstbits;
828 dstval=0;
829 for (x=0; x<width; x++) {
830 dstval|=(X11DRV_DIB_GetNearestIndex
831 (colors, 2,
832 srcbyte[0],
833 srcbyte[1],
834 srcbyte[2]) << (7-(x&7)) );
835 srcbyte+=bytes_per_pixel;
836 if ((x&7)==7) {
837 *dstbyte++=dstval;
838 dstval=0;
841 if ((width&7)!=0) {
842 *dstbyte=dstval;
844 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
845 dstbits += linebytes;
849 break;
851 default:
852 notsupported:
854 BYTE* dstbyte;
855 BYTE neg = 0;
856 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
858 /* ==== any bmp format -> pal 1 dib ==== */
859 if ((unsigned)colors[0].rgbRed+colors[0].rgbGreen+colors[0].rgbBlue >=
860 (unsigned)colors[1].rgbRed+colors[1].rgbGreen+colors[1].rgbBlue )
861 neg = 1;
863 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB, "
864 "%s color mapping\n",
865 bmpImage->bits_per_pixel, bmpImage->red_mask,
866 bmpImage->green_mask, bmpImage->blue_mask,
867 neg?"negative":"direct" );
869 for (h=lines-1; h>=0; h--) {
870 BYTE dstval;
871 dstbyte=dstbits;
872 dstval=0;
873 for (x=0; x<width; x++) {
874 dstval|=((XGetPixel( bmpImage, x, h) >= white) ^ neg) << (7 - (x&7));
875 if ((x&7)==7) {
876 *dstbyte++=dstval;
877 dstval=0;
880 if ((width&7)!=0) {
881 *dstbyte=dstval;
883 dstbits += linebytes;
886 break;
890 /***********************************************************************
891 * X11DRV_DIB_SetImageBits_4
893 * SetDIBits for a 4-bit deep DIB.
895 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
896 DWORD srcwidth, DWORD dstwidth, int left,
897 int *colors, XImage *bmpImage, DWORD linebytes)
899 int h, width;
900 const BYTE* srcbyte;
901 DWORD i, x;
903 if (lines < 0 ) {
904 lines = -lines;
905 srcbits = srcbits + linebytes * (lines - 1);
906 linebytes = -linebytes;
909 if (left & 1) {
910 left--;
911 dstwidth++;
913 srcbits += left >> 1;
914 width = min(srcwidth, dstwidth);
916 /* ==== pal 4 dib -> any bmp format ==== */
917 for (h = lines-1; h >= 0; h--) {
918 srcbyte=srcbits;
919 for (i = width/2, x = left; i > 0; i--) {
920 BYTE srcval=*srcbyte++;
921 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
922 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
924 if (width & 1)
925 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
926 srcbits += linebytes;
932 /***********************************************************************
933 * X11DRV_DIB_GetImageBits_4
935 * GetDIBits for a 4-bit deep DIB.
937 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
938 DWORD srcwidth, DWORD dstwidth,
939 RGBQUAD *colors, PALETTEENTRY *srccolors,
940 XImage *bmpImage, DWORD linebytes )
942 DWORD x;
943 int h, width = min(srcwidth, dstwidth);
944 BYTE *bits;
946 if (lines < 0 )
948 lines = -lines;
949 dstbits = dstbits + ( linebytes * (lines-1) );
950 linebytes = -linebytes;
953 bits = dstbits;
955 switch (bmpImage->depth) {
956 case 1:
957 case 4:
958 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
959 && srccolors) {
960 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
961 BYTE* dstbyte;
963 for (h = lines-1; h >= 0; h--) {
964 BYTE dstval;
965 dstbyte=dstbits;
966 dstval=0;
967 for (x = 0; x < width; x++) {
968 PALETTEENTRY srcval;
969 srcval=srccolors[XGetPixel(bmpImage, x, h)];
970 dstval|=(X11DRV_DIB_GetNearestIndex
971 (colors, 16,
972 srcval.peRed,
973 srcval.peGreen,
974 srcval.peBlue) << (4-((x&1)<<2)));
975 if ((x&1)==1) {
976 *dstbyte++=dstval;
977 dstval=0;
980 if ((width&1)!=0) {
981 *dstbyte=dstval;
983 dstbits += linebytes;
985 } else {
986 goto notsupported;
988 break;
990 case 8:
991 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
992 && srccolors) {
993 /* ==== pal 8 bmp -> pal 4 dib ==== */
994 const void* srcbits;
995 const BYTE *srcpixel;
996 BYTE* dstbyte;
998 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
999 for (h=0; h<lines; h++) {
1000 BYTE dstval;
1001 srcpixel=srcbits;
1002 dstbyte=dstbits;
1003 dstval=0;
1004 for (x=0; x<width; x++) {
1005 PALETTEENTRY srcval;
1006 srcval = srccolors[(int)*srcpixel++];
1007 dstval|=(X11DRV_DIB_GetNearestIndex
1008 (colors, 16,
1009 srcval.peRed,
1010 srcval.peGreen,
1011 srcval.peBlue) << (4*(1-(x&1))) );
1012 if ((x&1)==1) {
1013 *dstbyte++=dstval;
1014 dstval=0;
1017 if ((width&1)!=0) {
1018 *dstbyte=dstval;
1020 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1021 dstbits += linebytes;
1023 } else {
1024 goto notsupported;
1026 break;
1028 case 15:
1029 case 16:
1031 const void* srcbits;
1032 const WORD* srcpixel;
1033 BYTE* dstbyte;
1035 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1037 if (bmpImage->green_mask==0x03e0) {
1038 if (bmpImage->red_mask==0x7c00) {
1039 /* ==== rgb 555 bmp -> pal 4 dib ==== */
1040 for (h=0; h<lines; h++) {
1041 BYTE dstval;
1042 srcpixel=srcbits;
1043 dstbyte=dstbits;
1044 dstval=0;
1045 for (x=0; x<width; x++) {
1046 WORD srcval;
1047 srcval=*srcpixel++;
1048 dstval|=(X11DRV_DIB_GetNearestIndex
1049 (colors, 16,
1050 ((srcval >> 7) & 0xf8) | /* r */
1051 ((srcval >> 12) & 0x07),
1052 ((srcval >> 2) & 0xf8) | /* g */
1053 ((srcval >> 7) & 0x07),
1054 ((srcval << 3) & 0xf8) | /* b */
1055 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1056 if ((x&1)==1) {
1057 *dstbyte++=dstval;
1058 dstval=0;
1061 if ((width&1)!=0) {
1062 *dstbyte=dstval;
1064 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1065 dstbits += linebytes;
1067 } else if (bmpImage->blue_mask==0x7c00) {
1068 /* ==== bgr 555 bmp -> pal 4 dib ==== */
1069 for (h=0; h<lines; h++) {
1070 WORD dstval;
1071 srcpixel=srcbits;
1072 dstbyte=dstbits;
1073 dstval=0;
1074 for (x=0; x<width; x++) {
1075 WORD srcval;
1076 srcval=*srcpixel++;
1077 dstval|=(X11DRV_DIB_GetNearestIndex
1078 (colors, 16,
1079 ((srcval << 3) & 0xf8) | /* r */
1080 ((srcval >> 2) & 0x07),
1081 ((srcval >> 2) & 0xf8) | /* g */
1082 ((srcval >> 7) & 0x07),
1083 ((srcval >> 7) & 0xf8) | /* b */
1084 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
1085 if ((x&1)==1) {
1086 *dstbyte++=dstval;
1087 dstval=0;
1090 if ((width&1)!=0) {
1091 *dstbyte=dstval;
1093 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1094 dstbits += linebytes;
1096 } else {
1097 goto notsupported;
1099 } else if (bmpImage->green_mask==0x07e0) {
1100 if (bmpImage->red_mask==0xf800) {
1101 /* ==== rgb 565 bmp -> pal 4 dib ==== */
1102 for (h=0; h<lines; h++) {
1103 BYTE dstval;
1104 srcpixel=srcbits;
1105 dstbyte=dstbits;
1106 dstval=0;
1107 for (x=0; x<width; x++) {
1108 WORD srcval;
1109 srcval=*srcpixel++;
1110 dstval|=(X11DRV_DIB_GetNearestIndex
1111 (colors, 16,
1112 ((srcval >> 8) & 0xf8) | /* r */
1113 ((srcval >> 13) & 0x07),
1114 ((srcval >> 3) & 0xfc) | /* g */
1115 ((srcval >> 9) & 0x03),
1116 ((srcval << 3) & 0xf8) | /* b */
1117 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1118 if ((x&1)==1) {
1119 *dstbyte++=dstval;
1120 dstval=0;
1123 if ((width&1)!=0) {
1124 *dstbyte=dstval;
1126 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1127 dstbits += linebytes;
1129 } else if (bmpImage->blue_mask==0xf800) {
1130 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1131 for (h=0; h<lines; h++) {
1132 WORD dstval;
1133 srcpixel=srcbits;
1134 dstbyte=dstbits;
1135 dstval=0;
1136 for (x=0; x<width; x++) {
1137 WORD srcval;
1138 srcval=*srcpixel++;
1139 dstval|=(X11DRV_DIB_GetNearestIndex
1140 (colors, 16,
1141 ((srcval << 3) & 0xf8) | /* r */
1142 ((srcval >> 2) & 0x07),
1143 ((srcval >> 3) & 0xfc) | /* g */
1144 ((srcval >> 9) & 0x03),
1145 ((srcval >> 8) & 0xf8) | /* b */
1146 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1147 if ((x&1)==1) {
1148 *dstbyte++=dstval;
1149 dstval=0;
1152 if ((width&1)!=0) {
1153 *dstbyte=dstval;
1155 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1156 dstbits += linebytes;
1158 } else {
1159 goto notsupported;
1161 } else {
1162 goto notsupported;
1165 break;
1167 case 24:
1168 if (bmpImage->bits_per_pixel==24) {
1169 const void* srcbits;
1170 const BYTE *srcbyte;
1171 BYTE* dstbyte;
1173 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1175 if (bmpImage->green_mask!=0x00ff00 ||
1176 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1177 goto notsupported;
1178 } else if (bmpImage->blue_mask==0xff) {
1179 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1180 for (h=0; h<lines; h++) {
1181 srcbyte=srcbits;
1182 dstbyte=dstbits;
1183 for (x=0; x<width/2; x++) {
1184 /* Do 2 pixels at a time */
1185 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1186 (colors, 16,
1187 srcbyte[2],
1188 srcbyte[1],
1189 srcbyte[0]) << 4) |
1190 X11DRV_DIB_GetNearestIndex
1191 (colors, 16,
1192 srcbyte[5],
1193 srcbyte[4],
1194 srcbyte[3]);
1195 srcbyte+=6;
1197 if (width&1) {
1198 /* And the the odd pixel */
1199 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1200 (colors, 16,
1201 srcbyte[2],
1202 srcbyte[1],
1203 srcbyte[0]) << 4);
1205 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1206 dstbits += linebytes;
1208 } else {
1209 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1210 for (h=0; h<lines; h++) {
1211 srcbyte=srcbits;
1212 dstbyte=dstbits;
1213 for (x=0; x<width/2; x++) {
1214 /* Do 2 pixels at a time */
1215 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1216 (colors, 16,
1217 srcbyte[0],
1218 srcbyte[1],
1219 srcbyte[2]) << 4) |
1220 X11DRV_DIB_GetNearestIndex
1221 (colors, 16,
1222 srcbyte[3],
1223 srcbyte[4],
1224 srcbyte[5]);
1225 srcbyte+=6;
1227 if (width&1) {
1228 /* And the the odd pixel */
1229 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1230 (colors, 16,
1231 srcbyte[0],
1232 srcbyte[1],
1233 srcbyte[2]) << 4);
1235 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1236 dstbits += linebytes;
1239 break;
1241 /* Fall through */
1243 case 32:
1245 const void* srcbits;
1246 const BYTE *srcbyte;
1247 BYTE* dstbyte;
1249 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1251 if (bmpImage->green_mask!=0x00ff00 ||
1252 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1253 goto notsupported;
1254 } else if (bmpImage->blue_mask==0xff) {
1255 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1256 for (h=0; h<lines; h++) {
1257 srcbyte=srcbits;
1258 dstbyte=dstbits;
1259 for (x=0; x<width/2; x++) {
1260 /* Do 2 pixels at a time */
1261 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1262 (colors, 16,
1263 srcbyte[2],
1264 srcbyte[1],
1265 srcbyte[0]) << 4) |
1266 X11DRV_DIB_GetNearestIndex
1267 (colors, 16,
1268 srcbyte[6],
1269 srcbyte[5],
1270 srcbyte[4]);
1271 srcbyte+=8;
1273 if (width&1) {
1274 /* And the the odd pixel */
1275 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1276 (colors, 16,
1277 srcbyte[2],
1278 srcbyte[1],
1279 srcbyte[0]) << 4);
1281 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1282 dstbits += linebytes;
1284 } else {
1285 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1286 for (h=0; h<lines; h++) {
1287 srcbyte=srcbits;
1288 dstbyte=dstbits;
1289 for (x=0; x<width/2; x++) {
1290 /* Do 2 pixels at a time */
1291 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1292 (colors, 16,
1293 srcbyte[0],
1294 srcbyte[1],
1295 srcbyte[2]) << 4) |
1296 X11DRV_DIB_GetNearestIndex
1297 (colors, 16,
1298 srcbyte[4],
1299 srcbyte[5],
1300 srcbyte[6]);
1301 srcbyte+=8;
1303 if (width&1) {
1304 /* And the the odd pixel */
1305 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1306 (colors, 16,
1307 srcbyte[0],
1308 srcbyte[1],
1309 srcbyte[2]) << 4);
1311 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1312 dstbits += linebytes;
1316 break;
1318 default:
1319 notsupported:
1321 BYTE* dstbyte;
1323 /* ==== any bmp format -> pal 4 dib ==== */
1324 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1325 bmpImage->bits_per_pixel, bmpImage->red_mask,
1326 bmpImage->green_mask, bmpImage->blue_mask );
1327 for (h=lines-1; h>=0; h--) {
1328 dstbyte=dstbits;
1329 for (x=0; x<(width & ~1); x+=2) {
1330 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1331 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1333 if (width & 1) {
1334 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1336 dstbits += linebytes;
1339 break;
1343 /***********************************************************************
1344 * X11DRV_DIB_SetImageBits_RLE4
1346 * SetDIBits for a 4-bit deep compressed DIB.
1348 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1349 DWORD srcwidth, DWORD dstwidth,
1350 int left, int *colors,
1351 XImage *bmpImage )
1353 unsigned int x = 0, width = min(srcwidth, dstwidth);
1354 int y = lines - 1, c, length;
1355 const BYTE *begin = bits;
1357 while (y >= 0)
1359 length = *bits++;
1360 if (length) { /* encoded */
1361 c = *bits++;
1362 while (length--) {
1363 if (x >= (left + width)) break;
1364 if( x >= left) XPutPixel(bmpImage, x, y, colors[c >> 4]);
1365 x++;
1366 if (!length--) break;
1367 if (x >= (left + width)) break;
1368 if( x >= left) XPutPixel(bmpImage, x, y, colors[c & 0xf]);
1369 x++;
1371 } else {
1372 length = *bits++;
1373 switch (length)
1375 case RLE_EOL:
1376 x = 0;
1377 y--;
1378 break;
1380 case RLE_END:
1381 return;
1383 case RLE_DELTA:
1384 x += *bits++;
1385 y -= *bits++;
1386 break;
1388 default: /* absolute */
1389 while (length--) {
1390 c = *bits++;
1391 if (x >= left && x < (left + width))
1392 XPutPixel(bmpImage, x, y, colors[c >> 4]);
1393 x++;
1394 if (!length--) break;
1395 if (x >= left && x < (left + width))
1396 XPutPixel(bmpImage, x, y, colors[c & 0xf]);
1397 x++;
1399 if ((bits - begin) & 1)
1400 bits++;
1408 /***********************************************************************
1409 * X11DRV_DIB_SetImageBits_8
1411 * SetDIBits for an 8-bit deep DIB.
1413 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1414 DWORD srcwidth, DWORD dstwidth, int left,
1415 const int *colors, XImage *bmpImage,
1416 DWORD linebytes )
1418 DWORD x;
1419 int h, width = min(srcwidth, dstwidth);
1420 const BYTE* srcbyte;
1421 BYTE* dstbits;
1423 if (lines < 0 )
1425 lines = -lines;
1426 srcbits = srcbits + linebytes * (lines-1);
1427 linebytes = -linebytes;
1429 srcbits += left;
1430 srcbyte = srcbits;
1432 switch (bmpImage->depth) {
1433 case 15:
1434 case 16:
1435 #if defined(__i386__) && defined(__GNUC__)
1436 /* Some X servers might have 32 bit/ 16bit deep pixel */
1437 if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1438 (ImageByteOrder(gdi_display)==LSBFirst) )
1440 dstbits=(BYTE*)bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1441 /* FIXME: Does this really handle all these cases correctly? */
1442 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1443 for (h = lines ; h--; ) {
1444 int _cl1,_cl2; /* temp outputs for asm below */
1445 /* Borrowed from DirectDraw */
1446 __asm__ __volatile__(
1447 "xor %%eax,%%eax\n"
1448 "cld\n"
1449 "1:\n"
1450 " lodsb\n"
1451 " movw (%%edx,%%eax,4),%%ax\n"
1452 " stosw\n"
1453 " xor %%eax,%%eax\n"
1454 " loop 1b\n"
1455 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1456 :"S" (srcbyte),
1457 "D" (dstbits),
1458 "c" (width),
1459 "d" (colors)
1460 :"eax", "cc", "memory"
1462 srcbyte = (srcbits += linebytes);
1463 dstbits -= bmpImage->bytes_per_line;
1465 return;
1467 break;
1468 #endif
1469 case 24:
1470 case 32:
1471 #if defined(__i386__) && defined(__GNUC__)
1472 if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1473 (ImageByteOrder(gdi_display)==LSBFirst) )
1475 dstbits=(BYTE*)bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1476 /* FIXME: Does this really handle both cases correctly? */
1477 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1478 for (h = lines ; h--; ) {
1479 int _cl1,_cl2; /* temp outputs for asm below */
1480 /* Borrowed from DirectDraw */
1481 __asm__ __volatile__(
1482 "xor %%eax,%%eax\n"
1483 "cld\n"
1484 "1:\n"
1485 " lodsb\n"
1486 " movl (%%edx,%%eax,4),%%eax\n"
1487 " stosl\n"
1488 " xor %%eax,%%eax\n"
1489 " loop 1b\n"
1490 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1491 :"S" (srcbyte),
1492 "D" (dstbits),
1493 "c" (width),
1494 "d" (colors)
1495 :"eax", "cc", "memory"
1497 srcbyte = (srcbits += linebytes);
1498 dstbits -= bmpImage->bytes_per_line;
1500 return;
1502 break;
1503 #endif
1504 default:
1505 break; /* use slow generic case below */
1508 /* ==== pal 8 dib -> any bmp format ==== */
1509 for (h=lines-1; h>=0; h--) {
1510 for (x=left; x<width+left; x++) {
1511 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1513 srcbyte = (srcbits += linebytes);
1517 /***********************************************************************
1518 * X11DRV_DIB_GetImageBits_8
1520 * GetDIBits for an 8-bit deep DIB.
1522 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1523 DWORD srcwidth, DWORD dstwidth,
1524 RGBQUAD *colors, PALETTEENTRY *srccolors,
1525 XImage *bmpImage, DWORD linebytes )
1527 DWORD x;
1528 int h, width = min(srcwidth, dstwidth);
1529 BYTE* dstbyte;
1531 if (lines < 0 )
1533 lines = -lines;
1534 dstbits = dstbits + ( linebytes * (lines-1) );
1535 linebytes = -linebytes;
1538 #if 0
1540 * Hack for now
1541 * This condition is true when GetImageBits has been called by
1542 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1543 * 256 colormaps, so we'll just use it for GetDIBits calls.
1544 * (In some cases, in an updateDIBSection, the returned colors are bad too)
1546 if (!srccolors) goto updatesection;
1547 #endif
1549 switch (bmpImage->depth) {
1550 case 1:
1551 case 4:
1552 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1553 && srccolors) {
1555 /* ==== pal 1 bmp -> pal 8 dib ==== */
1556 /* ==== pal 4 bmp -> pal 8 dib ==== */
1557 for (h=lines-1; h>=0; h--) {
1558 dstbyte=dstbits;
1559 for (x=0; x<width; x++) {
1560 PALETTEENTRY srcval;
1561 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1562 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1563 srcval.peRed,
1564 srcval.peGreen,
1565 srcval.peBlue);
1567 dstbits += linebytes;
1569 } else {
1570 goto notsupported;
1572 break;
1574 case 8:
1575 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1576 && srccolors) {
1577 /* ==== pal 8 bmp -> pal 8 dib ==== */
1578 const void* srcbits;
1579 const BYTE* srcpixel;
1581 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1582 for (h=0; h<lines; h++) {
1583 srcpixel=srcbits;
1584 dstbyte=dstbits;
1585 for (x = 0; x < width; x++) {
1586 PALETTEENTRY srcval;
1587 srcval=srccolors[(int)*srcpixel++];
1588 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1589 srcval.peRed,
1590 srcval.peGreen,
1591 srcval.peBlue);
1593 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1594 dstbits += linebytes;
1596 } else {
1597 goto notsupported;
1599 break;
1601 case 15:
1602 case 16:
1604 const void* srcbits;
1605 const WORD* srcpixel;
1606 BYTE* dstbyte;
1608 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1610 if (bmpImage->green_mask==0x03e0) {
1611 if (bmpImage->red_mask==0x7c00) {
1612 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1613 for (h=0; h<lines; h++) {
1614 srcpixel=srcbits;
1615 dstbyte=dstbits;
1616 for (x=0; x<width; x++) {
1617 WORD srcval;
1618 srcval=*srcpixel++;
1619 *dstbyte++=X11DRV_DIB_GetNearestIndex
1620 (colors, 256,
1621 ((srcval >> 7) & 0xf8) | /* r */
1622 ((srcval >> 12) & 0x07),
1623 ((srcval >> 2) & 0xf8) | /* g */
1624 ((srcval >> 7) & 0x07),
1625 ((srcval << 3) & 0xf8) | /* b */
1626 ((srcval >> 2) & 0x07) );
1628 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1629 dstbits += linebytes;
1631 } else if (bmpImage->blue_mask==0x7c00) {
1632 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1633 for (h=0; h<lines; h++) {
1634 srcpixel=srcbits;
1635 dstbyte=dstbits;
1636 for (x=0; x<width; x++) {
1637 WORD srcval;
1638 srcval=*srcpixel++;
1639 *dstbyte++=X11DRV_DIB_GetNearestIndex
1640 (colors, 256,
1641 ((srcval << 3) & 0xf8) | /* r */
1642 ((srcval >> 2) & 0x07),
1643 ((srcval >> 2) & 0xf8) | /* g */
1644 ((srcval >> 7) & 0x07),
1645 ((srcval >> 7) & 0xf8) | /* b */
1646 ((srcval >> 12) & 0x07) );
1648 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1649 dstbits += linebytes;
1651 } else {
1652 goto notsupported;
1654 } else if (bmpImage->green_mask==0x07e0) {
1655 if (bmpImage->red_mask==0xf800) {
1656 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1657 for (h=0; h<lines; h++) {
1658 srcpixel=srcbits;
1659 dstbyte=dstbits;
1660 for (x=0; x<width; x++) {
1661 WORD srcval;
1662 srcval=*srcpixel++;
1663 *dstbyte++=X11DRV_DIB_GetNearestIndex
1664 (colors, 256,
1665 ((srcval >> 8) & 0xf8) | /* r */
1666 ((srcval >> 13) & 0x07),
1667 ((srcval >> 3) & 0xfc) | /* g */
1668 ((srcval >> 9) & 0x03),
1669 ((srcval << 3) & 0xf8) | /* b */
1670 ((srcval >> 2) & 0x07) );
1672 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1673 dstbits += linebytes;
1675 } else if (bmpImage->blue_mask==0xf800) {
1676 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1677 for (h=0; h<lines; h++) {
1678 srcpixel=srcbits;
1679 dstbyte=dstbits;
1680 for (x=0; x<width; x++) {
1681 WORD srcval;
1682 srcval=*srcpixel++;
1683 *dstbyte++=X11DRV_DIB_GetNearestIndex
1684 (colors, 256,
1685 ((srcval << 3) & 0xf8) | /* r */
1686 ((srcval >> 2) & 0x07),
1687 ((srcval >> 3) & 0xfc) | /* g */
1688 ((srcval >> 9) & 0x03),
1689 ((srcval >> 8) & 0xf8) | /* b */
1690 ((srcval >> 13) & 0x07) );
1692 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1693 dstbits += linebytes;
1695 } else {
1696 goto notsupported;
1698 } else {
1699 goto notsupported;
1702 break;
1704 case 24:
1705 case 32:
1707 const void* srcbits;
1708 const BYTE *srcbyte;
1709 BYTE* dstbyte;
1710 int bytes_per_pixel;
1712 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1713 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1715 if (bmpImage->green_mask!=0x00ff00 ||
1716 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1717 goto notsupported;
1718 } else if (bmpImage->blue_mask==0xff) {
1719 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1720 for (h=0; h<lines; h++) {
1721 srcbyte=srcbits;
1722 dstbyte=dstbits;
1723 for (x=0; x<width; x++) {
1724 *dstbyte++=X11DRV_DIB_GetNearestIndex
1725 (colors, 256,
1726 srcbyte[2],
1727 srcbyte[1],
1728 srcbyte[0]);
1729 srcbyte+=bytes_per_pixel;
1731 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1732 dstbits += linebytes;
1734 } else {
1735 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1736 for (h=0; h<lines; h++) {
1737 srcbyte=srcbits;
1738 dstbyte=dstbits;
1739 for (x=0; x<width; x++) {
1740 *dstbyte++=X11DRV_DIB_GetNearestIndex
1741 (colors, 256,
1742 srcbyte[0],
1743 srcbyte[1],
1744 srcbyte[2]);
1745 srcbyte+=bytes_per_pixel;
1747 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1748 dstbits += linebytes;
1752 break;
1754 default:
1755 notsupported:
1756 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1757 bmpImage->depth, bmpImage->red_mask,
1758 bmpImage->green_mask, bmpImage->blue_mask );
1759 #if 0
1760 updatesection:
1761 #endif
1762 /* ==== any bmp format -> pal 8 dib ==== */
1763 for (h=lines-1; h>=0; h--) {
1764 dstbyte=dstbits;
1765 for (x=0; x<width; x++) {
1766 *dstbyte=X11DRV_DIB_MapColor
1767 ((int*)colors, 256,
1768 XGetPixel(bmpImage, x, h), *dstbyte);
1769 dstbyte++;
1771 dstbits += linebytes;
1773 break;
1777 /***********************************************************************
1778 * X11DRV_DIB_SetImageBits_RLE8
1780 * SetDIBits for an 8-bit deep compressed DIB.
1782 * This function rewritten 941113 by James Youngman. WINE blew out when I
1783 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1785 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1786 * 'End of bitmap' escape code. This code is very much laxer in what it
1787 * allows to end the expansion. Possibly too lax. See the note by
1788 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1789 * bitmap should end with RleEnd, but on the other hand, software exists
1790 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1791 * about it.
1793 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1794 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1795 * [JAY]
1797 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1798 DWORD srcwidth, DWORD dstwidth,
1799 int left, int *colors,
1800 XImage *bmpImage )
1802 unsigned int x; /* X-position on each line. Increases. */
1803 int y; /* Line #. Starts at lines-1, decreases */
1804 const BYTE *pIn = bits; /* Pointer to current position in bits */
1805 BYTE length; /* The length pf a run */
1806 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1809 * Note that the bitmap data is stored by Windows starting at the
1810 * bottom line of the bitmap and going upwards. Within each line,
1811 * the data is stored left-to-right. That's the reason why line
1812 * goes from lines-1 to 0. [JAY]
1815 x = 0;
1816 y = lines - 1;
1817 while (y >= 0)
1819 length = *pIn++;
1822 * If the length byte is not zero (which is the escape value),
1823 * We have a run of length pixels all the same colour. The colour
1824 * index is stored next.
1826 * If the length byte is zero, we need to read the next byte to
1827 * know what to do. [JAY]
1829 if (length != 0)
1832 * [Run-Length] Encoded mode
1834 int color = colors[*pIn++];
1835 while (length-- && x < (left + dstwidth)) {
1836 if( x >= left) XPutPixel(bmpImage, x, y, color);
1837 x++;
1840 else
1843 * Escape codes (may be an absolute sequence though)
1845 escape_code = (*pIn++);
1846 switch(escape_code)
1848 case RLE_EOL:
1849 x = 0;
1850 y--;
1851 break;
1853 case RLE_END:
1854 /* Not all RLE8 bitmaps end with this code. For
1855 * example, Paint Shop Pro produces some that don't.
1856 * That's (I think) what caused the previous
1857 * implementation to fail. [JAY]
1859 return;
1861 case RLE_DELTA:
1862 x += (*pIn++);
1863 y -= (*pIn++);
1864 break;
1866 default: /* switch to absolute mode */
1867 length = escape_code;
1868 while (length--)
1870 int color = colors[*pIn++];
1871 if (x >= (left + dstwidth))
1873 pIn += length;
1874 break;
1876 if( x >= left) XPutPixel(bmpImage, x, y, color);
1877 x++;
1880 * If you think for a moment you'll realise that the
1881 * only time we could ever possibly read an odd
1882 * number of bytes is when there is a 0x00 (escape),
1883 * a value >0x02 (absolute mode) and then an odd-
1884 * length run. Therefore this is the only place we
1885 * need to worry about it. Everywhere else the
1886 * bytes are always read in pairs. [JAY]
1888 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1889 break;
1890 } /* switch (escape_code) : Escape sequence */
1896 /***********************************************************************
1897 * X11DRV_DIB_SetImageBits_16
1899 * SetDIBits for a 16-bit deep DIB.
1901 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1902 DWORD srcwidth, DWORD dstwidth, int left,
1903 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1904 XImage *bmpImage, DWORD linebytes )
1906 DWORD x;
1907 int h, width = min(srcwidth, dstwidth);
1908 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1910 if (lines < 0 )
1912 lines = -lines;
1913 srcbits = srcbits + ( linebytes * (lines-1));
1914 linebytes = -linebytes;
1917 switch (bmpImage->depth)
1919 case 15:
1920 case 16:
1922 char* dstbits;
1924 srcbits=srcbits+left*2;
1925 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1927 if (bmpImage->green_mask==0x03e0) {
1928 if (gSrc==bmpImage->green_mask) {
1929 if (rSrc==bmpImage->red_mask) {
1930 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1931 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1932 convs->Convert_5x5_asis
1933 (width,lines,
1934 srcbits,linebytes,
1935 dstbits,-bmpImage->bytes_per_line);
1936 } else if (rSrc==bmpImage->blue_mask) {
1937 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1938 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1939 convs->Convert_555_reverse
1940 (width,lines,
1941 srcbits,linebytes,
1942 dstbits,-bmpImage->bytes_per_line);
1944 } else {
1945 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1946 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1947 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1948 convs->Convert_565_to_555_asis
1949 (width,lines,
1950 srcbits,linebytes,
1951 dstbits,-bmpImage->bytes_per_line);
1952 } else {
1953 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1954 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1955 convs->Convert_565_to_555_reverse
1956 (width,lines,
1957 srcbits,linebytes,
1958 dstbits,-bmpImage->bytes_per_line);
1961 } else if (bmpImage->green_mask==0x07e0) {
1962 if (gSrc==bmpImage->green_mask) {
1963 if (rSrc==bmpImage->red_mask) {
1964 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1965 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1966 convs->Convert_5x5_asis
1967 (width,lines,
1968 srcbits,linebytes,
1969 dstbits,-bmpImage->bytes_per_line);
1970 } else {
1971 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1972 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1973 convs->Convert_565_reverse
1974 (width,lines,
1975 srcbits,linebytes,
1976 dstbits,-bmpImage->bytes_per_line);
1978 } else {
1979 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1980 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1981 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1982 convs->Convert_555_to_565_asis
1983 (width,lines,
1984 srcbits,linebytes,
1985 dstbits,-bmpImage->bytes_per_line);
1986 } else {
1987 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1988 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1989 convs->Convert_555_to_565_reverse
1990 (width,lines,
1991 srcbits,linebytes,
1992 dstbits,-bmpImage->bytes_per_line);
1995 } else {
1996 goto notsupported;
1999 break;
2001 case 24:
2002 if (bmpImage->bits_per_pixel==24) {
2003 char* dstbits;
2005 srcbits=srcbits+left*2;
2006 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2008 if (bmpImage->green_mask!=0x00ff00 ||
2009 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2010 goto notsupported;
2011 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
2012 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
2013 if (gSrc==0x03e0) {
2014 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
2015 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
2016 convs->Convert_555_to_888_asis
2017 (width,lines,
2018 srcbits,linebytes,
2019 dstbits,-bmpImage->bytes_per_line);
2020 } else {
2021 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
2022 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
2023 convs->Convert_565_to_888_asis
2024 (width,lines,
2025 srcbits,linebytes,
2026 dstbits,-bmpImage->bytes_per_line);
2028 } else {
2029 if (gSrc==0x03e0) {
2030 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
2031 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
2032 convs->Convert_555_to_888_reverse
2033 (width,lines,
2034 srcbits,linebytes,
2035 dstbits,-bmpImage->bytes_per_line);
2036 } else {
2037 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
2038 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
2039 convs->Convert_565_to_888_reverse
2040 (width,lines,
2041 srcbits,linebytes,
2042 dstbits,-bmpImage->bytes_per_line);
2045 break;
2047 /* Fall through */
2049 case 32:
2051 char* dstbits;
2053 srcbits=srcbits+left*2;
2054 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2056 if (bmpImage->green_mask!=0x00ff00 ||
2057 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2058 goto notsupported;
2059 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
2060 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
2061 if (gSrc==0x03e0) {
2062 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
2063 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
2064 convs->Convert_555_to_0888_asis
2065 (width,lines,
2066 srcbits,linebytes,
2067 dstbits,-bmpImage->bytes_per_line);
2068 } else {
2069 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
2070 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
2071 convs->Convert_565_to_0888_asis
2072 (width,lines,
2073 srcbits,linebytes,
2074 dstbits,-bmpImage->bytes_per_line);
2076 } else {
2077 if (gSrc==0x03e0) {
2078 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
2079 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
2080 convs->Convert_555_to_0888_reverse
2081 (width,lines,
2082 srcbits,linebytes,
2083 dstbits,-bmpImage->bytes_per_line);
2084 } else {
2085 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
2086 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
2087 convs->Convert_565_to_0888_reverse
2088 (width,lines,
2089 srcbits,linebytes,
2090 dstbits,-bmpImage->bytes_per_line);
2094 break;
2096 default:
2097 notsupported:
2098 WARN("from 16 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2099 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2100 bmpImage->green_mask, bmpImage->blue_mask );
2101 /* fall through */
2102 case 1:
2103 case 4:
2104 case 8:
2106 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
2107 const WORD* srcpixel;
2108 int rShift1,gShift1,bShift1;
2109 int rShift2,gShift2,bShift2;
2110 BYTE gMask1,gMask2;
2112 /* Set color scaling values */
2113 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
2114 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
2115 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
2116 rShift2=rShift1+5;
2117 gShift2=gShift1+5;
2118 bShift2=bShift1+5;
2119 if (gSrc==0x03e0) {
2120 /* Green has 5 bits, like the others */
2121 gMask1=0xf8;
2122 gMask2=0x07;
2123 } else {
2124 /* Green has 6 bits, not 5. Compensate. */
2125 gShift1++;
2126 gShift2+=2;
2127 gMask1=0xfc;
2128 gMask2=0x03;
2131 srcbits+=2*left;
2133 /* We could split it into four separate cases to optimize
2134 * but it is probably not worth it.
2136 for (h=lines-1; h>=0; h--) {
2137 srcpixel=(const WORD*)srcbits;
2138 for (x=left; x<width+left; x++) {
2139 DWORD srcval;
2140 BYTE red,green,blue;
2141 srcval=*srcpixel++ << 16;
2142 red= ((srcval >> rShift1) & 0xf8) |
2143 ((srcval >> rShift2) & 0x07);
2144 green=((srcval >> gShift1) & gMask1) |
2145 ((srcval >> gShift2) & gMask2);
2146 blue= ((srcval >> bShift1) & 0xf8) |
2147 ((srcval >> bShift2) & 0x07);
2148 XPutPixel(bmpImage, x, h,
2149 X11DRV_PALETTE_ToPhysical
2150 (physDev, RGB(red,green,blue)));
2152 srcbits += linebytes;
2155 break;
2160 /***********************************************************************
2161 * X11DRV_DIB_GetImageBits_16
2163 * GetDIBits for an 16-bit deep DIB.
2165 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
2166 DWORD dstwidth, DWORD srcwidth,
2167 PALETTEENTRY *srccolors,
2168 DWORD rDst, DWORD gDst, DWORD bDst,
2169 XImage *bmpImage, DWORD dibpitch )
2171 DWORD x;
2172 int h, width = min(srcwidth, dstwidth);
2173 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2175 DWORD linebytes = dibpitch;
2177 if (lines < 0 )
2179 lines = -lines;
2180 dstbits = dstbits + ( linebytes * (lines-1));
2181 linebytes = -linebytes;
2184 switch (bmpImage->depth)
2186 case 15:
2187 case 16:
2189 const char* srcbits;
2191 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2193 if (bmpImage->green_mask==0x03e0) {
2194 if (gDst==bmpImage->green_mask) {
2195 if (rDst==bmpImage->red_mask) {
2196 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2197 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2198 convs->Convert_5x5_asis
2199 (width,lines,
2200 srcbits,-bmpImage->bytes_per_line,
2201 dstbits,linebytes);
2202 } else {
2203 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2204 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2205 convs->Convert_555_reverse
2206 (width,lines,
2207 srcbits,-bmpImage->bytes_per_line,
2208 dstbits,linebytes);
2210 } else {
2211 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2212 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2213 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2214 convs->Convert_555_to_565_asis
2215 (width,lines,
2216 srcbits,-bmpImage->bytes_per_line,
2217 dstbits,linebytes);
2218 } else {
2219 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2220 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2221 convs->Convert_555_to_565_reverse
2222 (width,lines,
2223 srcbits,-bmpImage->bytes_per_line,
2224 dstbits,linebytes);
2227 } else if (bmpImage->green_mask==0x07e0) {
2228 if (gDst==bmpImage->green_mask) {
2229 if (rDst == bmpImage->red_mask) {
2230 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2231 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2232 convs->Convert_5x5_asis
2233 (width,lines,
2234 srcbits,-bmpImage->bytes_per_line,
2235 dstbits,linebytes);
2236 } else {
2237 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2238 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2239 convs->Convert_565_reverse
2240 (width,lines,
2241 srcbits,-bmpImage->bytes_per_line,
2242 dstbits,linebytes);
2244 } else {
2245 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2246 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2247 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2248 convs->Convert_565_to_555_asis
2249 (width,lines,
2250 srcbits,-bmpImage->bytes_per_line,
2251 dstbits,linebytes);
2252 } else {
2253 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2254 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2255 convs->Convert_565_to_555_reverse
2256 (width,lines,
2257 srcbits,-bmpImage->bytes_per_line,
2258 dstbits,linebytes);
2261 } else {
2262 goto notsupported;
2265 break;
2267 case 24:
2268 if (bmpImage->bits_per_pixel == 24) {
2269 const char* srcbits;
2271 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2273 if (bmpImage->green_mask!=0x00ff00 ||
2274 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2275 goto notsupported;
2276 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2277 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2278 if (gDst==0x03e0) {
2279 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2280 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2281 convs->Convert_888_to_555_asis
2282 (width,lines,
2283 srcbits,-bmpImage->bytes_per_line,
2284 dstbits,linebytes);
2285 } else {
2286 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2287 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2288 convs->Convert_888_to_565_asis
2289 (width,lines,
2290 srcbits,-bmpImage->bytes_per_line,
2291 dstbits,linebytes);
2293 } else {
2294 if (gDst==0x03e0) {
2295 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2296 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2297 convs->Convert_888_to_555_reverse
2298 (width,lines,
2299 srcbits,-bmpImage->bytes_per_line,
2300 dstbits,linebytes);
2301 } else {
2302 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2303 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2304 convs->Convert_888_to_565_reverse
2305 (width,lines,
2306 srcbits,-bmpImage->bytes_per_line,
2307 dstbits,linebytes);
2310 break;
2312 /* Fall through */
2314 case 32:
2316 const char* srcbits;
2318 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2320 if (bmpImage->green_mask!=0x00ff00 ||
2321 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2322 goto notsupported;
2323 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2324 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2325 if (gDst==0x03e0) {
2326 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2327 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2328 convs->Convert_0888_to_555_asis
2329 (width,lines,
2330 srcbits,-bmpImage->bytes_per_line,
2331 dstbits,linebytes);
2332 } else {
2333 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2334 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2335 convs->Convert_0888_to_565_asis
2336 (width,lines,
2337 srcbits,-bmpImage->bytes_per_line,
2338 dstbits,linebytes);
2340 } else {
2341 if (gDst==0x03e0) {
2342 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2343 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2344 convs->Convert_0888_to_555_reverse
2345 (width,lines,
2346 srcbits,-bmpImage->bytes_per_line,
2347 dstbits,linebytes);
2348 } else {
2349 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2350 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2351 convs->Convert_0888_to_565_reverse
2352 (width,lines,
2353 srcbits,-bmpImage->bytes_per_line,
2354 dstbits,linebytes);
2358 break;
2360 case 1:
2361 case 4:
2362 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2363 && srccolors) {
2364 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2365 int rShift,gShift,bShift;
2366 WORD* dstpixel;
2368 /* Shift everything 16 bits left so that all shifts are >0,
2369 * even for BGR DIBs. Then a single >> 16 will bring everything
2370 * back into place.
2372 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2373 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2374 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2375 if (gDst==0x07e0) {
2376 /* 6 bits for the green */
2377 gShift++;
2379 rDst=rDst << 16;
2380 gDst=gDst << 16;
2381 bDst=bDst << 16;
2382 for (h = lines - 1; h >= 0; h--) {
2383 dstpixel=(LPWORD)dstbits;
2384 for (x = 0; x < width; x++) {
2385 PALETTEENTRY srcval;
2386 DWORD dstval;
2387 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2388 dstval=((srcval.peRed << rShift) & rDst) |
2389 ((srcval.peGreen << gShift) & gDst) |
2390 ((srcval.peBlue << bShift) & bDst);
2391 *dstpixel++=dstval >> 16;
2393 dstbits += linebytes;
2395 } else {
2396 goto notsupported;
2398 break;
2400 case 8:
2401 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2402 && srccolors) {
2403 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2404 int rShift,gShift,bShift;
2405 const BYTE* srcbits;
2406 const BYTE* srcpixel;
2407 WORD* dstpixel;
2409 /* Shift everything 16 bits left so that all shifts are >0,
2410 * even for BGR DIBs. Then a single >> 16 will bring everything
2411 * back into place.
2413 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2414 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2415 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2416 if (gDst==0x07e0) {
2417 /* 6 bits for the green */
2418 gShift++;
2420 rDst=rDst << 16;
2421 gDst=gDst << 16;
2422 bDst=bDst << 16;
2423 srcbits=(BYTE*)bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2424 for (h=0; h<lines; h++) {
2425 srcpixel=srcbits;
2426 dstpixel=(LPWORD)dstbits;
2427 for (x = 0; x < width; x++) {
2428 PALETTEENTRY srcval;
2429 DWORD dstval;
2430 srcval=srccolors[(int)*srcpixel++];
2431 dstval=((srcval.peRed << rShift) & rDst) |
2432 ((srcval.peGreen << gShift) & gDst) |
2433 ((srcval.peBlue << bShift) & bDst);
2434 *dstpixel++=dstval >> 16;
2436 srcbits -= bmpImage->bytes_per_line;
2437 dstbits += linebytes;
2439 } else {
2440 goto notsupported;
2442 break;
2444 default:
2445 notsupported:
2447 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2448 int rShift,gShift,bShift;
2449 WORD* dstpixel;
2451 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%x,%x,%x)\n",
2452 bmpImage->depth, bmpImage->red_mask,
2453 bmpImage->green_mask, bmpImage->blue_mask,
2454 rDst, gDst, bDst);
2456 /* Shift everything 16 bits left so that all shifts are >0,
2457 * even for BGR DIBs. Then a single >> 16 will bring everything
2458 * back into place.
2460 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2461 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2462 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2463 if (gDst==0x07e0) {
2464 /* 6 bits for the green */
2465 gShift++;
2467 rDst=rDst << 16;
2468 gDst=gDst << 16;
2469 bDst=bDst << 16;
2470 for (h = lines - 1; h >= 0; h--) {
2471 dstpixel=(LPWORD)dstbits;
2472 for (x = 0; x < width; x++) {
2473 COLORREF srcval;
2474 DWORD dstval;
2475 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
2476 dstval=((GetRValue(srcval) << rShift) & rDst) |
2477 ((GetGValue(srcval) << gShift) & gDst) |
2478 ((GetBValue(srcval) << bShift) & bDst);
2479 *dstpixel++=dstval >> 16;
2481 dstbits += linebytes;
2484 break;
2489 /***********************************************************************
2490 * X11DRV_DIB_SetImageBits_24
2492 * SetDIBits for a 24-bit deep DIB.
2494 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2495 DWORD srcwidth, DWORD dstwidth, int left,
2496 X11DRV_PDEVICE *physDev,
2497 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2498 XImage *bmpImage, DWORD linebytes )
2500 DWORD x;
2501 int h, width = min(srcwidth, dstwidth);
2502 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2504 if (lines < 0 )
2506 lines = -lines;
2507 srcbits = srcbits + linebytes * (lines - 1);
2508 linebytes = -linebytes;
2511 switch (bmpImage->depth)
2513 case 24:
2514 if (bmpImage->bits_per_pixel==24) {
2515 char* dstbits;
2517 srcbits=srcbits+left*3;
2518 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2520 if (bmpImage->green_mask!=0x00ff00 ||
2521 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2522 goto notsupported;
2523 } else if (rSrc==bmpImage->red_mask) {
2524 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2525 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2526 convs->Convert_888_asis
2527 (width,lines,
2528 srcbits,linebytes,
2529 dstbits,-bmpImage->bytes_per_line);
2530 } else {
2531 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2532 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2533 convs->Convert_888_reverse
2534 (width,lines,
2535 srcbits,linebytes,
2536 dstbits,-bmpImage->bytes_per_line);
2538 break;
2540 /* fall through */
2542 case 32:
2544 char* dstbits;
2546 srcbits=srcbits+left*3;
2547 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2549 if (bmpImage->green_mask!=0x00ff00 ||
2550 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2551 goto notsupported;
2552 } else if (rSrc==bmpImage->red_mask) {
2553 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2554 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2555 convs->Convert_888_to_0888_asis
2556 (width,lines,
2557 srcbits,linebytes,
2558 dstbits,-bmpImage->bytes_per_line);
2559 } else {
2560 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2561 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2562 convs->Convert_888_to_0888_reverse
2563 (width,lines,
2564 srcbits,linebytes,
2565 dstbits,-bmpImage->bytes_per_line);
2567 break;
2570 case 15:
2571 case 16:
2573 char* dstbits;
2575 srcbits=srcbits+left*3;
2576 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2578 if (bmpImage->green_mask==0x03e0) {
2579 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2580 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2581 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2582 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2583 convs->Convert_888_to_555_asis
2584 (width,lines,
2585 srcbits,linebytes,
2586 dstbits,-bmpImage->bytes_per_line);
2587 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2588 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2589 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2590 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2591 convs->Convert_888_to_555_reverse
2592 (width,lines,
2593 srcbits,linebytes,
2594 dstbits,-bmpImage->bytes_per_line);
2595 } else {
2596 goto notsupported;
2598 } else if (bmpImage->green_mask==0x07e0) {
2599 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2600 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2601 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2602 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2603 convs->Convert_888_to_565_asis
2604 (width,lines,
2605 srcbits,linebytes,
2606 dstbits,-bmpImage->bytes_per_line);
2607 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2608 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2609 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2610 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2611 convs->Convert_888_to_565_reverse
2612 (width,lines,
2613 srcbits,linebytes,
2614 dstbits,-bmpImage->bytes_per_line);
2615 } else {
2616 goto notsupported;
2618 } else {
2619 goto notsupported;
2622 break;
2624 default:
2625 notsupported:
2626 WARN("from 24 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2627 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2628 bmpImage->green_mask, bmpImage->blue_mask );
2629 /* fall through */
2630 case 1:
2631 case 4:
2632 case 8:
2634 /* ==== rgb 888 dib -> any bmp bormat ==== */
2635 const BYTE* srcbyte;
2637 /* Windows only supports one 24bpp DIB format: RGB888 */
2638 srcbits+=left*3;
2639 for (h = lines - 1; h >= 0; h--) {
2640 srcbyte=(const BYTE*)srcbits;
2641 for (x = left; x < width+left; x++) {
2642 XPutPixel(bmpImage, x, h,
2643 X11DRV_PALETTE_ToPhysical
2644 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2645 srcbyte+=3;
2647 srcbits += linebytes;
2650 break;
2655 /***********************************************************************
2656 * X11DRV_DIB_GetImageBits_24
2658 * GetDIBits for an 24-bit deep DIB.
2660 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2661 DWORD dstwidth, DWORD srcwidth,
2662 PALETTEENTRY *srccolors,
2663 DWORD rDst, DWORD gDst, DWORD bDst,
2664 XImage *bmpImage, DWORD linebytes )
2666 DWORD x;
2667 int h, width = min(srcwidth, dstwidth);
2668 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2670 if (lines < 0 )
2672 lines = -lines;
2673 dstbits = dstbits + ( linebytes * (lines-1) );
2674 linebytes = -linebytes;
2677 switch (bmpImage->depth)
2679 case 24:
2680 if (bmpImage->bits_per_pixel==24) {
2681 const char* srcbits;
2683 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2685 if (bmpImage->green_mask!=0x00ff00 ||
2686 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2687 goto notsupported;
2688 } else if (rDst==bmpImage->red_mask) {
2689 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2690 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2691 convs->Convert_888_asis
2692 (width,lines,
2693 srcbits,-bmpImage->bytes_per_line,
2694 dstbits,linebytes);
2695 } else {
2696 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2697 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2698 convs->Convert_888_reverse
2699 (width,lines,
2700 srcbits,-bmpImage->bytes_per_line,
2701 dstbits,linebytes);
2703 break;
2705 /* fall through */
2707 case 32:
2709 const char* srcbits;
2711 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2713 if (bmpImage->green_mask!=0x00ff00 ||
2714 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2715 goto notsupported;
2716 } else if (rDst==bmpImage->red_mask) {
2717 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2718 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2719 convs->Convert_0888_to_888_asis
2720 (width,lines,
2721 srcbits,-bmpImage->bytes_per_line,
2722 dstbits,linebytes);
2723 } else {
2724 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2725 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2726 convs->Convert_0888_to_888_reverse
2727 (width,lines,
2728 srcbits,-bmpImage->bytes_per_line,
2729 dstbits,linebytes);
2731 break;
2734 case 15:
2735 case 16:
2737 const char* srcbits;
2739 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2741 if (bmpImage->green_mask==0x03e0) {
2742 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2743 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2744 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2745 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2746 convs->Convert_555_to_888_asis
2747 (width,lines,
2748 srcbits,-bmpImage->bytes_per_line,
2749 dstbits,linebytes);
2750 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2751 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2752 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2753 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2754 convs->Convert_555_to_888_reverse
2755 (width,lines,
2756 srcbits,-bmpImage->bytes_per_line,
2757 dstbits,linebytes);
2758 } else {
2759 goto notsupported;
2761 } else if (bmpImage->green_mask==0x07e0) {
2762 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2763 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2764 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2765 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2766 convs->Convert_565_to_888_asis
2767 (width,lines,
2768 srcbits,-bmpImage->bytes_per_line,
2769 dstbits,linebytes);
2770 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2771 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2772 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2773 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2774 convs->Convert_565_to_888_reverse
2775 (width,lines,
2776 srcbits,-bmpImage->bytes_per_line,
2777 dstbits,linebytes);
2778 } else {
2779 goto notsupported;
2781 } else {
2782 goto notsupported;
2785 break;
2787 case 1:
2788 case 4:
2789 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2790 && srccolors) {
2791 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2792 BYTE* dstbyte;
2794 /* Windows only supports one 24bpp DIB format: rgb 888 */
2795 for (h = lines - 1; h >= 0; h--) {
2796 dstbyte=dstbits;
2797 for (x = 0; x < width; x++) {
2798 PALETTEENTRY srcval;
2799 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2800 dstbyte[0]=srcval.peBlue;
2801 dstbyte[1]=srcval.peGreen;
2802 dstbyte[2]=srcval.peRed;
2803 dstbyte+=3;
2805 dstbits += linebytes;
2807 } else {
2808 goto notsupported;
2810 break;
2812 case 8:
2813 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2814 && srccolors) {
2815 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2816 const void* srcbits;
2817 const BYTE* srcpixel;
2818 BYTE* dstbyte;
2820 /* Windows only supports one 24bpp DIB format: rgb 888 */
2821 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2822 for (h = lines - 1; h >= 0; h--) {
2823 srcpixel=srcbits;
2824 dstbyte=dstbits;
2825 for (x = 0; x < width; x++ ) {
2826 PALETTEENTRY srcval;
2827 srcval=srccolors[(int)*srcpixel++];
2828 dstbyte[0]=srcval.peBlue;
2829 dstbyte[1]=srcval.peGreen;
2830 dstbyte[2]=srcval.peRed;
2831 dstbyte+=3;
2833 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
2834 dstbits += linebytes;
2836 } else {
2837 goto notsupported;
2839 break;
2841 default:
2842 notsupported:
2844 /* ==== any bmp format -> 888 dib ==== */
2845 BYTE* dstbyte;
2847 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%x,%x,%x)\n",
2848 bmpImage->depth, bmpImage->red_mask,
2849 bmpImage->green_mask, bmpImage->blue_mask,
2850 rDst, gDst, bDst );
2852 /* Windows only supports one 24bpp DIB format: rgb 888 */
2853 for (h = lines - 1; h >= 0; h--) {
2854 dstbyte=dstbits;
2855 for (x = 0; x < width; x++) {
2856 COLORREF srcval=X11DRV_PALETTE_ToLogical
2857 (XGetPixel( bmpImage, x, h ));
2858 dstbyte[0]=GetBValue(srcval);
2859 dstbyte[1]=GetGValue(srcval);
2860 dstbyte[2]=GetRValue(srcval);
2861 dstbyte+=3;
2863 dstbits += linebytes;
2866 break;
2871 /***********************************************************************
2872 * X11DRV_DIB_SetImageBits_32
2874 * SetDIBits for a 32-bit deep DIB.
2876 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2877 DWORD srcwidth, DWORD dstwidth, int left,
2878 X11DRV_PDEVICE *physDev,
2879 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2880 XImage *bmpImage,
2881 DWORD linebytes)
2883 DWORD x;
2884 int h, width = min(srcwidth, dstwidth);
2885 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2887 if (lines < 0 )
2889 lines = -lines;
2890 srcbits = srcbits + ( linebytes * (lines-1) );
2891 linebytes = -linebytes;
2894 switch (bmpImage->depth)
2896 case 24:
2897 if (bmpImage->bits_per_pixel==24) {
2898 char* dstbits;
2900 srcbits=srcbits+left*4;
2901 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2903 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2904 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2905 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2906 convs->Convert_0888_to_888_asis
2907 (width,lines,
2908 srcbits,linebytes,
2909 dstbits,-bmpImage->bytes_per_line);
2910 } else if (bmpImage->green_mask!=0x00ff00 ||
2911 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2912 goto notsupported;
2913 /* the tests below assume sane bmpImage masks */
2914 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2915 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2916 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2917 convs->Convert_0888_to_888_reverse
2918 (width,lines,
2919 srcbits,linebytes,
2920 dstbits,-bmpImage->bytes_per_line);
2921 } else if (bmpImage->blue_mask==0xff) {
2922 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2923 convs->Convert_any0888_to_rgb888
2924 (width,lines,
2925 srcbits,linebytes,
2926 rSrc,gSrc,bSrc,
2927 dstbits,-bmpImage->bytes_per_line);
2928 } else {
2929 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2930 convs->Convert_any0888_to_bgr888
2931 (width,lines,
2932 srcbits,linebytes,
2933 rSrc,gSrc,bSrc,
2934 dstbits,-bmpImage->bytes_per_line);
2936 break;
2938 /* fall through */
2940 case 32:
2942 char* dstbits;
2944 srcbits=srcbits+left*4;
2945 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2947 if (gSrc==bmpImage->green_mask) {
2948 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2949 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2950 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2951 convs->Convert_0888_asis
2952 (width,lines,
2953 srcbits,linebytes,
2954 dstbits,-bmpImage->bytes_per_line);
2955 } else if (bmpImage->green_mask!=0x00ff00 ||
2956 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2957 goto notsupported;
2958 /* the tests below assume sane bmpImage masks */
2959 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2960 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2961 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2962 convs->Convert_0888_reverse
2963 (width,lines,
2964 srcbits,linebytes,
2965 dstbits,-bmpImage->bytes_per_line);
2966 } else {
2967 /* ==== any 0888 dib -> any 0888 bmp ==== */
2968 convs->Convert_0888_any
2969 (width,lines,
2970 srcbits,linebytes,
2971 rSrc,gSrc,bSrc,
2972 dstbits,-bmpImage->bytes_per_line,
2973 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2975 } else if (bmpImage->green_mask!=0x00ff00 ||
2976 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2977 goto notsupported;
2978 /* the tests below assume sane bmpImage masks */
2979 } else {
2980 /* ==== any 0888 dib -> any 0888 bmp ==== */
2981 convs->Convert_0888_any
2982 (width,lines,
2983 srcbits,linebytes,
2984 rSrc,gSrc,bSrc,
2985 dstbits,-bmpImage->bytes_per_line,
2986 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2989 break;
2991 case 15:
2992 case 16:
2994 char* dstbits;
2996 srcbits=srcbits+left*4;
2997 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2999 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
3000 if (bmpImage->green_mask==0x03e0) {
3001 if (bmpImage->red_mask==0x7f00) {
3002 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
3003 convs->Convert_0888_to_555_asis
3004 (width,lines,
3005 srcbits,linebytes,
3006 dstbits,-bmpImage->bytes_per_line);
3007 } else if (bmpImage->blue_mask==0x7f00) {
3008 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
3009 convs->Convert_0888_to_555_reverse
3010 (width,lines,
3011 srcbits,linebytes,
3012 dstbits,-bmpImage->bytes_per_line);
3013 } else {
3014 goto notsupported;
3016 } else if (bmpImage->green_mask==0x07e0) {
3017 if (bmpImage->red_mask==0xf800) {
3018 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
3019 convs->Convert_0888_to_565_asis
3020 (width,lines,
3021 srcbits,linebytes,
3022 dstbits,-bmpImage->bytes_per_line);
3023 } else if (bmpImage->blue_mask==0xf800) {
3024 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
3025 convs->Convert_0888_to_565_reverse
3026 (width,lines,
3027 srcbits,linebytes,
3028 dstbits,-bmpImage->bytes_per_line);
3029 } else {
3030 goto notsupported;
3032 } else {
3033 goto notsupported;
3035 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
3036 if (bmpImage->green_mask==0x03e0) {
3037 if (bmpImage->blue_mask==0x7f00) {
3038 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
3039 convs->Convert_0888_to_555_asis
3040 (width,lines,
3041 srcbits,linebytes,
3042 dstbits,-bmpImage->bytes_per_line);
3043 } else if (bmpImage->red_mask==0x7f00) {
3044 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
3045 convs->Convert_0888_to_555_reverse
3046 (width,lines,
3047 srcbits,linebytes,
3048 dstbits,-bmpImage->bytes_per_line);
3049 } else {
3050 goto notsupported;
3052 } else if (bmpImage->green_mask==0x07e0) {
3053 if (bmpImage->blue_mask==0xf800) {
3054 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
3055 convs->Convert_0888_to_565_asis
3056 (width,lines,
3057 srcbits,linebytes,
3058 dstbits,-bmpImage->bytes_per_line);
3059 } else if (bmpImage->red_mask==0xf800) {
3060 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
3061 convs->Convert_0888_to_565_reverse
3062 (width,lines,
3063 srcbits,linebytes,
3064 dstbits,-bmpImage->bytes_per_line);
3065 } else {
3066 goto notsupported;
3068 } else {
3069 goto notsupported;
3071 } else {
3072 if (bmpImage->green_mask==0x03e0 &&
3073 (bmpImage->red_mask==0x7f00 ||
3074 bmpImage->blue_mask==0x7f00)) {
3075 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
3076 convs->Convert_any0888_to_5x5
3077 (width,lines,
3078 srcbits,linebytes,
3079 rSrc,gSrc,bSrc,
3080 dstbits,-bmpImage->bytes_per_line,
3081 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3082 } else if (bmpImage->green_mask==0x07e0 &&
3083 (bmpImage->red_mask==0xf800 ||
3084 bmpImage->blue_mask==0xf800)) {
3085 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
3086 convs->Convert_any0888_to_5x5
3087 (width,lines,
3088 srcbits,linebytes,
3089 rSrc,gSrc,bSrc,
3090 dstbits,-bmpImage->bytes_per_line,
3091 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3092 } else {
3093 goto notsupported;
3097 break;
3099 default:
3100 notsupported:
3101 WARN("from 32 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3102 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3103 bmpImage->green_mask, bmpImage->blue_mask );
3104 /* fall through */
3105 case 1:
3106 case 4:
3107 case 8:
3109 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
3110 const DWORD* srcpixel;
3111 int rShift,gShift,bShift;
3113 rShift=X11DRV_DIB_MaskToShift(rSrc);
3114 gShift=X11DRV_DIB_MaskToShift(gSrc);
3115 bShift=X11DRV_DIB_MaskToShift(bSrc);
3116 srcbits+=left*4;
3117 for (h = lines - 1; h >= 0; h--) {
3118 srcpixel=(const DWORD*)srcbits;
3119 for (x = left; x < width+left; x++) {
3120 DWORD srcvalue;
3121 BYTE red,green,blue;
3122 srcvalue=*srcpixel++;
3123 red= (srcvalue >> rShift) & 0xff;
3124 green=(srcvalue >> gShift) & 0xff;
3125 blue= (srcvalue >> bShift) & 0xff;
3126 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
3127 (physDev, RGB(red,green,blue)));
3129 srcbits += linebytes;
3132 break;
3137 /***********************************************************************
3138 * X11DRV_DIB_GetImageBits_32
3140 * GetDIBits for an 32-bit deep DIB.
3142 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
3143 DWORD dstwidth, DWORD srcwidth,
3144 PALETTEENTRY *srccolors,
3145 DWORD rDst, DWORD gDst, DWORD bDst,
3146 XImage *bmpImage, DWORD linebytes )
3148 DWORD x;
3149 int h, width = min(srcwidth, dstwidth);
3150 BYTE *bits;
3151 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
3153 if (lines < 0 )
3155 lines = -lines;
3156 dstbits = dstbits + ( linebytes * (lines-1) );
3157 linebytes = -linebytes;
3160 bits = dstbits;
3162 switch (bmpImage->depth)
3164 case 24:
3165 if (bmpImage->bits_per_pixel==24) {
3166 const void* srcbits;
3168 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3170 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
3171 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3172 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3173 convs->Convert_888_to_0888_asis
3174 (width,lines,
3175 srcbits,-bmpImage->bytes_per_line,
3176 dstbits,linebytes);
3177 } else if (bmpImage->green_mask!=0x00ff00 ||
3178 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3179 goto notsupported;
3180 /* the tests below assume sane bmpImage masks */
3181 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3182 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3183 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3184 convs->Convert_888_to_0888_reverse
3185 (width,lines,
3186 srcbits,-bmpImage->bytes_per_line,
3187 dstbits,linebytes);
3188 } else if (bmpImage->blue_mask==0xff) {
3189 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3190 convs->Convert_rgb888_to_any0888
3191 (width,lines,
3192 srcbits,-bmpImage->bytes_per_line,
3193 dstbits,linebytes,
3194 rDst,gDst,bDst);
3195 } else {
3196 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3197 convs->Convert_bgr888_to_any0888
3198 (width,lines,
3199 srcbits,-bmpImage->bytes_per_line,
3200 dstbits,linebytes,
3201 rDst,gDst,bDst);
3203 break;
3205 /* fall through */
3207 case 32:
3209 const char* srcbits;
3211 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3213 if (gDst==bmpImage->green_mask) {
3214 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3215 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3216 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3217 convs->Convert_0888_asis
3218 (width,lines,
3219 srcbits,-bmpImage->bytes_per_line,
3220 dstbits,linebytes);
3221 } else if (bmpImage->green_mask!=0x00ff00 ||
3222 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3223 goto notsupported;
3224 /* the tests below assume sane bmpImage masks */
3225 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3226 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3227 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3228 convs->Convert_0888_reverse
3229 (width,lines,
3230 srcbits,-bmpImage->bytes_per_line,
3231 dstbits,linebytes);
3232 } else {
3233 /* ==== any 0888 bmp -> any 0888 dib ==== */
3234 convs->Convert_0888_any
3235 (width,lines,
3236 srcbits,-bmpImage->bytes_per_line,
3237 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3238 dstbits,linebytes,
3239 rDst,gDst,bDst);
3241 } else if (bmpImage->green_mask!=0x00ff00 ||
3242 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3243 goto notsupported;
3244 /* the tests below assume sane bmpImage masks */
3245 } else {
3246 /* ==== any 0888 bmp -> any 0888 dib ==== */
3247 convs->Convert_0888_any
3248 (width,lines,
3249 srcbits,-bmpImage->bytes_per_line,
3250 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3251 dstbits,linebytes,
3252 rDst,gDst,bDst);
3255 break;
3257 case 15:
3258 case 16:
3260 const char* srcbits;
3262 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3264 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3265 if (bmpImage->green_mask==0x03e0) {
3266 if (bmpImage->red_mask==0x7f00) {
3267 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3268 convs->Convert_555_to_0888_asis
3269 (width,lines,
3270 srcbits,-bmpImage->bytes_per_line,
3271 dstbits,linebytes);
3272 } else if (bmpImage->blue_mask==0x7f00) {
3273 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3274 convs->Convert_555_to_0888_reverse
3275 (width,lines,
3276 srcbits,-bmpImage->bytes_per_line,
3277 dstbits,linebytes);
3278 } else {
3279 goto notsupported;
3281 } else if (bmpImage->green_mask==0x07e0) {
3282 if (bmpImage->red_mask==0xf800) {
3283 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3284 convs->Convert_565_to_0888_asis
3285 (width,lines,
3286 srcbits,-bmpImage->bytes_per_line,
3287 dstbits,linebytes);
3288 } else if (bmpImage->blue_mask==0xf800) {
3289 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3290 convs->Convert_565_to_0888_reverse
3291 (width,lines,
3292 srcbits,-bmpImage->bytes_per_line,
3293 dstbits,linebytes);
3294 } else {
3295 goto notsupported;
3297 } else {
3298 goto notsupported;
3300 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3301 if (bmpImage->green_mask==0x03e0) {
3302 if (bmpImage->blue_mask==0x7f00) {
3303 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3304 convs->Convert_555_to_0888_asis
3305 (width,lines,
3306 srcbits,-bmpImage->bytes_per_line,
3307 dstbits,linebytes);
3308 } else if (bmpImage->red_mask==0x7f00) {
3309 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3310 convs->Convert_555_to_0888_reverse
3311 (width,lines,
3312 srcbits,-bmpImage->bytes_per_line,
3313 dstbits,linebytes);
3314 } else {
3315 goto notsupported;
3317 } else if (bmpImage->green_mask==0x07e0) {
3318 if (bmpImage->blue_mask==0xf800) {
3319 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3320 convs->Convert_565_to_0888_asis
3321 (width,lines,
3322 srcbits,-bmpImage->bytes_per_line,
3323 dstbits,linebytes);
3324 } else if (bmpImage->red_mask==0xf800) {
3325 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3326 convs->Convert_565_to_0888_reverse
3327 (width,lines,
3328 srcbits,-bmpImage->bytes_per_line,
3329 dstbits,linebytes);
3330 } else {
3331 goto notsupported;
3333 } else {
3334 goto notsupported;
3336 } else {
3337 if (bmpImage->green_mask==0x03e0 &&
3338 (bmpImage->red_mask==0x7f00 ||
3339 bmpImage->blue_mask==0x7f00)) {
3340 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3341 convs->Convert_5x5_to_any0888
3342 (width,lines,
3343 srcbits,-bmpImage->bytes_per_line,
3344 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3345 dstbits,linebytes,
3346 rDst,gDst,bDst);
3347 } else if (bmpImage->green_mask==0x07e0 &&
3348 (bmpImage->red_mask==0xf800 ||
3349 bmpImage->blue_mask==0xf800)) {
3350 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3351 convs->Convert_5x5_to_any0888
3352 (width,lines,
3353 srcbits,-bmpImage->bytes_per_line,
3354 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3355 dstbits,linebytes,
3356 rDst,gDst,bDst);
3357 } else {
3358 goto notsupported;
3362 break;
3364 case 1:
3365 case 4:
3366 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3367 && srccolors) {
3368 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3369 int rShift,gShift,bShift;
3370 DWORD* dstpixel;
3372 rShift=X11DRV_DIB_MaskToShift(rDst);
3373 gShift=X11DRV_DIB_MaskToShift(gDst);
3374 bShift=X11DRV_DIB_MaskToShift(bDst);
3375 for (h = lines - 1; h >= 0; h--) {
3376 dstpixel=(DWORD*)dstbits;
3377 for (x = 0; x < width; x++) {
3378 PALETTEENTRY srcval;
3379 srcval = srccolors[XGetPixel(bmpImage, x, h)];
3380 *dstpixel++=(srcval.peRed << rShift) |
3381 (srcval.peGreen << gShift) |
3382 (srcval.peBlue << bShift);
3384 dstbits += linebytes;
3386 } else {
3387 goto notsupported;
3389 break;
3391 case 8:
3392 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3393 && srccolors) {
3394 /* ==== pal 8 bmp -> any 0888 dib ==== */
3395 int rShift,gShift,bShift;
3396 const void* srcbits;
3397 const BYTE* srcpixel;
3398 DWORD* dstpixel;
3400 rShift=X11DRV_DIB_MaskToShift(rDst);
3401 gShift=X11DRV_DIB_MaskToShift(gDst);
3402 bShift=X11DRV_DIB_MaskToShift(bDst);
3403 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3404 for (h = lines - 1; h >= 0; h--) {
3405 srcpixel=srcbits;
3406 dstpixel=(DWORD*)dstbits;
3407 for (x = 0; x < width; x++) {
3408 PALETTEENTRY srcval;
3409 srcval=srccolors[(int)*srcpixel++];
3410 *dstpixel++=(srcval.peRed << rShift) |
3411 (srcval.peGreen << gShift) |
3412 (srcval.peBlue << bShift);
3414 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
3415 dstbits += linebytes;
3417 } else {
3418 goto notsupported;
3420 break;
3422 default:
3423 notsupported:
3425 /* ==== any bmp format -> any 0888 dib ==== */
3426 int rShift,gShift,bShift;
3427 DWORD* dstpixel;
3429 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%x,%x,%x)\n",
3430 bmpImage->depth, bmpImage->red_mask,
3431 bmpImage->green_mask, bmpImage->blue_mask,
3432 rDst,gDst,bDst);
3434 rShift=X11DRV_DIB_MaskToShift(rDst);
3435 gShift=X11DRV_DIB_MaskToShift(gDst);
3436 bShift=X11DRV_DIB_MaskToShift(bDst);
3437 for (h = lines - 1; h >= 0; h--) {
3438 dstpixel=(DWORD*)dstbits;
3439 for (x = 0; x < width; x++) {
3440 COLORREF srcval;
3441 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3442 *dstpixel++=(GetRValue(srcval) << rShift) |
3443 (GetGValue(srcval) << gShift) |
3444 (GetBValue(srcval) << bShift);
3446 dstbits += linebytes;
3449 break;
3453 static int XGetSubImageErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
3455 return (event->request_code == X_GetImage && event->error_code == BadMatch);
3458 /***********************************************************************
3459 * X11DRV_DIB_SetImageBits_GetSubImage
3461 * Helper for X11DRV_DIB_SetImageBits
3463 static void X11DRV_DIB_SetImageBits_GetSubImage(
3464 const X11DRV_DIB_IMAGEBITS_DESCR *descr, XImage *bmpImage)
3466 /* compressed bitmaps may contain gaps in them. So make a copy
3467 * of the existing pixels first */
3468 RECT bmprc, rc;
3470 SetRect( &bmprc, descr->xDest, descr->yDest,
3471 descr->xDest + descr->width , descr->yDest + descr->height );
3472 GetRgnBox( descr->physDev->region, &rc );
3473 /* convert from dc to drawable origin */
3474 OffsetRect( &rc, descr->physDev->dc_rect.left, descr->physDev->dc_rect.top);
3475 /* clip visible rect with bitmap */
3476 if( IntersectRect( &rc, &rc, &bmprc))
3478 X11DRV_expect_error( gdi_display, XGetSubImageErrorHandler, NULL );
3479 XGetSubImage( gdi_display, descr->drawable, rc.left, rc.top,
3480 rc.right - rc.left, rc.bottom - rc.top, AllPlanes,
3481 ZPixmap, bmpImage,
3482 descr->xSrc + rc.left - bmprc.left,
3483 descr->ySrc + rc.top - bmprc.top);
3484 X11DRV_check_error();
3488 /***********************************************************************
3489 * X11DRV_DIB_SetImageBits
3491 * Transfer the bits to an X image.
3492 * Helper function for SetDIBits() and SetDIBitsToDevice().
3494 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3496 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3497 XImage *bmpImage;
3498 void *olddata = NULL;
3499 wine_tsx11_lock();
3500 if (descr->image)
3501 bmpImage = descr->image;
3502 else {
3503 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3504 descr->infoWidth, lines, 32, 0 );
3505 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3506 if(bmpImage->data == NULL) {
3507 ERR("Out of memory!\n");
3508 XDestroyImage( bmpImage );
3509 wine_tsx11_unlock();
3510 return lines;
3514 TRACE("Dib: depth=%d r=%x g=%x b=%x\n",
3515 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3516 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3517 bmpImage->depth,bmpImage->bits_per_pixel,
3518 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3520 #ifdef HAVE_LIBXXSHM
3521 if (descr->useShm && descr->xSrc == 0 && descr->ySrc == 0 && descr->xDest == 0 && descr->yDest == 0) {
3522 TRACE("using the shared pixmap data\n");
3523 XSync(gdi_display, False);
3524 olddata = descr->image->data;
3525 descr->image->data = descr->physBitmap->shminfo.shmaddr;
3527 #endif
3529 /* Transfer the pixels */
3530 switch(descr->infoBpp)
3532 case 1:
3533 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3534 descr->width, descr->xSrc, (int *)(descr->colorMap),
3535 bmpImage, descr->dibpitch );
3536 break;
3537 case 4:
3538 if (descr->compression) {
3539 X11DRV_DIB_SetImageBits_GetSubImage( descr, bmpImage);
3540 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3541 descr->infoWidth, descr->width,
3542 descr->xSrc, (int *)(descr->colorMap),
3543 bmpImage );
3544 } else
3545 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3546 descr->infoWidth, descr->width,
3547 descr->xSrc, (int*)(descr->colorMap),
3548 bmpImage, descr->dibpitch );
3549 break;
3550 case 8:
3551 if (descr->compression) {
3552 X11DRV_DIB_SetImageBits_GetSubImage( descr, bmpImage);
3553 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3554 descr->infoWidth, descr->width,
3555 descr->xSrc, (int *)(descr->colorMap),
3556 bmpImage );
3557 } else
3558 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3559 descr->infoWidth, descr->width,
3560 descr->xSrc, (int *)(descr->colorMap),
3561 bmpImage, descr->dibpitch );
3562 break;
3563 case 15:
3564 case 16:
3565 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3566 descr->infoWidth, descr->width,
3567 descr->xSrc, descr->physDev,
3568 descr->rMask, descr->gMask, descr->bMask,
3569 bmpImage, descr->dibpitch);
3570 break;
3571 case 24:
3572 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3573 descr->infoWidth, descr->width,
3574 descr->xSrc, descr->physDev,
3575 descr->rMask, descr->gMask, descr->bMask,
3576 bmpImage, descr->dibpitch);
3577 break;
3578 case 32:
3579 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3580 descr->infoWidth, descr->width,
3581 descr->xSrc, descr->physDev,
3582 descr->rMask, descr->gMask, descr->bMask,
3583 bmpImage, descr->dibpitch);
3584 break;
3585 default:
3586 WARN("(%d): Invalid depth\n", descr->infoBpp );
3587 break;
3590 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3591 descr->drawable, descr->gc, bmpImage,
3592 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3593 descr->width, descr->height);
3594 #ifdef HAVE_LIBXXSHM
3595 if (descr->useShm && descr->xSrc == 0 && descr->ySrc == 0 && descr->xDest == 0 && descr->yDest == 0)
3597 XSync( gdi_display, 0 );
3599 else
3600 #endif
3601 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3602 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3603 descr->width, descr->height );
3605 if(olddata) descr->image->data = olddata;
3607 if (!descr->image) XDestroyImage( bmpImage );
3608 wine_tsx11_unlock();
3609 return lines;
3612 /***********************************************************************
3613 * X11DRV_DIB_GetImageBits
3615 * Transfer the bits from an X image.
3617 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3619 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3620 XImage *bmpImage;
3621 void *olddata = NULL;
3623 wine_tsx11_lock();
3624 if (descr->image)
3625 bmpImage = descr->image;
3626 else {
3627 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3628 descr->infoWidth, lines, 32, 0 );
3629 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3630 if(bmpImage->data == NULL) {
3631 ERR("Out of memory!\n");
3632 XDestroyImage( bmpImage );
3633 wine_tsx11_unlock();
3634 return lines;
3638 #ifdef HAVE_LIBXXSHM
3639 if (descr->useShm && descr->xSrc == 0 && descr->ySrc == 0 && descr->xDest == 0 && descr->yDest == 0)
3641 XSync(gdi_display, False);
3642 olddata = bmpImage->data;
3643 bmpImage->data = descr->physBitmap->shminfo.shmaddr;
3644 TRACE("using shared pixmap data\n");
3646 else
3647 #endif /* HAVE_LIBXXSHM */
3649 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3650 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3651 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3652 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3653 descr->width, lines, AllPlanes, ZPixmap,
3654 bmpImage, descr->xDest, descr->yDest );
3657 TRACE("Dib: depth=%2d r=%x g=%x b=%x\n",
3658 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3659 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3660 bmpImage->depth,bmpImage->bits_per_pixel,
3661 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3662 /* Transfer the pixels */
3663 switch(descr->infoBpp)
3665 case 1:
3666 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3667 descr->infoWidth, descr->width,
3668 descr->colorMap, descr->palentry,
3669 bmpImage, descr->dibpitch );
3670 break;
3672 case 4:
3673 if (descr->compression) {
3674 FIXME("Compression not yet supported!\n");
3675 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 4 ) * abs(descr->lines))
3676 break;
3678 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3679 descr->infoWidth, descr->width,
3680 descr->colorMap, descr->palentry,
3681 bmpImage, descr->dibpitch );
3682 break;
3683 case 8:
3684 if (descr->compression) {
3685 FIXME("Compression not yet supported!\n");
3686 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 8 ) * abs(descr->lines))
3687 break;
3689 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3690 descr->infoWidth, descr->width,
3691 descr->colorMap, descr->palentry,
3692 bmpImage, descr->dibpitch );
3693 break;
3694 case 15:
3695 case 16:
3696 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
3697 descr->infoWidth,descr->width,
3698 descr->palentry,
3699 descr->rMask, descr->gMask, descr->bMask,
3700 bmpImage, descr->dibpitch );
3701 break;
3703 case 24:
3704 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
3705 descr->infoWidth,descr->width,
3706 descr->palentry,
3707 descr->rMask, descr->gMask, descr->bMask,
3708 bmpImage, descr->dibpitch);
3709 break;
3711 case 32:
3712 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
3713 descr->infoWidth, descr->width,
3714 descr->palentry,
3715 descr->rMask, descr->gMask, descr->bMask,
3716 bmpImage, descr->dibpitch);
3717 break;
3719 default:
3720 WARN("(%d): Invalid depth\n", descr->infoBpp );
3721 break;
3724 if(olddata) bmpImage->data = olddata;
3725 if (!descr->image) XDestroyImage( bmpImage );
3726 wine_tsx11_unlock();
3727 return lines;
3730 /*************************************************************************
3731 * X11DRV_SetDIBitsToDevice
3734 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
3735 DWORD cy, INT xSrc, INT ySrc,
3736 UINT startscan, UINT lines, LPCVOID bits,
3737 const BITMAPINFO *info, UINT coloruse )
3739 X11DRV_DIB_IMAGEBITS_DESCR descr;
3740 INT result;
3741 LONG width, height;
3742 BOOL top_down;
3743 POINT pt;
3745 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3746 &descr.infoBpp, &descr.compression ) == -1)
3747 return 0;
3749 top_down = (height < 0);
3750 if (top_down) height = -height;
3752 pt.x = xDest;
3753 pt.y = yDest;
3754 LPtoDP(physDev->hdc, &pt, 1);
3756 if (!lines || (startscan >= height)) return 0;
3757 if (!top_down && startscan + lines > height) lines = height - startscan;
3759 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3760 * and clamp all values to fit inside [startscan,startscan+lines]
3762 if (ySrc + cy <= startscan + lines)
3764 UINT y = startscan + lines - (ySrc + cy);
3765 if (ySrc < startscan) cy -= (startscan - ySrc);
3766 if (!top_down)
3768 /* avoid getting unnecessary lines */
3769 ySrc = 0;
3770 if (y >= lines) return 0;
3771 lines -= y;
3773 else
3775 if (y >= lines) return lines;
3776 ySrc = y; /* need to get all lines in top down mode */
3779 else
3781 if (ySrc >= startscan + lines) return lines;
3782 pt.y += ySrc + cy - (startscan + lines);
3783 cy = startscan + lines - ySrc;
3784 ySrc = 0;
3785 if (cy > lines) cy = lines;
3787 if (xSrc >= width) return lines;
3788 if (xSrc + cx >= width) cx = width - xSrc;
3789 if (!cx || !cy) return lines;
3791 /* Update the pixmap from the DIB section */
3792 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
3794 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
3795 wine_tsx11_lock();
3796 XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
3797 wine_tsx11_unlock();
3799 switch (descr.infoBpp)
3801 case 1:
3802 case 4:
3803 case 8:
3804 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3805 physDev, coloruse,
3806 physDev->depth, info, &descr.nColorMap );
3807 if (!descr.colorMap) return 0;
3808 descr.rMask = descr.gMask = descr.bMask = 0;
3809 break;
3810 case 15:
3811 case 16:
3812 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0x7c00;
3813 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
3814 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
3815 descr.colorMap = 0;
3816 break;
3818 case 24:
3819 case 32:
3820 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0xff0000;
3821 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
3822 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
3823 descr.colorMap = 0;
3824 break;
3827 descr.physDev = physDev;
3828 descr.bits = bits;
3829 descr.image = NULL;
3830 descr.palentry = NULL;
3831 descr.lines = top_down ? -lines : lines;
3832 descr.infoWidth = width;
3833 descr.depth = physDev->depth;
3834 descr.drawable = physDev->drawable;
3835 descr.gc = physDev->gc;
3836 descr.xSrc = xSrc;
3837 descr.ySrc = ySrc;
3838 descr.xDest = physDev->dc_rect.left + pt.x;
3839 descr.yDest = physDev->dc_rect.top + pt.y;
3840 descr.width = cx;
3841 descr.height = cy;
3842 descr.useShm = FALSE;
3843 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
3845 result = X11DRV_DIB_SetImageBits( &descr );
3847 if (descr.infoBpp <= 8)
3848 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3850 /* Update the DIBSection of the pixmap */
3851 X11DRV_UnlockDIBSection(physDev, TRUE);
3853 return result;
3856 /***********************************************************************
3857 * SetDIBits (X11DRV.@)
3859 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3860 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3862 X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
3863 X11DRV_DIB_IMAGEBITS_DESCR descr;
3864 BITMAP bitmap;
3865 LONG width, height, tmpheight;
3866 INT result;
3868 descr.physDev = physDev;
3870 if (!physBitmap) return 0;
3872 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3873 &descr.infoBpp, &descr.compression ) == -1)
3874 return 0;
3876 tmpheight = height;
3877 if (height < 0) height = -height;
3878 if (!lines || (startscan >= height))
3879 return 0;
3881 if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return 0;
3883 if (startscan + lines > height) lines = height - startscan;
3885 switch (descr.infoBpp)
3887 case 1:
3888 case 4:
3889 case 8:
3890 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3891 descr.physDev, coloruse,
3892 physBitmap->pixmap_depth,
3893 info, &descr.nColorMap );
3894 if (!descr.colorMap) return 0;
3895 descr.rMask = descr.gMask = descr.bMask = 0;
3896 break;
3897 case 15:
3898 case 16:
3899 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0x7c00;
3900 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
3901 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
3902 descr.colorMap = 0;
3903 break;
3905 case 24:
3906 case 32:
3907 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0xff0000;
3908 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
3909 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
3910 descr.colorMap = 0;
3911 break;
3913 default: break;
3916 descr.bits = bits;
3917 descr.image = NULL;
3918 descr.palentry = NULL;
3919 descr.infoWidth = width;
3920 descr.lines = tmpheight >= 0 ? lines : -lines;
3921 descr.depth = physBitmap->pixmap_depth;
3922 descr.drawable = physBitmap->pixmap;
3923 descr.gc = BITMAP_GC(physBitmap);
3924 descr.xSrc = 0;
3925 descr.ySrc = 0;
3926 descr.xDest = 0;
3927 descr.yDest = height - startscan - lines;
3928 descr.width = bitmap.bmWidth;
3929 descr.height = lines;
3930 descr.useShm = FALSE;
3931 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3932 X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod, FALSE );
3933 result = X11DRV_DIB_SetImageBits( &descr );
3934 X11DRV_DIB_Unlock( physBitmap, TRUE );
3936 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3938 return result;
3941 /***********************************************************************
3942 * GetDIBits (X11DRV.@)
3944 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3945 LPVOID bits, BITMAPINFO *info, UINT coloruse )
3947 X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
3948 DIBSECTION dib;
3949 X11DRV_DIB_IMAGEBITS_DESCR descr;
3950 PALETTEENTRY palette[256];
3951 size_t obj_size;
3952 int height;
3953 LONG width, tempHeight;
3954 int bitmap_type;
3955 BOOL core_header;
3956 void* colorPtr;
3958 GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
3960 if (!physBitmap) return 0;
3961 if (!(obj_size = GetObjectW( hbitmap, sizeof(dib), &dib ))) return 0;
3963 bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*)info, &width, &tempHeight, &descr.infoBpp, &descr.compression);
3964 descr.lines = tempHeight;
3965 if (bitmap_type == -1)
3967 ERR("Invalid bitmap\n");
3968 return 0;
3970 core_header = (bitmap_type == 0);
3971 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3973 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3974 lines, dib.dsBm.bmWidth, dib.dsBm.bmHeight, width, descr.lines, startscan);
3976 if( lines > dib.dsBm.bmHeight ) lines = dib.dsBm.bmHeight;
3978 height = descr.lines;
3979 if (height < 0) height = -height;
3980 if( lines > height ) lines = height;
3981 /* Top-down images have a negative biHeight, the scanlines of theses images
3982 * were inverted in X11DRV_DIB_GetImageBits_xx
3983 * To prevent this we simply change the sign of lines
3984 * (the number of scan lines to copy).
3985 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3987 if( descr.lines < 0 && lines > 0) lines = -lines;
3989 if( startscan >= dib.dsBm.bmHeight ) return 0;
3991 descr.colorMap = NULL;
3993 switch (descr.infoBpp)
3995 case 1:
3996 case 4:
3997 case 8:
3998 descr.rMask= descr.gMask = descr.bMask = 0;
3999 if(coloruse == DIB_RGB_COLORS)
4000 descr.colorMap = colorPtr;
4001 else {
4002 int num_colors = 1 << descr.infoBpp, i;
4003 RGBQUAD *rgb;
4004 COLORREF colref;
4005 WORD *index = (WORD*)colorPtr;
4006 descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
4007 for(i = 0; i < num_colors; i++, rgb++, index++) {
4008 colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
4009 rgb->rgbRed = GetRValue(colref);
4010 rgb->rgbGreen = GetGValue(colref);
4011 rgb->rgbBlue = GetBValue(colref);
4012 rgb->rgbReserved = 0;
4015 break;
4016 case 15:
4017 case 16:
4018 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0x7c00;
4019 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
4020 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
4021 break;
4022 case 24:
4023 case 32:
4024 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0xff0000;
4025 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
4026 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
4027 break;
4030 descr.physDev = physDev;
4031 descr.palentry = palette;
4032 descr.bits = bits;
4033 descr.image = physBitmap->image;
4034 descr.infoWidth = width;
4035 descr.lines = lines;
4036 descr.depth = physBitmap->pixmap_depth;
4037 descr.drawable = physBitmap->pixmap;
4038 descr.gc = BITMAP_GC(physBitmap);
4039 descr.width = dib.dsBm.bmWidth;
4040 descr.height = dib.dsBm.bmHeight;
4041 descr.xDest = 0;
4042 descr.yDest = 0;
4043 descr.xSrc = 0;
4044 descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
4045 descr.physBitmap = physBitmap;
4047 if (descr.lines > 0)
4049 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
4051 else
4053 descr.ySrc = startscan;
4055 descr.useShm = FALSE;
4056 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4058 X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod, FALSE );
4059 X11DRV_DIB_GetImageBits( &descr );
4060 X11DRV_DIB_Unlock( physBitmap, TRUE );
4062 if(!core_header && info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
4063 info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBImageBytes( descr.infoWidth,
4064 descr.lines,
4065 descr.infoBpp);
4067 if (descr.compression == BI_BITFIELDS)
4069 *(DWORD *)info->bmiColors = descr.rMask;
4070 *((DWORD *)info->bmiColors + 1) = descr.gMask;
4071 *((DWORD *)info->bmiColors + 2) = descr.bMask;
4073 else if (!core_header)
4075 /* if RLE or JPEG compression were supported,
4076 * this line would be invalid. */
4077 info->bmiHeader.biCompression = 0;
4080 if(descr.colorMap != colorPtr)
4081 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4082 return lines;
4085 /***********************************************************************
4086 * DIB_DoProtectDIBSection
4088 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
4090 DWORD old_prot;
4092 VirtualProtect(physBitmap->base, physBitmap->size, new_prot, &old_prot);
4093 TRACE("Changed protection from %d to %d\n", old_prot, new_prot);
4096 /***********************************************************************
4097 * X11DRV_DIB_DoCopyDIBSection
4099 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
4100 void *colorMap, int nColorMap,
4101 Drawable dest, GC gc,
4102 DWORD xSrc, DWORD ySrc,
4103 DWORD xDest, DWORD yDest,
4104 DWORD width, DWORD height)
4106 DIBSECTION dibSection;
4107 X11DRV_DIB_IMAGEBITS_DESCR descr;
4108 int identity[2] = {0,1};
4110 if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
4112 descr.physDev = NULL;
4113 descr.palentry = NULL;
4114 descr.image = physBitmap->image;
4115 descr.physBitmap= physBitmap;
4116 descr.infoWidth = dibSection.dsBmih.biWidth;
4117 descr.infoBpp = dibSection.dsBmih.biBitCount;
4118 descr.lines = dibSection.dsBmih.biHeight;
4119 descr.image = physBitmap->image;
4120 descr.colorMap = colorMap;
4121 descr.nColorMap = nColorMap;
4122 descr.bits = dibSection.dsBm.bmBits;
4123 descr.depth = physBitmap->pixmap_depth;
4124 descr.compression = dibSection.dsBmih.biCompression;
4126 if(descr.infoBpp == 1)
4127 descr.colorMap = (void*)identity;
4129 switch (descr.infoBpp)
4131 case 1:
4132 case 4:
4133 case 8:
4134 descr.rMask = descr.gMask = descr.bMask = 0;
4135 break;
4136 case 15:
4137 case 16:
4138 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0x7c00;
4139 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x03e0;
4140 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x001f;
4141 break;
4143 case 24:
4144 case 32:
4145 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0xff0000;
4146 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x00ff00;
4147 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x0000ff;
4148 break;
4151 /* Hack for now */
4152 descr.drawable = dest;
4153 descr.gc = gc;
4154 descr.xSrc = xSrc;
4155 descr.ySrc = ySrc;
4156 descr.xDest = xDest;
4157 descr.yDest = yDest;
4158 descr.width = width;
4159 descr.height = height;
4160 descr.sizeImage = 0;
4162 #ifdef HAVE_LIBXXSHM
4163 descr.useShm = (physBitmap->shminfo.shmid != -1) && (physBitmap->pixmap == dest);
4164 #else
4165 descr.useShm = FALSE;
4166 #endif
4167 descr.dibpitch = dibSection.dsBm.bmWidthBytes;
4169 if (toDIB)
4171 TRACE("Copying from Pixmap to DIB bits\n");
4172 X11DRV_DIB_GetImageBits( &descr );
4174 else
4176 TRACE("Copying from DIB bits to Pixmap\n");
4177 X11DRV_DIB_SetImageBits( &descr );
4181 /***********************************************************************
4182 * X11DRV_DIB_CopyDIBSection
4184 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
4185 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
4186 DWORD width, DWORD height)
4188 DIBSECTION dib;
4189 X_PHYSBITMAP *physBitmap;
4190 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
4192 TRACE("(%p,%p,%d,%d,%d,%d,%d,%d)\n", physDevSrc->hdc, physDevDst->hdc,
4193 xSrc, ySrc, xDest, yDest, width, height);
4194 /* this function is meant as an optimization for BitBlt,
4195 * not to be called otherwise */
4196 physBitmap = physDevSrc->bitmap;
4197 if (!physBitmap || GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib ) != sizeof(dib))
4199 ERR("called for non-DIBSection!?\n");
4200 return;
4202 /* while BitBlt should already have made sure we only get
4203 * positive values, we should check for oversize values */
4204 if ((xSrc < dib.dsBm.bmWidth) &&
4205 (ySrc < dib.dsBm.bmHeight)) {
4206 if (xSrc + width > dib.dsBm.bmWidth)
4207 width = dib.dsBm.bmWidth - xSrc;
4208 if (ySrc + height > dib.dsBm.bmHeight)
4209 height = dib.dsBm.bmHeight - ySrc;
4210 /* if the source bitmap is 8bpp or less, we're supposed to use the
4211 * DC's palette for color conversion (not the DIB color table) */
4212 if (dib.dsBm.bmBitsPixel <= 8) {
4213 HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL );
4214 if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
4215 /* HACK: no palette has been set in the source DC,
4216 * use the DIB colormap instead - this is necessary in some
4217 * cases since we need to do depth conversion in some places
4218 * where real Windows can just copy data straight over */
4219 colorMap = physBitmap->colorMap;
4220 nColorMap = physBitmap->nColorMap;
4221 } else {
4222 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4223 dib.dsBm.bmBitsPixel,
4224 (BITMAPINFO*)&dib.dsBmih,
4225 &nColorMap );
4226 if (colorMap) aColorMap = TRUE;
4229 /* perform the copy */
4230 X11DRV_DIB_DoCopyDIBSection(physBitmap, FALSE, colorMap, nColorMap,
4231 physDevDst->drawable, physDevDst->gc, xSrc, ySrc,
4232 physDevDst->dc_rect.left + xDest, physDevDst->dc_rect.top + yDest,
4233 width, height);
4234 /* free color mapping */
4235 if (aColorMap)
4236 HeapFree(GetProcessHeap(), 0, colorMap);
4240 /***********************************************************************
4241 * X11DRV_DIB_DoUpdateDIBSection
4243 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
4245 BITMAP bitmap;
4247 GetObjectW( physBitmap->hbitmap, sizeof(bitmap), &bitmap );
4248 X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
4249 physBitmap->colorMap, physBitmap->nColorMap,
4250 physBitmap->pixmap, BITMAP_GC(physBitmap),
4251 0, 0, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
4254 /***********************************************************************
4255 * X11DRV_DIB_FaultHandler
4257 static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep )
4259 X_PHYSBITMAP *physBitmap = NULL;
4260 BOOL found = FALSE;
4261 BYTE *addr;
4262 struct list *ptr;
4264 if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
4265 return EXCEPTION_CONTINUE_SEARCH;
4267 addr = (BYTE *)ep->ExceptionRecord->ExceptionInformation[1];
4269 EnterCriticalSection(&dibs_cs);
4270 LIST_FOR_EACH( ptr, &dibs_list )
4272 physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry );
4273 if ((physBitmap->base <= addr) && (addr < physBitmap->base + physBitmap->size))
4275 found = TRUE;
4276 break;
4279 LeaveCriticalSection(&dibs_cs);
4281 if (!found) return EXCEPTION_CONTINUE_SEARCH;
4283 X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE );
4284 if (ep->ExceptionRecord->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT) {
4285 /* the app tried to write the DIB bits */
4286 X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE );
4287 } else {
4288 /* the app tried to read the DIB bits */
4289 X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE );
4291 X11DRV_DIB_Unlock( physBitmap, TRUE );
4293 return EXCEPTION_CONTINUE_EXECUTION;
4296 /***********************************************************************
4297 * X11DRV_DIB_Coerce
4299 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *physBitmap, INT req, BOOL lossy)
4301 INT ret = DIB_Status_None;
4303 if (!physBitmap->image) return ret; /* not a DIB section */
4304 EnterCriticalSection(&physBitmap->lock);
4305 ret = physBitmap->status;
4306 switch (req) {
4307 case DIB_Status_GdiMod:
4308 /* GDI access - request to draw on pixmap */
4309 switch (physBitmap->status)
4311 default:
4312 case DIB_Status_None:
4313 physBitmap->p_status = DIB_Status_GdiMod;
4314 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4315 break;
4317 case DIB_Status_GdiMod:
4318 TRACE("GdiMod requested in status GdiMod\n" );
4319 physBitmap->p_status = DIB_Status_GdiMod;
4320 break;
4322 case DIB_Status_InSync:
4323 TRACE("GdiMod requested in status InSync\n" );
4324 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4325 physBitmap->status = DIB_Status_GdiMod;
4326 physBitmap->p_status = DIB_Status_InSync;
4327 break;
4329 case DIB_Status_AppMod:
4330 TRACE("GdiMod requested in status AppMod\n" );
4331 if (!lossy) {
4332 /* make it readonly to avoid app changing data while we copy */
4333 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4334 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4336 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4337 physBitmap->p_status = DIB_Status_AppMod;
4338 physBitmap->status = DIB_Status_GdiMod;
4339 break;
4341 break;
4343 case DIB_Status_InSync:
4344 /* App access - request access to read DIB surface */
4345 /* (typically called from signal handler) */
4346 switch (physBitmap->status)
4348 default:
4349 case DIB_Status_None:
4350 /* shouldn't happen from signal handler */
4351 break;
4353 case DIB_Status_GdiMod:
4354 TRACE("InSync requested in status GdiMod\n" );
4355 if (!lossy) {
4356 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4357 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4359 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4360 physBitmap->status = DIB_Status_InSync;
4361 break;
4363 case DIB_Status_InSync:
4364 TRACE("InSync requested in status InSync\n" );
4365 /* shouldn't happen from signal handler */
4366 break;
4368 case DIB_Status_AppMod:
4369 TRACE("InSync requested in status AppMod\n" );
4370 /* no reason to do anything here, and this
4371 * shouldn't happen from signal handler */
4372 break;
4374 break;
4376 case DIB_Status_AppMod:
4377 /* App access - request access to write DIB surface */
4378 /* (typically called from signal handler) */
4379 switch (physBitmap->status)
4381 default:
4382 case DIB_Status_None:
4383 /* shouldn't happen from signal handler */
4384 break;
4386 case DIB_Status_GdiMod:
4387 TRACE("AppMod requested in status GdiMod\n" );
4388 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4389 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4390 physBitmap->status = DIB_Status_AppMod;
4391 break;
4393 case DIB_Status_InSync:
4394 TRACE("AppMod requested in status InSync\n" );
4395 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4396 physBitmap->status = DIB_Status_AppMod;
4397 break;
4399 case DIB_Status_AppMod:
4400 TRACE("AppMod requested in status AppMod\n" );
4401 /* shouldn't happen from signal handler */
4402 break;
4404 break;
4406 /* it is up to the caller to do the copy/conversion, probably
4407 * using the return value to decide where to copy from */
4409 LeaveCriticalSection(&physBitmap->lock);
4410 return ret;
4413 /***********************************************************************
4414 * X11DRV_DIB_Lock
4416 static INT X11DRV_DIB_Lock(X_PHYSBITMAP *physBitmap, INT req, BOOL lossy)
4418 INT ret = DIB_Status_None;
4420 if (!physBitmap->image) return ret; /* not a DIB section */
4421 TRACE("Locking %p from thread %04x\n", physBitmap->hbitmap, GetCurrentThreadId());
4422 EnterCriticalSection(&physBitmap->lock);
4423 ret = physBitmap->status;
4424 if (req != DIB_Status_None)
4425 X11DRV_DIB_Coerce(physBitmap, req, lossy);
4426 return ret;
4429 /***********************************************************************
4430 * X11DRV_DIB_Unlock
4432 static void X11DRV_DIB_Unlock(X_PHYSBITMAP *physBitmap, BOOL commit)
4434 if (!physBitmap->image) return; /* not a DIB section */
4435 switch (physBitmap->status)
4437 default:
4438 case DIB_Status_None:
4439 /* in case anyone is wondering, this is the "signal handler doesn't
4440 * work" case, where we always have to be ready for app access */
4441 if (commit) {
4442 switch (physBitmap->p_status)
4444 case DIB_Status_GdiMod:
4445 TRACE("Unlocking and syncing from GdiMod\n" );
4446 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4447 break;
4449 default:
4450 TRACE("Unlocking without needing to sync\n" );
4451 break;
4454 else TRACE("Unlocking with no changes\n");
4455 physBitmap->p_status = DIB_Status_None;
4456 break;
4458 case DIB_Status_GdiMod:
4459 TRACE("Unlocking in status GdiMod\n" );
4460 /* DIB was protected in Coerce */
4461 if (!commit) {
4462 /* no commit, revert to InSync if applicable */
4463 if ((physBitmap->p_status == DIB_Status_InSync) ||
4464 (physBitmap->p_status == DIB_Status_AppMod)) {
4465 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4466 physBitmap->status = DIB_Status_InSync;
4469 break;
4471 case DIB_Status_InSync:
4472 TRACE("Unlocking in status InSync\n" );
4473 /* DIB was already protected in Coerce */
4474 break;
4476 case DIB_Status_AppMod:
4477 TRACE("Unlocking in status AppMod\n" );
4478 /* DIB was already protected in Coerce */
4479 /* this case is ordinary only called from the signal handler,
4480 * so we don't bother to check for !commit */
4481 break;
4483 LeaveCriticalSection(&physBitmap->lock);
4484 TRACE("Unlocked %p\n", physBitmap->hbitmap);
4487 /***********************************************************************
4488 * X11DRV_CoerceDIBSection
4490 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4492 if (!physDev || !physDev->bitmap) return DIB_Status_None;
4493 return X11DRV_DIB_Coerce(physDev->bitmap, req, lossy);
4496 /***********************************************************************
4497 * X11DRV_LockDIBSection
4499 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4501 if (!physDev || !physDev->bitmap) return DIB_Status_None;
4502 return X11DRV_DIB_Lock(physDev->bitmap, req, lossy);
4505 /***********************************************************************
4506 * X11DRV_UnlockDIBSection
4508 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4510 if (!physDev || !physDev->bitmap) return;
4511 X11DRV_DIB_Unlock(physDev->bitmap, commit);
4515 #ifdef HAVE_LIBXXSHM
4516 /***********************************************************************
4517 * X11DRV_XShmErrorHandler
4520 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4522 return 1; /* FIXME: should check event contents */
4525 /***********************************************************************
4526 * X11DRV_XShmCreateImage
4529 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4530 XShmSegmentInfo* shminfo)
4532 XImage *image;
4534 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4535 if (image)
4537 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4538 IPC_CREAT|0700);
4539 if( shminfo->shmid != -1 )
4541 shminfo->shmaddr = shmat(shminfo->shmid, 0, 0);
4542 image->data = calloc(height, image->bytes_per_line);
4543 if( shminfo->shmaddr != (char*)-1 )
4545 BOOL ok;
4547 shminfo->readOnly = FALSE;
4548 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4549 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4550 XSync( gdi_display, False );
4551 if (X11DRV_check_error()) ok = FALSE;
4552 if (ok)
4554 shmctl(shminfo->shmid, IPC_RMID, 0);
4555 return image; /* Success! */
4557 /* An error occurred */
4558 shmdt(shminfo->shmaddr);
4560 shmctl(shminfo->shmid, IPC_RMID, 0);
4561 shminfo->shmid = -1;
4563 XFlush(gdi_display);
4564 XDestroyImage(image);
4565 image = NULL;
4567 return image;
4569 #endif /* HAVE_LIBXXSHM */
4572 /***********************************************************************
4573 * X11DRV_CreateDIBSection (X11DRV.@)
4575 HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
4576 const BITMAPINFO *bmi, UINT usage )
4578 X_PHYSBITMAP *physBitmap;
4579 DIBSECTION dib;
4580 #ifdef HAVE_LIBXXSHM
4581 int major, minor;
4582 Bool pixmaps;
4583 #endif
4585 if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
4586 physBitmap->status = DIB_Status_None;
4588 GetObjectW( hbitmap, sizeof(dib), &dib );
4590 /* create color map */
4591 if (dib.dsBm.bmBitsPixel <= 8)
4593 physBitmap->colorMap = X11DRV_DIB_BuildColorMap( physDev,
4594 usage, dib.dsBm.bmBitsPixel, bmi,
4595 &physBitmap->nColorMap );
4598 /* create pixmap and X image */
4599 wine_tsx11_lock();
4600 physBitmap->pixmap_depth = (dib.dsBm.bmBitsPixel == 1) ? 1 : screen_depth;
4602 #ifdef HAVE_LIBXXSHM
4603 physBitmap->shminfo.shmid = -1;
4604 if(!(XShmQueryVersion(gdi_display, &major, &minor, &pixmaps) && pixmaps &&
4605 (physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4606 physBitmap->pixmap_depth, &physBitmap->shminfo ))) )
4607 #endif
4608 physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4609 physBitmap->pixmap_depth );
4610 #ifdef HAVE_LIBXXSHM
4611 if (physBitmap->shminfo.shmid != -1)
4613 TRACE("Creating shared pixmap for bmp %p\n", physBitmap->hbitmap);
4614 physBitmap->pixmap = XShmCreatePixmap(gdi_display, root_window,
4615 physBitmap->shminfo.shmaddr, &physBitmap->shminfo,
4616 dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4617 physBitmap->pixmap_depth);
4618 } else
4619 #endif
4620 physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
4621 dib.dsBm.bmHeight, physBitmap->pixmap_depth );
4622 wine_tsx11_unlock();
4623 if (!physBitmap->pixmap || !physBitmap->image) return 0;
4625 /* install fault handler */
4626 InitializeCriticalSection( &physBitmap->lock );
4627 physBitmap->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": X_PHYSBITMAP.lock");
4629 physBitmap->base = dib.dsBm.bmBits;
4630 physBitmap->size = dib.dsBmih.biSizeImage;
4631 physBitmap->status = DIB_Status_AppMod;
4633 if (!dibs_handler)
4634 dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler );
4635 EnterCriticalSection( &dibs_cs );
4636 list_add_head( &dibs_list, &physBitmap->entry );
4637 LeaveCriticalSection( &dibs_cs );
4639 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4641 return hbitmap;
4644 /***********************************************************************
4645 * X11DRV_DIB_DeleteDIBSection
4647 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
4649 BOOL last;
4651 EnterCriticalSection( &dibs_cs );
4652 list_remove( &physBitmap->entry );
4653 last = list_empty( &dibs_list );
4654 LeaveCriticalSection( &dibs_cs );
4656 if (last)
4658 RemoveVectoredExceptionHandler( dibs_handler );
4659 dibs_handler = NULL;
4662 if (dib->dshSection)
4663 X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
4665 if (physBitmap->image)
4667 wine_tsx11_lock();
4668 #ifdef HAVE_LIBXXSHM
4669 if (physBitmap->shminfo.shmid != -1)
4671 XShmDetach( gdi_display, &(physBitmap->shminfo) );
4672 if(physBitmap->image->data) {
4673 free(physBitmap->image->data);
4674 physBitmap->image->data = NULL;
4676 XDestroyImage( physBitmap->image );
4677 shmdt( physBitmap->shminfo.shmaddr );
4678 physBitmap->shminfo.shmid = -1;
4680 else
4681 #endif
4682 XDestroyImage( physBitmap->image );
4683 wine_tsx11_unlock();
4686 HeapFree(GetProcessHeap(), 0, physBitmap->colorMap);
4687 physBitmap->lock.DebugInfo->Spare[0] = 0;
4688 DeleteCriticalSection(&physBitmap->lock);
4691 /***********************************************************************
4692 * SetDIBColorTable (X11DRV.@)
4694 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4696 DIBSECTION dib;
4697 UINT ret = 0;
4698 X_PHYSBITMAP *physBitmap = physDev->bitmap;
4700 if (!physBitmap) return 0;
4701 GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4703 if (physBitmap->colorMap && start < physBitmap->nColorMap) {
4704 UINT end = count + start;
4705 if (end > physBitmap->nColorMap) end = physBitmap->nColorMap;
4707 * Changing color table might change the mapping between
4708 * DIB colors and X11 colors and thus alter the visible state
4709 * of the bitmap object.
4712 * FIXME we need to recalculate the pen, brush, text and bkgnd pixels here,
4713 * at least for a 1 bpp dibsection
4715 /* X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod, FALSE ); */
4716 X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
4717 dib.dsBm.bmBitsPixel,
4718 TRUE, colors, start, end );
4719 /* X11DRV_DIB_Unlock( physBitmap, TRUE ); */
4720 ret = end - start;
4722 return ret;
4726 /***********************************************************************
4727 * X11DRV_DIB_CreateDIBFromBitmap
4729 * Allocates a packed DIB and copies the bitmap data into it.
4731 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4733 BITMAP bmp;
4734 HGLOBAL hPackedDIB;
4735 LPBYTE pPackedDIB;
4736 LPBITMAPINFOHEADER pbmiHeader;
4737 unsigned int cDataSize, cPackedSize, OffsetBits;
4738 int nLinesCopied;
4740 if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4743 * A packed DIB contains a BITMAPINFO structure followed immediately by
4744 * an optional color palette and the pixel data.
4747 /* Calculate the size of the packed DIB */
4748 cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4749 cPackedSize = sizeof(BITMAPINFOHEADER)
4750 + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4751 + cDataSize;
4752 /* Get the offset to the bits */
4753 OffsetBits = cPackedSize - cDataSize;
4755 /* Allocate the packed DIB */
4756 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4757 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4758 cPackedSize );
4759 if ( !hPackedDIB )
4761 WARN("Could not allocate packed DIB!\n");
4762 return 0;
4765 /* A packed DIB starts with a BITMAPINFOHEADER */
4766 pPackedDIB = GlobalLock(hPackedDIB);
4767 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4769 /* Init the BITMAPINFOHEADER */
4770 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4771 pbmiHeader->biWidth = bmp.bmWidth;
4772 pbmiHeader->biHeight = bmp.bmHeight;
4773 pbmiHeader->biPlanes = 1;
4774 pbmiHeader->biBitCount = bmp.bmBitsPixel;
4775 pbmiHeader->biCompression = BI_RGB;
4776 pbmiHeader->biSizeImage = 0;
4777 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4778 pbmiHeader->biClrUsed = 0;
4779 pbmiHeader->biClrImportant = 0;
4781 /* Retrieve the DIB bits from the bitmap and fill in the
4782 * DIB color table if present */
4784 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
4785 hBmp, /* Handle to bitmap */
4786 0, /* First scan line to set in dest bitmap */
4787 bmp.bmHeight, /* Number of scan lines to copy */
4788 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
4789 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4790 0); /* RGB or palette index */
4791 GlobalUnlock(hPackedDIB);
4793 /* Cleanup if GetDIBits failed */
4794 if (nLinesCopied != bmp.bmHeight)
4796 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4797 GlobalFree(hPackedDIB);
4798 hPackedDIB = 0;
4800 return hPackedDIB;
4804 /**************************************************************************
4805 * X11DRV_DIB_CreateDIBFromPixmap
4807 * Allocates a packed DIB and copies the Pixmap data into it.
4808 * The Pixmap passed in is deleted after the conversion.
4810 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc)
4812 HDC hdcMem;
4813 X_PHYSBITMAP *physBitmap;
4814 HBITMAP hBmp = 0, old;
4815 HGLOBAL hPackedDIB = 0;
4816 Window root;
4817 int x,y; /* Unused */
4818 unsigned border_width; /* Unused */
4819 unsigned int depth, width, height;
4821 /* Get the Pixmap dimensions and bit depth */
4822 wine_tsx11_lock();
4823 if (!XGetGeometry(gdi_display, pixmap, &root, &x, &y, &width, &height,
4824 &border_width, &depth)) depth = 0;
4825 wine_tsx11_unlock();
4826 if (!depth) return 0;
4828 TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4829 width, height, depth);
4832 * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4833 * and make it a container for the pixmap passed.
4835 hBmp = CreateBitmap( width, height, 1, depth, NULL );
4837 /* force bitmap to be owned by a screen DC */
4838 hdcMem = CreateCompatibleDC( hdc );
4839 old = SelectObject( hdcMem, hBmp );
4841 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4843 wine_tsx11_lock();
4844 if (physBitmap->pixmap) XFreePixmap( gdi_display, physBitmap->pixmap );
4845 physBitmap->pixmap = pixmap;
4846 wine_tsx11_unlock();
4848 SelectObject( hdcMem, old );
4849 DeleteDC( hdcMem );
4852 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4853 * A packed DIB contains a BITMAPINFO structure followed immediately by
4854 * an optional color palette and the pixel data.
4856 hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4858 /* We can now get rid of the HBITMAP wrapper we created earlier.
4859 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4861 DeleteObject(hBmp);
4863 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4864 return hPackedDIB;
4868 /**************************************************************************
4869 * X11DRV_DIB_CreatePixmapFromDIB
4871 * Creates a Pixmap from a packed DIB
4873 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4875 Pixmap pixmap;
4876 X_PHYSBITMAP *physBitmap;
4877 HBITMAP hBmp;
4878 LPBITMAPINFO pbmi;
4880 /* Create a DDB from the DIB */
4882 pbmi = GlobalLock(hPackedDIB);
4883 hBmp = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
4884 (LPBYTE)pbmi + X11DRV_DIB_BitmapInfoSize( pbmi, DIB_RGB_COLORS ),
4885 pbmi, DIB_RGB_COLORS);
4886 GlobalUnlock(hPackedDIB);
4888 /* clear the physBitmap so that we can steal its pixmap */
4889 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4890 pixmap = physBitmap->pixmap;
4891 physBitmap->pixmap = 0;
4893 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4894 DeleteObject(hBmp);
4896 TRACE("Returning Pixmap %ld\n", pixmap);
4897 return pixmap;