windows-nt/Source/XPSP1/NT/multimedia/opengl/gls/lib/write.c
2020-09-26 16:20:57 +08:00

836 lines
26 KiB
C

/*
** Copyright 1995-2095, Silicon Graphics, Inc.
** All Rights Reserved.
**
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
** the contents of this file may not be disclosed to third parties, copied or
** duplicated in any form, in whole or in part, without the prior written
** permission of Silicon Graphics, Inc.
**
** RESTRICTED RIGHTS LEGEND:
** Use, duplication or disclosure by the Government is subject to restrictions
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
** rights reserved under the Copyright Laws of the United States.
*/
#include "glslib.h"
#include <stdlib.h>
/******************************************************************************
__GLSwriteStream
******************************************************************************/
__GLSwriteStream* __glsWriteStream_create(
const GLubyte *inName, GLboolean inAppend
) {
__GLScontext *const ctx = __GLS_CONTEXT;
__GLSwriteStream *const outStream = __glsCalloc(
1, sizeof(__GLSwriteStream)
);
if (!outStream) return GLS_NONE;
__glsString_init(&outStream->name);
if (inName[0]) {
const GLubyte *openName;
if (
!__glsListString_prefix(
ctx->writePrefix, inName, &outStream->name
) ||
!(openName = __glsUCS1String(outStream->name.head))
) {
return __glsWriteStream_destroy(outStream);
}
if (outStream->channel = fopen((const char *)openName, "rb")) {
fclose(outStream->channel);
} else {
outStream->created = GL_TRUE;
}
outStream->channel = fopen(
(const char *)openName, inAppend ? "ab" : "wb"
);
if (openName != outStream->name.head) free((GLvoid *)openName);
if (outStream->channel) {
setbuf(outStream->channel, GLS_NONE);
outStream->opened = GL_TRUE;
return outStream;
}
__GLS_RAISE_ERROR(GLS_STREAM_OPEN_ERROR);
return __glsWriteStream_destroy(outStream);
} else {
outStream->writeFunc = ctx->writeFunc;
if (!outStream->writeFunc) {
outStream->channel = ctx->defaultWriteChannel;
}
return outStream;
}
}
__GLSwriteStream* __glsWriteStream_destroy(__GLSwriteStream *inStream) {
if (!inStream) return GLS_NONE;
if (inStream->opened && fclose(inStream->channel)) {
__GLS_RAISE_ERROR(GLS_STREAM_CLOSE_ERROR);
}
__glsString_final(&inStream->name);
free(inStream);
return GLS_NONE;
}
size_t __glsWriteStream_getByteCount(const __GLSwriteStream *inStream) {
fpos_t pos;
if (!inStream->channel) return 0;
if (
!fgetpos(inStream->channel, &pos) &&
!fseek(inStream->channel, 0, SEEK_END)
) {
const long outVal = ftell(inStream->channel);
fsetpos(inStream->channel, &pos);
return outVal >= 0 ? (size_t)outVal : 0;
} else {
return 0;
}
}
/******************************************************************************
__GLSwriter
******************************************************************************/
static const GLvoid* __glsPixelBase(
GLenum inType,
GLint inGroupElems,
GLint inStrideElems,
const __GLSpixelStoreConfig *inConfig,
const GLvoid *inPixels
) {
GLint skipRows = inConfig->skipRows;
#if __GL_EXT_texture3D
skipRows += inConfig->skipImages * inConfig->imageHeight;
#endif /* __GL_EXT_texture3D */
#if __GL_SGIS_texture4D
skipRows += (
inConfig->skipVolumes *
inConfig->imageDepth *
inConfig->imageHeight
);
#endif /* __GL_SGIS_texture4D */
switch (inType) {
case GL_BITMAP:
return (
(const GLubyte *)inPixels +
skipRows * inStrideElems / 8 +
inConfig->skipPixels * inGroupElems / 8
);
case GL_BYTE:
case GL_UNSIGNED_BYTE:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_BYTE_3_3_2_EXT:
#endif /* __GL_EXT_packed_pixels */
return (
(const GLbyte *)inPixels +
skipRows * inStrideElems +
inConfig->skipPixels * inGroupElems
);
case GL_SHORT:
case GL_UNSIGNED_SHORT:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_SHORT_4_4_4_4_EXT:
case GL_UNSIGNED_SHORT_5_5_5_1_EXT:
#endif /* __GL_EXT_packed_pixels */
return (
(const GLshort *)inPixels +
skipRows * inStrideElems +
inConfig->skipPixels * inGroupElems
);
case GL_FLOAT:
case GL_INT:
case GL_UNSIGNED_INT:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_INT_8_8_8_8_EXT:
case GL_UNSIGNED_INT_10_10_10_2_EXT:
#endif /* __GL_EXT_packed_pixels */
return (
(const GLint *)inPixels +
skipRows * inStrideElems +
inConfig->skipPixels * inGroupElems
);
default:
return inPixels;
}
}
static GLint __glsPixelStrideElems(
GLenum inType,
GLint inGroupElems,
GLint inWidth,
const __GLSpixelStoreConfig *inConfig
) {
const GLint align = inConfig->alignment;
GLint elemLog, padBytes, strideBytes;
const GLint strideElems = (
inGroupElems * (inConfig->rowLength ? inConfig->rowLength : inWidth)
);
switch (inType) {
case GL_BITMAP:
strideBytes = (strideElems + 7) >> 3;
if (padBytes = strideBytes & align - 1) {
strideBytes += align - padBytes;
}
return strideBytes << 3;
case GL_BYTE:
case GL_UNSIGNED_BYTE:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_BYTE_3_3_2_EXT:
#endif /* __GL_EXT_packed_pixels */
elemLog = 0;
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_SHORT_4_4_4_4_EXT:
case GL_UNSIGNED_SHORT_5_5_5_1_EXT:
#endif /* __GL_EXT_packed_pixels */
elemLog = 1;
break;
case GL_FLOAT:
case GL_INT:
case GL_UNSIGNED_INT:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_INT_8_8_8_8_EXT:
case GL_UNSIGNED_INT_10_10_10_2_EXT:
#endif /* __GL_EXT_packed_pixels */
elemLog = 2;
break;
default:
return 0;
}
strideBytes = strideElems << elemLog;
if (padBytes = strideBytes & align - 1) {
return (strideBytes + align - padBytes) >> elemLog;
} else {
return strideElems;
}
}
static __GLSwriter* __glsWriter_create_context(
const GLubyte *inStreamName, GLbitfield inWriteFlags
) {
__GLScontext *const ctx = __GLS_CONTEXT;
__GLScontextStreamBlock *block;
__GLSwriter *outWriter = GLS_NONE;
__GLScontextStream *stream = GLS_NONE;
if (stream = __glsStr2PtrDict_find(ctx->contextStreamDict, inStreamName)) {
GLint i;
for (i = 0 ; i < ctx->captureNesting ; ++i) {
if (ctx->writers[i]->contextStream == stream) {
__GLS_RAISE_ERROR(GLS_INVALID_OPERATION);
return GLS_NONE;
}
}
if (stream->callCount) {
__GLS_RAISE_ERROR(GLS_INVALID_OPERATION);
return GLS_NONE;
}
outWriter = __glsCalloc(1, sizeof(__GLSwriter));
if (!outWriter) return GLS_NONE;
if (!(inWriteFlags & GLS_WRITE_APPEND_BIT)) {
__glsContextStream_truncate(
stream, __glsContextStream_firstBlock(stream), 0
);
}
} else {
if (
!(outWriter = __glsCalloc(1, sizeof(__GLSwriter))) ||
!(stream = __glsContextStream_create(inStreamName)) ||
!__glsStr2PtrDict_add(ctx->contextStreamDict, inStreamName, stream)
) {
__glsContextStream_destroy(stream);
return __glsWriter_destroy(outWriter);
}
__GLS_ITERLIST_APPEND(&ctx->contextStreamList, stream);
outWriter->contextCreated = GL_TRUE;
}
block = __glsContextStream_lastBlock(stream);
__glsContextStreamBlock_removeJump(block);
outWriter->bufPtr = block->writeTail;
outWriter->bufTail = block->bufTail - __GLS_JUMP_ALLOC;
outWriter->startBlock = block;
outWriter->startOffset = (size_t)((ULONG_PTR)(block->writeTail - block->buf));
outWriter->contextStream = stream;
__glsWriter_initDispatch_bin(outWriter, GLS_CONTEXT);
outWriter->type = GLS_CONTEXT;
return outWriter;
}
static __GLSwriter* __glsWriter_create_extern(
const GLubyte *inStreamName, GLSenum inStreamType, GLbitfield inWriteFlags
) {
__GLSwriter *outWriter;
outWriter = __glsCalloc(1, sizeof(__GLSwriter));
if (!outWriter) return GLS_NONE;
outWriter->externStream = __glsWriteStream_create(
inStreamName,
(GLboolean)(inWriteFlags & GLS_WRITE_APPEND_BIT ? GL_TRUE : GL_FALSE)
);
if (!outWriter->externStream) return __glsWriter_destroy(outWriter);
outWriter->startOffset = __glsWriteStream_getByteCount(
outWriter->externStream
);
outWriter->externBuf = outWriter->externBufHead = __glsMalloc(
__GLS_WRITER_EXTERN_BUF_BYTES
);
if (!outWriter->externBuf) return __glsWriter_destroy(outWriter);
outWriter->bufPtr = outWriter->externBufHead;
/*
** bufTail is moved back from actual buffer tail to streamline ALLOC
** check for GLS_TEXT parameter writing.
*/
outWriter->bufTail = (
outWriter->externBufHead +
__GLS_WRITER_EXTERN_BUF_BYTES -
__GLS_WRITER_EXTERN_BUF_SLOP
);
if (inStreamType == GLS_TEXT) {
__glsWriter_initDispatch_text(outWriter);
} else {
__glsWriter_initDispatch_bin(outWriter, inStreamType);
}
outWriter->type = inStreamType;
return outWriter;
}
__GLSwriter* __glsWriter_create(
const GLubyte *inStreamName, GLSenum inStreamType, GLbitfield inWriteFlags
) {
__GLSwriter *outWriter;
if (inStreamType == GLS_CONTEXT) {
outWriter = __glsWriter_create_context(inStreamName, inWriteFlags);
} else {
outWriter = __glsWriter_create_extern(
inStreamName, inStreamType, inWriteFlags
);
}
if (outWriter) {
outWriter->beginCommand(outWriter, GLS_OP_glsBeginGLS, 8);
outWriter->putGLint(outWriter, __GLS_VERSION_MAJOR);
outWriter->putGLint(outWriter, __GLS_VERSION_MINOR);
outWriter->endCommand(outWriter);
__glsWriter_flush(outWriter);
}
return outWriter;
}
__GLSwriter* __glsWriter_destroy(__GLSwriter *inWriter) {
if (!inWriter) return GLS_NONE;
if (inWriter->type != GLS_NONE) {
if (inWriter->beginCommand(inWriter, GLS_OP_glsEndGLS, 0)) {
inWriter->endCommand(inWriter);
}
__glsWriter_flush(inWriter);
if (inWriter->type == GLS_CONTEXT) {
__GLScontextStreamBlock *endBlock;
if (inWriter->error && inWriter->contextCreated) {
__glsStrDict_remove(
__GLS_CONTEXT->contextStreamDict,
inWriter->contextStream->name.head
);
__GLS_ITERLIST_REMOVE_DESTROY(
&__GLS_CONTEXT->contextStreamList,
inWriter->contextStream,
__glsContextStream_destroy
);
} else if (inWriter->error) {
endBlock = inWriter->startBlock;
endBlock->writeTail = endBlock->buf + inWriter->startOffset;
__glsContextStream_truncate(
inWriter->contextStream,
endBlock,
(size_t)((ULONG_PTR)(endBlock->writeTail - endBlock->buf))
);
} else {
endBlock = __glsContextStream_lastBlock(
inWriter->contextStream
);
endBlock->writeTail = inWriter->bufPtr;
__glsContextStream_truncate(
inWriter->contextStream,
endBlock,
(size_t)((ULONG_PTR)(endBlock->writeTail - endBlock->buf))
);
}
} else {
if (inWriter->error && inWriter->externStream->opened) {
if (inWriter->externStream->created) {
if (
remove((const char *)inWriter->externStream->name.head)
) {
__GLS_RAISE_ERROR(GLS_STREAM_DELETE_ERROR);
}
} else if (inWriter->externStream->channel) {
__GLS_TRUNCATE_EXTERN(
inWriter->externStream->channel, inWriter->startOffset
);
}
}
}
}
free(inWriter->externBuf);
__glsWriteStream_destroy(inWriter->externStream);
free(inWriter);
return GLS_NONE;
}
GLboolean __glsWriter_flush(__GLSwriter *inoutWriter) {
if (inoutWriter->error) return GL_FALSE;
inoutWriter->prevCommand = GLS_NONE;
if (inoutWriter->type == GLS_CONTEXT) {
return GL_TRUE;
} else {
FILE *channel;
const size_t n = (size_t)((ULONG_PTR)(inoutWriter->bufPtr - inoutWriter->externBufHead));
if (!n) return GL_TRUE;
if (channel = inoutWriter->externStream->channel) {
if (
fwrite(inoutWriter->externBufHead, 1, n, channel) == n &&
!fflush(channel)
) {
inoutWriter->externBufHead = (
(inoutWriter->wordCount & 1) ?
inoutWriter->externBuf + 4 :
inoutWriter->externBuf
);
inoutWriter->bufPtr = inoutWriter->externBufHead;
return GL_TRUE;
} else {
__GLS_RAISE_ERROR(GLS_STREAM_WRITE_ERROR);
clearerr(channel);
inoutWriter->error = GL_TRUE;
return GL_FALSE;
}
} else {
if (
inoutWriter->externStream->writeFunc(
n, inoutWriter->externBufHead
)
== n
) {
inoutWriter->externBufHead = (
(inoutWriter->wordCount & 1) ?
inoutWriter->externBuf + 4 :
inoutWriter->externBuf
);
inoutWriter->bufPtr = inoutWriter->externBufHead;
return GL_TRUE;
} else {
__GLS_RAISE_ERROR(GLS_STREAM_WRITE_ERROR);
inoutWriter->error = GL_TRUE;
return GL_FALSE;
}
}
}
}
void __glsWriter_putListv(
__GLSwriter *inoutWriter,
GLenum inType,
GLint inCount,
const GLvoid *inVec
) {
switch (inType) {
case GL_2_BYTES:
inoutWriter->putGLubytev(
inoutWriter, 2 * inCount, (const GLubyte *)inVec
);
break;
case GL_3_BYTES:
inoutWriter->putGLubytev(
inoutWriter, 3 * inCount, (const GLubyte *)inVec
);
break;
case GL_4_BYTES:
inoutWriter->putGLubytev(
inoutWriter, 4 * inCount, (const GLubyte *)inVec
);
break;
case GL_BYTE:
inoutWriter->putGLbytev(
inoutWriter, inCount, (const GLbyte *)inVec
);
break;
case GL_FLOAT:
inoutWriter->putGLfloatv(
inoutWriter, inCount, (const GLfloat *)inVec
);
break;
case GL_INT:
inoutWriter->putGLintv(
inoutWriter, inCount, (const GLint *)inVec
);
break;
case GL_SHORT:
inoutWriter->putGLshortv(
inoutWriter, inCount, (const GLshort *)inVec
);
break;
case GL_UNSIGNED_BYTE:
inoutWriter->putGLubytev(
inoutWriter, inCount, (const GLubyte *)inVec
);
break;
case GL_UNSIGNED_INT:
inoutWriter->putGLuintv(
inoutWriter, inCount, (const GLuint *)inVec
);
break;
case GL_UNSIGNED_SHORT:
inoutWriter->putGLushortv(
inoutWriter, inCount, (const GLushort *)inVec
);
break;
default:
inoutWriter->putGLbytev(inoutWriter, 0, GLS_NONE);
break;
}
}
void __glsWriter_putPixelv(
__GLSwriter *inoutWriter,
GLenum inFormat,
GLenum inType,
GLint inWidth,
GLint inHeight,
const GLvoid *inVec
) {
GLint groupElems;
GLint rowElems;
GLint strideElems;
__GLSpixelStoreConfig pixelStore;
if (!inVec) inType = GLS_NONE;
__glsPixelStoreConfig_get_unpack(&pixelStore);
switch (inFormat) {
case GL_ALPHA:
case GL_BLUE:
case GL_COLOR_INDEX:
case GL_DEPTH_COMPONENT:
case GL_GREEN:
case GL_LUMINANCE:
case GL_RED:
case GL_STENCIL_INDEX:
groupElems = 1;
break;
case GL_LUMINANCE_ALPHA:
groupElems = 2;
break;
case GL_RGB:
#if __GL_EXT_bgra
case GL_BGR_EXT:
#endif
groupElems = 3;
break;
case GL_RGBA:
#if __GL_EXT_bgra
case GL_BGRA_EXT:
#endif
groupElems = 4;
break;
#if __GL_EXT_abgr
case GL_ABGR_EXT:
groupElems = 4;
break;
#endif /* __GL_EXT_abgr */
#if __GL_EXT_cmyka
case GL_CMYK_EXT:
groupElems = 4;
break;
case GL_CMYKA_EXT:
groupElems = 5;
break;
#endif /* __GL_EXT_cmyka */
default:
groupElems = 0;
inType = GLS_NONE;
}
#if __GL_EXT_packed_pixels
switch (inType) {
case GL_UNSIGNED_BYTE_3_3_2_EXT:
if (groupElems != 3) inType = GLS_NONE;
break;
case GL_UNSIGNED_SHORT_4_4_4_4_EXT:
case GL_UNSIGNED_SHORT_5_5_5_1_EXT:
case GL_UNSIGNED_INT_8_8_8_8_EXT:
case GL_UNSIGNED_INT_10_10_10_2_EXT:
if (groupElems != 4) inType = GLS_NONE;
break;
}
#endif /* __GL_EXT_packed_pixels */
rowElems = groupElems * inWidth;
strideElems = __glsPixelStrideElems(
inType, groupElems, inWidth, &pixelStore
);
switch (inType) {
case GL_BITMAP:
inoutWriter->putGLbitvs(
inoutWriter,
(GLboolean)pixelStore.lsbFirst,
pixelStore.skipPixels * groupElems & 7,
rowElems,
strideElems - rowElems,
inHeight,
(const GLubyte *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_BYTE:
inoutWriter->putGLbytevs(
inoutWriter,
GL_FALSE,
rowElems,
strideElems - rowElems,
inHeight,
0,
1,
(const GLbyte *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_FLOAT:
inoutWriter->putGLfloatvs(
inoutWriter,
(GLboolean)pixelStore.swapBytes,
rowElems,
(strideElems - rowElems) * 4,
inHeight,
0,
1,
(const GLfloat *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_INT:
inoutWriter->putGLintvs(
inoutWriter,
(GLboolean)pixelStore.swapBytes,
rowElems,
(strideElems - rowElems) * 4,
inHeight,
0,
1,
(const GLint *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_SHORT:
inoutWriter->putGLshortvs(
inoutWriter,
(GLboolean)pixelStore.swapBytes,
rowElems,
(strideElems - rowElems) * 2,
inHeight,
0,
1,
(const GLshort *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_UNSIGNED_BYTE:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_BYTE_3_3_2_EXT:
#endif /* __GL_EXT_packed_pixels */
inoutWriter->putGLubytevs(
inoutWriter,
GL_FALSE,
rowElems,
strideElems - rowElems,
inHeight,
0,
1,
(const GLubyte *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_UNSIGNED_INT:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_INT_8_8_8_8_EXT:
case GL_UNSIGNED_INT_10_10_10_2_EXT:
#endif /* __GL_EXT_packed_pixels */
inoutWriter->putGLuintvs(
inoutWriter,
(GLboolean)pixelStore.swapBytes,
rowElems,
(strideElems - rowElems) * 4,
inHeight,
0,
1,
(const GLuint *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
case GL_UNSIGNED_SHORT:
#if __GL_EXT_packed_pixels
case GL_UNSIGNED_SHORT_4_4_4_4_EXT:
case GL_UNSIGNED_SHORT_5_5_5_1_EXT:
#endif /* __GL_EXT_packed_pixels */
inoutWriter->putGLushortvs(
inoutWriter,
(GLboolean)pixelStore.swapBytes,
rowElems,
(strideElems - rowElems) * 2,
inHeight,
0,
1,
(const GLushort *)__glsPixelBase(
inType, groupElems, strideElems, &pixelStore, inVec
)
);
break;
default:
inoutWriter->putGLbytev(inoutWriter, 0, GLS_NONE);
break;
}
}
// DrewB - Always enabled for 1.1 support
void __glsWriter_putVertexv(
__GLSwriter *inoutWriter,
GLint inSize,
GLenum inType,
GLint inStride,
GLint inCount,
const GLvoid *inVec
) {
if (!inVec) inType = GLS_NONE;
switch (inType) {
case __GLS_BOOLEAN:
inoutWriter->putGLbooleanvs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize : 0,
inCount,
0,
1,
(const GLboolean *)inVec
);
break;
case GL_BYTE:
inoutWriter->putGLbytevs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize : 0,
inCount,
0,
1,
(const GLbyte *)inVec
);
break;
case GL_DOUBLE_EXT:
inoutWriter->putGLdoublevs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize * 8 : 0,
inCount,
0,
1,
(const GLdouble *)inVec
);
break;
case GL_FLOAT:
inoutWriter->putGLfloatvs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize * 4 : 0,
inCount,
0,
1,
(const GLfloat *)inVec
);
break;
case GL_INT:
inoutWriter->putGLintvs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize * 4 : 0,
inCount,
0,
1,
(const GLint *)inVec
);
break;
case GL_SHORT:
inoutWriter->putGLshortvs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize * 2 : 0,
inCount,
0,
1,
(const GLshort *)inVec
);
break;
case GL_UNSIGNED_BYTE:
inoutWriter->putGLubytevs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize : 0,
inCount,
0,
1,
(const GLubyte *)inVec
);
break;
case GL_UNSIGNED_INT:
inoutWriter->putGLuintvs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize * 4 : 0,
inCount,
0,
1,
(const GLuint *)inVec
);
break;
case GL_UNSIGNED_SHORT:
inoutWriter->putGLushortvs(
inoutWriter,
GL_FALSE,
inSize,
inStride ? inStride - inSize * 2 : 0,
inCount,
0,
1,
(const GLushort *)inVec
);
break;
default:
inoutWriter->putGLbytev(inoutWriter, 0, GLS_NONE);
break;
}
}