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.5 by nigel, 2002-07-02T09:47:57Z

# 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"
# Line 40 | Line 39
39   #define DEBUG 0
40   #include "debug.h"
41  
42 + #ifdef NSBITMAP
43 + #import <AppKit/NSBitmapImageRep.h>
44 + #endif
45 +
46   #import <Foundation/NSString.h>                         // Needed for NSLog(@"")
47   #import "misc_macosx.h"                                         // WarningSheet() prototype
48  
# Line 54 | Line 57 | uint16         init_width  = MIN_WIDTH,                // as
57  
58                  EmulatorView    *output = nil;          // Set by [EmulatorView init]
59                  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
60  
61 + static  BOOL                    singleDisplay = YES;
62  
63   /*
64   *  Utility functions
# Line 143 | Line 122 | parse_screen_prefs(const char *mode_str)
122          return true;
123   }
124  
125 + // Supported video modes
126 + static vector<video_mode> VideoModes;
127 +
128  
129   // Add mode to list of supported modes
130   static void
131   add_mode(const uint16 width, const uint16 height,
132                   const uint32 resolution_id, const uint32 bytes_per_row,
133 +                 const uint32 user_data,
134                   const video_depth depth)
135   {
136          vector<video_mode>::const_iterator      i,
# Line 168 | Line 151 | add_mode(const uint16 width, const uint1
151          mode.y = height;
152          mode.resolution_id = resolution_id;
153          mode.bytes_per_row = bytes_per_row;
154 +        mode.user_data = user_data;
155          mode.depth = depth;
156  
157          D(bug("Added video mode: w=%d  h=%d  d=%d(%d bits)\n",
# Line 182 | Line 166 | static void add_standard_modes(const vid
166          D(bug("add_standard_modes: depth=%d(%d bits)\n",
167                                                  depth, bits_from_depth(depth) ));
168  
169 <        add_mode(512,  384,  0x80, TrivialBytesPerRow(512,  depth), depth);
170 <        add_mode(640,  480,  0x81, TrivialBytesPerRow(640,  depth), depth);
171 <        add_mode(800,  600,  0x82, TrivialBytesPerRow(800,  depth), depth);
172 <        add_mode(832,  624,  0x83, TrivialBytesPerRow(832,  depth), depth);
173 <        add_mode(1024, 768,  0x84, TrivialBytesPerRow(1024, depth), depth);
174 <        add_mode(1152, 768,  0x85, TrivialBytesPerRow(1152, depth), depth);
175 <        add_mode(1152, 870,  0x86, TrivialBytesPerRow(1152, depth), depth);
176 <        add_mode(1280, 1024, 0x87, TrivialBytesPerRow(1280, depth), depth);
177 <        add_mode(1600, 1200, 0x88, TrivialBytesPerRow(1600, depth), depth);
169 >        add_mode(512,  384,  0x80, TrivialBytesPerRow(512,  depth), 0, depth);
170 >        add_mode(640,  480,  0x81, TrivialBytesPerRow(640,  depth), 0, depth);
171 >        add_mode(800,  600,  0x82, TrivialBytesPerRow(800,  depth), 0, depth);
172 >        add_mode(832,  624,  0x83, TrivialBytesPerRow(832,  depth), 0, depth);
173 >        add_mode(1024, 768,  0x84, TrivialBytesPerRow(1024, depth), 0, depth);
174 >        add_mode(1152, 768,  0x85, TrivialBytesPerRow(1152, depth), 0, depth);
175 >        add_mode(1152, 870,  0x86, TrivialBytesPerRow(1152, depth), 0, depth);
176 >        add_mode(1280, 1024, 0x87, TrivialBytesPerRow(1280, depth), 0, depth);
177 >        add_mode(1600, 1200, 0x88, TrivialBytesPerRow(1600, depth), 0, depth);
178   }
179  
180   // Helper function to get a 32bit int from a dictionary
# Line 213 | Line 197 | static int32 getCFint32 (CFDictionaryRef
197          return 0;
198   }
199  
200 + // Nasty hack. CGDisplayAvailableModes() does not provide bytes per row,
201 + // and the emulator doesn't like setting the bytes per row after the screen,
202 + // so we use a lot of magic numbers here.
203 + // This will probably fail on some video hardware.
204 + // I have tested on my G4 PowerBook 400 and G3 PowerBook Series 292
205 +
206 + static int
207 + CGBytesPerRow(const uint16 width, const video_depth depth)
208 + {
209 +        if ( depth == VDEPTH_8BIT )
210 +                switch ( width )
211 +                {
212 +                        case 640:
213 +                        case 720:       return 768;
214 +                        case 800:
215 +                        case 896:       return 1024;
216 +                        case 1152:      return 1280;
217 +                }
218 +
219 +        if ( width == 720  && depth == VDEPTH_16BIT)    return 1536;
220 +        if ( width == 720  && depth == VDEPTH_32BIT)    return 3072;
221 +        if ( width == 800  && depth == VDEPTH_16BIT)    return 1792;
222 +        if ( width == 800  && depth == VDEPTH_32BIT)    return 3328;
223 +
224 +        return TrivialBytesPerRow(width, depth);
225 + }
226 +
227   static bool add_CGDirectDisplay_modes()
228   {
229   #define kMaxDisplays 8
# Line 239 | Line 250 | static bool add_CGDirectDisplay_modes()
250                          add_mode(CGDisplayPixelsWide(d),
251                                           CGDisplayPixelsHigh(d),
252                                           res_id++, CGDisplayBytesPerRow(d),
253 +                                         (const uint32) d,
254                                           DepthModeForPixelDepth(CGDisplayBitsPerPixel(d)));
255                  else
256                  {
# Line 273 | Line 285 | static bool add_CGDirectDisplay_modes()
285                                                  ++res_id;
286                                          }
287  
288 <                                add_mode(width, height, res_id, 0, depth);
288 >                                add_mode(width, height, res_id,
289 >                                                 CGBytesPerRow(width, depth), (const uint32) d, depth);
290                          }
291                  }
292          }
# Line 281 | Line 294 | static bool add_CGDirectDisplay_modes()
294          return true;
295   }
296  
297 +
298 + // monitor_desc subclass for Mac OS X displays
299 +
300 + class OSX_monitor : public monitor_desc
301 + {
302 +        public:
303 +                OSX_monitor(const vector<video_mode>    &available_modes,
304 +                                        video_depth                                     default_depth,
305 +                                        uint32                                          default_id);
306 +
307 +                virtual void set_palette(uint8 *pal, int num);
308 +                virtual void switch_to_current_mode(void);
309 +
310 +                                void set_mac_frame_buffer(const video_mode mode);
311 +
312 +                                void video_close(void);
313 +                                bool video_open (const video_mode &mode);
314 +
315 +
316 +        private:
317 +                bool init_opengl(const video_mode &mode);
318 +                bool init_screen(      video_mode &mode);
319 +                bool init_window(const video_mode &mode);
320 +
321 +
322 + #ifdef CGIMAGEREF
323 +                CGImageRef                      imageRef;
324 + #endif
325 + #ifdef NSBITMAP
326 +                NSBitmapImageRep        *bitmap;
327 + #endif
328 +                void                            *the_buffer;
329 +
330 +
331 +                // These record changes we made in setting full screen mode,
332 +                // so that we can set the display back as it was again.
333 +                CGDirectDisplayID       theDisplay;
334 +                CFDictionaryRef         originalMode,
335 +                                                        newMode;
336 + };
337 +
338 +
339 + OSX_monitor :: OSX_monitor (const       vector<video_mode>      &available_modes,
340 +                                                                        video_depth                     default_depth,
341 +                                                                        uint32                          default_id)
342 +                        : monitor_desc (available_modes, default_depth, default_id)
343 + {
344 + #ifdef CGIMAGEREF
345 +        imageRef = nil;
346 + #endif
347 + #ifdef NSBITMAP
348 +        bitmap = nil;
349 + #endif
350 +        newMode = originalMode = nil;
351 +        the_buffer = NULL;
352 +        theDisplay = nil;
353 + };
354 +
355 +
356   // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac)
357 < static void set_mac_frame_buffer(const video_depth depth)
357 > void
358 > OSX_monitor::set_mac_frame_buffer(const video_mode mode)
359   {
360   #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
361 <        switch ( depth )
361 >        switch ( mode.depth )
362          {
363          //      case VDEPTH_15BIT:
364                  case VDEPTH_16BIT: MacFrameLayout = FLAYOUT_HOST_555; break;
# Line 293 | Line 366 | static void set_mac_frame_buffer(const v
366                  case VDEPTH_32BIT: MacFrameLayout = FLAYOUT_HOST_888; break;
367                  default                  : MacFrameLayout = FLAYOUT_DIRECT;
368          }
369 <        VideoMonitor.mac_frame_base = MacFrameBaseMac;
369 >        set_mac_frame_base(MacFrameBaseMac);
370  
371          // Set variables used by UAE memory banking
372          MacFrameBaseHost = the_buffer;
373 <        MacFrameSize = VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y;
373 >        MacFrameSize = mode.bytes_per_row * mode.y;
374          InitFrameBufferMapping();
375   #else
376 <        VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer);
376 >        set_mac_frame_base(Host2MacAddr(the_buffer));
377   #endif
378 <        D(bug("VideoMonitor.mac_frame_base = %08x\n", VideoMonitor.mac_frame_base));
378 >        D(bug("mac_frame_base = %08x\n", get_mac_frame_base()));
379   }
380  
381   static void
# Line 334 | Line 407 | void resizeWinTo(const uint16 newWidth,
407   }
408  
409   // Open window
410 < static bool init_window(const video_mode &mode)
410 > bool
411 > OSX_monitor::init_window(const video_mode &mode)
412   {
413   #ifdef CGIMAGEREF
414          CGColorSpaceRef         colourSpace;
# Line 467 | Line 541 | static bool init_window(const video_mode
541                             hasAlpha: NO];
542   #endif
543  
470        // Set VideoMonitor
471        VideoMonitor.mode = mode;
472        set_mac_frame_buffer(mode.depth);
473
544          return true;
545   }
546  
547   #import <AppKit/NSEvent.h>
548   #import <Carbon/Carbon.h>
549 + #import "NNThread.h"
550  
551 < static bool init_screen(video_mode &mode)
551 > bool
552 > OSX_monitor::init_screen(video_mode &mode)
553   {
554          // Set absolute mouse mode
555          ADBSetRelMouseMode(false);
556  
557 <        theDisplay = kCGDirectMainDisplay;      // For now
557 >        // Display stored by add_CGDirectDisplay_modes()
558 >        theDisplay = (CGDirectDisplayID) mode.user_data;
559  
560          originalMode = CGDisplayCurrentMode(theDisplay);
561          if ( ! originalMode )
# Line 513 | Line 586 | static bool init_screen(video_mode &mode
586                  return false;
587          }
588  
516        [output startedFullScreen: theDisplay];         // For mouse event processing
517
589          D(NSLog(@"About to call CGDisplaySwitchToMode()"));
590          if ( CGDisplaySwitchToMode(theDisplay, newMode) != CGDisplayNoErr )
591          {
# Line 524 | Line 595 | static bool init_screen(video_mode &mode
595                  return false;
596          }
597  
598 +        // For mouse event processing: update screen height
599 +        [output startedFullScreen: theDisplay];
600 +
601 +        the_buffer = CGDisplayBaseAddress(theDisplay);
602 +        if ( ! the_buffer )
603 +        {
604 +                CGDisplaySwitchToMode(theDisplay, originalMode);
605 +                CGDisplayRelease(theDisplay);
606 + //              [the_win deminiaturize: nil];
607 +                ErrorSheet(@"Could not get base address of screen", the_win);
608 +                return false;
609 +        }
610 + NSLog(@"Starting full screen mode, height = %d",
611 +                                        CGDisplayPixelsHigh(theDisplay));
612 +        [output startedFullScreen: theDisplay];         // For mouse event processing
613 +
614          if ( mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) )
615          {
616                  D(bug("Bytes per row (%d) doesn't match current (%ld)\n",
# Line 545 | Line 632 | static bool init_screen(video_mode &mode
632                          ErrorSheet(@"Could move (jump) cursor on screen", the_win);
633                          return false;
634                  }
635 +
636 +                // Send emulated mouse to current location
637 + //              [output performSelector: @selector(processMouseMove:)
638 + //                                       withObject: nil
639 + //                                       afterDelay: 7.0];
640 + //              NNTimer *moveMouse = [[NNTimer new] retain];
641 + //              [moveMouse perform: @selector(processMouseMove:)
642 + //                                              of: output
643 + //                                       after: 3
644 + //                                       units: NNseconds];
645          }
646          else
647          {
648                  // Should set up something to hide the cursor when it enters theDisplay?
649          }
650  
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
651          return true;
652   }
653  
654 < static bool init_opengl(const video_mode &mode)
654 >
655 > bool
656 > OSX_monitor::init_opengl(const video_mode &mode)
657   {
658          ErrorAlert("Sorry. OpenGL mode is not implemented yet");
659          return false;
# Line 576 | Line 662 | static bool init_opengl(const video_mode
662   /*
663   *  Initialization
664   */
665 + static bool
666 + monitor_init(const video_mode &init_mode)
667 + {
668 +        OSX_monitor     *monitor;
669 +        BOOL            success;
670 +
671 +        monitor = new OSX_monitor(VideoModes, init_mode.depth,
672 +                                                                                  init_mode.resolution_id);
673 +        success = monitor->video_open(init_mode);
674 +
675 +        if ( success )
676 +        {
677 +                monitor->set_mac_frame_buffer(init_mode);
678 +                VideoMonitors.push_back(monitor);
679 +                return YES;
680 +        }
681 +
682 +        return NO;
683 + }
684  
685   bool VideoInit(bool classic)
686   {
# Line 596 | Line 701 | bool VideoInit(bool classic)
701  
702          // Construct list of supported modes
703          if (classic)
704 <                add_mode(512, 342, 0x80, 64, VDEPTH_1BIT);
704 >                add_mode(512, 342, 0x80, 64, 0, VDEPTH_1BIT);
705          else
706                  switch ( display_type )
707                  {
# Line 617 | Line 722 | bool VideoInit(bool classic)
722                                  break;
723                  }
724  
725 <        video_init_depth_list();
725 > //      video_init_depth_list();                Now done in monitor_desc constructor?
726  
727   #if DEBUG
728          bug("Available video modes:\n");
# Line 641 | Line 746 | bool VideoInit(bool classic)
746                                          i->x, i->y, bits_from_depth(i->depth)));
747                          if (i->x == init_width && i->y == init_height
748                                          && bits_from_depth(i->depth) == init_depth)
749 <                                return video_open(*i);
749 >                                return monitor_init(*i);
750                  }
751          }
752  
# Line 651 | Line 756 | bool VideoInit(bool classic)
756                          colours_from_depth(init_depth), "Using lowest resolution");
757          WarningAlert(str);
758  
759 <        return video_open(VideoModes[0]);
759 >        return monitor_init(VideoModes[0]);
760   }
761  
762  
763   // Open display for specified mode
764 < static bool video_open(const video_mode &mode)
764 > bool
765 > OSX_monitor::video_open(const video_mode &mode)
766   {
767          D(bug("video_open: width=%d  height=%d  depth=%d  bytes_per_row=%d\n",
768                          mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row));
# Line 673 | Line 779 | static bool video_open(const video_mode
779   }
780  
781  
782 < static void video_close()
782 > void
783 > OSX_monitor::video_close()
784   {
785          D(bug("video_close()\n"));
786  
# Line 717 | Line 824 | static void video_close()
824  
825   void VideoExit(void)
826   {
827 <        video_close();
827 >        // Close displays
828 >        vector<monitor_desc *>::iterator        i, end;
829 >
830 >        end = VideoMonitors.end();
831 >
832 >        for (i = VideoMonitors.begin(); i != end; ++i)
833 >                dynamic_cast<OSX_monitor *>(*i)->video_close();
834   }
835  
836  
# Line 725 | Line 838 | void VideoExit(void)
838   *  Set palette
839   */
840  
841 < void video_set_palette(uint8 *pal, int num)
841 > void
842 > OSX_monitor::set_palette(uint8 *pal, int num)
843   {
844          if ( [output isFullScreen] && CGDisplayCanSetPalette(theDisplay)
845 <                                                                && ! IsDirectMode(VideoMonitor.mode) )
845 >                                                                && ! IsDirectMode(get_current_mode()) )
846          {
847                  CGDirectPaletteRef      CGpal;
848                  CGDisplayErr            err;
# Line 747 | Line 861 | void video_set_palette(uint8 *pal, int n
861   *  Switch video mode
862   */
863  
864 < void video_switch_to_mode(const video_mode &mode)
864 > void
865 > OSX_monitor::switch_to_current_mode(void)
866   {
867 +        video_mode      mode = get_current_mode();
868          char            *failure = NULL;
869  
870  
871          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));
872 <
872 >        
873          if ( display_type == DISPLAY_SCREEN && originalMode )
874          {
875                  D(NSLog(@"About to call CGDisplayBestModeForParameters()"));
# Line 769 | Line 885 | void video_switch_to_mode(const video_mo
885                                  failure = "Could not switch to matching screen mode";
886                  }
887  
888 +                // For mouse event processing: update screen height
889 +                [output startedFullScreen: theDisplay];
890 +
891                  if ( ! failure &&
892                          mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) )
893                  {
894                          D(bug("Bytes per row (%d) doesn't match current (%ld)\n",
895                                          mode.bytes_per_row, CGDisplayBytesPerRow(theDisplay)));
896 <                        ((video_mode &)mode).bytes_per_row
778 <                                                                        = CGDisplayBytesPerRow(theDisplay);
896 >                        mode.bytes_per_row = CGDisplayBytesPerRow(theDisplay);
897                  }
898  
899                  if ( ! failure &&
# Line 800 | Line 918 | void video_switch_to_mode(const video_mo
918                  QuitEmulator();
919          }
920          else
921 <                set_mac_frame_buffer(mode.depth);
921 >                set_mac_frame_buffer(mode);
922   }
923  
924   /*

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines