📄 atifragshader.c
字号:
/** * \file atifragshader.c * \author David Airlie * Copyright (C) 2004 David Airlie All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "context.h"#include "hash.h"#include "imports.h"#include "macros.h"#include "enums.h"#include "mtypes.h"#include "atifragshader.h"#define MESA_DEBUG_ATI_FS 0static struct ati_fragment_shader DummyShader;/** * Allocate and initialize a new ATI fragment shader object. */struct ati_fragment_shader *_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id){ struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader); (void) ctx; if (s) { s->Id = id; s->RefCount = 1; } return s;}/** * Delete the given ati fragment shader */void_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s){ GLuint i; for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { if (s->Instructions[i]) _mesa_free(s->Instructions[i]); if (s->SetupInst[i]) _mesa_free(s->SetupInst[i]); } _mesa_free(s);}static voidnew_arith_inst(struct ati_fragment_shader *prog){/* set "default" instruction as not all may get defined. there is no specified way to express a nop with ati fragment shaders we use GL_NONE as the op enum and just set some params to 0 - so nothing to do here */ prog->numArithInstr[prog->cur_pass >> 1]++;}static voidnew_tex_inst(struct ati_fragment_shader *prog){}static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype){ if (optype == curProg->last_optype) { curProg->last_optype = 1; }}#if MESA_DEBUG_ATI_FSstatic char *create_dst_mod_str(GLuint mod){ static char ret_str[1024]; _mesa_memset(ret_str, 0, 1024); if (mod & GL_2X_BIT_ATI) _mesa_strncat(ret_str, "|2X", 1024); if (mod & GL_4X_BIT_ATI) _mesa_strncat(ret_str, "|4X", 1024); if (mod & GL_8X_BIT_ATI) _mesa_strncat(ret_str, "|8X", 1024); if (mod & GL_HALF_BIT_ATI) _mesa_strncat(ret_str, "|HA", 1024); if (mod & GL_QUARTER_BIT_ATI) _mesa_strncat(ret_str, "|QU", 1024); if (mod & GL_EIGHTH_BIT_ATI) _mesa_strncat(ret_str, "|EI", 1024); if (mod & GL_SATURATE_BIT_ATI) _mesa_strncat(ret_str, "|SAT", 1024); if (_mesa_strlen(ret_str) == 0) _mesa_strncat(ret_str, "NONE", 1024); return ret_str;}static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod){ char *op_name; op_name = atifs_ops[(arg_count-1)+(optype?3:0)]; fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op), _mesa_lookup_enum_by_nr(dst)); if (!optype) fprintf(stderr, ", %d", dstMask); fprintf(stderr, ", %s", create_dst_mod_str(dstMod)); fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1), _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod); if (arg_count>1) fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2), _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod); if (arg_count>2) fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3), _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod); fprintf(stderr,")\n");}#endifstatic int check_arith_arg(struct ati_fragment_shader *curProg, GLuint optype, GLuint arg, GLuint argRep){ GET_CURRENT_CONTEXT(ctx); if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) && ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) && (arg != GL_ZERO) && (arg != GL_ONE) && (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) { _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)"); return 0; } if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); return 0; } if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); return 0; } if ((curProg->cur_pass == 1) && ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) { curProg->interpinp1 = GL_TRUE; } return 1;}GLuint GLAPIENTRY_mesa_GenFragmentShadersATI(GLuint range){ GLuint first; GLuint i; GET_CURRENT_CONTEXT(ctx); if (range == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)"); return 0; } if (ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)"); return 0; } first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range); for (i = 0; i < range; i++) { _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader); } return first;}void GLAPIENTRY_mesa_BindFragmentShaderATI(GLuint id){ GET_CURRENT_CONTEXT(ctx); struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; struct ati_fragment_shader *newProg; if (ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)"); return; } FLUSH_VERTICES(ctx, _NEW_PROGRAM); if (curProg->Id == id) { return; } /* unbind current */ if (curProg->Id != 0) { curProg->RefCount--; if (curProg->RefCount <= 0) { _mesa_HashRemove(ctx->Shared->ATIShaders, id); } } /* find new shader */ if (id == 0) { newProg = ctx->Shared->DefaultFragmentShader; } else { newProg = (struct ati_fragment_shader *) _mesa_HashLookup(ctx->Shared->ATIShaders, id); if (!newProg || newProg == &DummyShader) { /* allocate a new program now */ newProg = _mesa_new_ati_fragment_shader(ctx, id); if (!newProg) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI"); return; } _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg); } } /* do actual bind */ ctx->ATIFragmentShader.Current = newProg; ASSERT(ctx->ATIFragmentShader.Current); if (newProg) newProg->RefCount++; /*if (ctx->Driver.BindProgram) ctx->Driver.BindProgram(ctx, target, prog); */}void GLAPIENTRY_mesa_DeleteFragmentShaderATI(GLuint id){ GET_CURRENT_CONTEXT(ctx); if (ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)"); return; } if (id != 0) { struct ati_fragment_shader *prog = (struct ati_fragment_shader *) _mesa_HashLookup(ctx->Shared->ATIShaders, id); if (prog == &DummyShader) { _mesa_HashRemove(ctx->Shared->ATIShaders, id); } else if (prog) { if (ctx->ATIFragmentShader.Current && ctx->ATIFragmentShader.Current->Id == id) { FLUSH_VERTICES(ctx, _NEW_PROGRAM); _mesa_BindFragmentShaderATI(0); } } /* The ID is immediately available for re-use now */ _mesa_HashRemove(ctx->Shared->ATIShaders, id); prog->RefCount--; if (prog->RefCount <= 0) { _mesa_free(prog); } }}void GLAPIENTRY_mesa_BeginFragmentShaderATI(void){ GLint i; GET_CURRENT_CONTEXT(ctx); if (ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)"); return; } FLUSH_VERTICES(ctx, _NEW_PROGRAM); /* if the shader was already defined free instructions and get new ones (or, could use the same mem but would need to reinitialize) */ /* no idea if it's allowed to redefine a shader */ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { if (ctx->ATIFragmentShader.Current->Instructions[i]) _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]); if (ctx->ATIFragmentShader.Current->SetupInst[i]) _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]); } /* malloc the instructions here - not sure if the best place but its a start */ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { ctx->ATIFragmentShader.Current->Instructions[i] = (struct atifs_instruction *) _mesa_calloc(sizeof(struct atifs_instruction) * (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI)); ctx->ATIFragmentShader.Current->SetupInst[i] = (struct atifs_setupinst *) _mesa_calloc(sizeof(struct atifs_setupinst) * (MAX_NUM_FRAGMENT_REGISTERS_ATI)); }/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */ ctx->ATIFragmentShader.Current->LocalConstDef = 0; ctx->ATIFragmentShader.Current->numArithInstr[0] = 0; ctx->ATIFragmentShader.Current->numArithInstr[1] = 0; ctx->ATIFragmentShader.Current->regsAssigned[0] = 0; ctx->ATIFragmentShader.Current->regsAssigned[1] = 0; ctx->ATIFragmentShader.Current->NumPasses = 0; ctx->ATIFragmentShader.Current->cur_pass = 0; ctx->ATIFragmentShader.Current->last_optype = 0; ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE; ctx->ATIFragmentShader.Current->isValid = GL_FALSE; ctx->ATIFragmentShader.Current->swizzlerq = 0; ctx->ATIFragmentShader.Compiling = 1;}void GLAPIENTRY_mesa_EndFragmentShaderATI(void){ GET_CURRENT_CONTEXT(ctx); struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;#if MESA_DEBUG_ATI_FS GLint i, j;#endif if (!ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)"); return; } if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)"); /* according to spec, DON'T return here */ } match_pair_inst(curProg, 0); ctx->ATIFragmentShader.Compiling = 0; ctx->ATIFragmentShader.Current->isValid = GL_TRUE; if ((ctx->ATIFragmentShader.Current->cur_pass == 0) || (ctx->ATIFragmentShader.Current->cur_pass == 2)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)"); } if (ctx->ATIFragmentShader.Current->cur_pass > 1) ctx->ATIFragmentShader.Current->NumPasses = 2; else ctx->ATIFragmentShader.Current->NumPasses = 1; ctx->ATIFragmentShader.Current->cur_pass=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -