/* * $Id$ * * $Date$ * $Revision$ * * (C) 1999 by Hyperion * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ #include "displaylists.h" #include "smartlock.h" #include "sysinc.h" #include #include #include static char rcsid[] UNUSED = "$Id$"; #define min(x,y) (x) < (y) ? (x) : (y) #define max(x,y) (x) > (y) ? (x) : (y) void tex_FreeTextures(GLcontext context); void tex_SetEnv(GLcontext context, GLenum env); static ULONG tex_GLFilter2W3D(GLcontext, GLenum filter); void tex_SetFilter(GLcontext context, GLenum min, GLenum mag); void tex_SetWrap(GLcontext context, GLenum wrap_s, GLenum wrap_t); void DisableBlendStage(GLcontext context, uint32 stage); uint32 MGLConvert(GLcontext context, GLenum internalformat, GLuint width, GLuint height, GLenum format, GLenum type, GLubyte *source, GLubyte *dest); void MGLUpdate(GLcontext context, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLubyte *pixels, GLubyte *dest, GLsizei dstWidth, GLint internal, GLint unpacker); int32 SelectUnpacker(GLcontext context, GLenum format, GLenum type); int32 SelectInternalFormat(GLcontext context, GLenum internalformat); struct W3DtoGL *MGLGetFormatInfo(uint32 w3dFormat); extern GLsizei next_pwr(GLsizei x); extern struct FormatTypeToUnpack ft2u[]; extern struct InternalToW3D i2w3d[]; extern GLboolean MGLTransferImage(GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLpixel_store *srcPs, GLimage_info *dst, GLpixel_store *dstPs, struct GLpixel_state *pixelState); extern GLboolean MGLUnpackImage(GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLimage_info *dst, GLboolean doPixelState); extern GLboolean MGLPackImage(GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLimage_info *dst, GLboolean doPixelState); extern _glPackFn MGLSelectPacker(GLenum format, GLenum type, GLuint *pixelStride); extern _glUnpackFn MGLSelectUnpacker(GLenum format, GLenum type, GLuint *pixelStride); extern float CLAMPF(float a); static ULONG Allocated_Size = 0; static ULONG Peak_Size = 0; void SetBlendStageState(GLcontext context, uint32 stage) { if (context->enable.Texture2D[stage] || context->enable.Texture1D[stage]) { switch (context->texture.TextureEnv[stage]) { case GL_REPLACE: IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, stage, W3D_ENV_MODE, W3D_REPLACE, TAG_DONE); break; case GL_MODULATE: IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, stage, W3D_ENV_MODE, W3D_MODULATE, TAG_DONE); break; case GL_DECAL: IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, stage, W3D_ENV_MODE, W3D_DECAL, TAG_DONE); break; case GL_BLEND: IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, stage, W3D_ENV_MODE, W3D_BLEND, TAG_DONE); break; case GL_ADD: IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, stage, W3D_ENV_MODE, W3D_ADD, TAG_DONE); break; } } else DisableBlendStage(context, stage); } void DisableBlendStage(GLcontext context, uint32 stage) { IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, stage, W3D_ENV_MODE, W3D_OFF, TAG_DONE); } void RebindTextures(GLcontext context) { int i; for (i = 0; i <= context->texture.MaxTextureUnit; i++) { if (context->w3dTextures[context->texture.CurrentBinding[i]].texObj == 0) { dprintf("Warning: rebinding texture that does not exist\n"); IWarp3D->W3D_BindTexture(context->w3dContext, i, context->w3dTextures[context->texture.CurrentBinding[i]].texObj); // Incomplete textures should be rendered as if texturing was disabled IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, i, W3D_ENV_MODE, W3D_ADD, TAG_DONE); } else { IWarp3D->W3D_BindTexture(context->w3dContext, i, context->w3dTextures[context->texture.CurrentBinding[i]].texObj); SetBlendStageState(context, i); } } } void *tex_Alloc(ULONG size, BOOL clear) { ULONG *x; Allocated_Size += size+4; if(clear) { x=(ULONG *)IExec->AllocVec(size+4, MEMF_ANY | MEMF_CLEAR); } else { x=(ULONG *)IExec->AllocVec(size+4, MEMF_ANY); } if (!x) return 0; *x = size; if (Allocated_Size > Peak_Size) Peak_Size = Allocated_Size; return x+1; } void tex_Free(void *chunk) { ULONG *mem = (ULONG *)chunk; mem--; Allocated_Size -= *mem; Allocated_Size -= 4; IExec->FreeVec(mem); } void tex_Statistic(void) { dprintf("Peak Allocation Size: %ld\n", Peak_Size); } void MGLTexMemStat(GLcontext context, GLint *Current, GLint *Peak) { if (Current) *Current = (GLint)Allocated_Size; if (Peak) *Peak = (GLint)Peak_Size; } void cgl_GLDeleteTextures(struct GLContextIFace *Self, GLsizei n, const GLuint *textures) { GLcontext context = GET_INSTANCE(Self); int i; if (!context) return; for (i=0; i 0 && j < context->TexBufferSize) { if (context->w3dTextures[j].texObj) { // Work around a bug in Warp3D (fixed in the meantime) //IWarp3D->W3D_BindTexture(context->w3dContext, j, NULL); IWarp3D->W3D_FreeTexObj(context->w3dContext, context->w3dTextures[j].texObj); context->w3dTextures[j].texObj = NULL; } if (context->w3dTextures[j].texData) { tex_Free(context->w3dTextures[j].texData); context->w3dTextures[j].texData = NULL; } context->GeneratedTextures[j] = 0; } } } void cgl_GLGenTextures(struct GLContextIFace *Self, GLsizei n, GLuint *textures) { GLcontext context = GET_INSTANCE(Self); int i,j; j = 1; for (i=0; iTexBufferSize) { if (context->GeneratedTextures[j] == 0) break; j++; } // If we get here, we found one, or there's noting available. Flag an error in that case.. if (j == context->TexBufferSize) { GLFlagError(context, j == context->TexBufferSize, GL_INVALID_OPERATION); return; } // Insert the texture in the output array, and flag it as used internally *textures = j; context->GeneratedTextures[j] = 1; textures++; j++; } } void tex_FreeTextures(GLcontext context) { int i; for (i=0; iTexBufferSize; i++) { if (context->w3dTextures[i].texObj) { IWarp3D->W3D_FreeTexObj(context->w3dContext, context->w3dTextures[i].texObj); context->w3dTextures[i].texObj = NULL; } if (context->w3dTextures[i].texData) { tex_Free(context->w3dTextures[i].texData); context->w3dTextures[i].texData = 0; } } IWarp3D->W3D_FreeAllTexObj(context->w3dContext); } void tex_SetEnv(GLcontext context, GLenum env) { SetBlendStageState(context, context->texture.ActiveTexture); } static ULONG tex_GLFilter2W3D(GLcontext context, GLenum filter) { switch(filter) { case GL_NEAREST: return W3D_NEAREST; case GL_LINEAR: return W3D_LINEAR; case GL_NEAREST_MIPMAP_NEAREST: if (context->NoMipMapping) return W3D_NEAREST; return W3D_NEAREST_MIP_NEAREST; case GL_LINEAR_MIPMAP_NEAREST: if (context->NoMipMapping) return W3D_LINEAR; return W3D_LINEAR_MIP_NEAREST; case GL_NEAREST_MIPMAP_LINEAR: if (context->NoMipMapping) return W3D_NEAREST; return W3D_NEAREST_MIP_LINEAR; case GL_LINEAR_MIPMAP_LINEAR: if (context->NoMipMapping) return W3D_LINEAR; return W3D_LINEAR_MIP_LINEAR; } return 0; } void tex_SetFilter(GLcontext context, GLenum min, GLenum mag) { ULONG minf, magf; W3D_Texture *tex = context->w3dTextures[context->texture.CurrentBinding[ context->texture.ActiveTexture]].texObj; if (!tex) return; minf = tex_GLFilter2W3D(context, min); magf = tex_GLFilter2W3D(context, mag); //kprintf("Setting MinFilter %s, MagFilter %s\n", filters[minf-1], filters[magf-1]); IWarp3D->W3D_SetFilter(context->w3dContext, tex, minf, magf); context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].MinFilter = min; context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].MagFilter = mag; } void tex_SetWrap(GLcontext context, GLenum wrap_s, GLenum wrap_t) { ULONG Ws,Wt; W3D_Texture *tex = context->w3dTextures[context->texture.CurrentBinding[ context->texture.ActiveTexture]].texObj; if (!tex) return; if (wrap_s == GL_REPEAT) Ws = W3D_REPEAT; else Ws = W3D_CLAMP; if (wrap_t == GL_REPEAT) Wt = W3D_REPEAT; else Wt = W3D_CLAMP; IWarp3D->W3D_SetWrapMode(context->w3dContext, tex, Ws, Wt, NULL); context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].WrapS = wrap_s; context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].WrapT = wrap_t; } void cgl_GLTexEnvi(struct GLContextIFace *Self, GLenum target, GLenum pname, GLint param) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_TexEnvi(Self, target, pname, param); if(!dl_CompileAndExecuteMode(Self)){ return; } } GLFlagError(context, target != GL_TEXTURE_ENV, GL_INVALID_ENUM); switch(pname) { case GL_TEXTURE_ENV_MODE: GLFlagError(context, param != GL_ADD && param != GL_MODULATE && param != GL_DECAL && param != GL_BLEND && param != GL_REPLACE && param != GL_COMBINE, GL_INVALID_ENUM); context->texture.TextureEnv[context->texture.ActiveTexture] = (GLenum)param; tex_SetEnv(context, param); break; case GL_COMBINE_RGB: GLFlagError(context, param != GL_REPLACE && param != GL_MODULATE && param != GL_ADD && param != GL_ADD_SIGNED && param != GL_INTERPOLATE && param != GL_SUBTRACT && param != GL_DOT3_RGB && param != GL_DOT3_RGBA, GL_INVALID_ENUM); if (context->texture.colorCombine[context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorCombine[context->texture.ActiveTexture] = (GLenum)param; break; case GL_COMBINE_ALPHA: GLFlagError(context, param != GL_REPLACE && param != GL_MODULATE && param != GL_ADD && param != GL_ADD_SIGNED && param != GL_INTERPOLATE && param != GL_SUBTRACT, GL_INVALID_ENUM); if (context->texture.alphaCombine[context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaCombine[context->texture.ActiveTexture] = (GLenum)param; break; case GL_SOURCE0_RGB: GLFlagError(context, param != GL_TEXTURE && param != GL_CONSTANT && param != GL_PRIMARY_COLOR && param != GL_PREVIOUS, GL_INVALID_ENUM); if (context->texture.colorSource[0][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorSource[0][context->texture.ActiveTexture] = (GLenum)param; break; case GL_SOURCE1_RGB: GLFlagError(context, param != GL_TEXTURE && param != GL_CONSTANT && param != GL_PRIMARY_COLOR && param != GL_PREVIOUS, GL_INVALID_ENUM); if (context->texture.colorSource[1][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorSource[1][context->texture.ActiveTexture] = (GLenum)param; break; case GL_SOURCE2_RGB: GLFlagError(context, param != GL_TEXTURE && param != GL_CONSTANT && param != GL_PRIMARY_COLOR && param != GL_PREVIOUS, GL_INVALID_ENUM); if (context->texture.colorSource[2][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorSource[2][context->texture.ActiveTexture] = (GLenum)param; break; case GL_SOURCE0_ALPHA: GLFlagError(context, param != GL_TEXTURE && param != GL_CONSTANT && param != GL_PRIMARY_COLOR && param != GL_PREVIOUS, GL_INVALID_ENUM); if (context->texture.alphaSource[0][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaSource[0][context->texture.ActiveTexture] = (GLenum)param; break; case GL_SOURCE1_ALPHA: GLFlagError(context, param != GL_TEXTURE && param != GL_CONSTANT && param != GL_PRIMARY_COLOR && param != GL_PREVIOUS, GL_INVALID_ENUM); if (context->texture.alphaSource[1][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaSource[1][context->texture.ActiveTexture] = (GLenum)param; break; case GL_SOURCE2_ALPHA: GLFlagError(context, param != GL_TEXTURE && param != GL_CONSTANT && param != GL_PRIMARY_COLOR && param != GL_PREVIOUS, GL_INVALID_ENUM); if (context->texture.alphaSource[2][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaSource[2][context->texture.ActiveTexture] = (GLenum)param; break; case GL_OPERAND0_RGB: GLFlagError(context, param != GL_SRC_COLOR && param != GL_ONE_MINUS_SRC_COLOR && param != GL_SRC_ALPHA && param != GL_ONE_MINUS_SRC_ALPHA, GL_INVALID_ENUM); if (context->texture.colorOperand[0][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorOperand[0][context->texture.ActiveTexture] = (GLenum)param; break; case GL_OPERAND1_RGB: GLFlagError(context, param != GL_SRC_COLOR && param != GL_ONE_MINUS_SRC_COLOR && param != GL_SRC_ALPHA && param != GL_ONE_MINUS_SRC_ALPHA, GL_INVALID_ENUM); if (context->texture.colorOperand[1][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorOperand[1][context->texture.ActiveTexture] = (GLenum)param; break; case GL_OPERAND2_RGB: GLFlagError(context, param != GL_SRC_COLOR && param != GL_ONE_MINUS_SRC_COLOR && param != GL_SRC_ALPHA && param != GL_ONE_MINUS_SRC_ALPHA, GL_INVALID_ENUM); if (context->texture.colorOperand[2][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorOperand[2][context->texture.ActiveTexture] = (GLenum)param; break; case GL_OPERAND0_ALPHA: GLFlagError(context, param != GL_SRC_ALPHA && param != GL_ONE_MINUS_SRC_ALPHA, GL_INVALID_ENUM); if (context->texture.alphaOperand[0][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaOperand[0][context->texture.ActiveTexture] = (GLenum)param; break; case GL_OPERAND1_ALPHA: GLFlagError(context, param != GL_SRC_ALPHA && param != GL_ONE_MINUS_SRC_ALPHA, GL_INVALID_ENUM); if (context->texture.alphaOperand[1][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaOperand[1][context->texture.ActiveTexture] = (GLenum)param; break; case GL_OPERAND2_ALPHA: GLFlagError(context, param != GL_SRC_ALPHA && param != GL_ONE_MINUS_SRC_ALPHA, GL_INVALID_ENUM); if (context->texture.alphaOperand[2][context->texture.ActiveTexture] == (GLenum)param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaOperand[2][context->texture.ActiveTexture] = (GLenum)param; break; case GL_RGB_SCALE: GLFlagError(context, param != 1 && param != 2 && param != 4, GL_INVALID_VALUE); if (context->texture.colorScale[context->texture.ActiveTexture] == param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.colorScale[context->texture.ActiveTexture] = param; break; case GL_ALPHA_SCALE: GLFlagError(context, param != 1 && param != 2 && param != 4, GL_INVALID_VALUE); if (context->texture.alphaScale[context->texture.ActiveTexture] == param) break; context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.alphaScale[context->texture.ActiveTexture] = param; break; default: GLFlagError(context, 1, GL_INVALID_ENUM); } } void cgl_GLTexEnvfv(struct GLContextIFace *Self, GLenum target, GLenum pname, const GLfloat* param) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_TexEnvfv(Self, target, pname, param); if(!dl_CompileAndExecuteMode(Self)){ return; } } GLFlagError(context, target != GL_TEXTURE_ENV, GL_INVALID_ENUM); switch (pname) { case GL_TEXTURE_ENV_COLOR: context->combineDirty[context->texture.ActiveTexture] = GL_TRUE; context->texture.envColor[context->texture.ActiveTexture].r = CLAMPF(param[0]); context->texture.envColor[context->texture.ActiveTexture].g = CLAMPF(param[1]); context->texture.envColor[context->texture.ActiveTexture].b = CLAMPF(param[2]); context->texture.envColor[context->texture.ActiveTexture].a = CLAMPF(param[3]); break; default: Self->GLTexEnvi(target, pname, (GLint)param[0]); break; } } void cgl_GLGetTexEnviv(struct GLContextIFace *Self, GLenum target, GLenum pname, GLint* params) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, target != GL_TEXTURE_ENV, GL_INVALID_ENUM); #define FROM_BOOL(x) (GLint)((x) ? 1 : 0) #define FROM_COLOR(x) (GLint)((0xffffffff * (x) - 1)/2) #define FROM_FLOAT(x) (GLint)(x) #define FROM_INT(x) (x) switch (pname) { case GL_TEXTURE_ENV_MODE: params[0] = FROM_INT(context->texture.TextureEnv[context->texture.ActiveTexture]); break; case GL_TEXTURE_ENV_COLOR: params[0] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].r); params[1] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].g); params[2] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].b); params[3] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].a); break; case GL_COMBINE_RGB: params[0] = FROM_INT(context->texture.colorCombine[context->texture.ActiveTexture]); break; case GL_COMBINE_ALPHA: params[0] = FROM_INT(context->texture.alphaCombine[context->texture.ActiveTexture]); break; case GL_SOURCE0_RGB: params[0] = FROM_INT(context->texture.colorSource[0][context->texture.ActiveTexture]); break; case GL_SOURCE1_RGB: params[0] = FROM_INT(context->texture.colorSource[1][context->texture.ActiveTexture]); break; case GL_SOURCE2_RGB: params[0] = FROM_INT(context->texture.colorSource[2][context->texture.ActiveTexture]); break; case GL_SOURCE0_ALPHA: params[0] = FROM_INT(context->texture.alphaSource[0][context->texture.ActiveTexture]); break; case GL_SOURCE1_ALPHA: params[0] = FROM_INT(context->texture.alphaSource[1][context->texture.ActiveTexture]); break; case GL_SOURCE2_ALPHA: params[0] = FROM_INT(context->texture.alphaSource[2][context->texture.ActiveTexture]); break; case GL_OPERAND0_RGB: params[0] = FROM_INT(context->texture.colorOperand[0][context->texture.ActiveTexture]); break; case GL_OPERAND1_RGB: params[0] = FROM_INT(context->texture.colorOperand[1][context->texture.ActiveTexture]); break; case GL_OPERAND2_RGB: params[0] = FROM_INT(context->texture.colorOperand[2][context->texture.ActiveTexture]); break; case GL_OPERAND0_ALPHA: params[0] = FROM_INT(context->texture.alphaOperand[0][context->texture.ActiveTexture]); break; case GL_OPERAND1_ALPHA: params[0] = FROM_INT(context->texture.alphaOperand[1][context->texture.ActiveTexture]); break; case GL_OPERAND2_ALPHA: params[0] = FROM_INT(context->texture.alphaOperand[2][context->texture.ActiveTexture]); break; case GL_RGB_SCALE: params[0] = FROM_INT(context->texture.colorScale[context->texture.ActiveTexture]); break; case GL_ALPHA_SCALE: params[0] = FROM_INT(context->texture.alphaScale[context->texture.ActiveTexture]); break; default: GLFlagError(context, 1, GL_INVALID_ENUM); break; } #undef FROM_BOOL(x) #undef FROM_COLOR(x) #undef FROM_FLOAT(x) #undef FROM_INT(x) } void cgl_GLGetTexEnvfv(struct GLContextIFace* Self, GLenum target, GLenum pname, GLfloat* params) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, target != GL_TEXTURE_ENV, GL_INVALID_ENUM); #define FROM_BOOL(x) (GLfloat)((x) ? 1.0f : 0.0f) #define FROM_COLOR(x) (GLfloat)(x) #define FROM_FLOAT(x) (x) #define FROM_INT(x) (GLfloat)(x) switch (pname) { case GL_TEXTURE_ENV_MODE: params[0] = FROM_INT(context->texture.TextureEnv[context->texture.ActiveTexture]); break; case GL_TEXTURE_ENV_COLOR: params[0] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].r); params[1] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].g); params[2] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].b); params[3] = FROM_COLOR(context->texture.envColor[context->texture.ActiveTexture].a); break; case GL_COMBINE_RGB: params[0] = FROM_INT(context->texture.colorCombine[context->texture.ActiveTexture]); break; case GL_COMBINE_ALPHA: params[0] = FROM_INT(context->texture.alphaCombine[context->texture.ActiveTexture]); break; case GL_SOURCE0_RGB: params[0] = FROM_INT(context->texture.colorSource[0][context->texture.ActiveTexture]); break; case GL_SOURCE1_RGB: params[0] = FROM_INT(context->texture.colorSource[1][context->texture.ActiveTexture]); break; case GL_SOURCE2_RGB: params[0] = FROM_INT(context->texture.colorSource[2][context->texture.ActiveTexture]); break; case GL_SOURCE0_ALPHA: params[0] = FROM_INT(context->texture.alphaSource[0][context->texture.ActiveTexture]); break; case GL_SOURCE1_ALPHA: params[0] = FROM_INT(context->texture.alphaSource[1][context->texture.ActiveTexture]); break; case GL_SOURCE2_ALPHA: params[0] = FROM_INT(context->texture.alphaSource[2][context->texture.ActiveTexture]); break; case GL_OPERAND0_RGB: params[0] = FROM_INT(context->texture.colorOperand[0][context->texture.ActiveTexture]); break; case GL_OPERAND1_RGB: params[0] = FROM_INT(context->texture.colorOperand[1][context->texture.ActiveTexture]); break; case GL_OPERAND2_RGB: params[0] = FROM_INT(context->texture.colorOperand[2][context->texture.ActiveTexture]); break; case GL_OPERAND0_ALPHA: params[0] = FROM_INT(context->texture.alphaOperand[0][context->texture.ActiveTexture]); break; case GL_OPERAND1_ALPHA: params[0] = FROM_INT(context->texture.alphaOperand[1][context->texture.ActiveTexture]); break; case GL_OPERAND2_ALPHA: params[0] = FROM_INT(context->texture.alphaOperand[2][context->texture.ActiveTexture]); break; case GL_RGB_SCALE: params[0] = FROM_INT(context->texture.colorScale[context->texture.ActiveTexture]); break; case GL_ALPHA_SCALE: params[0] = FROM_INT(context->texture.alphaScale[context->texture.ActiveTexture]); break; default: GLFlagError(context, 1, GL_INVALID_ENUM); break; } #undef FROM_BOOL(x) #undef FROM_COLOR(x) #undef FROM_FLOAT(x) #undef FROM_INT(x) } void cgl_GLTexParameteri(struct GLContextIFace *Self, GLenum target, GLenum pname, GLint param) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_TexParameteri(Self, target, pname, param); if(!dl_CompileAndExecuteMode(Self)){ return; } } GLenum min, mag; GLenum wraps, wrapt; switch(pname) { case GL_TEXTURE_MIN_FILTER: mag = context->texture.MagFilter; tex_SetFilter(context, (GLenum)param, mag); context->texture.MinFilter = (GLenum)param; break; case GL_TEXTURE_MAG_FILTER: min = context->texture.MinFilter; tex_SetFilter(context, min, (GLenum)param); context->texture.MagFilter = (GLenum)param; break; case GL_TEXTURE_WRAP_S: wrapt = context->texture.WrapT; tex_SetWrap(context, (GLenum)param, wrapt); context->texture.WrapS = (GLenum)param; break; case GL_TEXTURE_WRAP_T: wraps = context->texture.WrapS; tex_SetWrap(context, wraps, (GLenum)param); context->texture.WrapT = (GLenum)param; break; default: GLFlagError(context, 1, GL_INVALID_ENUM); } } void cgl_GLTexParameterfv(struct GLContextIFace *Self, GLenum target, GLenum pname, GLfloat *param) { Self->GLTexParameteri(target, pname, (GLint)param[0]); } void cgl_GLTexParameteriv(struct GLContextIFace *Self, GLenum target, GLenum pname, GLint *param) { Self->GLTexParameteri(target, pname, param[0]); } void cgl_GLBindTexture(struct GLContextIFace *Self, GLenum target, GLuint texture) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_BindTexture(Self, target, texture); if(!dl_CompileAndExecuteMode(Self)){ return; } } if (!context) return; GLFlagError(context, target != GL_TEXTURE_2D && target != GL_TEXTURE_1D, GL_INVALID_ENUM); GLFlagError(context, texture >= context->TexBufferSize, GL_INVALID_OPERATION); context->texture.CurrentBinding[context->texture.ActiveTexture] = texture; if (context->w3dTextures[context->texture.CurrentBinding[ context->texture.ActiveTexture]].texObj == NULL) { IWarp3D->W3D_BindTexture(context->w3dContext, context->texture.ActiveTexture, context->w3dTextures[context->texture.CurrentBinding[ context->texture.ActiveTexture]].texObj); // Incomplete textures should be rendered as if texturing was disabled IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, context->texture.ActiveTexture, W3D_ENV_MODE, W3D_ADD, TAG_DONE); } else { IWarp3D->W3D_BindTexture(context->w3dContext, context->texture.ActiveTexture, context->w3dTextures[context->texture.CurrentBinding[ context->texture.ActiveTexture]].texObj); SetBlendStageState(context, context->texture.ActiveTexture); } } void GLTexImage2DNoMIP(GLcontext context, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static void UpdateTexImage(GLcontext context, int texnum, void *image, int level, ULONG *pal) { IWarp3D->W3D_UpdateTexImage(context->w3dContext, context->w3dTextures[texnum].texObj, image, level, pal); /* Rebind the currently bound textures, just in case the current one hasn't * been bound before */ RebindTextures(context); } static void UpdateTexSubImage(GLcontext context, int texnum, void *image, int level, ULONG *pal, int x, int y, int width, int height, int bytesPerRow) { GLboolean relock = GL_FALSE; // for manual locking mode only if (context->w3dLocked == GL_TRUE) { switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_forceUnlock(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_UnLockHardware(context->w3dContext); relock = GL_TRUE; context->w3dLocked = GL_FALSE; break; } } W3D_Scissor scissor = {x, y, width, height}; IWarp3D->W3D_UpdateTexSubImage(context->w3dContext, context->w3dTextures[texnum].texObj, image, level, pal, &scissor, bytesPerRow); if(relock) { IWarp3D->W3D_LockHardware(context->w3dContext); context->w3dLocked = GL_TRUE; } /* Rebind the currently bound textures, just in case the current one hasn't * been bound before */ RebindTextures(context); } static uint32 MGLCalculateMipArray(uint32 width, uint32 height, uint32 bpp, GLubyte *mipmaps[]) { int level = 0; uint32 res = width * height * bpp; int i; for (i = 0; i < 20; i++) mipmaps[i] = (GLubyte *)0xffffffff; mipmaps[level++] = (GLubyte *)res; do { if (width > 1) width /= 2; if (height > 1) height /= 2; res += width * height * bpp; mipmaps[level++] = (GLubyte *)res; if (width == 1 && height == 1) break; } while (1); return res; } void cgl_GLTexImage2D(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { GLcontext context = GET_INSTANCE(Self); if(gltarget != GL_PROXY_TEXTURE_2D && dl_IsDLActive(Self)){ dl_save_TexImage2D(Self, gltarget, level, internalformat, width, height, border, format, type, pixels); if(!dl_CompileAndExecuteMode(Self)){ return; } } int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; ULONG w,h; ULONG targetsize; ULONG error; UBYTE *target; ULONG useFormat; int32 internal = SelectInternalFormat(context, internalformat); int32 unpacker = SelectUnpacker(context, format, type); /* Handle GL_PROXY_TEXTURE_2D */ if (gltarget == GL_PROXY_TEXTURE_2D) { extern struct InternalToW3D i2w3d[]; context->proxy_width = width << level; context->proxy_height = height << level; if (internal == -1) context->proxy_internalFormat = -1; else context->proxy_internalFormat = i2w3d[internal].internalformat; return; } if (context->NoMipMapping == GL_TRUE) { GLTexImage2DNoMIP(context, gltarget, level, internalformat, width, height, border, format, type, pixels); return; } GLFlagError(context, internal == -1 || unpacker == -1, GL_INVALID_OPERATION); GLFlagError(context, gltarget != GL_TEXTURE_2D && gltarget != GL_PROXY_TEXTURE_2D, GL_INVALID_ENUM); /* ** We will use width and height only when the mipmap level ** is really 0. Otherwise, we need to upscale the values ** according to the level. ** ** Note this will most likely be difficult with non-square ** textures, as the first side to reach one will remain ** there. For example, consider the sequence ** 8x4, 4x2, 2x1, 1x1 ** 0 1 2 3 ** If the 1x1 mipmap is given, upscaling will yield 8x8, not 8x4 */ if (context->w3dTextures[current].texObj == NULL) { w=(ULONG)width<w3dTextures[current].texObj->texwidth; h = context->w3dTextures[current].texObj->texheight; if (w != (width<W3D_FreeTexObj(context->w3dContext, context->w3dTextures[current].texObj); context->w3dTextures[current].texObj = NULL; // dprintf("texture size change detected (%ldx%ld -> %ldx%ld)\n", // w, h, width<w3dTextures[current].texObj == NULL) { int i; /* ** Create a new texture object ** Get the memory */ targetsize = MGLCalculateMipArray(w, h, i2w3d[internal].w3dBpp, context->w3dTextures[current].mipmaps); if (context->w3dTextures[current].texData) tex_Free(context->w3dTextures[current].texData); context->w3dTextures[current].texData = (GLubyte *)tex_Alloc(targetsize, (pixels ? FALSE : TRUE)); context->w3dTextures[current].internalFormat = internalformat; // dprintf("(re)allocated texData at %p-%p (%ldx%ldx%ld = %ld bytes)\n", context->w3dTextures[current].texData, context->w3dTextures[current].texData + targetsize - 1, w, h, i2w3d[internal].w3dBpp, targetsize); /* Fixup mipmaps */ for (i = 0; i < 20; i++) { if (context->w3dTextures[current].mipmaps[i] != (GLubyte *)0xffffffff) context->w3dTextures[current].mipmaps[i] = (GLubyte *)((uint32)context->w3dTextures[current].mipmaps[i] + (uint32)context->w3dTextures[current].texData); else context->w3dTextures[current].mipmaps[i] = 0; } if (!context->w3dTextures[current].texData) return; } /* ** Find the starting address for the given mipmap level in the ** texture memory area */ if (level == 0) target = context->w3dTextures[current].texData; else target = context->w3dTextures[current].mipmaps[level-1]; // dprintf("Mipmap %ld at %p\n", level, target); /* ** Convert the data to the target address */ if(pixels) { useFormat = MGLConvert(context, internalformat, width, height, format, type, (GLubyte *)pixels, (GLubyte *)target); } else { useFormat = i2w3d[internal].w3dFormat; } /* ** Create a new W3D_Texture if none was present, using the converted ** data. ** Otherwise, call W3D_UpdateTexImage */ if (context->w3dTextures[current].texObj == NULL) { context->w3dTextures[current].texObj = IWarp3D->W3D_AllocTexObjTags(context->w3dContext, &error, W3D_ATO_IMAGE, context->w3dTextures[current].texData, W3D_ATO_FORMAT, useFormat, W3D_ATO_WIDTH, w, W3D_ATO_HEIGHT, h, W3D_ATO_MIPMAP, 0, W3D_ATO_MIPMAPPTRS, context->w3dTextures[current].mipmaps, TAG_DONE); if (context->w3dTextures[current].texObj == NULL || error != W3D_SUCCESS) return; // dprintf("Allocated new texture object %p (%ldx%ld)\n", context->w3dTextures[current].texObj, w, h); RebindTextures(context); /* ** Set the appropriate wrap modes, texture env, and filters */ tex_SetWrap(context, context->texture.WrapS, context->texture.WrapT); tex_SetFilter(context, context->texture.MinFilter, context->texture.MagFilter); tex_SetEnv(context, context->texture.TextureEnv[context->texture.ActiveTexture]); } else { UpdateTexImage(context, current, target, level, NULL); } } void GLTexImage2DNoMIP(GLcontext context, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; ULONG w,h; ULONG targetsize; ULONG error; UBYTE *target; ULONG useFormat; int32 internal = SelectInternalFormat(context, internalformat); int32 unpacker = SelectUnpacker(context, format, type); //LOG(3, glTexImage2DNoMIP, "target = %d level=%d, size=%d×%d", gltarget, level, width, height); GLFlagError(context, internal == -1 || unpacker == -1, GL_INVALID_OPERATION); GLFlagError(context, gltarget != GL_TEXTURE_2D, GL_INVALID_ENUM); if (level != 0) return; w = (ULONG)width; h = (ULONG)height; if (context->w3dTextures[current].texObj && (w != context->w3dTextures[current].texObj->texwidth || h != context->w3dTextures[current].texObj->texheight)) { dprintf("texture size change detected (%ldx%ld -> %ldx%ld)\n", w, h, context->w3dTextures[current].texObj->texwidth, context->w3dTextures[current].texObj->texheight); IWarp3D->W3D_FreeTexObj(context->w3dContext, context->w3dTextures[current].texObj); context->w3dTextures[current].texObj = NULL; } if (context->w3dTextures[current].texObj == NULL) { /* ** Create a new texture object ** Get the memory */ targetsize = (w * h * i2w3d[internal].w3dBpp); if (context->w3dTextures[current].texData) tex_Free(context->w3dTextures[current].texData); context->w3dTextures[current].texData = (GLubyte *)tex_Alloc(targetsize, (pixels ? FALSE : TRUE)); if (!context->w3dTextures[current].texData) return; context->w3dTextures[current].internalFormat = internalformat; } target = context->w3dTextures[current].texData; /* ** Convert the data to the target address */ if(pixels) { useFormat = MGLConvert(context, internalformat, width, height, format, type, (GLubyte *)pixels, (GLubyte *)target); } else { useFormat = i2w3d[internal].w3dFormat; } /* ** Create a new W3D_Texture if none was present, using the converted ** data. ** Otherwise, call W3D_UpdateTexImage */ if (context->w3dTextures[current].texObj == NULL) { int i; W3D_Texture *tex; tex = IWarp3D->W3D_AllocTexObjTags(context->w3dContext, &error, W3D_ATO_IMAGE, context->w3dTextures[current].texData, W3D_ATO_FORMAT, useFormat, W3D_ATO_WIDTH, w, W3D_ATO_HEIGHT, h, TAG_DONE); if (tex == NULL || error != W3D_SUCCESS) return; context->w3dTextures[current].texObj = tex; context->w3dTextures[current].mipmaps[0] = target; for (i = 1; i < 20; i++) context->w3dTextures[current].mipmaps[i] = 0; /* ** Set the appropriate wrap modes, texture env, and filters */ RebindTextures(context); tex_SetWrap(context, context->texture.WrapS, context->texture.WrapT); tex_SetFilter(context, context->texture.MinFilter, context->texture.MagFilter); tex_SetEnv(context, context->texture.TextureEnv[context->texture.ActiveTexture]); } else { UpdateTexImage(context, current, target, level, NULL); } } void cgl_GLTexImage1D(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { // Faking 1D textures using 2D textures // WARNING: This assumes that Warp3D doesn't support texture borders. If this changes, then so must this // function /*if(gltarget != GL_PROXY_TEXTURE_2D && dl_IsDLActive(Self)){ dl_save_TexImage1D(Self, gltarget, level, internalformat, width, border, format, type, pixels); if(!dl_CompileAndExecuteMode(Self)){ return; } }*/ cgl_GLTexImage2D(Self, GL_TEXTURE_2D, level, internalformat, width, 1, border, format, type, pixels); // The vertical direction should always be repeated cgl_GLTexParameteri(Self, gltarget, GL_TEXTURE_WRAP_T, GL_REPEAT); } void GLTexSubImage2DNoMIP(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); #define max(x,y) (x) > (y) ? (x) : (y) void cgl_GLTexSubImage2D(struct GLContextIFace *Self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_TexSubImage2D(Self, target, level, xoffset, yoffset, width, height, format, type, pixels); if(!dl_CompileAndExecuteMode(Self)){ return; } } int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; GLubyte *dest; int internal = SelectInternalFormat(context, context->w3dTextures[current].internalFormat); int unpacker = SelectUnpacker(context, format, type); // if (context->NoMipMapping == GL_TRUE) { GLTexSubImage2DNoMIP(context, target, level, xoffset, yoffset, width, height, format, type, (void *)pixels); return; } GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM); GLFlagError(context, context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].texObj == NULL, GL_INVALID_OPERATION); GLFlagError(context, context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].mipmaps[level] == 0, GL_INVALID_OPERATION); GLFlagError(context, unpacker == -1, GL_INVALID_ENUM); dest = context->w3dTextures[current].mipmaps[level]; MGLUpdate(context, xoffset, yoffset, width, height, (GLubyte *)pixels, dest, max(1,context->w3dTextures[current].texObj->texwidth >> level), internal, unpacker); UpdateTexImage(context, current, context->w3dTextures[current].texData, 0, NULL); } void GLTexSubImage2DNoMIP(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; GLubyte *dest; int internal = SelectInternalFormat(context, context->w3dTextures[current].internalFormat); int unpacker = SelectUnpacker(context, format, type); GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM); GLFlagError(context, context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].texObj == NULL, GL_INVALID_OPERATION); GLFlagError(context, level != 0, GL_INVALID_OPERATION); GLFlagError(context, unpacker == -1, GL_INVALID_ENUM); dest = context->w3dTextures[current].texData; MGLUpdate(context, xoffset, yoffset, width, height, pixels, dest, context->w3dTextures[current].texObj->texwidth, internal, unpacker); UpdateTexImage(context, current, context->w3dTextures[current].texData, 0, NULL); } void cgl_GLTexSubImage1D(struct GLContextIFace *Self, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) { // Faking 1D textures using 2D textures /*if(dl_IsDLActive(Self)){ dl_save_TexSubImage1D(Self, target, level, xoffset, width, format, type, pixels); if(!dl_CompileAndExecuteMode(Self)){ return; } }*/ cgl_GLTexSubImage2D(Self, GL_TEXTURE_2D, level, xoffset, 0, width,1, format, type, pixels); // The vertical direction should always be repeated cgl_GLTexParameteri(Self, target, GL_TEXTURE_WRAP_T, GL_REPEAT); } static RGBFTYPE getP96Format(GLenum internalFormat); // returns bytes per row, or 0 if failed static int p96CopyBMToTex(GLcontext context, GLint srcXOffset, GLint srcYOffset, GLint destXOffset, GLint destYOffset, GLsizei width, GLsizei height, struct BitMap *source, GLubyte *dest, GLsizei destWidth, RGBFTYPE destFormat); void GLCopyTexImage2DNoMIP(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); void cgl_GLCopyTexImage2D(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_CopyTexImage2D(Self, gltarget, level, internalFormat, x, y, width, height, border); if(!dl_CompileAndExecuteMode(Self)){ return; } } GLFlagError(context, gltarget != GL_TEXTURE_2D && gltarget != GL_PROXY_TEXTURE_2D, GL_INVALID_ENUM); // Prepare for the copy GLFlagError(context, width < 0, GL_INVALID_VALUE); GLFlagError(context, height < 0, GL_INVALID_VALUE); struct BitMap *inputBitMap = context->readBuffer->bitMap; if(!inputBitMap) { return; } if (context->NoMipMapping == GL_TRUE) { GLCopyTexImage2DNoMIP(Self, gltarget, level, internalFormat, x, y, width, height, border); return; } GLsizei rw = next_pwr(width); GLsizei rh = next_pwr(height); uint32 maxTextureSize = IWarp3D->W3D_Query(context->w3dContext, W3D_Q_MAXTEXWIDTH, 0); uint32 texWidthReal = min(maxTextureSize, rw); uint32 texHeightReal = min(maxTextureSize, rh); uint32 ibmWidth = IGraphics->GetBitMapAttr(inputBitMap, BMA_WIDTH); uint32 ibmHeight = IGraphics->GetBitMapAttr(inputBitMap, BMA_HEIGHT); if(x + width > ibmWidth) { width = ibmWidth - x; } if(y + height > ibmHeight) { height = ibmHeight - y; } if(width > texWidthReal) { width = texWidthReal; } if(height > texHeightReal) { height = texHeightReal; } int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; ULONG w,h; ULONG targetsize; ULONG error; UBYTE *target; GLuint src_pixel_stride; int32 internal = SelectInternalFormat(context, internalFormat); RGBFTYPE p96Format = getP96Format(internalFormat); ULONG useFormat = i2w3d[internal].w3dFormat; GLFlagError(context, internal == -1, GL_INVALID_OPERATION); /* ** We will use width and height only when the mipmap level ** is really 0. Otherwise, we need to upscale the values ** according to the level. ** ** Note this will most likely be difficult with non-square ** textures, as the first side to reach one will remain ** there. For example, consider the sequence ** 8x4, 4x2, 2x1, 1x1 ** 0 1 2 3 ** If the 1x1 mipmap is given, upscaling will yield 8x8, not 8x4 */ if (context->w3dTextures[current].texObj == NULL) { w=(ULONG)texWidthReal<w3dTextures[current].texObj->texwidth; h = context->w3dTextures[current].texObj->texheight; if (w != (texWidthReal<W3D_FreeTexObj(context->w3dContext, context->w3dTextures[current].texObj); context->w3dTextures[current].texObj = NULL; } w=(ULONG)texWidthReal<w3dTextures[current].texObj == NULL) { int i; /* ** Create a new texture object ** Get the memory */ targetsize = MGLCalculateMipArray(w, h, i2w3d[internal].w3dBpp, context->w3dTextures[current].mipmaps); if (context->w3dTextures[current].texData) tex_Free(context->w3dTextures[current].texData); context->w3dTextures[current].texData = (GLubyte *)tex_Alloc(targetsize, FALSE); context->w3dTextures[current].internalFormat = internalFormat; /* Fixup mipmaps */ for (i = 0; i < 20; i++) { if (context->w3dTextures[current].mipmaps[i] != (GLubyte *)0xffffffff) context->w3dTextures[current].mipmaps[i] = (GLubyte *)((uint32)context->w3dTextures[current].mipmaps[i] + (uint32)context->w3dTextures[current].texData); else context->w3dTextures[current].mipmaps[i] = 0; } if (!context->w3dTextures[current].texData) return; } /* ** Find the starting address for the given mipmap level in the ** texture memory area */ if (level == 0) target = context->w3dTextures[current].texData; else target = context->w3dTextures[current].mipmaps[level-1]; // ----------------------------------------------------------------------------------- /*struct RenderInfo { APTR Memory; WORD BytesPerRow; WORD pad; RGBFTYPE RGBFormat; };*/ // Copy/convert the image data from the screen buffer // ##### FIXME! ##### What about GL_DEPTH_COMPONENT and GL_STENCIL_INDEX //GLboolean MGLUnpackImage(GLcontext context, GLsizei width, GLsizei height, // GLimage_info *src, GLimage_info *dst, GLboolean doPixelState) // ##### FIXME! ##### // Discover the rendered image's format GLenum sourceFormat; // ##### FIXME! ##### if(sourceFormat == internalFormat) { // copy straight into the texture's memory // ##### FIXME! ##### ReadPixelArray() } else { // Read to an intermediate buffer and convert from there // ##### FIXME! ##### ReadPixelArray() } // ----------------------------------------------------------------------------------- /* ** Create a new W3D_Texture if none was present, using the converted ** data. ** Otherwise, call W3D_UpdateTexImage */ if (context->w3dTextures[current].texObj == NULL) { context->w3dTextures[current].texObj = IWarp3D->W3D_AllocTexObjTags(context->w3dContext, &error, W3D_ATO_IMAGE, context->w3dTextures[current].texData, W3D_ATO_FORMAT, useFormat, W3D_ATO_WIDTH, w, W3D_ATO_HEIGHT, h, W3D_ATO_MIPMAP, 0, W3D_ATO_MIPMAPPTRS, context->w3dTextures[current].mipmaps, TAG_DONE); if (context->w3dTextures[current].texObj == NULL || error != W3D_SUCCESS) return; // dprintf("Allocated new texture object %p (%ldx%ld)\n", context->w3dTextures[current].texObj, w, h); RebindTextures(context); /* ** Set the appropriate wrap modes, texture env, and filters */ tex_SetWrap(context, context->texture.WrapS, context->texture.WrapT); tex_SetFilter(context, context->texture.MinFilter, context->texture.MagFilter); tex_SetEnv(context, context->texture.TextureEnv[context->texture.ActiveTexture]); } else { UpdateTexImage(context, current, target, level, NULL); } } void GLCopyTexImage2DNoMIP(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, gltarget != GL_TEXTURE_2D, GL_INVALID_ENUM); struct BitMap *inputBitMap = context->readBuffer->bitMap; if(!inputBitMap) { return; } int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; ULONG w,h; ULONG targetsize; ULONG error; UBYTE *target; GLuint src_pixel_stride; int32 internal = SelectInternalFormat(context, internalFormat); RGBFTYPE p96Format = getP96Format(internalFormat); ULONG useFormat = i2w3d[internal].w3dFormat; GLFlagError(context, internal == -1, GL_INVALID_OPERATION); GLsizei rw = next_pwr(width); GLsizei rh = next_pwr(height); uint32 maxTextureSize = IWarp3D->W3D_Query(context->w3dContext, W3D_Q_MAXTEXWIDTH, 0); uint32 texWidthReal = min(maxTextureSize, rw); uint32 texHeightReal = min(maxTextureSize, rh); uint32 ibmWidth = IGraphics->GetBitMapAttr(inputBitMap, BMA_WIDTH); uint32 ibmHeight = IGraphics->GetBitMapAttr(inputBitMap, BMA_HEIGHT); if(x + width > ibmWidth) { width = ibmWidth - x; } if(y + height > ibmHeight) { height = ibmHeight - y; } if(width > texWidthReal) { width = texWidthReal; } if(height > texHeightReal) { height = texHeightReal; } if (level != 0) return; w = (ULONG)texWidthReal; h = (ULONG)texHeightReal; if (context->w3dTextures[current].texObj && (w != context->w3dTextures[current].texObj->texwidth || h != context->w3dTextures[current].texObj->texheight)) { dprintf("texture size change detected (%ldx%ld -> %ldx%ld)\n", w, h, context->w3dTextures[current].texObj->texwidth, context->w3dTextures[current].texObj->texheight); IWarp3D->W3D_FreeTexObj(context->w3dContext, context->w3dTextures[current].texObj); context->w3dTextures[current].texObj = NULL; } if (context->w3dTextures[current].texObj == NULL) { /* ** Create a new texture object ** Get the memory */ targetsize = (w * h * i2w3d[internal].w3dBpp); if (context->w3dTextures[current].texData) tex_Free(context->w3dTextures[current].texData); context->w3dTextures[current].texData = (GLubyte *)tex_Alloc(targetsize, FALSE); if (!context->w3dTextures[current].texData) return; context->w3dTextures[current].internalFormat = internalFormat; } target = context->w3dTextures[current].texData; // ------------------------------------------------------------------ // Copy/convert the data // useFormat = // ##### FIXME! ##### // Now perform color scale and bias // ##### FIXME! ##### // ------------------------------------------------------------------ /* ** Create a new W3D_Texture if none was present, using the converted ** data. ** Otherwise, call W3D_UpdateTexImage */ if (context->w3dTextures[current].texObj == NULL) { int i; W3D_Texture *tex; tex = IWarp3D->W3D_AllocTexObjTags(context->w3dContext, &error, W3D_ATO_IMAGE, context->w3dTextures[current].texData, W3D_ATO_FORMAT, useFormat, W3D_ATO_WIDTH, w, W3D_ATO_HEIGHT, h, TAG_DONE); if (tex == NULL || error != W3D_SUCCESS) return; context->w3dTextures[current].texObj = tex; context->w3dTextures[current].mipmaps[0] = target; for (i = 1; i < 20; i++) context->w3dTextures[current].mipmaps[i] = 0; /* ** Set the appropriate wrap modes, texture env, and filters */ RebindTextures(context); tex_SetWrap(context, context->texture.WrapS, context->texture.WrapT); tex_SetFilter(context, context->texture.MinFilter, context->texture.MagFilter); tex_SetEnv(context, context->texture.TextureEnv[context->texture.ActiveTexture]); } else { UpdateTexImage(context, current, target, level, NULL); } } void cgl_GLCopyTexImage1D(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border) { // Faking 1D textures using 2D textures // WARNING: This assumes that Warp3D doesn't support texture borders. If this changes, then so must this // function /*if(dl_IsDLActive(Self)){ dl_save_CopyTexImage1D(Self, gltarget, level, internalFormat, x, y, width, border); if(!dl_CompileAndExecuteMode(Self)){ return; } }*/ cgl_GLCopyTexImage2D(Self, GL_TEXTURE_2D, level, internalFormat, x, y, width, 1, border); // The vertical direction should always be repeated cgl_GLTexParameteri(Self, gltarget, GL_TEXTURE_WRAP_T, GL_REPEAT); } void GLCopyTexSubImage2DNoMIP(struct GLContextIFace *Self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); void cgl_GLCopyTexSubImage2D(struct GLContextIFace *Self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_CopyTexSubImage2D(Self, target, level, xoffset, yoffset, x, y, width, height); if(!dl_CompileAndExecuteMode(Self)){ return; } } int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; GLubyte *dest; GLenum internalFormat = context->w3dTextures[current].internalFormat; int internal = SelectInternalFormat(context, internalFormat); RGBFTYPE p96Format = getP96Format(internalFormat); // if (context->NoMipMapping == GL_TRUE) { GLCopyTexSubImage2DNoMIP(Self, target, level, xoffset, yoffset, x, y, width, height); return; } struct BitMap *inputBitMap = context->readBuffer->bitMap; if(!inputBitMap) { return; } uint32 ibmWidth = IGraphics->GetBitMapAttr(inputBitMap, BMA_WIDTH); uint32 ibmHeight = IGraphics->GetBitMapAttr(inputBitMap, BMA_HEIGHT); if(x + width > ibmWidth) { width = ibmWidth - x; } if(y + height > ibmHeight) { height = ibmHeight - y; } GLint texWidth = max(1,context->w3dTextures[current].texObj->texwidth >> level); GLint texHeight = max(1,context->w3dTextures[current].texObj->texheight >> level); if(xoffset + width > texWidth) { width = texWidth - xoffset; } if(yoffset + height > texHeight) { height = texHeight - yoffset; } GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM); GLFlagError(context, context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].texObj == NULL, GL_INVALID_OPERATION); GLFlagError(context, context->w3dTextures[context->texture.CurrentBinding[context->texture.ActiveTexture]].mipmaps[level] == 0, GL_INVALID_OPERATION); dest = context->w3dTextures[current].mipmaps[level]; // ---------------------------------------------------------------------------------- int bytesPerRow; if(p96Format != RGBFB_NONE) { // The texture data can be copied directly into the texture's buffer using Picasso96 bytesPerRow = p96CopyBMToTex(context, x, y, xoffset, yoffset, width, height, inputBitMap, dest, texWidth, p96Format); } else { bytesPerRow = 0; // Will need to do a pixel format conversion // ##### FIXME! ##### } //MGLUpdate(context, xoffset, yoffset, width, height, (GLubyte *)pixels, dest, // max(1,context->w3dTextures[current].texObj->texwidth >> level), // internal, unpacker); // Now perform color scale and bias // ##### FIXME! ##### // ##### FIXME! ##### what about glPixelZoom? // ---------------------------------------------------------------------------------- if(bytesPerRow) { //UpdateTexImage(context, current, context->w3dTextures[current].texData, 0, NULL); UpdateTexSubImage(context, current, context->w3dTextures[current].texData, 0, NULL, xoffset, yoffset, width, height, bytesPerRow); } } void GLCopyTexSubImage2DNoMIP(struct GLContextIFace *Self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { GLcontext context = GET_INSTANCE(Self); struct BitMap *inputBitMap = context->readBuffer->bitMap; if(!inputBitMap) { return; } uint32 ibmWidth = IGraphics->GetBitMapAttr(inputBitMap, BMA_WIDTH); uint32 ibmHeight = IGraphics->GetBitMapAttr(inputBitMap, BMA_HEIGHT); if(x + width > ibmWidth) { width = ibmWidth - x; } if(y + height > ibmHeight) { height = ibmHeight - y; } int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; GLint texWidth = max(1,context->w3dTextures[current].texObj->texwidth >> level); GLint texHeight = max(1,context->w3dTextures[current].texObj->texheight >> level); if(xoffset + width > texWidth) { width = texWidth - xoffset; } if(yoffset + height > texHeight) { height = texHeight - yoffset; } GLubyte *dest; GLenum internalFormat = context->w3dTextures[current].internalFormat; int internal = SelectInternalFormat(context, internalFormat); RGBFTYPE p96Format = getP96Format(internalFormat); GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM); GLFlagError(context, context->w3dTextures[current].texObj == NULL, GL_INVALID_OPERATION); GLFlagError(context, level != 0, GL_INVALID_OPERATION); dest = context->w3dTextures[current].texData; // -------------------------------------------------------------------- int bytesPerRow; if(p96Format != RGBFB_NONE) { // The texture data can be copied directly into the texture's buffer using Picasso96 bytesPerRow = p96CopyBMToTex(context, x, y, xoffset, yoffset, width, height, inputBitMap, dest, texWidth, p96Format); } else { bytesPerRow = 0; // Will need to do a pixel format conversion // ##### FIXME! ##### } // ##### FIXME! ##### //MGLUpdate(context, xoffset, yoffset, width, height, pixels, dest, // context->w3dTextures[current].texObj->texwidth, // internal, unpacker); // Now perform color scale and bias // ##### FIXME! ##### // ##### FIXME! ##### what about glPixelZoom? // -------------------------------------------------------------------- if(bytesPerRow) { //UpdateTexImage(context, current, context->w3dTextures[current].texData, 0, NULL); UpdateTexSubImage(context, current, context->w3dTextures[current].texData, 0, NULL, xoffset, yoffset, width, height, bytesPerRow); } } void cgl_GLCopyTexSubImage1D(struct GLContextIFace *Self, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { // Faking 1D textures using 2D textures /*if(dl_IsDLActive(Self)){ dl_save_CopyTexSubImage1D(Self, target, level, xoffset, x, y, width); if(!dl_CompileAndExecuteMode(Self)){ return; } }*/ cgl_GLCopyTexSubImage2D(Self, GL_TEXTURE_2D, level, xoffset, 0, x, y, width, 1); // The vertical direction should always be repeated cgl_GLTexParameteri(Self, target, GL_TEXTURE_WRAP_T, GL_REPEAT); } static RGBFTYPE getP96Format(GLenum internalFormat) { switch(internalFormat) { case GL_RGB: case GL_RGB8: case 3: return RGBFB_B8G8R8; case GL_BGR: // case GL_BGR8: return RGBFB_R8G8B8; case GL_RGBA: case 4: case GL_RGBA8: return RGBFB_A8R8G8B8; case GL_RGB5: return RGBFB_R5G6B5PC; case GL_RGB5_A1: return RGBFB_R5G5B5PC; // None of the following have Picasso96 equivalents case GL_RGB4: case GL_RGBA4: case GL_ALPHA: case GL_LUMINANCE: case 1: case GL_LUMINANCE_ALPHA: case 2: case GL_INTENSITY: default: return RGBFB_NONE; } } static int p96CopyBMToTex(GLcontext context, GLint srcXOffset, GLint srcYOffset, GLint destXOffset, GLint destYOffset, GLsizei width, GLsizei height, struct BitMap *source, GLubyte *dest, GLsizei destWidth, RGBFTYPE destFormat) { struct RenderInfo rInfo; int bytesPerPixel; switch(destFormat) { case RGBFB_R8G8B8: case RGBFB_B8G8R8: bytesPerPixel = 3; break; case RGBFB_A8R8G8B8: case RGBFB_A8B8G8R8: case RGBFB_R8G8B8A8: case RGBFB_B8G8R8A8: bytesPerPixel = 4; break; case RGBFB_R5G6B5: case RGBFB_R5G5B5: case RGBFB_B5G6R5PC: case RGBFB_B5G5R5PC: case RGBFB_R5G6B5PC: case RGBFB_R5G5B5PC: bytesPerPixel = 2; break; case RGBFB_CLUT: bytesPerPixel = 1; break; default: return 0; } // Need to invert the y-axis coordinates uint32 ibmHeight = IGraphics->GetBitMapAttr(source, BMA_HEIGHT); srcYOffset = ibmHeight - srcYOffset - height - 1; rInfo.Memory = dest + (height + destYOffset - 1) * destWidth * bytesPerPixel; rInfo.BytesPerRow = -destWidth * bytesPerPixel; // OpenGL starts at the bottom left, not the top left rInfo.RGBFormat = destFormat; struct RastPort rPort; IGraphics->InitRastPort(&rPort); rPort.BitMap = source; IP96->p96ReadPixelArray(&rInfo, destXOffset, 0, &rPort, srcXOffset, srcYOffset, width, height); return -rInfo.BytesPerRow; } void cgl_GLColorTable(struct GLContextIFace *Self, GLenum target, GLenum internalformat, GLint width, GLenum format, GLenum type, const GLvoid* data) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_ColorTable(Self, target, internalformat, width, format, type, data); if(!dl_CompileAndExecuteMode(Self)){ return; } } int i; GLubyte *palette; GLubyte *where; GLubyte a,r,g,b; GLFlagError(context, width>256, GL_INVALID_VALUE); GLFlagError(context, target!=GL_COLOR_TABLE, GL_INVALID_OPERATION); palette = (GLubyte *)data; where = (GLubyte *)context->PaletteData; GLFlagError(context, where == NULL, GL_INVALID_OPERATION); switch(internalformat) { case 4: case GL_RGBA: // convert to argb from... switch(format) { case GL_RGB: // ...RGB, ignoring alpha for (i=0; iPaletteFormat = format; context->PaletteSize = width; } void cgl_GLActiveTexture(struct GLContextIFace *Self, GLenum unit) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_ActiveTexture(Self, unit); if(!dl_CompileAndExecuteMode(Self)){ return; } } unit -= GL_TEXTURE0; GLFlagError(context, unit >= context->NumTextureUnits, GL_INVALID_VALUE); context->texture.ActiveTexture = unit; } GLboolean cgl_GLAreTexturesResident(struct GLContextIFace* Self, GLsizei n, GLuint* textures, GLboolean* residences) { int t = 0; GLboolean all_resident = GL_TRUE; GLcontext context = GET_INSTANCE(Self); // Cannot be called between glBegin and glEnd GLFlagError2(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION, GL_FALSE); for (t = 0; t < n; ++t) { GLuint texture = textures[t]; // Texture object 0 cannot be used GLFlagError2(context, texture == 0, GL_INVALID_VALUE, GL_FALSE); // Cant have more textures than TexBuffserSize GLFlagError2(context, texture >= context->TexBufferSize, GL_INVALID_VALUE, GL_FALSE); // Has the texture been generated? GLFlagError2(context, context->GeneratedTextures[texture] == 0, GL_INVALID_VALUE, GL_FALSE); // Is the texture used? GLFlagError2(context, context->w3dTextures[texture].texObj == NULL, GL_INVALID_VALUE, GL_FALSE); } for (t = 0; t < n; ++t) { all_resident &= (GLboolean)context->w3dTextures[textures[t]].texObj->resident; } if (all_resident == GL_FALSE) { for (t = 0; t < n; ++t) { residences[t] = (GLboolean)context->w3dTextures[textures[t]].texObj->resident; } return GL_FALSE; } return GL_TRUE; } void tex_EstablishEnvCombine(GLcontext context) { int i,j; uint32 colorarg[3]; uint32 alphaarg[3]; uint32 colorcombine = W3D_COMBINE_DISABLED, alphacombine = W3D_COMBINE_DISABLED; for (i=0; iNumTextureUnits; i++) { if (context->enable.Texture2D[i] == GL_FALSE && context->enable.Texture1D[i] == GL_FALSE) { IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, i, W3D_COLOR_COMBINE, W3D_COMBINE_DISABLED, W3D_ALPHA_COMBINE, W3D_COMBINE_DISABLED, TAG_DONE); IWarp3D->W3D_SetTextureBlend(context->w3dContext, NULL); continue; } if (context->texture.TextureEnv[i] != GL_COMBINE) continue; if (context->combineDirty[i] == GL_FALSE) continue; switch(context->texture.colorCombine[i]) { case GL_REPLACE: colorcombine = W3D_COMBINE_SELECT_A; break; case GL_MODULATE: colorcombine = W3D_COMBINE_MODULATE; break; case GL_ADD: colorcombine = W3D_COMBINE_ADD; break; case GL_ADD_SIGNED: colorcombine = W3D_COMBINE_ADDSIGNED; break; case GL_INTERPOLATE: colorcombine = W3D_COMBINE_INTERPOLATE; break; case GL_DOT3_RGB: colorcombine = W3D_COMBINE_DOT3RGB; break; case GL_DOT3_RGBA: colorcombine = W3D_COMBINE_DOT3RGB; break; } switch(context->texture.alphaCombine[i]) { case GL_REPLACE: alphacombine = W3D_COMBINE_SELECT_A; break; case GL_MODULATE: alphacombine = W3D_COMBINE_MODULATE; break; case GL_ADD: alphacombine = W3D_COMBINE_ADD; break; case GL_ADD_SIGNED: alphacombine = W3D_COMBINE_ADDSIGNED; break; case GL_INTERPOLATE: alphacombine = W3D_COMBINE_INTERPOLATE; break; } for (j=0; j<3; j++) { switch(context->texture.colorSource[j][i]) { case GL_TEXTURE: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE0: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE0_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE0_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE0_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE0_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE1: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE1_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE1_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE1_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE1_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE2: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE2_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE2_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE2_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE2_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE3: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE3_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_TEXTURE3_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE3_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_TEXTURE3_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_CONSTANT: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_FACTOR_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_FACTOR_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_FACTOR_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_FACTOR_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_PRIMARY_COLOR: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_DIFFUSE_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_DIFFUSE_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_DIFFUSE_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_DIFFUSE_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_PREVIOUS: switch(context->texture.colorOperand[j][i]) { case GL_SRC_COLOR: colorarg[j] = W3D_ARG_PREVIOUS_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: colorarg[j] = W3D_ARG_PREVIOUS_COLOR | W3D_ARG_COMPLEMENT; break; case GL_SRC_ALPHA: colorarg[j] = W3D_ARG_PREVIOUS_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: colorarg[j] = W3D_ARG_PREVIOUS_ALPHA | W3D_ARG_COMPLEMENT; break; } break; } // switch color arg switch(context->texture.alphaSource[j][i]) { case GL_TEXTURE: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE0: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE0_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE0_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE1: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE1_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE1_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE2: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE2_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE2_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_TEXTURE3: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE3_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_TEXTURE3_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_CONSTANT: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_FACTOR_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_FACTOR_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_PRIMARY_COLOR: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_DIFFUSE_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_DIFFUSE_ALPHA | W3D_ARG_COMPLEMENT; break; } break; case GL_PREVIOUS: switch(context->texture.alphaOperand[j][i]) { case GL_SRC_ALPHA: alphaarg[j] = W3D_ARG_PREVIOUS_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: alphaarg[j] = W3D_ARG_PREVIOUS_ALPHA | W3D_ARG_COMPLEMENT; break; } break; } // Switch alpha arg } // for j IWarp3D->W3D_SetTextureBlendTags(context->w3dContext, W3D_BLEND_STAGE, i, W3D_COLOR_COMBINE, colorcombine, W3D_COLOR_ARG_A, colorarg[0], W3D_COLOR_ARG_B, colorarg[1], W3D_COLOR_ARG_C, colorarg[2], W3D_ALPHA_COMBINE, alphacombine, W3D_ALPHA_ARG_A, alphaarg[0], W3D_ALPHA_ARG_B, alphaarg[1], W3D_ALPHA_ARG_C, alphaarg[2], W3D_COLOR_SCALE, context->texture.colorScale[i], W3D_ALPHA_SCALE, context->texture.alphaScale[i], W3D_BLEND_FACTOR, context->texture.envColor[i], TAG_DONE); } // for texture unit IWarp3D->W3D_SetTextureBlend(context->w3dContext, NULL); } void cgl_GLTexGenfv(struct GLContextIFace *Self, GLenum coord, GLenum pname, GLfloat *params) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_TexGenfv(Self, coord, pname, params); if(!dl_CompileAndExecuteMode(Self)){ return; } } uint32 current = context->texture.ActiveTexture; GLtexgen *texgen = 0; if (coord == GL_S) texgen = & context->texture.TexGenS[current]; else if (coord == GL_T) texgen = & context->texture.TexGenT[current]; else if (coord == GL_R) return; GLFlagError(context, texgen == 0, GL_INVALID_ENUM); switch (pname) { case GL_EYE_PLANE: /* FIXME: Transform to eye space */ break; case GL_OBJECT_PLANE: texgen->objectPlane[0] = params[0]; texgen->objectPlane[1] = params[1]; texgen->objectPlane[2] = params[2]; texgen->objectPlane[3] = params[3]; break; default: Self->GLTexGeni(coord, pname, (GLint)params[0]); break; } } void cgl_GLTexGeni(struct GLContextIFace *Self, GLenum coord, GLenum pname, GLint param) { GLcontext context = GET_INSTANCE(Self); if(dl_IsDLActive(Self)){ dl_save_TexGeni(Self, coord, pname, param); if(!dl_CompileAndExecuteMode(Self)){ return; } } uint32 current = context->texture.ActiveTexture; GLtexgen *texgen = 0; if (coord == GL_S) texgen = & context->texture.TexGenS[current]; else if (coord == GL_T) texgen = & context->texture.TexGenT[current]; else if (coord == GL_R) return; GLFlagError(context, texgen == 0, GL_INVALID_ENUM); switch (pname) { case GL_TEXTURE_GEN_MODE: GLFlagError(context, param != GL_OBJECT_LINEAR && param != GL_EYE_LINEAR && param != GL_SPHERE_MAP && param != GL_REFLECTION_MAP && param != GL_NORMAL_MAP, GL_INVALID_ENUM); texgen->mode = param; if (param == GL_SPHERE_MAP) { texgen->needR = GL_TRUE; texgen->needM = GL_TRUE; } else if (param == GL_REFLECTION_MAP) { texgen->needR = GL_TRUE; texgen->needM = GL_FALSE; } else { texgen->needR = GL_FALSE; texgen->needM = GL_FALSE; } break; default: GLFlagError(context, 1, GL_INVALID_ENUM); break; } } GLboolean cgl_GLIsTexture(struct GLContextIFace *Self, GLuint texture){ GLcontext context = GET_INSTANCE(Self); if(texture > context->TexBufferSize) return GL_FALSE; if(context->GeneratedTextures[texture] != 0) return GL_TRUE; else return GL_FALSE; } void cgl_GLGetTexLevelParameterfv(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLenum pname, GLfloat *param) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, gltarget != GL_TEXTURE_2D && gltarget != GL_PROXY_TEXTURE_2D && gltarget != GL_TEXTURE_1D && gltarget != GL_PROXY_TEXTURE_1D, GL_INVALID_ENUM); int current; MGLTexture *curTex; if (gltarget == GL_TEXTURE_2D || gltarget == GL_TEXTURE_1D) { current = context->texture.CurrentBinding[context->texture.ActiveTexture]; curTex = &context->w3dTextures[current]; switch (pname) { case GL_TEXTURE_WIDTH: if (!curTex->texObj) param[0] = 0; else { uint32 width = curTex->texObj->texwidth >> level; param[0] = width > 0 ? width : 1; } break; case GL_TEXTURE_HEIGHT: if (!curTex->texObj) param[0] = 0; else { uint32 height = curTex->texObj->texheight >> level; param[0] = height > 0 ? height : 1; } break; case GL_TEXTURE_DEPTH: param[0] = 0; break; case GL_TEXTURE_INTERNAL_FORMAT: param[0] = curTex->internalFormat; break; case GL_TEXTURE_BORDER: param[0] = 0; break; case GL_TEXTURE_RED_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].redsize; else param[0] = 0; break; case GL_TEXTURE_GREEN_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].greensize; else param[0] = 0; break; case GL_TEXTURE_BLUE_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].bluesize; else param[0] = 0; break; case GL_TEXTURE_ALPHA_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].alphasize; else param[0] = 0; break; case GL_TEXTURE_LUMINANCE_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].luminancesize; else param[0] = 0; break; case GL_TEXTURE_INTENSITY_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].intensitysize; else param[0] = 0; break; default: context->CurrentError = GL_INVALID_ENUM; break; } } if (gltarget == GL_PROXY_TEXTURE_2D || gltarget == GL_PROXY_TEXTURE_1D) { switch (pname) { case GL_TEXTURE_WIDTH: param[0] = (GLfloat)context->proxy_width; break; case GL_TEXTURE_HEIGHT: param[0] = (GLfloat)context->proxy_height; break; case GL_TEXTURE_DEPTH: param[0] = 0.0; break; case GL_TEXTURE_INTERNAL_FORMAT: param[0] = (GLfloat)context->proxy_internalFormat; break; case GL_TEXTURE_BORDER: param[0] = 0.0; break; case GL_TEXTURE_RED_SIZE: if (context->proxy_internalFormat >= 0) param[0] = (GLfloat)i2w3d[context->proxy_internalFormat].redsize; else param[0] = 0.0; break; case GL_TEXTURE_GREEN_SIZE: if (context->proxy_internalFormat >= 0) param[0] = (GLfloat)i2w3d[context->proxy_internalFormat].greensize; else param[0] = 0.0; break; case GL_TEXTURE_BLUE_SIZE: if (context->proxy_internalFormat >= 0) param[0] = (GLfloat)i2w3d[context->proxy_internalFormat].bluesize; else param[0] = 0.0; break; case GL_TEXTURE_ALPHA_SIZE: if (context->proxy_internalFormat >= 0) param[0] = (GLfloat)i2w3d[context->proxy_internalFormat].alphasize; else param[0] = 0.0; break; case GL_TEXTURE_LUMINANCE_SIZE: if (context->proxy_internalFormat >= 0) param[0] = (GLfloat)i2w3d[context->proxy_internalFormat].luminancesize; else param[0] = 0.0; break; case GL_TEXTURE_INTENSITY_SIZE: if (context->proxy_internalFormat >= 0) param[0] = (GLfloat)i2w3d[context->proxy_internalFormat].intensitysize; else param[0] = 0.0; break; default: context->CurrentError = GL_INVALID_ENUM; break; } } } void cgl_GLGetTexLevelParameteriv(struct GLContextIFace *Self, GLenum gltarget, GLint level, GLenum pname, GLfloat *param) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, gltarget != GL_TEXTURE_2D && gltarget != GL_PROXY_TEXTURE_2D && gltarget != GL_TEXTURE_2D && gltarget != GL_PROXY_TEXTURE_2D, GL_INVALID_ENUM); int current; MGLTexture *curTex; if (gltarget == GL_TEXTURE_2D || gltarget == GL_TEXTURE_1D) { current = context->texture.CurrentBinding[context->texture.ActiveTexture]; curTex = &context->w3dTextures[current]; switch (pname) { case GL_TEXTURE_WIDTH: if (!curTex->texObj) param[0] = 0; else { uint32 width = curTex->texObj->texwidth >> level; param[0] = width > 0 ? width : 1; } break; case GL_TEXTURE_HEIGHT: if (!curTex->texObj) param[0] = 0; else { uint32 height = curTex->texObj->texheight >> level; param[0] = height > 0 ? height : 1; } break; case GL_TEXTURE_DEPTH: param[0] = 0; break; case GL_TEXTURE_INTERNAL_FORMAT: param[0] = curTex->internalFormat; break; case GL_TEXTURE_BORDER: param[0] = 0; break; case GL_TEXTURE_RED_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].redsize; else param[0] = 0; break; case GL_TEXTURE_GREEN_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].greensize; else param[0] = 0; break; case GL_TEXTURE_BLUE_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].bluesize; else param[0] = 0; break; case GL_TEXTURE_ALPHA_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].alphasize; else param[0] = 0; break; case GL_TEXTURE_LUMINANCE_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].luminancesize; else param[0] = 0; break; case GL_TEXTURE_INTENSITY_SIZE: if (curTex->internalFormat >= 0) param[0] = i2w3d[curTex->internalFormat].intensitysize; else param[0] = 0; break; default: context->CurrentError = GL_INVALID_ENUM; break; } } if (gltarget == GL_PROXY_TEXTURE_2D || gltarget == GL_PROXY_TEXTURE_1D) { switch (pname) { case GL_TEXTURE_WIDTH: param[0] = context->proxy_width; break; case GL_TEXTURE_HEIGHT: param[0] = context->proxy_height; break; case GL_TEXTURE_DEPTH: param[0] = 0; break; case GL_TEXTURE_INTERNAL_FORMAT: param[0] = context->proxy_internalFormat; break; case GL_TEXTURE_BORDER: param[0] = 0; break; case GL_TEXTURE_RED_SIZE: if (context->proxy_internalFormat >= 0) param[0] = i2w3d[context->proxy_internalFormat].redsize; else param[0] = 0; break; case GL_TEXTURE_GREEN_SIZE: if (context->proxy_internalFormat >= 0) param[0] = i2w3d[context->proxy_internalFormat].greensize; else param[0] = 0; break; case GL_TEXTURE_BLUE_SIZE: if (context->proxy_internalFormat >= 0) param[0] = i2w3d[context->proxy_internalFormat].bluesize; else param[0] = 0; break; case GL_TEXTURE_ALPHA_SIZE: if (context->proxy_internalFormat >= 0) param[0] = i2w3d[context->proxy_internalFormat].alphasize; else param[0] = 0; break; case GL_TEXTURE_LUMINANCE_SIZE: if (context->proxy_internalFormat >= 0) param[0] = i2w3d[context->proxy_internalFormat].luminancesize; else param[0] = 0; break; case GL_TEXTURE_INTENSITY_SIZE: if (context->proxy_internalFormat >= 0) param[0] = i2w3d[context->proxy_internalFormat].intensitysize; else param[0] = 0; break; default: context->CurrentError = GL_INVALID_ENUM; break; } } } void cgl_GLGetTexParameterfv(struct GLContextIFace *Self, GLenum gltarget, GLenum pname, GLfloat *param) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, gltarget != GL_TEXTURE_2D && gltarget != GL_TEXTURE_1D, GL_INVALID_ENUM); int current; MGLTexture *curTex; #define FROM_BOOL(x) (GLfloat)((x) ? 1.0f : 0.0f) #define FROM_COLOR(x) (GLfloat)(x) #define FROM_FLOAT(x) (x) #define FROM_INT(x) (GLfloat)(x) current = context->texture.CurrentBinding[context->texture.ActiveTexture]; curTex = &context->w3dTextures[current]; switch (pname) { case GL_TEXTURE_RESIDENT: if (!curTex->texObj) param[0] = 0.0; else param[0] = FROM_BOOL(curTex->texObj->resident); break; case GL_TEXTURE_WRAP_S: param[0] = FROM_INT(curTex->WrapS); break; case GL_TEXTURE_WRAP_T: param[0] = FROM_INT(curTex->WrapT); break; case GL_TEXTURE_WRAP_R: param[0] = 0.0; break; case GL_TEXTURE_MIN_FILTER: param[0] = FROM_INT(curTex->MinFilter); break; case GL_TEXTURE_MAG_FILTER: param[0] = FROM_INT(curTex->MagFilter); break; } #undef FROM_BOOL #undef FROM_COLOR #undef FROM_FLOAT #undef FROM_INT } void cgl_GLGetTexParameteriv(struct GLContextIFace *Self, GLenum gltarget, GLenum pname, GLint *param) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, gltarget != GL_TEXTURE_2D && gltarget != GL_TEXTURE_1D, GL_INVALID_ENUM); int current; MGLTexture *curTex; #define FROM_BOOL(x) (GLint)((x) ? 1 : 0) #define FROM_COLOR(x) (GLint)((0xffffffff * (x) - 1)/2) #define FROM_FLOAT(x) (GLint)(x) #define FROM_INT(x) (x) current = context->texture.CurrentBinding[context->texture.ActiveTexture]; curTex = &context->w3dTextures[current]; switch (pname) { case GL_TEXTURE_RESIDENT: if (!curTex->texObj) param[0] = 0.0; else param[0] = FROM_BOOL(curTex->texObj->resident); break; case GL_TEXTURE_WRAP_S: param[0] = FROM_INT(curTex->WrapS); break; case GL_TEXTURE_WRAP_T: param[0] = FROM_INT(curTex->WrapT); break; case GL_TEXTURE_WRAP_R: param[0] = 0.0; break; case GL_TEXTURE_MIN_FILTER: param[0] = FROM_INT(curTex->MinFilter); break; case GL_TEXTURE_MAG_FILTER: param[0] = FROM_INT(curTex->MagFilter); break; } #undef FROM_BOOL #undef FROM_COLOR #undef FROM_FLOAT #undef FROM_INT } void cgl_GLGetTexImage(struct GLContextIFace *Self, GLenum target, GLint lod, GLenum format, GLenum type, GLvoid *pixels) { GLcontext context = GET_INSTANCE(Self); GLFlagError(context, target != GL_TEXTURE_2D && target != GL_TEXTURE_1D, GL_INVALID_ENUM); if (pixels == 0) return; if (context->NoMipMapping == GL_TRUE && lod != 0) { context->CurrentError = GL_INVALID_ENUM; return; } GLimage_info src; GLimage_info dst; int current = context->texture.CurrentBinding[context->texture.ActiveTexture]; /* Peek the size. We didn't record it anywhere, so we peek it from the * texture object :S */ GLsizei width = (context->w3dTextures[current].texObj->texwidth); GLsizei height = (context->w3dTextures[current].texObj->texheight); if (width == 0) width = 1; if (height == 0) height = 1; /* Find and setup the source image */ if (context->w3dTextures[current].texObj == NULL) { context->CurrentError = GL_INVALID_ENUM; return; } struct W3DtoGL *formatInfo = MGLGetFormatInfo(context->w3dTextures[current].texObj->texfmtsrc); if (!formatInfo) { context->CurrentError = GL_INVALID_ENUM; return; } if (lod == 0) src.data = context->w3dTextures[current].texData; else src.data = context->w3dTextures[current].mipmaps[lod-1]; src.stride = formatInfo->w3dBpp * width; src.format = formatInfo->glformat; src.type = formatInfo->gltype; src.pixel_stride = formatInfo->w3dBpp; /* Setup destination. Select a packer to get the pixel stride */ dst.data = pixels; MGLSelectPacker(format, type, &dst.pixel_stride); dst.format = format; dst.type = type; dst.stride = width * dst.pixel_stride; MGLPackImage(context, width, height, &src, &dst, GL_FALSE); }