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