From e94d644b191e214ae5f9ee01ec1da39adc1783df Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 28 Jan 2001 14:05:19 +0000 Subject: [PATCH] Mainly changes to the VOSF code: - improved blitters selection - improved blitters performance if UNALIGNED_PROFITABLE is set - cleaned up 8 bpp blitters --- BasiliskII/src/Unix/Makefile.in | 4 +- BasiliskII/src/Unix/video_blit.cpp | 302 +++++++++++++++++++++++++++++ BasiliskII/src/Unix/video_blit.h | 81 ++++---- BasiliskII/src/Unix/video_vosf.h | 211 ++------------------ BasiliskII/src/Unix/video_x.cpp | 53 ++--- 5 files changed, 383 insertions(+), 268 deletions(-) create mode 100644 BasiliskII/src/Unix/video_blit.cpp diff --git a/BasiliskII/src/Unix/Makefile.in b/BasiliskII/src/Unix/Makefile.in index 0fb8b872..90fad151 100644 --- a/BasiliskII/src/Unix/Makefile.in +++ b/BasiliskII/src/Unix/Makefile.in @@ -32,8 +32,8 @@ SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp sys_unix.cpp ../rom_patches.cpp ../slot_rom.cpp ../rsrc_patches.cpp \ ../emul_op.cpp ../macos_util.cpp ../xpram.cpp xpram_unix.cpp ../timer.cpp \ timer_unix.cpp clip_unix.cpp ../adb.cpp ../serial.cpp ../ether.cpp \ - ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp video_x.cpp \ - ../audio.cpp ../extfs.cpp extfs_unix.cpp ../user_strings.cpp \ + ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp video_blit.cpp \ + video_x.cpp ../audio.cpp ../extfs.cpp extfs_unix.cpp ../user_strings.cpp \ user_strings_unix.cpp \ $(SYSSRCS) $(CPUSRCS) APP = BasiliskII diff --git a/BasiliskII/src/Unix/video_blit.cpp b/BasiliskII/src/Unix/video_blit.cpp new file mode 100644 index 00000000..aced22d0 --- /dev/null +++ b/BasiliskII/src/Unix/video_blit.cpp @@ -0,0 +1,302 @@ +/* + * video_blit.cpp - Video/graphics emulation, blitters + * + * Basilisk II (C) 1997-2001 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include +#include +#include +#include + +#ifdef ENABLE_VOSF +// Format of the target visual +struct VisualFormat { + int depth; // Screen depth + uint32 Rmask, Gmask, Bmask; // RGB mask values + uint32 Rshift, Gshift, Bshift; // RGB shift values +}; +static VisualFormat visualFormat; + +/* -------------------------------------------------------------------------- */ +/* --- Raw Copy / No conversion required --- */ +/* -------------------------------------------------------------------------- */ + +static void Blit_Copy_Raw(uint8 * dest, const uint8 * source, uint32 length) +{ + // This function is likely to be inlined and/or highly optimized + memcpy(dest, source, length); +} + +/* -------------------------------------------------------------------------- */ +/* --- RGB 555 --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef WORDS_BIGENDIAN +# define FB_FUNC_NAME Blit_RGB555_OBO +#else +# define FB_FUNC_NAME Blit_RGB555_NBO +#endif + +#define FB_BLIT_1(dst, src) \ + (dst = (((src) >> 8) & 0xff) | (((src) & 0xff) << 8)) + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) >> 8) & 0x00ff00ff) | (((src) & 0x00ff00ff) << 8)) + +#define FB_DEPTH 15 +#include "video_blit.h" + +/* -------------------------------------------------------------------------- */ +/* --- BGR 555 --- */ +/* -------------------------------------------------------------------------- */ + +// TODO: BGR 555 (SGI/Irix) +// R/G/B mask values: 0x001f, 0x03e0, 0x7c00 + +/* -------------------------------------------------------------------------- */ +/* --- RGB 565 --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef WORDS_BIGENDIAN + +// Native byte order + +#define FB_BLIT_1(dst, src) \ + (dst = (((src) & 0x1f) | (((src) << 1) & 0xffc0))) + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) & 0x001f001f) | (((src) << 1) & 0xffc0ffc0))) + +#define FB_DEPTH 16 +#define FB_FUNC_NAME Blit_RGB565_NBO +#include "video_blit.h" + +// Opposite byte order + +#define FB_BLIT_1(dst, src) \ + (dst = ((((src) >> 7) & 0xff) | (((src) << 9) & 0xc000) | (((src) << 8) & 0x1f00))) + +#define FB_BLIT_2(dst, src) \ + (dst = ((((src) >> 7) & 0x00ff00ff) | (((src) << 9) & 0xc000c000) | (((src) << 8) & 0x1f001f00))) + +#define FB_DEPTH 16 +#define FB_FUNC_NAME Blit_RGB565_OBO +#include "video_blit.h" + +#else + +// Native byte order + +#define FB_BLIT_1(dst, src) \ + (dst = (((src) >> 8) & 0x001f) | (((src) << 9) & 0xfe00) | (((src) >> 7) & 0x01c0)) + +// gb-- Disabled because I don't see any improvement +#if 0 && defined(__i386__) && defined(X86_ASSEMBLY) + +#define FB_BLIT_2(dst, src) \ + __asm__ ( "movl %0,%%ebx\n\t" \ + "movl %0,%%ebp\n\t" \ + "andl $0x1f001f00,%%ebx\n\t" \ + "andl $0x007f007f,%0\n\t" \ + "andl $0xe000e000,%%ebp\n\t" \ + "shrl $8,%%ebx\n\t" \ + "shrl $7,%%ebp\n\t" \ + "shll $9,%0\n\t" \ + "orl %%ebx,%%ebp\n\t" \ + "orl %%ebp,%0\n\t" \ + : "=r" (dst) : "0" (src) : "ebx", "ebp", "cc" ) + +#else + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) >> 8) & 0x001f001f) | (((src) << 9) & 0xfe00fe00) | (((src) >> 7) & 0x01c001c0)) + +#endif + +#define FB_DEPTH 16 +#define FB_FUNC_NAME Blit_RGB565_NBO +#include "video_blit.h" + +// Opposite byte order (untested) + +#define FB_BLIT_1(dst, src) \ + (dst = (((src) & 0x1f00) | (((src) << 1) & 0xe0fe) | (((src) >> 15) & 1))) + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) & 0x1f001f00) | (((src) << 1) & 0xe0fee0fe) | (((src) >> 15) & 0x10001))) + +#define FB_DEPTH 16 +#define FB_FUNC_NAME Blit_RGB565_OBO +#include "video_blit.h" + +#endif + +/* -------------------------------------------------------------------------- */ +/* --- RGB 888 --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef WORDS_BIGENDIAN +# define FB_FUNC_NAME Blit_RGB888_OBO +#else +# define FB_FUNC_NAME Blit_RGB888_NBO +#endif + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) >> 24) & 0xff) | (((src) >> 8) & 0xff00) | (((src) & 0xff00) << 8) | (((src) & 0xff) << 24)) + +#define FB_DEPTH 24 +#include "video_blit.h" + +/* -------------------------------------------------------------------------- */ +/* --- BGR 888 --- */ +/* -------------------------------------------------------------------------- */ + +// Native byte order (untested) + +#ifdef WORDS_BIGENDIAN + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) >> 16) & 0xff) | ((src) & 0xff00) | (((src) & 0xff) << 16)) + +#define FB_FUNC_NAME Blit_BGR888_NBO +#define FB_DEPTH 24 +#include "video_blit.h" + +#else + +#define FB_BLIT_2(dst, src) \ + (dst = (((src) >> 16) & 0xff) | ((src) & 0xff0000) | (((src) & 0xff) << 16)) + +#define FB_FUNC_NAME Blit_BGR888_OBO +#define FB_DEPTH 24 +#include "video_blit.h" + +#endif + +// Opposite byte order (untested) + +#ifdef WORDS_BIGENDIAN +# define FB_FUNC_NAME Blit_BGR888_OBO +#else +# define FB_FUNC_NAME Blit_BGR888_NBO +#endif + +#define FB_BLIT_2(dst, src) \ + (dst = ((src) & 0xff00ff) | (((src) & 0xff00) << 16)) + +#define FB_DEPTH 24 +#include "video_blit.h" + +/* -------------------------------------------------------------------------- */ +/* --- Blitters to the host frame buffer, or XImage buffer --- */ +/* -------------------------------------------------------------------------- */ + +// Function used to update the hosst frame buffer (DGA), or an XImage buffer (WIN) +// --> Shall be initialized only through the Screen_blitter_init() function +typedef void (*Screen_blit_func)(uint8 * dest, const uint8 * source, uint32 length); +Screen_blit_func Screen_blit = 0; + +// Structure used to match the adequate framebuffer update function +struct Screen_blit_func_info { + int depth; // Screen depth + uint32 Rmask; // Red mask + uint32 Gmask; // Green mask + uint32 Bmask; // Blue mask + Screen_blit_func handler_nbo; // Update function (native byte order) + Screen_blit_func handler_obo; // Update function (opposite byte order) +}; + +// Table of visual formats supported and their respective handler +static Screen_blit_func_info Screen_blitters[] = { +#ifdef WORDS_BIGENDIAN + { 1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // NT + { 8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // OK (NBO) + { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_Copy_Raw , Blit_RGB555_OBO }, // OK (OBO) + { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO , Blit_RGB565_OBO }, // OK (OBO) + { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK (OBO) + { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO }, // NT + { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw , Blit_RGB888_OBO }, // OK (OBO) + { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // NT +#else + { 1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // NT + { 8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw , Blit_Copy_Raw }, // OK (NBO) + { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_RGB555_NBO , Blit_Copy_Raw }, // OK (NBO) + { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO , Blit_RGB565_OBO }, // OK (NBO) + { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO , Blit_Copy_Raw }, // OK (NBO) + { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO }, // NT + { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO , Blit_Copy_Raw }, // OK (NBO) + { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO , Blit_BGR888_OBO } // NT +#endif +}; + +// Initialize the framebuffer update function +// Returns FALSE, if the function was to be reduced to a simple memcpy() +// --> In that case, VOSF is not necessary +bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order) +{ + visualFormat.depth = visual_info->depth; + visualFormat.Rmask = visual_info->red_mask; + visualFormat.Gmask = visual_info->green_mask; + visualFormat.Bmask = visual_info->blue_mask; + + // Compute RGB shift values + visualFormat.Rshift = 0; + for (uint32 Rmask = visualFormat.Rmask; Rmask && ((Rmask & 1) != 1); Rmask >>= 1) + ++visualFormat.Rshift; + visualFormat.Gshift = 0; + for (uint32 Gmask = visualFormat.Gmask; Gmask && ((Gmask & 1) != 1); Gmask >>= 1) + ++visualFormat.Gshift; + visualFormat.Bshift = 0; + for (uint32 Bmask = visualFormat.Bmask; Bmask && ((Bmask & 1) != 1); Bmask >>= 1) + ++visualFormat.Bshift; + + // Search for an adequate blit function + bool blitter_found = false; + const int blitters_count = sizeof(Screen_blitters)/sizeof(Screen_blitters[0]); + for (int i = 0; !blitter_found && (i < blitters_count); i++) { + if ( (visualFormat.depth == Screen_blitters[i].depth) + && (visualFormat.Rmask == Screen_blitters[i].Rmask) + && (visualFormat.Gmask == Screen_blitters[i].Gmask) + && (visualFormat.Bmask == Screen_blitters[i].Bmask) + ) + { + blitter_found = true; + Screen_blit = native_byte_order + ? Screen_blitters[i].handler_nbo + : Screen_blitters[i].handler_obo + ; + } + } + + // No appropriate blitter found, dump RGB mask values and abort() + if (!blitter_found) { + fprintf(stderr, "### No appropriate blitter found\n"); + fprintf(stderr, "\tR/G/B mask values : 0x%06x, 0x%06x, 0x%06x (depth = %d)\n", + visualFormat.Rmask, visualFormat.Gmask, visualFormat.Bmask, visualFormat.depth); + fprintf(stderr, "\tR/G/B shift values : %d/%d/%d\n", + visualFormat.Rshift, visualFormat.Gshift, visualFormat.Bshift); + abort(); + } + + // If the blitter simply reduces to a copy, we don't need VOSF in DGA mode + // --> In that case, we return FALSE + return (Screen_blit != Blit_Copy_Raw); +} +#endif /* ENABLE_VOSF */ diff --git a/BasiliskII/src/Unix/video_blit.h b/BasiliskII/src/Unix/video_blit.h index de66f5c1..e69f9927 100644 --- a/BasiliskII/src/Unix/video_blit.h +++ b/BasiliskII/src/Unix/video_blit.h @@ -1,7 +1,7 @@ /* * video_blit.h - Video/graphics emulation, blitters * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-2001 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,90 +18,83 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef FB_BLIT_1 -# error "Undefined 16-bit word blit function" -#endif - -#ifndef FB_BLIT_2 -# error "Undefined 32-bit word blit function" -#endif - #ifndef FB_DEPTH # error "Undefined screen depth" #endif +#if !defined(FB_BLIT_1) && (FB_DEPTH <= 16) +# error "Undefined 16-bit word blit function" +#endif + +#if !defined(FB_BLIT_2) +# error "Undefined 32-bit word blit function" +#endif + static void FB_FUNC_NAME(uint8 * dest, const uint8 * source, uint32 length) { - union { - uint8 * bp; - uint16 * wp; - uint32 * lp; - } s, d; - - s.bp = (uint8 *)source; - d.bp = dest; +#define DEREF_LONG_PTR(ptr, ofs) (((uint32 *)(ptr))[(ofs)]) +#define DEREF_WORD_PTR(ptr, ofs) (((uint16 *)(ptr))[(ofs)]) +#ifndef UNALIGNED_PROFITABLE #if FB_DEPTH <= 8 // Align source and dest to 16-bit word boundaries - if (FB_DEPTH <= 8 && ((unsigned long) source) & 1) { - *d.bp++ = *s.bp++; + if (((unsigned long) source) & 1) { + *dest++ = *source++; length -= 1; } #endif -#if FB_DEPTH <= 8 - if (length >= 2) { -#endif - #if FB_DEPTH <= 16 // Align source and dest to 32-bit word boundaries if (((unsigned long) source) & 2) { - const uint16 val = *s.wp++; - FB_BLIT_1(*d.wp++, val); + FB_BLIT_1(DEREF_WORD_PTR(dest, 0), DEREF_WORD_PTR(source, 0)); + dest += 2; source += 2; length -= 2; } +#endif #endif // Blit 4-byte words if (length >= 4) { const int remainder = (length / 4) % 8; - s.lp += remainder; - d.lp += remainder; + source += remainder * 4; + dest += remainder * 4; int n = ((length / 4) + 7) / 8; switch (remainder) { case 0: do { - s.lp += 8; d.lp += 8; - FB_BLIT_2(d.lp[-8], s.lp[-8]); - case 7: FB_BLIT_2(d.lp[-7], s.lp[-7]); - case 6: FB_BLIT_2(d.lp[-6], s.lp[-6]); - case 5: FB_BLIT_2(d.lp[-5], s.lp[-5]); - case 4: FB_BLIT_2(d.lp[-4], s.lp[-4]); - case 3: FB_BLIT_2(d.lp[-3], s.lp[-3]); - case 2: FB_BLIT_2(d.lp[-2], s.lp[-2]); - case 1: FB_BLIT_2(d.lp[-1], s.lp[-1]); + dest += 32; source += 32; + FB_BLIT_2(DEREF_LONG_PTR(dest, -8), DEREF_LONG_PTR(source, -8)); + case 7: FB_BLIT_2(DEREF_LONG_PTR(dest, -7), DEREF_LONG_PTR(source, -7)); + case 6: FB_BLIT_2(DEREF_LONG_PTR(dest, -6), DEREF_LONG_PTR(source, -6)); + case 5: FB_BLIT_2(DEREF_LONG_PTR(dest, -5), DEREF_LONG_PTR(source, -5)); + case 4: FB_BLIT_2(DEREF_LONG_PTR(dest, -4), DEREF_LONG_PTR(source, -4)); + case 3: FB_BLIT_2(DEREF_LONG_PTR(dest, -3), DEREF_LONG_PTR(source, -3)); + case 2: FB_BLIT_2(DEREF_LONG_PTR(dest, -2), DEREF_LONG_PTR(source, -2)); + case 1: FB_BLIT_2(DEREF_LONG_PTR(dest, -1), DEREF_LONG_PTR(source, -1)); } while (--n > 0); } } #if FB_DEPTH <= 16 - // There might remain at least one word to blit + // There could be one word left to blit if (length & 2) { - FB_BLIT_1(*d.wp, *s.wp); + FB_BLIT_1(DEREF_WORD_PTR(dest, 0), DEREF_WORD_PTR(source, 0)); #if FB_DEPTH <= 8 - d.wp++; - s.wp++; + dest += 2; + source += 2; #endif } #endif #if FB_DEPTH <= 8 - } - - // There might remain one byte to blit + // There could be one byte left to blit if (length & 1) - *d.bp = *s.bp; + *dest = *source; #endif + +#undef DEREF_LONG_PTR +#undef DEREF_WORD_PTR } #undef FB_FUNC_NAME diff --git a/BasiliskII/src/Unix/video_vosf.h b/BasiliskII/src/Unix/video_vosf.h index fd3d43da..b7e53ce2 100644 --- a/BasiliskII/src/Unix/video_vosf.h +++ b/BasiliskII/src/Unix/video_vosf.h @@ -1,7 +1,7 @@ /* * video_vosf.h - Video/graphics emulation, video on SEGV signals support * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-2001 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,198 +44,6 @@ static void * allocate_framebuffer(uint32 size, uint8 * hint = 0) } -/* - * Screen depth identification - */ - -enum { - ID_DEPTH_UNKNOWN = -1, - ID_DEPTH_1, - ID_DEPTH_8, - ID_DEPTH_15, - ID_DEPTH_16, - ID_DEPTH_24, - ID_DEPTH_32 = ID_DEPTH_24, - ID_DEPTH_COUNT -}; - -static int depth_id(int depth) -{ - int id; - switch (depth) { - case 1 : id = ID_DEPTH_1; break; - case 8 : id = ID_DEPTH_8; break; - case 15 : id = ID_DEPTH_15; break; - case 16 : id = ID_DEPTH_16; break; - case 24 : id = ID_DEPTH_24; break; - case 32 : id = ID_DEPTH_32; break; - default : id = ID_DEPTH_UNKNOWN; - } - return id; -} - - -/* - * Frame buffer copy function templates - */ - -// No conversion required - -#define MEMCPY_PROFITABLE -#ifdef MEMCPY_PROFITABLE -static void do_fbcopy_raw(uint8 * dest, const uint8 * source, uint32 length) -{ - memcpy(dest, source, length); -} -#else -#define FB_BLIT_1(dst, src) (dst = (src)) -#define FB_BLIT_2(dst, src) (dst = (src)) -#define FB_DEPTH 0 -#define FB_FUNC_NAME do_fbcopy_raw -#include "video_blit.h" -#endif - - -// RGB 555 - -#ifdef WORDS_BIGENDIAN -# define FB_FUNC_NAME do_fbcopy_15_obo -#else -# define FB_FUNC_NAME do_fbcopy_15_nbo -#endif - -#define FB_BLIT_1(dst, src) \ - (dst = (((src) >> 8) & 0xff) | (((src) & 0xff) << 8)) - -#define FB_BLIT_2(dst, src) \ - (dst = (((src) >> 8) & 0x00ff00ff) | (((src) & 0x00ff00ff) << 8)) - -#define FB_DEPTH 15 -#include "video_blit.h" - - -// RGB 565 - -#ifdef WORDS_BIGENDIAN - -// native byte order - -#define FB_BLIT_1(dst, src) \ - (dst = (((src) & 0x1f) | (((src) << 1) & 0xffc0))) - -#define FB_BLIT_2(dst, src) \ - (dst = (((src) & 0x001f001f) | (((src) << 1) & 0xffc0ffc0))) - -#define FB_DEPTH 16 -#define FB_FUNC_NAME do_fbcopy_16_nbo -#include "video_blit.h" - -// opposite byte order - -#define FB_BLIT_1(dst, src) \ - (dst = ((((src) >> 7) & 0xff) | (((src) << 9) & 0xc000) | (((src) << 8) & 0x1f00))) - -#define FB_BLIT_2(dst, src) \ - (dst = ((((src) >> 7) & 0x00ff00ff) | (((src) << 9) & 0xc000c000) | (((src) << 8) & 0x1f001f00))) - -#define FB_DEPTH 16 -#define FB_FUNC_NAME do_fbcopy_16_obo -#include "video_blit.h" - -#else - -// native byte order - -#define FB_BLIT_1(dst, src) \ - (dst = (((src) >> 8) & 0x001f) | (((src) << 9) & 0xfe00) | (((src) >> 7) & 0x01c0)) - -#define FB_BLIT_2(dst, src) \ - (dst = (((src) >> 8) & 0x001f001f) | (((src) << 9) & 0xfe00fe00) | (((src) >> 7) & 0x01c001c0)) - -#define FB_DEPTH 16 -#define FB_FUNC_NAME do_fbcopy_16_nbo -#include "video_blit.h" - -// opposite byte order (untested) - -#define FB_BLIT_1(dst, src) \ - (dst = (((src) & 0x1f00) | (((src) << 1) & 0xe0fe) | (((src) >> 15) & 1))) - -#define FB_BLIT_2(dst, src) \ - (dst = (((src) & 0x1f001f00) | (((src) << 1) & 0xe0fee0fe) | (((src) >> 15) & 0x10001))) - -#define FB_DEPTH 16 -#define FB_FUNC_NAME do_fbcopy_16_obo -#include "video_blit.h" - -#endif - -// RGB 888 - -#ifdef WORDS_BIGENDIAN -# define FB_FUNC_NAME do_fbcopy_24_obo -#else -# define FB_FUNC_NAME do_fbcopy_24_nbo -#endif - -#define FB_BLIT_1(dst, src) \ - (dst = (src)) - -#define FB_BLIT_2(dst, src) \ - (dst = (((src) >> 24) & 0xff) | (((src) >> 8) & 0xff00) | (((src) & 0xff00) << 8) | (((src) & 0xff) << 24)) - -#define FB_DEPTH 24 -#include "video_blit.h" - - -/* - * Frame buffer copy functions map table - */ - -typedef void (*fbcopy_func)(uint8 *, const uint8 *, uint32); -static fbcopy_func do_update_framebuffer; - -#define FBCOPY_FUNC(aHandler) do_ ## aHandler - -#if REAL_ADDRESSING || DIRECT_ADDRESSING -#define WD(X) { FBCOPY_FUNC(X), FBCOPY_FUNC(X) } -#else -#define WD(X) { FBCOPY_FUNC(fbcopy_raw), FBCOPY_FUNC(fbcopy_raw) } -#endif - -// fb_copy_funcs[depth_id][native_byte_order][dga_mode] -// NT : not tested -// OK : has been successfully tested -// NBO : native byte order (X server vs. client) -// OBO : opposite byte order (X server vs. client) -static fbcopy_func fbcopy_funcs[ID_DEPTH_COUNT][2][2] = { -#ifdef WORDS_BIGENDIAN - /* opposite byte order native byte order */ -/* 1 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // NT -/* 8 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // OK (NBO) -/* 15 bpp */ { WD(fbcopy_15_obo) , WD(fbcopy_raw) }, // OK (OBO) -/* 16 bpp */ { WD(fbcopy_16_obo) , WD(fbcopy_16_nbo) }, // OK (OBO) -/* 24 bpp */ { WD(fbcopy_24_obo) , WD(fbcopy_raw) } // OK (OBO) -#else - /* opposite byte order native byte order */ -/* 1 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // NT -/* 8 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // OK (NBO) -/* 15 bpp */ { WD(fbcopy_raw) , WD(fbcopy_15_nbo) }, // OK (NBO) -/* 16 bpp */ { WD(fbcopy_16_obo) , WD(fbcopy_16_nbo) }, // OK (NBO) -/* 24 bpp */ { WD(fbcopy_raw) , WD(fbcopy_24_nbo) } // OK (NBO) -#endif -}; - -#undef WD - -#define FBCOPY_FUNC_ERROR \ - ErrorAlert("Invalid screen depth") - -#define GET_FBCOPY_FUNC(aDepth, aNativeByteOrder, aDisplay) \ - ((depth_id(aDepth) == ID_DEPTH_UNKNOWN) ? ( FBCOPY_FUNC_ERROR, (fbcopy_func)0 ) : \ - fbcopy_funcs[depth_id(aDepth)][(aNativeByteOrder)][(aDisplay) == DISPLAY_DGA ? 1 : 0]) - - /* * Screen fault handler */ @@ -254,6 +62,7 @@ static inline void do_handle_screen_fault(uintptr addr, uintptr pc = INVALID_PC) LOCK_VOSF; PFLAG_SET(page); mprotect(page_ad, mainBuffer.pageSize, PROT_READ | PROT_WRITE); + mainBuffer.dirty = true; UNLOCK_VOSF; return; } @@ -350,6 +159,10 @@ static bool Screen_fault_handler_init() * Update display for Windowed mode and VOSF */ +// From video_blit.cpp +extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length); +extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order); + /* How can we deal with array overrun conditions ? The state of the framebuffer pages that have been touched are maintained @@ -364,12 +177,12 @@ Terminology Rough process - The update routines must determine which pages have to blitted to the + The update routines must determine which pages have to be blitted to the screen. This job consists in finding the first_page that was touched. i.e. find the next page that is SET. Then, finding how many pages were touched starting from first_page. i.e. find the next page that is CLEAR. -Two cases +There are two cases to check: - Last Page is CLEAR: find_next_page_set() will reach the SET Page Guard but it is beyond the valid pageCount value. Therefore, we exit from the @@ -441,7 +254,7 @@ static inline void update_display_window_vosf(void) // Update the_host_buffer and copy of the_buffer i = y1 * bytes_per_row + (x1 >> 3); for (j = y1; j <= y2; j++) { - do_update_framebuffer(the_host_buffer + i, the_buffer + i, width >> 3); + Screen_blit(the_host_buffer + i, the_buffer + i, width >> 3); memcpy(the_buffer_copy + i, the_buffer + i, width >> 3); i += bytes_per_row; } @@ -478,7 +291,7 @@ static inline void update_display_window_vosf(void) // Update the_host_buffer and copy of the_buffer i = y1 * bytes_per_row + x1 * bytes_per_pixel; for (j = y1; j <= y2; j++) { - do_update_framebuffer(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width); + Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width); memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width); i += bytes_per_row; } @@ -489,6 +302,7 @@ static inline void update_display_window_vosf(void) else XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, width, height); } + mainBuffer.dirty = false; } @@ -555,11 +369,12 @@ static inline void update_display_dga_vosf(void) const int width = x2 - x1 + 1; i = y1 * bytes_per_row + x1 * bytes_per_pixel; for (j = y1; j <= y2; j++) { - do_update_framebuffer(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width); + Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width); memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width); i += bytes_per_row; } } + mainBuffer.dirty = false; } #endif diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index 55802a1f..ad3201f7 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -1,7 +1,7 @@ /* * video_x.cpp - Video/graphics emulation, X11 specific stuff * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-2001 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -197,6 +197,7 @@ struct ScreenInfo { int pageBits; // Shift count to get the page number uint32 pageCount; // Number of pages allocated to the screen + bool dirty; // Flag: set if the frame buffer was touched char * dirtyPages; // Table of flags set if page was altered ScreenPageInfo * pageInfo; // Table of mappings page -> Mac scanlines }; @@ -234,11 +235,15 @@ static ScreenInfo mainBuffer; memset(mainBuffer.dirtyPages + (first_page), PFLAG_CLEAR_VALUE, \ (last_page) - (first_page)) -#define PFLAG_SET_ALL \ - PFLAG_SET_RANGE(0, mainBuffer.pageCount) +#define PFLAG_SET_ALL do { \ + PFLAG_SET_RANGE(0, mainBuffer.pageCount); \ + mainBuffer.dirty = true; \ +} while (0) -#define PFLAG_CLEAR_ALL \ - PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount) +#define PFLAG_CLEAR_ALL do { \ + PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount); \ + mainBuffer.dirty = false; \ +} while (0) // Set the following macro definition to 1 if your system // provides a really fast strchr() implementation @@ -575,7 +580,7 @@ static bool init_window(int width, int height) native_byte_order = (XImageByteOrder(x_display) == LSBFirst); #endif #ifdef ENABLE_VOSF - do_update_framebuffer = GET_FBCOPY_FUNC(depth, native_byte_order, DISPLAY_WINDOW); + Screen_blitter_init(&visualInfo, native_byte_order); #endif set_video_monitor(width, height, img->bytes_per_line, native_byte_order); @@ -714,12 +719,9 @@ static bool init_fbdev_dga(char *in_fb_name) #if ENABLE_VOSF #if REAL_ADDRESSING || DIRECT_ADDRESSING - // If the blit function is null, i.e. just a copy of the buffer, - // we first try to avoid the allocation of a temporary frame buffer - use_vosf = true; - do_update_framebuffer = GET_FBCOPY_FUNC(depth, true, DISPLAY_DGA); - if (do_update_framebuffer == FBCOPY_FUNC(fbcopy_raw)) - use_vosf = false; + // Screen_blitter_init() returns TRUE if VOSF is mandatory + // i.e. the framebuffer update function is not Blit_Copy_Raw + use_vosf = Screen_blitter_init(&visualInfo, true); if (use_vosf) { the_host_buffer = the_buffer; @@ -824,12 +826,9 @@ static bool init_xf86_dga(int width, int height) } #if REAL_ADDRESSING || DIRECT_ADDRESSING - // If the blit function is null, i.e. just a copy of the buffer, - // we first try to avoid the allocation of a temporary frame buffer - use_vosf = true; - do_update_framebuffer = GET_FBCOPY_FUNC(depth, true, DISPLAY_DGA); - if (do_update_framebuffer == FBCOPY_FUNC(fbcopy_raw)) - use_vosf = false; + // Screen_blitter_init() returns TRUE if VOSF is mandatory + // i.e. the framebuffer update function is not Blit_Copy_Raw + use_vosf = Screen_blitter_init(&visualInfo, true); if (use_vosf) { the_host_buffer = the_buffer; @@ -952,6 +951,8 @@ bool VideoInitBuffer() if ((mainBuffer.dirtyPages == 0) || (mainBuffer.pageInfo == 0)) return false; + + mainBuffer.dirty = false; PFLAG_CLEAR_ALL; // Safety net to insure the loops in the update routines will terminate @@ -2024,9 +2025,11 @@ static void video_refresh_dga_vosf(void) static int tick_counter = 0; if (++tick_counter >= frame_skip) { tick_counter = 0; - LOCK_VOSF; - update_display_dga_vosf(); - UNLOCK_VOSF; + if (mainBuffer.dirty) { + LOCK_VOSF; + update_display_dga_vosf(); + UNLOCK_VOSF; + } } } #endif @@ -2046,9 +2049,11 @@ static void video_refresh_window_vosf(void) static int tick_counter = 0; if (++tick_counter >= frame_skip) { tick_counter = 0; - LOCK_VOSF; - update_display_window_vosf(); - UNLOCK_VOSF; + if (mainBuffer.dirty) { + LOCK_VOSF; + update_display_window_vosf(); + UNLOCK_VOSF; + } } } #endif // def ENABLE_VOSF