mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-02-20 19:12:11 +00:00
Use SDL GLimp and input implementations on OSX
This commit is contained in:
parent
03d4833aa9
commit
bf69f7ec76
12 changed files with 13 additions and 1885 deletions
|
@ -624,6 +624,7 @@ if (APPLE)
|
|||
set(src_sys_base
|
||||
sys/cpu.cpp
|
||||
sys/threads.cpp
|
||||
sys/events.cpp
|
||||
sys/sys_local.cpp
|
||||
sys/posix/posix_net.cpp
|
||||
sys/posix/posix_signal.cpp
|
||||
|
@ -631,13 +632,11 @@ if (APPLE)
|
|||
)
|
||||
|
||||
set(src_sys_core
|
||||
sys/glimp.cpp
|
||||
sys/glimp_ati_fragment_shader.cpp
|
||||
sys/posix/posix_input.cpp
|
||||
sys/osx/PickMonitor.cpp
|
||||
sys/osx/PreferencesDialog.cpp
|
||||
sys/osx/DOOMController.mm
|
||||
sys/osx/macosx_event.mm
|
||||
sys/osx/macosx_glimp.mm
|
||||
sys/osx/macosx_misc.mm
|
||||
)
|
||||
elseif (WIN32)
|
||||
|
|
|
@ -33,8 +33,9 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "framework/Licensee.h"
|
||||
|
||||
#include "renderer/tr_local.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(MACOS_X)
|
||||
#include "sys/glimp_ati_fragment_shader.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "sys/win32/win_local.h"
|
||||
#endif
|
||||
|
||||
|
@ -252,6 +253,13 @@ GLimp_ExtensionPointer
|
|||
GLExtension_t GLimp_ExtensionPointer(const char *name) {
|
||||
assert(SDL_WasInit(SDL_INIT_VIDEO));
|
||||
|
||||
#ifdef MACOS_X
|
||||
// special case for ATI_fragment_shader calls to map to ATI_text_fragment_shader routines
|
||||
GLExtension_t res = GLimp_ExtensionPointer_ATI_fragment_shader(name);
|
||||
if (res)
|
||||
return res;
|
||||
#endif
|
||||
|
||||
return (GLExtension_t)SDL_GL_GetProcAddress(name);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,17 +44,12 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#import "idlib/Str.h"
|
||||
#import "framework/Licensee.h"
|
||||
#import "framework/Common.h"
|
||||
#import "sys/osx/macosx_local.h"
|
||||
#import "sys/osx/macosx_sys.h"
|
||||
#import "sys/posix/posix_public.h"
|
||||
|
||||
#import "DOOMController.h"
|
||||
|
||||
#define MAX_KEYS 256
|
||||
|
||||
static idStr savepath;
|
||||
|
||||
extern bool key_overstrikeMode;
|
||||
|
||||
#define TEST_FPU_EXCEPTIONS \
|
||||
FPU_EXCEPTION_INVALID_OPERATION | \
|
||||
FPU_EXCEPTION_DENORMALIZED_OPERAND | \
|
||||
|
@ -97,16 +92,6 @@ FPU_EXCEPTION_DIVIDE_BY_ZERO | \
|
|||
Sys_Quit();
|
||||
}
|
||||
|
||||
- (void)applicationWillHide:(NSNotification *)notification;
|
||||
{
|
||||
Sys_ShutdownInput();
|
||||
}
|
||||
|
||||
- (void)applicationWillUnhide:(NSNotification *)notification;
|
||||
{
|
||||
Sys_InitInput();
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
common->Quit();
|
||||
|
@ -575,37 +560,6 @@ int Sys_GetSystemRam( void ) {
|
|||
return 1024;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetVideoRam
|
||||
returns in megabytes
|
||||
================
|
||||
*/
|
||||
int Sys_GetVideoRam( void ) {
|
||||
unsigned int i;
|
||||
CFTypeRef typeCode;
|
||||
long vramStorage = 64;
|
||||
const short MAXDISPLAYS = 8;
|
||||
CGDisplayCount displayCount;
|
||||
io_service_t dspPorts[MAXDISPLAYS];
|
||||
CGDirectDisplayID displays[MAXDISPLAYS];
|
||||
|
||||
CGGetOnlineDisplayList( MAXDISPLAYS, displays, &displayCount );
|
||||
|
||||
for ( i = 0; i < displayCount; i++ ) {
|
||||
if ( Sys_DisplayToUse() == displays[i] ) {
|
||||
dspPorts[i] = CGDisplayIOServicePort(displays[i]);
|
||||
typeCode = IORegistryEntryCreateCFProperty( dspPorts[i], CFSTR("IOFBMemorySize"), kCFAllocatorDefault, kNilOptions );
|
||||
if( typeCode && CFGetTypeID( typeCode ) == CFNumberGetTypeID() ) {
|
||||
CFNumberGetValue( ( CFNumberRef )typeCode, kCFNumberSInt32Type, &vramStorage );
|
||||
vramStorage /= (1024*1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vramStorage;
|
||||
}
|
||||
|
||||
bool OSX_GetCPUIdentification( int& cpuId, bool& oldArchitecture )
|
||||
{
|
||||
long cpu;
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#include "macosx_local.h"
|
||||
|
||||
@class NSDictionary;
|
||||
|
||||
extern NSDictionary *Sys_GetMatchingDisplayMode( glimpParms_t parms );
|
||||
|
||||
extern void Sys_StoreGammaTables();
|
||||
extern void Sys_GetGammaTable(glwgamma_t *table);
|
||||
extern void Sys_SetScreenFade(glwgamma_t *table, float fraction);
|
||||
|
||||
extern void Sys_FadeScreens();
|
||||
extern void Sys_FadeScreen(CGDirectDisplayID display);
|
||||
extern void Sys_UnfadeScreens();
|
||||
extern void Sys_UnfadeScreen(CGDirectDisplayID display, glwgamma_t *table);
|
||||
extern void Sys_ReleaseAllDisplays();
|
||||
|
|
@ -1,542 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// -*- mode: objc -*-
|
||||
#import <AppKit/NSCursor.h>
|
||||
#import <AppKit/NSWindow.h>
|
||||
#import <AppKit/NSScreen.h>
|
||||
#import <AppKit/NSApplication.h>
|
||||
#import <AppKit/NSGraphicsContext.h>
|
||||
#import <AppKit/NSEvent.h>
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSRunLoop.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
#import <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
#import <sys/types.h>
|
||||
#import <sys/time.h>
|
||||
#import <unistd.h>
|
||||
|
||||
#import "sys/platform.h"
|
||||
#import "framework/Common.h"
|
||||
#import "framework/KeyInput.h"
|
||||
#import "sys/osx/macosx_local.h"
|
||||
#import "sys/osx/macosx_sys.h"
|
||||
|
||||
static NSDate *distantPast = NULL;
|
||||
static bool inputActive = false;
|
||||
static bool mouseActive = false;
|
||||
static bool inputRectValid = NO;
|
||||
static CGRect inputRect;
|
||||
static const void *sKLuchrData = NULL;
|
||||
static const void *sKLKCHRData = NULL;
|
||||
|
||||
int vkeyToDoom3Key[256] = {
|
||||
/*0x00*/ 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x',
|
||||
/*0x08*/ 'c', 'v', '?', 'b', 'q', 'w', 'e', 'r',
|
||||
/*0x10*/ 'y', 't', '1', '2', '3', '4', '6', '5',
|
||||
/*0x18*/ '=', '9', '7', '-', '8', '0', ']', 'o',
|
||||
/*0x20*/ 'u', '[', 'i', 'p', K_ENTER, 'l', 'j', '\'',
|
||||
/*0x28*/ 'k', ';', '\\', ',', '/', 'n', 'm', '.',
|
||||
/*0x30*/ K_TAB, K_SPACE, '`', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
|
||||
/*0x38*/ K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
|
||||
/*0x40*/ '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
|
||||
/*0x48*/ '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
|
||||
/*0x50*/ '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
|
||||
/*0x58*/ K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
|
||||
/*0x60*/ K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
|
||||
/*0x68*/ '?', K_PRINT_SCR, '?', K_F14, '?', K_F10, '?', K_F12,
|
||||
/*0x70*/ '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,
|
||||
/*0x78*/ K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
|
||||
};
|
||||
|
||||
int vkeyToDoom3Key_French[256] = {
|
||||
/*0x00*/ 'q', 's', 'd', 'f', 'h', 'g', 'w', 'x',
|
||||
/*0x08*/ 'c', 'v', '?', 'b', 'a', 'z', 'e', 'r',
|
||||
/*0x10*/ 'y', 't', '1', '2', '3', '4', '6', '5',
|
||||
/*0x18*/ '-', '9', '7', ')', '8', '0', '$', 'o',
|
||||
/*0x20*/ 'u', '^', 'i', 'p', K_ENTER, 'l', 'j', 'ù',
|
||||
/*0x28*/ 'k', 'm', 0x60, ';', '=', 'n', ',', ':',
|
||||
/*0x30*/ K_TAB, K_SPACE, '<', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
|
||||
/*0x38*/ K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
|
||||
/*0x40*/ '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
|
||||
/*0x48*/ '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
|
||||
/*0x50*/ '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
|
||||
/*0x58*/ K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
|
||||
/*0x60*/ K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
|
||||
/*0x68*/ '?', K_PRINT_SCR, '?', K_F14, '?', K_F10, '?', K_F12,
|
||||
/*0x70*/ '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,
|
||||
/*0x78*/ K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
|
||||
};
|
||||
|
||||
int vkeyToDoom3Key_German[256] = {
|
||||
/*0x00*/ 'a', 's', 'd', 'f', 'h', 'g', 'y', 'x',
|
||||
/*0x08*/ 'c', 'v', '?', 'b', 'q', 'w', 'e', 'r',
|
||||
/*0x10*/ 'z', 't', '1', '2', '3', '4', '6', '5',
|
||||
/*0x18*/ '«', '9', '7', '-', '8', '0', '+', 'o',
|
||||
/*0x20*/ 'u', '[', 'i', 'p', K_ENTER, 'l', 'j', '\'',
|
||||
/*0x28*/ 'k', ';', '#', ',', '-', 'n', 'm', '.',
|
||||
/*0x30*/ K_TAB, K_SPACE, '`', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
|
||||
/*0x38*/ K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
|
||||
/*0x40*/ '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
|
||||
/*0x48*/ '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
|
||||
/*0x50*/ '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
|
||||
/*0x58*/ K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
|
||||
/*0x60*/ K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
|
||||
/*0x68*/ '?', K_PRINT_SCR, '?', K_F14, '?', K_F10, '?', K_F12,
|
||||
/*0x70*/ '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,
|
||||
/*0x78*/ K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
|
||||
};
|
||||
|
||||
static const int *vkeyTable = vkeyToDoom3Key;
|
||||
|
||||
/*
|
||||
===========
|
||||
Sys_InitScanTable
|
||||
===========
|
||||
*/
|
||||
void Sys_InitScanTable( void ) {
|
||||
KeyboardLayoutRef kbLayout;
|
||||
|
||||
idStr lang = cvarSystem->GetCVarString( "sys_lang" );
|
||||
if ( lang.Length() == 0 ) {
|
||||
lang = "english";
|
||||
}
|
||||
|
||||
if ( lang.Icmp( "english" ) == 0 ) {
|
||||
vkeyTable = vkeyToDoom3Key;
|
||||
} else if ( lang.Icmp( "french" ) == 0 ) {
|
||||
vkeyTable = vkeyToDoom3Key_French;
|
||||
} else if ( lang.Icmp( "german" ) == 0 ) {
|
||||
vkeyTable = vkeyToDoom3Key_German;
|
||||
}
|
||||
|
||||
if ( KLGetCurrentKeyboardLayout( &kbLayout ) == 0 ) {
|
||||
if ( KLGetKeyboardLayoutProperty( kbLayout, kKLuchrData, &sKLuchrData ) ) {
|
||||
common->Warning("KLGetKeyboardLayoutProperty failed");
|
||||
}
|
||||
if ( !sKLuchrData ) {
|
||||
if ( KLGetKeyboardLayoutProperty( kbLayout, kKLKCHRData, &sKLKCHRData ) ) {
|
||||
common->Warning("KLGetKeyboardLayoutProperty failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !sKLuchrData && !sKLKCHRData ) {
|
||||
common->Warning("Keyboard input initialziation failed");
|
||||
}
|
||||
}
|
||||
|
||||
void Sys_InitInput( void ) {
|
||||
common->Printf( "------- Input Initialization -------\n" );
|
||||
|
||||
if ( !distantPast ) {
|
||||
distantPast = [ [ NSDate distantPast ] retain ];
|
||||
}
|
||||
|
||||
IN_ActivateMouse();
|
||||
|
||||
inputActive = true;
|
||||
}
|
||||
|
||||
void Sys_ShutdownInput( void ) {
|
||||
common->Printf( "------- Input Shutdown -------\n" );
|
||||
|
||||
if ( !inputActive ) {
|
||||
return;
|
||||
}
|
||||
inputActive = false;
|
||||
if ( mouseActive ) {
|
||||
IN_DeactivateMouse();
|
||||
}
|
||||
|
||||
common->Printf( "------------------------------\n" );
|
||||
}
|
||||
|
||||
void processMouseMovedEvent( NSEvent *mouseMovedEvent ) {
|
||||
CGMouseDelta dx, dy;
|
||||
|
||||
if ( !mouseActive ) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#define ACT_LIKE_WINDOWS
|
||||
#ifdef ACT_LIKE_WINDOWS
|
||||
cvar_t *in_mouseLowEndSlope = Cvar_Get("in_mouseLowEndSlope", "3.5", CVAR_ARCHIVE);
|
||||
if (in_mouseLowEndSlope->value < 1) {
|
||||
Cvar_Set("in_mouseLowEndSlope", "1");
|
||||
}
|
||||
#else
|
||||
cvar_t *in_mouseLowEndSlope = Cvar_Get("in_mouseLowEndSlope", "1", CVAR_ARCHIVE);
|
||||
if (in_mouseLowEndSlope->value < 1) {
|
||||
Cvar_Set("in_mouseLowEndSlope", "1");
|
||||
}
|
||||
#endif
|
||||
|
||||
cvar_t *in_mouseHighEndCutoff = Cvar_Get("in_mouseHighEndCutoff", "20", CVAR_ARCHIVE);
|
||||
if (in_mouseLowEndSlope->value < 1) {
|
||||
Cvar_Set("in_mouseHighEndCutoff", "1");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CGGetLastMouseDelta(&dx, &dy);
|
||||
|
||||
if ( dx || dy ) {
|
||||
#if 0 // this is be handled by the mouse driver clean me out later
|
||||
CGMouseDelta distSqr;
|
||||
float m0, N;
|
||||
|
||||
distSqr = dx * dx + dy * dy;
|
||||
//Com_Printf("distSqr = %d\n", distSqr);
|
||||
|
||||
/* This code is here to help people that like the feel of the Logitech USB Gaming Mouse with the Win98 drivers. By empirical testing, the Windows drivers seem to be more heavily accelerated at the low end of the curve. */
|
||||
//N = in_mouseHighEndCutoff->value;
|
||||
N = 1;
|
||||
|
||||
if (distSqr < N*N) {
|
||||
float dist, accel, scale;
|
||||
|
||||
//m0 = in_mouseLowEndSlope->value;
|
||||
m0 = 1;
|
||||
dist = sqrt(distSqr);
|
||||
accel = (((m0 - 1.0)/(N*N) * dist + (2.0 - 2.0*m0)/N) * dist + m0) * dist;
|
||||
|
||||
scale = accel / dist;
|
||||
//Com_Printf("dx = %d, dy = %d, dist = %f, accel = %f, scale = %f\n", dx, dy, dist, accel, scale);
|
||||
|
||||
dx *= scale;
|
||||
dy *= scale;
|
||||
}
|
||||
#endif
|
||||
Posix_QueEvent( SE_MOUSE, dx, dy, 0, NULL );
|
||||
Posix_AddMousePollEvent( M_DELTAX, dx );
|
||||
Posix_AddMousePollEvent( M_DELTAY, dy );
|
||||
}
|
||||
}
|
||||
|
||||
inline bool OSX_LookupCharacter(unsigned short vkey, unsigned int modifiers, bool keyDownFlag, unsigned char *outChar)
|
||||
{
|
||||
UInt32 translated;
|
||||
UInt32 deadKeyState = 0;
|
||||
UniChar unicodeString[16];
|
||||
UniCharCount actualStringLength = 0;
|
||||
static UInt32 keyTranslateState = 0;
|
||||
|
||||
// Only want character if Translate() returns a single character
|
||||
if ( sKLuchrData ) {
|
||||
UCKeyTranslate( (UCKeyboardLayout*)sKLuchrData, vkey, keyDownFlag ? kUCKeyActionDown : kUCKeyActionUp, modifiers,
|
||||
LMGetKbdType(), 0, &deadKeyState, 16, &actualStringLength, unicodeString );
|
||||
|
||||
if ( actualStringLength == 1 ) {
|
||||
*outChar = (unsigned char)unicodeString[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ( sKLKCHRData ) {
|
||||
translated = KeyTranslate( sKLKCHRData, vkey, &keyTranslateState );
|
||||
if ( ( translated & 0x00ff0000 ) == 0 ) {
|
||||
*outChar = translated & 0xff;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OSX_ProcessKeyEvent( NSEvent *keyEvent, bool keyDownFlag ) {
|
||||
unsigned char character;
|
||||
unsigned int modifiers = 0;
|
||||
unsigned short vkey = [ keyEvent keyCode ];
|
||||
|
||||
if ( [ keyEvent modifierFlags ] & NSAlphaShiftKeyMask )
|
||||
modifiers |= alphaLock;
|
||||
if ( [ keyEvent modifierFlags ] & NSShiftKeyMask )
|
||||
modifiers |= shiftKey;
|
||||
if ( [ keyEvent modifierFlags ] & NSControlKeyMask )
|
||||
modifiers |= controlKey;
|
||||
if ( [ keyEvent modifierFlags ] & NSAlternateKeyMask )
|
||||
modifiers |= optionKey;
|
||||
if ( [ keyEvent modifierFlags ] & NSCommandKeyMask )
|
||||
modifiers |= cmdKey;
|
||||
modifiers >>= 8;
|
||||
|
||||
int doomKey = (unsigned char)vkeyTable[vkey];
|
||||
Posix_QueEvent( SE_KEY, doomKey, keyDownFlag, 0, NULL );
|
||||
if ( keyDownFlag ) {
|
||||
if ( OSX_LookupCharacter(vkey, modifiers, keyDownFlag, &character ) &&
|
||||
character != Sys_GetConsoleKey( false ) && character != Sys_GetConsoleKey( true ) ) {
|
||||
Posix_QueEvent( SE_CHAR, character, 0, 0, NULL);
|
||||
}
|
||||
}
|
||||
Posix_AddKeyboardPollEvent( doomKey, keyDownFlag );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void sendEventForMaskChangeInFlags( int quakeKey, unsigned int modifierMask, unsigned int oldModifierFlags, unsigned int newModifierFlags ) {
|
||||
bool oldHadModifier, newHasModifier;
|
||||
|
||||
oldHadModifier = (oldModifierFlags & modifierMask) != 0;
|
||||
newHasModifier = (newModifierFlags & modifierMask) != 0;
|
||||
if (oldHadModifier != newHasModifier) {
|
||||
//NSLog(@"Key %d posted for modifier mask modifierMask", quakeKey);
|
||||
Posix_QueEvent( SE_KEY, quakeKey, newHasModifier, 0, NULL);
|
||||
Posix_AddKeyboardPollEvent( quakeKey, newHasModifier );
|
||||
}
|
||||
}
|
||||
|
||||
void processFlagsChangedEvent( NSEvent *flagsChangedEvent ) {
|
||||
static int oldModifierFlags;
|
||||
int newModifierFlags;
|
||||
|
||||
newModifierFlags = [flagsChangedEvent modifierFlags];
|
||||
sendEventForMaskChangeInFlags( K_ALT, NSAlternateKeyMask, oldModifierFlags, newModifierFlags );
|
||||
sendEventForMaskChangeInFlags( K_CTRL, NSControlKeyMask, oldModifierFlags, newModifierFlags );
|
||||
sendEventForMaskChangeInFlags( K_SHIFT, NSShiftKeyMask, oldModifierFlags, newModifierFlags );
|
||||
oldModifierFlags = newModifierFlags;
|
||||
}
|
||||
|
||||
void processSystemDefinedEvent( NSEvent *systemDefinedEvent ) {
|
||||
static int oldButtons = 0;
|
||||
int buttonsDelta;
|
||||
int buttons;
|
||||
int isDown;
|
||||
|
||||
if ( [systemDefinedEvent subtype] == 7 ) {
|
||||
|
||||
if ( !mouseActive ) {
|
||||
return;
|
||||
}
|
||||
|
||||
buttons = [systemDefinedEvent data2];
|
||||
buttonsDelta = oldButtons ^ buttons;
|
||||
|
||||
//common->Printf( "uberbuttons: %08lx %08lx\n", buttonsDelta, buttons );
|
||||
|
||||
if (buttonsDelta & 1) {
|
||||
isDown = buttons & 1;
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE1, isDown, 0, NULL);
|
||||
Posix_AddMousePollEvent( M_ACTION1, isDown );
|
||||
}
|
||||
|
||||
if (buttonsDelta & 2) {
|
||||
isDown = buttons & 2;
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE2, isDown, 0, NULL);
|
||||
Posix_AddMousePollEvent( M_ACTION2, isDown );
|
||||
}
|
||||
|
||||
if (buttonsDelta & 4) {
|
||||
isDown = buttons & 4;
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE3, isDown, 0, NULL);
|
||||
Posix_AddMousePollEvent( M_ACTION3, isDown );
|
||||
}
|
||||
|
||||
if (buttonsDelta & 8) {
|
||||
isDown = buttons & 8;
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE4, isDown, 0, NULL);
|
||||
Posix_AddMousePollEvent( M_ACTION4, isDown );
|
||||
}
|
||||
|
||||
if (buttonsDelta & 16) {
|
||||
isDown = buttons & 16;
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE5, isDown, 0, NULL);
|
||||
Posix_AddMousePollEvent( M_ACTION5, isDown );
|
||||
}
|
||||
|
||||
oldButtons = buttons;
|
||||
}
|
||||
}
|
||||
|
||||
void processEvent( NSEvent *event ) {
|
||||
NSEventType eventType;
|
||||
|
||||
if ( !inputActive ) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventType = [ event type ];
|
||||
|
||||
switch ( eventType ) {
|
||||
// These four event types are ignored since we do all of our mouse down/up process via the uber-mouse system defined event. We have to accept these events however since they get enqueued and the queue will fill up if we don't.
|
||||
case NSLeftMouseDown:
|
||||
case NSLeftMouseUp:
|
||||
case NSRightMouseDown:
|
||||
case NSRightMouseUp:
|
||||
//NSLog( @"ignore simple mouse event %@", event );
|
||||
return;
|
||||
case NSMouseMoved:
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
processMouseMovedEvent( event );
|
||||
return;
|
||||
case NSKeyDown:
|
||||
// Send ALL command key-ups to Quake, but not command key-downs, otherwise if the user hits a key, presses command, and lets up on the key, the key-up won't register.
|
||||
if ( [ event modifierFlags ] & NSCommandKeyMask ) {
|
||||
NSLog( @"command key up ignored: %@", event );
|
||||
break;
|
||||
}
|
||||
case NSKeyUp:
|
||||
OSX_ProcessKeyEvent( event, eventType == NSKeyDown );
|
||||
return;
|
||||
case NSFlagsChanged:
|
||||
processFlagsChangedEvent( event );
|
||||
return;
|
||||
case NSSystemDefined:
|
||||
processSystemDefinedEvent( event );
|
||||
return;
|
||||
case NSScrollWheel:
|
||||
if ([event deltaY] < 0.0) {
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELDOWN, true, 0, NULL );
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELDOWN, false, 0, NULL );
|
||||
Posix_AddMousePollEvent( M_DELTAZ, -1 );
|
||||
} else {
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELUP, true, 0, NULL );
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELUP, false, 0, NULL );
|
||||
Posix_AddMousePollEvent( M_DELTAZ, 1 );
|
||||
}
|
||||
return;
|
||||
default:
|
||||
//NSLog( @"handle event %@", event );
|
||||
break;
|
||||
}
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
|
||||
void Posix_PollInput( void ) {
|
||||
NSEvent *event;
|
||||
unsigned int eventMask;
|
||||
|
||||
eventMask = NSAnyEventMask;
|
||||
|
||||
while ( ( event = [ NSApp nextEventMatchingMask: eventMask
|
||||
untilDate: distantPast
|
||||
inMode: NSDefaultRunLoopMode
|
||||
dequeue:YES ] ) ) {
|
||||
processEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
void Sys_PreventMouseMovement( CGPoint point ) {
|
||||
CGEventErr err;
|
||||
|
||||
//common->Printf( "**** Calling CGAssociateMouseAndMouseCursorPosition(false)\n" );
|
||||
err = CGAssociateMouseAndMouseCursorPosition( false );
|
||||
if ( err != CGEventNoErr ) {
|
||||
common->Error( "Could not disable mouse movement, CGAssociateMouseAndMouseCursorPosition returned %d\n", err );
|
||||
}
|
||||
|
||||
// Put the mouse in the position we want to leave it at
|
||||
err = CGWarpMouseCursorPosition( point );
|
||||
if ( err != CGEventNoErr ) {
|
||||
common->Error( "Could not disable mouse movement, CGWarpMouseCursorPosition returned %d\n", err );
|
||||
}
|
||||
}
|
||||
|
||||
void Sys_ReenableMouseMovement() {
|
||||
CGEventErr err;
|
||||
|
||||
//common->Printf( "**** Calling CGAssociateMouseAndMouseCursorPosition(true)\n" );
|
||||
err = CGAssociateMouseAndMouseCursorPosition( true );
|
||||
if ( err != CGEventNoErr ) {
|
||||
common->Error( "Could not reenable mouse movement, CGAssociateMouseAndMouseCursorPosition returned %d\n", err );
|
||||
}
|
||||
|
||||
// Leave the mouse where it was -- don't warp here.
|
||||
}
|
||||
|
||||
void Sys_LockMouseInInputRect(CGRect rect) {
|
||||
CGPoint center;
|
||||
|
||||
center.x = rect.origin.x + rect.size.width / 2.0;
|
||||
center.y = rect.origin.y + rect.size.height / 2.0;
|
||||
|
||||
// Now, put the mouse in the middle of the input rect (anywhere over it would do)
|
||||
// and don't allow it to move. This means that the user won't be able to accidentally
|
||||
// select another application.
|
||||
Sys_PreventMouseMovement(center);
|
||||
}
|
||||
|
||||
void Sys_SetMouseInputRect(CGRect newRect) {
|
||||
inputRectValid = YES;
|
||||
inputRect = newRect;
|
||||
|
||||
if ( mouseActive ) {
|
||||
Sys_LockMouseInInputRect( inputRect );
|
||||
}
|
||||
}
|
||||
|
||||
void IN_ActivateMouse( void ) {
|
||||
if ( mouseActive ) {
|
||||
return;
|
||||
}
|
||||
if ( inputRectValid ) {
|
||||
// Make sure that if window moved we don't hose the user...
|
||||
Sys_UpdateWindowMouseInputRect();
|
||||
}
|
||||
Sys_LockMouseInInputRect( inputRect );
|
||||
CGDisplayHideCursor( Sys_DisplayToUse() );
|
||||
mouseActive = true;
|
||||
}
|
||||
|
||||
void IN_DeactivateMouse( void ) {
|
||||
if ( !mouseActive ) {
|
||||
return;
|
||||
}
|
||||
Sys_ReenableMouseMovement();
|
||||
CGDisplayShowCursor( Sys_DisplayToUse() );
|
||||
mouseActive = false;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_MapCharForKey
|
||||
===============
|
||||
*/
|
||||
unsigned char Sys_MapCharForKey( int key ) {
|
||||
return (unsigned char)key;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_GetConsoleKey
|
||||
===============
|
||||
*/
|
||||
unsigned char Sys_GetConsoleKey( bool shifted ) {
|
||||
if ( vkeyTable == vkeyToDoom3Key_French ) {
|
||||
return shifted ? '>' : '<';
|
||||
}
|
||||
else {
|
||||
return shifted ? '~' : '`';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#ifndef GL_EXT_abgr
|
||||
#include <OpenGL/glext.h>
|
||||
#endif
|
||||
|
||||
// This can be defined to use the CGLMacro.h support which avoids looking up
|
||||
// the current context.
|
||||
//#define USE_CGLMACROS
|
||||
|
||||
#ifdef USE_CGLMACROS
|
||||
#include "macosx_local.h"
|
||||
#define cgl_ctx glw_state._cgl_ctx
|
||||
#include <OpenGL/CGLMacro.h>
|
||||
#endif
|
||||
|
|
@ -1,936 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// -*- mode: objc -*-
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <mach-o/dyld.h>
|
||||
#import <mach/mach.h>
|
||||
#import <mach/mach_error.h>
|
||||
|
||||
#import "sys/platform.h"
|
||||
#import "framework/Licensee.h"
|
||||
#import "renderer/tr_local.h"
|
||||
#import "sys/glimp_ati_fragment_shader.h"
|
||||
#import "sys/osx/macosx_glimp.h"
|
||||
#import "sys/osx/macosx_local.h"
|
||||
#import "sys/osx/macosx_sys.h"
|
||||
#import "sys/osx/macosx_display.h"
|
||||
|
||||
static idCVar r_minDisplayRefresh( "r_minDisplayRefresh", "0", CVAR_ARCHIVE | CVAR_INTEGER, "" );
|
||||
static idCVar r_maxDisplayRefresh( "r_maxDisplayRefresh", "0", CVAR_ARCHIVE | CVAR_INTEGER, "" );
|
||||
static idCVar r_screen( "r_screen", "-1", CVAR_ARCHIVE | CVAR_INTEGER, "which display to use" );
|
||||
|
||||
static bool CreateGameWindow( glimpParms_t parms );
|
||||
static unsigned long Sys_QueryVideoMemory();
|
||||
CGDisplayErr Sys_CaptureActiveDisplays(void);
|
||||
|
||||
glwstate_t glw_state;
|
||||
static bool isHidden = false;
|
||||
|
||||
@interface NSOpenGLContext (CGLContextAccess)
|
||||
- (CGLContextObj) cglContext;
|
||||
@end
|
||||
|
||||
@implementation NSOpenGLContext (CGLContextAccess)
|
||||
- (CGLContextObj) cglContext;
|
||||
{
|
||||
return _contextAuxiliary;
|
||||
}
|
||||
@end
|
||||
|
||||
/*
|
||||
============
|
||||
CheckErrors
|
||||
============
|
||||
*/
|
||||
void CheckErrors( void ) {
|
||||
GLenum err;
|
||||
|
||||
err = qglGetError();
|
||||
if ( err != GL_NO_ERROR ) {
|
||||
common->Error( "glGetError: %s\n", qglGetString( err ) );
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && defined(QGL_CHECK_GL_ERRORS)
|
||||
|
||||
unsigned int QGLBeginStarted = 0;
|
||||
|
||||
void QGLErrorBreak(void) { }
|
||||
|
||||
void QGLCheckError( const char *message ) {
|
||||
GLenum error;
|
||||
static unsigned int errorCount = 0;
|
||||
|
||||
error = _glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
if (errorCount == 100) {
|
||||
common->Printf("100 GL errors printed ... disabling further error reporting.\n");
|
||||
} else if (errorCount < 100) {
|
||||
if (errorCount == 0) {
|
||||
common->Warning("BREAK ON QGLErrorBreak to stop at the GL errors\n");
|
||||
}
|
||||
common->Warning("OpenGL Error(%s): 0x%04x -- %s\n", message, (int)error, gluErrorString(error));
|
||||
QGLErrorBreak();
|
||||
}
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** GLimp_SetMode
|
||||
*/
|
||||
|
||||
bool GLimp_SetMode( glimpParms_t parms ) {
|
||||
if ( !CreateGameWindow( parms ) ) {
|
||||
common->Printf( "GLimp_SetMode: window could not be created!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
glConfig.vidWidth = parms.width;
|
||||
glConfig.vidHeight = parms.height;
|
||||
glConfig.isFullscreen = parms.fullScreen;
|
||||
|
||||
// draw something to show that GL is alive
|
||||
qglClearColor( 0.5, 0.5, 0.7, 0 );
|
||||
qglClear( GL_COLOR_BUFFER_BIT );
|
||||
GLimp_SwapBuffers();
|
||||
|
||||
qglClearColor( 0.5, 0.5, 0.7, 0 );
|
||||
qglClear( GL_COLOR_BUFFER_BIT );
|
||||
GLimp_SwapBuffers();
|
||||
|
||||
CheckErrors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GetPixelAttributes
|
||||
=================
|
||||
*/
|
||||
|
||||
#define ADD_ATTR(x) \
|
||||
do { \
|
||||
if (attributeIndex >= attributeSize) { \
|
||||
attributeSize *= 2; \
|
||||
pixelAttributes = (NSOpenGLPixelFormatAttribute *)NSZoneRealloc(NULL, pixelAttributes, sizeof(*pixelAttributes) * attributeSize); \
|
||||
} \
|
||||
pixelAttributes[attributeIndex] = (NSOpenGLPixelFormatAttribute)x; \
|
||||
attributeIndex++; \
|
||||
if ( verbose ) { \
|
||||
common->Printf( "Adding pixel attribute: %d (%s)\n", x, #x); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static NSOpenGLPixelFormatAttribute *GetPixelAttributes( unsigned int multisamples ) {
|
||||
NSOpenGLPixelFormatAttribute *pixelAttributes;
|
||||
unsigned int attributeIndex = 0;
|
||||
unsigned int attributeSize = 128;
|
||||
int verbose;
|
||||
unsigned int colorDepth;
|
||||
unsigned int desktopColorDepth;
|
||||
unsigned int depthBits;
|
||||
unsigned int stencilBits;
|
||||
unsigned int buffers;
|
||||
|
||||
verbose = 0;
|
||||
|
||||
pixelAttributes = (NSOpenGLPixelFormatAttribute *)NSZoneMalloc(NULL, sizeof(*pixelAttributes) * attributeSize);
|
||||
|
||||
// only greater or equal attributes will be selected
|
||||
ADD_ATTR( NSOpenGLPFAMinimumPolicy );
|
||||
ADD_ATTR( 1 );
|
||||
|
||||
if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
|
||||
ADD_ATTR(NSOpenGLPFAFullScreen);
|
||||
}
|
||||
|
||||
ADD_ATTR(NSOpenGLPFAScreenMask);
|
||||
ADD_ATTR(CGDisplayIDToOpenGLDisplayMask(Sys_DisplayToUse()));
|
||||
|
||||
// Require hardware acceleration
|
||||
ADD_ATTR(NSOpenGLPFAAccelerated);
|
||||
|
||||
// Require double-buffer
|
||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
||||
|
||||
// color bits
|
||||
ADD_ATTR(NSOpenGLPFAColorSize);
|
||||
colorDepth = 32;
|
||||
if ( !cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
|
||||
desktopColorDepth = [[glw_state.desktopMode objectForKey: (id)kCGDisplayBitsPerPixel] intValue];
|
||||
if ( desktopColorDepth != 32 ) {
|
||||
common->Warning( "Desktop display colors should be 32 bits for window rendering" );
|
||||
}
|
||||
}
|
||||
ADD_ATTR(colorDepth);
|
||||
|
||||
// Specify the number of depth bits
|
||||
ADD_ATTR( NSOpenGLPFADepthSize );
|
||||
depthBits = 24;
|
||||
ADD_ATTR( depthBits );
|
||||
|
||||
// Specify the number of stencil bits
|
||||
stencilBits = 8;
|
||||
ADD_ATTR( NSOpenGLPFAStencilSize );
|
||||
ADD_ATTR( stencilBits );
|
||||
|
||||
// Specify destination alpha
|
||||
ADD_ATTR( NSOpenGLPFAAlphaSize );
|
||||
ADD_ATTR( 8 );
|
||||
|
||||
if ( multisamples ) {
|
||||
buffers = 1;
|
||||
ADD_ATTR( NSOpenGLPFASampleBuffers );
|
||||
ADD_ATTR( buffers );
|
||||
ADD_ATTR( NSOpenGLPFASamples );
|
||||
ADD_ATTR( multisamples );
|
||||
}
|
||||
|
||||
// Terminate the list
|
||||
ADD_ATTR(0);
|
||||
|
||||
return pixelAttributes;
|
||||
}
|
||||
|
||||
void Sys_UpdateWindowMouseInputRect(void) {
|
||||
NSRect windowRect, screenRect;
|
||||
NSScreen *screen;
|
||||
|
||||
/*
|
||||
|
||||
// TTimo - I guess glw_state.window is bogus .. getting crappy data out of this
|
||||
|
||||
// It appears we need to flip the coordinate system here. This means we need
|
||||
// to know the size of the screen.
|
||||
screen = [glw_state.window screen];
|
||||
screenRect = [screen frame];
|
||||
windowRect = [glw_state.window frame];
|
||||
windowRect.origin.y = screenRect.size.height - (windowRect.origin.y + windowRect.size.height);
|
||||
|
||||
Sys_SetMouseInputRect( CGRectMake( windowRect.origin.x, windowRect.origin.y, windowRect.size.width, windowRect.size.height ) );
|
||||
*/
|
||||
|
||||
Sys_SetMouseInputRect( CGDisplayBounds( glw_state.display ) );
|
||||
}
|
||||
|
||||
// This is needed since CGReleaseAllDisplays() restores the gamma on the displays and we want to fade it up rather than just flickering all the displays
|
||||
static void ReleaseAllDisplays() {
|
||||
CGDisplayCount displayIndex;
|
||||
|
||||
common->Printf("Releasing displays\n");
|
||||
for (displayIndex = 0; displayIndex < glw_state.displayCount; displayIndex++) {
|
||||
CGDisplayRelease(glw_state.originalDisplayGammaTables[displayIndex].display);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CreateGameWindow
|
||||
=================
|
||||
*/
|
||||
static bool CreateGameWindow( glimpParms_t parms ) {
|
||||
const char *windowed[] = { "Windowed", "Fullscreen" };
|
||||
NSOpenGLPixelFormatAttribute *pixelAttributes;
|
||||
NSOpenGLPixelFormat *pixelFormat;
|
||||
CGDisplayErr err;
|
||||
unsigned int multisamples;
|
||||
const long swap_limit = false;
|
||||
int nsOpenGLCPSwapLimit = 203;
|
||||
|
||||
glw_state.display = Sys_DisplayToUse();
|
||||
glw_state.desktopMode = (NSDictionary *)CGDisplayCurrentMode( glw_state.display );
|
||||
if ( !glw_state.desktopMode ) {
|
||||
common->Error( "Could not get current graphics mode for display 0x%08x\n", glw_state.display );
|
||||
}
|
||||
|
||||
common->Printf( " %d %d %s\n", parms.width, parms.height, windowed[ parms.fullScreen ] );
|
||||
|
||||
if (parms.fullScreen) {
|
||||
|
||||
// We'll set up the screen resolution first in case that effects the list of pixel
|
||||
// formats that are available (for example, a smaller frame buffer might mean more
|
||||
// bits for depth/stencil buffers). Allow stretched video modes if we are in fallback mode.
|
||||
glw_state.gameMode = Sys_GetMatchingDisplayMode(parms);
|
||||
if (!glw_state.gameMode) {
|
||||
common->Printf( "Unable to find requested display mode.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
err = Sys_CaptureActiveDisplays();
|
||||
if ( err != CGDisplayNoErr ) {
|
||||
CGDisplayRestoreColorSyncSettings();
|
||||
common->Printf( " Unable to capture displays err = %d\n", err );
|
||||
return false;
|
||||
}
|
||||
|
||||
err = CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.gameMode);
|
||||
if ( err != CGDisplayNoErr ) {
|
||||
CGDisplayRestoreColorSyncSettings();
|
||||
ReleaseAllDisplays();
|
||||
common->Printf( " Unable to set display mode, err = %d\n", err );
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
glw_state.gameMode = glw_state.desktopMode;
|
||||
}
|
||||
|
||||
// Get the GL pixel format
|
||||
pixelFormat = nil;
|
||||
multisamples = cvarSystem->GetCVarInteger( "r_multiSamples" );
|
||||
while ( !pixelFormat ) {
|
||||
pixelAttributes = GetPixelAttributes( multisamples );
|
||||
pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes: pixelAttributes] autorelease];
|
||||
NSZoneFree(NULL, pixelAttributes);
|
||||
if ( pixelFormat || multisamples == 0 )
|
||||
break;
|
||||
multisamples >>= 1;
|
||||
}
|
||||
cvarSystem->SetCVarInteger( "r_multiSamples", multisamples );
|
||||
|
||||
if (!pixelFormat) {
|
||||
CGDisplayRestoreColorSyncSettings();
|
||||
CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.desktopMode);
|
||||
ReleaseAllDisplays();
|
||||
common->Printf( " No pixel format found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a context with the desired pixel attributes
|
||||
OSX_SetGLContext([[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: nil]);
|
||||
if ( !OSX_GetNSGLContext() ) {
|
||||
CGDisplayRestoreColorSyncSettings();
|
||||
CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.desktopMode);
|
||||
ReleaseAllDisplays();
|
||||
common->Printf( "... +[NSOpenGLContext createWithFormat:share:] failed.\n" );
|
||||
return false;
|
||||
}
|
||||
#ifdef __ppc__
|
||||
long system_version = 0;
|
||||
Gestalt( gestaltSystemVersion, &system_version );
|
||||
if ( parms.width <= 1024 && parms.height <= 768 && system_version <= 0x1045 ) {
|
||||
[ OSX_GetNSGLContext() setValues: &swap_limit forParameter: (NSOpenGLContextParameter)nsOpenGLCPSwapLimit ];
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !parms.fullScreen ) {
|
||||
NSScreen* screen;
|
||||
NSRect windowRect;
|
||||
int displayIndex;
|
||||
int displayCount;
|
||||
|
||||
displayIndex = r_screen.GetInteger();
|
||||
displayCount = [[NSScreen screens] count];
|
||||
if ( displayIndex < 0 || displayIndex >= displayCount ) {
|
||||
screen = [NSScreen mainScreen];
|
||||
} else {
|
||||
screen = [[NSScreen screens] objectAtIndex:displayIndex];
|
||||
}
|
||||
|
||||
NSRect r = [screen frame];
|
||||
windowRect.origin.x = ((short)r.size.width - parms.width) / 2;
|
||||
windowRect.origin.y = ((short)r.size.height - parms.height) / 2;
|
||||
windowRect.size.width = parms.width;
|
||||
windowRect.size.height = parms.height;
|
||||
|
||||
glw_state.window = [NSWindow alloc];
|
||||
[glw_state.window initWithContentRect:windowRect styleMask:NSTitledWindowMask backing:NSBackingStoreRetained defer:NO screen:screen];
|
||||
|
||||
[glw_state.window setTitle: @GAME_NAME];
|
||||
|
||||
[glw_state.window orderFront: nil];
|
||||
|
||||
// Always get mouse moved events (if mouse support is turned off (rare)
|
||||
// the event system will filter them out.
|
||||
[glw_state.window setAcceptsMouseMovedEvents: YES];
|
||||
|
||||
// Direct the context to draw in this window
|
||||
[OSX_GetNSGLContext() setView: [glw_state.window contentView]];
|
||||
|
||||
// Sync input rect with where the window actually is...
|
||||
Sys_UpdateWindowMouseInputRect();
|
||||
} else {
|
||||
CGLError err;
|
||||
|
||||
glw_state.window = NULL;
|
||||
|
||||
err = CGLSetFullScreen(OSX_GetCGLContext());
|
||||
if (err) {
|
||||
CGDisplayRestoreColorSyncSettings();
|
||||
CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.desktopMode);
|
||||
ReleaseAllDisplays();
|
||||
common->Printf("CGLSetFullScreen -> %d (%s)\n", err, CGLErrorString(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
Sys_SetMouseInputRect( CGDisplayBounds( glw_state.display ) );
|
||||
}
|
||||
|
||||
#ifndef USE_CGLMACROS
|
||||
// Make this the current context
|
||||
OSX_GLContextSetCurrent();
|
||||
#endif
|
||||
|
||||
// Store off the pixel format attributes that we actually got
|
||||
[pixelFormat getValues: (long *) &glConfig.colorBits forAttribute: NSOpenGLPFAColorSize forVirtualScreen: 0];
|
||||
[pixelFormat getValues: (long *) &glConfig.depthBits forAttribute: NSOpenGLPFADepthSize forVirtualScreen: 0];
|
||||
[pixelFormat getValues: (long *) &glConfig.stencilBits forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: 0];
|
||||
|
||||
glConfig.displayFrequency = [[glw_state.gameMode objectForKey: (id)kCGDisplayRefreshRate] intValue];
|
||||
|
||||
common->Printf( "ok\n" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
GLimp_Init
|
||||
|
||||
Don't return unless OpenGL has been properly initialized
|
||||
===================
|
||||
*/
|
||||
bool GLimp_Init( glimpParms_t parms ) {
|
||||
char *buf;
|
||||
|
||||
common->Printf( "Initializing OpenGL subsystem\n" );
|
||||
common->Printf( " fullscreen: %s\n", cvarSystem->GetCVarBool( "r_fullscreen" ) ? "yes" : "no" );
|
||||
|
||||
Sys_StoreGammaTables();
|
||||
|
||||
if ( !Sys_QueryVideoMemory() ) {
|
||||
common->Error( "Could not initialize OpenGL. There does not appear to be an OpenGL-supported video card in your system.\n" );
|
||||
}
|
||||
|
||||
if ( !GLimp_SetMode( parms ) ) {
|
||||
common->Warning( "Could not initialize OpenGL\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
common->Printf( "------------------\n" );
|
||||
|
||||
// get our config strings
|
||||
glConfig.vendor_string = (const char *)qglGetString( GL_VENDOR );
|
||||
glConfig.renderer_string = (const char *)qglGetString( GL_RENDERER );
|
||||
glConfig.version_string = (const char *)qglGetString( GL_VERSION );
|
||||
glConfig.extensions_string = (const char *)qglGetString( GL_EXTENSIONS );
|
||||
|
||||
//
|
||||
// chipset specific configuration
|
||||
//
|
||||
buf = (char *)malloc(strlen(glConfig.renderer_string) + 1);
|
||||
strcpy( buf, glConfig.renderer_string );
|
||||
|
||||
// Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string );
|
||||
free(buf);
|
||||
|
||||
/*
|
||||
#ifndef USE_CGLMACROS
|
||||
if (!r_enablerender->integer)
|
||||
OSX_GLContextClearCurrent();
|
||||
#endif
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLimp_SwapBuffers
|
||||
**
|
||||
** Responsible for doing a swapbuffers and possibly for other stuff
|
||||
** as yet to be determined. Probably better not to make this a GLimp
|
||||
** function and instead do a call to GLimp_SwapBuffers.
|
||||
*/
|
||||
void GLimp_SwapBuffers( void ) {
|
||||
if ( r_swapInterval.IsModified() ) {
|
||||
r_swapInterval.ClearModified();
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && defined(QGL_CHECK_GL_ERRORS)
|
||||
QGLCheckError("GLimp_EndFrame");
|
||||
#endif
|
||||
|
||||
if (!glw_state.glPauseCount && !isHidden) {
|
||||
glw_state.bufferSwapCount++;
|
||||
[OSX_GetNSGLContext() flushBuffer];
|
||||
}
|
||||
|
||||
/*
|
||||
// Enable turning off GL at any point for performance testing
|
||||
if (OSX_GLContextIsCurrent() != r_enablerender->integer) {
|
||||
if (r_enablerender->integer) {
|
||||
common->Printf("--- Enabling Renderer ---\n");
|
||||
OSX_GLContextSetCurrent();
|
||||
} else {
|
||||
common->Printf("--- Disabling Renderer ---\n");
|
||||
OSX_GLContextClearCurrent();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_Shutdown
|
||||
**
|
||||
** This routine does all OS specific shutdown procedures for the OpenGL
|
||||
** subsystem. Under OpenGL this means NULLing out the current DC and
|
||||
** HGLRC, deleting the rendering context, and releasing the DC acquired
|
||||
** for the window. The state structure is also nulled out.
|
||||
**
|
||||
*/
|
||||
|
||||
static void _GLimp_RestoreOriginalVideoSettings() {
|
||||
CGDisplayErr err;
|
||||
|
||||
// CGDisplayCurrentMode lies because we've captured the display and thus we won't
|
||||
// get any notifications about what the current display mode really is. For now,
|
||||
// we just always force it back to what mode we remember the desktop being in.
|
||||
if (glConfig.isFullscreen) {
|
||||
err = CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.desktopMode);
|
||||
if ( err != CGDisplayNoErr )
|
||||
common->Printf( " Unable to restore display mode!\n" );
|
||||
|
||||
ReleaseAllDisplays();
|
||||
}
|
||||
}
|
||||
|
||||
void GLimp_Shutdown( void ) {
|
||||
CGDisplayCount displayIndex;
|
||||
|
||||
common->Printf("----- Shutting down GL -----\n");
|
||||
|
||||
if (OSX_GetNSGLContext()) {
|
||||
#ifndef USE_CGLMACROS
|
||||
OSX_GLContextClearCurrent();
|
||||
#endif
|
||||
// Have to call both to actually deallocate kernel resources and free the NSSurface
|
||||
CGLClearDrawable(OSX_GetCGLContext());
|
||||
[OSX_GetNSGLContext() clearDrawable];
|
||||
|
||||
[OSX_GetNSGLContext() release];
|
||||
OSX_SetGLContext((id)nil);
|
||||
}
|
||||
|
||||
_GLimp_RestoreOriginalVideoSettings();
|
||||
|
||||
// Restore the original gamma if needed.
|
||||
// if (glConfig.deviceSupportsGamma) {
|
||||
// common->Printf("Restoring ColorSync settings\n");
|
||||
// CGDisplayRestoreColorSyncSettings();
|
||||
// }
|
||||
|
||||
if (glw_state.window) {
|
||||
[glw_state.window release];
|
||||
glw_state.window = nil;
|
||||
}
|
||||
|
||||
for (displayIndex = 0; displayIndex < glw_state.displayCount; displayIndex++) {
|
||||
free(glw_state.originalDisplayGammaTables[displayIndex].red);
|
||||
free(glw_state.originalDisplayGammaTables[displayIndex].blue);
|
||||
free(glw_state.originalDisplayGammaTables[displayIndex].green);
|
||||
}
|
||||
free(glw_state.originalDisplayGammaTables);
|
||||
if (glw_state.tempTable.red) {
|
||||
free(glw_state.tempTable.red);
|
||||
free(glw_state.tempTable.blue);
|
||||
free(glw_state.tempTable.green);
|
||||
}
|
||||
if (glw_state.inGameTable.red) {
|
||||
free(glw_state.inGameTable.red);
|
||||
free(glw_state.inGameTable.blue);
|
||||
free(glw_state.inGameTable.green);
|
||||
}
|
||||
|
||||
memset(&glConfig, 0, sizeof(glConfig));
|
||||
// memset(&glState, 0, sizeof(glState));
|
||||
memset(&glw_state, 0, sizeof(glw_state));
|
||||
|
||||
common->Printf("----- Done shutting down GL -----\n");
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GLimp_SetGamma
|
||||
===============
|
||||
*/
|
||||
void GLimp_SetGamma(unsigned short red[256],
|
||||
unsigned short green[256],
|
||||
unsigned short blue[256]) {
|
||||
CGGammaValue redGamma[256], greenGamma[256], blueGamma[256];
|
||||
CGTableCount i;
|
||||
CGDisplayErr err;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
redGamma[i] = red[i] / 65535.0;
|
||||
greenGamma[i] = green[i] / 65535.0;
|
||||
blueGamma[i] = blue[i] / 65535.0;
|
||||
}
|
||||
|
||||
err = CGSetDisplayTransferByTable(glw_state.display, 256, redGamma, greenGamma, blueGamma);
|
||||
if (err != CGDisplayNoErr) {
|
||||
common->Printf("GLimp_SetGamma: CGSetDisplayTransferByByteTable returned %d.\n", err);
|
||||
}
|
||||
|
||||
// Store the gamma table that we ended up using so we can reapply it later when unhiding or to work around the bug where if you leave the game sitting and the monitor sleeps, when it wakes, the gamma isn't reset.
|
||||
glw_state.inGameTable.display = glw_state.display;
|
||||
Sys_GetGammaTable(&glw_state.inGameTable);
|
||||
}
|
||||
|
||||
GLExtension_t GLimp_ExtensionPointer(const char *name) {
|
||||
NSSymbol symbol;
|
||||
char *symbolName;
|
||||
|
||||
// special case for ATI_fragment_shader calls to map to ATI_text_fragment_shader routines
|
||||
GLExtension_t res = GLimp_ExtensionPointer_ATI_fragment_shader(name);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
// Prepend a '_' for the Unix C symbol mangling convention
|
||||
symbolName = (char *)alloca(strlen(name) + 2);
|
||||
strcpy(symbolName + 1, name);
|
||||
symbolName[0] = '_';
|
||||
|
||||
if ( !NSIsSymbolNameDefined( symbolName ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symbol = NSLookupAndBindSymbol(symbolName);
|
||||
if ( !symbol ) {
|
||||
// shouldn't happen ...
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (GLExtension_t)(NSAddressOfSymbol(symbol));
|
||||
}
|
||||
|
||||
#define MAX_RENDERER_INFO_COUNT 128
|
||||
|
||||
// Returns zero if there are no hardware renderers. Otherwise, returns the max memory across all renderers (on the presumption that the screen that we'll use has the most memory).
|
||||
unsigned long Sys_QueryVideoMemory() {
|
||||
CGLError err;
|
||||
CGLRendererInfoObj rendererInfo, rendererInfos[MAX_RENDERER_INFO_COUNT];
|
||||
long rendererInfoIndex, rendererInfoCount = MAX_RENDERER_INFO_COUNT;
|
||||
long rendererIndex, rendererCount;
|
||||
long maxVRAM = 0, vram = 0;
|
||||
long accelerated;
|
||||
long rendererID;
|
||||
long totalRenderers = 0;
|
||||
|
||||
err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(Sys_DisplayToUse()), rendererInfos, &rendererInfoCount);
|
||||
if (err) {
|
||||
common->Printf("CGLQueryRendererInfo -> %d\n", err);
|
||||
return vram;
|
||||
}
|
||||
|
||||
//common->Printf("rendererInfoCount = %d\n", rendererInfoCount);
|
||||
for (rendererInfoIndex = 0; rendererInfoIndex < rendererInfoCount && totalRenderers < rendererInfoCount; rendererInfoIndex++) {
|
||||
rendererInfo = rendererInfos[rendererInfoIndex];
|
||||
//common->Printf("rendererInfo: 0x%08x\n", rendererInfo);
|
||||
|
||||
|
||||
err = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRendererCount, &rendererCount);
|
||||
if (err) {
|
||||
common->Printf("CGLDescribeRenderer(kCGLRPRendererID) -> %d\n", err);
|
||||
continue;
|
||||
}
|
||||
//common->Printf(" rendererCount: %d\n", rendererCount);
|
||||
|
||||
for (rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) {
|
||||
totalRenderers++;
|
||||
//common->Printf(" rendererIndex: %d\n", rendererIndex);
|
||||
|
||||
rendererID = 0xffffffff;
|
||||
err = CGLDescribeRenderer(rendererInfo, rendererIndex, kCGLRPRendererID, &rendererID);
|
||||
if (err) {
|
||||
common->Printf("CGLDescribeRenderer(kCGLRPRendererID) -> %d\n", err);
|
||||
continue;
|
||||
}
|
||||
//common->Printf(" rendererID: 0x%08x\n", rendererID);
|
||||
|
||||
accelerated = 0;
|
||||
err = CGLDescribeRenderer(rendererInfo, rendererIndex, kCGLRPAccelerated, &accelerated);
|
||||
if (err) {
|
||||
common->Printf("CGLDescribeRenderer(kCGLRPAccelerated) -> %d\n", err);
|
||||
continue;
|
||||
}
|
||||
//common->Printf(" accelerated: %d\n", accelerated);
|
||||
if (!accelerated)
|
||||
continue;
|
||||
|
||||
vram = 0;
|
||||
err = CGLDescribeRenderer(rendererInfo, rendererIndex, kCGLRPVideoMemory, &vram);
|
||||
if (err) {
|
||||
common->Printf("CGLDescribeRenderer -> %d\n", err);
|
||||
continue;
|
||||
}
|
||||
//common->Printf(" vram: 0x%08x\n", vram);
|
||||
|
||||
// presumably we'll be running on the best card, so we'll take the max of the vrams
|
||||
if (vram > maxVRAM)
|
||||
maxVRAM = vram;
|
||||
}
|
||||
|
||||
#if 0
|
||||
err = CGLDestroyRendererInfo(rendererInfo);
|
||||
if (err) {
|
||||
common->Printf("CGLDestroyRendererInfo -> %d\n", err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return maxVRAM;
|
||||
}
|
||||
|
||||
CGDisplayErr Sys_CaptureActiveDisplays(void) {
|
||||
CGDisplayErr err;
|
||||
CGDisplayCount displayIndex;
|
||||
for (displayIndex = 0; displayIndex < glw_state.displayCount; displayIndex++) {
|
||||
const glwgamma_t *table;
|
||||
table = &glw_state.originalDisplayGammaTables[displayIndex];
|
||||
err = CGDisplayCapture(table->display);
|
||||
if (err != CGDisplayNoErr)
|
||||
return err;
|
||||
}
|
||||
return CGDisplayNoErr;
|
||||
}
|
||||
|
||||
// enable / disable context is just for the r_skipRenderContext debug option
|
||||
void GLimp_DeactivateContext( void ) {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
void GLimp_ActivateContext( void ) {
|
||||
[OSX_GetNSGLContext() makeCurrentContext];
|
||||
}
|
||||
|
||||
NSDictionary *Sys_GetMatchingDisplayMode( glimpParms_t parms ) {
|
||||
NSArray *displayModes;
|
||||
NSDictionary *mode;
|
||||
unsigned int modeIndex, modeCount, bestModeIndex;
|
||||
int verbose;
|
||||
// cvar_t *cMinFreq, *cMaxFreq;
|
||||
int minFreq, maxFreq;
|
||||
unsigned int colorDepth;
|
||||
|
||||
verbose = 0;
|
||||
|
||||
colorDepth = 32;
|
||||
|
||||
minFreq = r_minDisplayRefresh.GetInteger();
|
||||
maxFreq = r_maxDisplayRefresh.GetInteger();
|
||||
if ( minFreq > maxFreq ) {
|
||||
common->Error( "r_minDisplayRefresh must be less than or equal to r_maxDisplayRefresh" );
|
||||
}
|
||||
|
||||
displayModes = (NSArray *)CGDisplayAvailableModes(glw_state.display);
|
||||
if (!displayModes) {
|
||||
common->Error( "CGDisplayAvailableModes returned NULL -- 0x%0x is an invalid display", glw_state.display);
|
||||
}
|
||||
|
||||
modeCount = [displayModes count];
|
||||
if (verbose) {
|
||||
common->Printf( "%d modes avaliable\n", modeCount);
|
||||
common->Printf( "Current mode is %s\n", [[(id)CGDisplayCurrentMode(glw_state.display) description] cString]);
|
||||
}
|
||||
|
||||
// Default to the current desktop mode
|
||||
bestModeIndex = 0xFFFFFFFF;
|
||||
|
||||
for ( modeIndex = 0; modeIndex < modeCount; ++modeIndex ) {
|
||||
id object;
|
||||
int refresh;
|
||||
|
||||
mode = [displayModes objectAtIndex: modeIndex];
|
||||
if (verbose) {
|
||||
common->Printf( " mode %d -- %s\n", modeIndex, [[mode description] cString]);
|
||||
}
|
||||
|
||||
// Make sure we get the right size
|
||||
if ([[mode objectForKey: (id)kCGDisplayWidth] intValue] != parms.width ||
|
||||
[[mode objectForKey: (id)kCGDisplayHeight] intValue] != parms.height) {
|
||||
if (verbose)
|
||||
common->Printf( " -- bad size\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure that our frequency restrictions are observed
|
||||
refresh = [[mode objectForKey: (id)kCGDisplayRefreshRate] intValue];
|
||||
if (minFreq && refresh < minFreq) {
|
||||
if (verbose)
|
||||
common->Printf( " -- refresh too low\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (maxFreq && refresh > maxFreq) {
|
||||
if (verbose)
|
||||
common->Printf( " -- refresh too high\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([[mode objectForKey: (id)kCGDisplayBitsPerPixel] intValue] != colorDepth) {
|
||||
if (verbose)
|
||||
common->Printf( " -- bad depth\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
object = [mode objectForKey: (id)kCGDisplayModeIsStretched];
|
||||
if ( object ) {
|
||||
if ( [object boolValue] != cvarSystem->GetCVarBool( "r_stretched" ) ) {
|
||||
if (verbose)
|
||||
common->Printf( " -- bad stretch setting\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( cvarSystem->GetCVarBool( "r_stretched" ) ) {
|
||||
if (verbose)
|
||||
common->Printf( " -- stretch requested, stretch property not available\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bestModeIndex = modeIndex;
|
||||
if (verbose)
|
||||
common->Printf( " -- OK\n", bestModeIndex);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
common->Printf( " bestModeIndex = %d\n", bestModeIndex);
|
||||
|
||||
if (bestModeIndex == 0xFFFFFFFF) {
|
||||
common->Printf( "No suitable display mode available.\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [displayModes objectAtIndex: bestModeIndex];
|
||||
}
|
||||
|
||||
|
||||
#define MAX_DISPLAYS 128
|
||||
|
||||
void Sys_GetGammaTable(glwgamma_t *table) {
|
||||
CGTableCount tableSize = 512;
|
||||
CGDisplayErr err;
|
||||
|
||||
table->tableSize = tableSize;
|
||||
if (table->red)
|
||||
free(table->red);
|
||||
table->red = (float *)malloc(tableSize * sizeof(*table->red));
|
||||
if (table->green)
|
||||
free(table->green);
|
||||
table->green = (float *)malloc(tableSize * sizeof(*table->green));
|
||||
if (table->blue)
|
||||
free(table->blue);
|
||||
table->blue = (float *)malloc(tableSize * sizeof(*table->blue));
|
||||
|
||||
// TJW: We _could_ loop here if we get back the same size as our table, increasing the table size.
|
||||
err = CGGetDisplayTransferByTable(table->display, tableSize, table->red, table->green, table->blue,
|
||||
&table->tableSize);
|
||||
if (err != CGDisplayNoErr) {
|
||||
common->Printf("GLimp_Init: CGGetDisplayTransferByTable returned %d.\n", err);
|
||||
table->tableSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Sys_StoreGammaTables() {
|
||||
// Store the original gamma for all monitors so that we can fade and unfade them all
|
||||
CGDirectDisplayID displays[MAX_DISPLAYS];
|
||||
CGDisplayCount displayIndex;
|
||||
CGDisplayErr err;
|
||||
|
||||
err = CGGetActiveDisplayList(MAX_DISPLAYS, displays, &glw_state.displayCount);
|
||||
if (err != CGDisplayNoErr)
|
||||
Sys_Error("Cannot get display list -- CGGetActiveDisplayList returned %d.\n", err);
|
||||
|
||||
glw_state.originalDisplayGammaTables = (glwgamma_t *)calloc(glw_state.displayCount, sizeof(*glw_state.originalDisplayGammaTables));
|
||||
for (displayIndex = 0; displayIndex < glw_state.displayCount; displayIndex++) {
|
||||
glwgamma_t *table;
|
||||
|
||||
table = &glw_state.originalDisplayGammaTables[displayIndex];
|
||||
table->display = displays[displayIndex];
|
||||
Sys_GetGammaTable(table);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_DISPLAYS 128
|
||||
|
||||
CGDirectDisplayID Sys_DisplayToUse(void) {
|
||||
static bool gotDisplay = NO;
|
||||
static CGDirectDisplayID displayToUse;
|
||||
|
||||
CGDisplayErr err;
|
||||
CGDirectDisplayID displays[MAX_DISPLAYS];
|
||||
CGDisplayCount displayCount;
|
||||
int displayIndex;
|
||||
|
||||
if ( gotDisplay ) {
|
||||
return displayToUse;
|
||||
}
|
||||
gotDisplay = YES;
|
||||
|
||||
err = CGGetActiveDisplayList( MAX_DISPLAYS, displays, &displayCount );
|
||||
if ( err != CGDisplayNoErr ) {
|
||||
common->Error("Cannot get display list -- CGGetActiveDisplayList returned %d.\n", err );
|
||||
}
|
||||
|
||||
// -1, the default, means to use the main screen
|
||||
displayIndex = r_screen.GetInteger();
|
||||
|
||||
if ( displayIndex < 0 || displayIndex >= displayCount ) {
|
||||
// This is documented (in CGDirectDisplay.h) to be the main display. We want to
|
||||
// return this instead of kCGDirectMainDisplay since this will allow us to compare
|
||||
// display IDs.
|
||||
displayToUse = displays[ 0 ];
|
||||
} else {
|
||||
displayToUse = displays[ displayIndex ];
|
||||
}
|
||||
|
||||
return displayToUse;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
GLimp_SetScreenParms
|
||||
===================
|
||||
*/
|
||||
bool GLimp_SetScreenParms( glimpParms_t parms ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Sys_GrabMouseCursor
|
||||
===================
|
||||
*/
|
||||
void Sys_GrabMouseCursor( bool grabIt ) { }
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "sys/sys_public.h"
|
||||
|
||||
// input
|
||||
void Sys_InitInput( void );
|
||||
void Sys_ShutdownInput( void );
|
||||
|
||||
void IN_DeactivateMouse( void);
|
||||
void IN_ActivateMouse( void);
|
||||
|
||||
void IN_Activate (bool active);
|
||||
void IN_Frame (void);
|
||||
|
||||
void Sys_UpdateWindowMouseInputRect( void );
|
|
@ -1,65 +0,0 @@
|
|||
#import "sys/posix/posix_public.h"
|
||||
|
||||
#import <Foundation/NSGeometry.h>
|
||||
@class NSEvent, NSOpenGLContext, NSWindow;
|
||||
|
||||
#import <ApplicationServices/ApplicationServices.h>
|
||||
#import <OpenGL/CGLTypes.h>
|
||||
|
||||
// In macosx_input.m
|
||||
CGDirectDisplayID Sys_DisplayToUse(void);
|
||||
void SetProgramPath(char *path);
|
||||
void Sys_SetMouseInputRect(CGRect newRect);
|
||||
|
||||
typedef struct {
|
||||
CGDirectDisplayID display;
|
||||
CGTableCount tableSize;
|
||||
CGGammaValue *red;
|
||||
CGGammaValue *blue;
|
||||
CGGammaValue *green;
|
||||
} glwgamma_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CGDirectDisplayID display;
|
||||
NSDictionary *desktopMode;
|
||||
NSDictionary *gameMode;
|
||||
|
||||
CGDisplayCount displayCount;
|
||||
glwgamma_t *originalDisplayGammaTables;
|
||||
glwgamma_t inGameTable;
|
||||
glwgamma_t tempTable;
|
||||
|
||||
NSOpenGLContext *_ctx;
|
||||
CGLContextObj _cgl_ctx;
|
||||
bool _ctx_is_current;
|
||||
NSWindow *window;
|
||||
|
||||
unsigned int bufferSwapCount;
|
||||
unsigned int glPauseCount;
|
||||
} glwstate_t;
|
||||
|
||||
extern glwstate_t glw_state;
|
||||
|
||||
#define OSX_SetGLContext(context) \
|
||||
do { \
|
||||
NSOpenGLContext *_context = (context); \
|
||||
glw_state._ctx = _context; \
|
||||
glw_state._cgl_ctx = [_context cglContext]; \
|
||||
} while (0)
|
||||
|
||||
#define OSX_GetNSGLContext() glw_state._ctx
|
||||
#define OSX_GetCGLContext() glw_state._cgl_ctx
|
||||
|
||||
#define OSX_GLContextIsCurrent() glw_state._ctx_is_current
|
||||
#define OSX_GLContextSetCurrent() \
|
||||
do { \
|
||||
[glw_state._ctx makeCurrentContext]; \
|
||||
glw_state._ctx_is_current = (glw_state._ctx != nil); \
|
||||
} while (0)
|
||||
|
||||
#define OSX_GLContextClearCurrent() \
|
||||
do { \
|
||||
[NSOpenGLContext clearCurrentContext]; \
|
||||
glw_state._ctx_is_current = NO; \
|
||||
} while (0)
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#include "sys/platform.h"
|
||||
#include "framework/Common.h"
|
||||
|
||||
#include "sys/posix/posix_public.h"
|
||||
|
||||
typedef struct poll_keyboard_event_s
|
||||
{
|
||||
int key;
|
||||
bool state;
|
||||
} poll_keyboard_event_t;
|
||||
|
||||
typedef struct poll_mouse_event_s
|
||||
{
|
||||
int action;
|
||||
int value;
|
||||
} poll_mouse_event_t;
|
||||
|
||||
#define MAX_POLL_EVENTS 50
|
||||
#define POLL_EVENTS_HEADROOM 2 // some situations require to add several events
|
||||
static poll_keyboard_event_t poll_events_keyboard[MAX_POLL_EVENTS + POLL_EVENTS_HEADROOM];
|
||||
static int poll_keyboard_event_count;
|
||||
static poll_mouse_event_t poll_events_mouse[MAX_POLL_EVENTS + POLL_EVENTS_HEADROOM];
|
||||
static int poll_mouse_event_count;
|
||||
|
||||
/*
|
||||
==========
|
||||
Posix_AddKeyboardPollEvent
|
||||
==========
|
||||
*/
|
||||
bool Posix_AddKeyboardPollEvent(int key, bool state) {
|
||||
if (poll_keyboard_event_count >= MAX_POLL_EVENTS + POLL_EVENTS_HEADROOM)
|
||||
common->FatalError( "poll_keyboard_event_count exceeded MAX_POLL_EVENT + POLL_EVENTS_HEADROOM\n");
|
||||
poll_events_keyboard[poll_keyboard_event_count].key = key;
|
||||
poll_events_keyboard[poll_keyboard_event_count++].state = state;
|
||||
if (poll_keyboard_event_count >= MAX_POLL_EVENTS) {
|
||||
common->DPrintf("WARNING: reached MAX_POLL_EVENT poll_keyboard_event_count\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==========
|
||||
Posix_AddMousePollEvent
|
||||
==========
|
||||
*/
|
||||
bool Posix_AddMousePollEvent(int action, int value) {
|
||||
if (poll_mouse_event_count >= MAX_POLL_EVENTS + POLL_EVENTS_HEADROOM)
|
||||
common->FatalError( "poll_mouse_event_count exceeded MAX_POLL_EVENT + POLL_EVENTS_HEADROOM\n");
|
||||
poll_events_mouse[poll_mouse_event_count].action = action;
|
||||
poll_events_mouse[poll_mouse_event_count++].value = value;
|
||||
if (poll_mouse_event_count >= MAX_POLL_EVENTS) {
|
||||
common->DPrintf("WARNING: reached MAX_POLL_EVENT poll_mouse_event_count\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
polled from GetDirectUsercmd
|
||||
async input polling is obsolete
|
||||
we have a single entry point for both mouse and keyboard
|
||||
the mouse/keyboard seperation is API legacy
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
int Sys_PollKeyboardInputEvents( void ) {
|
||||
return poll_keyboard_event_count;
|
||||
}
|
||||
|
||||
int Sys_ReturnKeyboardInputEvent( const int n, int &key, bool &state ) {
|
||||
if ( n >= poll_keyboard_event_count ) {
|
||||
return 0;
|
||||
}
|
||||
key = poll_events_keyboard[n].key;
|
||||
state = poll_events_keyboard[n].state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Sys_EndKeyboardInputEvents( void ) {
|
||||
//isn't this were it's supposed to be, was missing some key strokes with it set below
|
||||
poll_keyboard_event_count = 0;
|
||||
}
|
||||
|
||||
int Sys_PollMouseInputEvents( void ) {
|
||||
#if 0 //moved to the Sys_End functions
|
||||
poll_keyboard_event_count = 0;
|
||||
poll_mouse_event_count = 0;
|
||||
#endif
|
||||
|
||||
// that's OS specific, implemented in osx/ and linux/
|
||||
Posix_PollInput( );
|
||||
|
||||
return poll_mouse_event_count;
|
||||
}
|
||||
|
||||
int Sys_ReturnMouseInputEvent( const int n, int &action, int &value )
|
||||
{
|
||||
if ( n>=poll_mouse_event_count ) {
|
||||
return 0;
|
||||
}
|
||||
action = poll_events_mouse[ n ].action;
|
||||
value = poll_events_mouse[ n ].value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Sys_EndMouseInputEvents( void ) {
|
||||
// moved out of the Sys_PollMouseInputEvents
|
||||
poll_mouse_event_count = 0;
|
||||
}
|
|
@ -223,84 +223,6 @@ int Sys_ListFiles( const char *directory, const char *extension, idStrList &list
|
|||
return list.Num();
|
||||
}
|
||||
|
||||
#ifdef MACOS_X
|
||||
/*
|
||||
============================================================================
|
||||
EVENT LOOP
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#define MAX_QUED_EVENTS 256
|
||||
#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 )
|
||||
|
||||
static sysEvent_t eventQue[MAX_QUED_EVENTS];
|
||||
static int eventHead, eventTail;
|
||||
|
||||
/*
|
||||
================
|
||||
Posix_QueEvent
|
||||
|
||||
ptr should either be null, or point to a block of data that can be freed later
|
||||
================
|
||||
*/
|
||||
void Posix_QueEvent( sysEventType_t type, int value, int value2,
|
||||
int ptrLength, void *ptr ) {
|
||||
sysEvent_t *ev;
|
||||
|
||||
ev = &eventQue[eventHead & MASK_QUED_EVENTS];
|
||||
if (eventHead - eventTail >= MAX_QUED_EVENTS) {
|
||||
common->Printf( "Posix_QueEvent: overflow\n" );
|
||||
// we are discarding an event, but don't leak memory
|
||||
// TTimo: verbose dropped event types?
|
||||
if (ev->evPtr) {
|
||||
Mem_Free(ev->evPtr);
|
||||
ev->evPtr = NULL;
|
||||
}
|
||||
eventTail++;
|
||||
}
|
||||
|
||||
eventHead++;
|
||||
|
||||
ev->evType = type;
|
||||
ev->evValue = value;
|
||||
ev->evValue2 = value2;
|
||||
ev->evPtrLength = ptrLength;
|
||||
ev->evPtr = ptr;
|
||||
|
||||
#if 0
|
||||
common->Printf( "Event %d: %d %d\n", ev->evType, ev->evValue, ev->evValue2 );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetEvent
|
||||
================
|
||||
*/
|
||||
sysEvent_t Sys_GetEvent(void) {
|
||||
static sysEvent_t ev;
|
||||
|
||||
// return if we have data
|
||||
if (eventHead > eventTail) {
|
||||
eventTail++;
|
||||
return eventQue[(eventTail - 1) & MASK_QUED_EVENTS];
|
||||
}
|
||||
// return the empty event with the current time
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ClearEvents
|
||||
================
|
||||
*/
|
||||
void Sys_ClearEvents( void ) {
|
||||
eventHead = eventTail = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
Posix_Cwd
|
||||
|
@ -914,26 +836,6 @@ char *Sys_ConsoleInput( void ) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef MACOS_X
|
||||
/*
|
||||
called during frame loops, pacifier updates etc.
|
||||
this is only for console input polling and misc mouse grab tasks
|
||||
the actual mouse and keyboard input is in the Sys_Poll logic
|
||||
*/
|
||||
void Sys_GenerateEvents( void ) {
|
||||
char *s;
|
||||
if ( ( s = Sys_ConsoleInput() ) ) {
|
||||
char *b;
|
||||
int len;
|
||||
|
||||
len = strlen( s ) + 1;
|
||||
b = (char *)Mem_Alloc( len );
|
||||
strcpy( b, s );
|
||||
Posix_QueEvent( SE_CONSOLE, 0, 0, len, b );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
===============
|
||||
low level output
|
||||
|
|
|
@ -33,7 +33,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "sys/sys_public.h"
|
||||
|
||||
void Posix_QueEvent( sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
|
||||
const char* Posix_Cwd( void );
|
||||
|
||||
// called first thing. does InitSigs and various things
|
||||
|
@ -48,10 +47,6 @@ void Posix_Exit( int ret );
|
|||
void Posix_SetExit(int ret); // override the exit code
|
||||
void Posix_SetExitSpawn( const char *exeName ); // set the process to be spawned when we quit
|
||||
|
||||
bool Posix_AddKeyboardPollEvent( int key, bool state );
|
||||
bool Posix_AddMousePollEvent( int action, int value );
|
||||
|
||||
void Posix_PollInput( void );
|
||||
void Posix_InitConsoleInput( void );
|
||||
void Posix_Shutdown( void );
|
||||
|
||||
|
|
Loading…
Reference in a new issue