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 (22 years, 11 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

# Content
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 #include "video.h"
23
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 // This holds the pixels values of the palette colors for 8->16/32-bit expansion
39 uint32 ExpandMap[256];
40
41 /* -------------------------------------------------------------------------- */
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 #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
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 // Native byte order [BE] (untested)
227
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 // Opposite byte order [LE] (untested)
240
241 #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 // Opposite byte order [BE] (untested) / Native byte order [LE] (untested)
251
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 /* --- 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 /* --- 2/4/8-bit indexed to 16-bit mode color expansion --- */
292 /* -------------------------------------------------------------------------- */
293
294 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 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 /* --- 2/4/8-bit indexed to 32-bit mode color expansion --- */
325 /* -------------------------------------------------------------------------- */
326
327 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 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 /* --- 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 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
382 { 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 { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK
386 { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // OK
387 #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 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
392 { 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 bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth)
404 {
405 #if REAL_ADDRESSING || DIRECT_ADDRESSING
406 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
418 // 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
429 bool blitter_found = false;
430
431 // 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 if (mac_depth == VDEPTH_2BIT) {
453 Screen_blit = Blit_Expand_2_To_32;
454 blitter_found = true;
455 } else if (mac_depth == VDEPTH_4BIT) {
456 Screen_blit = Blit_Expand_4_To_32;
457 blitter_found = true;
458 } else if (mac_depth == VDEPTH_8BIT) {
459 Screen_blit = Blit_Expand_8_To_32;
460 blitter_found = true;
461 }
462 }
463
464 // 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 }
480
481 // 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 }
491 #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
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 */