We now have a really crappy gl renderer for macosx.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2689 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2007-09-23 22:00:19 +00:00
parent 4046adbe48
commit e59d02ed52
9 changed files with 1281 additions and 3 deletions

View file

@ -575,12 +575,25 @@ ifeq ($(FTE_TARGET),macosx)
SWCL_DIR=sw_macosx
GL_CFLAGS=$(GLCFLAGS) -D__MACOSX__
GL_LDFLAGS=-framework AGL -framework OpenGL
GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidmac.o sys_linux.o cd_null.o
GL_LDFLAGS=-framework AGL -framework OpenGL -framework Cocoa -framework AudioUnit
GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidcocoa.mo gl_vidmacos.o sys_linux.o in_macos.o cd_null.o snd_macos.o
SW_CFLAGS=$(SWCFLAGS) -D__MACOSX__
SW_LDFLAGS=
SWCL_OBJS=$(SOFTWARE_OBJS) cd_null.o sys_linux.o
SWCL_OBJS=$(SOFTWARE_OBJS) cd_null.o sys_linux.o vid_null.o
GL_EXE_NAME=../fteqw.gl
GLCL_EXE_NAME=../fteqwcl.gl
SW_EXE_NAME=../fteqw.sw
SWCL_EXE_NAME=../fteqwcl.sw
M_EXE_NAME=../fteqw
MCL_EXE_NAME=../fteqwcl
MINGL_EXE_NAME=../fteqw.mingl
MINGL_DIR=mingl_morphos
#seems, macosx has a more limited version of strip
STRIPFLAGS=
endif
ifeq ($(FTE_TARGET),morphos)
@ -714,6 +727,13 @@ $(OUT_DIR)/%.oo $(OUT_DIR)/%.d : %.c
rm -f $@.d.$$$$
$(DO_CC) -I$(OUT_DIR)
$(OUT_DIR)/%.mo $(OUT_DIR)/%.d : %.m
@set -e; rm -f $@.d; \
$(CC) -MM $(ALL_CFLAGS) $< > $@.d.$$$$; \
sed 's,\($*\)\.mo[ :]*,\1.mo $@.d : ,g' < $@.d.$$$$ > $@.d; \
rm -f $@.d.$$$$
$(DO_CC) -I$(OUT_DIR)
ifeq ($(USEASM),true)
$(OUT_DIR)/%.o : %.s sw/*.h
$(DO_AS)

97
engine/client/in_macos.c Normal file
View file

@ -0,0 +1,97 @@
/*
Copyright (C) 2001-2002 A Nourai
Copyright (C) 2006 Jacek Piszczek (Mac OSX port)
This program 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 2
of the License, or (at your option) any later version.
This program 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 included (GNU.txt) GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
float mouse_x,mouse_y;
float old_mouse_x,old_mouse_y;
cvar_t m_filter = SCVARF("m_filter", "1", CVAR_ARCHIVE);
void IN_Init (void)
{
Cvar_Register (&m_filter, "input values");
}
void IN_ReInit(void)
{
}
void IN_Shutdown (void)
{
}
void IN_Commands (void)
{
}
// oportunity for devices to stick commands on the script buffer
void IN_ModeChanged (void)
{
}
// called whenever screen dimensions change
void IN_Move (usercmd_t *cmd, int pnum)
{
float tx, ty, filterfrac;
tx = mouse_x;
ty = mouse_y;
if (m_filter.value)
{
filterfrac = bound(0, m_filter.value, 1) / 2.0;
mouse_x = (tx * (1 - filterfrac) + old_mouse_x * filterfrac);
mouse_y = (ty * (1 - filterfrac) + old_mouse_y * filterfrac);
}
old_mouse_x = tx;
old_mouse_y = ty;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
if ((in_strafe.state[pnum] & 1) || (lookstrafe.value && in_mlook.state[pnum]))
{
cmd->sidemove += m_side.value * mouse_x;
}
else
{
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
}
if (in_mlook.state[pnum])
V_StopPitchDrift(pnum);
if (in_mlook.state[pnum] && !(in_strafe.state[pnum] & 1))
{
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
cl.viewangles[pnum][PITCH] = bound(-70, cl.viewangles[pnum][PITCH], 80);
}
else
{
cmd->forwardmove -= m_forward.value * mouse_y;
}
mouse_x = mouse_y = 0.0;
}
// add additional movement on top of the keyboard move cmd

View file

@ -159,6 +159,11 @@ K_APP = 241,
K_MAX = 256
};
#define K_LSHIFT K_SHIFT
#define K_RSHIFT K_SHIFT
#define K_RCTRL K_CTRL
#define K_LCTRL K_CTRL
typedef enum {key_game, key_console, key_message, key_menu, key_editor} keydest_t;
extern keydest_t key_dest;

View file

@ -144,6 +144,7 @@ void S_RunCapture(void)
sounddriver pDSOUND_InitCard;
sounddriver pALSA_InitCard;
sounddriver pOSS_InitCard;
sounddriver pMacOS_InitCard;
sounddriver pSDL_InitCard;
sounddriver pWAV_InitCard;
sounddriver pAHI_InitCard;
@ -157,6 +158,7 @@ sdriver_t drivers[] = {
{"DSound", &pDSOUND_InitCard},
{"ALSA", &pALSA_InitCard},
{"OSS", &pOSS_InitCard},
{"MacOS", &pMacOS_InitCard},
{"SDL", &pSDL_InitCard},
{"WaveOut", &pWAV_InitCard},
{"AHI", &pAHI_InitCard},

258
engine/client/snd_macos.c Normal file
View file

@ -0,0 +1,258 @@
/*
Copyright (C) 2001-2002 A Nourai
Copyright (C) 2006 Jacek Piszczek (Mac OSX port)
This program 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 2
of the License, or (at your option) any later version.
This program 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 included (GNU.txt) GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "sound.h"
#include <CoreServices/CoreServices.h>
#include <AudioUnit/AudioUnit.h>
// Jacek:
// coreaudio is poorly documented so I'm not 100% sure the code below
// is correct :(
struct MacOSSound_Private
{
AudioUnit gOutputUnit;
unsigned int readpos;
};
static OSStatus AudioRender(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
soundcardinfo_t *sc = inRefCon;
struct MacOSSound_Private *pdata = sc->handle;
int start = pdata->readpos;
int buffersize = sc->sn.samples * (sc->sn.samplebits/8);
int bytes = ioData->mBuffers[0].mDataByteSize;
int remaining;
start %= buffersize;
if (start + bytes > buffersize)
{
remaining = bytes;
bytes = buffersize - start;
remaining -= bytes;
}
else
{
remaining = 0;
}
memcpy(ioData->mBuffers[0].mData, sc->sn.buffer + start, bytes);
memcpy((char*)ioData->mBuffers[0].mData+bytes, sc->sn.buffer, remaining);
pdata->readpos += inNumberFrames*sc->sn.numchannels * (sc->sn.samplebits/8);
return noErr;
}
static void MacOS_Shutdown(soundcardinfo_t *sc)
{
struct MacOSSound_Private *pdata = sc->handle;
sc->handle = NULL;
if (!pdata)
return;
// stop playback
AudioOutputUnitStop (pdata->gOutputUnit);
// release the unit
AudioUnitUninitialize (pdata->gOutputUnit);
// free the unit
CloseComponent (pdata->gOutputUnit);
// free the buffer memory
Z_Free(sc->sn.buffer);
Z_Free(pdata);
}
static unsigned int MacOS_GetDMAPos(soundcardinfo_t *sc)
{
struct MacOSSound_Private *pdata = sc->handle;
sc->sn.samplepos = pdata->readpos/(sc->sn.samplebits/8);
return sc->sn.samplepos;
}
static void MacOS_Submit(soundcardinfo_t *sc)
{
}
static void *MacOS_Lock(soundcardinfo_t *sc)
{
return sc->sn.buffer;
}
static void MacOS_Unlock(soundcardinfo_t *sc, void *buffer)
{
}
static void MacOS_SetWaterDistortion(soundcardinfo_t *sc, qboolean isunderwater)
{
}
static int MacOS_InitCard(soundcardinfo_t *sc, int cardnum)
{
ComponentResult err = noErr;
if (cardnum)
return 2; /* no more */
struct MacOSSound_Private *pdata = Z_Malloc(sizeof(*pdata));
if (!pdata)
return FALSE;
// Open the default output unit
ComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
Component comp = FindNextComponent(NULL, &desc);
if (comp == NULL)
{
Con_Printf("FindNextComponent failed\n");
Z_Free(pdata);
return FALSE;
}
err = OpenAComponent(comp, &pdata->gOutputUnit);
if (comp == NULL)
{
Con_Printf("OpenAComponent failed\n");
Z_Free(pdata);
return FALSE;
}
// Set up a callback function to generate output to the output unit
AURenderCallbackStruct input;
input.inputProc = AudioRender;
input.inputProcRefCon = sc;
err = AudioUnitSetProperty ( pdata->gOutputUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&input,
sizeof(input));
if (err)
{
Con_Printf("AudioUnitSetProperty failed\n");
CloseComponent(pdata->gOutputUnit);
Z_Free(pdata);
return FALSE;
}
// describe our audio data
AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = sc->sn.speed;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kAudioFormatFlagsNativeEndian
| kLinearPCMFormatFlagIsPacked;
//| kAudioFormatFlagIsNonInterleaved;
streamFormat.mFramesPerPacket = 1;
streamFormat.mChannelsPerFrame = 2;
streamFormat.mBitsPerChannel = 16;
if (streamFormat.mBitsPerChannel >= 16)
streamFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
else
streamFormat.mFormatFlags |= 0;
streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame * (streamFormat.mBitsPerChannel/8);
streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame * streamFormat.mFramesPerPacket;
err = AudioUnitSetProperty (pdata->gOutputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&streamFormat,
sizeof(AudioStreamBasicDescription));
if (err)
{
Con_Printf("AudioUnitSetProperty failed\n");
CloseComponent(pdata->gOutputUnit);
Z_Free(pdata);
return FALSE;
}
// set the shm structure
sc->sn.speed = streamFormat.mSampleRate;
sc->sn.samplebits = streamFormat.mBitsPerChannel;
sc->sn.numchannels = streamFormat.mChannelsPerFrame;
sc->sn.samples = 256 * 1024;
sc->sn.buffer = Z_Malloc(sc->sn.samples*sc->sn.samplebits/8);
int i;
for (i = 0; i < sc->sn.samples*sc->sn.samplebits/8; i++)
sc->sn.buffer[i] = rand();
if (sc->sn.buffer == 0)
{
Con_Printf("Malloc failed - cannot allocate sound buffer\n");
CloseComponent(pdata->gOutputUnit);
Z_Free(pdata);
return FALSE;
}
// Initialize unit
err = AudioUnitInitialize(pdata->gOutputUnit);
if (err)
{
Con_Printf("AudioOutputInitialize failed\n");
CloseComponent(pdata->gOutputUnit);
Z_Free(sc->sn.buffer);
Z_Free(pdata);
return FALSE;
}
// start playing :)
err = AudioOutputUnitStart (pdata->gOutputUnit);
if (err)
{
Con_Printf("AudioOutputUnitStart failed\n");
AudioUnitUninitialize (pdata->gOutputUnit);
CloseComponent(pdata->gOutputUnit);
Z_Free(sc->sn.buffer);
Z_Free(pdata);
return FALSE;
}
sc->handle = pdata;
sc->Lock = MacOS_Lock;
sc->Unlock = MacOS_Unlock;
sc->SetWaterDistortion = MacOS_SetWaterDistortion;
sc->Submit = MacOS_Submit;
sc->GetDMAPos = MacOS_GetDMAPos;
sc->Shutdown = MacOS_Shutdown;
Con_Printf("Sound initialised\n");
return TRUE;
}
sounddriver pMacOS_InitCard = &MacOS_InitCard;

