macemu/SheepShaver/src/BeOS/video_beos.cpp

769 lines
23 KiB
C++

/*
* video_beos.cpp - Video/graphics emulation, BeOS specific things
*
* SheepShaver (C) 1997-2002 Marc Hellwig and 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 "video.h"
#include "video_defs.h"
#include "main.h"
#include "adb.h"
#include "prefs.h"
#include "user_strings.h"
#include "about_window.h"
#include "version.h"
#define DEBUG 0
#include "debug.h"
// Global variables
static sem_id video_lock = -1; // Protection during mode changes
static sem_id mac_os_lock = -1; // This is used to stop the MacOS thread when the SheepShaver workspace is switched out
// Prototypes
static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter);
// From sys_beos.cpp
extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg);
extern void SysMountVolume(const char *name);
#include "video_window.h"
#include "video_screen.h"
/*
* Display manager thread (for opening and closing windows and screens;
* this is not safe under R4 when running on the MacOS stack in kernel
* space)
*/
// Message constants
const uint32 MSG_OPEN_WINDOW = 'owin';
const uint32 MSG_CLOSE_WINDOW = 'cwin';
const uint32 MSG_OPEN_SCREEN = 'oscr';
const uint32 MSG_CLOSE_SCREEN = 'cscr';
const uint32 MSG_QUIT_DISPLAY_MANAGER = 'quit';
static thread_id dm_thread = -1;
static sem_id dm_done_sem = -1;
static status_t display_manager(void *arg)
{
for (;;) {
// Receive message
thread_id sender;
uint32 code = receive_data(&sender, NULL, 0);
D(bug("Display manager received %08lx\n", code));
switch (code) {
case MSG_QUIT_DISPLAY_MANAGER:
return 0;
case MSG_OPEN_WINDOW:
D(bug("Opening window\n"));
the_window = new MacWindow(BRect(0, 0, VModes[cur_mode].viXsize-1, VModes[cur_mode].viYsize-1));
D(bug("Opened\n"));
break;
case MSG_CLOSE_WINDOW:
if (the_window != NULL) {
D(bug("Posting quit to window\n"));
the_window->PostMessage(B_QUIT_REQUESTED);
D(bug("Posted, waiting\n"));
while (the_window)
snooze(200000);
D(bug("Window closed\n"));
}
break;
case MSG_OPEN_SCREEN: {
D(bug("Opening screen\n"));
long scr_mode = 0;
switch (VModes[cur_mode].viAppleMode) {
case APPLE_8_BIT:
switch (VModes[cur_mode].viAppleID) {
case APPLE_640x480:
scr_mode = B_8_BIT_640x480;
break;
case APPLE_800x600:
scr_mode = B_8_BIT_800x600;
break;
case APPLE_1024x768:
scr_mode = B_8_BIT_1024x768;
break;
case APPLE_1152x900:
scr_mode = B_8_BIT_1152x900;
break;
case APPLE_1280x1024:
scr_mode = B_8_BIT_1280x1024;
break;
case APPLE_1600x1200:
scr_mode = B_8_BIT_1600x1200;
break;
}
break;
case APPLE_16_BIT:
switch (VModes[cur_mode].viAppleID) {
case APPLE_640x480:
scr_mode = B_15_BIT_640x480;
break;
case APPLE_800x600:
scr_mode = B_15_BIT_800x600;
break;
case APPLE_1024x768:
scr_mode = B_15_BIT_1024x768;
break;
case APPLE_1152x900:
scr_mode = B_15_BIT_1152x900;
break;
case APPLE_1280x1024:
scr_mode = B_15_BIT_1280x1024;
break;
case APPLE_1600x1200:
scr_mode = B_15_BIT_1600x1200;
break;
}
break;
case APPLE_32_BIT:
switch (VModes[cur_mode].viAppleID) {
case APPLE_640x480:
scr_mode = B_32_BIT_640x480;
break;
case APPLE_800x600:
scr_mode = B_32_BIT_800x600;
break;
case APPLE_1024x768:
scr_mode = B_32_BIT_1024x768;
break;
case APPLE_1152x900:
scr_mode = B_32_BIT_1152x900;
break;
case APPLE_1280x1024:
scr_mode = B_32_BIT_1280x1024;
break;
case APPLE_1600x1200:
scr_mode = B_32_BIT_1600x1200;
break;
}
break;
}
the_screen = new MacScreen(GetString(STR_WINDOW_TITLE), scr_mode);
D(bug("Opened, error %08lx\n", screen_error));
if (screen_error != B_NO_ERROR) {
D(bug("Error, posting quit to screen\n"));
the_screen->PostMessage(B_QUIT_REQUESTED);
D(bug("Posted, waiting\n"));
while (the_screen)
snooze(200000);
D(bug("Screen closed\n"));
break;
}
// Wait for video mem access
D(bug("Showing screen\n"));
the_screen->Show();
D(bug("Shown, waiting for frame buffer access\n"));
while (!drawing_enable)
snooze(200000);
D(bug("Access granted\n"));
break;
}
case MSG_CLOSE_SCREEN:
if (the_screen != NULL) {
D(bug("Posting quit to screen\n"));
the_screen->PostMessage(B_QUIT_REQUESTED);
D(bug("Posted, waiting\n"));
while (the_screen)
snooze(200000);
D(bug("Screen closed\n"));
}
break;
}
// Acknowledge
release_sem(dm_done_sem);
}
}
/*
* Open display (window or screen)
*/
static void open_display(void)
{
D(bug("entering open_display()\n"));
display_type = VModes[cur_mode].viType;
if (display_type == DIS_SCREEN) {
while (send_data(dm_thread, MSG_OPEN_SCREEN, NULL, 0) == B_INTERRUPTED) ;
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
} else if (display_type == DIS_WINDOW) {
while (send_data(dm_thread, MSG_OPEN_WINDOW, NULL, 0) == B_INTERRUPTED) ;
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
}
D(bug("exiting open_display()\n"));
}
/*
* Close display
*/
static void close_display(void)
{
D(bug("entering close_display()\n"));
if (display_type == DIS_SCREEN) {
while (send_data(dm_thread, MSG_CLOSE_SCREEN, NULL, 0) == B_INTERRUPTED) ;
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
} else if (display_type == DIS_WINDOW) {
while (send_data(dm_thread, MSG_CLOSE_WINDOW, NULL, 0) == B_INTERRUPTED) ;
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
}
D(bug("exiting close_display()\n"));
}
/*
* Initialization
*/
static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type)
{
if (allow & test) {
p->viType = type;
switch (apple_id) {
case APPLE_W_640x480:
case APPLE_640x480:
p->viXsize = 640;
p->viYsize = 480;
break;
case APPLE_W_800x600:
case APPLE_800x600:
p->viXsize = 800;
p->viYsize = 600;
break;
case APPLE_1024x768:
p->viXsize = 1024;
p->viYsize = 768;
break;
case APPLE_1152x900:
p->viXsize = 1152;
p->viYsize = 900;
break;
case APPLE_1280x1024:
p->viXsize = 1280;
p->viYsize = 1024;
break;
case APPLE_1600x1200:
p->viXsize = 1600;
p->viYsize = 1200;
break;
}
switch (apple_mode) {
case APPLE_8_BIT:
p->viRowBytes = p->viXsize;
break;
case APPLE_16_BIT:
p->viRowBytes = p->viXsize * 2;
break;
case APPLE_32_BIT:
p->viRowBytes = p->viXsize * 4;
break;
}
p->viAppleMode = apple_mode;
p->viAppleID = apple_id;
p++;
}
}
bool VideoInit(void)
{
// Init variables, create semaphores
private_data = NULL;
cur_mode = 0; // Window 640x480
video_lock = create_sem(1, "Video Lock");
mac_os_lock = create_sem(0, "MacOS Frame Buffer Lock");
dm_done_sem = create_sem(0, "Display Manager Done");
// Construct video mode table
VideoInfo *p = VModes;
uint32 window_modes = PrefsFindInt32("windowmodes");
uint32 screen_modes = PrefsFindInt32("screenmodes");
if (window_modes == 0 && screen_modes == 0)
window_modes |= B_8_BIT_640x480 | B_8_BIT_800x600; // Allow at least 640x480 and 800x600 window modes
add_mode(p, window_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_W_640x480, DIS_WINDOW);
add_mode(p, window_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_W_800x600, DIS_WINDOW);
add_mode(p, window_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_W_640x480, DIS_WINDOW);
add_mode(p, window_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_W_800x600, DIS_WINDOW);
add_mode(p, window_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_W_640x480, DIS_WINDOW);
add_mode(p, window_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_W_800x600, DIS_WINDOW);
add_mode(p, screen_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_640x480, DIS_SCREEN);
add_mode(p, screen_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_800x600, DIS_SCREEN);
add_mode(p, screen_modes, B_8_BIT_1024x768, APPLE_8_BIT, APPLE_1024x768, DIS_SCREEN);
add_mode(p, screen_modes, B_8_BIT_1152x900, APPLE_8_BIT, APPLE_1152x900, DIS_SCREEN);
add_mode(p, screen_modes, B_8_BIT_1280x1024, APPLE_8_BIT, APPLE_1280x1024, DIS_SCREEN);
add_mode(p, screen_modes, B_8_BIT_1600x1200, APPLE_8_BIT, APPLE_1600x1200, DIS_SCREEN);
add_mode(p, screen_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_640x480, DIS_SCREEN);
add_mode(p, screen_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_800x600, DIS_SCREEN);
add_mode(p, screen_modes, B_15_BIT_1024x768, APPLE_16_BIT, APPLE_1024x768, DIS_SCREEN);
add_mode(p, screen_modes, B_15_BIT_1152x900, APPLE_16_BIT, APPLE_1152x900, DIS_SCREEN);
add_mode(p, screen_modes, B_15_BIT_1280x1024, APPLE_16_BIT, APPLE_1280x1024, DIS_SCREEN);
add_mode(p, screen_modes, B_15_BIT_1600x1200, APPLE_16_BIT, APPLE_1600x1200, DIS_SCREEN);
add_mode(p, screen_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_640x480, DIS_SCREEN);
add_mode(p, screen_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_800x600, DIS_SCREEN);
add_mode(p, screen_modes, B_32_BIT_1024x768, APPLE_32_BIT, APPLE_1024x768, DIS_SCREEN);
add_mode(p, screen_modes, B_32_BIT_1152x900, APPLE_32_BIT, APPLE_1152x900, DIS_SCREEN);
add_mode(p, screen_modes, B_32_BIT_1280x1024, APPLE_32_BIT, APPLE_1280x1024, DIS_SCREEN);
add_mode(p, screen_modes, B_32_BIT_1600x1200, APPLE_32_BIT, APPLE_1600x1200, DIS_SCREEN);
p->viType = DIS_INVALID; // End marker
p->viRowBytes = 0;
p->viXsize = p->viYsize = 0;
p->viAppleMode = 0;
p->viAppleID = 0;
// Start display manager thread
dm_thread = spawn_thread(display_manager, "Display Manager", B_NORMAL_PRIORITY, NULL);
resume_thread(dm_thread);
// Open window/screen
open_display();
if (display_type == DIS_SCREEN && the_screen == NULL) {
char str[256];
sprintf(str, GetString(STR_FULL_SCREEN_ERR), strerror(screen_error), screen_error);
ErrorAlert(str);
return false;
}
return true;
}
/*
* Deinitialization
*/
void VideoExit(void)
{
if (dm_thread >= 0) {
// Close display
acquire_sem(video_lock);
close_display();
if (private_data != NULL) {
delete private_data->gammaTable;
delete private_data;
}
// Stop display manager
status_t l;
send_data(dm_thread, MSG_QUIT_DISPLAY_MANAGER, NULL, 0);
while (wait_for_thread(dm_thread, &l) == B_INTERRUPTED) ;
}
// Delete semaphores
delete_sem(video_lock);
delete_sem(mac_os_lock);
delete_sem(dm_done_sem);
}
/*
* Close screen in full-screen mode
*/
void VideoQuitFullScreen(void)
{
D(bug("VideoQuitFullScreen()\n"));
if (display_type == DIS_SCREEN) {
acquire_sem(video_lock);
close_display();
release_sem(video_lock);
}
}
/*
* Execute video VBL routine
*/
void VideoVBL(void)
{
release_sem(mac_os_lock);
if (private_data != NULL && private_data->interruptsEnabled)
VSLDoInterruptService(private_data->vslServiceID);
while (acquire_sem(mac_os_lock) == B_INTERRUPTED) ;
}
/*
* Filter function for receiving mouse and keyboard events
*/
#define MENU_IS_POWER 0
// Be -> Mac raw keycode translation table
static const uint8 keycode2mac[0x80] = {
0xff, 0x35, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, // inv Esc F1 F2 F3 F4 F5 F6
0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b, // F7 F8 F9 F10 F11 F12 F13 F14
0x71, 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, // F15 ` 1 2 3 4 5 6
0x1a, 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x33, 0x72, // 7 8 9 0 - = BSP INS
0x73, 0x74, 0x47, 0x4b, 0x43, 0x4e, 0x30, 0x0c, // HOM PUP NUM / * - TAB Q
0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, 0x1f, // W E R T Y U I O
0x23, 0x21, 0x1e, 0x2a, 0x75, 0x77, 0x79, 0x59, // P [ ] \ DEL END PDN 7
0x5b, 0x5c, 0x45, 0x39, 0x00, 0x01, 0x02, 0x03, // 8 9 + CAP A S D F
0x05, 0x04, 0x26, 0x28, 0x25, 0x29, 0x27, 0x24, // G H J K L ; ' RET
0x56, 0x57, 0x58, 0x38, 0x06, 0x07, 0x08, 0x09, // 4 5 6 SHL Z X C V
0x0b, 0x2d, 0x2e, 0x2b, 0x2f, 0x2c, 0x38, 0x3e, // B N M , . / SHR CUP
0x53, 0x54, 0x55, 0x4c, 0x36, 0x37, 0x31, 0x37, // 1 2 3 ENT CTL ALT SPC ALT
0x36, 0x3b, 0x3d, 0x3c, 0x52, 0x41, 0x3a, 0x3a, // CTR CLF CDN CRT 0 . CMD CMD
#if MENU_IS_POWER
0x7f, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv
#else
0x32, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv
#endif
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv
};
static const uint8 modifier2mac[0x20] = {
#if MENU_IS_POWER
0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x7f, // SHF CMD inv CAP F14 NUM OPT MNU
#else
0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x32, // SHF CMD CTR CAP F14 NUM OPT MNU
#endif
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv
};
static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter)
{
// msg->PrintToStream();
switch (msg->what) {
case B_KEY_DOWN:
case B_KEY_UP: {
uint32 be_code = msg->FindInt32("key") & 0xff;
uint32 mac_code = keycode2mac[be_code];
// Intercept Ctrl-F1 (mount floppy disk shortcut)
uint32 mods = msg->FindInt32("modifiers");
if (be_code == 0x02 && (mods & B_CONTROL_KEY))
SysMountVolume("/dev/disk/floppy/raw");
if (mac_code == 0xff)
return B_DISPATCH_MESSAGE;
if (msg->what == B_KEY_DOWN)
ADBKeyDown(mac_code);
else
ADBKeyUp(mac_code);
return B_SKIP_MESSAGE;
}
case B_MODIFIERS_CHANGED: {
uint32 mods = msg->FindInt32("modifiers");
uint32 old_mods = msg->FindInt32("be:old_modifiers");
uint32 changed = mods ^ old_mods;
uint32 mask = 1;
for (int i=0; i<32; i++, mask<<=1)
if (changed & mask) {
uint32 mac_code = modifier2mac[i];
if (mac_code == 0xff)
continue;
if (mods & mask)
ADBKeyDown(mac_code);
else
ADBKeyUp(mac_code);
}
return B_SKIP_MESSAGE;
}
case B_MOUSE_MOVED: {
BPoint point;
msg->FindPoint("where", &point);
ADBMouseMoved(int(point.x), int(point.y));
return B_DISPATCH_MESSAGE; // Otherwise BitmapView::MouseMoved() wouldn't be called
}
case B_MOUSE_DOWN: {
uint32 buttons = msg->FindInt32("buttons");
if (buttons & B_PRIMARY_MOUSE_BUTTON)
ADBMouseDown(0);
if (buttons & B_SECONDARY_MOUSE_BUTTON)
ADBMouseDown(1);
if (buttons & B_TERTIARY_MOUSE_BUTTON)
ADBMouseDown(2);
return B_SKIP_MESSAGE;
}
case B_MOUSE_UP: // B_MOUSE_UP means "all buttons released"
ADBMouseUp(0);
ADBMouseUp(1);
ADBMouseUp(2);
return B_SKIP_MESSAGE;
default:
return B_DISPATCH_MESSAGE;
}
}
/*
* Install graphics acceleration
*/
// Rectangle blitting
static void accl_bitblt(accl_params *p)
{
D(bug("accl_bitblt\n"));
// Get blitting parameters
int16 src_X = p->src_rect[1] - p->src_bounds[1];
int16 src_Y = p->src_rect[0] - p->src_bounds[0];
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
int16 width = p->dest_rect[3] - p->dest_rect[1] - 1;
int16 height = p->dest_rect[2] - p->dest_rect[0] - 1;
D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y));
D(bug(" width %d, height %d\n", width, height));
// And perform the blit
bitblt_hook(src_X, src_Y, dest_X, dest_Y, width, height);
}
static bool accl_bitblt_hook(accl_params *p)
{
D(bug("accl_draw_hook %p\n", p));
// Check if we can accelerate this bitblt
if (p->src_base_addr == screen_base && p->dest_base_addr == screen_base &&
display_type == DIS_SCREEN && bitblt_hook != NULL &&
((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 &&
((uint32 *)p)[0x130 >> 2] == 0 &&
p->transfer_mode == 0 &&
p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) {
// Yes, set function pointer
p->draw_proc = accl_bitblt;
return true;
}
return false;
}
// Rectangle filling/inversion
static void accl_fillrect8(accl_params *p)
{
D(bug("accl_fillrect8\n"));
// Get filling parameters
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1;
int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1;
uint8 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen;
D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max));
// And perform the fill
fillrect8_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color);
}
static void accl_fillrect32(accl_params *p)
{
D(bug("accl_fillrect32\n"));
// Get filling parameters
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1;
int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1;
uint32 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen;
D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max));
// And perform the fill
fillrect32_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color);
}
static void accl_invrect(accl_params *p)
{
D(bug("accl_invrect\n"));
// Get inversion parameters
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1;
int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1;
D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max));
//!!?? pen_mode == 14
// And perform the inversion
invrect_hook(dest_X, dest_Y, dest_X_max, dest_Y_max);
}
static bool accl_fillrect_hook(accl_params *p)
{
D(bug("accl_fillrect_hook %p\n", p));
// Check if we can accelerate this fillrect
if (p->dest_base_addr == screen_base && ((uint32 *)p)[0x284 >> 2] != 0 && display_type == DIS_SCREEN) {
if (p->transfer_mode == 8) {
// Fill
if (p->dest_pixel_size == 8 && fillrect8_hook != NULL) {
p->draw_proc = accl_fillrect8;
return true;
} else if (p->dest_pixel_size == 32 && fillrect32_hook != NULL) {
p->draw_proc = accl_fillrect32;
return true;
}
} else if (p->transfer_mode == 10 && invrect_hook != NULL) {
// Invert
p->draw_proc = accl_invrect;
return true;
}
}
return false;
}
// Dummy for testing
/*
static void do_nothing(accl_params *p) {}
static bool accl_foobar_hook(accl_params *p)
{
printf("accl_foobar_hook %p\n", p);
printf(" src_base_addr %p, dest_base_addr %p\n", p->src_base_addr, p->dest_base_addr);
printf(" src_row_bytes %d, dest_row_bytes %d\n", p->src_row_bytes, p->dest_row_bytes);
printf(" src_pixel_size %d, dest_pixel_size %d\n", p->src_pixel_size, p->dest_pixel_size);
printf(" src_bounds (%d,%d,%d,%d), dest_bounds (%d,%d,%d,%d)\n", p->src_bounds[0], p->src_bounds[1], p->src_bounds[2], p->src_bounds[3], p->dest_bounds[0], p->dest_bounds[1], p->dest_bounds[2], p->dest_bounds[3]);
printf(" src_rect (%d,%d,%d,%d), dest_rect (%d,%d,%d,%d)\n", p->src_rect[0], p->src_rect[1], p->src_rect[2], p->src_rect[3], p->dest_rect[0], p->dest_rect[1], p->dest_rect[2], p->dest_rect[3]);
printf(" transfer mode %d\n", p->transfer_mode);
printf(" pen mode %d\n", p->pen_mode);
printf(" fore_pen %08x, back_pen %08x\n", p->fore_pen, p->back_pen);
printf(" val1 %08x, val2 %08x\n", ((uint32 *)p)[0x18 >> 2], ((uint32 *)p)[0x128 >> 2]);
printf(" val3 %08x\n", ((uint32 *)p)[0x130 >> 2]);
printf(" val4 %08x\n", ((uint32 *)p)[0x15c >> 2]);
printf(" val5 %08x\n", ((uint32 *)p)[0x160 >> 2]);
printf(" val6 %08x\n", ((uint32 *)p)[0x1b4 >> 2]);
printf(" val7 %08x\n", ((uint32 *)p)[0x284 >> 2]);
p->draw_proc = do_nothing;
return true;
}
static struct accl_hook_info foobar_hook_info = {accl_foobar_hook, accl_sync_hook, 6};
*/
// Wait for graphics operation to finish
static bool accl_sync_hook(void *arg)
{
D(bug("accl_sync_hook %p\n", arg));
if (sync_hook != NULL)
sync_hook();
return true;
}
static struct accl_hook_info bitblt_hook_info = {accl_bitblt_hook, accl_sync_hook, ACCL_BITBLT};
static struct accl_hook_info fillrect_hook_info = {accl_fillrect_hook, accl_sync_hook, ACCL_FILLRECT};
void VideoInstallAccel(void)
{
// Install acceleration hooks
if (PrefsFindBool("gfxaccel")) {
D(bug("Video: Installing acceleration hooks\n"));
NQDMisc(6, &bitblt_hook_info);
NQDMisc(6, &fillrect_hook_info);
}
}
/*
* Change video mode
*/
int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr)
{
/* return if no mode change */
if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) &&
(csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr;
/* first find video mode in table */
for (int i=0; VModes[i].viType != DIS_INVALID; i++) {
if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) &&
(ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) {
csSave->saveMode = ReadMacInt16(ParamPtr + csMode);
csSave->saveData = ReadMacInt32(ParamPtr + csData);
csSave->savePage = ReadMacInt16(ParamPtr + csPage);
while (acquire_sem(video_lock) == B_INTERRUPTED) ;
DisableInterrupt();
/* close old display */
close_display();
/* open new display */
cur_mode = i;
open_display();
/* opening the screen failed? Then bail out */
if (display_type == DIS_SCREEN && the_screen == NULL) {
release_sem(video_lock);
ErrorAlert(GetString(STR_FULL_SCREEN_ERR));
QuitEmulator();
}
WriteMacInt32(ParamPtr + csBaseAddr, screen_base);
csSave->saveBaseAddr=screen_base;
csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */
csSave->saveMode=VModes[cur_mode].viAppleMode;
EnableInterrupt();
release_sem(video_lock);
return noErr;
}
}
return paramErr;
}
/*
* Set color palette
*/
void video_set_palette(void)
{
if (display_type == DIS_SCREEN && the_screen != NULL)
the_screen->palette_changed = true;
else { // remap colors to BeOS-Palette
BScreen screen;
for (int i=0;i<256;i++)
remap_mac_be[i]=screen.IndexForColor(mac_pal[i].red,mac_pal[i].green,mac_pal[i].blue);
}
}
/*
* Set cursor image for window
*/
void video_set_cursor(void)
{
the_window->cursor_changed = true; // Inform window (don't set cursor directly because this may run at interrupt (i.e. signal handler) time)
}