mirror of https://github.com/BOINC/boinc.git
410 lines
14 KiB
C
410 lines
14 KiB
C
// The contents of this file are subject to the Mozilla Public License
|
|
// Version 1.0 (the "License"); you may not use this file except in
|
|
// compliance with the License. You may obtain a copy of the License at
|
|
// http://www.mozilla.org/MPL/
|
|
//
|
|
// Software distributed under the License is distributed on an "AS IS"
|
|
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing rights and limitations
|
|
// under the License.
|
|
//
|
|
// The Original Code is the Berkeley Open Infrastructure for Network Computing.
|
|
//
|
|
// The Initial Developer of the Original Code is the SETI@home project.
|
|
// Portions created by the SETI@home project are Copyright (C) 2002
|
|
// University of California at Berkeley. All Rights Reserved.
|
|
//
|
|
// Contributor(s):
|
|
//
|
|
|
|
#include "graphics_api.h"
|
|
|
|
#include "mac_app_opengl.h"
|
|
#include "mac_carbon_gl.h"
|
|
|
|
#ifdef __APPLE_CC__
|
|
#include <Carbon/Carbon.h>
|
|
#include <OpenGL/gl.h>
|
|
#else
|
|
#include <gl.h>
|
|
|
|
#include <Devices.h>
|
|
#include <Dialogs.h>
|
|
#include <DriverServices.h>
|
|
#include <Events.h>
|
|
#include <Gestalt.h>
|
|
#include <LowMem.h>
|
|
#include <PictUtils.h>
|
|
#include <TextEdit.h>
|
|
#include <ToolUtils.h>
|
|
#include <QDOffscreen.h>
|
|
#include <Windows.h>
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
// project includes ---------------------------------------------------------
|
|
|
|
#include "mac_main.h"
|
|
|
|
void drawGL(WindowPtr pWindow);
|
|
|
|
static void DisposeGLWindow (WindowPtr pWindow); // Dispose a single window and it's GL context
|
|
|
|
// statics/globals (internal only) ------------------------------------------
|
|
|
|
static const EventTypeSpec appEventList[] =
|
|
{
|
|
{kEventClassCommand, kEventCommandProcess},
|
|
{kEventClassMouse, kEventMouseDown},
|
|
{kEventClassMouse, kEventMouseUp},
|
|
{kEventClassMouse, kEventMouseMoved},
|
|
{kEventClassMouse, kEventMouseDragged},
|
|
{kEventClassMouse, kEventMouseWheelMoved}
|
|
};
|
|
|
|
WindowRef appGLWindow;
|
|
EventLoopTimerRef boincTimer;
|
|
EventLoopTimerUPP boincTimerUPP;
|
|
EventHandlerUPP appCommandProcessor;
|
|
WindowPtr boincAboutWindow;
|
|
AGLContext boincAGLContext;
|
|
GLuint monacoFontList;
|
|
char boincStrContext [256];
|
|
structGLWindowInfo glInfo;
|
|
|
|
long gFrameWindow=0;
|
|
float gRotation=0;
|
|
AbsoluteTime gTimeWindow;
|
|
|
|
bool user_requested_exit = false;
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
int InitGLWindow(int xsize, int ysize, int depth)
|
|
{
|
|
OSStatus err;
|
|
Rect winRect;
|
|
TimerUPP boincYieldUPP;
|
|
EventLoopTimerRef boincYieldTimer;
|
|
short i,fNum;
|
|
long response;
|
|
MenuHandle menu;
|
|
|
|
InitCursor();
|
|
|
|
// add quit if not under Mac OS X
|
|
err = Gestalt (gestaltMenuMgrAttr, &response);
|
|
if ((err == noErr) && !(response & gestaltMenuMgrAquaLayoutMask)) {
|
|
menu = NewMenu (128, "\pFile"); // new menu
|
|
InsertMenu (menu, 0); // add menu to end
|
|
|
|
AppendMenu (menu, "\pQuit/Q"); // add quit
|
|
}
|
|
|
|
SetRect( &winRect, 100, 100, 100+xsize, 100+ysize );
|
|
|
|
err = CreateNewWindow ( kDocumentWindowClass, kWindowStandardDocumentAttributes, &winRect, &appGLWindow );
|
|
if (err != noErr) return -1;
|
|
|
|
// Application-level event handler installer
|
|
appCommandProcessor = NewEventHandlerUPP(MainAppEventHandler);
|
|
err = InstallApplicationEventHandler(appCommandProcessor, GetEventTypeCount(appEventList),
|
|
appEventList, 0, NULL);
|
|
// Install application graphics timer
|
|
boincTimerUPP = NewEventLoopTimerUPP(GraphicsLoopProcessor);
|
|
err = InstallEventLoopTimer(GetMainEventLoop(), 0,
|
|
kEventDurationMillisecond*10, // Every 1/60th of a second
|
|
boincTimerUPP, NULL, &boincTimer);
|
|
|
|
// Install preemption
|
|
boincYieldUPP = NewEventLoopTimerUPP(YieldProcessor);
|
|
err = InstallEventLoopTimer(GetMainEventLoop(), 0,
|
|
kEventDurationMillisecond*10, // Every 10 ms
|
|
boincYieldUPP, NULL, &boincYieldTimer);
|
|
|
|
// TODO: add an event handler for the window
|
|
ChangeWindowAttributes( appGLWindow, kWindowStandardHandlerAttribute, 0 );
|
|
SetWTitle (appGLWindow, "\pWindow");
|
|
ShowWindow(appGLWindow);
|
|
SetPortWindowPort (appGLWindow);
|
|
|
|
glInfo.fAcceleratedMust = false; // must renderer be accelerated?
|
|
glInfo.VRAM = 0 * 1048576; // minimum VRAM (if not zero this is always a required minimum)
|
|
glInfo.textureRAM = 0 * 1048576; // minimum texture RAM (if not zero this is always a required minimum)
|
|
if (!CheckMacOSX ()) // this is false on Mac OS 9 since Mac OS 9 does not support dragging conttexts with shared txtures between to different vendor's renderers.
|
|
glInfo.fDraggable = false; // should a pixel format that supports all monitors be chosen?
|
|
else
|
|
glInfo.fDraggable = true; // should a pixel format that supports all monitors be chosen?
|
|
glInfo.fmt = 0; // output pixel format
|
|
|
|
i = 0;
|
|
glInfo.aglAttributes [i++] = AGL_RGBA;
|
|
glInfo.aglAttributes [i++] = AGL_DOUBLEBUFFER;
|
|
glInfo.aglAttributes [i++] = AGL_ACCELERATED;
|
|
glInfo.aglAttributes [i++] = AGL_NO_RECOVERY;
|
|
glInfo.aglAttributes [i++] = AGL_DEPTH_SIZE;
|
|
glInfo.aglAttributes [i++] = 16;
|
|
glInfo.aglAttributes [i++] = AGL_NONE;
|
|
|
|
BuildGLFromWindow (appGLWindow, &boincAGLContext, &glInfo, NULL );
|
|
if (!boincAGLContext)
|
|
{
|
|
DestroyGLFromWindow (&boincAGLContext, &glInfo);
|
|
sprintf (boincStrContext, "No context");
|
|
}
|
|
else
|
|
{
|
|
Rect rectPort;
|
|
|
|
GetWindowPortBounds (appGLWindow, &rectPort);
|
|
aglSetCurrentContext (boincAGLContext);
|
|
aglReportError ();
|
|
aglUpdateContext (boincAGLContext);
|
|
aglReportError ();
|
|
|
|
// Set Texture mapping parameters
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glClearColor(0.15f, 0.15f, 0.15f, 1.0f); // Clear color buffer to dark grey
|
|
glClear (GL_COLOR_BUFFER_BIT);
|
|
glReportError ();
|
|
aglSwapBuffers (boincAGLContext);
|
|
aglReportError ();
|
|
|
|
aglDisable (boincAGLContext, AGL_BUFFER_RECT);
|
|
aglReportError ();
|
|
glViewport (0, 0, rectPort.right - rectPort.left, rectPort.bottom - rectPort.top);
|
|
glReportError ();
|
|
sprintf (boincStrContext, "%d x %d", rectPort.right - rectPort.left, rectPort.bottom - rectPort.top);
|
|
|
|
GetFNum("\pMonaco", &fNum); // build font
|
|
monacoFontList = BuildFontGL (boincAGLContext, fNum, normal, 9);
|
|
|
|
aglUpdateContext (boincAGLContext);
|
|
aglReportError ();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// GraphicsLoopProcessor //
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
pascal void GraphicsLoopProcessor(EventLoopTimerRef inTimer, void* timeData) {
|
|
DoUpdate (boincAGLContext);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// YieldProcessor //
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
pascal void YieldProcessor(EventLoopTimerRef inTimer, void* timeData) {
|
|
YieldToAnyThread();
|
|
}
|
|
|
|
/*
|
|
if ((pWindowInfo) && (boincAGLContext))
|
|
{
|
|
GetWindowPortBounds (whichWindow, &rectTemp);
|
|
aglSetCurrentContext (boincAGLContext); // ensure the context we are working with is current
|
|
aglUpdateContext (boincAGLContext);
|
|
glViewport (0, 0, rectTemp.right - rectTemp.left, rectTemp.bottom - rectTemp.top);
|
|
sprintf (pWindowInfo->strContext, "%d x %d", rectTemp.right - rectTemp.left, rectTemp.bottom - rectTemp.top);
|
|
}
|
|
*/
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// MainAppEventHandler //
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
pascal OSStatus MainAppEventHandler(EventHandlerCallRef appHandler, EventRef theEvent, void* appData)
|
|
{
|
|
#pragma unused (appHandler, appData)
|
|
|
|
HICommand aCommand;
|
|
OSStatus result;
|
|
Point mDelta;
|
|
|
|
switch(GetEventClass(theEvent))
|
|
{
|
|
case kEventClassMouse: // 'mous'
|
|
GetEventParameter(theEvent, // the event itself
|
|
kEventParamMouseDelta, // symbolic parameter name
|
|
typeQDPoint, // expected type
|
|
NULL, // actual type (NULL is valid)
|
|
sizeof(mDelta), // buffer size
|
|
NULL, // actual buffer size (Can be NULL)
|
|
&mDelta); // variable to hold data
|
|
switch(GetEventKind(theEvent))
|
|
{
|
|
case kEventMouseDown:
|
|
break;
|
|
case kEventMouseUp:
|
|
break;
|
|
case kEventMouseMoved:
|
|
break;
|
|
case kEventMouseDragged:
|
|
break;
|
|
case kEventMouseWheelMoved:
|
|
break;
|
|
default:
|
|
result = eventNotHandledErr;
|
|
break;
|
|
}
|
|
break;
|
|
case kEventClassCommand:
|
|
result = GetEventParameter(theEvent, kEventParamDirectObject,
|
|
typeHICommand, NULL, sizeof(HICommand),
|
|
NULL, &aCommand);
|
|
switch (aCommand.commandID)
|
|
{
|
|
case kHICommandQuit:
|
|
QuitApplicationEventLoop();
|
|
result = noErr;
|
|
break;
|
|
case kHICommandOK: // 'ok '
|
|
case kHICommandCancel: // 'not!'
|
|
case kHICommandUndo: // 'undo'
|
|
case kHICommandRedo: // 'redo'
|
|
case kHICommandCut: // 'cut '
|
|
case kHICommandCopy: // 'copy'
|
|
case kHICommandPaste: // 'past'
|
|
case kHICommandClear: // 'clea'
|
|
case kHICommandSelectAll: // 'sall'
|
|
case kHICommandHide: // 'hide'
|
|
case kHICommandZoomWindow: // 'zoom'
|
|
case kHICommandMinimizeWindow: // 'mini'
|
|
case kHICommandArrangeInFront: // 'frnt'
|
|
break;
|
|
case kHICommandAbout: // 'abou'
|
|
// Open About window
|
|
//CreateAboutWindow();
|
|
result = noErr;
|
|
break;
|
|
default:
|
|
result = eventNotHandledErr;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
result = eventNotHandledErr;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
pascal void mac_graphics_event_loop ( GRAPHICS_INFO *gi ) {
|
|
InitGLWindow(gi->xsize, gi->ysize, 16);
|
|
RunApplicationEventLoop();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
void mac_cleanup (void)
|
|
{
|
|
// TODO: Dispose all the timers here
|
|
RemoveEventLoopTimer(boincTimer);
|
|
DisposeEventLoopTimerUPP(boincTimerUPP);
|
|
DisposeEventHandlerUPP(appCommandProcessor);
|
|
//DisposeGLWindow (appGLWindow);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
static void DisposeGLWindow (WindowPtr pWindow) // Dispose a single window and it's GL context
|
|
{
|
|
if (pWindow)
|
|
{
|
|
DeleteFontGL (monacoFontList);
|
|
// must clean up failure to do so will result in an Unmapped Memory Exception
|
|
DestroyGLFromWindow (&boincAGLContext, &glInfo);
|
|
|
|
DisposeWindow (pWindow);
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
//-----------------------------------------------------------------------------------------------------------------------
|
|
|
|
// OpenGL Drawing
|
|
|
|
void drawGL(WindowPtr pWindow)
|
|
{
|
|
static int first = 1;
|
|
static char myStr[256];
|
|
|
|
if( first ) {
|
|
gFrameWindow = 0;
|
|
gTimeWindow.hi = 0;
|
|
gTimeWindow.lo = 0;
|
|
gRotation = 0.0;
|
|
first = 0;
|
|
}
|
|
float f = 0.0;
|
|
|
|
glClearColor(0.25f, 0.25f, 0.25f, 1.0f); // Clear color buffer to dark grey
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
gRotation += 0.5;
|
|
f = gRotation;
|
|
|
|
glMatrixMode (GL_MODELVIEW);
|
|
glLoadIdentity ();
|
|
glRotated (f, 0.0, 0.0, 1.0);
|
|
glEnable (GL_TEXTURE_2D);
|
|
glBegin(GL_QUADS); // Draw textured polygon
|
|
|
|
glColor3d(1.0, 0.0, 0.0);
|
|
glVertex3d(0.7, 0.7, 0.0);
|
|
|
|
glColor3d(0.0, 1.0, 0.0);
|
|
glVertex3d(-0.7, 0.7, 0.0);
|
|
|
|
glColor3d(0.0, 0.0, 1.0);
|
|
glVertex3d(-0.7, -0.7, 0.0);
|
|
|
|
glColor3d(0.7, 0.7, 0.7);
|
|
glVertex3d(0.7, -0.7, 0.0);
|
|
|
|
glEnd();
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
|
// draw info
|
|
|
|
Rect rectPort;
|
|
GLint matrixMode;
|
|
GetWindowPortBounds (pWindow, &rectPort);
|
|
glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
|
|
glMatrixMode (GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity ();
|
|
glMatrixMode (GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity ();
|
|
glScalef (2.0 / (rectPort.right - rectPort.left), -2.0 / (rectPort.bottom - rectPort.top), 1.0);
|
|
glTranslatef (-(rectPort.right - rectPort.left) / 2.0, -(rectPort.bottom - rectPort.top) / 2.0, 0.0);
|
|
glColor3f (1.0, 1.0, 1.0);
|
|
glRasterPos3d (10, 12, 0);
|
|
|
|
MultiWinDrawFrameRate (monacoFontList, myStr, &gFrameWindow, &gTimeWindow);
|
|
|
|
glRasterPos3d (10, 24, 0);
|
|
DrawCStringGL (boincStrContext, monacoFontList);
|
|
glRasterPos3d (10, (rectPort.bottom - rectPort.top) - 15, 0);
|
|
DrawCStringGL ((char*) glGetString (GL_VENDOR), monacoFontList);
|
|
glRasterPos3d (10, (rectPort.bottom - rectPort.top) - 3, 0);
|
|
DrawCStringGL ((char*) glGetString (GL_RENDERER), monacoFontList);
|
|
glPopMatrix(); // GL_MODELVIEW
|
|
glMatrixMode (GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode (matrixMode);
|
|
}
|