|
|
/******************************Module*Header*******************************\
* Module Name: makecur.c * * wglMakeCurrent implementation * * Created: 02-10-1997 * * Copyright (c) 1993-1997 Microsoft Corporation \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include <context.h>
#include <global.h>
#include "metasup.h"
#include "wgldef.h"
/******************************Public*Routine******************************\
* * __wglSetProcTable * * Callback function given to ICDs to set a proc table * \**************************************************************************/
void APIENTRY __wglSetProcTable(PGLCLTPROCTABLE pglCltProcTable) { if (pglCltProcTable == (PGLCLTPROCTABLE) NULL) return;
// It must have either 306 entries for version 1.0 or 336 entries for 1.1
if (pglCltProcTable->cEntries != OPENGL_VERSION_100_ENTRIES && pglCltProcTable->cEntries != OPENGL_VERSION_110_ENTRIES) { return; }
// This function is called by client drivers which do not use
// the EXT procs provided by opengl32. Use the null EXT proc
// table to disable those stubs since they should never be
// called anyway
SetCltProcTable(pglCltProcTable, &glNullExtProcTable, TRUE); }
/******************************Public*Routine******************************\
* * CheckDeviceModes * * Ensures that the HDC doesn't have any disallowed state * * History: * Mon Aug 26 15:03:28 1996 -by- Drew Bliss [drewb] * Split from wglMakeCurrent * \**************************************************************************/
BOOL CheckDeviceModes(HDC hdc) { SIZE szW, szV; XFORM xform; POINT pt; HRGN hrgnTmp; int iRgn;
// For release 1, GDI transforms must be identity.
// This is to allow GDI transform binding in future.
switch (GetMapMode(hdc)) { case MM_TEXT: break; case MM_ANISOTROPIC: if (!GetWindowExtEx(hdc, &szW) || !GetViewportExtEx(hdc, &szV) || szW.cx != szV.cx || szW.cy != szV.cy) goto wglMakeCurrent_xform_error; break; default: goto wglMakeCurrent_xform_error; }
if (!GetViewportOrgEx(hdc, &pt) || pt.x != 0 || pt.y != 0) goto wglMakeCurrent_xform_error;
if (!GetWindowOrgEx(hdc, &pt) || pt.x != 0 || pt.y != 0) goto wglMakeCurrent_xform_error;
if (!GetWorldTransform(hdc, &xform)) { // Win95 does not support GetWorldTransform.
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) goto wglMakeCurrent_xform_error; } else if (xform.eDx != 0.0f || xform.eDy != 0.0f || xform.eM12 != 0.0f || xform.eM21 != 0.0f || xform.eM11 < 0.999f || xform.eM11 > 1.001f // allow rounding errors
|| xform.eM22 < 0.999f || xform.eM22 > 1.001f) { wglMakeCurrent_xform_error: DBGERROR("wglMakeCurrent: GDI transforms not identity\n"); SetLastError(ERROR_TRANSFORM_NOT_SUPPORTED); return FALSE; }
// For release 1, GDI clip region is not allowed.
// This is to allow GDI clip region binding in future.
if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0))) return FALSE;
iRgn = GetClipRgn(hdc, hrgnTmp);
if (!DeleteObject(hrgnTmp)) ASSERTOPENGL(FALSE, "DeleteObject failed");
switch (iRgn) { case -1: // error
WARNING("wglMakeCurrent: GetClipRgn failed\n"); return FALSE;
case 0: // no initial clip region
break;
case 1: // has initial clip region
DBGERROR("wglMakeCurrent: GDI clip region not allowed\n"); SetLastError(ERROR_CLIPPING_NOT_SUPPORTED); return FALSE; }
return TRUE; }
/******************************Public*Routine******************************\
* * MakeAnyCurrent * * Makes any type of context current * * History: * Mon Aug 26 15:00:44 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL MakeAnyCurrent(HGLRC hrc, int ipfd, DWORD dwObjectType, GLWINDOWID *pgwid) { HGLRC hrcSrv; PLRC plrc; DWORD tidCurrent; ULONG irc; PLHE plheRC; PGLCLTPROCTABLE pglProcTable; PGLEXTPROCTABLE pglExtProcTable; POLYARRAY *pa;
DBGENTRY("wglMakeCurrent\n");
// If this is a new, uninitialized thread, try to initialize it
if (CURRENT_GLTEBINFO() == NULL) { GLInitializeThread(DLL_THREAD_ATTACH); // If the teb was not set up at thread initialization, return failure.
if (!CURRENT_GLTEBINFO()) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } }
// There are four cases:
//
// 1. hrc is NULL and there is no current RC.
// 2. hrc is NULL and there is a current RC.
// 3. hrc is not NULL and there is a current RC.
// 4. hrc is not NULL and there is no current RC.
// Case 1: hrc is NULL and there is no current RC.
// This is a noop, return success.
if (hrc == (HGLRC) 0 && (GLTEB_CLTCURRENTRC() == (PLRC) NULL)) return(TRUE);
// Case 2: hrc is NULL and there is a current RC.
// Make the current RC inactive.
if (hrc == (HGLRC) 0 && (GLTEB_CLTCURRENTRC() != (PLRC) NULL)) return(bMakeNoCurrent());
// Get the current thread id.
tidCurrent = GetCurrentThreadId(); ASSERTOPENGL(tidCurrent != INVALID_THREAD_ID, "wglMakeCurrent: GetCurrentThreadId returned a bad value\n");
// Validate the handles. hrc is not NULL here.
ASSERTOPENGL(hrc != (HGLRC) NULL, "wglMakeCurrent: hrc is NULL\n");
// Validate the RC.
if (cLockHandle((ULONG_PTR)hrc) <= 0) { DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: can't lock hrc 0x%lx\n", hrc); goto wglMakeCurrent_error_nolock; } irc = MASKINDEX(hrc); plheRC = pLocalTable + irc; plrc = (PLRC) plheRC->pv; hrcSrv = (HGLRC) plheRC->hgre; ASSERTOPENGL(plrc->ident == LRC_IDENTIFIER, "wglMakeCurrent: Bad plrc\n");
#ifdef GL_METAFILE
// Ensure that metafile RC's are made current only to
// metafile DC's
if (plrc->uiGlsCaptureContext != 0 && dwObjectType != OBJ_ENHMETADC) { DBGLEVEL(LEVEL_ERROR, "wglMakeCurrent: attempt to make meta RC current " "to non-meta DC\n"); SetLastError(ERROR_INVALID_HANDLE); vUnlockHandle((ULONG_PTR)hrc); return FALSE; }
// Ensure that non-metafile RC's are made current only to
// non-metafile DC's
if (plrc->uiGlsCaptureContext == 0 && dwObjectType == OBJ_ENHMETADC) { DBGLEVEL(LEVEL_ERROR, "wglMakeCurrent: attempt to make non-meta RC current " "to meta DC\n"); SetLastError(ERROR_METAFILE_NOT_SUPPORTED); vUnlockHandle((ULONG_PTR)hrc); return FALSE; } #endif
// If the RC is current, it must be current to this thread because
// makecurrent locks down the handle.
// If the given RC is already current to this thread, we will release it first,
// then make it current again. This is to support DC/RC attribute bindings in
// this function.
ASSERTOPENGL(plrc->tidCurrent == INVALID_THREAD_ID || plrc->tidCurrent == tidCurrent, "wglMakeCurrent: hrc is current to another thread\n");
// Case 3: hrc is not NULL and there is a current RC.
// This is case 2 followed by case 4.
if (GLTEB_CLTCURRENTRC()) { // First, make the current RC inactive.
if (!bMakeNoCurrent()) { DBGERROR("wglMakeCurrent: bMakeNoCurrent failed\n"); vUnlockHandle((ULONG_PTR)hrc); return(FALSE); }
// Second, make hrc current. Fall through to case 4.
}
// Case 4: hrc is not NULL and there is no current RC.
ASSERTOPENGL(GLTEB_CLTCURRENTRC() == (PLRC) NULL, "wglMakeCurrent: There is a current RC!\n");
// If the pixel format of the window or surface is different from that of
// the RC, return error.
if (ipfd != plrc->iPixelFormat) { DBGERROR("wglMakeCurrent: different hdc and hrc pixel formats\n"); SetLastError(ERROR_INVALID_PIXEL_FORMAT); goto wglMakeCurrent_error; }
// Since the client code manages the function table, we will make
// either the server or the driver current.
if (!plrc->dhrc) { // If this is a generic format, tell the server to make it current.
#ifndef _CLIENTSIDE_
// If the subbatch data has not been set up for this thread, set it up now.
if (GLTEB_CLTSHAREDSECTIONINFO() == NULL) { if (!glsbCreateAndDuplicateSection(SHARED_SECTION_SIZE)) { WARNING("wglMakeCurrent: unable to create section\n"); goto wglMakeCurrent_error; } } #endif // !_CLIENTSIDE_
if (!__wglMakeCurrent(pgwid, hrcSrv, plrc->uiGlsCaptureContext != 0)) { DBGERROR("wglMakeCurrent: server failed\n"); goto wglMakeCurrent_error; }
// Get the generic function table or metafile function table
#ifdef GL_METAFILE
if (plrc->fCapturing) { MetaGlProcTables(&pglProcTable, &pglExtProcTable); } else #endif
{ // Use RGBA or CI proc table depending on the color mode.
// The gc should be available by now.
__GL_SETUP();
if (gc->modes.colorIndexMode) pglProcTable = &glCltCIProcTable; else pglProcTable = &glCltRGBAProcTable; pglExtProcTable = &glExtProcTable; } } else { // If this is a device format, tell the driver to make it current.
// Get the driver function table from the driver.
// pfnDrvSetContext returns the address of the driver OpenGL function
// table if successful; NULL otherwise.
ASSERTOPENGL(plrc->pGLDriver, "wglMakeCurrent: No GLDriver\n");
pglProcTable = plrc->pGLDriver->pfnDrvSetContext(pgwid->hdc, plrc->dhrc, __wglSetProcTable); if (pglProcTable == (PGLCLTPROCTABLE) NULL) { DBGERROR("wglMakeCurrent: pfnDrvSetContext failed\n"); goto wglMakeCurrent_error; }
// It must have either 306 entries for version 1.0 or 336 entries for 1.1
if (pglProcTable->cEntries != OPENGL_VERSION_100_ENTRIES && pglProcTable->cEntries != OPENGL_VERSION_110_ENTRIES) { DBGERROR("wglMakeCurrent: pfnDrvSetContext returned bad table\n"); plrc->pGLDriver->pfnDrvReleaseContext(plrc->dhrc); SetLastError(ERROR_BAD_DRIVER); goto wglMakeCurrent_error; }
DBGLEVEL1(LEVEL_INFO, "wglMakeCurrent: driver function table 0x%lx\n", pglProcTable);
// Always use the null EXT proc table since client drivers don't
// use opengl32's stubs for EXT procs
pglExtProcTable = &glNullExtProcTable; }
// Make hrc current.
plrc->tidCurrent = tidCurrent; plrc->gwidCurrent = *pgwid; GLTEB_SET_CLTCURRENTRC(plrc); SetCltProcTable(pglProcTable, pglExtProcTable, TRUE);
#ifdef GL_METAFILE
// Set up metafile context if necessary
if (plrc->fCapturing) { __GL_SETUP(); ActivateMetaRc(plrc, pgwid->hdc);
// Set the metafile's base dispatch table by resetting
// the proc table. Since we know we're capturing, this
// will cause the GLS capture exec table to be updated
// with the RGBA or CI proc table, preparing the
// GLS context for correct passthrough
if (gc->modes.colorIndexMode) pglProcTable = &glCltCIProcTable; else pglProcTable = &glCltRGBAProcTable; pglExtProcTable = &glExtProcTable; SetCltProcTable(pglProcTable, pglExtProcTable, FALSE); } #endif
// Initialize polyarray structure in the TEB.
pa = GLTEB_CLTPOLYARRAY(); pa->flags = 0; // not in begin mode
if (!plrc->dhrc) { POLYMATERIAL *pm; __GL_SETUP();
pa->pdBufferNext = &gc->vertex.pdBuf[0]; pa->pdBuffer0 = &gc->vertex.pdBuf[0]; pa->pdBufferMax = &gc->vertex.pdBuf[gc->vertex.pdBufSize - 1]; // reset next DPA message offset
pa->nextMsgOffset = PA_nextMsgOffset_RESET_VALUE;
// Vertex buffer size may have changed. For example, a generic gc's
// vertex buffer may be of a different size than a MCD vertex buffer.
// If it has changed, free the polymaterial array and realloc it later.
pm = GLTEB_CLTPOLYMATERIAL(); if (pm) { if (pm->aMatSize != gc->vertex.pdBufSize * 2 / POLYMATERIAL_ARRAY_SIZE + 1) FreePolyMaterial(); } }
// Keep the handle locked while it is current.
return(TRUE);
// An error has occured, release the current RC.
wglMakeCurrent_error: vUnlockHandle((ULONG_PTR)hrc); wglMakeCurrent_error_nolock: if (GLTEB_CLTCURRENTRC() != (PLRC) NULL) (void) bMakeNoCurrent(); return(FALSE); }
/******************************Public*Routine******************************\
* * WindowIdFromHdc * * Fills out a GLWINDOWID for an HDC * * History: * Wed Aug 28 18:33:19 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void APIENTRY WindowIdFromHdc(HDC hdc, GLWINDOWID *pgwid) { LPDIRECTDRAWSURFACE pdds; HDC hdcDriver;
if (pfnGetSurfaceFromDC != NULL && pfnGetSurfaceFromDC(hdc, &pdds, &hdcDriver) == DD_OK) { // Release reference on the surface since this surface value
// is only used as an identifier.
pdds->lpVtbl->Release(pdds); pgwid->iType = GLWID_DDRAW; pgwid->hwnd = NULL; pgwid->hdc = hdcDriver; pgwid->pdds = pdds; } else { pgwid->hdc = hdc; pgwid->hwnd = WindowFromDC(hdc); if (pgwid->hwnd == NULL) { pgwid->iType = GLWID_HDC; } else { pgwid->iType = GLWID_HWND; } pgwid->pdds = NULL; } } /******************************Public*Routine******************************\
* wglMakeCurrent(HDC hdc, HGLRC hrc) * * Make the hrc current. * Both hrc and hdc must have the same pixel format. * * If an error occurs, the current RC, if any, is made not current! * * Arguments: * hdc - Device context. * hrc - Rendering context. * * History: * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hrc) { int iPixelFormat; DWORD dwObjectType; GLWINDOWID gwid;
DBGENTRY("wglMakeCurrent\n");
if (GLTEB_CLTCURRENTRC() != NULL) { // Flush OpenGL calls.
glFlush();
// Avoid HDC validation for simple make-non-current cases
if (hrc == NULL) { return bMakeNoCurrent(); } } // Validate the DC.
dwObjectType = wglObjectType(hdc); switch (dwObjectType) { case OBJ_DC: case OBJ_MEMDC: break;
case OBJ_ENHMETADC: #ifdef GL_METAFILE
if (pfnGdiAddGlsRecord == NULL) { DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: metafile hdc: 0x%lx\n", hdc); SetLastError(ERROR_INVALID_HANDLE); return FALSE; } break; #else
DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: metafile hdc: 0x%lx\n", hdc); SetLastError(ERROR_INVALID_HANDLE); return FALSE; #endif
case OBJ_METADC: default: // 16-bit metafiles are not supported
DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: bad hdc: 0x%lx\n", hdc); SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
if (!CheckDeviceModes(hdc)) { return FALSE; } #ifdef GL_METAFILE
// For metafile RC's, use the reference HDC rather than the
// metafile DC
// Skip pixel format checks
if (dwObjectType == OBJ_ENHMETADC) { iPixelFormat = 0; goto NoPixelFormat; } #endif
// Get the current pixel format of the window or surface.
// If no pixel format has been set, return error.
if (!(iPixelFormat = GetPixelFormat(hdc))) { WARNING("wglMakeCurrent: No pixel format set in hdc\n"); return FALSE; }
#ifdef GL_METAFILE
NoPixelFormat: #endif
WindowIdFromHdc(hdc, &gwid); return MakeAnyCurrent(hrc, iPixelFormat, dwObjectType, &gwid); }
/******************************Public*Routine******************************\
* bMakeNoCurrent * * Make the current RC inactive. * * History: * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
BOOL bMakeNoCurrent(void) { BOOL bRet = FALSE; // assume error
PLRC plrc = GLTEB_CLTCURRENTRC();
DBGENTRY("bMakeNoCurrent\n");
ASSERTOPENGL(plrc != (PLRC) NULL, "bMakeNoCurrent: No current RC!\n"); ASSERTOPENGL(plrc->tidCurrent == GetCurrentThreadId(), "bMakeNoCurrent: Current RC does not belong to this thread!\n"); ASSERTOPENGL(plrc->gwidCurrent.iType != GLWID_ERROR, "bMakeNoCurrent: Current surface is NULL!\n");
if (!plrc->dhrc) { #ifdef GL_METAFILE
// Reset metafile context if necessary
if (plrc->uiGlsCaptureContext != 0) { DeactivateMetaRc(plrc); } #endif
// If this is a generic format, tell the server to make the current RC inactive.
bRet = __wglMakeCurrent(NULL, NULL, FALSE); if (!bRet) { DBGERROR("bMakeNoCurrent: server failed\n"); } } else { // If this is a device format, tell the driver to make the current RC inactive.
ASSERTOPENGL(plrc->pGLDriver, "wglMakeCurrent: No GLDriver\n");
bRet = plrc->pGLDriver->pfnDrvReleaseContext(plrc->dhrc); if (!bRet) { DBGERROR("bMakeNoCurrent: pfnDrvReleaseContext failed\n"); } }
// Always make the current RC inactive.
// The handle is also unlocked when the RC becomes inactive.
plrc->tidCurrent = INVALID_THREAD_ID; plrc->gwidCurrent.iType = GLWID_ERROR; GLTEB_SET_CLTCURRENTRC(NULL); SetCltProcTable(&glNullCltProcTable, &glNullExtProcTable, TRUE); vUnlockHandle((ULONG_PTR)(plrc->hrc)); return(bRet); }
|