ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/video_macosx.mm
(Generate patch)

Comparing BasiliskII/src/MacOSX/video_macosx.mm (file contents):
Revision 1.4 by nigel, 2002-06-05T10:11:40Z vs.
Revision 1.15 by gbeauche, 2005-01-30T21:42:13Z

# Line 4 | Line 4
4   *  video_macosx.mm - Interface between Basilisk II and Cocoa windowing.
5   *                    Based on video_amiga.cpp and video_x.cpp
6   *
7 < *  Basilisk II (C) 1997-2002 Christian Bauer
7 > *  Basilisk II (C) 1997-2005 Christian Bauer
8   *
9   *  This program is free software; you can redistribute it and/or modify
10   *  it under the terms of the GNU General Public License as published by
# Line 32 | Line 32
32   #include <cpu_emulation.h>
33   #include <main.h>
34   #include "macos_util_macosx.h"
35 #include "main_macosx.h"
35   #include <prefs.h>
36   #include <user_strings.h>
37   #include "video_macosx.h"
38  
39   #define DEBUG 0
40 + #define VERBOSE 0
41   #include "debug.h"
42  
43 + #ifdef NSBITMAP
44 + #import <AppKit/NSBitmapImageRep.h>
45 + #endif
46 +
47   #import <Foundation/NSString.h>                         // Needed for NSLog(@"")
48   #import "misc_macosx.h"                                         // WarningSheet() prototype
49  
# Line 54 | Line 58 | uint16         init_width  = MIN_WIDTH,                // as
58  
59                  EmulatorView    *output = nil;          // Set by [EmulatorView init]
60                  NSWindow                *the_win = nil;         // Set by [Emulator awakeFromNib]
57 static  void                    *the_buffer = NULL;
58
59
60 #ifdef CGIMAGEREF
61 static CGImageRef               imageRef = nil;
62 #endif
63
64 #ifdef NSBITMAP
65 #import <AppKit/NSBitmapImageRep.h>
66
67 static NSBitmapImageRep *bitmap = nil;
68 #endif
69
70 // These record changes we made in setting full screen mode
71 static CGDirectDisplayID        theDisplay   = NULL;
72 static CFDictionaryRef          originalMode = NULL,
73                                                        newMode      = NULL;
74 static BOOL                                     singleDisplay = YES;
75
76
77 // Prototypes
78
79 static bool video_open  (const video_mode &mode);
80 static void video_close (void);
81
61  
62 + static  BOOL                    singleDisplay = YES;
63  
64   /*
65   *  Utility functions
# Line 121 | Line 101 | colours_from_depth(const uint16 depth)
101   bool
102   parse_screen_prefs(const char *mode_str)
103   {
104 +        if ( ! mode_str )
105 +        {
106 +                // No screen pref was found. Supply a default:
107 +                mode_str = "win/512/384";
108 +        }
109 +
110          if (sscanf(mode_str, "win/%hd/%hd/%hd",
111                                  &init_width, &init_height, &init_depth) == 3)
112                  display_type = DISPLAY_WINDOW;
# Line 143 | Line 129 | parse_screen_prefs(const char *mode_str)
129          return true;
130   }
131  
132 + // Supported video modes
133 + static vector<video_mode> VideoModes;
134 +
135  
136   // Add mode to list of supported modes
137   static void
138   add_mode(const uint16 width, const uint16 height,
139                   const uint32 resolution_id, const uint32 bytes_per_row,
140 +                 const uint32 user_data,
141                   const video_depth depth)
142   {
143          vector<video_mode>::const_iterator      i,
# Line 168 | Line 158 | add_mode(const uint16 width, const uint1
158          mode.y = height;
159          mode.resolution_id = resolution_id;
160          mode.bytes_per_row = bytes_per_row;
161 +        mode.user_data = user_data;
162          mode.depth = depth;
163  
164          D(bug("Added video mode: w=%d  h=%d  d=%d(%d bits)\n",
# Line 182 | Line 173 | static void add_standard_modes(const vid
173          D(bug("add_standard_modes: depth=%d(%d bits)\n",
174                                                  depth, bits_from_depth(depth) ));
175  
176 <        add_mode(512,  384,  0x80, TrivialBytesPerRow(512,  depth), depth);
177 <        add_mode(640,  480,  0x81, TrivialBytesPerRow(640,  depth), depth);
178 <        add_mode(800,  600,  0x82, TrivialBytesPerRow(800,  depth), depth);
179 <        add_mode(832,  624,  0x83, TrivialBytesPerRow(832,  depth), depth);
180 <        add_mode(1024, 768,  0x84, TrivialBytesPerRow(1024, depth), depth);
181 <        add_mode(1152, 768,  0x85, TrivialBytesPerRow(1152, depth), depth);
182 <        add_mode(1152, 870,  0x86, TrivialBytesPerRow(1152, depth), depth);
183 <        add_mode(1280, 1024, 0x87, TrivialBytesPerRow(1280, depth), depth);
184 <        add_mode(1600, 1200, 0x88, TrivialBytesPerRow(1600, depth), depth);
176 >        add_mode(512,  384,  0x80, TrivialBytesPerRow(512,  depth), 0, depth);
177 >        add_mode(640,  480,  0x81, TrivialBytesPerRow(640,  depth), 0, depth);
178 >        add_mode(800,  600,  0x82, TrivialBytesPerRow(800,  depth), 0, depth);
179 >        add_mode(832,  624,  0x83, TrivialBytesPerRow(832,  depth), 0, depth);
180 >        add_mode(1024, 768,  0x84, TrivialBytesPerRow(1024, depth), 0, depth);
181 >        add_mode(1152, 768,  0x85, TrivialBytesPerRow(1152, depth), 0, depth);
182 >        add_mode(1152, 870,  0x86, TrivialBytesPerRow(1152, depth), 0, depth);
183 >        add_mode(1280, 1024, 0x87, TrivialBytesPerRow(1280, depth), 0, depth);
184 >        add_mode(1600, 1200, 0x88, TrivialBytesPerRow(1600, depth), 0, depth);
185   }
186  
187   // Helper function to get a 32bit int from a dictionary
188   static int32 getCFint32 (CFDictionaryRef dict, CFStringRef key)
189   {
190 <        CFNumberRef     ref = CFDictionaryGetValue(dict, key);
190 >        CFNumberRef     ref = (CFNumberRef) CFDictionaryGetValue(dict, key);
191  
192          if ( ref )
193          {
# Line 213 | Line 204 | static int32 getCFint32 (CFDictionaryRef
204          return 0;
205   }
206  
207 + // Nasty hack. Under 10.1, CGDisplayAvailableModes() does not provide bytes per row,
208 + // and the emulator doesn't like setting the bytes per row after the screen,
209 + // so we use a lot of magic numbers here.
210 + // This will probably fail on some video hardware.
211 + // I have tested on my G4 PowerBook 400 and G3 PowerBook Series 292
212 +
213 + static int
214 + CGBytesPerRow(const uint16 width, const video_depth depth)
215 + {
216 +        if ( depth == VDEPTH_8BIT )
217 +                switch ( width )
218 +                {
219 +                        case 640:
220 +                        case 720:       return 768;
221 +                        case 800:
222 +                        case 896:       return 1024;
223 +                        case 1152:      return 1280;
224 +                }
225 +
226 +        if ( width == 720  && depth == VDEPTH_16BIT)    return 1536;
227 +        if ( width == 720  && depth == VDEPTH_32BIT)    return 3072;
228 +        if ( width == 800  && depth == VDEPTH_16BIT)    return 1792;
229 +        if ( width == 800  && depth == VDEPTH_32BIT)    return 3328;
230 +
231 +        return TrivialBytesPerRow(width, depth);
232 + }
233 +
234   static bool add_CGDirectDisplay_modes()
235   {
236   #define kMaxDisplays 8
# Line 239 | Line 257 | static bool add_CGDirectDisplay_modes()
257                          add_mode(CGDisplayPixelsWide(d),
258                                           CGDisplayPixelsHigh(d),
259                                           res_id++, CGDisplayBytesPerRow(d),
260 +                                         (const uint32) d,
261                                           DepthModeForPixelDepth(CGDisplayBitsPerPixel(d)));
262                  else
263                  {
# Line 246 | Line 265 | static bool add_CGDirectDisplay_modes()
265  
266                          for ( CFIndex mc = 0; mc < nModes; ++mc )
267                          {
268 <                                CFDictionaryRef modeSpec = CFArrayGetValueAtIndex(m, mc);
268 >                                CFDictionaryRef modeSpec = (CFDictionaryRef)
269 >                                                                                        CFArrayGetValueAtIndex(m, mc);
270  
271                                  int32   bpp    = getCFint32(modeSpec, kCGDisplayBitsPerPixel);
272                                  int32   height = getCFint32(modeSpec, kCGDisplayHeight);
273                                  int32   width  = getCFint32(modeSpec, kCGDisplayWidth);
274 + #ifdef MAC_OS_X_VERSION_10_2
275 +                                int32   bytes  = getCFint32(modeSpec, kCGDisplayBytesPerRow);
276 + #else
277 +                                int32   bytes  = 0;
278 + #endif
279                                  video_depth     depth = DepthModeForPixelDepth(bpp);
280  
281                                  if ( ! bpp || ! height || ! width )
# Line 264 | Line 289 | static bool add_CGDirectDisplay_modes()
289                                          NSLog(@"Display %ld, spec = %@", d, modeSpec);
290   #endif
291  
292 +                                if ( ! bytes )
293 +                                {
294 +                                        NSLog(@"Could not get bytes per row, guessing");
295 +                                        bytes = CGBytesPerRow(width, depth);
296 +                                }
297 +
298                                  if ( ! oldRes )
299                                          oldRes = width * height;
300                                  else
# Line 273 | Line 304 | static bool add_CGDirectDisplay_modes()
304                                                  ++res_id;
305                                          }
306  
307 <                                add_mode(width, height, res_id, 0, depth);
307 >                                add_mode(width, height, res_id, bytes, (const uint32) d, depth);
308                          }
309                  }
310          }
# Line 281 | Line 312 | static bool add_CGDirectDisplay_modes()
312          return true;
313   }
314  
315 + #ifdef CG_USE_ALPHA
316 + // memset() by long instead of byte
317 +
318 + static void memsetl (long *buffer, long pattern, size_t length)
319 + {
320 +        long    *buf = (long *) buffer,
321 +                        *end = buf + length/4;
322 +
323 +        while ( ++buf < end )
324 +                *buf = pattern;
325 + }
326 +
327 + // Sets the alpha channel in a image to full on, except for the corners
328 +
329 + static void mask_buffer (void *buffer, size_t width, size_t size)
330 + {
331 +        long    *bufl = (long *) buffer;
332 +        char    *bufc = (char *) buffer;
333 +
334 +
335 +        memsetl(bufl, 0xFF000000, size);
336 +
337 +
338 +        // Round upper-left corner
339 +                                   *bufl = 0, *bufc+4 = 0;                                      // XXXXX
340 +        bufc += width, *bufc++ = 0, *bufc++ = 0, *bufc++ = 0;   // XXX
341 +        bufc += width, *bufc++ = 0, *bufc = 0;                                  // XX
342 +        bufc += width, *bufc = 0;                                                               // X
343 +        bufc += width, *bufc = 0;                                                               // X
344 +
345 +
346 +        NSLog(@"Masked buffer");
347 + }
348 + #endif
349 +
350 + // monitor_desc subclass for Mac OS X displays
351 +
352 + class OSX_monitor : public monitor_desc
353 + {
354 +        public:
355 +                OSX_monitor(const vector<video_mode>    &available_modes,
356 +                                        video_depth                                     default_depth,
357 +                                        uint32                                          default_id);
358 +
359 +                virtual void set_palette(uint8 *pal, int num);
360 +                virtual void switch_to_current_mode(void);
361 +
362 +                                void set_mac_frame_buffer(const video_mode mode);
363 +
364 +                                void video_close(void);
365 +                                bool video_open (const video_mode &mode);
366 +
367 +
368 +        private:
369 +                bool init_opengl(const video_mode &mode);
370 +                bool init_screen(      video_mode &mode);
371 +                bool init_window(const video_mode &mode);
372 +
373 +
374 + #ifdef CGIMAGEREF
375 +                CGColorSpaceRef         colourSpace;
376 +                uint8                           *colourTable;
377 +                CGImageRef                      imageRef;
378 +                CGDataProviderRef       provider;
379 +                short                           x, y, bpp, depth, bpr;
380 + #endif
381 + #ifdef NSBITMAP
382 +                NSBitmapImageRep        *bitmap;
383 + #endif
384 +                void                            *the_buffer;
385 +
386 +
387 +                // These record changes we made in setting full screen mode,
388 +                // so that we can set the display back as it was again.
389 +                CGDirectDisplayID       theDisplay;
390 +                CFDictionaryRef         originalMode,
391 +                                                        newMode;
392 + };
393 +
394 +
395 + OSX_monitor :: OSX_monitor (const       vector<video_mode>      &available_modes,
396 +                                                                        video_depth                     default_depth,
397 +                                                                        uint32                          default_id)
398 +                        : monitor_desc (available_modes, default_depth, default_id)
399 + {
400 + #ifdef CGIMAGEREF
401 +        colourSpace = nil;
402 +        colourTable = (uint8 *) malloc(256 * 3);
403 +        imageRef = nil;
404 +        provider = nil;
405 + #endif
406 + #ifdef NSBITMAP
407 +        bitmap = nil;
408 + #endif
409 +        newMode = originalMode = nil;
410 +        the_buffer = NULL;
411 +        theDisplay = nil;
412 + };
413 +
414 + // Should also have a destructor which does
415 + //#ifdef CGIMAGEREF
416 + //      free(colourTable);
417 + //#endif
418 +
419 +
420   // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac)
421 < static void set_mac_frame_buffer(const video_depth depth)
421 > void
422 > OSX_monitor::set_mac_frame_buffer(const video_mode mode)
423   {
424   #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
425 <        switch ( depth )
425 >        switch ( mode.depth )
426          {
427          //      case VDEPTH_15BIT:
428                  case VDEPTH_16BIT: MacFrameLayout = FLAYOUT_HOST_555; break;
# Line 293 | Line 430 | static void set_mac_frame_buffer(const v
430                  case VDEPTH_32BIT: MacFrameLayout = FLAYOUT_HOST_888; break;
431                  default                  : MacFrameLayout = FLAYOUT_DIRECT;
432          }
433 <        VideoMonitor.mac_frame_base = MacFrameBaseMac;
433 >        set_mac_frame_base(MacFrameBaseMac);
434  
435          // Set variables used by UAE memory banking
436 <        MacFrameBaseHost = the_buffer;
437 <        MacFrameSize = VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y;
436 >        MacFrameBaseHost = (uint8 *) the_buffer;
437 >        MacFrameSize = mode.bytes_per_row * mode.y;
438          InitFrameBufferMapping();
439   #else
440 <        VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer);
440 >        set_mac_frame_base((unsigned int)Host2MacAddr((uint8 *)the_buffer));
441   #endif
442 <        D(bug("VideoMonitor.mac_frame_base = %08x\n", VideoMonitor.mac_frame_base));
442 >        D(bug("mac_frame_base = %08x\n", get_mac_frame_base()));
443   }
444  
445   static void
# Line 318 | Line 455 | resizeWinBy(const short deltaX, const sh
455  
456          D(bug(", new x=%g, y=%g\n", rect.size.width, rect.size.height));
457  
458 <        [the_win setFrame: rect display: YES];
458 >        [the_win setFrame: rect display: YES animate: YES];
459 >        [the_win center];
460          rect = [the_win frame];
461   }
462  
# Line 334 | Line 472 | void resizeWinTo(const uint16 newWidth,
472   }
473  
474   // Open window
475 < static bool init_window(const video_mode &mode)
475 > bool
476 > OSX_monitor::init_window(const video_mode &mode)
477   {
339 #ifdef CGIMAGEREF
340        CGColorSpaceRef         colourSpace;
341        CGDataProviderRef       provider;
342 #endif
343        short                           bitsPer, samplesPer;    // How big is each Pixel?
344        int                                     the_buffer_size;
345
478          D(bug("init_window: depth=%d(%d bits)\n",
479                          mode.depth, bits_from_depth(mode.depth) ));
480  
# Line 351 | Line 483 | static bool init_window(const video_mode
483          ADBSetRelMouseMode(false);
484  
485  
486 <        // Open window
486 >        // Is the window open?
487          if ( ! the_win )
488          {
489                  ErrorAlert(STR_OPEN_WINDOW_ERR);
# Line 361 | Line 493 | static bool init_window(const video_mode
493  
494  
495          // Create frame buffer ("height + 2" for safety)
496 <        the_buffer_size = mode.bytes_per_row * (mode.y + 2);
496 >        int the_buffer_size = mode.bytes_per_row * (mode.y + 2);
497 >
498          the_buffer = calloc(the_buffer_size, 1);
499          if ( ! the_buffer )
500          {
# Line 372 | Line 505 | static bool init_window(const video_mode
505          D(bug("the_buffer = %p\n", the_buffer));
506  
507  
508 <        if ( mode.depth == VDEPTH_1BIT )
509 <                bitsPer = 1;
377 <        else
378 <                bitsPer = 8;
379 <
380 <        if ( mode.depth == VDEPTH_32BIT )
381 <                samplesPer = 3;
382 <        else
383 <                samplesPer = 1;
508 >        unsigned char *offsetBuffer = (unsigned char *) the_buffer;
509 >        offsetBuffer += 1;              // OS X NSBitmaps are RGBA, but Basilisk generates ARGB
510  
511   #ifdef CGIMAGEREF
512          switch ( mode.depth )
513          {
514 <                //case VDEPTH_1BIT:     colourSpace = CGColorSpaceCreateDeviceMono(); break
515 <                case VDEPTH_8BIT:       colourSpace = CGColorSpaceCreateDeviceGray(); break;
516 <                case VDEPTH_32BIT:      colourSpace = CGColorSpaceCreateDeviceRGB();  break;
517 <                default:                        colourSpace = NULL;
514 >                case VDEPTH_1BIT:       bpp = 1; break;
515 >                case VDEPTH_2BIT:       bpp = 2; break;
516 >                case VDEPTH_4BIT:       bpp = 4; break;
517 >                case VDEPTH_8BIT:       bpp = 8; break;
518 >                case VDEPTH_16BIT:      bpp = 5; break;
519 >                case VDEPTH_32BIT:      bpp = 8; break;
520 >        }
521 >
522 >        x = mode.x, y = mode.y, depth = bits_from_depth(mode.depth), bpr = mode.bytes_per_row;
523 >
524 >        colourSpace = CGColorSpaceCreateDeviceRGB();
525 >
526 >        if ( mode.depth < VDEPTH_16BIT )
527 >        {
528 >                CGColorSpaceRef oldColourSpace = colourSpace;
529 >
530 >                colourSpace = CGColorSpaceCreateIndexed(colourSpace, 255, colourTable);
531 >
532 >                CGColorSpaceRelease(oldColourSpace);
533          }
534  
535          if ( ! colourSpace )
# Line 404 | Line 545 | static bool init_window(const video_mode
545                  ErrorAlert("Could not create CGDataProvider from buffer data");
546                  return false;
547          }
548 <        imageRef = CGImageCreate(mode.x,
549 <                                                         mode.y,
550 <                                                         bitsPer,
551 <                                                         bits_from_depth(mode.depth),
552 <                                                         mode.bytes_per_row,
412 <                                                         colourSpace,
548 >
549 >        imageRef = CGImageCreate(x, y, bpp, depth, bpr, colourSpace,
550 >  #ifdef CG_USE_ALPHA
551 >                                                         kCGImageAlphaPremultipliedFirst,
552 >  #else
553                                                           kCGImageAlphaNoneSkipFirst,
554 +  #endif
555                                                           provider,
556 <                                                         NULL,  // colourMap
557 <                                                         NO,    // shouldInterpolate
556 >                                                         NULL,  // colourMap translation table
557 >                                                         NO,    // shouldInterpolate colours?
558                                                           kCGRenderingIntentDefault);
559          if ( ! imageRef )
560          {
561                  ErrorAlert("Could not create CGImage from CGDataProvider");
562                  return false;
563          }
423        CGDataProviderRelease(provider);
424        CGColorSpaceRelease(colourSpace);
564  
565          [output readyToDraw: imageRef
566 <                         imageWidth: mode.x
567 <                        imageHeight: mode.y];
568 < #else
569 <        unsigned char *offsetBuffer = the_buffer;
570 <        offsetBuffer += 1;      // OS X NSBitmaps are RGBA, but Basilisk generates ARGB
566 >                                 bitmap: offsetBuffer
567 >                         imageWidth: x
568 >                        imageHeight: y];
569 >
570 >
571 >  #ifdef CG_USE_ALPHA
572 >        mask_buffer(the_buffer, x, the_buffer_size);
573 >
574 > /* Create an image mask with this call? */
575 > //CG_EXTERN CGImageRef
576 > //CGImageMaskCreate(size_t width, size_t height, size_t bitsPerComponent,
577 > //                                      size_t bitsPerPixel, size_t bytesPerRow,
578 > //                                      CGDataProviderRef provider, const float decode[], bool shouldInterpolate);
579 >  #endif
580 >
581 >        return true;
582 > #endif
583 >
584 >
585 > #ifndef CGIMAGEREF
586 >        short   bitsPer, samplesPer;    // How big is each Pixel?
587 >
588 >        if ( mode.depth == VDEPTH_1BIT )
589 >                bitsPer = 1;
590 >        else
591 >                bitsPer = 8;
592 >
593 >        if ( mode.depth == VDEPTH_32BIT )
594 >                samplesPer = 3;
595 >        else
596 >                samplesPer = 1;
597   #endif
598  
599 +
600   #ifdef NSBITMAP
601          bitmap = [NSBitmapImageRep alloc];
602          bitmap = [bitmap initWithBitmapDataPlanes: (unsigned char **) &offsetBuffer
# Line 467 | Line 633 | static bool init_window(const video_mode
633                             hasAlpha: NO];
634   #endif
635  
470        // Set VideoMonitor
471        VideoMonitor.mode = mode;
472        set_mac_frame_buffer(mode.depth);
473
636          return true;
637   }
638  
639   #import <AppKit/NSEvent.h>
640   #import <Carbon/Carbon.h>
641 + #import "NNThread.h"
642  
643 < static bool init_screen(video_mode &mode)
643 > bool
644 > OSX_monitor::init_screen(video_mode &mode)
645   {
646          // Set absolute mouse mode
647          ADBSetRelMouseMode(false);
648  
649 <        theDisplay = kCGDirectMainDisplay;      // For now
649 >        // Display stored by add_CGDirectDisplay_modes()
650 >        theDisplay = (CGDirectDisplayID) mode.user_data;
651  
652          originalMode = CGDisplayCurrentMode(theDisplay);
653          if ( ! originalMode )
# Line 513 | Line 678 | static bool init_screen(video_mode &mode
678                  return false;
679          }
680  
516        [output startedFullScreen: theDisplay];         // For mouse event processing
517
681          D(NSLog(@"About to call CGDisplaySwitchToMode()"));
682          if ( CGDisplaySwitchToMode(theDisplay, newMode) != CGDisplayNoErr )
683          {
# Line 524 | Line 687 | static bool init_screen(video_mode &mode
687                  return false;
688          }
689  
690 +        the_buffer = CGDisplayBaseAddress(theDisplay);
691 +        if ( ! the_buffer )
692 +        {
693 +                CGDisplaySwitchToMode(theDisplay, originalMode);
694 +                CGDisplayRelease(theDisplay);
695 + //              [the_win deminiaturize: nil];
696 +                ErrorSheet(@"Could not get base address of screen", the_win);
697 +                return false;
698 +        }
699 +
700          if ( mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) )
701          {
702                  D(bug("Bytes per row (%d) doesn't match current (%ld)\n",
# Line 537 | Line 710 | static bool init_screen(video_mode &mode
710          {
711                  CGDisplayHideCursor(theDisplay);
712  
713 <                // Send real mouse to emulated location
714 <                if ( CGDisplayMoveCursorToPoint(theDisplay, CGPointMake(15,15))
715 <                                                                                                                != CGDisplayNoErr )
716 <                {
544 <                        video_close();
545 <                        ErrorSheet(@"Could move (jump) cursor on screen", the_win);
546 <                        return false;
547 <                }
713 >                [output startedFullScreen: theDisplay];
714 >
715 >                // Send emulated mouse to current location
716 >                [output fullscreenMouseMove];
717          }
718          else
719          {
720                  // Should set up something to hide the cursor when it enters theDisplay?
721          }
722  
554        the_buffer = CGDisplayBaseAddress(theDisplay);
555        if ( ! the_buffer )
556        {
557                video_close();
558                ErrorSheet(@"Could not get base address of screen", the_win);
559                return false;
560        }
561
562        // Set VideoMonitor
563        VideoMonitor.mode = mode;
564        set_mac_frame_buffer(mode.depth);
565
566
723          return true;
724   }
725  
726 < static bool init_opengl(const video_mode &mode)
726 >
727 > bool
728 > OSX_monitor::init_opengl(const video_mode &mode)
729   {
730          ErrorAlert("Sorry. OpenGL mode is not implemented yet");
731          return false;
# Line 576 | Line 734 | static bool init_opengl(const video_mode
734   /*
735   *  Initialization
736   */
737 + static bool
738 + monitor_init(const video_mode &init_mode)
739 + {
740 +        OSX_monitor     *monitor;
741 +        BOOL            success;
742 +
743 +        monitor = new OSX_monitor(VideoModes, init_mode.depth,
744 +                                                                                  init_mode.resolution_id);
745 +        success = monitor->video_open(init_mode);
746 +
747 +        if ( success )
748 +        {
749 +                monitor->set_mac_frame_buffer(init_mode);
750 +                VideoMonitors.push_back(monitor);
751 +                return YES;
752 +        }
753 +
754 +        return NO;
755 + }
756  
757   bool VideoInit(bool classic)
758   {
# Line 596 | Line 773 | bool VideoInit(bool classic)
773  
774          // Construct list of supported modes
775          if (classic)
776 <                add_mode(512, 342, 0x80, 64, VDEPTH_1BIT);
776 >                add_mode(512, 342, 0x80, 64, 0, VDEPTH_1BIT);
777          else
778                  switch ( display_type )
779                  {
# Line 610 | Line 787 | bool VideoInit(bool classic)
787                          case DISPLAY_OPENGL:
788                                  // Same as window depths and sizes?
789                          case DISPLAY_WINDOW:
790 <                                //add_standard_modes(VDEPTH_1BIT);
791 <                                //add_standard_modes(VDEPTH_8BIT);
792 <                                //add_standard_modes(VDEPTH_16BIT);
790 > #ifdef CGIMAGEREF
791 >                                add_standard_modes(VDEPTH_1BIT);
792 >                                add_standard_modes(VDEPTH_2BIT);
793 >                                add_standard_modes(VDEPTH_4BIT);
794 >                                add_standard_modes(VDEPTH_8BIT);
795 >                                add_standard_modes(VDEPTH_16BIT);
796 > #endif
797                                  add_standard_modes(VDEPTH_32BIT);
798                                  break;
799                  }
800  
801 <        video_init_depth_list();
801 > //      video_init_depth_list();                Now done in monitor_desc constructor?
802  
803   #if DEBUG
804          bug("Available video modes:\n");
# Line 641 | Line 822 | bool VideoInit(bool classic)
822                                          i->x, i->y, bits_from_depth(i->depth)));
823                          if (i->x == init_width && i->y == init_height
824                                          && bits_from_depth(i->depth) == init_depth)
825 <                                return video_open(*i);
825 >                                return monitor_init(*i);
826                  }
827          }
828  
# Line 651 | Line 832 | bool VideoInit(bool classic)
832                          colours_from_depth(init_depth), "Using lowest resolution");
833          WarningAlert(str);
834  
835 <        return video_open(VideoModes[0]);
835 >        return monitor_init(VideoModes[0]);
836   }
837  
838  
839   // Open display for specified mode
840 < static bool video_open(const video_mode &mode)
840 > bool
841 > OSX_monitor::video_open(const video_mode &mode)
842   {
843          D(bug("video_open: width=%d  height=%d  depth=%d  bytes_per_row=%d\n",
844                          mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row));
# Line 673 | Line 855 | static bool video_open(const video_mode
855   }
856  
857  
858 < static void video_close()
858 > void
859 > OSX_monitor::video_close()
860   {
861          D(bug("video_close()\n"));
862  
# Line 685 | Line 868 | static void video_close()
868                          // Free frame buffer stuff
869   #ifdef CGIMAGEREF
870                          CGImageRelease(imageRef);
871 +                        CGColorSpaceRelease(colourSpace);
872 +                        CGDataProviderRelease(provider);
873   #endif
874   #ifdef NSBITMAP
875                          [bitmap release];
# Line 717 | Line 902 | static void video_close()
902  
903   void VideoExit(void)
904   {
905 <        video_close();
905 >        // Close displays
906 >        vector<monitor_desc *>::iterator        i, end;
907 >
908 >        end = VideoMonitors.end();
909 >
910 >        for (i = VideoMonitors.begin(); i != end; ++i)
911 >                dynamic_cast<OSX_monitor *>(*i)->video_close();
912 >
913 >        VideoMonitors.clear();
914 >        VideoModes.clear();
915   }
916  
917  
# Line 725 | Line 919 | void VideoExit(void)
919   *  Set palette
920   */
921  
922 < void video_set_palette(uint8 *pal, int num)
922 > void
923 > OSX_monitor::set_palette(uint8 *pal, int num)
924   {
925          if ( [output isFullScreen] && CGDisplayCanSetPalette(theDisplay)
926 <                                                                && ! IsDirectMode(VideoMonitor.mode) )
926 >                                                                && ! IsDirectMode(get_current_mode()) )
927          {
928                  CGDirectPaletteRef      CGpal;
929                  CGDisplayErr            err;
# Line 740 | Line 935 | void video_set_palette(uint8 *pal, int n
935                          NSLog(@"Failed to set palette, error = %d", err);
936                  CGPaletteRelease(CGpal);
937          }
938 +
939 + #ifdef CGIMAGEREF
940 +        if ( display_type != DISPLAY_WINDOW )
941 +                return;
942 +
943 +        // To change the palette, we have to regenerate
944 +        // the CGImageRef with the new colour space.
945 +
946 +        CGImageRef                      oldImageRef = imageRef;
947 +        CGColorSpaceRef         oldColourSpace = colourSpace;
948 +
949 +        colourSpace = CGColorSpaceCreateDeviceRGB();
950 +
951 +        if ( depth < 16 )
952 +        {
953 +                CGColorSpaceRef         tempColourSpace = colourSpace;
954 +
955 +                colourSpace = CGColorSpaceCreateIndexed(colourSpace, 255, pal);
956 +                CGColorSpaceRelease(tempColourSpace);
957 +        }
958 +
959 +        if ( ! colourSpace )
960 +        {
961 +                ErrorAlert("No valid colour space");
962 +                return;
963 +        }
964 +
965 +        imageRef = CGImageCreate(x, y, bpp, depth, bpr, colourSpace,
966 +  #ifdef CG_USE_ALPHA
967 +                                                         kCGImageAlphaPremultipliedFirst,
968 +  #else
969 +                                                         kCGImageAlphaNoneSkipFirst,
970 +  #endif
971 +                                                         provider,
972 +                                                         NULL,  // colourMap translation table
973 +                                                         NO,    // shouldInterpolate colours?
974 +                                                         kCGRenderingIntentDefault);
975 +        if ( ! imageRef )
976 +        {
977 +                ErrorAlert("Could not create CGImage from CGDataProvider");
978 +                return;
979 +        }
980 +
981 +        unsigned char *offsetBuffer = (unsigned char *) the_buffer;
982 +        offsetBuffer += 1;              // OS X NSBitmaps are RGBA, but Basilisk generates ARGB
983 +
984 +        [output readyToDraw: imageRef
985 +                                 bitmap: offsetBuffer
986 +                         imageWidth: x
987 +                        imageHeight: y];
988 +
989 +        CGColorSpaceRelease(oldColourSpace);
990 +        CGImageRelease(oldImageRef);
991 + #endif
992   }
993  
994  
# Line 747 | Line 996 | void video_set_palette(uint8 *pal, int n
996   *  Switch video mode
997   */
998  
999 < void video_switch_to_mode(const video_mode &mode)
999 > void
1000 > OSX_monitor::switch_to_current_mode(void)
1001   {
1002 +        video_mode      mode = get_current_mode();
1003          char            *failure = NULL;
1004  
1005  
1006          D(bug("switch_to_current_mode(): width=%d  height=%d  depth=%d  bytes_per_row=%d\n", mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row));
1007 <
1007 >        
1008          if ( display_type == DISPLAY_SCREEN && originalMode )
1009          {
1010                  D(NSLog(@"About to call CGDisplayBestModeForParameters()"));
# Line 769 | Line 1020 | void video_switch_to_mode(const video_mo
1020                                  failure = "Could not switch to matching screen mode";
1021                  }
1022  
1023 +                // For mouse event processing: update screen height
1024 +                [output startedFullScreen: theDisplay];
1025 +
1026                  if ( ! failure &&
1027                          mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) )
1028                  {
1029                          D(bug("Bytes per row (%d) doesn't match current (%ld)\n",
1030                                          mode.bytes_per_row, CGDisplayBytesPerRow(theDisplay)));
1031 <                        ((video_mode &)mode).bytes_per_row
778 <                                                                        = CGDisplayBytesPerRow(theDisplay);
1031 >                        mode.bytes_per_row = CGDisplayBytesPerRow(theDisplay);
1032                  }
1033  
1034                  if ( ! failure &&
1035                           ! ( the_buffer = CGDisplayBaseAddress(theDisplay) ) )
1036                          failure = "Could not get base address of screen";
1037 +
1038 +        }
1039 + #ifdef CGIMAGEREF
1040 +        // Clean up the old CGImageRef stuff
1041 +        else if ( display_type == DISPLAY_WINDOW && imageRef )
1042 +        {
1043 +                CGImageRef                      oldImageRef             = imageRef;
1044 +                CGColorSpaceRef         oldColourSpace  = colourSpace;
1045 +                CGDataProviderRef       oldProvider             = provider;
1046 +                void                            *oldBuffer              = the_buffer;
1047 +
1048 +                if ( video_open(mode) )
1049 +                {
1050 +                        CGImageRelease(oldImageRef);
1051 +                        CGColorSpaceRelease(oldColourSpace);
1052 +                        CGDataProviderRelease(oldProvider);
1053 +                        free(oldBuffer);
1054 +                }
1055                  else
1056 <                        // Send emulated mouse to current location
786 <                        [output processMouseMove: nil];
1056 >                        failure = "Could not video_open() requested mode";
1057          }
1058 + #endif
1059          else if ( ! video_open(mode) )
1060                  failure = "Could not video_open() requested mode";
1061  
1062 +        if ( ! failure && display_type == DISPLAY_SCREEN )
1063 +        {
1064 +                // Whenever we change screen resolution, the MacOS mouse starts
1065 +                // up in the top left corner. Send real mouse to that location
1066 + //              if ( CGDisplayMoveCursorToPoint(theDisplay, CGPointMake(15,15))
1067 + //                                                                                                              == CGDisplayNoErr )
1068 + //              {
1069 +                        //
1070 +                        [output fullscreenMouseMove];
1071 + //              }
1072 + //              else
1073 + //                      failure = "Could move (jump) cursor on screen";
1074 +        }
1075 +
1076          if ( failure )
1077          {
1078                  NSLog(@"In switch_to_current_mode():");
# Line 800 | Line 1085 | void video_switch_to_mode(const video_mo
1085                  QuitEmulator();
1086          }
1087          else
1088 <                set_mac_frame_buffer(mode.depth);
1088 >                set_mac_frame_buffer(mode);
1089   }
1090  
1091   /*
# Line 826 | Line 1111 | void VideoInterrupt(void)
1111   void VideoRefresh(void)
1112   {
1113   }
1114 +
1115 +
1116 +
1117 + // Deal with a memory access signal referring to the screen.
1118 + // For now, just ignore
1119 + bool Screen_fault_handler(char *a, char *b)
1120 + {
1121 + //      NSLog(@"Got a screen fault %lx %lx", a, b);
1122 + //      [output setNeedsDisplay: YES];
1123 +        return YES;
1124 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines