Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwgl.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: lib/opengl32/wgl.c 00005 * PURPOSE: OpenGL32 lib, rosglXXX functions 00006 * PROGRAMMER: Anich Gregor (blight) 00007 * UPDATE HISTORY: 00008 * Feb 2, 2004: Created 00009 */ 00010 00011 #define OPENGL32_GL_FUNC_PROTOTYPES 00012 #include "opengl32.h" 00013 00014 #ifdef __cplusplus 00015 extern "C" { 00016 #endif /* __cplusplus */ 00017 00018 #if !defined(UNIMPLEMENTED) 00019 # define UNIMPLEMENTED DBGPRINT( "UNIMPLEMENTED" ) 00020 #endif 00021 00022 00023 typedef struct _OPENGL_INFO 00024 { 00025 DWORD Version; 00026 DWORD DriverVersion; 00027 WCHAR DriverName[256]; 00028 } OPENGL_INFO, *POPENGL_INFO; 00029 00034 static 00035 void 00036 ROSGL_AppendContext( GLRC *glrc ) 00037 { 00038 /* synchronize */ 00039 if (WaitForSingleObject( OPENGL32_processdata.glrc_mutex, INFINITE ) == 00040 WAIT_FAILED) 00041 { 00042 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00043 return; /* FIXME: do we have to expect such an error and handle it? */ 00044 } 00045 00046 if (OPENGL32_processdata.glrc_list == NULL) 00047 OPENGL32_processdata.glrc_list = glrc; 00048 else 00049 { 00050 GLRC *p = OPENGL32_processdata.glrc_list; 00051 while (p->next != NULL) 00052 p = p->next; 00053 p->next = glrc; 00054 } 00055 00056 /* release mutex */ 00057 if (!ReleaseMutex( OPENGL32_processdata.glrc_mutex )) 00058 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00059 } 00060 00061 00066 static 00067 void 00068 ROSGL_RemoveContext( GLRC *glrc ) 00069 { 00070 /* synchronize */ 00071 if (WaitForSingleObject( OPENGL32_processdata.glrc_mutex, INFINITE ) == 00072 WAIT_FAILED) 00073 { 00074 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00075 return; /* FIXME: do we have to expect such an error and handle it? */ 00076 } 00077 00078 if (glrc == OPENGL32_processdata.glrc_list) 00079 OPENGL32_processdata.glrc_list = glrc->next; 00080 else 00081 { 00082 GLRC *p = OPENGL32_processdata.glrc_list; 00083 while (p != NULL) 00084 { 00085 if (p->next == glrc) 00086 { 00087 p->next = glrc->next; 00088 break; 00089 } 00090 p = p->next; 00091 } 00092 if (p == NULL) 00093 DBGPRINT( "Error: GLRC 0x%08x not found in list!", glrc ); 00094 } 00095 00096 /* release mutex */ 00097 if (!ReleaseMutex( OPENGL32_processdata.glrc_mutex )) 00098 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00099 } 00100 00101 00107 static 00108 GLRC * 00109 ROSGL_NewContext(void) 00110 { 00111 GLRC *glrc; 00112 00113 /* allocate GLRC */ 00114 glrc = (GLRC*)HeapAlloc( GetProcessHeap(), 00115 HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, sizeof (GLRC) ); 00116 00117 /* append to list */ 00118 ROSGL_AppendContext( glrc ); 00119 00120 return glrc; 00121 } 00122 00127 static 00128 VOID 00129 ROSGL_DeleteDCDataForICD( GLDRIVERDATA *icd ) 00130 { 00131 GLDCDATA *p, **pptr; 00132 00133 /* synchronize */ 00134 if (WaitForSingleObject( OPENGL32_processdata.dcdata_mutex, INFINITE ) == 00135 WAIT_FAILED) 00136 { 00137 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00138 return; 00139 } 00140 00141 p = OPENGL32_processdata.dcdata_list; 00142 pptr = &OPENGL32_processdata.dcdata_list; 00143 while (p != NULL) 00144 { 00145 if (p->icd == icd) 00146 { 00147 *pptr = p->next; 00148 OPENGL32_UnloadICD( p->icd ); 00149 00150 if (!HeapFree( GetProcessHeap(), 0, p )) 00151 DBGPRINT( "Warning: HeapFree() on GLDCDATA failed (%d)", 00152 GetLastError() ); 00153 00154 p = *pptr; 00155 } 00156 else 00157 { 00158 pptr = &p->next; 00159 p = p->next; 00160 } 00161 } 00162 00163 /* release mutex */ 00164 if (!ReleaseMutex( OPENGL32_processdata.dcdata_mutex )) 00165 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00166 } 00167 00168 00176 static 00177 BOOL 00178 ROSGL_DeleteContext( GLRC *glrc ) 00179 { 00180 /* unload icd */ 00181 if ((glrc->icd != NULL) && (!InterlockedDecrement((LONG*)&glrc->icd->refcount))) 00182 { 00183 /* This is the last context, remove the ICD*/ 00184 ROSGL_DeleteDCDataForICD( glrc->icd ); 00185 } 00186 00187 /* remove from list */ 00188 ROSGL_RemoveContext( glrc ); 00189 00190 /* free memory */ 00191 HeapFree( GetProcessHeap(), 0, glrc ); 00192 00193 return TRUE; 00194 } 00195 00196 00204 static 00205 BOOL 00206 ROSGL_ContainsContext( GLRC *glrc ) 00207 { 00208 GLRC *p; 00209 BOOL found = FALSE; 00210 00211 /* synchronize */ 00212 if (WaitForSingleObject( OPENGL32_processdata.glrc_mutex, INFINITE ) == 00213 WAIT_FAILED) 00214 { 00215 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00216 return FALSE; /* FIXME: do we have to expect such an error and handle it? */ 00217 } 00218 00219 p = OPENGL32_processdata.glrc_list; 00220 while (p != NULL) 00221 { 00222 if (p == glrc) 00223 { 00224 found = TRUE; 00225 break; 00226 } 00227 p = p->next; 00228 } 00229 00230 /* release mutex */ 00231 if (!ReleaseMutex( OPENGL32_processdata.glrc_mutex )) 00232 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00233 00234 return found; 00235 } 00236 00237 00248 static 00249 GLDCDATA * 00250 ROSGL_GetPrivateDCData( HDC hdc ) 00251 { 00252 GLDCDATA *data; 00253 00254 /* check hdc */ 00255 if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC) 00256 { 00257 DBGPRINT( "Error: hdc is not a DC handle!" ); 00258 SetLastError( ERROR_INVALID_HANDLE ); 00259 return FALSE; 00260 } 00261 00262 /* synchronize */ 00263 if (WaitForSingleObject( OPENGL32_processdata.dcdata_mutex, INFINITE ) == 00264 WAIT_FAILED) 00265 { 00266 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00267 return NULL; /* FIXME: do we have to expect such an error and handle it? */ 00268 } 00269 00270 /* look for data in list */ 00271 data = OPENGL32_processdata.dcdata_list; 00272 while (data != NULL) 00273 { 00274 if (data->hdc == hdc) /* found */ 00275 break; 00276 data = data->next; 00277 } 00278 00279 /* allocate new data if not found in list */ 00280 if (data == NULL) 00281 { 00282 data = HeapAlloc( GetProcessHeap(), 00283 HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, 00284 sizeof (GLDCDATA) ); 00285 if (data == NULL) 00286 { 00287 DBGPRINT( "Error: HeapAlloc() failed (%d)", GetLastError() ); 00288 } 00289 else 00290 { 00291 data->hdc = hdc; 00292 00293 /* append data to list */ 00294 if (OPENGL32_processdata.dcdata_list == NULL) 00295 OPENGL32_processdata.dcdata_list = data; 00296 else 00297 { 00298 GLDCDATA *p = OPENGL32_processdata.dcdata_list; 00299 while (p->next != NULL) 00300 p = p->next; 00301 p->next = data; 00302 } 00303 } 00304 } 00305 00306 /* release mutex */ 00307 if (!ReleaseMutex( OPENGL32_processdata.dcdata_mutex )) 00308 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00309 00310 return data; 00311 } 00312 00313 00324 static 00325 GLDRIVERDATA * 00326 ROSGL_ICDForHDC( HDC hdc ) 00327 { 00328 GLDCDATA *dcdata; 00329 GLDRIVERDATA *drvdata; 00330 00331 dcdata = ROSGL_GetPrivateDCData( hdc ); 00332 if (dcdata == NULL) 00333 return NULL; 00334 00335 if (dcdata->icd == NULL) 00336 { 00337 LPCWSTR driverName; 00338 OPENGL_INFO info; 00339 00340 /* NOTE: This might be done by multiple threads simultaneously, but only the fastest 00341 actually gets to set the ICD! */ 00342 00343 driverName = _wgetenv( L"OPENGL32_DRIVER" ); 00344 if (driverName == NULL) 00345 { 00346 DWORD dwInput; 00347 LONG ret; 00348 00349 /* get driver name */ 00350 dwInput = OPENGL_GETINFO; 00351 ret = ExtEscape( hdc, QUERYESCSUPPORT, sizeof (dwInput), (LPCSTR)&dwInput, 0, NULL ); 00352 if (ret > 0) 00353 { 00354 dwInput = 0; 00355 ret = ExtEscape( hdc, OPENGL_GETINFO, sizeof (dwInput), 00356 (LPCSTR)&dwInput, sizeof (OPENGL_INFO), 00357 (LPSTR)&info ); 00358 } 00359 if (ret <= 0) 00360 { 00361 HKEY hKey; 00362 DWORD type, size; 00363 00364 if (ret < 0) 00365 { 00366 DBGPRINT( "Warning: ExtEscape to get the drivername failed! (%d)", GetLastError() ); 00367 if (MessageBox( WindowFromDC( hdc ), L"Couldn't get installable client driver name!\nUsing default driver.", 00368 L"OPENGL32.dll: Warning", MB_OKCANCEL | MB_ICONWARNING ) == IDCANCEL) 00369 { 00370 return NULL; 00371 } 00372 } 00373 00374 /* open registry key */ 00375 ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, OPENGL_DRIVERS_SUBKEY, 0, KEY_QUERY_VALUE, &hKey ); 00376 if (ret != ERROR_SUCCESS) 00377 { 00378 DBGPRINT( "Error: Couldn't open registry key '%ws'", OPENGL_DRIVERS_SUBKEY ); 00379 SetLastError( ret ); 00380 return NULL; 00381 } 00382 00383 /* query value */ 00384 size = sizeof (info.DriverName); 00385 ret = RegQueryValueExW( hKey, L"DefaultDriver", 0, &type, (LPBYTE)info.DriverName, &size ); 00386 RegCloseKey( hKey ); 00387 if (ret != ERROR_SUCCESS || type != REG_SZ) 00388 { 00389 DBGPRINT( "Error: Couldn't query DefaultDriver value or not a string" ); 00390 SetLastError( ret ); 00391 return NULL; 00392 } 00393 } 00394 } 00395 else 00396 { 00397 wcsncpy( info.DriverName, driverName, sizeof (info.DriverName) / sizeof (info.DriverName[0]) ); 00398 } 00399 /* load driver (or get a reference) */ 00400 drvdata = OPENGL32_LoadICD( info.DriverName ); 00401 if (drvdata == NULL) 00402 { 00403 WCHAR Buffer[256]; 00404 snwprintf(Buffer, sizeof(Buffer)/sizeof(WCHAR), 00405 L"Couldn't load driver \"%s\".", info.DriverName); 00406 MessageBox(WindowFromDC( hdc ), Buffer, 00407 L"OPENGL32.dll: Warning", 00408 MB_OK | MB_ICONWARNING); 00409 } 00410 else 00411 { 00412 /* Atomically set the ICD!!! */ 00413 if (InterlockedCompareExchangePointer((PVOID*)&dcdata->icd, 00414 (PVOID)drvdata, 00415 NULL) != NULL) 00416 { 00417 /* Too bad, somebody else was faster... */ 00418 DBGTRACE("ICD is already set!\n"); 00419 } 00420 } 00421 } 00422 00423 return dcdata->icd; 00424 } 00425 00426 00436 DWORD 00437 CALLBACK 00438 ROSGL_SetContextCallBack( const ICDTable *table ) 00439 { 00440 TEB *teb; 00441 PROC *tebTable, *tebDispatchTable; 00442 INT size; 00443 00444 teb = NtCurrentTeb(); 00445 tebTable = (PROC *)teb->glTable; 00446 tebDispatchTable = (PROC *)teb->glDispatchTable; 00447 00448 DBGTRACE( "Called!" ); 00449 00450 if (table != NULL) 00451 { 00452 DBGPRINT( "Function count: %d\n", table->num_funcs ); 00453 00454 /* save table */ 00455 size = sizeof (PROC) * table->num_funcs; 00456 memcpy( tebTable, table->dispatch_table, size ); 00457 memset( tebTable + table->num_funcs, 0, DISPATCH_TABLE_SIZE - size ); 00458 } 00459 else 00460 { 00461 DBGPRINT( "Unsetting current context" ); 00462 memset( tebTable, 0, DISPATCH_TABLE_SIZE ); 00463 } 00464 00465 /* put in empty functions as long as we dont have a fallback */ 00466 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \ 00467 if (tebTable[icdidx] == NULL) \ 00468 { \ 00469 if (table != NULL) \ 00470 DBGPRINT( "Warning: GL proc '%s' is NULL", #func ); \ 00471 tebTable[icdidx] = (PROC)glEmptyFunc##stack; \ 00472 } 00473 GLFUNCS_MACRO 00474 #undef X 00475 00476 /* fill teb->glDispatchTable for fast calls */ 00477 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \ 00478 if (tebidx >= 0) \ 00479 tebDispatchTable[tebidx] = tebTable[icdidx]; 00480 GLFUNCS_MACRO 00481 #undef X 00482 00483 DBGPRINT( "Done." ); 00484 00485 return ERROR_SUCCESS; 00486 } 00487 00488 00504 #define BUFFERDEPTH_SCORE(want, have) \ 00505 ((want == 0) ? (0) : ((want < have) ? (1) : ((want > have) ? (3) : (0)))) 00506 00507 /* Score if we want and not have it */ 00508 #define FLAG_SCORE(want, have, flag) \ 00509 (((want & ~have) & flag) ? (1) : (0)) 00510 00511 /* Score if what we want is different than what we have, except when 00512 _DONTCARE was set */ 00513 #define FLAG_SCORE_DONTCARE(want, have, flag) \ 00514 ((!(have & flag ## _DONTCARE)) && ((want & flag) != (have & flag)) ? (1) : (0)) 00515 00516 int 00517 APIENTRY 00518 rosglChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *pfd ) 00519 { 00520 GLDRIVERDATA *icd; 00521 PIXELFORMATDESCRIPTOR icdPfd; 00522 int i; 00523 int best = 0; 00524 int score, bestScore = 0x7fff; /* used to choose a pfd if no exact match */ 00525 int icdNumFormats; 00526 00527 DBGTRACE( "Called!" ); 00528 00529 /* load ICD */ 00530 icd = ROSGL_ICDForHDC( hdc ); 00531 if (icd == NULL) 00532 return 0; 00533 00534 /* check input */ 00535 if (pfd->nSize != sizeof (PIXELFORMATDESCRIPTOR) || pfd->nVersion != 1) 00536 { 00537 SetLastError( ERROR_INVALID_PARAMETER ); 00538 return 0; 00539 } 00540 00541 /* get number of formats */ 00542 icdNumFormats = icd->DrvDescribePixelFormat( hdc, 1, 00543 sizeof (PIXELFORMATDESCRIPTOR), &icdPfd ); 00544 if (icdNumFormats == 0) 00545 { 00546 DBGPRINT( "Error: DrvDescribePixelFormat failed (%d)", GetLastError() ); 00547 return 0; 00548 } 00549 DBGPRINT( "Info: Enumerating %d pixelformats", icdNumFormats ); 00550 00551 /* try to find best format */ 00552 for (i = 0; i < icdNumFormats; i++) 00553 { 00554 if (icd->DrvDescribePixelFormat( hdc, i + 1, 00555 sizeof (PIXELFORMATDESCRIPTOR), &icdPfd ) == 0) 00556 { 00557 DBGPRINT( "Warning: DrvDescribePixelFormat failed (%d)", 00558 GetLastError() ); 00559 break; 00560 } 00561 00562 if ((pfd->dwFlags & PFD_GENERIC_ACCELERATED) != 0) /* we do not support such kind of drivers */ 00563 { 00564 continue; 00565 } 00566 00567 score = 0; /* higher is worse */ 00568 00569 /* compare flags */ 00570 score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_DRAW_TO_WINDOW); 00571 score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_DRAW_TO_BITMAP); 00572 score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_SUPPORT_GDI); 00573 score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_SUPPORT_OPENGL); 00574 score += FLAG_SCORE_DONTCARE(pfd->dwFlags, icdPfd.dwFlags, PFD_DOUBLEBUFFER); 00575 score += FLAG_SCORE_DONTCARE(pfd->dwFlags, icdPfd.dwFlags, PFD_STEREO); 00576 00577 /* check other attribs */ 00578 if (pfd->iPixelType != icdPfd.iPixelType) 00579 score += 5; /* this is really bad i think */ 00580 if (pfd->iLayerType != icdPfd.iLayerType) 00581 score += 15; /* this is very very bad ;) */ 00582 00583 score += BUFFERDEPTH_SCORE(pfd->cAlphaBits, icdPfd.cAlphaBits); 00584 score += BUFFERDEPTH_SCORE(pfd->cAccumBits, icdPfd.cAccumBits); 00585 score += BUFFERDEPTH_SCORE(pfd->cDepthBits, icdPfd.cDepthBits); 00586 score += BUFFERDEPTH_SCORE(pfd->cStencilBits, icdPfd.cStencilBits); 00587 score += BUFFERDEPTH_SCORE(pfd->cAuxBuffers, icdPfd.cAuxBuffers); 00588 00589 /* check score */ 00590 if (score < bestScore) 00591 { 00592 bestScore = score; 00593 best = i + 1; 00594 if (bestScore == 0) 00595 break; 00596 } 00597 } 00598 00599 if (best == 0) 00600 SetLastError( 0 ); /* FIXME: set appropriate error */ 00601 00602 DBGPRINT( "Info: Suggesting pixelformat %d", best ); 00603 return best; 00604 } 00605 00606 00616 BOOL 00617 APIENTRY 00618 rosglCopyContext( HGLRC hsrc, HGLRC hdst, UINT mask ) 00619 { 00620 GLRC *src = (GLRC *)hsrc; 00621 GLRC *dst = (GLRC *)hdst; 00622 00623 /* check glrcs */ 00624 if (!ROSGL_ContainsContext( src )) 00625 { 00626 DBGPRINT( "Error: src GLRC not found!" ); 00627 SetLastError( ERROR_INVALID_HANDLE ); 00628 return FALSE; 00629 } 00630 if (!ROSGL_ContainsContext( dst )) 00631 { 00632 DBGPRINT( "Error: dst GLRC not found!" ); 00633 SetLastError( ERROR_INVALID_HANDLE ); 00634 return FALSE; 00635 } 00636 00637 /* I think this is only possible within one ICD */ 00638 if (src->icd != dst->icd) 00639 { 00640 DBGPRINT( "Error: src and dst GLRC use different ICDs!" ); 00641 SetLastError( ERROR_INVALID_HANDLE ); 00642 return FALSE; 00643 } 00644 00645 /* copy data (call ICD) */ 00646 return src->icd->DrvCopyContext( src->hglrc, dst->hglrc, mask ); 00647 } 00648 00649 00660 HGLRC 00661 APIENTRY 00662 rosglCreateLayerContext( HDC hdc, int layer ) 00663 { 00664 GLDRIVERDATA *icd = NULL; 00665 GLRC *glrc; 00666 HGLRC drvHglrc = NULL; 00667 00668 DBGTRACE( "Called!" ); 00669 00670 /* if (GetObjectType( hdc ) != OBJ_DC) 00671 { 00672 DBGPRINT( "Error: hdc is not a DC handle!" ); 00673 return NULL; 00674 } 00675 */ 00676 /* create new GLRC */ 00677 glrc = ROSGL_NewContext(); 00678 if (glrc == NULL) 00679 return NULL; 00680 00681 /* load ICD */ 00682 icd = ROSGL_ICDForHDC( hdc ); 00683 if (icd == NULL) 00684 { 00685 ROSGL_DeleteContext( glrc ); 00686 DBGPRINT( "Couldn't get ICD by HDC :-(" ); 00687 /* FIXME: fallback? */ 00688 return NULL; 00689 } 00690 /* Don't forget to refcount it, icd will be released when last context is deleted */ 00691 InterlockedIncrement((LONG*)&icd->refcount); 00692 00693 00694 /* create context */ 00695 if (icd->DrvCreateLayerContext != NULL) 00696 drvHglrc = icd->DrvCreateLayerContext( hdc, layer ); 00697 if (drvHglrc == NULL) 00698 { 00699 if (layer == 0 && icd->DrvCreateContext != NULL) 00700 drvHglrc = icd->DrvCreateContext( hdc ); 00701 else 00702 DBGPRINT( "Warning: CreateLayerContext not supported by ICD!" ); 00703 } 00704 00705 if (drvHglrc == NULL) 00706 { 00707 /* FIXME: fallback to mesa? */ 00708 DBGPRINT( "Error: DrvCreate[Layer]Context failed! (%d)", GetLastError() ); 00709 ROSGL_DeleteContext( glrc ); 00710 return NULL; 00711 } 00712 00713 /* we have our GLRC in glrc and the ICD's GLRC in drvHglrc */ 00714 glrc->hglrc = drvHglrc; 00715 glrc->icd = icd; 00716 00717 return (HGLRC)glrc; 00718 } 00719 00720 00728 HGLRC 00729 APIENTRY 00730 rosglCreateContext( HDC hdc ) 00731 { 00732 return rosglCreateLayerContext( hdc, 0 ); 00733 } 00734 00735 00743 BOOL 00744 APIENTRY 00745 rosglDeleteContext( HGLRC hglrc ) 00746 { 00747 GLRC *glrc = (GLRC *)hglrc; 00748 00749 /* check if we know about this context */ 00750 if (!ROSGL_ContainsContext( glrc )) 00751 { 00752 DBGPRINT( "Error: hglrc not found!" ); 00753 SetLastError( ERROR_INVALID_HANDLE ); 00754 return FALSE; 00755 } 00756 00757 /* make sure GLRC is not current for some thread */ 00758 if (glrc->is_current) 00759 { 00760 DBGPRINT( "Error: GLRC is current for DC 0x%08x", glrc->hdc ); 00761 SetLastError( ERROR_INVALID_FUNCTION ); 00762 return FALSE; 00763 } 00764 00765 /* release ICD's context */ 00766 if (glrc->hglrc != NULL) 00767 { 00768 if (!glrc->icd->DrvDeleteContext( glrc->hglrc )) 00769 { 00770 DBGPRINT( "Warning: DrvDeleteContext() failed (%d)", GetLastError() ); 00771 return FALSE; 00772 } 00773 } 00774 00775 /* free resources */ 00776 return ROSGL_DeleteContext( glrc ); 00777 } 00778 00779 00780 BOOL 00781 APIENTRY 00782 rosglDescribeLayerPlane( HDC hdc, int iPixelFormat, int iLayerPlane, 00783 UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd ) 00784 { 00785 UNIMPLEMENTED; 00786 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00787 return FALSE; 00788 } 00789 00790 00801 int 00802 APIENTRY 00803 rosglDescribePixelFormat( HDC hdc, int iFormat, UINT nBytes, 00804 LPPIXELFORMATDESCRIPTOR pfd ) 00805 { 00806 int ret = 0; 00807 GLDRIVERDATA *icd = ROSGL_ICDForHDC( hdc ); 00808 00809 if (icd != NULL) 00810 { 00811 ret = icd->DrvDescribePixelFormat( hdc, iFormat, nBytes, pfd ); 00812 if (ret == 0) 00813 DBGPRINT( "Error: DrvDescribePixelFormat(format=%d) failed (%d)", iFormat, GetLastError() ); 00814 } 00815 else 00816 { 00817 SetLastError( ERROR_INVALID_FUNCTION ); 00818 } 00819 00820 return ret; 00821 } 00822 00823 00829 HGLRC 00830 APIENTRY 00831 rosglGetCurrentContext() 00832 { 00833 return (HGLRC)(OPENGL32_threaddata->glrc); 00834 } 00835 00836 00842 HDC 00843 APIENTRY 00844 rosglGetCurrentDC() 00845 { 00846 /* FIXME: is it correct to return NULL when there is no current GLRC or 00847 is there another way to find out the wanted HDC? */ 00848 if (OPENGL32_threaddata->glrc == NULL) 00849 return NULL; 00850 return (HDC)(OPENGL32_threaddata->glrc->hdc); 00851 } 00852 00853 00854 int 00855 APIENTRY 00856 rosglGetLayerPaletteEntries( HDC hdc, int iLayerPlane, int iStart, 00857 int cEntries, COLORREF *pcr ) 00858 { 00859 UNIMPLEMENTED; 00860 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00861 return 0; 00862 } 00863 00864 00872 int 00873 WINAPI 00874 rosglGetPixelFormat( HDC hdc ) 00875 { 00876 GLDCDATA *dcdata; 00877 00878 DBGTRACE( "Called!" ); 00879 00880 dcdata = ROSGL_GetPrivateDCData( hdc ); 00881 if (dcdata == NULL) 00882 { 00883 DBGPRINT( "Error: ROSGL_GetPrivateDCData failed!" ); 00884 return 0; 00885 } 00886 00887 return dcdata->pixel_format; 00888 } 00889 00890 00901 PROC 00902 APIENTRY 00903 rosglGetProcAddress( LPCSTR proc ) 00904 { 00905 PROC func; 00906 GLDRIVERDATA *icd; 00907 00908 /* FIXME we should Flush the gl here */ 00909 00910 if (OPENGL32_threaddata->glrc == NULL) 00911 { 00912 DBGPRINT( "Error: No current GLRC!" ); 00913 SetLastError( ERROR_INVALID_FUNCTION ); 00914 return NULL; 00915 } 00916 00917 icd = OPENGL32_threaddata->glrc->icd; 00918 func = icd->DrvGetProcAddress( proc ); 00919 if (func != NULL) 00920 { 00921 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc ); 00922 return func; 00923 } 00924 00925 /* FIXME: Should we return wgl/gl 1.1 functions? */ 00926 SetLastError( ERROR_PROC_NOT_FOUND ); 00927 return NULL; 00928 } 00929 00930 PROC 00931 APIENTRY 00932 rosglGetDefaultProcAddress( LPCSTR proc ) 00933 { 00934 PROC func; 00935 GLDRIVERDATA *icd; 00936 00937 /* wglGetDefaultProcAddress does not flush the gl */ 00938 00939 if (OPENGL32_threaddata->glrc == NULL) 00940 { 00941 DBGPRINT( "Error: No current GLRC!" ); 00942 SetLastError( ERROR_INVALID_FUNCTION ); 00943 return NULL; 00944 } 00945 00946 icd = OPENGL32_threaddata->glrc->icd; 00947 func = icd->DrvGetProcAddress( proc ); 00948 if (func != NULL) 00949 { 00950 DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc ); 00951 return func; 00952 } 00953 00954 /* FIXME: Should we return wgl/gl 1.1 functions? */ 00955 SetLastError( ERROR_PROC_NOT_FOUND ); 00956 return NULL; 00957 } 00958 00959 00968 BOOL 00969 APIENTRY 00970 rosglMakeCurrent( HDC hdc, HGLRC hglrc ) 00971 { 00972 GLRC *glrc = (GLRC *)hglrc; 00973 ICDTable *icdTable = NULL; 00974 00975 DBGTRACE( "Called!" ); 00976 00977 if (OPENGL32_threaddata == NULL) 00978 return FALSE; 00979 00980 /* flush current context */ 00981 if (OPENGL32_threaddata->glrc != NULL) 00982 { 00983 glFlush(); 00984 } 00985 00986 /* check if current context is unset */ 00987 if (glrc == NULL) 00988 { 00989 if (OPENGL32_threaddata->glrc != NULL) 00990 { 00991 glrc = OPENGL32_threaddata->glrc; 00992 glrc->icd->DrvReleaseContext( glrc->hglrc ); 00993 glrc->is_current = FALSE; 00994 OPENGL32_threaddata->glrc = NULL; 00995 } 00996 } 00997 else 00998 { 00999 /* check hdc */ 01000 if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC) 01001 { 01002 DBGPRINT( "Error: hdc is not a DC handle!" ); 01003 SetLastError( ERROR_INVALID_HANDLE ); 01004 return FALSE; 01005 } 01006 01007 /* check if we know about this glrc */ 01008 if (!ROSGL_ContainsContext( glrc )) 01009 { 01010 DBGPRINT( "Error: hglrc not found!" ); 01011 SetLastError( ERROR_INVALID_HANDLE ); 01012 return FALSE; 01013 } 01014 01015 /* check if it is available */ 01016 if (glrc->is_current && glrc->thread_id != GetCurrentThreadId()) /* used by another thread */ 01017 { 01018 DBGPRINT( "Error: hglrc is current for thread 0x%08x", glrc->thread_id ); 01019 SetLastError( ERROR_INVALID_HANDLE ); 01020 return FALSE; 01021 } 01022 01023 /* call the ICD */ 01024 if (glrc->hglrc != NULL) 01025 { 01026 DBGPRINT( "Info: Calling DrvSetContext!" ); 01027 SetLastError( ERROR_SUCCESS ); 01028 icdTable = glrc->icd->DrvSetContext( hdc, glrc->hglrc, 01029 (void *)ROSGL_SetContextCallBack ); 01030 if (icdTable == NULL) 01031 { 01032 DBGPRINT( "Error: DrvSetContext failed (%d)\n", GetLastError() ); 01033 return FALSE; 01034 } 01035 DBGPRINT( "Info: DrvSetContext succeeded!" ); 01036 } 01037 01038 /* make it current */ 01039 if (OPENGL32_threaddata->glrc != NULL) 01040 OPENGL32_threaddata->glrc->is_current = FALSE; 01041 glrc->is_current = TRUE; 01042 glrc->thread_id = GetCurrentThreadId(); 01043 glrc->hdc = hdc; 01044 OPENGL32_threaddata->glrc = glrc; 01045 } 01046 01047 if (ROSGL_SetContextCallBack( icdTable ) != ERROR_SUCCESS && icdTable == NULL) 01048 { 01049 DBGPRINT( "Warning: ROSGL_SetContextCallBack failed!" ); 01050 } 01051 01052 return TRUE; 01053 } 01054 01055 01056 BOOL 01057 APIENTRY 01058 rosglRealizeLayerPalette( HDC hdc, int iLayerPlane, BOOL bRealize ) 01059 { 01060 UNIMPLEMENTED; 01061 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 01062 return FALSE; 01063 } 01064 01065 01066 int 01067 APIENTRY 01068 rosglSetLayerPaletteEntries( HDC hdc, int iLayerPlane, int iStart, 01069 int cEntries, CONST COLORREF *pcr ) 01070 { 01071 UNIMPLEMENTED; 01072 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 01073 return 0; 01074 } 01075 01076 01086 BOOL 01087 WINAPI 01088 rosglSetPixelFormat( HDC hdc, int iFormat, CONST PIXELFORMATDESCRIPTOR *pfd ) 01089 { 01090 GLDRIVERDATA *icd; 01091 GLDCDATA *dcdata; 01092 01093 DBGTRACE( "Called!" ); 01094 01095 /* load ICD */ 01096 icd = ROSGL_ICDForHDC( hdc ); 01097 if (icd == NULL) 01098 { 01099 DBGPRINT( "Warning: ICDForHDC() failed" ); 01100 return FALSE; 01101 } 01102 01103 /* call ICD */ 01104 if (!icd->DrvSetPixelFormat( hdc, iFormat, pfd )) 01105 { 01106 DBGPRINT( "Warning: DrvSetPixelFormat(format=%d) failed (%d)", 01107 iFormat, GetLastError() ); 01108 return FALSE; 01109 } 01110 01111 /* store format in private DC data */ 01112 dcdata = ROSGL_GetPrivateDCData( hdc ); 01113 if (dcdata == NULL) 01114 { 01115 DBGPRINT( "Error: ROSGL_GetPrivateDCData() failed!" ); 01116 return FALSE; 01117 } 01118 dcdata->pixel_format = iFormat; 01119 01120 return TRUE; 01121 } 01122 01123 01134 BOOL 01135 APIENTRY 01136 rosglShareLists( HGLRC hglrc1, HGLRC hglrc2 ) 01137 { 01138 GLRC *glrc1 = (GLRC *)hglrc1; 01139 GLRC *glrc2 = (GLRC *)hglrc2; 01140 01141 /* check glrcs */ 01142 if (!ROSGL_ContainsContext( glrc1 )) 01143 { 01144 DBGPRINT( "Error: hglrc1 not found!" ); 01145 SetLastError( ERROR_INVALID_HANDLE ); 01146 return FALSE; 01147 } 01148 if (!ROSGL_ContainsContext( glrc2 )) 01149 { 01150 DBGPRINT( "Error: hglrc2 not found!" ); 01151 SetLastError( ERROR_INVALID_HANDLE ); 01152 return FALSE; 01153 } 01154 01155 /* I think this is only possible within one ICD */ 01156 if (glrc1->icd != glrc2->icd) 01157 { 01158 DBGPRINT( "Error: hglrc1 and hglrc2 use different ICDs!" ); 01159 SetLastError( ERROR_INVALID_HANDLE ); 01160 return FALSE; 01161 } 01162 01163 /* share lists (call ICD) */ 01164 return glrc1->icd->DrvShareLists( glrc1->hglrc, glrc2->hglrc ); 01165 } 01166 01167 01175 BOOL 01176 APIENTRY 01177 rosglSwapBuffers( HDC hdc ) 01178 { 01179 GLDRIVERDATA *icd = ROSGL_ICDForHDC( hdc ); 01180 DBGTRACE( "Called!" ); 01181 if (icd != NULL) 01182 { 01183 DBGPRINT( "Swapping buffers!" ); 01184 if (!icd->DrvSwapBuffers( hdc )) 01185 { 01186 DBGPRINT( "Error: DrvSwapBuffers failed (%d)", GetLastError() ); 01187 return FALSE; 01188 } 01189 return TRUE; 01190 } 01191 01192 /* FIXME: implement own functionality? */ 01193 SetLastError( ERROR_INVALID_FUNCTION ); 01194 return FALSE; 01195 } 01196 01197 01198 BOOL 01199 APIENTRY 01200 rosglSwapLayerBuffers( HDC hdc, UINT fuPlanes ) 01201 { 01202 BOOL ret = FALSE; 01203 01204 if(fuPlanes & WGL_SWAP_MAIN_PLANE) 01205 ret = rosglSwapBuffers(hdc); 01206 01207 if(fuPlanes &~WGL_SWAP_MAIN_PLANE) 01208 DBGTRACE("wglSwapLayerBuffers is not fully implemented\n"); 01209 01210 return ret; 01211 } 01212 01213 01214 BOOL 01215 APIENTRY 01216 rosglUseFontBitmapsA( HDC hdc, DWORD first, DWORD count, DWORD listBase ) 01217 { 01218 return IntUseFontBitmapsA(hdc, first, count, listBase); 01219 } 01220 01221 01222 BOOL 01223 APIENTRY 01224 rosglUseFontBitmapsW( HDC hdc, DWORD first, DWORD count, DWORD listBase ) 01225 { 01226 return IntUseFontBitmapsW(hdc, first, count, listBase); 01227 } 01228 01229 BOOL 01230 APIENTRY 01231 rosglUseFontOutlinesA( HDC hdc, DWORD first, DWORD count, DWORD listBase, 01232 FLOAT deviation, FLOAT extrusion, int format, 01233 GLYPHMETRICSFLOAT *pgmf ) 01234 { 01235 return IntUseFontOutlinesA(hdc, first, count, listBase, deviation, extrusion, format, pgmf); 01236 } 01237 01238 01239 BOOL 01240 APIENTRY 01241 rosglUseFontOutlinesW( HDC hdc, DWORD first, DWORD count, DWORD listBase, 01242 FLOAT deviation, FLOAT extrusion, int format, 01243 GLYPHMETRICSFLOAT *pgmf ) 01244 { 01245 return IntUseFontOutlinesW(hdc, first, count, listBase, deviation, extrusion, format, pgmf); 01246 } 01247 01248 #ifdef __cplusplus 01249 }; /* extern "C" */ 01250 #endif /* __cplusplus */ 01251 01252 /* EOF */ Generated on Sun May 27 2012 04:19:57 for ReactOS by
1.7.6.1
|