2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/opengl32/wgl.c
5 * PURPOSE: OpenGL32 lib, rosglXXX functions
6 * PROGRAMMER: Anich Gregor (blight)
11 #define OPENGL32_GL_FUNC_PROTOTYPES
16 #endif /* __cplusplus */
18 #if !defined(UNIMPLEMENTED)
19 # define UNIMPLEMENTED DBGPRINT( "UNIMPLEMENTED" )
23 typedef struct _OPENGL_INFO
25 DWORD Version
; /*!< Driver interface version */
26 DWORD DriverVersion
; /*!< Driver version */
27 WCHAR DriverName
[256]; /*!< Driver name */
28 } OPENGL_INFO
, *POPENGL_INFO
;
31 /*! \brief Append OpenGL Rendering Context (GLRC) to list
33 * \param glrc [IN] Pointer to GLRC to append to list
37 ROSGL_AppendContext( GLRC
*glrc
)
40 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
43 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
44 return; /* FIXME: do we have to expect such an error and handle it? */
47 if (OPENGL32_processdata
.glrc_list
== NULL
)
48 OPENGL32_processdata
.glrc_list
= glrc
;
51 GLRC
*p
= OPENGL32_processdata
.glrc_list
;
52 while (p
->next
!= NULL
)
58 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
59 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
63 /*! \brief Remove OpenGL Rendering Context (GLRC) from list
65 * \param glrc [IN] Pointer to GLRC to remove from list
69 ROSGL_RemoveContext( GLRC
*glrc
)
72 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
75 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
76 return; /* FIXME: do we have to expect such an error and handle it? */
79 if (glrc
== OPENGL32_processdata
.glrc_list
)
80 OPENGL32_processdata
.glrc_list
= glrc
->next
;
83 GLRC
*p
= OPENGL32_processdata
.glrc_list
;
94 DBGPRINT( "Error: GLRC 0x%08x not found in list!", glrc
);
98 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
99 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
103 /*! \brief Create a new GL Context (GLRC) and append it to the list
105 * \return Pointer to new GLRC on success
106 * \retval NULL Returned on failure (i.e. Out of memory)
110 ROSGL_NewContext(void)
115 glrc
= (GLRC
*)HeapAlloc( GetProcessHeap(),
116 HEAP_ZERO_MEMORY
| HEAP_GENERATE_EXCEPTIONS
, sizeof (GLRC
) );
119 ROSGL_AppendContext( glrc
);
124 /*! \brief Delete all GLDCDATA with this IDC
126 * \param icd [IN] Pointer to a ICD
130 ROSGL_DeleteDCDataForICD( GLDRIVERDATA
*icd
)
135 if (WaitForSingleObject( OPENGL32_processdata
.dcdata_mutex
, INFINITE
) ==
138 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
142 p
= OPENGL32_processdata
.dcdata_list
;
143 pptr
= &OPENGL32_processdata
.dcdata_list
;
149 OPENGL32_UnloadICD( p
->icd
);
151 if (!HeapFree( GetProcessHeap(), 0, p
))
152 DBGPRINT( "Warning: HeapFree() on GLDCDATA failed (%d)",
165 if (!ReleaseMutex( OPENGL32_processdata
.dcdata_mutex
))
166 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
170 /*! \brief Delete a GL Context (GLRC) and remove it from the list
172 * \param glrc [IN] Pointer to GLRC to delete
174 * \retval TRUE Success
175 * \retval FALSE Failure
179 ROSGL_DeleteContext( GLRC
*glrc
)
182 if (glrc
->icd
!= NULL
)
183 ROSGL_DeleteDCDataForICD( glrc
->icd
);
185 /* remove from list */
186 ROSGL_RemoveContext( glrc
);
189 HeapFree( GetProcessHeap(), 0, glrc
);
195 /*! \brief Check wether a GLRC is in the list
197 * \param glrc [IN] Pointer to GLRC to look for in the list
199 * \retval TRUE GLRC was found
200 * \retval FALSE GLRC was not found
204 ROSGL_ContainsContext( GLRC
*glrc
)
210 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
213 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
214 return FALSE
; /* FIXME: do we have to expect such an error and handle it? */
217 p
= OPENGL32_processdata
.glrc_list
;
229 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
230 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
236 /*! \brief Get GL private DC data.
238 * This function adds an empty GLDCDATA to the list if there is no data for the
241 * \param hdc [IN] Handle to a Device Context for which to get the data
243 * \return Pointer to GLDCDATA on success
244 * \retval NULL on failure
248 ROSGL_GetPrivateDCData( HDC hdc
)
253 if (GetObjectType( hdc
) != OBJ_DC
&& GetObjectType( hdc
) != OBJ_MEMDC
)
255 DBGPRINT( "Error: hdc is not a DC handle!" );
256 SetLastError( ERROR_INVALID_HANDLE
);
261 if (WaitForSingleObject( OPENGL32_processdata
.dcdata_mutex
, INFINITE
) ==
264 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
265 return NULL
; /* FIXME: do we have to expect such an error and handle it? */
268 /* look for data in list */
269 data
= OPENGL32_processdata
.dcdata_list
;
272 if (data
->hdc
== hdc
) /* found */
277 /* allocate new data if not found in list */
280 data
= HeapAlloc( GetProcessHeap(),
281 HEAP_ZERO_MEMORY
| HEAP_GENERATE_EXCEPTIONS
,
285 DBGPRINT( "Error: HeapAlloc() failed (%d)", GetLastError() );
291 /* append data to list */
292 if (OPENGL32_processdata
.dcdata_list
== NULL
)
293 OPENGL32_processdata
.dcdata_list
= data
;
296 GLDCDATA
*p
= OPENGL32_processdata
.dcdata_list
;
297 while (p
->next
!= NULL
)
305 if (!ReleaseMutex( OPENGL32_processdata
.dcdata_mutex
))
306 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
312 /*! \brief Get ICD from HDC.
314 * This function asks the display driver which OpenGL ICD to load for the given
315 * HDC, loads it and returns a pointer to a GLDRIVERDATA struct on success.
317 * \param hdc [IN] Handle for DC for which to load/get the ICD
319 * \return Pointer to GLDRIVERDATA
320 * \retval NULL Failure.
324 ROSGL_ICDForHDC( HDC hdc
)
327 GLDRIVERDATA
*drvdata
;
329 dcdata
= ROSGL_GetPrivateDCData( hdc
);
333 if (dcdata
->icd
== NULL
)
338 /* NOTE: This might be done by multiple threads simultaneously, but only the fastest
339 actually gets to set the ICD! */
341 driverName
= _wgetenv( L
"OPENGL32_DRIVER" );
342 if (driverName
== NULL
)
347 /* get driver name */
348 dwInput
= OPENGL_GETINFO
;
349 ret
= ExtEscape( hdc
, QUERYESCSUPPORT
, sizeof (dwInput
), (LPCSTR
)&dwInput
, 0, NULL
);
353 ret
= ExtEscape( hdc
, OPENGL_GETINFO
, sizeof (dwInput
),
354 (LPCSTR
)&dwInput
, sizeof (OPENGL_INFO
),
364 DBGPRINT( "Warning: ExtEscape to get the drivername failed! (%d)", GetLastError() );
365 if (MessageBox( WindowFromDC( hdc
), L
"Couldn't get installable client driver name!\nUsing default driver.",
366 L
"OPENGL32.dll: Warning", MB_OKCANCEL
| MB_ICONWARNING
) == IDCANCEL
)
372 /* open registry key */
373 ret
= RegOpenKeyExW( HKEY_LOCAL_MACHINE
, OPENGL_DRIVERS_SUBKEY
, 0, KEY_QUERY_VALUE
, &hKey
);
374 if (ret
!= ERROR_SUCCESS
)
376 DBGPRINT( "Error: Couldn't open registry key '%ws'", OPENGL_DRIVERS_SUBKEY
);
382 size
= sizeof (info
.DriverName
);
383 ret
= RegQueryValueExW( hKey
, L
"DefaultDriver", 0, &type
, (LPBYTE
)info
.DriverName
, &size
);
385 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
387 DBGPRINT( "Error: Couldn't query DefaultDriver value or not a string" );
395 wcsncpy( info
.DriverName
, driverName
, sizeof (info
.DriverName
) / sizeof (info
.DriverName
[0]) );
397 /* load driver (or get a reference) */
398 drvdata
= OPENGL32_LoadICD( info
.DriverName
);
402 snwprintf(Buffer
, sizeof(Buffer
)/sizeof(WCHAR
),
403 L
"Couldn't load driver \"%s\".", driverName
);
404 MessageBox(WindowFromDC( hdc
), Buffer
,
405 L
"OPENGL32.dll: Warning",
406 MB_OK
| MB_ICONWARNING
);
410 /* Atomically set the ICD!!! */
411 if (InterlockedCompareExchangePointer((PVOID
*)&dcdata
->icd
,
415 /* Too bad, somebody else was faster... */
416 OPENGL32_UnloadICD(drvdata
);
425 /*! \brief SetContextCallBack passed to DrvSetContext.
427 * This function gets called by the OpenGL driver whenever the current GL
428 * context (dispatch table) is to be changed.
430 * \param table [IN] Function pointer table (first DWORD is number of functions)
432 * \return unkown (maybe void? ERROR_SUCCESS at the moment)
436 ROSGL_SetContextCallBack( const ICDTable
*table
)
439 PROC
*tebTable
, *tebDispatchTable
;
442 teb
= NtCurrentTeb();
443 tebTable
= (PROC
*)teb
->glTable
;
444 tebDispatchTable
= (PROC
*)teb
->glDispatchTable
;
446 DBGTRACE( "Called!" );
450 DBGPRINT( "Function count: %d\n", table
->num_funcs
);
453 size
= sizeof (PROC
) * table
->num_funcs
;
454 memcpy( tebTable
, table
->dispatch_table
, size
);
455 memset( tebTable
+ table
->num_funcs
, 0,
456 sizeof (table
->dispatch_table
) - size
);
460 DBGPRINT( "Unsetting current context" );
461 memset( tebTable
, 0, sizeof (table
->dispatch_table
) );
464 /* put in empty functions as long as we dont have a fallback */
465 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
466 if (tebTable[icdidx] == NULL) \
469 DBGPRINT( "Warning: GL proc '%s' is NULL", #func ); \
470 tebTable[icdidx] = (PROC)glEmptyFunc##stack; \
475 /* fill teb->glDispatchTable for fast calls */
476 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
478 tebDispatchTable[tebidx] = tebTable[icdidx];
484 return ERROR_SUCCESS
;
488 /*! \brief Attempts to find the best matching pixel format for HDC
490 * This function is comparing each available format with the preferred one
491 * and returns the one which is closest to it.
492 * If PFD_DOUBLEBUFFER, PFD_STEREO or one of PFD_DRAW_TO_WINDOW,
493 * PFD_DRAW_TO_BITMAP, PFD_SUPPORT_GDI and PDF_SUPPORT_OPENGL is given then
494 * only formats which also support those will be enumerated (unless
495 * PFD_DOUBLEBUFFER_DONTCARE or PFD_STEREO_DONTCARE is also set)
497 * \param hdc [IN] Handle to DC for which to get a pixel format index
498 * \param pfd [IN] PFD describing what kind of format you want
500 * \return Pixel format index
501 * \retval 0 Failed to find a suitable format
503 #define BUFFERDEPTH_SCORE(want, have) \
504 ((want == 0) ? (0) : ((want < have) ? (1) : ((want > have) ? (3) : (0))))
507 rosglChoosePixelFormat( HDC hdc
, CONST PIXELFORMATDESCRIPTOR
*pfd
)
510 PIXELFORMATDESCRIPTOR icdPfd
;
513 int score
, bestScore
= 0x7fff; /* used to choose a pfd if no exact match */
515 const DWORD compareFlags
= PFD_DRAW_TO_WINDOW
| PFD_DRAW_TO_BITMAP
|
516 PFD_SUPPORT_GDI
| PFD_SUPPORT_OPENGL
;
518 DBGTRACE( "Called!" );
521 icd
= ROSGL_ICDForHDC( hdc
);
526 if (pfd
->nSize
!= sizeof (PIXELFORMATDESCRIPTOR
) || pfd
->nVersion
!= 1)
528 SetLastError( ERROR_INVALID_PARAMETER
);
532 /* get number of formats */
533 icdNumFormats
= icd
->DrvDescribePixelFormat( hdc
, 1,
534 sizeof (PIXELFORMATDESCRIPTOR
), &icdPfd
);
535 if (icdNumFormats
== 0)
537 DBGPRINT( "Error: DrvDescribePixelFormat failed (%d)", GetLastError() );
540 DBGPRINT( "Info: Enumerating %d pixelformats", icdNumFormats
);
542 /* try to find best format */
543 for (i
= 0; i
< icdNumFormats
; i
++)
545 if (icd
->DrvDescribePixelFormat( hdc
, i
+ 1,
546 sizeof (PIXELFORMATDESCRIPTOR
), &icdPfd
) == 0)
548 DBGPRINT( "Warning: DrvDescribePixelFormat failed (%d)",
553 if ((pfd
->dwFlags
& PFD_GENERIC_ACCELERATED
) != 0) /* we do not support such kind of drivers */
559 if ((pfd
->dwFlags
& compareFlags
) != (icdPfd
.dwFlags
& compareFlags
))
561 if (!(pfd
->dwFlags
& PFD_DOUBLEBUFFER_DONTCARE
) &&
562 ((pfd
->dwFlags
& PFD_DOUBLEBUFFER
) != (icdPfd
.dwFlags
& PFD_DOUBLEBUFFER
)))
564 if (!(pfd
->dwFlags
& PFD_STEREO_DONTCARE
) &&
565 ((pfd
->dwFlags
& PFD_STEREO
) != (icdPfd
.dwFlags
& PFD_STEREO
)))
568 /* check other attribs */
569 score
= 0; /* higher is worse */
570 if (pfd
->iPixelType
!= icdPfd
.iPixelType
)
571 score
+= 5; /* this is really bad i think */
572 if (pfd
->iLayerType
!= icdPfd
.iLayerType
)
573 score
+= 15; /* this is very very bad ;) */
575 score
+= BUFFERDEPTH_SCORE(pfd
->cAlphaBits
, icdPfd
.cAlphaBits
);
576 score
+= BUFFERDEPTH_SCORE(pfd
->cAccumBits
, icdPfd
.cAccumBits
);
577 score
+= BUFFERDEPTH_SCORE(pfd
->cDepthBits
, icdPfd
.cDepthBits
);
578 score
+= BUFFERDEPTH_SCORE(pfd
->cStencilBits
, icdPfd
.cStencilBits
);
579 score
+= BUFFERDEPTH_SCORE(pfd
->cAuxBuffers
, icdPfd
.cAuxBuffers
);
582 if (score
< bestScore
)
592 SetLastError( 0 ); /* FIXME: set appropriate error */
594 DBGPRINT( "Info: Suggesting pixelformat %d", best
);
599 /*! \brief Copy data specified by mask from one GLRC to another.
601 * \param src [IN] Source GLRC
602 * \param src [OUT] Destination GLRC
603 * \param mask [IN] Bitfield like given to glPushAttrib()
605 * \retval TRUE Success
606 * \retval FALSE Failure
610 rosglCopyContext( HGLRC hsrc
, HGLRC hdst
, UINT mask
)
612 GLRC
*src
= (GLRC
*)hsrc
;
613 GLRC
*dst
= (GLRC
*)hdst
;
616 if (!ROSGL_ContainsContext( src
))
618 DBGPRINT( "Error: src GLRC not found!" );
619 SetLastError( ERROR_INVALID_HANDLE
);
622 if (!ROSGL_ContainsContext( dst
))
624 DBGPRINT( "Error: dst GLRC not found!" );
625 SetLastError( ERROR_INVALID_HANDLE
);
629 /* I think this is only possible within one ICD */
630 if (src
->icd
!= dst
->icd
)
632 DBGPRINT( "Error: src and dst GLRC use different ICDs!" );
633 SetLastError( ERROR_INVALID_HANDLE
);
637 /* copy data (call ICD) */
638 return src
->icd
->DrvCopyContext( src
->hglrc
, dst
->hglrc
, mask
);
642 /*! \brief Create a new GL Rendering Context.
644 * This function can create over- or underlay surfaces.
646 * \param hdc [IN] Handle for DC for which to create context
647 * \param layer [IN] Layer number to bind (draw?) to
649 * \return Handle for the created GLRC
650 * \retval NULL Failure
654 rosglCreateLayerContext( HDC hdc
, int layer
)
656 GLDRIVERDATA
*icd
= NULL
;
658 HGLRC drvHglrc
= NULL
;
660 DBGTRACE( "Called!" );
662 /* if (GetObjectType( hdc ) != OBJ_DC)
664 DBGPRINT( "Error: hdc is not a DC handle!" );
668 /* create new GLRC */
669 glrc
= ROSGL_NewContext();
674 icd
= ROSGL_ICDForHDC( hdc
);
677 ROSGL_DeleteContext( glrc
);
678 DBGPRINT( "Couldn't get ICD by HDC :-(" );
679 /* FIXME: fallback? */
684 if (icd
->DrvCreateLayerContext
!= NULL
)
685 drvHglrc
= icd
->DrvCreateLayerContext( hdc
, layer
);
686 if (drvHglrc
== NULL
)
688 if (layer
== 0 && icd
->DrvCreateContext
!= NULL
)
689 drvHglrc
= icd
->DrvCreateContext( hdc
);
691 DBGPRINT( "Warning: CreateLayerContext not supported by ICD!" );
694 if (drvHglrc
== NULL
)
696 /* FIXME: fallback to mesa? */
697 DBGPRINT( "Error: DrvCreate[Layer]Context failed! (%d)", GetLastError() );
698 ROSGL_DeleteContext( glrc
);
702 /* we have our GLRC in glrc and the ICD's GLRC in drvHglrc */
703 glrc
->hglrc
= drvHglrc
;
710 /*! \brief Create a new GL Rendering Context.
712 * \param hdc [IN] Handle for DC for which to create context
714 * \return Handle for the created GLRC
715 * \retval NULL Failure
719 rosglCreateContext( HDC hdc
)
721 return rosglCreateLayerContext( hdc
, 0 );
725 /*! \brief Delete an OpenGL context
727 * \param hglrc [IN] Handle to GLRC to delete; must not be a threads current RC!
729 * \retval TRUE Success
730 * \retval FALSE Failure (i.e. GLRC is current for a thread)
734 rosglDeleteContext( HGLRC hglrc
)
736 GLRC
*glrc
= (GLRC
*)hglrc
;
738 /* check if we know about this context */
739 if (!ROSGL_ContainsContext( glrc
))
741 DBGPRINT( "Error: hglrc not found!" );
742 SetLastError( ERROR_INVALID_HANDLE
);
746 /* make sure GLRC is not current for some thread */
747 if (glrc
->is_current
)
749 DBGPRINT( "Error: GLRC is current for DC 0x%08x", glrc
->hdc
);
750 SetLastError( ERROR_INVALID_FUNCTION
);
754 /* release ICD's context */
755 if (glrc
->hglrc
!= NULL
)
757 if (!glrc
->icd
->DrvDeleteContext( glrc
->hglrc
))
759 DBGPRINT( "Warning: DrvDeleteContext() failed (%d)", GetLastError() );
765 return ROSGL_DeleteContext( glrc
);
771 rosglDescribeLayerPlane( HDC hdc
, int iPixelFormat
, int iLayerPlane
,
772 UINT nBytes
, LPLAYERPLANEDESCRIPTOR plpd
)
775 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
780 /*! \brief Gets information about a pixelformat.
782 * \param hdc [IN] Handle to DC
783 * \param iFormat [IN] Pixelformat index
784 * \param nBytes [IN] sizeof (pfd) - at most nBytes are copied into pfd
785 * \param pfd [OUT] Pointer to a PIXELFORMATDESCRIPTOR
787 * \return Maximum pixelformat index/number of formats
792 rosglDescribePixelFormat( HDC hdc
, int iFormat
, UINT nBytes
,
793 LPPIXELFORMATDESCRIPTOR pfd
)
796 GLDRIVERDATA
*icd
= ROSGL_ICDForHDC( hdc
);
800 ret
= icd
->DrvDescribePixelFormat( hdc
, iFormat
, nBytes
, pfd
);
802 DBGPRINT( "Error: DrvDescribePixelFormat(format=%d) failed (%d)", iFormat
, GetLastError() );
806 SetLastError( ERROR_INVALID_FUNCTION
);
813 /*! \brief Return the thread's current GLRC
815 * \return Handle for thread's current GLRC
816 * \retval NULL No current GLRC set
820 rosglGetCurrentContext()
822 return (HGLRC
)(OPENGL32_threaddata
->glrc
);
826 /*! \brief Return the thread's current DC
828 * \return Handle for thread's current DC
829 * \retval NULL No current DC/GLRC set
835 /* FIXME: is it correct to return NULL when there is no current GLRC or
836 is there another way to find out the wanted HDC? */
837 if (OPENGL32_threaddata
->glrc
== NULL
)
839 return (HDC
)(OPENGL32_threaddata
->glrc
->hdc
);
845 rosglGetLayerPaletteEntries( HDC hdc
, int iLayerPlane
, int iStart
,
846 int cEntries
, COLORREF
*pcr
)
849 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
854 /*! \brief Returns the current pixelformat.
856 * \param hdc [IN] Handle to DC to get the pixelformat from
858 * \return Pixelformat index
863 rosglGetPixelFormat( HDC hdc
)
867 DBGTRACE( "Called!" );
869 dcdata
= ROSGL_GetPrivateDCData( hdc
);
872 DBGPRINT( "Error: ROSGL_GetPrivateDCData failed!" );
876 return dcdata
->pixel_format
;
880 /*! \brief Get the address for an OpenGL extension function.
882 * The addresses this function returns are only valid within the same thread
883 * which it was called from.
885 * \param proc [IN] Name of the function to look for
887 * \return The address of the proc
888 * \retval NULL Failure
892 rosglGetProcAddress( LPCSTR proc
)
897 /* FIXME we should Flush the gl here */
899 if (OPENGL32_threaddata
->glrc
== NULL
)
901 DBGPRINT( "Error: No current GLRC!" );
902 SetLastError( ERROR_INVALID_FUNCTION
);
906 icd
= OPENGL32_threaddata
->glrc
->icd
;
907 func
= icd
->DrvGetProcAddress( proc
);
910 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc
);
914 /* FIXME: Should we return wgl/gl 1.1 functions? */
915 SetLastError( ERROR_PROC_NOT_FOUND
);
921 rosglGetDefaultProcAddress( LPCSTR proc
)
926 /* wglGetDefaultProcAddress does not flush the gl */
928 if (OPENGL32_threaddata
->glrc
== NULL
)
930 DBGPRINT( "Error: No current GLRC!" );
931 SetLastError( ERROR_INVALID_FUNCTION
);
935 icd
= OPENGL32_threaddata
->glrc
->icd
;
936 func
= icd
->DrvGetProcAddress( proc
);
939 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc
);
943 /* FIXME: Should we return wgl/gl 1.1 functions? */
944 SetLastError( ERROR_PROC_NOT_FOUND
);
949 /*! \brief Make the given GLRC the threads current GLRC for hdc
951 * \param hdc [IN] Handle for a DC to be drawn on
952 * \param hglrc [IN] Handle for a GLRC to make current
954 * \retval TRUE Success
955 * \retval FALSE Failure
959 rosglMakeCurrent( HDC hdc
, HGLRC hglrc
)
961 GLRC
*glrc
= (GLRC
*)hglrc
;
962 ICDTable
*icdTable
= NULL
;
964 DBGTRACE( "Called!" );
966 if (OPENGL32_threaddata
== NULL
)
969 /* flush current context */
970 if (OPENGL32_threaddata
->glrc
!= NULL
)
975 /* check if current context is unset */
978 if (OPENGL32_threaddata
->glrc
!= NULL
)
980 glrc
= OPENGL32_threaddata
->glrc
;
981 glrc
->icd
->DrvReleaseContext( glrc
->hglrc
);
982 glrc
->is_current
= FALSE
;
983 OPENGL32_threaddata
->glrc
= NULL
;
989 if (GetObjectType( hdc
) != OBJ_DC
&& GetObjectType( hdc
) != OBJ_MEMDC
)
991 DBGPRINT( "Error: hdc is not a DC handle!" );
992 SetLastError( ERROR_INVALID_HANDLE
);
996 /* check if we know about this glrc */
997 if (!ROSGL_ContainsContext( glrc
))
999 DBGPRINT( "Error: hglrc not found!" );
1000 SetLastError( ERROR_INVALID_HANDLE
);
1004 /* check if it is available */
1005 if (glrc
->is_current
&& glrc
->thread_id
!= GetCurrentThreadId()) /* used by another thread */
1007 DBGPRINT( "Error: hglrc is current for thread 0x%08x", glrc
->thread_id
);
1008 SetLastError( ERROR_INVALID_HANDLE
);
1013 if (glrc
->hglrc
!= NULL
)
1015 DBGPRINT( "Info: Calling DrvSetContext!" );
1016 SetLastError( ERROR_SUCCESS
);
1017 icdTable
= glrc
->icd
->DrvSetContext( hdc
, glrc
->hglrc
,
1018 (void *)ROSGL_SetContextCallBack
);
1019 if (icdTable
== NULL
)
1021 DBGPRINT( "Error: DrvSetContext failed (%d)\n", GetLastError() );
1024 DBGPRINT( "Info: DrvSetContext succeeded!" );
1027 /* make it current */
1028 if (OPENGL32_threaddata
->glrc
!= NULL
)
1029 OPENGL32_threaddata
->glrc
->is_current
= FALSE
;
1030 glrc
->is_current
= TRUE
;
1031 glrc
->thread_id
= GetCurrentThreadId();
1033 OPENGL32_threaddata
->glrc
= glrc
;
1036 if (ROSGL_SetContextCallBack( icdTable
) != ERROR_SUCCESS
&& icdTable
== NULL
)
1038 DBGPRINT( "Warning: ROSGL_SetContextCallBack failed!" );
1047 rosglRealizeLayerPalette( HDC hdc
, int iLayerPlane
, BOOL bRealize
)
1050 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1057 rosglSetLayerPaletteEntries( HDC hdc
, int iLayerPlane
, int iStart
,
1058 int cEntries
, CONST COLORREF
*pcr
)
1061 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1066 /*! \brief Set a DCs pixelformat
1068 * \param hdc [IN] Handle to DC for which to set the format
1069 * \param iFormat [IN] Index of the pixelformat to set
1070 * \param pfd [IN] Not sure what this is for
1072 * \retval TRUE Success
1073 * \retval FALSE Failure
1077 rosglSetPixelFormat( HDC hdc
, int iFormat
, CONST PIXELFORMATDESCRIPTOR
*pfd
)
1082 DBGTRACE( "Called!" );
1085 icd
= ROSGL_ICDForHDC( hdc
);
1088 DBGPRINT( "Warning: ICDForHDC() failed" );
1093 if (!icd
->DrvSetPixelFormat( hdc
, iFormat
, pfd
))
1095 DBGPRINT( "Warning: DrvSetPixelFormat(format=%d) failed (%d)",
1096 iFormat
, GetLastError() );
1100 /* store format in private DC data */
1101 dcdata
= ROSGL_GetPrivateDCData( hdc
);
1104 DBGPRINT( "Error: ROSGL_GetPrivateDCData() failed!" );
1107 dcdata
->pixel_format
= iFormat
;
1113 /*! \brief Enable display-list sharing between multiple GLRCs
1115 * This will only work if both GLRCs are from the same driver.
1117 * \param hglrc1 [IN] GLRC number 1
1118 * \param hglrc2 [IN] GLRC number 2
1120 * \retval TRUE Success
1121 * \retval FALSE Failure
1125 rosglShareLists( HGLRC hglrc1
, HGLRC hglrc2
)
1127 GLRC
*glrc1
= (GLRC
*)hglrc1
;
1128 GLRC
*glrc2
= (GLRC
*)hglrc2
;
1131 if (!ROSGL_ContainsContext( glrc1
))
1133 DBGPRINT( "Error: hglrc1 not found!" );
1134 SetLastError( ERROR_INVALID_HANDLE
);
1137 if (!ROSGL_ContainsContext( glrc2
))
1139 DBGPRINT( "Error: hglrc2 not found!" );
1140 SetLastError( ERROR_INVALID_HANDLE
);
1144 /* I think this is only possible within one ICD */
1145 if (glrc1
->icd
!= glrc2
->icd
)
1147 DBGPRINT( "Error: hglrc1 and hglrc2 use different ICDs!" );
1148 SetLastError( ERROR_INVALID_HANDLE
);
1152 /* share lists (call ICD) */
1153 return glrc1
->icd
->DrvShareLists( glrc1
->hglrc
, glrc2
->hglrc
);
1157 /*! \brief Flushes GL and swaps front/back buffer if appropriate
1159 * \param hdc [IN] Handle to device context to swap buffers for
1161 * \retval TRUE Success
1162 * \retval FALSE Failure
1166 rosglSwapBuffers( HDC hdc
)
1168 GLDRIVERDATA
*icd
= ROSGL_ICDForHDC( hdc
);
1169 DBGTRACE( "Called!" );
1172 DBGPRINT( "Swapping buffers!" );
1173 if (!icd
->DrvSwapBuffers( hdc
))
1175 DBGPRINT( "Error: DrvSwapBuffers failed (%d)", GetLastError() );
1181 /* FIXME: implement own functionality? */
1182 SetLastError( ERROR_INVALID_FUNCTION
);
1189 rosglSwapLayerBuffers( HDC hdc
, UINT fuPlanes
)
1192 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1199 rosglUseFontBitmapsA( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
)
1202 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1209 rosglUseFontBitmapsW( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
)
1212 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1219 rosglUseFontOutlinesA( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
,
1220 FLOAT deviation
, FLOAT extrusion
, int format
,
1221 GLYPHMETRICSFLOAT
*pgmf
)
1224 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1231 rosglUseFontOutlinesW( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
,
1232 FLOAT deviation
, FLOAT extrusion
, int format
,
1233 GLYPHMETRICSFLOAT
*pgmf
)
1236 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1242 #endif /* __cplusplus */