View file

@ -478,6 +478,25 @@ int main (int c, char **v)
oldtime = Sys_DoubleTime ();
while (1)
{
#ifdef __MACOSX__
//wow, not even windows was this absurd.
#ifdef RGLQUAKE
if (glcocoaRunLoop())
{
oldtime = Sys_DoubleTime ();
continue;
}
#endif
#ifdef SWQUAKE
#warning don't worry if this causes linker errors - we don't have a macos sw renderer yet!
if (swcocoaRunLoop())
{
oldtime = Sys_DoubleTime ();
continue;
}
#endif
#endif
// find time spent rendering last frame
newtime = Sys_DoubleTime ();
time = newtime - oldtime;

View file

@ -154,6 +154,10 @@ void *Sys_LoadDLL(const char *name, void **vmMain, int (EXPORT_FN *syscall)(int
sprintf(dllname, "%samd.so", name);
#elif defined(_M_IX86) || defined(__i386__)
sprintf(dllname, "%sx86.so", name);
#elif defined(__powerpc__)
sprintf(dllname, "%sppc.so", name);
#elif defined(__ppc__)
sprintf(dllname, "%sppc.so", name);
#else
sprintf(dllname, "%sunk.so", name);
#endif

634
engine/gl/gl_vidcocoa.m Normal file
View file

@ -0,0 +1,634 @@
/*
Copyright (C) 2001-2002 A Nourai
Copyright (C) 2006 Jacek Piszczek (Mac OSX port)
This program 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 2
of the License, or (at your option) any later version.
This program 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 included (GNU.txt) GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Cocoa/Cocoa.h>
#import <Quartz/Quartz.h>
#include "quakedef.h"
id _p;
extern float mouse_x,mouse_y;
int evcnt = 2;
// Jacek: some keys are bogus, my ibook kb lacks keys and apple's docs lack
// keyCode documentation
unsigned char keyconv[] =
{
'a', /* 0 */
's',
'd',
'f',
'h',
'g',
'z',
'x',
'c',
'v',
'0', /* 10 */
'b',
'q',
'w',
'e',
'r',
'y',
't',
'1',
'2',
'3', /* 20 */
'4',
'6',
'5',
'=',
'9',
'7',
'-',
'8',
'0',
']', /* 30 */
'o',
'u',
'[',
'i',
'p',
K_ENTER,
'l',
'j',
'\'',
'k', /* 40 */
';',
'\\',
',',
'/',
'n',
'm',
'.',
K_TAB,
K_SPACE,
'`', /* 50 */
K_BACKSPACE,
'v',
K_ESCAPE,
'n',
'm',
',',
'.',
'/',
0,
K_KP_DEL, /* 60 */
K_KP_HOME,
K_KP_UPARROW,
K_KP_PGUP,
' ',
K_KP_DEL,
K_TAB,
K_KP_STAR,
K_ENTER,
K_KP_PLUS,
K_DEL, /* 70 */
K_INS,
K_PGUP,
K_PGDN,
K_KP_MINUS,
K_KP_SLASH,
K_KP_ENTER,
0,
K_KP_MINUS,
0,
K_F1, /* 80 */
K_F2,
K_KP_INS,
K_KP_END,
K_KP_DOWNARROW,
K_KP_PGDN,
K_KP_LEFTARROW,
K_KP_5,
K_KP_RIGHTARROW,
K_KP_HOME,
0, /* 90 */
K_KP_UPARROW,
K_KP_PGUP,
0,
K_KP_PLUS,
0,
K_LSHIFT,
K_RSHIFT,
0,
K_RCTRL,
K_ALT, /* 100 */
K_ALT,
0,
0,
0,
0,
0,
0,
0,
0,
K_PAUSE, /* 110 */
K_F12,
0,
0,
0,
K_HOME,
K_PGUP,
K_DEL,
0,
K_END,
0, /* 120 */
K_PGDN,
0,
K_LEFTARROW,
K_RIGHTARROW,
K_DOWNARROW,
K_UPARROW,
0,
0,
0,
0, /* 130 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 140 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 150 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 160 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 170 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 180 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 190 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 200 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 210 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 220 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 230 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 240 */
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, /* 250 */
0,
0,
0,
0,
0,
0,
0,
0,
0
};
// validate the depth
int checkDepth(int d)
{
if (d == 24)
d = 32;
if (d != 15 && d != 16 && d != 32)
d = 32;
return d;
}
@interface FTEApplication : NSApplication
{
NSOpenGLContext *_openGLContext;
NSTimer *_timer;
double time, oldtime, newtime;
unsigned int oldmflags;
CFDictionaryRef olddmode;
}
- (void)initDisplayWidth:(int)width height:(int)height depth:(int)depth;
- (void)flushBuffer;
- (void)runLoop:(NSTimer *)timer;
@end
@implementation FTEApplication
- (id)init
{
if((self = [super init]))
[self setDelegate:self];
oldmflags = 0;
return self;
}
- (void)initDisplayWidth:(int)width height:(int)height depth:(int)depth;
{
long value = 1;
NSOpenGLPixelFormat* format;
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAFullScreen,
NSOpenGLPFAScreenMask,
CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
NSOpenGLPFANoRecovery,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFADepthSize, checkDepth(depth),
0};
olddmode = CGDisplayCurrentMode(kCGDirectMainDisplay);
// zeros mean we use the default screen! (but with 32bit depth)
if (!((width == 0) && (height == 0) && (depth == 0)))
{
depth = checkDepth(depth);
if (width == 0)
width = CGDisplayPixelsWide(kCGDirectMainDisplay);
if (height == 0)
height = CGDisplayPixelsHigh(kCGDirectMainDisplay);
CFDictionaryRef dmode = CGDisplayBestModeForParameters(
kCGDirectMainDisplay,
checkDepth(depth),
width,
height,
FALSE);
CGDisplaySwitchToMode(kCGDirectMainDisplay,dmode);
}
// get screen size
vid.width = CGDisplayPixelsWide(kCGDirectMainDisplay);
vid.height = CGDisplayPixelsHigh(kCGDirectMainDisplay);
// capture the display!
CGDisplayCapture(kCGDirectMainDisplay);
CGDisplayHideCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(false);
format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
_openGLContext = [[NSOpenGLContext alloc]
initWithFormat:format
shareContext:nil];
[format release];
if(_openGLContext == nil)
{
NSLog(@"Cannot create OpenGL context");
[NSApp terminate:nil];
return;
}
[_openGLContext setFullScreen];
[_openGLContext setValues:&value forParameter:kCGLCPSwapInterval];
[_openGLContext makeCurrentContext];
_timer = [[NSTimer scheduledTimerWithTimeInterval:1.0/250.0
target:self
selector:@selector(runLoop:)
userInfo:nil
repeats:YES]
retain];
[[NSApp mainWindow] setAcceptsMouseMovedEvents:YES];
}
- (void)dealloc
{
CGAssociateMouseAndMouseCursorPosition(true);
CGDisplayRelease(kCGDirectMainDisplay);
CGDisplayRestoreColorSyncSettings();
CGDisplaySwitchToMode(kCGDirectMainDisplay,olddmode);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
CGPointMake(vid.width/2,vid.height/2));
[_openGLContext release];
[_timer invalidate];
[_timer release];
[super dealloc];
}
- (void) sendEvent:(NSEvent*)event
{
if ([event type] == NSKeyDown)
{
Key_Event(keyconv[[event keyCode]],TRUE);
//printf("%d\n",[event keyCode]);
return;
}
if ([event type] == NSKeyUp)
{
Key_Event(keyconv[[event keyCode]],FALSE);
return;
}
if ([event type] == NSFlagsChanged)
{
unsigned int mflags = [event modifierFlags];
if ((mflags & NSAlternateKeyMask) ^ (oldmflags & NSAlternateKeyMask))
{
Key_Event(K_ALT,(mflags & NSAlternateKeyMask) ? TRUE : FALSE);
}
if ((mflags & NSControlKeyMask) ^ (oldmflags & NSControlKeyMask))
{
Key_Event(K_LCTRL,(mflags & NSControlKeyMask) ? TRUE : FALSE);
}
if ((mflags & NSShiftKeyMask) ^ (oldmflags & NSShiftKeyMask))
{
Key_Event(K_LSHIFT,(mflags & NSShiftKeyMask) ? TRUE : FALSE);
}
if ((mflags & NSCommandKeyMask) ^ (oldmflags & NSCommandKeyMask))
{
Key_Event(K_LWIN,(mflags & NSCommandKeyMask) ? TRUE : FALSE);
}
if ((mflags & NSAlphaShiftKeyMask) ^ (oldmflags & NSAlphaShiftKeyMask))
{
Key_Event(K_CAPSLOCK,(mflags & NSAlphaShiftKeyMask) ? TRUE : FALSE);
}
oldmflags = mflags;
return;
}
if ([event type] == NSMouseMoved)
{
mouse_x += [event deltaX];
mouse_y += [event deltaY];
// lame hack to avoid mouse ptr moving to the top of the screen since
// a click there causes the mouse to appear and lock the event stream
// Apple sucks :(
// NOTE: it seems this is still needed for 10.3.x!
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
CGPointMake(vid.width - 1,vid.height - 1));
return;
}
if ([event type] == NSLeftMouseDragged)
{
mouse_x += [event deltaX];
mouse_y += [event deltaY];
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
CGPointMake(vid.width - 1,vid.height - 1));
return;
}
if ([event type] == NSRightMouseDragged)
{
mouse_x += [event deltaX];
mouse_y += [event deltaY];
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
CGPointMake(vid.width - 1,vid.height - 1));
return;
}
if ([event type] == NSOtherMouseDragged)
{
mouse_x += [event deltaX];
mouse_y += [event deltaY];
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
CGPointMake(vid.width - 1,vid.height - 1));
return;
}
if ([event type] == NSLeftMouseDown)
{
Key_Event(K_MOUSE1,TRUE);
return;
}
if ([event type] == NSLeftMouseUp)
{
Key_Event(K_MOUSE1,FALSE);
return;
}
if ([event type] == NSRightMouseDown)
{
Key_Event(K_MOUSE2,TRUE);
return;
}
if ([event type] == NSRightMouseUp)
{
Key_Event(K_MOUSE2,FALSE);
return;
}
if ([event type] == NSOtherMouseDown)
{
Key_Event(K_MOUSE3,TRUE);
return;
}
if ([event type] == NSOtherMouseUp)
{
Key_Event(K_MOUSE3,FALSE);
return;
}
if ([event type] == NSScrollWheel)
{
Key_Event(([event deltaY] > 0.0) ? K_MWHEELUP : K_MWHEELDOWN,TRUE);
return;
}
}
- (void)flushBuffer
{
// synchronise display
[_openGLContext flushBuffer];
}
// called on a timer event
- (void)runLoop:(NSTimer *)timer
{
newtime = Sys_DoubleTime ();
time = newtime - oldtime;
oldtime = newtime;
Host_Frame(time);
}
- (void)run
{
oldtime = Sys_DoubleTime ();
[super run];
}
@end
static FTEApplication *fteglapp;
BOOL initCocoa(rendererstate_t *info)
{
// init the application the hard way since we don't want to run it
// immediately
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
fteglapp = [FTEApplication sharedApplication];
// store the var for later disposal
_p = pool;
// init the display
[fteglapp initDisplayWidth:info->width height:info->height depth:info->bpp];
return TRUE;
}
qboolean glcocoaRunLoop(void)
{
if (!fteglapp)
return false;
// this will initialise the NSTimer and run the app
[NSApp run];
return true;
}
void killCocoa(void)
{
// terminates FTEApplicaiton
[NSApp terminate:nil];
[_p release];
fteglapp = NULL;
}
void flushCocoa(void)
{
// synchronises display
[NSApp flushBuffer];
}
void cocoaGamma(unsigned short *r,unsigned short *g,unsigned short *b)
{
CGByteValue gammatable[3*256];
int i;
// convert the gamma values
for(i=0;i<256;i++)
{
gammatable[i] = r[i] >> 8;
gammatable[i+256] = g[i] >> 8;
gammatable[i+512] = b[i] >> 8;
}
//... and set them
CGSetDisplayTransferByByteTable(kCGDirectMainDisplay,256,
gammatable,
gammatable + 256,
gammatable + 512);
}

