82 Uint32 flags); |
82 Uint32 flags); |
83 static int QZ_ToggleFullScreen (_THIS, int on); |
83 static int QZ_ToggleFullScreen (_THIS, int on); |
84 static int QZ_SetColors (_THIS, int first_color, |
84 static int QZ_SetColors (_THIS, int first_color, |
85 int num_colors, SDL_Color *colors); |
85 int num_colors, SDL_Color *colors); |
86 |
86 |
87 static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); |
|
88 static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); |
|
89 static int QZ_ThreadFlip (_THIS); |
|
90 static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); |
|
91 static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); |
|
92 |
|
93 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); |
|
94 static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); |
87 static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); |
95 static void QZ_VideoQuit (_THIS); |
88 static void QZ_VideoQuit (_THIS); |
96 |
89 |
97 /* Hardware surface functions (for fullscreen mode only) */ |
|
98 #if 0 /* Not used (apparently, it's really slow) */ |
|
99 static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); |
|
100 #endif |
|
101 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); |
90 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); |
102 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); |
91 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); |
103 static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface); |
92 static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface); |
104 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); |
93 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); |
105 /* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */ |
|
106 |
94 |
107 /* Bootstrap binding, enables entry point into the driver */ |
95 /* Bootstrap binding, enables entry point into the driver */ |
108 VideoBootStrap QZ_bootstrap = { |
96 VideoBootStrap QZ_bootstrap = { |
109 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice |
97 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice |
110 }; |
98 }; |
138 device->ListModes = QZ_ListModes; |
126 device->ListModes = QZ_ListModes; |
139 device->SetVideoMode = QZ_SetVideoMode; |
127 device->SetVideoMode = QZ_SetVideoMode; |
140 device->ToggleFullScreen = QZ_ToggleFullScreen; |
128 device->ToggleFullScreen = QZ_ToggleFullScreen; |
141 device->UpdateMouse = QZ_UpdateMouse; |
129 device->UpdateMouse = QZ_UpdateMouse; |
142 device->SetColors = QZ_SetColors; |
130 device->SetColors = QZ_SetColors; |
143 /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */ |
131 device->UpdateRects = QZ_UpdateRects; |
144 device->VideoQuit = QZ_VideoQuit; |
132 device->VideoQuit = QZ_VideoQuit; |
145 |
133 |
146 device->LockHWSurface = QZ_LockHWSurface; |
134 device->LockHWSurface = QZ_LockHWSurface; |
147 device->UnlockHWSurface = QZ_UnlockHWSurface; |
135 device->UnlockHWSurface = QZ_UnlockHWSurface; |
148 device->AllocHWSurface = QZ_AllocHWSurface; |
136 device->AllocHWSurface = QZ_AllocHWSurface; |
149 device->FreeHWSurface = QZ_FreeHWSurface; |
137 device->FreeHWSurface = QZ_FreeHWSurface; |
150 /* device->FlipHWSurface = QZ_FlipHWSurface */; |
|
151 |
138 |
152 device->SetGamma = QZ_SetGamma; |
139 device->SetGamma = QZ_SetGamma; |
153 device->GetGamma = QZ_GetGamma; |
140 device->GetGamma = QZ_GetGamma; |
154 device->SetGammaRamp = QZ_SetGammaRamp; |
141 device->SetGammaRamp = QZ_SetGammaRamp; |
155 device->GetGammaRamp = QZ_GetGammaRamp; |
142 device->GetGammaRamp = QZ_GetGammaRamp; |
396 |
383 |
397 static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) |
384 static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) |
398 { |
385 { |
399 /* Reset values that may change between switches */ |
386 /* Reset values that may change between switches */ |
400 this->info.blit_fill = 0; |
387 this->info.blit_fill = 0; |
401 this->FillHWRect = NULL; |
388 |
402 this->UpdateRects = NULL; |
|
403 this->LockHWSurface = NULL; |
|
404 this->UnlockHWSurface = NULL; |
|
405 |
|
406 if (cg_context) { |
389 if (cg_context) { |
407 CGContextFlush (cg_context); |
390 CGContextFlush (cg_context); |
408 CGContextRelease (cg_context); |
391 CGContextRelease (cg_context); |
409 cg_context = nil; |
392 cg_context = nil; |
410 } |
393 } |
411 |
394 |
412 /* Release fullscreen resources */ |
395 /* Release fullscreen resources */ |
413 if ( mode_flags & SDL_FULLSCREEN ) { |
396 if ( mode_flags & SDL_FULLSCREEN ) { |
414 |
397 |
415 NSRect screen_rect; |
398 NSRect screen_rect; |
416 |
399 |
417 /* Release double buffer stuff */ |
|
418 if ( mode_flags & SDL_DOUBLEBUF) { |
|
419 quit_thread = YES; |
|
420 SDL_SemPost (sem1); |
|
421 SDL_WaitThread (thread, NULL); |
|
422 SDL_DestroySemaphore (sem1); |
|
423 SDL_DestroySemaphore (sem2); |
|
424 SDL_free (sw_buffers[0]); |
|
425 } |
|
426 |
|
427 /* If we still have a valid window, close it. */ |
400 /* If we still have a valid window, close it. */ |
428 if ( qz_window ) { |
401 if ( qz_window ) { |
429 NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */ |
402 NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */ |
430 [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ |
403 [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ |
431 qz_window = nil; |
404 qz_window = nil; |
477 NSRect screen_rect; |
450 NSRect screen_rect; |
478 CGError error; |
451 CGError error; |
479 NSRect contentRect; |
452 NSRect contentRect; |
480 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; |
453 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; |
481 |
454 |
|
455 current->flags = SDL_FULLSCREEN; |
|
456 current->w = width; |
|
457 current->h = height; |
|
458 |
482 contentRect = NSMakeRect (0, 0, width, height); |
459 contentRect = NSMakeRect (0, 0, width, height); |
483 |
460 |
484 /* Fade to black to hide resolution-switching flicker (and garbage |
461 /* Fade to black to hide resolution-switching flicker (and garbage |
485 that is displayed by a destroyed OpenGL context, if applicable) */ |
462 that is displayed by a destroyed OpenGL context, if applicable) */ |
486 if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { |
463 if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { |
522 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { |
499 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { |
523 SDL_SetError ("Failed switching display resolution"); |
500 SDL_SetError ("Failed switching display resolution"); |
524 goto ERR_NO_SWITCH; |
501 goto ERR_NO_SWITCH; |
525 } |
502 } |
526 |
503 |
527 current->pixels = (Uint32*) CGDisplayBaseAddress (display_id); |
|
528 current->pitch = CGDisplayBytesPerRow (display_id); |
|
529 |
|
530 current->flags = 0; |
|
531 current->w = width; |
|
532 current->h = height; |
|
533 current->flags |= SDL_FULLSCREEN; |
|
534 current->flags |= SDL_HWSURFACE; |
|
535 current->flags |= SDL_PREALLOC; |
|
536 /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */ |
|
537 |
|
538 this->UpdateRects = QZ_DirectUpdate; |
|
539 this->LockHWSurface = QZ_LockHWSurface; |
|
540 this->UnlockHWSurface = QZ_UnlockHWSurface; |
|
541 |
|
542 /* Setup double-buffer emulation */ |
|
543 if ( flags & SDL_DOUBLEBUF ) { |
|
544 |
|
545 /* |
|
546 Setup a software backing store for reasonable results when |
|
547 double buffering is requested (since a single-buffered hardware |
|
548 surface looks hideous). |
|
549 |
|
550 The actual screen blit occurs in a separate thread to allow |
|
551 other blitting while waiting on the VBL (and hence results in higher framerates). |
|
552 */ |
|
553 this->LockHWSurface = NULL; |
|
554 this->UnlockHWSurface = NULL; |
|
555 this->UpdateRects = NULL; |
|
556 |
|
557 current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); |
|
558 this->UpdateRects = QZ_DoubleBufferUpdate; |
|
559 this->LockHWSurface = QZ_LockDoubleBuffer; |
|
560 this->UnlockHWSurface = QZ_UnlockDoubleBuffer; |
|
561 this->FlipHWSurface = QZ_FlipDoubleBuffer; |
|
562 |
|
563 current->pixels = SDL_malloc (current->pitch * current->h * 2); |
|
564 if (current->pixels == NULL) { |
|
565 SDL_OutOfMemory (); |
|
566 goto ERR_DOUBLEBUF; |
|
567 } |
|
568 |
|
569 sw_buffers[0] = current->pixels; |
|
570 sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; |
|
571 |
|
572 quit_thread = NO; |
|
573 sem1 = SDL_CreateSemaphore (0); |
|
574 sem2 = SDL_CreateSemaphore (1); |
|
575 thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this); |
|
576 } |
|
577 |
|
578 if ( CGDisplayCanSetPalette (display_id) ) |
|
579 current->flags |= SDL_HWPALETTE; |
|
580 |
|
581 /* Check if we should recreate the window */ |
504 /* Check if we should recreate the window */ |
582 if (qz_window == nil) { |
505 if (qz_window == nil) { |
583 /* Manually create a window, avoids having a nib file resource */ |
506 /* Manually create a window, avoids having a nib file resource */ |
584 qz_window = [ [ SDL_QuartzWindow alloc ] |
507 qz_window = [ [ SDL_QuartzWindow alloc ] |
585 initWithContentRect:contentRect |
508 initWithContentRect:contentRect |
586 styleMask:0 |
509 styleMask:NSBorderlessWindowMask |
587 backing:NSBackingStoreBuffered |
510 backing:NSBackingStoreBuffered |
588 defer:NO ]; |
511 defer:NO ]; |
589 |
512 |
590 if (qz_window != nil) { |
513 if (qz_window != nil) { |
591 [ qz_window setAcceptsMouseMovedEvents:YES ]; |
514 [ qz_window setAcceptsMouseMovedEvents:YES ]; |
592 [ qz_window setViewsNeedDisplay:NO ]; |
515 [ qz_window setViewsNeedDisplay:NO ]; |
|
516 [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; |
593 } |
517 } |
594 } |
518 } |
595 /* We already have a window, just change its size */ |
519 /* We already have a window, just change its size */ |
596 else { |
520 else { |
597 [ qz_window setContentSize:contentRect.size ]; |
521 [ qz_window setContentSize:contentRect.size ]; |
629 |
556 |
630 [ gl_context flushBuffer ]; |
557 [ gl_context flushBuffer ]; |
631 |
558 |
632 current->flags |= SDL_OPENGL; |
559 current->flags |= SDL_OPENGL; |
633 } |
560 } |
|
561 /* For 2D, we build a CGBitmapContext */ |
|
562 else { |
|
563 CGColorSpaceRef cgColorspace; |
|
564 |
|
565 /* Only recreate the view if it doesn't already exist */ |
|
566 if (window_view == nil) { |
|
567 window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; |
|
568 [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; |
|
569 [ [ qz_window contentView ] addSubview:window_view ]; |
|
570 [ window_view release ]; |
|
571 } |
|
572 |
|
573 cgColorspace = CGColorSpaceCreateDeviceRGB(); |
|
574 current->pitch = 4 * current->w; |
|
575 current->pixels = SDL_malloc (current->h * current->pitch); |
|
576 |
|
577 cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, |
|
578 8, current->pitch, cgColorspace, |
|
579 kCGImageAlphaNoneSkipFirst); |
|
580 CGColorSpaceRelease (cgColorspace); |
|
581 |
|
582 current->flags |= SDL_SWSURFACE; |
|
583 current->flags |= SDL_ASYNCBLIT; |
|
584 current->hwdata = (void *) cg_context; |
|
585 |
|
586 /* Force this window to draw above _everything_. */ |
|
587 [ qz_window setLevel:CGShieldingWindowLevel() ]; |
|
588 } |
|
589 |
|
590 [ qz_window setHasShadow:NO]; |
|
591 [ qz_window setOpaque:YES]; |
|
592 [ qz_window center ]; |
|
593 [ qz_window makeKeyAndOrderFront:nil ]; |
634 |
594 |
635 /* If we don't hide menu bar, it will get events and interrupt the program */ |
595 /* If we don't hide menu bar, it will get events and interrupt the program */ |
636 HideMenuBar (); |
596 HideMenuBar (); |
637 |
597 |
638 /* Fade in again (asynchronously) */ |
598 /* Fade in again (asynchronously) */ |
842 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, |
798 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, |
843 int height, int bpp, Uint32 flags) |
799 int height, int bpp, Uint32 flags) |
844 { |
800 { |
845 current->flags = 0; |
801 current->flags = 0; |
846 current->pixels = NULL; |
802 current->pixels = NULL; |
|
803 |
|
804 /* Force bpp to 32 */ |
|
805 bpp = 32; |
847 |
806 |
848 /* Setup full screen video */ |
807 /* Setup full screen video */ |
849 if ( flags & SDL_FULLSCREEN ) { |
808 if ( flags & SDL_FULLSCREEN ) { |
850 current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); |
809 current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); |
851 if (current == NULL) |
810 if (current == NULL) |
852 return NULL; |
811 return NULL; |
853 } |
812 } |
854 /* Setup windowed video */ |
813 /* Setup windowed video */ |
855 else { |
814 else { |
856 /* Force bpp to 32 */ |
|
857 bpp = 32; |
|
858 current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags); |
815 current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags); |
859 if (current == NULL) |
816 if (current == NULL) |
860 return NULL; |
817 return NULL; |
861 } |
818 } |
862 |
819 |
938 |
886 |
939 if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) |
887 if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) |
940 return 0; |
888 return 0; |
941 |
889 |
942 return 1; |
890 return 1; |
943 } |
|
944 |
|
945 static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface) |
|
946 { |
|
947 return 1; |
|
948 } |
|
949 |
|
950 static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface) |
|
951 { |
|
952 } |
|
953 |
|
954 /* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */ |
|
955 static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) |
|
956 { |
|
957 union |
|
958 { |
|
959 UInt64 i; |
|
960 Nanoseconds ns; |
|
961 } temp; |
|
962 |
|
963 temp.i = seconds * 1000000000.0; |
|
964 |
|
965 return NanosecondsToAbsolute ( temp.ns ); |
|
966 } |
|
967 |
|
968 static int QZ_ThreadFlip (_THIS) |
|
969 { |
|
970 Uint8 *src, *dst; |
|
971 int skip, len, h; |
|
972 |
|
973 /* |
|
974 Give this thread the highest scheduling priority possible, |
|
975 in the hopes that it will immediately run after the VBL delay |
|
976 */ |
|
977 { |
|
978 pthread_t current_thread; |
|
979 int policy; |
|
980 struct sched_param param; |
|
981 |
|
982 current_thread = pthread_self (); |
|
983 pthread_getschedparam (current_thread, &policy, ¶m); |
|
984 policy = SCHED_RR; |
|
985 param.sched_priority = sched_get_priority_max (policy); |
|
986 pthread_setschedparam (current_thread, policy, ¶m); |
|
987 } |
|
988 |
|
989 while (1) { |
|
990 |
|
991 SDL_SemWait (sem1); |
|
992 if (quit_thread) |
|
993 return 0; |
|
994 |
|
995 /* |
|
996 * We have to add SDL_VideoSurface->offset here, since we might be a |
|
997 * smaller surface in the center of the framebuffer (you asked for |
|
998 * a fullscreen resolution smaller than the hardware could supply |
|
999 * so SDL is centering it in a bigger resolution)... |
|
1000 */ |
|
1001 dst = (Uint8 *)CGDisplayBaseAddress (display_id) + SDL_VideoSurface->offset; |
|
1002 src = current_buffer + SDL_VideoSurface->offset; |
|
1003 len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel; |
|
1004 h = SDL_VideoSurface->h; |
|
1005 skip = SDL_VideoSurface->pitch; |
|
1006 |
|
1007 /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */ |
|
1008 { |
|
1009 |
|
1010 /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */ |
|
1011 double refreshRate; |
|
1012 double linesPerSecond; |
|
1013 double target; |
|
1014 double position; |
|
1015 double adjustment; |
|
1016 AbsoluteTime nextTime; |
|
1017 CFNumberRef refreshRateCFNumber; |
|
1018 |
|
1019 refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate); |
|
1020 if ( NULL == refreshRateCFNumber ) { |
|
1021 SDL_SetError ("Mode has no refresh rate"); |
|
1022 goto ERROR; |
|
1023 } |
|
1024 |
|
1025 if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) { |
|
1026 SDL_SetError ("Error getting refresh rate"); |
|
1027 goto ERROR; |
|
1028 } |
|
1029 |
|
1030 if ( 0 == refreshRate ) { |
|
1031 |
|
1032 SDL_SetError ("Display has no refresh rate, using 60hz"); |
|
1033 |
|
1034 /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */ |
|
1035 refreshRate = 60.0; |
|
1036 } |
|
1037 |
|
1038 linesPerSecond = refreshRate * h; |
|
1039 target = h; |
|
1040 |
|
1041 /* Figure out the first delay so we start off about right */ |
|
1042 position = CGDisplayBeamPosition (display_id); |
|
1043 if (position > target) |
|
1044 position = 0; |
|
1045 |
|
1046 adjustment = (target - position) / linesPerSecond; |
|
1047 |
|
1048 nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment)); |
|
1049 |
|
1050 MPDelayUntil (&nextTime); |
|
1051 } |
|
1052 |
|
1053 |
|
1054 /* On error, skip VBL delay */ |
|
1055 ERROR: |
|
1056 |
|
1057 /* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we |
|
1058 create two buffers, replace current_buffer with current_context and set it |
|
1059 appropriately in QZ_FlipDoubleBuffer. */ |
|
1060 while ( h-- ) { |
|
1061 |
|
1062 SDL_memcpy (dst, src, len); |
|
1063 src += skip; |
|
1064 dst += skip; |
|
1065 } |
|
1066 |
|
1067 /* signal flip completion */ |
|
1068 SDL_SemPost (sem2); |
|
1069 } |
|
1070 |
|
1071 return 0; |
|
1072 } |
|
1073 |
|
1074 static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface) |
|
1075 { |
|
1076 /* wait for previous flip to complete */ |
|
1077 SDL_SemWait (sem2); |
|
1078 |
|
1079 current_buffer = surface->pixels; |
|
1080 |
|
1081 if (surface->pixels == sw_buffers[0]) |
|
1082 surface->pixels = sw_buffers[1]; |
|
1083 else |
|
1084 surface->pixels = sw_buffers[0]; |
|
1085 |
|
1086 /* signal worker thread to do the flip */ |
|
1087 SDL_SemPost (sem1); |
|
1088 |
|
1089 return 0; |
|
1090 } |
|
1091 |
|
1092 static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects) |
|
1093 { |
|
1094 /* perform a flip if someone calls updaterects on a doublebuferred surface */ |
|
1095 this->FlipHWSurface (this, SDL_VideoSurface); |
|
1096 } |
|
1097 |
|
1098 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) |
|
1099 { |
|
1100 #pragma unused(this,num_rects,rects) |
|
1101 } |
891 } |
1102 |
892 |
1103 |
893 |
1104 /* Resize icon, BMP format */ |
894 /* Resize icon, BMP format */ |
1105 static const unsigned char QZ_ResizeIcon[] = { |
895 static const unsigned char QZ_ResizeIcon[] = { |
1235 [field_edit release]; |
1025 [field_edit release]; |
1236 field_edit = NULL; |
1026 field_edit = NULL; |
1237 } |
1027 } |
1238 } |
1028 } |
1239 |
1029 |
1240 #if 0 /* Not used (apparently, it's really slow) */ |
|
1241 static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) |
|
1242 { |
|
1243 CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color); |
|
1244 |
|
1245 return 0; |
|
1246 } |
|
1247 #endif |
|
1248 |
|
1249 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) |
1030 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) |
1250 { |
1031 { |
1251 /* |
|
1252 * Always get latest bitmap address and rowbytes for the screen surface; |
|
1253 * they can change dynamically (user has multiple monitors, etc). |
|
1254 */ |
|
1255 if ((surface == SDL_VideoSurface) && (surface->flags & SDL_HWSURFACE)) { |
|
1256 surface->pixels = (void*) CGDisplayBaseAddress (kCGDirectMainDisplay); |
|
1257 surface->pitch = CGDisplayBytesPerRow (kCGDirectMainDisplay); |
|
1258 return (surface->pixels != NULL); |
|
1259 } |
|
1260 |
|
1261 return 1; |
1032 return 1; |
1262 } |
1033 } |
1263 |
1034 |
1264 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) |
1035 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) |
1265 { |
1036 { |