Redline/source/macscreen.cpp
2016-04-04 17:08:13 +02:00

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;
}