2004-06-21 15:35:05 +02:00
/*
2009-11-07 20:28:18 +01:00
* File : indirect . c
* Purpose : A GLX implementation that uses Windows OpenGL library
*
* Authors : Alexander Gottwald
* Jon TURNEY
*
* Copyright ( c ) Jon TURNEY 2009
* Copyright ( c ) Alexander Gottwald 2004
2004-06-21 15:35:05 +02:00
*
* Portions of this file are copied from GL / apple / indirect . c ,
* which contains the following copyright :
2009-11-07 20:28:18 +01:00
*
* Copyright ( c ) 2007 , 2008 , 2009 Apple Inc .
* Copyright ( c ) 2004 Torrey T . Lyons . All Rights Reserved .
2004-06-21 15:35:05 +02:00
* Copyright ( c ) 2002 Greg Parker . All Rights Reserved .
*
2009-11-07 20:28:18 +01:00
* Portions of this file are copied from Mesa ' s xf86glx . c ,
2004-06-21 15:35:05 +02:00
* which contains the following copyright :
*
* Copyright 1998 - 1999 Precision Insight , Inc . , Cedar Park , Texas .
* All Rights Reserved .
*
2009-11-07 20:28:18 +01:00
*
2004-06-21 15:35:05 +02:00
* 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 ABOVE LISTED COPYRIGHT HOLDER ( S ) 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 .
*/
2009-11-07 20:28:18 +01:00
/*
TODO :
- hook up remaining unimplemented extensions
- research what guarantees glXWaitX , glXWaitGL are supposed to offer , and implement then
using GdiFlush and / or glFinish
- pbuffer clobbering : we don ' t get async notification , but can we arrange to emit the
event when we notice it ' s been clobbered ? at the very least , check if it ' s been clobbered
before using it ?
2010-11-02 12:38:53 +01:00
- XGetImage ( ) doesn ' t work on pixmaps ; need to do more work to make the format and location
of the native pixmap compatible
- implement GLX_EXT_texture_from_pixmap in terms of WGL_ARB_render_texture
( not quite straightforward as we will have to create a pbuffer and copy the pixmap texture
into it )
*/
/*
Assumptions :
- the __GLXConfig * we get handed back ones we are made ( so we can extend the structure
with privates ) and never get created inside the GLX core
2009-11-07 20:28:18 +01:00
*/
/*
MSDN clarifications :
It says SetPixelFormat ( ) ' s PIXELFORMATDESCRIPTOR pointer argument has no effect
except on metafiles , this seems to mean that as it ' s ok to supply NULL if the DC
is not for a metafile
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
wglMakeCurrent ignores the hdc if hglrc is NULL , so wglMakeCurrent ( NULL , NULL )
is used to make no context current
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
*/
# ifdef HAVE_XWIN_CONFIG_H
# include <xwin-config.h>
2005-07-03 09:02:09 +02:00
# endif
2004-06-21 15:35:05 +02:00
# include "glwindows.h"
2009-11-07 20:28:18 +01:00
# include <glx/glxserver.h>
# include <glx/glxutil.h>
# include <glx/extension_string.h>
# include <GL/glxtokens.h>
2004-06-21 15:35:05 +02:00
2004-11-15 16:06:51 +01:00
# include <winpriv.h>
2009-11-07 20:28:18 +01:00
# include <wgl_ext_api.h>
# define NUM_ELEMENTS(x) (sizeof(x) / sizeof(x[1]))
2010-10-11 17:21:40 +02:00
/* Not yet in w32api */
# ifndef PFD_SUPPORT_DIRECTDRAW
# define PFD_SUPPORT_DIRECTDRAW 0x00002000
# endif
# ifndef PFD_DIRECT3D_ACCELERATED
# define PFD_DIRECT3D_ACCELERATED 0x00004000
# endif
# ifndef PFD_SUPPORT_COMPOSITION
# define PFD_SUPPORT_COMPOSITION 0x00008000
# endif
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* structure definitions
*/
typedef struct __GLXWinContext __GLXWinContext ;
typedef struct __GLXWinDrawable __GLXWinDrawable ;
typedef struct __GLXWinScreen glxWinScreen ;
typedef struct __GLXWinConfig GLXWinConfig ;
struct __GLXWinContext {
__GLXcontext base ;
HGLRC ctx ; /* Windows GL Context */
__GLXWinContext * shareContext ; /* Context with which we will share display lists and textures */
HWND hwnd ; /* For detecting when HWND has changed */
} ;
struct __GLXWinDrawable
{
__GLXdrawable base ;
__GLXWinContext * drawContext ;
__GLXWinContext * readContext ;
/* If this drawable is GLX_DRAWABLE_PBUFFER */
HPBUFFERARB hPbuffer ;
/* If this drawable is GLX_DRAWABLE_PIXMAP */
HDC dibDC ;
HBITMAP hDIB ;
HBITMAP hOldDIB ; /* original DIB for DC */
void * pOldBits ; /* original pBits for this drawable's pixmap */
} ;
struct __GLXWinScreen
{
__GLXscreen base ;
/* Supported GLX extensions */
unsigned char glx_enable_bits [ __GLX_EXT_BYTES ] ;
Bool has_WGL_ARB_multisample ;
Bool has_WGL_ARB_pixel_format ;
Bool has_WGL_ARB_pbuffer ;
Bool has_WGL_ARB_render_texture ;
/* wrapped screen functions */
RealizeWindowProcPtr RealizeWindow ;
UnrealizeWindowProcPtr UnrealizeWindow ;
CopyWindowProcPtr CopyWindow ;
} ;
struct __GLXWinConfig
{
__GLXconfig base ;
int pixelFormatIndex ;
} ;
/* ---------------------------------------------------------------------- */
/*
* Various debug helpers
*/
2004-06-21 15:35:05 +02:00
# define GLWIN_DEBUG_HWND(hwnd) \
2009-11-07 20:28:18 +01:00
if ( glxWinDebugSettings . dumpHWND ) { \
2004-06-21 15:35:05 +02:00
char buffer [ 1024 ] ; \
if ( GetWindowText ( hwnd , buffer , sizeof ( buffer ) ) = = 0 ) * buffer = 0 ; \
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " Got HWND %p for window '%s' " , hwnd , buffer ) ; \
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
glxWinDebugSettingsRec glxWinDebugSettings = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
static void glxWinInitDebugSettings ( void )
2004-06-21 15:35:05 +02:00
{
char * envptr ;
envptr = getenv ( " GLWIN_ENABLE_DEBUG " ) ;
if ( envptr ! = NULL )
2009-11-07 20:28:18 +01:00
glxWinDebugSettings . enableDebug = ( atoi ( envptr ) = = 1 ) ;
2004-06-21 15:35:05 +02:00
2005-03-01 19:58:17 +01:00
envptr = getenv ( " GLWIN_ENABLE_TRACE " ) ;
if ( envptr ! = NULL )
2009-11-07 20:28:18 +01:00
glxWinDebugSettings . enableTrace = ( atoi ( envptr ) = = 1 ) ;
2005-03-01 19:58:17 +01:00
2004-06-21 15:35:05 +02:00
envptr = getenv ( " GLWIN_DUMP_PFD " ) ;
if ( envptr ! = NULL )
2009-11-07 20:28:18 +01:00
glxWinDebugSettings . dumpPFD = ( atoi ( envptr ) = = 1 ) ;
2004-06-21 15:35:05 +02:00
envptr = getenv ( " GLWIN_DUMP_HWND " ) ;
if ( envptr ! = NULL )
2009-11-07 20:28:18 +01:00
glxWinDebugSettings . dumpHWND = ( atoi ( envptr ) = = 1 ) ;
2004-06-21 15:35:05 +02:00
envptr = getenv ( " GLWIN_DUMP_DC " ) ;
if ( envptr ! = NULL )
2009-11-07 20:28:18 +01:00
glxWinDebugSettings . dumpDC = ( atoi ( envptr ) = = 1 ) ;
envptr = getenv ( " GLWIN_ENABLE_GLCALL_TRACE " ) ;
if ( envptr ! = NULL )
glxWinDebugSettings . enableGLcallTrace = ( atoi ( envptr ) = = 1 ) ;
envptr = getenv ( " GLWIN_ENABLE_WGLCALL_TRACE " ) ;
if ( envptr ! = NULL )
glxWinDebugSettings . enableWGLcallTrace = ( atoi ( envptr ) = = 1 ) ;
envptr = getenv ( " GLWIN_DEBUG_ALL " ) ;
if ( envptr ! = NULL )
{
glxWinDebugSettings . enableDebug = 1 ;
glxWinDebugSettings . enableTrace = 1 ;
glxWinDebugSettings . dumpPFD = 1 ;
glxWinDebugSettings . dumpHWND = 1 ;
glxWinDebugSettings . dumpDC = 1 ;
glxWinDebugSettings . enableGLcallTrace = 1 ;
glxWinDebugSettings . enableWGLcallTrace = 1 ;
}
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static
const char * glxWinErrorMessage ( void )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
static char errorbuffer [ 1024 ] ;
2010-10-30 18:22:33 +02:00
unsigned int last_error = GetLastError ( ) ;
2009-11-07 20:28:18 +01:00
if ( ! FormatMessage (
2010-10-30 18:22:33 +02:00
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK ,
2009-11-07 20:28:18 +01:00
NULL ,
2010-10-30 18:22:33 +02:00
last_error ,
0 ,
2009-11-07 20:28:18 +01:00
( LPTSTR ) & errorbuffer ,
sizeof ( errorbuffer ) ,
NULL ) )
2004-06-21 15:35:05 +02:00
{
2010-10-30 18:22:33 +02:00
snprintf ( errorbuffer , sizeof ( errorbuffer ) , " Unknown error " ) ;
2004-06-21 15:35:05 +02:00
}
2010-10-30 18:22:33 +02:00
if ( ( errorbuffer [ strlen ( errorbuffer ) - 1 ] = = ' \n ' ) | | ( errorbuffer [ strlen ( errorbuffer ) - 1 ] = = ' \r ' ) )
2009-11-07 20:28:18 +01:00
errorbuffer [ strlen ( errorbuffer ) - 1 ] = 0 ;
2004-06-21 15:35:05 +02:00
2010-10-30 18:22:33 +02:00
sprintf ( errorbuffer + strlen ( errorbuffer ) , " (%08x) " , last_error ) ;
2009-11-07 20:28:18 +01:00
return errorbuffer ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
static void pfdOut ( const PIXELFORMATDESCRIPTOR * pfd ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
# define DUMP_PFD_FLAG(flag) \
if ( pfd - > dwFlags & flag ) { \
ErrorF ( " %s%s " , pipesym , # flag ) ; \
pipesym = " | " ; \
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static void pfdOut ( const PIXELFORMATDESCRIPTOR * pfd )
{
const char * pipesym = " " ; /* will be set after first flag dump */
ErrorF ( " PIXELFORMATDESCRIPTOR: \n " ) ;
ErrorF ( " nSize = %u \n " , pfd - > nSize ) ;
ErrorF ( " nVersion = %u \n " , pfd - > nVersion ) ;
ErrorF ( " dwFlags = %lu = { " , pfd - > dwFlags ) ;
DUMP_PFD_FLAG ( PFD_DOUBLEBUFFER ) ;
DUMP_PFD_FLAG ( PFD_STEREO ) ;
DUMP_PFD_FLAG ( PFD_DRAW_TO_WINDOW ) ;
DUMP_PFD_FLAG ( PFD_DRAW_TO_BITMAP ) ;
DUMP_PFD_FLAG ( PFD_SUPPORT_GDI ) ;
DUMP_PFD_FLAG ( PFD_SUPPORT_OPENGL ) ;
DUMP_PFD_FLAG ( PFD_GENERIC_FORMAT ) ;
DUMP_PFD_FLAG ( PFD_NEED_PALETTE ) ;
DUMP_PFD_FLAG ( PFD_NEED_SYSTEM_PALETTE ) ;
DUMP_PFD_FLAG ( PFD_SWAP_EXCHANGE ) ;
DUMP_PFD_FLAG ( PFD_SWAP_COPY ) ;
DUMP_PFD_FLAG ( PFD_SWAP_LAYER_BUFFERS ) ;
DUMP_PFD_FLAG ( PFD_GENERIC_ACCELERATED ) ;
2010-10-11 17:21:40 +02:00
DUMP_PFD_FLAG ( PFD_SUPPORT_DIRECTDRAW ) ;
DUMP_PFD_FLAG ( PFD_DIRECT3D_ACCELERATED ) ;
DUMP_PFD_FLAG ( PFD_SUPPORT_COMPOSITION ) ;
2009-11-07 20:28:18 +01:00
DUMP_PFD_FLAG ( PFD_DEPTH_DONTCARE ) ;
DUMP_PFD_FLAG ( PFD_DOUBLEBUFFER_DONTCARE ) ;
DUMP_PFD_FLAG ( PFD_STEREO_DONTCARE ) ;
ErrorF ( " } \n " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
ErrorF ( " iPixelType = %hu = %s \n " , pfd - > iPixelType ,
( pfd - > iPixelType = = PFD_TYPE_RGBA ? " PFD_TYPE_RGBA " : " PFD_TYPE_COLORINDEX " ) ) ;
ErrorF ( " cColorBits = %hhu \n " , pfd - > cColorBits ) ;
ErrorF ( " cRedBits = %hhu \n " , pfd - > cRedBits ) ;
ErrorF ( " cRedShift = %hhu \n " , pfd - > cRedShift ) ;
ErrorF ( " cGreenBits = %hhu \n " , pfd - > cGreenBits ) ;
ErrorF ( " cGreenShift = %hhu \n " , pfd - > cGreenShift ) ;
ErrorF ( " cBlueBits = %hhu \n " , pfd - > cBlueBits ) ;
ErrorF ( " cBlueShift = %hhu \n " , pfd - > cBlueShift ) ;
ErrorF ( " cAlphaBits = %hhu \n " , pfd - > cAlphaBits ) ;
ErrorF ( " cAlphaShift = %hhu \n " , pfd - > cAlphaShift ) ;
ErrorF ( " cAccumBits = %hhu \n " , pfd - > cAccumBits ) ;
ErrorF ( " cAccumRedBits = %hhu \n " , pfd - > cAccumRedBits ) ;
ErrorF ( " cAccumGreenBits = %hhu \n " , pfd - > cAccumGreenBits ) ;
ErrorF ( " cAccumBlueBits = %hhu \n " , pfd - > cAccumBlueBits ) ;
ErrorF ( " cAccumAlphaBits = %hhu \n " , pfd - > cAccumAlphaBits ) ;
ErrorF ( " cDepthBits = %hhu \n " , pfd - > cDepthBits ) ;
ErrorF ( " cStencilBits = %hhu \n " , pfd - > cStencilBits ) ;
ErrorF ( " cAuxBuffers = %hhu \n " , pfd - > cAuxBuffers ) ;
ErrorF ( " iLayerType = %hhu \n " , pfd - > iLayerType ) ;
ErrorF ( " bReserved = %hhu \n " , pfd - > bReserved ) ;
ErrorF ( " dwLayerMask = %lu \n " , pfd - > dwLayerMask ) ;
ErrorF ( " dwVisibleMask = %lu \n " , pfd - > dwVisibleMask ) ;
ErrorF ( " dwDamageMask = %lu \n " , pfd - > dwDamageMask ) ;
ErrorF ( " \n " ) ;
2004-07-26 21:06:04 +02:00
}
2009-11-07 20:28:18 +01:00
static const char *
visual_class_name ( int cls )
{
switch ( cls ) {
case GLX_STATIC_COLOR :
return " StaticColor " ;
case GLX_PSEUDO_COLOR :
return " PseudoColor " ;
case GLX_STATIC_GRAY :
return " StaticGray " ;
case GLX_GRAY_SCALE :
return " GrayScale " ;
case GLX_TRUE_COLOR :
return " TrueColor " ;
case GLX_DIRECT_COLOR :
return " DirectColor " ;
default :
return " -none- " ;
}
2004-07-26 21:06:04 +02:00
}
2009-11-07 20:28:18 +01:00
static const char *
swap_method_name ( int mthd )
{
switch ( mthd )
{
case GLX_SWAP_EXCHANGE_OML :
return " xchg " ;
case GLX_SWAP_COPY_OML :
return " copy " ;
case GLX_SWAP_UNDEFINED_OML :
return " " ;
default :
return " ???? " ;
}
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
static void
fbConfigsDump ( unsigned int n , __GLXconfig * c )
{
ErrorF ( " %d fbConfigs \n " , n ) ;
ErrorF ( " pxf vis fb render Ste aux accum MS drawable Group/ \n " ) ;
ErrorF ( " idx ID ID VisualType Depth Lvl RGB CI DB Swap reo R G B A Z S buf AR AG AB AA bufs num W P Pb Float Trans Caveat \n " ) ;
ErrorF ( " ----------------------------------------------------------------------------------------------------------------------------- \n " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
while ( c ! = NULL )
{
unsigned int i = ( ( GLXWinConfig * ) c ) - > pixelFormatIndex ;
2010-10-11 17:21:40 +02:00
ErrorF ( " %3d %3x %3x "
2009-11-07 20:28:18 +01:00
" %-11s "
" %3d %3d %s %s %s %s %s "
" %2d %2d %2d %2d "
" %2d %2d "
" %2d "
" %2d %2d %2d %2d "
" %2d %2d "
" %s %s %s "
" %s "
" %s "
" %d %s "
" \n " ,
i , c - > visualID , c - > fbconfigID ,
visual_class_name ( c - > visualType ) ,
c - > rgbBits ? c - > rgbBits : c - > indexBits ,
c - > level ,
( c - > renderType & GLX_RGBA_BIT ) ? " y " : " . " ,
( c - > renderType & GLX_COLOR_INDEX_BIT ) ? " y " : " . " ,
c - > doubleBufferMode ? " y " : " . " ,
swap_method_name ( c - > swapMethod ) ,
c - > stereoMode ? " y " : " . " ,
c - > redBits , c - > greenBits , c - > blueBits , c - > alphaBits ,
c - > depthBits , c - > stencilBits ,
c - > numAuxBuffers ,
c - > accumRedBits , c - > accumGreenBits , c - > accumBlueBits , c - > accumAlphaBits ,
c - > sampleBuffers , c - > samples ,
( c - > drawableType & GLX_WINDOW_BIT ) ? " y " : " . " ,
( c - > drawableType & GLX_PIXMAP_BIT ) ? " y " : " . " ,
( c - > drawableType & GLX_PBUFFER_BIT ) ? " y " : " . " ,
" . " ,
( c - > transparentPixel ! = GLX_NONE_EXT ) ? " y " : " . " ,
c - > visualSelectGroup , ( c - > visualRating = = GLX_SLOW_VISUAL_EXT ) ? " * " : " " ) ;
c = c - > next ;
}
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* Forward declarations
*/
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
static __GLXscreen * glxWinScreenProbe ( ScreenPtr pScreen ) ;
static __GLXcontext * glxWinCreateContext ( __GLXscreen * screen ,
__GLXconfig * modes ,
__GLXcontext * baseShareContext ) ;
2010-08-05 16:19:20 +02:00
static __GLXdrawable * glxWinCreateDrawable ( ClientPtr client ,
__GLXscreen * screen ,
2009-11-07 20:28:18 +01:00
DrawablePtr pDraw ,
XID drawId ,
2010-08-05 16:19:20 +02:00
int type ,
XID glxDrawId ,
2009-11-07 20:28:18 +01:00
__GLXconfig * conf ) ;
static Bool glxWinRealizeWindow ( WindowPtr pWin ) ;
static Bool glxWinUnrealizeWindow ( WindowPtr pWin ) ;
static void glxWinCopyWindow ( WindowPtr pWindow , DDXPointRec ptOldOrg , RegionPtr prgnSrc ) ;
static HDC glxWinMakeDC ( __GLXWinContext * gc , __GLXWinDrawable * draw , HDC * hdc , HWND * hwnd ) ;
static void glxWinReleaseDC ( HWND hwnd , HDC hdc , __GLXWinDrawable * draw ) ;
static void glxWinCreateConfigs ( HDC dc , glxWinScreen * screen ) ;
static void glxWinCreateConfigsExt ( HDC hdc , glxWinScreen * screen ) ;
static int fbConfigToPixelFormat ( __GLXconfig * mode , PIXELFORMATDESCRIPTOR * pfdret , int drawableTypeOverride ) ;
static int fbConfigToPixelFormatIndex ( HDC hdc , __GLXconfig * mode , int drawableTypeOverride , glxWinScreen * winScreen ) ;
/* ---------------------------------------------------------------------- */
/*
* The GLX provider
*/
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
__GLXprovider __glXWGLProvider = {
glxWinScreenProbe ,
" Win32 native WGL " ,
NULL
2004-06-21 15:35:05 +02:00
} ;
2009-11-07 20:28:18 +01:00
void
glxWinPushNativeProvider ( void )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
GlxPushProvider ( & __glXWGLProvider ) ;
}
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* Screen functions
*/
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
static void
glxWinScreenDestroy ( __GLXscreen * screen )
{
GLWIN_DEBUG_MSG ( " glxWinScreenDestroy(%p) " , screen ) ;
__glXScreenDestroy ( screen ) ;
2010-05-05 20:44:06 +02:00
free ( screen ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static int
glxWinScreenSwapInterval ( __GLXdrawable * drawable , int interval )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
BOOL ret = wglSwapIntervalEXTWrapper ( interval ) ;
if ( ! ret )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
ErrorF ( " wglSwapIntervalEXT interval %d failed:%s \n " , interval , glxWinErrorMessage ( ) ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
return ret ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/*
Report the extensions split and formatted to avoid overflowing a line
*/
static void
glxLogExtensions ( const char * prefix , const char * extensions )
2005-03-01 19:58:17 +01:00
{
2009-11-07 20:28:18 +01:00
int length = 0 ;
char * strl ;
2010-08-28 00:34:49 +02:00
char * str = strdup ( extensions ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
if ( str = = NULL )
2005-03-01 19:58:17 +01:00
{
2009-11-07 20:28:18 +01:00
ErrorF ( " glxLogExtensions: xalloc error \n " ) ;
return ;
2005-03-01 19:58:17 +01:00
}
2009-11-07 20:28:18 +01:00
strl = strtok ( str , " " ) ;
ErrorF ( " %s%s " , prefix , strl ) ;
length = strlen ( prefix ) + strlen ( strl ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
while ( 1 )
2005-03-01 19:58:17 +01:00
{
2009-11-07 20:28:18 +01:00
strl = strtok ( NULL , " " ) ;
if ( strl = = NULL ) break ;
if ( length + strlen ( strl ) + 1 > 120 )
2005-03-01 19:58:17 +01:00
{
2009-11-07 20:28:18 +01:00
ErrorF ( " \n " ) ;
ErrorF ( " %s " , prefix ) ;
length = strlen ( prefix ) ;
}
else
{
ErrorF ( " " ) ;
length + + ;
2005-03-01 19:58:17 +01:00
}
2009-11-07 20:28:18 +01:00
ErrorF ( " %s " , strl ) ;
length = length + strlen ( strl ) ;
2005-03-01 19:58:17 +01:00
}
2009-11-07 20:28:18 +01:00
ErrorF ( " \n " ) ;
2005-03-01 19:58:17 +01:00
2010-05-05 20:44:06 +02:00
free ( str ) ;
2005-03-01 19:58:17 +01:00
}
2009-11-07 20:28:18 +01:00
/* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
static __GLXscreen *
glxWinScreenProbe ( ScreenPtr pScreen )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
glxWinScreen * screen ;
const char * gl_extensions ;
const char * wgl_extensions ;
HWND hwnd ;
HDC hdc ;
HGLRC hglrc ;
GLWIN_DEBUG_MSG ( " glxWinScreenProbe " ) ;
glxWinInitDebugSettings ( ) ;
if ( pScreen = = NULL )
return NULL ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! winCheckScreenAiglxIsSupported ( pScreen ) )
{
LogMessage ( X_ERROR , " AIGLX: No native OpenGL in modes with a root window \n " ) ;
return NULL ;
}
2010-05-05 20:44:06 +02:00
screen = calloc ( 1 , sizeof ( glxWinScreen ) ) ;
2009-11-07 20:28:18 +01:00
if ( NULL = = screen )
return NULL ;
/* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
screen - > RealizeWindow = pScreen - > RealizeWindow ;
pScreen - > RealizeWindow = glxWinRealizeWindow ;
screen - > UnrealizeWindow = pScreen - > UnrealizeWindow ;
pScreen - > UnrealizeWindow = glxWinUnrealizeWindow ;
screen - > CopyWindow = pScreen - > CopyWindow ;
pScreen - > CopyWindow = glxWinCopyWindow ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
/* Dump out some useful information about the native renderer */
// create window class
# define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
static wATOM glTestWndClass = 0 ;
if ( glTestWndClass = = 0 )
{
WNDCLASSEX wc ;
wc . cbSize = sizeof ( WNDCLASSEX ) ;
wc . style = CS_HREDRAW | CS_VREDRAW ;
wc . lpfnWndProc = DefWindowProc ;
wc . cbClsExtra = 0 ;
wc . cbWndExtra = 0 ;
wc . hInstance = GetModuleHandle ( NULL ) ;
wc . hIcon = 0 ;
wc . hCursor = 0 ;
wc . hbrBackground = ( HBRUSH ) GetStockObject ( WHITE_BRUSH ) ;
wc . lpszMenuName = NULL ;
wc . lpszClassName = WIN_GL_TEST_WINDOW_CLASS ;
wc . hIconSm = 0 ;
RegisterClassEx ( & wc ) ;
}
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
// create an invisible window for a scratch DC
hwnd = CreateWindowExA ( 0 ,
WIN_GL_TEST_WINDOW_CLASS ,
" XWin GL Renderer Capabilities Test Window " ,
0 , 0 , 0 , 0 , 0 , NULL , NULL , GetModuleHandle ( NULL ) , NULL ) ;
if ( hwnd = = NULL )
LogMessage ( X_ERROR , " AIGLX: Couldn't create a window for render capabilities testing \n " ) ;
hdc = GetDC ( hwnd ) ;
// we must set a pixel format before we can create a context, just use the first one...
SetPixelFormat ( hdc , 1 , NULL ) ;
hglrc = wglCreateContext ( hdc ) ;
wglMakeCurrent ( hdc , hglrc ) ;
// initialize wgl extension proc pointers (don't call them before here...)
// (but we need to have a current context for them to be resolvable)
wglResolveExtensionProcs ( ) ;
ErrorF ( " GL_VERSION: %s \n " , glGetStringWrapperNonstatic ( GL_VERSION ) ) ;
ErrorF ( " GL_VENDOR: %s \n " , glGetStringWrapperNonstatic ( GL_VENDOR ) ) ;
ErrorF ( " GL_RENDERER: %s \n " , glGetStringWrapperNonstatic ( GL_RENDERER ) ) ;
gl_extensions = ( const char * ) glGetStringWrapperNonstatic ( GL_EXTENSIONS ) ;
glxLogExtensions ( " GL_EXTENSIONS: " , gl_extensions ) ;
wgl_extensions = wglGetExtensionsStringARBWrapper ( hdc ) ;
if ( ! wgl_extensions ) wgl_extensions = " " ;
glxLogExtensions ( " WGL_EXTENSIONS: " , wgl_extensions ) ;
// Can you see the problem here? The extensions string is DC specific
// Different DCs for windows on a multimonitor system driven by multiple cards
// might have completely different capabilities. Of course, good luck getting
// those screens to be accelerated in XP and earlier...
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
// testing facility to not use any WGL extensions
char * envptr = getenv ( " GLWIN_NO_WGL_EXTENSIONS " ) ;
if ( ( envptr ! = NULL ) & & ( atoi ( envptr ) ! = 0 ) )
{
ErrorF ( " GLWIN_NO_WGL_EXTENSIONS is set, ignoring WGL_EXTENSIONS \n " ) ;
wgl_extensions = " " ;
}
2004-06-21 15:35:05 +02:00
}
{
2009-11-07 20:28:18 +01:00
Bool glx_sgi_make_current_read = FALSE ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
//
// Based on the WGL extensions available, enable various GLX extensions
// XXX: make this table-driven ?
//
memset ( screen - > glx_enable_bits , 0 , __GLX_EXT_BYTES ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_EXT_visual_info " ) ;
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_EXT_visual_rating " ) ;
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_EXT_import_context " ) ;
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_OML_swap_method " ) ;
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_SGIX_fbconfig " ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
if ( strstr ( wgl_extensions , " WGL_ARB_make_current_read " ) )
{
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_SGI_make_current_read " ) ;
LogMessage ( X_INFO , " AIGLX: enabled GLX_SGI_make_current_read \n " ) ;
glx_sgi_make_current_read = TRUE ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( strstr ( gl_extensions , " GL_WIN_swap_hint " ) )
{
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_MESA_copy_sub_buffer " ) ;
LogMessage ( X_INFO , " AIGLX: enabled GLX_MESA_copy_sub_buffer \n " ) ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( strstr ( wgl_extensions , " WGL_EXT_swap_control " ) )
{
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_SGI_swap_control " ) ;
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_MESA_swap_control " ) ;
LogMessage ( X_INFO , " AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control \n " ) ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* // Hmm? screen->texOffset */
/* if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */
/* { */
/* __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); */
/* LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); */
/* screen->has_WGL_ARB_render_texture = TRUE; */
/* } */
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( strstr ( wgl_extensions , " WGL_ARB_pbuffer " ) )
{
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_SGIX_pbuffer " ) ;
LogMessage ( X_INFO , " AIGLX: enabled GLX_SGIX_pbuffer \n " ) ;
screen - > has_WGL_ARB_pbuffer = TRUE ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( strstr ( wgl_extensions , " WGL_ARB_multisample " ) )
{
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_ARB_multisample " ) ;
__glXEnableExtension ( screen - > glx_enable_bits , " GLX_SGIS_multisample " ) ;
LogMessage ( X_INFO , " AIGLX: enabled GLX_ARB_multisample and GLX_SGIS_multisample \n " ) ;
screen - > has_WGL_ARB_multisample = TRUE ;
}
screen - > base . destroy = glxWinScreenDestroy ;
screen - > base . createContext = glxWinCreateContext ;
screen - > base . createDrawable = glxWinCreateDrawable ;
screen - > base . swapInterval = glxWinScreenSwapInterval ;
screen - > base . pScreen = pScreen ;
2011-01-24 19:41:05 +01:00
// Creating the fbConfigs initializes screen->base.fbconfigs and screen->base.numFBConfigs
2009-11-07 20:28:18 +01:00
if ( strstr ( wgl_extensions , " WGL_ARB_pixel_format " ) )
{
glxWinCreateConfigsExt ( hdc , screen ) ;
2011-01-24 19:41:05 +01:00
/*
Some graphics drivers appear to advertise WGL_ARB_pixel_format ,
but it doesn ' t work usefully , so we have to be prepared for it
to fail and fall back to using DescribePixelFormat ( )
*/
if ( screen - > base . numFBConfigs > 0 )
{
screen - > has_WGL_ARB_pixel_format = TRUE ;
}
2009-11-07 20:28:18 +01:00
}
2011-01-24 19:41:05 +01:00
if ( screen - > base . numFBConfigs < = 0 )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
glxWinCreateConfigs ( hdc , screen ) ;
screen - > has_WGL_ARB_pixel_format = FALSE ;
}
2011-01-24 19:41:05 +01:00
/*
If we still didn ' t get any fbConfigs , we can ' t provide GLX for this screen
*/
if ( screen - > base . numFBConfigs < = 0 )
{
free ( screen ) ;
LogMessage ( X_ERROR , " AIGLX: No fbConfigs could be made from native OpenGL pixel formats \n " ) ;
return NULL ;
}
2009-11-07 20:28:18 +01:00
/* These will be set by __glXScreenInit */
screen - > base . visuals = NULL ;
screen - > base . numVisuals = 0 ;
__glXScreenInit ( & screen - > base , pScreen ) ;
// dump out fbConfigs now fbConfigIds and visualIDs have been assigned
fbConfigsDump ( screen - > base . numFBConfigs , screen - > base . fbconfigs ) ;
// Override the GL extensions string set by __glXScreenInit()
2010-06-04 12:01:05 +02:00
screen - > base . GLextensions = strdup ( gl_extensions ) ;
2009-11-07 20:28:18 +01:00
// Generate the GLX extensions string (overrides that set by __glXScreenInit())
{
unsigned int buffer_size = __glXGetExtensionString ( screen - > glx_enable_bits , NULL ) ;
if ( buffer_size > 0 )
{
2010-11-10 15:28:29 +01:00
free ( screen - > base . GLXextensions ) ;
2009-11-07 20:28:18 +01:00
screen - > base . GLXextensions = xnfalloc ( buffer_size ) ;
__glXGetExtensionString ( screen - > glx_enable_bits , screen - > base . GLXextensions ) ;
}
}
//
// Override the GLX version (__glXScreenInit() sets it to "1.2")
// if we have all the needed extensionsto operate as a higher version
//
// SGIX_fbconfig && SGIX_pbuffer && SGI_make_current_read -> 1.3
// ARB_multisample -> 1.4
//
if ( screen - > has_WGL_ARB_pbuffer & & glx_sgi_make_current_read )
2004-06-21 15:35:05 +02:00
{
2010-05-05 20:44:06 +02:00
free ( screen - > base . GLXversion ) ;
2009-11-07 20:28:18 +01:00
if ( screen - > has_WGL_ARB_multisample )
{
2010-06-04 12:01:05 +02:00
screen - > base . GLXversion = strdup ( " 1.4 " ) ;
2009-11-07 20:28:18 +01:00
screen - > base . GLXmajor = 1 ;
screen - > base . GLXminor = 4 ;
}
else
2004-06-21 15:35:05 +02:00
{
2010-06-04 12:01:05 +02:00
screen - > base . GLXversion = strdup ( " 1.3 " ) ;
2009-11-07 20:28:18 +01:00
screen - > base . GLXmajor = 1 ;
screen - > base . GLXminor = 3 ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
LogMessage ( X_INFO , " AIGLX: Set GLX version to %s \n " , screen - > base . GLXversion ) ;
2004-06-21 15:35:05 +02:00
}
}
2009-11-07 20:28:18 +01:00
wglMakeCurrent ( NULL , NULL ) ;
wglDeleteContext ( hglrc ) ;
ReleaseDC ( hwnd , hdc ) ;
DestroyWindow ( hwnd ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
return & screen - > base ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* Window functions
*/
static Bool
glxWinRealizeWindow ( WindowPtr pWin )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
Bool result ;
ScreenPtr pScreen = pWin - > drawable . pScreen ;
glxWinScreen * screenPriv = ( glxWinScreen * ) glxGetScreen ( pScreen ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " glxWinRealizeWindow " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
pScreen - > RealizeWindow = screenPriv - > RealizeWindow ;
result = pScreen - > RealizeWindow ( pWin ) ;
pScreen - > RealizeWindow = glxWinRealizeWindow ;
return result ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static void
glxWinCopyWindow ( WindowPtr pWindow , DDXPointRec ptOldOrg , RegionPtr prgnSrc )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
__GLXWinDrawable * pGlxDraw ;
ScreenPtr pScreen = pWindow - > drawable . pScreen ;
glxWinScreen * screenPriv = ( glxWinScreen * ) glxGetScreen ( pScreen ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_TRACE_MSG ( " glxWinCopyWindow pWindow %p " , pWindow ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
dixLookupResourceByType ( ( pointer ) & pGlxDraw , pWindow - > drawable . id , __glXDrawableRes ,
NullClient , DixUnknownAccess ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/*
Discard any CopyWindow requests if a GL drawing context is pointing at the window
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
For regions which are being drawn by GL , the shadow framebuffer doesn ' t have the
correct bits , so we wish to avoid shadow framebuffer damage occuring , which will
cause those incorrect bits to be transferred to the display . . . .
*/
if ( pGlxDraw & & pGlxDraw - > drawContext )
{
GLWIN_DEBUG_MSG ( " glxWinCopyWindow: discarding " ) ;
return ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " glxWinCopyWindow - passing to hw layer " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
pScreen - > CopyWindow = screenPriv - > CopyWindow ;
pScreen - > CopyWindow ( pWindow , ptOldOrg , prgnSrc ) ;
pScreen - > CopyWindow = glxWinCopyWindow ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static Bool
glxWinUnrealizeWindow ( WindowPtr pWin )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
Bool result ;
ScreenPtr pScreen = pWin - > drawable . pScreen ;
glxWinScreen * screenPriv = ( glxWinScreen * ) glxGetScreen ( pScreen ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " glxWinUnrealizeWindow " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
pScreen - > UnrealizeWindow = screenPriv - > UnrealizeWindow ;
result = pScreen - > UnrealizeWindow ( pWin ) ;
pScreen - > UnrealizeWindow = glxWinUnrealizeWindow ;
return result ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* Drawable functions
*/
static GLboolean
glxWinDrawableSwapBuffers ( ClientPtr client , __GLXdrawable * base )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
HDC dc ;
HWND hwnd ;
BOOL ret ;
__GLXWinDrawable * draw = ( __GLXWinDrawable * ) base ;
/* Swap buffers on the last active context for drawing on the drawable */
if ( draw - > drawContext = = NULL )
{
GLWIN_TRACE_MSG ( " glxWinSwapBuffers - no context for drawable " ) ;
return GL_FALSE ;
}
GLWIN_TRACE_MSG ( " glxWinSwapBuffers on drawable %p, last context %p (native ctx %p) " , base , draw - > drawContext , draw - > drawContext - > ctx ) ;
/*
draw - > drawContext - > base . drawPriv will not be set if the context is not current anymore ,
but if it is , it should point to this drawable . . . .
*/
assert ( ( draw - > drawContext - > base . drawPriv = = NULL ) | | ( draw - > drawContext - > base . drawPriv = = base ) ) ;
dc = glxWinMakeDC ( draw - > drawContext , draw , & dc , & hwnd ) ;
if ( dc = = NULL )
return GL_FALSE ;
ret = wglSwapLayerBuffers ( dc , WGL_SWAP_MAIN_PLANE ) ;
glxWinReleaseDC ( hwnd , dc , draw ) ;
if ( ! ret )
{
ErrorF ( " wglSwapBuffers failed: %s \n " , glxWinErrorMessage ( ) ) ;
return GL_FALSE ;
}
2004-06-21 15:35:05 +02:00
2005-03-01 19:58:17 +01:00
return GL_TRUE ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static void
glxWinDrawableCopySubBuffer ( __GLXdrawable * drawable ,
int x , int y , int w , int h )
{
glAddSwapHintRectWINWrapperNonstatic ( x , y , w , h ) ;
glxWinDrawableSwapBuffers ( NULL , drawable ) ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
static void
glxWinDrawableDestroy ( __GLXdrawable * base )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
__GLXWinDrawable * glxPriv = ( __GLXWinDrawable * ) base ;
if ( glxPriv - > drawContext & & ( __glXLastContext = = & ( ( glxPriv - > drawContext ) - > base ) ) )
{
// if this context is current and has unflushed commands, say we have flushed them
// (don't actually flush them, the window is going away anyhow, and an implict flush occurs
// on the next context change)
// (GLX core considers it an error when we try to select a new current context if the old one
// has unflushed commands, but the window has disappeared..)
2011-03-18 22:44:11 +01:00
__glXLastContext - > hasUnflushedCommands = FALSE ;
2009-11-07 20:28:18 +01:00
__glXLastContext = NULL ;
}
if ( glxPriv - > hPbuffer )
if ( ! wglDestroyPbufferARBWrapper ( glxPriv - > hPbuffer ) )
{
ErrorF ( " wglDestroyPbufferARB failed: %s \n " , glxWinErrorMessage ( ) ) ;
}
if ( glxPriv - > dibDC )
{
// restore the default DIB
SelectObject ( glxPriv - > dibDC , glxPriv - > hOldDIB ) ;
if ( ! DeleteDC ( glxPriv - > dibDC ) )
{
ErrorF ( " DeleteDC failed: %s \n " , glxWinErrorMessage ( ) ) ;
}
}
if ( glxPriv - > hDIB )
{
if ( ! DeleteObject ( glxPriv - > hDIB ) )
{
ErrorF ( " DeleteObject failed: %s \n " , glxWinErrorMessage ( ) ) ;
}
( ( PixmapPtr ) glxPriv - > base . pDraw ) - > devPrivate . ptr = glxPriv - > pOldBits ;
}
GLWIN_DEBUG_MSG ( " glxWinDestroyDrawable " ) ;
2010-05-05 20:44:06 +02:00
free ( glxPriv ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static __GLXdrawable *
2010-08-05 16:19:20 +02:00
glxWinCreateDrawable ( ClientPtr client ,
__GLXscreen * screen ,
2009-11-07 20:28:18 +01:00
DrawablePtr pDraw ,
XID drawId ,
2010-08-05 16:19:20 +02:00
int type ,
XID glxDrawId ,
2009-11-07 20:28:18 +01:00
__GLXconfig * conf )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
__GLXWinDrawable * glxPriv ;
2010-05-05 20:44:06 +02:00
glxPriv = malloc ( sizeof * glxPriv ) ;
2009-11-07 20:28:18 +01:00
if ( glxPriv = = NULL )
return NULL ;
memset ( glxPriv , 0 , sizeof * glxPriv ) ;
2010-08-05 16:19:20 +02:00
if ( ! __glXDrawableInit ( & glxPriv - > base , screen , pDraw , type , glxDrawId , conf ) ) {
2010-05-05 20:44:06 +02:00
free ( glxPriv ) ;
2009-11-07 20:28:18 +01:00
return NULL ;
}
glxPriv - > base . destroy = glxWinDrawableDestroy ;
glxPriv - > base . swapBuffers = glxWinDrawableSwapBuffers ;
glxPriv - > base . copySubBuffer = glxWinDrawableCopySubBuffer ;
// glxPriv->base.waitX what are these for?
// glxPriv->base.waitGL
GLWIN_DEBUG_MSG ( " glxWinCreateDrawable %p " , glxPriv ) ;
return & glxPriv - > base ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* Texture functions
*/
static
int glxWinBindTexImage ( __GLXcontext * baseContext ,
int buffer ,
__GLXdrawable * pixmap )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
ErrorF ( " glxWinBindTexImage: not implemented \n " ) ;
return FALSE ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static
int glxWinReleaseTexImage ( __GLXcontext * baseContext ,
int buffer ,
__GLXdrawable * pixmap )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
ErrorF ( " glxWinReleaseTexImage: not implemented \n " ) ;
return FALSE ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
/*
* Lazy update context implementation
*
* WGL contexts are created for a specific HDC , so we cannot create the WGL
* context in glxWinCreateContext ( ) , we must defer creation until the context
* is actually used on a specifc drawable which is connected to a native window ,
* pbuffer or DIB
*
* The WGL context may be used on other , compatible HDCs , so we don ' t need to
* recreate it for every new native window
*
* XXX : I wonder why we can ' t create the WGL context on the screen HDC ?
* Basically we assume all HDCs are compatible at the moment : if they are not
* we are in a muddle , there was some code in the old implementation to attempt
* to transparently migrate a context to a new DC by copying state and sharing
* lists with the old one . . .
*/
2010-10-30 18:23:52 +02:00
static Bool
2009-11-07 20:28:18 +01:00
glxWinSetPixelFormat ( __GLXWinContext * gc , HDC hdc , int bppOverride , int drawableTypeOverride )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
__GLXscreen * screen = gc - > base . pGlxScreen ;
glxWinScreen * winScreen = ( glxWinScreen * ) screen ;
__GLXconfig * config = gc - > base . config ;
GLXWinConfig * winConfig = ( GLXWinConfig * ) config ;
GLWIN_DEBUG_MSG ( " glxWinSetPixelFormat: pixelFormatIndex %d " , winConfig - > pixelFormatIndex ) ;
/*
Normally , we can just use the the pixelFormatIndex corresponding
to the fbconfig which has been specified by the client
*/
if ( ! ( ( bppOverride & & ( bppOverride ! = ( config - > redBits + config - > greenBits + config - > blueBits ) ) )
| | ( ( config - > drawableType & drawableTypeOverride ) = = 0 ) ) )
{
if ( ! SetPixelFormat ( hdc , winConfig - > pixelFormatIndex , NULL ) )
{
ErrorF ( " SetPixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
2010-10-30 18:23:52 +02:00
return FALSE ;
2009-11-07 20:28:18 +01:00
}
2010-10-30 18:23:52 +02:00
return TRUE ;
2009-11-07 20:28:18 +01:00
}
/*
However , in certain special cases this pixel format will be incompatible with the
use we are going to put it to , so we need to re - evaluate the pixel format to use :
1 ) When PFD_DRAW_TO_BITMAP is set , ChoosePixelFormat ( ) always returns a format with
the cColorBits we asked for , so we need to ensure it matches the bpp of the bitmap
2 ) Applications may assume that visuals selected with glXChooseVisual ( ) work with
pixmap drawables ( there is no attribute to explicitly query for pixmap drawable
support as there is for glXChooseFBConfig ( ) )
( it ' s arguable this is an error in the application , but we try to make it work )
pixmap rendering is always slow for us , so we don ' t want to choose those visuals
by default , but if the actual drawable type we ' re trying to select the context
on ( drawableTypeOverride ) isn ' t supported by the selected fbConfig , reconsider
and see if we can find a suitable one . . .
*/
ErrorF ( " glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d \n " ,
( config - > redBits + config - > greenBits + config - > blueBits ) , bppOverride , config - > drawableType , drawableTypeOverride ) ;
if ( ! winScreen - > has_WGL_ARB_pixel_format )
{
PIXELFORMATDESCRIPTOR pfd ;
int pixelFormat ;
/* convert fbConfig to PFD */
if ( fbConfigToPixelFormat ( gc - > base . config , & pfd , drawableTypeOverride ) )
{
ErrorF ( " glxWinSetPixelFormat: fbConfigToPixelFormat failed \n " ) ;
2010-10-30 18:23:52 +02:00
return FALSE ;
2009-11-07 20:28:18 +01:00
}
if ( glxWinDebugSettings . dumpPFD )
pfdOut ( & pfd ) ;
if ( bppOverride )
{
GLWIN_DEBUG_MSG ( " glxWinSetPixelFormat: Forcing bpp from %d to %d \n " , pfd . cColorBits , bppOverride ) ;
pfd . cColorBits = bppOverride ;
}
pixelFormat = ChoosePixelFormat ( hdc , & pfd ) ;
if ( pixelFormat = = 0 )
{
ErrorF ( " ChoosePixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
2010-10-30 18:23:52 +02:00
return FALSE ;
2009-11-07 20:28:18 +01:00
}
GLWIN_DEBUG_MSG ( " ChoosePixelFormat: chose pixelFormatIndex %d " , pixelFormat ) ;
ErrorF ( " ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned) \n " , pixelFormat , winConfig - > pixelFormatIndex ) ;
if ( ! SetPixelFormat ( hdc , pixelFormat , & pfd ) )
{
ErrorF ( " SetPixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
2010-10-30 18:23:52 +02:00
return FALSE ;
2009-11-07 20:28:18 +01:00
}
}
else
{
int pixelFormat = fbConfigToPixelFormatIndex ( hdc , gc - > base . config , drawableTypeOverride , winScreen ) ;
if ( pixelFormat = = 0 )
{
ErrorF ( " wglChoosePixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
2010-10-30 18:23:52 +02:00
return FALSE ;
2009-11-07 20:28:18 +01:00
}
GLWIN_DEBUG_MSG ( " wglChoosePixelFormat: chose pixelFormatIndex %d " , pixelFormat ) ;
ErrorF ( " wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned) \n " , pixelFormat , winConfig - > pixelFormatIndex ) ;
if ( ! SetPixelFormat ( hdc , pixelFormat , NULL ) )
{
ErrorF ( " SetPixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
2010-10-30 18:23:52 +02:00
return FALSE ;
2009-11-07 20:28:18 +01:00
}
}
2010-10-30 18:23:52 +02:00
return TRUE ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static HDC
glxWinMakeDC ( __GLXWinContext * gc , __GLXWinDrawable * draw , HDC * hdc , HWND * hwnd )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
* hdc = NULL ;
* hwnd = NULL ;
if ( draw = = NULL )
{
GLWIN_TRACE_MSG ( " No drawable for context %p (native ctx %p) " , gc , gc - > ctx ) ;
return NULL ;
}
switch ( draw - > base . type )
{
case GLX_DRAWABLE_WINDOW :
{
WindowPtr pWin ;
pWin = ( WindowPtr ) draw - > base . pDraw ;
if ( pWin = = NULL )
{
GLWIN_TRACE_MSG ( " for drawable %p, no WindowPtr " , pWin ) ;
return NULL ;
}
* hwnd = winGetWindowInfo ( pWin ) ;
if ( * hwnd = = NULL )
{
ErrorF ( " No HWND error: %s \n " , glxWinErrorMessage ( ) ) ;
return NULL ;
}
* hdc = GetDC ( * hwnd ) ;
if ( * hdc = = NULL )
ErrorF ( " GetDC error: %s \n " , glxWinErrorMessage ( ) ) ;
/* Check if the hwnd has changed... */
if ( * hwnd ! = gc - > hwnd )
{
if ( glxWinDebugSettings . enableTrace )
GLWIN_DEBUG_HWND ( * hwnd ) ;
GLWIN_TRACE_MSG ( " for context %p (native ctx %p), hWnd changed from %p to %p " , gc , gc - > ctx , gc - > hwnd , * hwnd ) ;
gc - > hwnd = * hwnd ;
/* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
2010-10-30 18:23:52 +02:00
if ( ! glxWinSetPixelFormat ( gc , * hdc , 0 , GLX_WINDOW_BIT ) )
{
ErrorF ( " glxWinSetPixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
ReleaseDC ( * hwnd , * hdc ) ;
* hdc = NULL ;
return NULL ;
}
2009-11-07 20:28:18 +01:00
}
}
break ;
case GLX_DRAWABLE_PBUFFER :
{
* hdc = wglGetPbufferDCARBWrapper ( draw - > hPbuffer ) ;
if ( * hdc = = NULL )
ErrorF ( " GetDC (pbuffer) error: %s \n " , glxWinErrorMessage ( ) ) ;
}
break ;
case GLX_DRAWABLE_PIXMAP :
{
* hdc = draw - > dibDC ;
}
break ;
default :
{
ErrorF ( " glxWinMakeDC: tried to makeDC for unhandled drawable type %d \n " , draw - > base . type ) ;
}
}
if ( glxWinDebugSettings . dumpDC )
GLWIN_DEBUG_MSG ( " Got HDC %p " , * hdc ) ;
return * hdc ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
static void
glxWinReleaseDC ( HWND hwnd , HDC hdc , __GLXWinDrawable * draw )
{
switch ( draw - > base . type )
{
case GLX_DRAWABLE_WINDOW :
{
ReleaseDC ( hwnd , hdc ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
break ;
case GLX_DRAWABLE_PBUFFER :
{
if ( ! wglReleasePbufferDCARBWrapper ( draw - > hPbuffer , hdc ) )
{
ErrorF ( " wglReleasePbufferDCARB error: %s \n " , glxWinErrorMessage ( ) ) ;
}
}
break ;
case GLX_DRAWABLE_PIXMAP :
{
// don't release DC, the memory DC lives as long as the bitmap
// We must ensure that all GDI drawing into the bitmap has completed
// in case we subsequently access the bits from it
GdiFlush ( ) ;
}
break ;
default :
{
ErrorF ( " glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d \n " , draw - > base . type ) ;
}
}
}
static void
glxWinDeferredCreateContext ( __GLXWinContext * gc , __GLXWinDrawable * draw )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
HDC dc ;
HWND hwnd ;
GLWIN_DEBUG_MSG ( " glxWinDeferredCreateContext: attach context %p to drawable %p " , gc , draw ) ;
switch ( draw - > base . type )
{
case GLX_DRAWABLE_WINDOW :
{
WindowPtr pWin = ( WindowPtr ) draw - > base . pDraw ;
if ( ! ( gc - > base . config - > drawableType & GLX_WINDOW_BIT ) )
{
ErrorF ( " glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable \n " ) ;
}
if ( pWin = = NULL )
{
GLWIN_DEBUG_MSG ( " Deferring until X window is created " ) ;
return ;
}
GLWIN_DEBUG_MSG ( " glxWinDeferredCreateContext: pWin %p " , pWin ) ;
if ( winGetWindowInfo ( pWin ) = = NULL )
{
GLWIN_DEBUG_MSG ( " Deferring until native window is created " ) ;
return ;
}
}
break ;
case GLX_DRAWABLE_PBUFFER :
{
if ( draw - > hPbuffer = = NULL )
{
__GLXscreen * screen ;
glxWinScreen * winScreen ;
int pixelFormat ;
// XXX: which DC are supposed to use???
HDC screenDC = GetDC ( NULL ) ;
if ( ! ( gc - > base . config - > drawableType & GLX_PBUFFER_BIT ) )
{
ErrorF ( " glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable \n " ) ;
}
screen = gc - > base . pGlxScreen ;
winScreen = ( glxWinScreen * ) screen ;
pixelFormat = fbConfigToPixelFormatIndex ( screenDC , gc - > base . config , GLX_DRAWABLE_PBUFFER , winScreen ) ;
if ( pixelFormat = = 0 )
{
ErrorF ( " wglChoosePixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
return ;
}
draw - > hPbuffer = wglCreatePbufferARBWrapper ( screenDC , pixelFormat , draw - > base . pDraw - > width , draw - > base . pDraw - > height , NULL ) ;
ReleaseDC ( NULL , screenDC ) ;
if ( draw - > hPbuffer = = NULL )
{
ErrorF ( " wglCreatePbufferARBWrapper error: %s \n " , glxWinErrorMessage ( ) ) ;
return ;
}
GLWIN_DEBUG_MSG ( " glxWinDeferredCreateContext: pBuffer %p created for drawable %p " , draw - > hPbuffer , draw ) ;
}
}
break ;
case GLX_DRAWABLE_PIXMAP :
{
if ( draw - > dibDC = = NULL )
{
BITMAPINFOHEADER bmpHeader ;
void * pBits ;
memset ( & bmpHeader , 0 , sizeof ( BITMAPINFOHEADER ) ) ;
bmpHeader . biSize = sizeof ( BITMAPINFOHEADER ) ;
bmpHeader . biWidth = draw - > base . pDraw - > width ;
bmpHeader . biHeight = draw - > base . pDraw - > height ;
bmpHeader . biPlanes = 1 ;
bmpHeader . biBitCount = draw - > base . pDraw - > bitsPerPixel ;
bmpHeader . biCompression = BI_RGB ;
if ( ! ( gc - > base . config - > drawableType & GLX_PIXMAP_BIT ) )
{
ErrorF ( " glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable \n " ) ;
}
draw - > dibDC = CreateCompatibleDC ( NULL ) ;
if ( draw - > dibDC = = NULL )
{
ErrorF ( " CreateCompatibleDC error: %s \n " , glxWinErrorMessage ( ) ) ;
return ;
}
draw - > hDIB = CreateDIBSection ( draw - > dibDC , ( BITMAPINFO * ) & bmpHeader , DIB_RGB_COLORS , & pBits , 0 , 0 ) ;
if ( draw - > dibDC = = NULL )
{
ErrorF ( " CreateDIBSection error: %s \n " , glxWinErrorMessage ( ) ) ;
return ;
}
// XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
// need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
// so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
// even compatible ...
draw - > pOldBits = ( ( PixmapPtr ) draw - > base . pDraw ) - > devPrivate . ptr ;
( ( PixmapPtr ) draw - > base . pDraw ) - > devPrivate . ptr = pBits ;
// Select the DIB into the DC
draw - > hOldDIB = SelectObject ( draw - > dibDC , draw - > hDIB ) ;
if ( ! draw - > hOldDIB )
{
ErrorF ( " SelectObject error: %s \n " , glxWinErrorMessage ( ) ) ;
}
// Set the pixel format of the bitmap
glxWinSetPixelFormat ( gc , draw - > dibDC , draw - > base . pDraw - > bitsPerPixel , GLX_PIXMAP_BIT ) ;
GLWIN_DEBUG_MSG ( " glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p " , draw - > hDIB , draw ) ;
}
}
break ;
default :
{
ErrorF ( " glxWinDeferredCreateContext: tried to attach unhandled drawable type %d \n " , draw - > base . type ) ;
return ;
}
}
dc = glxWinMakeDC ( gc , draw , & dc , & hwnd ) ;
gc - > ctx = wglCreateContext ( dc ) ;
glxWinReleaseDC ( hwnd , dc , draw ) ;
if ( gc - > ctx = = NULL )
{
ErrorF ( " wglCreateContext error: %s \n " , glxWinErrorMessage ( ) ) ;
return ;
}
GLWIN_DEBUG_MSG ( " glxWinDeferredCreateContext: attached context %p to native context %p drawable %p " , gc , gc - > ctx , draw ) ;
// if the native context was created successfully, shareLists if needed
if ( gc - > ctx & & gc - > shareContext )
{
GLWIN_DEBUG_MSG ( " glxWinCreateContextReal shareLists with context %p (native ctx %p) " , gc - > shareContext , gc - > shareContext - > ctx ) ;
if ( ! wglShareLists ( gc - > shareContext - > ctx , gc - > ctx ) )
{
ErrorF ( " wglShareLists error: %s \n " , glxWinErrorMessage ( ) ) ;
}
}
}
/* ---------------------------------------------------------------------- */
/*
* Context functions
*/
/* Context manipulation routines should return TRUE on success, FALSE on failure */
static int
glxWinContextMakeCurrent ( __GLXcontext * base )
{
__GLXWinContext * gc = ( __GLXWinContext * ) base ;
BOOL ret ;
HDC drawDC ;
HDC readDC = NULL ;
__GLXdrawable * drawPriv ;
__GLXdrawable * readPriv = NULL ;
HWND hDrawWnd ;
HWND hReadWnd ;
GLWIN_TRACE_MSG ( " glxWinContextMakeCurrent context %p (native ctx %p) " , gc , gc - > ctx ) ;
glWinCallDelta ( ) ;
/* Keep a note of the last active context in the drawable */
drawPriv = gc - > base . drawPriv ;
( ( __GLXWinDrawable * ) drawPriv ) - > drawContext = gc ;
if ( gc - > ctx = = NULL )
{
glxWinDeferredCreateContext ( gc , ( __GLXWinDrawable * ) drawPriv ) ;
}
if ( gc - > ctx = = NULL )
{
ErrorF ( " glxWinContextMakeCurrent: Native context is NULL \n " ) ;
return FALSE ;
}
drawDC = glxWinMakeDC ( gc , ( __GLXWinDrawable * ) drawPriv , & drawDC , & hDrawWnd ) ;
if ( drawDC = = NULL )
{
ErrorF ( " glxWinMakeDC failed for drawDC \n " ) ;
return FALSE ;
}
if ( ( gc - > base . readPriv ! = NULL ) & & ( gc - > base . readPriv ! = gc - > base . drawPriv ) )
{
// XXX: should only occur with WGL_ARB_make_current_read
/*
If there is a separate read drawable , create a separate read DC , and
use the wglMakeContextCurrent extension to make the context current drawing
to one DC and reading from the other
*/
readPriv = gc - > base . readPriv ;
readDC = glxWinMakeDC ( gc , ( __GLXWinDrawable * ) readPriv , & readDC , & hReadWnd ) ;
if ( readDC = = NULL )
{
ErrorF ( " glxWinMakeDC failed for readDC \n " ) ;
glxWinReleaseDC ( hDrawWnd , drawDC , ( __GLXWinDrawable * ) drawPriv ) ;
return FALSE ;
}
ret = wglMakeContextCurrentARBWrapper ( drawDC , readDC , gc - > ctx ) ;
if ( ! ret )
{
ErrorF ( " wglMakeContextCurrentARBWrapper error: %s \n " , glxWinErrorMessage ( ) ) ;
}
}
else
{
/* Otherwise, just use wglMakeCurrent */
ret = wglMakeCurrent ( drawDC , gc - > ctx ) ;
if ( ! ret )
{
ErrorF ( " wglMakeCurrent error: %s \n " , glxWinErrorMessage ( ) ) ;
}
}
// apparently make current could fail if the context is current in a different thread,
// but that shouldn't be able to happen in the current server...
glxWinReleaseDC ( hDrawWnd , drawDC , ( __GLXWinDrawable * ) drawPriv ) ;
if ( readDC )
glxWinReleaseDC ( hReadWnd , readDC , ( __GLXWinDrawable * ) readPriv ) ;
return ret ;
}
static int
glxWinContextLoseCurrent ( __GLXcontext * base )
{
BOOL ret ;
__GLXWinContext * gc = ( __GLXWinContext * ) base ;
GLWIN_TRACE_MSG ( " glxWinContextLoseCurrent context %p (native ctx %p) " , gc , gc - > ctx ) ;
glWinCallDelta ( ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/*
An error seems to be reported if we try to make no context current
if there is already no current context , so avoid doing that . . .
*/
if ( __glXLastContext ! = NULL )
{
ret = wglMakeCurrent ( NULL , NULL ) ; /* We don't need a DC when setting no current context */
if ( ! ret )
ErrorF ( " glxWinContextLoseCurrent error: %s \n " , glxWinErrorMessage ( ) ) ;
}
return TRUE ;
}
static int
glxWinContextCopy ( __GLXcontext * dst_base , __GLXcontext * src_base , unsigned long mask )
{
__GLXWinContext * dst = ( __GLXWinContext * ) dst_base ;
__GLXWinContext * src = ( __GLXWinContext * ) src_base ;
BOOL ret ;
GLWIN_DEBUG_MSG ( " glxWinContextCopy " ) ;
ret = wglCopyContext ( src - > ctx , dst - > ctx , mask ) ;
if ( ! ret )
{
ErrorF ( " wglCopyContext error: %s \n " , glxWinErrorMessage ( ) ) ;
}
return ret ;
}
static void
glxWinContextDestroy ( __GLXcontext * base )
{
__GLXWinContext * gc = ( __GLXWinContext * ) base ;
if ( gc ! = NULL )
{
GLWIN_DEBUG_MSG ( " GLXcontext %p destroyed (native ctx %p) " , base , gc - > ctx ) ;
if ( gc - > ctx )
{
/* It's bad style to delete the context while it's still current */
if ( wglGetCurrentContext ( ) = = gc - > ctx )
{
wglMakeCurrent ( NULL , NULL ) ;
}
{
BOOL ret = wglDeleteContext ( gc - > ctx ) ;
if ( ! ret )
ErrorF ( " wglDeleteContext error: %s \n " , glxWinErrorMessage ( ) ) ;
}
gc - > ctx = NULL ;
}
2010-05-05 20:44:06 +02:00
free ( gc ) ;
2009-11-07 20:28:18 +01:00
}
}
static __GLXcontext *
glxWinCreateContext ( __GLXscreen * screen ,
__GLXconfig * modes ,
__GLXcontext * baseShareContext )
{
__GLXWinContext * context ;
__GLXWinContext * shareContext = ( __GLXWinContext * ) baseShareContext ;
static __GLXtextureFromPixmap glxWinTextureFromPixmap =
{
glxWinBindTexImage ,
glxWinReleaseTexImage
} ;
2010-05-05 20:44:06 +02:00
context = ( __GLXWinContext * ) calloc ( 1 , sizeof ( __GLXWinContext ) ) ;
2009-11-07 20:28:18 +01:00
if ( ! context )
return NULL ;
memset ( context , 0 , sizeof * context ) ;
context - > base . destroy = glxWinContextDestroy ;
context - > base . makeCurrent = glxWinContextMakeCurrent ;
context - > base . loseCurrent = glxWinContextLoseCurrent ;
context - > base . copy = glxWinContextCopy ;
context - > base . textureFromPixmap = & glxWinTextureFromPixmap ;
context - > base . config = modes ;
context - > base . pGlxScreen = screen ;
// actual native GL context creation is deferred until attach()
context - > ctx = NULL ;
context - > shareContext = shareContext ;
glWinSetupDispatchTable ( ) ;
GLWIN_DEBUG_MSG ( " GLXcontext %p created " , context ) ;
return & ( context - > base ) ;
}
/* ---------------------------------------------------------------------- */
/*
* Utility functions
*/
static int
fbConfigToPixelFormat ( __GLXconfig * mode , PIXELFORMATDESCRIPTOR * pfdret , int drawableTypeOverride )
2004-06-21 15:35:05 +02:00
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof ( PIXELFORMATDESCRIPTOR ) , /* size of this pfd */
1 , /* version number */
PFD_SUPPORT_OPENGL , /* support OpenGL */
PFD_TYPE_RGBA , /* RGBA type */
24 , /* 24-bit 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 */
2009-11-07 20:28:18 +01:00
32 , /* 32-bit z-buffer */
2004-06-21 15:35:05 +02:00
0 , /* no stencil buffer */
0 , /* no auxiliary buffer */
PFD_MAIN_PLANE , /* main layer */
0 , /* reserved */
0 , 0 , 0 /* layer masks ignored */
2009-11-07 20:28:18 +01:00
} ;
if ( ( mode - > drawableType | drawableTypeOverride ) & GLX_WINDOW_BIT )
pfd . dwFlags | = PFD_DRAW_TO_WINDOW ; /* support window */
if ( ( mode - > drawableType | drawableTypeOverride ) & GLX_PIXMAP_BIT )
pfd . dwFlags | = ( PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI ) ; /* supports software rendering to bitmap */
2004-06-21 15:35:05 +02:00
if ( mode - > stereoMode ) {
2009-11-07 20:28:18 +01:00
pfd . dwFlags | = PFD_STEREO ;
2004-06-21 15:35:05 +02:00
}
if ( mode - > doubleBufferMode ) {
2009-11-07 20:28:18 +01:00
pfd . dwFlags | = PFD_DOUBLEBUFFER ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
pfd . iPixelType = PFD_TYPE_RGBA ;
pfd . cColorBits = mode - > redBits + mode - > greenBits + mode - > blueBits ;
pfd . cRedBits = mode - > redBits ;
pfd . cRedShift = 0 ; /* FIXME */
pfd . cGreenBits = mode - > greenBits ;
pfd . cGreenShift = 0 ; /* FIXME */
pfd . cBlueBits = mode - > blueBits ;
pfd . cBlueShift = 0 ; /* FIXME */
pfd . cAlphaBits = mode - > alphaBits ;
pfd . cAlphaShift = 0 ; /* FIXME */
pfd . cAccumBits = mode - > accumRedBits + mode - > accumGreenBits + mode - > accumBlueBits + mode - > accumAlphaBits ;
pfd . cAccumRedBits = mode - > accumRedBits ;
pfd . cAccumGreenBits = mode - > accumGreenBits ;
pfd . cAccumBlueBits = mode - > accumBlueBits ;
pfd . cAccumAlphaBits = mode - > accumAlphaBits ;
pfd . cDepthBits = mode - > depthBits ;
pfd . cStencilBits = mode - > stencilBits ;
pfd . cAuxBuffers = mode - > numAuxBuffers ;
/* mode->level ? */
/* mode->pixmapMode ? */
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
* pfdret = pfd ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
return 0 ;
}
# define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < NUM_ELEMENTS(attribList)); }
static int
fbConfigToPixelFormatIndex ( HDC hdc , __GLXconfig * mode , int drawableTypeOverride , glxWinScreen * winScreen )
{
UINT numFormats ;
unsigned int i = 0 ;
/* convert fbConfig to attr-value list */
int attribList [ 60 ] ;
SET_ATTR_VALUE ( WGL_SUPPORT_OPENGL_ARB , TRUE ) ;
SET_ATTR_VALUE ( WGL_PIXEL_TYPE_ARB , ( mode - > visualType = = GLX_TRUE_COLOR ) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB ) ;
SET_ATTR_VALUE ( WGL_COLOR_BITS_ARB , ( mode - > visualType = = GLX_TRUE_COLOR ) ? mode - > rgbBits : mode - > indexBits ) ;
SET_ATTR_VALUE ( WGL_RED_BITS_ARB , mode - > redBits ) ;
SET_ATTR_VALUE ( WGL_GREEN_BITS_ARB , mode - > greenBits ) ;
SET_ATTR_VALUE ( WGL_BLUE_BITS_ARB , mode - > blueBits ) ;
SET_ATTR_VALUE ( WGL_ALPHA_BITS_ARB , mode - > alphaBits ) ;
SET_ATTR_VALUE ( WGL_ACCUM_RED_BITS_ARB , mode - > accumRedBits ) ;
SET_ATTR_VALUE ( WGL_ACCUM_GREEN_BITS_ARB , mode - > accumGreenBits ) ;
SET_ATTR_VALUE ( WGL_ACCUM_BLUE_BITS_ARB , mode - > accumBlueBits ) ;
SET_ATTR_VALUE ( WGL_ACCUM_ALPHA_BITS_ARB , mode - > accumAlphaBits ) ;
SET_ATTR_VALUE ( WGL_DEPTH_BITS_ARB , mode - > depthBits ) ;
SET_ATTR_VALUE ( WGL_STENCIL_BITS_ARB , mode - > stencilBits ) ;
SET_ATTR_VALUE ( WGL_AUX_BUFFERS_ARB , mode - > numAuxBuffers ) ;
if ( mode - > doubleBufferMode )
SET_ATTR_VALUE ( WGL_DOUBLE_BUFFER_ARB , TRUE ) ;
if ( mode - > stereoMode )
SET_ATTR_VALUE ( WGL_STEREO_ARB , TRUE ) ;
// Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft..
if ( mode - > swapMethod = = GLX_SWAP_EXCHANGE_OML )
SET_ATTR_VALUE ( WGL_SWAP_METHOD_ARB , WGL_SWAP_EXCHANGE_ARB ) ;
if ( mode - > swapMethod = = GLX_SWAP_COPY_OML )
SET_ATTR_VALUE ( WGL_SWAP_COPY_ARB , TRUE ) ;
// XXX: this should probably be the other way around, but that messes up drawableTypeOverride
if ( mode - > visualRating = = GLX_SLOW_VISUAL_EXT )
SET_ATTR_VALUE ( WGL_ACCELERATION_ARB , WGL_NO_ACCELERATION_ARB ) ;
// must support all the drawable types the mode supports
if ( ( mode - > drawableType | drawableTypeOverride ) & GLX_WINDOW_BIT )
SET_ATTR_VALUE ( WGL_DRAW_TO_WINDOW_ARB , TRUE ) ;
// XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea
// try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride)
if ( drawableTypeOverride = = GLX_WINDOW_BIT )
{
if ( mode - > drawableType & GLX_PIXMAP_BIT )
SET_ATTR_VALUE ( WGL_DRAW_TO_BITMAP_ARB , TRUE ) ;
if ( mode - > drawableType & GLX_PBUFFER_BIT )
if ( winScreen - > has_WGL_ARB_pbuffer )
SET_ATTR_VALUE ( WGL_DRAW_TO_PBUFFER_ARB , TRUE ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
else
{
if ( drawableTypeOverride & GLX_PIXMAP_BIT )
SET_ATTR_VALUE ( WGL_DRAW_TO_BITMAP_ARB , TRUE ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( drawableTypeOverride & GLX_PBUFFER_BIT )
if ( winScreen - > has_WGL_ARB_pbuffer )
SET_ATTR_VALUE ( WGL_DRAW_TO_PBUFFER_ARB , TRUE ) ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
SET_ATTR_VALUE ( 0 , 0 ) ; // terminator
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* choose the first match */
{
int pixelFormatIndex ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! wglChoosePixelFormatARBWrapper ( hdc , attribList , NULL , 1 , & pixelFormatIndex , & numFormats ) )
{
ErrorF ( " wglChoosePixelFormat error: %s \n " , glxWinErrorMessage ( ) ) ;
}
else
{
if ( numFormats > 0 )
{
GLWIN_DEBUG_MSG ( " wglChoosePixelFormat: chose pixelFormatIndex %d) " , pixelFormatIndex ) ;
return pixelFormatIndex ;
}
else
ErrorF ( " wglChoosePixelFormat couldn't decide \n " ) ;
}
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
return 0 ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* ---------------------------------------------------------------------- */
# define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
//
// Create the GLXconfigs using DescribePixelFormat()
//
static void
glxWinCreateConfigs ( HDC hdc , glxWinScreen * screen )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
GLXWinConfig * c , * result , * prev = NULL ;
int numConfigs = 0 ;
int i = 0 ;
int n = 0 ;
PIXELFORMATDESCRIPTOR pfd ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " glxWinCreateConfigs " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
screen - > base . numFBConfigs = 0 ;
screen - > base . fbconfigs = NULL ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
// get the number of pixelformats
numConfigs = DescribePixelFormat ( hdc , 1 , sizeof ( PIXELFORMATDESCRIPTOR ) , NULL ) ;
GLWIN_DEBUG_MSG ( " DescribePixelFormat says %d possible pixel formats " , numConfigs ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* alloc */
2010-05-05 20:44:06 +02:00
result = malloc ( sizeof ( GLXWinConfig ) * numConfigs ) ;
2009-11-07 20:28:18 +01:00
if ( NULL = = result )
2004-06-21 15:35:05 +02:00
{
2009-11-07 20:28:18 +01:00
return ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
memset ( result , 0 , sizeof ( GLXWinConfig ) * numConfigs ) ;
n = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* fill in configs */
for ( i = 0 ; i < numConfigs ; i + + )
{
int rc ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c = & ( result [ i ] ) ;
c - > base . next = NULL ;
c - > pixelFormatIndex = i + 1 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
rc = DescribePixelFormat ( hdc , i + 1 , sizeof ( PIXELFORMATDESCRIPTOR ) , & pfd ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! rc )
{
ErrorF ( " DescribePixelFormat failed for index %d, error %s \n " , i + 1 , glxWinErrorMessage ( ) ) ;
break ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
if ( glxWinDebugSettings . dumpPFD )
pfdOut ( & pfd ) ;
if ( ! ( pfd . dwFlags & ( PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP ) ) | | ! ( pfd . dwFlags & PFD_SUPPORT_OPENGL ) )
{
GLWIN_DEBUG_MSG ( " pixelFormat %d has unsuitable flags 0x%08lx, skipping " , i + 1 , pfd . dwFlags ) ;
continue ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
c - > base . doubleBufferMode = ( pfd . dwFlags & PFD_DOUBLEBUFFER ) ? GL_TRUE : GL_FALSE ;
c - > base . stereoMode = ( pfd . dwFlags & PFD_STEREO ) ? GL_TRUE : GL_FALSE ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . redBits = pfd . cRedBits ;
c - > base . greenBits = pfd . cGreenBits ;
c - > base . blueBits = pfd . cBlueBits ;
c - > base . alphaBits = pfd . cAlphaBits ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . redMask = BITS_AND_SHIFT_TO_MASK ( pfd . cRedBits , pfd . cRedShift ) ;
c - > base . greenMask = BITS_AND_SHIFT_TO_MASK ( pfd . cGreenBits , pfd . cGreenShift ) ;
c - > base . blueMask = BITS_AND_SHIFT_TO_MASK ( pfd . cBlueBits , pfd . cBlueShift ) ;
c - > base . alphaMask = BITS_AND_SHIFT_TO_MASK ( pfd . cAlphaBits , pfd . cAlphaShift ) ;
c - > base . rgbBits = pfd . cColorBits ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( pfd . iPixelType = = PFD_TYPE_COLORINDEX )
{
c - > base . indexBits = pfd . cColorBits ;
}
else
{
c - > base . indexBits = 0 ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
c - > base . accumRedBits = pfd . cAccumRedBits ;
c - > base . accumGreenBits = pfd . cAccumGreenBits ;
c - > base . accumBlueBits = pfd . cAccumBlueBits ;
c - > base . accumAlphaBits = pfd . cAccumAlphaBits ;
// pfd.cAccumBits;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . depthBits = pfd . cDepthBits ;
c - > base . stencilBits = pfd . cStencilBits ;
c - > base . numAuxBuffers = pfd . cAuxBuffers ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
// pfd.iLayerType; // ignored
c - > base . level = 0 ;
// pfd.dwLayerMask; // ignored
// pfd.dwDamageMask; // ignored
c - > base . pixmapMode = 0 ;
c - > base . visualID = - 1 ; // will be set by __glXScreenInit()
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_visual_rating / GLX 1.2 */
if ( pfd . dwFlags & PFD_GENERIC_FORMAT )
{
c - > base . visualRating = GLX_SLOW_VISUAL_EXT ;
}
else
{
// PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated...
c - > base . visualRating = GLX_NONE_EXT ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* EXT_visual_info / GLX 1.2 */
if ( pfd . iPixelType = = PFD_TYPE_COLORINDEX )
{
c - > base . visualType = GLX_STATIC_COLOR ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! getenv ( " GLWIN_ENABLE_COLORINDEX_FBCONFIGS " ) )
{
GLWIN_DEBUG_MSG ( " pixelFormat %d is PFD_TYPE_COLORINDEX, skipping " , i + 1 ) ;
continue ;
}
}
else
{
c - > base . visualType = GLX_TRUE_COLOR ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
// pfd.dwVisibleMask; ???
c - > base . transparentPixel = GLX_NONE ;
c - > base . transparentRed = GLX_NONE ;
c - > base . transparentGreen = GLX_NONE ;
c - > base . transparentBlue = GLX_NONE ;
c - > base . transparentAlpha = GLX_NONE ;
c - > base . transparentIndex = GLX_NONE ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* ARB_multisample / SGIS_multisample */
c - > base . sampleBuffers = 0 ;
c - > base . samples = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* SGIX_fbconfig / GLX 1.3 */
c - > base . drawableType = ( ( ( pfd . dwFlags & PFD_DRAW_TO_WINDOW ) ? GLX_WINDOW_BIT : 0 )
| ( ( pfd . dwFlags & PFD_DRAW_TO_BITMAP ) ? GLX_PIXMAP_BIT : 0 ) ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( pfd . iPixelType = = PFD_TYPE_COLORINDEX )
{
c - > base . renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT ;
}
else
{
c - > base . renderType = GLX_RGBA_BIT ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . xRenderable = GL_TRUE ;
c - > base . fbconfigID = - 1 ; // will be set by __glXScreenInit()
2005-04-09 21:20:03 +02:00
2009-11-07 20:28:18 +01:00
/* SGIX_pbuffer / GLX 1.3 */
// XXX: How can we find these values out ???
c - > base . maxPbufferWidth = - 1 ;
c - > base . maxPbufferHeight = - 1 ;
c - > base . maxPbufferPixels = - 1 ;
c - > base . optimalPbufferWidth = 0 ; // there is no optimal value
c - > base . optimalPbufferHeight = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* SGIX_visual_select_group */
// arrange for visuals with the best acceleration to be preferred in selection
switch ( pfd . dwFlags & ( PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED ) )
{
case 0 :
c - > base . visualSelectGroup = 2 ;
break ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case PFD_GENERIC_ACCELERATED :
c - > base . visualSelectGroup = 1 ;
break ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case PFD_GENERIC_FORMAT :
c - > base . visualSelectGroup = 0 ;
break ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
default :
;
// "can't happen"
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* OML_swap_method */
if ( pfd . dwFlags & PFD_SWAP_EXCHANGE )
c - > base . swapMethod = GLX_SWAP_EXCHANGE_OML ;
else if ( pfd . dwFlags & PFD_SWAP_COPY )
c - > base . swapMethod = GLX_SWAP_COPY_OML ;
else
c - > base . swapMethod = GLX_SWAP_UNDEFINED_OML ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_import_context */
c - > base . screen = screen - > base . pScreen - > myNum ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_texture_from_pixmap */
c - > base . bindToTextureRgb = - 1 ;
c - > base . bindToTextureRgba = - 1 ;
c - > base . bindToMipmapTexture = - 1 ;
c - > base . bindToTextureTargets = - 1 ;
c - > base . yInverted = - 1 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
n + + ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
// update previous config to point to this config
if ( prev )
prev - > base . next = & ( c - > base ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
prev = c ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " found %d pixelFormats suitable for conversion to fbConfigs " , n ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
screen - > base . numFBConfigs = n ;
screen - > base . fbconfigs = & ( result - > base ) ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
// helper function to access an attribute value from an attribute value array by attribute
static
int getAttrValue ( const int attrs [ ] , int values [ ] , unsigned int num , int attr , int fallback )
{
unsigned int i ;
for ( i = 0 ; i < num ; i + + )
{
if ( attrs [ i ] = = attr )
2005-03-01 19:58:17 +01:00
{
2009-11-07 20:28:18 +01:00
GLWIN_TRACE_MSG ( " getAttrValue attr 0x%x, value %d " , attr , values [ i ] ) ;
return values [ i ] ;
}
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
ErrorF ( " getAttrValue failed to find attr 0x%x, using default value %d \n " , attr , fallback ) ;
return fallback ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
//
// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
//
static void
glxWinCreateConfigsExt ( HDC hdc , glxWinScreen * screen )
{
GLXWinConfig * c , * result , * prev = NULL ;
int i = 0 ;
int n = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB ;
int numConfigs ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
int attrs [ 50 ] ;
unsigned int num_attrs = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " glxWinCreateConfigsExt " ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
screen - > base . numFBConfigs = 0 ;
screen - > base . fbconfigs = NULL ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! wglGetPixelFormatAttribivARBWrapper ( hdc , 0 , 0 , 1 , & attr , & numConfigs ) )
{
ErrorF ( " wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s \n " , glxWinErrorMessage ( ) ) ;
return ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
GLWIN_DEBUG_MSG ( " wglGetPixelFormatAttribivARB says %d possible pixel formats " , numConfigs ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
/* alloc */
2010-05-05 20:44:06 +02:00
result = malloc ( sizeof ( GLXWinConfig ) * numConfigs ) ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
if ( NULL = = result )
{
return ;
}
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
memset ( result , 0 , sizeof ( GLXWinConfig ) * numConfigs ) ;
n = 0 ;
# define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < NUM_ELEMENTS(attrs)); }
ADD_ATTR ( WGL_DRAW_TO_WINDOW_ARB ) ;
ADD_ATTR ( WGL_DRAW_TO_BITMAP_ARB ) ;
ADD_ATTR ( WGL_ACCELERATION_ARB ) ;
ADD_ATTR ( WGL_SWAP_LAYER_BUFFERS_ARB ) ;
ADD_ATTR ( WGL_NUMBER_OVERLAYS_ARB ) ;
ADD_ATTR ( WGL_NUMBER_UNDERLAYS_ARB ) ;
ADD_ATTR ( WGL_TRANSPARENT_ARB ) ;
ADD_ATTR ( WGL_TRANSPARENT_RED_VALUE_ARB ) ;
ADD_ATTR ( WGL_TRANSPARENT_GREEN_VALUE_ARB ) ;
ADD_ATTR ( WGL_TRANSPARENT_GREEN_VALUE_ARB ) ;
ADD_ATTR ( WGL_TRANSPARENT_ALPHA_VALUE_ARB ) ;
ADD_ATTR ( WGL_SUPPORT_OPENGL_ARB ) ;
ADD_ATTR ( WGL_DOUBLE_BUFFER_ARB ) ;
ADD_ATTR ( WGL_STEREO_ARB ) ;
ADD_ATTR ( WGL_PIXEL_TYPE_ARB ) ;
ADD_ATTR ( WGL_COLOR_BITS_ARB ) ;
ADD_ATTR ( WGL_RED_BITS_ARB ) ;
ADD_ATTR ( WGL_RED_SHIFT_ARB ) ;
ADD_ATTR ( WGL_GREEN_BITS_ARB ) ;
ADD_ATTR ( WGL_GREEN_SHIFT_ARB ) ;
ADD_ATTR ( WGL_BLUE_BITS_ARB ) ;
ADD_ATTR ( WGL_BLUE_SHIFT_ARB ) ;
ADD_ATTR ( WGL_ALPHA_BITS_ARB ) ;
ADD_ATTR ( WGL_ALPHA_SHIFT_ARB ) ;
ADD_ATTR ( WGL_ACCUM_RED_BITS_ARB ) ;
ADD_ATTR ( WGL_ACCUM_GREEN_BITS_ARB ) ;
ADD_ATTR ( WGL_ACCUM_BLUE_BITS_ARB ) ;
ADD_ATTR ( WGL_ACCUM_ALPHA_BITS_ARB ) ;
ADD_ATTR ( WGL_DEPTH_BITS_ARB ) ;
ADD_ATTR ( WGL_STENCIL_BITS_ARB ) ;
ADD_ATTR ( WGL_AUX_BUFFERS_ARB ) ;
ADD_ATTR ( WGL_SWAP_METHOD_ARB ) ;
if ( screen - > has_WGL_ARB_multisample )
{
// we may not query these attrs if WGL_ARB_multisample is not offered
ADD_ATTR ( WGL_SAMPLE_BUFFERS_ARB ) ;
ADD_ATTR ( WGL_SAMPLES_ARB ) ;
}
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
if ( screen - > has_WGL_ARB_render_texture )
{
// we may not query these attrs if WGL_ARB_render_texture is not offered
ADD_ATTR ( WGL_BIND_TO_TEXTURE_RGB_ARB ) ;
ADD_ATTR ( WGL_BIND_TO_TEXTURE_RGBA_ARB ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
if ( screen - > has_WGL_ARB_pbuffer )
{
// we may not query these attrs if WGL_ARB_pbuffer is not offered
ADD_ATTR ( WGL_DRAW_TO_PBUFFER_ARB ) ;
ADD_ATTR ( WGL_MAX_PBUFFER_PIXELS_ARB ) ;
ADD_ATTR ( WGL_MAX_PBUFFER_WIDTH_ARB ) ;
ADD_ATTR ( WGL_MAX_PBUFFER_HEIGHT_ARB ) ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
/* fill in configs */
for ( i = 0 ; i < numConfigs ; i + + )
{
int values [ num_attrs ] ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c = & ( result [ i ] ) ;
c - > base . next = NULL ;
c - > pixelFormatIndex = i + 1 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! wglGetPixelFormatAttribivARBWrapper ( hdc , i + 1 , 0 , num_attrs , attrs , values ) )
{
ErrorF ( " wglGetPixelFormatAttribivARB failed for index %d, error %s \n " , i + 1 , glxWinErrorMessage ( ) ) ;
break ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
# define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! ATTR_VALUE ( WGL_SUPPORT_OPENGL_ARB , 0 ) )
{
GLWIN_DEBUG_MSG ( " pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping " , i + 1 ) ;
continue ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . doubleBufferMode = ATTR_VALUE ( WGL_DOUBLE_BUFFER_ARB , 0 ) ? GL_TRUE : GL_FALSE ;
c - > base . stereoMode = ATTR_VALUE ( WGL_STEREO_ARB , 0 ) ? GL_TRUE : GL_FALSE ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . redBits = ATTR_VALUE ( WGL_RED_BITS_ARB , 0 ) ;
c - > base . greenBits = ATTR_VALUE ( WGL_GREEN_BITS_ARB , 0 ) ;
c - > base . blueBits = ATTR_VALUE ( WGL_BLUE_BITS_ARB , 0 ) ;
c - > base . alphaBits = ATTR_VALUE ( WGL_ALPHA_BITS_ARB , 0 ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . redMask = BITS_AND_SHIFT_TO_MASK ( c - > base . redBits , ATTR_VALUE ( WGL_RED_SHIFT_ARB , 0 ) ) ;
c - > base . greenMask = BITS_AND_SHIFT_TO_MASK ( c - > base . greenBits , ATTR_VALUE ( WGL_GREEN_SHIFT_ARB , 0 ) ) ;
c - > base . blueMask = BITS_AND_SHIFT_TO_MASK ( c - > base . blueBits , ATTR_VALUE ( WGL_BLUE_SHIFT_ARB , 0 ) ) ;
c - > base . alphaMask = BITS_AND_SHIFT_TO_MASK ( c - > base . alphaBits , ATTR_VALUE ( WGL_ALPHA_SHIFT_ARB , 0 ) ) ;
switch ( ATTR_VALUE ( WGL_PIXEL_TYPE_ARB , 0 ) )
{
case WGL_TYPE_COLORINDEX_ARB :
c - > base . indexBits = ATTR_VALUE ( WGL_COLOR_BITS_ARB , 0 ) ;
c - > base . rgbBits = 0 ;
c - > base . visualType = GLX_STATIC_COLOR ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( ! getenv ( " GLWIN_ENABLE_COLORINDEX_FBCONFIGS " ) )
{
GLWIN_DEBUG_MSG ( " pixelFormat %d is WGL_TYPE_COLORINDEX_ARB, skipping " , i + 1 ) ;
continue ;
2004-06-21 15:35:05 +02:00
}
2009-11-07 20:28:18 +01:00
break ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
case WGL_TYPE_RGBA_FLOAT_ARB :
GLWIN_DEBUG_MSG ( " pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping " , i + 1 ) ;
continue ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT :
GLWIN_DEBUG_MSG ( " pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping " , i + 1 ) ;
continue ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case WGL_TYPE_RGBA_ARB :
c - > base . indexBits = 0 ;
c - > base . rgbBits = ATTR_VALUE ( WGL_COLOR_BITS_ARB , 0 ) ;
c - > base . visualType = GLX_TRUE_COLOR ;
break ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
default :
ErrorF ( " wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB \n " , ATTR_VALUE ( WGL_PIXEL_TYPE_ARB , 0 ) ) ;
continue ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . accumRedBits = ATTR_VALUE ( WGL_ACCUM_RED_BITS_ARB , 0 ) ;
c - > base . accumGreenBits = ATTR_VALUE ( WGL_ACCUM_GREEN_BITS_ARB , 0 ) ;
c - > base . accumBlueBits = ATTR_VALUE ( WGL_ACCUM_BLUE_BITS_ARB , 0 ) ;
c - > base . accumAlphaBits = ATTR_VALUE ( WGL_ACCUM_ALPHA_BITS_ARB , 0 ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . depthBits = ATTR_VALUE ( WGL_DEPTH_BITS_ARB , 0 ) ;
c - > base . stencilBits = ATTR_VALUE ( WGL_STENCIL_BITS_ARB , 0 ) ;
c - > base . numAuxBuffers = ATTR_VALUE ( WGL_AUX_BUFFERS_ARB , 0 ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
{
int layers = ATTR_VALUE ( WGL_NUMBER_OVERLAYS_ARB , 0 ) + ATTR_VALUE ( WGL_NUMBER_UNDERLAYS_ARB , 0 ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
if ( layers > 0 )
{
ErrorF ( " pixelFormat %d: has %d overlay, %d underlays which aren't currently handled " , i , ATTR_VALUE ( WGL_NUMBER_OVERLAYS_ARB , 0 ) , ATTR_VALUE ( WGL_NUMBER_UNDERLAYS_ARB , 0 ) ) ;
// XXX: need to iterate over layers?
}
}
c - > base . level = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . pixmapMode = 0 ; // ???
c - > base . visualID = - 1 ; // will be set by __glXScreenInit()
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_visual_rating / GLX 1.2 */
switch ( ATTR_VALUE ( WGL_ACCELERATION_ARB , 0 ) )
{
default :
ErrorF ( " wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB \n " , ATTR_VALUE ( WGL_ACCELERATION_ARB , 0 ) ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case WGL_NO_ACCELERATION_ARB :
c - > base . visualRating = GLX_SLOW_VISUAL_EXT ;
break ;
2005-03-01 19:58:17 +01:00
2009-11-07 20:28:18 +01:00
case WGL_GENERIC_ACCELERATION_ARB :
case WGL_FULL_ACCELERATION_ARB :
c - > base . visualRating = GLX_NONE_EXT ;
break ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_visual_info / GLX 1.2 */
// c->base.visualType is set above
if ( ATTR_VALUE ( WGL_TRANSPARENT_ARB , 0 ) )
{
c - > base . transparentPixel = ( c - > base . visualType = = GLX_TRUE_COLOR ) ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT ;
c - > base . transparentRed = ATTR_VALUE ( WGL_TRANSPARENT_RED_VALUE_ARB , 0 ) ;
c - > base . transparentGreen = ATTR_VALUE ( WGL_TRANSPARENT_GREEN_VALUE_ARB , 0 ) ;
c - > base . transparentBlue = ATTR_VALUE ( WGL_TRANSPARENT_BLUE_VALUE_ARB , 0 ) ;
c - > base . transparentAlpha = ATTR_VALUE ( WGL_TRANSPARENT_ALPHA_VALUE_ARB , 0 ) ;
c - > base . transparentIndex = ATTR_VALUE ( WGL_TRANSPARENT_INDEX_VALUE_ARB , 0 ) ;
}
else
{
c - > base . transparentPixel = GLX_NONE_EXT ;
c - > base . transparentRed = GLX_NONE ;
c - > base . transparentGreen = GLX_NONE ;
c - > base . transparentBlue = GLX_NONE ;
c - > base . transparentAlpha = GLX_NONE ;
c - > base . transparentIndex = GLX_NONE ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* ARB_multisample / SGIS_multisample */
if ( screen - > has_WGL_ARB_multisample )
{
c - > base . sampleBuffers = ATTR_VALUE ( WGL_SAMPLE_BUFFERS_ARB , 0 ) ;
c - > base . samples = ATTR_VALUE ( WGL_SAMPLES_ARB , 0 ) ;
}
else
{
c - > base . sampleBuffers = 0 ;
c - > base . samples = 0 ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* SGIX_fbconfig / GLX 1.3 */
c - > base . drawableType = ( ( ATTR_VALUE ( WGL_DRAW_TO_WINDOW_ARB , 0 ) ? GLX_WINDOW_BIT : 0 )
| ( ATTR_VALUE ( WGL_DRAW_TO_BITMAP_ARB , 0 ) ? GLX_PIXMAP_BIT : 0 )
| ( ATTR_VALUE ( WGL_DRAW_TO_PBUFFER_ARB , 0 ) ? GLX_PBUFFER_BIT : 0 ) ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/*
Assume OpenGL RGBA rendering is available on all visuals
( it is specified to render to red component in single - channel visuals ,
if supported , but there doesn ' t seem to be any mechanism to check if it
is supported )
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
Color index rendering is only supported on single - channel visuals
*/
if ( c - > base . visualType = = GLX_STATIC_COLOR )
{
c - > base . renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT ;
}
else
{
c - > base . renderType = GLX_RGBA_BIT ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
c - > base . xRenderable = GL_TRUE ;
c - > base . fbconfigID = - 1 ; // will be set by __glXScreenInit()
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* SGIX_pbuffer / GLX 1.3 */
if ( screen - > has_WGL_ARB_pbuffer )
{
c - > base . maxPbufferWidth = ATTR_VALUE ( WGL_MAX_PBUFFER_WIDTH_ARB , - 1 ) ;
c - > base . maxPbufferHeight = ATTR_VALUE ( WGL_MAX_PBUFFER_HEIGHT_ARB , - 1 ) ;
c - > base . maxPbufferPixels = ATTR_VALUE ( WGL_MAX_PBUFFER_PIXELS_ARB , - 1 ) ;
}
else
{
c - > base . maxPbufferWidth = - 1 ;
c - > base . maxPbufferHeight = - 1 ;
c - > base . maxPbufferPixels = - 1 ;
}
c - > base . optimalPbufferWidth = 0 ; // there is no optimal value
c - > base . optimalPbufferHeight = 0 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* SGIX_visual_select_group */
// arrange for visuals with the best acceleration to be preferred in selection
switch ( ATTR_VALUE ( WGL_ACCELERATION_ARB , 0 ) )
{
case WGL_FULL_ACCELERATION_ARB :
c - > base . visualSelectGroup = 2 ;
break ;
case WGL_GENERIC_ACCELERATION_ARB :
c - > base . visualSelectGroup = 1 ;
break ;
default :
case WGL_NO_ACCELERATION_ARB :
c - > base . visualSelectGroup = 0 ;
break ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* OML_swap_method */
switch ( ATTR_VALUE ( WGL_SWAP_METHOD_ARB , 0 ) )
{
case WGL_SWAP_EXCHANGE_ARB :
c - > base . swapMethod = GLX_SWAP_EXCHANGE_OML ;
break ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case WGL_SWAP_COPY_ARB :
c - > base . swapMethod = GLX_SWAP_COPY_OML ;
break ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
default :
ErrorF ( " wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB \n " , ATTR_VALUE ( WGL_SWAP_METHOD_ARB , 0 ) ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
case WGL_SWAP_UNDEFINED_ARB :
c - > base . swapMethod = GLX_SWAP_UNDEFINED_OML ;
2005-03-01 19:58:17 +01:00
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_import_context */
c - > base . screen = screen - > base . pScreen - > myNum ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
/* EXT_texture_from_pixmap */
/*
Mesa ' s DRI configs always have bindToTextureRgb / Rgba TRUE ( see driCreateConfigs ( ) , so setting
bindToTextureRgb / bindToTextureRgba to FALSE means that swrast can ' t find any fbConfigs to use ,
so setting these to 0 , even if we know bindToTexture isn ' t available , isn ' t a good idea . . .
*/
if ( screen - > has_WGL_ARB_render_texture )
{
c - > base . bindToTextureRgb = ATTR_VALUE ( WGL_BIND_TO_TEXTURE_RGB_ARB , - 1 ) ;
c - > base . bindToTextureRgba = ATTR_VALUE ( WGL_BIND_TO_TEXTURE_RGBA_ARB , - 1 ) ;
}
else
{
c - > base . bindToTextureRgb = - 1 ;
c - > base . bindToTextureRgba = - 1 ;
}
c - > base . bindToMipmapTexture = - 1 ;
c - > base . bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT ;
c - > base . yInverted = - 1 ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
n + + ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
// update previous config to point to this config
if ( prev )
prev - > base . next = & ( c - > base ) ;
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
prev = c ;
}
2004-06-21 15:35:05 +02:00
2009-11-07 20:28:18 +01:00
screen - > base . numFBConfigs = n ;
screen - > base . fbconfigs = & ( result - > base ) ;
2004-06-21 15:35:05 +02:00
}