Patch [#20588] Adding multisample support to Win32 Ghost - by Mitchell Stokes (Moguri)

Note: AA is still disabled due to AA creating problems for selection tools. If you must, set AA to 2 or 4 in wm_window.c where the GHOST window is created (line 317).
This commit is contained in:
Nathan Letwory 2010-01-13 19:02:13 +00:00
parent ef5ab2b8e9
commit e594a8739b
5 changed files with 242 additions and 39 deletions

@ -24,7 +24,7 @@
# #
# ***** END GPL LICENSE BLOCK ***** # ***** END GPL LICENSE BLOCK *****
SET(INC . ../string) SET(INC . ../string ../../extern/glew/include)
FILE(GLOB SRC intern/*.cpp intern/*.mm) FILE(GLOB SRC intern/*.cpp intern/*.mm)

@ -57,7 +57,7 @@ else:
if env['BF_GHOST_DEBUG']: if env['BF_GHOST_DEBUG']:
defs.append('BF_GHOST_DEBUG') defs.append('BF_GHOST_DEBUG')
incs = '. ../string ' + env['BF_OPENGL_INC'] incs = '. ../string #extern/glew/include ' + env['BF_OPENGL_INC']
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs incs = env['BF_WINTAB_INC'] + ' ' + incs
env.BlenderLib ('bf_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] ) env.BlenderLib ('bf_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )

@ -193,7 +193,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow )
{ {
GHOST_Window* window = 0; GHOST_Window* window = 0;
window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual); window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
if (window) { if (window) {
if (window->getValid()) { if (window->getValid()) {
// Store the pointer to the window // Store the pointer to the window
@ -202,8 +202,18 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
// } // }
} }
else { else {
// An invalid window could be one that was used to test for AA
GHOST_Window *other_window = ((GHOST_WindowWin32*)window)->getNextWindow();
delete window; delete window;
window = 0; window = 0;
// If another window is found, let the wm know about that one, but not the old one
if (other_window)
{
m_windowManager->addWindow(other_window);
window = other_window;
}
} }
} }
return window; return window;

@ -42,7 +42,10 @@
#include "GHOST_WindowWin32.h" #include "GHOST_WindowWin32.h"
#include "GHOST_SystemWin32.h" #include "GHOST_SystemWin32.h"
#include "GHOST_DropTargetWin32.h" #include "GHOST_DropTargetWin32.h"
#include <GL/gl.h>
// Need glew for some defines
#include <GL/glew.h>
#include <GL/wglew.h>
#include <math.h> #include <math.h>
// MSVC6 still doesn't define M_PI // MSVC6 still doesn't define M_PI
@ -50,6 +53,10 @@
#define M_PI 3.1415926536 #define M_PI 3.1415926536
#endif #endif
// Some more multisample defines
#define WGL_SAMPLE_BUFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
// win64 doesn't define GWL_USERDATA // win64 doesn't define GWL_USERDATA
#ifdef WIN32 #ifdef WIN32
#ifndef GWL_USERDATA #ifndef GWL_USERDATA
@ -106,7 +113,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(
GHOST_TWindowState state, GHOST_TWindowState state,
GHOST_TDrawingContextType type, GHOST_TDrawingContextType type,
const bool stereoVisual, const bool stereoVisual,
const GHOST_TUns16 numOfAASamples) const GHOST_TUns16 numOfAASamples,
GHOST_TSuccess msEnabled,
int msPixelFormat)
: :
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone,
stereoVisual,numOfAASamples), stereoVisual,numOfAASamples),
@ -119,7 +128,18 @@ GHOST_WindowWin32::GHOST_WindowWin32(
m_wintab(NULL), m_wintab(NULL),
m_tabletData(NULL), m_tabletData(NULL),
m_tablet(0), m_tablet(0),
m_maxPressure(0) m_maxPressure(0),
m_multisample(numOfAASamples),
m_multisampleEnabled(msEnabled),
m_msPixelFormat(msPixelFormat),
//For recreation
m_title(title),
m_left(left),
m_top(top),
m_width(width),
m_height(height),
m_stereo(stereoVisual),
m_nextWindow(NULL)
{ {
if (state != GHOST_kWindowStateFullScreen) { if (state != GHOST_kWindowStateFullScreen) {
RECT rect; RECT rect;
@ -195,10 +215,20 @@ GHOST_WindowWin32::GHOST_WindowWin32(
nCmdShow = SW_SHOWNORMAL; nCmdShow = SW_SHOWNORMAL;
break; break;
} }
setDrawingContextType(type); GHOST_TSuccess success;
::ShowWindow(m_hWnd, nCmdShow); success = setDrawingContextType(type);
// Force an initial paint of the window
::UpdateWindow(m_hWnd); if (success)
{
::ShowWindow(m_hWnd, nCmdShow);
// Force an initial paint of the window
::UpdateWindow(m_hWnd);
}
else
{
//invalidate the window
m_hWnd = 0;
}
} }
m_wintab = ::LoadLibrary("Wintab32.dll"); m_wintab = ::LoadLibrary("Wintab32.dll");
@ -277,6 +307,8 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_customCursor = NULL; m_customCursor = NULL;
} }
m_multisampleEnabled = GHOST_kFailure;
m_multisample = 0;
setDrawingContextType(GHOST_kDrawingContextTypeNone); setDrawingContextType(GHOST_kDrawingContextTypeNone);
if (m_hDC) { if (m_hDC) {
::ReleaseDC(m_hWnd, m_hDC); ::ReleaseDC(m_hWnd, m_hDC);
@ -289,6 +321,11 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
} }
} }
GHOST_Window *GHOST_WindowWin32::getNextWindow()
{
return m_nextWindow;
}
bool GHOST_WindowWin32::getValid() const bool GHOST_WindowWin32::getValid() const
{ {
return m_hWnd != 0; return m_hWnd != 0;
@ -516,6 +553,69 @@ GHOST_TSuccess GHOST_WindowWin32::invalidate()
return success; return success;
} }
GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd)
{
int pixelFormat;
bool success;
UINT numFormats;
HDC hDC = GetDC(getHWND());
float fAttributes[] = {0, 0};
// The attributes to look for
int iAttributes[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, pfd.cColorBits,
WGL_DEPTH_BITS_ARB, pfd.cDepthBits,
WGL_STENCIL_BITS_ARB, pfd.cStencilBits,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, m_multisample,
0, 0
};
// Get the function
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
if (!wglChoosePixelFormatARB)
{
m_multisampleEnabled = GHOST_kFailure;
return GHOST_kFailure;
}
// See if the format is valid
success = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
if (success && numFormats >= 1)
{
m_multisampleEnabled = GHOST_kSuccess;
m_msPixelFormat = pixelFormat;
return GHOST_kSuccess;
}
else
{
// See if any formats are supported
while (!success && iAttributes[19] != 0)
{
iAttributes[19] /= 2;
success = wglChoosePixelFormatARB(m_hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
if (success && numFormats >= 1)
{
m_multisampleEnabled = GHOST_kSuccess;
m_msPixelFormat = pixelFormat;
return GHOST_kSuccess;
}
success = GHOST_kFailure;
}
}
// No available pixel format...
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type) GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type)
{ {
@ -523,36 +623,101 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp
switch (type) { switch (type) {
case GHOST_kDrawingContextTypeOpenGL: case GHOST_kDrawingContextTypeOpenGL:
{ {
if(m_stereoVisual) // If this window has multisample enabled, use the supplied format
sPreferredFormat.dwFlags |= PFD_STEREO; if (m_multisampleEnabled)
{
// Attempt to match device context pixel format to the preferred format if (SetPixelFormat(m_hDC, m_msPixelFormat, &sPreferredFormat)==FALSE)
int iPixelFormat = EnumPixelFormats(m_hDC); {
if (iPixelFormat == 0) { success = GHOST_kFailure;
success = GHOST_kFailure; break;
break;
}
if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
success = GHOST_kFailure;
break;
}
// For debugging only: retrieve the pixel format chosen
PIXELFORMATDESCRIPTOR preferredFormat;
::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
// Create the context
m_hGlRc = ::wglCreateContext(m_hDC);
if (m_hGlRc) {
if (s_firsthGLRc) {
wglShareLists(s_firsthGLRc, m_hGlRc);
} else {
s_firsthGLRc = m_hGlRc;
} }
success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; // Create the context
m_hGlRc = ::wglCreateContext(m_hDC);
if (m_hGlRc) {
if (s_firsthGLRc) {
wglShareLists(s_firsthGLRc, m_hGlRc);
} else {
s_firsthGLRc = m_hGlRc;
}
success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
}
else {
printf("Failed to get a context....\n");
success = GHOST_kFailure;
}
} }
else { else
success = GHOST_kFailure; {
if(m_stereoVisual)
sPreferredFormat.dwFlags |= PFD_STEREO;
// Attempt to match device context pixel format to the preferred format
int iPixelFormat = EnumPixelFormats(m_hDC);
if (iPixelFormat == 0) {
success = GHOST_kFailure;
break;
}
if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
success = GHOST_kFailure;
break;
}
// For debugging only: retrieve the pixel format chosen
PIXELFORMATDESCRIPTOR preferredFormat;
::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
// Create the context
m_hGlRc = ::wglCreateContext(m_hDC);
if (m_hGlRc) {
if (s_firsthGLRc) {
wglShareLists(s_firsthGLRc, m_hGlRc);
} else {
s_firsthGLRc = m_hGlRc;
}
success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
}
else {
printf("Failed to get a context....\n");
success = GHOST_kFailure;
}
// Attempt to enable multisample
if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled)
{
success = initMultisample(preferredFormat);
if (success)
{
// Make sure we don't screw up the context
m_drawingContextType = GHOST_kDrawingContextTypeOpenGL;
removeDrawingContext();
// Create a new window
GHOST_TWindowState new_state = getState();
m_nextWindow = new GHOST_WindowWin32((GHOST_SystemWin32*)GHOST_ISystem::getSystem(),
m_title,
m_left,
m_top,
m_width,
m_height,
new_state,
type,
m_stereo,
m_multisample,
m_multisampleEnabled,
m_msPixelFormat);
// Return failure so we can trash this window.
success = GHOST_kFailure;
break;
}
}
} }
} }
break; break;
@ -566,7 +731,6 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp
return success; return success;
} }
GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext() GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext()
{ {
GHOST_TSuccess success; GHOST_TSuccess success;

@ -87,7 +87,9 @@ public:
GHOST_TWindowState state, GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false, const bool stereoVisual = false,
const GHOST_TUns16 numOfAASamples = 0 const GHOST_TUns16 numOfAASamples = 0,
GHOST_TSuccess msEnabled = GHOST_kFailure,
int msPixelFormat = 0
); );
/** /**
@ -96,6 +98,13 @@ public:
*/ */
virtual ~GHOST_WindowWin32(); virtual ~GHOST_WindowWin32();
/**
* Returns the window to replace this one if it's getting replaced
* @return The window replacing this one.
*/
GHOST_Window *getNextWindow();
/** /**
* Returns indication as to whether the window is valid. * Returns indication as to whether the window is valid.
* @return The validity of the window. * @return The validity of the window.
@ -243,6 +252,8 @@ public:
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
protected: protected:
GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);
/** /**
* Tries to install a rendering context in this window. * Tries to install a rendering context in this window.
* @param type The type of rendering context installed. * @param type The type of rendering context installed.
@ -325,7 +336,25 @@ protected:
LONG m_maxPressure; LONG m_maxPressure;
LONG m_maxAzimuth, m_maxAltitude; LONG m_maxAzimuth, m_maxAltitude;
/** Preferred number of samples */
GHOST_TUns16 m_multisample;
/** Check if multisample is supported */
GHOST_TSuccess m_multisampleEnabled;
/** The pixelFormat to use for multisample */
int m_msPixelFormat;
/** We need to following to recreate the window */
const STR_String& m_title;
GHOST_TInt32 m_left;
GHOST_TInt32 m_top;
GHOST_TUns32 m_width;
GHOST_TUns32 m_height;
bool m_stereo;
/** The GHOST_System passes this to wm if this window is being replaced */
GHOST_Window *m_nextWindow;
}; };
#endif // _GHOST_WINDOW_WIN32_H_ #endif // _GHOST_WINDOW_WIN32_H_