⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macosx_glimp.m

📁 quakeIII源码这个不用我多说吧
💻 M
📖 第 1 页 / 共 3 页
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.

This file is part of Quake III Arena source code.

Quake III Arena 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 2 of the License,
or (at your option) any later version.

Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/
#import "macosx_glimp.h"

#include "tr_local.h"
#import "macosx_local.h"
#import "macosx_display.h"
#import "macosx_timers.h"

#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>

#import <mach-o/dyld.h>
#import <mach/mach.h>
#import <mach/mach_error.h>

cvar_t	*r_allowSoftwareGL;		// don't abort out if the pixelformat claims software
cvar_t  *r_enablerender;                // Enable actual rendering
cvar_t  *r_appleTransformHint;          // Enable Apple transform hint

static void GLW_InitExtensions( void );
static qboolean CreateGameWindow( qboolean isSecondTry );
static unsigned long Sys_QueryVideoMemory();
static CGDisplayErr Sys_CaptureActiveDisplays(void);


glwstate_t glw_state;
qboolean Sys_IsHidden = qfalse;

#ifdef OMNI_TIMER
OTStampList glThreadStampList;
#endif

@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 ) {
        ri.Error( ERR_FATAL, "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) {
            Com_Printf("100 GL errors printed ... disabling further error reporting.\n");
        } else if (errorCount < 100) {
            if (errorCount == 0) {
                fprintf(stderr, "BREAK ON QGLErrorBreak to stop at the GL errors\n");
            }
            fprintf(stderr, "OpenGL Error(%s): 0x%04x -- %s\n", message, (int)error,  gluErrorString(error));
            QGLErrorBreak();
        }
        errorCount++;
    }
}
#endif

/*
** GLimp_SetMode
*/

qboolean GLimp_SetMode( qboolean isSecondTry )
{
    if ( !CreateGameWindow(isSecondTry) ) {
        ri.Printf( PRINT_ALL, "GLimp_Init: window could not be created!\n" );
        return qfalse;
    }

    // draw something to show that GL is alive	
    if (r_enablerender->integer) {
        qglClearColor( 0.5, 0.5, 0.7, 0 );
        qglClear( GL_COLOR_BUFFER_BIT );
        GLimp_EndFrame();
        
        qglClearColor( 0.5, 0.5, 0.7, 0 );
        qglClear( GL_COLOR_BUFFER_BIT );
        GLimp_EndFrame();
    }

    Sys_UnfadeScreen(Sys_DisplayToUse(), NULL);
    
    CheckErrors();

    return qtrue;
}

/*
 =================
 GetPixelAttributes
 =================
 */

