winex11.drv: Mark some fall-throughs in switch statements.
[wine.git] / dlls / winex11.drv / dib.c
bloba1ce9bb54116c8afad880fde4b8f9781f13d14d8
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"
22 #include "wine/port.h"
24 #include <X11/Xlib.h>
25 #ifdef HAVE_LIBXXSHM
26 #include <X11/extensions/XShm.h>
27 # ifdef HAVE_SYS_SHM_H
28 # include <sys/shm.h>
29 # endif
30 # ifdef HAVE_SYS_IPC_H
31 # include <sys/ipc.h>
32 # endif
33 #endif /* defined(HAVE_LIBXXSHM) */
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "windef.h"
39 #include "winbase.h"
40 #include "wingdi.h"
41 #include "x11drv.h"
42 #include "wine/exception.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
47 static struct list dibs_list = LIST_INIT(dibs_list);
49 static CRITICAL_SECTION dibs_cs;
50 static CRITICAL_SECTION_DEBUG dibs_cs_debug =
52 0, 0, &dibs_cs,
53 { &dibs_cs_debug.ProcessLocksList, &dibs_cs_debug.ProcessLocksList },
54 0, 0, { (DWORD_PTR)(__FILE__ ": dibs_cs") }
56 static CRITICAL_SECTION dibs_cs = { &dibs_cs_debug, -1, 0, 0, 0, 0 };
58 static PVOID dibs_handler;
60 static int ximageDepthTable[32];
62 /* This structure holds the arguments for DIB_SetImageBits() */
63 typedef struct
65 X11DRV_PDEVICE *physDev;
66 LPCVOID bits;
67 XImage *image;
68 PALETTEENTRY *palentry;
69 int lines;
70 DWORD infoWidth;
71 WORD depth;
72 WORD infoBpp;
73 WORD compression;
74 ColorShifts *shifts;
75 RGBQUAD *colorMap;
76 int nColorMap;
77 Drawable drawable;
78 GC gc;
79 int xSrc;
80 int ySrc;
81 int xDest;
82 int yDest;
83 int width;
84 int height;
85 DWORD rMask;
86 DWORD gMask;
87 DWORD bMask;
88 enum x11drv_shm_mode shm_mode;
89 int dibpitch;
90 DWORD sizeImage;
91 X_PHYSBITMAP *physBitmap;
92 } X11DRV_DIB_IMAGEBITS_DESCR;
95 enum Rle_EscapeCodes
97 RLE_EOL = 0, /* End of line */
98 RLE_END = 1, /* End of bitmap */
99 RLE_DELTA = 2 /* Delta */
103 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *,INT);
106 Some of the following helper functions are duplicated in
107 dlls/gdi/dib.c
110 /***********************************************************************
111 * DIB_DoProtectDIBSection
113 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
115 DWORD old_prot;
117 VirtualProtect(physBitmap->base, physBitmap->size, new_prot, &old_prot);
118 TRACE("Changed protection from %d to %d\n", old_prot, new_prot);
121 /***********************************************************************
122 * X11DRV_DIB_GetXImageWidthBytes
124 * Return the width of an X image in bytes
126 static inline int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
128 if (!depth || depth > 32) goto error;
130 if (!ximageDepthTable[depth-1])
132 XImage *testimage = XCreateImage( gdi_display, visual, depth,
133 ZPixmap, 0, NULL, 1, 1, 32, 20 );
134 if (testimage)
136 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
137 XDestroyImage( testimage );
139 else ximageDepthTable[depth-1] = -1;
141 if (ximageDepthTable[depth-1] != -1)
142 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
144 error:
145 WARN( "(%d): Unsupported depth\n", depth );
146 return 4 * width;
150 /***********************************************************************
151 * X11DRV_DIB_GetDIBWidthBytes
153 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
155 static int X11DRV_DIB_GetDIBWidthBytes( int width, int depth )
157 return ((width * depth + 31) / 8) & ~3;
161 /***********************************************************************
162 * bitmap_info_size
164 * Return the size of the bitmap info structure including color table.
166 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
168 unsigned int colors, size, masks = 0;
170 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
172 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
173 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
174 return sizeof(BITMAPCOREHEADER) + colors *
175 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
177 else /* assume BITMAPINFOHEADER */
179 colors = info->bmiHeader.biClrUsed;
180 if (!colors && (info->bmiHeader.biBitCount <= 8))
181 colors = 1 << info->bmiHeader.biBitCount;
182 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
183 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
184 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
189 /***********************************************************************
190 * X11DRV_DIB_CreateXImage
192 * Create an X image.
194 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
196 int width_bytes;
197 XImage *image = NULL;
198 void *data;
200 wine_tsx11_lock();
201 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
202 data = HeapAlloc( GetProcessHeap(), 0, height * width_bytes );
203 if (data) image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
204 data, width, height, 32, width_bytes );
205 if (!image) HeapFree( GetProcessHeap(), 0, data );
206 wine_tsx11_unlock();
207 return image;
211 /***********************************************************************
212 * X11DRV_DIB_DestroyXImage
214 * Destroy an X image created with X11DRV_DIB_CreateXImage.
216 void X11DRV_DIB_DestroyXImage( XImage *image )
218 HeapFree( GetProcessHeap(), 0, image->data );
219 image->data = NULL;
220 wine_tsx11_lock();
221 XDestroyImage( image );
222 wine_tsx11_unlock();
226 /***********************************************************************
227 * X11DRV_DIB_GetColorCount
229 * Computes the number of colors for the bitmap palette.
230 * Should not be called for a >8-bit deep bitmap.
232 static unsigned int X11DRV_DIB_GetColorCount(const BITMAPINFO *info)
234 unsigned int colors = min( info->bmiHeader.biClrUsed, 256 );
235 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
236 return colors;
240 static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
242 return (c1.rgbRed * c1.rgbRed + c1.rgbGreen * c1.rgbGreen + c1.rgbBlue * c1.rgbBlue) >
243 (c2.rgbRed * c2.rgbRed + c2.rgbGreen * c2.rgbGreen + c2.rgbBlue * c2.rgbBlue);
246 /***********************************************************************
247 * X11DRV_DIB_GenColorMap
249 * Fills the color map of a bitmap palette. Should not be called
250 * for a >8-bit deep bitmap.
252 static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
253 WORD coloruse, WORD depth, const void *colorPtr, int start, int end )
255 int i;
257 if (coloruse == DIB_RGB_COLORS)
259 const RGBQUAD * rgb = colorPtr;
261 if (depth == 1) /* Monochrome */
263 BOOL invert = FALSE;
264 RGBQUAD table[2];
266 if (GetDIBColorTable( physDev->dev.hdc, 0, 2, table ) == 2)
267 invert = !colour_is_brighter(table[1], table[0]);
269 for (i = start; i < end; i++, rgb++)
270 colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
271 rgb->rgbBlue > 255*3/2 && !invert) ||
272 (rgb->rgbRed + rgb->rgbGreen +
273 rgb->rgbBlue <= 255*3/2 && invert));
275 else
276 for (i = start; i < end; i++, rgb++)
277 colorMapping[i] = X11DRV_PALETTE_LookupPixel(physDev->color_shifts, RGB(rgb->rgbRed,
278 rgb->rgbGreen,
279 rgb->rgbBlue));
281 else /* DIB_PAL_COLORS */
283 const WORD * index = colorPtr;
285 for (i = start; i < end; i++, index++)
286 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
289 return colorMapping;
292 /***********************************************************************
293 * X11DRV_DIB_BuildColorMap
295 * Build the color map from the bitmap palette. Should not be called
296 * for a >8-bit deep bitmap.
298 static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
299 const BITMAPINFO *info, int *nColors )
301 const void *colorPtr;
302 int *colorMapping;
305 *nColors = X11DRV_DIB_GetColorCount(info);
306 if (!*nColors) return NULL;
308 colorPtr = (const BYTE*)info + (WORD)info->bmiHeader.biSize;
309 if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, *nColors * sizeof(int) )))
310 return NULL;
312 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
313 colorPtr, 0, *nColors);
316 /***********************************************************************
317 * X11DRV_DIB_MapColor
319 static int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
321 int color;
323 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
324 return oldcol;
326 for (color = 0; color < nPhysMap; color++)
327 if (physMap[color] == phys)
328 return color;
330 WARN("Strange color %08x\n", phys);
331 return 0;
335 /*********************************************************************
336 * X11DRV_DIB_GetNearestIndex
338 * Helper for X11DRV_DIB_GetDIBits.
339 * Returns the nearest colour table index for a given RGB.
340 * Nearest is defined by minimizing the sum of the squares.
342 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
344 INT i, best = -1, diff, bestdiff = -1;
345 RGBQUAD *color;
347 for(color = colormap, i = 0; i < numColors; color++, i++) {
348 diff = (r - color->rgbRed) * (r - color->rgbRed) +
349 (g - color->rgbGreen) * (g - color->rgbGreen) +
350 (b - color->rgbBlue) * (b - color->rgbBlue);
351 if(diff == 0)
352 return i;
353 if(best == -1 || diff < bestdiff) {
354 best = i;
355 bestdiff = diff;
358 return best;
360 /*********************************************************************
361 * X11DRV_DIB_MaskToShift
363 * Helper for X11DRV_DIB_GetDIBits.
364 * Returns the by how many bits to shift a given color so that it is
365 * in the proper position.
367 INT X11DRV_DIB_MaskToShift(DWORD mask)
369 int shift;
371 if (mask==0)
372 return 0;
374 shift=0;
375 while ((mask&1)==0) {
376 mask>>=1;
377 shift++;
379 return shift;
382 /***********************************************************************
383 * X11DRV_DIB_CheckMask
385 * Check RGB mask if it is either 0 or matches visual's mask.
387 static inline int X11DRV_DIB_CheckMask(int red_mask, int green_mask, int blue_mask)
389 return ( red_mask == 0 && green_mask == 0 && blue_mask == 0 ) ||
390 ( red_mask == visual->red_mask && green_mask == visual->green_mask &&
391 blue_mask == visual->blue_mask );
394 /***********************************************************************
395 * X11DRV_DIB_SetImageBits_1
397 * SetDIBits for a 1-bit deep DIB.
399 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
400 DWORD srcwidth, DWORD dstwidth, int left,
401 int *colors, XImage *bmpImage, int linebytes)
403 int h, width;
404 const BYTE* srcbyte;
405 BYTE srcval, extra;
406 DWORD i, x;
408 if (lines < 0 ) {
409 lines = -lines;
410 srcbits = srcbits + linebytes * (lines - 1);
411 linebytes = -linebytes;
414 if ((extra = (left & 7)) != 0) {
415 left &= ~7;
416 dstwidth += extra;
418 srcbits += left >> 3;
419 width = min(srcwidth, dstwidth);
421 /* ==== pal 1 dib -> any bmp format ==== */
422 for (h = lines-1; h >=0; h--) {
423 srcbyte=srcbits;
424 for (i = width/8, x = left; i > 0; i--) {
425 srcval=*srcbyte++;
426 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
427 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
428 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
429 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
430 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
431 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
432 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
433 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
435 if (width % 8){
436 srcval=*srcbyte;
437 switch (width & 7)
439 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
440 /* fall through */
441 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
442 /* fall through */
443 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
444 /* fall through */
445 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
446 /* fall through */
447 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
448 /* fall through */
449 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
450 /* fall through */
451 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
454 srcbits += linebytes;
458 /***********************************************************************
459 * X11DRV_DIB_GetImageBits_1
461 * GetDIBits for a 1-bit deep DIB.
463 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
464 DWORD dstwidth, DWORD srcwidth,
465 RGBQUAD *colors, PALETTEENTRY *srccolors,
466 XImage *bmpImage, int linebytes )
468 DWORD x;
469 int h, width = min(dstwidth, srcwidth);
471 if (lines < 0 ) {
472 lines = -lines;
473 dstbits = dstbits + linebytes * (lines - 1);
474 linebytes = -linebytes;
477 switch (bmpImage->depth)
479 case 1:
480 case 4:
481 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
482 && srccolors) {
483 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
484 BYTE* dstbyte;
486 for (h=lines-1; h>=0; h--) {
487 BYTE dstval;
488 dstbyte=dstbits;
489 dstval=0;
490 for (x=0; x<width; x++) {
491 PALETTEENTRY srcval;
492 srcval=srccolors[XGetPixel(bmpImage, x, h)];
493 dstval|=(X11DRV_DIB_GetNearestIndex
494 (colors, 2,
495 srcval.peRed,
496 srcval.peGreen,
497 srcval.peBlue) << (7 - (x & 7)));
498 if ((x&7)==7) {
499 *dstbyte++=dstval;
500 dstval=0;
503 if ((width&7)!=0) {
504 *dstbyte++=dstval;
506 /* pad with 0 to DWORD alignment */
507 for (x = (x+7)&~7; x < ((width + 31) & ~31); x+=8)
508 *dstbyte++ = 0;
509 dstbits += linebytes;
511 } else {
512 goto notsupported;
514 break;
516 case 8:
517 if (X11DRV_DIB_CheckMask(bmpImage->red_mask, bmpImage->green_mask, bmpImage->blue_mask)
518 && srccolors) {
519 /* ==== pal 8 bmp -> pal 1 dib ==== */
520 const void* srcbits;
521 const BYTE* srcpixel;
522 BYTE* dstbyte;
524 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
526 for (h=0; h<lines; h++) {
527 BYTE dstval;
528 srcpixel=srcbits;
529 dstbyte=dstbits;
530 dstval=0;
531 for (x=0; x<width; x++) {
532 PALETTEENTRY srcval;
533 srcval=srccolors[*srcpixel++];
534 dstval|=(X11DRV_DIB_GetNearestIndex
535 (colors, 2,
536 srcval.peRed,
537 srcval.peGreen,
538 srcval.peBlue) << (7-(x&7)) );
539 if ((x&7)==7) {
540 *dstbyte++=dstval;
541 dstval=0;
544 if ((width&7)!=0) {
545 *dstbyte=dstval;
547 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
548 dstbits += linebytes;
550 } else {
551 goto notsupported;
553 break;
555 case 15:
556 case 16:
558 const void* srcbits;
559 const WORD* srcpixel;
560 BYTE* dstbyte;
562 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
564 if (bmpImage->green_mask==0x03e0) {
565 if (bmpImage->red_mask==0x7c00) {
566 /* ==== rgb 555 bmp -> pal 1 dib ==== */
567 for (h=0; h<lines; h++) {
568 BYTE dstval;
569 srcpixel=srcbits;
570 dstbyte=dstbits;
571 dstval=0;
572 for (x=0; x<width; x++) {
573 WORD srcval;
574 srcval=*srcpixel++;
575 dstval|=(X11DRV_DIB_GetNearestIndex
576 (colors, 2,
577 ((srcval >> 7) & 0xf8) | /* r */
578 ((srcval >> 12) & 0x07),
579 ((srcval >> 2) & 0xf8) | /* g */
580 ((srcval >> 7) & 0x07),
581 ((srcval << 3) & 0xf8) | /* b */
582 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
583 if ((x&7)==7) {
584 *dstbyte++=dstval;
585 dstval=0;
588 if ((width&7)!=0) {
589 *dstbyte=dstval;
591 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
592 dstbits += linebytes;
594 } else if (bmpImage->blue_mask==0x7c00) {
595 /* ==== bgr 555 bmp -> pal 1 dib ==== */
596 for (h=0; h<lines; h++) {
597 WORD dstval;
598 srcpixel=srcbits;
599 dstbyte=dstbits;
600 dstval=0;
601 for (x=0; x<width; x++) {
602 BYTE srcval;
603 srcval=*srcpixel++;
604 dstval|=(X11DRV_DIB_GetNearestIndex
605 (colors, 2,
606 ((srcval << 3) & 0xf8) | /* r */
607 ((srcval >> 2) & 0x07),
608 ((srcval >> 2) & 0xf8) | /* g */
609 ((srcval >> 7) & 0x07),
610 ((srcval >> 7) & 0xf8) | /* b */
611 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
612 if ((x&7)==7) {
613 *dstbyte++=dstval;
614 dstval=0;
617 if ((width&7)!=0) {
618 *dstbyte=dstval;
620 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
621 dstbits += linebytes;
623 } else {
624 goto notsupported;
626 } else if (bmpImage->green_mask==0x07e0) {
627 if (bmpImage->red_mask==0xf800) {
628 /* ==== rgb 565 bmp -> pal 1 dib ==== */
629 for (h=0; h<lines; h++) {
630 BYTE dstval;
631 srcpixel=srcbits;
632 dstbyte=dstbits;
633 dstval=0;
634 for (x=0; x<width; x++) {
635 WORD srcval;
636 srcval=*srcpixel++;
637 dstval|=(X11DRV_DIB_GetNearestIndex
638 (colors, 2,
639 ((srcval >> 8) & 0xf8) | /* r */
640 ((srcval >> 13) & 0x07),
641 ((srcval >> 3) & 0xfc) | /* g */
642 ((srcval >> 9) & 0x03),
643 ((srcval << 3) & 0xf8) | /* b */
644 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
645 if ((x&7)==7) {
646 *dstbyte++=dstval;
647 dstval=0;
650 if ((width&7)!=0) {
651 *dstbyte=dstval;
653 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
654 dstbits += linebytes;
656 } else if (bmpImage->blue_mask==0xf800) {
657 /* ==== bgr 565 bmp -> pal 1 dib ==== */
658 for (h=0; h<lines; h++) {
659 BYTE dstval;
660 srcpixel=srcbits;
661 dstbyte=dstbits;
662 dstval=0;
663 for (x=0; x<width; x++) {
664 WORD srcval;
665 srcval=*srcpixel++;
666 dstval|=(X11DRV_DIB_GetNearestIndex
667 (colors, 2,
668 ((srcval << 3) & 0xf8) | /* r */
669 ((srcval >> 2) & 0x07),
670 ((srcval >> 3) & 0xfc) | /* g */
671 ((srcval >> 9) & 0x03),
672 ((srcval >> 8) & 0xf8) | /* b */
673 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
674 if ((x&7)==7) {
675 *dstbyte++=dstval;
676 dstval=0;
679 if ((width&7)!=0) {
680 *dstbyte=dstval;
682 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
683 dstbits += linebytes;
685 } else {
686 goto notsupported;
688 } else {
689 goto notsupported;
692 break;
694 case 24:
695 case 32:
697 const void* srcbits;
698 const BYTE *srcbyte;
699 BYTE* dstbyte;
700 int bytes_per_pixel;
702 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
703 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
705 if (bmpImage->green_mask!=0x00ff00 ||
706 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
707 goto notsupported;
708 } else if (bmpImage->blue_mask==0xff) {
709 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
710 for (h=0; h<lines; h++) {
711 BYTE dstval;
712 srcbyte=srcbits;
713 dstbyte=dstbits;
714 dstval=0;
715 for (x=0; x<width; x++) {
716 dstval|=(X11DRV_DIB_GetNearestIndex
717 (colors, 2,
718 srcbyte[2],
719 srcbyte[1],
720 srcbyte[0]) << (7-(x&7)) );
721 srcbyte+=bytes_per_pixel;
722 if ((x&7)==7) {
723 *dstbyte++=dstval;
724 dstval=0;
727 if ((width&7)!=0) {
728 *dstbyte=dstval;
730 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
731 dstbits += linebytes;
733 } else {
734 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
735 for (h=0; h<lines; h++) {
736 BYTE dstval;
737 srcbyte=srcbits;
738 dstbyte=dstbits;
739 dstval=0;
740 for (x=0; x<width; x++) {
741 dstval|=(X11DRV_DIB_GetNearestIndex
742 (colors, 2,
743 srcbyte[0],
744 srcbyte[1],
745 srcbyte[2]) << (7-(x&7)) );
746 srcbyte+=bytes_per_pixel;
747 if ((x&7)==7) {
748 *dstbyte++=dstval;
749 dstval=0;
752 if ((width&7)!=0) {
753 *dstbyte=dstval;
755 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
756 dstbits += linebytes;
760 break;
762 default:
763 notsupported:
765 BYTE* dstbyte;
766 BYTE neg = 0;
767 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
769 /* ==== any bmp format -> pal 1 dib ==== */
770 if ((unsigned)colors[0].rgbRed+colors[0].rgbGreen+colors[0].rgbBlue >=
771 (unsigned)colors[1].rgbRed+colors[1].rgbGreen+colors[1].rgbBlue )
772 neg = 1;
774 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB, "
775 "%s color mapping\n",
776 bmpImage->bits_per_pixel, bmpImage->red_mask,
777 bmpImage->green_mask, bmpImage->blue_mask,
778 neg?"negative":"direct" );
780 for (h=lines-1; h>=0; h--) {
781 BYTE dstval;
782 dstbyte=dstbits;
783 dstval=0;
784 for (x=0; x<width; x++) {
785 dstval|=((XGetPixel( bmpImage, x, h) >= white) ^ neg) << (7 - (x&7));
786 if ((x&7)==7) {
787 *dstbyte++=dstval;
788 dstval=0;
791 if ((width&7)!=0) {
792 *dstbyte=dstval;
794 dstbits += linebytes;
797 break;
801 /***********************************************************************
802 * X11DRV_DIB_SetImageBits_4
804 * SetDIBits for a 4-bit deep DIB.
806 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
807 DWORD srcwidth, DWORD dstwidth, int left,
808 int *colors, XImage *bmpImage, int linebytes)
810 int h, width;
811 const BYTE* srcbyte;
812 DWORD i, x;
814 if (lines < 0 ) {
815 lines = -lines;
816 srcbits = srcbits + linebytes * (lines - 1);
817 linebytes = -linebytes;
820 if (left & 1) {
821 left--;
822 dstwidth++;
824 srcbits += left >> 1;
825 width = min(srcwidth, dstwidth);
827 /* ==== pal 4 dib -> any bmp format ==== */
828 for (h = lines-1; h >= 0; h--) {
829 srcbyte=srcbits;
830 for (i = width/2, x = left; i > 0; i--) {
831 BYTE srcval=*srcbyte++;
832 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
833 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
835 if (width & 1)
836 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
837 srcbits += linebytes;
843 /***********************************************************************
844 * X11DRV_DIB_GetImageBits_4
846 * GetDIBits for a 4-bit deep DIB.
848 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
849 DWORD srcwidth, DWORD dstwidth,
850 RGBQUAD *colors, PALETTEENTRY *srccolors,
851 XImage *bmpImage, int linebytes )
853 DWORD x;
854 int h, width = min(srcwidth, dstwidth);
856 if (lines < 0 )
858 lines = -lines;
859 dstbits = dstbits + ( linebytes * (lines-1) );
860 linebytes = -linebytes;
863 switch (bmpImage->depth) {
864 case 1:
865 case 4:
866 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
867 && srccolors) {
868 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
869 BYTE* dstbyte;
871 for (h = lines-1; h >= 0; h--) {
872 BYTE dstval;
873 dstbyte=dstbits;
874 dstval=0;
875 for (x = 0; x < width; x++) {
876 PALETTEENTRY srcval;
877 srcval=srccolors[XGetPixel(bmpImage, x, h)];
878 dstval|=(X11DRV_DIB_GetNearestIndex
879 (colors, 16,
880 srcval.peRed,
881 srcval.peGreen,
882 srcval.peBlue) << (4-((x&1)<<2)));
883 if ((x&1)==1) {
884 *dstbyte++=dstval;
885 dstval=0;
888 if ((width&1)!=0) {
889 *dstbyte=dstval;
891 dstbits += linebytes;
893 } else {
894 goto notsupported;
896 break;
898 case 8:
899 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
900 && srccolors) {
901 /* ==== pal 8 bmp -> pal 4 dib ==== */
902 const void* srcbits;
903 const BYTE *srcpixel;
904 BYTE* dstbyte;
906 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
907 for (h=0; h<lines; h++) {
908 BYTE dstval;
909 srcpixel=srcbits;
910 dstbyte=dstbits;
911 dstval=0;
912 for (x=0; x<width; x++) {
913 PALETTEENTRY srcval;
914 srcval = srccolors[*srcpixel++];
915 dstval|=(X11DRV_DIB_GetNearestIndex
916 (colors, 16,
917 srcval.peRed,
918 srcval.peGreen,
919 srcval.peBlue) << (4*(1-(x&1))) );
920 if ((x&1)==1) {
921 *dstbyte++=dstval;
922 dstval=0;
925 if ((width&1)!=0) {
926 *dstbyte=dstval;
928 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
929 dstbits += linebytes;
931 } else {
932 goto notsupported;
934 break;
936 case 15:
937 case 16:
939 const void* srcbits;
940 const WORD* srcpixel;
941 BYTE* dstbyte;
943 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
945 if (bmpImage->green_mask==0x03e0) {
946 if (bmpImage->red_mask==0x7c00) {
947 /* ==== rgb 555 bmp -> pal 4 dib ==== */
948 for (h=0; h<lines; h++) {
949 BYTE dstval;
950 srcpixel=srcbits;
951 dstbyte=dstbits;
952 dstval=0;
953 for (x=0; x<width; x++) {
954 WORD srcval;
955 srcval=*srcpixel++;
956 dstval|=(X11DRV_DIB_GetNearestIndex
957 (colors, 16,
958 ((srcval >> 7) & 0xf8) | /* r */
959 ((srcval >> 12) & 0x07),
960 ((srcval >> 2) & 0xf8) | /* g */
961 ((srcval >> 7) & 0x07),
962 ((srcval << 3) & 0xf8) | /* b */
963 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
964 if ((x&1)==1) {
965 *dstbyte++=dstval;
966 dstval=0;
969 if ((width&1)!=0) {
970 *dstbyte=dstval;
972 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
973 dstbits += linebytes;
975 } else if (bmpImage->blue_mask==0x7c00) {
976 /* ==== bgr 555 bmp -> pal 4 dib ==== */
977 for (h=0; h<lines; h++) {
978 WORD dstval;
979 srcpixel=srcbits;
980 dstbyte=dstbits;
981 dstval=0;
982 for (x=0; x<width; x++) {
983 WORD srcval;
984 srcval=*srcpixel++;
985 dstval|=(X11DRV_DIB_GetNearestIndex
986 (colors, 16,
987 ((srcval << 3) & 0xf8) | /* r */
988 ((srcval >> 2) & 0x07),
989 ((srcval >> 2) & 0xf8) | /* g */
990 ((srcval >> 7) & 0x07),
991 ((srcval >> 7) & 0xf8) | /* b */
992 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
993 if ((x&1)==1) {
994 *dstbyte++=dstval;
995 dstval=0;
998 if ((width&1)!=0) {
999 *dstbyte=dstval;
1001 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1002 dstbits += linebytes;
1004 } else {
1005 goto notsupported;
1007 } else if (bmpImage->green_mask==0x07e0) {
1008 if (bmpImage->red_mask==0xf800) {
1009 /* ==== rgb 565 bmp -> pal 4 dib ==== */
1010 for (h=0; h<lines; h++) {
1011 BYTE dstval;
1012 srcpixel=srcbits;
1013 dstbyte=dstbits;
1014 dstval=0;
1015 for (x=0; x<width; x++) {
1016 WORD srcval;
1017 srcval=*srcpixel++;
1018 dstval|=(X11DRV_DIB_GetNearestIndex
1019 (colors, 16,
1020 ((srcval >> 8) & 0xf8) | /* r */
1021 ((srcval >> 13) & 0x07),
1022 ((srcval >> 3) & 0xfc) | /* g */
1023 ((srcval >> 9) & 0x03),
1024 ((srcval << 3) & 0xf8) | /* b */
1025 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1026 if ((x&1)==1) {
1027 *dstbyte++=dstval;
1028 dstval=0;
1031 if ((width&1)!=0) {
1032 *dstbyte=dstval;
1034 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1035 dstbits += linebytes;
1037 } else if (bmpImage->blue_mask==0xf800) {
1038 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1039 for (h=0; h<lines; h++) {
1040 WORD dstval;
1041 srcpixel=srcbits;
1042 dstbyte=dstbits;
1043 dstval=0;
1044 for (x=0; x<width; x++) {
1045 WORD srcval;
1046 srcval=*srcpixel++;
1047 dstval|=(X11DRV_DIB_GetNearestIndex
1048 (colors, 16,
1049 ((srcval << 3) & 0xf8) | /* r */
1050 ((srcval >> 2) & 0x07),
1051 ((srcval >> 3) & 0xfc) | /* g */
1052 ((srcval >> 9) & 0x03),
1053 ((srcval >> 8) & 0xf8) | /* b */
1054 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1055 if ((x&1)==1) {
1056 *dstbyte++=dstval;
1057 dstval=0;
1060 if ((width&1)!=0) {
1061 *dstbyte=dstval;
1063 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1064 dstbits += linebytes;
1066 } else {
1067 goto notsupported;
1069 } else {
1070 goto notsupported;
1073 break;
1075 case 24:
1076 if (bmpImage->bits_per_pixel==24) {
1077 const void* srcbits;
1078 const BYTE *srcbyte;
1079 BYTE* dstbyte;
1081 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1083 if (bmpImage->green_mask!=0x00ff00 ||
1084 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1085 goto notsupported;
1086 } else if (bmpImage->blue_mask==0xff) {
1087 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1088 for (h=0; h<lines; h++) {
1089 srcbyte=srcbits;
1090 dstbyte=dstbits;
1091 for (x=0; x<width/2; x++) {
1092 /* Do 2 pixels at a time */
1093 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1094 (colors, 16,
1095 srcbyte[2],
1096 srcbyte[1],
1097 srcbyte[0]) << 4) |
1098 X11DRV_DIB_GetNearestIndex
1099 (colors, 16,
1100 srcbyte[5],
1101 srcbyte[4],
1102 srcbyte[3]);
1103 srcbyte+=6;
1105 if (width&1) {
1106 /* And then the odd pixel */
1107 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1108 (colors, 16,
1109 srcbyte[2],
1110 srcbyte[1],
1111 srcbyte[0]) << 4);
1113 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1114 dstbits += linebytes;
1116 } else {
1117 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1118 for (h=0; h<lines; h++) {
1119 srcbyte=srcbits;
1120 dstbyte=dstbits;
1121 for (x=0; x<width/2; x++) {
1122 /* Do 2 pixels at a time */
1123 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1124 (colors, 16,
1125 srcbyte[0],
1126 srcbyte[1],
1127 srcbyte[2]) << 4) |
1128 X11DRV_DIB_GetNearestIndex
1129 (colors, 16,
1130 srcbyte[3],
1131 srcbyte[4],
1132 srcbyte[5]);
1133 srcbyte+=6;
1135 if (width&1) {
1136 /* And then the odd pixel */
1137 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1138 (colors, 16,
1139 srcbyte[0],
1140 srcbyte[1],
1141 srcbyte[2]) << 4);
1143 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1144 dstbits += linebytes;
1147 break;
1149 /* Fall through */
1151 case 32:
1153 const void* srcbits;
1154 const BYTE *srcbyte;
1155 BYTE* dstbyte;
1157 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1159 if (bmpImage->green_mask!=0x00ff00 ||
1160 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1161 goto notsupported;
1162 } else if (bmpImage->blue_mask==0xff) {
1163 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1164 for (h=0; h<lines; h++) {
1165 srcbyte=srcbits;
1166 dstbyte=dstbits;
1167 for (x=0; x<width/2; x++) {
1168 /* Do 2 pixels at a time */
1169 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1170 (colors, 16,
1171 srcbyte[2],
1172 srcbyte[1],
1173 srcbyte[0]) << 4) |
1174 X11DRV_DIB_GetNearestIndex
1175 (colors, 16,
1176 srcbyte[6],
1177 srcbyte[5],
1178 srcbyte[4]);
1179 srcbyte+=8;
1181 if (width&1) {
1182 /* And then the odd pixel */
1183 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1184 (colors, 16,
1185 srcbyte[2],
1186 srcbyte[1],
1187 srcbyte[0]) << 4);
1189 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1190 dstbits += linebytes;
1192 } else {
1193 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1194 for (h=0; h<lines; h++) {
1195 srcbyte=srcbits;
1196 dstbyte=dstbits;
1197 for (x=0; x<width/2; x++) {
1198 /* Do 2 pixels at a time */
1199 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1200 (colors, 16,
1201 srcbyte[0],
1202 srcbyte[1],
1203 srcbyte[2]) << 4) |
1204 X11DRV_DIB_GetNearestIndex
1205 (colors, 16,
1206 srcbyte[4],
1207 srcbyte[5],
1208 srcbyte[6]);
1209 srcbyte+=8;
1211 if (width&1) {
1212 /* And then the odd pixel */
1213 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1214 (colors, 16,
1215 srcbyte[0],
1216 srcbyte[1],
1217 srcbyte[2]) << 4);
1219 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1220 dstbits += linebytes;
1224 break;
1226 default:
1227 notsupported:
1229 BYTE* dstbyte;
1231 /* ==== any bmp format -> pal 4 dib ==== */
1232 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1233 bmpImage->bits_per_pixel, bmpImage->red_mask,
1234 bmpImage->green_mask, bmpImage->blue_mask );
1235 for (h=lines-1; h>=0; h--) {
1236 dstbyte=dstbits;
1237 for (x=0; x<(width & ~1); x+=2) {
1238 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1239 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1241 if (width & 1) {
1242 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1244 dstbits += linebytes;
1247 break;
1251 /***********************************************************************
1252 * X11DRV_DIB_SetImageBits_8
1254 * SetDIBits for an 8-bit deep DIB.
1256 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1257 DWORD srcwidth, DWORD dstwidth, int left,
1258 const int *colors, XImage *bmpImage,
1259 int linebytes )
1261 DWORD x;
1262 int h, width = min(srcwidth, dstwidth);
1263 const BYTE* srcbyte;
1264 BYTE* dstbits;
1266 if (lines < 0 )
1268 lines = -lines;
1269 srcbits = srcbits + linebytes * (lines-1);
1270 linebytes = -linebytes;
1272 srcbits += left;
1273 srcbyte = srcbits;
1275 switch (bmpImage->depth) {
1276 case 15:
1277 case 16:
1278 /* Some X servers might have 32 bit/ 16bit deep pixel */
1279 if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1280 (ImageByteOrder(gdi_display)==LSBFirst) )
1282 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1283 dstbits=(BYTE*)bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1284 for (h = lines ; h--; ) {
1285 DWORD* dstpixel=(DWORD*)dstbits;
1286 for (x=0; x<width/2; x++) {
1287 /* Do 2 pixels at a time */
1288 *dstpixel++=(colors[srcbyte[1]] << 16) | colors[srcbyte[0]];
1289 srcbyte+=2;
1291 if (width&1) {
1292 /* And then the odd pixel */
1293 *((WORD*)dstpixel)=colors[srcbyte[0]];
1295 srcbyte = (srcbits += linebytes);
1296 dstbits -= bmpImage->bytes_per_line;
1298 return;
1300 break;
1301 case 24:
1302 case 32:
1303 if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1304 (ImageByteOrder(gdi_display)==LSBFirst) )
1306 dstbits=(BYTE*)bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1307 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1308 for (h = lines ; h--; ) {
1309 DWORD* dstpixel=(DWORD*)dstbits;
1310 for (x=0; x<width; x++) {
1311 *dstpixel++=colors[*srcbyte++];
1313 srcbyte = (srcbits += linebytes);
1314 dstbits -= bmpImage->bytes_per_line;
1316 return;
1318 break;
1319 default:
1320 break; /* use slow generic case below */
1323 /* ==== pal 8 dib -> any bmp format ==== */
1324 for (h=lines-1; h>=0; h--) {
1325 for (x=left; x<width+left; x++) {
1326 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1328 srcbyte = (srcbits += linebytes);
1332 /***********************************************************************
1333 * X11DRV_DIB_GetImageBits_8
1335 * GetDIBits for an 8-bit deep DIB.
1337 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1338 DWORD srcwidth, DWORD dstwidth,
1339 RGBQUAD *colors, PALETTEENTRY *srccolors,
1340 XImage *bmpImage, int linebytes )
1342 DWORD x;
1343 int h, width = min(srcwidth, dstwidth);
1344 BYTE* dstbyte;
1346 if (lines < 0 )
1348 lines = -lines;
1349 dstbits = dstbits + ( linebytes * (lines-1) );
1350 linebytes = -linebytes;
1354 * Hack for now
1355 * This condition is true when GetImageBits has been called by
1356 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1357 * 256 colormaps, so we'll just use it for GetDIBits calls.
1358 * (In some cases, in an updateDIBSection, the returned colors are bad too)
1360 if (!srccolors) goto updatesection;
1362 switch (bmpImage->depth) {
1363 case 1:
1364 case 4:
1365 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1366 && srccolors) {
1368 /* ==== pal 1 bmp -> pal 8 dib ==== */
1369 /* ==== pal 4 bmp -> pal 8 dib ==== */
1370 for (h=lines-1; h>=0; h--) {
1371 dstbyte=dstbits;
1372 for (x=0; x<width; x++) {
1373 PALETTEENTRY srcval;
1374 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1375 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1376 srcval.peRed,
1377 srcval.peGreen,
1378 srcval.peBlue);
1380 dstbits += linebytes;
1382 } else {
1383 goto notsupported;
1385 break;
1387 case 8:
1388 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1389 && srccolors) {
1390 /* ==== pal 8 bmp -> pal 8 dib ==== */
1391 const void* srcbits;
1392 const BYTE* srcpixel;
1394 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1395 for (h=0; h<lines; h++) {
1396 srcpixel=srcbits;
1397 dstbyte=dstbits;
1398 for (x = 0; x < width; x++) {
1399 PALETTEENTRY srcval;
1400 srcval=srccolors[*srcpixel++];
1401 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1402 srcval.peRed,
1403 srcval.peGreen,
1404 srcval.peBlue);
1406 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1407 dstbits += linebytes;
1409 } else {
1410 goto notsupported;
1412 break;
1414 case 15:
1415 case 16:
1417 const void* srcbits;
1418 const WORD* srcpixel;
1419 BYTE* dstbyte;
1421 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1423 if (bmpImage->green_mask==0x03e0) {
1424 if (bmpImage->red_mask==0x7c00) {
1425 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1426 for (h=0; h<lines; h++) {
1427 srcpixel=srcbits;
1428 dstbyte=dstbits;
1429 for (x=0; x<width; x++) {
1430 WORD srcval;
1431 srcval=*srcpixel++;
1432 *dstbyte++=X11DRV_DIB_GetNearestIndex
1433 (colors, 256,
1434 ((srcval >> 7) & 0xf8) | /* r */
1435 ((srcval >> 12) & 0x07),
1436 ((srcval >> 2) & 0xf8) | /* g */
1437 ((srcval >> 7) & 0x07),
1438 ((srcval << 3) & 0xf8) | /* b */
1439 ((srcval >> 2) & 0x07) );
1441 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1442 dstbits += linebytes;
1444 } else if (bmpImage->blue_mask==0x7c00) {
1445 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1446 for (h=0; h<lines; h++) {
1447 srcpixel=srcbits;
1448 dstbyte=dstbits;
1449 for (x=0; x<width; x++) {
1450 WORD srcval;
1451 srcval=*srcpixel++;
1452 *dstbyte++=X11DRV_DIB_GetNearestIndex
1453 (colors, 256,
1454 ((srcval << 3) & 0xf8) | /* r */
1455 ((srcval >> 2) & 0x07),
1456 ((srcval >> 2) & 0xf8) | /* g */
1457 ((srcval >> 7) & 0x07),
1458 ((srcval >> 7) & 0xf8) | /* b */
1459 ((srcval >> 12) & 0x07) );
1461 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1462 dstbits += linebytes;
1464 } else {
1465 goto notsupported;
1467 } else if (bmpImage->green_mask==0x07e0) {
1468 if (bmpImage->red_mask==0xf800) {
1469 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1470 for (h=0; h<lines; h++) {
1471 srcpixel=srcbits;
1472 dstbyte=dstbits;
1473 for (x=0; x<width; x++) {
1474 WORD srcval;
1475 srcval=*srcpixel++;
1476 *dstbyte++=X11DRV_DIB_GetNearestIndex
1477 (colors, 256,
1478 ((srcval >> 8) & 0xf8) | /* r */
1479 ((srcval >> 13) & 0x07),
1480 ((srcval >> 3) & 0xfc) | /* g */
1481 ((srcval >> 9) & 0x03),
1482 ((srcval << 3) & 0xf8) | /* b */
1483 ((srcval >> 2) & 0x07) );
1485 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1486 dstbits += linebytes;
1488 } else if (bmpImage->blue_mask==0xf800) {
1489 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1490 for (h=0; h<lines; h++) {
1491 srcpixel=srcbits;
1492 dstbyte=dstbits;
1493 for (x=0; x<width; x++) {
1494 WORD srcval;
1495 srcval=*srcpixel++;
1496 *dstbyte++=X11DRV_DIB_GetNearestIndex
1497 (colors, 256,
1498 ((srcval << 3) & 0xf8) | /* r */
1499 ((srcval >> 2) & 0x07),
1500 ((srcval >> 3) & 0xfc) | /* g */
1501 ((srcval >> 9) & 0x03),
1502 ((srcval >> 8) & 0xf8) | /* b */
1503 ((srcval >> 13) & 0x07) );
1505 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1506 dstbits += linebytes;
1508 } else {
1509 goto notsupported;
1511 } else {
1512 goto notsupported;
1515 break;
1517 case 24:
1518 case 32:
1520 const void* srcbits;
1521 const BYTE *srcbyte;
1522 BYTE* dstbyte;
1523 int bytes_per_pixel;
1525 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1526 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1528 if (bmpImage->green_mask!=0x00ff00 ||
1529 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1530 goto notsupported;
1531 } else if (bmpImage->blue_mask==0xff) {
1532 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1533 for (h=0; h<lines; h++) {
1534 srcbyte=srcbits;
1535 dstbyte=dstbits;
1536 for (x=0; x<width; x++) {
1537 *dstbyte++=X11DRV_DIB_GetNearestIndex
1538 (colors, 256,
1539 srcbyte[2],
1540 srcbyte[1],
1541 srcbyte[0]);
1542 srcbyte+=bytes_per_pixel;
1544 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1545 dstbits += linebytes;
1547 } else {
1548 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1549 for (h=0; h<lines; h++) {
1550 srcbyte=srcbits;
1551 dstbyte=dstbits;
1552 for (x=0; x<width; x++) {
1553 *dstbyte++=X11DRV_DIB_GetNearestIndex
1554 (colors, 256,
1555 srcbyte[0],
1556 srcbyte[1],
1557 srcbyte[2]);
1558 srcbyte+=bytes_per_pixel;
1560 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1561 dstbits += linebytes;
1565 break;
1567 default:
1568 notsupported:
1569 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1570 bmpImage->depth, bmpImage->red_mask,
1571 bmpImage->green_mask, bmpImage->blue_mask );
1572 updatesection:
1573 /* ==== any bmp format -> pal 8 dib ==== */
1574 for (h=lines-1; h>=0; h--) {
1575 dstbyte=dstbits;
1576 for (x=0; x<width; x++) {
1577 *dstbyte=X11DRV_DIB_MapColor
1578 ((int*)colors, 256,
1579 XGetPixel(bmpImage, x, h), *dstbyte);
1580 dstbyte++;
1582 dstbits += linebytes;
1584 break;
1588 /***********************************************************************
1589 * X11DRV_DIB_SetImageBits_16
1591 * SetDIBits for a 16-bit deep DIB.
1593 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1594 DWORD srcwidth, DWORD dstwidth, int left,
1595 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1596 XImage *bmpImage, int linebytes )
1598 DWORD x;
1599 int h, width = min(srcwidth, dstwidth);
1600 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1602 if (lines < 0 )
1604 lines = -lines;
1605 srcbits = srcbits + ( linebytes * (lines-1));
1606 linebytes = -linebytes;
1609 switch (bmpImage->depth)
1611 case 15:
1612 case 16:
1614 char* dstbits;
1616 srcbits=srcbits+left*2;
1617 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1619 if (bmpImage->green_mask==0x03e0) {
1620 if (gSrc==bmpImage->green_mask) {
1621 if (rSrc==bmpImage->red_mask) {
1622 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1623 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1624 convs->Convert_5x5_asis
1625 (width,lines,
1626 srcbits,linebytes,
1627 dstbits,-bmpImage->bytes_per_line);
1628 } else if (rSrc==bmpImage->blue_mask) {
1629 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1630 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1631 convs->Convert_555_reverse
1632 (width,lines,
1633 srcbits,linebytes,
1634 dstbits,-bmpImage->bytes_per_line);
1636 } else {
1637 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1638 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1639 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1640 convs->Convert_565_to_555_asis
1641 (width,lines,
1642 srcbits,linebytes,
1643 dstbits,-bmpImage->bytes_per_line);
1644 } else {
1645 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1646 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1647 convs->Convert_565_to_555_reverse
1648 (width,lines,
1649 srcbits,linebytes,
1650 dstbits,-bmpImage->bytes_per_line);
1653 } else if (bmpImage->green_mask==0x07e0) {
1654 if (gSrc==bmpImage->green_mask) {
1655 if (rSrc==bmpImage->red_mask) {
1656 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1657 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1658 convs->Convert_5x5_asis
1659 (width,lines,
1660 srcbits,linebytes,
1661 dstbits,-bmpImage->bytes_per_line);
1662 } else {
1663 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1664 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1665 convs->Convert_565_reverse
1666 (width,lines,
1667 srcbits,linebytes,
1668 dstbits,-bmpImage->bytes_per_line);
1670 } else {
1671 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1672 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1673 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1674 convs->Convert_555_to_565_asis
1675 (width,lines,
1676 srcbits,linebytes,
1677 dstbits,-bmpImage->bytes_per_line);
1678 } else {
1679 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1680 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1681 convs->Convert_555_to_565_reverse
1682 (width,lines,
1683 srcbits,linebytes,
1684 dstbits,-bmpImage->bytes_per_line);
1687 } else {
1688 goto notsupported;
1691 break;
1693 case 24:
1694 if (bmpImage->bits_per_pixel==24) {
1695 char* dstbits;
1697 srcbits=srcbits+left*2;
1698 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1700 if (bmpImage->green_mask!=0x00ff00 ||
1701 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1702 goto notsupported;
1703 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1704 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1705 if (gSrc==0x03e0) {
1706 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1707 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1708 convs->Convert_555_to_888_asis
1709 (width,lines,
1710 srcbits,linebytes,
1711 dstbits,-bmpImage->bytes_per_line);
1712 } else {
1713 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
1714 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
1715 convs->Convert_565_to_888_asis
1716 (width,lines,
1717 srcbits,linebytes,
1718 dstbits,-bmpImage->bytes_per_line);
1720 } else {
1721 if (gSrc==0x03e0) {
1722 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
1723 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
1724 convs->Convert_555_to_888_reverse
1725 (width,lines,
1726 srcbits,linebytes,
1727 dstbits,-bmpImage->bytes_per_line);
1728 } else {
1729 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
1730 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
1731 convs->Convert_565_to_888_reverse
1732 (width,lines,
1733 srcbits,linebytes,
1734 dstbits,-bmpImage->bytes_per_line);
1737 break;
1739 /* Fall through */
1741 case 32:
1743 char* dstbits;
1745 srcbits=srcbits+left*2;
1746 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1748 if (bmpImage->green_mask!=0x00ff00 ||
1749 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1750 goto notsupported;
1751 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1752 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1753 if (gSrc==0x03e0) {
1754 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
1755 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
1756 convs->Convert_555_to_0888_asis
1757 (width,lines,
1758 srcbits,linebytes,
1759 dstbits,-bmpImage->bytes_per_line);
1760 } else {
1761 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
1762 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
1763 convs->Convert_565_to_0888_asis
1764 (width,lines,
1765 srcbits,linebytes,
1766 dstbits,-bmpImage->bytes_per_line);
1768 } else {
1769 if (gSrc==0x03e0) {
1770 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
1771 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
1772 convs->Convert_555_to_0888_reverse
1773 (width,lines,
1774 srcbits,linebytes,
1775 dstbits,-bmpImage->bytes_per_line);
1776 } else {
1777 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
1778 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
1779 convs->Convert_565_to_0888_reverse
1780 (width,lines,
1781 srcbits,linebytes,
1782 dstbits,-bmpImage->bytes_per_line);
1786 break;
1788 default:
1789 notsupported:
1790 WARN("from 16 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
1791 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
1792 bmpImage->green_mask, bmpImage->blue_mask );
1793 /* fall through */
1794 case 1:
1795 case 4:
1796 case 8:
1798 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
1799 const WORD* srcpixel;
1800 int rShift1,gShift1,bShift1;
1801 int rShift2,gShift2,bShift2;
1802 BYTE gMask1,gMask2;
1804 /* Set color scaling values */
1805 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
1806 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
1807 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
1808 rShift2=rShift1+5;
1809 gShift2=gShift1+5;
1810 bShift2=bShift1+5;
1811 if (gSrc==0x03e0) {
1812 /* Green has 5 bits, like the others */
1813 gMask1=0xf8;
1814 gMask2=0x07;
1815 } else {
1816 /* Green has 6 bits, not 5. Compensate. */
1817 gShift1++;
1818 gShift2+=2;
1819 gMask1=0xfc;
1820 gMask2=0x03;
1823 srcbits+=2*left;
1825 /* We could split it into four separate cases to optimize
1826 * but it is probably not worth it.
1828 for (h=lines-1; h>=0; h--) {
1829 srcpixel=(const WORD*)srcbits;
1830 for (x=left; x<width+left; x++) {
1831 DWORD srcval;
1832 BYTE red,green,blue;
1833 srcval=*srcpixel++ << 16;
1834 red= ((srcval >> rShift1) & 0xf8) |
1835 ((srcval >> rShift2) & 0x07);
1836 green=((srcval >> gShift1) & gMask1) |
1837 ((srcval >> gShift2) & gMask2);
1838 blue= ((srcval >> bShift1) & 0xf8) |
1839 ((srcval >> bShift2) & 0x07);
1840 XPutPixel(bmpImage, x, h,
1841 X11DRV_PALETTE_ToPhysical
1842 (physDev, RGB(red,green,blue)));
1844 srcbits += linebytes;
1847 break;
1852 /***********************************************************************
1853 * X11DRV_DIB_GetImageBits_16
1855 * GetDIBits for an 16-bit deep DIB.
1857 static void X11DRV_DIB_GetImageBits_16( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
1858 DWORD dstwidth, DWORD srcwidth,
1859 PALETTEENTRY *srccolors,
1860 DWORD rDst, DWORD gDst, DWORD bDst,
1861 XImage *bmpImage, int linebytes )
1863 DWORD x;
1864 int h, width = min(srcwidth, dstwidth);
1865 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
1867 if (lines < 0 )
1869 lines = -lines;
1870 dstbits = dstbits + ( linebytes * (lines-1));
1871 linebytes = -linebytes;
1874 switch (bmpImage->depth)
1876 case 15:
1877 case 16:
1879 const char* srcbits;
1881 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1883 if (bmpImage->green_mask==0x03e0) {
1884 if (gDst==bmpImage->green_mask) {
1885 if (rDst==bmpImage->red_mask) {
1886 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
1887 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
1888 convs->Convert_5x5_asis
1889 (width,lines,
1890 srcbits,-bmpImage->bytes_per_line,
1891 dstbits,linebytes);
1892 } else {
1893 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
1894 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
1895 convs->Convert_555_reverse
1896 (width,lines,
1897 srcbits,-bmpImage->bytes_per_line,
1898 dstbits,linebytes);
1900 } else {
1901 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
1902 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
1903 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
1904 convs->Convert_555_to_565_asis
1905 (width,lines,
1906 srcbits,-bmpImage->bytes_per_line,
1907 dstbits,linebytes);
1908 } else {
1909 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
1910 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
1911 convs->Convert_555_to_565_reverse
1912 (width,lines,
1913 srcbits,-bmpImage->bytes_per_line,
1914 dstbits,linebytes);
1917 } else if (bmpImage->green_mask==0x07e0) {
1918 if (gDst==bmpImage->green_mask) {
1919 if (rDst == bmpImage->red_mask) {
1920 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
1921 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
1922 convs->Convert_5x5_asis
1923 (width,lines,
1924 srcbits,-bmpImage->bytes_per_line,
1925 dstbits,linebytes);
1926 } else {
1927 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
1928 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
1929 convs->Convert_565_reverse
1930 (width,lines,
1931 srcbits,-bmpImage->bytes_per_line,
1932 dstbits,linebytes);
1934 } else {
1935 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
1936 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
1937 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
1938 convs->Convert_565_to_555_asis
1939 (width,lines,
1940 srcbits,-bmpImage->bytes_per_line,
1941 dstbits,linebytes);
1942 } else {
1943 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
1944 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
1945 convs->Convert_565_to_555_reverse
1946 (width,lines,
1947 srcbits,-bmpImage->bytes_per_line,
1948 dstbits,linebytes);
1951 } else {
1952 goto notsupported;
1955 break;
1957 case 24:
1958 if (bmpImage->bits_per_pixel == 24) {
1959 const char* srcbits;
1961 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1963 if (bmpImage->green_mask!=0x00ff00 ||
1964 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1965 goto notsupported;
1966 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
1967 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
1968 if (gDst==0x03e0) {
1969 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
1970 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
1971 convs->Convert_888_to_555_asis
1972 (width,lines,
1973 srcbits,-bmpImage->bytes_per_line,
1974 dstbits,linebytes);
1975 } else {
1976 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
1977 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
1978 convs->Convert_888_to_565_asis
1979 (width,lines,
1980 srcbits,-bmpImage->bytes_per_line,
1981 dstbits,linebytes);
1983 } else {
1984 if (gDst==0x03e0) {
1985 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
1986 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
1987 convs->Convert_888_to_555_reverse
1988 (width,lines,
1989 srcbits,-bmpImage->bytes_per_line,
1990 dstbits,linebytes);
1991 } else {
1992 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
1993 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
1994 convs->Convert_888_to_565_reverse
1995 (width,lines,
1996 srcbits,-bmpImage->bytes_per_line,
1997 dstbits,linebytes);
2000 break;
2002 /* Fall through */
2004 case 32:
2006 const char* srcbits;
2008 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2010 if (bmpImage->green_mask!=0x00ff00 ||
2011 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2012 goto notsupported;
2013 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2014 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2015 if (gDst==0x03e0) {
2016 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2017 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2018 convs->Convert_0888_to_555_asis
2019 (width,lines,
2020 srcbits,-bmpImage->bytes_per_line,
2021 dstbits,linebytes);
2022 } else {
2023 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2024 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2025 convs->Convert_0888_to_565_asis
2026 (width,lines,
2027 srcbits,-bmpImage->bytes_per_line,
2028 dstbits,linebytes);
2030 } else {
2031 if (gDst==0x03e0) {
2032 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2033 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2034 convs->Convert_0888_to_555_reverse
2035 (width,lines,
2036 srcbits,-bmpImage->bytes_per_line,
2037 dstbits,linebytes);
2038 } else {
2039 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2040 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2041 convs->Convert_0888_to_565_reverse
2042 (width,lines,
2043 srcbits,-bmpImage->bytes_per_line,
2044 dstbits,linebytes);
2048 break;
2050 case 1:
2051 case 4:
2052 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2053 && srccolors) {
2054 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2055 int rShift,gShift,bShift;
2056 WORD* dstpixel;
2058 /* Shift everything 16 bits left so that all shifts are >0,
2059 * even for BGR DIBs. Then a single >> 16 will bring everything
2060 * back into place.
2062 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2063 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2064 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2065 if (gDst==0x07e0) {
2066 /* 6 bits for the green */
2067 gShift++;
2069 rDst=rDst << 16;
2070 gDst=gDst << 16;
2071 bDst=bDst << 16;
2072 for (h = lines - 1; h >= 0; h--) {
2073 dstpixel=(LPWORD)dstbits;
2074 for (x = 0; x < width; x++) {
2075 PALETTEENTRY srcval;
2076 DWORD dstval;
2077 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2078 dstval=((srcval.peRed << rShift) & rDst) |
2079 ((srcval.peGreen << gShift) & gDst) |
2080 ((srcval.peBlue << bShift) & bDst);
2081 *dstpixel++=dstval >> 16;
2083 dstbits += linebytes;
2085 } else {
2086 goto notsupported;
2088 break;
2090 case 8:
2091 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2092 && srccolors) {
2093 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2094 int rShift,gShift,bShift;
2095 const BYTE* srcbits;
2096 const BYTE* srcpixel;
2097 WORD* dstpixel;
2099 /* Shift everything 16 bits left so that all shifts are >0,
2100 * even for BGR DIBs. Then a single >> 16 will bring everything
2101 * back into place.
2103 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2104 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2105 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2106 if (gDst==0x07e0) {
2107 /* 6 bits for the green */
2108 gShift++;
2110 rDst=rDst << 16;
2111 gDst=gDst << 16;
2112 bDst=bDst << 16;
2113 srcbits=(BYTE*)bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2114 for (h=0; h<lines; h++) {
2115 srcpixel=srcbits;
2116 dstpixel=(LPWORD)dstbits;
2117 for (x = 0; x < width; x++) {
2118 PALETTEENTRY srcval;
2119 DWORD dstval;
2120 srcval=srccolors[*srcpixel++];
2121 dstval=((srcval.peRed << rShift) & rDst) |
2122 ((srcval.peGreen << gShift) & gDst) |
2123 ((srcval.peBlue << bShift) & bDst);
2124 *dstpixel++=dstval >> 16;
2126 srcbits -= bmpImage->bytes_per_line;
2127 dstbits += linebytes;
2129 } else {
2130 goto notsupported;
2132 break;
2134 default:
2135 notsupported:
2137 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2138 int rShift,gShift,bShift;
2139 WORD* dstpixel;
2141 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%x,%x,%x)\n",
2142 bmpImage->depth, bmpImage->red_mask,
2143 bmpImage->green_mask, bmpImage->blue_mask,
2144 rDst, gDst, bDst);
2146 /* Shift everything 16 bits left so that all shifts are >0,
2147 * even for BGR DIBs. Then a single >> 16 will bring everything
2148 * back into place.
2150 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2151 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2152 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2153 if (gDst==0x07e0) {
2154 /* 6 bits for the green */
2155 gShift++;
2157 rDst=rDst << 16;
2158 gDst=gDst << 16;
2159 bDst=bDst << 16;
2160 for (h = lines - 1; h >= 0; h--) {
2161 dstpixel=(LPWORD)dstbits;
2162 for (x = 0; x < width; x++) {
2163 COLORREF srcval;
2164 DWORD dstval;
2165 srcval=X11DRV_PALETTE_ToLogical(physDev, XGetPixel(bmpImage, x, h));
2166 dstval=((GetRValue(srcval) << rShift) & rDst) |
2167 ((GetGValue(srcval) << gShift) & gDst) |
2168 ((GetBValue(srcval) << bShift) & bDst);
2169 *dstpixel++=dstval >> 16;
2171 dstbits += linebytes;
2174 break;
2179 /***********************************************************************
2180 * X11DRV_DIB_SetImageBits_24
2182 * SetDIBits for a 24-bit deep DIB.
2184 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2185 DWORD srcwidth, DWORD dstwidth, int left,
2186 X11DRV_PDEVICE *physDev,
2187 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2188 XImage *bmpImage, DWORD linebytes )
2190 DWORD x;
2191 int h, width = min(srcwidth, dstwidth);
2192 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2194 if (lines < 0 )
2196 lines = -lines;
2197 srcbits = srcbits + linebytes * (lines - 1);
2198 linebytes = -linebytes;
2201 switch (bmpImage->depth)
2203 case 24:
2204 if (bmpImage->bits_per_pixel==24) {
2205 char* dstbits;
2207 srcbits=srcbits+left*3;
2208 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2210 if (bmpImage->green_mask!=0x00ff00 ||
2211 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2212 goto notsupported;
2213 } else if (rSrc==bmpImage->red_mask) {
2214 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2215 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2216 convs->Convert_888_asis
2217 (width,lines,
2218 srcbits,linebytes,
2219 dstbits,-bmpImage->bytes_per_line);
2220 } else {
2221 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2222 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2223 convs->Convert_888_reverse
2224 (width,lines,
2225 srcbits,linebytes,
2226 dstbits,-bmpImage->bytes_per_line);
2228 break;
2230 /* fall through */
2232 case 32:
2234 char* dstbits;
2236 srcbits=srcbits+left*3;
2237 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2239 if (bmpImage->green_mask!=0x00ff00 ||
2240 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2241 goto notsupported;
2242 } else if (rSrc==bmpImage->red_mask) {
2243 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2244 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2245 convs->Convert_888_to_0888_asis
2246 (width,lines,
2247 srcbits,linebytes,
2248 dstbits,-bmpImage->bytes_per_line);
2249 } else {
2250 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2251 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2252 convs->Convert_888_to_0888_reverse
2253 (width,lines,
2254 srcbits,linebytes,
2255 dstbits,-bmpImage->bytes_per_line);
2257 break;
2260 case 15:
2261 case 16:
2263 char* dstbits;
2265 srcbits=srcbits+left*3;
2266 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2268 if (bmpImage->green_mask==0x03e0) {
2269 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2270 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2271 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2272 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2273 convs->Convert_888_to_555_asis
2274 (width,lines,
2275 srcbits,linebytes,
2276 dstbits,-bmpImage->bytes_per_line);
2277 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2278 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2279 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2280 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2281 convs->Convert_888_to_555_reverse
2282 (width,lines,
2283 srcbits,linebytes,
2284 dstbits,-bmpImage->bytes_per_line);
2285 } else {
2286 goto notsupported;
2288 } else if (bmpImage->green_mask==0x07e0) {
2289 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2290 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2291 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2292 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2293 convs->Convert_888_to_565_asis
2294 (width,lines,
2295 srcbits,linebytes,
2296 dstbits,-bmpImage->bytes_per_line);
2297 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2298 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2299 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2300 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2301 convs->Convert_888_to_565_reverse
2302 (width,lines,
2303 srcbits,linebytes,
2304 dstbits,-bmpImage->bytes_per_line);
2305 } else {
2306 goto notsupported;
2308 } else {
2309 goto notsupported;
2312 break;
2314 default:
2315 notsupported:
2316 WARN("from 24 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2317 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2318 bmpImage->green_mask, bmpImage->blue_mask );
2319 /* fall through */
2320 case 1:
2321 case 4:
2322 case 8:
2324 /* ==== rgb 888 dib -> any bmp format ==== */
2325 const BYTE* srcbyte;
2327 /* Windows only supports one 24bpp DIB format: RGB888 */
2328 srcbits+=left*3;
2329 for (h = lines - 1; h >= 0; h--) {
2330 srcbyte = srcbits;
2331 for (x = left; x < width+left; x++) {
2332 XPutPixel(bmpImage, x, h,
2333 X11DRV_PALETTE_ToPhysical
2334 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2335 srcbyte+=3;
2337 srcbits += linebytes;
2340 break;
2345 /***********************************************************************
2346 * X11DRV_DIB_GetImageBits_24
2348 * GetDIBits for an 24-bit deep DIB.
2350 static void X11DRV_DIB_GetImageBits_24( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
2351 DWORD dstwidth, DWORD srcwidth,
2352 PALETTEENTRY *srccolors,
2353 DWORD rDst, DWORD gDst, DWORD bDst,
2354 XImage *bmpImage, DWORD linebytes )
2356 DWORD x;
2357 int h, width = min(srcwidth, dstwidth);
2358 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2360 if (lines < 0 )
2362 lines = -lines;
2363 dstbits = dstbits + ( linebytes * (lines-1) );
2364 linebytes = -linebytes;
2367 switch (bmpImage->depth)
2369 case 24:
2370 if (bmpImage->bits_per_pixel==24) {
2371 const char* srcbits;
2373 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2375 if (bmpImage->green_mask!=0x00ff00 ||
2376 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2377 goto notsupported;
2378 } else if (rDst==bmpImage->red_mask) {
2379 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2380 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2381 convs->Convert_888_asis
2382 (width,lines,
2383 srcbits,-bmpImage->bytes_per_line,
2384 dstbits,linebytes);
2385 } else {
2386 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2387 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2388 convs->Convert_888_reverse
2389 (width,lines,
2390 srcbits,-bmpImage->bytes_per_line,
2391 dstbits,linebytes);
2393 break;
2395 /* fall through */
2397 case 32:
2399 const char* srcbits;
2401 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2403 if (bmpImage->green_mask!=0x00ff00 ||
2404 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2405 goto notsupported;
2406 } else if (rDst==bmpImage->red_mask) {
2407 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2408 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2409 convs->Convert_0888_to_888_asis
2410 (width,lines,
2411 srcbits,-bmpImage->bytes_per_line,
2412 dstbits,linebytes);
2413 } else {
2414 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2415 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2416 convs->Convert_0888_to_888_reverse
2417 (width,lines,
2418 srcbits,-bmpImage->bytes_per_line,
2419 dstbits,linebytes);
2421 break;
2424 case 15:
2425 case 16:
2427 const char* srcbits;
2429 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2431 if (bmpImage->green_mask==0x03e0) {
2432 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2433 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2434 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2435 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2436 convs->Convert_555_to_888_asis
2437 (width,lines,
2438 srcbits,-bmpImage->bytes_per_line,
2439 dstbits,linebytes);
2440 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2441 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2442 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2443 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2444 convs->Convert_555_to_888_reverse
2445 (width,lines,
2446 srcbits,-bmpImage->bytes_per_line,
2447 dstbits,linebytes);
2448 } else {
2449 goto notsupported;
2451 } else if (bmpImage->green_mask==0x07e0) {
2452 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2453 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2454 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2455 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2456 convs->Convert_565_to_888_asis
2457 (width,lines,
2458 srcbits,-bmpImage->bytes_per_line,
2459 dstbits,linebytes);
2460 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2461 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2462 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2463 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2464 convs->Convert_565_to_888_reverse
2465 (width,lines,
2466 srcbits,-bmpImage->bytes_per_line,
2467 dstbits,linebytes);
2468 } else {
2469 goto notsupported;
2471 } else {
2472 goto notsupported;
2475 break;
2477 case 1:
2478 case 4:
2479 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2480 && srccolors) {
2481 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2482 BYTE* dstbyte;
2484 /* Windows only supports one 24bpp DIB format: rgb 888 */
2485 for (h = lines - 1; h >= 0; h--) {
2486 dstbyte=dstbits;
2487 for (x = 0; x < width; x++) {
2488 PALETTEENTRY srcval;
2489 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2490 dstbyte[0]=srcval.peBlue;
2491 dstbyte[1]=srcval.peGreen;
2492 dstbyte[2]=srcval.peRed;
2493 dstbyte+=3;
2495 dstbits += linebytes;
2497 } else {
2498 goto notsupported;
2500 break;
2502 case 8:
2503 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2504 && srccolors) {
2505 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2506 const void* srcbits;
2507 const BYTE* srcpixel;
2508 BYTE* dstbyte;
2510 /* Windows only supports one 24bpp DIB format: rgb 888 */
2511 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2512 for (h = lines - 1; h >= 0; h--) {
2513 srcpixel=srcbits;
2514 dstbyte=dstbits;
2515 for (x = 0; x < width; x++ ) {
2516 PALETTEENTRY srcval;
2517 srcval=srccolors[*srcpixel++];
2518 dstbyte[0]=srcval.peBlue;
2519 dstbyte[1]=srcval.peGreen;
2520 dstbyte[2]=srcval.peRed;
2521 dstbyte+=3;
2523 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
2524 dstbits += linebytes;
2526 } else {
2527 goto notsupported;
2529 break;
2531 default:
2532 notsupported:
2534 /* ==== any bmp format -> 888 dib ==== */
2535 BYTE* dstbyte;
2537 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%x,%x,%x)\n",
2538 bmpImage->depth, bmpImage->red_mask,
2539 bmpImage->green_mask, bmpImage->blue_mask,
2540 rDst, gDst, bDst );
2542 /* Windows only supports one 24bpp DIB format: rgb 888 */
2543 for (h = lines - 1; h >= 0; h--) {
2544 dstbyte=dstbits;
2545 for (x = 0; x < width; x++) {
2546 COLORREF srcval=X11DRV_PALETTE_ToLogical
2547 (physDev, XGetPixel( bmpImage, x, h ));
2548 dstbyte[0]=GetBValue(srcval);
2549 dstbyte[1]=GetGValue(srcval);
2550 dstbyte[2]=GetRValue(srcval);
2551 dstbyte+=3;
2553 dstbits += linebytes;
2556 break;
2561 /***********************************************************************
2562 * X11DRV_DIB_SetImageBits_32
2564 * SetDIBits for a 32-bit deep DIB.
2566 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2567 DWORD srcwidth, DWORD dstwidth, int left,
2568 X11DRV_PDEVICE *physDev,
2569 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2570 XImage *bmpImage,
2571 DWORD linebytes)
2573 DWORD x;
2574 int h, width = min(srcwidth, dstwidth);
2575 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2577 if (lines < 0 )
2579 lines = -lines;
2580 srcbits = srcbits + ( linebytes * (lines-1) );
2581 linebytes = -linebytes;
2584 switch (bmpImage->depth)
2586 case 24:
2587 if (bmpImage->bits_per_pixel==24) {
2588 char* dstbits;
2590 srcbits=srcbits+left*4;
2591 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2593 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2594 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2595 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2596 convs->Convert_0888_to_888_asis
2597 (width,lines,
2598 srcbits,linebytes,
2599 dstbits,-bmpImage->bytes_per_line);
2600 } else if (bmpImage->green_mask!=0x00ff00 ||
2601 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2602 goto notsupported;
2603 /* the tests below assume sane bmpImage masks */
2604 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2605 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2606 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2607 convs->Convert_0888_to_888_reverse
2608 (width,lines,
2609 srcbits,linebytes,
2610 dstbits,-bmpImage->bytes_per_line);
2611 } else if (bmpImage->blue_mask==0xff) {
2612 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2613 convs->Convert_any0888_to_rgb888
2614 (width,lines,
2615 srcbits,linebytes,
2616 rSrc,gSrc,bSrc,
2617 dstbits,-bmpImage->bytes_per_line);
2618 } else {
2619 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2620 convs->Convert_any0888_to_bgr888
2621 (width,lines,
2622 srcbits,linebytes,
2623 rSrc,gSrc,bSrc,
2624 dstbits,-bmpImage->bytes_per_line);
2626 break;
2628 /* fall through */
2630 case 32:
2632 char* dstbits;
2634 srcbits=srcbits+left*4;
2635 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2637 if (gSrc==bmpImage->green_mask) {
2638 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2639 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2640 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2641 convs->Convert_0888_asis
2642 (width,lines,
2643 srcbits,linebytes,
2644 dstbits,-bmpImage->bytes_per_line);
2645 } else if (bmpImage->green_mask!=0x00ff00 ||
2646 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2647 goto notsupported;
2648 /* the tests below assume sane bmpImage masks */
2649 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2650 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2651 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2652 convs->Convert_0888_reverse
2653 (width,lines,
2654 srcbits,linebytes,
2655 dstbits,-bmpImage->bytes_per_line);
2656 } else {
2657 /* ==== any 0888 dib -> any 0888 bmp ==== */
2658 convs->Convert_0888_any
2659 (width,lines,
2660 srcbits,linebytes,
2661 rSrc,gSrc,bSrc,
2662 dstbits,-bmpImage->bytes_per_line,
2663 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2665 } else if (bmpImage->green_mask!=0x00ff00 ||
2666 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2667 goto notsupported;
2668 /* the tests below assume sane bmpImage masks */
2669 } else {
2670 /* ==== any 0888 dib -> any 0888 bmp ==== */
2671 convs->Convert_0888_any
2672 (width,lines,
2673 srcbits,linebytes,
2674 rSrc,gSrc,bSrc,
2675 dstbits,-bmpImage->bytes_per_line,
2676 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2679 break;
2681 case 15:
2682 case 16:
2684 char* dstbits;
2686 srcbits=srcbits+left*4;
2687 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2689 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2690 if (bmpImage->green_mask==0x03e0) {
2691 if (bmpImage->red_mask==0x7f00) {
2692 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2693 convs->Convert_0888_to_555_asis
2694 (width,lines,
2695 srcbits,linebytes,
2696 dstbits,-bmpImage->bytes_per_line);
2697 } else if (bmpImage->blue_mask==0x7f00) {
2698 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2699 convs->Convert_0888_to_555_reverse
2700 (width,lines,
2701 srcbits,linebytes,
2702 dstbits,-bmpImage->bytes_per_line);
2703 } else {
2704 goto notsupported;
2706 } else if (bmpImage->green_mask==0x07e0) {
2707 if (bmpImage->red_mask==0xf800) {
2708 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
2709 convs->Convert_0888_to_565_asis
2710 (width,lines,
2711 srcbits,linebytes,
2712 dstbits,-bmpImage->bytes_per_line);
2713 } else if (bmpImage->blue_mask==0xf800) {
2714 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
2715 convs->Convert_0888_to_565_reverse
2716 (width,lines,
2717 srcbits,linebytes,
2718 dstbits,-bmpImage->bytes_per_line);
2719 } else {
2720 goto notsupported;
2722 } else {
2723 goto notsupported;
2725 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
2726 if (bmpImage->green_mask==0x03e0) {
2727 if (bmpImage->blue_mask==0x7f00) {
2728 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
2729 convs->Convert_0888_to_555_asis
2730 (width,lines,
2731 srcbits,linebytes,
2732 dstbits,-bmpImage->bytes_per_line);
2733 } else if (bmpImage->red_mask==0x7f00) {
2734 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
2735 convs->Convert_0888_to_555_reverse
2736 (width,lines,
2737 srcbits,linebytes,
2738 dstbits,-bmpImage->bytes_per_line);
2739 } else {
2740 goto notsupported;
2742 } else if (bmpImage->green_mask==0x07e0) {
2743 if (bmpImage->blue_mask==0xf800) {
2744 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
2745 convs->Convert_0888_to_565_asis
2746 (width,lines,
2747 srcbits,linebytes,
2748 dstbits,-bmpImage->bytes_per_line);
2749 } else if (bmpImage->red_mask==0xf800) {
2750 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
2751 convs->Convert_0888_to_565_reverse
2752 (width,lines,
2753 srcbits,linebytes,
2754 dstbits,-bmpImage->bytes_per_line);
2755 } else {
2756 goto notsupported;
2758 } else {
2759 goto notsupported;
2761 } else {
2762 if (bmpImage->green_mask==0x03e0 &&
2763 (bmpImage->red_mask==0x7f00 ||
2764 bmpImage->blue_mask==0x7f00)) {
2765 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
2766 convs->Convert_any0888_to_5x5
2767 (width,lines,
2768 srcbits,linebytes,
2769 rSrc,gSrc,bSrc,
2770 dstbits,-bmpImage->bytes_per_line,
2771 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2772 } else if (bmpImage->green_mask==0x07e0 &&
2773 (bmpImage->red_mask==0xf800 ||
2774 bmpImage->blue_mask==0xf800)) {
2775 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
2776 convs->Convert_any0888_to_5x5
2777 (width,lines,
2778 srcbits,linebytes,
2779 rSrc,gSrc,bSrc,
2780 dstbits,-bmpImage->bytes_per_line,
2781 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2782 } else {
2783 goto notsupported;
2787 break;
2789 default:
2790 notsupported:
2791 WARN("from 32 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2792 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2793 bmpImage->green_mask, bmpImage->blue_mask );
2794 /* fall through */
2795 case 1:
2796 case 4:
2797 case 8:
2799 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
2800 const DWORD* srcpixel;
2801 int rShift,gShift,bShift;
2803 rShift=X11DRV_DIB_MaskToShift(rSrc);
2804 gShift=X11DRV_DIB_MaskToShift(gSrc);
2805 bShift=X11DRV_DIB_MaskToShift(bSrc);
2806 srcbits+=left*4;
2807 for (h = lines - 1; h >= 0; h--) {
2808 srcpixel=(const DWORD*)srcbits;
2809 for (x = left; x < width+left; x++) {
2810 DWORD srcvalue;
2811 BYTE red,green,blue;
2812 srcvalue=*srcpixel++;
2813 red= (srcvalue >> rShift) & 0xff;
2814 green=(srcvalue >> gShift) & 0xff;
2815 blue= (srcvalue >> bShift) & 0xff;
2816 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
2817 (physDev, RGB(red,green,blue)));
2819 srcbits += linebytes;
2822 break;
2827 /***********************************************************************
2828 * X11DRV_DIB_GetImageBits_32
2830 * GetDIBits for an 32-bit deep DIB.
2832 static void X11DRV_DIB_GetImageBits_32( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
2833 DWORD dstwidth, DWORD srcwidth,
2834 PALETTEENTRY *srccolors,
2835 DWORD rDst, DWORD gDst, DWORD bDst,
2836 XImage *bmpImage, int linebytes )
2838 DWORD x;
2839 int h, width = min(srcwidth, dstwidth);
2840 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2842 if (lines < 0 )
2844 lines = -lines;
2845 dstbits = dstbits + ( linebytes * (lines-1) );
2846 linebytes = -linebytes;
2849 switch (bmpImage->depth)
2851 case 24:
2852 if (bmpImage->bits_per_pixel==24) {
2853 const void* srcbits;
2855 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2857 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
2858 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2859 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2860 convs->Convert_888_to_0888_asis
2861 (width,lines,
2862 srcbits,-bmpImage->bytes_per_line,
2863 dstbits,linebytes);
2864 } else if (bmpImage->green_mask!=0x00ff00 ||
2865 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2866 goto notsupported;
2867 /* the tests below assume sane bmpImage masks */
2868 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
2869 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2870 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2871 convs->Convert_888_to_0888_reverse
2872 (width,lines,
2873 srcbits,-bmpImage->bytes_per_line,
2874 dstbits,linebytes);
2875 } else if (bmpImage->blue_mask==0xff) {
2876 /* ==== rgb 888 bmp -> any 0888 dib ==== */
2877 convs->Convert_rgb888_to_any0888
2878 (width,lines,
2879 srcbits,-bmpImage->bytes_per_line,
2880 dstbits,linebytes,
2881 rDst,gDst,bDst);
2882 } else {
2883 /* ==== bgr 888 bmp -> any 0888 dib ==== */
2884 convs->Convert_bgr888_to_any0888
2885 (width,lines,
2886 srcbits,-bmpImage->bytes_per_line,
2887 dstbits,linebytes,
2888 rDst,gDst,bDst);
2890 break;
2892 /* fall through */
2894 case 32:
2896 const char* srcbits;
2898 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2900 if (gDst==bmpImage->green_mask) {
2901 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
2902 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
2903 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
2904 convs->Convert_0888_asis
2905 (width,lines,
2906 srcbits,-bmpImage->bytes_per_line,
2907 dstbits,linebytes);
2908 } else if (bmpImage->green_mask!=0x00ff00 ||
2909 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2910 goto notsupported;
2911 /* the tests below assume sane bmpImage masks */
2912 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
2913 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
2914 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
2915 convs->Convert_0888_reverse
2916 (width,lines,
2917 srcbits,-bmpImage->bytes_per_line,
2918 dstbits,linebytes);
2919 } else {
2920 /* ==== any 0888 bmp -> any 0888 dib ==== */
2921 convs->Convert_0888_any
2922 (width,lines,
2923 srcbits,-bmpImage->bytes_per_line,
2924 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
2925 dstbits,linebytes,
2926 rDst,gDst,bDst);
2928 } else if (bmpImage->green_mask!=0x00ff00 ||
2929 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2930 goto notsupported;
2931 /* the tests below assume sane bmpImage masks */
2932 } else {
2933 /* ==== any 0888 bmp -> any 0888 dib ==== */
2934 convs->Convert_0888_any
2935 (width,lines,
2936 srcbits,-bmpImage->bytes_per_line,
2937 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
2938 dstbits,linebytes,
2939 rDst,gDst,bDst);
2942 break;
2944 case 15:
2945 case 16:
2947 const char* srcbits;
2949 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2951 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
2952 if (bmpImage->green_mask==0x03e0) {
2953 if (bmpImage->red_mask==0x7f00) {
2954 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
2955 convs->Convert_555_to_0888_asis
2956 (width,lines,
2957 srcbits,-bmpImage->bytes_per_line,
2958 dstbits,linebytes);
2959 } else if (bmpImage->blue_mask==0x7f00) {
2960 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
2961 convs->Convert_555_to_0888_reverse
2962 (width,lines,
2963 srcbits,-bmpImage->bytes_per_line,
2964 dstbits,linebytes);
2965 } else {
2966 goto notsupported;
2968 } else if (bmpImage->green_mask==0x07e0) {
2969 if (bmpImage->red_mask==0xf800) {
2970 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
2971 convs->Convert_565_to_0888_asis
2972 (width,lines,
2973 srcbits,-bmpImage->bytes_per_line,
2974 dstbits,linebytes);
2975 } else if (bmpImage->blue_mask==0xf800) {
2976 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
2977 convs->Convert_565_to_0888_reverse
2978 (width,lines,
2979 srcbits,-bmpImage->bytes_per_line,
2980 dstbits,linebytes);
2981 } else {
2982 goto notsupported;
2984 } else {
2985 goto notsupported;
2987 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
2988 if (bmpImage->green_mask==0x03e0) {
2989 if (bmpImage->blue_mask==0x7f00) {
2990 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
2991 convs->Convert_555_to_0888_asis
2992 (width,lines,
2993 srcbits,-bmpImage->bytes_per_line,
2994 dstbits,linebytes);
2995 } else if (bmpImage->red_mask==0x7f00) {
2996 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
2997 convs->Convert_555_to_0888_reverse
2998 (width,lines,
2999 srcbits,-bmpImage->bytes_per_line,
3000 dstbits,linebytes);
3001 } else {
3002 goto notsupported;
3004 } else if (bmpImage->green_mask==0x07e0) {
3005 if (bmpImage->blue_mask==0xf800) {
3006 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3007 convs->Convert_565_to_0888_asis
3008 (width,lines,
3009 srcbits,-bmpImage->bytes_per_line,
3010 dstbits,linebytes);
3011 } else if (bmpImage->red_mask==0xf800) {
3012 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3013 convs->Convert_565_to_0888_reverse
3014 (width,lines,
3015 srcbits,-bmpImage->bytes_per_line,
3016 dstbits,linebytes);
3017 } else {
3018 goto notsupported;
3020 } else {
3021 goto notsupported;
3023 } else {
3024 if (bmpImage->green_mask==0x03e0 &&
3025 (bmpImage->red_mask==0x7f00 ||
3026 bmpImage->blue_mask==0x7f00)) {
3027 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3028 convs->Convert_5x5_to_any0888
3029 (width,lines,
3030 srcbits,-bmpImage->bytes_per_line,
3031 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3032 dstbits,linebytes,
3033 rDst,gDst,bDst);
3034 } else if (bmpImage->green_mask==0x07e0 &&
3035 (bmpImage->red_mask==0xf800 ||
3036 bmpImage->blue_mask==0xf800)) {
3037 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3038 convs->Convert_5x5_to_any0888
3039 (width,lines,
3040 srcbits,-bmpImage->bytes_per_line,
3041 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3042 dstbits,linebytes,
3043 rDst,gDst,bDst);
3044 } else {
3045 goto notsupported;
3049 break;
3051 case 1:
3052 case 4:
3053 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3054 && srccolors) {
3055 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3056 int rShift,gShift,bShift;
3057 DWORD* dstpixel;
3059 rShift=X11DRV_DIB_MaskToShift(rDst);
3060 gShift=X11DRV_DIB_MaskToShift(gDst);
3061 bShift=X11DRV_DIB_MaskToShift(bDst);
3062 for (h = lines - 1; h >= 0; h--) {
3063 dstpixel=(DWORD*)dstbits;
3064 for (x = 0; x < width; x++) {
3065 PALETTEENTRY srcval;
3066 srcval = srccolors[XGetPixel(bmpImage, x, h)];
3067 *dstpixel++=(srcval.peRed << rShift) |
3068 (srcval.peGreen << gShift) |
3069 (srcval.peBlue << bShift);
3071 dstbits += linebytes;
3073 } else {
3074 goto notsupported;
3076 break;
3078 case 8:
3079 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3080 && srccolors) {
3081 /* ==== pal 8 bmp -> any 0888 dib ==== */
3082 int rShift,gShift,bShift;
3083 const void* srcbits;
3084 const BYTE* srcpixel;
3085 DWORD* dstpixel;
3087 rShift=X11DRV_DIB_MaskToShift(rDst);
3088 gShift=X11DRV_DIB_MaskToShift(gDst);
3089 bShift=X11DRV_DIB_MaskToShift(bDst);
3090 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3091 for (h = lines - 1; h >= 0; h--) {
3092 srcpixel=srcbits;
3093 dstpixel=(DWORD*)dstbits;
3094 for (x = 0; x < width; x++) {
3095 PALETTEENTRY srcval;
3096 srcval=srccolors[*srcpixel++];
3097 *dstpixel++=(srcval.peRed << rShift) |
3098 (srcval.peGreen << gShift) |
3099 (srcval.peBlue << bShift);
3101 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
3102 dstbits += linebytes;
3104 } else {
3105 goto notsupported;
3107 break;
3109 default:
3110 notsupported:
3112 /* ==== any bmp format -> any 0888 dib ==== */
3113 int rShift,gShift,bShift;
3114 DWORD* dstpixel;
3116 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%x,%x,%x)\n",
3117 bmpImage->depth, bmpImage->red_mask,
3118 bmpImage->green_mask, bmpImage->blue_mask,
3119 rDst,gDst,bDst);
3121 rShift=X11DRV_DIB_MaskToShift(rDst);
3122 gShift=X11DRV_DIB_MaskToShift(gDst);
3123 bShift=X11DRV_DIB_MaskToShift(bDst);
3124 for (h = lines - 1; h >= 0; h--) {
3125 dstpixel=(DWORD*)dstbits;
3126 for (x = 0; x < width; x++) {
3127 COLORREF srcval;
3128 srcval=X11DRV_PALETTE_ToLogical(physDev, XGetPixel(bmpImage, x, h));
3129 *dstpixel++=(GetRValue(srcval) << rShift) |
3130 (GetGValue(srcval) << gShift) |
3131 (GetBValue(srcval) << bShift);
3133 dstbits += linebytes;
3136 break;
3140 /***********************************************************************
3141 * X11DRV_DIB_SetImageBits
3143 * Transfer the bits to an X image.
3144 * Helper function for SetDIBits() and SetDIBitsToDevice().
3146 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3148 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3149 void *old_data = NULL;
3150 XImage *bmpImage;
3152 wine_tsx11_lock();
3153 if (descr->image)
3154 bmpImage = descr->image;
3155 else {
3156 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3157 descr->infoWidth, lines, 32, 0 );
3158 bmpImage->data = HeapAlloc( GetProcessHeap(), 0, lines * bmpImage->bytes_per_line );
3159 if(bmpImage->data == NULL) {
3160 ERR("Out of memory!\n");
3161 XDestroyImage( bmpImage );
3162 wine_tsx11_unlock();
3163 return 0;
3165 if (descr->shifts)
3167 bmpImage->red_mask = descr->shifts->physicalRed.max << descr->shifts->physicalRed.shift;
3168 bmpImage->green_mask = descr->shifts->physicalGreen.max << descr->shifts->physicalGreen.shift;
3169 bmpImage->blue_mask = descr->shifts->physicalBlue.max << descr->shifts->physicalBlue.shift;
3172 wine_tsx11_unlock();
3174 TRACE("Dib: depth=%d r=%x g=%x b=%x\n",
3175 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3176 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3177 bmpImage->depth,bmpImage->bits_per_pixel,
3178 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3180 #ifdef HAVE_LIBXXSHM
3181 if (descr->shm_mode == X11DRV_SHM_PIXMAP
3182 && descr->xSrc == 0 && descr->ySrc == 0
3183 && descr->xDest == 0 && descr->yDest == 0)
3185 TRACE("Using the shared pixmap data.\n");
3187 wine_tsx11_lock();
3188 XSync( gdi_display, False );
3189 wine_tsx11_unlock();
3191 old_data = descr->image->data;
3192 descr->image->data = descr->physBitmap->shminfo.shmaddr;
3194 #endif
3196 /* Transfer the pixels */
3197 __TRY
3199 switch(descr->infoBpp)
3201 case 1:
3202 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3203 descr->width, descr->xSrc, (int *)(descr->colorMap),
3204 bmpImage, descr->dibpitch );
3205 break;
3206 case 4:
3207 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3208 descr->infoWidth, descr->width,
3209 descr->xSrc, (int*)(descr->colorMap),
3210 bmpImage, descr->dibpitch );
3211 break;
3212 case 8:
3213 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3214 descr->infoWidth, descr->width,
3215 descr->xSrc, (int *)(descr->colorMap),
3216 bmpImage, descr->dibpitch );
3217 break;
3218 case 16:
3219 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3220 descr->infoWidth, descr->width,
3221 descr->xSrc, descr->physDev,
3222 descr->rMask, descr->gMask, descr->bMask,
3223 bmpImage, descr->dibpitch);
3224 break;
3225 case 24:
3226 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3227 descr->infoWidth, descr->width,
3228 descr->xSrc, descr->physDev,
3229 descr->rMask, descr->gMask, descr->bMask,
3230 bmpImage, descr->dibpitch);
3231 break;
3232 case 32:
3233 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3234 descr->infoWidth, descr->width,
3235 descr->xSrc, descr->physDev,
3236 descr->rMask, descr->gMask, descr->bMask,
3237 bmpImage, descr->dibpitch);
3238 break;
3239 default:
3240 WARN("(%d): Invalid depth\n", descr->infoBpp );
3241 break;
3244 __EXCEPT_PAGE_FAULT
3246 WARN( "invalid bits pointer %p\n", descr->bits );
3247 lines = 0;
3249 __ENDTRY
3251 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3252 descr->drawable, descr->gc, bmpImage,
3253 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3254 descr->width, descr->height);
3256 wine_tsx11_lock();
3257 if (lines)
3259 #ifdef HAVE_LIBXXSHM
3260 if (descr->shm_mode == X11DRV_SHM_PIXMAP
3261 && descr->xSrc == 0 && descr->ySrc == 0
3262 && descr->xDest == 0 && descr->yDest == 0)
3264 XSync( gdi_display, False );
3266 else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image)
3268 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3269 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3270 descr->width, descr->height, FALSE );
3271 XSync( gdi_display, 0 );
3273 else
3274 #endif
3276 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3277 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3278 descr->width, descr->height );
3282 if (old_data) descr->image->data = old_data;
3284 if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
3285 wine_tsx11_unlock();
3286 return lines;
3289 /***********************************************************************
3290 * X11DRV_DIB_GetImageBits
3292 * Transfer the bits from an X image.
3294 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3296 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3297 void *old_data = NULL;
3298 XImage *bmpImage;
3300 wine_tsx11_lock();
3301 if (descr->image)
3302 bmpImage = descr->image;
3303 else {
3304 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3305 descr->infoWidth, lines, 32, 0 );
3306 bmpImage->data = HeapAlloc( GetProcessHeap(), 0, lines * bmpImage->bytes_per_line );
3307 if(bmpImage->data == NULL) {
3308 ERR("Out of memory!\n");
3309 XDestroyImage( bmpImage );
3310 wine_tsx11_unlock();
3311 return 0;
3313 if (descr->shifts)
3315 bmpImage->red_mask = descr->shifts->physicalRed.max << descr->shifts->physicalRed.shift;
3316 bmpImage->green_mask = descr->shifts->physicalGreen.max << descr->shifts->physicalGreen.shift;
3317 bmpImage->blue_mask = descr->shifts->physicalBlue.max << descr->shifts->physicalBlue.shift;
3321 #ifdef HAVE_LIBXXSHM
3323 /* We must not call XShmGetImage() with a bitmap which is bigger than the available area.
3324 If we do, XShmGetImage() will fail (X exception), as it checks for this internally. */
3325 if (descr->shm_mode == X11DRV_SHM_PIXMAP && descr->image
3326 && descr->xSrc == 0 && descr->ySrc == 0
3327 && descr->xDest == 0 && descr->yDest == 0
3328 && bmpImage->width <= (descr->width - descr->xSrc)
3329 && bmpImage->height <= (descr->height - descr->ySrc))
3331 XSync( gdi_display, False );
3332 old_data = bmpImage->data;
3333 bmpImage->data = descr->physBitmap->shminfo.shmaddr;
3334 TRACE("Using shared pixmap data.\n");
3336 else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image
3337 && bmpImage->width <= (descr->width - descr->xSrc)
3338 && bmpImage->height <= (descr->height - descr->ySrc))
3340 int saveRed, saveGreen, saveBlue;
3342 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3343 gdi_display, descr->drawable, bmpImage,
3344 descr->xSrc, descr->ySrc, AllPlanes);
3346 /* We must save and restore the bmpImage's masks in order
3347 * to preserve them across the call to XShmGetImage, which
3348 * decides to eliminate them since it doesn't happen to know
3349 * what the format of the image is supposed to be, even though
3350 * we do. */
3351 saveRed = bmpImage->red_mask;
3352 saveBlue= bmpImage->blue_mask;
3353 saveGreen = bmpImage->green_mask;
3355 XShmGetImage( gdi_display, descr->drawable, bmpImage,
3356 descr->xSrc, descr->ySrc, AllPlanes);
3358 bmpImage->red_mask = saveRed;
3359 bmpImage->blue_mask = saveBlue;
3360 bmpImage->green_mask = saveGreen;
3362 else
3363 #endif /* HAVE_LIBXXSHM */
3365 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3366 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3367 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3368 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3369 descr->width, lines, AllPlanes, ZPixmap,
3370 bmpImage, descr->xDest, descr->yDest );
3372 wine_tsx11_unlock();
3374 TRACE("Dib: depth=%2d r=%x g=%x b=%x\n",
3375 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3376 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3377 bmpImage->depth,bmpImage->bits_per_pixel,
3378 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3379 /* Transfer the pixels */
3380 switch(descr->infoBpp)
3382 case 1:
3383 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3384 descr->infoWidth, descr->width,
3385 descr->colorMap, descr->palentry,
3386 bmpImage, descr->dibpitch );
3387 break;
3389 case 4:
3390 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3391 descr->infoWidth, descr->width,
3392 descr->colorMap, descr->palentry,
3393 bmpImage, descr->dibpitch );
3394 break;
3395 case 8:
3396 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3397 descr->infoWidth, descr->width,
3398 descr->colorMap, descr->palentry,
3399 bmpImage, descr->dibpitch );
3400 break;
3401 case 16:
3402 X11DRV_DIB_GetImageBits_16( descr->physDev, descr->lines, (LPVOID)descr->bits,
3403 descr->infoWidth,descr->width,
3404 descr->palentry,
3405 descr->rMask, descr->gMask, descr->bMask,
3406 bmpImage, descr->dibpitch );
3407 break;
3409 case 24:
3410 X11DRV_DIB_GetImageBits_24( descr->physDev, descr->lines, (LPVOID)descr->bits,
3411 descr->infoWidth,descr->width,
3412 descr->palentry,
3413 descr->rMask, descr->gMask, descr->bMask,
3414 bmpImage, descr->dibpitch);
3415 break;
3417 case 32:
3418 X11DRV_DIB_GetImageBits_32( descr->physDev, descr->lines, (LPVOID)descr->bits,
3419 descr->infoWidth, descr->width,
3420 descr->palentry,
3421 descr->rMask, descr->gMask, descr->bMask,
3422 bmpImage, descr->dibpitch);
3423 break;
3425 default:
3426 WARN("(%d): Invalid depth\n", descr->infoBpp );
3427 break;
3430 if (old_data) bmpImage->data = old_data;
3431 if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
3432 return lines;
3435 /***********************************************************************
3436 * X11DRV_DIB_DoCopyDIBSection
3438 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
3439 void *colorMap, int nColorMap,
3440 Drawable dest, GC gc,
3441 DWORD xSrc, DWORD ySrc,
3442 DWORD xDest, DWORD yDest,
3443 DWORD width, DWORD height)
3445 DIBSECTION dibSection;
3446 X11DRV_DIB_IMAGEBITS_DESCR descr;
3447 int identity[2] = {0,1};
3449 if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
3451 descr.physDev = NULL;
3452 descr.palentry = NULL;
3453 descr.infoWidth = dibSection.dsBmih.biWidth;
3454 descr.infoBpp = dibSection.dsBmih.biBitCount;
3455 descr.lines = physBitmap->topdown ? -dibSection.dsBmih.biHeight : dibSection.dsBmih.biHeight;
3456 descr.image = physBitmap->image;
3457 descr.colorMap = colorMap;
3458 descr.nColorMap = nColorMap;
3459 descr.bits = dibSection.dsBm.bmBits;
3460 descr.depth = physBitmap->depth;
3461 descr.shifts = physBitmap->trueColor ? &physBitmap->color_shifts : NULL;
3462 descr.compression = dibSection.dsBmih.biCompression;
3463 descr.physBitmap = physBitmap;
3465 if(descr.infoBpp == 1)
3466 descr.colorMap = (void*)identity;
3468 switch (descr.infoBpp)
3470 case 1:
3471 case 4:
3472 case 8:
3473 descr.rMask = descr.gMask = descr.bMask = 0;
3474 break;
3475 case 15:
3476 case 16:
3477 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0x7c00;
3478 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x03e0;
3479 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x001f;
3480 break;
3482 case 24:
3483 case 32:
3484 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0xff0000;
3485 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x00ff00;
3486 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x0000ff;
3487 break;
3490 /* Hack for now */
3491 descr.drawable = dest;
3492 descr.gc = gc;
3493 descr.xSrc = xSrc;
3494 descr.ySrc = ySrc;
3495 descr.xDest = xDest;
3496 descr.yDest = yDest;
3497 descr.width = width;
3498 descr.height = height;
3499 descr.sizeImage = 0;
3501 descr.shm_mode = physBitmap->shm_mode;
3502 #ifdef HAVE_LIBXXSHM
3503 if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP && physBitmap->pixmap != dest)
3505 descr.shm_mode = X11DRV_SHM_NONE;
3507 #endif
3508 descr.dibpitch = dibSection.dsBm.bmWidthBytes;
3510 if (toDIB)
3512 TRACE("Copying from Pixmap to DIB bits\n");
3513 X11DRV_DIB_GetImageBits( &descr );
3515 else
3517 TRACE("Copying from DIB bits to Pixmap\n");
3518 X11DRV_DIB_SetImageBits( &descr );
3522 /***********************************************************************
3523 * X11DRV_DIB_DoUpdateDIBSection
3525 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
3527 BITMAP bitmap;
3529 GetObjectW( physBitmap->hbitmap, sizeof(bitmap), &bitmap );
3530 X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
3531 physBitmap->colorMap, physBitmap->nColorMap,
3532 physBitmap->pixmap, get_bitmap_gc(physBitmap->depth),
3533 0, 0, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
3536 /***********************************************************************
3537 * X11DRV_DIB_FaultHandler
3539 static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep )
3541 X_PHYSBITMAP *physBitmap = NULL;
3542 BOOL found = FALSE;
3543 BYTE *addr;
3544 struct list *ptr;
3545 const size_t pagemask = getpagesize() - 1;
3547 if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
3548 return EXCEPTION_CONTINUE_SEARCH;
3550 addr = (BYTE *)ep->ExceptionRecord->ExceptionInformation[1];
3552 EnterCriticalSection(&dibs_cs);
3553 LIST_FOR_EACH( ptr, &dibs_list )
3555 physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry );
3556 if ((physBitmap->base <= addr) &&
3557 (addr < physBitmap->base + ((physBitmap->size + pagemask) & ~pagemask)))
3559 found = TRUE;
3560 break;
3563 LeaveCriticalSection(&dibs_cs);
3565 if (!found) return EXCEPTION_CONTINUE_SEARCH;
3567 if (addr >= physBitmap->base + physBitmap->size)
3568 WARN( "%p: access to %p beyond the end of the DIB\n", physBitmap->hbitmap, addr );
3570 X11DRV_DIB_Lock( physBitmap, DIB_Status_None );
3571 if (ep->ExceptionRecord->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT) {
3572 /* the app tried to write the DIB bits */
3573 X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod);
3574 } else {
3575 /* the app tried to read the DIB bits */
3576 X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync);
3578 X11DRV_DIB_Unlock( physBitmap, TRUE );
3580 return EXCEPTION_CONTINUE_EXECUTION;
3583 /***********************************************************************
3584 * X11DRV_DIB_Coerce
3586 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *physBitmap, INT req)
3588 INT ret = DIB_Status_None;
3590 if (!physBitmap->image) return ret; /* not a DIB section */
3591 EnterCriticalSection(&physBitmap->lock);
3592 ret = physBitmap->status;
3593 switch (req) {
3594 case DIB_Status_GdiMod:
3595 /* GDI access - request to draw on pixmap */
3596 switch (physBitmap->status)
3598 default:
3599 case DIB_Status_None:
3600 physBitmap->p_status = DIB_Status_GdiMod;
3601 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
3602 break;
3604 case DIB_Status_GdiMod:
3605 TRACE("GdiMod requested in status GdiMod\n" );
3606 physBitmap->p_status = DIB_Status_GdiMod;
3607 break;
3609 case DIB_Status_InSync:
3610 TRACE("GdiMod requested in status InSync\n" );
3611 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
3612 physBitmap->status = DIB_Status_GdiMod;
3613 physBitmap->p_status = DIB_Status_InSync;
3614 break;
3616 case DIB_Status_AppMod:
3617 TRACE("GdiMod requested in status AppMod\n" );
3618 /* make it readonly to avoid app changing data while we copy */
3619 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
3620 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
3621 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
3622 physBitmap->p_status = DIB_Status_AppMod;
3623 physBitmap->status = DIB_Status_GdiMod;
3624 break;
3626 break;
3628 case DIB_Status_InSync:
3629 /* App access - request access to read DIB surface */
3630 /* (typically called from signal handler) */
3631 switch (physBitmap->status)
3633 default:
3634 case DIB_Status_None:
3635 /* shouldn't happen from signal handler */
3636 break;
3638 case DIB_Status_GdiMod:
3639 TRACE("InSync requested in status GdiMod\n" );
3640 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3641 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
3642 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
3643 physBitmap->status = DIB_Status_InSync;
3644 break;
3646 case DIB_Status_InSync:
3647 TRACE("InSync requested in status InSync\n" );
3648 /* shouldn't happen from signal handler */
3649 break;
3651 case DIB_Status_AppMod:
3652 TRACE("InSync requested in status AppMod\n" );
3653 /* no reason to do anything here, and this
3654 * shouldn't happen from signal handler */
3655 break;
3657 break;
3659 case DIB_Status_AppMod:
3660 /* App access - request access to write DIB surface */
3661 /* (typically called from signal handler) */
3662 switch (physBitmap->status)
3664 default:
3665 case DIB_Status_None:
3666 /* shouldn't happen from signal handler */
3667 break;
3669 case DIB_Status_GdiMod:
3670 TRACE("AppMod requested in status GdiMod\n" );
3671 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3672 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
3673 physBitmap->status = DIB_Status_AppMod;
3674 break;
3676 case DIB_Status_InSync:
3677 TRACE("AppMod requested in status InSync\n" );
3678 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3679 physBitmap->status = DIB_Status_AppMod;
3680 break;
3682 case DIB_Status_AppMod:
3683 TRACE("AppMod requested in status AppMod\n" );
3684 /* shouldn't happen from signal handler */
3685 break;
3687 break;
3689 /* it is up to the caller to do the copy/conversion, probably
3690 * using the return value to decide where to copy from */
3692 LeaveCriticalSection(&physBitmap->lock);
3693 return ret;
3696 /***********************************************************************
3697 * X11DRV_DIB_Lock
3699 INT X11DRV_DIB_Lock(X_PHYSBITMAP *physBitmap, INT req)
3701 INT ret = DIB_Status_None;
3703 if (!physBitmap->image) return ret; /* not a DIB section */
3704 TRACE("Locking %p from thread %04x\n", physBitmap->hbitmap, GetCurrentThreadId());
3705 EnterCriticalSection(&physBitmap->lock);
3706 ret = physBitmap->status;
3707 if (req != DIB_Status_None)
3708 X11DRV_DIB_Coerce(physBitmap, req);
3709 return ret;
3712 /***********************************************************************
3713 * X11DRV_DIB_Unlock
3715 void X11DRV_DIB_Unlock(X_PHYSBITMAP *physBitmap, BOOL commit)
3717 if (!physBitmap->image) return; /* not a DIB section */
3718 switch (physBitmap->status)
3720 default:
3721 case DIB_Status_None:
3722 /* in case anyone is wondering, this is the "signal handler doesn't
3723 * work" case, where we always have to be ready for app access */
3724 if (commit) {
3725 switch (physBitmap->p_status)
3727 case DIB_Status_GdiMod:
3728 TRACE("Unlocking and syncing from GdiMod\n" );
3729 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
3730 break;
3732 default:
3733 TRACE("Unlocking without needing to sync\n" );
3734 break;
3737 else TRACE("Unlocking with no changes\n");
3738 physBitmap->p_status = DIB_Status_None;
3739 break;
3741 case DIB_Status_GdiMod:
3742 TRACE("Unlocking in status GdiMod\n" );
3743 /* DIB was protected in Coerce */
3744 if (!commit) {
3745 /* no commit, revert to InSync if applicable */
3746 if ((physBitmap->p_status == DIB_Status_InSync) ||
3747 (physBitmap->p_status == DIB_Status_AppMod)) {
3748 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
3749 physBitmap->status = DIB_Status_InSync;
3752 break;
3754 case DIB_Status_InSync:
3755 TRACE("Unlocking in status InSync\n" );
3756 /* DIB was already protected in Coerce */
3757 break;
3759 case DIB_Status_AppMod:
3760 TRACE("Unlocking in status AppMod\n" );
3761 /* DIB was already protected in Coerce */
3762 /* this case is ordinary only called from the signal handler,
3763 * so we don't bother to check for !commit */
3764 break;
3766 LeaveCriticalSection(&physBitmap->lock);
3767 TRACE("Unlocked %p\n", physBitmap->hbitmap);
3770 /***********************************************************************
3771 * X11DRV_CoerceDIBSection
3773 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req)
3775 if (!physDev || !physDev->bitmap) return DIB_Status_None;
3776 return X11DRV_DIB_Coerce(physDev->bitmap, req);
3779 /***********************************************************************
3780 * X11DRV_LockDIBSection
3782 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req)
3784 if (!physDev || !physDev->bitmap) return DIB_Status_None;
3785 return X11DRV_DIB_Lock(physDev->bitmap, req);
3788 /***********************************************************************
3789 * X11DRV_UnlockDIBSection
3791 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
3793 if (!physDev || !physDev->bitmap) return;
3794 X11DRV_DIB_Unlock(physDev->bitmap, commit);
3798 #ifdef HAVE_LIBXXSHM
3799 /***********************************************************************
3800 * X11DRV_XShmErrorHandler
3803 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
3805 return 1; /* FIXME: should check event contents */
3808 /***********************************************************************
3809 * X11DRV_XShmCreateImage
3812 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
3813 XShmSegmentInfo* shminfo)
3815 XImage *image;
3817 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
3818 if (image)
3820 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
3821 IPC_CREAT|0700);
3822 if( shminfo->shmid != -1 )
3824 shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 );
3825 if( shminfo->shmaddr != (char*)-1 )
3827 BOOL ok;
3829 shminfo->readOnly = FALSE;
3830 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
3831 ok = (XShmAttach( gdi_display, shminfo ) != 0);
3832 XSync( gdi_display, False );
3833 if (X11DRV_check_error()) ok = FALSE;
3834 if (ok)
3836 shmctl(shminfo->shmid, IPC_RMID, 0);
3837 return image; /* Success! */
3839 /* An error occurred */
3840 shmdt(shminfo->shmaddr);
3842 shmctl(shminfo->shmid, IPC_RMID, 0);
3843 shminfo->shmid = -1;
3845 XFlush(gdi_display);
3846 XDestroyImage(image);
3847 image = NULL;
3849 return image;
3851 #endif /* HAVE_LIBXXSHM */
3853 static Bool X11DRV_DIB_QueryXShm( Bool *pixmaps )
3855 static Bool have_xshm, have_xshm_pixmaps;
3856 static BOOL initialized;
3858 if (!initialized)
3860 #ifdef HAVE_LIBXXSHM
3861 int major, minor;
3863 have_xshm = XShmQueryVersion( gdi_display, &major, &minor, &have_xshm_pixmaps );
3864 #endif
3865 initialized = TRUE;
3868 *pixmaps = have_xshm_pixmaps;
3869 return have_xshm;
3872 /***********************************************************************
3873 * X11DRV_CreateDIBSection (X11DRV.@)
3875 HBITMAP X11DRV_CreateDIBSection( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *bmi, UINT usage )
3877 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
3878 X_PHYSBITMAP *physBitmap;
3879 DIBSECTION dib;
3880 #ifdef HAVE_LIBXXSHM
3881 Bool pixmaps;
3882 #endif
3884 if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
3885 physBitmap->topdown = bmi->bmiHeader.biHeight < 0;
3886 physBitmap->status = DIB_Status_None;
3888 GetObjectW( hbitmap, sizeof(dib), &dib );
3890 /* create color map */
3891 if (dib.dsBm.bmBitsPixel <= 8)
3893 physBitmap->colorMap = X11DRV_DIB_BuildColorMap( physDev,
3894 usage, dib.dsBm.bmBitsPixel, bmi,
3895 &physBitmap->nColorMap );
3898 if (!X11DRV_XRender_SetPhysBitmapDepth( physBitmap, dib.dsBm.bmBitsPixel, &dib ))
3900 if (dib.dsBm.bmBitsPixel == 1)
3902 physBitmap->depth = 1;
3903 physBitmap->trueColor = FALSE;
3905 else
3907 physBitmap->depth = screen_depth;
3908 physBitmap->color_shifts = X11DRV_PALETTE_default_shifts;
3909 physBitmap->trueColor = (visual->class == TrueColor || visual->class == DirectColor);
3913 /* create pixmap and X image */
3914 wine_tsx11_lock();
3915 #ifdef HAVE_LIBXXSHM
3916 physBitmap->shminfo.shmid = -1;
3918 if (X11DRV_DIB_QueryXShm( &pixmaps )
3919 && (physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
3920 physBitmap->depth, &physBitmap->shminfo )))
3922 if (pixmaps)
3924 physBitmap->shm_mode = X11DRV_SHM_PIXMAP;
3925 physBitmap->image->data = HeapAlloc( GetProcessHeap(), 0,
3926 dib.dsBm.bmHeight * physBitmap->image->bytes_per_line );
3928 else
3930 physBitmap->shm_mode = X11DRV_SHM_IMAGE;
3931 physBitmap->image->data = physBitmap->shminfo.shmaddr;
3934 else
3935 #endif
3937 physBitmap->shm_mode = X11DRV_SHM_NONE;
3938 physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
3939 physBitmap->depth );
3942 #ifdef HAVE_LIBXXSHM
3943 if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP)
3945 TRACE("Creating shared pixmap for bmp %p.\n", physBitmap->hbitmap);
3946 physBitmap->pixmap = XShmCreatePixmap( gdi_display, root_window,
3947 physBitmap->shminfo.shmaddr, &physBitmap->shminfo,
3948 dib.dsBm.bmWidth, dib.dsBm.bmHeight,
3949 physBitmap->depth );
3951 else
3952 #endif
3954 physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
3955 dib.dsBm.bmHeight, physBitmap->depth );
3958 wine_tsx11_unlock();
3959 if (!physBitmap->pixmap || !physBitmap->image) return 0;
3961 if (physBitmap->trueColor)
3963 ColorShifts *shifts = &physBitmap->color_shifts;
3965 /* When XRender is around and used, we also support dibsections in other formats like 16-bit. In these
3966 * cases we need to override the mask of XImages. The reason is that during XImage creation the masks are
3967 * derived from a 24-bit visual (no 16-bit ones are around when X runs at 24-bit). SetImageBits and other
3968 * functions rely on the color masks for proper color conversion, so we need to override the masks here. */
3969 physBitmap->image->red_mask = shifts->physicalRed.max << shifts->physicalRed.shift;
3970 physBitmap->image->green_mask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
3971 physBitmap->image->blue_mask = shifts->physicalBlue.max << shifts->physicalBlue.shift;
3974 /* install fault handler */
3975 InitializeCriticalSection( &physBitmap->lock );
3976 physBitmap->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": X_PHYSBITMAP.lock");
3978 physBitmap->base = dib.dsBm.bmBits;
3979 physBitmap->size = dib.dsBmih.biSizeImage;
3980 physBitmap->status = DIB_Status_AppMod;
3982 if (!dibs_handler)
3983 dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler );
3984 EnterCriticalSection( &dibs_cs );
3985 list_add_head( &dibs_list, &physBitmap->entry );
3986 LeaveCriticalSection( &dibs_cs );
3988 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
3990 return hbitmap;
3993 /***********************************************************************
3994 * X11DRV_DIB_DeleteDIBSection
3996 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
3998 BOOL last;
4000 EnterCriticalSection( &dibs_cs );
4001 list_remove( &physBitmap->entry );
4002 last = list_empty( &dibs_list );
4003 LeaveCriticalSection( &dibs_cs );
4005 if (last)
4007 RemoveVectoredExceptionHandler( dibs_handler );
4008 dibs_handler = NULL;
4011 if (dib->dshSection)
4012 X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync);
4014 if (physBitmap->image)
4016 wine_tsx11_lock();
4017 #ifdef HAVE_LIBXXSHM
4018 if (physBitmap->shminfo.shmid != -1)
4020 XShmDetach( gdi_display, &(physBitmap->shminfo) );
4021 if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP) X11DRV_DIB_DestroyXImage( physBitmap->image );
4022 else XDestroyImage( physBitmap->image );
4023 shmdt( physBitmap->shminfo.shmaddr );
4024 physBitmap->shminfo.shmid = -1;
4025 physBitmap->shm_mode = X11DRV_SHM_NONE;
4027 else
4028 #endif
4029 X11DRV_DIB_DestroyXImage( physBitmap->image );
4030 wine_tsx11_unlock();
4033 HeapFree(GetProcessHeap(), 0, physBitmap->colorMap);
4034 physBitmap->lock.DebugInfo->Spare[0] = 0;
4035 DeleteCriticalSection(&physBitmap->lock);
4038 /***********************************************************************
4039 * SetDIBColorTable (X11DRV.@)
4041 UINT X11DRV_SetDIBColorTable( PHYSDEV dev, UINT start, UINT count, const RGBQUAD *colors )
4043 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
4044 DIBSECTION dib;
4045 UINT ret = 0;
4046 X_PHYSBITMAP *physBitmap = physDev->bitmap;
4048 if (!physBitmap) return 0;
4049 GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4051 if (physBitmap->colorMap && start < physBitmap->nColorMap) {
4052 UINT end = count + start;
4053 if (end > physBitmap->nColorMap) end = physBitmap->nColorMap;
4055 * Changing color table might change the mapping between
4056 * DIB colors and X11 colors and thus alter the visible state
4057 * of the bitmap object.
4060 * FIXME we need to recalculate the pen, brush, text and bkgnd pixels here,
4061 * at least for a 1 bpp dibsection
4063 X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod );
4064 X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
4065 dib.dsBm.bmBitsPixel, colors, start, end );
4066 X11DRV_DIB_Unlock( physBitmap, TRUE );
4067 ret = end - start;
4069 return ret;
4073 /***********************************************************************
4074 * X11DRV_DIB_CreateDIBFromBitmap
4076 * Allocates a packed DIB and copies the bitmap data into it.
4078 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4080 BITMAP bmp;
4081 HGLOBAL hPackedDIB;
4082 LPBYTE pPackedDIB;
4083 LPBITMAPINFOHEADER pbmiHeader;
4084 unsigned int cDataSize, cPackedSize, OffsetBits;
4085 int nLinesCopied;
4087 if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4090 * A packed DIB contains a BITMAPINFO structure followed immediately by
4091 * an optional color palette and the pixel data.
4094 /* Calculate the size of the packed DIB */
4095 cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4096 cPackedSize = sizeof(BITMAPINFOHEADER)
4097 + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4098 + cDataSize;
4099 /* Get the offset to the bits */
4100 OffsetBits = cPackedSize - cDataSize;
4102 /* Allocate the packed DIB */
4103 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4104 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4105 cPackedSize );
4106 if ( !hPackedDIB )
4108 WARN("Could not allocate packed DIB!\n");
4109 return 0;
4112 /* A packed DIB starts with a BITMAPINFOHEADER */
4113 pPackedDIB = GlobalLock(hPackedDIB);
4114 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4116 /* Init the BITMAPINFOHEADER */
4117 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4118 pbmiHeader->biWidth = bmp.bmWidth;
4119 pbmiHeader->biHeight = bmp.bmHeight;
4120 pbmiHeader->biPlanes = 1;
4121 pbmiHeader->biBitCount = bmp.bmBitsPixel;
4122 pbmiHeader->biCompression = BI_RGB;
4123 pbmiHeader->biSizeImage = 0;
4124 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4125 pbmiHeader->biClrUsed = 0;
4126 pbmiHeader->biClrImportant = 0;
4128 /* Retrieve the DIB bits from the bitmap and fill in the
4129 * DIB color table if present */
4131 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
4132 hBmp, /* Handle to bitmap */
4133 0, /* First scan line to set in dest bitmap */
4134 bmp.bmHeight, /* Number of scan lines to copy */
4135 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
4136 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4137 0); /* RGB or palette index */
4138 GlobalUnlock(hPackedDIB);
4140 /* Cleanup if GetDIBits failed */
4141 if (nLinesCopied != bmp.bmHeight)
4143 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4144 GlobalFree(hPackedDIB);
4145 hPackedDIB = 0;
4147 return hPackedDIB;
4151 /**************************************************************************
4152 * X11DRV_DIB_CreateDIBFromPixmap
4154 * Allocates a packed DIB and copies the Pixmap data into it.
4155 * The Pixmap passed in is deleted after the conversion.
4157 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc)
4159 HDC hdcMem;
4160 X_PHYSBITMAP *physBitmap;
4161 Pixmap orig_pixmap;
4162 HBITMAP hBmp = 0;
4163 HGLOBAL hPackedDIB = 0;
4164 Window root;
4165 int x,y; /* Unused */
4166 unsigned border_width; /* Unused */
4167 unsigned int depth, width, height;
4169 /* Get the Pixmap dimensions and bit depth */
4170 wine_tsx11_lock();
4171 if (!XGetGeometry(gdi_display, pixmap, &root, &x, &y, &width, &height,
4172 &border_width, &depth)) depth = 0;
4173 wine_tsx11_unlock();
4174 if (!pixmap_formats[depth]) return 0;
4176 TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4177 width, height, depth);
4180 * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4181 * and make it a container for the pixmap passed.
4183 if (!(hBmp = CreateBitmap( width, height, 1, pixmap_formats[depth]->bits_per_pixel, NULL ))) return 0;
4185 /* force bitmap to be owned by a screen DC */
4186 hdcMem = CreateCompatibleDC( hdc );
4187 SelectObject( hdcMem, SelectObject( hdcMem, hBmp ));
4188 DeleteDC( hdcMem );
4190 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4192 /* swap the new pixmap in */
4193 orig_pixmap = physBitmap->pixmap;
4194 physBitmap->pixmap = pixmap;
4197 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4198 * A packed DIB contains a BITMAPINFO structure followed immediately by
4199 * an optional color palette and the pixel data.
4201 hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4203 /* we can now get rid of the HBITMAP and its original pixmap */
4204 physBitmap->pixmap = orig_pixmap;
4205 DeleteObject(hBmp);
4207 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4208 return hPackedDIB;
4212 /**************************************************************************
4213 * X11DRV_DIB_CreatePixmapFromDIB
4215 * Creates a Pixmap from a packed DIB
4217 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4219 Pixmap pixmap = 0;
4220 X_PHYSBITMAP *physBitmap;
4221 HBITMAP hBmp;
4222 LPBITMAPINFO pbmi;
4223 HDC memdc;
4225 /* Create a DDB from the DIB */
4227 pbmi = GlobalLock(hPackedDIB);
4228 hBmp = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
4229 (LPBYTE)pbmi + bitmap_info_size( pbmi, DIB_RGB_COLORS ),
4230 pbmi, DIB_RGB_COLORS);
4231 GlobalUnlock(hPackedDIB);
4233 /* make sure it's owned by x11drv */
4234 memdc = CreateCompatibleDC( hdc );
4235 SelectObject( memdc, hBmp );
4236 DeleteDC( memdc );
4238 /* clear the physBitmap so that we can steal its pixmap */
4239 if ((physBitmap = X11DRV_get_phys_bitmap( hBmp )))
4241 pixmap = physBitmap->pixmap;
4242 physBitmap->pixmap = 0;
4245 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4246 DeleteObject(hBmp);
4248 TRACE("Returning Pixmap %lx\n", pixmap);
4249 return pixmap;