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
;
30 /*! \brief Append OpenGL Rendering Context (GLRC) to list
32 * \param glrc [IN] Pointer to GLRC to append to list
36 ROSGL_AppendContext( GLRC
*glrc
)
39 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
42 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
43 return; /* FIXME: do we have to expect such an error and handle it? */
46 if (OPENGL32_processdata
.glrc_list
== NULL
)
47 OPENGL32_processdata
.glrc_list
= glrc
;
50 GLRC
*p
= OPENGL32_processdata
.glrc_list
;
51 while (p
->next
!= NULL
)
57 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
58 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
62 /*! \brief Remove OpenGL Rendering Context (GLRC) from list
64 * \param glrc [IN] Pointer to GLRC to remove from list
68 ROSGL_RemoveContext( GLRC
*glrc
)
71 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
74 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
75 return; /* FIXME: do we have to expect such an error and handle it? */
78 if (glrc
== OPENGL32_processdata
.glrc_list
)
79 OPENGL32_processdata
.glrc_list
= glrc
->next
;
82 GLRC
*p
= OPENGL32_processdata
.glrc_list
;
93 DBGPRINT( "Error: GLRC 0x%08x not found in list!", glrc
);
97 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
98 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
102 /*! \brief Create a new GL Context (GLRC) and append it to the list
104 * \return Pointer to new GLRC on success
105 * \retval NULL Returned on failure (i.e. Out of memory)
109 ROSGL_NewContext(void)
114 glrc
= (GLRC
*)HeapAlloc( GetProcessHeap(),
115 HEAP_ZERO_MEMORY
| HEAP_GENERATE_EXCEPTIONS
, sizeof (GLRC
) );
118 ROSGL_AppendContext( glrc
);
123 /*! \brief Delete all GLDCDATA with this IDC
125 * \param icd [IN] Pointer to a ICD
129 ROSGL_DeleteDCDataForICD( GLDRIVERDATA
*icd
)
134 if (WaitForSingleObject( OPENGL32_processdata
.dcdata_mutex
, INFINITE
) ==
137 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
141 p
= OPENGL32_processdata
.dcdata_list
;
142 pptr
= &OPENGL32_processdata
.dcdata_list
;
148 OPENGL32_UnloadICD( p
->icd
);
150 if (!HeapFree( GetProcessHeap(), 0, p
))
151 DBGPRINT( "Warning: HeapFree() on GLDCDATA failed (%d)",
164 if (!ReleaseMutex( OPENGL32_processdata
.dcdata_mutex
))
165 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
169 /*! \brief Delete a GL Context (GLRC) and remove it from the list
171 * \param glrc [IN] Pointer to GLRC to delete
173 * \retval TRUE Success
174 * \retval FALSE Failure
178 ROSGL_DeleteContext( GLRC
*glrc
)
181 if ((glrc
->icd
!= NULL
) && (!InterlockedDecrement((LONG
*)&glrc
->icd
->refcount
)))
183 /* This is the last context, remove the ICD*/
184 ROSGL_DeleteDCDataForICD( glrc
->icd
);
187 /* remove from list */
188 ROSGL_RemoveContext( glrc
);
191 HeapFree( GetProcessHeap(), 0, glrc
);
197 /*! \brief Check wether a GLRC is in the list
199 * \param glrc [IN] Pointer to GLRC to look for in the list
201 * \retval TRUE GLRC was found
202 * \retval FALSE GLRC was not found
206 ROSGL_ContainsContext( GLRC
*glrc
)
212 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
215 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
216 return FALSE
; /* FIXME: do we have to expect such an error and handle it? */
219 p
= OPENGL32_processdata
.glrc_list
;
231 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
232 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
238 /*! \brief Get GL private DC data.
240 * This function adds an empty GLDCDATA to the list if there is no data for the
243 * \param hdc [IN] Handle to a Device Context for which to get the data
245 * \return Pointer to GLDCDATA on success
246 * \retval NULL on failure
250 ROSGL_GetPrivateDCData( HDC hdc
)
255 if (GetObjectType( hdc
) != OBJ_DC
&& GetObjectType( hdc
) != OBJ_MEMDC
)
257 DBGPRINT( "Error: hdc is not a DC handle!" );
258 SetLastError( ERROR_INVALID_HANDLE
);
263 if (WaitForSingleObject( OPENGL32_processdata
.dcdata_mutex
, INFINITE
) ==
266 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
267 return NULL
; /* FIXME: do we have to expect such an error and handle it? */
270 /* look for data in list */
271 data
= OPENGL32_processdata
.dcdata_list
;
274 if (data
->hdc
== hdc
) /* found */
279 /* allocate new data if not found in list */
282 data
= HeapAlloc( GetProcessHeap(),
283 HEAP_ZERO_MEMORY
| HEAP_GENERATE_EXCEPTIONS
,
287 DBGPRINT( "Error: HeapAlloc() failed (%d)", GetLastError() );
293 /* append data to list */
294 if (OPENGL32_processdata
.dcdata_list
== NULL
)
295 OPENGL32_processdata
.dcdata_list
= data
;
298 GLDCDATA
*p
= OPENGL32_processdata
.dcdata_list
;
299 while (p
->next
!= NULL
)
307 if (!ReleaseMutex( OPENGL32_processdata
.dcdata_mutex
))
308 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
314 /*! \brief Get ICD from HDC.
316 * This function asks the display driver which OpenGL ICD to load for the given
317 * HDC, loads it and returns a pointer to a GLDRIVERDATA struct on success.
319 * \param hdc [IN] Handle for DC for which to load/get the ICD
321 * \return Pointer to GLDRIVERDATA
322 * \retval NULL Failure.
326 ROSGL_ICDForHDC( HDC hdc
)
329 GLDRIVERDATA
*drvdata
;
331 dcdata
= ROSGL_GetPrivateDCData( hdc
);
335 if (dcdata
->icd
== NULL
)
340 /* NOTE: This might be done by multiple threads simultaneously, but only the fastest
341 actually gets to set the ICD! */
343 driverName
= _wgetenv( L
"OPENGL32_DRIVER" );
344 if (driverName
== NULL
)
349 /* get driver name */
350 dwInput
= OPENGL_GETINFO
;
351 ret
= ExtEscape( hdc
, QUERYESCSUPPORT
, sizeof (dwInput
), (LPCSTR
)&dwInput
, 0, NULL
);
355 ret
= ExtEscape( hdc
, OPENGL_GETINFO
, sizeof (dwInput
),
356 (LPCSTR
)&dwInput
, sizeof (OPENGL_INFO
),
366 DBGPRINT( "Warning: ExtEscape to get the drivername failed! (%d)", GetLastError() );
367 if (MessageBox( WindowFromDC( hdc
), L
"Couldn't get installable client driver name!\nUsing default driver.",
368 L
"OPENGL32.dll: Warning", MB_OKCANCEL
| MB_ICONWARNING
) == IDCANCEL
)
374 /* open registry key */
375 ret
= RegOpenKeyExW( HKEY_LOCAL_MACHINE
, OPENGL_DRIVERS_SUBKEY
, 0, KEY_QUERY_VALUE
, &hKey
);
376 if (ret
!= ERROR_SUCCESS
)
378 DBGPRINT( "Error: Couldn't open registry key '%ws'", OPENGL_DRIVERS_SUBKEY
);
384 size
= sizeof (info
.DriverName
);
385 ret
= RegQueryValueExW( hKey
, L
"DefaultDriver", 0, &type
, (LPBYTE
)info
.DriverName
, &size
);
387 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
389 DBGPRINT( "Error: Couldn't query DefaultDriver value or not a string" );
397 wcsncpy( info
.DriverName
, driverName
, sizeof (info
.DriverName
) / sizeof (info
.DriverName
[0]) );
399 /* load driver (or get a reference) */
400 drvdata
= OPENGL32_LoadICD( info
.DriverName
);
404 snwprintf(Buffer
, sizeof(Buffer
)/sizeof(WCHAR
),
405 L
"Couldn't load driver \"%s\".", info
.DriverName
);
406 MessageBox(WindowFromDC( hdc
), Buffer
,
407 L
"OPENGL32.dll: Warning",
408 MB_OK
| MB_ICONWARNING
);
412 /* Atomically set the ICD!!! */
413 if (InterlockedCompareExchangePointer((PVOID
*)&dcdata
->icd
,
417 /* Too bad, somebody else was faster... */
418 DBGTRACE("ICD is already set!\n");
427 /*! \brief SetContextCallBack passed to DrvSetContext.
429 * This function gets called by the OpenGL driver whenever the current GL
430 * context (dispatch table) is to be changed.
432 * \param table [IN] Function pointer table (first DWORD is number of functions)
434 * \return unkown (maybe void? ERROR_SUCCESS at the moment)
438 ROSGL_SetContextCallBack( const ICDTable
*table
)
441 PROC
*tebTable
, *tebDispatchTable
;
444 teb
= NtCurrentTeb();
445 tebTable
= (PROC
*)teb
->glTable
;
446 tebDispatchTable
= (PROC
*)teb
->glDispatchTable
;
448 DBGTRACE( "Called!" );
452 DBGPRINT( "Function count: %d\n", table
->num_funcs
);
455 size
= sizeof (PROC
) * table
->num_funcs
;
456 memcpy( tebTable
, table
->dispatch_table
, size
);
457 memset( tebTable
+ table
->num_funcs
, 0,
458 sizeof (table
->dispatch_table
) - size
);
462 DBGPRINT( "Unsetting current context" );
463 memset( tebTable
, 0, sizeof (table
->dispatch_table
) );
466 /* put in empty functions as long as we dont have a fallback */
467 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
468 if (tebTable[icdidx] == NULL) \
471 DBGPRINT( "Warning: GL proc '%s' is NULL", #func ); \
472 tebTable[icdidx] = (PROC)glEmptyFunc##stack; \
477 /* fill teb->glDispatchTable for fast calls */
478 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
480 tebDispatchTable[tebidx] = tebTable[icdidx];
486 return ERROR_SUCCESS
;
490 /*! \brief Attempts to find the best matching pixel format for HDC
492 * This function is comparing each available format with the preferred one
493 * and returns the one which is closest to it.
494 * If PFD_DOUBLEBUFFER, PFD_STEREO or one of PFD_DRAW_TO_WINDOW,
495 * PFD_DRAW_TO_BITMAP, PFD_SUPPORT_GDI and PDF_SUPPORT_OPENGL is given then
496 * only formats which also support those will be enumerated (unless
497 * PFD_DOUBLEBUFFER_DONTCARE or PFD_STEREO_DONTCARE is also set)
499 * \param hdc [IN] Handle to DC for which to get a pixel format index
500 * \param pfd [IN] PFD describing what kind of format you want
502 * \return Pixel format index
503 * \retval 0 Failed to find a suitable format
505 #define BUFFERDEPTH_SCORE(want, have) \
506 ((want == 0) ? (0) : ((want < have) ? (1) : ((want > have) ? (3) : (0))))
508 /* Score if we want and not have it */
509 #define FLAG_SCORE(want, have, flag) \
510 (((want & ~have) & flag) ? (1) : (0))
512 /* Score if what we want is different than what we have, except when
514 #define FLAG_SCORE_DONTCARE(want, have, flag) \
515 ((!(have & flag ## _DONTCARE)) && ((want & flag) != (have & flag)) ? (1) : (0))
519 rosglChoosePixelFormat( HDC hdc
, CONST PIXELFORMATDESCRIPTOR
*pfd
)
522 PIXELFORMATDESCRIPTOR icdPfd
;
525 int score
, bestScore
= 0x7fff; /* used to choose a pfd if no exact match */
528 DBGTRACE( "Called!" );
531 icd
= ROSGL_ICDForHDC( hdc
);
536 if (pfd
->nSize
!= sizeof (PIXELFORMATDESCRIPTOR
) || pfd
->nVersion
!= 1)
538 SetLastError( ERROR_INVALID_PARAMETER
);
542 /* get number of formats */
543 icdNumFormats
= icd
->DrvDescribePixelFormat( hdc
, 1,
544 sizeof (PIXELFORMATDESCRIPTOR
), &icdPfd
);
545 if (icdNumFormats
== 0)
547 DBGPRINT( "Error: DrvDescribePixelFormat failed (%d)", GetLastError() );
550 DBGPRINT( "Info: Enumerating %d pixelformats", icdNumFormats
);
552 /* try to find best format */
553 for (i
= 0; i
< icdNumFormats
; i
++)
555 if (icd
->DrvDescribePixelFormat( hdc
, i
+ 1,
556 sizeof (PIXELFORMATDESCRIPTOR
), &icdPfd
) == 0)
558 DBGPRINT( "Warning: DrvDescribePixelFormat failed (%d)",
563 if ((pfd
->dwFlags
& PFD_GENERIC_ACCELERATED
) != 0) /* we do not support such kind of drivers */
568 score
= 0; /* higher is worse */
571 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_DRAW_TO_WINDOW
);
572 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_DRAW_TO_BITMAP
);
573 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_SUPPORT_GDI
);
574 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_SUPPORT_OPENGL
);
575 score
+= FLAG_SCORE_DONTCARE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_DOUBLEBUFFER
);
576 score
+= FLAG_SCORE_DONTCARE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_STEREO
);
578 /* check other attribs */
579 if (pfd
->iPixelType
!= icdPfd
.iPixelType
)
580 score
+= 5; /* this is really bad i think */
581 if (pfd
->iLayerType
!= icdPfd
.iLayerType
)
582 score
+= 15; /* this is very very bad ;) */
584 score
+= BUFFERDEPTH_SCORE(pfd
->cAlphaBits
, icdPfd
.cAlphaBits
);
585 score
+= BUFFERDEPTH_SCORE(pfd
->cAccumBits
, icdPfd
.cAccumBits
);
586 score
+= BUFFERDEPTH_SCORE(pfd
->cDepthBits
, icdPfd
.cDepthBits
);
587 score
+= BUFFERDEPTH_SCORE(pfd
->cStencilBits
, icdPfd
.cStencilBits
);
588 score
+= BUFFERDEPTH_SCORE(pfd
->cAuxBuffers
, icdPfd
.cAuxBuffers
);
591 if (score
< bestScore
)
601 SetLastError( 0 ); /* FIXME: set appropriate error */
603 DBGPRINT( "Info: Suggesting pixelformat %d", best
);
608 /*! \brief Copy data specified by mask from one GLRC to another.
610 * \param src [IN] Source GLRC
611 * \param src [OUT] Destination GLRC
612 * \param mask [IN] Bitfield like given to glPushAttrib()
614 * \retval TRUE Success
615 * \retval FALSE Failure
619 rosglCopyContext( HGLRC hsrc
, HGLRC hdst
, UINT mask
)
621 GLRC
*src
= (GLRC
*)hsrc
;
622 GLRC
*dst
= (GLRC
*)hdst
;
625 if (!ROSGL_ContainsContext( src
))
627 DBGPRINT( "Error: src GLRC not found!" );
628 SetLastError( ERROR_INVALID_HANDLE
);
631 if (!ROSGL_ContainsContext( dst
))
633 DBGPRINT( "Error: dst GLRC not found!" );
634 SetLastError( ERROR_INVALID_HANDLE
);
638 /* I think this is only possible within one ICD */
639 if (src
->icd
!= dst
->icd
)
641 DBGPRINT( "Error: src and dst GLRC use different ICDs!" );
642 SetLastError( ERROR_INVALID_HANDLE
);
646 /* copy data (call ICD) */
647 return src
->icd
->DrvCopyContext( src
->hglrc
, dst
->hglrc
, mask
);
651 /*! \brief Create a new GL Rendering Context.
653 * This function can create over- or underlay surfaces.
655 * \param hdc [IN] Handle for DC for which to create context
656 * \param layer [IN] Layer number to bind (draw?) to
658 * \return Handle for the created GLRC
659 * \retval NULL Failure
663 rosglCreateLayerContext( HDC hdc
, int layer
)
665 GLDRIVERDATA
*icd
= NULL
;
667 HGLRC drvHglrc
= NULL
;
669 DBGTRACE( "Called!" );
671 /* if (GetObjectType( hdc ) != OBJ_DC)
673 DBGPRINT( "Error: hdc is not a DC handle!" );
677 /* create new GLRC */
678 glrc
= ROSGL_NewContext();
683 icd
= ROSGL_ICDForHDC( hdc
);
686 ROSGL_DeleteContext( glrc
);
687 DBGPRINT( "Couldn't get ICD by HDC :-(" );
688 /* FIXME: fallback? */
691 /* Don't forget to refcount it, icd will be released when last context is deleted */
692 InterlockedIncrement((LONG
*)&icd
->refcount
);
696 if (icd
->DrvCreateLayerContext
!= NULL
)
697 drvHglrc
= icd
->DrvCreateLayerContext( hdc
, layer
);
698 if (drvHglrc
== NULL
)
700 if (layer
== 0 && icd
->DrvCreateContext
!= NULL
)
701 drvHglrc
= icd
->DrvCreateContext( hdc
);
703 DBGPRINT( "Warning: CreateLayerContext not supported by ICD!" );
706 if (drvHglrc
== NULL
)
708 /* FIXME: fallback to mesa? */
709 DBGPRINT( "Error: DrvCreate[Layer]Context failed! (%d)", GetLastError() );
710 ROSGL_DeleteContext( glrc
);
714 /* we have our GLRC in glrc and the ICD's GLRC in drvHglrc */
715 glrc
->hglrc
= drvHglrc
;
722 /*! \brief Create a new GL Rendering Context.
724 * \param hdc [IN] Handle for DC for which to create context
726 * \return Handle for the created GLRC
727 * \retval NULL Failure
731 rosglCreateContext( HDC hdc
)
733 return rosglCreateLayerContext( hdc
, 0 );
737 /*! \brief Delete an OpenGL context
739 * \param hglrc [IN] Handle to GLRC to delete; must not be a threads current RC!
741 * \retval TRUE Success
742 * \retval FALSE Failure (i.e. GLRC is current for a thread)
746 rosglDeleteContext( HGLRC hglrc
)
748 GLRC
*glrc
= (GLRC
*)hglrc
;
750 /* check if we know about this context */
751 if (!ROSGL_ContainsContext( glrc
))
753 DBGPRINT( "Error: hglrc not found!" );
754 SetLastError( ERROR_INVALID_HANDLE
);
758 /* make sure GLRC is not current for some thread */
759 if (glrc
->is_current
)
761 DBGPRINT( "Error: GLRC is current for DC 0x%08x", glrc
->hdc
);
762 SetLastError( ERROR_INVALID_FUNCTION
);
766 /* release ICD's context */
767 if (glrc
->hglrc
!= NULL
)
769 if (!glrc
->icd
->DrvDeleteContext( glrc
->hglrc
))
771 DBGPRINT( "Warning: DrvDeleteContext() failed (%d)", GetLastError() );
777 return ROSGL_DeleteContext( glrc
);
783 rosglDescribeLayerPlane( HDC hdc
, int iPixelFormat
, int iLayerPlane
,
784 UINT nBytes
, LPLAYERPLANEDESCRIPTOR plpd
)
787 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
792 /*! \brief Gets information about a pixelformat.
794 * \param hdc [IN] Handle to DC
795 * \param iFormat [IN] Pixelformat index
796 * \param nBytes [IN] sizeof (pfd) - at most nBytes are copied into pfd
797 * \param pfd [OUT] Pointer to a PIXELFORMATDESCRIPTOR
799 * \return Maximum pixelformat index/number of formats
804 rosglDescribePixelFormat( HDC hdc
, int iFormat
, UINT nBytes
,
805 LPPIXELFORMATDESCRIPTOR pfd
)
808 GLDRIVERDATA
*icd
= ROSGL_ICDForHDC( hdc
);
812 ret
= icd
->DrvDescribePixelFormat( hdc
, iFormat
, nBytes
, pfd
);
814 DBGPRINT( "Error: DrvDescribePixelFormat(format=%d) failed (%d)", iFormat
, GetLastError() );
818 SetLastError( ERROR_INVALID_FUNCTION
);
825 /*! \brief Return the thread's current GLRC
827 * \return Handle for thread's current GLRC
828 * \retval NULL No current GLRC set
832 rosglGetCurrentContext()
834 return (HGLRC
)(OPENGL32_threaddata
->glrc
);
838 /*! \brief Return the thread's current DC
840 * \return Handle for thread's current DC
841 * \retval NULL No current DC/GLRC set
847 /* FIXME: is it correct to return NULL when there is no current GLRC or
848 is there another way to find out the wanted HDC? */
849 if (OPENGL32_threaddata
->glrc
== NULL
)
851 return (HDC
)(OPENGL32_threaddata
->glrc
->hdc
);
857 rosglGetLayerPaletteEntries( HDC hdc
, int iLayerPlane
, int iStart
,
858 int cEntries
, COLORREF
*pcr
)
861 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
866 /*! \brief Returns the current pixelformat.
868 * \param hdc [IN] Handle to DC to get the pixelformat from
870 * \return Pixelformat index
875 rosglGetPixelFormat( HDC hdc
)
879 DBGTRACE( "Called!" );
881 dcdata
= ROSGL_GetPrivateDCData( hdc
);
884 DBGPRINT( "Error: ROSGL_GetPrivateDCData failed!" );
888 return dcdata
->pixel_format
;
892 /*! \brief Get the address for an OpenGL extension function.
894 * The addresses this function returns are only valid within the same thread
895 * which it was called from.
897 * \param proc [IN] Name of the function to look for
899 * \return The address of the proc
900 * \retval NULL Failure
904 rosglGetProcAddress( LPCSTR proc
)
909 /* FIXME we should Flush the gl here */
911 if (OPENGL32_threaddata
->glrc
== NULL
)
913 DBGPRINT( "Error: No current GLRC!" );
914 SetLastError( ERROR_INVALID_FUNCTION
);
918 icd
= OPENGL32_threaddata
->glrc
->icd
;
919 func
= icd
->DrvGetProcAddress( proc
);
922 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc
);
926 /* FIXME: Should we return wgl/gl 1.1 functions? */
927 SetLastError( ERROR_PROC_NOT_FOUND
);
933 rosglGetDefaultProcAddress( LPCSTR proc
)
938 /* wglGetDefaultProcAddress does not flush the gl */
940 if (OPENGL32_threaddata
->glrc
== NULL
)
942 DBGPRINT( "Error: No current GLRC!" );
943 SetLastError( ERROR_INVALID_FUNCTION
);
947 icd
= OPENGL32_threaddata
->glrc
->icd
;
948 func
= icd
->DrvGetProcAddress( proc
);
951 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc
);
955 /* FIXME: Should we return wgl/gl 1.1 functions? */
956 SetLastError( ERROR_PROC_NOT_FOUND
);
961 /*! \brief Make the given GLRC the threads current GLRC for hdc
963 * \param hdc [IN] Handle for a DC to be drawn on
964 * \param hglrc [IN] Handle for a GLRC to make current
966 * \retval TRUE Success
967 * \retval FALSE Failure
971 rosglMakeCurrent( HDC hdc
, HGLRC hglrc
)
973 GLRC
*glrc
= (GLRC
*)hglrc
;
974 ICDTable
*icdTable
= NULL
;
976 DBGTRACE( "Called!" );
978 if (OPENGL32_threaddata
== NULL
)
981 /* flush current context */
982 if (OPENGL32_threaddata
->glrc
!= NULL
)
987 /* check if current context is unset */
990 if (OPENGL32_threaddata
->glrc
!= NULL
)
992 glrc
= OPENGL32_threaddata
->glrc
;
993 glrc
->icd
->DrvReleaseContext( glrc
->hglrc
);
994 glrc
->is_current
= FALSE
;
995 OPENGL32_threaddata
->glrc
= NULL
;
1001 if (GetObjectType( hdc
) != OBJ_DC
&& GetObjectType( hdc
) != OBJ_MEMDC
)
1003 DBGPRINT( "Error: hdc is not a DC handle!" );
1004 SetLastError( ERROR_INVALID_HANDLE
);
1008 /* check if we know about this glrc */
1009 if (!ROSGL_ContainsContext( glrc
))
1011 DBGPRINT( "Error: hglrc not found!" );
1012 SetLastError( ERROR_INVALID_HANDLE
);
1016 /* check if it is available */
1017 if (glrc
->is_current
&& glrc
->thread_id
!= GetCurrentThreadId()) /* used by another thread */
1019 DBGPRINT( "Error: hglrc is current for thread 0x%08x", glrc
->thread_id
);
1020 SetLastError( ERROR_INVALID_HANDLE
);
1025 if (glrc
->hglrc
!= NULL
)
1027 DBGPRINT( "Info: Calling DrvSetContext!" );
1028 SetLastError( ERROR_SUCCESS
);
1029 icdTable
= glrc
->icd
->DrvSetContext( hdc
, glrc
->hglrc
,
1030 (void *)ROSGL_SetContextCallBack
);
1031 if (icdTable
== NULL
)
1033 DBGPRINT( "Error: DrvSetContext failed (%d)\n", GetLastError() );
1036 DBGPRINT( "Info: DrvSetContext succeeded!" );
1039 /* make it current */
1040 if (OPENGL32_threaddata
->glrc
!= NULL
)
1041 OPENGL32_threaddata
->glrc
->is_current
= FALSE
;
1042 glrc
->is_current
= TRUE
;
1043 glrc
->thread_id
= GetCurrentThreadId();
1045 OPENGL32_threaddata
->glrc
= glrc
;
1048 if (ROSGL_SetContextCallBack( icdTable
) != ERROR_SUCCESS
&& icdTable
== NULL
)
1050 DBGPRINT( "Warning: ROSGL_SetContextCallBack failed!" );
1059 rosglRealizeLayerPalette( HDC hdc
, int iLayerPlane
, BOOL bRealize
)
1062 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1069 rosglSetLayerPaletteEntries( HDC hdc
, int iLayerPlane
, int iStart
,
1070 int cEntries
, CONST COLORREF
*pcr
)
1073 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1078 /*! \brief Set a DCs pixelformat
1080 * \param hdc [IN] Handle to DC for which to set the format
1081 * \param iFormat [IN] Index of the pixelformat to set
1082 * \param pfd [IN] Not sure what this is for
1084 * \retval TRUE Success
1085 * \retval FALSE Failure
1089 rosglSetPixelFormat( HDC hdc
, int iFormat
, CONST PIXELFORMATDESCRIPTOR
*pfd
)
1094 DBGTRACE( "Called!" );
1097 icd
= ROSGL_ICDForHDC( hdc
);
1100 DBGPRINT( "Warning: ICDForHDC() failed" );
1105 if (!icd
->DrvSetPixelFormat( hdc
, iFormat
, pfd
))
1107 DBGPRINT( "Warning: DrvSetPixelFormat(format=%d) failed (%d)",
1108 iFormat
, GetLastError() );
1112 /* store format in private DC data */
1113 dcdata
= ROSGL_GetPrivateDCData( hdc
);
1116 DBGPRINT( "Error: ROSGL_GetPrivateDCData() failed!" );
1119 dcdata
->pixel_format
= iFormat
;
1125 /*! \brief Enable display-list sharing between multiple GLRCs
1127 * This will only work if both GLRCs are from the same driver.
1129 * \param hglrc1 [IN] GLRC number 1
1130 * \param hglrc2 [IN] GLRC number 2
1132 * \retval TRUE Success
1133 * \retval FALSE Failure
1137 rosglShareLists( HGLRC hglrc1
, HGLRC hglrc2
)
1139 GLRC
*glrc1
= (GLRC
*)hglrc1
;
1140 GLRC
*glrc2
= (GLRC
*)hglrc2
;
1143 if (!ROSGL_ContainsContext( glrc1
))
1145 DBGPRINT( "Error: hglrc1 not found!" );
1146 SetLastError( ERROR_INVALID_HANDLE
);
1149 if (!ROSGL_ContainsContext( glrc2
))
1151 DBGPRINT( "Error: hglrc2 not found!" );
1152 SetLastError( ERROR_INVALID_HANDLE
);
1156 /* I think this is only possible within one ICD */
1157 if (glrc1
->icd
!= glrc2
->icd
)
1159 DBGPRINT( "Error: hglrc1 and hglrc2 use different ICDs!" );
1160 SetLastError( ERROR_INVALID_HANDLE
);
1164 /* share lists (call ICD) */
1165 return glrc1
->icd
->DrvShareLists( glrc1
->hglrc
, glrc2
->hglrc
);
1169 /*! \brief Flushes GL and swaps front/back buffer if appropriate
1171 * \param hdc [IN] Handle to device context to swap buffers for
1173 * \retval TRUE Success
1174 * \retval FALSE Failure
1178 rosglSwapBuffers( HDC hdc
)
1180 GLDRIVERDATA
*icd
= ROSGL_ICDForHDC( hdc
);
1181 DBGTRACE( "Called!" );
1184 DBGPRINT( "Swapping buffers!" );
1185 if (!icd
->DrvSwapBuffers( hdc
))
1187 DBGPRINT( "Error: DrvSwapBuffers failed (%d)", GetLastError() );
1193 /* FIXME: implement own functionality? */
1194 SetLastError( ERROR_INVALID_FUNCTION
);
1201 rosglSwapLayerBuffers( HDC hdc
, UINT fuPlanes
)
1205 if(fuPlanes
& WGL_SWAP_MAIN_PLANE
)
1206 ret
= rosglSwapBuffers(hdc
);
1208 if(fuPlanes
&~WGL_SWAP_MAIN_PLANE
)
1209 DBGTRACE("wglSwapLayerBuffers is not fully implemented\n");
1217 rosglUseFontBitmapsA( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
)
1219 return IntUseFontBitmapsA(hdc
, first
, count
, listBase
);
1225 rosglUseFontBitmapsW( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
)
1227 return IntUseFontBitmapsW(hdc
, first
, count
, listBase
);
1232 rosglUseFontOutlinesA( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
,
1233 FLOAT deviation
, FLOAT extrusion
, int format
,
1234 GLYPHMETRICSFLOAT
*pgmf
)
1236 return IntUseFontOutlinesA(hdc
, first
, count
, listBase
, deviation
, extrusion
, format
, pgmf
);
1242 rosglUseFontOutlinesW( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
,
1243 FLOAT deviation
, FLOAT extrusion
, int format
,
1244 GLYPHMETRICSFLOAT
*pgmf
)
1246 return IntUseFontOutlinesW(hdc
, first
, count
, listBase
, deviation
, extrusion
, format
, pgmf
);
1251 #endif /* __cplusplus */