mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-26 16:31:11 +00:00
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:
parent
069a1ba3ad
commit
e94d644b19
@ -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
|
||||
|
302
BasiliskII/src/Unix/video_blit.cpp
Normal file
302
BasiliskII/src/Unix/video_blit.cpp
Normal 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 */
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user