|
|
/******************************Module*Header*******************************\
* Module Name: metasup.c * * OpenGL metafile support * * History: * Thu Feb 23 15:27:47 1995 -by- Drew Bliss [drewb] * Created * * Copyright (c) 1995 Microsoft Corporation \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include <ntpsapi.h>
#include <wingdip.h>
#include "global.h"
#include <glgenwin.h>
#include "metasup.h"
#if defined(GL_METAFILE)
#include <glmf.h>
#include <encoding.h>
GLCLTPROCTABLE gcptGlsProcTable; GLEXTPROCTABLE geptGlsExtProcTable;
// Functions in GL which we will do device coordinate translation for
typedef struct _GLDEVICEPROCS { void (APIENTRY *glBitmap)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); void (APIENTRY *glCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); void (APIENTRY *glCopyTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); void (APIENTRY *glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); void (APIENTRY *glCopyTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); void (APIENTRY *glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); void (APIENTRY *glDrawPixels)(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); void (APIENTRY *glLineWidth)(GLfloat width); void (APIENTRY *glPointSize)(GLfloat size); void (APIENTRY *glScissor)(GLint x, GLint y, GLsizei width, GLsizei height); void (APIENTRY *glViewport)(GLint x, GLint y, GLsizei w, GLsizei h); } GLDEVICEPROCS; #define GL_DEVICE_PROCS (sizeof(GLDEVICEPROCS)/sizeof(PROC))
// Opcode for device procs
static GLSopcode glsopDeviceProcs[GL_DEVICE_PROCS] = { GLS_OP_glBitmap, GLS_OP_glCopyPixels, GLS_OP_glCopyTexImage1D, GLS_OP_glCopyTexImage2D, GLS_OP_glCopyTexSubImage1D, GLS_OP_glCopyTexSubImage2D, GLS_OP_glDrawPixels, GLS_OP_glLineWidth, GLS_OP_glPointSize, GLS_OP_glScissor, GLS_OP_glViewport };
static GLDEVICEPROCS gdpGlsActual;
/*****************************Private*Routine******************************\
* * GLS recording callbacks * * Perfoms any necessary work when capturing a call * * History: * Mon Mar 27 14:21:09 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlsBitmapIn(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) { PLRC plrc; RECTL rcl;
plrc = GLTEB_CLTCURRENTRC(); ASSERTOPENGL(plrc != NULL, "GlsBitmapIn: No current RC!\n");
// Record bounds for the bitmap
rcl.left = 0; rcl.top = 0; rcl.right = width; rcl.bottom = height; plrc->prclGlsBounds = &rcl;
gdpGlsActual.glBitmap(width, height, xorig, yorig, xmove, ymove, bitmap);
plrc->prclGlsBounds = NULL; }
void GlsDrawPixelsIn(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { PLRC plrc; RECTL rcl;
plrc = GLTEB_CLTCURRENTRC(); ASSERTOPENGL(plrc != NULL, "GlsBitmapIn: No current RC!\n");
// Record bounds for the bitmap
rcl.left = 0; rcl.top = 0; rcl.right = width; rcl.bottom = height; plrc->prclGlsBounds = &rcl;
gdpGlsActual.glDrawPixels(width, height, format, type, pixels);
plrc->prclGlsBounds = NULL; }
void GlsViewportIn(GLint x, GLint y, GLsizei width, GLsizei height) { RECTL rcl; PLRC plrc; plrc = GLTEB_CLTCURRENTRC(); ASSERTOPENGL(plrc != NULL, "GlsViewportIn: No current RC!\n"); // Send the bounds on
// The rect is inclusive-exclusive while the incoming parameters
// are inclusive-inclusive
rcl.left = x; rcl.right = x+width+1; rcl.top = y; rcl.bottom = y+height+1; if (!GlGdiAddGlsBounds(plrc->gwidCreate.hdc, &rcl)) { ASSERTOPENGL(FALSE, "GdiAddGlsBounds failed"); }
gdpGlsActual.glViewport(x, y, width, height); }
// glViewport is the only device-dependent function that we need to
// do work for on input
static GLDEVICEPROCS gdpInput = { GlsBitmapIn, NULL, NULL, NULL, NULL, NULL, GlsDrawPixelsIn, NULL, NULL, NULL, GlsViewportIn };
/*****************************Private*Routine******************************\
* * MetaLoadGls * * Loads glmf32.dll for metafile use * * History: * Thu Feb 23 17:40:59 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
static char *pszGlsEntryPoints[] = { "glsBeginCapture", "glsBinary", "glsCallArrayInContext", "glsCaptureFlags", "glsCaptureFunc", "glsCommandFunc", "glsContext", "glsDeleteContext", "glsEndCapture", "glsFlush", "glsGenContext", "glsGetCaptureDispatchTable", "glsGetCaptureExecTable", "glsGetCommandAlignment", "glsGetCurrentContext", "glsUpdateCaptureExecTable", "glsWriteFunc", "glsBeginGLS", "glsBlock", "glsCallStream", "glsEndGLS", "glsError", "glsGLRC", "glsGLRCLayer", "glsHeaderGLRCi", "glsHeaderLayerf", "glsHeaderLayeri", "glsHeaderf", "glsHeaderfv", "glsHeaderi", "glsHeaderiv", "glsHeaderubz", "glsRequireExtension", "glsUnsupportedCommand", "glsAppRef", "glsBeginObj", "glsCharubz", "glsComment", "glsDisplayMapfv", "glsEndObj", "glsNumb", "glsNumbv", "glsNumd", "glsNumdv", "glsNumf", "glsNumfv", "glsNumi", "glsNumiv", "glsNuml", "glsNumlv", "glsNums", "glsNumsv", "glsNumub", "glsNumubv", "glsNumui", "glsNumuiv", "glsNumul", "glsNumulv", "glsNumus", "glsNumusv", "glsPad", "glsSwapBuffers" }; #define GLS_ENTRY_POINT_STRINGS (sizeof(pszGlsEntryPoints)/sizeof(char *))
typedef struct _GLSENTRYPOINTS { GLboolean (APIENTRY *glsBeginCapture)(const GLubyte *, GLSenum, GLbitfield); GLSenum (APIENTRY *glsBinary)(GLboolean); void (APIENTRY *glsCallArrayInContext)(GLuint, GLSenum, size_t, const GLubyte *); void (APIENTRY *glsCaptureFlags)(GLSopcode, GLbitfield); void (APIENTRY *glsCaptureFunc)(GLSenum, GLScaptureFunc); void (APIENTRY *glsCommandFunc)(GLSopcode, GLSfunc); void (APIENTRY *glsContext)(GLuint); void (APIENTRY *glsDeleteContext)(GLuint); void (APIENTRY *glsEndCapture)(void); void (APIENTRY *glsFlush)(GLSenum); GLuint (APIENTRY *glsGenContext)(void); void (APIENTRY *glsGetCaptureDispatchTable)(GLCLTPROCTABLE *, GLEXTPROCTABLE *); void (APIENTRY *glsGetCaptureExecTable)(GLCLTPROCTABLE *, GLEXTPROCTABLE *); GLScommandAlignment * (APIENTRY *glsGetCommandAlignment)(GLSopcode, GLSenum, GLScommandAlignment *); GLuint (APIENTRY *glsGetCurrentContext)(void); void (APIENTRY *glsUpdateCaptureExecTable)(GLCLTPROCTABLE *, GLEXTPROCTABLE *); void (APIENTRY *glsWriteFunc)(GLSwriteFunc);
// The following are only used in glsCommandFunc and so don't
// require real prototypes
GLSfunc glsBeginGLS; GLSfunc glsBlock; GLSfunc glsCallStream; GLSfunc glsEndGLS; GLSfunc glsError; GLSfunc glsGLRC; GLSfunc glsGLRCLayer; GLSfunc glsHeaderGLRCi; GLSfunc glsHeaderLayerf; GLSfunc glsHeaderLayeri; GLSfunc glsHeaderf; GLSfunc glsHeaderfv; GLSfunc glsHeaderi; GLSfunc glsHeaderiv; GLSfunc glsHeaderubz; GLSfunc glsRequireExtension; GLSfunc glsUnsupportedCommand; GLSfunc glsAppRef; GLSfunc glsBeginObj; GLSfunc glsCharubz; GLSfunc glsComment; GLSfunc glsDisplayMapfv; GLSfunc glsEndObj; GLSfunc glsNumb; GLSfunc glsNumbv; GLSfunc glsNumd; GLSfunc glsNumdv; GLSfunc glsNumf; GLSfunc glsNumfv; GLSfunc glsNumi; GLSfunc glsNumiv; GLSfunc glsNuml; GLSfunc glsNumlv; GLSfunc glsNums; GLSfunc glsNumsv; GLSfunc glsNumub; GLSfunc glsNumubv; GLSfunc glsNumui; GLSfunc glsNumuiv; GLSfunc glsNumul; GLSfunc glsNumulv; GLSfunc glsNumus; GLSfunc glsNumusv; GLSfunc glsPad; GLSfunc glsSwapBuffers; } GLSENTRYPOINTS; #define GLS_ENTRY_POINTS (sizeof(GLSENTRYPOINTS)/sizeof(void *))
static GLSENTRYPOINTS gepGlsFuncs = {NULL}; static HMODULE hGlsDll = NULL;
BOOL MetaLoadGls(void) { HMODULE hdll; BOOL bRet = FALSE; GLSENTRYPOINTS gep; PROC *ppfn, *ppfnActual, *ppfnInput; GLSfunc *pgfnNormal, *pgfnExt; int i; ASSERTOPENGL(GLS_ENTRY_POINT_STRINGS == GLS_ENTRY_POINTS, "GLS entry point strings/pointers mismatch\n"); ENTERCRITICALSECTION(&semLocal);
if (hGlsDll != NULL) { bRet = TRUE; goto Exit; }
hdll = LoadLibrary(__TEXT("glmf32.dll")); if (hdll == NULL) { WARNING1("Unable to load glmf32.dll, %d\n", GetLastError()); goto Exit; } ppfn = (PROC *)&gep; for (i = 0; i < GLS_ENTRY_POINTS; i++) { if (!(*ppfn = GetProcAddress(hdll, pszGlsEntryPoints[i]))) { WARNING1("glmf32.dll is missing '%s'\n", pszGlsEntryPoints[i]); FreeLibrary(hdll); goto Exit; } ppfn++; }
// The table copied out is constant as long as the DLL is loaded
gep.glsGetCaptureDispatchTable(&gcptGlsProcTable, &geptGlsExtProcTable); // Patch the table for certain functions to allow us to
// do some coordinate conversion and bounds accumlation
ppfnActual = (PROC *)&gdpGlsActual; ppfnInput = (PROC *)&gdpInput; for (i = 0; i < GL_DEVICE_PROCS; i++) { if (*ppfnInput != NULL) { ppfn = ((PROC *)&gcptGlsProcTable.glDispatchTable)+ glsopDeviceProcs[i]-GLS_OP_glNewList; *ppfnActual = *ppfn; *ppfn = *ppfnInput; }
ppfnActual++; ppfnInput++; } gepGlsFuncs = gep; hGlsDll = hdll; bRet = TRUE; Exit: LEAVECRITICALSECTION(&semLocal); return bRet; }
/*****************************Private*Routine******************************\
* * MetaGlProcTables * * Returns the GL dispatch tables to use for metafile RC's * * History: * Thu Feb 23 17:40:25 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void MetaGlProcTables(PGLCLTPROCTABLE *ppgcpt, PGLEXTPROCTABLE *ppgept) { ASSERTOPENGL(hGlsDll != NULL, "MetaGlProcTables: GLS not loaded\n"); *ppgcpt = &gcptGlsProcTable; *ppgept = &geptGlsExtProcTable; }
/******************************Public*Routine******************************\
* * MetaSetCltProcTable * * Update GLS's generic dispatch tables * * History: * Fri Jan 05 16:40:31 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void MetaSetCltProcTable(GLCLTPROCTABLE *pgcpt, GLEXTPROCTABLE *pgept) { gepGlsFuncs.glsUpdateCaptureExecTable(pgcpt, pgept); }
/******************************Public*Routine******************************\
* * MetaGetCltProcTable * * Retrieves GLS's generic dispatch tables * * History: * Fri Jan 05 19:14:18 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void MetaGetCltProcTable(GLCLTPROCTABLE *pgcpt, GLEXTPROCTABLE *pgept) { gepGlsFuncs.glsGetCaptureExecTable(pgcpt, pgept); }
/*****************************Private*Routine******************************\
* * GlsWriter * * GLS write function for metafile support * * History: * Thu Feb 23 15:49:03 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
size_t GlsWriter(size_t cb, CONST BYTE *pb) { PLRC plrc;
#if 0
DbgPrint("GlsWriter(%d)\n", cb); #endif
plrc = GLTEB_CLTCURRENTRC(); if( plrc == NULL ) { DBGERROR( "GlsWriter: No current RC!\n"); return 0; } ASSERTOPENGL(plrc->gwidCreate.hdc != NULL, "GlsWriter: hdcCreate is NULL\n"); ASSERTOPENGL(gepGlsFuncs.glsGetCurrentContext() == plrc->uiGlsCaptureContext, "GlsWriter: Wrong GLS context\n"); ASSERTOPENGL(plrc->fCapturing == TRUE, "GlsWriter: Not capturing\n");
if (GlGdiAddGlsRecord(plrc->gwidCreate.hdc, cb, (BYTE *)pb, plrc->prclGlsBounds)) { return cb; } else { return 0; } }
/*****************************Private*Routine******************************\
* * GlsFlush * * Post-command GLS callback to flush the GLS stream * * History: * Fri Feb 24 10:12:49 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlsFlush(GLSopcode op) { gepGlsFuncs.glsFlush(GLS_LAST); }
/*****************************Private*Routine******************************\
* * MetaRcBegin * * Start capturing on a metafile * * History: * Thu Feb 23 18:35:32 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL MetaRcBegin(PLRC plrc, HDC hdc) { PLRC plrcOld;
// The GLS commands here will cause data to be written, which
// requires a current RC. The RC is only used for data storage
// so we don't need to set the proc table
plrcOld = GLTEB_CLTCURRENTRC(); GLTEB_SET_CLTCURRENTRC(plrc); // Set capturing first because the block commands will cause
// GlsWriter calls
plrc->fCapturing = TRUE;
// Start recording
if (!gepGlsFuncs.glsBeginCapture("", gepGlsFuncs.glsBinary(GL_FALSE), GLS_NONE)) { plrc->fCapturing = FALSE; SetLastError(ERROR_NOT_ENOUGH_MEMORY); GLTEB_SET_CLTCURRENTRC(plrcOld); return FALSE; }
GLTEB_SET_CLTCURRENTRC(plrcOld); return TRUE; }
/*****************************Private*Routine******************************\
* * MetaRcEnd * * Stop capturing on a metafile RC * * History: * Thu Feb 23 17:13:48 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void MetaRcEnd(PLRC plrc) { PLRC plrcOld; // The GLS commands here will cause data to be written, which
// requires a current RC. The RC is only used for data storage
// so we don't need to set the proc table
plrcOld = GLTEB_CLTCURRENTRC(); GLTEB_SET_CLTCURRENTRC(plrc); gepGlsFuncs.glsEndCapture(); plrc->fCapturing = FALSE; GLTEB_SET_CLTCURRENTRC(plrcOld); }
// Table of operations which GLS should execute when capturing
// in order to return information
// Currently all of them are in the list
// Should we attempt to do only the critical calls?
static GLSopcode opExecuteBits[] = { GLS_OP_glAccum, GLS_OP_glAlphaFunc, GLS_OP_glAreTexturesResidentEXT, GLS_OP_glArrayElementEXT, GLS_OP_glBegin, GLS_OP_glBindTextureEXT, GLS_OP_glBitmap, GLS_OP_glBlendColorEXT, GLS_OP_glBlendEquationEXT, GLS_OP_glBlendFunc, GLS_OP_glCallList, GLS_OP_glCallLists, GLS_OP_glClear, GLS_OP_glClearAccum, GLS_OP_glClearColor, GLS_OP_glClearDepth, GLS_OP_glClearIndex, GLS_OP_glClearStencil, GLS_OP_glClipPlane, GLS_OP_glColor3b, GLS_OP_glColor3bv, GLS_OP_glColor3d, GLS_OP_glColor3dv, GLS_OP_glColor3f, GLS_OP_glColor3fv, GLS_OP_glColor3i, GLS_OP_glColor3iv, GLS_OP_glColor3s, GLS_OP_glColor3sv, GLS_OP_glColor3ub, GLS_OP_glColor3ubv, GLS_OP_glColor3ui, GLS_OP_glColor3uiv, GLS_OP_glColor3us, GLS_OP_glColor3usv, GLS_OP_glColor4b, GLS_OP_glColor4bv, GLS_OP_glColor4d, GLS_OP_glColor4dv, GLS_OP_glColor4f, GLS_OP_glColor4fv, GLS_OP_glColor4i, GLS_OP_glColor4iv, GLS_OP_glColor4s, GLS_OP_glColor4sv, GLS_OP_glColor4ub, GLS_OP_glColor4ubv, GLS_OP_glColor4ui, GLS_OP_glColor4uiv, GLS_OP_glColor4us, GLS_OP_glColor4usv, GLS_OP_glColorMask, GLS_OP_glColorMaterial, GLS_OP_glColorPointerEXT, GLS_OP_glColorSubTableEXT, GLS_OP_glDrawRangeElementsWIN, GLS_OP_glColorTableParameterfvSGI, GLS_OP_glColorTableParameterivSGI, GLS_OP_glColorTableEXT, GLS_OP_glConvolutionFilter1DEXT, GLS_OP_glConvolutionFilter2DEXT, GLS_OP_glConvolutionParameterfEXT, GLS_OP_glConvolutionParameterfvEXT, GLS_OP_glConvolutionParameteriEXT, GLS_OP_glConvolutionParameterivEXT, GLS_OP_glCopyColorTableSGI, GLS_OP_glCopyConvolutionFilter1DEXT, GLS_OP_glCopyConvolutionFilter2DEXT, GLS_OP_glCopyPixels, GLS_OP_glCopyTexImage1DEXT, GLS_OP_glCopyTexImage2DEXT, GLS_OP_glCopyTexSubImage1DEXT, GLS_OP_glCopyTexSubImage2DEXT, GLS_OP_glCopyTexSubImage3DEXT, GLS_OP_glCullFace, GLS_OP_glDeleteLists, GLS_OP_glDeleteTexturesEXT, GLS_OP_glDepthFunc, GLS_OP_glDepthMask, GLS_OP_glDepthRange, GLS_OP_glDetailTexFuncSGIS, GLS_OP_glDisable, GLS_OP_glDrawArraysEXT, GLS_OP_glDrawBuffer, GLS_OP_glDrawPixels, GLS_OP_glEdgeFlag, GLS_OP_glEdgeFlagPointerEXT, GLS_OP_glEdgeFlagv, GLS_OP_glEnable, GLS_OP_glEnd, GLS_OP_glEndList, GLS_OP_glEvalCoord1d, GLS_OP_glEvalCoord1dv, GLS_OP_glEvalCoord1f, GLS_OP_glEvalCoord1fv, GLS_OP_glEvalCoord2d, GLS_OP_glEvalCoord2dv, GLS_OP_glEvalCoord2f, GLS_OP_glEvalCoord2fv, GLS_OP_glEvalMesh1, GLS_OP_glEvalMesh2, GLS_OP_glEvalPoint1, GLS_OP_glEvalPoint2, GLS_OP_glFeedbackBuffer, GLS_OP_glFinish, GLS_OP_glFlush, GLS_OP_glFogf, GLS_OP_glFogfv, GLS_OP_glFogi, GLS_OP_glFogiv, GLS_OP_glFrontFace, GLS_OP_glFrustum, GLS_OP_glGenLists, GLS_OP_glGenTexturesEXT, GLS_OP_glGetBooleanv, GLS_OP_glGetClipPlane, GLS_OP_glGetColorTableParameterfvEXT, GLS_OP_glGetColorTableParameterivEXT, GLS_OP_glGetColorTableEXT, GLS_OP_glGetConvolutionFilterEXT, GLS_OP_glGetConvolutionParameterfvEXT, GLS_OP_glGetConvolutionParameterivEXT, GLS_OP_glGetDetailTexFuncSGIS, GLS_OP_glGetDoublev, GLS_OP_glGetError, GLS_OP_glGetFloatv, GLS_OP_glGetHistogramEXT, GLS_OP_glGetHistogramParameterfvEXT, GLS_OP_glGetHistogramParameterivEXT, GLS_OP_glGetIntegerv, GLS_OP_glGetLightfv, GLS_OP_glGetLightiv, GLS_OP_glGetMapdv, GLS_OP_glGetMapfv, GLS_OP_glGetMapiv, GLS_OP_glGetMaterialfv, GLS_OP_glGetMaterialiv, GLS_OP_glGetMinmaxEXT, GLS_OP_glGetMinmaxParameterfvEXT, GLS_OP_glGetMinmaxParameterivEXT, GLS_OP_glGetPixelMapfv, GLS_OP_glGetPixelMapuiv, GLS_OP_glGetPixelMapusv, GLS_OP_glGetPointervEXT, GLS_OP_glGetPolygonStipple, GLS_OP_glGetSeparableFilterEXT, GLS_OP_glGetSharpenTexFuncSGIS, GLS_OP_glGetString, GLS_OP_glGetTexColorTableParameterfvSGI, GLS_OP_glGetTexColorTableParameterivSGI, GLS_OP_glGetTexEnvfv, GLS_OP_glGetTexEnviv, GLS_OP_glGetTexGendv, GLS_OP_glGetTexGenfv, GLS_OP_glGetTexGeniv, GLS_OP_glGetTexImage, GLS_OP_glGetTexLevelParameterfv, GLS_OP_glGetTexLevelParameteriv, GLS_OP_glGetTexParameterfv, GLS_OP_glGetTexParameteriv, GLS_OP_glHint, GLS_OP_glHistogramEXT, GLS_OP_glIndexMask, GLS_OP_glIndexPointerEXT, GLS_OP_glIndexd, GLS_OP_glIndexdv, GLS_OP_glIndexf, GLS_OP_glIndexfv, GLS_OP_glIndexi, GLS_OP_glIndexiv, GLS_OP_glIndexs, GLS_OP_glIndexsv, GLS_OP_glInitNames, GLS_OP_glIsEnabled, GLS_OP_glIsList, GLS_OP_glIsTextureEXT, GLS_OP_glLightModelf, GLS_OP_glLightModelfv, GLS_OP_glLightModeli, GLS_OP_glLightModeliv, GLS_OP_glLightf, GLS_OP_glLightfv, GLS_OP_glLighti, GLS_OP_glLightiv, GLS_OP_glLineStipple, GLS_OP_glLineWidth, GLS_OP_glListBase, GLS_OP_glLoadIdentity, GLS_OP_glLoadMatrixd, GLS_OP_glLoadMatrixf, GLS_OP_glLoadName, GLS_OP_glLogicOp, GLS_OP_glMap1d, GLS_OP_glMap1f, GLS_OP_glMap2d, GLS_OP_glMap2f, GLS_OP_glMapGrid1d, GLS_OP_glMapGrid1f, GLS_OP_glMapGrid2d, GLS_OP_glMapGrid2f, GLS_OP_glMaterialf, GLS_OP_glMaterialfv, GLS_OP_glMateriali, GLS_OP_glMaterialiv, GLS_OP_glMatrixMode, GLS_OP_glMinmaxEXT, GLS_OP_glMultMatrixd, GLS_OP_glMultMatrixf, GLS_OP_glNewList, GLS_OP_glNormal3b, GLS_OP_glNormal3bv, GLS_OP_glNormal3d, GLS_OP_glNormal3dv, GLS_OP_glNormal3f, GLS_OP_glNormal3fv, GLS_OP_glNormal3i, GLS_OP_glNormal3iv, GLS_OP_glNormal3s, GLS_OP_glNormal3sv, GLS_OP_glNormalPointerEXT, GLS_OP_glOrtho, GLS_OP_glPassThrough, GLS_OP_glPixelMapfv, GLS_OP_glPixelMapuiv, GLS_OP_glPixelMapusv, GLS_OP_glPixelStoref, GLS_OP_glPixelStorei, GLS_OP_glPixelTexGenSGIX, GLS_OP_glPixelTransferf, GLS_OP_glPixelTransferi, GLS_OP_glPixelZoom, GLS_OP_glPointSize, GLS_OP_glPolygonMode, GLS_OP_glPolygonOffsetEXT, GLS_OP_glPolygonStipple, GLS_OP_glPopAttrib, GLS_OP_glPopMatrix, GLS_OP_glPopName, GLS_OP_glPrioritizeTexturesEXT, GLS_OP_glPushAttrib, GLS_OP_glPushMatrix, GLS_OP_glPushName, GLS_OP_glRasterPos2d, GLS_OP_glRasterPos2dv, GLS_OP_glRasterPos2f, GLS_OP_glRasterPos2fv, GLS_OP_glRasterPos2i, GLS_OP_glRasterPos2iv, GLS_OP_glRasterPos2s, GLS_OP_glRasterPos2sv, GLS_OP_glRasterPos3d, GLS_OP_glRasterPos3dv, GLS_OP_glRasterPos3f, GLS_OP_glRasterPos3fv, GLS_OP_glRasterPos3i, GLS_OP_glRasterPos3iv, GLS_OP_glRasterPos3s, GLS_OP_glRasterPos3sv, GLS_OP_glRasterPos4d, GLS_OP_glRasterPos4dv, GLS_OP_glRasterPos4f, GLS_OP_glRasterPos4fv, GLS_OP_glRasterPos4i, GLS_OP_glRasterPos4iv, GLS_OP_glRasterPos4s, GLS_OP_glRasterPos4sv, GLS_OP_glReadBuffer, GLS_OP_glReadPixels, GLS_OP_glRectd, GLS_OP_glRectdv, GLS_OP_glRectf, GLS_OP_glRectfv, GLS_OP_glRecti, GLS_OP_glRectiv, GLS_OP_glRects, GLS_OP_glRectsv, GLS_OP_glRenderMode, GLS_OP_glResetHistogramEXT, GLS_OP_glResetMinmaxEXT, GLS_OP_glRotated, GLS_OP_glRotatef, GLS_OP_glSampleMaskSGIS, GLS_OP_glSamplePatternSGIS, GLS_OP_glScaled, GLS_OP_glScalef, GLS_OP_glScissor, GLS_OP_glSelectBuffer, GLS_OP_glSeparableFilter2DEXT, GLS_OP_glShadeModel, GLS_OP_glSharpenTexFuncSGIS, GLS_OP_glStencilFunc, GLS_OP_glStencilMask, GLS_OP_glStencilOp, GLS_OP_glTagSampleBufferSGIX, GLS_OP_glTexColorTableParameterfvSGI, GLS_OP_glTexColorTableParameterivSGI, GLS_OP_glTexCoord1d, GLS_OP_glTexCoord1dv, GLS_OP_glTexCoord1f, GLS_OP_glTexCoord1fv, GLS_OP_glTexCoord1i, GLS_OP_glTexCoord1iv, GLS_OP_glTexCoord1s, GLS_OP_glTexCoord1sv, GLS_OP_glTexCoord2d, GLS_OP_glTexCoord2dv, GLS_OP_glTexCoord2f, GLS_OP_glTexCoord2fv, GLS_OP_glTexCoord2i, GLS_OP_glTexCoord2iv, GLS_OP_glTexCoord2s, GLS_OP_glTexCoord2sv, GLS_OP_glTexCoord3d, GLS_OP_glTexCoord3dv, GLS_OP_glTexCoord3f, GLS_OP_glTexCoord3fv, GLS_OP_glTexCoord3i, GLS_OP_glTexCoord3iv, GLS_OP_glTexCoord3s, GLS_OP_glTexCoord3sv, GLS_OP_glTexCoord4d, GLS_OP_glTexCoord4dv, GLS_OP_glTexCoord4f, GLS_OP_glTexCoord4fv, GLS_OP_glTexCoord4i, GLS_OP_glTexCoord4iv, GLS_OP_glTexCoord4s, GLS_OP_glTexCoord4sv, GLS_OP_glTexCoordPointerEXT, GLS_OP_glTexEnvf, GLS_OP_glTexEnvfv, GLS_OP_glTexEnvi, GLS_OP_glTexEnviv, GLS_OP_glTexGend, GLS_OP_glTexGendv, GLS_OP_glTexGenf, GLS_OP_glTexGenfv, GLS_OP_glTexGeni, GLS_OP_glTexGeniv, GLS_OP_glTexImage1D, GLS_OP_glTexImage2D, GLS_OP_glTexImage3DEXT, GLS_OP_glTexImage4DSGIS, GLS_OP_glTexParameterf, GLS_OP_glTexParameterfv, GLS_OP_glTexParameteri, GLS_OP_glTexParameteriv, GLS_OP_glTexSubImage1DEXT, GLS_OP_glTexSubImage2DEXT, GLS_OP_glTexSubImage3DEXT, GLS_OP_glTexSubImage4DSGIS, GLS_OP_glTranslated, GLS_OP_glTranslatef, GLS_OP_glVertex2d, GLS_OP_glVertex2dv, GLS_OP_glVertex2f, GLS_OP_glVertex2fv, GLS_OP_glVertex2i, GLS_OP_glVertex2iv, GLS_OP_glVertex2s, GLS_OP_glVertex2sv, GLS_OP_glVertex3d, GLS_OP_glVertex3dv, GLS_OP_glVertex3f, GLS_OP_glVertex3fv, GLS_OP_glVertex3i, GLS_OP_glVertex3iv, GLS_OP_glVertex3s, GLS_OP_glVertex3sv, GLS_OP_glVertex4d, GLS_OP_glVertex4dv, GLS_OP_glVertex4f, GLS_OP_glVertex4fv, GLS_OP_glVertex4i, GLS_OP_glVertex4iv, GLS_OP_glVertex4s, GLS_OP_glVertex4sv, GLS_OP_glVertexPointerEXT, GLS_OP_glViewport, GLS_OP_glArrayElement, GLS_OP_glBindTexture, GLS_OP_glColorPointer, GLS_OP_glDisableClientState, GLS_OP_glDrawArrays, GLS_OP_glDrawElements, GLS_OP_glEdgeFlagPointer, GLS_OP_glEnableClientState, GLS_OP_glIndexPointer, GLS_OP_glIndexub, GLS_OP_glIndexubv, GLS_OP_glInterleavedArrays, GLS_OP_glNormalPointer, GLS_OP_glPolygonOffset, GLS_OP_glTexCoordPointer, GLS_OP_glVertexPointer, GLS_OP_glAreTexturesResident, GLS_OP_glCopyTexImage1D, GLS_OP_glCopyTexImage2D, GLS_OP_glCopyTexSubImage1D, GLS_OP_glCopyTexSubImage2D, GLS_OP_glDeleteTextures, GLS_OP_glGenTextures, GLS_OP_glGetPointerv, GLS_OP_glIsTexture, GLS_OP_glPrioritizeTextures, GLS_OP_glTexSubImage1D, GLS_OP_glTexSubImage2D, GLS_OP_glPushClientAttrib, GLS_OP_glPopClientAttrib, }; #define EXECUTE_BITS (sizeof(opExecuteBits)/sizeof(opExecuteBits[0]))
/*****************************Private*Routine******************************\
* * CreateMetaRc * * Creates a rendering context for a metafile DC * * History: * Thu Feb 23 15:27:47 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL CreateMetaRc(HDC hdc, PLRC plrc) { int i; BOOL fSuccess; if (!MetaLoadGls()) { return FALSE; } // If there's currently a GLS context active we can't record
// because we require our own context to be current for recording
if (gepGlsFuncs.glsGetCurrentContext() != 0) { SetLastError(ERROR_BUSY); return FALSE; } // Create a GLS context to record into
plrc->uiGlsCaptureContext = gepGlsFuncs.glsGenContext(); if (plrc->uiGlsCaptureContext == 0) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto EH_NoContext; }
// No bounds by default
plrc->prclGlsBounds = NULL; // Set current GLS context
gepGlsFuncs.glsContext(plrc->uiGlsCaptureContext);
// Point to our writer function
gepGlsFuncs.glsWriteFunc(GlsWriter);
// Set up a callback to flush after every command
// This lets every GL command form its own separate record in the
// metafile
gepGlsFuncs.glsCaptureFunc(GLS_CAPTURE_EXIT_FUNC, GlsFlush);
// Set execute bits on commands which retrieve state
// This allows accurate results to come back for retrieval functions
for (i = 0; i < EXECUTE_BITS; i++) { gepGlsFuncs.glsCaptureFlags(opExecuteBits[i], GLS_CAPTURE_EXECUTE_BIT | GLS_CAPTURE_WRITE_BIT); } fSuccess = MetaRcBegin(plrc, hdc); // Remove context to avoid inadvertent GLS calls
// Also needed in failure case
gepGlsFuncs.glsContext(0);
if (fSuccess) { return TRUE; }
gepGlsFuncs.glsDeleteContext(plrc->uiGlsCaptureContext); plrc->uiGlsCaptureContext = 0; EH_NoContext: DBGERROR("CreateMetaRc failed\n"); return FALSE; }
/*****************************Private*Routine******************************\
* * DeleteMetaRc * * Cleans up a metafile RC * * History: * Thu Feb 23 16:35:19 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void DeleteMetaRc(PLRC plrc) { GLuint uiGlsCurrent; if (plrc->uiGlsCaptureContext != 0) { // Make the GLS context current just in case
// A different GLS context can be active at this time, though,
// because a different metafile RC could be current to this
// thread at the time of the delete, so we have to preserve
// any current context
uiGlsCurrent = gepGlsFuncs.glsGetCurrentContext(); gepGlsFuncs.glsContext(plrc->uiGlsCaptureContext);
// If we're still capturing, stop
if (plrc->fCapturing) { MetaRcEnd(plrc); }
// Restore old context
gepGlsFuncs.glsContext(uiGlsCurrent); // Clean up dying context
gepGlsFuncs.glsDeleteContext(plrc->uiGlsCaptureContext); plrc->uiGlsCaptureContext = 0; }
// Clean up playback context if necessary
// This can happen when metafile playback crashes or an
// application crashes while enumerating
if (plrc->uiGlsPlaybackContext != 0) { gepGlsFuncs.glsDeleteContext(plrc->uiGlsPlaybackContext); plrc->uiGlsPlaybackContext = 0; } // LRC and handle will be cleaned up elsewhere
}
/*****************************Private*Routine******************************\
* * ActivateMetaRc * * Make a metafile RC current * * History: * Thu Feb 23 16:50:31 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void ActivateMetaRc(PLRC plrc, HDC hdc) { ASSERTOPENGL(plrc->uiGlsCaptureContext != 0, "ActivateMetaRc: No GLS context\n"); ASSERTOPENGL(gepGlsFuncs.glsGetCurrentContext() == 0, "ActivateMetaRc: Already a current GLS context\n"); gepGlsFuncs.glsContext(plrc->uiGlsCaptureContext); }
/*****************************Private*Routine******************************\
* * DeactivateMetaRc * * Make a metafile RC non-current * * History: * Thu Feb 23 16:49:51 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void DeactivateMetaRc(PLRC plrc) { // The current GLS context may not be this RC's capturing context
// in the case where the RC has been made current after a
// CloseEnhMetaFile has stopped capturing
if (gepGlsFuncs.glsGetCurrentContext() == plrc->uiGlsCaptureContext) { gepGlsFuncs.glsContext(0); } }
/*****************************Private*Routine******************************\
* * GlmfSave * * Save all current GL state * * History: * Fri Feb 24 15:15:50 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlmfSave(void) { // What is the exact list of state to be saved?
// What about overflowing the projection and textures stacks?
// They're small
glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_MODELVIEW); glPushMatrix();
glMatrixMode(GL_PROJECTION); glPushMatrix();
glMatrixMode(GL_TEXTURE); glPushMatrix(); }
/*****************************Private*Routine******************************\
* * GlmfRestore * * Restores saved state * * History: * Fri Feb 24 15:16:14 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlmfRestore(void) { glMatrixMode(GL_TEXTURE); glPopMatrix();
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glPopMatrix();
glPopAttrib(); }
#define ScaleLongX(plrc, l) \
MulDiv(l, plrc->iGlsNumeratorX, plrc->iGlsDenominatorX) #define ScaleLongY(plrc, l) \
MulDiv(l, plrc->iGlsNumeratorY, plrc->iGlsDenominatorY) #define ScaleFloatX(plrc, f) ((f)*(plrc)->fGlsScaleX)
#define ScaleFloatY(plrc, f) ((f)*(plrc)->fGlsScaleY)
/*****************************Private*Routine******************************\
* * TransformLongPt * * Transform an integer point * * History: * Fri Feb 24 15:27:37 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void TransformLongPt(PLRC plrc, POINT *ppt) { ppt->x = MulDiv(ppt->x-plrc->iGlsSubtractX, plrc->iGlsNumeratorX, plrc->iGlsDenominatorX)+plrc->iGlsAddX; ppt->y = MulDiv(ppt->y-plrc->iGlsSubtractY, plrc->iGlsNumeratorY, plrc->iGlsDenominatorY)+plrc->iGlsAddY; }
/*****************************Private*Routine******************************\
* * ScaleLongPt * * Scale an integer point, no translation, for values rather than coordinates * * History: * Fri Feb 24 15:27:52 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void ScaleLongPt(PLRC plrc, POINT *ppt) { ppt->x = MulDiv(ppt->x, plrc->iGlsNumeratorX, plrc->iGlsDenominatorX); ppt->y = MulDiv(ppt->y, plrc->iGlsNumeratorY, plrc->iGlsDenominatorY); }
/*****************************Private*Routine******************************\
* * TransformFloatPt * * Transform a float point * * History: * Fri Feb 24 15:27:37 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void TransformFloatPt(PLRC plrc, POINTFLOAT *pptf) { pptf->x = (pptf->x-plrc->iGlsSubtractX)*plrc->iGlsNumeratorX/ plrc->iGlsDenominatorX+plrc->iGlsAddX; pptf->y = (pptf->y-plrc->iGlsSubtractY)*plrc->iGlsNumeratorY/ plrc->iGlsDenominatorY+plrc->iGlsAddY; }
/*****************************Private*Routine******************************\
* * ScaleFloatPt * * Scale a float point * * History: * Fri Feb 24 15:27:37 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void ScaleFloatPt(PLRC plrc, POINTFLOAT *pptf) { pptf->x = pptf->x*plrc->iGlsNumeratorX/plrc->iGlsDenominatorX; pptf->y = pptf->y*plrc->iGlsNumeratorY/plrc->iGlsDenominatorY; }
/*****************************Private*Routine******************************\
* * GLS output scaling callbacks * * The following functions are used as GLS command functions for * intercepting device coordinates and scaling them appropriately * * Bitmap contents are not scaled, but the current raster position is * correctly maintained so that they are positioned appropriately * * Stipples are not scaled * * History: * Fri Feb 24 15:28:23 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlsBitmapOut(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) { PLRC plrc; POINTFLOAT ptf;
plrc = GLTEB_CLTCURRENTRC(); ptf.x = xmove; ptf.y = ymove; ScaleFloatPt(plrc, &ptf); glBitmap(width, height, xorig, yorig, ptf.x, ptf.y, bitmap); }
void GlsCopyPixelsOut(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) { POINT ptXY, ptWH; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC(); ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); ptWH.x = (LONG)width; ptWH.y = (LONG)height; ScaleLongPt(plrc, &ptWH);
glCopyPixels(ptXY.x, ptXY.y, ptWH.x, ptWH.y, type); }
void GlsCopyTexImage1DOut(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) { POINT ptXY; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); glCopyTexImage1D(target, level, internalformat, ptXY.x, ptXY.y, ScaleLongX(plrc, width), border); }
void GlsCopyTexImage2DOut(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { POINT ptXY, ptWH; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); ptWH.x = (LONG)width; ptWH.y = (LONG)height; ScaleLongPt(plrc, &ptWH); glCopyTexImage2D(target, level, internalformat, ptXY.x, ptXY.y, ptWH.x, ptWH.y, border); }
void GlsCopyTexSubImage1DOut(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { POINT ptXY; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); glCopyTexSubImage1D(target, level, xoffset, ptXY.x, ptXY.y, ScaleLongX(plrc, width)); }
void GlsCopyTexSubImage2DOut(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { POINT ptXY, ptWH; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); ptWH.x = (LONG)width; ptWH.y = (LONG)height; ScaleLongPt(plrc, &ptWH); glCopyTexSubImage2D(target, level, xoffset, yoffset, ptXY.x, ptXY.y, ptWH.x, ptWH.y); }
void GlsLineWidthOut(GLfloat width) { PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
// Use X scaling here
glLineWidth(ScaleFloatX(plrc, width)); }
void GlsPointSizeOut(GLfloat size) { PLRC plrc;
plrc = GLTEB_CLTCURRENTRC(); // Use X scaling here
glPointSize(ScaleFloatX(plrc, size)); }
void GlsScissorOut(GLint x, GLint y, GLsizei width, GLsizei height) { POINT ptXY, ptWH; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); ptWH.x = (LONG)width; ptWH.y = (LONG)height; ScaleLongPt(plrc, &ptWH);
glScissor(ptXY.x, ptXY.y, ptWH.x, ptWH.y); }
void GlsViewportOut(GLint x, GLint y, GLsizei width, GLsizei height) { POINT ptXY, ptWH; PLRC plrc;
plrc = GLTEB_CLTCURRENTRC();
ptXY.x = x; ptXY.y = y; TransformLongPt(plrc, &ptXY); ptWH.x = (LONG)width; ptWH.y = (LONG)height; ScaleLongPt(plrc, &ptWH);
#if 0
DbgPrint("glViewport(%d, %d, %d, %d)\n", ptXY.x, ptXY.y, ptWH.x, ptWH.y); #endif
glViewport(ptXY.x, ptXY.y, ptWH.x, ptWH.y); }
static GLDEVICEPROCS gdpOutput = { GlsBitmapOut, GlsCopyPixelsOut, GlsCopyTexImage1DOut, GlsCopyTexImage2DOut, GlsCopyTexSubImage1DOut, GlsCopyTexSubImage2DOut, NULL, // glDrawPixels
GlsLineWidthOut, GlsPointSizeOut, GlsScissorOut, GlsViewportOut };
/*****************************Private*Routine******************************\
* * GlmfHookDeviceFns * * Hook all functions that deal with device units * * History: * Fri Feb 24 15:30:45 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlmfHookDeviceFns(void) { int i; PROC *ppfn;
ppfn = (PROC *)&gdpOutput; for (i = 0; i < GL_DEVICE_PROCS; i++) { if (*ppfn != NULL) { gepGlsFuncs.glsCommandFunc(glsopDeviceProcs[i], *ppfn); } ppfn++; } }
/*****************************Private*Routine******************************\
* * GlmfInitTransform * * Compute 2D playback transform from source and destination rectangles * Hook GLS with scaling functions * * History: * Fri Feb 24 15:31:24 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void GlmfInitTransform(LPRECTL prclFrom, LPRECTL prclTo) { PLRC plrc;
plrc = GLTEB_CLTCURRENTRC(); // Rectangles are inclusive-inclusive
plrc->iGlsSubtractX = prclFrom->left; plrc->iGlsSubtractY = prclFrom->top; plrc->iGlsNumeratorX = prclTo->right-prclTo->left+1; plrc->iGlsNumeratorY = prclTo->bottom-prclTo->top+1; plrc->iGlsDenominatorX = prclFrom->right-prclFrom->left+1; plrc->iGlsDenominatorY = prclFrom->bottom-prclFrom->top+1; plrc->iGlsAddX = prclTo->left; plrc->iGlsAddY = prclTo->top;
#if 0
DbgPrint("- %d,%d * %d,%d / %d,%d + %d,%d\n", plrc->iGlsSubtractX, plrc->iGlsSubtractY, plrc->iGlsNumeratorX, plrc->iGlsNumeratorY, plrc->iGlsDenominatorX, plrc->iGlsDenominatorY, plrc->iGlsAddX, plrc->iGlsAddY); #endif
// Only install hooks if the transform is not identity
if (plrc->iGlsSubtractX != plrc->iGlsAddX || plrc->iGlsSubtractY != plrc->iGlsAddY || plrc->iGlsNumeratorX != plrc->iGlsDenominatorX || plrc->iGlsNumeratorY != plrc->iGlsDenominatorY) { plrc->fGlsScaleX = (GLfloat)plrc->iGlsNumeratorX/ plrc->iGlsDenominatorX; plrc->fGlsScaleY = (GLfloat)plrc->iGlsNumeratorY/ plrc->iGlsDenominatorY;
GlmfHookDeviceFns(); } }
// Table of functions which need to have their command funcs
// reset for playback virtualization
static GLSopcode opRecirculate[] = { GLS_OP_glsBeginGLS, GLS_OP_glsBlock, GLS_OP_glsCallStream, GLS_OP_glsEndGLS, GLS_OP_glsError, GLS_OP_glsGLRC, GLS_OP_glsGLRCLayer, GLS_OP_glsHeaderGLRCi, GLS_OP_glsHeaderLayerf, GLS_OP_glsHeaderLayeri, GLS_OP_glsHeaderf, GLS_OP_glsHeaderfv, GLS_OP_glsHeaderi, GLS_OP_glsHeaderiv, GLS_OP_glsHeaderubz, GLS_OP_glsRequireExtension, GLS_OP_glsUnsupportedCommand, GLS_OP_glsAppRef, GLS_OP_glsBeginObj, GLS_OP_glsCharubz, GLS_OP_glsComment, GLS_OP_glsDisplayMapfv, GLS_OP_glsEndObj, GLS_OP_glsNumb, GLS_OP_glsNumbv, GLS_OP_glsNumd, GLS_OP_glsNumdv, GLS_OP_glsNumf, GLS_OP_glsNumfv, GLS_OP_glsNumi, GLS_OP_glsNumiv, GLS_OP_glsNuml, GLS_OP_glsNumlv, GLS_OP_glsNums, GLS_OP_glsNumsv, GLS_OP_glsNumub, GLS_OP_glsNumubv, GLS_OP_glsNumui, GLS_OP_glsNumuiv, GLS_OP_glsNumul, GLS_OP_glsNumulv, GLS_OP_glsNumus, GLS_OP_glsNumusv, GLS_OP_glsPad, GLS_OP_glsSwapBuffers }; #define RECIRCULATE_OPS (sizeof(opRecirculate)/sizeof(opRecirculate[0]))
/******************************Public*Routine******************************\
* * GlmfInitPlayback * * Initialize GL metafile playback, called from PlayEnhMetaFile for * metafiles with GL information in them * * History: * Fri Feb 24 10:32:29 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL APIENTRY GlmfInitPlayback(HDC hdc, ENHMETAHEADER *pemh, LPRECTL prclDest) { GLuint uiCurrentCtx; PLRC plrc; RECTL rclSourceDevice; int i;
// If we don't have the appropriate GL context set up,
// do nothing. This allows applications to play metafiles containing
// GL information even if they don't know anything about GL
plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL) { return TRUE; } if (!MetaLoadGls()) { return FALSE; }
plrc->uiGlsPlaybackContext = gepGlsFuncs.glsGenContext(); if (plrc->uiGlsPlaybackContext == 0) { return FALSE; }
GlmfSave();
// Set an initial viewport just as a default
glViewport(prclDest->left, prclDest->top, prclDest->right-prclDest->left, prclDest->bottom-prclDest->top);
// The frame is in .01mm units. Convert it to reference
// device units using the information in the metafile header
rclSourceDevice.left = MulDiv(pemh->rclFrame.left, pemh->szlDevice.cx, pemh->szlMillimeters.cx*100); rclSourceDevice.right = MulDiv(pemh->rclFrame.right, pemh->szlDevice.cx, pemh->szlMillimeters.cx*100); rclSourceDevice.top = MulDiv(pemh->rclFrame.top, pemh->szlDevice.cy, pemh->szlMillimeters.cy*100); rclSourceDevice.bottom = MulDiv(pemh->rclFrame.bottom, pemh->szlDevice.cy, pemh->szlMillimeters.cy*100);
// We are resetting command funcs so we need our playback context
// to be current. Another context could be current now, though,
// so preserve it
uiCurrentCtx = gepGlsFuncs.glsGetCurrentContext(); gepGlsFuncs.glsContext(plrc->uiGlsPlaybackContext); GlmfInitTransform(&rclSourceDevice, prclDest);
// Reset all GLS command funcs to point to the actual exported
// routines. This means that playback on this context will
// be exactly the same as if all the routines were being called
// directly, so embedding a metafile into another one works
// as expected
//
// NOTE: This context should not be made current because any
// GLS commands executed on it when it is current will now
// cause infinite loops
for (i = 0; i < RECIRCULATE_OPS; i++) { gepGlsFuncs.glsCommandFunc(opRecirculate[i], (&gepGlsFuncs.glsBeginGLS)[i]); }
// Restore preserved context
gepGlsFuncs.glsContext(uiCurrentCtx); return TRUE; }
/******************************Public*Routine******************************\
* * GlmfBeginGlsBlock * * Sets up things for GLS record playback which can only be active during * GLS records * Currently this only sets the world transform to identity to avoid * it interacting with GL drawing * * History: * Mon Apr 10 11:20:19 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL APIENTRY GlmfBeginGlsBlock(HDC hdc) { PLRC plrc; BOOL bRet; // If we don't have the appropriate GL context set up,
// do nothing. This allows applications to play metafiles containing
// GL information even if they don't know anything about GL
plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL) { return TRUE; } bRet = GetWorldTransform(hdc, &plrc->xformMeta); if (bRet) { bRet = ModifyWorldTransform(hdc, NULL, MWT_IDENTITY); }
return bRet; } /******************************Public*Routine******************************\
* * GlmfPlayGlsRecord * * Play a GL metafile record * * History: * Fri Feb 24 10:33:38 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
#define PLAY_STACK_BUFFER 256
BOOL APIENTRY GlmfPlayGlsRecord(HDC hdc, DWORD cb, BYTE *pb, LPRECTL prclBounds) { PLRC plrc; LARGE_INTEGER liBuffer[(PLAY_STACK_BUFFER+sizeof(LARGE_INTEGER)-1)/ sizeof(LARGE_INTEGER)+1]; BYTE *pbPlay, *pbAlloc = NULL; __GLSbinCommandHead_large *gbch; GLSopcode op; GLScommandAlignment gca;
#if 0
DbgPrint("GlmfPlayGlsRecord(%d)\n", cb); #endif
// If we don't have the appropriate GL and GLS contexts set up,
// do nothing. This allows applications to play metafiles containing
// GL information even if they don't know anything about GL
plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL || plrc->uiGlsPlaybackContext == 0) { return TRUE; } ASSERTOPENGL(hGlsDll != NULL, "GlmfPlayGlsRecord: GLS not loaded\n"); ASSERTOPENGL(plrc->tidCurrent == GetCurrentThreadId(), "GlmfPlayGlsRecord: " "Current RC does not belong to this thread!\n"); ASSERTOPENGL(plrc->gwidCurrent.hdc != 0, "GlmfPlayGlsRecord: Current HDC is NULL!\n");
// pb points to some arbitrary block of memory
// GLS requires that this block be appropriately aligned for
// any commands that are executed out of it, so we need to
// determine which command is in the buffer and then query
// GLS for its alignment.
// This is trickier than you would think since GLS doesn't
// always add padding to commands relative to their beginning; it
// sometimes adds padding to the end of the previous command.
// We need to detect the case where padding is added.
//
// NOTE: This definitely works when there is only one command
// in the buffer. It should work when there are multiple commands
// because the following commands are padded according to the
// alignment of the initial command. However, this assumption
// should probably be validated if blocks start containing
// multiple commands.
// Check for an initial pad and skip it if necessary
gbch = (__GLSbinCommandHead_large *)pb; if (gbch->opSmall == GLS_OP_glsPad && gbch->countSmall == 1) { pb += sizeof(__GLSbinCommandHead_small); cb -= sizeof(__GLSbinCommandHead_small); gbch = (__GLSbinCommandHead_large *)pb; }
ASSERTOPENGL(gbch->countSmall == 0 || gbch->opSmall != GLS_OP_glsPad, "Unexpected glsPad in command buffer\n");
op = gbch->countSmall == 0 ? gbch->opLarge : gbch->opSmall;
gepGlsFuncs.glsGetCommandAlignment(op, gepGlsFuncs.glsBinary(GL_FALSE), &gca); ASSERTOPENGL(gca.mask <= 7, "Unhandled GLS playback alignment\n");
if (((ULONG_PTR)pb & gca.mask) != gca.value) { if (cb <= PLAY_STACK_BUFFER) { pbPlay = (BYTE *)liBuffer+gca.value; } else { pbAlloc = (BYTE *)ALLOC(cb+gca.value); if (pbAlloc == NULL) { return FALSE; }
pbPlay = pbAlloc+gca.value; } RtlCopyMemory(pbPlay, pb, cb); } else { pbPlay = pb; } gepGlsFuncs.glsCallArrayInContext(plrc->uiGlsPlaybackContext, gepGlsFuncs.glsBinary(GL_FALSE), cb, pbPlay);
if (pbAlloc != NULL) { FREE(pbAlloc); } return TRUE; }
/******************************Public*Routine******************************\
* * GlmfEndGlsBlock * * Resets state changed for GLS record playback * Currently restores the world transform * * History: * Mon Apr 10 11:23:06 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL APIENTRY GlmfEndGlsBlock(HDC hdc) { PLRC plrc; // If we don't have the appropriate GL context set up,
// do nothing. This allows applications to play metafiles containing
// GL information even if they don't know anything about GL
plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL) { return TRUE; }
// Doesn't matter which side we multiply by since the transform
// should be identity
return ModifyWorldTransform(hdc, &plrc->xformMeta, MWT_LEFTMULTIPLY); } /******************************Public*Routine******************************\
* * GlmfEndPlayback * * End GL metafile playback, called at the end of metafile playback * Only called if GlmfInitPlayback was successful * * History: * Fri Feb 24 10:36:36 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL APIENTRY GlmfEndPlayback(HDC hdc) { PLRC plrc;
// If we don't have the appropriate GL and GLS contexts set up,
// do nothing. This allows applications to play metafiles containing
// GL information even if they don't know anything about GL
plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL || plrc->uiGlsPlaybackContext == 0) { return TRUE; }
ASSERTOPENGL(hGlsDll != NULL, "GlmfEndPlayback: GLS not loaded\n");
// Since GlmfInitPlayback completed, we must have saved state
GlmfRestore();
ASSERTOPENGL(plrc->uiGlsPlaybackContext != 0, "GlmfEndPlayback: No playback context\n"); gepGlsFuncs.glsDeleteContext(plrc->uiGlsPlaybackContext); plrc->uiGlsPlaybackContext = 0;
// Request cleanup of windows on the theory that most orphaned
// windows are produced by DCs created for metafiles and memory
// DCs used by printing. Cleaning up during playback will mean
// that orphaned windows are only around for one extra playback
wglValidateWindows();
return TRUE; }
/******************************Public*Routine******************************\
* * GlmfCloseMetaFile * * Called in CloseEnhMetaFile if GL records are present in the metafile * * History: * Fri Mar 03 18:05:50 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL APIENTRY GlmfCloseMetaFile(HDC hdc) { PLRC plrc; GLGENwindow *pwnd; GLWINDOWID gwid;
// This DC has just gone away so clean up its WNDOBJ if necessary
WindowIdFromHdc(hdc, &gwid); pwnd = pwndGetFromID(&gwid); if (pwnd != NULL) { pwndCleanup(pwnd); } // The app could have called wglDeleteContext before CloseEnhMetaFile,
// so we're not guaranteed to have a context
plrc = GLTEB_CLTCURRENTRC(); if (plrc == NULL || !plrc->fCapturing) { return TRUE; }
ASSERTOPENGL(hGlsDll != NULL, "GlmfCloseMetaFile: GLS not loaded\n");
ASSERTOPENGL(plrc->uiGlsCaptureContext != 0, "GlmfCloseMetaFile: GLS context is invalid"); MetaRcEnd(plrc);
// Set the proc table to the generic routines because capturing
// is over. Metafiling always uses the generic routines because
// the underlying surface is always faked on top of an info DC.
{ // Use RGBA or CI proc table depending on the color mode.
GLCLTPROCTABLE *pglProcTable; __GL_SETUP();
if (gc->modes.colorIndexMode) pglProcTable = &glCltCIProcTable; else pglProcTable = &glCltRGBAProcTable;
SetCltProcTable(pglProcTable, &glExtProcTable, TRUE); }
return TRUE; }
/******************************Public*Routine******************************\
* * GlGdi routines * * Thunks to allow the same binary to run on both NT with metafile support * and Win95 without it * * History: * Thu Aug 31 15:46:37 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
#if DBG
BOOL APIENTRY GlGdiAddGlsRecord(HDC hdc, DWORD cb, BYTE *pb, LPRECTL prclBounds) { ASSERTOPENGL(pfnGdiAddGlsRecord != NULL, "GdiAddGlsRecord called without support\n"); return pfnGdiAddGlsRecord(hdc, cb, pb, prclBounds); }
BOOL APIENTRY GlGdiAddGlsBounds(HDC hdc, LPRECTL prclBounds) { ASSERTOPENGL(pfnGdiAddGlsBounds != NULL, "GdiAddGlsBounds called without support\n"); return pfnGdiAddGlsBounds(hdc, prclBounds); }
BOOL APIENTRY GlGdiIsMetaPrintDC(HDC hdc) { ASSERTOPENGL(pfnGdiIsMetaPrintDC != NULL, "GdiIsMetaPrintDC called without support\n"); return pfnGdiIsMetaPrintDC(hdc); } #endif
#else
PROC * APIENTRY wglGetDefaultDispatchTable(void) { return NULL; }
BOOL APIENTRY GlmfInitPlayback(HDC hdc, ENHMETAHEADER *pemh, LPRECTL prclDest) { return FALSE; }
BOOL APIENTRY GlmfBeginGlsBlock(HDC hdc) { return FALSE; }
BOOL APIENTRY GlmfPlayGlsRecord(HDC hdc, DWORD cb, BYTE *pb, LPRECTL prclBounds) { return FALSE; }
BOOL APIENTRY GlmfEndGlsBlock(HDC hdc) { return FALSE; }
BOOL APIENTRY GlmfEndPlayback(HDC hdc) { return FALSE; }
BOOL APIENTRY GlmfCloseMetaFile(HDC hdc) { return FALSE; }
#endif
|