ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_blit.cpp
Revision: 1.6
Committed: 2001-07-01T21:09:29Z (23 years, 5 months ago) by cebix
Branch: MAIN
Changes since 1.5: +72 -10 lines
Log Message:
- video_set_palette() gets passed the number of used palette entries
- video_x.cpp supports 2- and 4-bit modes on truecolor screens

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * video_blit.cpp - Video/graphics emulation, blitters
3     *
4     * Basilisk II (C) 1997-2001 Christian Bauer
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22 cebix 1.4 #include "video.h"
23 gbeauche 1.1
24     #include <stdio.h>
25     #include <stdlib.h>
26     #include <X11/Xlib.h>
27     #include <X11/Xutil.h>
28    
29     #ifdef ENABLE_VOSF
30     // Format of the target visual
31     struct VisualFormat {
32     int depth; // Screen depth
33     uint32 Rmask, Gmask, Bmask; // RGB mask values
34     uint32 Rshift, Gshift, Bshift; // RGB shift values
35     };
36     static VisualFormat visualFormat;
37    
38 cebix 1.5 // This holds the pixels values of the palette colors for 8->16/32-bit expansion
39     uint32 ExpandMap[256];
40    
41 gbeauche 1.1 /* -------------------------------------------------------------------------- */
42     /* --- Raw Copy / No conversion required --- */
43     /* -------------------------------------------------------------------------- */
44    
45     static void Blit_Copy_Raw(uint8 * dest, const uint8 * source, uint32 length)
46     {
47     // This function is likely to be inlined and/or highly optimized
48     memcpy(dest, source, length);
49     }
50    
51     /* -------------------------------------------------------------------------- */
52     /* --- RGB 555 --- */
53     /* -------------------------------------------------------------------------- */
54    
55     #ifdef WORDS_BIGENDIAN
56     # define FB_FUNC_NAME Blit_RGB555_OBO
57     #else
58     # define FB_FUNC_NAME Blit_RGB555_NBO
59     #endif
60    
61     #define FB_BLIT_1(dst, src) \
62     (dst = (((src) >> 8) & 0xff) | (((src) & 0xff) << 8))
63    
64     #define FB_BLIT_2(dst, src) \
65     (dst = (((src) >> 8) & 0x00ff00ff) | (((src) & 0x00ff00ff) << 8))
66    
67     #define FB_DEPTH 15
68     #include "video_blit.h"
69    
70     /* -------------------------------------------------------------------------- */
71     /* --- BGR 555 --- */
72     /* -------------------------------------------------------------------------- */
73    
74 gbeauche 1.2 #ifdef WORDS_BIGENDIAN
75    
76     // Native byte order
77    
78     #define FB_BLIT_1(dst, src) \
79     (dst = (((src) >> 10) & 0x001f) | ((src) & 0x03e0) | (((src) << 10) & 0x7c00))
80    
81     #define FB_BLIT_2(dst, src) \
82     (dst = (((src) >> 10) & 0x001f001f) | ((src) & 0x03e003e0) | (((src) << 10) & 0x7c007c00))
83    
84     #define FB_DEPTH 15
85     #define FB_FUNC_NAME Blit_BGR555_NBO
86     #include "video_blit.h"
87    
88     // Opposite byte order (untested)
89    
90     #define FB_BLIT_1(dst, src) \
91     (dst = (((src) >> 2) & 0x1f00) | (((src) >> 8) & 3) | (((src) << 8) & 0xe000) | (((src) << 2) & 0x7c))
92    
93     #define FB_BLIT_2(dst, src) \
94     (dst = (((src) >> 2) & 0x1f001f00) | (((src) >> 8) & 0x30003) | (((src) << 8) & 0xe000e000) | (((src) << 2) & 0x7c007c))
95    
96     #define FB_DEPTH 15
97     #define FB_FUNC_NAME Blit_BGR555_OBO
98     #include "video_blit.h"
99    
100     #else
101    
102     // Native byte order (untested)
103    
104     #define FB_BLIT_1(dst, src) \
105     (dst = (((src) >> 2) & 0x1f) | (((src) >> 8) & 0xe0) | (((src) << 8) & 0x0300) | (((src) << 2) & 0x7c00))
106    
107     #define FB_BLIT_2(dst, src) \
108     (dst = (((src) >> 2) & 0x1f001f) | (((src) >> 8) & 0xe000e0) | (((src) << 8) & 0x03000300) | (((src) << 2) & 0x7c007c00))
109    
110     #define FB_DEPTH 15
111     #define FB_FUNC_NAME Blit_BGR555_NBO
112     #include "video_blit.h"
113    
114     // Opposite byte order (untested)
115    
116     #define FB_BLIT_1(dst, src) \
117     (dst = (((src) << 6) & 0x1f00) | ((src) & 0xe003) | (((src) >> 6) & 0x7c))
118    
119     #define FB_BLIT_2(dst, src) \
120     (dst = (((src) << 6) & 0x1f001f00) | ((src) & 0xe003e003) | (((src) >> 6) & 0x7c007c))
121    
122     #define FB_DEPTH 15
123     #define FB_FUNC_NAME Blit_BGR555_OBO
124     #include "video_blit.h"
125    
126     #endif
127 gbeauche 1.1
128     /* -------------------------------------------------------------------------- */
129     /* --- RGB 565 --- */
130     /* -------------------------------------------------------------------------- */
131    
132     #ifdef WORDS_BIGENDIAN
133    
134     // Native byte order
135    
136     #define FB_BLIT_1(dst, src) \
137     (dst = (((src) & 0x1f) | (((src) << 1) & 0xffc0)))
138    
139     #define FB_BLIT_2(dst, src) \
140     (dst = (((src) & 0x001f001f) | (((src) << 1) & 0xffc0ffc0)))
141    
142     #define FB_DEPTH 16
143     #define FB_FUNC_NAME Blit_RGB565_NBO
144     #include "video_blit.h"
145    
146     // Opposite byte order
147    
148     #define FB_BLIT_1(dst, src) \
149     (dst = ((((src) >> 7) & 0xff) | (((src) << 9) & 0xc000) | (((src) << 8) & 0x1f00)))
150    
151     #define FB_BLIT_2(dst, src) \
152     (dst = ((((src) >> 7) & 0x00ff00ff) | (((src) << 9) & 0xc000c000) | (((src) << 8) & 0x1f001f00)))
153    
154     #define FB_DEPTH 16
155     #define FB_FUNC_NAME Blit_RGB565_OBO
156     #include "video_blit.h"
157    
158     #else
159    
160     // Native byte order
161    
162     #define FB_BLIT_1(dst, src) \
163     (dst = (((src) >> 8) & 0x001f) | (((src) << 9) & 0xfe00) | (((src) >> 7) & 0x01c0))
164    
165     // gb-- Disabled because I don't see any improvement
166     #if 0 && defined(__i386__) && defined(X86_ASSEMBLY)
167    
168     #define FB_BLIT_2(dst, src) \
169     __asm__ ( "movl %0,%%ebx\n\t" \
170     "movl %0,%%ebp\n\t" \
171     "andl $0x1f001f00,%%ebx\n\t" \
172     "andl $0x007f007f,%0\n\t" \
173     "andl $0xe000e000,%%ebp\n\t" \
174     "shrl $8,%%ebx\n\t" \
175     "shrl $7,%%ebp\n\t" \
176     "shll $9,%0\n\t" \
177     "orl %%ebx,%%ebp\n\t" \
178     "orl %%ebp,%0\n\t" \
179     : "=r" (dst) : "0" (src) : "ebx", "ebp", "cc" )
180    
181     #else
182    
183     #define FB_BLIT_2(dst, src) \
184     (dst = (((src) >> 8) & 0x001f001f) | (((src) << 9) & 0xfe00fe00) | (((src) >> 7) & 0x01c001c0))
185    
186     #endif
187    
188     #define FB_DEPTH 16
189     #define FB_FUNC_NAME Blit_RGB565_NBO
190     #include "video_blit.h"
191    
192     // Opposite byte order (untested)
193    
194     #define FB_BLIT_1(dst, src) \
195     (dst = (((src) & 0x1f00) | (((src) << 1) & 0xe0fe) | (((src) >> 15) & 1)))
196    
197     #define FB_BLIT_2(dst, src) \
198     (dst = (((src) & 0x1f001f00) | (((src) << 1) & 0xe0fee0fe) | (((src) >> 15) & 0x10001)))
199    
200     #define FB_DEPTH 16
201     #define FB_FUNC_NAME Blit_RGB565_OBO
202     #include "video_blit.h"
203    
204     #endif
205    
206     /* -------------------------------------------------------------------------- */
207     /* --- RGB 888 --- */
208     /* -------------------------------------------------------------------------- */
209    
210     #ifdef WORDS_BIGENDIAN
211     # define FB_FUNC_NAME Blit_RGB888_OBO
212     #else
213     # define FB_FUNC_NAME Blit_RGB888_NBO
214     #endif
215    
216     #define FB_BLIT_2(dst, src) \
217     (dst = (((src) >> 24) & 0xff) | (((src) >> 8) & 0xff00) | (((src) & 0xff00) << 8) | (((src) & 0xff) << 24))
218    
219     #define FB_DEPTH 24
220     #include "video_blit.h"
221    
222     /* -------------------------------------------------------------------------- */
223     /* --- BGR 888 --- */
224     /* -------------------------------------------------------------------------- */
225    
226 gbeauche 1.2 // Native byte order [BE] (untested)
227 gbeauche 1.1
228     #ifdef WORDS_BIGENDIAN
229    
230     #define FB_BLIT_2(dst, src) \
231     (dst = (((src) >> 16) & 0xff) | ((src) & 0xff00) | (((src) & 0xff) << 16))
232    
233     #define FB_FUNC_NAME Blit_BGR888_NBO
234     #define FB_DEPTH 24
235     #include "video_blit.h"
236    
237     #else
238    
239 gbeauche 1.2 // Opposite byte order [LE] (untested)
240    
241 gbeauche 1.1 #define FB_BLIT_2(dst, src) \
242     (dst = (((src) >> 16) & 0xff) | ((src) & 0xff0000) | (((src) & 0xff) << 16))
243    
244     #define FB_FUNC_NAME Blit_BGR888_OBO
245     #define FB_DEPTH 24
246     #include "video_blit.h"
247    
248     #endif
249    
250 gbeauche 1.2 // Opposite byte order [BE] (untested) / Native byte order [LE] (untested)
251 gbeauche 1.1
252     #ifdef WORDS_BIGENDIAN
253     # define FB_FUNC_NAME Blit_BGR888_OBO
254     #else
255     # define FB_FUNC_NAME Blit_BGR888_NBO
256     #endif
257    
258     #define FB_BLIT_2(dst, src) \
259     (dst = ((src) & 0xff00ff) | (((src) & 0xff00) << 16))
260    
261     #define FB_DEPTH 24
262     #include "video_blit.h"
263    
264     /* -------------------------------------------------------------------------- */
265 cebix 1.6 /* --- 2/4/8-bit indexed to 16-bit mode color expansion --- */
266 cebix 1.5 /* -------------------------------------------------------------------------- */
267    
268 cebix 1.6 static void Blit_Expand_2_To_16(uint8 * dest, const uint8 * p, uint32 length)
269     {
270     uint16 *q = (uint16 *)dest;
271     for (int i=0; i<length; i++) {
272     uint8 c = *p++;
273     *q++ = ExpandMap[c >> 6];
274     *q++ = ExpandMap[c >> 4];
275     *q++ = ExpandMap[c >> 2];
276     *q++ = ExpandMap[c];
277     }
278     }
279    
280     static void Blit_Expand_4_To_16(uint8 * dest, const uint8 * p, uint32 length)
281     {
282     uint16 *q = (uint16 *)dest;
283     for (int i=0; i<length; i++) {
284     uint8 c = *p++;
285     *q++ = ExpandMap[c >> 4];
286     *q++ = ExpandMap[c];
287     }
288     }
289    
290 cebix 1.5 static void Blit_Expand_8_To_16(uint8 * dest, const uint8 * p, uint32 length)
291     {
292     uint16 *q = (uint16 *)dest;
293     for (int i=0; i<length; i++)
294     *q++ = ExpandMap[*p++];
295     }
296    
297     /* -------------------------------------------------------------------------- */
298 cebix 1.6 /* --- 2/4/8-bit indexed to 32-bit mode color expansion --- */
299 cebix 1.5 /* -------------------------------------------------------------------------- */
300    
301 cebix 1.6 static void Blit_Expand_2_To_32(uint8 * dest, const uint8 * p, uint32 length)
302     {
303     uint32 *q = (uint32 *)dest;
304     for (int i=0; i<length; i++) {
305     uint8 c = *p++;
306     *q++ = ExpandMap[c >> 6];
307     *q++ = ExpandMap[c >> 4];
308     *q++ = ExpandMap[c >> 2];
309     *q++ = ExpandMap[c];
310     }
311     }
312    
313     static void Blit_Expand_4_To_32(uint8 * dest, const uint8 * p, uint32 length)
314     {
315     uint32 *q = (uint32 *)dest;
316     for (int i=0; i<length; i++) {
317     uint8 c = *p++;
318     *q++ = ExpandMap[c >> 4];
319     *q++ = ExpandMap[c];
320     }
321     }
322    
323 cebix 1.5 static void Blit_Expand_8_To_32(uint8 * dest, const uint8 * p, uint32 length)
324     {
325     uint32 *q = (uint32 *)dest;
326     for (int i=0; i<length; i++)
327     *q++ = ExpandMap[*p++];
328     }
329    
330     /* -------------------------------------------------------------------------- */
331 gbeauche 1.1 /* --- Blitters to the host frame buffer, or XImage buffer --- */
332     /* -------------------------------------------------------------------------- */
333    
334     // Function used to update the hosst frame buffer (DGA), or an XImage buffer (WIN)
335     // --> Shall be initialized only through the Screen_blitter_init() function
336     typedef void (*Screen_blit_func)(uint8 * dest, const uint8 * source, uint32 length);
337     Screen_blit_func Screen_blit = 0;
338    
339     // Structure used to match the adequate framebuffer update function
340     struct Screen_blit_func_info {
341     int depth; // Screen depth
342     uint32 Rmask; // Red mask
343     uint32 Gmask; // Green mask
344     uint32 Bmask; // Blue mask
345     Screen_blit_func handler_nbo; // Update function (native byte order)
346     Screen_blit_func handler_obo; // Update function (opposite byte order)
347     };
348    
349     // Table of visual formats supported and their respective handler
350     static Screen_blit_func_info Screen_blitters[] = {
351     #ifdef WORDS_BIGENDIAN
352     { 1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // NT
353     { 8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // OK (NBO)
354     { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_Copy_Raw , Blit_RGB555_OBO }, // OK (OBO)
355 gbeauche 1.2 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
356 gbeauche 1.1 { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO , Blit_RGB565_OBO }, // OK (OBO)
357     { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK (OBO)
358     { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO }, // NT
359 gbeauche 1.2 { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK
360     { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // OK
361 gbeauche 1.1 #else
362     { 1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // NT
363     { 8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // OK (NBO)
364     { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_RGB555_NBO , Blit_Copy_Raw }, // OK (NBO)
365 gbeauche 1.2 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
366 gbeauche 1.1 { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO , Blit_RGB565_OBO }, // OK (NBO)
367     { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO , Blit_Copy_Raw }, // OK (NBO)
368     { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO }, // NT
369     { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO , Blit_Copy_Raw }, // OK (NBO)
370     { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // NT
371     #endif
372     };
373    
374     // Initialize the framebuffer update function
375     // Returns FALSE, if the function was to be reduced to a simple memcpy()
376     // --> In that case, VOSF is not necessary
377 cebix 1.4 bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth)
378 gbeauche 1.1 {
379 gbeauche 1.3 #if REAL_ADDRESSING || DIRECT_ADDRESSING
380 cebix 1.4 if (mac_depth == VDEPTH_1BIT) {
381    
382     // 1-bit mode uses a 1-bit X image, so there's no need for special blitting routines
383     Screen_blit = Blit_Copy_Raw;
384    
385     } else {
386    
387     visualFormat.depth = visual_info->depth;
388     visualFormat.Rmask = visual_info->red_mask;
389     visualFormat.Gmask = visual_info->green_mask;
390     visualFormat.Bmask = visual_info->blue_mask;
391 cebix 1.5
392 cebix 1.4 // Compute RGB shift values
393     visualFormat.Rshift = 0;
394     for (uint32 Rmask = visualFormat.Rmask; Rmask && ((Rmask & 1) != 1); Rmask >>= 1)
395     ++visualFormat.Rshift;
396     visualFormat.Gshift = 0;
397     for (uint32 Gmask = visualFormat.Gmask; Gmask && ((Gmask & 1) != 1); Gmask >>= 1)
398     ++visualFormat.Gshift;
399     visualFormat.Bshift = 0;
400     for (uint32 Bmask = visualFormat.Bmask; Bmask && ((Bmask & 1) != 1); Bmask >>= 1)
401     ++visualFormat.Bshift;
402 cebix 1.5
403     bool blitter_found = false;
404    
405 cebix 1.6 // 2/4/8-bit mode on 16/32-bit screen?
406     if (visualFormat.depth > 8) {
407     if (mac_depth == VDEPTH_2BIT) {
408     if (visual_info->depth <= 16) {
409     Screen_blit = Blit_Expand_2_To_16;
410     blitter_found = true;
411     } else {
412     Screen_blit = Blit_Expand_2_To_32;
413     blitter_found = true;
414     }
415     } else if (mac_depth == VDEPTH_4BIT) {
416     if (visual_info->depth <= 16) {
417     Screen_blit = Blit_Expand_4_To_16;
418     blitter_found = true;
419     } else {
420     Screen_blit = Blit_Expand_4_To_32;
421     blitter_found = true;
422     }
423     } else if (mac_depth == VDEPTH_8BIT) {
424     if (visual_info->depth <= 16) {
425     Screen_blit = Blit_Expand_8_To_16;
426     blitter_found = true;
427     } else {
428     Screen_blit = Blit_Expand_8_To_32;
429     blitter_found = true;
430     }
431 cebix 1.5 }
432     }
433 gbeauche 1.1
434 cebix 1.4 // Search for an adequate blit function
435     const int blitters_count = sizeof(Screen_blitters)/sizeof(Screen_blitters[0]);
436     for (int i = 0; !blitter_found && (i < blitters_count); i++) {
437     if ( (visualFormat.depth == Screen_blitters[i].depth)
438     && (visualFormat.Rmask == Screen_blitters[i].Rmask)
439     && (visualFormat.Gmask == Screen_blitters[i].Gmask)
440     && (visualFormat.Bmask == Screen_blitters[i].Bmask)
441     )
442     {
443     blitter_found = true;
444     Screen_blit = native_byte_order
445     ? Screen_blitters[i].handler_nbo
446     : Screen_blitters[i].handler_obo
447     ;
448     }
449 gbeauche 1.1 }
450    
451 cebix 1.4 // No appropriate blitter found, dump RGB mask values and abort()
452     if (!blitter_found) {
453     fprintf(stderr, "### No appropriate blitter found\n");
454     fprintf(stderr, "\tR/G/B mask values : 0x%06x, 0x%06x, 0x%06x (depth = %d)\n",
455     visualFormat.Rmask, visualFormat.Gmask, visualFormat.Bmask, visualFormat.depth);
456     fprintf(stderr, "\tR/G/B shift values : %d/%d/%d\n",
457     visualFormat.Rshift, visualFormat.Gshift, visualFormat.Bshift);
458     abort();
459     }
460 gbeauche 1.1 }
461 gbeauche 1.3 #else
462     // The UAE memory handlers will blit correctly
463     // --> no need for specialised blitters here
464     Screen_blit = Blit_Copy_Raw;
465     #endif
466 gbeauche 1.1
467     // If the blitter simply reduces to a copy, we don't need VOSF in DGA mode
468     // --> In that case, we return FALSE
469     return (Screen_blit != Blit_Copy_Raw);
470     }
471     #endif /* ENABLE_VOSF */