Call TSXFlush after setting DGA palette, so it updates immediately.
[wine] / dlls / ddraw / convert.c
1 #include "ddraw_private.h"
2 #include "debugtools.h"
3
4 DEFAULT_DEBUG_CHANNEL(ddraw);
5
6 /* *************************************
7       16 / 15 bpp to palettized 8 bpp
8    ************************************* */
9 static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
10     unsigned char  *c_src = (unsigned char  *) src;
11     unsigned short *c_dst = (unsigned short *) dst;
12     int y;
13
14     if (palette != NULL) {
15         const unsigned int * pal = (unsigned int *) palette->screen_palents;
16
17         for (y = height; y--; ) {
18 #if defined(__i386__) && defined(__GNUC__)
19             /* gcc generates slightly inefficient code for the the copy/lookup,
20              * it generates one excess memory access (to pal) per pixel. Since
21              * we know that pal is not modified by the memory write we can
22              * put it into a register and reduce the number of memory accesses 
23              * from 4 to 3 pp. There are two xor eax,eax to avoid pipeline
24              * stalls. (This is not guaranteed to be the fastest method.)
25              */
26             __asm__ __volatile__(
27             "xor %%eax,%%eax\n"
28             "1:\n"
29             "    lodsb\n"
30             "    movw (%%edx,%%eax,4),%%ax\n"
31             "    stosw\n"
32             "      xor %%eax,%%eax\n"
33             "    loop 1b\n"
34             : "=S" (c_src), "=D" (c_dst)
35             : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
36             : "eax", "cc", "memory"
37             );
38             c_src+=(pitch-width);
39 #else
40             unsigned char * srclineend = c_src+width;
41             while (c_src < srclineend)
42                 *c_dst++ = pal[*c_src++];
43             c_src+=(pitch-width);
44 #endif
45         }
46     } else {
47         WARN("No palette set...\n");
48         memset(dst, 0, width * height * 2);
49     }
50 }
51 static void palette_convert_16_to_8(
52         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
53 ) {
54     int i;
55     unsigned int *pal = (unsigned int *) screen_palette;
56
57     for (i = 0; i < count; i++)
58         pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
59                           ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
60                           ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
61 }
62
63 static void palette_convert_15_to_8(
64         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
65 ) {
66     int i;
67     unsigned int *pal = (unsigned int *) screen_palette;
68
69     for (i = 0; i < count; i++)
70         pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) |
71                           ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
72                           ((((unsigned short) palent[i].peGreen) & 0xF8) << 2));
73 }
74
75 /* *************************************
76       24 to palettized 8 bpp
77    ************************************* */
78 static void pixel_convert_24_to_8(
79         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
80         IDirectDrawPaletteImpl* palette
81 ) {
82     unsigned char  *c_src = (unsigned char  *) src;
83     unsigned char *c_dst = (unsigned char *) dst;
84     int y;
85
86     if (palette != NULL) {
87         const unsigned int *pal = (unsigned int *) palette->screen_palents;
88
89         for (y = height; y--; ) {
90             unsigned char * srclineend = c_src+width;
91             while (c_src < srclineend ) {
92                 register long pixel = pal[*c_src++];
93                 *c_dst++ = pixel;
94                 *c_dst++ = pixel>>8;
95                 *c_dst++ = pixel>>16;
96             }
97             c_src+=(pitch-width);
98         }
99     } else {
100         WARN("No palette set...\n");
101         memset(dst, 0, width * height * 4);
102     }
103 }
104
105 /* *************************************
106       32 bpp to palettized 8 bpp
107    ************************************* */
108 static void pixel_convert_32_to_8(
109         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
110         IDirectDrawPaletteImpl* palette
111 ) {
112     unsigned char  *c_src = (unsigned char  *) src;
113     unsigned int *c_dst = (unsigned int *) dst;
114     int y;
115
116     if (palette != NULL) {
117         const unsigned int *pal = (unsigned int *) palette->screen_palents;
118
119         for (y = height; y--; ) {
120 #if defined(__i386__) && defined(__GNUC__)
121             /* See comment in pixel_convert_16_to_8 */
122             __asm__ __volatile__(
123             "xor %%eax,%%eax\n"
124             "1:\n"
125             "    lodsb\n"
126             "    movl (%%edx,%%eax,4),%%eax\n"
127             "    stosl\n"
128             "      xor %%eax,%%eax\n"
129             "    loop 1b\n"
130             : "=S" (c_src), "=D" (c_dst)
131             : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
132             : "eax", "cc", "memory"
133             );
134             c_src+=(pitch-width);
135 #else
136             unsigned char * srclineend = c_src+width;
137             while (c_src < srclineend )
138                 *c_dst++ = pal[*c_src++];
139             c_src+=(pitch-width);
140 #endif
141         }
142     } else {
143         WARN("No palette set...\n");
144         memset(dst, 0, width * height * 4);
145     }
146 }
147
148 static void palette_convert_24_to_8(
149         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
150 ) {
151     int i;
152     unsigned int *pal = (unsigned int *) screen_palette;
153   
154     for (i = 0; i < count; i++)
155         pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) |
156                           (((unsigned int) palent[i].peGreen) << 8) |
157                            ((unsigned int) palent[i].peBlue));
158 }
159
160 /* *************************************
161       32 bpp to 16 bpp
162    ************************************* */
163 static void pixel_convert_32_to_16(
164         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
165         IDirectDrawPaletteImpl* palette
166 ) {
167     unsigned short *c_src = (unsigned short *) src;
168     unsigned int *c_dst = (unsigned int *) dst;
169     int y;
170
171     for (y = height; y--; ) {
172         unsigned short * srclineend = c_src+width;
173         while (c_src < srclineend ) {
174             *c_dst++ = (((*c_src & 0xF800) << 8) |
175                         ((*c_src & 0x07E0) << 5) |
176                         ((*c_src & 0x001F) << 3));
177             c_src++;
178         }
179         c_src+=((pitch/2)-width);
180     }
181 }
182
183 Convert ModeEmulations[5] = {
184   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_32_to_8,  palette_convert_24_to_8 } },
185   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  16, 16, 0xF800, 0x07E0, 0x001F }, { pixel_convert_32_to_16, NULL } },
186   { { 24, 24,   0xFF0000,   0x00FF00,   0x0000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_24_to_8,  palette_convert_24_to_8 } },
187   { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_16_to_8 } },
188   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_15_to_8 } },
189 };