ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/BeOS/video_beos.cpp
Revision: 1.3
Committed: 2004-04-18T23:03:51Z (20 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.2: +8 -8 lines
Log Message:
Start Native QuickDraw acceleration

File Contents

# Content
1 /*
2 * video_beos.cpp - Video/graphics emulation, BeOS specific things
3 *
4 * SheepShaver (C) 1997-2004 Marc Hellwig and Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sysdeps.h"
22
23 #include "video.h"
24 #include "video_defs.h"
25 #include "main.h"
26 #include "adb.h"
27 #include "prefs.h"
28 #include "user_strings.h"
29 #include "about_window.h"
30 #include "version.h"
31
32 #define DEBUG 0
33 #include "debug.h"
34
35
36 // Global variables
37 static sem_id video_lock = -1; // Protection during mode changes
38 static sem_id mac_os_lock = -1; // This is used to stop the MacOS thread when the SheepShaver workspace is switched out
39
40 // Prototypes
41 static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter);
42
43 // From sys_beos.cpp
44 extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg);
45 extern void SysMountVolume(const char *name);
46
47
48 #include "video_window.h"
49 #include "video_screen.h"
50
51
52 /*
53 * Display manager thread (for opening and closing windows and screens;
54 * this is not safe under R4 when running on the MacOS stack in kernel
55 * space)
56 */
57
58 // Message constants
59 const uint32 MSG_OPEN_WINDOW = 'owin';
60 const uint32 MSG_CLOSE_WINDOW = 'cwin';
61 const uint32 MSG_OPEN_SCREEN = 'oscr';
62 const uint32 MSG_CLOSE_SCREEN = 'cscr';
63 const uint32 MSG_QUIT_DISPLAY_MANAGER = 'quit';
64
65 static thread_id dm_thread = -1;
66 static sem_id dm_done_sem = -1;
67
68 static status_t display_manager(void *arg)
69 {
70 for (;;) {
71
72 // Receive message
73 thread_id sender;
74 uint32 code = receive_data(&sender, NULL, 0);
75 D(bug("Display manager received %08lx\n", code));
76 switch (code) {
77 case MSG_QUIT_DISPLAY_MANAGER:
78 return 0;
79
80 case MSG_OPEN_WINDOW:
81 D(bug("Opening window\n"));
82 the_window = new MacWindow(BRect(0, 0, VModes[cur_mode].viXsize-1, VModes[cur_mode].viYsize-1));
83 D(bug("Opened\n"));
84 break;
85
86 case MSG_CLOSE_WINDOW:
87 if (the_window != NULL) {
88 D(bug("Posting quit to window\n"));
89 the_window->PostMessage(B_QUIT_REQUESTED);
90 D(bug("Posted, waiting\n"));
91 while (the_window)
92 snooze(200000);
93 D(bug("Window closed\n"));
94 }
95 break;
96
97 case MSG_OPEN_SCREEN: {
98 D(bug("Opening screen\n"));
99 long scr_mode = 0;
100 switch (VModes[cur_mode].viAppleMode) {
101 case APPLE_8_BIT:
102 switch (VModes[cur_mode].viAppleID) {
103 case APPLE_640x480:
104 scr_mode = B_8_BIT_640x480;
105 break;
106 case APPLE_800x600:
107 scr_mode = B_8_BIT_800x600;
108 break;
109 case APPLE_1024x768:
110 scr_mode = B_8_BIT_1024x768;
111 break;
112 case APPLE_1152x900:
113 scr_mode = B_8_BIT_1152x900;
114 break;
115 case APPLE_1280x1024:
116 scr_mode = B_8_BIT_1280x1024;
117 break;
118 case APPLE_1600x1200:
119 scr_mode = B_8_BIT_1600x1200;
120 break;
121 }
122 break;
123 case APPLE_16_BIT:
124 switch (VModes[cur_mode].viAppleID) {
125 case APPLE_640x480:
126 scr_mode = B_15_BIT_640x480;
127 break;
128 case APPLE_800x600:
129 scr_mode = B_15_BIT_800x600;
130 break;
131 case APPLE_1024x768:
132 scr_mode = B_15_BIT_1024x768;
133 break;
134 case APPLE_1152x900:
135 scr_mode = B_15_BIT_1152x900;
136 break;
137 case APPLE_1280x1024:
138 scr_mode = B_15_BIT_1280x1024;
139 break;
140 case APPLE_1600x1200:
141 scr_mode = B_15_BIT_1600x1200;
142 break;
143 }
144 break;
145 case APPLE_32_BIT:
146 switch (VModes[cur_mode].viAppleID) {
147 case APPLE_640x480:
148 scr_mode = B_32_BIT_640x480;
149 break;
150 case APPLE_800x600:
151 scr_mode = B_32_BIT_800x600;
152 break;
153 case APPLE_1024x768:
154 scr_mode = B_32_BIT_1024x768;
155 break;
156 case APPLE_1152x900:
157 scr_mode = B_32_BIT_1152x900;
158 break;
159 case APPLE_1280x1024:
160 scr_mode = B_32_BIT_1280x1024;
161 break;
162 case APPLE_1600x1200:
163 scr_mode = B_32_BIT_1600x1200;
164 break;
165 }
166 break;
167 }
168 the_screen = new MacScreen(GetString(STR_WINDOW_TITLE), scr_mode);
169 D(bug("Opened, error %08lx\n", screen_error));
170 if (screen_error != B_NO_ERROR) {
171 D(bug("Error, posting quit to screen\n"));
172 the_screen->PostMessage(B_QUIT_REQUESTED);
173 D(bug("Posted, waiting\n"));
174 while (the_screen)
175 snooze(200000);
176 D(bug("Screen closed\n"));
177 break;
178 }
179
180 // Wait for video mem access
181 D(bug("Showing screen\n"));
182 the_screen->Show();
183 D(bug("Shown, waiting for frame buffer access\n"));
184 while (!drawing_enable)
185 snooze(200000);
186 D(bug("Access granted\n"));
187 break;
188 }
189
190 case MSG_CLOSE_SCREEN:
191 if (the_screen != NULL) {
192 D(bug("Posting quit to screen\n"));
193 the_screen->PostMessage(B_QUIT_REQUESTED);
194 D(bug("Posted, waiting\n"));
195 while (the_screen)
196 snooze(200000);
197 D(bug("Screen closed\n"));
198 }
199 break;
200 }
201
202 // Acknowledge
203 release_sem(dm_done_sem);
204 }
205 }
206
207
208 /*
209 * Open display (window or screen)
210 */
211
212 static void open_display(void)
213 {
214 D(bug("entering open_display()\n"));
215 display_type = VModes[cur_mode].viType;
216 if (display_type == DIS_SCREEN) {
217 while (send_data(dm_thread, MSG_OPEN_SCREEN, NULL, 0) == B_INTERRUPTED) ;
218 while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
219 } else if (display_type == DIS_WINDOW) {
220 while (send_data(dm_thread, MSG_OPEN_WINDOW, NULL, 0) == B_INTERRUPTED) ;
221 while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
222 }
223 D(bug("exiting open_display()\n"));
224 }
225
226
227 /*
228 * Close display
229 */
230
231 static void close_display(void)
232 {
233 D(bug("entering close_display()\n"));
234 if (display_type == DIS_SCREEN) {
235 while (send_data(dm_thread, MSG_CLOSE_SCREEN, NULL, 0) == B_INTERRUPTED) ;
236 while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
237 } else if (display_type == DIS_WINDOW) {
238 while (send_data(dm_thread, MSG_CLOSE_WINDOW, NULL, 0) == B_INTERRUPTED) ;
239 while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ;
240 }
241 D(bug("exiting close_display()\n"));
242 }
243
244
245 /*
246 * Initialization
247 */
248
249 static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type)
250 {
251 if (allow & test) {
252 p->viType = type;
253 switch (apple_id) {
254 case APPLE_W_640x480:
255 case APPLE_640x480:
256 p->viXsize = 640;
257 p->viYsize = 480;
258 break;
259 case APPLE_W_800x600:
260 case APPLE_800x600:
261 p->viXsize = 800;
262 p->viYsize = 600;
263 break;
264 case APPLE_1024x768:
265 p->viXsize = 1024;
266 p->viYsize = 768;
267 break;
268 case APPLE_1152x900:
269 p->viXsize = 1152;
270 p->viYsize = 900;
271 break;
272 case APPLE_1280x1024:
273 p->viXsize = 1280;
274 p->viYsize = 1024;
275 break;
276 case APPLE_1600x1200:
277 p->viXsize = 1600;
278 p->viYsize = 1200;
279 break;
280 }
281 switch (apple_mode) {
282 case APPLE_8_BIT:
283 p->viRowBytes = p->viXsize;
284 break;
285 case APPLE_16_BIT:
286 p->viRowBytes = p->viXsize * 2;
287 break;
288 case APPLE_32_BIT:
289 p->viRowBytes = p->viXsize * 4;
290 break;
291 }
292 p->viAppleMode = apple_mode;
293 p->viAppleID = apple_id;
294 p++;
295 }
296 }
297
298 bool VideoInit(void)
299 {
300 // Init variables, create semaphores
301 private_data = NULL;
302 cur_mode = 0; // Window 640x480
303 video_lock = create_sem(1, "Video Lock");
304 mac_os_lock = create_sem(0, "MacOS Frame Buffer Lock");
305 dm_done_sem = create_sem(0, "Display Manager Done");
306
307 // Construct video mode table
308 VideoInfo *p = VModes;
309 uint32 window_modes = PrefsFindInt32("windowmodes");
310 uint32 screen_modes = PrefsFindInt32("screenmodes");
311 if (window_modes == 0 && screen_modes == 0)
312 window_modes |= B_8_BIT_640x480 | B_8_BIT_800x600; // Allow at least 640x480 and 800x600 window modes
313 add_mode(p, window_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_W_640x480, DIS_WINDOW);
314 add_mode(p, window_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_W_800x600, DIS_WINDOW);
315 add_mode(p, window_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_W_640x480, DIS_WINDOW);
316 add_mode(p, window_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_W_800x600, DIS_WINDOW);
317 add_mode(p, window_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_W_640x480, DIS_WINDOW);
318 add_mode(p, window_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_W_800x600, DIS_WINDOW);
319 add_mode(p, screen_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_640x480, DIS_SCREEN);
320 add_mode(p, screen_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_800x600, DIS_SCREEN);
321 add_mode(p, screen_modes, B_8_BIT_1024x768, APPLE_8_BIT, APPLE_1024x768, DIS_SCREEN);
322 add_mode(p, screen_modes, B_8_BIT_1152x900, APPLE_8_BIT, APPLE_1152x900, DIS_SCREEN);
323 add_mode(p, screen_modes, B_8_BIT_1280x1024, APPLE_8_BIT, APPLE_1280x1024, DIS_SCREEN);
324 add_mode(p, screen_modes, B_8_BIT_1600x1200, APPLE_8_BIT, APPLE_1600x1200, DIS_SCREEN);
325 add_mode(p, screen_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_640x480, DIS_SCREEN);
326 add_mode(p, screen_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_800x600, DIS_SCREEN);
327 add_mode(p, screen_modes, B_15_BIT_1024x768, APPLE_16_BIT, APPLE_1024x768, DIS_SCREEN);
328 add_mode(p, screen_modes, B_15_BIT_1152x900, APPLE_16_BIT, APPLE_1152x900, DIS_SCREEN);
329 add_mode(p, screen_modes, B_15_BIT_1280x1024, APPLE_16_BIT, APPLE_1280x1024, DIS_SCREEN);
330 add_mode(p, screen_modes, B_15_BIT_1600x1200, APPLE_16_BIT, APPLE_1600x1200, DIS_SCREEN);
331 add_mode(p, screen_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_640x480, DIS_SCREEN);
332 add_mode(p, screen_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_800x600, DIS_SCREEN);
333 add_mode(p, screen_modes, B_32_BIT_1024x768, APPLE_32_BIT, APPLE_1024x768, DIS_SCREEN);
334 add_mode(p, screen_modes, B_32_BIT_1152x900, APPLE_32_BIT, APPLE_1152x900, DIS_SCREEN);
335 add_mode(p, screen_modes, B_32_BIT_1280x1024, APPLE_32_BIT, APPLE_1280x1024, DIS_SCREEN);
336 add_mode(p, screen_modes, B_32_BIT_1600x1200, APPLE_32_BIT, APPLE_1600x1200, DIS_SCREEN);
337 p->viType = DIS_INVALID; // End marker
338 p->viRowBytes = 0;
339 p->viXsize = p->viYsize = 0;
340 p->viAppleMode = 0;
341 p->viAppleID = 0;
342
343 // Start display manager thread
344 dm_thread = spawn_thread(display_manager, "Display Manager", B_NORMAL_PRIORITY, NULL);
345 resume_thread(dm_thread);
346
347 // Open window/screen
348 open_display();
349 if (display_type == DIS_SCREEN && the_screen == NULL) {
350 char str[256];
351 sprintf(str, GetString(STR_FULL_SCREEN_ERR), strerror(screen_error), screen_error);
352 ErrorAlert(str);
353 return false;
354 }
355 return true;
356 }
357
358
359 /*
360 * Deinitialization
361 */
362
363 void VideoExit(void)
364 {
365 if (dm_thread >= 0) {
366
367 // Close display
368 acquire_sem(video_lock);
369 close_display();
370 if (private_data != NULL) {
371 delete private_data->gammaTable;
372 delete private_data;
373 }
374
375 // Stop display manager
376 status_t l;
377 send_data(dm_thread, MSG_QUIT_DISPLAY_MANAGER, NULL, 0);
378 while (wait_for_thread(dm_thread, &l) == B_INTERRUPTED) ;
379 }
380
381 // Delete semaphores
382 delete_sem(video_lock);
383 delete_sem(mac_os_lock);
384 delete_sem(dm_done_sem);
385 }
386
387
388 /*
389 * Close screen in full-screen mode
390 */
391
392 void VideoQuitFullScreen(void)
393 {
394 D(bug("VideoQuitFullScreen()\n"));
395 if (display_type == DIS_SCREEN) {
396 acquire_sem(video_lock);
397 close_display();
398 release_sem(video_lock);
399 }
400 }
401
402
403 /*
404 * Execute video VBL routine
405 */
406
407 void VideoVBL(void)
408 {
409 release_sem(mac_os_lock);
410 if (private_data != NULL && private_data->interruptsEnabled)
411 VSLDoInterruptService(private_data->vslServiceID);
412 while (acquire_sem(mac_os_lock) == B_INTERRUPTED) ;
413 }
414
415
416 /*
417 * Filter function for receiving mouse and keyboard events
418 */
419
420 #define MENU_IS_POWER 0
421
422 // Be -> Mac raw keycode translation table
423 static const uint8 keycode2mac[0x80] = {
424 0xff, 0x35, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, // inv Esc F1 F2 F3 F4 F5 F6
425 0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b, // F7 F8 F9 F10 F11 F12 F13 F14
426 0x71, 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, // F15 ` 1 2 3 4 5 6
427 0x1a, 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x33, 0x72, // 7 8 9 0 - = BSP INS
428 0x73, 0x74, 0x47, 0x4b, 0x43, 0x4e, 0x30, 0x0c, // HOM PUP NUM / * - TAB Q
429 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, 0x1f, // W E R T Y U I O
430 0x23, 0x21, 0x1e, 0x2a, 0x75, 0x77, 0x79, 0x59, // P [ ] \ DEL END PDN 7
431 0x5b, 0x5c, 0x45, 0x39, 0x00, 0x01, 0x02, 0x03, // 8 9 + CAP A S D F
432 0x05, 0x04, 0x26, 0x28, 0x25, 0x29, 0x27, 0x24, // G H J K L ; ' RET
433 0x56, 0x57, 0x58, 0x38, 0x06, 0x07, 0x08, 0x09, // 4 5 6 SHL Z X C V
434 0x0b, 0x2d, 0x2e, 0x2b, 0x2f, 0x2c, 0x38, 0x3e, // B N M , . / SHR CUP
435 0x53, 0x54, 0x55, 0x4c, 0x36, 0x37, 0x31, 0x37, // 1 2 3 ENT CTL ALT SPC ALT
436 0x36, 0x3b, 0x3d, 0x3c, 0x52, 0x41, 0x3a, 0x3a, // CTR CLF CDN CRT 0 . CMD CMD
437 #if MENU_IS_POWER
438 0x7f, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv
439 #else
440 0x32, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv
441 #endif
442 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
443 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv
444 };
445
446 static const uint8 modifier2mac[0x20] = {
447 #if MENU_IS_POWER
448 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x7f, // SHF CMD inv CAP F14 NUM OPT MNU
449 #else
450 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x32, // SHF CMD CTR CAP F14 NUM OPT MNU
451 #endif
452 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
454 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv
455 };
456
457 static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter)
458 {
459 // msg->PrintToStream();
460 switch (msg->what) {
461 case B_KEY_DOWN:
462 case B_KEY_UP: {
463 uint32 be_code = msg->FindInt32("key") & 0xff;
464 uint32 mac_code = keycode2mac[be_code];
465
466 // Intercept Ctrl-F1 (mount floppy disk shortcut)
467 uint32 mods = msg->FindInt32("modifiers");
468 if (be_code == 0x02 && (mods & B_CONTROL_KEY))
469 SysMountVolume("/dev/disk/floppy/raw");
470
471 if (mac_code == 0xff)
472 return B_DISPATCH_MESSAGE;
473 if (msg->what == B_KEY_DOWN)
474 ADBKeyDown(mac_code);
475 else
476 ADBKeyUp(mac_code);
477 return B_SKIP_MESSAGE;
478 }
479
480 case B_MODIFIERS_CHANGED: {
481 uint32 mods = msg->FindInt32("modifiers");
482 uint32 old_mods = msg->FindInt32("be:old_modifiers");
483 uint32 changed = mods ^ old_mods;
484 uint32 mask = 1;
485 for (int i=0; i<32; i++, mask<<=1)
486 if (changed & mask) {
487 uint32 mac_code = modifier2mac[i];
488 if (mac_code == 0xff)
489 continue;
490 if (mods & mask)
491 ADBKeyDown(mac_code);
492 else
493 ADBKeyUp(mac_code);
494 }
495 return B_SKIP_MESSAGE;
496 }
497
498 case B_MOUSE_MOVED: {
499 BPoint point;
500 msg->FindPoint("where", &point);
501 ADBMouseMoved(int(point.x), int(point.y));
502 return B_DISPATCH_MESSAGE; // Otherwise BitmapView::MouseMoved() wouldn't be called
503 }
504
505 case B_MOUSE_DOWN: {
506 uint32 buttons = msg->FindInt32("buttons");
507 if (buttons & B_PRIMARY_MOUSE_BUTTON)
508 ADBMouseDown(0);
509 if (buttons & B_SECONDARY_MOUSE_BUTTON)
510 ADBMouseDown(1);
511 if (buttons & B_TERTIARY_MOUSE_BUTTON)
512 ADBMouseDown(2);
513 return B_SKIP_MESSAGE;
514 }
515
516 case B_MOUSE_UP: // B_MOUSE_UP means "all buttons released"
517 ADBMouseUp(0);
518 ADBMouseUp(1);
519 ADBMouseUp(2);
520 return B_SKIP_MESSAGE;
521
522 default:
523 return B_DISPATCH_MESSAGE;
524 }
525 }
526
527
528 /*
529 * Install graphics acceleration
530 */
531
532 // Rectangle blitting
533 static void accl_bitblt(accl_params *p)
534 {
535 D(bug("accl_bitblt\n"));
536
537 // Get blitting parameters
538 int16 src_X = p->src_rect[1] - p->src_bounds[1];
539 int16 src_Y = p->src_rect[0] - p->src_bounds[0];
540 int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
541 int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
542 int16 width = p->dest_rect[3] - p->dest_rect[1] - 1;
543 int16 height = p->dest_rect[2] - p->dest_rect[0] - 1;
544 D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y));
545 D(bug(" width %d, height %d\n", width, height));
546
547 // And perform the blit
548 bitblt_hook(src_X, src_Y, dest_X, dest_Y, width, height);
549 }
550
551 static bool accl_bitblt_hook(accl_params *p)
552 {
553 D(bug("accl_draw_hook %p\n", p));
554
555 // Check if we can accelerate this bitblt
556 if (p->src_base_addr == screen_base && p->dest_base_addr == screen_base &&
557 display_type == DIS_SCREEN && bitblt_hook != NULL &&
558 ((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 &&
559 ((uint32 *)p)[0x130 >> 2] == 0 &&
560 p->transfer_mode == 0 &&
561 p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) {
562
563 // Yes, set function pointer
564 p->draw_proc = (uint32)accl_bitblt;
565 return true;
566 }
567 return false;
568 }
569
570 // Rectangle filling/inversion
571 static void accl_fillrect8(accl_params *p)
572 {
573 D(bug("accl_fillrect8\n"));
574
575 // Get filling parameters
576 int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
577 int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
578 int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1;
579 int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1;
580 uint8 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen;
581 D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
582 D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max));
583
584 // And perform the fill
585 fillrect8_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color);
586 }
587
588 static void accl_fillrect32(accl_params *p)
589 {
590 D(bug("accl_fillrect32\n"));
591
592 // Get filling parameters
593 int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
594 int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
595 int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1;
596 int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1;
597 uint32 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen;
598 D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
599 D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max));
600
601 // And perform the fill
602 fillrect32_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color);
603 }
604
605 static void accl_invrect(accl_params *p)
606 {
607 D(bug("accl_invrect\n"));
608
609 // Get inversion parameters
610 int16 dest_X = p->dest_rect[1] - p->dest_bounds[1];
611 int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0];
612 int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1;
613 int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1;
614 D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
615 D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max));
616
617 //!!?? pen_mode == 14
618
619 // And perform the inversion
620 invrect_hook(dest_X, dest_Y, dest_X_max, dest_Y_max);
621 }
622
623 static bool accl_fillrect_hook(accl_params *p)
624 {
625 D(bug("accl_fillrect_hook %p\n", p));
626
627 // Check if we can accelerate this fillrect
628 if (p->dest_base_addr == screen_base && ((uint32 *)p)[0x284 >> 2] != 0 && display_type == DIS_SCREEN) {
629 if (p->transfer_mode == 8) {
630 // Fill
631 if (p->dest_pixel_size == 8 && fillrect8_hook != NULL) {
632 p->draw_proc = (uint32)accl_fillrect8;
633 return true;
634 } else if (p->dest_pixel_size == 32 && fillrect32_hook != NULL) {
635 p->draw_proc = (uint32)accl_fillrect32;
636 return true;
637 }
638 } else if (p->transfer_mode == 10 && invrect_hook != NULL) {
639 // Invert
640 p->draw_proc = (uint32)accl_invrect;
641 return true;
642 }
643 }
644 return false;
645 }
646
647 // Dummy for testing
648 /*
649 static void do_nothing(accl_params *p) {}
650 static bool accl_foobar_hook(accl_params *p)
651 {
652 printf("accl_foobar_hook %p\n", p);
653 printf(" src_base_addr %p, dest_base_addr %p\n", p->src_base_addr, p->dest_base_addr);
654 printf(" src_row_bytes %d, dest_row_bytes %d\n", p->src_row_bytes, p->dest_row_bytes);
655 printf(" src_pixel_size %d, dest_pixel_size %d\n", p->src_pixel_size, p->dest_pixel_size);
656 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]);
657 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]);
658 printf(" transfer mode %d\n", p->transfer_mode);
659 printf(" pen mode %d\n", p->pen_mode);
660 printf(" fore_pen %08x, back_pen %08x\n", p->fore_pen, p->back_pen);
661 printf(" val1 %08x, val2 %08x\n", ((uint32 *)p)[0x18 >> 2], ((uint32 *)p)[0x128 >> 2]);
662 printf(" val3 %08x\n", ((uint32 *)p)[0x130 >> 2]);
663 printf(" val4 %08x\n", ((uint32 *)p)[0x15c >> 2]);
664 printf(" val5 %08x\n", ((uint32 *)p)[0x160 >> 2]);
665 printf(" val6 %08x\n", ((uint32 *)p)[0x1b4 >> 2]);
666 printf(" val7 %08x\n", ((uint32 *)p)[0x284 >> 2]);
667 p->draw_proc = (uint32)do_nothing;
668 return true;
669 }
670 static struct accl_hook_info foobar_hook_info = {(uint32)accl_foobar_hook, (uint32)accl_sync_hook, 6};
671 */
672
673 // Wait for graphics operation to finish
674 static bool accl_sync_hook(void *arg)
675 {
676 D(bug("accl_sync_hook %p\n", arg));
677 if (sync_hook != NULL)
678 sync_hook();
679 return true;
680 }
681
682 static struct accl_hook_info bitblt_hook_info = {(uint32)accl_bitblt_hook, (uint32)accl_sync_hook, ACCL_BITBLT};
683 static struct accl_hook_info fillrect_hook_info = {(uint32)accl_fillrect_hook, (uint32)accl_sync_hook, ACCL_FILLRECT};
684
685 void VideoInstallAccel(void)
686 {
687 // Install acceleration hooks
688 if (PrefsFindBool("gfxaccel")) {
689 D(bug("Video: Installing acceleration hooks\n"));
690 NQDMisc(6, &bitblt_hook_info);
691 NQDMisc(6, &fillrect_hook_info);
692 }
693 }
694
695
696 /*
697 * Change video mode
698 */
699
700 int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr)
701 {
702 /* return if no mode change */
703 if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) &&
704 (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr;
705
706 /* first find video mode in table */
707 for (int i=0; VModes[i].viType != DIS_INVALID; i++) {
708 if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) &&
709 (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) {
710 csSave->saveMode = ReadMacInt16(ParamPtr + csMode);
711 csSave->saveData = ReadMacInt32(ParamPtr + csData);
712 csSave->savePage = ReadMacInt16(ParamPtr + csPage);
713
714 while (acquire_sem(video_lock) == B_INTERRUPTED) ;
715 DisableInterrupt();
716
717 /* close old display */
718 close_display();
719
720 /* open new display */
721 cur_mode = i;
722 open_display();
723
724 /* opening the screen failed? Then bail out */
725 if (display_type == DIS_SCREEN && the_screen == NULL) {
726 release_sem(video_lock);
727 ErrorAlert(GetString(STR_FULL_SCREEN_ERR));
728 QuitEmulator();
729 }
730
731 WriteMacInt32(ParamPtr + csBaseAddr, screen_base);
732 csSave->saveBaseAddr=screen_base;
733 csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */
734 csSave->saveMode=VModes[cur_mode].viAppleMode;
735
736 EnableInterrupt();
737 release_sem(video_lock);
738 return noErr;
739 }
740 }
741 return paramErr;
742 }
743
744
745 /*
746 * Set color palette
747 */
748
749 void video_set_palette(void)
750 {
751 if (display_type == DIS_SCREEN && the_screen != NULL)
752 the_screen->palette_changed = true;
753 else { // remap colors to BeOS-Palette
754 BScreen screen;
755 for (int i=0;i<256;i++)
756 remap_mac_be[i]=screen.IndexForColor(mac_pal[i].red,mac_pal[i].green,mac_pal[i].blue);
757 }
758 }
759
760
761 /*
762 * Set cursor image for window
763 */
764
765 void video_set_cursor(void)
766 {
767 the_window->cursor_changed = true; // Inform window (don't set cursor directly because this may run at interrupt (i.e. signal handler) time)
768 }