239
engine/gl/gl_vidmacos.c Normal file
View file

@ -0,0 +1,239 @@
/*
Copyright (C) 2001-2002 A Nourai
Copyright (C) 2006 Jacek Piszczek (Mac OSX port)
This program 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 2
of the License, or (at your option) any later version.
This program 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 included (GNU.txt) GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "glquake.h"
#include <dlfcn.h>
//#include "vid_macos.h"
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
// note: cocoa code is separated in vid_cocoa.m because of compilation pbs
static qboolean vid_hwgamma_enabled = false;
cvar_t in_xflip = SCVAR("in_xflip", "0");
static int real_width, real_height;
static void *agllibrary;
static void *opengllibrary;
void *AGL_GetProcAddress(char *functionname)
{
void *func;
if (agllibrary)
{
func = dlsym(agllibrary, functionname);
if (func)
return func;
}
if (opengllibrary)
{
func = dlsym(opengllibrary, functionname);
if (func)
return func;
}
return NULL;
}
qboolean GLVID_Init(rendererstate_t *info, unsigned char *palette)
{
int argnum;
int i;
agllibrary = dlopen("/System/Library/Frameworks/AGL.framework/AGL", RTLD_LAZY);
if (!agllibrary)
{
Con_Printf("Couldn't load AGL framework\n");
return false;
}
opengllibrary = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY);
//don't care if opengl failed.
vid.width = info->width;
vid.height = info->height;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.numpages = 2;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
// initialise the NSApplication and the screen
initCocoa(info);
// initCocoa stores current screen size in vid
real_width = vid.width;
real_height = vid.height;
// calculate the conwidth AFTER the screen has been opened
if (vid.width <= 640)
{
vid.conwidth = vid.width;
vid.conheight = vid.height;
}
else
{
vid.conwidth = vid.width/2;
vid.conheight = vid.height/2;
}
if ((i = COM_CheckParm("-conwidth")) && i + 1 < com_argc)
{
vid.conwidth = Q_atoi(com_argv[i + 1]);
// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth * 3 / 4;
}
vid.conwidth &= 0xfff8; // make it a multiple of eight
if ((i = COM_CheckParm("-conheight")) && i + 1 < com_argc)
vid.conheight = Q_atoi(com_argv[i + 1]);
if (vid.conwidth < 320)
vid.conwidth = 320;
if (vid.conheight < 200)
vid.conheight = 200;
vid.rowbytes = vid.width;
vid.direct = 0; /* Isn't used anywhere, but whatever. */
vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
if (vid.conheight > vid.height)
vid.conheight = vid.height;
if (vid.conwidth > vid.width)
vid.conwidth = vid.width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
GL_Init(AGL_GetProcAddress);
GLVID_SetPalette(palette);
vid.recalc_refdef = 1;
return true;
}
void GLVID_DeInit(void)
{
killCocoa();
}
void GL_DoSwap(void)
{
}
void GLVID_ForceLockState(int i)
{
}
int GLVID_ForceUnlockedAndReturnState(void)
{
return 0;
}
void GLVID_SetPalette (unsigned char *palette)
{
qbyte *pal;
unsigned int r,g,b;
int i;
unsigned *table1;
unsigned *table2;
extern qbyte gammatable[256];
Con_Printf("Converting 8to24\n");
pal = palette;
table1 = d_8to24rgbtable;
table2 = d_8to24bgrtable;
for (i=0 ; i<256 ; i++)
{
r = gammatable[pal[0]];
g = gammatable[pal[1]];
b = gammatable[pal[2]];
pal += 3;
*table1++ = LittleLong((255<<24) + (r<<0) + (g<<8) + (b<<16));
*table2++ = LittleLong((255<<24) + (r<<16) + (g<<8) + (b<<0));
}
d_8to24bgrtable[255] &= LittleLong(0xffffff); // 255 is transparent
d_8to24rgbtable[255] &= LittleLong(0xffffff); // 255 is transparent
Con_Printf("Converted\n");
}
void GLVID_ShiftPalette(unsigned char *p)
{
// GLVID_SetPalette(p);
}
void Sys_SendKeyEvents(void)
{
}
void GLVID_LockBuffer(void)
{
}
void GLVID_UnlockBuffer(void)
{
}
qboolean GLVID_IsLocked(void)
{
return 0;
}
void GLD_BeginDirectRect(int x, int y, qbyte *pbitmap, int width, int height)
{
}
void GLD_EndDirectRect(int x, int y, int width, int height)
{
}
void GLVID_SetCaption(char *text)
{
}
void GL_BeginRendering (int *x, int *y, int *width, int *height)
{
*x = *y = 0;
*width = real_width;
*height = real_height;
}
void GL_EndRendering(void)
{
flushCocoa();
}
void GLVID_SetDeviceGammaRamp(unsigned short *ramps)
{
cocoaGamma(ramps,ramps+256,ramps+512);
}