Make the testing framework thread safe.
[wine/gsoc_dplay.git] / graphics / x11drv / dib.c
blob7354b0393804ce7b25baf0aeb86730b4c8451ef7
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "ts_xlib.h"
24 #include "ts_xutil.h"
25 #ifdef HAVE_LIBXXSHM
26 # include "ts_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 <stdlib.h>
36 #include <string.h>
37 #include "windef.h"
38 #include "bitmap.h"
39 #include "x11drv.h"
40 #include "wine/debug.h"
41 #include "gdi.h"
42 #include "palette.h"
43 #include "global.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
46 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
48 static int ximageDepthTable[32];
50 #ifdef HAVE_LIBXXSHM
51 static int XShmErrorFlag = 0;
52 #endif
54 /* This structure holds the arguments for DIB_SetImageBits() */
55 typedef struct
57 X11DRV_PDEVICE *physDev;
58 LPCVOID bits;
59 XImage *image;
60 PALETTEENTRY *palentry;
61 int lines;
62 DWORD infoWidth;
63 WORD depth;
64 WORD infoBpp;
65 WORD compression;
66 RGBQUAD *colorMap;
67 int nColorMap;
68 Drawable drawable;
69 GC gc;
70 int xSrc;
71 int ySrc;
72 int xDest;
73 int yDest;
74 int width;
75 int height;
76 DWORD rMask;
77 DWORD gMask;
78 DWORD bMask;
79 BOOL useShm;
80 int dibpitch;
81 } X11DRV_DIB_IMAGEBITS_DESCR;
84 enum Rle_EscapeCodes
86 RLE_EOL = 0, /* End of line */
87 RLE_END = 1, /* End of bitmap */
88 RLE_DELTA = 2 /* Delta */
91 /***********************************************************************
92 * X11DRV_DIB_GetXImageWidthBytes
94 * Return the width of an X image in bytes
96 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
98 if (!depth || depth > 32) goto error;
100 if (!ximageDepthTable[depth-1])
102 XImage *testimage = XCreateImage( gdi_display, visual, depth,
103 ZPixmap, 0, NULL, 1, 1, 32, 20 );
104 if (testimage)
106 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
107 XDestroyImage( testimage );
109 else ximageDepthTable[depth-1] = -1;
111 if (ximageDepthTable[depth-1] != -1)
112 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
114 error:
115 WARN( "(%d): Unsupported depth\n", depth );
116 return 4 * width;
120 /***********************************************************************
121 * X11DRV_DIB_CreateXImage
123 * Create an X image.
125 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
127 int width_bytes;
128 XImage *image;
130 wine_tsx11_lock();
131 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
132 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
133 calloc( height, width_bytes ),
134 width, height, 32, width_bytes );
135 wine_tsx11_unlock();
136 return image;
140 /***********************************************************************
141 * X11DRV_DIB_GenColorMap
143 * Fills the color map of a bitmap palette. Should not be called
144 * for a >8-bit deep bitmap.
146 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
147 WORD coloruse, WORD depth, BOOL quads,
148 const void *colorPtr, int start, int end )
150 int i;
152 if (coloruse == DIB_RGB_COLORS)
154 int max = 1 << depth;
156 if (end > max) end = max;
158 if (quads)
160 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
162 if (depth == 1) /* Monochrome */
163 for (i = start; i < end; i++, rgb++)
164 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
165 rgb->rgbBlue > 255*3/2);
166 else
167 for (i = start; i < end; i++, rgb++)
168 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
169 rgb->rgbGreen,
170 rgb->rgbBlue));
172 else
174 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
176 if (depth == 1) /* Monochrome */
177 for (i = start; i < end; i++, rgb++)
178 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
179 rgb->rgbtBlue > 255*3/2);
180 else
181 for (i = start; i < end; i++, rgb++)
182 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
183 rgb->rgbtGreen,
184 rgb->rgbtBlue));
187 else /* DIB_PAL_COLORS */
189 if (colorPtr) {
190 WORD * index = (WORD *)colorPtr;
192 for (i = start; i < end; i++, index++)
193 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
194 } else {
195 for (i = start; i < end; i++)
196 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
200 return colorMapping;
203 /***********************************************************************
204 * X11DRV_DIB_BuildColorMap
206 * Build the color map from the bitmap palette. Should not be called
207 * for a >8-bit deep bitmap.
209 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
210 const BITMAPINFO *info, int *nColors )
212 int colors;
213 BOOL isInfo;
214 const void *colorPtr;
215 int *colorMapping;
217 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
219 colors = info->bmiHeader.biClrUsed;
220 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
221 colorPtr = info->bmiColors;
223 else /* assume BITMAPCOREINFO */
225 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
226 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
229 if (colors > 256)
231 ERR("called with >256 colors!\n");
232 return NULL;
235 /* just so CopyDIBSection doesn't have to create an identity palette */
236 if (coloruse == (WORD)-1) colorPtr = NULL;
238 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
239 colors * sizeof(int) )))
240 return NULL;
242 *nColors = colors;
243 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
244 isInfo, colorPtr, 0, colors);
248 /***********************************************************************
249 * X11DRV_DIB_MapColor
251 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
253 int color;
255 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
256 return oldcol;
258 for (color = 0; color < nPhysMap; color++)
259 if (physMap[color] == phys)
260 return color;
262 WARN("Strange color %08x\n", phys);
263 return 0;
267 /*********************************************************************
268 * X11DRV_DIB_GetNearestIndex
270 * Helper for X11DRV_DIB_GetDIBits.
271 * Returns the nearest colour table index for a given RGB.
272 * Nearest is defined by minimizing the sum of the squares.
274 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
276 INT i, best = -1, diff, bestdiff = -1;
277 RGBQUAD *color;
279 for(color = colormap, i = 0; i < numColors; color++, i++) {
280 diff = (r - color->rgbRed) * (r - color->rgbRed) +
281 (g - color->rgbGreen) * (g - color->rgbGreen) +
282 (b - color->rgbBlue) * (b - color->rgbBlue);
283 if(diff == 0)
284 return i;
285 if(best == -1 || diff < bestdiff) {
286 best = i;
287 bestdiff = diff;
290 return best;
292 /*********************************************************************
293 * X11DRV_DIB_MaskToShift
295 * Helper for X11DRV_DIB_GetDIBits.
296 * Returns the by how many bits to shift a given color so that it is
297 * in the proper position.
299 static INT X11DRV_DIB_MaskToShift(DWORD mask)
301 int shift;
303 if (mask==0)
304 return 0;
306 shift=0;
307 while ((mask&1)==0) {
308 mask>>=1;
309 shift++;
311 return shift;
314 /***********************************************************************
315 * X11DRV_DIB_Convert_any_asis
317 * All X11DRV_DIB_Convert_Xxx functions take at least the following
318 * parameters:
319 * - width
320 * This is the width in pixel of the surface to copy. This may be less
321 * than the full width of the image.
322 * - height
323 * The number of lines to copy. This may be less than the full height
324 * of the image. This is always >0.
325 * - srcbits
326 * Points to the first byte containing data to be copied. If the source
327 * surface starts are coordinates (x,y) then this is:
328 * image_ptr+x*bytes_pre_pixel+y*bytes_per_line
329 * (with further adjustments for top-down/bottom-up images)
330 * - srclinebytes
331 * This is the number of bytes per line. It may be >0 or <0 depending on
332 * whether this is a top-down or bottom-up image.
333 * - dstbits
334 * Same as srcbits but for the destination
335 * - dstlinebytes
336 * Same as srclinebytes but for the destination.
338 * Notes:
339 * - The supported Dib formats are: pal1, pal4, pal8, rgb555, bgr555,
340 * rgb565, bgr565, rgb888 and any 32bit (0888) format.
341 * The supported XImage (Bmp) formats are: pal1, pal4, pal8,
342 * rgb555, bgr555, rgb565, bgr565, rgb888, bgr888, rgb0888, bgr0888.
343 * - Rgb formats are those for which the masks are such that:
344 * red_mask > green_mask > blue_mask
345 * - Bgr formats are those for which the masks sort in the other direction.
346 * - Many conversion functions handle both rgb->bgr and bgr->rgb conversions
347 * so the comments use h, g, l to mean respectively the source color in the
348 * high bits, the green, and the source color in the low bits.
350 static void X11DRV_DIB_Convert_any_asis(int width, int height,
351 int bytes_per_pixel,
352 const void* srcbits, int srclinebytes,
353 void* dstbits, int dstlinebytes)
355 int y;
357 width*=bytes_per_pixel;
358 for (y=0; y<height; y++) {
359 memcpy(dstbits, srcbits, width);
360 srcbits += srclinebytes;
361 dstbits += dstlinebytes;
366 * 15 bit conversions
369 static void X11DRV_DIB_Convert_555_reverse(int width, int height,
370 const void* srcbits, int srclinebytes,
371 void* dstbits, int dstlinebytes)
373 const DWORD* srcpixel;
374 DWORD* dstpixel;
375 int x,y;
377 for (y=0; y<height; y++) {
378 srcpixel=srcbits;
379 dstpixel=dstbits;
380 for (x=0; x<width/2; x++) {
381 /* Do 2 pixels at a time */
382 DWORD srcval;
383 srcval=*srcpixel++;
384 *dstpixel++=((srcval << 10) & 0x7c007c00) | /* h */
385 ( srcval & 0x03e003e0) | /* g */
386 ((srcval >> 10) & 0x001f001f); /* l */
388 if (width&1) {
389 /* And the the odd pixel */
390 WORD srcval;
391 srcval=*((WORD*)srcpixel);
392 *((WORD*)dstpixel)=((srcval << 10) & 0x7c00) | /* h */
393 ( srcval & 0x03e0) | /* g */
394 ((srcval >> 10) & 0x001f); /* l */
396 srcbits += srclinebytes;
397 dstbits += dstlinebytes;
401 static void X11DRV_DIB_Convert_555_to_565_asis(int width, int height,
402 const void* srcbits, int srclinebytes,
403 void* dstbits, int dstlinebytes)
405 const DWORD* srcpixel;
406 DWORD* dstpixel;
407 int x,y;
409 for (y=0; y<height; y++) {
410 srcpixel=srcbits;
411 dstpixel=dstbits;
412 for (x=0; x<width/2; x++) {
413 /* Do 2 pixels at a time */
414 DWORD srcval;
415 srcval=*srcpixel++;
416 *dstpixel++=((srcval << 1) & 0xffc0ffc0) | /* h, g */
417 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
418 ( srcval & 0x001f001f); /* l */
420 if (width&1) {
421 /* And the the odd pixel */
422 WORD srcval;
423 srcval=*((WORD*)srcpixel);
424 *((WORD*)dstpixel)=((srcval << 1) & 0xffc0) | /* h, g */
425 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
426 (srcval & 0x001f); /* l */
428 srcbits += srclinebytes;
429 dstbits += dstlinebytes;
433 static void X11DRV_DIB_Convert_555_to_565_reverse(int width, int height,
434 const void* srcbits, int srclinebytes,
435 void* dstbits, int dstlinebytes)
437 const DWORD* srcpixel;
438 DWORD* dstpixel;
439 int x,y;
441 for (y=0; y<height; y++) {
442 srcpixel=srcbits;
443 dstpixel=dstbits;
444 for (x=0; x<width/2; x++) {
445 /* Do 2 pixels at a time */
446 DWORD srcval;
447 srcval=*srcpixel++;
448 *dstpixel++=((srcval >> 10) & 0x001f001f) | /* h */
449 ((srcval << 1) & 0x07c007c0) | /* g */
450 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
451 ((srcval << 11) & 0xf800f800); /* l */
453 if (width&1) {
454 /* And the the odd pixel */
455 WORD srcval;
456 srcval=*((WORD*)srcpixel);
457 *((WORD*)dstpixel)=((srcval >> 10) & 0x001f) | /* h */
458 ((srcval << 1) & 0x07c0) | /* g */
459 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
460 ((srcval << 11) & 0xf800); /* l */
462 srcbits += srclinebytes;
463 dstbits += dstlinebytes;
467 static void X11DRV_DIB_Convert_555_to_888_asis(int width, int height,
468 const void* srcbits, int srclinebytes,
469 void* dstbits, int dstlinebytes)
471 const WORD* srcpixel;
472 BYTE* dstpixel;
473 int x,y;
475 for (y=0; y<height; y++) {
476 srcpixel=srcbits;
477 dstpixel=dstbits;
478 for (x=0; x<width; x++) {
479 WORD srcval;
480 srcval=*srcpixel++;
481 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
482 ((srcval >> 2) & 0x07); /* l - 3 bits */
483 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
484 ((srcval >> 7) & 0x07); /* g - 3 bits */
485 dstpixel[2]=((srcval >> 7) & 0xf8) | /* h */
486 ((srcval >> 12) & 0x07); /* h - 3 bits */
487 dstpixel+=3;
489 srcbits += srclinebytes;
490 dstbits += dstlinebytes;
494 static void X11DRV_DIB_Convert_555_to_888_reverse(int width, int height,
495 const void* srcbits, int srclinebytes,
496 void* dstbits, int dstlinebytes)
498 const WORD* srcpixel;
499 BYTE* dstpixel;
500 int x,y;
502 for (y=0; y<height; y++) {
503 srcpixel=srcbits;
504 dstpixel=dstbits;
505 for (x=0; x<width; x++) {
506 WORD srcval;
507 srcval=*srcpixel++;
508 dstpixel[0]=((srcval >> 7) & 0xf8) | /* h */
509 ((srcval >> 12) & 0x07); /* h - 3 bits */
510 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
511 ((srcval >> 7) & 0x07); /* g - 3 bits */
512 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
513 ((srcval >> 2) & 0x07); /* l - 3 bits */
514 dstpixel+=3;
516 srcbits += srclinebytes;
517 dstbits += dstlinebytes;
521 static void X11DRV_DIB_Convert_555_to_0888_asis(int width, int height,
522 const void* srcbits, int srclinebytes,
523 void* dstbits, int dstlinebytes)
525 const WORD* srcpixel;
526 DWORD* dstpixel;
527 int x,y;
529 for (y=0; y<height; y++) {
530 srcpixel=srcbits;
531 dstpixel=dstbits;
532 for (x=0; x<width; x++) {
533 WORD srcval;
534 srcval=*srcpixel++;
535 *dstpixel++=((srcval << 9) & 0xf80000) | /* h */
536 ((srcval << 4) & 0x070000) | /* h - 3 bits */
537 ((srcval << 6) & 0x00f800) | /* g */
538 ((srcval << 1) & 0x000700) | /* g - 3 bits */
539 ((srcval << 3) & 0x0000f8) | /* l */
540 ((srcval >> 2) & 0x000007); /* l - 3 bits */
542 srcbits += srclinebytes;
543 dstbits += dstlinebytes;
547 static void X11DRV_DIB_Convert_555_to_0888_reverse(int width, int height,
548 const void* srcbits, int srclinebytes,
549 void* dstbits, int dstlinebytes)
551 const WORD* srcpixel;
552 DWORD* dstpixel;
553 int x,y;
555 for (y=0; y<height; y++) {
556 srcpixel=srcbits;
557 dstpixel=dstbits;
558 for (x=0; x<width; x++) {
559 WORD srcval;
560 srcval=*srcpixel++;
561 *dstpixel++=((srcval >> 7) & 0x0000f8) | /* h */
562 ((srcval >> 12) & 0x000007) | /* h - 3 bits */
563 ((srcval << 6) & 0x00f800) | /* g */
564 ((srcval << 1) & 0x000700) | /* g - 3 bits */
565 ((srcval << 19) & 0xf80000) | /* l */
566 ((srcval << 14) & 0x070000); /* l - 3 bits */
568 srcbits += srclinebytes;
569 dstbits += dstlinebytes;
573 static void X11DRV_DIB_Convert_5x5_to_any0888(int width, int height,
574 const void* srcbits, int srclinebytes,
575 WORD rsrc, WORD gsrc, WORD bsrc,
576 void* dstbits, int dstlinebytes,
577 DWORD rdst, DWORD gdst, DWORD bdst)
579 int rRightShift1,gRightShift1,bRightShift1;
580 int rRightShift2,gRightShift2,bRightShift2;
581 BYTE gMask1,gMask2;
582 int rLeftShift,gLeftShift,bLeftShift;
583 const WORD* srcpixel;
584 DWORD* dstpixel;
585 int x,y;
587 /* Note, the source pixel value is shifted left by 16 bits so that
588 * we know we will always have to shift right to extract the components.
590 rRightShift1=16+X11DRV_DIB_MaskToShift(rsrc)-3;
591 gRightShift1=16+X11DRV_DIB_MaskToShift(gsrc)-3;
592 bRightShift1=16+X11DRV_DIB_MaskToShift(bsrc)-3;
593 rRightShift2=rRightShift1+5;
594 gRightShift2=gRightShift1+5;
595 bRightShift2=bRightShift1+5;
596 if (gsrc==0x03e0) {
597 /* Green has 5 bits, like the others */
598 gMask1=0xf8;
599 gMask2=0x07;
600 } else {
601 /* Green has 6 bits, not 5. Compensate. */
602 gRightShift1++;
603 gRightShift2+=2;
604 gMask1=0xfc;
605 gMask2=0x03;
608 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
609 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
610 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
612 for (y=0; y<height; y++) {
613 srcpixel=srcbits;
614 dstpixel=dstbits;
615 for (x=0; x<width; x++) {
616 DWORD srcval;
617 BYTE red,green,blue;
618 srcval=*srcpixel++ << 16;
619 red= ((srcval >> rRightShift1) & 0xf8) |
620 ((srcval >> rRightShift2) & 0x07);
621 green=((srcval >> gRightShift1) & gMask1) |
622 ((srcval >> gRightShift2) & gMask2);
623 blue= ((srcval >> bRightShift1) & 0xf8) |
624 ((srcval >> bRightShift2) & 0x07);
625 *dstpixel++=(red << rLeftShift) |
626 (green << gLeftShift) |
627 (blue << bLeftShift);
629 srcbits += srclinebytes;
630 dstbits += dstlinebytes;
635 * 16 bits conversions
638 static void X11DRV_DIB_Convert_565_reverse(int width, int height,
639 const void* srcbits, int srclinebytes,
640 void* dstbits, int dstlinebytes)
642 const DWORD* srcpixel;
643 DWORD* dstpixel;
644 int x,y;
646 for (y=0; y<height; y++) {
647 srcpixel=srcbits;
648 dstpixel=dstbits;
649 for (x=0; x<width/2; x++) {
650 /* Do 2 pixels at a time */
651 DWORD srcval;
652 srcval=*srcpixel++;
653 *dstpixel++=((srcval << 11) & 0xf800f800) | /* h */
654 ( srcval & 0x07e007e0) | /* g */
655 ((srcval >> 11) & 0x001f001f); /* l */
657 if (width&1) {
658 /* And the the odd pixel */
659 WORD srcval;
660 srcval=*((WORD*)srcpixel);
661 *((WORD*)dstpixel)=((srcval << 11) & 0xf800) | /* h */
662 ( srcval & 0x07e0) | /* g */
663 ((srcval >> 11) & 0x001f); /* l */
665 srcbits += srclinebytes;
666 dstbits += dstlinebytes;
670 static void X11DRV_DIB_Convert_565_to_555_asis(int width, int height,
671 const void* srcbits, int srclinebytes,
672 void* dstbits, int dstlinebytes)
674 const DWORD* srcpixel;
675 DWORD* dstpixel;
676 int x,y;
678 for (y=0; y<height; y++) {
679 srcpixel=srcbits;
680 dstpixel=dstbits;
681 for (x=0; x<width/2; x++) {
682 /* Do 2 pixels at a time */
683 DWORD srcval;
684 srcval=*srcpixel++;
685 *dstpixel++=((srcval >> 1) & 0x7fe07fe0) | /* h, g */
686 ( srcval & 0x001f001f); /* l */
688 if (width&1) {
689 /* And the the odd pixel */
690 WORD srcval;
691 srcval=*((WORD*)srcpixel);
692 *((WORD*)dstpixel)=((srcval >> 1) & 0x7fe0) | /* h, g */
693 ( srcval & 0x001f); /* l */
695 srcbits += srclinebytes;
696 dstbits += dstlinebytes;
700 static void X11DRV_DIB_Convert_565_to_555_reverse(int width, int height,
701 const void* srcbits, int srclinebytes,
702 void* dstbits, int dstlinebytes)
704 const DWORD* srcpixel;
705 DWORD* dstpixel;
706 int x,y;
708 for (y=0; y<height; y++) {
709 srcpixel=srcbits;
710 dstpixel=dstbits;
711 for (x=0; x<width/2; x++) {
712 /* Do 2 pixels at a time */
713 DWORD srcval;
714 srcval=*srcpixel++;
715 *dstpixel++=((srcval >> 11) & 0x001f001f) | /* h */
716 ((srcval >> 1) & 0x03e003e0) | /* g */
717 ((srcval << 10) & 0x7c007c00); /* l */
719 if (width&1) {
720 /* And the the odd pixel */
721 WORD srcval;
722 srcval=*((WORD*)srcpixel);
723 *((WORD*)dstpixel)=((srcval >> 11) & 0x001f) | /* h */
724 ((srcval >> 1) & 0x03e0) | /* g */
725 ((srcval << 10) & 0x7c00); /* l */
727 srcbits += srclinebytes;
728 dstbits += dstlinebytes;
732 static void X11DRV_DIB_Convert_565_to_888_asis(int width, int height,
733 const void* srcbits, int srclinebytes,
734 void* dstbits, int dstlinebytes)
736 const WORD* srcpixel;
737 BYTE* dstpixel;
738 int x,y;
740 for (y=0; y<height; y++) {
741 srcpixel=srcbits;
742 dstpixel=dstbits;
743 for (x=0; x<width; x++) {
744 WORD srcval;
745 srcval=*srcpixel++;
746 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
747 ((srcval >> 2) & 0x07); /* l - 3 bits */
748 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
749 ((srcval >> 9) & 0x03); /* g - 2 bits */
750 dstpixel[2]=((srcval >> 8) & 0xf8) | /* h */
751 ((srcval >> 13) & 0x07); /* h - 3 bits */
752 dstpixel+=3;
754 srcbits += srclinebytes;
755 dstbits += dstlinebytes;
759 static void X11DRV_DIB_Convert_565_to_888_reverse(int width, int height,
760 const void* srcbits, int srclinebytes,
761 void* dstbits, int dstlinebytes)
763 const WORD* srcpixel;
764 BYTE* dstpixel;
765 int x,y;
767 for (y=0; y<height; y++) {
768 srcpixel=srcbits;
769 dstpixel=dstbits;
770 for (x=0; x<width; x++) {
771 WORD srcval;
772 srcval=*srcpixel++;
773 dstpixel[0]=((srcval >> 8) & 0xf8) | /* h */
774 ((srcval >> 13) & 0x07); /* h - 3 bits */
775 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
776 ((srcval >> 9) & 0x03); /* g - 2 bits */
777 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
778 ((srcval >> 2) & 0x07); /* l - 3 bits */
779 dstpixel+=3;
781 srcbits += srclinebytes;
782 dstbits += dstlinebytes;
786 static void X11DRV_DIB_Convert_565_to_0888_asis(int width, int height,
787 const void* srcbits, int srclinebytes,
788 void* dstbits, int dstlinebytes)
790 const WORD* srcpixel;
791 DWORD* dstpixel;
792 int x,y;
794 for (y=0; y<height; y++) {
795 srcpixel=srcbits;
796 dstpixel=dstbits;
797 for (x=0; x<width; x++) {
798 WORD srcval;
799 srcval=*srcpixel++;
800 *dstpixel++=((srcval << 8) & 0xf80000) | /* h */
801 ((srcval << 3) & 0x070000) | /* h - 3 bits */
802 ((srcval << 5) & 0x00fc00) | /* g */
803 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
804 ((srcval << 3) & 0x0000f8) | /* l */
805 ((srcval >> 2) & 0x000007); /* l - 3 bits */
807 srcbits += srclinebytes;
808 dstbits += dstlinebytes;
812 static void X11DRV_DIB_Convert_565_to_0888_reverse(int width, int height,
813 const void* srcbits, int srclinebytes,
814 void* dstbits, int dstlinebytes)
816 const WORD* srcpixel;
817 DWORD* dstpixel;
818 int x,y;
820 for (y=0; y<height; y++) {
821 srcpixel=srcbits;
822 dstpixel=dstbits;
823 for (x=0; x<width; x++) {
824 WORD srcval;
825 srcval=*srcpixel++;
826 *dstpixel++=((srcval >> 8) & 0x0000f8) | /* h */
827 ((srcval >> 13) & 0x000007) | /* h - 3 bits */
828 ((srcval << 5) & 0x00fc00) | /* g */
829 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
830 ((srcval << 19) & 0xf80000) | /* l */
831 ((srcval << 14) & 0x070000); /* l - 3 bits */
833 srcbits += srclinebytes;
834 dstbits += dstlinebytes;
839 * 24 bit conversions
842 static void X11DRV_DIB_Convert_888_reverse(int width, int height,
843 const void* srcbits, int srclinebytes,
844 void* dstbits, int dstlinebytes)
846 const BYTE* srcpixel;
847 BYTE* dstpixel;
848 int x,y;
850 for (y=0; y<height; y++) {
851 srcpixel=srcbits;
852 dstpixel=dstbits;
853 for (x=0; x<width; x++) {
854 dstpixel[0]=srcpixel[2];
855 dstpixel[1]=srcpixel[1];
856 dstpixel[2]=srcpixel[0];
857 srcpixel+=3;
858 dstpixel+=3;
860 srcbits += srclinebytes;
861 dstbits += dstlinebytes;
865 static void X11DRV_DIB_Convert_888_to_555_asis(int width, int height,
866 const void* srcbits, int srclinebytes,
867 void* dstbits, int dstlinebytes)
869 const DWORD* srcpixel;
870 const BYTE* srcbyte;
871 WORD* dstpixel;
872 int x,y;
873 int oddwidth;
875 oddwidth=width & 3;
876 width=width/4;
877 for (y=0; y<height; y++) {
878 srcpixel=srcbits;
879 dstpixel=dstbits;
880 for (x=0; x<width; x++) {
881 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
882 DWORD srcval1,srcval2;
883 srcval1=srcpixel[0];
884 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
885 ((srcval1 >> 6) & 0x03e0) | /* g1 */
886 ((srcval1 >> 9) & 0x7c00); /* h1 */
887 srcval2=srcpixel[1];
888 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
889 ((srcval2 << 2) & 0x03e0) | /* g2 */
890 ((srcval2 >> 1) & 0x7c00); /* h2 */
891 srcval1=srcpixel[2];
892 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
893 ((srcval2 >> 22) & 0x03e0) | /* g3 */
894 ((srcval1 << 7) & 0x7c00); /* h3 */
895 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
896 ((srcval1 >> 14) & 0x03e0) | /* g4 */
897 ((srcval1 >> 17) & 0x7c00); /* h4 */
898 srcpixel+=3;
899 dstpixel+=4;
901 /* And now up to 3 odd pixels */
902 srcbyte=(LPBYTE)srcpixel;
903 for (x=0; x<oddwidth; x++) {
904 WORD dstval;
905 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
906 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
907 dstval|=((srcbyte[2] << 7) & 0x7c00); /* h */
908 *dstpixel++=dstval;
909 srcbyte+=3;
911 srcbits += srclinebytes;
912 dstbits += dstlinebytes;
916 static void X11DRV_DIB_Convert_888_to_555_reverse(int width, int height,
917 const void* srcbits, int srclinebytes,
918 void* dstbits, int dstlinebytes)
920 const DWORD* srcpixel;
921 const BYTE* srcbyte;
922 WORD* dstpixel;
923 int x,y;
924 int oddwidth;
926 oddwidth=width & 3;
927 width=width/4;
928 for (y=0; y<height; y++) {
929 srcpixel=srcbits;
930 dstpixel=dstbits;
931 for (x=0; x<width; x++) {
932 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
933 DWORD srcval1,srcval2;
934 srcval1=srcpixel[0];
935 dstpixel[0]=((srcval1 << 7) & 0x7c00) | /* l1 */
936 ((srcval1 >> 6) & 0x03e0) | /* g1 */
937 ((srcval1 >> 19) & 0x001f); /* h1 */
938 srcval2=srcpixel[1];
939 dstpixel[1]=((srcval1 >> 17) & 0x7c00) | /* l2 */
940 ((srcval2 << 2) & 0x03e0) | /* g2 */
941 ((srcval2 >> 11) & 0x001f); /* h2 */
942 srcval1=srcpixel[2];
943 dstpixel[2]=((srcval2 >> 9) & 0x7c00) | /* l3 */
944 ((srcval2 >> 22) & 0x03e0) | /* g3 */
945 ((srcval1 >> 3) & 0x001f); /* h3 */
946 dstpixel[3]=((srcval1 >> 1) & 0x7c00) | /* l4 */
947 ((srcval1 >> 14) & 0x03e0) | /* g4 */
948 ((srcval1 >> 27) & 0x001f); /* h4 */
949 srcpixel+=3;
950 dstpixel+=4;
952 /* And now up to 3 odd pixels */
953 srcbyte=(LPBYTE)srcpixel;
954 for (x=0; x<oddwidth; x++) {
955 WORD dstval;
956 dstval =((srcbyte[0] << 7) & 0x7c00); /* l */
957 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
958 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
959 *dstpixel++=dstval;
960 srcbyte+=3;
962 srcbits += srclinebytes;
963 dstbits += dstlinebytes;
967 static void X11DRV_DIB_Convert_888_to_565_asis(int width, int height,
968 const void* srcbits, int srclinebytes,
969 void* dstbits, int dstlinebytes)
971 const DWORD* srcpixel;
972 const BYTE* srcbyte;
973 WORD* dstpixel;
974 int x,y;
975 int oddwidth;
977 oddwidth=width & 3;
978 width=width/4;
979 for (y=0; y<height; y++) {
980 srcpixel=srcbits;
981 dstpixel=dstbits;
982 for (x=0; x<width; x++) {
983 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
984 DWORD srcval1,srcval2;
985 srcval1=srcpixel[0];
986 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
987 ((srcval1 >> 5) & 0x07e0) | /* g1 */
988 ((srcval1 >> 8) & 0xf800); /* h1 */
989 srcval2=srcpixel[1];
990 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
991 ((srcval2 << 3) & 0x07e0) | /* g2 */
992 ( srcval2 & 0xf800); /* h2 */
993 srcval1=srcpixel[2];
994 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
995 ((srcval2 >> 21) & 0x07e0) | /* g3 */
996 ((srcval1 << 8) & 0xf800); /* h3 */
997 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
998 ((srcval1 >> 13) & 0x07e0) | /* g4 */
999 ((srcval1 >> 16) & 0xf800); /* h4 */
1000 srcpixel+=3;
1001 dstpixel+=4;
1003 /* And now up to 3 odd pixels */
1004 srcbyte=(LPBYTE)srcpixel;
1005 for (x=0; x<oddwidth; x++) {
1006 WORD dstval;
1007 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
1008 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1009 dstval|=((srcbyte[2] << 8) & 0xf800); /* h */
1010 *dstpixel++=dstval;
1011 srcbyte+=3;
1013 srcbits += srclinebytes;
1014 dstbits += dstlinebytes;
1018 static void X11DRV_DIB_Convert_888_to_565_reverse(int width, int height,
1019 const void* srcbits, int srclinebytes,
1020 void* dstbits, int dstlinebytes)
1022 const DWORD* srcpixel;
1023 const BYTE* srcbyte;
1024 WORD* dstpixel;
1025 int x,y;
1026 int oddwidth;
1028 oddwidth=width & 3;
1029 width=width/4;
1030 for (y=0; y<height; y++) {
1031 srcpixel=srcbits;
1032 dstpixel=dstbits;
1033 for (x=0; x<width; x++) {
1034 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1035 DWORD srcval1,srcval2;
1036 srcval1=srcpixel[0];
1037 dstpixel[0]=((srcval1 << 8) & 0xf800) | /* l1 */
1038 ((srcval1 >> 5) & 0x07e0) | /* g1 */
1039 ((srcval1 >> 19) & 0x001f); /* h1 */
1040 srcval2=srcpixel[1];
1041 dstpixel[1]=((srcval1 >> 16) & 0xf800) | /* l2 */
1042 ((srcval2 << 3) & 0x07e0) | /* g2 */
1043 ((srcval2 >> 11) & 0x001f); /* h2 */
1044 srcval1=srcpixel[2];
1045 dstpixel[2]=((srcval2 >> 8) & 0xf800) | /* l3 */
1046 ((srcval2 >> 21) & 0x07e0) | /* g3 */
1047 ((srcval1 >> 3) & 0x001f); /* h3 */
1048 dstpixel[3]=(srcval1 & 0xf800) | /* l4 */
1049 ((srcval1 >> 13) & 0x07e0) | /* g4 */
1050 ((srcval1 >> 27) & 0x001f); /* h4 */
1051 srcpixel+=3;
1052 dstpixel+=4;
1054 /* And now up to 3 odd pixels */
1055 srcbyte=(LPBYTE)srcpixel;
1056 for (x=0; x<oddwidth; x++) {
1057 WORD dstval;
1058 dstval =((srcbyte[0] << 8) & 0xf800); /* l */
1059 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1060 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
1061 *dstpixel++=dstval;
1062 srcbyte+=3;
1064 srcbits += srclinebytes;
1065 dstbits += dstlinebytes;
1069 static void X11DRV_DIB_Convert_888_to_0888_asis(int width, int height,
1070 const void* srcbits, int srclinebytes,
1071 void* dstbits, int dstlinebytes)
1073 const DWORD* srcpixel;
1074 DWORD* dstpixel;
1075 int x,y;
1076 int oddwidth;
1078 oddwidth=width & 3;
1079 width=width/4;
1080 for (y=0; y<height; y++) {
1081 srcpixel=srcbits;
1082 dstpixel=dstbits;
1083 for (x=0; x<width; x++) {
1084 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1085 DWORD srcval1,srcval2;
1086 srcval1=srcpixel[0];
1087 dstpixel[0]=( srcval1 & 0x00ffffff); /* h1, g1, l1 */
1088 srcval2=srcpixel[1];
1089 dstpixel[1]=( srcval1 >> 24) | /* l2 */
1090 ((srcval2 << 8) & 0x00ffff00); /* h2, g2 */
1091 srcval1=srcpixel[2];
1092 dstpixel[2]=( srcval2 >> 16) | /* g3, l3 */
1093 ((srcval1 << 16) & 0x00ff0000); /* h3 */
1094 dstpixel[3]=( srcval1 >> 8); /* h4, g4, l4 */
1095 srcpixel+=3;
1096 dstpixel+=4;
1098 /* And now up to 3 odd pixels */
1099 for (x=0; x<oddwidth; x++) {
1100 DWORD srcval;
1101 srcval=*srcpixel;
1102 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1103 *dstpixel++=( srcval & 0x00ffffff); /* h, g, l */
1105 srcbits += srclinebytes;
1106 dstbits += dstlinebytes;
1110 static void X11DRV_DIB_Convert_888_to_0888_reverse(int width, int height,
1111 const void* srcbits, int srclinebytes,
1112 void* dstbits, int dstlinebytes)
1114 const DWORD* srcpixel;
1115 DWORD* dstpixel;
1116 int x,y;
1117 int oddwidth;
1119 oddwidth=width & 3;
1120 width=width/4;
1121 for (y=0; y<height; y++) {
1122 srcpixel=srcbits;
1123 dstpixel=dstbits;
1124 for (x=0; x<width; x++) {
1125 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1126 DWORD srcval1,srcval2;
1128 srcval1=srcpixel[0];
1129 dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */
1130 ( srcval1 & 0x00ff00) | /* g1 */
1131 ((srcval1 << 16) & 0xff0000); /* l1 */
1132 srcval2=srcpixel[1];
1133 dstpixel[1]=((srcval1 >> 8) & 0xff0000) | /* l2 */
1134 ((srcval2 << 8) & 0x00ff00) | /* g2 */
1135 ((srcval2 >> 8) & 0x0000ff); /* h2 */
1136 srcval1=srcpixel[2];
1137 dstpixel[2]=( srcval2 & 0xff0000) | /* l3 */
1138 ((srcval2 >> 16) & 0x00ff00) | /* g3 */
1139 ( srcval1 & 0x0000ff); /* h3 */
1140 dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */
1141 ((srcval1 >> 8) & 0x00ff00) | /* g4 */
1142 ((srcval1 << 8) & 0xff0000); /* l4 */
1143 srcpixel+=3;
1144 dstpixel+=4;
1146 /* And now up to 3 odd pixels */
1147 for (x=0; x<oddwidth; x++) {
1148 DWORD srcval;
1149 srcval=*srcpixel;
1150 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1151 *dstpixel++=((srcval >> 16) & 0x0000ff) | /* h */
1152 ( srcval & 0x00ff00) | /* g */
1153 ((srcval << 16) & 0xff0000); /* l */
1155 srcbits += srclinebytes;
1156 dstbits += dstlinebytes;
1160 static void X11DRV_DIB_Convert_rgb888_to_any0888(int width, int height,
1161 const void* srcbits, int srclinebytes,
1162 void* dstbits, int dstlinebytes,
1163 DWORD rdst, DWORD gdst, DWORD bdst)
1165 int rLeftShift,gLeftShift,bLeftShift;
1166 const BYTE* srcpixel;
1167 DWORD* dstpixel;
1168 int x,y;
1170 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1171 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1172 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1173 for (y=0; y<height; y++) {
1174 srcpixel=srcbits;
1175 dstpixel=dstbits;
1176 for (x=0; x<width; x++) {
1177 *dstpixel++=(srcpixel[0] << bLeftShift) | /* b */
1178 (srcpixel[1] << gLeftShift) | /* g */
1179 (srcpixel[2] << rLeftShift); /* r */
1180 srcpixel+=3;
1182 srcbits += srclinebytes;
1183 dstbits += dstlinebytes;
1187 static void X11DRV_DIB_Convert_bgr888_to_any0888(int width, int height,
1188 const void* srcbits, int srclinebytes,
1189 void* dstbits, int dstlinebytes,
1190 DWORD rdst, DWORD gdst, DWORD bdst)
1192 int rLeftShift,gLeftShift,bLeftShift;
1193 const BYTE* srcpixel;
1194 DWORD* dstpixel;
1195 int x,y;
1197 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1198 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1199 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1200 for (y=0; y<height; y++) {
1201 srcpixel=srcbits;
1202 dstpixel=dstbits;
1203 for (x=0; x<width; x++) {
1204 *dstpixel++=(srcpixel[0] << rLeftShift) | /* r */
1205 (srcpixel[1] << gLeftShift) | /* g */
1206 (srcpixel[2] << bLeftShift); /* b */
1207 srcpixel+=3;
1209 srcbits += srclinebytes;
1210 dstbits += dstlinebytes;
1215 * 32 bit conversions
1218 static void X11DRV_DIB_Convert_0888_reverse(int width, int height,
1219 const void* srcbits, int srclinebytes,
1220 void* dstbits, int dstlinebytes)
1222 const DWORD* srcpixel;
1223 DWORD* dstpixel;
1224 int x,y;
1226 for (y=0; y<height; y++) {
1227 srcpixel=srcbits;
1228 dstpixel=dstbits;
1229 for (x=0; x<width; x++) {
1230 DWORD srcval;
1231 srcval=*srcpixel++;
1232 *dstpixel++=((srcval << 16) & 0x00ff0000) | /* h */
1233 ( srcval & 0x0000ff00) | /* g */
1234 ((srcval >> 16) & 0x000000ff); /* l */
1236 srcbits += srclinebytes;
1237 dstbits += dstlinebytes;
1241 static void X11DRV_DIB_Convert_0888_any(int width, int height,
1242 const void* srcbits, int srclinebytes,
1243 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1244 void* dstbits, int dstlinebytes,
1245 DWORD rdst, DWORD gdst, DWORD bdst)
1247 int rRightShift,gRightShift,bRightShift;
1248 int rLeftShift,gLeftShift,bLeftShift;
1249 const DWORD* srcpixel;
1250 DWORD* dstpixel;
1251 int x,y;
1253 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1254 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1255 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1256 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1257 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1258 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1259 for (y=0; y<height; y++) {
1260 srcpixel=srcbits;
1261 dstpixel=dstbits;
1262 for (x=0; x<width; x++) {
1263 DWORD srcval;
1264 srcval=*srcpixel++;
1265 *dstpixel++=(((srcval >> rRightShift) & 0xff) << rLeftShift) |
1266 (((srcval >> gRightShift) & 0xff) << gLeftShift) |
1267 (((srcval >> bRightShift) & 0xff) << bLeftShift);
1269 srcbits += srclinebytes;
1270 dstbits += dstlinebytes;
1274 static void X11DRV_DIB_Convert_0888_to_555_asis(int width, int height,
1275 const void* srcbits, int srclinebytes,
1276 void* dstbits, int dstlinebytes)
1278 const DWORD* srcpixel;
1279 WORD* dstpixel;
1280 int x,y;
1282 for (y=0; y<height; y++) {
1283 srcpixel=srcbits;
1284 dstpixel=dstbits;
1285 for (x=0; x<width; x++) {
1286 DWORD srcval;
1287 srcval=*srcpixel++;
1288 *dstpixel++=((srcval >> 9) & 0x7c00) | /* h */
1289 ((srcval >> 6) & 0x03e0) | /* g */
1290 ((srcval >> 3) & 0x001f); /* l */
1292 srcbits += srclinebytes;
1293 dstbits += dstlinebytes;
1297 static void X11DRV_DIB_Convert_0888_to_555_reverse(int width, int height,
1298 const void* srcbits, int srclinebytes,
1299 void* dstbits, int dstlinebytes)
1301 const DWORD* srcpixel;
1302 WORD* dstpixel;
1303 int x,y;
1305 for (y=0; y<height; y++) {
1306 srcpixel=srcbits;
1307 dstpixel=dstbits;
1308 for (x=0; x<width; x++) {
1309 DWORD srcval;
1310 srcval=*srcpixel++;
1311 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1312 ((srcval >> 6) & 0x03e0) | /* g */
1313 ((srcval << 7) & 0x7c00); /* l */
1315 srcbits += srclinebytes;
1316 dstbits += dstlinebytes;
1320 static void X11DRV_DIB_Convert_0888_to_565_asis(int width, int height,
1321 const void* srcbits, int srclinebytes,
1322 void* dstbits, int dstlinebytes)
1324 const DWORD* srcpixel;
1325 WORD* dstpixel;
1326 int x,y;
1328 for (y=0; y<height; y++) {
1329 srcpixel=srcbits;
1330 dstpixel=dstbits;
1331 for (x=0; x<width; x++) {
1332 DWORD srcval;
1333 srcval=*srcpixel++;
1334 *dstpixel++=((srcval >> 8) & 0xf800) | /* h */
1335 ((srcval >> 5) & 0x07e0) | /* g */
1336 ((srcval >> 3) & 0x001f); /* l */
1338 srcbits += srclinebytes;
1339 dstbits += dstlinebytes;
1343 static void X11DRV_DIB_Convert_0888_to_565_reverse(int width, int height,
1344 const void* srcbits, int srclinebytes,
1345 void* dstbits, int dstlinebytes)
1347 const DWORD* srcpixel;
1348 WORD* dstpixel;
1349 int x,y;
1351 for (y=0; y<height; y++) {
1352 srcpixel=srcbits;
1353 dstpixel=dstbits;
1354 for (x=0; x<width; x++) {
1355 DWORD srcval;
1356 srcval=*srcpixel++;
1357 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1358 ((srcval >> 5) & 0x07e0) | /* g */
1359 ((srcval << 8) & 0xf800); /* l */
1361 srcbits += srclinebytes;
1362 dstbits += dstlinebytes;
1366 static void X11DRV_DIB_Convert_any0888_to_5x5(int width, int height,
1367 const void* srcbits, int srclinebytes,
1368 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1369 void* dstbits, int dstlinebytes,
1370 WORD rdst, WORD gdst, WORD bdst)
1372 int rRightShift,gRightShift,bRightShift;
1373 int rLeftShift,gLeftShift,bLeftShift;
1374 const DWORD* srcpixel;
1375 WORD* dstpixel;
1376 int x,y;
1378 /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel
1379 * contains 0x11223344.
1380 * - first we shift 0x11223344 right by rRightShift to bring the most
1381 * significant bits of the red components in the bottom 5 (or 6) bits
1382 * -> 0x4488c
1383 * - then we remove non red bits by anding with the modified rdst (0x1f)
1384 * -> 0x0c
1385 * - finally shift these bits left by rLeftShift so that they end up in
1386 * the right place
1387 * -> 0x3000
1389 rRightShift=X11DRV_DIB_MaskToShift(rsrc)+3;
1390 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1391 gRightShift+=(gdst==0x07e0?2:3);
1392 bRightShift=X11DRV_DIB_MaskToShift(bsrc)+3;
1394 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1395 rdst=rdst >> rLeftShift;
1396 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1397 gdst=gdst >> gLeftShift;
1398 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1399 bdst=bdst >> bLeftShift;
1401 for (y=0; y<height; y++) {
1402 srcpixel=srcbits;
1403 dstpixel=dstbits;
1404 for (x=0; x<width; x++) {
1405 DWORD srcval;
1406 srcval=*srcpixel++;
1407 *dstpixel++=(((srcval >> rRightShift) & rdst) << rLeftShift) |
1408 (((srcval >> gRightShift) & gdst) << gLeftShift) |
1409 (((srcval >> bRightShift) & bdst) << bLeftShift);
1411 srcbits += srclinebytes;
1412 dstbits += dstlinebytes;
1416 static void X11DRV_DIB_Convert_0888_to_888_asis(int width, int height,
1417 const void* srcbits, int srclinebytes,
1418 void* dstbits, int dstlinebytes)
1420 const DWORD* srcpixel;
1421 DWORD* dstpixel;
1422 BYTE* dstbyte;
1423 int x,y;
1424 int oddwidth;
1426 oddwidth=width & 3;
1427 width=width/4;
1428 for (y=0; y<height; y++) {
1429 srcpixel=srcbits;
1430 dstpixel=dstbits;
1431 for (x=0; x<width; x++) {
1432 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1433 DWORD srcval;
1434 srcval=((*srcpixel++) & 0x00ffffff); /* h1, g1, l1*/
1435 *dstpixel++=srcval | ((*srcpixel) << 24); /* h2 */
1436 srcval=((*srcpixel++ >> 8 ) & 0x0000ffff); /* g2, l2 */
1437 *dstpixel++=srcval | ((*srcpixel) << 16); /* h3, g3 */
1438 srcval=((*srcpixel++ >> 16) & 0x000000ff); /* l3 */
1439 *dstpixel++=srcval | ((*srcpixel++) << 8); /* h4, g4, l4 */
1441 /* And now up to 3 odd pixels */
1442 dstbyte=(BYTE*)dstpixel;
1443 for (x=0; x<oddwidth; x++) {
1444 DWORD srcval;
1445 srcval=*srcpixel++;
1446 *((WORD*)dstbyte)++=srcval; /* h, g */
1447 *dstbyte++=srcval >> 16; /* l */
1449 srcbits += srclinebytes;
1450 dstbits += dstlinebytes;
1454 static void X11DRV_DIB_Convert_0888_to_888_reverse(int width, int height,
1455 const void* srcbits, int srclinebytes,
1456 void* dstbits, int dstlinebytes)
1458 const DWORD* srcpixel;
1459 DWORD* dstpixel;
1460 BYTE* dstbyte;
1461 int x,y;
1462 int oddwidth;
1464 oddwidth=width & 3;
1465 width=width/4;
1466 for (y=0; y<height; y++) {
1467 srcpixel=srcbits;
1468 dstpixel=dstbits;
1469 for (x=0; x<width; x++) {
1470 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1471 DWORD srcval1,srcval2;
1472 srcval1=*srcpixel++;
1473 srcval2= ((srcval1 >> 16) & 0x000000ff) | /* h1 */
1474 ( srcval1 & 0x0000ff00) | /* g1 */
1475 ((srcval1 << 16) & 0x00ff0000); /* l1 */
1476 srcval1=*srcpixel++;
1477 *dstpixel++=srcval2 |
1478 ((srcval1 << 8) & 0xff000000); /* h2 */
1479 srcval2= ((srcval1 >> 8) & 0x000000ff) | /* g2 */
1480 ((srcval1 << 8) & 0x0000ff00); /* l2 */
1481 srcval1=*srcpixel++;
1482 *dstpixel++=srcval2 |
1483 ( srcval1 & 0x00ff0000) | /* h3 */
1484 ((srcval1 << 16) & 0xff000000); /* g3 */
1485 srcval2= ( srcval1 & 0x000000ff); /* l3 */
1486 srcval1=*srcpixel++;
1487 *dstpixel++=srcval2 |
1488 ((srcval1 >> 8) & 0x0000ff00) | /* h4 */
1489 ((srcval1 << 8) & 0x00ff0000) | /* g4 */
1490 ( srcval1 << 24); /* l4 */
1492 /* And now up to 3 odd pixels */
1493 dstbyte=(BYTE*)dstpixel;
1494 for (x=0; x<oddwidth; x++) {
1495 DWORD srcval;
1496 srcval=*srcpixel++;
1497 *((WORD*)dstbyte)++=((srcval >> 16) & 0x00ff) | /* h */
1498 (srcval & 0xff00); /* g */
1499 *dstbyte++=srcval; /* l */
1501 srcbits += srclinebytes;
1502 dstbits += dstlinebytes;
1506 static void X11DRV_DIB_Convert_any0888_to_rgb888(int width, int height,
1507 const void* srcbits, int srclinebytes,
1508 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1509 void* dstbits, int dstlinebytes)
1511 int rRightShift,gRightShift,bRightShift;
1512 const DWORD* srcpixel;
1513 BYTE* dstpixel;
1514 int x,y;
1516 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1517 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1518 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1519 for (y=0; y<height; y++) {
1520 srcpixel=srcbits;
1521 dstpixel=dstbits;
1522 for (x=0; x<width; x++) {
1523 DWORD srcval;
1524 srcval=*srcpixel++;
1525 dstpixel[0]=(srcval >> bRightShift); /* b */
1526 dstpixel[1]=(srcval >> gRightShift); /* g */
1527 dstpixel[2]=(srcval >> rRightShift); /* r */
1528 dstpixel+=3;
1530 srcbits += srclinebytes;
1531 dstbits += dstlinebytes;
1535 static void X11DRV_DIB_Convert_any0888_to_bgr888(int width, int height,
1536 const void* srcbits, int srclinebytes,
1537 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1538 void* dstbits, int dstlinebytes)
1540 int rRightShift,gRightShift,bRightShift;
1541 const DWORD* srcpixel;
1542 BYTE* dstpixel;
1543 int x,y;
1545 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1546 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1547 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1548 for (y=0; y<height; y++) {
1549 srcpixel=srcbits;
1550 dstpixel=dstbits;
1551 for (x=0; x<width; x++) {
1552 DWORD srcval;
1553 srcval=*srcpixel++;
1554 dstpixel[0]=(srcval >> rRightShift); /* r */
1555 dstpixel[1]=(srcval >> gRightShift); /* g */
1556 dstpixel[2]=(srcval >> bRightShift); /* b */
1557 dstpixel+=3;
1559 srcbits += srclinebytes;
1560 dstbits += dstlinebytes;
1564 /***********************************************************************
1565 * X11DRV_DIB_SetImageBits_1
1567 * SetDIBits for a 1-bit deep DIB.
1569 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
1570 DWORD srcwidth, DWORD dstwidth, int left,
1571 int *colors, XImage *bmpImage, DWORD linebytes)
1573 int h;
1574 const BYTE* srcbyte;
1575 BYTE srcval, extra;
1576 DWORD i, x;
1578 if (lines < 0 ) {
1579 lines = -lines;
1580 srcbits = srcbits + linebytes * (lines - 1);
1581 linebytes = -linebytes;
1584 if ((extra = (left & 7)) != 0) {
1585 left &= ~7;
1586 dstwidth += extra;
1588 srcbits += left >> 3;
1590 /* ==== pal 1 dib -> any bmp format ==== */
1591 for (h = lines-1; h >=0; h--) {
1592 srcbyte=srcbits;
1593 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
1594 for (i = dstwidth/8, x = left; i > 0; i--) {
1595 srcval=*srcbyte++;
1596 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
1597 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
1598 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
1599 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
1600 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
1601 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
1602 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
1603 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
1605 srcval=*srcbyte;
1606 switch (dstwidth & 7)
1608 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1609 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1610 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1611 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1612 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1613 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1614 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1616 srcbits += linebytes;
1620 /***********************************************************************
1621 * X11DRV_DIB_GetImageBits_1
1623 * GetDIBits for a 1-bit deep DIB.
1625 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1626 DWORD dstwidth, DWORD srcwidth,
1627 RGBQUAD *colors, PALETTEENTRY *srccolors,
1628 XImage *bmpImage, DWORD linebytes )
1630 DWORD x;
1631 int h;
1633 if (lines < 0 ) {
1634 lines = -lines;
1635 dstbits = dstbits + linebytes * (lines - 1);
1636 linebytes = -linebytes;
1639 switch (bmpImage->depth)
1641 case 1:
1642 case 4:
1643 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1644 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1645 BYTE* dstbyte;
1647 for (h=lines-1; h>=0; h--) {
1648 BYTE dstval;
1649 dstbyte=dstbits;
1650 dstval=0;
1651 for (x=0; x<dstwidth; x++) {
1652 PALETTEENTRY srcval;
1653 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1654 dstval|=(X11DRV_DIB_GetNearestIndex
1655 (colors, 2,
1656 srcval.peRed,
1657 srcval.peGreen,
1658 srcval.peBlue) << (7 - (x & 7)));
1659 if ((x&7)==7) {
1660 *dstbyte++=dstval;
1661 dstval=0;
1664 if ((dstwidth&7)!=0) {
1665 *dstbyte=dstval;
1667 dstbits += linebytes;
1669 } else {
1670 goto notsupported;
1672 break;
1674 case 8:
1675 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1676 /* ==== pal 8 bmp -> pal 1 dib ==== */
1677 const void* srcbits;
1678 const BYTE* srcpixel;
1679 BYTE* dstbyte;
1681 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1683 for (h=0; h<lines; h++) {
1684 BYTE dstval;
1685 srcpixel=srcbits;
1686 dstbyte=dstbits;
1687 dstval=0;
1688 for (x=0; x<dstwidth; x++) {
1689 PALETTEENTRY srcval;
1690 srcval=srccolors[(int)*srcpixel++];
1691 dstval|=(X11DRV_DIB_GetNearestIndex
1692 (colors, 2,
1693 srcval.peRed,
1694 srcval.peGreen,
1695 srcval.peBlue) << (7-(x&7)) );
1696 if ((x&7)==7) {
1697 *dstbyte++=dstval;
1698 dstval=0;
1701 if ((dstwidth&7)!=0) {
1702 *dstbyte=dstval;
1704 srcbits -= bmpImage->bytes_per_line;
1705 dstbits += linebytes;
1707 } else {
1708 goto notsupported;
1710 break;
1712 case 15:
1713 case 16:
1715 const void* srcbits;
1716 const WORD* srcpixel;
1717 BYTE* dstbyte;
1719 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1721 if (bmpImage->green_mask==0x03e0) {
1722 if (bmpImage->red_mask==0x7c00) {
1723 /* ==== rgb 555 bmp -> pal 1 dib ==== */
1724 for (h=0; h<lines; h++) {
1725 BYTE dstval;
1726 srcpixel=srcbits;
1727 dstbyte=dstbits;
1728 dstval=0;
1729 for (x=0; x<dstwidth; x++) {
1730 WORD srcval;
1731 srcval=*srcpixel++;
1732 dstval|=(X11DRV_DIB_GetNearestIndex
1733 (colors, 2,
1734 ((srcval >> 7) & 0xf8) | /* r */
1735 ((srcval >> 12) & 0x07),
1736 ((srcval >> 2) & 0xf8) | /* g */
1737 ((srcval >> 7) & 0x07),
1738 ((srcval << 3) & 0xf8) | /* b */
1739 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1740 if ((x&7)==7) {
1741 *dstbyte++=dstval;
1742 dstval=0;
1745 if ((dstwidth&7)!=0) {
1746 *dstbyte=dstval;
1748 srcbits -= bmpImage->bytes_per_line;
1749 dstbits += linebytes;
1751 } else if (bmpImage->blue_mask==0x7c00) {
1752 /* ==== bgr 555 bmp -> pal 1 dib ==== */
1753 for (h=0; h<lines; h++) {
1754 WORD dstval;
1755 srcpixel=srcbits;
1756 dstbyte=dstbits;
1757 dstval=0;
1758 for (x=0; x<dstwidth; x++) {
1759 BYTE srcval;
1760 srcval=*srcpixel++;
1761 dstval|=(X11DRV_DIB_GetNearestIndex
1762 (colors, 2,
1763 ((srcval << 3) & 0xf8) | /* r */
1764 ((srcval >> 2) & 0x07),
1765 ((srcval >> 2) & 0xf8) | /* g */
1766 ((srcval >> 7) & 0x07),
1767 ((srcval >> 7) & 0xf8) | /* b */
1768 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1769 if ((x&7)==7) {
1770 *dstbyte++=dstval;
1771 dstval=0;
1774 if ((dstwidth&7)!=0) {
1775 *dstbyte=dstval;
1777 srcbits -= bmpImage->bytes_per_line;
1778 dstbits += linebytes;
1780 } else {
1781 goto notsupported;
1783 } else if (bmpImage->green_mask==0x07e0) {
1784 if (bmpImage->red_mask==0xf800) {
1785 /* ==== rgb 565 bmp -> pal 1 dib ==== */
1786 for (h=0; h<lines; h++) {
1787 BYTE dstval;
1788 srcpixel=srcbits;
1789 dstbyte=dstbits;
1790 dstval=0;
1791 for (x=0; x<dstwidth; x++) {
1792 WORD srcval;
1793 srcval=*srcpixel++;
1794 dstval|=(X11DRV_DIB_GetNearestIndex
1795 (colors, 2,
1796 ((srcval >> 8) & 0xf8) | /* r */
1797 ((srcval >> 13) & 0x07),
1798 ((srcval >> 3) & 0xfc) | /* g */
1799 ((srcval >> 9) & 0x03),
1800 ((srcval << 3) & 0xf8) | /* b */
1801 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1802 if ((x&7)==7) {
1803 *dstbyte++=dstval;
1804 dstval=0;
1807 if ((dstwidth&7)!=0) {
1808 *dstbyte=dstval;
1810 srcbits -= bmpImage->bytes_per_line;
1811 dstbits += linebytes;
1813 } else if (bmpImage->blue_mask==0xf800) {
1814 /* ==== bgr 565 bmp -> pal 1 dib ==== */
1815 for (h=0; h<lines; h++) {
1816 BYTE dstval;
1817 srcpixel=srcbits;
1818 dstbyte=dstbits;
1819 dstval=0;
1820 for (x=0; x<dstwidth; x++) {
1821 WORD srcval;
1822 srcval=*srcpixel++;
1823 dstval|=(X11DRV_DIB_GetNearestIndex
1824 (colors, 2,
1825 ((srcval << 3) & 0xf8) | /* r */
1826 ((srcval >> 2) & 0x07),
1827 ((srcval >> 3) & 0xfc) | /* g */
1828 ((srcval >> 9) & 0x03),
1829 ((srcval >> 8) & 0xf8) | /* b */
1830 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1831 if ((x&7)==7) {
1832 *dstbyte++=dstval;
1833 dstval=0;
1836 if ((dstwidth&7)!=0) {
1837 *dstbyte=dstval;
1839 srcbits -= bmpImage->bytes_per_line;
1840 dstbits += linebytes;
1842 } else {
1843 goto notsupported;
1845 } else {
1846 goto notsupported;
1849 break;
1851 case 24:
1852 case 32:
1854 const void* srcbits;
1855 const BYTE *srcbyte;
1856 BYTE* dstbyte;
1857 int bytes_per_pixel;
1859 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1860 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1862 if (bmpImage->green_mask!=0x00ff00 ||
1863 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1864 goto notsupported;
1865 } else if (bmpImage->blue_mask==0xff) {
1866 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1867 for (h=0; h<lines; h++) {
1868 BYTE dstval;
1869 srcbyte=srcbits;
1870 dstbyte=dstbits;
1871 dstval=0;
1872 for (x=0; x<dstwidth; x++) {
1873 dstval|=(X11DRV_DIB_GetNearestIndex
1874 (colors, 2,
1875 srcbyte[2],
1876 srcbyte[1],
1877 srcbyte[0]) << (7-(x&7)) );
1878 srcbyte+=bytes_per_pixel;
1879 if ((x&7)==7) {
1880 *dstbyte++=dstval;
1881 dstval=0;
1884 if ((dstwidth&7)!=0) {
1885 *dstbyte=dstval;
1887 srcbits -= bmpImage->bytes_per_line;
1888 dstbits += linebytes;
1890 } else {
1891 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1892 for (h=0; h<lines; h++) {
1893 BYTE dstval;
1894 srcbyte=srcbits;
1895 dstbyte=dstbits;
1896 dstval=0;
1897 for (x=0; x<dstwidth; x++) {
1898 dstval|=(X11DRV_DIB_GetNearestIndex
1899 (colors, 2,
1900 srcbyte[0],
1901 srcbyte[1],
1902 srcbyte[2]) << (7-(x&7)) );
1903 srcbyte+=bytes_per_pixel;
1904 if ((x&7)==7) {
1905 *dstbyte++=dstval;
1906 dstval=0;
1909 if ((dstwidth&7)!=0) {
1910 *dstbyte=dstval;
1912 srcbits -= bmpImage->bytes_per_line;
1913 dstbits += linebytes;
1917 break;
1919 default:
1920 notsupported:
1922 BYTE* dstbyte;
1923 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1925 /* ==== any bmp format -> pal 1 dib ==== */
1926 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1927 bmpImage->bits_per_pixel, bmpImage->red_mask,
1928 bmpImage->green_mask, bmpImage->blue_mask );
1930 for (h=lines-1; h>=0; h--) {
1931 BYTE dstval;
1932 dstbyte=dstbits;
1933 dstval=0;
1934 for (x=0; x<dstwidth; x++) {
1935 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1936 if ((x&7)==7) {
1937 *dstbyte++=dstval;
1938 dstval=0;
1941 if ((dstwidth&7)!=0) {
1942 *dstbyte=dstval;
1944 dstbits += linebytes;
1947 break;
1951 /***********************************************************************
1952 * X11DRV_DIB_SetImageBits_4
1954 * SetDIBits for a 4-bit deep DIB.
1956 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1957 DWORD srcwidth, DWORD dstwidth, int left,
1958 int *colors, XImage *bmpImage, DWORD linebytes)
1960 int h;
1961 const BYTE* srcbyte;
1962 DWORD i, x;
1964 if (lines < 0 ) {
1965 lines = -lines;
1966 srcbits = srcbits + linebytes * (lines - 1);
1967 linebytes = -linebytes;
1970 if (left & 1) {
1971 left--;
1972 dstwidth++;
1974 srcbits += left >> 1;
1976 /* ==== pal 4 dib -> any bmp format ==== */
1977 for (h = lines-1; h >= 0; h--) {
1978 srcbyte=srcbits;
1979 for (i = dstwidth/2, x = left; i > 0; i--) {
1980 BYTE srcval=*srcbyte++;
1981 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
1982 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
1984 if (dstwidth & 1)
1985 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
1986 srcbits += linebytes;
1992 /***********************************************************************
1993 * X11DRV_DIB_GetImageBits_4
1995 * GetDIBits for a 4-bit deep DIB.
1997 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
1998 DWORD srcwidth, DWORD dstwidth,
1999 RGBQUAD *colors, PALETTEENTRY *srccolors,
2000 XImage *bmpImage, DWORD linebytes )
2002 DWORD x;
2003 int h;
2004 BYTE *bits;
2006 if (lines < 0 )
2008 lines = -lines;
2009 dstbits = dstbits + ( linebytes * (lines-1) );
2010 linebytes = -linebytes;
2013 bits = dstbits;
2015 switch (bmpImage->depth) {
2016 case 1:
2017 case 4:
2018 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2019 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2020 BYTE* dstbyte;
2022 for (h = lines-1; h >= 0; h--) {
2023 BYTE dstval;
2024 dstbyte=dstbits;
2025 dstval=0;
2026 for (x = 0; x < dstwidth; x++) {
2027 PALETTEENTRY srcval;
2028 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2029 dstval|=(X11DRV_DIB_GetNearestIndex
2030 (colors, 16,
2031 srcval.peRed,
2032 srcval.peGreen,
2033 srcval.peBlue) << (4-((x&1)<<2)));
2034 if ((x&1)==1) {
2035 *dstbyte++=dstval;
2036 dstval=0;
2039 if ((dstwidth&1)!=0) {
2040 *dstbyte=dstval;
2042 dstbits += linebytes;
2044 } else {
2045 goto notsupported;
2047 break;
2049 case 8:
2050 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2051 /* ==== pal 8 bmp -> pal 4 dib ==== */
2052 const void* srcbits;
2053 const BYTE *srcpixel;
2054 BYTE* dstbyte;
2056 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2057 for (h=0; h<lines; h++) {
2058 BYTE dstval;
2059 srcpixel=srcbits;
2060 dstbyte=dstbits;
2061 dstval=0;
2062 for (x=0; x<dstwidth; x++) {
2063 PALETTEENTRY srcval;
2064 srcval = srccolors[(int)*srcpixel++];
2065 dstval|=(X11DRV_DIB_GetNearestIndex
2066 (colors, 16,
2067 srcval.peRed,
2068 srcval.peGreen,
2069 srcval.peBlue) << (4*(1-(x&1))) );
2070 if ((x&1)==1) {
2071 *dstbyte++=dstval;
2072 dstval=0;
2075 if ((dstwidth&1)!=0) {
2076 *dstbyte=dstval;
2078 srcbits -= bmpImage->bytes_per_line;
2079 dstbits += linebytes;
2081 } else {
2082 goto notsupported;
2084 break;
2086 case 15:
2087 case 16:
2089 const void* srcbits;
2090 const WORD* srcpixel;
2091 BYTE* dstbyte;
2093 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2095 if (bmpImage->green_mask==0x03e0) {
2096 if (bmpImage->red_mask==0x7c00) {
2097 /* ==== rgb 555 bmp -> pal 4 dib ==== */
2098 for (h=0; h<lines; h++) {
2099 BYTE dstval;
2100 srcpixel=srcbits;
2101 dstbyte=dstbits;
2102 dstval=0;
2103 for (x=0; x<dstwidth; x++) {
2104 WORD srcval;
2105 srcval=*srcpixel++;
2106 dstval|=(X11DRV_DIB_GetNearestIndex
2107 (colors, 16,
2108 ((srcval >> 7) & 0xf8) | /* r */
2109 ((srcval >> 12) & 0x07),
2110 ((srcval >> 2) & 0xf8) | /* g */
2111 ((srcval >> 7) & 0x07),
2112 ((srcval << 3) & 0xf8) | /* b */
2113 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2114 if ((x&1)==1) {
2115 *dstbyte++=dstval;
2116 dstval=0;
2119 if ((dstwidth&1)!=0) {
2120 *dstbyte=dstval;
2122 srcbits -= bmpImage->bytes_per_line;
2123 dstbits += linebytes;
2125 } else if (bmpImage->blue_mask==0x7c00) {
2126 /* ==== bgr 555 bmp -> pal 4 dib ==== */
2127 for (h=0; h<lines; h++) {
2128 WORD dstval;
2129 srcpixel=srcbits;
2130 dstbyte=dstbits;
2131 dstval=0;
2132 for (x=0; x<dstwidth; x++) {
2133 WORD srcval;
2134 srcval=*srcpixel++;
2135 dstval|=(X11DRV_DIB_GetNearestIndex
2136 (colors, 16,
2137 ((srcval << 3) & 0xf8) | /* r */
2138 ((srcval >> 2) & 0x07),
2139 ((srcval >> 2) & 0xf8) | /* g */
2140 ((srcval >> 7) & 0x07),
2141 ((srcval >> 7) & 0xf8) | /* b */
2142 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2143 if ((x&1)==1) {
2144 *dstbyte++=dstval;
2145 dstval=0;
2148 if ((dstwidth&1)!=0) {
2149 *dstbyte=dstval;
2151 srcbits -= bmpImage->bytes_per_line;
2152 dstbits += linebytes;
2154 } else {
2155 goto notsupported;
2157 } else if (bmpImage->green_mask==0x07e0) {
2158 if (bmpImage->red_mask==0xf800) {
2159 /* ==== rgb 565 bmp -> pal 4 dib ==== */
2160 for (h=0; h<lines; h++) {
2161 BYTE dstval;
2162 srcpixel=srcbits;
2163 dstbyte=dstbits;
2164 dstval=0;
2165 for (x=0; x<dstwidth; x++) {
2166 WORD srcval;
2167 srcval=*srcpixel++;
2168 dstval|=(X11DRV_DIB_GetNearestIndex
2169 (colors, 16,
2170 ((srcval >> 8) & 0xf8) | /* r */
2171 ((srcval >> 13) & 0x07),
2172 ((srcval >> 3) & 0xfc) | /* g */
2173 ((srcval >> 9) & 0x03),
2174 ((srcval << 3) & 0xf8) | /* b */
2175 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2176 if ((x&1)==1) {
2177 *dstbyte++=dstval;
2178 dstval=0;
2181 if ((dstwidth&1)!=0) {
2182 *dstbyte=dstval;
2184 srcbits -= bmpImage->bytes_per_line;
2185 dstbits += linebytes;
2187 } else if (bmpImage->blue_mask==0xf800) {
2188 /* ==== bgr 565 bmp -> pal 4 dib ==== */
2189 for (h=0; h<lines; h++) {
2190 WORD dstval;
2191 srcpixel=srcbits;
2192 dstbyte=dstbits;
2193 dstval=0;
2194 for (x=0; x<dstwidth; x++) {
2195 WORD srcval;
2196 srcval=*srcpixel++;
2197 dstval|=(X11DRV_DIB_GetNearestIndex
2198 (colors, 16,
2199 ((srcval << 3) & 0xf8) | /* r */
2200 ((srcval >> 2) & 0x07),
2201 ((srcval >> 3) & 0xfc) | /* g */
2202 ((srcval >> 9) & 0x03),
2203 ((srcval >> 8) & 0xf8) | /* b */
2204 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2205 if ((x&1)==1) {
2206 *dstbyte++=dstval;
2207 dstval=0;
2210 if ((dstwidth&1)!=0) {
2211 *dstbyte=dstval;
2213 srcbits -= bmpImage->bytes_per_line;
2214 dstbits += linebytes;
2216 } else {
2217 goto notsupported;
2219 } else {
2220 goto notsupported;
2223 break;
2225 case 24:
2226 if (bmpImage->bits_per_pixel==24) {
2227 const void* srcbits;
2228 const BYTE *srcbyte;
2229 BYTE* dstbyte;
2231 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2233 if (bmpImage->green_mask!=0x00ff00 ||
2234 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2235 goto notsupported;
2236 } else if (bmpImage->blue_mask==0xff) {
2237 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2238 for (h=0; h<lines; h++) {
2239 srcbyte=srcbits;
2240 dstbyte=dstbits;
2241 for (x=0; x<dstwidth/2; x++) {
2242 /* Do 2 pixels at a time */
2243 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2244 (colors, 16,
2245 srcbyte[2],
2246 srcbyte[1],
2247 srcbyte[0]) << 4) |
2248 X11DRV_DIB_GetNearestIndex
2249 (colors, 16,
2250 srcbyte[5],
2251 srcbyte[4],
2252 srcbyte[3]);
2253 srcbyte+=6;
2255 if (dstwidth&1) {
2256 /* And the the odd pixel */
2257 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2258 (colors, 16,
2259 srcbyte[2],
2260 srcbyte[1],
2261 srcbyte[0]) << 4);
2263 srcbits -= bmpImage->bytes_per_line;
2264 dstbits += linebytes;
2266 } else {
2267 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2268 for (h=0; h<lines; h++) {
2269 srcbyte=srcbits;
2270 dstbyte=dstbits;
2271 for (x=0; x<dstwidth/2; x++) {
2272 /* Do 2 pixels at a time */
2273 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2274 (colors, 16,
2275 srcbyte[0],
2276 srcbyte[1],
2277 srcbyte[2]) << 4) |
2278 X11DRV_DIB_GetNearestIndex
2279 (colors, 16,
2280 srcbyte[3],
2281 srcbyte[4],
2282 srcbyte[5]);
2283 srcbyte+=6;
2285 if (dstwidth&1) {
2286 /* And the the odd pixel */
2287 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2288 (colors, 16,
2289 srcbyte[0],
2290 srcbyte[1],
2291 srcbyte[2]) << 4);
2293 srcbits -= bmpImage->bytes_per_line;
2294 dstbits += linebytes;
2297 break;
2299 /* Fall through */
2301 case 32:
2303 const void* srcbits;
2304 const BYTE *srcbyte;
2305 BYTE* dstbyte;
2307 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2309 if (bmpImage->green_mask!=0x00ff00 ||
2310 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2311 goto notsupported;
2312 } else if (bmpImage->blue_mask==0xff) {
2313 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2314 for (h=0; h<lines; h++) {
2315 srcbyte=srcbits;
2316 dstbyte=dstbits;
2317 for (x=0; x<dstwidth/2; x++) {
2318 /* Do 2 pixels at a time */
2319 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2320 (colors, 16,
2321 srcbyte[2],
2322 srcbyte[1],
2323 srcbyte[0]) << 4) |
2324 X11DRV_DIB_GetNearestIndex
2325 (colors, 16,
2326 srcbyte[6],
2327 srcbyte[5],
2328 srcbyte[4]);
2329 srcbyte+=8;
2331 if (dstwidth&1) {
2332 /* And the the odd pixel */
2333 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2334 (colors, 16,
2335 srcbyte[2],
2336 srcbyte[1],
2337 srcbyte[0]) << 4);
2339 srcbits -= bmpImage->bytes_per_line;
2340 dstbits += linebytes;
2342 } else {
2343 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2344 for (h=0; h<lines; h++) {
2345 srcbyte=srcbits;
2346 dstbyte=dstbits;
2347 for (x=0; x<dstwidth/2; x++) {
2348 /* Do 2 pixels at a time */
2349 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2350 (colors, 16,
2351 srcbyte[0],
2352 srcbyte[1],
2353 srcbyte[2]) << 4) |
2354 X11DRV_DIB_GetNearestIndex
2355 (colors, 16,
2356 srcbyte[4],
2357 srcbyte[5],
2358 srcbyte[6]);
2359 srcbyte+=8;
2361 if (dstwidth&1) {
2362 /* And the the odd pixel */
2363 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2364 (colors, 16,
2365 srcbyte[0],
2366 srcbyte[1],
2367 srcbyte[2]) << 4);
2369 srcbits -= bmpImage->bytes_per_line;
2370 dstbits += linebytes;
2374 break;
2376 default:
2377 notsupported:
2379 BYTE* dstbyte;
2381 /* ==== any bmp format -> pal 4 dib ==== */
2382 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2383 bmpImage->bits_per_pixel, bmpImage->red_mask,
2384 bmpImage->green_mask, bmpImage->blue_mask );
2385 for (h=lines-1; h>=0; h--) {
2386 dstbyte=dstbits;
2387 for (x=0; x<(dstwidth & ~1); x+=2) {
2388 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2389 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2391 if (dstwidth & 1) {
2392 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2394 dstbits += linebytes;
2397 break;
2401 /***********************************************************************
2402 * X11DRV_DIB_SetImageBits_RLE4
2404 * SetDIBits for a 4-bit deep compressed DIB.
2406 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2407 DWORD width, DWORD dstwidth,
2408 int left, int *colors,
2409 XImage *bmpImage )
2411 int x = 0, y = lines - 1, c, length;
2412 const BYTE *begin = bits;
2414 while (y >= 0)
2416 length = *bits++;
2417 if (length) { /* encoded */
2418 c = *bits++;
2419 while (length--) {
2420 if (x >= width) break;
2421 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2422 if (!length--) break;
2423 if (x >= width) break;
2424 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2426 } else {
2427 length = *bits++;
2428 switch (length)
2430 case RLE_EOL:
2431 x = 0;
2432 y--;
2433 break;
2435 case RLE_END:
2436 return;
2438 case RLE_DELTA:
2439 x += *bits++;
2440 y -= *bits++;
2441 break;
2443 default: /* absolute */
2444 while (length--) {
2445 c = *bits++;
2446 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2447 if (!length--) break;
2448 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2450 if ((bits - begin) & 1)
2451 bits++;
2459 /***********************************************************************
2460 * X11DRV_DIB_SetImageBits_8
2462 * SetDIBits for an 8-bit deep DIB.
2464 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2465 DWORD srcwidth, DWORD dstwidth, int left,
2466 const int *colors, XImage *bmpImage,
2467 DWORD linebytes )
2469 DWORD x;
2470 int h;
2471 const BYTE* srcbyte;
2472 BYTE* dstbits;
2474 if (lines < 0 )
2476 lines = -lines;
2477 srcbits = srcbits + linebytes * (lines-1);
2478 linebytes = -linebytes;
2480 srcbits += left;
2481 srcbyte = srcbits;
2483 switch (bmpImage->depth) {
2484 case 15:
2485 case 16:
2486 #if defined(__i386__) && defined(__GNUC__)
2487 /* Some X servers might have 32 bit/ 16bit deep pixel */
2488 if (lines && dstwidth && (bmpImage->bits_per_pixel == 16))
2490 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2491 /* FIXME: Does this really handle all these cases correctly? */
2492 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2493 for (h = lines ; h--; ) {
2494 int _cl1,_cl2; /* temp outputs for asm below */
2495 /* Borrowed from DirectDraw */
2496 __asm__ __volatile__(
2497 "xor %%eax,%%eax\n"
2498 "cld\n"
2499 "1:\n"
2500 " lodsb\n"
2501 " movw (%%edx,%%eax,4),%%ax\n"
2502 " stosw\n"
2503 " xor %%eax,%%eax\n"
2504 " loop 1b\n"
2505 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2506 :"S" (srcbyte),
2507 "D" (dstbits),
2508 "c" (dstwidth),
2509 "d" (colors)
2510 :"eax", "cc", "memory"
2512 srcbyte = (srcbits += linebytes);
2513 dstbits -= bmpImage->bytes_per_line;
2515 return;
2517 break;
2518 #endif
2519 case 24:
2520 case 32:
2521 #if defined(__i386__) && defined(__GNUC__)
2522 if (lines && dstwidth && (bmpImage->bits_per_pixel == 32))
2524 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2525 /* FIXME: Does this really handle both cases correctly? */
2526 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2527 for (h = lines ; h--; ) {
2528 int _cl1,_cl2; /* temp outputs for asm below */
2529 /* Borrowed from DirectDraw */
2530 __asm__ __volatile__(
2531 "xor %%eax,%%eax\n"
2532 "cld\n"
2533 "1:\n"
2534 " lodsb\n"
2535 " movl (%%edx,%%eax,4),%%eax\n"
2536 " stosl\n"
2537 " xor %%eax,%%eax\n"
2538 " loop 1b\n"
2539 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2540 :"S" (srcbyte),
2541 "D" (dstbits),
2542 "c" (dstwidth),
2543 "d" (colors)
2544 :"eax", "cc", "memory"
2546 srcbyte = (srcbits += linebytes);
2547 dstbits -= bmpImage->bytes_per_line;
2549 return;
2551 break;
2552 #endif
2553 default:
2554 break; /* use slow generic case below */
2557 /* ==== pal 8 dib -> any bmp format ==== */
2558 for (h=lines-1; h>=0; h--) {
2559 for (x=left; x<dstwidth+left; x++) {
2560 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2562 srcbyte = (srcbits += linebytes);
2566 /***********************************************************************
2567 * X11DRV_DIB_GetImageBits_8
2569 * GetDIBits for an 8-bit deep DIB.
2571 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2572 DWORD srcwidth, DWORD dstwidth,
2573 RGBQUAD *colors, PALETTEENTRY *srccolors,
2574 XImage *bmpImage, DWORD linebytes )
2576 DWORD x;
2577 int h;
2578 BYTE* dstbyte;
2580 if (lines < 0 )
2582 lines = -lines;
2583 dstbits = dstbits + ( linebytes * (lines-1) );
2584 linebytes = -linebytes;
2588 * Hack for now
2589 * This condition is true when GetImageBits has been called by
2590 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2591 * 256 colormaps, so we'll just use for for GetDIBits calls.
2592 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2594 if (!srccolors) goto updatesection;
2596 switch (bmpImage->depth) {
2597 case 1:
2598 case 4:
2599 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2601 /* ==== pal 1 bmp -> pal 8 dib ==== */
2602 /* ==== pal 4 bmp -> pal 8 dib ==== */
2603 for (h=lines-1; h>=0; h--) {
2604 dstbyte=dstbits;
2605 for (x=0; x<dstwidth; x++) {
2606 PALETTEENTRY srcval;
2607 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2608 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2609 srcval.peRed,
2610 srcval.peGreen,
2611 srcval.peBlue);
2613 dstbits += linebytes;
2615 } else {
2616 goto notsupported;
2618 break;
2620 case 8:
2621 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2622 /* ==== pal 8 bmp -> pal 8 dib ==== */
2623 const void* srcbits;
2624 const BYTE* srcpixel;
2626 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2627 for (h=0; h<lines; h++) {
2628 srcpixel=srcbits;
2629 dstbyte=dstbits;
2630 for (x = 0; x < dstwidth; x++) {
2631 PALETTEENTRY srcval;
2632 srcval=srccolors[(int)*srcpixel++];
2633 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2634 srcval.peRed,
2635 srcval.peGreen,
2636 srcval.peBlue);
2638 srcbits -= bmpImage->bytes_per_line;
2639 dstbits += linebytes;
2641 } else {
2642 goto notsupported;
2644 break;
2646 case 15:
2647 case 16:
2649 const void* srcbits;
2650 const WORD* srcpixel;
2651 BYTE* dstbyte;
2653 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2655 if (bmpImage->green_mask==0x03e0) {
2656 if (bmpImage->red_mask==0x7c00) {
2657 /* ==== rgb 555 bmp -> pal 8 dib ==== */
2658 for (h=0; h<lines; h++) {
2659 srcpixel=srcbits;
2660 dstbyte=dstbits;
2661 for (x=0; x<dstwidth; x++) {
2662 WORD srcval;
2663 srcval=*srcpixel++;
2664 *dstbyte++=X11DRV_DIB_GetNearestIndex
2665 (colors, 256,
2666 ((srcval >> 7) & 0xf8) | /* r */
2667 ((srcval >> 12) & 0x07),
2668 ((srcval >> 2) & 0xf8) | /* g */
2669 ((srcval >> 7) & 0x07),
2670 ((srcval << 3) & 0xf8) | /* b */
2671 ((srcval >> 2) & 0x07) );
2673 srcbits -= bmpImage->bytes_per_line;
2674 dstbits += linebytes;
2676 } else if (bmpImage->blue_mask==0x7c00) {
2677 /* ==== bgr 555 bmp -> pal 8 dib ==== */
2678 for (h=0; h<lines; h++) {
2679 srcpixel=srcbits;
2680 dstbyte=dstbits;
2681 for (x=0; x<dstwidth; x++) {
2682 WORD srcval;
2683 srcval=*srcpixel++;
2684 *dstbyte++=X11DRV_DIB_GetNearestIndex
2685 (colors, 256,
2686 ((srcval << 3) & 0xf8) | /* r */
2687 ((srcval >> 2) & 0x07),
2688 ((srcval >> 2) & 0xf8) | /* g */
2689 ((srcval >> 7) & 0x07),
2690 ((srcval >> 7) & 0xf8) | /* b */
2691 ((srcval >> 12) & 0x07) );
2693 srcbits -= bmpImage->bytes_per_line;
2694 dstbits += linebytes;
2696 } else {
2697 goto notsupported;
2699 } else if (bmpImage->green_mask==0x07e0) {
2700 if (bmpImage->red_mask==0xf800) {
2701 /* ==== rgb 565 bmp -> pal 8 dib ==== */
2702 for (h=0; h<lines; h++) {
2703 srcpixel=srcbits;
2704 dstbyte=dstbits;
2705 for (x=0; x<dstwidth; x++) {
2706 WORD srcval;
2707 srcval=*srcpixel++;
2708 *dstbyte++=X11DRV_DIB_GetNearestIndex
2709 (colors, 256,
2710 ((srcval >> 8) & 0xf8) | /* r */
2711 ((srcval >> 13) & 0x07),
2712 ((srcval >> 3) & 0xfc) | /* g */
2713 ((srcval >> 9) & 0x03),
2714 ((srcval << 3) & 0xf8) | /* b */
2715 ((srcval >> 2) & 0x07) );
2717 srcbits -= bmpImage->bytes_per_line;
2718 dstbits += linebytes;
2720 } else if (bmpImage->blue_mask==0xf800) {
2721 /* ==== bgr 565 bmp -> pal 8 dib ==== */
2722 for (h=0; h<lines; h++) {
2723 srcpixel=srcbits;
2724 dstbyte=dstbits;
2725 for (x=0; x<dstwidth; x++) {
2726 WORD srcval;
2727 srcval=*srcpixel++;
2728 *dstbyte++=X11DRV_DIB_GetNearestIndex
2729 (colors, 256,
2730 ((srcval << 3) & 0xf8) | /* r */
2731 ((srcval >> 2) & 0x07),
2732 ((srcval >> 3) & 0xfc) | /* g */
2733 ((srcval >> 9) & 0x03),
2734 ((srcval >> 8) & 0xf8) | /* b */
2735 ((srcval >> 13) & 0x07) );
2737 srcbits -= bmpImage->bytes_per_line;
2738 dstbits += linebytes;
2740 } else {
2741 goto notsupported;
2743 } else {
2744 goto notsupported;
2747 break;
2749 case 24:
2750 case 32:
2752 const void* srcbits;
2753 const BYTE *srcbyte;
2754 BYTE* dstbyte;
2755 int bytes_per_pixel;
2757 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2758 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2760 if (bmpImage->green_mask!=0x00ff00 ||
2761 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2762 goto notsupported;
2763 } else if (bmpImage->blue_mask==0xff) {
2764 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2765 for (h=0; h<lines; h++) {
2766 srcbyte=srcbits;
2767 dstbyte=dstbits;
2768 for (x=0; x<dstwidth; x++) {
2769 *dstbyte++=X11DRV_DIB_GetNearestIndex
2770 (colors, 256,
2771 srcbyte[2],
2772 srcbyte[1],
2773 srcbyte[0]);
2774 srcbyte+=bytes_per_pixel;
2776 srcbits -= bmpImage->bytes_per_line;
2777 dstbits += linebytes;
2779 } else {
2780 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2781 for (h=0; h<lines; h++) {
2782 srcbyte=srcbits;
2783 dstbyte=dstbits;
2784 for (x=0; x<dstwidth; x++) {
2785 *dstbyte++=X11DRV_DIB_GetNearestIndex
2786 (colors, 256,
2787 srcbyte[0],
2788 srcbyte[1],
2789 srcbyte[2]);
2790 srcbyte+=bytes_per_pixel;
2792 srcbits -= bmpImage->bytes_per_line;
2793 dstbits += linebytes;
2797 break;
2799 default:
2800 notsupported:
2801 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2802 bmpImage->depth, bmpImage->red_mask,
2803 bmpImage->green_mask, bmpImage->blue_mask );
2804 updatesection:
2805 /* ==== any bmp format -> pal 8 dib ==== */
2806 for (h=lines-1; h>=0; h--) {
2807 dstbyte=dstbits;
2808 for (x=0; x<dstwidth; x++) {
2809 *dstbyte=X11DRV_DIB_MapColor
2810 ((int*)colors, 256,
2811 XGetPixel(bmpImage, x, h), *dstbyte);
2812 dstbyte++;
2814 dstbits += linebytes;
2816 break;
2820 /***********************************************************************
2821 * X11DRV_DIB_SetImageBits_RLE8
2823 * SetDIBits for an 8-bit deep compressed DIB.
2825 * This function rewritten 941113 by James Youngman. WINE blew out when I
2826 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2828 * This was because the algorithm assumed that all RLE8 bitmaps end with the
2829 * 'End of bitmap' escape code. This code is very much laxer in what it
2830 * allows to end the expansion. Possibly too lax. See the note by
2831 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
2832 * bitmap should end with RleEnd, but on the other hand, software exists
2833 * that produces ones that don't and Windows 3.1 doesn't complain a bit
2834 * about it.
2836 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
2837 * James A. Youngman <mbcstjy@afs.man.ac.uk>
2838 * [JAY]
2840 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2841 DWORD width, DWORD dstwidth,
2842 int left, int *colors,
2843 XImage *bmpImage )
2845 int x; /* X-positon on each line. Increases. */
2846 int y; /* Line #. Starts at lines-1, decreases */
2847 const BYTE *pIn = bits; /* Pointer to current position in bits */
2848 BYTE length; /* The length pf a run */
2849 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
2852 * Note that the bitmap data is stored by Windows starting at the
2853 * bottom line of the bitmap and going upwards. Within each line,
2854 * the data is stored left-to-right. That's the reason why line
2855 * goes from lines-1 to 0. [JAY]
2858 x = 0;
2859 y = lines - 1;
2860 while (y >= 0)
2862 length = *pIn++;
2865 * If the length byte is not zero (which is the escape value),
2866 * We have a run of length pixels all the same colour. The colour
2867 * index is stored next.
2869 * If the length byte is zero, we need to read the next byte to
2870 * know what to do. [JAY]
2872 if (length != 0)
2875 * [Run-Length] Encoded mode
2877 int color = colors[*pIn++];
2878 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2880 else
2883 * Escape codes (may be an absolute sequence though)
2885 escape_code = (*pIn++);
2886 switch(escape_code)
2888 case RLE_EOL:
2889 x = 0;
2890 y--;
2891 break;
2893 case RLE_END:
2894 /* Not all RLE8 bitmaps end with this code. For
2895 * example, Paint Shop Pro produces some that don't.
2896 * That's (I think) what caused the previous
2897 * implementation to fail. [JAY]
2899 return;
2901 case RLE_DELTA:
2902 x += (*pIn++);
2903 y -= (*pIn++);
2904 break;
2906 default: /* switch to absolute mode */
2907 length = escape_code;
2908 while (length--)
2910 int color = colors[*pIn++];
2911 if (x >= dstwidth)
2913 pIn += length;
2914 break;
2916 XPutPixel(bmpImage, x++, y, color);
2919 * If you think for a moment you'll realise that the
2920 * only time we could ever possibly read an odd
2921 * number of bytes is when there is a 0x00 (escape),
2922 * a value >0x02 (absolute mode) and then an odd-
2923 * length run. Therefore this is the only place we
2924 * need to worry about it. Everywhere else the
2925 * bytes are always read in pairs. [JAY]
2927 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2928 break;
2929 } /* switch (escape_code) : Escape sequence */
2935 /***********************************************************************
2936 * X11DRV_DIB_SetImageBits_16
2938 * SetDIBits for a 16-bit deep DIB.
2940 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2941 DWORD srcwidth, DWORD dstwidth, int left,
2942 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2943 XImage *bmpImage, DWORD linebytes )
2945 DWORD x;
2946 int h;
2948 if (lines < 0 )
2950 lines = -lines;
2951 srcbits = srcbits + ( linebytes * (lines-1));
2952 linebytes = -linebytes;
2955 switch (bmpImage->depth)
2957 case 15:
2958 case 16:
2960 char* dstbits;
2962 srcbits=srcbits+left*2;
2963 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2965 if (bmpImage->green_mask==0x03e0) {
2966 if (gSrc==bmpImage->green_mask) {
2967 if (rSrc==bmpImage->red_mask) {
2968 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2969 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
2970 X11DRV_DIB_Convert_any_asis
2971 (dstwidth,lines,2,
2972 srcbits,linebytes,
2973 dstbits,-bmpImage->bytes_per_line);
2974 } else if (rSrc==bmpImage->blue_mask) {
2975 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
2976 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
2977 X11DRV_DIB_Convert_555_reverse
2978 (dstwidth,lines,
2979 srcbits,linebytes,
2980 dstbits,-bmpImage->bytes_per_line);
2982 } else {
2983 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
2984 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
2985 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
2986 X11DRV_DIB_Convert_565_to_555_asis
2987 (dstwidth,lines,
2988 srcbits,linebytes,
2989 dstbits,-bmpImage->bytes_per_line);
2990 } else {
2991 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
2992 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
2993 X11DRV_DIB_Convert_565_to_555_reverse
2994 (dstwidth,lines,
2995 srcbits,linebytes,
2996 dstbits,-bmpImage->bytes_per_line);
2999 } else if (bmpImage->green_mask==0x07e0) {
3000 if (gSrc==bmpImage->green_mask) {
3001 if (rSrc==bmpImage->red_mask) {
3002 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
3003 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
3004 X11DRV_DIB_Convert_any_asis
3005 (dstwidth,lines,2,
3006 srcbits,linebytes,
3007 dstbits,-bmpImage->bytes_per_line);
3008 } else {
3009 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
3010 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
3011 X11DRV_DIB_Convert_565_reverse
3012 (dstwidth,lines,
3013 srcbits,linebytes,
3014 dstbits,-bmpImage->bytes_per_line);
3016 } else {
3017 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3018 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3019 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3020 X11DRV_DIB_Convert_555_to_565_asis
3021 (dstwidth,lines,
3022 srcbits,linebytes,
3023 dstbits,-bmpImage->bytes_per_line);
3024 } else {
3025 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3026 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3027 X11DRV_DIB_Convert_555_to_565_reverse
3028 (dstwidth,lines,
3029 srcbits,linebytes,
3030 dstbits,-bmpImage->bytes_per_line);
3033 } else {
3034 goto notsupported;
3037 break;
3039 case 24:
3040 if (bmpImage->bits_per_pixel==24) {
3041 char* dstbits;
3043 srcbits=srcbits+left*2;
3044 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3046 if (bmpImage->green_mask!=0x00ff00 ||
3047 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3048 goto notsupported;
3049 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3050 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3051 if (gSrc==0x03e0) {
3052 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3053 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3054 X11DRV_DIB_Convert_555_to_888_asis
3055 (dstwidth,lines,
3056 srcbits,linebytes,
3057 dstbits,-bmpImage->bytes_per_line);
3058 } else {
3059 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3060 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3061 X11DRV_DIB_Convert_565_to_888_asis
3062 (dstwidth,lines,
3063 srcbits,linebytes,
3064 dstbits,-bmpImage->bytes_per_line);
3066 } else {
3067 if (gSrc==0x03e0) {
3068 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3069 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3070 X11DRV_DIB_Convert_555_to_888_reverse
3071 (dstwidth,lines,
3072 srcbits,linebytes,
3073 dstbits,-bmpImage->bytes_per_line);
3074 } else {
3075 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3076 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3077 X11DRV_DIB_Convert_565_to_888_reverse
3078 (dstwidth,lines,
3079 srcbits,linebytes,
3080 dstbits,-bmpImage->bytes_per_line);
3083 break;
3085 /* Fall through */
3087 case 32:
3089 char* dstbits;
3091 srcbits=srcbits+left*2;
3092 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3094 if (bmpImage->green_mask!=0x00ff00 ||
3095 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3096 goto notsupported;
3097 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3098 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3099 if (gSrc==0x03e0) {
3100 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3101 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3102 X11DRV_DIB_Convert_555_to_0888_asis
3103 (dstwidth,lines,
3104 srcbits,linebytes,
3105 dstbits,-bmpImage->bytes_per_line);
3106 } else {
3107 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3108 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3109 X11DRV_DIB_Convert_565_to_0888_asis
3110 (dstwidth,lines,
3111 srcbits,linebytes,
3112 dstbits,-bmpImage->bytes_per_line);
3114 } else {
3115 if (gSrc==0x03e0) {
3116 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3117 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3118 X11DRV_DIB_Convert_555_to_0888_reverse
3119 (dstwidth,lines,
3120 srcbits,linebytes,
3121 dstbits,-bmpImage->bytes_per_line);
3122 } else {
3123 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3124 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3125 X11DRV_DIB_Convert_565_to_0888_reverse
3126 (dstwidth,lines,
3127 srcbits,linebytes,
3128 dstbits,-bmpImage->bytes_per_line);
3132 break;
3134 default:
3135 notsupported:
3136 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3137 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3138 bmpImage->green_mask, bmpImage->blue_mask );
3139 /* fall through */
3140 case 1:
3141 case 4:
3142 case 8:
3144 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3145 const WORD* srcpixel;
3146 int rShift1,gShift1,bShift1;
3147 int rShift2,gShift2,bShift2;
3148 BYTE gMask1,gMask2;
3150 /* Set color scaling values */
3151 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3152 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3153 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3154 rShift2=rShift1+5;
3155 gShift2=gShift1+5;
3156 bShift2=bShift1+5;
3157 if (gSrc==0x03e0) {
3158 /* Green has 5 bits, like the others */
3159 gMask1=0xf8;
3160 gMask2=0x07;
3161 } else {
3162 /* Green has 6 bits, not 5. Compensate. */
3163 gShift1++;
3164 gShift2+=2;
3165 gMask1=0xfc;
3166 gMask2=0x03;
3169 srcbits+=2*left;
3171 /* We could split it into four separate cases to optimize
3172 * but it is probably not worth it.
3174 for (h=lines-1; h>=0; h--) {
3175 srcpixel=(const WORD*)srcbits;
3176 for (x=left; x<dstwidth+left; x++) {
3177 DWORD srcval;
3178 BYTE red,green,blue;
3179 srcval=*srcpixel++ << 16;
3180 red= ((srcval >> rShift1) & 0xf8) |
3181 ((srcval >> rShift2) & 0x07);
3182 green=((srcval >> gShift1) & gMask1) |
3183 ((srcval >> gShift2) & gMask2);
3184 blue= ((srcval >> bShift1) & 0xf8) |
3185 ((srcval >> bShift2) & 0x07);
3186 XPutPixel(bmpImage, x, h,
3187 X11DRV_PALETTE_ToPhysical
3188 (physDev, RGB(red,green,blue)));
3190 srcbits += linebytes;
3193 break;
3198 /***********************************************************************
3199 * X11DRV_DIB_GetImageBits_16
3201 * GetDIBits for an 16-bit deep DIB.
3203 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3204 DWORD dstwidth, DWORD srcwidth,
3205 PALETTEENTRY *srccolors,
3206 DWORD rDst, DWORD gDst, DWORD bDst,
3207 XImage *bmpImage, DWORD dibpitch )
3209 DWORD x;
3210 int h;
3212 DWORD linebytes = dibpitch;
3214 if (lines < 0 )
3216 lines = -lines;
3217 dstbits = dstbits + ( linebytes * (lines-1));
3218 linebytes = -linebytes;
3221 switch (bmpImage->depth)
3223 case 15:
3224 case 16:
3226 const char* srcbits;
3228 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3230 if (bmpImage->green_mask==0x03e0) {
3231 if (gDst==bmpImage->green_mask) {
3232 if (rDst==bmpImage->red_mask) {
3233 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3234 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3235 X11DRV_DIB_Convert_any_asis
3236 (dstwidth,lines,2,
3237 srcbits,-bmpImage->bytes_per_line,
3238 dstbits,linebytes);
3239 } else {
3240 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3241 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3242 X11DRV_DIB_Convert_555_reverse
3243 (dstwidth,lines,
3244 srcbits,-bmpImage->bytes_per_line,
3245 dstbits,linebytes);
3247 } else {
3248 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3249 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3250 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3251 X11DRV_DIB_Convert_555_to_565_asis
3252 (dstwidth,lines,
3253 srcbits,-bmpImage->bytes_per_line,
3254 dstbits,linebytes);
3255 } else {
3256 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3257 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3258 X11DRV_DIB_Convert_555_to_565_reverse
3259 (dstwidth,lines,
3260 srcbits,-bmpImage->bytes_per_line,
3261 dstbits,linebytes);
3264 } else if (bmpImage->green_mask==0x07e0) {
3265 if (gDst==bmpImage->green_mask) {
3266 if (rDst == bmpImage->red_mask) {
3267 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3268 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3269 X11DRV_DIB_Convert_any_asis
3270 (dstwidth,lines,2,
3271 srcbits,-bmpImage->bytes_per_line,
3272 dstbits,linebytes);
3273 } else {
3274 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3275 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3276 X11DRV_DIB_Convert_565_reverse
3277 (dstwidth,lines,
3278 srcbits,-bmpImage->bytes_per_line,
3279 dstbits,linebytes);
3281 } else {
3282 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3283 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3284 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3285 X11DRV_DIB_Convert_565_to_555_asis
3286 (dstwidth,lines,
3287 srcbits,-bmpImage->bytes_per_line,
3288 dstbits,linebytes);
3289 } else {
3290 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3291 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3292 X11DRV_DIB_Convert_565_to_555_reverse
3293 (dstwidth,lines,
3294 srcbits,-bmpImage->bytes_per_line,
3295 dstbits,linebytes);
3298 } else {
3299 goto notsupported;
3302 break;
3304 case 24:
3305 if (bmpImage->bits_per_pixel == 24) {
3306 const char* srcbits;
3308 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3310 if (bmpImage->green_mask!=0x00ff00 ||
3311 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3312 goto notsupported;
3313 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3314 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3315 if (gDst==0x03e0) {
3316 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3317 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3318 X11DRV_DIB_Convert_888_to_555_asis
3319 (dstwidth,lines,
3320 srcbits,-bmpImage->bytes_per_line,
3321 dstbits,linebytes);
3322 } else {
3323 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3324 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3325 X11DRV_DIB_Convert_888_to_565_asis
3326 (dstwidth,lines,
3327 srcbits,-bmpImage->bytes_per_line,
3328 dstbits,linebytes);
3330 } else {
3331 if (gDst==0x03e0) {
3332 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3333 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3334 X11DRV_DIB_Convert_888_to_555_reverse
3335 (dstwidth,lines,
3336 srcbits,-bmpImage->bytes_per_line,
3337 dstbits,linebytes);
3338 } else {
3339 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3340 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3341 X11DRV_DIB_Convert_888_to_565_reverse
3342 (dstwidth,lines,
3343 srcbits,-bmpImage->bytes_per_line,
3344 dstbits,linebytes);
3347 break;
3349 /* Fall through */
3351 case 32:
3353 const char* srcbits;
3355 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3357 if (bmpImage->green_mask!=0x00ff00 ||
3358 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3359 goto notsupported;
3360 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3361 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3362 if (gDst==0x03e0) {
3363 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3364 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3365 X11DRV_DIB_Convert_0888_to_555_asis
3366 (dstwidth,lines,
3367 srcbits,-bmpImage->bytes_per_line,
3368 dstbits,linebytes);
3369 } else {
3370 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3371 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3372 X11DRV_DIB_Convert_0888_to_565_asis
3373 (dstwidth,lines,
3374 srcbits,-bmpImage->bytes_per_line,
3375 dstbits,linebytes);
3377 } else {
3378 if (gDst==0x03e0) {
3379 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3380 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3381 X11DRV_DIB_Convert_0888_to_555_reverse
3382 (dstwidth,lines,
3383 srcbits,-bmpImage->bytes_per_line,
3384 dstbits,linebytes);
3385 } else {
3386 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3387 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3388 X11DRV_DIB_Convert_0888_to_565_reverse
3389 (dstwidth,lines,
3390 srcbits,-bmpImage->bytes_per_line,
3391 dstbits,linebytes);
3395 break;
3397 case 1:
3398 case 4:
3399 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3400 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3401 int rShift,gShift,bShift;
3402 WORD* dstpixel;
3404 /* Shift everything 16 bits left so that all shifts are >0,
3405 * even for BGR DIBs. Then a single >> 16 will bring everything
3406 * back into place.
3408 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3409 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3410 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3411 if (gDst==0x07e0) {
3412 /* 6 bits for the green */
3413 gShift++;
3415 rDst=rDst << 16;
3416 gDst=gDst << 16;
3417 bDst=bDst << 16;
3418 for (h = lines - 1; h >= 0; h--) {
3419 dstpixel=(LPWORD)dstbits;
3420 for (x = 0; x < dstwidth; x++) {
3421 PALETTEENTRY srcval;
3422 DWORD dstval;
3423 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3424 dstval=((srcval.peRed << rShift) & rDst) |
3425 ((srcval.peGreen << gShift) & gDst) |
3426 ((srcval.peBlue << bShift) & bDst);
3427 *dstpixel++=dstval >> 16;
3429 dstbits += linebytes;
3431 } else {
3432 goto notsupported;
3434 break;
3436 case 8:
3437 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3438 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3439 int rShift,gShift,bShift;
3440 const BYTE* srcbits;
3441 const BYTE* srcpixel;
3442 WORD* dstpixel;
3444 /* Shift everything 16 bits left so that all shifts are >0,
3445 * even for BGR DIBs. Then a single >> 16 will bring everything
3446 * back into place.
3448 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3449 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3450 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3451 if (gDst==0x07e0) {
3452 /* 6 bits for the green */
3453 gShift++;
3455 rDst=rDst << 16;
3456 gDst=gDst << 16;
3457 bDst=bDst << 16;
3458 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3459 for (h=0; h<lines; h++) {
3460 srcpixel=srcbits;
3461 dstpixel=(LPWORD)dstbits;
3462 for (x = 0; x < dstwidth; x++) {
3463 PALETTEENTRY srcval;
3464 DWORD dstval;
3465 srcval=srccolors[(int)*srcpixel++];
3466 dstval=((srcval.peRed << rShift) & rDst) |
3467 ((srcval.peGreen << gShift) & gDst) |
3468 ((srcval.peBlue << bShift) & bDst);
3469 *dstpixel++=dstval >> 16;
3471 srcbits -= bmpImage->bytes_per_line;
3472 dstbits += linebytes;
3474 } else {
3475 goto notsupported;
3477 break;
3479 default:
3480 notsupported:
3482 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3483 int rShift,gShift,bShift;
3484 WORD* dstpixel;
3486 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3487 bmpImage->depth, bmpImage->red_mask,
3488 bmpImage->green_mask, bmpImage->blue_mask,
3489 rDst, gDst, bDst);
3491 /* Shift everything 16 bits left so that all shifts are >0,
3492 * even for BGR DIBs. Then a single >> 16 will bring everything
3493 * back into place.
3495 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3496 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3497 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3498 if (gDst==0x07e0) {
3499 /* 6 bits for the green */
3500 gShift++;
3502 rDst=rDst << 16;
3503 gDst=gDst << 16;
3504 bDst=bDst << 16;
3505 for (h = lines - 1; h >= 0; h--) {
3506 dstpixel=(LPWORD)dstbits;
3507 for (x = 0; x < dstwidth; x++) {
3508 COLORREF srcval;
3509 DWORD dstval;
3510 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3511 dstval=((GetRValue(srcval) << rShift) & rDst) |
3512 ((GetGValue(srcval) << gShift) & gDst) |
3513 ((GetBValue(srcval) << bShift) & bDst);
3514 *dstpixel++=dstval >> 16;
3516 dstbits += linebytes;
3519 break;
3524 /***********************************************************************
3525 * X11DRV_DIB_SetImageBits_24
3527 * SetDIBits for a 24-bit deep DIB.
3529 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3530 DWORD srcwidth, DWORD dstwidth, int left,
3531 X11DRV_PDEVICE *physDev,
3532 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3533 XImage *bmpImage, DWORD linebytes )
3535 DWORD x;
3536 int h;
3538 if (lines < 0 )
3540 lines = -lines;
3541 srcbits = srcbits + linebytes * (lines - 1);
3542 linebytes = -linebytes;
3545 switch (bmpImage->depth)
3547 case 24:
3548 if (bmpImage->bits_per_pixel==24) {
3549 char* dstbits;
3551 srcbits=srcbits+left*3;
3552 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3554 if (bmpImage->green_mask!=0x00ff00 ||
3555 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3556 goto notsupported;
3557 } else if (rSrc==bmpImage->red_mask) {
3558 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3559 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3560 X11DRV_DIB_Convert_any_asis
3561 (dstwidth,lines,3,
3562 srcbits,linebytes,
3563 dstbits,-bmpImage->bytes_per_line);
3564 } else {
3565 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3566 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3567 X11DRV_DIB_Convert_888_reverse
3568 (dstwidth,lines,
3569 srcbits,linebytes,
3570 dstbits,-bmpImage->bytes_per_line);
3572 break;
3574 /* fall through */
3576 case 32:
3578 char* dstbits;
3580 srcbits=srcbits+left*3;
3581 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3583 if (bmpImage->green_mask!=0x00ff00 ||
3584 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3585 goto notsupported;
3586 } else if (rSrc==bmpImage->red_mask) {
3587 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3588 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3589 X11DRV_DIB_Convert_888_to_0888_asis
3590 (dstwidth,lines,
3591 srcbits,linebytes,
3592 dstbits,-bmpImage->bytes_per_line);
3593 } else {
3594 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3595 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3596 X11DRV_DIB_Convert_888_to_0888_reverse
3597 (dstwidth,lines,
3598 srcbits,linebytes,
3599 dstbits,-bmpImage->bytes_per_line);
3601 break;
3604 case 15:
3605 case 16:
3607 char* dstbits;
3609 srcbits=srcbits+left*3;
3610 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3612 if (bmpImage->green_mask==0x03e0) {
3613 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3614 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3615 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3616 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3617 X11DRV_DIB_Convert_888_to_555_asis
3618 (dstwidth,lines,
3619 srcbits,linebytes,
3620 dstbits,-bmpImage->bytes_per_line);
3621 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3622 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3623 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3624 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3625 X11DRV_DIB_Convert_888_to_555_reverse
3626 (dstwidth,lines,
3627 srcbits,linebytes,
3628 dstbits,-bmpImage->bytes_per_line);
3629 } else {
3630 goto notsupported;
3632 } else if (bmpImage->green_mask==0x07e0) {
3633 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3634 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3635 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3636 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3637 X11DRV_DIB_Convert_888_to_565_asis
3638 (dstwidth,lines,
3639 srcbits,linebytes,
3640 dstbits,-bmpImage->bytes_per_line);
3641 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3642 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3643 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3644 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3645 X11DRV_DIB_Convert_888_to_565_reverse
3646 (dstwidth,lines,
3647 srcbits,linebytes,
3648 dstbits,-bmpImage->bytes_per_line);
3649 } else {
3650 goto notsupported;
3652 } else {
3653 goto notsupported;
3656 break;
3658 default:
3659 notsupported:
3660 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3661 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3662 bmpImage->green_mask, bmpImage->blue_mask );
3663 /* fall through */
3664 case 1:
3665 case 4:
3666 case 8:
3668 /* ==== rgb 888 dib -> any bmp bormat ==== */
3669 const BYTE* srcbyte;
3671 /* Windows only supports one 24bpp DIB format: RGB888 */
3672 srcbits+=left*3;
3673 for (h = lines - 1; h >= 0; h--) {
3674 srcbyte=(const BYTE*)srcbits;
3675 for (x = left; x < dstwidth+left; x++) {
3676 XPutPixel(bmpImage, x, h,
3677 X11DRV_PALETTE_ToPhysical
3678 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3679 srcbyte+=3;
3681 srcbits += linebytes;
3684 break;
3689 /***********************************************************************
3690 * X11DRV_DIB_GetImageBits_24
3692 * GetDIBits for an 24-bit deep DIB.
3694 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3695 DWORD dstwidth, DWORD srcwidth,
3696 PALETTEENTRY *srccolors,
3697 DWORD rDst, DWORD gDst, DWORD bDst,
3698 XImage *bmpImage, DWORD linebytes )
3700 DWORD x;
3701 int h;
3703 if (lines < 0 )
3705 lines = -lines;
3706 dstbits = dstbits + ( linebytes * (lines-1) );
3707 linebytes = -linebytes;
3710 switch (bmpImage->depth)
3712 case 24:
3713 if (bmpImage->bits_per_pixel==24) {
3714 const char* srcbits;
3716 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3718 if (bmpImage->green_mask!=0x00ff00 ||
3719 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3720 goto notsupported;
3721 } else if (rDst==bmpImage->red_mask) {
3722 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3723 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3724 X11DRV_DIB_Convert_any_asis
3725 (dstwidth,lines,3,
3726 srcbits,-bmpImage->bytes_per_line,
3727 dstbits,linebytes);
3728 } else {
3729 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3730 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3731 X11DRV_DIB_Convert_888_reverse
3732 (dstwidth,lines,
3733 srcbits,-bmpImage->bytes_per_line,
3734 dstbits,linebytes);
3736 break;
3738 /* fall through */
3740 case 32:
3742 const char* srcbits;
3744 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3746 if (bmpImage->green_mask!=0x00ff00 ||
3747 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3748 goto notsupported;
3749 } else if (rDst==bmpImage->red_mask) {
3750 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3751 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3752 X11DRV_DIB_Convert_0888_to_888_asis
3753 (dstwidth,lines,
3754 srcbits,-bmpImage->bytes_per_line,
3755 dstbits,linebytes);
3756 } else {
3757 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3758 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3759 X11DRV_DIB_Convert_0888_to_888_reverse
3760 (dstwidth,lines,
3761 srcbits,-bmpImage->bytes_per_line,
3762 dstbits,linebytes);
3764 break;
3767 case 15:
3768 case 16:
3770 const char* srcbits;
3772 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3774 if (bmpImage->green_mask==0x03e0) {
3775 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3776 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3777 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3778 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3779 X11DRV_DIB_Convert_555_to_888_asis
3780 (dstwidth,lines,
3781 srcbits,-bmpImage->bytes_per_line,
3782 dstbits,linebytes);
3783 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3784 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3785 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3786 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3787 X11DRV_DIB_Convert_555_to_888_reverse
3788 (dstwidth,lines,
3789 srcbits,-bmpImage->bytes_per_line,
3790 dstbits,linebytes);
3791 } else {
3792 goto notsupported;
3794 } else if (bmpImage->green_mask==0x07e0) {
3795 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3796 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3797 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3798 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3799 X11DRV_DIB_Convert_565_to_888_asis
3800 (dstwidth,lines,
3801 srcbits,-bmpImage->bytes_per_line,
3802 dstbits,linebytes);
3803 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3804 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3805 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3806 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3807 X11DRV_DIB_Convert_565_to_888_reverse
3808 (dstwidth,lines,
3809 srcbits,-bmpImage->bytes_per_line,
3810 dstbits,linebytes);
3811 } else {
3812 goto notsupported;
3814 } else {
3815 goto notsupported;
3818 break;
3820 case 1:
3821 case 4:
3822 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3823 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3824 BYTE* dstbyte;
3826 /* Windows only supports one 24bpp DIB format: rgb 888 */
3827 for (h = lines - 1; h >= 0; h--) {
3828 dstbyte=dstbits;
3829 for (x = 0; x < dstwidth; x++) {
3830 PALETTEENTRY srcval;
3831 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3832 dstbyte[0]=srcval.peBlue;
3833 dstbyte[1]=srcval.peGreen;
3834 dstbyte[2]=srcval.peRed;
3835 dstbyte+=3;
3837 dstbits += linebytes;
3839 } else {
3840 goto notsupported;
3842 break;
3844 case 8:
3845 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3846 /* ==== pal 8 bmp -> rgb 888 dib ==== */
3847 const void* srcbits;
3848 const BYTE* srcpixel;
3849 BYTE* dstbyte;
3851 /* Windows only supports one 24bpp DIB format: rgb 888 */
3852 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3853 for (h = lines - 1; h >= 0; h--) {
3854 srcpixel=srcbits;
3855 dstbyte=dstbits;
3856 for (x = 0; x < dstwidth; x++ ) {
3857 PALETTEENTRY srcval;
3858 srcval=srccolors[(int)*srcpixel++];
3859 dstbyte[0]=srcval.peBlue;
3860 dstbyte[1]=srcval.peGreen;
3861 dstbyte[2]=srcval.peRed;
3862 dstbyte+=3;
3864 srcbits -= bmpImage->bytes_per_line;
3865 dstbits += linebytes;
3867 } else {
3868 goto notsupported;
3870 break;
3872 default:
3873 notsupported:
3875 /* ==== any bmp format -> 888 dib ==== */
3876 BYTE* dstbyte;
3878 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3879 bmpImage->depth, bmpImage->red_mask,
3880 bmpImage->green_mask, bmpImage->blue_mask,
3881 rDst, gDst, bDst );
3883 /* Windows only supports one 24bpp DIB format: rgb 888 */
3884 for (h = lines - 1; h >= 0; h--) {
3885 dstbyte=dstbits;
3886 for (x = 0; x < dstwidth; x++) {
3887 COLORREF srcval=X11DRV_PALETTE_ToLogical
3888 (XGetPixel( bmpImage, x, h ));
3889 dstbyte[0]=GetBValue(srcval);
3890 dstbyte[1]=GetGValue(srcval);
3891 dstbyte[2]=GetRValue(srcval);
3892 dstbyte+=3;
3894 dstbits += linebytes;
3897 break;
3902 /***********************************************************************
3903 * X11DRV_DIB_SetImageBits_32
3905 * SetDIBits for a 32-bit deep DIB.
3907 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3908 DWORD srcwidth, DWORD dstwidth, int left,
3909 X11DRV_PDEVICE *physDev,
3910 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3911 XImage *bmpImage,
3912 DWORD linebytes)
3914 DWORD x, *ptr;
3915 int h;
3917 if (lines < 0 )
3919 lines = -lines;
3920 srcbits = srcbits + ( linebytes * (lines-1) );
3921 linebytes = -linebytes;
3924 ptr = (DWORD *) srcbits + left;
3926 switch (bmpImage->depth)
3928 case 24:
3929 if (bmpImage->bits_per_pixel==24) {
3930 char* dstbits;
3932 srcbits=srcbits+left*4;
3933 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3935 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3936 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3937 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3938 X11DRV_DIB_Convert_0888_to_888_asis
3939 (dstwidth,lines,
3940 srcbits,linebytes,
3941 dstbits,-bmpImage->bytes_per_line);
3942 } else if (bmpImage->green_mask!=0x00ff00 ||
3943 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3944 goto notsupported;
3945 /* the tests below assume sane bmpImage masks */
3946 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3947 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3948 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3949 X11DRV_DIB_Convert_0888_to_888_reverse
3950 (dstwidth,lines,
3951 srcbits,linebytes,
3952 dstbits,-bmpImage->bytes_per_line);
3953 } else if (bmpImage->blue_mask==0xff) {
3954 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3955 X11DRV_DIB_Convert_any0888_to_rgb888
3956 (dstwidth,lines,
3957 srcbits,linebytes,
3958 rSrc,gSrc,bSrc,
3959 dstbits,-bmpImage->bytes_per_line);
3960 } else {
3961 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3962 X11DRV_DIB_Convert_any0888_to_bgr888
3963 (dstwidth,lines,
3964 srcbits,linebytes,
3965 rSrc,gSrc,bSrc,
3966 dstbits,-bmpImage->bytes_per_line);
3968 break;
3970 /* fall through */
3972 case 32:
3974 char* dstbits;
3976 srcbits=srcbits+left*4;
3977 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3979 if (gSrc==bmpImage->green_mask) {
3980 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
3981 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
3982 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
3983 X11DRV_DIB_Convert_any_asis
3984 (dstwidth,lines,4,
3985 srcbits,linebytes,
3986 dstbits,-bmpImage->bytes_per_line);
3987 } else if (bmpImage->green_mask!=0x00ff00 ||
3988 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3989 goto notsupported;
3990 /* the tests below assume sane bmpImage masks */
3991 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
3992 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
3993 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
3994 X11DRV_DIB_Convert_0888_reverse
3995 (dstwidth,lines,
3996 srcbits,linebytes,
3997 dstbits,-bmpImage->bytes_per_line);
3998 } else {
3999 /* ==== any 0888 dib -> any 0888 bmp ==== */
4000 X11DRV_DIB_Convert_0888_any
4001 (dstwidth,lines,
4002 srcbits,linebytes,
4003 rSrc,gSrc,bSrc,
4004 dstbits,-bmpImage->bytes_per_line,
4005 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4007 } else if (bmpImage->green_mask!=0x00ff00 ||
4008 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4009 goto notsupported;
4010 /* the tests below assume sane bmpImage masks */
4011 } else {
4012 /* ==== any 0888 dib -> any 0888 bmp ==== */
4013 X11DRV_DIB_Convert_0888_any
4014 (dstwidth,lines,
4015 srcbits,linebytes,
4016 rSrc,gSrc,bSrc,
4017 dstbits,-bmpImage->bytes_per_line,
4018 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4021 break;
4023 case 15:
4024 case 16:
4026 char* dstbits;
4028 srcbits=srcbits+left*4;
4029 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4031 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4032 if (bmpImage->green_mask==0x03e0) {
4033 if (bmpImage->red_mask==0x7f00) {
4034 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4035 X11DRV_DIB_Convert_0888_to_555_asis
4036 (dstwidth,lines,
4037 srcbits,linebytes,
4038 dstbits,-bmpImage->bytes_per_line);
4039 } else if (bmpImage->blue_mask==0x7f00) {
4040 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4041 X11DRV_DIB_Convert_0888_to_555_reverse
4042 (dstwidth,lines,
4043 srcbits,linebytes,
4044 dstbits,-bmpImage->bytes_per_line);
4045 } else {
4046 goto notsupported;
4048 } else if (bmpImage->green_mask==0x07e0) {
4049 if (bmpImage->red_mask==0xf800) {
4050 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4051 X11DRV_DIB_Convert_0888_to_565_asis
4052 (dstwidth,lines,
4053 srcbits,linebytes,
4054 dstbits,-bmpImage->bytes_per_line);
4055 } else if (bmpImage->blue_mask==0xf800) {
4056 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4057 X11DRV_DIB_Convert_0888_to_565_reverse
4058 (dstwidth,lines,
4059 srcbits,linebytes,
4060 dstbits,-bmpImage->bytes_per_line);
4061 } else {
4062 goto notsupported;
4064 } else {
4065 goto notsupported;
4067 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4068 if (bmpImage->green_mask==0x03e0) {
4069 if (bmpImage->blue_mask==0x7f00) {
4070 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4071 X11DRV_DIB_Convert_0888_to_555_asis
4072 (dstwidth,lines,
4073 srcbits,linebytes,
4074 dstbits,-bmpImage->bytes_per_line);
4075 } else if (bmpImage->red_mask==0x7f00) {
4076 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4077 X11DRV_DIB_Convert_0888_to_555_reverse
4078 (dstwidth,lines,
4079 srcbits,linebytes,
4080 dstbits,-bmpImage->bytes_per_line);
4081 } else {
4082 goto notsupported;
4084 } else if (bmpImage->green_mask==0x07e0) {
4085 if (bmpImage->blue_mask==0xf800) {
4086 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4087 X11DRV_DIB_Convert_0888_to_565_asis
4088 (dstwidth,lines,
4089 srcbits,linebytes,
4090 dstbits,-bmpImage->bytes_per_line);
4091 } else if (bmpImage->red_mask==0xf800) {
4092 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4093 X11DRV_DIB_Convert_0888_to_565_reverse
4094 (dstwidth,lines,
4095 srcbits,linebytes,
4096 dstbits,-bmpImage->bytes_per_line);
4097 } else {
4098 goto notsupported;
4100 } else {
4101 goto notsupported;
4103 } else {
4104 if (bmpImage->green_mask==0x03e0 &&
4105 (bmpImage->red_mask==0x7f00 ||
4106 bmpImage->blue_mask==0x7f00)) {
4107 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4108 X11DRV_DIB_Convert_any0888_to_5x5
4109 (dstwidth,lines,
4110 srcbits,linebytes,
4111 rSrc,gSrc,bSrc,
4112 dstbits,-bmpImage->bytes_per_line,
4113 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4114 } else if (bmpImage->green_mask==0x07e0 &&
4115 (bmpImage->red_mask==0xf800 ||
4116 bmpImage->blue_mask==0xf800)) {
4117 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4118 X11DRV_DIB_Convert_any0888_to_5x5
4119 (dstwidth,lines,
4120 srcbits,linebytes,
4121 rSrc,gSrc,bSrc,
4122 dstbits,-bmpImage->bytes_per_line,
4123 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4124 } else {
4125 goto notsupported;
4129 break;
4131 default:
4132 notsupported:
4133 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4134 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4135 bmpImage->green_mask, bmpImage->blue_mask );
4136 /* fall through */
4137 case 1:
4138 case 4:
4139 case 8:
4141 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4142 const DWORD* srcpixel;
4143 int rShift,gShift,bShift;
4145 rShift=X11DRV_DIB_MaskToShift(rSrc);
4146 gShift=X11DRV_DIB_MaskToShift(gSrc);
4147 bShift=X11DRV_DIB_MaskToShift(bSrc);
4148 srcbits+=left*4;
4149 for (h = lines - 1; h >= 0; h--) {
4150 srcpixel=(const DWORD*)srcbits;
4151 for (x = left; x < dstwidth+left; x++) {
4152 DWORD srcvalue;
4153 BYTE red,green,blue;
4154 srcvalue=*srcpixel++;
4155 red= (srcvalue >> rShift) & 0xff;
4156 green=(srcvalue >> gShift) & 0xff;
4157 blue= (srcvalue >> bShift) & 0xff;
4158 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4159 (physDev, RGB(red,green,blue)));
4161 srcbits += linebytes;
4164 break;
4169 /***********************************************************************
4170 * X11DRV_DIB_GetImageBits_32
4172 * GetDIBits for an 32-bit deep DIB.
4174 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4175 DWORD dstwidth, DWORD srcwidth,
4176 PALETTEENTRY *srccolors,
4177 DWORD rDst, DWORD gDst, DWORD bDst,
4178 XImage *bmpImage, DWORD linebytes )
4180 DWORD x;
4181 int h;
4182 BYTE *bits;
4184 if (lines < 0 )
4186 lines = -lines;
4187 dstbits = dstbits + ( linebytes * (lines-1) );
4188 linebytes = -linebytes;
4191 bits = dstbits;
4193 switch (bmpImage->depth)
4195 case 24:
4196 if (bmpImage->bits_per_pixel==24) {
4197 const void* srcbits;
4199 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4201 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4202 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4203 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4204 X11DRV_DIB_Convert_888_to_0888_asis
4205 (dstwidth,lines,
4206 srcbits,-bmpImage->bytes_per_line,
4207 dstbits,linebytes);
4208 } else if (bmpImage->green_mask!=0x00ff00 ||
4209 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4210 goto notsupported;
4211 /* the tests below assume sane bmpImage masks */
4212 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4213 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4214 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4215 X11DRV_DIB_Convert_888_to_0888_reverse
4216 (dstwidth,lines,
4217 srcbits,-bmpImage->bytes_per_line,
4218 dstbits,linebytes);
4219 } else if (bmpImage->blue_mask==0xff) {
4220 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4221 X11DRV_DIB_Convert_rgb888_to_any0888
4222 (dstwidth,lines,
4223 srcbits,-bmpImage->bytes_per_line,
4224 dstbits,linebytes,
4225 rDst,gDst,bDst);
4226 } else {
4227 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4228 X11DRV_DIB_Convert_bgr888_to_any0888
4229 (dstwidth,lines,
4230 srcbits,-bmpImage->bytes_per_line,
4231 dstbits,linebytes,
4232 rDst,gDst,bDst);
4234 break;
4236 /* fall through */
4238 case 32:
4240 const char* srcbits;
4242 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4244 if (gDst==bmpImage->green_mask) {
4245 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4246 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4247 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4248 X11DRV_DIB_Convert_any_asis
4249 (dstwidth,lines,4,
4250 srcbits,-bmpImage->bytes_per_line,
4251 dstbits,linebytes);
4252 } else if (bmpImage->green_mask!=0x00ff00 ||
4253 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4254 goto notsupported;
4255 /* the tests below assume sane bmpImage masks */
4256 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
4257 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4258 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4259 X11DRV_DIB_Convert_0888_reverse
4260 (dstwidth,lines,
4261 srcbits,-bmpImage->bytes_per_line,
4262 dstbits,linebytes);
4263 } else {
4264 /* ==== any 0888 bmp -> any 0888 dib ==== */
4265 X11DRV_DIB_Convert_0888_any
4266 (dstwidth,lines,
4267 srcbits,-bmpImage->bytes_per_line,
4268 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4269 dstbits,linebytes,
4270 rDst,gDst,bDst);
4272 } else if (bmpImage->green_mask!=0x00ff00 ||
4273 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4274 goto notsupported;
4275 /* the tests below assume sane bmpImage masks */
4276 } else {
4277 /* ==== any 0888 bmp -> any 0888 dib ==== */
4278 X11DRV_DIB_Convert_0888_any
4279 (dstwidth,lines,
4280 srcbits,-bmpImage->bytes_per_line,
4281 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4282 dstbits,linebytes,
4283 rDst,gDst,bDst);
4286 break;
4288 case 15:
4289 case 16:
4291 const char* srcbits;
4293 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4295 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4296 if (bmpImage->green_mask==0x03e0) {
4297 if (bmpImage->red_mask==0x7f00) {
4298 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4299 X11DRV_DIB_Convert_555_to_0888_asis
4300 (dstwidth,lines,
4301 srcbits,-bmpImage->bytes_per_line,
4302 dstbits,linebytes);
4303 } else if (bmpImage->blue_mask==0x7f00) {
4304 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4305 X11DRV_DIB_Convert_555_to_0888_reverse
4306 (dstwidth,lines,
4307 srcbits,-bmpImage->bytes_per_line,
4308 dstbits,linebytes);
4309 } else {
4310 goto notsupported;
4312 } else if (bmpImage->green_mask==0x07e0) {
4313 if (bmpImage->red_mask==0xf800) {
4314 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4315 X11DRV_DIB_Convert_565_to_0888_asis
4316 (dstwidth,lines,
4317 srcbits,-bmpImage->bytes_per_line,
4318 dstbits,linebytes);
4319 } else if (bmpImage->blue_mask==0xf800) {
4320 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4321 X11DRV_DIB_Convert_565_to_0888_reverse
4322 (dstwidth,lines,
4323 srcbits,-bmpImage->bytes_per_line,
4324 dstbits,linebytes);
4325 } else {
4326 goto notsupported;
4328 } else {
4329 goto notsupported;
4331 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4332 if (bmpImage->green_mask==0x03e0) {
4333 if (bmpImage->blue_mask==0x7f00) {
4334 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4335 X11DRV_DIB_Convert_555_to_0888_asis
4336 (dstwidth,lines,
4337 srcbits,-bmpImage->bytes_per_line,
4338 dstbits,linebytes);
4339 } else if (bmpImage->red_mask==0x7f00) {
4340 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4341 X11DRV_DIB_Convert_555_to_0888_reverse
4342 (dstwidth,lines,
4343 srcbits,-bmpImage->bytes_per_line,
4344 dstbits,linebytes);
4345 } else {
4346 goto notsupported;
4348 } else if (bmpImage->green_mask==0x07e0) {
4349 if (bmpImage->blue_mask==0xf800) {
4350 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4351 X11DRV_DIB_Convert_565_to_0888_asis
4352 (dstwidth,lines,
4353 srcbits,-bmpImage->bytes_per_line,
4354 dstbits,linebytes);
4355 } else if (bmpImage->red_mask==0xf800) {
4356 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4357 X11DRV_DIB_Convert_565_to_0888_reverse
4358 (dstwidth,lines,
4359 srcbits,-bmpImage->bytes_per_line,
4360 dstbits,linebytes);
4361 } else {
4362 goto notsupported;
4364 } else {
4365 goto notsupported;
4367 } else {
4368 if (bmpImage->green_mask==0x03e0 &&
4369 (bmpImage->red_mask==0x7f00 ||
4370 bmpImage->blue_mask==0x7f00)) {
4371 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4372 X11DRV_DIB_Convert_5x5_to_any0888
4373 (dstwidth,lines,
4374 srcbits,-bmpImage->bytes_per_line,
4375 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4376 dstbits,linebytes,
4377 rDst,gDst,bDst);
4378 } else if (bmpImage->green_mask==0x07e0 &&
4379 (bmpImage->red_mask==0xf800 ||
4380 bmpImage->blue_mask==0xf800)) {
4381 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4382 X11DRV_DIB_Convert_5x5_to_any0888
4383 (dstwidth,lines,
4384 srcbits,-bmpImage->bytes_per_line,
4385 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4386 dstbits,linebytes,
4387 rDst,gDst,bDst);
4388 } else {
4389 goto notsupported;
4393 break;
4395 case 1:
4396 case 4:
4397 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4398 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4399 int rShift,gShift,bShift;
4400 DWORD* dstpixel;
4402 rShift=X11DRV_DIB_MaskToShift(rDst);
4403 gShift=X11DRV_DIB_MaskToShift(gDst);
4404 bShift=X11DRV_DIB_MaskToShift(bDst);
4405 for (h = lines - 1; h >= 0; h--) {
4406 dstpixel=(DWORD*)dstbits;
4407 for (x = 0; x < dstwidth; x++) {
4408 PALETTEENTRY srcval;
4409 srcval = srccolors[XGetPixel(bmpImage, x, h)];
4410 *dstpixel++=(srcval.peRed << rShift) |
4411 (srcval.peGreen << gShift) |
4412 (srcval.peBlue << bShift);
4414 dstbits += linebytes;
4416 } else {
4417 goto notsupported;
4419 break;
4421 case 8:
4422 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4423 /* ==== pal 8 bmp -> any 0888 dib ==== */
4424 int rShift,gShift,bShift;
4425 const void* srcbits;
4426 const BYTE* srcpixel;
4427 DWORD* dstpixel;
4429 rShift=X11DRV_DIB_MaskToShift(rDst);
4430 gShift=X11DRV_DIB_MaskToShift(gDst);
4431 bShift=X11DRV_DIB_MaskToShift(bDst);
4432 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4433 for (h = lines - 1; h >= 0; h--) {
4434 srcpixel=srcbits;
4435 dstpixel=(DWORD*)dstbits;
4436 for (x = 0; x < dstwidth; x++) {
4437 PALETTEENTRY srcval;
4438 srcval=srccolors[(int)*srcpixel++];
4439 *dstpixel++=(srcval.peRed << rShift) |
4440 (srcval.peGreen << gShift) |
4441 (srcval.peBlue << bShift);
4443 srcbits -= bmpImage->bytes_per_line;
4444 dstbits += linebytes;
4446 } else {
4447 goto notsupported;
4449 break;
4451 default:
4452 notsupported:
4454 /* ==== any bmp format -> any 0888 dib ==== */
4455 int rShift,gShift,bShift;
4456 DWORD* dstpixel;
4458 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4459 bmpImage->depth, bmpImage->red_mask,
4460 bmpImage->green_mask, bmpImage->blue_mask,
4461 rDst,gDst,bDst);
4463 rShift=X11DRV_DIB_MaskToShift(rDst);
4464 gShift=X11DRV_DIB_MaskToShift(gDst);
4465 bShift=X11DRV_DIB_MaskToShift(bDst);
4466 for (h = lines - 1; h >= 0; h--) {
4467 dstpixel=(DWORD*)dstbits;
4468 for (x = 0; x < dstwidth; x++) {
4469 COLORREF srcval;
4470 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4471 *dstpixel++=(GetRValue(srcval) << rShift) |
4472 (GetGValue(srcval) << gShift) |
4473 (GetBValue(srcval) << bShift);
4475 dstbits += linebytes;
4478 break;
4482 /***********************************************************************
4483 * X11DRV_DIB_SetImageBits
4485 * Transfer the bits to an X image.
4486 * Helper function for SetDIBits() and SetDIBitsToDevice().
4488 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4490 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4491 XImage *bmpImage;
4493 wine_tsx11_lock();
4494 if (descr->image)
4495 bmpImage = descr->image;
4496 else {
4497 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4498 descr->infoWidth, lines, 32, 0 );
4499 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4500 if(bmpImage->data == NULL) {
4501 ERR("Out of memory!\n");
4502 XDestroyImage( bmpImage );
4503 wine_tsx11_unlock();
4504 return lines;
4508 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4509 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4510 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4511 bmpImage->depth,bmpImage->bits_per_pixel,
4512 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4514 /* Transfer the pixels */
4515 switch(descr->infoBpp)
4517 case 1:
4518 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4519 descr->width, descr->xSrc, (int *)(descr->colorMap),
4520 bmpImage, descr->dibpitch );
4521 break;
4522 case 4:
4523 if (descr->compression) {
4524 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4525 descr->width, descr->height, AllPlanes, ZPixmap,
4526 bmpImage, descr->xSrc, descr->ySrc );
4528 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4529 descr->infoWidth, descr->width,
4530 descr->xSrc, (int *)(descr->colorMap),
4531 bmpImage );
4532 } else
4533 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4534 descr->infoWidth, descr->width,
4535 descr->xSrc, (int*)(descr->colorMap),
4536 bmpImage, descr->dibpitch );
4537 break;
4538 case 8:
4539 if (descr->compression) {
4540 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4541 descr->width, descr->height, AllPlanes, ZPixmap,
4542 bmpImage, descr->xSrc, descr->ySrc );
4543 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4544 descr->infoWidth, descr->width,
4545 descr->xSrc, (int *)(descr->colorMap),
4546 bmpImage );
4547 } else
4548 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4549 descr->infoWidth, descr->width,
4550 descr->xSrc, (int *)(descr->colorMap),
4551 bmpImage, descr->dibpitch );
4552 break;
4553 case 15:
4554 case 16:
4555 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4556 descr->infoWidth, descr->width,
4557 descr->xSrc, descr->physDev,
4558 descr->rMask, descr->gMask, descr->bMask,
4559 bmpImage, descr->dibpitch);
4560 break;
4561 case 24:
4562 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4563 descr->infoWidth, descr->width,
4564 descr->xSrc, descr->physDev,
4565 descr->rMask, descr->gMask, descr->bMask,
4566 bmpImage, descr->dibpitch);
4567 break;
4568 case 32:
4569 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4570 descr->infoWidth, descr->width,
4571 descr->xSrc, descr->physDev,
4572 descr->rMask, descr->gMask, descr->bMask,
4573 bmpImage, descr->dibpitch);
4574 break;
4575 default:
4576 WARN("(%d): Invalid depth\n", descr->infoBpp );
4577 break;
4580 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4581 descr->drawable, descr->gc, bmpImage,
4582 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4583 descr->width, descr->height);
4584 #ifdef HAVE_LIBXXSHM
4585 if (descr->useShm)
4587 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4588 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4589 descr->width, descr->height, FALSE );
4590 XSync( gdi_display, 0 );
4592 else
4593 #endif
4594 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4595 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4596 descr->width, descr->height );
4598 if (!descr->image) XDestroyImage( bmpImage );
4599 wine_tsx11_unlock();
4600 return lines;
4603 /***********************************************************************
4604 * X11DRV_DIB_GetImageBits
4606 * Transfer the bits from an X image.
4608 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4610 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4611 XImage *bmpImage;
4613 wine_tsx11_lock();
4614 if (descr->image)
4615 bmpImage = descr->image;
4616 else {
4617 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4618 descr->infoWidth, lines, 32, 0 );
4619 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4620 if(bmpImage->data == NULL) {
4621 ERR("Out of memory!\n");
4622 XDestroyImage( bmpImage );
4623 wine_tsx11_unlock();
4624 return lines;
4628 if (descr->useShm)
4630 int saveRed, saveGreen, saveBlue;
4632 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4633 gdi_display, descr->drawable, bmpImage,
4634 descr->xSrc, descr->ySrc, AllPlanes);
4636 /* We must save and restore the bmpImage's masks in order
4637 * to preserve them across the call to XShmGetImage, which
4638 * decides to eleminate them since it doesn't happen to know
4639 * what the format of the image is supposed to be, even though
4640 * we do. */
4641 saveRed = bmpImage->red_mask;
4642 saveBlue= bmpImage->blue_mask;
4643 saveGreen = bmpImage->green_mask;
4645 XShmGetImage( gdi_display, descr->drawable, bmpImage,
4646 descr->xSrc, descr->ySrc, AllPlanes);
4648 bmpImage->red_mask = saveRed;
4649 bmpImage->blue_mask = saveBlue;
4650 bmpImage->green_mask = saveGreen;
4652 else
4654 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4655 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4656 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4657 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4658 descr->width, lines, AllPlanes, ZPixmap,
4659 bmpImage, descr->xDest, descr->yDest );
4662 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4663 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4664 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4665 bmpImage->depth,bmpImage->bits_per_pixel,
4666 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4667 /* Transfer the pixels */
4668 switch(descr->infoBpp)
4670 case 1:
4671 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4672 descr->infoWidth, descr->width,
4673 descr->colorMap, descr->palentry,
4674 bmpImage, descr->dibpitch );
4675 break;
4677 case 4:
4678 if (descr->compression)
4679 FIXME("Compression not yet supported!\n");
4680 else
4681 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4682 descr->infoWidth, descr->width,
4683 descr->colorMap, descr->palentry,
4684 bmpImage, descr->dibpitch );
4685 break;
4687 case 8:
4688 if (descr->compression)
4689 FIXME("Compression not yet supported!\n");
4690 else
4691 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4692 descr->infoWidth, descr->width,
4693 descr->colorMap, descr->palentry,
4694 bmpImage, descr->dibpitch );
4695 break;
4696 case 15:
4697 case 16:
4698 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4699 descr->infoWidth,descr->width,
4700 descr->palentry,
4701 descr->rMask, descr->gMask, descr->bMask,
4702 bmpImage, descr->dibpitch );
4703 break;
4705 case 24:
4706 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4707 descr->infoWidth,descr->width,
4708 descr->palentry,
4709 descr->rMask, descr->gMask, descr->bMask,
4710 bmpImage, descr->dibpitch);
4711 break;
4713 case 32:
4714 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4715 descr->infoWidth, descr->width,
4716 descr->palentry,
4717 descr->rMask, descr->gMask, descr->bMask,
4718 bmpImage, descr->dibpitch);
4719 break;
4721 default:
4722 WARN("(%d): Invalid depth\n", descr->infoBpp );
4723 break;
4726 if (!descr->image) XDestroyImage( bmpImage );
4727 wine_tsx11_unlock();
4728 return lines;
4731 /*************************************************************************
4732 * X11DRV_SetDIBitsToDevice
4735 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
4736 DWORD cy, INT xSrc, INT ySrc,
4737 UINT startscan, UINT lines, LPCVOID bits,
4738 const BITMAPINFO *info, UINT coloruse )
4740 X11DRV_DIB_IMAGEBITS_DESCR descr;
4741 DWORD width, oldcy = cy;
4742 INT result;
4743 int height, tmpheight;
4744 DC *dc = physDev->dc;
4746 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4747 &descr.infoBpp, &descr.compression ) == -1)
4748 return 0;
4749 tmpheight = height;
4750 if (height < 0) height = -height;
4751 if (!lines || (startscan >= height)) return 0;
4752 if (startscan + lines > height) lines = height - startscan;
4753 if (ySrc < startscan) ySrc = startscan;
4754 else if (ySrc >= startscan + lines) return 0;
4755 if (xSrc >= width) return 0;
4756 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
4757 if (xSrc + cx >= width) cx = width - xSrc;
4758 if (!cx || !cy) return 0;
4760 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
4761 TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4763 switch (descr.infoBpp)
4765 case 1:
4766 case 4:
4767 case 8:
4768 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4769 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
4770 dc->bitsPerPixel, info, &descr.nColorMap );
4771 if (!descr.colorMap) return 0;
4772 descr.rMask = descr.gMask = descr.bMask = 0;
4773 break;
4774 case 15:
4775 case 16:
4776 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4777 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4778 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4779 descr.colorMap = 0;
4780 break;
4782 case 24:
4783 case 32:
4784 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4785 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4786 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4787 descr.colorMap = 0;
4788 break;
4791 descr.physDev = physDev;
4792 descr.bits = bits;
4793 descr.image = NULL;
4794 descr.palentry = NULL;
4795 descr.lines = tmpheight >= 0 ? lines : -lines;
4796 descr.infoWidth = width;
4797 descr.depth = dc->bitsPerPixel;
4798 descr.drawable = physDev->drawable;
4799 descr.gc = physDev->gc;
4800 descr.xSrc = xSrc;
4801 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
4802 : ySrc - startscan;
4803 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
4804 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
4805 (tmpheight >= 0 ? oldcy-cy : 0);
4806 descr.width = cx;
4807 descr.height = cy;
4808 descr.useShm = FALSE;
4809 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
4811 result = X11DRV_DIB_SetImageBits( &descr );
4813 if (descr.infoBpp <= 8)
4814 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4815 return result;
4818 /***********************************************************************
4819 * X11DRV_SetDIBits (X11DRV.@)
4821 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
4822 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
4824 X11DRV_DIB_IMAGEBITS_DESCR descr;
4825 BITMAPOBJ *bmp;
4826 int height, tmpheight;
4827 INT result;
4829 descr.physDev = physDev;
4831 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4832 &descr.infoBpp, &descr.compression ) == -1)
4833 return 0;
4835 tmpheight = height;
4836 if (height < 0) height = -height;
4837 if (!lines || (startscan >= height))
4838 return 0;
4840 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
4842 if (startscan + lines > height) lines = height - startscan;
4844 switch (descr.infoBpp)
4846 case 1:
4847 case 4:
4848 case 8:
4849 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4850 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
4851 bmp->bitmap.bmBitsPixel,
4852 info, &descr.nColorMap );
4853 if (!descr.colorMap)
4855 GDI_ReleaseObj( hbitmap );
4856 return 0;
4858 descr.rMask = descr.gMask = descr.bMask = 0;
4859 break;
4860 case 15:
4861 case 16:
4862 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4863 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4864 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4865 descr.colorMap = 0;
4866 break;
4868 case 24:
4869 case 32:
4870 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4871 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4872 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4873 descr.colorMap = 0;
4874 break;
4876 default: break;
4879 /* HACK for now */
4880 if(!bmp->physBitmap)
4881 X11DRV_CreateBitmap(hbitmap);
4883 descr.bits = bits;
4884 descr.image = NULL;
4885 descr.palentry = NULL;
4886 descr.lines = tmpheight >= 0 ? lines : -lines;
4887 descr.depth = bmp->bitmap.bmBitsPixel;
4888 descr.drawable = (Pixmap)bmp->physBitmap;
4889 descr.gc = BITMAP_GC(bmp);
4890 descr.xSrc = 0;
4891 descr.ySrc = 0;
4892 descr.xDest = 0;
4893 descr.yDest = height - startscan - lines;
4894 descr.width = bmp->bitmap.bmWidth;
4895 descr.height = lines;
4896 descr.useShm = FALSE;
4897 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4898 result = X11DRV_DIB_SetImageBits( &descr );
4900 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4902 GDI_ReleaseObj( hbitmap );
4903 return result;
4906 /***********************************************************************
4907 * X11DRV_GetDIBits (X11DRV.@)
4909 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
4910 LPVOID bits, BITMAPINFO *info, UINT coloruse )
4912 X11DRV_DIBSECTION *dib;
4913 X11DRV_DIB_IMAGEBITS_DESCR descr;
4914 PALETTEOBJ * palette;
4915 BITMAPOBJ *bmp;
4916 int height;
4917 DC *dc = physDev->dc;
4919 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4920 return 0;
4921 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
4923 GDI_ReleaseObj( dc->hPalette );
4924 return 0;
4926 dib = (X11DRV_DIBSECTION *) bmp->dib;
4928 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4929 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4930 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4931 startscan );
4933 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4935 height = info->bmiHeader.biHeight;
4936 if (height < 0) height = -height;
4937 if( lines > height ) lines = height;
4938 /* Top-down images have a negative biHeight, the scanlines of theses images
4939 * were inverted in X11DRV_DIB_GetImageBits_xx
4940 * To prevent this we simply change the sign of lines
4941 * (the number of scan lines to copy).
4942 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
4944 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
4946 if( startscan >= bmp->bitmap.bmHeight )
4948 lines = 0;
4949 goto done;
4952 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
4953 &descr.infoBpp, &descr.compression ) == -1)
4955 lines = 0;
4956 goto done;
4959 switch (descr.infoBpp)
4961 case 1:
4962 case 4:
4963 case 8:
4964 descr.rMask= descr.gMask = descr.bMask = 0;
4965 break;
4966 case 15:
4967 case 16:
4968 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4969 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4970 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4971 break;
4972 case 24:
4973 case 32:
4974 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4975 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4976 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4977 break;
4980 /* Hack for now */
4981 if(!bmp->physBitmap)
4982 X11DRV_CreateBitmap(hbitmap);
4985 descr.physDev = physDev;
4986 descr.palentry = palette->logpalette.palPalEntry;
4987 descr.bits = bits;
4988 descr.image = NULL;
4989 descr.lines = lines;
4990 descr.depth = bmp->bitmap.bmBitsPixel;
4991 descr.drawable = (Pixmap)bmp->physBitmap;
4992 descr.gc = BITMAP_GC(bmp);
4993 descr.width = bmp->bitmap.bmWidth;
4994 descr.height = bmp->bitmap.bmHeight;
4995 descr.colorMap = info->bmiColors;
4996 descr.xDest = 0;
4997 descr.yDest = 0;
4998 descr.xSrc = 0;
5000 if (descr.lines > 0)
5002 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
5004 else
5006 descr.ySrc = startscan;
5008 #ifdef HAVE_LIBXXSHM
5009 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
5010 #else
5011 descr.useShm = FALSE;
5012 #endif
5013 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
5014 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
5016 X11DRV_DIB_GetImageBits( &descr );
5018 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
5019 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
5020 info->bmiHeader.biWidth,
5021 info->bmiHeader.biHeight,
5022 info->bmiHeader.biBitCount );
5024 info->bmiHeader.biCompression = 0;
5025 if (descr.compression == BI_BITFIELDS)
5027 *(DWORD *)info->bmiColors = descr.rMask;
5028 *((DWORD *)info->bmiColors+1) = descr.gMask;
5029 *((DWORD *)info->bmiColors+2) = descr.bMask;
5032 done:
5033 GDI_ReleaseObj( dc->hPalette );
5034 GDI_ReleaseObj( hbitmap );
5035 return lines;
5038 /***********************************************************************
5039 * DIB_DoProtectDIBSection
5041 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5043 DIBSECTION *dib = bmp->dib;
5044 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5045 : -dib->dsBm.bmHeight;
5046 /* use the biSizeImage data as the memory size only if we're dealing with a
5047 compressed image where the value is set. Otherwise, calculate based on
5048 width * height */
5049 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5050 ? dib->dsBmih.biSizeImage
5051 : dib->dsBm.bmWidthBytes * effHeight;
5052 DWORD old_prot;
5054 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5055 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5058 /***********************************************************************
5059 * X11DRV_DIB_DoUpdateDIBSection
5061 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5062 void *colorMap, int nColorMap,
5063 Drawable dest,
5064 DWORD xSrc, DWORD ySrc,
5065 DWORD xDest, DWORD yDest,
5066 DWORD width, DWORD height)
5068 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5069 X11DRV_DIB_IMAGEBITS_DESCR descr;
5071 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5072 &descr.infoBpp, &descr.compression ) == -1)
5073 return;
5075 descr.physDev = NULL;
5076 descr.palentry = NULL;
5077 descr.image = dib->image;
5078 descr.colorMap = colorMap;
5079 descr.nColorMap = nColorMap;
5080 descr.bits = dib->dibSection.dsBm.bmBits;
5081 descr.depth = bmp->bitmap.bmBitsPixel;
5083 switch (descr.infoBpp)
5085 case 1:
5086 case 4:
5087 case 8:
5088 descr.rMask = descr.gMask = descr.bMask = 0;
5089 break;
5090 case 15:
5091 case 16:
5092 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5093 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5094 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5095 break;
5097 case 24:
5098 case 32:
5099 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5100 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5101 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5102 break;
5105 /* Hack for now */
5106 descr.drawable = dest;
5107 descr.gc = BITMAP_GC(bmp);
5108 descr.xSrc = xSrc;
5109 descr.ySrc = ySrc;
5110 descr.xDest = xDest;
5111 descr.yDest = yDest;
5112 descr.width = width;
5113 descr.height = height;
5114 #ifdef HAVE_LIBXXSHM
5115 descr.useShm = (dib->shminfo.shmid != -1);
5116 #else
5117 descr.useShm = FALSE;
5118 #endif
5119 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5121 if (toDIB)
5123 TRACE("Copying from Pixmap to DIB bits\n");
5124 X11DRV_DIB_GetImageBits( &descr );
5126 else
5128 TRACE("Copying from DIB bits to Pixmap\n");
5129 X11DRV_DIB_SetImageBits( &descr );
5133 /***********************************************************************
5134 * X11DRV_DIB_CopyDIBSection
5136 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
5137 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
5138 DWORD width, DWORD height)
5140 BITMAPOBJ *bmp;
5141 DC *dcSrc = physDevSrc->dc;
5142 DC *dcDst = physDevDst->dc;
5143 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5145 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5146 xSrc, ySrc, xDest, yDest, width, height);
5147 /* this function is meant as an optimization for BitBlt,
5148 * not to be called otherwise */
5149 if (!(dcSrc->flags & DC_MEMORY)) {
5150 ERR("called for non-memory source DC!?\n");
5151 return;
5154 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5155 if (!(bmp && bmp->dib)) {
5156 ERR("called for non-DIBSection!?\n");
5157 GDI_ReleaseObj( dcSrc->hBitmap );
5158 return;
5160 /* while BitBlt should already have made sure we only get
5161 * positive values, we should check for oversize values */
5162 if ((xSrc < bmp->bitmap.bmWidth) &&
5163 (ySrc < bmp->bitmap.bmHeight)) {
5164 if (xSrc + width > bmp->bitmap.bmWidth)
5165 width = bmp->bitmap.bmWidth - xSrc;
5166 if (ySrc + height > bmp->bitmap.bmHeight)
5167 height = bmp->bitmap.bmHeight - ySrc;
5168 /* if the source bitmap is 8bpp or less, we're supposed to use the
5169 * DC's palette for color conversion (not the DIB color table) */
5170 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5171 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5172 if ((!dcSrc->hPalette) ||
5173 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5174 /* HACK: no palette has been set in the source DC,
5175 * use the DIB colormap instead - this is necessary in some
5176 * cases since we need to do depth conversion in some places
5177 * where real Windows can just copy data straight over */
5178 colorMap = dib->colorMap;
5179 nColorMap = dib->nColorMap;
5180 } else {
5181 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
5182 bmp->dib->dsBm.bmBitsPixel,
5183 (BITMAPINFO*)&(bmp->dib->dsBmih),
5184 &nColorMap );
5185 if (colorMap) aColorMap = TRUE;
5188 /* perform the copy */
5189 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5190 physDevDst->drawable, xSrc, ySrc, xDest, yDest,
5191 width, height);
5192 /* free color mapping */
5193 if (aColorMap)
5194 HeapFree(GetProcessHeap(), 0, colorMap);
5196 GDI_ReleaseObj( dcSrc->hBitmap );
5199 /***********************************************************************
5200 * X11DRV_DIB_DoUpdateDIBSection
5202 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5204 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5205 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5206 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5207 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5210 /***********************************************************************
5211 * X11DRV_DIB_FaultHandler
5213 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5215 BITMAPOBJ *bmp;
5216 INT state;
5218 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5219 if (!bmp) return FALSE;
5221 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5222 if (state != DIB_Status_InSync) {
5223 /* no way to tell whether app needs read or write yet,
5224 * try read first */
5225 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5226 } else {
5227 /* hm, apparently the app must have write access */
5228 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5230 X11DRV_DIB_Unlock(bmp, TRUE);
5232 GDI_ReleaseObj( (HBITMAP)res );
5233 return TRUE;
5236 /***********************************************************************
5237 * X11DRV_DIB_Coerce
5239 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5241 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5242 INT ret = DIB_Status_None;
5244 if (dib) {
5245 EnterCriticalSection(&(dib->lock));
5246 ret = dib->status;
5247 switch (req) {
5248 case DIB_Status_GdiMod:
5249 /* GDI access - request to draw on pixmap */
5250 switch (dib->status)
5252 default:
5253 case DIB_Status_None:
5254 dib->p_status = DIB_Status_GdiMod;
5255 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5256 break;
5258 case DIB_Status_GdiMod:
5259 TRACE("GdiMod requested in status GdiMod\n" );
5260 break;
5262 case DIB_Status_InSync:
5263 TRACE("GdiMod requested in status InSync\n" );
5264 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5265 dib->status = DIB_Status_GdiMod;
5266 dib->p_status = DIB_Status_InSync;
5267 break;
5269 case DIB_Status_AuxMod:
5270 TRACE("GdiMod requested in status AuxMod\n" );
5271 if (lossy) dib->status = DIB_Status_GdiMod;
5272 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5273 dib->p_status = DIB_Status_AuxMod;
5274 if (dib->status != DIB_Status_AppMod) {
5275 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5276 break;
5278 /* fall through if copy_aux() had to change to AppMod state */
5280 case DIB_Status_AppMod:
5281 TRACE("GdiMod requested in status AppMod\n" );
5282 if (!lossy) {
5283 /* make it readonly to avoid app changing data while we copy */
5284 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5285 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5287 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5288 dib->p_status = DIB_Status_AppMod;
5289 dib->status = DIB_Status_GdiMod;
5290 break;
5292 break;
5294 case DIB_Status_InSync:
5295 /* App access - request access to read DIB surface */
5296 /* (typically called from signal handler) */
5297 switch (dib->status)
5299 default:
5300 case DIB_Status_None:
5301 /* shouldn't happen from signal handler */
5302 break;
5304 case DIB_Status_AuxMod:
5305 TRACE("InSync requested in status AuxMod\n" );
5306 if (lossy) dib->status = DIB_Status_InSync;
5307 else {
5308 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5309 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5311 if (dib->status != DIB_Status_GdiMod) {
5312 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5313 break;
5315 /* fall through if copy_aux() had to change to GdiMod state */
5317 case DIB_Status_GdiMod:
5318 TRACE("InSync requested in status GdiMod\n" );
5319 if (!lossy) {
5320 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5321 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5323 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5324 dib->status = DIB_Status_InSync;
5325 break;
5327 case DIB_Status_InSync:
5328 TRACE("InSync requested in status InSync\n" );
5329 /* shouldn't happen from signal handler */
5330 break;
5332 case DIB_Status_AppMod:
5333 TRACE("InSync requested in status AppMod\n" );
5334 /* no reason to do anything here, and this
5335 * shouldn't happen from signal handler */
5336 break;
5338 break;
5340 case DIB_Status_AppMod:
5341 /* App access - request access to write DIB surface */
5342 /* (typically called from signal handler) */
5343 switch (dib->status)
5345 default:
5346 case DIB_Status_None:
5347 /* shouldn't happen from signal handler */
5348 break;
5350 case DIB_Status_AuxMod:
5351 TRACE("AppMod requested in status AuxMod\n" );
5352 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5353 if (lossy) dib->status = DIB_Status_AppMod;
5354 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5355 if (dib->status != DIB_Status_GdiMod)
5356 break;
5357 /* fall through if copy_aux() had to change to GdiMod state */
5359 case DIB_Status_GdiMod:
5360 TRACE("AppMod requested in status GdiMod\n" );
5361 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5362 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5363 dib->status = DIB_Status_AppMod;
5364 break;
5366 case DIB_Status_InSync:
5367 TRACE("AppMod requested in status InSync\n" );
5368 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5369 dib->status = DIB_Status_AppMod;
5370 break;
5372 case DIB_Status_AppMod:
5373 TRACE("AppMod requested in status AppMod\n" );
5374 /* shouldn't happen from signal handler */
5375 break;
5377 break;
5379 case DIB_Status_AuxMod:
5380 if (dib->status == DIB_Status_None) {
5381 dib->p_status = req;
5382 } else {
5383 if (dib->status != DIB_Status_AuxMod)
5384 dib->p_status = dib->status;
5385 dib->status = DIB_Status_AuxMod;
5387 break;
5388 /* it is up to the caller to do the copy/conversion, probably
5389 * using the return value to decide where to copy from */
5391 LeaveCriticalSection(&(dib->lock));
5393 return ret;
5396 /***********************************************************************
5397 * X11DRV_DIB_Lock
5399 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5401 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5402 INT ret = DIB_Status_None;
5404 if (dib) {
5405 TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
5406 EnterCriticalSection(&(dib->lock));
5407 ret = dib->status;
5408 if (req != DIB_Status_None)
5409 X11DRV_DIB_Coerce(bmp, req, lossy);
5411 return ret;
5414 /***********************************************************************
5415 * X11DRV_DIB_Unlock
5417 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5419 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5421 if (dib) {
5422 switch (dib->status)
5424 default:
5425 case DIB_Status_None:
5426 /* in case anyone is wondering, this is the "signal handler doesn't
5427 * work" case, where we always have to be ready for app access */
5428 if (commit) {
5429 switch (dib->p_status)
5431 case DIB_Status_AuxMod:
5432 TRACE("Unlocking and syncing from AuxMod\n" );
5433 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5434 if (dib->status != DIB_Status_None) {
5435 dib->p_status = dib->status;
5436 dib->status = DIB_Status_None;
5438 if (dib->p_status != DIB_Status_GdiMod)
5439 break;
5440 /* fall through if copy_aux() had to change to GdiMod state */
5442 case DIB_Status_GdiMod:
5443 TRACE("Unlocking and syncing from GdiMod\n" );
5444 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5445 break;
5447 default:
5448 TRACE("Unlocking without needing to sync\n" );
5449 break;
5452 else TRACE("Unlocking with no changes\n");
5453 dib->p_status = DIB_Status_None;
5454 break;
5456 case DIB_Status_GdiMod:
5457 TRACE("Unlocking in status GdiMod\n" );
5458 /* DIB was protected in Coerce */
5459 if (!commit) {
5460 /* no commit, revert to InSync if applicable */
5461 if ((dib->p_status == DIB_Status_InSync) ||
5462 (dib->p_status == DIB_Status_AppMod)) {
5463 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5464 dib->status = DIB_Status_InSync;
5467 break;
5469 case DIB_Status_InSync:
5470 TRACE("Unlocking in status InSync\n" );
5471 /* DIB was already protected in Coerce */
5472 break;
5474 case DIB_Status_AppMod:
5475 TRACE("Unlocking in status AppMod\n" );
5476 /* DIB was already protected in Coerce */
5477 /* this case is ordinary only called from the signal handler,
5478 * so we don't bother to check for !commit */
5479 break;
5481 case DIB_Status_AuxMod:
5482 TRACE("Unlocking in status AuxMod\n" );
5483 if (commit) {
5484 /* DIB may need protection now */
5485 if ((dib->p_status == DIB_Status_InSync) ||
5486 (dib->p_status == DIB_Status_AppMod))
5487 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5488 } else {
5489 /* no commit, revert to previous state */
5490 if (dib->p_status != DIB_Status_None)
5491 dib->status = dib->p_status;
5492 /* no protections changed */
5494 dib->p_status = DIB_Status_None;
5495 break;
5497 LeaveCriticalSection(&(dib->lock));
5498 TRACE("Unlocked %p\n", bmp);
5502 /***********************************************************************
5503 * X11DRV_CoerceDIBSection2
5505 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5507 BITMAPOBJ *bmp;
5508 INT ret;
5510 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5511 if (!bmp) return DIB_Status_None;
5512 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5513 GDI_ReleaseObj( hBmp );
5514 return ret;
5517 /***********************************************************************
5518 * X11DRV_LockDIBSection2
5520 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5522 BITMAPOBJ *bmp;
5523 INT ret;
5525 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5526 if (!bmp) return DIB_Status_None;
5527 ret = X11DRV_DIB_Lock(bmp, req, lossy);
5528 GDI_ReleaseObj( hBmp );
5529 return ret;
5532 /***********************************************************************
5533 * X11DRV_UnlockDIBSection2
5535 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5537 BITMAPOBJ *bmp;
5539 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5540 if (!bmp) return;
5541 X11DRV_DIB_Unlock(bmp, commit);
5542 GDI_ReleaseObj( hBmp );
5545 /***********************************************************************
5546 * X11DRV_CoerceDIBSection
5548 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5550 if (!physDev) return DIB_Status_None;
5551 return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
5554 /***********************************************************************
5555 * X11DRV_LockDIBSection
5557 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5559 if (!physDev) return DIB_Status_None;
5560 if (!(physDev->dc->flags & DC_MEMORY)) return DIB_Status_None;
5562 return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
5565 /***********************************************************************
5566 * X11DRV_UnlockDIBSection
5568 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
5570 if (!physDev) return;
5571 if (!(physDev->dc->flags & DC_MEMORY)) return;
5573 X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
5577 #ifdef HAVE_LIBXXSHM
5578 /***********************************************************************
5579 * X11DRV_XShmErrorHandler
5582 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
5584 XShmErrorFlag = 1;
5585 return 0;
5588 /***********************************************************************
5589 * X11DRV_XShmCreateImage
5592 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5593 XShmSegmentInfo* shminfo)
5595 int (*WineXHandler)(Display *, XErrorEvent *);
5596 XImage *image;
5598 wine_tsx11_lock();
5599 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5600 if (image)
5602 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5603 IPC_CREAT|0700);
5604 if( shminfo->shmid != -1 )
5606 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5607 if( shminfo->shmaddr != (char*)-1 )
5609 shminfo->readOnly = FALSE;
5610 if( XShmAttach( gdi_display, shminfo ) != 0)
5612 /* Reset the error flag */
5613 XShmErrorFlag = 0;
5614 WineXHandler = XSetErrorHandler(XShmErrorHandler);
5615 XSync( gdi_display, 0 );
5617 if (!XShmErrorFlag)
5619 shmctl(shminfo->shmid, IPC_RMID, 0);
5621 XSetErrorHandler(WineXHandler);
5622 wine_tsx11_unlock();
5623 return image; /* Success! */
5625 /* An error occurred */
5626 XShmErrorFlag = 0;
5627 XSetErrorHandler(WineXHandler);
5629 shmdt(shminfo->shmaddr);
5631 shmctl(shminfo->shmid, IPC_RMID, 0);
5633 XFlush(gdi_display);
5634 XDestroyImage(image);
5635 image = NULL;
5637 wine_tsx11_unlock();
5638 return image;
5640 #endif /* HAVE_LIBXXSHM */
5643 /***********************************************************************
5644 * X11DRV_DIB_CreateDIBSection
5646 HBITMAP X11DRV_DIB_CreateDIBSection(
5647 X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
5648 LPVOID *bits, HANDLE section,
5649 DWORD offset, DWORD ovr_pitch)
5651 HBITMAP res = 0;
5652 BITMAPOBJ *bmp = NULL;
5653 X11DRV_DIBSECTION *dib = NULL;
5654 int *colorMap = NULL;
5655 int nColorMap;
5657 /* Fill BITMAP32 structure with DIB data */
5658 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5659 INT effHeight, totalSize;
5660 BITMAP bm;
5661 LPVOID mapBits = NULL;
5663 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5664 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5665 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5667 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5668 bm.bmType = 0;
5669 bm.bmWidth = bi->biWidth;
5670 bm.bmHeight = effHeight;
5671 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5672 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5673 bm.bmPlanes = bi->biPlanes;
5674 bm.bmBitsPixel = bi->biBitCount;
5675 bm.bmBits = NULL;
5677 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
5678 we're dealing with a compressed bitmap. Otherwise, use width * height. */
5679 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5680 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5682 if (section)
5684 SYSTEM_INFO SystemInfo;
5685 DWORD mapOffset;
5686 INT mapSize;
5688 GetSystemInfo( &SystemInfo );
5689 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5690 mapSize = totalSize + (offset - mapOffset);
5691 mapBits = MapViewOfFile( section,
5692 FILE_MAP_ALL_ACCESS,
5694 mapOffset,
5695 mapSize );
5696 bm.bmBits = (char *)mapBits + (offset - mapOffset);
5698 else if (ovr_pitch && offset)
5699 bm.bmBits = (LPVOID) offset;
5700 else {
5701 offset = 0;
5702 bm.bmBits = VirtualAlloc(NULL, totalSize,
5703 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5706 /* Create Color Map */
5707 if (bm.bmBits && bm.bmBitsPixel <= 8)
5708 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
5709 usage, bm.bmBitsPixel, bmi, &nColorMap );
5711 /* Allocate Memory for DIB and fill structure */
5712 if (bm.bmBits)
5713 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5714 if (dib)
5716 dib->dibSection.dsBm = bm;
5717 dib->dibSection.dsBmih = *bi;
5718 dib->dibSection.dsBmih.biSizeImage = totalSize;
5720 /* Set dsBitfields values */
5721 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5723 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5725 else switch( bi->biBitCount )
5727 case 15:
5728 case 16:
5729 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5730 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5731 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5732 break;
5734 case 24:
5735 case 32:
5736 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
5737 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5738 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5739 break;
5741 dib->dibSection.dshSection = section;
5742 dib->dibSection.dsOffset = offset;
5744 dib->status = DIB_Status_None;
5745 dib->nColorMap = nColorMap;
5746 dib->colorMap = colorMap;
5749 /* Create Device Dependent Bitmap and add DIB pointer */
5750 if (dib)
5752 res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
5753 if (res)
5755 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5756 if (bmp)
5758 bmp->dib = (DIBSECTION *) dib;
5759 /* HACK for now */
5760 if(!bmp->physBitmap)
5761 X11DRV_CreateBitmap(res);
5766 /* Create XImage */
5767 if (dib && bmp)
5769 #ifdef HAVE_LIBXXSHM
5770 if (TSXShmQueryExtension(gdi_display) &&
5771 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5772 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5774 ; /* Created Image */
5775 } else {
5776 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5777 dib->shminfo.shmid = -1;
5779 #else
5780 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5781 #endif
5784 /* Clean up in case of errors */
5785 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5787 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
5788 res, bmp, dib, bm.bmBits);
5789 if (bm.bmBits)
5791 if (section)
5792 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5793 else if (!offset)
5794 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5797 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5798 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5799 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5800 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5801 if (res) { DeleteObject(res); res = 0; }
5803 else if (bm.bmBits)
5805 /* Install fault handler, if possible */
5806 InitializeCriticalSection(&(dib->lock));
5807 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5809 if (section || offset)
5811 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5812 if (dib) dib->status = DIB_Status_AppMod;
5814 else
5816 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5817 if (dib) dib->status = DIB_Status_InSync;
5822 /* Return BITMAP handle and storage location */
5823 if (bmp) GDI_ReleaseObj(res);
5824 if (bm.bmBits && bits) *bits = bm.bmBits;
5825 return res;
5828 /***********************************************************************
5829 * X11DRV_DIB_DeleteDIBSection
5831 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5833 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5835 if (dib->image)
5837 #ifdef HAVE_LIBXXSHM
5838 if (dib->shminfo.shmid != -1)
5840 TSXShmDetach (gdi_display, &(dib->shminfo));
5841 XDestroyImage (dib->image);
5842 shmdt (dib->shminfo.shmaddr);
5843 dib->shminfo.shmid = -1;
5845 else
5846 #endif
5847 XDestroyImage( dib->image );
5850 if (dib->colorMap)
5851 HeapFree(GetProcessHeap(), 0, dib->colorMap);
5853 DeleteCriticalSection(&(dib->lock));
5856 /***********************************************************************
5857 * X11DRV_SetDIBColorTable (X11DRV.@)
5859 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
5861 BITMAPOBJ * bmp;
5862 X11DRV_DIBSECTION *dib;
5863 UINT ret = 0;
5865 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5866 dib = (X11DRV_DIBSECTION *) bmp->dib;
5868 if (dib && dib->colorMap) {
5869 UINT end = count + start;
5870 if (end > dib->nColorMap) end = dib->nColorMap;
5872 * Changing color table might change the mapping between
5873 * DIB colors and X11 colors and thus alter the visible state
5874 * of the bitmap object.
5876 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5877 X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
5878 dib->dibSection.dsBm.bmBitsPixel,
5879 TRUE, colors, start, end );
5880 X11DRV_DIB_Unlock(bmp, TRUE);
5881 ret = end - start;
5883 GDI_ReleaseObj( physDev->dc->hBitmap );
5884 return ret;
5887 /***********************************************************************
5888 * X11DRV_GetDIBColorTable (X11DRV.@)
5890 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
5892 BITMAPOBJ * bmp;
5893 X11DRV_DIBSECTION *dib;
5894 UINT ret = 0;
5896 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5897 dib = (X11DRV_DIBSECTION *) bmp->dib;
5899 if (dib && dib->colorMap) {
5900 UINT i, end = count + start;
5901 if (end > dib->nColorMap) end = dib->nColorMap;
5902 for (i = start; i < end; i++,colors++) {
5903 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5904 colors->rgbBlue = GetBValue(col);
5905 colors->rgbGreen = GetGValue(col);
5906 colors->rgbRed = GetRValue(col);
5907 colors->rgbReserved = 0;
5909 ret = end-start;
5911 GDI_ReleaseObj( physDev->dc->hBitmap );
5912 return ret;
5916 /**************************************************************************
5917 * X11DRV_DIB_CreateDIBFromPixmap
5919 * Allocates a packed DIB and copies the Pixmap data into it.
5920 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5922 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5924 HBITMAP hBmp = 0;
5925 BITMAPOBJ *pBmp = NULL;
5926 HGLOBAL hPackedDIB = 0;
5928 /* Allocates an HBITMAP which references the Pixmap passed to us */
5929 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5930 if (!hBmp)
5932 TRACE("\tCould not create bitmap header for Pixmap\n");
5933 goto END;
5937 * Create a packed DIB from the Pixmap wrapper bitmap created above.
5938 * A packed DIB contains a BITMAPINFO structure followed immediately by
5939 * an optional color palette and the pixel data.
5941 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5943 /* Get a pointer to the BITMAPOBJ structure */
5944 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5946 /* We can now get rid of the HBITMAP wrapper we created earlier.
5947 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5949 if (!bDeletePixmap)
5951 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5952 pBmp->physBitmap = NULL;
5953 pBmp->funcs = NULL;
5955 GDI_ReleaseObj( hBmp );
5956 DeleteObject(hBmp);
5958 END:
5959 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
5960 return hPackedDIB;
5964 /**************************************************************************
5965 * X11DRV_DIB_CreatePixmapFromDIB
5967 * Creates a Pixmap from a packed DIB
5969 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
5971 Pixmap pixmap = None;
5972 HBITMAP hBmp = 0;
5973 BITMAPOBJ *pBmp = NULL;
5974 LPBYTE pPackedDIB = NULL;
5975 LPBITMAPINFO pbmi = NULL;
5976 LPBITMAPINFOHEADER pbmiHeader = NULL;
5977 LPBYTE pbits = NULL;
5979 /* Get a pointer to the packed DIB's data */
5980 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
5981 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
5982 pbmi = (LPBITMAPINFO)pPackedDIB;
5983 pbits = (LPBYTE)(pPackedDIB
5984 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
5986 /* Create a DDB from the DIB */
5988 hBmp = CreateDIBitmap(hdc,
5989 pbmiHeader,
5990 CBM_INIT,
5991 (LPVOID)pbits,
5992 pbmi,
5993 DIB_RGB_COLORS);
5995 GlobalUnlock(hPackedDIB);
5997 TRACE("CreateDIBitmap returned %x\n", hBmp);
5999 /* Retrieve the internal Pixmap from the DDB */
6001 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
6003 pixmap = (Pixmap)pBmp->physBitmap;
6004 /* clear the physBitmap so that we can steal its pixmap */
6005 pBmp->physBitmap = NULL;
6006 pBmp->funcs = NULL;
6008 /* Delete the DDB we created earlier now that we have stolen its pixmap */
6009 GDI_ReleaseObj( hBmp );
6010 DeleteObject(hBmp);
6012 TRACE("\tReturning Pixmap %ld\n", pixmap);
6013 return pixmap;