mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
404 lines
13 KiB
C++
404 lines
13 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platformWin32/platformWin32.h"
|
|
#include "gfx/gfxCubemap.h"
|
|
#include "gfx/screenshot.h"
|
|
|
|
#include "gfx/GL/gfxGLDevice.h"
|
|
#include "gfx/GL/gfxGLEnumTranslate.h"
|
|
#include "gfx/GL/gfxGLVertexBuffer.h"
|
|
#include "gfx/GL/gfxGLPrimitiveBuffer.h"
|
|
#include "gfx/gl/gfxGLTextureTarget.h"
|
|
#include "gfx/GL/gfxGLWindowTarget.h"
|
|
#include "gfx/GL/gfxGLTextureManager.h"
|
|
#include "gfx/GL/gfxGLTextureObject.h"
|
|
#include "gfx/GL/gfxGLCubemap.h"
|
|
#include "gfx/GL/gfxGLCardProfiler.h"
|
|
#include "windowManager/win32/win32Window.h"
|
|
#include "ggl/Win32/wgl.h"
|
|
|
|
#define GETHWND(x) static_cast<Win32Window*>(x)->getHWND()
|
|
|
|
// yonked from winWindow.cc
|
|
void CreatePixelFormat( PIXELFORMATDESCRIPTOR *pPFD, S32 colorBits, S32 depthBits, S32 stencilBits, bool stereo )
|
|
{
|
|
PIXELFORMATDESCRIPTOR src =
|
|
{
|
|
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
|
|
1, // version number
|
|
PFD_DRAW_TO_WINDOW | // support window
|
|
PFD_SUPPORT_OPENGL | // support OpenGL
|
|
PFD_DOUBLEBUFFER, // double buffered
|
|
PFD_TYPE_RGBA, // RGBA type
|
|
colorBits, // color depth
|
|
0, 0, 0, 0, 0, 0, // color bits ignored
|
|
0, // no alpha buffer
|
|
0, // shift bit ignored
|
|
0, // no accumulation buffer
|
|
0, 0, 0, 0, // accum bits ignored
|
|
depthBits, // z-buffer
|
|
stencilBits, // stencil buffer
|
|
0, // no auxiliary buffer
|
|
PFD_MAIN_PLANE, // main layer
|
|
0, // reserved
|
|
0, 0, 0 // layer masks ignored
|
|
};
|
|
|
|
if ( stereo )
|
|
{
|
|
//ri.Printf( PRINT_ALL, "...attempting to use stereo\n" );
|
|
src.dwFlags |= PFD_STEREO;
|
|
//glConfig.stereoEnabled = true;
|
|
}
|
|
else
|
|
{
|
|
//glConfig.stereoEnabled = qfalse;
|
|
}
|
|
*pPFD = src;
|
|
}
|
|
|
|
extern void loadGLCore();
|
|
extern void loadGLExtensions(void* context);
|
|
|
|
void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
|
|
{
|
|
// GL_ERROR_CHECK();
|
|
WNDCLASS windowclass;
|
|
dMemset( &windowclass, 0, sizeof( WNDCLASS ) );
|
|
|
|
windowclass.lpszClassName = L"GFX-OpenGL";
|
|
windowclass.style = CS_OWNDC;
|
|
windowclass.lpfnWndProc = DefWindowProc;
|
|
windowclass.hInstance = winState.appInstance;
|
|
|
|
if( !RegisterClass( &windowclass ) )
|
|
AssertFatal( false, "Failed to register the window class for the GL test window." );
|
|
|
|
// Now create a window
|
|
HWND hwnd = CreateWindow( L"GFX-OpenGL", L"", WS_POPUP, 0, 0, 640, 480,
|
|
NULL, NULL, winState.appInstance, NULL );
|
|
AssertFatal( hwnd != NULL, "Failed to create the window for the GL test window." );
|
|
|
|
// Create a device context
|
|
HDC tempDC = GetDC( hwnd );
|
|
AssertFatal( tempDC != NULL, "Failed to create device context" );
|
|
|
|
// Create pixel format descriptor...
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
|
|
if( !SetPixelFormat( tempDC, ChoosePixelFormat( tempDC, &pfd ), &pfd ) )
|
|
AssertFatal( false, "I don't know who's responcible for this, but I want caught..." );
|
|
|
|
// Create a rendering context!
|
|
HGLRC tempGLRC = wglCreateContext( tempDC );
|
|
if( !wglMakeCurrent( tempDC, tempGLRC ) )
|
|
AssertFatal( false, "I want them caught and killed." );
|
|
|
|
// Add the GL renderer
|
|
loadGLCore();
|
|
loadGLExtensions(tempDC);
|
|
|
|
GFXAdapter *toAdd = new GFXAdapter;
|
|
toAdd->mIndex = 0;
|
|
|
|
const char* renderer = (const char*) glGetString( GL_RENDERER );
|
|
AssertFatal( renderer != NULL, "GL_RENDERER returned NULL!" );
|
|
|
|
if (renderer)
|
|
{
|
|
dStrcpy(toAdd->mName, renderer);
|
|
dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen);
|
|
}
|
|
else
|
|
dStrcpy(toAdd->mName, "OpenGL");
|
|
|
|
toAdd->mType = OpenGL;
|
|
toAdd->mShaderModel = 0.f;
|
|
toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance;
|
|
|
|
// Enumerate all available resolutions:
|
|
DEVMODE devMode;
|
|
U32 modeNum = 0;
|
|
U32 stillGoing = true;
|
|
while ( stillGoing )
|
|
{
|
|
dMemset( &devMode, 0, sizeof( devMode ) );
|
|
devMode.dmSize = sizeof( devMode );
|
|
|
|
stillGoing = EnumDisplaySettings( NULL, modeNum++, &devMode );
|
|
|
|
if (( devMode.dmPelsWidth >= 480) && (devMode.dmPelsHeight >= 360 )
|
|
&& ( devMode.dmBitsPerPel == 16 || devMode.dmBitsPerPel == 32 ))
|
|
{
|
|
GFXVideoMode vmAdd;
|
|
|
|
vmAdd.bitDepth = devMode.dmBitsPerPel;
|
|
vmAdd.fullScreen = true;
|
|
vmAdd.refreshRate = devMode.dmDisplayFrequency;
|
|
vmAdd.resolution.x = devMode.dmPelsWidth;
|
|
vmAdd.resolution.y = devMode.dmPelsHeight;
|
|
|
|
// Only add this resolution if it is not already in the list:
|
|
bool alreadyInList = false;
|
|
for (Vector<GFXVideoMode>::iterator i = toAdd->mAvailableModes.begin(); i != toAdd->mAvailableModes.end(); i++)
|
|
{
|
|
if (vmAdd == *i)
|
|
{
|
|
alreadyInList = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(alreadyInList)
|
|
continue;
|
|
|
|
toAdd->mAvailableModes.push_back( vmAdd );
|
|
}
|
|
}
|
|
|
|
// Add to the list of available adapters.
|
|
adapterList.push_back(toAdd);
|
|
|
|
// Cleanup our window
|
|
wglMakeCurrent(NULL, NULL);
|
|
wglDeleteContext(tempGLRC);
|
|
ReleaseDC(hwnd, tempDC);
|
|
DestroyWindow(hwnd);
|
|
UnregisterClass(L"GFX-OpenGL", winState.appInstance);
|
|
}
|
|
|
|
void GFXGLDevice::enumerateVideoModes()
|
|
{
|
|
mVideoModes.clear();
|
|
|
|
// Enumerate all available resolutions:
|
|
DEVMODE devMode;
|
|
U32 modeNum = 0;
|
|
U32 stillGoing = true;
|
|
while ( stillGoing )
|
|
{
|
|
dMemset( &devMode, 0, sizeof( devMode ) );
|
|
devMode.dmSize = sizeof( devMode );
|
|
|
|
stillGoing = EnumDisplaySettings( NULL, modeNum++, &devMode );
|
|
|
|
if (( devMode.dmPelsWidth >= 480) && (devMode.dmPelsHeight >= 360 )
|
|
&& ( devMode.dmBitsPerPel == 16 || devMode.dmBitsPerPel == 32 ))
|
|
//( smCanSwitchBitDepth || devMode.dmBitsPerPel == winState.desktopBitsPixel ) )
|
|
{
|
|
GFXVideoMode toAdd;
|
|
|
|
toAdd.bitDepth = devMode.dmBitsPerPel;
|
|
toAdd.fullScreen = false;
|
|
toAdd.refreshRate = devMode.dmDisplayFrequency;
|
|
toAdd.resolution.x = devMode.dmPelsWidth;
|
|
toAdd.resolution.y = devMode.dmPelsHeight;
|
|
|
|
// Only add this resolution if it is not already in the list:
|
|
bool alreadyInList = false;
|
|
for (Vector<GFXVideoMode>::iterator i = mVideoModes.begin(); i != mVideoModes.end(); i++)
|
|
{
|
|
if (toAdd == *i)
|
|
{
|
|
alreadyInList = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( !alreadyInList )
|
|
{
|
|
//Con::printf("Resolution: %dx%d %d bpp %d Refresh rate: %d", toAdd.resolution.x, toAdd.resolution.y, toAdd.bitDepth, toAdd.refreshRate);
|
|
mVideoModes.push_back( toAdd );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
|
|
{
|
|
AssertFatal(window, "GFXGLDevice::init - no window specified, can't init device without a window!");
|
|
AssertFatal(dynamic_cast<Win32Window*>(window), "Invalid window class type!");
|
|
HWND hwnd = GETHWND(window);
|
|
|
|
RECT rect;
|
|
GetClientRect(hwnd, &rect);
|
|
|
|
Point2I resolution;
|
|
resolution.x = rect.right - rect.left;
|
|
resolution.y = rect.bottom - rect.top;
|
|
|
|
// Create a device context
|
|
HDC hdcGL = GetDC( hwnd );
|
|
AssertFatal( hdcGL != NULL, "Failed to create device context" );
|
|
|
|
// Create pixel format descriptor...
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
|
|
if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
|
|
{
|
|
AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." );
|
|
}
|
|
|
|
// Create a rendering context!
|
|
mContext = wglCreateContext( hdcGL );
|
|
if( !wglMakeCurrent( hdcGL, (HGLRC)mContext ) )
|
|
AssertFatal( false , "GFXGLDevice::init - cannot make our context current. Or maybe we can't create it." );
|
|
|
|
loadGLCore();
|
|
loadGLExtensions(hdcGL);
|
|
|
|
wglSwapIntervalEXT(0);
|
|
|
|
// It is very important that extensions be loaded
|
|
// before we call initGLState()
|
|
initGLState();
|
|
|
|
mProjectionMatrix.identity();
|
|
|
|
mInitialized = true;
|
|
deviceInited();
|
|
}
|
|
|
|
bool GFXGLDevice::beginSceneInternal()
|
|
{
|
|
glGetError();
|
|
return true;
|
|
}
|
|
|
|
U32 GFXGLDevice::getTotalVideoMemory()
|
|
{
|
|
// CodeReview [ags 12/21/07] Figure out how to do this.
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
|
|
{
|
|
HDC hdcGL = GetDC(GETHWND(window));
|
|
|
|
if(!mContext)
|
|
{
|
|
init(window->getVideoMode(), window);
|
|
GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
|
|
ggwt->registerResourceWithDevice(this);
|
|
ggwt->mContext = wglCreateContext(hdcGL);
|
|
AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
|
|
|
|
return ggwt;
|
|
}
|
|
|
|
GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
|
|
ggwt->registerResourceWithDevice(this);
|
|
|
|
// Create pixel format descriptor...
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
|
|
if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
|
|
{
|
|
AssertFatal( false, "GFXGLDevice::allocWindowTarget - cannot get the one and only pixel format we check for." );
|
|
}
|
|
|
|
ggwt->mContext = wglCreateContext(hdcGL);
|
|
DWORD w = GetLastError();
|
|
AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
|
|
|
|
wglMakeCurrent(NULL, NULL);
|
|
bool res = wglShareLists((HGLRC)mContext, (HGLRC)ggwt->mContext);
|
|
w = GetLastError();
|
|
|
|
wglMakeCurrent(hdcGL, (HGLRC)ggwt->mContext);
|
|
AssertFatal(res, "GFXGLDevice::allocWindowTarget - wasn't able to share contexts!");
|
|
|
|
return ggwt;
|
|
}
|
|
|
|
void GFXGLDevice::_updateRenderTargets()
|
|
{
|
|
if ( mRTDirty || mCurrentRT->isPendingState() )
|
|
{
|
|
// GL doesn't need to deactivate targets.
|
|
mRTDeactivate = NULL;
|
|
|
|
// NOTE: The render target changes is not really accurate
|
|
// as the GFXTextureTarget supports MRT internally. So when
|
|
// we activate a GFXTarget it could result in multiple calls
|
|
// to SetRenderTarget on the actual device.
|
|
mDeviceStatistics.mRenderTargetChanges++;
|
|
|
|
GFXGLTextureTarget *tex = dynamic_cast<GFXGLTextureTarget*>( mCurrentRT.getPointer() );
|
|
if ( tex )
|
|
{
|
|
tex->applyState();
|
|
tex->makeActive();
|
|
}
|
|
else
|
|
{
|
|
GFXGLWindowTarget *win = dynamic_cast<GFXGLWindowTarget*>( mCurrentRT.getPointer() );
|
|
AssertFatal( win != NULL,
|
|
"GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
|
|
|
|
//DWORD w1 = GetLastError();
|
|
HWND hwnd = GETHWND(win->getWindow());
|
|
HDC winDc = GetDC(hwnd);
|
|
bool res = wglMakeCurrent(winDc,(HGLRC)win->mContext);
|
|
//DWORD w2 = GetLastError();
|
|
AssertFatal(res==true,"GFXGLDevice::setActiveRenderTarget - failed");
|
|
}
|
|
|
|
mRTDirty = false;
|
|
}
|
|
|
|
if ( mViewportDirty )
|
|
{
|
|
glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y );
|
|
mViewportDirty = false;
|
|
}
|
|
}
|
|
|
|
GFXFence* GFXGLDevice::_createPlatformSpecificFence()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GFXGLWindowTarget::makeActive()
|
|
{
|
|
}
|
|
|
|
bool GFXGLWindowTarget::present()
|
|
{
|
|
HWND hwnd = GETHWND(getWindow());
|
|
SwapBuffers(GetDC(hwnd));
|
|
return true;
|
|
}
|
|
|
|
void GFXGLWindowTarget::_teardownCurrentMode()
|
|
{
|
|
}
|
|
|
|
void GFXGLWindowTarget::_setupNewMode()
|
|
{
|
|
}
|