Added LGPL standard comment, and copyright notices where necessary.
[wine] / dlls / ddraw / convert.c
1 /*
2  * Copyright 2000 Marcus Meissner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <string.h>
20 #include "ddraw_private.h"
21 #include "wine/debug.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
24
25 /* *************************************
26       16 / 15 bpp to palettized 8 bpp
27    ************************************* */
28 static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
29     unsigned char  *c_src = (unsigned char  *) src;
30     unsigned short *c_dst = (unsigned short *) dst;
31     int y;
32
33     if (palette != NULL) {
34         const unsigned int * pal = (unsigned int *) palette->screen_palents;
35
36         for (y = height; y--; ) {
37 #if defined(__i386__) && defined(__GNUC__)
38             /* gcc generates slightly inefficient code for the the copy/lookup,
39              * it generates one excess memory access (to pal) per pixel. Since
40              * we know that pal is not modified by the memory write we can
41              * put it into a register and reduce the number of memory accesses 
42              * from 4 to 3 pp. There are two xor eax,eax to avoid pipeline
43              * stalls. (This is not guaranteed to be the fastest method.)
44              */
45             __asm__ __volatile__(
46             "xor %%eax,%%eax\n"
47             "1:\n"
48             "    lodsb\n"
49             "    movw (%%edx,%%eax,4),%%ax\n"
50             "    stosw\n"
51             "      xor %%eax,%%eax\n"
52             "    loop 1b\n"
53             : "=S" (c_src), "=D" (c_dst)
54             : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
55             : "eax", "cc", "memory"
56             );
57             c_src+=(pitch-width);
58 #else
59             unsigned char * srclineend = c_src+width;
60             while (c_src < srclineend)
61                 *c_dst++ = pal[*c_src++];
62             c_src+=(pitch-width);
63 #endif
64         }
65     } else {
66         FIXME("No palette set...\n");
67         memset(dst, 0, width * height * 2);
68     }
69 }
70 static void palette_convert_16_to_8(
71         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
72 ) {
73     int i;
74     unsigned int *pal = (unsigned int *) screen_palette;
75
76     for (i = 0; i < count; i++)
77         pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
78                           ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
79                           ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
80 }
81
82 static void palette_convert_15_to_8(
83         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
84 ) {
85     int i;
86     unsigned int *pal = (unsigned int *) screen_palette;
87
88     for (i = 0; i < count; i++)
89         pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) |
90                           ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
91                           ((((unsigned short) palent[i].peGreen) & 0xF8) << 2));
92 }
93
94 /* *************************************
95       24 to palettized 8 bpp
96    ************************************* */
97 static void pixel_convert_24_to_8(
98         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
99         IDirectDrawPaletteImpl* palette
100 ) {
101     unsigned char  *c_src = (unsigned char  *) src;
102     unsigned char *c_dst = (unsigned char *) dst;
103     int y;
104
105     if (palette != NULL) {
106         const unsigned int *pal = (unsigned int *) palette->screen_palents;
107
108         for (y = height; y--; ) {
109             unsigned char * srclineend = c_src+width;
110             while (c_src < srclineend ) {
111                 register long pixel = pal[*c_src++];
112                 *c_dst++ = pixel;
113                 *c_dst++ = pixel>>8;
114                 *c_dst++ = pixel>>16;
115             }
116             c_src+=(pitch-width);
117         }
118     } else {
119         FIXME("No palette set...\n");
120         memset(dst, 0, width * height * 3);
121     }
122 }
123
124 /* *************************************
125       32 bpp to palettized 8 bpp
126    ************************************* */
127 static void pixel_convert_32_to_8(
128         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
129         IDirectDrawPaletteImpl* palette
130 ) {
131     unsigned char  *c_src = (unsigned char  *) src;
132     unsigned int *c_dst = (unsigned int *) dst;
133     int y;
134
135     if (palette != NULL) {
136         const unsigned int *pal = (unsigned int *) palette->screen_palents;
137
138         for (y = height; y--; ) {
139 #if defined(__i386__) && defined(__GNUC__)
140             /* See comment in pixel_convert_16_to_8 */
141             __asm__ __volatile__(
142             "xor %%eax,%%eax\n"
143             "1:\n"
144             "    lodsb\n"
145             "    movl (%%edx,%%eax,4),%%eax\n"
146             "    stosl\n"
147             "      xor %%eax,%%eax\n"
148             "    loop 1b\n"
149             : "=S" (c_src), "=D" (c_dst)
150             : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
151             : "eax", "cc", "memory"
152             );
153             c_src+=(pitch-width);
154 #else
155             unsigned char * srclineend = c_src+width;
156             while (c_src < srclineend )
157                 *c_dst++ = pal[*c_src++];
158             c_src+=(pitch-width);
159 #endif
160         }
161     } else {
162         FIXME("No palette set...\n");
163         memset(dst, 0, width * height * 4);
164     }
165 }
166
167 static void palette_convert_24_to_8(
168         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
169 ) {
170     int i;
171     unsigned int *pal = (unsigned int *) screen_palette;
172
173     for (i = 0; i < count; i++)
174         pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) |
175                           (((unsigned int) palent[i].peGreen) << 8) |
176                            ((unsigned int) palent[i].peBlue));
177 }
178
179 /* *************************************
180       16 bpp to 15 bpp
181    ************************************* */
182 static void pixel_convert_15_to_16(
183         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
184         IDirectDrawPaletteImpl* palette
185 ) {
186     unsigned short *c_src = (unsigned short *) src;
187     unsigned short *c_dst = (unsigned short *) dst;
188     int y;
189
190     for (y = height; y--; ) {
191         unsigned short * srclineend = c_src+width;
192         while (c_src < srclineend ) {
193             unsigned short val = *c_src++;
194             *c_dst++=((val&0xFFC0)>>1)|(val&0x001f);
195         }
196         c_src+=((pitch/2)-width);
197     }
198 }
199
200 /* *************************************
201       32 bpp to 16 bpp
202    ************************************* */
203 static void pixel_convert_32_to_16(
204         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
205         IDirectDrawPaletteImpl* palette
206 ) {
207     unsigned short *c_src = (unsigned short *) src;
208     unsigned int *c_dst = (unsigned int *) dst;
209     int y;
210
211     for (y = height; y--; ) {
212         unsigned short * srclineend = c_src+width;
213         while (c_src < srclineend ) {
214             *c_dst++ = (((*c_src & 0xF800) << 8) |
215                         ((*c_src & 0x07E0) << 5) |
216                         ((*c_src & 0x001F) << 3));
217             c_src++;
218         }
219         c_src+=((pitch/2)-width);
220     }
221 }
222
223 /* *************************************
224       32 bpp to 24 bpp
225    ************************************* */
226 static void pixel_convert_32_to_24(
227         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
228         IDirectDrawPaletteImpl* palette
229 ) {
230     unsigned char *c_src = (unsigned char *) src;
231     unsigned int *c_dst = (unsigned int *) dst;
232     int y;
233
234     for (y = height; y--; ) {
235         unsigned char * srclineend = c_src+width*3;
236         while (c_src < srclineend ) {
237             /* FIXME: wrong for big endian */
238             memcpy(c_dst,c_src,3);
239             c_src+=3;
240             c_dst++;
241         }
242         c_src+=pitch-width*3;
243     }
244 }
245
246 /* *************************************
247       16 bpp to 32 bpp
248    ************************************* */
249 static void pixel_convert_16_to_32(
250         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
251         IDirectDrawPaletteImpl* palette
252 ) {
253     unsigned int *c_src = (unsigned int *) src;
254     unsigned short *c_dst = (unsigned short *) dst;
255     int y;
256
257     for (y = height; y--; ) {
258         unsigned int * srclineend = c_src+width;
259         while (c_src < srclineend ) {
260             *c_dst++ = (((*c_src & 0xF80000) >> 8) |
261                         ((*c_src & 0x00FC00) >> 5) |
262                         ((*c_src & 0x0000F8) >> 3));
263             c_src++;
264         }
265         c_src+=((pitch/4)-width);
266     }
267 }
268
269 Convert ModeEmulations[8] = {
270   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  24, 24, 0xFF0000, 0x00FF00, 0x0000FF }, { pixel_convert_32_to_24, NULL } },
271   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  16, 16, 0xF800, 0x07E0, 0x001F }, { pixel_convert_32_to_16, NULL } },
272   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_32_to_8,  palette_convert_24_to_8 } },
273   { { 24, 24,   0xFF0000,   0x00FF00,   0x0000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_24_to_8,  palette_convert_24_to_8 } },
274   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  16,16, 0xf800, 0x07e0, 0x001f }, { pixel_convert_15_to_16,  NULL } },
275   { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_16_to_8 } },
276   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_15_to_8 } },
277   { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { pixel_convert_16_to_32, NULL } }
278 };