blob: 9131cab4873498d729dabe3201b49a04f3c2e242 [file] [log] [blame]
/*
* Project: VizKit
* Version: 2.3
* Date: 20090823
* File: VisualGraphicsCore.cpp
*
*/
/***************************************************************************
Copyright (c) 2004-2009 Heiko Wichmann (http://www.imagomat.de/vizkit)
This software is provided 'as-is', without any expressed or implied warranty.
In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated
but is not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
***************************************************************************/
#include "VisualGraphicsCore.h"
#include "VisualErrorHandling.h"
#if TARGET_OS_WIN
#include <stdio.h> // sprintf
#endif
#if TARGET_OS_WIN
#include <GL/gl.h>
#include <GL/glu.h>
#endif
using namespace VizKit;
VisualGraphicsCore* VisualGraphicsCore::theVisualGraphicsCore = NULL; // singleton
VisualGraphicsCore::VisualGraphicsCore() {
ctx = NULL;
#if TARGET_OS_MAC
directDisplayId = CGMainDisplayID();
#endif
#if TARGET_OS_WIN
windowDC = NULL;
#endif
}
VisualGraphicsCore::~VisualGraphicsCore() {
// null
}
VisualGraphicsCore* VisualGraphicsCore::getInstance() {
if (theVisualGraphicsCore == NULL) {
theVisualGraphicsCore = new VisualGraphicsCore;
}
return theVisualGraphicsCore;
}
void VisualGraphicsCore::dispose() {
if (theVisualGraphicsCore != NULL) {
delete theVisualGraphicsCore;
theVisualGraphicsCore = NULL;
}
}
bool VisualGraphicsCore::setupContext() {
bool success = true;
uint8 errNum = 0;
char errLog[256];
#if TARGET_OS_MAC
errNum = theVisualGraphicsCore->setupAGL();
if (errNum != 0) {
sprintf(errLog, "error %d on setupAGL in file: %s (line: %d) [%s])", errNum, __FILE__, __LINE__, __FUNCTION__);
writeLog(errLog);
success = false;
}
#endif
#if TARGET_OS_WIN
errNum = theVisualGraphicsCore->setupWGL();
if (errNum != 0) {
sprintf(errLog, "error %d on setupWGL in file: %s (line: %d) [%s])", errNum, __FILE__, __LINE__, __FUNCTION__);
writeLog(errLog);
success = false;
}
#endif
return success;
}
#if TARGET_OS_MAC
uint8 VisualGraphicsCore::setupAGL() {
GLboolean ok;
GLint attrib[] = {AGL_RGBA, AGL_RED_SIZE, 8, AGL_GREEN_SIZE, 8, AGL_BLUE_SIZE, 8, AGL_ALPHA_SIZE, 8, AGL_ACCELERATED, AGL_DOUBLEBUFFER, AGL_DEPTH_SIZE, 24, AGL_CLOSEST_POLICY, AGL_NONE};
AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, attrib);
if (fmt == NULL) {
return 1;
}
theVisualGraphicsCore->ctx = aglCreateContext(fmt, NULL);
if (theVisualGraphicsCore->ctx == NULL) {
return 2;
}
ok = aglSetDrawable(theVisualGraphicsCore->ctx, theVisualGraphicsCore->port);
if (!ok) {
return 3;
}
ok = aglSetCurrentContext(theVisualGraphicsCore->ctx);
if (!ok) {
return 4;
}
ok = aglUpdateContext(theVisualGraphicsCore->ctx);
if (!ok) {
return 5;
}
GLint swapinterval = 1;
ok = aglSetInteger(theVisualGraphicsCore->ctx, AGL_SWAP_INTERVAL, &swapinterval);
if (!ok) {
return 6;
}
aglDestroyPixelFormat(fmt);
return 0;
}
void VisualGraphicsCore::cleanupAGL() {
aglSetCurrentContext(NULL);
if (theVisualGraphicsCore->ctx != NULL) {
aglSetDrawable(theVisualGraphicsCore->ctx, NULL);
aglDestroyContext(theVisualGraphicsCore->ctx);
}
}
#endif
uint16 VisualGraphicsCore::setCurrentContext() {
#if TARGET_OS_MAC
GLboolean ok;
ok = aglSetCurrentContext(theVisualGraphicsCore->ctx);
if(!ok) {
return 1;
}
#endif
#if TARGET_OS_WIN
if (!wglMakeCurrent(theVisualGraphicsCore->windowDC, theVisualGraphicsCore->ctx)) {
writeLastErrorLog("setCurrentContext");
return 1;
}
#endif
return 0;
}
#if TARGET_OS_WIN
uint8 VisualGraphicsCore::setupWGL() {
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixelFormat = ChoosePixelFormat(theVisualGraphicsCore->windowDC, &pfd);
if (pixelFormat == 0) {
writeLastErrorLog("setupWGL1");
return 1;
}
if (SetPixelFormat(theVisualGraphicsCore->windowDC, pixelFormat, &pfd) == 0) {
writeLastErrorLog("setupWGL2");
return 2;
}
theVisualGraphicsCore->ctx = wglCreateContext(theVisualGraphicsCore->windowDC);
if (theVisualGraphicsCore->ctx == NULL) {
writeLastErrorLog("setupWGL3");
return 3;
}
if (!wglMakeCurrent(theVisualGraphicsCore->windowDC, theVisualGraphicsCore->ctx)) {
writeLastErrorLog("setupWGL4");
return 4;
}
// enable v-sync if WGL_EXT_swap_control is supported
/*
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT != NULL)
wglSwapIntervalEXT(1);
*/
return 0;
}
void VisualGraphicsCore::cleanUpWGL() {
wglMakeCurrent(NULL, NULL);
if (theVisualGraphicsCore->ctx != NULL) {
wglDeleteContext(theVisualGraphicsCore->ctx);
theVisualGraphicsCore->ctx = NULL;
}
if (theVisualGraphicsCore->windowDC) {
ReleaseDC(theVisualGraphicsCore->port, theVisualGraphicsCore->windowDC);
theVisualGraphicsCore->windowDC = NULL;
}
}
HDC VisualGraphicsCore::getWindowDC() {
if (theVisualGraphicsCore->windowDC) {
return theVisualGraphicsCore->windowDC;
} else {
// if the HDC has not been set yet for the visualizer, we return the HDC of the main screen
return GetDC(NULL);
}
}
#endif
void VisualGraphicsCore::setGraphicsDevicePort(const GRAPHICS_DEVICE thePort) {
theVisualGraphicsCore->port = thePort;
#if TARGET_OS_WIN
theVisualGraphicsCore->windowDC = GetDC(thePort);
#endif
}
GRAPHICS_DEVICE VisualGraphicsCore::getGraphicsDevicePort() {
return theVisualGraphicsCore->port;
}
PixelRect VisualGraphicsCore::getScreenRect() {
PixelRect screenRect;
uint32 screenWidth;
uint32 screenHeight;
#if TARGET_OS_WIN
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
#endif
#if TARGET_OS_MAC
screenWidth = (uint32)CGDisplayPixelsWide(theVisualGraphicsCore->directDisplayId);
screenHeight = (uint32)CGDisplayPixelsHigh(theVisualGraphicsCore->directDisplayId);
#endif
screenRect.width = screenWidth;
screenRect.height = screenHeight;
return screenRect;
}
uint16 VisualGraphicsCore::getBitsPerPixelOfScreen() {
uint16 bitsPerPixel;
#if TARGET_OS_WIN
bitsPerPixel = GetDeviceCaps(theVisualGraphicsCore->windowDC, BITSPIXEL);
#endif
#if TARGET_OS_MAC
bitsPerPixel = (uint16)CGDisplayBitsPerPixel(theVisualGraphicsCore->directDisplayId);
#endif
return bitsPerPixel;
}
uint16 VisualGraphicsCore::getRefreshRateOfScreen() {
uint16 refreshRate = 0;
#if TARGET_OS_MAC
long refreshRateLong;
CFDictionaryRef displayMode;
CFNumberRef number;
displayMode = CGDisplayCurrentMode(theVisualGraphicsCore->directDisplayId);
number = (CFNumberRef)CFDictionaryGetValue(displayMode, kCGDisplayRefreshRate);
CFNumberGetValue(number, kCFNumberLongType, &refreshRateLong);
refreshRate = (uint16)refreshRateLong;
#endif
#if TARGET_OS_WIN
refreshRate = GetDeviceCaps(theVisualGraphicsCore->windowDC, VREFRESH);
#endif
return refreshRate;
}
void VisualGraphicsCore::finishGLDrawing() {
//glFinish();
//glFlush();
#if TARGET_OS_MAC
aglSwapBuffers(theVisualGraphicsCore->ctx);
#endif
#if TARGET_OS_WIN
SwapBuffers(theVisualGraphicsCore->windowDC);
#endif
}
PixelRect VisualGraphicsCore::getCanvasSurroundingRect() {
PixelRect pixelSize;
#if TARGET_OS_MAC
::Rect aRect;
GetPortBounds(theVisualGraphicsCore->port, &aRect);
pixelSize.width = aRect.right - aRect.left;
pixelSize.height = aRect.bottom - aRect.top;
#endif
#if TARGET_OS_WIN
HWND windowHandle;
RECT windowRect;
POINT aPoint;
aPoint.x = 0;
aPoint.y = 0;
windowHandle = theVisualGraphicsCore->port;
ClientToScreen(windowHandle, &aPoint);
GetClientRect(windowHandle, &windowRect);
windowRect.bottom += aPoint.y;
windowRect.right += aPoint.x;
pixelSize.width = windowRect.right - aPoint.x;
pixelSize.height = windowRect.bottom - aPoint.y;
#endif
return pixelSize;
}
void VisualGraphicsCore::setViewport(const BottomLeftPositionedPixelRect& canvasRect, const bool isFullscreen) {
Pixel viewportBottomLeft;
viewportBottomLeft.x = 0;
viewportBottomLeft.y = 0;
#if TARGET_OS_MAC
GLboolean ok;
GLint bufferRect[4];
bufferRect[0] = (GLint)canvasRect.bottomLeftPixel.x;
bufferRect[1] = (GLint)canvasRect.bottomLeftPixel.y;
bufferRect[2] = (GLint)canvasRect.pixelRect.width;
bufferRect[3] = (GLint)canvasRect.pixelRect.height;
ok = GL_FALSE;
ok = aglEnable(theVisualGraphicsCore->ctx, AGL_BUFFER_RECT);
if(!ok) {
writeLog("setViewport: unable to enable AGL_BUFFER_RECT");
}
// adjust drawing rectange
ok = aglSetInteger(theVisualGraphicsCore->ctx, AGL_BUFFER_RECT, bufferRect);
if(!ok) {
writeLog("setViewport: aglSetInteger AGL_BUFFER_RECT != ok");
}
ok = aglUpdateContext(theVisualGraphicsCore->ctx);
if(!ok) {
writeLog("setViewport: aglUpdateContext != ok");
}
#endif
#if TARGET_OS_WIN
if (isFullscreen == true) {
glEnable(GL_SCISSOR_TEST);
glScissor(canvasRect.bottomLeftPixel.x, canvasRect.bottomLeftPixel.y, (GLsizei)canvasRect.pixelRect.width, (GLsizei)canvasRect.pixelRect.height);
viewportBottomLeft.x = canvasRect.bottomLeftPixel.x;
viewportBottomLeft.y = canvasRect.bottomLeftPixel.y;
}
#endif
glViewport((GLint)viewportBottomLeft.x, (GLint)viewportBottomLeft.y, (GLsizei)canvasRect.pixelRect.width, (GLsizei)canvasRect.pixelRect.height);
}