Mainly changes to the VOSF code:

- improved blitters selection
- improved blitters performance if UNALIGNED_PROFITABLE is set
- cleaned up 8 bpp blitters
This commit is contained in:
gbeauche 2001-01-28 14:05:19 +00:00
parent 069a1ba3ad
commit e94d644b19
5 changed files with 383 additions and 268 deletions

View File

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

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#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 */

View File

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

View File

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

View File

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