ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_blit.cpp
Revision: 1.7
Committed: 2001-07-06T22:00:39Z (23 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.6: +53 -23 lines
Log Message:
added support for 2/4-bit modes on 8-bit visuals

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.7 /* --- 2/4-bit indexed to 8-bit mode conversion --- */
266     /* -------------------------------------------------------------------------- */
267    
268     static void Blit_Expand_2_To_8(uint8 * dest, const uint8 * p, uint32 length)
269     {
270     uint8 *q = (uint8 *)dest;
271     for (int i=0; i<length; i++) {
272     uint8 c = *p++;
273     *q++ = c >> 6;
274     *q++ = (c >> 4) & 3;
275     *q++ = (c >> 2) & 3;
276     *q++ = c & 3;
277     }
278     }
279    
280     static void Blit_Expand_4_To_8(uint8 * dest, const uint8 * p, uint32 length)
281     {
282     uint8 *q = (uint8 *)dest;
283     for (int i=0; i<length; i++) {
284     uint8 c = *p++;
285     *q++ = c >> 4;
286     *q++ = c & 0x0f;
287     }
288     }
289    
290     /* -------------------------------------------------------------------------- */
291 cebix 1.6 /* --- 2/4/8-bit indexed to 16-bit mode color expansion --- */
292 cebix 1.5 /* -------------------------------------------------------------------------- */
293    
294 cebix 1.6 static void Blit_Expand_2_To_16(uint8 * dest, const uint8 * p, uint32 length)
295     {
296     uint16 *q = (uint16 *)dest;
297     for (int i=0; i<length; i++) {
298     uint8 c = *p++;
299     *q++ = ExpandMap[c >> 6];
300     *q++ = ExpandMap[c >> 4];
301     *q++ = ExpandMap[c >> 2];
302     *q++ = ExpandMap[c];
303     }
304     }
305    
306     static void Blit_Expand_4_To_16(uint8 * dest, const uint8 * p, uint32 length)
307     {
308     uint16 *q = (uint16 *)dest;
309     for (int i=0; i<length; i++) {
310     uint8 c = *p++;
311     *q++ = ExpandMap[c >> 4];
312     *q++ = ExpandMap[c];
313     }
314     }
315    
316 cebix 1.5 static void Blit_Expand_8_To_16(uint8 * dest, const uint8 * p, uint32 length)
317     {
318     uint16 *q = (uint16 *)dest;
319     for (int i=0; i<length; i++)
320     *q++ = ExpandMap[*p++];
321     }
322    
323     /* -------------------------------------------------------------------------- */
324 cebix 1.6 /* --- 2/4/8-bit indexed to 32-bit mode color expansion --- */
325 cebix 1.5 /* -------------------------------------------------------------------------- */
326    
327 cebix 1.6 static void Blit_Expand_2_To_32(uint8 * dest, const uint8 * p, uint32 length)
328     {
329     uint32 *q = (uint32 *)dest;
330     for (int i=0; i<length; i++) {
331     uint8 c = *p++;
332     *q++ = ExpandMap[c >> 6];
333     *q++ = ExpandMap[c >> 4];
334     *q++ = ExpandMap[c >> 2];
335     *q++ = ExpandMap[c];
336     }
337     }
338    
339     static void Blit_Expand_4_To_32(uint8 * dest, const uint8 * p, uint32 length)
340     {
341     uint32 *q = (uint32 *)dest;
342     for (int i=0; i<length; i++) {
343     uint8 c = *p++;
344     *q++ = ExpandMap[c >> 4];
345     *q++ = ExpandMap[c];
346     }
347     }
348    
349 cebix 1.5 static void Blit_Expand_8_To_32(uint8 * dest, const uint8 * p, uint32 length)
350     {
351     uint32 *q = (uint32 *)dest;
352     for (int i=0; i<length; i++)
353     *q++ = ExpandMap[*p++];
354     }
355    
356     /* -------------------------------------------------------------------------- */
357 gbeauche 1.1 /* --- Blitters to the host frame buffer, or XImage buffer --- */
358     /* -------------------------------------------------------------------------- */
359    
360     // Function used to update the hosst frame buffer (DGA), or an XImage buffer (WIN)
361     // --> Shall be initialized only through the Screen_blitter_init() function
362     typedef void (*Screen_blit_func)(uint8 * dest, const uint8 * source, uint32 length);
363     Screen_blit_func Screen_blit = 0;
364    
365     // Structure used to match the adequate framebuffer update function
366     struct Screen_blit_func_info {
367     int depth; // Screen depth
368     uint32 Rmask; // Red mask
369     uint32 Gmask; // Green mask
370     uint32 Bmask; // Blue mask
371     Screen_blit_func handler_nbo; // Update function (native byte order)
372     Screen_blit_func handler_obo; // Update function (opposite byte order)
373     };
374    
375     // Table of visual formats supported and their respective handler
376     static Screen_blit_func_info Screen_blitters[] = {
377     #ifdef WORDS_BIGENDIAN
378     { 1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // NT
379     { 8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // OK (NBO)
380     { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_Copy_Raw , Blit_RGB555_OBO }, // OK (OBO)
381 gbeauche 1.2 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
382 gbeauche 1.1 { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO , Blit_RGB565_OBO }, // OK (OBO)
383     { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK (OBO)
384     { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO }, // NT
385 gbeauche 1.2 { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK
386     { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // OK
387 gbeauche 1.1 #else
388     { 1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // NT
389     { 8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // OK (NBO)
390     { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_RGB555_NBO , Blit_Copy_Raw }, // OK (NBO)
391 gbeauche 1.2 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
392 gbeauche 1.1 { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO , Blit_RGB565_OBO }, // OK (NBO)
393     { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO , Blit_Copy_Raw }, // OK (NBO)
394     { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO }, // NT
395     { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO , Blit_Copy_Raw }, // OK (NBO)
396     { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // NT
397     #endif
398     };
399    
400     // Initialize the framebuffer update function
401     // Returns FALSE, if the function was to be reduced to a simple memcpy()
402     // --> In that case, VOSF is not necessary
403 cebix 1.4 bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth)
404 gbeauche 1.1 {
405 gbeauche 1.3 #if REAL_ADDRESSING || DIRECT_ADDRESSING
406 cebix 1.4 if (mac_depth == VDEPTH_1BIT) {
407    
408     // 1-bit mode uses a 1-bit X image, so there's no need for special blitting routines
409     Screen_blit = Blit_Copy_Raw;
410    
411     } else {
412    
413     visualFormat.depth = visual_info->depth;
414     visualFormat.Rmask = visual_info->red_mask;
415     visualFormat.Gmask = visual_info->green_mask;
416     visualFormat.Bmask = visual_info->blue_mask;
417 cebix 1.5
418 cebix 1.4 // Compute RGB shift values
419     visualFormat.Rshift = 0;
420     for (uint32 Rmask = visualFormat.Rmask; Rmask && ((Rmask & 1) != 1); Rmask >>= 1)
421     ++visualFormat.Rshift;
422     visualFormat.Gshift = 0;
423     for (uint32 Gmask = visualFormat.Gmask; Gmask && ((Gmask & 1) != 1); Gmask >>= 1)
424     ++visualFormat.Gshift;
425     visualFormat.Bshift = 0;
426     for (uint32 Bmask = visualFormat.Bmask; Bmask && ((Bmask & 1) != 1); Bmask >>= 1)
427     ++visualFormat.Bshift;
428 cebix 1.5
429     bool blitter_found = false;
430    
431 cebix 1.7 // 2/4/8-bit mode on 8/16/32-bit screen?
432     if (visualFormat.depth == 8) {
433     if (mac_depth == VDEPTH_2BIT) {
434     Screen_blit = Blit_Expand_2_To_8;
435     blitter_found = true;
436     } else if (mac_depth == VDEPTH_4BIT) {
437     Screen_blit = Blit_Expand_4_To_8;
438     blitter_found = true;
439     }
440     } else if (visualFormat.depth == 15 || visualFormat.depth == 16) {
441     if (mac_depth == VDEPTH_2BIT) {
442     Screen_blit = Blit_Expand_2_To_16;
443     blitter_found = true;
444     } else if (mac_depth == VDEPTH_4BIT) {
445     Screen_blit = Blit_Expand_4_To_16;
446     blitter_found = true;
447     } else if (mac_depth == VDEPTH_8BIT) {
448     Screen_blit = Blit_Expand_8_To_16;
449     blitter_found = true;
450     }
451     } else if (visualFormat.depth == 24 || visualFormat.depth == 32) {
452 cebix 1.6 if (mac_depth == VDEPTH_2BIT) {
453 cebix 1.7 Screen_blit = Blit_Expand_2_To_32;
454     blitter_found = true;
455 cebix 1.6 } else if (mac_depth == VDEPTH_4BIT) {
456 cebix 1.7 Screen_blit = Blit_Expand_4_To_32;
457     blitter_found = true;
458 cebix 1.6 } else if (mac_depth == VDEPTH_8BIT) {
459 cebix 1.7 Screen_blit = Blit_Expand_8_To_32;
460     blitter_found = true;
461 cebix 1.5 }
462     }
463 gbeauche 1.1
464 cebix 1.4 // Search for an adequate blit function
465     const int blitters_count = sizeof(Screen_blitters)/sizeof(Screen_blitters[0]);
466     for (int i = 0; !blitter_found && (i < blitters_count); i++) {
467     if ( (visualFormat.depth == Screen_blitters[i].depth)
468     && (visualFormat.Rmask == Screen_blitters[i].Rmask)
469     && (visualFormat.Gmask == Screen_blitters[i].Gmask)
470     && (visualFormat.Bmask == Screen_blitters[i].Bmask)
471     )
472     {
473     blitter_found = true;
474     Screen_blit = native_byte_order
475     ? Screen_blitters[i].handler_nbo
476     : Screen_blitters[i].handler_obo
477     ;
478     }
479 gbeauche 1.1 }
480    
481 cebix 1.4 // No appropriate blitter found, dump RGB mask values and abort()
482     if (!blitter_found) {
483     fprintf(stderr, "### No appropriate blitter found\n");
484     fprintf(stderr, "\tR/G/B mask values : 0x%06x, 0x%06x, 0x%06x (depth = %d)\n",
485     visualFormat.Rmask, visualFormat.Gmask, visualFormat.Bmask, visualFormat.depth);
486     fprintf(stderr, "\tR/G/B shift values : %d/%d/%d\n",
487     visualFormat.Rshift, visualFormat.Gshift, visualFormat.Bshift);
488     abort();
489     }
490 gbeauche 1.1 }
491 gbeauche 1.3 #else
492     // The UAE memory handlers will blit correctly
493     // --> no need for specialised blitters here
494     Screen_blit = Blit_Copy_Raw;
495     #endif
496 gbeauche 1.1
497     // If the blitter simply reduces to a copy, we don't need VOSF in DGA mode
498     // --> In that case, we return FALSE
499     return (Screen_blit != Blit_Copy_Raw);
500     }
501     #endif /* ENABLE_VOSF */