#define ADD_ATTR(x) \
do { \
    if (attributeIndex >= attributeSize) { \
        attributeSize *= 2; \
        pixelAttributes = NSZoneRealloc(NULL, pixelAttributes, sizeof(*pixelAttributes) * attributeSize); \
    } \
    pixelAttributes[attributeIndex] = x; \
    attributeIndex++; \
    if (verbose) { \
        ri.Printf(PRINT_ALL, "Adding pixel attribute: %d (%s)\n", x, #x); \
    } \
} while(0)

static NSOpenGLPixelFormatAttribute *GetPixelAttributes()
{
    NSOpenGLPixelFormatAttribute *pixelAttributes;
    unsigned int attributeIndex = 0;
    unsigned int attributeSize = 128;
    int verbose = 0;
    unsigned int colorDepth;
    
    verbose = r_verbose->integer;
    
    pixelAttributes = NSZoneMalloc(NULL, sizeof(*pixelAttributes) * attributeSize);

    if (r_fullscreen->integer) {
        ADD_ATTR(NSOpenGLPFAFullScreen);

        // Since we are fullscreen, specify the screen that we need.
        ADD_ATTR(NSOpenGLPFAScreenMask);
        ADD_ATTR(CGDisplayIDToOpenGLDisplayMask(Sys_DisplayToUse()));
    }
    
    // Require hardware acceleration unless otherwise directed
    if (!r_allowSoftwareGL->integer) {
        ADD_ATTR(NSOpenGLPFAAccelerated);
    }

    // Require double-buffer
    ADD_ATTR(NSOpenGLPFADoubleBuffer);

    // Specify the number of color bits.  If we don't have a valid specified value or we are not full screen, use the current display mode's value.
    ADD_ATTR(NSOpenGLPFAColorSize);
    colorDepth = r_colorbits->integer;
    if (colorDepth < 16)
        colorDepth = 16;
    else if (colorDepth > 16)
        colorDepth = 32;
    if (!r_fullscreen->integer)
        colorDepth = [[glw_state.desktopMode objectForKey: (id)kCGDisplayBitsPerPixel] intValue];
    ADD_ATTR(colorDepth);

    // Specify the number of depth bits
    ADD_ATTR(NSOpenGLPFADepthSize);
    ADD_ATTR(r_depthbits->integer ? r_depthbits->integer : 16);

    // Specify the number of stencil bits
    if (r_stencilbits->integer) {
        ADD_ATTR(NSOpenGLPFAStencilSize);
        ADD_ATTR(r_stencilbits->integer);
    }

    // Terminate the list
    ADD_ATTR(0);
    
    return pixelAttributes;
}

// Needs to be visible to Q3Controller.m.
void Sys_UpdateWindowMouseInputRect(void)
{		
    NSRect           windowRect, screenRect;
    NSScreen        *screen;

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

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

    Com_Printf("Releasing displays\n");
    for (displayIndex = 0; displayIndex < glw_state.displayCount; displayIndex++) {
        CGDisplayRelease(glw_state.originalDisplayGammaTables[displayIndex].display);
    }
}

/*
=================
CreateGameWindow
=================
*/
static qboolean CreateGameWindow( qboolean isSecondTry )
{
    const char *windowed[] = { "Windowed", "Fullscreen" };
    int			current_mode;
    NSOpenGLPixelFormatAttribute *pixelAttributes;
    NSOpenGLPixelFormat *pixelFormat;
    CGDisplayErr err;
            

    // get mode info
    current_mode = r_mode->integer;
    glConfig.isFullscreen = (r_fullscreen->integer != 0);

    glw_state.desktopMode = (NSDictionary *)CGDisplayCurrentMode(glw_state.display);
    if (!glw_state.desktopMode) {
        ri.Error(ERR_FATAL, "Could not get current graphics mode for display 0x%08x\n", glw_state.display);
    }

#if 0
    ri.Printf( PRINT_ALL, "... desktop mode %d = %dx%d %s\n", glw_state.desktopMode,
               glw_state.desktopDesc.width, glw_state.desktopDesc.height,
               depthStrings[glw_state.desktopDesc.depth]);
#endif

    ri.Printf( PRINT_ALL, "...setting mode %d:\n", current_mode );
    if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, current_mode ) )  {
        ri.Printf( PRINT_ALL, " invalid mode\n" );
        return qfalse;
    }
    ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, windowed[glConfig.isFullscreen] );

    if (glConfig.isFullscreen) {
        
        // 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(isSecondTry);
        if (!glw_state.gameMode) {
            ri.Printf( PRINT_ALL, "Unable to find requested display mode.\n");
            return qfalse;
        }

        // Fade all screens to black
        Sys_FadeScreens();
        
        err = Sys_CaptureActiveDisplays();
        if ( err != CGDisplayNoErr ) {
            CGDisplayRestoreColorSyncSettings();
            ri.Printf( PRINT_ALL, " Unable to capture displays err = %d\n", err );
            return qfalse;
        }

        err = CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.gameMode);
        if ( err != CGDisplayNoErr ) {
            CGDisplayRestoreColorSyncSettings();
            ReleaseAllDisplays();
            ri.Printf( PRINT_ALL, " Unable to set display mode, err = %d\n", err );
            return qfalse;
        }
    } else {
        glw_state.gameMode = glw_state.desktopMode;
    }

    
    // Get the GL pixel format
    pixelAttributes = GetPixelAttributes();
    pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes: pixelAttributes] autorelease];
    NSZoneFree(NULL, pixelAttributes);
    
    if (!pixelFormat) {
        CGDisplayRestoreColorSyncSettings();
        CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.desktopMode);
        ReleaseAllDisplays();
        ri.Printf( PRINT_ALL, " No pixel format found\n");
        return qfalse;
    }

    // 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();
        ri.Printf(PRINT_ALL, "... +[NSOpenGLContext createWithFormat:share:] failed.\n" );
        return qfalse;
    }

    if (!glConfig.isFullscreen) {
        cvar_t		*vid_xpos;
        cvar_t		*vid_ypos;
        NSRect           windowRect;
        
        vid_xpos = ri.Cvar_Get( "vid_xpos", "100", CVAR_ARCHIVE );
        vid_ypos = ri.Cvar_Get( "vid_ypos", "100", CVAR_ARCHIVE );

        // Create a window of the desired size
        windowRect.origin.x = vid_xpos->integer;
        windowRect.origin.y = vid_ypos->integer;
        windowRect.size.width = glConfig.vidWidth;
        windowRect.size.height = glConfig.vidHeight;
        
        glw_state.window = [[NSWindow alloc] initWithContentRect:windowRect
                                                       styleMask:NSTitledWindowMask
                                                         backing:NSBackingStoreRetained
                                                           defer:NO];
                                                           
        [glw_state.window setTitle: @"Quake3"];

        [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;
        
        err = CGLSetFullScreen(OSX_GetCGLContext());
        if (err) {
            CGDisplayRestoreColorSyncSettings();
            CGDisplaySwitchToMode(glw_state.display, (CFDictionaryRef)glw_state.desktopMode);
            ReleaseAllDisplays();
            Com_Printf("CGLSetFullScreen -> %d (%s)\n", err, CGLErrorString(err));
            return qfalse;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -