dolphin/Externals/wxWidgets3/src/msw/glcanvas.cpp

901 lines
28 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/glcanvas.cpp
// Purpose: wxGLCanvas, for using OpenGL with wxWidgets under MS Windows
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id: glcanvas.cpp 67681 2011-05-03 16:29:04Z DS $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
#if wxUSE_GLCANVAS
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/app.h"
#endif
#include "wx/msw/private.h"
#include "wx/glcanvas.h"
// from src/msw/window.cpp
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
#ifdef GL_EXT_vertex_array
#define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) name
#else
#define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name)
#endif
// ----------------------------------------------------------------------------
// define possibly missing WGL constants
// ----------------------------------------------------------------------------
#ifndef WGL_ARB_pixel_format
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_NUMBER_OVERLAYS_ARB 0x2008
#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_STEREO_ARB 0x2012
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB 0x2015
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_BLUE_BITS_ARB 0x2019
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_ACCUM_RED_BITS_ARB 0x201E
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_AUX_BUFFERS_ARB 0x2024
#define WGL_FULL_ACCELERATION_ARB 0x2027
#endif
#ifndef WGL_ARB_multisample
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
#endif
// ----------------------------------------------------------------------------
// libraries
// ----------------------------------------------------------------------------
/*
The following two compiler directives are specific to the Microsoft Visual
C++ family of compilers
Fundementally what they do is instruct the linker to use these two libraries
for the resolution of symbols. In essence, this is the equivalent of adding
these two libraries to either the Makefile or project file.
This is NOT a recommended technique, and certainly is unlikely to be used
anywhere else in wxWidgets given it is so specific to not only wxMSW, but
also the VC compiler. However, in the case of opengl support, it's an
applicable technique as opengl is optional in setup.h This code (wrapped by
wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying
setup.h rather than by having to modify either the project or DSP fle.
See MSDN for further information on the exact usage of these commands.
*/
#ifdef _MSC_VER
# pragma comment( lib, "opengl32" )
# pragma comment( lib, "glu32" )
#endif
// ----------------------------------------------------------------------------
// wxGLContext
// ----------------------------------------------------------------------------
IMPLEMENT_CLASS(wxGLContext, wxObject)
wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext* other)
{
m_glContext = wglCreateContext(win->GetHDC());
wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
if ( other )
{
if ( !wglShareLists(other->m_glContext, m_glContext) )
{
wxLogLastError(wxT("wglShareLists"));
}
}
}
wxGLContext::~wxGLContext()
{
// note that it's ok to delete the context even if it's the current one
wglDeleteContext(m_glContext);
}
bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
{
if ( !wglMakeCurrent(win.GetHDC(), m_glContext) )
{
wxLogLastError(wxT("wglMakeCurrent"));
return false;
}
return true;
}
// ============================================================================
// wxGLCanvas
// ============================================================================
IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
#if wxUSE_PALETTE
EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
#endif
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// wxGLCanvas construction
// ----------------------------------------------------------------------------
static int ChoosePixelFormatARB(HDC hdc, const int *attribList);
void wxGLCanvas::Init()
{
#if WXWIN_COMPATIBILITY_2_8
m_glContext = NULL;
#endif
m_hDC = NULL;
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
wxWindowID id,
const int *attribList,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const wxPalette& palette)
{
Init();
(void)Create(parent, id, pos, size, style, name, attribList, palette);
}
wxGLCanvas::~wxGLCanvas()
{
::ReleaseDC(GetHwnd(), m_hDC);
}
// Replaces wxWindow::Create functionality, since we need to use a different
// window class
bool wxGLCanvas::CreateWindow(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
return false;
parent->AddChild(this);
/*
A general rule with OpenGL and Win32 is that any window that will have a
HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
You can find references about this within the knowledge base and most OpenGL
books that contain the wgl function descriptions.
*/
WXDWORD exStyle = 0;
DWORD msflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
msflags |= MSWGetStyle(style, &exStyle);
if ( !MSWCreate(wxApp::GetRegisteredClassName(wxT("wxGLCanvas"), -1, CS_OWNDC),
NULL, pos, size, msflags, exStyle) )
return false;
m_hDC = ::GetDC(GetHwnd());
if ( !m_hDC )
return false;
return true;
}
bool wxGLCanvas::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
// Create the window first: we will either use it as is or use it to query
// for multisampling support and recreate it later with another pixel format
if ( !CreateWindow(parent, id, pos, size, style, name) )
return false;
PIXELFORMATDESCRIPTOR pfd;
const int setupVal = DoSetup(pfd, attribList);
if ( setupVal == 0 ) // PixelFormat error
return false;
if ( setupVal == -1 ) // FSAA requested
{
// now that we have a valid OpenGL window, query it for FSAA support
int pixelFormat;
{
wxGLContext ctx(this);
ctx.SetCurrent(*this);
pixelFormat = ::ChoosePixelFormatARB(m_hDC, attribList);
}
if ( pixelFormat > 0 )
{
// from http://msdn.microsoft.com/en-us/library/ms537559(VS.85).aspx:
//
// Setting the pixel format of a window more than once can
// lead to significant complications for the Window Manager
// and for multithread applications, so it is not allowed. An
// application can only set the pixel format of a window one
// time. Once a window's pixel format is set, it cannot be
// changed.
//
// so we need to delete the old window and create the new one
// destroy Window
::ReleaseDC(GetHwnd(), m_hDC);
m_hDC = 0;
parent->RemoveChild(this);
const HWND hwnd = GetHwnd();
DissociateHandle(); // will do SetHWND(0);
::DestroyWindow(hwnd);
// now recreate with FSAA pixelFormat
if ( !CreateWindow(parent, id, pos, size, style, name) )
return false;
if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
{
wxLogLastError(wxT("SetPixelFormat"));
return false;
}
}
}
#if wxUSE_PALETTE
if ( !SetupPalette(palette) )
return false;
#else // !wxUSE_PALETTE
wxUnusedVar(palette);
#endif // wxUSE_PALETTE/!wxUSE_PALETTE
return true;
}
// ----------------------------------------------------------------------------
// operations
// ----------------------------------------------------------------------------
bool wxGLCanvas::SwapBuffers()
{
if ( !::SwapBuffers(m_hDC) )
{
wxLogLastError(wxT("SwapBuffers"));
return false;
}
return true;
}
// ----------------------------------------------------------------------------
// multi sample support
// ----------------------------------------------------------------------------
// this macro defines a variable of type "name_t" called "name" and initializes
// it with the pointer to WGL function "name" (which may be NULL)
#define wxDEFINE_WGL_FUNC(name) \
name##_t name = (name##_t)wglGetProcAddress(#name)
/* static */
bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
{
static const char *s_extensionsList = (char *)wxUIntPtr(-1);
if ( s_extensionsList == (char *)wxUIntPtr(-1) )
{
typedef const char * (WINAPI *wglGetExtensionsStringARB_t)(HDC hdc);
wxDEFINE_WGL_FUNC(wglGetExtensionsStringARB);
if ( wglGetExtensionsStringARB )
{
s_extensionsList = wglGetExtensionsStringARB(wglGetCurrentDC());
}
else
{
typedef const char * (WINAPI * wglGetExtensionsStringEXT_t)();
wxDEFINE_WGL_FUNC(wglGetExtensionsStringEXT);
if ( wglGetExtensionsStringEXT )
{
s_extensionsList = wglGetExtensionsStringEXT();
}
else
{
s_extensionsList = NULL;
}
}
}
return s_extensionsList && IsExtensionInList(s_extensionsList, extension);
}
// this is a wrapper around wglChoosePixelFormatARB(): returns the pixel format
// index matching the given attributes on success or 0 on failure
static int ChoosePixelFormatARB(HDC hdc, const int *attribList)
{
if ( !wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample") )
return 0;
typedef BOOL (WINAPI * wglChoosePixelFormatARB_t)
(HDC hdc,
const int *piAttribIList,
const FLOAT *pfAttribFList,
UINT nMaxFormats,
int *piFormats,
UINT *nNumFormats
);
wxDEFINE_WGL_FUNC(wglChoosePixelFormatARB);
if ( !wglChoosePixelFormatARB )
return 0; // should not occur if extension is supported
int iAttributes[128];
int dst = 0; // index in iAttributes array
#define ADD_ATTR(attr, value) \
iAttributes[dst++] = attr; iAttributes[dst++] = value
ADD_ATTR( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
ADD_ATTR( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
ADD_ATTR( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
if ( !attribList )
{
ADD_ATTR( WGL_COLOR_BITS_ARB, 24 );
ADD_ATTR( WGL_ALPHA_BITS_ARB, 8 );
ADD_ATTR( WGL_DEPTH_BITS_ARB, 16 );
ADD_ATTR( WGL_STENCIL_BITS_ARB, 0 );
ADD_ATTR( WGL_DOUBLE_BUFFER_ARB, GL_TRUE );
ADD_ATTR( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
ADD_ATTR( WGL_SAMPLES_ARB, 4 );
}
else // have custom attributes
{
#define ADD_ATTR_VALUE(attr) ADD_ATTR(attr, attribList[src++])
int src = 0;
while ( attribList[src] )
{
switch ( attribList[src++] )
{
case WX_GL_RGBA:
ADD_ATTR( WGL_COLOR_BITS_ARB, 24 );
ADD_ATTR( WGL_ALPHA_BITS_ARB, 8 );
break;
case WX_GL_BUFFER_SIZE:
ADD_ATTR_VALUE( WGL_COLOR_BITS_ARB);
break;
case WX_GL_LEVEL:
if ( attribList[src] > 0 )
{
ADD_ATTR( WGL_NUMBER_OVERLAYS_ARB, 1 );
}
else if ( attribList[src] <0 )
{
ADD_ATTR( WGL_NUMBER_UNDERLAYS_ARB, 1 );
}
//else: ignore it
src++; // skip the value in any case
break;
case WX_GL_DOUBLEBUFFER:
ADD_ATTR( WGL_DOUBLE_BUFFER_ARB, GL_TRUE );
break;
case WX_GL_STEREO:
ADD_ATTR( WGL_STEREO_ARB, GL_TRUE );
break;
case WX_GL_AUX_BUFFERS:
ADD_ATTR_VALUE( WGL_AUX_BUFFERS_ARB );
break;
case WX_GL_MIN_RED:
ADD_ATTR_VALUE( WGL_RED_BITS_ARB );
break;
case WX_GL_MIN_GREEN:
ADD_ATTR_VALUE( WGL_GREEN_BITS_ARB );
break;
case WX_GL_MIN_BLUE:
ADD_ATTR_VALUE( WGL_BLUE_BITS_ARB );
break;
case WX_GL_MIN_ALPHA:
ADD_ATTR_VALUE( WGL_ALPHA_BITS_ARB );
break;
case WX_GL_DEPTH_SIZE:
ADD_ATTR_VALUE( WGL_DEPTH_BITS_ARB );
break;
case WX_GL_STENCIL_SIZE:
ADD_ATTR_VALUE( WGL_STENCIL_BITS_ARB );
break;
case WX_GL_MIN_ACCUM_RED:
ADD_ATTR_VALUE( WGL_ACCUM_RED_BITS_ARB );
break;
case WX_GL_MIN_ACCUM_GREEN:
ADD_ATTR_VALUE( WGL_ACCUM_GREEN_BITS_ARB );
break;
case WX_GL_MIN_ACCUM_BLUE:
ADD_ATTR_VALUE( WGL_ACCUM_BLUE_BITS_ARB );
break;
case WX_GL_MIN_ACCUM_ALPHA:
ADD_ATTR_VALUE( WGL_ACCUM_ALPHA_BITS_ARB );
break;
case WX_GL_SAMPLE_BUFFERS:
ADD_ATTR_VALUE( WGL_SAMPLE_BUFFERS_ARB );
break;
case WX_GL_SAMPLES:
ADD_ATTR_VALUE( WGL_SAMPLES_ARB );
break;
}
}
#undef ADD_ATTR_VALUE
}
#undef ADD_ATTR
iAttributes[dst++] = 0;
int pf;
UINT numFormats = 0;
if ( !wglChoosePixelFormatARB(hdc, iAttributes, NULL, 1, &pf, &numFormats) )
{
wxLogLastError(wxT("wglChoosePixelFormatARB"));
return 0;
}
// Although TRUE is returned if no matching formats are found (see
// http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt), pf is
// not initialized in this case so we need to check for numFormats being
// not 0 explicitly (however this is not an error so don't call
// wxLogLastError() here).
if ( !numFormats )
pf = 0;
return pf;
}
// ----------------------------------------------------------------------------
// pixel format stuff
// ----------------------------------------------------------------------------
// returns true if pfd was adjusted accordingly to attributes provided, false
// if there is an error with attributes or -1 if the attributes indicate
// features not supported by ChoosePixelFormat() at all (currently only multi
// sampling)
static int
AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList)
{
if ( !attribList )
return 1;
// remove default attributes
pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_COLORINDEX;
bool requestFSAA = false;
for ( int arg = 0; attribList[arg]; )
{
switch ( attribList[arg++] )
{
case WX_GL_RGBA:
pfd.iPixelType = PFD_TYPE_RGBA;
break;
case WX_GL_BUFFER_SIZE:
pfd.cColorBits = attribList[arg++];
break;
case WX_GL_LEVEL:
// this member looks like it may be obsolete
if ( attribList[arg] > 0 )
pfd.iLayerType = PFD_OVERLAY_PLANE;
else if ( attribList[arg] < 0 )
pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
else
pfd.iLayerType = PFD_MAIN_PLANE;
arg++;
break;
case WX_GL_DOUBLEBUFFER:
pfd.dwFlags |= PFD_DOUBLEBUFFER;
break;
case WX_GL_STEREO:
pfd.dwFlags |= PFD_STEREO;
break;
case WX_GL_AUX_BUFFERS:
pfd.cAuxBuffers = attribList[arg++];
break;
case WX_GL_MIN_RED:
pfd.cColorBits += (pfd.cRedBits = attribList[arg++]);
break;
case WX_GL_MIN_GREEN:
pfd.cColorBits += (pfd.cGreenBits = attribList[arg++]);
break;
case WX_GL_MIN_BLUE:
pfd.cColorBits += (pfd.cBlueBits = attribList[arg++]);
break;
case WX_GL_MIN_ALPHA:
// doesn't count in cColorBits
pfd.cAlphaBits = attribList[arg++];
break;
case WX_GL_DEPTH_SIZE:
pfd.cDepthBits = attribList[arg++];
break;
case WX_GL_STENCIL_SIZE:
pfd.cStencilBits = attribList[arg++];
break;
case WX_GL_MIN_ACCUM_RED:
pfd.cAccumBits += (pfd.cAccumRedBits = attribList[arg++]);
break;
case WX_GL_MIN_ACCUM_GREEN:
pfd.cAccumBits += (pfd.cAccumGreenBits = attribList[arg++]);
break;
case WX_GL_MIN_ACCUM_BLUE:
pfd.cAccumBits += (pfd.cAccumBlueBits = attribList[arg++]);
break;
case WX_GL_MIN_ACCUM_ALPHA:
pfd.cAccumBits += (pfd.cAccumAlphaBits = attribList[arg++]);
break;
case WX_GL_SAMPLE_BUFFERS:
case WX_GL_SAMPLES:
// There is no support for multisample when using PIXELFORMATDESCRIPTOR
requestFSAA = true; // Remember that multi sample is requested.
arg++; // will call ChoosePixelFormatARB() later
break;
}
}
return requestFSAA ? -1 : 1;
}
/* static */
int
wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc,
const int *attribList,
PIXELFORMATDESCRIPTOR *ppfd)
{
// default neutral pixel format
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_DOUBLEBUFFER, // use double-buffering by default
PFD_TYPE_RGBA, // default pixel type
0, // preferred color depth (don't care)
0, 0, 0, 0, 0, 0, // color bits and shift bits (ignored)
0, 0, // alpha bits and shift (ignored)
0, // accumulation total bits
0, 0, 0, 0, // accumulator RGBA bits (not used)
16, // depth buffer
0, // no stencil buffer
0, // no auxiliary buffers
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0, // no layer, visible, damage masks
};
if ( !ppfd )
ppfd = &pfd;
else
*ppfd = pfd;
// adjust the PFD using the provided attributes and also check if we can
// use PIXELFORMATDESCRIPTOR at all: if multisampling is requested, we
// can't as it's not supported by ChoosePixelFormat()
switch ( AdjustPFDForAttributes(*ppfd, attribList) )
{
case 1:
return ::ChoosePixelFormat(hdc, ppfd);
default:
wxFAIL_MSG( "unexpected AdjustPFDForAttributes() return value" );
// fall through
case 0:
// error in attributes
return 0;
case -1:
// requestFSAA == true, will continue as normal
// in order to query later for a FSAA pixelformat
return -1;
}
}
/* static */
bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
{
// We need a device context to test the pixel format, so get one
// for the root window.
return wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) > 0;
}
int wxGLCanvas::DoSetup(PIXELFORMATDESCRIPTOR &pfd, const int *attribList)
{
int pixelFormat = ChooseMatchingPixelFormat(m_hDC, attribList, &pfd);
const bool requestFSAA = pixelFormat == -1;
if ( requestFSAA )
pixelFormat = ::ChoosePixelFormat(m_hDC, &pfd);
if ( !pixelFormat )
{
wxLogLastError(wxT("ChoosePixelFormat"));
return 0;
}
if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
{
wxLogLastError(wxT("SetPixelFormat"));
return 0;
}
return requestFSAA ? -1 : 1;
}
// ----------------------------------------------------------------------------
// palette stuff
// ----------------------------------------------------------------------------
#if wxUSE_PALETTE
bool wxGLCanvas::SetupPalette(const wxPalette& palette)
{
const int pixelFormat = ::GetPixelFormat(m_hDC);
if ( !pixelFormat )
{
wxLogLastError(wxT("GetPixelFormat"));
return false;
}
PIXELFORMATDESCRIPTOR pfd;
if ( !::DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd) )
{
wxLogLastError(wxT("DescribePixelFormat"));
return false;
}
if ( !(pfd.dwFlags & PFD_NEED_PALETTE) )
return true;
m_palette = palette;
if ( !m_palette.IsOk() )
{
m_palette = CreateDefaultPalette();
if ( !m_palette.IsOk() )
return false;
}
if ( !::SelectPalette(m_hDC, GetHpaletteOf(m_palette), FALSE) )
{
wxLogLastError(wxT("SelectPalette"));
return false;
}
if ( ::RealizePalette(m_hDC) == GDI_ERROR )
{
wxLogLastError(wxT("RealizePalette"));
return false;
}
return true;
}
wxPalette wxGLCanvas::CreateDefaultPalette()
{
PIXELFORMATDESCRIPTOR pfd;
int paletteSize;
int pixelFormat = GetPixelFormat(m_hDC);
DescribePixelFormat(m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
paletteSize = 1 << pfd.cColorBits;
LOGPALETTE* pPal =
(LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
pPal->palVersion = 0x300;
pPal->palNumEntries = (WORD)paletteSize;
/* build a simple RGB color palette */
int redMask = (1 << pfd.cRedBits) - 1;
int greenMask = (1 << pfd.cGreenBits) - 1;
int blueMask = (1 << pfd.cBlueBits) - 1;
for (int i=0; i<paletteSize; ++i)
{
pPal->palPalEntry[i].peRed =
(BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
pPal->palPalEntry[i].peGreen =
(BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
pPal->palPalEntry[i].peBlue =
(BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
pPal->palPalEntry[i].peFlags = 0;
}
HPALETTE hPalette = CreatePalette(pPal);
free(pPal);
wxPalette palette;
palette.SetHPALETTE((WXHPALETTE) hPalette);
return palette;
}
void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
{
/* realize palette if this is the current window */
if ( GetPalette()->IsOk() ) {
::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
::RealizePalette(GetHDC());
Refresh();
event.SetPaletteRealized(true);
}
else
event.SetPaletteRealized(false);
}
void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
{
/* realize palette if this is *not* the current window */
if ( GetPalette() &&
GetPalette()->IsOk() && (this != event.GetChangedWindow()) )
{
::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
::RealizePalette(GetHDC());
Refresh();
}
}
#endif // wxUSE_PALETTE
// ----------------------------------------------------------------------------
// deprecated wxGLCanvas methods using implicit wxGLContext
// ----------------------------------------------------------------------------
// deprecated constructors creating an implicit m_glContext
#if WXWIN_COMPATIBILITY_2_8
wxGLCanvas::wxGLCanvas(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
Init();
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLContext *shared,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
Init();
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this, shared);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLCanvas *shared,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
Init();
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
}
#endif // WXWIN_COMPATIBILITY_2_8
// ----------------------------------------------------------------------------
// wxGLApp
// ----------------------------------------------------------------------------
bool wxGLApp::InitGLVisual(const int *attribList)
{
if ( !wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) )
{
wxLogError(_("Failed to initialize OpenGL"));
return false;
}
return true;
}
#endif // wxUSE_GLCANVAS