2134 lines
56 KiB
C
2134 lines
56 KiB
C
/******************************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
|