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 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

# 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/8-bit indexed to 16-bit mode color expansion --- */
266 /* -------------------------------------------------------------------------- */
267
268 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 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 /* --- 2/4/8-bit indexed to 32-bit mode color expansion --- */
299 /* -------------------------------------------------------------------------- */
300
301 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 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 /* --- 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 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
356 { 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 { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK
360 { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // OK
361 #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 { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO , Blit_BGR555_OBO }, // NT
366 { 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 bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth)
378 {
379 #if REAL_ADDRESSING || DIRECT_ADDRESSING
380 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
392 // 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
403 bool blitter_found = false;
404
405 // 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 }
432 }
433
434 // 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 }
450
451 // 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 }
461 #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
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 */