347 lines
8.5 KiB
C++
347 lines
8.5 KiB
C++
//macscreen.cpp
|
|
//mac-specific code to access the screen device
|
|
#include <QuickTime/QuickTime.h>
|
|
#include <AGL/AGL.h>
|
|
#include <QD/QD.h>
|
|
#include "screen.h"
|
|
#include "config.h"
|
|
#include "error.h"
|
|
#include "textures.h"
|
|
|
|
AGLContext gOpenGLContext=NULL;
|
|
|
|
AGLContext SetupAGL( AGLDrawable window,GLint *attrib,int width, int height)
|
|
{
|
|
AGLPixelFormat format;
|
|
AGLContext context;
|
|
GLboolean ok;
|
|
GLint attrib2[256];
|
|
|
|
GDHandle screen;
|
|
if(window)
|
|
screen=GetGWorldDevice((GWorldPtr)window);
|
|
else
|
|
screen=DMGetFirstScreenDevice(true);
|
|
|
|
if(window==NULL)
|
|
{
|
|
int i=0;
|
|
while(attrib[i]!=AGL_NONE)
|
|
attrib2[i++]=attrib[i];
|
|
attrib2[i++]=AGL_FULLSCREEN;
|
|
//attrib2[i++]=AGL_NO_RECOVERY;
|
|
attrib2[i++]=AGL_NONE;
|
|
attrib=attrib2;
|
|
}
|
|
|
|
// Choose an rgb pixel format
|
|
format = aglChoosePixelFormat( &screen, 1, attrib );
|
|
if ( format == NULL )
|
|
{
|
|
printf("aglChoosePixelFormat: %s\n",aglErrorString(aglGetError()));
|
|
return NULL;
|
|
}
|
|
// Create an AGL context
|
|
context = aglCreateContext( format, gOpenGLContext );
|
|
if ( context == NULL )
|
|
{
|
|
printf("aglCreateContext: %s\n",aglErrorString(aglGetError()));
|
|
return NULL;
|
|
}
|
|
|
|
if(window){
|
|
ok = aglSetDrawable(context,window);
|
|
if ( !ok )
|
|
{
|
|
printf("aglSetDrawable: %s\n",aglErrorString(aglGetError()));
|
|
return NULL;
|
|
}
|
|
}
|
|
else{
|
|
ok = aglSetFullScreen (context,width,height,75,0);
|
|
if ( !ok )
|
|
{
|
|
ok = aglSetFullScreen (context,640,480,75,0);
|
|
if ( !ok )
|
|
{
|
|
printf("aglSetFullScreen: %s\n",aglErrorString(aglGetError()));
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make the context the current context
|
|
ok = aglSetCurrentContext( context );
|
|
if ( !ok )
|
|
{
|
|
printf("aglSetCurrentContext: %s\n",aglErrorString(aglGetError()));
|
|
return NULL;
|
|
}
|
|
// The pixel format is no longer needed so get rid of it
|
|
aglDestroyPixelFormat( format );
|
|
return context;
|
|
}
|
|
|
|
//Initialize an OpenGL context using AGL
|
|
void InitGLContext()
|
|
{
|
|
CGrafPtr theScreen=NULL;
|
|
|
|
//is fullscreen mode enabled?
|
|
if(gConfig->fullscreen)
|
|
theScreen=NULL;
|
|
else
|
|
{
|
|
//get a Window Context
|
|
Rect boundsRect;
|
|
if(gConfig->windowY<40)
|
|
gConfig->windowY=40;
|
|
SetRect(&boundsRect,gConfig->windowX,gConfig->windowY,gConfig->windowX+gConfig->screenXSize,gConfig->windowY+gConfig->screenYSize);
|
|
WindowRef win=NewCWindow(0,&boundsRect,"\pRedline",true,0,(WindowRef)-1L,false,0);
|
|
if(!RectInRgn(&boundsRect,GetGrayRgn()))
|
|
MoveWindow(win,40,40,true);
|
|
theScreen=GetWindowPort(win);
|
|
SetPort(theScreen);
|
|
GetPortBounds(theScreen,&boundsRect);
|
|
Pattern black;
|
|
GetQDGlobalsBlack(&black);
|
|
FillRect(&boundsRect,&black);
|
|
HIWindowFlush(FrontWindow());
|
|
}
|
|
|
|
// Setup the OpenGL context
|
|
AGLContext ctx;
|
|
if(gConfig->fsaa)
|
|
{
|
|
GLint attrib[] = { AGL_RGBA, AGL_PIXEL_SIZE, gConfig->color32Bit?32:16,AGL_NO_RECOVERY,AGL_DOUBLEBUFFER, AGL_STENCIL_SIZE, 8,AGL_SAMPLE_BUFFERS_ARB,1,AGL_SAMPLES_ARB,gConfig->fsaa, AGL_NONE};
|
|
// GLint attrib[] = { AGL_RGBA, AGL_PIXEL_SIZE, gConfig->color32Bit?32:16,AGL_DOUBLEBUFFER, AGL_STENCIL_SIZE, 8,AGL_SAMPLE_BUFFERS_ARB,1,AGL_SAMPLES_ARB,gConfig->fsaa, AGL_NONE};
|
|
ctx=SetupAGL((AGLDrawable)theScreen,attrib,gConfig->screenXSize,gConfig->screenYSize);
|
|
}
|
|
else
|
|
{
|
|
GLint attrib[] = { AGL_RGBA, AGL_PIXEL_SIZE, gConfig->color32Bit?32:16,AGL_NO_RECOVERY,AGL_DOUBLEBUFFER, AGL_STENCIL_SIZE, 8, AGL_NONE};
|
|
// GLint attrib[] = { AGL_RGBA, AGL_PIXEL_SIZE, gConfig->color32Bit?32:16,AGL_DOUBLEBUFFER, AGL_STENCIL_SIZE, 8, AGL_NONE};
|
|
ctx=SetupAGL((AGLDrawable)theScreen,attrib,gConfig->screenXSize,gConfig->screenYSize);
|
|
}
|
|
if(!ctx)
|
|
{
|
|
if(gConfig->fullscreen)
|
|
{
|
|
gConfig->fullscreen=false;
|
|
InitGLContext();
|
|
}
|
|
else
|
|
FailWithErrorString("Couldn't Create Screen");
|
|
}
|
|
else
|
|
{
|
|
if(gOpenGLContext)
|
|
aglDestroyContext(gOpenGLContext);
|
|
gOpenGLContext=ctx;
|
|
}
|
|
}
|
|
|
|
static int numberForKey( CFDictionaryRef desc, CFStringRef key )
|
|
{
|
|
CFNumberRef value;
|
|
int num = 0;
|
|
|
|
if ( (value = (CFNumberRef)CFDictionaryGetValue(desc, key)) == NULL )
|
|
return 0;
|
|
CFNumberGetValue(value, kCFNumberIntType, &num);
|
|
return num;
|
|
}
|
|
|
|
void ScreenGetModes()
|
|
{
|
|
CFArrayRef modeList;
|
|
CFIndex i, cnt;
|
|
|
|
gVideoNumModes=0;
|
|
modeList = CGDisplayAvailableModes(kCGDirectMainDisplay);
|
|
if ( modeList == NULL )
|
|
{
|
|
printf( "Display is invalid\n" );
|
|
exit(1);
|
|
}
|
|
cnt = CFArrayGetCount(modeList);
|
|
for ( i = 0; i < cnt; ++i )
|
|
{
|
|
CFDictionaryRef desc = (CFDictionaryRef)CFArrayGetValueAtIndex(modeList, i);
|
|
int depth=numberForKey(desc, kCGDisplayBitsPerPixel);
|
|
if(depth==32&&gVideoNumModes<kMaxModes)
|
|
{
|
|
int height=numberForKey(desc, kCGDisplayHeight);
|
|
int width=numberForKey(desc, kCGDisplayWidth);
|
|
int freq=numberForKey(desc, kCGDisplayRefreshRate);
|
|
int exists=false;
|
|
for(int j=0;j<gVideoNumModes;j++)
|
|
if(gVideoModes[j].height==height&&gVideoModes[j].width==width)
|
|
{
|
|
if(freq<gVideoModes[j].freq&&freq>=60)
|
|
gVideoModes[j].freq=freq;
|
|
exists=true;
|
|
}
|
|
if(!exists)
|
|
{
|
|
gVideoModes[gVideoNumModes].height=height;
|
|
gVideoModes[gVideoNumModes].width=width;
|
|
gVideoModes[gVideoNumModes].freq=freq;
|
|
gVideoNumModes++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(int i=0;i<gVideoNumModes;i++)
|
|
for(int j=0;j<gVideoNumModes-1-i;j++)
|
|
if(gVideoModes[j].width<gVideoModes[j+1].width||(gVideoModes[j].width==gVideoModes[j+1].width&&gVideoModes[j].height<gVideoModes[j+1].height))
|
|
{
|
|
tVideoMode tmp=gVideoModes[j];
|
|
gVideoModes[j]=gVideoModes[j+1];
|
|
gVideoModes[j+1]=tmp;
|
|
}
|
|
}
|
|
|
|
void ScreenExit()
|
|
{
|
|
#ifndef __TARGET_TOOLAPP
|
|
aglSetDrawable(gOpenGLContext,NULL);
|
|
if(FrontWindow())
|
|
DisposeWindow(FrontWindow());
|
|
InitCursor();
|
|
#endif
|
|
}
|
|
|
|
//Swap front- and backbuffer
|
|
void ScreenBlit()
|
|
{
|
|
aglSwapBuffers(gOpenGLContext);
|
|
}
|
|
|
|
int GetVRAMSize()
|
|
{
|
|
char str[256];
|
|
|
|
AGLRendererInfo info, head_info;
|
|
GLint inum;
|
|
GLint dAccel = 0;
|
|
GLint dVRAM = 0, dMaxVRAM = 0;
|
|
AGLDevice gd=GetMainDevice();
|
|
head_info = aglQueryRendererInfo(&gd, 1);
|
|
if(!head_info)
|
|
return 0;
|
|
info = head_info;
|
|
inum = 0;
|
|
// see if we have an accelerated renderer, if so ignore non-accelerated ones
|
|
// this prevents returning info on software renderer when actually we'll get the hardware one
|
|
|
|
while (info)
|
|
{
|
|
aglDescribeRenderer (info, AGL_ACCELERATED, &dAccel);
|
|
// if we can accel then we will choose the accelerated renderer
|
|
// how about compliant renderers???
|
|
if (dAccel)
|
|
{
|
|
aglDescribeRenderer (info, AGL_VIDEO_MEMORY, &dVRAM); // we assume that VRAM returned is total thus add texture and VRAM required
|
|
if (dVRAM >= dMaxVRAM) // find card with max VRAM
|
|
dMaxVRAM = dVRAM; // store max
|
|
}
|
|
info = aglNextRendererInfo(info);
|
|
inum++;
|
|
}
|
|
// aglDestroyRendererInfo(head_info);
|
|
|
|
return dVRAM;
|
|
}
|
|
|
|
int ScreenSupportsTextureCompression()
|
|
{
|
|
static int result=-1;
|
|
if(result==-1)
|
|
{
|
|
char* extensions=(char*)glGetString(GL_EXTENSIONS);
|
|
result=strstr(extensions,"GL_EXT_texture_compression_s3tc")?true:false;
|
|
|
|
long resp;
|
|
Gestalt(gestaltSystemVersion,&resp);
|
|
if(resp<0x00001030)
|
|
{
|
|
//GeForce Texture compression seems buggy in 10.2.8
|
|
char* renderer=(char*)glGetString(GL_RENDERER);
|
|
if (strstr(renderer,"GeForce"))
|
|
result=false;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int ScreenSupportsAnisotropicFiltering()
|
|
{
|
|
static int result=-1;
|
|
if(result==-1)
|
|
{
|
|
char* extensions=(char*)glGetString(GL_EXTENSIONS);
|
|
result=strstr(extensions,"GL_EXT_texture_filter_anisotropic")?true:false;
|
|
|
|
char* renderer=(char*)glGetString(GL_RENDERER);
|
|
//GeForce 5200 bug
|
|
if (strstr (renderer, "NV34MAP") || (strstr (renderer , "GeForce") && strstr (renderer, "5200")))
|
|
result=false;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int ScreenSupports3DTextures()
|
|
{
|
|
static int result=-1;
|
|
if(result==-1)
|
|
{
|
|
/*
|
|
char* extensions=(char*)glGetString(GL_EXTENSIONS);
|
|
result=strstr(extensions,"GL_EXT_texture3D")?true:false;
|
|
*/
|
|
|
|
result=true; //built-in in GL 1.2 or higher.
|
|
|
|
char* renderer=(char*)glGetString(GL_RENDERER);
|
|
printf("Renderer: %s\n",renderer);
|
|
//GeForce 2 only has software 3d textures (? - according to unity)
|
|
if (strstr (renderer, "GeForce") && !(strstr (renderer , "TI") || strstr (renderer, "FX")))
|
|
result=false;
|
|
//same with Rage128
|
|
if (strstr (renderer, "Rage") && strstr (renderer, "128"))
|
|
result=false;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int ScreenSupportsBlendColor()
|
|
{
|
|
static int result=-1;
|
|
if(result==-1)
|
|
{
|
|
char* extensions=(char*)glGetString(GL_EXTENSIONS);
|
|
result=strstr(extensions,"GL_ARB_imaging")?true:false;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int ScreenNoBigTextures()
|
|
{
|
|
static int result=-1;
|
|
if(result==-1)
|
|
result=GetVRAMSize()<=1024*1024*8;
|
|
return result;
|
|
}
|
|
|
|
int ScreenNoWindow()
|
|
{
|
|
static int result=-1;
|
|
if(result==-1)
|
|
{
|
|
long resp;
|
|
Gestalt(gestaltSystemVersion,&resp);
|
|
result=(resp<0x00001030);
|
|
}
|
|
return result;
|
|
} |