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
)
136 if (WaitForSingleObject( OPENGL32_processdata
.dcdata_mutex
, INFINITE
) ==
139 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
143 p
= OPENGL32_processdata
.dcdata_list
;
144 pptr
= &OPENGL32_processdata
.dcdata_list
;
150 OPENGL32_UnloadICD( p
->icd
);
152 if (!HeapFree( GetProcessHeap(), 0, p
))
153 DBGPRINT( "Warning: HeapFree() on GLDCDATA failed (%d)",
166 if (!ReleaseMutex( OPENGL32_processdata
.dcdata_mutex
))
167 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
171 /*! \brief Delete a GL Context (GLRC) and remove it from the list
173 * \param glrc [IN] Pointer to GLRC to delete
175 * \retval TRUE Success
176 * \retval FALSE Failure
180 ROSGL_DeleteContext( GLRC
*glrc
)
183 if ((glrc
->icd
!= NULL
) && (!InterlockedDecrement((LONG
*)&glrc
->icd
->refcount
)))
185 /* This is the last context, remove the ICD*/
186 ROSGL_DeleteDCDataForICD( glrc
->icd
);
189 /* remove from list */
190 ROSGL_RemoveContext( glrc
);
193 HeapFree( GetProcessHeap(), 0, glrc
);
199 /*! \brief Check wether a GLRC is in the list
201 * \param glrc [IN] Pointer to GLRC to look for in the list
203 * \retval TRUE GLRC was found
204 * \retval FALSE GLRC was not found
208 ROSGL_ContainsContext( GLRC
*glrc
)
214 if (WaitForSingleObject( OPENGL32_processdata
.glrc_mutex
, INFINITE
) ==
217 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
218 return FALSE
; /* FIXME: do we have to expect such an error and handle it? */
221 p
= OPENGL32_processdata
.glrc_list
;
233 if (!ReleaseMutex( OPENGL32_processdata
.glrc_mutex
))
234 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
240 /*! \brief Get GL private DC data.
242 * This function adds an empty GLDCDATA to the list if there is no data for the
245 * \param hdc [IN] Handle to a Device Context for which to get the data
247 * \return Pointer to GLDCDATA on success
248 * \retval NULL on failure
252 ROSGL_GetPrivateDCData( HDC hdc
)
258 if (GetObjectType( hdc
) != OBJ_DC
&& GetObjectType( hdc
) != OBJ_MEMDC
)
260 DBGPRINT( "Error: hdc is not a DC handle!" );
261 SetLastError( ERROR_INVALID_HANDLE
);
266 if (WaitForSingleObject( OPENGL32_processdata
.dcdata_mutex
, INFINITE
) ==
269 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
270 return NULL
; /* FIXME: do we have to expect such an error and handle it? */
273 /* We must use the window to identify our data, as pixel format is
274 * specific to a window for device context */
275 handle
= WindowFromDC(hdc
);
279 /* look for data in list */
280 data
= OPENGL32_processdata
.dcdata_list
;
283 if (data
->handle
== handle
) /* found */
288 /* allocate new data if not found in list */
291 data
= HeapAlloc( GetProcessHeap(),
292 HEAP_ZERO_MEMORY
| HEAP_GENERATE_EXCEPTIONS
,
296 DBGPRINT( "Error: HeapAlloc() failed (%d)", GetLastError() );
300 data
->handle
= handle
;
302 /* append data to list */
303 if (OPENGL32_processdata
.dcdata_list
== NULL
)
304 OPENGL32_processdata
.dcdata_list
= data
;
307 GLDCDATA
*p
= OPENGL32_processdata
.dcdata_list
;
308 while (p
->next
!= NULL
)
316 if (!ReleaseMutex( OPENGL32_processdata
.dcdata_mutex
))
317 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
323 /*! \brief Get ICD from HDC.
325 * This function asks the display driver which OpenGL ICD to load for the given
326 * HDC, loads it and returns a pointer to a GLDRIVERDATA struct on success.
328 * \param hdc [IN] Handle for DC for which to load/get the ICD
330 * \return Pointer to GLDRIVERDATA
331 * \retval NULL Failure.
335 ROSGL_ICDForHDC( HDC hdc
)
338 GLDRIVERDATA
*drvdata
;
340 dcdata
= ROSGL_GetPrivateDCData( hdc
);
344 if (dcdata
->icd
== NULL
)
349 /* NOTE: This might be done by multiple threads simultaneously, but only the fastest
350 actually gets to set the ICD! */
352 driverName
= _wgetenv( L
"OPENGL32_DRIVER" );
353 if (driverName
== NULL
)
358 /* get driver name */
359 dwInput
= OPENGL_GETINFO
;
360 ret
= ExtEscape( hdc
, QUERYESCSUPPORT
, sizeof (dwInput
), (LPCSTR
)&dwInput
, 0, NULL
);
364 ret
= ExtEscape( hdc
, OPENGL_GETINFO
, sizeof (dwInput
),
365 (LPCSTR
)&dwInput
, sizeof (OPENGL_INFO
),
375 DBGPRINT( "Warning: ExtEscape to get the drivername failed! (%d)", GetLastError() );
376 if (MessageBox( WindowFromDC( hdc
), L
"Couldn't get installable client driver name!\nUsing default driver.",
377 L
"OPENGL32.dll: Warning", MB_OKCANCEL
| MB_ICONWARNING
) == IDCANCEL
)
383 /* open registry key */
384 ret
= RegOpenKeyExW( HKEY_LOCAL_MACHINE
, OPENGL_DRIVERS_SUBKEY
, 0, KEY_QUERY_VALUE
, &hKey
);
385 if (ret
!= ERROR_SUCCESS
)
387 DBGPRINT( "Error: Couldn't open registry key '%ws'", OPENGL_DRIVERS_SUBKEY
);
393 size
= sizeof (info
.DriverName
);
394 ret
= RegQueryValueExW( hKey
, L
"DefaultDriver", 0, &type
, (LPBYTE
)info
.DriverName
, &size
);
396 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
398 DBGPRINT( "Error: Couldn't query DefaultDriver value or not a string" );
406 wcsncpy( info
.DriverName
, driverName
, sizeof (info
.DriverName
) / sizeof (info
.DriverName
[0]) );
408 /* load driver (or get a reference) */
409 drvdata
= OPENGL32_LoadICD( info
.DriverName
);
413 snwprintf(Buffer
, sizeof(Buffer
)/sizeof(WCHAR
),
414 L
"Couldn't load driver \"%s\".", info
.DriverName
);
415 MessageBox(WindowFromDC( hdc
), Buffer
,
416 L
"OPENGL32.dll: Warning",
417 MB_OK
| MB_ICONWARNING
);
421 /* Atomically set the ICD!!! */
422 if (InterlockedCompareExchangePointer((PVOID
*)&dcdata
->icd
,
426 /* Too bad, somebody else was faster... */
427 DBGTRACE("ICD is already set!\n");
436 /*! \brief SetContextCallBack passed to DrvSetContext.
438 * This function gets called by the OpenGL driver whenever the current GL
439 * context (dispatch table) is to be changed.
441 * \param table [IN] Function pointer table (first DWORD is number of functions)
443 * \return unkown (maybe void? ERROR_SUCCESS at the moment)
447 ROSGL_SetContextCallBack( const ICDTable
*table
)
450 PROC
*tebTable
, *tebDispatchTable
;
453 teb
= NtCurrentTeb();
454 tebTable
= (PROC
*)teb
->glTable
;
455 tebDispatchTable
= (PROC
*)teb
->glDispatchTable
;
457 DBGTRACE( "Called!" );
461 DBGPRINT( "Function count: %d\n", table
->num_funcs
);
464 size
= sizeof (PROC
) * table
->num_funcs
;
465 memcpy( tebTable
, table
->dispatch_table
, size
);
466 memset( tebTable
+ table
->num_funcs
, 0, DISPATCH_TABLE_SIZE
- size
);
470 DBGPRINT( "Unsetting current context" );
471 memset( tebTable
, 0, DISPATCH_TABLE_SIZE
);
474 /* put in empty functions as long as we dont have a fallback */
475 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
476 if (tebTable[icdidx] == NULL) \
479 DBGPRINT( "Warning: GL proc '%s' is NULL", #func ); \
480 tebTable[icdidx] = (PROC)glEmptyFunc##stack; \
485 /* fill teb->glDispatchTable for fast calls */
486 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
488 tebDispatchTable[tebidx] = tebTable[icdidx];
494 return ERROR_SUCCESS
;
498 /*! \brief Returns the current pixelformat.
500 * \param hdc [IN] Handle to DC to get the pixelformat from
502 * \return Pixelformat index
507 rosglGetPixelFormat( HDC hdc
)
511 DBGTRACE( "Called!" );
513 dcdata
= ROSGL_GetPrivateDCData( hdc
);
516 DBGPRINT( "Error: ROSGL_GetPrivateDCData failed!" );
520 return dcdata
->pixel_format
;
524 /*! \brief Attempts to find the best matching pixel format for HDC
526 * This function is comparing each available format with the preferred one
527 * and returns the one which is closest to it.
528 * If PFD_DOUBLEBUFFER, PFD_STEREO or one of PFD_DRAW_TO_WINDOW,
529 * PFD_DRAW_TO_BITMAP, PFD_SUPPORT_GDI and PDF_SUPPORT_OPENGL is given then
530 * only formats which also support those will be enumerated (unless
531 * PFD_DOUBLEBUFFER_DONTCARE or PFD_STEREO_DONTCARE is also set)
533 * \param hdc [IN] Handle to DC for which to get a pixel format index
534 * \param pfd [IN] PFD describing what kind of format you want
536 * \return Pixel format index
537 * \retval 0 Failed to find a suitable format
539 #define BUFFERDEPTH_SCORE(want, have) \
540 ((want == 0) ? (0) : ((want < have) ? (1) : ((want > have) ? (3) : (0))))
542 /* Score if we want and not have it */
543 #define FLAG_SCORE(want, have, flag) \
544 (((want & ~have) & flag) ? (1) : (0))
546 /* Score if what we want is different than what we have, except when
548 #define FLAG_SCORE_DONTCARE(want, have, flag) \
549 ((!(have & flag ## _DONTCARE)) && ((want & flag) != (have & flag)) ? (1) : (0))
553 rosglChoosePixelFormat( HDC hdc
, CONST PIXELFORMATDESCRIPTOR
*pfd
)
556 PIXELFORMATDESCRIPTOR icdPfd
;
559 int score
, bestScore
= 0x7fff; /* used to choose a pfd if no exact match */
562 DBGTRACE( "Called!" );
565 icd
= ROSGL_ICDForHDC( hdc
);
570 if (pfd
->nSize
!= sizeof (PIXELFORMATDESCRIPTOR
) || pfd
->nVersion
!= 1)
572 SetLastError( ERROR_INVALID_PARAMETER
);
576 /* get number of formats */
577 icdNumFormats
= icd
->DrvDescribePixelFormat( hdc
, 1,
578 sizeof (PIXELFORMATDESCRIPTOR
), &icdPfd
);
579 if (icdNumFormats
== 0)
581 DBGPRINT( "Error: DrvDescribePixelFormat failed (%d)", GetLastError() );
584 DBGPRINT( "Info: Enumerating %d pixelformats", icdNumFormats
);
586 /* try to find best format */
587 for (i
= 0; i
< icdNumFormats
; i
++)
589 if (icd
->DrvDescribePixelFormat( hdc
, i
+ 1,
590 sizeof (PIXELFORMATDESCRIPTOR
), &icdPfd
) == 0)
592 DBGPRINT( "Warning: DrvDescribePixelFormat failed (%d)",
597 if ((pfd
->dwFlags
& PFD_GENERIC_ACCELERATED
) != 0) /* we do not support such kind of drivers */
602 score
= 0; /* higher is worse */
605 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_DRAW_TO_WINDOW
);
606 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_DRAW_TO_BITMAP
);
607 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_SUPPORT_GDI
);
608 score
+= FLAG_SCORE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_SUPPORT_OPENGL
);
609 score
+= FLAG_SCORE_DONTCARE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_DOUBLEBUFFER
);
610 score
+= FLAG_SCORE_DONTCARE(pfd
->dwFlags
, icdPfd
.dwFlags
, PFD_STEREO
);
612 /* check other attribs */
613 if (pfd
->iPixelType
!= icdPfd
.iPixelType
)
614 score
+= 5; /* this is really bad i think */
615 if (pfd
->iLayerType
!= icdPfd
.iLayerType
)
616 score
+= 15; /* this is very very bad ;) */
618 score
+= BUFFERDEPTH_SCORE(pfd
->cAlphaBits
, icdPfd
.cAlphaBits
);
619 score
+= BUFFERDEPTH_SCORE(pfd
->cAccumBits
, icdPfd
.cAccumBits
);
620 score
+= BUFFERDEPTH_SCORE(pfd
->cDepthBits
, icdPfd
.cDepthBits
);
621 score
+= BUFFERDEPTH_SCORE(pfd
->cStencilBits
, icdPfd
.cStencilBits
);
622 score
+= BUFFERDEPTH_SCORE(pfd
->cAuxBuffers
, icdPfd
.cAuxBuffers
);
625 if (score
< bestScore
)
635 SetLastError( 0 ); /* FIXME: set appropriate error */
637 DBGPRINT( "Info: Suggesting pixelformat %d", best
);
642 /*! \brief Copy data specified by mask from one GLRC to another.
644 * \param src [IN] Source GLRC
645 * \param src [OUT] Destination GLRC
646 * \param mask [IN] Bitfield like given to glPushAttrib()
648 * \retval TRUE Success
649 * \retval FALSE Failure
653 rosglCopyContext( HGLRC hsrc
, HGLRC hdst
, UINT mask
)
655 GLRC
*src
= (GLRC
*)hsrc
;
656 GLRC
*dst
= (GLRC
*)hdst
;
659 if (!ROSGL_ContainsContext( src
))
661 DBGPRINT( "Error: src GLRC not found!" );
662 SetLastError( ERROR_INVALID_HANDLE
);
665 if (!ROSGL_ContainsContext( dst
))
667 DBGPRINT( "Error: dst GLRC not found!" );
668 SetLastError( ERROR_INVALID_HANDLE
);
672 /* I think this is only possible within one ICD */
673 if (src
->icd
!= dst
->icd
)
675 DBGPRINT( "Error: src and dst GLRC use different ICDs!" );
676 SetLastError( ERROR_INVALID_HANDLE
);
680 /* copy data (call ICD) */
681 return src
->icd
->DrvCopyContext( src
->hglrc
, dst
->hglrc
, mask
);
685 /*! \brief Create a new GL Rendering Context.
687 * This function can create over- or underlay surfaces.
689 * \param hdc [IN] Handle for DC for which to create context
690 * \param layer [IN] Layer number to bind (draw?) to
692 * \return Handle for the created GLRC
693 * \retval NULL Failure
697 rosglCreateLayerContext( HDC hdc
, int layer
)
699 GLDRIVERDATA
*icd
= NULL
;
701 HGLRC drvHglrc
= NULL
;
703 DBGTRACE( "Called!" );
705 /* if (GetObjectType( hdc ) != OBJ_DC)
707 DBGPRINT( "Error: hdc is not a DC handle!" );
713 icd
= ROSGL_ICDForHDC( hdc
);
716 DBGPRINT( "Couldn't get ICD by HDC :-(" );
717 /* FIXME: fallback? */
721 /* create new GLRC */
722 glrc
= ROSGL_NewContext();
726 /* Don't forget to refcount it, icd will be released when last context is deleted */
727 InterlockedIncrement((LONG
*)&icd
->refcount
);
729 /* You can't create a context without first setting a valid pixel format */
730 if(rosglGetPixelFormat(hdc
) == 0)
732 ROSGL_DeleteContext( glrc
);
733 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
739 if (icd
->DrvCreateLayerContext
!= NULL
)
740 drvHglrc
= icd
->DrvCreateLayerContext( hdc
, layer
);
741 if (drvHglrc
== NULL
)
743 if (layer
== 0 && icd
->DrvCreateContext
!= NULL
)
744 drvHglrc
= icd
->DrvCreateContext( hdc
);
746 DBGPRINT( "Warning: CreateLayerContext not supported by ICD!" );
749 if (drvHglrc
== NULL
)
751 /* FIXME: fallback to mesa? */
752 DBGPRINT( "Error: DrvCreate[Layer]Context failed! (%d)", GetLastError() );
753 ROSGL_DeleteContext( glrc
);
757 /* we have our GLRC in glrc and the ICD's GLRC in drvHglrc */
758 glrc
->hglrc
= drvHglrc
;
765 /*! \brief Create a new GL Rendering Context.
767 * \param hdc [IN] Handle for DC for which to create context
769 * \return Handle for the created GLRC
770 * \retval NULL Failure
774 rosglCreateContext( HDC hdc
)
776 return rosglCreateLayerContext( hdc
, 0 );
780 /*! \brief Delete an OpenGL context
782 * \param hglrc [IN] Handle to GLRC to delete;
784 * \retval TRUE Success
785 * \retval FALSE Failure (i.e. GLRC is current for a thread)
789 rosglDeleteContext( HGLRC hglrc
)
791 GLRC
*glrc
= (GLRC
*)hglrc
;
793 /* check if we know about this context */
794 if (!ROSGL_ContainsContext( glrc
))
796 DBGPRINT( "Error: hglrc not found!" );
797 SetLastError( ERROR_INVALID_HANDLE
);
801 /* On windows, this is allowed to delete a context which is current */
802 if (glrc
->is_current
)
804 /* But only for its own thread */
805 if(glrc
->thread_id
!= GetCurrentThreadId())
807 DBGPRINT( "Error: GLRC is current for DC 0x%08x", glrc
->hdc
);
808 SetLastError( ERROR_INVALID_FUNCTION
);
811 /* Unset it before going further */
812 rosglMakeCurrent(NULL
, NULL
);
815 /* release ICD's context */
816 if (glrc
->hglrc
!= NULL
)
818 if (!glrc
->icd
->DrvDeleteContext( glrc
->hglrc
))
820 DBGPRINT( "Warning: DrvDeleteContext() failed (%d)", GetLastError() );
826 return ROSGL_DeleteContext( glrc
);
832 rosglDescribeLayerPlane( HDC hdc
, int iPixelFormat
, int iLayerPlane
,
833 UINT nBytes
, LPLAYERPLANEDESCRIPTOR plpd
)
836 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
841 /*! \brief Gets information about a pixelformat.
843 * \param hdc [IN] Handle to DC
844 * \param iFormat [IN] Pixelformat index
845 * \param nBytes [IN] sizeof (pfd) - at most nBytes are copied into pfd
846 * \param pfd [OUT] Pointer to a PIXELFORMATDESCRIPTOR
848 * \return Maximum pixelformat index/number of formats
853 rosglDescribePixelFormat( HDC hdc
, int iFormat
, UINT nBytes
,
854 LPPIXELFORMATDESCRIPTOR pfd
)
857 GLDRIVERDATA
*icd
= ROSGL_ICDForHDC( hdc
);
861 ret
= icd
->DrvDescribePixelFormat( hdc
, iFormat
, nBytes
, pfd
);
863 DBGPRINT( "Error: DrvDescribePixelFormat(format=%d) failed (%d)", iFormat
, GetLastError() );
867 SetLastError( ERROR_INVALID_FUNCTION
);
874 /*! \brief Return the thread's current GLRC
876 * \return Handle for thread's current GLRC
877 * \retval NULL No current GLRC set
881 rosglGetCurrentContext()
883 return NtCurrentTeb()->glCurrentRC
;
887 /*! \brief Return the thread's current DC
889 * \return Handle for thread's current DC
890 * \retval NULL No current DC/GLRC set
896 GLRC
* glrc
= (GLRC
*)NtCurrentTeb()->glCurrentRC
;
897 if(glrc
) return glrc
->hdc
;
904 rosglGetLayerPaletteEntries( HDC hdc
, int iLayerPlane
, int iStart
,
905 int cEntries
, COLORREF
*pcr
)
908 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
913 /*! \brief Get the address for an OpenGL extension function.
915 * The addresses this function returns are only valid within the same thread
916 * which it was called from.
918 * \param proc [IN] Name of the function to look for
920 * \return The address of the proc
921 * \retval NULL Failure
925 rosglGetProcAddress( LPCSTR proc
)
928 GLRC
* glrc
= (GLRC
*)NtCurrentTeb()->glCurrentRC
;
930 /* FIXME we should Flush the gl here */
934 DBGPRINT( "Error: No current GLRC!" );
935 SetLastError( ERROR_INVALID_FUNCTION
);
939 func
= glrc
->icd
->DrvGetProcAddress( proc
);
942 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc
);
946 /* FIXME: Should we return wgl/gl 1.1 functions? */
947 SetLastError( ERROR_PROC_NOT_FOUND
);
953 rosglGetDefaultProcAddress( LPCSTR proc
)
956 GLRC
* glrc
= (GLRC
*)NtCurrentTeb()->glCurrentRC
;
958 /* wglGetDefaultProcAddress does not flush the gl */
962 DBGPRINT( "Error: No current GLRC!" );
963 SetLastError( ERROR_INVALID_FUNCTION
);
967 func
= glrc
->icd
->DrvGetProcAddress( proc
);
970 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc
);
974 /* FIXME: Should we return wgl/gl 1.1 functions? */
975 SetLastError( ERROR_PROC_NOT_FOUND
);
980 /*! \brief Make the given GLRC the threads current GLRC for hdc
982 * \param hdc [IN] Handle for a DC to be drawn on
983 * \param hglrc [IN] Handle for a GLRC to make current
985 * \retval TRUE Success
986 * \retval FALSE Failure
990 rosglMakeCurrent( HDC hdc
, HGLRC hglrc
)
992 GLRC
*glrc
= (GLRC
*)hglrc
;
993 ICDTable
*icdTable
= NULL
;
995 DBGTRACE( "Called!" );
997 /* Is t a new context ? */
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
);
1024 /* Unset previous one */
1025 if (NtCurrentTeb()->glCurrentRC
!= NULL
)
1027 GLRC
*oldglrc
= (GLRC
*)NtCurrentTeb()->glCurrentRC
;
1028 oldglrc
->is_current
= FALSE
;
1029 oldglrc
->thread_id
= 0;
1030 oldglrc
->hdc
= NULL
;
1031 oldglrc
->icd
->DrvReleaseContext(oldglrc
->hglrc
);
1035 if (glrc
->hglrc
!= NULL
)
1037 DBGPRINT( "Info: Calling DrvSetContext!" );
1038 SetLastError( ERROR_SUCCESS
);
1039 icdTable
= glrc
->icd
->DrvSetContext( hdc
, glrc
->hglrc
,
1040 (void *)ROSGL_SetContextCallBack
);
1041 if (icdTable
== NULL
)
1043 DBGPRINT( "Error: DrvSetContext failed (%d)\n", GetLastError() );
1044 NtCurrentTeb()->glCurrentRC
= NULL
;
1047 DBGPRINT( "Info: DrvSetContext succeeded!" );
1050 /* make it current */
1051 glrc
->is_current
= TRUE
;
1052 glrc
->thread_id
= GetCurrentThreadId();
1054 NtCurrentTeb()->glCurrentRC
= (HGLRC
)glrc
;
1056 else if(NtCurrentTeb()->glCurrentRC
)
1058 /* This is a call to unset the context */
1059 GLRC
*oldglrc
= (GLRC
*)NtCurrentTeb()->glCurrentRC
;
1060 oldglrc
->is_current
= FALSE
;
1061 oldglrc
->thread_id
= 0;
1062 oldglrc
->hdc
= NULL
;
1063 oldglrc
->icd
->DrvReleaseContext(oldglrc
->hglrc
);
1064 NtCurrentTeb()->glCurrentRC
= NULL
;
1069 * To make wine tests happy.
1070 * Now, who cares if MakeCurrentContext(NULL, NULL) fails when current context is already NULL
1072 if (GetObjectType( hdc
) != OBJ_DC
&& GetObjectType( hdc
) != OBJ_MEMDC
)
1074 DBGPRINT( "Error: hdc is not a DC handle!" );
1075 SetLastError( ERROR_INVALID_HANDLE
);
1080 if (ROSGL_SetContextCallBack( icdTable
) != ERROR_SUCCESS
&& icdTable
== NULL
)
1082 DBGPRINT( "Warning: ROSGL_SetContextCallBack failed!" );
1091 rosglRealizeLayerPalette( HDC hdc
, int iLayerPlane
, BOOL bRealize
)
1094 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1101 rosglSetLayerPaletteEntries( HDC hdc
, int iLayerPlane
, int iStart
,
1102 int cEntries
, CONST COLORREF
*pcr
)
1105 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1110 /*! \brief Set a DCs pixelformat
1112 * \param hdc [IN] Handle to DC for which to set the format
1113 * \param iFormat [IN] Index of the pixelformat to set
1114 * \param pfd [IN] Not sure what this is for
1116 * \retval TRUE Success
1117 * \retval FALSE Failure
1121 rosglSetPixelFormat( HDC hdc
, int iFormat
, CONST PIXELFORMATDESCRIPTOR
*pfd
)
1126 DBGTRACE( "Called!" );
1128 /* Get private DC data */
1129 dcdata
= ROSGL_GetPrivateDCData( hdc
);
1132 DBGPRINT( "Error: ROSGL_GetPrivateDCData() failed!" );
1135 /* you can set the same pixel format twice, but you can't modify it */
1136 if(dcdata
->pixel_format
) return dcdata
->pixel_format
== iFormat
;
1138 icd
= ROSGL_ICDForHDC(hdc
);
1142 /* Call ICD function */
1143 if (!icd
->DrvSetPixelFormat( hdc
, iFormat
, pfd
))
1145 DBGPRINT( "Warning: DrvSetPixelFormat(format=%d) failed (%d)",
1146 iFormat
, GetLastError() );
1149 dcdata
->pixel_format
= iFormat
;
1155 /*! \brief Enable display-list sharing between multiple GLRCs
1157 * This will only work if both GLRCs are from the same driver.
1159 * \param hglrc1 [IN] GLRC number 1
1160 * \param hglrc2 [IN] GLRC number 2
1162 * \retval TRUE Success
1163 * \retval FALSE Failure
1167 rosglShareLists( HGLRC hglrc1
, HGLRC hglrc2
)
1169 GLRC
*glrc1
= (GLRC
*)hglrc1
;
1170 GLRC
*glrc2
= (GLRC
*)hglrc2
;
1173 if (!ROSGL_ContainsContext( glrc1
))
1175 DBGPRINT( "Error: hglrc1 not found!" );
1176 SetLastError( ERROR_INVALID_HANDLE
);
1179 if (!ROSGL_ContainsContext( glrc2
))
1181 DBGPRINT( "Error: hglrc2 not found!" );
1182 SetLastError( ERROR_INVALID_HANDLE
);
1186 /* I think this is only possible within one ICD */
1187 if (glrc1
->icd
!= glrc2
->icd
)
1189 DBGPRINT( "Error: hglrc1 and hglrc2 use different ICDs!" );
1190 SetLastError( ERROR_INVALID_HANDLE
);
1194 /* share lists (call ICD) */
1195 return glrc1
->icd
->DrvShareLists( glrc1
->hglrc
, glrc2
->hglrc
);
1199 /*! \brief Flushes GL and swaps front/back buffer if appropriate
1201 * \param hdc [IN] Handle to device context to swap buffers for
1203 * \retval TRUE Success
1204 * \retval FALSE Failure
1208 rosglSwapBuffers( HDC hdc
)
1210 GLDRIVERDATA
*icd
= ROSGL_ICDForHDC( hdc
);
1211 DBGTRACE( "Called!" );
1214 DBGPRINT( "Swapping buffers!" );
1215 if (!icd
->DrvSwapBuffers( hdc
))
1217 DBGPRINT( "Error: DrvSwapBuffers failed (%d)", GetLastError() );
1223 /* FIXME: implement own functionality? */
1224 SetLastError( ERROR_INVALID_FUNCTION
);
1231 rosglSwapLayerBuffers( HDC hdc
, UINT fuPlanes
)
1235 if(fuPlanes
& WGL_SWAP_MAIN_PLANE
)
1236 ret
= rosglSwapBuffers(hdc
);
1238 if(fuPlanes
&~WGL_SWAP_MAIN_PLANE
)
1239 DBGTRACE("wglSwapLayerBuffers is not fully implemented\n");
1247 rosglUseFontBitmapsA( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
)
1249 return IntUseFontBitmapsA(hdc
, first
, count
, listBase
);
1255 rosglUseFontBitmapsW( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
)
1257 return IntUseFontBitmapsW(hdc
, first
, count
, listBase
);
1262 rosglUseFontOutlinesA( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
,
1263 FLOAT deviation
, FLOAT extrusion
, int format
,
1264 GLYPHMETRICSFLOAT
*pgmf
)
1266 return IntUseFontOutlinesA(hdc
, first
, count
, listBase
, deviation
, extrusion
, format
, pgmf
);
1272 rosglUseFontOutlinesW( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
,
1273 FLOAT deviation
, FLOAT extrusion
, int format
,
1274 GLYPHMETRICSFLOAT
*pgmf
)
1276 return IntUseFontOutlinesW(hdc
, first
, count
, listBase
, deviation
, extrusion
, format
, pgmf
);
1281 #endif /* __cplusplus */