msvcrt: Added _swscanf_l implementation.
[wine] / dlls / winex11.drv / dib_convert.c
1 /*
2  * DIB conversion routinues for cases where the source and destination
3  * have the same byte order.
4  *
5  * Copyright (C) 2001 Francois Gouget
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25
26 #include "windef.h"
27 #include "x11drv.h"
28
29
30 /***********************************************************************
31  *           X11DRV_DIB_Convert_*
32  *
33  * All X11DRV_DIB_Convert_Xxx functions take at least the following
34  * parameters:
35  * - width
36  *   This is the width in pixel of the surface to copy. This may be less
37  *   than the full width of the image.
38  * - height
39  *   The number of lines to copy. This may be less than the full height
40  *   of the image. This is always >0.
41  * - srcbits
42  *   Points to the first byte containing data to be copied. If the source
43  *   surface starts at coordinates (x,y) then this is:
44  *   image_ptr+x*bytes_per_pixel+y*bytes_per_line
45  *   (with further adjustments for top-down/bottom-up images)
46  * - srclinebytes
47  *   This is the number of bytes per line. It may be >0 or <0 depending on
48  *   whether this is a top-down or bottom-up image.
49  * - dstbits
50  *   Same as srcbits but for the destination
51  * - dstlinebytes
52  *   Same as srclinebytes but for the destination.
53  *
54  * Notes:
55  * - The supported Dib formats are: pal1, pal4, pal8, rgb555, bgr555,
56  *   rgb565, bgr565, rgb888 and any 32bit (0888) format.
57  *   The supported XImage (Bmp) formats are: pal1, pal4, pal8,
58  *   rgb555, bgr555, rgb565, bgr565, rgb888, bgr888, rgb0888, bgr0888.
59  * - Rgb formats are those for which the masks are such that:
60  *   red_mask > green_mask > blue_mask
61  * - Bgr formats are those for which the masks sort in the other direction.
62  * - Many conversion functions handle both rgb->bgr and bgr->rgb conversions
63  *   so the comments use h, g, l to mean respectively the source color in the
64  *   high bits, the green, and the source color in the low bits.
65  */
66
67
68 /*
69  * 15 bit conversions
70  */
71
72 static void convert_5x5_asis(int width, int height,
73                              const void* srcbits, int srclinebytes,
74                              void* dstbits, int dstlinebytes)
75 {
76     int y;
77
78     width *= 2;
79
80     if (srclinebytes == dstlinebytes && srclinebytes == width)
81     {
82         memcpy(dstbits, srcbits, height * width);
83         return;
84     }
85
86     for (y=0; y<height; y++) {
87         memcpy(dstbits, srcbits, width);
88         srcbits = (const char*)srcbits + srclinebytes;
89         dstbits = (char*)dstbits + dstlinebytes;
90     }
91 }
92
93
94 static void convert_555_reverse(int width, int height,
95                                 const void* srcbits, int srclinebytes,
96                                 void* dstbits, int dstlinebytes)
97 {
98     const DWORD* srcpixel;
99     DWORD* dstpixel;
100     int x,y;
101
102     for (y=0; y<height; y++) {
103         srcpixel=srcbits;
104         dstpixel=dstbits;
105         for (x=0; x<width/2; x++) {
106             /* Do 2 pixels at a time */
107             DWORD srcval;
108             srcval=*srcpixel++;
109             *dstpixel++=((srcval << 10) & 0x7c007c00) | /* h */
110                         ( srcval        & 0x03e003e0) | /* g */
111                         ((srcval >> 10) & 0x001f001f);  /* l */
112         }
113         if (width&1) {
114             /* And then the odd pixel */
115             WORD srcval;
116             srcval=*((const WORD*)srcpixel);
117             *((WORD*)dstpixel)=((srcval << 10) & 0x7c00) | /* h */
118                                ( srcval        & 0x03e0) | /* g */
119                                ((srcval >> 10) & 0x001f);  /* l */
120         }
121         srcbits = (const char*)srcbits + srclinebytes;
122         dstbits = (char*)dstbits + dstlinebytes;
123     }
124 }
125
126 static void convert_555_to_565_asis(int width, int height,
127                                     const void* srcbits, int srclinebytes,
128                                     void* dstbits, int dstlinebytes)
129 {
130     const DWORD* srcpixel;
131     DWORD* dstpixel;
132     int x,y;
133
134     for (y=0; y<height; y++) {
135         srcpixel=srcbits;
136         dstpixel=dstbits;
137         for (x=0; x<width/2; x++) {
138             /* Do 2 pixels at a time */
139             DWORD srcval;
140             srcval=*srcpixel++;
141             *dstpixel++=((srcval << 1) & 0xffc0ffc0) | /* h, g */
142                         ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
143                         ( srcval       & 0x001f001f);  /* l */
144         }
145         if (width&1) {
146             /* And then the odd pixel */
147             WORD srcval;
148             srcval=*((const WORD*)srcpixel);
149             *((WORD*)dstpixel)=((srcval << 1) & 0xffc0) | /* h, g */
150                                ((srcval >> 4) & 0x0020) | /* g - 1 bit */
151                                 (srcval       & 0x001f);  /* l */
152         }
153         srcbits = (const char*)srcbits + srclinebytes;
154         dstbits = (char*)dstbits + dstlinebytes;
155     }
156 }
157
158 static void convert_555_to_565_reverse(int width, int height,
159                                        const void* srcbits, int srclinebytes,
160                                        void* dstbits, int dstlinebytes)
161 {
162     const DWORD* srcpixel;
163     DWORD* dstpixel;
164     int x,y;
165
166     for (y=0; y<height; y++) {
167         srcpixel=srcbits;
168         dstpixel=dstbits;
169         for (x=0; x<width/2; x++) {
170             /* Do 2 pixels at a time */
171             DWORD srcval;
172             srcval=*srcpixel++;
173             *dstpixel++=((srcval >> 10) & 0x001f001f) | /* h */
174                         ((srcval <<  1) & 0x07c007c0) | /* g */
175                         ((srcval >>  4) & 0x00200020) | /* g - 1 bit */
176                         ((srcval << 11) & 0xf800f800);  /* l */
177         }
178         if (width&1) {
179             /* And then the odd pixel */
180             WORD srcval;
181             srcval=*((const WORD*)srcpixel);
182             *((WORD*)dstpixel)=((srcval >> 10) & 0x001f) | /* h */
183                                ((srcval <<  1) & 0x07c0) | /* g */
184                                ((srcval >>  4) & 0x0020) | /* g - 1 bit */
185                                ((srcval << 11) & 0xf800);  /* l */
186         }
187         srcbits = (const char*)srcbits + srclinebytes;
188         dstbits = (char*)dstbits + dstlinebytes;
189     }
190 }
191
192 static void convert_555_to_888_asis(int width, int height,
193                                     const void* srcbits, int srclinebytes,
194                                     void* dstbits, int dstlinebytes)
195 {
196     const WORD* srcpixel;
197     BYTE* dstpixel;
198     int x,y;
199
200     for (y=0; y<height; y++) {
201         srcpixel=srcbits;
202         dstpixel=dstbits;
203         for (x=0; x<width; x++) {
204             WORD srcval;
205             srcval=*srcpixel++;
206             dstpixel[0]=((srcval <<  3) & 0xf8) | /* l */
207                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
208             dstpixel[1]=((srcval >>  2) & 0xf8) | /* g */
209                         ((srcval >>  7) & 0x07);  /* g - 3 bits */
210             dstpixel[2]=((srcval >>  7) & 0xf8) | /* h */
211                         ((srcval >> 12) & 0x07);  /* h - 3 bits */
212             dstpixel+=3;
213         }
214         srcbits = (const char*)srcbits + srclinebytes;
215         dstbits = (char*)dstbits + dstlinebytes;
216     }
217 }
218
219 static void convert_555_to_888_reverse(int width, int height,
220                                        const void* srcbits, int srclinebytes,
221                                        void* dstbits, int dstlinebytes)
222 {
223     const WORD* srcpixel;
224     BYTE* dstpixel;
225     int x,y;
226
227     for (y=0; y<height; y++) {
228         srcpixel=srcbits;
229         dstpixel=dstbits;
230         for (x=0; x<width; x++) {
231             WORD srcval;
232             srcval=*srcpixel++;
233             dstpixel[0]=((srcval >>  7) & 0xf8) | /* h */
234                         ((srcval >> 12) & 0x07);  /* h - 3 bits */
235             dstpixel[1]=((srcval >>  2) & 0xf8) | /* g */
236                         ((srcval >>  7) & 0x07);  /* g - 3 bits */
237             dstpixel[2]=((srcval <<  3) & 0xf8) | /* l */
238                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
239             dstpixel+=3;
240         }
241         srcbits = (const char*)srcbits + srclinebytes;
242         dstbits = (char*)dstbits + dstlinebytes;
243     }
244 }
245
246 static void convert_555_to_0888_asis(int width, int height,
247                                      const void* srcbits, int srclinebytes,
248                                      void* dstbits, int dstlinebytes)
249 {
250     const WORD* srcpixel;
251     DWORD* dstpixel;
252     int x,y;
253
254     for (y=0; y<height; y++) {
255         srcpixel=srcbits;
256         dstpixel=dstbits;
257         for (x=0; x<width; x++) {
258             WORD srcval;
259             srcval=*srcpixel++;
260             *dstpixel++=((srcval << 9) & 0xf80000) | /* h */
261                         ((srcval << 4) & 0x070000) | /* h - 3 bits */
262                         ((srcval << 6) & 0x00f800) | /* g */
263                         ((srcval << 1) & 0x000700) | /* g - 3 bits */
264                         ((srcval << 3) & 0x0000f8) | /* l */
265                         ((srcval >> 2) & 0x000007);  /* l - 3 bits */
266         }
267         srcbits = (const char*)srcbits + srclinebytes;
268         dstbits = (char*)dstbits + dstlinebytes;
269     }
270 }
271
272 static void convert_555_to_0888_reverse(int width, int height,
273                                         const void* srcbits, int srclinebytes,
274                                         void* dstbits, int dstlinebytes)
275 {
276     const WORD* srcpixel;
277     DWORD* dstpixel;
278     int x,y;
279
280     for (y=0; y<height; y++) {
281         srcpixel=srcbits;
282         dstpixel=dstbits;
283         for (x=0; x<width; x++) {
284             WORD srcval;
285             srcval=*srcpixel++;
286             *dstpixel++=((srcval >>  7) & 0x0000f8) | /* h */
287                         ((srcval >> 12) & 0x000007) | /* h - 3 bits */
288                         ((srcval <<  6) & 0x00f800) | /* g */
289                         ((srcval <<  1) & 0x000700) | /* g - 3 bits */
290                         ((srcval << 19) & 0xf80000) | /* l */
291                         ((srcval << 14) & 0x070000);  /* l - 3 bits */
292         }
293         srcbits = (const char*)srcbits + srclinebytes;
294         dstbits = (char*)dstbits + dstlinebytes;
295     }
296 }
297
298 static void convert_5x5_to_any0888(int width, int height,
299                                    const void* srcbits, int srclinebytes,
300                                    WORD rsrc, WORD gsrc, WORD bsrc,
301                                    void* dstbits, int dstlinebytes,
302                                    DWORD rdst, DWORD gdst, DWORD bdst)
303 {
304     int rRightShift1,gRightShift1,bRightShift1;
305     int rRightShift2,gRightShift2,bRightShift2;
306     BYTE gMask1,gMask2;
307     int rLeftShift,gLeftShift,bLeftShift;
308     const WORD* srcpixel;
309     DWORD* dstpixel;
310     int x,y;
311
312     /* Note, the source pixel value is shifted left by 16 bits so that
313      * we know we will always have to shift right to extract the components.
314      */
315     rRightShift1=16+X11DRV_DIB_MaskToShift(rsrc)-3;
316     gRightShift1=16+X11DRV_DIB_MaskToShift(gsrc)-3;
317     bRightShift1=16+X11DRV_DIB_MaskToShift(bsrc)-3;
318     rRightShift2=rRightShift1+5;
319     gRightShift2=gRightShift1+5;
320     bRightShift2=bRightShift1+5;
321     if (gsrc==0x03e0) {
322         /* Green has 5 bits, like the others */
323         gMask1=0xf8;
324         gMask2=0x07;
325     } else {
326         /* Green has 6 bits, not 5. Compensate. */
327         gRightShift1++;
328         gRightShift2+=2;
329         gMask1=0xfc;
330         gMask2=0x03;
331     }
332
333     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
334     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
335     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
336
337     for (y=0; y<height; y++) {
338         srcpixel=srcbits;
339         dstpixel=dstbits;
340         for (x=0; x<width; x++) {
341             DWORD srcval;
342             BYTE red,green,blue;
343             srcval=*srcpixel++ << 16;
344             red=  ((srcval >> rRightShift1) & 0xf8) |
345                   ((srcval >> rRightShift2) & 0x07);
346             green=((srcval >> gRightShift1) & gMask1) |
347                   ((srcval >> gRightShift2) & gMask2);
348             blue= ((srcval >> bRightShift1) & 0xf8) |
349                   ((srcval >> bRightShift2) & 0x07);
350             *dstpixel++=(red   << rLeftShift) |
351                         (green << gLeftShift) |
352                         (blue  << bLeftShift);
353         }
354         srcbits = (const char*)srcbits + srclinebytes;
355         dstbits = (char*)dstbits + dstlinebytes;
356     }
357 }
358
359 /*
360  * 16 bits conversions
361  */
362
363 static void convert_565_reverse(int width, int height,
364                                 const void* srcbits, int srclinebytes,
365                                 void* dstbits, int dstlinebytes)
366 {
367     const DWORD* srcpixel;
368     DWORD* dstpixel;
369     int x,y;
370
371     for (y=0; y<height; y++) {
372         srcpixel=srcbits;
373         dstpixel=dstbits;
374         for (x=0; x<width/2; x++) {
375             /* Do 2 pixels at a time */
376             DWORD srcval;
377             srcval=*srcpixel++;
378             *dstpixel++=((srcval << 11) & 0xf800f800) | /* h */
379                         ( srcval        & 0x07e007e0) | /* g */
380                         ((srcval >> 11) & 0x001f001f);  /* l */
381         }
382         if (width&1) {
383             /* And then the odd pixel */
384             WORD srcval;
385             srcval=*((const WORD*)srcpixel);
386             *((WORD*)dstpixel)=((srcval << 11) & 0xf800) | /* h */
387                                ( srcval        & 0x07e0) | /* g */
388                                ((srcval >> 11) & 0x001f);  /* l */
389         }
390         srcbits = (const char*)srcbits + srclinebytes;
391         dstbits = (char*)dstbits + dstlinebytes;
392     }
393 }
394
395 static void convert_565_to_555_asis(int width, int height,
396                                     const void* srcbits, int srclinebytes,
397                                     void* dstbits, int dstlinebytes)
398 {
399     const DWORD* srcpixel;
400     DWORD* dstpixel;
401     int x,y;
402
403     for (y=0; y<height; y++) {
404         srcpixel=srcbits;
405         dstpixel=dstbits;
406         for (x=0; x<width/2; x++) {
407             /* Do 2 pixels at a time */
408             DWORD srcval;
409             srcval=*srcpixel++;
410             *dstpixel++=((srcval >> 1) & 0x7fe07fe0) | /* h, g */
411                         ( srcval       & 0x001f001f);  /* l */
412         }
413         if (width&1) {
414             /* And then the odd pixel */
415             WORD srcval;
416             srcval=*((const WORD*)srcpixel);
417             *((WORD*)dstpixel)=((srcval >> 1) & 0x7fe0) | /* h, g */
418                                ( srcval       & 0x001f);  /* l */
419         }
420         srcbits = (const char*)srcbits + srclinebytes;
421         dstbits = (char*)dstbits + dstlinebytes;
422     }
423 }
424
425 static void convert_565_to_555_reverse(int width, int height,
426                                        const void* srcbits, int srclinebytes,
427                                        void* dstbits, int dstlinebytes)
428 {
429     const DWORD* srcpixel;
430     DWORD* dstpixel;
431     int x,y;
432
433     for (y=0; y<height; y++) {
434         srcpixel=srcbits;
435         dstpixel=dstbits;
436         for (x=0; x<width/2; x++) {
437             /* Do 2 pixels at a time */
438             DWORD srcval;
439             srcval=*srcpixel++;
440             *dstpixel++=((srcval >> 11) & 0x001f001f) | /* h */
441                         ((srcval >>  1) & 0x03e003e0) | /* g */
442                         ((srcval << 10) & 0x7c007c00);  /* l */
443         }
444         if (width&1) {
445             /* And then the odd pixel */
446             WORD srcval;
447             srcval=*((const WORD*)srcpixel);
448             *((WORD*)dstpixel)=((srcval >> 11) & 0x001f) | /* h */
449                                ((srcval >>  1) & 0x03e0) | /* g */
450                                ((srcval << 10) & 0x7c00);  /* l */
451         }
452         srcbits = (const char*)srcbits + srclinebytes;
453         dstbits = (char*)dstbits + dstlinebytes;
454     }
455 }
456
457 static void convert_565_to_888_asis(int width, int height,
458                                     const void* srcbits, int srclinebytes,
459                                     void* dstbits, int dstlinebytes)
460 {
461     const WORD* srcpixel;
462     BYTE* dstpixel;
463     int x,y;
464
465     for (y=0; y<height; y++) {
466         srcpixel=srcbits;
467         dstpixel=dstbits;
468         for (x=0; x<width; x++) {
469             WORD srcval;
470             srcval=*srcpixel++;
471             dstpixel[0]=((srcval <<  3) & 0xf8) | /* l */
472                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
473             dstpixel[1]=((srcval >>  3) & 0xfc) | /* g */
474                         ((srcval >>  9) & 0x03);  /* g - 2 bits */
475             dstpixel[2]=((srcval >>  8) & 0xf8) | /* h */
476                         ((srcval >> 13) & 0x07);  /* h - 3 bits */
477             dstpixel+=3;
478         }
479         srcbits = (const char*)srcbits + srclinebytes;
480         dstbits = (char*)dstbits + dstlinebytes;
481     }
482 }
483
484 static void convert_565_to_888_reverse(int width, int height,
485                                        const void* srcbits, int srclinebytes,
486                                        void* dstbits, int dstlinebytes)
487 {
488     const WORD* srcpixel;
489     BYTE* dstpixel;
490     int x,y;
491
492     for (y=0; y<height; y++) {
493         srcpixel=srcbits;
494         dstpixel=dstbits;
495         for (x=0; x<width; x++) {
496             WORD srcval;
497             srcval=*srcpixel++;
498             dstpixel[0]=((srcval >>  8) & 0xf8) | /* h */
499                         ((srcval >> 13) & 0x07);  /* h - 3 bits */
500             dstpixel[1]=((srcval >>  3) & 0xfc) | /* g */
501                         ((srcval >>  9) & 0x03);  /* g - 2 bits */
502             dstpixel[2]=((srcval <<  3) & 0xf8) | /* l */
503                         ((srcval >>  2) & 0x07);  /* l - 3 bits */
504             dstpixel+=3;
505         }
506         srcbits = (const char*)srcbits + srclinebytes;
507         dstbits = (char*)dstbits + dstlinebytes;
508     }
509 }
510
511 static void convert_565_to_0888_asis(int width, int height,
512                                      const void* srcbits, int srclinebytes,
513                                      void* dstbits, int dstlinebytes)
514 {
515     const WORD* srcpixel;
516     DWORD* dstpixel;
517     int x,y;
518
519     for (y=0; y<height; y++) {
520         srcpixel=srcbits;
521         dstpixel=dstbits;
522         for (x=0; x<width; x++) {
523             WORD srcval;
524             srcval=*srcpixel++;
525             *dstpixel++=((srcval << 8) & 0xf80000) | /* h */
526                         ((srcval << 3) & 0x070000) | /* h - 3 bits */
527                         ((srcval << 5) & 0x00fc00) | /* g */
528                         ((srcval >> 1) & 0x000300) | /* g - 2 bits */
529                         ((srcval << 3) & 0x0000f8) | /* l */
530                         ((srcval >> 2) & 0x000007);  /* l - 3 bits */
531         }
532         srcbits = (const char*)srcbits + srclinebytes;
533         dstbits = (char*)dstbits + dstlinebytes;
534     }
535 }
536
537 static void convert_565_to_0888_reverse(int width, int height,
538                                         const void* srcbits, int srclinebytes,
539                                         void* dstbits, int dstlinebytes)
540 {
541     const WORD* srcpixel;
542     DWORD* dstpixel;
543     int x,y;
544
545     for (y=0; y<height; y++) {
546         srcpixel=srcbits;
547         dstpixel=dstbits;
548         for (x=0; x<width; x++) {
549             WORD srcval;
550             srcval=*srcpixel++;
551             *dstpixel++=((srcval >>  8) & 0x0000f8) | /* h */
552                         ((srcval >> 13) & 0x000007) | /* h - 3 bits */
553                         ((srcval <<  5) & 0x00fc00) | /* g */
554                         ((srcval >>  1) & 0x000300) | /* g - 2 bits */
555                         ((srcval << 19) & 0xf80000) | /* l */
556                         ((srcval << 14) & 0x070000);  /* l - 3 bits */
557         }
558         srcbits = (const char*)srcbits + srclinebytes;
559         dstbits = (char*)dstbits + dstlinebytes;
560     }
561 }
562
563
564 /*
565  * 24 bit conversions
566  */
567
568 static void convert_888_asis(int width, int height,
569                              const void* srcbits, int srclinebytes,
570                              void* dstbits, int dstlinebytes)
571 {
572     int y;
573
574     width *= 3;
575
576     if (srclinebytes == dstlinebytes && srclinebytes == width)
577     {
578         memcpy(dstbits, srcbits, height * width);
579         return;
580     }
581
582     for (y=0; y<height; y++) {
583         memcpy(dstbits, srcbits, width);
584         srcbits = (const char*)srcbits + srclinebytes;
585         dstbits = (char*)dstbits + dstlinebytes;
586     }
587 }
588
589
590 static void convert_888_reverse(int width, int height,
591                                 const void* srcbits, int srclinebytes,
592                                 void* dstbits, int dstlinebytes)
593 {
594     const BYTE* srcpixel;
595     BYTE* dstpixel;
596     int x,y;
597
598     for (y=0; y<height; y++) {
599         srcpixel=srcbits;
600         dstpixel=dstbits;
601         for (x=0; x<width; x++) {
602             dstpixel[0]=srcpixel[2];
603             dstpixel[1]=srcpixel[1];
604             dstpixel[2]=srcpixel[0];
605             srcpixel+=3;
606             dstpixel+=3;
607         }
608         srcbits = (const char*)srcbits + srclinebytes;
609         dstbits = (char*)dstbits + dstlinebytes;
610     }
611 }
612
613 static void convert_888_to_555_asis(int width, int height,
614                                     const void* srcbits, int srclinebytes,
615                                     void* dstbits, int dstlinebytes)
616 {
617     const DWORD* srcpixel;
618     const BYTE* srcbyte;
619     WORD* dstpixel;
620     int x,y;
621     int oddwidth;
622
623     oddwidth=width & 3;
624     width=width/4;
625     for (y=0; y<height; y++) {
626         srcpixel=srcbits;
627         dstpixel=dstbits;
628         for (x=0; x<width; x++) {
629             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
630             DWORD srcval1,srcval2;
631             srcval1=srcpixel[0];
632             dstpixel[0]=((srcval1 >>  3) & 0x001f) | /* l1 */
633                         ((srcval1 >>  6) & 0x03e0) | /* g1 */
634                         ((srcval1 >>  9) & 0x7c00);  /* h1 */
635             srcval2=srcpixel[1];
636             dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
637                         ((srcval2 <<  2) & 0x03e0) | /* g2 */
638                         ((srcval2 >>  1) & 0x7c00);  /* h2 */
639             srcval1=srcpixel[2];
640             dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
641                         ((srcval2 >> 22) & 0x03e0) | /* g3 */
642                         ((srcval1 <<  7) & 0x7c00);  /* h3 */
643             dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
644                         ((srcval1 >> 14) & 0x03e0) | /* g4 */
645                         ((srcval1 >> 17) & 0x7c00);  /* h4 */
646             srcpixel+=3;
647             dstpixel+=4;
648         }
649         /* And now up to 3 odd pixels */
650         srcbyte=(const BYTE*)srcpixel;
651         for (x=0; x<oddwidth; x++) {
652             WORD dstval;
653             dstval =((srcbyte[0] >> 3) & 0x001f);    /* l */
654             dstval|=((srcbyte[1] << 2) & 0x03e0);    /* g */
655             dstval|=((srcbyte[2] << 7) & 0x7c00);    /* h */
656             *dstpixel++=dstval;
657             srcbyte+=3;
658         }
659         srcbits = (const char*)srcbits + srclinebytes;
660         dstbits = (char*)dstbits + dstlinebytes;
661     }
662 }
663
664 static void convert_888_to_555_reverse(int width, int height,
665                                        const void* srcbits, int srclinebytes,
666                                        void* dstbits, int dstlinebytes)
667 {
668     const DWORD* srcpixel;
669     const BYTE* srcbyte;
670     WORD* dstpixel;
671     int x,y;
672     int oddwidth;
673
674     oddwidth=width & 3;
675     width=width/4;
676     for (y=0; y<height; y++) {
677         srcpixel=srcbits;
678         dstpixel=dstbits;
679         for (x=0; x<width; x++) {
680             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
681             DWORD srcval1,srcval2;
682             srcval1=srcpixel[0];
683             dstpixel[0]=((srcval1 <<  7) & 0x7c00) | /* l1 */
684                         ((srcval1 >>  6) & 0x03e0) | /* g1 */
685                         ((srcval1 >> 19) & 0x001f);  /* h1 */
686             srcval2=srcpixel[1];
687             dstpixel[1]=((srcval1 >> 17) & 0x7c00) | /* l2 */
688                         ((srcval2 <<  2) & 0x03e0) | /* g2 */
689                         ((srcval2 >> 11) & 0x001f);  /* h2 */
690             srcval1=srcpixel[2];
691             dstpixel[2]=((srcval2 >>  9) & 0x7c00) | /* l3 */
692                         ((srcval2 >> 22) & 0x03e0) | /* g3 */
693                         ((srcval1 >>  3) & 0x001f);  /* h3 */
694             dstpixel[3]=((srcval1 >>  1) & 0x7c00) | /* l4 */
695                         ((srcval1 >> 14) & 0x03e0) | /* g4 */
696                         ((srcval1 >> 27) & 0x001f);  /* h4 */
697             srcpixel+=3;
698             dstpixel+=4;
699         }
700         /* And now up to 3 odd pixels */
701         srcbyte=(const BYTE*)srcpixel;
702         for (x=0; x<oddwidth; x++) {
703             WORD dstval;
704             dstval =((srcbyte[0] << 7) & 0x7c00);    /* l */
705             dstval|=((srcbyte[1] << 2) & 0x03e0);    /* g */
706             dstval|=((srcbyte[2] >> 3) & 0x001f);    /* h */
707             *dstpixel++=dstval;
708             srcbyte+=3;
709         }
710         srcbits = (const char*)srcbits + srclinebytes;
711         dstbits = (char*)dstbits + dstlinebytes;
712     }
713 }
714
715 static void convert_888_to_565_asis(int width, int height,
716                                     const void* srcbits, int srclinebytes,
717                                     void* dstbits, int dstlinebytes)
718 {
719     const DWORD* srcpixel;
720     const BYTE* srcbyte;
721     WORD* dstpixel;
722     int x,y;
723     int oddwidth;
724
725     oddwidth=width & 3;
726     width=width/4;
727     for (y=0; y<height; y++) {
728         srcpixel=srcbits;
729         dstpixel=dstbits;
730         for (x=0; x<width; x++) {
731             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
732             DWORD srcval1,srcval2;
733             srcval1=srcpixel[0];
734             dstpixel[0]=((srcval1 >>  3) & 0x001f) | /* l1 */
735                         ((srcval1 >>  5) & 0x07e0) | /* g1 */
736                         ((srcval1 >>  8) & 0xf800);  /* h1 */
737             srcval2=srcpixel[1];
738             dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
739                         ((srcval2 <<  3) & 0x07e0) | /* g2 */
740                         ( srcval2        & 0xf800);  /* h2 */
741             srcval1=srcpixel[2];
742             dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
743                         ((srcval2 >> 21) & 0x07e0) | /* g3 */
744                         ((srcval1 <<  8) & 0xf800);  /* h3 */
745             dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
746                         ((srcval1 >> 13) & 0x07e0) | /* g4 */
747                         ((srcval1 >> 16) & 0xf800);  /* h4 */
748             srcpixel+=3;
749             dstpixel+=4;
750         }
751         /* And now up to 3 odd pixels */
752         srcbyte=(const BYTE*)srcpixel;
753         for (x=0; x<oddwidth; x++) {
754             WORD dstval;
755             dstval =((srcbyte[0] >> 3) & 0x001f);    /* l */
756             dstval|=((srcbyte[1] << 3) & 0x07e0);    /* g */
757             dstval|=((srcbyte[2] << 8) & 0xf800);    /* h */
758             *dstpixel++=dstval;
759             srcbyte+=3;
760         }
761         srcbits = (const char*)srcbits + srclinebytes;
762         dstbits = (char*)dstbits + dstlinebytes;
763     }
764 }
765
766 static void convert_888_to_565_reverse(int width, int height,
767                                        const void* srcbits, int srclinebytes,
768                                        void* dstbits, int dstlinebytes)
769 {
770     const DWORD* srcpixel;
771     const BYTE* srcbyte;
772     WORD* dstpixel;
773     int x,y;
774     int oddwidth;
775
776     oddwidth=width & 3;
777     width=width/4;
778     for (y=0; y<height; y++) {
779         srcpixel=srcbits;
780         dstpixel=dstbits;
781         for (x=0; x<width; x++) {
782             /* Do 4 pixels at a time: 3 dwords in and 4 words out */
783             DWORD srcval1,srcval2;
784             srcval1=srcpixel[0];
785             dstpixel[0]=((srcval1 <<  8) & 0xf800) | /* l1 */
786                         ((srcval1 >>  5) & 0x07e0) | /* g1 */
787                         ((srcval1 >> 19) & 0x001f);  /* h1 */
788             srcval2=srcpixel[1];
789             dstpixel[1]=((srcval1 >> 16) & 0xf800) | /* l2 */
790                         ((srcval2 <<  3) & 0x07e0) | /* g2 */
791                         ((srcval2 >> 11) & 0x001f);  /* h2 */
792             srcval1=srcpixel[2];
793             dstpixel[2]=((srcval2 >>  8) & 0xf800) | /* l3 */
794                         ((srcval2 >> 21) & 0x07e0) | /* g3 */
795                         ((srcval1 >>  3) & 0x001f);  /* h3 */
796             dstpixel[3]=(srcval1         & 0xf800) | /* l4 */
797                         ((srcval1 >> 13) & 0x07e0) | /* g4 */
798                         ((srcval1 >> 27) & 0x001f);  /* h4 */
799             srcpixel+=3;
800             dstpixel+=4;
801         }
802         /* And now up to 3 odd pixels */
803         srcbyte=(const BYTE*)srcpixel;
804         for (x=0; x<oddwidth; x++) {
805             WORD dstval;
806             dstval =((srcbyte[0] << 8) & 0xf800);    /* l */
807             dstval|=((srcbyte[1] << 3) & 0x07e0);    /* g */
808             dstval|=((srcbyte[2] >> 3) & 0x001f);    /* h */
809             *dstpixel++=dstval;
810             srcbyte+=3;
811         }
812         srcbits = (const char*)srcbits + srclinebytes;
813         dstbits = (char*)dstbits + dstlinebytes;
814     }
815 }
816
817 static void convert_888_to_0888_asis(int width, int height,
818                                      const void* srcbits, int srclinebytes,
819                                      void* dstbits, int dstlinebytes)
820 {
821     const DWORD* srcpixel;
822     DWORD* dstpixel;
823     int x,y;
824     int w1, w2, w3;
825     
826     w1 = min( (INT_PTR)srcbits & 3, width);
827     w2 = ( width - w1) / 4;
828     w3 = ( width - w1) & 3;
829     for (y=0; y<height; y++) {
830         srcpixel=srcbits;
831         dstpixel=dstbits;
832         /* advance  w1 pixels to make srcpixel 32 bit aligned */
833         srcpixel = (const DWORD*)((INT_PTR)srcpixel & ~3);
834         srcpixel += w1;
835         dstpixel += w1;
836         /* and do the w1 pixels */
837         x = w1;
838         if( x) {
839             dstpixel[ -1] = ( srcpixel[ -1] >>  8);               /* h4, g4, l4 */
840             if( --x) {
841                 dstpixel[ -2] = ( srcpixel[ -2] >> 16) |              /* g3, l3 */
842                                 ((srcpixel[ -1] << 16) & 0x00ff0000); /* h3 */
843                 if( --x) {
844                     dstpixel[ -3] = ( srcpixel[ -3] >> 24) |              /* l2 */
845                                     ((srcpixel[ -2] <<  8) & 0x00ffff00); /* h2, g2 */
846                 }
847             }
848         }
849         for (x=0; x < w2; x++) {
850             /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
851             DWORD srcval1,srcval2;
852             srcval1=srcpixel[0];
853             dstpixel[0]=( srcval1        & 0x00ffffff); /* h1, g1, l1 */
854             srcval2=srcpixel[1];
855             dstpixel[1]=( srcval1 >> 24) |              /* l2 */
856                         ((srcval2 <<  8) & 0x00ffff00); /* h2, g2 */
857             srcval1=srcpixel[2];
858             dstpixel[2]=( srcval2 >> 16) |              /* g3, l3 */
859                         ((srcval1 << 16) & 0x00ff0000); /* h3 */
860             dstpixel[3]=( srcval1 >>  8);               /* h4, g4, l4 */
861             srcpixel+=3;
862             dstpixel+=4;
863         }
864         /* do last w3 pixels */
865         x = w3;
866         if( x) {
867             dstpixel[0]=( srcpixel[0]       & 0x00ffffff); /* h1, g1, l1 */
868             if( --x) {
869                 dstpixel[1]=( srcpixel[0]>> 24) |              /* l2 */
870                             ((srcpixel[1]<<  8) & 0x00ffff00); /* h2, g2 */
871                 if( --x) {
872                     dstpixel[2]=( srcpixel[1]>> 16) |              /* g3, l3 */
873                                 ((srcpixel[2]<< 16) & 0x00ff0000); /* h3 */
874                 }
875             }
876         }
877         srcbits = (const char*)srcbits + srclinebytes;
878         dstbits = (char*)dstbits + dstlinebytes;
879     }
880 }
881
882 static void convert_888_to_0888_reverse(int width, int height,
883                                         const void* srcbits, int srclinebytes,
884                                         void* dstbits, int dstlinebytes)
885 {
886     const DWORD* srcpixel;
887     DWORD* dstpixel;
888     int x,y;
889     int w1, w2, w3;
890
891     w1 = min( (INT_PTR)srcbits & 3, width);
892     w2 = ( width - w1) / 4;
893     w3 = ( width - w1) & 3;
894     for (y=0; y<height; y++) {
895         srcpixel=srcbits;
896         dstpixel=dstbits;
897         /* advance w1 pixels to make srcpixel 32 bit aligned */
898         srcpixel =  (const DWORD*)((INT_PTR)srcpixel & ~3);
899         srcpixel += w1;
900         dstpixel += w1;
901         /* and do the w1 pixels */
902         x = w1;
903         if( x) {
904             dstpixel[ -1]=((srcpixel[ -1] >> 24) & 0x0000ff) | /* h4 */
905                           ((srcpixel[ -1] >>  8) & 0x00ff00) | /* g4 */
906                           ((srcpixel[ -1] <<  8) & 0xff0000);  /* l4 */
907             if( --x) {
908                 dstpixel[ -2]=( srcpixel[ -2]        & 0xff0000) | /* l3 */
909                               ((srcpixel[ -2] >> 16) & 0x00ff00) | /* g3 */
910                               ( srcpixel[ -1]        & 0x0000ff);  /* h3 */
911                 if( --x) {
912                     dstpixel[ -3]=((srcpixel[ -3] >>  8) & 0xff0000) | /* l2 */
913                                   ((srcpixel[ -2] <<  8) & 0x00ff00) | /* g2 */
914                                   ((srcpixel[ -2] >>  8) & 0x0000ff);  /* h2 */
915                 }
916             }
917         }
918         for (x=0; x < w2; x++) {
919             /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
920             DWORD srcval1,srcval2;
921
922             srcval1=srcpixel[0];
923             dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */
924                         ( srcval1        & 0x00ff00) | /* g1 */
925                         ((srcval1 << 16) & 0xff0000);  /* l1 */
926             srcval2=srcpixel[1];
927             dstpixel[1]=((srcval1 >>  8) & 0xff0000) | /* l2 */
928                         ((srcval2 <<  8) & 0x00ff00) | /* g2 */
929                         ((srcval2 >>  8) & 0x0000ff);  /* h2 */
930             srcval1=srcpixel[2];
931             dstpixel[2]=( srcval2        & 0xff0000) | /* l3 */
932                         ((srcval2 >> 16) & 0x00ff00) | /* g3 */
933                         ( srcval1        & 0x0000ff);  /* h3 */
934             dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */
935                         ((srcval1 >>  8) & 0x00ff00) | /* g4 */
936                         ((srcval1 <<  8) & 0xff0000);  /* l4 */
937             srcpixel+=3;
938             dstpixel+=4;
939         }
940         /* do last w3 pixels */
941         x = w3;
942         if( x) {
943             dstpixel[0]=((srcpixel[0] >> 16) & 0x0000ff) | /* h1 */
944                         ( srcpixel[0]        & 0x00ff00) | /* g1 */
945                         ((srcpixel[0] << 16) & 0xff0000);  /* l1 */
946             if( --x) {
947                 dstpixel[1]=((srcpixel[0] >>  8) & 0xff0000) | /* l2 */
948                             ((srcpixel[1] <<  8) & 0x00ff00) | /* g2 */
949                             ((srcpixel[1] >>  8) & 0x0000ff);  /* h2 */
950                 if( --x) {
951                     dstpixel[2]=( srcpixel[1]        & 0xff0000) | /* l3 */
952                                 ((srcpixel[1] >> 16) & 0x00ff00) | /* g3 */
953                                 ( srcpixel[2]        & 0x0000ff);  /* h3 */
954                 }
955             }
956         }
957         srcbits = (const char*)srcbits + srclinebytes;
958         dstbits = (char*)dstbits + dstlinebytes;
959     }
960 }
961
962 static void convert_rgb888_to_any0888(int width, int height,
963                                       const void* srcbits, int srclinebytes,
964                                       void* dstbits, int dstlinebytes,
965                                       DWORD rdst, DWORD gdst, DWORD bdst)
966 {
967     int rLeftShift,gLeftShift,bLeftShift;
968     const BYTE* srcpixel;
969     DWORD* dstpixel;
970     int x,y;
971
972     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
973     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
974     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
975     for (y=0; y<height; y++) {
976         srcpixel=srcbits;
977         dstpixel=dstbits;
978         for (x=0; x<width; x++) {
979             *dstpixel++=(srcpixel[0] << bLeftShift) | /* b */
980                         (srcpixel[1] << gLeftShift) | /* g */
981                         (srcpixel[2] << rLeftShift);  /* r */
982             srcpixel+=3;
983         }
984         srcbits = (const char*)srcbits + srclinebytes;
985         dstbits = (char*)dstbits + dstlinebytes;
986     }
987 }
988
989 static void convert_bgr888_to_any0888(int width, int height,
990                                       const void* srcbits, int srclinebytes,
991                                       void* dstbits, int dstlinebytes,
992                                       DWORD rdst, DWORD gdst, DWORD bdst)
993 {
994     int rLeftShift,gLeftShift,bLeftShift;
995     const BYTE* srcpixel;
996     DWORD* dstpixel;
997     int x,y;
998
999     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1000     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1001     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1002     for (y=0; y<height; y++) {
1003         srcpixel=srcbits;
1004         dstpixel=dstbits;
1005         for (x=0; x<width; x++) {
1006             *dstpixel++=(srcpixel[0] << rLeftShift) | /* r */
1007                         (srcpixel[1] << gLeftShift) | /* g */
1008                         (srcpixel[2] << bLeftShift);  /* b */
1009             srcpixel+=3;
1010         }
1011         srcbits = (const char*)srcbits + srclinebytes;
1012         dstbits = (char*)dstbits + dstlinebytes;
1013     }
1014 }
1015
1016 /*
1017  * 32 bit conversions
1018  */
1019
1020 static void convert_0888_asis(int width, int height,
1021                               const void* srcbits, int srclinebytes,
1022                               void* dstbits, int dstlinebytes)
1023 {
1024     int y;
1025
1026     width *= 4;
1027
1028     if (srclinebytes == dstlinebytes && srclinebytes == width)
1029     {
1030         memcpy(dstbits, srcbits, height * width);
1031         return;
1032     }
1033
1034     for (y=0; y<height; y++) {
1035         memcpy(dstbits, srcbits, width);
1036         srcbits = (const char*)srcbits + srclinebytes;
1037         dstbits = (char*)dstbits + dstlinebytes;
1038     }
1039 }
1040
1041 static void convert_0888_reverse(int width, int height,
1042                                  const void* srcbits, int srclinebytes,
1043                                  void* dstbits, int dstlinebytes)
1044 {
1045     const DWORD* srcpixel;
1046     DWORD* dstpixel;
1047     int x,y;
1048
1049     for (y=0; y<height; y++) {
1050         srcpixel=srcbits;
1051         dstpixel=dstbits;
1052         for (x=0; x<width; x++) {
1053             DWORD srcval;
1054             srcval=*srcpixel++;
1055             *dstpixel++=((srcval << 16) & 0x00ff0000) | /* h */
1056                         ( srcval        & 0x0000ff00) | /* g */
1057                         ((srcval >> 16) & 0x000000ff);  /* l */
1058         }
1059         srcbits = (const char*)srcbits + srclinebytes;
1060         dstbits = (char*)dstbits + dstlinebytes;
1061     }
1062 }
1063
1064 static void convert_0888_any(int width, int height,
1065                              const void* srcbits, int srclinebytes,
1066                              DWORD rsrc, DWORD gsrc, DWORD bsrc,
1067                              void* dstbits, int dstlinebytes,
1068                              DWORD rdst, DWORD gdst, DWORD bdst)
1069 {
1070     int rRightShift,gRightShift,bRightShift;
1071     int rLeftShift,gLeftShift,bLeftShift;
1072     const DWORD* srcpixel;
1073     DWORD* dstpixel;
1074     int x,y;
1075
1076     rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1077     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1078     bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1079     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1080     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1081     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1082     for (y=0; y<height; y++) {
1083         srcpixel=srcbits;
1084         dstpixel=dstbits;
1085         for (x=0; x<width; x++) {
1086             DWORD srcval;
1087             srcval=*srcpixel++;
1088             *dstpixel++=(((srcval >> rRightShift) & 0xff) << rLeftShift) |
1089                         (((srcval >> gRightShift) & 0xff) << gLeftShift) |
1090                         (((srcval >> bRightShift) & 0xff) << bLeftShift);
1091         }
1092         srcbits = (const char*)srcbits + srclinebytes;
1093         dstbits = (char*)dstbits + dstlinebytes;
1094     }
1095 }
1096
1097 static void convert_0888_to_555_asis(int width, int height,
1098                                      const void* srcbits, int srclinebytes,
1099                                      void* dstbits, int dstlinebytes)
1100 {
1101     const DWORD* srcpixel;
1102     WORD* dstpixel;
1103     int x,y;
1104
1105     for (y=0; y<height; y++) {
1106         srcpixel=srcbits;
1107         dstpixel=dstbits;
1108         for (x=0; x<width; x++) {
1109             DWORD srcval;
1110             srcval=*srcpixel++;
1111             *dstpixel++=((srcval >> 9) & 0x7c00) | /* h */
1112                         ((srcval >> 6) & 0x03e0) | /* g */
1113                         ((srcval >> 3) & 0x001f);  /* l */
1114         }
1115         srcbits = (const char*)srcbits + srclinebytes;
1116         dstbits = (char*)dstbits + dstlinebytes;
1117     }
1118 }
1119
1120 static void convert_0888_to_555_reverse(int width, int height,
1121                                         const void* srcbits, int srclinebytes,
1122                                         void* dstbits, int dstlinebytes)
1123 {
1124     const DWORD* srcpixel;
1125     WORD* dstpixel;
1126     int x,y;
1127
1128     for (y=0; y<height; y++) {
1129         srcpixel=srcbits;
1130         dstpixel=dstbits;
1131         for (x=0; x<width; x++) {
1132             DWORD srcval;
1133             srcval=*srcpixel++;
1134             *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1135                         ((srcval >>  6) & 0x03e0) | /* g */
1136                         ((srcval <<  7) & 0x7c00);  /* l */
1137         }
1138         srcbits = (const char*)srcbits + srclinebytes;
1139         dstbits = (char*)dstbits + dstlinebytes;
1140     }
1141 }
1142
1143 static void convert_0888_to_565_asis(int width, int height,
1144                                      const void* srcbits, int srclinebytes,
1145                                      void* dstbits, int dstlinebytes)
1146 {
1147     const DWORD* srcpixel;
1148     WORD* dstpixel;
1149     int x,y;
1150
1151     for (y=0; y<height; y++) {
1152         srcpixel=srcbits;
1153         dstpixel=dstbits;
1154         for (x=0; x<width; x++) {
1155             DWORD srcval;
1156             srcval=*srcpixel++;
1157             *dstpixel++=((srcval >> 8) & 0xf800) | /* h */
1158                         ((srcval >> 5) & 0x07e0) | /* g */
1159                         ((srcval >> 3) & 0x001f);  /* l */
1160         }
1161         srcbits = (const char*)srcbits + srclinebytes;
1162         dstbits = (char*)dstbits + dstlinebytes;
1163     }
1164 }
1165
1166 static void convert_0888_to_565_reverse(int width, int height,
1167                                         const void* srcbits, int srclinebytes,
1168                                         void* dstbits, int dstlinebytes)
1169 {
1170     const DWORD* srcpixel;
1171     WORD* dstpixel;
1172     int x,y;
1173
1174     for (y=0; y<height; y++) {
1175         srcpixel=srcbits;
1176         dstpixel=dstbits;
1177         for (x=0; x<width; x++) {
1178             DWORD srcval;
1179             srcval=*srcpixel++;
1180             *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1181                         ((srcval >>  5) & 0x07e0) | /* g */
1182                         ((srcval <<  8) & 0xf800);  /* l */
1183         }
1184         srcbits = (const char*)srcbits + srclinebytes;
1185         dstbits = (char*)dstbits + dstlinebytes;
1186     }
1187 }
1188
1189 static void convert_any0888_to_5x5(int width, int height,
1190                                    const void* srcbits, int srclinebytes,
1191                                    DWORD rsrc, DWORD gsrc, DWORD bsrc,
1192                                    void* dstbits, int dstlinebytes,
1193                                    WORD rdst, WORD gdst, WORD bdst)
1194 {
1195     int rRightShift,gRightShift,bRightShift;
1196     int rLeftShift,gLeftShift,bLeftShift;
1197     const DWORD* srcpixel;
1198     WORD* dstpixel;
1199     int x,y;
1200
1201     /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel
1202      * contains 0x11223344.
1203      * - first we shift 0x11223344 right by rRightShift to bring the most
1204      *   significant bits of the red components in the bottom 5 (or 6) bits
1205      *   -> 0x4488c
1206      * - then we remove non red bits by anding with the modified rdst (0x1f)
1207      *   -> 0x0c
1208      * - finally shift these bits left by rLeftShift so that they end up in
1209      *   the right place
1210      *   -> 0x3000
1211      */
1212     rRightShift=X11DRV_DIB_MaskToShift(rsrc)+3;
1213     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1214     gRightShift+=(gdst==0x07e0?2:3);
1215     bRightShift=X11DRV_DIB_MaskToShift(bsrc)+3;
1216
1217     rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1218     rdst=rdst >> rLeftShift;
1219     gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1220     gdst=gdst >> gLeftShift;
1221     bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1222     bdst=bdst >> bLeftShift;
1223
1224     for (y=0; y<height; y++) {
1225         srcpixel=srcbits;
1226         dstpixel=dstbits;
1227         for (x=0; x<width; x++) {
1228             DWORD srcval;
1229             srcval=*srcpixel++;
1230             *dstpixel++=(((srcval >> rRightShift) & rdst) << rLeftShift) |
1231                         (((srcval >> gRightShift) & gdst) << gLeftShift) |
1232                         (((srcval >> bRightShift) & bdst) << bLeftShift);
1233         }
1234         srcbits = (const char*)srcbits + srclinebytes;
1235         dstbits = (char*)dstbits + dstlinebytes;
1236     }
1237 }
1238
1239 static void convert_0888_to_888_asis(int width, int height,
1240                                      const void* srcbits, int srclinebytes,
1241                                      void* dstbits, int dstlinebytes)
1242 {
1243     const DWORD* srcpixel;
1244     DWORD* dstpixel;
1245     BYTE* dstbyte;
1246     int x,y;
1247     int oddwidth;
1248
1249     oddwidth=width & 3;
1250     width=width/4;
1251     for (y=0; y<height; y++) {
1252         srcpixel=srcbits;
1253         dstpixel=dstbits;
1254         for (x=0; x<width; x++) {
1255             /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1256             DWORD srcval;
1257             srcval=((*srcpixel++)       & 0x00ffffff);  /* h1, g1, l1*/
1258             *dstpixel++=srcval | ((*srcpixel)   << 24); /* h2 */
1259             srcval=((*srcpixel++ >> 8 ) & 0x0000ffff);  /* g2, l2 */
1260             *dstpixel++=srcval | ((*srcpixel)   << 16); /* h3, g3 */
1261             srcval=((*srcpixel++ >> 16) & 0x000000ff);  /* l3 */
1262             *dstpixel++=srcval | ((*srcpixel++) << 8);  /* h4, g4, l4 */
1263         }
1264         /* And now up to 3 odd pixels */
1265         dstbyte=(BYTE*)dstpixel;
1266         for (x=0; x<oddwidth; x++) {
1267             DWORD srcval;
1268             srcval=*srcpixel++;
1269             *((WORD*)dstbyte) = srcval;                 /* h, g */
1270             dstbyte+=sizeof(WORD);
1271             *dstbyte++=srcval >> 16;                    /* l */
1272         }
1273         srcbits = (const char*)srcbits + srclinebytes;
1274         dstbits = (char*)dstbits + dstlinebytes;
1275     }
1276 }
1277
1278 static void convert_0888_to_888_reverse(int width, int height,
1279                                         const void* srcbits, int srclinebytes,
1280                                         void* dstbits, int dstlinebytes)
1281 {
1282     const DWORD* srcpixel;
1283     DWORD* dstpixel;
1284     BYTE* dstbyte;
1285     int x,y;
1286     int oddwidth;
1287
1288     oddwidth=width & 3;
1289     width=width/4;
1290     for (y=0; y<height; y++) {
1291         srcpixel=srcbits;
1292         dstpixel=dstbits;
1293         for (x=0; x<width; x++) {
1294             /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1295             DWORD srcval1,srcval2;
1296             srcval1=*srcpixel++;
1297             srcval2=    ((srcval1 >> 16) & 0x000000ff) | /* h1 */
1298                         ( srcval1        & 0x0000ff00) | /* g1 */
1299                         ((srcval1 << 16) & 0x00ff0000);  /* l1 */
1300             srcval1=*srcpixel++;
1301             *dstpixel++=srcval2 |
1302                         ((srcval1 <<  8) & 0xff000000);  /* h2 */
1303             srcval2=    ((srcval1 >>  8) & 0x000000ff) | /* g2 */
1304                         ((srcval1 <<  8) & 0x0000ff00);  /* l2 */
1305             srcval1=*srcpixel++;
1306             *dstpixel++=srcval2 |
1307                         ( srcval1        & 0x00ff0000) | /* h3 */
1308                         ((srcval1 << 16) & 0xff000000);  /* g3 */
1309             srcval2=    ( srcval1        & 0x000000ff);  /* l3 */
1310             srcval1=*srcpixel++;
1311             *dstpixel++=srcval2 |
1312                         ((srcval1 >>  8) & 0x0000ff00) | /* h4 */
1313                         ((srcval1 <<  8) & 0x00ff0000) | /* g4 */
1314                         ( srcval1 << 24);                /* l4 */
1315         }
1316         /* And now up to 3 odd pixels */
1317         dstbyte=(BYTE*)dstpixel;
1318         for (x=0; x<oddwidth; x++) {
1319             DWORD srcval;
1320             srcval=*srcpixel++;
1321             *((WORD*)dstbyte)=((srcval >> 16) & 0x00ff) | /* h */
1322                               (srcval         & 0xff00);  /* g */
1323             dstbyte += sizeof(WORD);
1324             *dstbyte++=srcval;                              /* l */
1325         }
1326         srcbits = (const char*)srcbits + srclinebytes;
1327         dstbits = (char*)dstbits + dstlinebytes;
1328     }
1329 }
1330
1331 static void convert_any0888_to_rgb888(int width, int height,
1332                                       const void* srcbits, int srclinebytes,
1333                                       DWORD rsrc, DWORD gsrc, DWORD bsrc,
1334                                       void* dstbits, int dstlinebytes)
1335 {
1336     int rRightShift,gRightShift,bRightShift;
1337     const DWORD* srcpixel;
1338     BYTE* dstpixel;
1339     int x,y;
1340
1341     rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1342     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1343     bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1344     for (y=0; y<height; y++) {
1345         srcpixel=srcbits;
1346         dstpixel=dstbits;
1347         for (x=0; x<width; x++) {
1348             DWORD srcval;
1349             srcval=*srcpixel++;
1350             dstpixel[0]=(srcval >> bRightShift); /* b */
1351             dstpixel[1]=(srcval >> gRightShift); /* g */
1352             dstpixel[2]=(srcval >> rRightShift); /* r */
1353             dstpixel+=3;
1354         }
1355         srcbits = (const char*)srcbits + srclinebytes;
1356         dstbits = (char*)dstbits + dstlinebytes;
1357     }
1358 }
1359
1360 static void convert_any0888_to_bgr888(int width, int height,
1361                                       const void* srcbits, int srclinebytes,
1362                                       DWORD rsrc, DWORD gsrc, DWORD bsrc,
1363                                       void* dstbits, int dstlinebytes)
1364 {
1365     int rRightShift,gRightShift,bRightShift;
1366     const DWORD* srcpixel;
1367     BYTE* dstpixel;
1368     int x,y;
1369
1370     rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1371     gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1372     bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1373     for (y=0; y<height; y++) {
1374         srcpixel=srcbits;
1375         dstpixel=dstbits;
1376         for (x=0; x<width; x++) {
1377             DWORD srcval;
1378             srcval=*srcpixel++;
1379             dstpixel[0]=(srcval >> rRightShift); /* r */
1380             dstpixel[1]=(srcval >> gRightShift); /* g */
1381             dstpixel[2]=(srcval >> bRightShift); /* b */
1382             dstpixel+=3;
1383         }
1384         srcbits = (const char*)srcbits + srclinebytes;
1385         dstbits = (char*)dstbits + dstlinebytes;
1386     }
1387 }
1388
1389 const dib_conversions dib_normal = {
1390     convert_5x5_asis,
1391     convert_555_reverse,
1392     convert_555_to_565_asis,
1393     convert_555_to_565_reverse,
1394     convert_555_to_888_asis,
1395     convert_555_to_888_reverse,
1396     convert_555_to_0888_asis,
1397     convert_555_to_0888_reverse,
1398     convert_5x5_to_any0888,
1399     convert_565_reverse,
1400     convert_565_to_555_asis,
1401     convert_565_to_555_reverse,
1402     convert_565_to_888_asis,
1403     convert_565_to_888_reverse,
1404     convert_565_to_0888_asis,
1405     convert_565_to_0888_reverse,
1406     convert_888_asis,
1407     convert_888_reverse,
1408     convert_888_to_555_asis,
1409     convert_888_to_555_reverse,
1410     convert_888_to_565_asis,
1411     convert_888_to_565_reverse,
1412     convert_888_to_0888_asis,
1413     convert_888_to_0888_reverse,
1414     convert_rgb888_to_any0888,
1415     convert_bgr888_to_any0888,
1416     convert_0888_asis,
1417     convert_0888_reverse,
1418     convert_0888_any,
1419     convert_0888_to_555_asis,
1420     convert_0888_to_555_reverse,
1421     convert_0888_to_565_asis,
1422     convert_0888_to_565_reverse,
1423     convert_any0888_to_5x5,
1424     convert_0888_to_888_asis,
1425     convert_0888_to_888_reverse,
1426     convert_any0888_to_rgb888,
1427     convert_any0888_to_bgr888
1428 };