/** * Construct the GL_EXTENSIONS string. Called the first time that * glGetString(GL_EXTENSIONS) is called. */ GLubyte * _mesa_make_extension_string( GLcontext *ctx ) { const GLboolean *base = (const GLboolean *) &ctx->Extensions; GLuint extStrLen = 0; GLubyte *s; GLuint i; /* first, compute length of the extension string */ for (i = 0 ; i < Elements(default_extensions) ; i++) { if (!default_extensions[i].flag_offset || *(base + default_extensions[i].flag_offset)) { extStrLen += (GLuint)_mesa_strlen(default_extensions[i].name) + 1; } } s = (GLubyte *) _mesa_malloc(extStrLen); /* second, build the extension string */ extStrLen = 0; for (i = 0 ; i < Elements(default_extensions) ; i++) { if (!default_extensions[i].flag_offset || *(base + default_extensions[i].flag_offset)) { GLuint len = (GLuint)_mesa_strlen(default_extensions[i].name); _mesa_memcpy(s + extStrLen, default_extensions[i].name, len); extStrLen += len; s[extStrLen] = (GLubyte) ' '; extStrLen++; } } ASSERT(extStrLen > 0); s[extStrLen - 1] = 0; return s; }
/** * Get a program attribute. * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ void GLAPIENTRY _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) { struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); if (!ctx->_CurrentProgram) ASSERT_OUTSIDE_BEGIN_END(ctx); prog = _mesa_lookup_program(ctx, id); if (!prog) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); return; } switch (pname) { case GL_PROGRAM_TARGET_NV: *params = prog->Target; return; case GL_PROGRAM_LENGTH_NV: *params = prog->String ?(GLint)_mesa_strlen((char *) prog->String) : 0; return; case GL_PROGRAM_RESIDENT_NV: *params = prog->Resident; return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); return; } }
void GLAPIENTRY _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string) { const struct gl_program *prog; char *dst = (char *) string; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (target == GL_VERTEX_PROGRAM_ARB) { prog = &(ctx->VertexProgram.Current->Base); } else if (target == GL_FRAGMENT_PROGRAM_ARB) { prog = &(ctx->FragmentProgram.Current->Base); } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)"); return; } ASSERT(prog); if (pname != GL_PROGRAM_STRING_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)"); return; } if (prog->String) _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String)); else *dst = '\0'; }
/** * Get the program source code. * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ void GLAPIENTRY _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) { struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); if (!ctx->_CurrentProgram) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname != GL_PROGRAM_STRING_NV) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)"); return; } prog = _mesa_lookup_program(ctx, id); if (!prog) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV"); return; } if (prog->String) { MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String)); } else { program[0] = 0; } }
/** * Lookup a parameter value by name in the given parameter list. * \return pointer to the float[4] values. */ GLfloat * _mesa_lookup_parameter_value(struct program_parameter_list *paramList, GLsizei nameLen, const char *name) { GLuint i; if (!paramList) return NULL; if (nameLen == -1) { /* name is null-terminated */ for (i = 0; i < paramList->NumParameters; i++) { if (_mesa_strcmp(paramList->Parameters[i].Name, name) == 0) return paramList->Parameters[i].Values; } } else { /* name is not null-terminated, use nameLen */ for (i = 0; i < paramList->NumParameters; i++) { if (_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) return paramList->Parameters[i].Values; } } return NULL; }
/** * Get the program source code. * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ void _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) { struct vp_program *vprog; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname != GL_PROGRAM_STRING_NV) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); return; } vprog = (struct vp_program *) _mesa_HashLookup(ctx->Shared->VertexPrograms, id); if (!vprog) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); return; } if (vprog->String) { MEMCPY(program, vprog->String, _mesa_strlen((char *) vprog->String)); } else { program[0] = 0; } }
/** * Get a program attribute. * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ void _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) { struct vp_program *vprog; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); vprog = (struct vp_program *) _mesa_HashLookup(ctx->Shared->VertexPrograms, id); if (!vprog) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); return; } switch (pname) { case GL_PROGRAM_TARGET_NV: *params = vprog->Target; return; case GL_PROGRAM_LENGTH_NV: *params = vprog->String ? _mesa_strlen((char *) vprog->String) : 0; return; case GL_PROGRAM_RESIDENT_NV: *params = vprog->Resident; return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); return; } }
/** * Lookup a parameter index by name in the given parameter list. * \return index of parameter in the list. */ GLint _mesa_lookup_parameter_index(struct program_parameter_list *paramList, GLsizei nameLen, const char *name) { GLint i; if (!paramList) return -1; if (nameLen == -1) { /* name is null-terminated */ for (i = 0; i < (GLint) paramList->NumParameters; i++) { if (_mesa_strcmp(paramList->Parameters[i].Name, name) == 0) return i; } } else { /* name is not null-terminated, use nameLen */ for (i = 0; i < (GLint) paramList->NumParameters; i++) { if (_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) return i; } } return -1; }
/** * Get next token from input stream but don't increment stream pointer. */ static GLboolean Peek_Token(struct parse_state *parseState, GLubyte *token) { GLint i, len; i = GetToken(parseState, token); if (i <= 0) { parseState->pos += (-i); return GL_FALSE; } len = _mesa_strlen((const char *) token); parseState->pos += (i - len); return GL_TRUE; }
/** * Clone string, storing in current mempool. */ char * _slang_strdup(const char *s) { if (s) { size_t l = _mesa_strlen(s); char *s2 = (char *) _slang_alloc(l + 1); if (s2) _mesa_strcpy(s2, s); return s2; } else { return NULL; } }
/** * Find longest name of all uniform parameters in list. */ GLuint _mesa_longest_parameter_name(const struct gl_program_parameter_list *list, enum register_file type) { GLuint i, maxLen = 0; if (!list) return 0; for (i = 0; i < list->NumParameters; i++) { if (list->Parameters[i].Type == type) { GLuint len = _mesa_strlen(list->Parameters[i].Name); if (len > maxLen) maxLen = len; } } return maxLen; }
static GLvoid pp_annotate (slang_string *output, const char *fmt, ...) { #if PP_ANNOTATE va_list va; char buffer[1024]; va_start (va, fmt); _mesa_vsprintf (buffer, fmt, va); va_end (va); slang_string_pushs (output, buffer, _mesa_strlen (buffer)); #else (GLvoid) (output); (GLvoid) (fmt); #endif }
static GLboolean parse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_state *state, grammar eid) { const char *text; GLuint len; text = (const char *) (&prod[*pi]); len = _mesa_strlen (text); if (state->cond.top->effective) { slang_string expr; GLuint count; GLint results[2]; expand_state es; /* Expand the expression. */ slang_string_init (&expr); es.output = &expr; es.input = text; es.state = state; if (!expand (&es, &state->symbols)) return GL_FALSE; /* Execute the expression. */ count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&expr)), results, state->elog); slang_string_free (&expr); if (count != 1) return GL_FALSE; *result = results[0]; } else { /* The directive is dead. */ *result = 0; } *pi += len + 1; return GL_TRUE; }
void GLAPIENTRY _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params) { struct program *prog; GET_CURRENT_CONTEXT(ctx); if (!ctx->_CurrentProgram) ASSERT_OUTSIDE_BEGIN_END(ctx); if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { prog = &(ctx->VertexProgram.Current->Base); } else if (target == GL_FRAGMENT_PROGRAM_ARB && ctx->Extensions.ARB_fragment_program) { prog = &(ctx->FragmentProgram.Current->Base); } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } ASSERT(prog); switch (pname) { case GL_PROGRAM_LENGTH_ARB: *params = prog->String ? (GLint)_mesa_strlen((char *) prog->String) : 0; break; case GL_PROGRAM_FORMAT_ARB: *params = prog->Format; break; case GL_PROGRAM_BINDING_ARB: *params = prog->Id; break; case GL_PROGRAM_INSTRUCTIONS_ARB: *params = prog->NumInstructions; break; case GL_MAX_PROGRAM_INSTRUCTIONS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramInstructions; else *params = ctx->Const.MaxFragmentProgramInstructions; break; case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB: *params = prog->NumInstructions; break; case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramInstructions; else *params = ctx->Const.MaxFragmentProgramInstructions; break; case GL_PROGRAM_TEMPORARIES_ARB: *params = prog->NumTemporaries; break; case GL_MAX_PROGRAM_TEMPORARIES_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramTemps; else *params = ctx->Const.MaxFragmentProgramTemps; break; case GL_PROGRAM_NATIVE_TEMPORARIES_ARB: /* XXX same as GL_PROGRAM_TEMPORARIES_ARB? */ *params = prog->NumTemporaries; break; case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB: /* XXX same as GL_MAX_PROGRAM_TEMPORARIES_ARB? */ if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramTemps; else *params = ctx->Const.MaxFragmentProgramTemps; break; case GL_PROGRAM_PARAMETERS_ARB: *params = prog->NumParameters; break; case GL_MAX_PROGRAM_PARAMETERS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramLocalParams; else *params = ctx->Const.MaxFragmentProgramLocalParams; break; case GL_PROGRAM_NATIVE_PARAMETERS_ARB: /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */ *params = prog->NumParameters; break; case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB: /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */ if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramLocalParams; else *params = ctx->Const.MaxFragmentProgramLocalParams; break; case GL_PROGRAM_ATTRIBS_ARB: *params = prog->NumAttributes; break; case GL_MAX_PROGRAM_ATTRIBS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramAttribs; else *params = ctx->Const.MaxFragmentProgramAttribs; break; case GL_PROGRAM_NATIVE_ATTRIBS_ARB: /* XXX same as GL_PROGRAM_ATTRIBS_ARB? */ *params = prog->NumAttributes; break; case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB: /* XXX same as GL_MAX_PROGRAM_ATTRIBS_ARB? */ if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramAttribs; else *params = ctx->Const.MaxFragmentProgramAttribs; break; case GL_PROGRAM_ADDRESS_REGISTERS_ARB: *params = prog->NumAddressRegs; break; case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramAddressRegs; else *params = ctx->Const.MaxFragmentProgramAddressRegs; break; case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: /* XXX same as GL_PROGRAM_ADDRESS_REGISTERS_ARB? */ *params = prog->NumAddressRegs; break; case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: /* XXX same as GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB? */ if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramAddressRegs; else *params = ctx->Const.MaxFragmentProgramAddressRegs; break; case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramLocalParams; else *params = ctx->Const.MaxFragmentProgramLocalParams; break; case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB: if (target == GL_VERTEX_PROGRAM_ARB) *params = ctx->Const.MaxVertexProgramEnvParams; else *params = ctx->Const.MaxFragmentProgramEnvParams; break; case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: if (ctx->Driver.IsProgramNative) *params = ctx->Driver.IsProgramNative( ctx, target, prog ); else *params = GL_TRUE; break; /* * The following apply to fragment programs only. */ case GL_PROGRAM_ALU_INSTRUCTIONS_ARB: case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: if (target != GL_FRAGMENT_PROGRAM_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } *params = ctx->FragmentProgram.Current->NumAluInstructions; break; case GL_PROGRAM_TEX_INSTRUCTIONS_ARB: case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: if (target != GL_FRAGMENT_PROGRAM_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } *params = ctx->FragmentProgram.Current->NumTexInstructions; break; case GL_PROGRAM_TEX_INDIRECTIONS_ARB: case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: if (target != GL_FRAGMENT_PROGRAM_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } *params = ctx->FragmentProgram.Current->NumTexIndirections; break; case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB: case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: if (target != GL_FRAGMENT_PROGRAM_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } *params = ctx->Const.MaxFragmentProgramAluInstructions; break; case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB: case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: if (target != GL_FRAGMENT_PROGRAM_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } *params = ctx->Const.MaxFragmentProgramTexInstructions; break; case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB: case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: if (target != GL_FRAGMENT_PROGRAM_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } *params = ctx->Const.MaxFragmentProgramTexIndirections; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); return; } }
unsigned int slang_string_length (const char *str) { return _mesa_strlen (str); }
void _mesa_GetProgramRegisterfvMESA(GLenum target, GLsizei len, const GLubyte *registerName, GLfloat *v) { char reg[1000]; GET_CURRENT_CONTEXT(ctx); /* We _should_ be inside glBegin/glEnd */ #if 0 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA"); return; } #endif /* make null-terminated copy of registerName */ len = MIN2((unsigned int) len, sizeof(reg) - 1); _mesa_memcpy(reg, registerName, len); reg[len] = 0; switch (target) { case GL_VERTEX_PROGRAM_NV: if (!ctx->Extensions.ARB_vertex_program && !ctx->Extensions.NV_vertex_program) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramRegisterfvMESA(target)"); return; } if (!ctx->VertexProgram.Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA"); return; } /* GL_NV_vertex_program */ if (reg[0] == 'R') { /* Temp register */ GLint i = _mesa_atoi(reg + 1); if (i >= (GLint)ctx->Const.MaxVertexProgramTemps) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramRegisterfvMESA(registerName)"); return; } COPY_4V(v, ctx->VertexProgram.Temporaries[i]); } else if (reg[0] == 'v' && reg[1] == '[') { /* Vertex Input attribute */ GLuint i; for (i = 0; i < ctx->Const.MaxVertexProgramAttribs; i++) { const char *name = _mesa_nv_vertex_input_register_name(i); char number[10]; sprintf(number, "%d", i); if (_mesa_strncmp(reg + 2, name, 4) == 0 || _mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) { COPY_4V(v, ctx->VertexProgram.Inputs[i]); return; } } _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramRegisterfvMESA(registerName)"); return; } else if (reg[0] == 'o' && reg[1] == '[') { /* Vertex output attribute */ } /* GL_ARB_vertex_program */ else if (_mesa_strncmp(reg, "vertex.", 7) == 0) { } else { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramRegisterfvMESA(registerName)"); return; } break; case GL_FRAGMENT_PROGRAM_ARB: if (!ctx->Extensions.ARB_fragment_program) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramRegisterfvMESA(target)"); return; } if (!ctx->FragmentProgram.Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA"); return; } /* XXX to do */ break; case GL_FRAGMENT_PROGRAM_NV: if (!ctx->Extensions.NV_fragment_program) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramRegisterfvMESA(target)"); return; } if (!ctx->FragmentProgram.Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA"); return; } if (reg[0] == 'R') { /* Temp register */ GLint i = _mesa_atoi(reg + 1); if (i >= (GLint)ctx->Const.MaxFragmentProgramTemps) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramRegisterfvMESA(registerName)"); return; } COPY_4V(v, ctx->FragmentProgram.Machine.Temporaries[i]); } else if (reg[0] == 'f' && reg[1] == '[') { /* Fragment input attribute */ GLuint i; for (i = 0; i < ctx->Const.MaxFragmentProgramAttribs; i++) { const char *name = _mesa_nv_fragment_input_register_name(i); if (_mesa_strncmp(reg + 2, name, 4) == 0) { COPY_4V(v, ctx->FragmentProgram.Machine.Inputs[i]); return; } } _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramRegisterfvMESA(registerName)"); return; } else if (_mesa_strcmp(reg, "o[COLR]") == 0) { /* Fragment output color */ COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_COLR]); } else if (_mesa_strcmp(reg, "o[COLH]") == 0) { /* Fragment output color */ COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_COLH]); } else if (_mesa_strcmp(reg, "o[DEPR]") == 0) { /* Fragment output depth */ COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_DEPR]); } else { /* try user-defined identifiers */ const GLfloat *value = _mesa_lookup_parameter_value( ctx->FragmentProgram.Current->Parameters, -1, reg); if (value) { COPY_4V(v, value); } else { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramRegisterfvMESA(registerName)"); return; } } break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramRegisterfvMESA(target)"); return; } }
char *slang_string_concat (char *dst, const char *src) { return _mesa_strcpy (dst + _mesa_strlen (dst), src); }
void GLAPIENTRY _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params) { const struct gl_program_constants *limits; struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { prog = &(ctx->VertexProgram.Current->Base); limits = &ctx->Const.VertexProgram; } else if (target == GL_FRAGMENT_PROGRAM_ARB && ctx->Extensions.ARB_fragment_program) { prog = &(ctx->FragmentProgram.Current->Base); limits = &ctx->Const.FragmentProgram; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); return; } ASSERT(prog); ASSERT(limits); /* Queries supported for both vertex and fragment programs */ switch (pname) { case GL_PROGRAM_LENGTH_ARB: *params = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0; return; case GL_PROGRAM_FORMAT_ARB: *params = prog->Format; return; case GL_PROGRAM_BINDING_ARB: *params = prog->Id; return; case GL_PROGRAM_INSTRUCTIONS_ARB: *params = prog->NumInstructions; return; case GL_MAX_PROGRAM_INSTRUCTIONS_ARB: *params = limits->MaxInstructions; return; case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB: *params = prog->NumNativeInstructions; return; case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB: *params = limits->MaxNativeInstructions; return; case GL_PROGRAM_TEMPORARIES_ARB: *params = prog->NumTemporaries; return; case GL_MAX_PROGRAM_TEMPORARIES_ARB: *params = limits->MaxTemps; return; case GL_PROGRAM_NATIVE_TEMPORARIES_ARB: *params = prog->NumNativeTemporaries; return; case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB: *params = limits->MaxNativeTemps; return; case GL_PROGRAM_PARAMETERS_ARB: *params = prog->NumParameters; return; case GL_MAX_PROGRAM_PARAMETERS_ARB: *params = limits->MaxParameters; return; case GL_PROGRAM_NATIVE_PARAMETERS_ARB: *params = prog->NumNativeParameters; return; case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB: *params = limits->MaxNativeParameters; return; case GL_PROGRAM_ATTRIBS_ARB: *params = prog->NumAttributes; return; case GL_MAX_PROGRAM_ATTRIBS_ARB: *params = limits->MaxAttribs; return; case GL_PROGRAM_NATIVE_ATTRIBS_ARB: *params = prog->NumNativeAttributes; return; case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB: *params = limits->MaxNativeAttribs; return; case GL_PROGRAM_ADDRESS_REGISTERS_ARB: *params = prog->NumAddressRegs; return; case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB: *params = limits->MaxAddressRegs; return; case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: *params = prog->NumNativeAddressRegs; return; case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: *params = limits->MaxNativeAddressRegs; return; case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB: *params = limits->MaxLocalParams; return; case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB: *params = limits->MaxEnvParams; return; case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: /* * XXX we may not really need a driver callback here. * If the number of native instructions, registers, etc. used * are all below the maximums, we could return true. * The spec says that even if this query returns true, there's * no guarantee that the program will run in hardware. */ if (prog->Id == 0) { /* default/null program */ *params = GL_FALSE; } else if (ctx->Driver.IsProgramNative) { /* ask the driver */ *params = ctx->Driver.IsProgramNative( ctx, target, prog ); } else { /* probably running in software */ *params = GL_TRUE; } return; default: /* continue with fragment-program only queries below */ break; } /* * The following apply to fragment programs only (at this time) */ if (target == GL_FRAGMENT_PROGRAM_ARB) { const struct gl_fragment_program *fp = ctx->FragmentProgram.Current; switch (pname) { case GL_PROGRAM_ALU_INSTRUCTIONS_ARB: *params = fp->Base.NumNativeAluInstructions; return; case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: *params = fp->Base.NumAluInstructions; return; case GL_PROGRAM_TEX_INSTRUCTIONS_ARB: *params = fp->Base.NumTexInstructions; return; case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: *params = fp->Base.NumNativeTexInstructions; return; case GL_PROGRAM_TEX_INDIRECTIONS_ARB: *params = fp->Base.NumTexIndirections; return; case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: *params = fp->Base.NumNativeTexIndirections; return; case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB: *params = limits->MaxAluInstructions; return; case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: *params = limits->MaxNativeAluInstructions; return; case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB: *params = limits->MaxTexInstructions; return; case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: *params = limits->MaxNativeTexInstructions; return; case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB: *params = limits->MaxTexIndirections; return; case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: *params = limits->MaxNativeTexIndirections; return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); return; } } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); return; } }
/** * Return a string describing the CPU architexture and extensions that * Mesa is using (such as SSE or Altivec). * \return information string, free it with _mesa_free() */ char * _mesa_get_cpu_string(void) { #define MAX_STRING 50 char *buffer; buffer = (char *) _mesa_malloc(MAX_STRING); if (!buffer) return NULL; buffer[0] = 0; #ifdef USE_X86_ASM if (_mesa_x86_cpu_features) { strcat(buffer, "x86"); } # ifdef USE_MMX_ASM if (cpu_has_mmx) { strcat(buffer, (cpu_has_mmxext) ? "/MMX+" : "/MMX"); } # endif # ifdef USE_3DNOW_ASM if (cpu_has_3dnow) { strcat(buffer, (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!"); } # endif # ifdef USE_SSE_ASM if (cpu_has_xmm) { strcat(buffer, (cpu_has_xmm2) ? "/SSE2" : "/SSE"); } # endif #elif defined(USE_SPARC_ASM) strcat(buffer, "SPARC"); #elif defined(USE_PPC_ASM) if (_mesa_ppc_cpu_features) { strcat(buffer, (cpu_has_64) ? "PowerPC 64" : "PowerPC"); } # ifdef USE_VMX_ASM if (cpu_has_vmx) { strcat(buffer, "/Altivec"); } # endif if (! cpu_has_fpu) { strcat(buffer, "/No FPU"); } #endif assert(_mesa_strlen(buffer) < MAX_STRING); return buffer; }
static GLboolean execute_expression (slang_string *output, const byte *code, GLuint *pi, GLint *result, slang_info_log *elog) { GLuint i = *pi; GLint stack[EXECUTION_STACK_SIZE]; GLuint sp = EXECUTION_STACK_SIZE; while (code[i] != OP_END) { switch (code[i++]) { case OP_PUSHINT: i++; PUSH(_mesa_atoi ((const char *) (&code[i]))); i += _mesa_strlen ((const char *) (&code[i])) + 1; break; case OP_LOGICALOR: BINARY(||); break; case OP_LOGICALAND: BINARY(&&); break; case OP_OR: BINARY(|); break; case OP_XOR: BINARY(^); break; case OP_AND: BINARY(&); break; case OP_EQUAL: BINARY(==); break; case OP_NOTEQUAL: BINARY(!=); break; case OP_LESSEQUAL: BINARY(<=); break; case OP_GREATEREQUAL: BINARY(>=); break; case OP_LESS: BINARY(<); break; case OP_GREATER: BINARY(>); break; case OP_LEFTSHIFT: BINARY(<<); break; case OP_RIGHTSHIFT: BINARY(>>); break; case OP_ADD: BINARY(+); break; case OP_SUBTRACT: BINARY(-); break; case OP_MULTIPLY: BINARY(*); break; case OP_DIVIDE: BINARYDIV(/); break; case OP_MODULUS: BINARYDIV(%); break; case OP_PLUS: UNARY(+); break; case OP_MINUS: UNARY(-); break; case OP_NEGATE: UNARY(!); break; case OP_COMPLEMENT: UNARY(~); break; default: assert (0); } } /* Write-back the index skipping the OP_END. */ *pi = i + 1; /* There should be exactly one value left on the stack. This is our result. */ POP(*result); pp_annotate (output, "%d ", *result); assert (sp == EXECUTION_STACK_SIZE); return GL_TRUE; }
static GLboolean preprocess_source (slang_string *output, const char *source, grammar pid, grammar eid, slang_info_log *elog, const struct gl_extensions *extensions, struct gl_sl_pragmas *pragmas) { static const char *predefined[] = { "__FILE__", "__LINE__", "__VERSION__", #if FEATURE_es2_glsl "GL_ES", "GL_FRAGMENT_PRECISION_HIGH", #endif NULL }; byte *prod; GLuint size, i; pp_state state; if (!grammar_fast_check (pid, (const byte *) (source), &prod, &size, 65536)) { grammar_error_to_log (elog); return GL_FALSE; } pp_state_init (&state, elog, extensions); pp_pragmas_init (pragmas); /* add the predefined symbols to the symbol table */ for (i = 0; predefined[i]; i++) { pp_symbol *symbol = NULL; symbol = pp_symbols_push(&state.symbols); assert(symbol); slang_string_pushs(&symbol->name, predefined[i], _mesa_strlen(predefined[i])); } i = 0; while (i < size) { if (prod[i] != ESCAPE_TOKEN) { if (state.cond.top->effective) { slang_string input; expand_state es; /* Eat only one line of source code to expand it. * FIXME: This approach has one drawback. If a macro with parameters spans across * multiple lines, the preprocessor will raise an error. */ slang_string_init (&input); while (prod[i] != '\0' && prod[i] != '\n') slang_string_pushc (&input, prod[i++]); if (prod[i] != '\0') slang_string_pushc (&input, prod[i++]); /* Increment line number. */ state.line++; es.output = output; es.input = slang_string_cstr (&input); es.state = &state; if (!expand (&es, &state.symbols)) goto error; slang_string_free (&input); } else { /* Condition stack is disabled - keep track on line numbers and output only newlines. */ if (prod[i] == '\n') { state.line++; /*pp_annotate (output, "%c", prod[i]);*/ } else { /*pp_annotate (output, "%c", prod[i]);*/ } i++; } } else { const char *id; GLuint idlen; GLubyte token; i++; token = prod[i++]; switch (token) { case TOKEN_END: /* End of source string. * Check if all #ifs have been terminated by matching #endifs. * On condition stack there should be only the global condition context. */ if (state.cond.top->endif_required) { slang_info_log_error (elog, "end of source without matching #endif."); return GL_FALSE; } break; case TOKEN_DEFINE: { pp_symbol *symbol = NULL; /* Parse macro name. */ id = (const char *) (&prod[i]); idlen = _mesa_strlen (id); if (state.cond.top->effective) { pp_annotate (output, "// #define %s(", id); /* If the symbol is already defined, override it. */ symbol = pp_symbols_find (&state.symbols, id); if (symbol == NULL) { symbol = pp_symbols_push (&state.symbols); if (symbol == NULL) goto error; slang_string_pushs (&symbol->name, id, idlen); } else { pp_symbol_reset (symbol); } } i += idlen + 1; /* Parse optional macro parameters. */ while (prod[i++] != PARAM_END) { pp_symbol *param; id = (const char *) (&prod[i]); idlen = _mesa_strlen (id); if (state.cond.top->effective) { pp_annotate (output, "%s, ", id); param = pp_symbols_push (&symbol->parameters); if (param == NULL) goto error; slang_string_pushs (¶m->name, id, idlen); } i += idlen + 1; } /* Parse macro replacement. */ id = (const char *) (&prod[i]); idlen = _mesa_strlen (id); if (state.cond.top->effective) { slang_string replacement; expand_state es; pp_annotate (output, ") %s", id); slang_string_init(&replacement); slang_string_pushs(&replacement, id, idlen); /* Expand macro replacement. */ es.output = &symbol->replacement; es.input = slang_string_cstr(&replacement); es.state = &state; if (!expand(&es, &state.symbols)) { slang_string_free(&replacement); goto error; } slang_string_free(&replacement); } i += idlen + 1; } break; case TOKEN_UNDEF: id = (const char *) (&prod[i]); i += _mesa_strlen (id) + 1; if (state.cond.top->effective) { pp_symbol *symbol; pp_annotate (output, "// #undef %s", id); /* Try to find symbol with given name and remove it. */ symbol = pp_symbols_find (&state.symbols, id); if (symbol != NULL) if (!pp_symbols_erase (&state.symbols, symbol)) goto error; } break; case TOKEN_IF: { GLint result; /* Parse #if expression end execute it. */ pp_annotate (output, "// #if "); if (!parse_if (output, prod, &i, &result, &state, eid)) goto error; /* Push new condition on the stack. */ if (!pp_cond_stack_push (&state.cond, state.elog)) goto error; state.cond.top->current = result ? GL_TRUE : GL_FALSE; state.cond.top->else_allowed = GL_TRUE; state.cond.top->endif_required = GL_TRUE; pp_cond_stack_reevaluate (&state.cond); } break; case TOKEN_ELSE: /* Check if #else is alloved here. */ if (!state.cond.top->else_allowed) { slang_info_log_error (elog, "#else without matching #if."); goto error; } /* Negate current condition and reevaluate it. */ state.cond.top->current = !state.cond.top->current; state.cond.top->else_allowed = GL_FALSE; pp_cond_stack_reevaluate (&state.cond); if (state.cond.top->effective) pp_annotate (output, "// #else"); break; case TOKEN_ELIF: /* Check if #elif is alloved here. */ if (!state.cond.top->else_allowed) { slang_info_log_error (elog, "#elif without matching #if."); goto error; } /* Negate current condition and reevaluate it. */ state.cond.top->current = !state.cond.top->current; pp_cond_stack_reevaluate (&state.cond); if (state.cond.top->effective) pp_annotate (output, "// #elif "); { GLint result; /* Parse #elif expression end execute it. */ if (!parse_if (output, prod, &i, &result, &state, eid)) goto error; /* Update current condition and reevaluate it. */ state.cond.top->current = result ? GL_TRUE : GL_FALSE; pp_cond_stack_reevaluate (&state.cond); } break; case TOKEN_ENDIF: /* Check if #endif is alloved here. */ if (!state.cond.top->endif_required) { slang_info_log_error (elog, "#endif without matching #if."); goto error; } /* Pop the condition off the stack. */ state.cond.top++; if (state.cond.top->effective) pp_annotate (output, "// #endif"); break; case TOKEN_EXTENSION: /* Parse the extension name. */ id = (const char *) (&prod[i]); i += _mesa_strlen (id) + 1; if (state.cond.top->effective) pp_annotate (output, "// #extension %s: ", id); /* Parse and apply extension behavior. */ if (state.cond.top->effective) { switch (prod[i++]) { case BEHAVIOR_REQUIRE: pp_annotate (output, "require"); if (!pp_ext_set (&state.ext, id, GL_TRUE)) { if (_mesa_strcmp (id, "all") == 0) { slang_info_log_error (elog, "require: bad behavior for #extension all."); goto error; } else { slang_info_log_error (elog, "%s: required extension is not supported.", id); goto error; } } break; case BEHAVIOR_ENABLE: pp_annotate (output, "enable"); if (!pp_ext_set (&state.ext, id, GL_TRUE)) { if (_mesa_strcmp (id, "all") == 0) { slang_info_log_error (elog, "enable: bad behavior for #extension all."); goto error; } else { slang_info_log_warning (elog, "%s: enabled extension is not supported.", id); } } break; case BEHAVIOR_WARN: pp_annotate (output, "warn"); if (!pp_ext_set (&state.ext, id, GL_TRUE)) { if (_mesa_strcmp (id, "all") != 0) { slang_info_log_warning (elog, "%s: enabled extension is not supported.", id); } } break; case BEHAVIOR_DISABLE: pp_annotate (output, "disable"); if (!pp_ext_set (&state.ext, id, GL_FALSE)) { if (_mesa_strcmp (id, "all") == 0) { pp_ext_disable_all (&state.ext); } else { slang_info_log_warning (elog, "%s: disabled extension is not supported.", id); } } break; default: assert (0); } } break; case TOKEN_PRAGMA: { GLint have_param; const char *pragma, *param; pragma = (const char *) (&prod[i]); i += _mesa_strlen(pragma) + 1; have_param = (prod[i++] == PRAGMA_PARAM); if (have_param) { param = (const char *) (&prod[i]); i += _mesa_strlen(param) + 1; } else { param = NULL; } pp_pragma(pragmas, pragma, param); } break; case TOKEN_LINE: id = (const char *) (&prod[i]); i += _mesa_strlen (id) + 1; if (state.cond.top->effective) { slang_string buffer; GLuint count; GLint results[2]; expand_state es; slang_string_init (&buffer); state.line++; es.output = &buffer; es.input = id; es.state = &state; if (!expand (&es, &state.symbols)) goto error; pp_annotate (output, "// #line "); count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&buffer)), results, state.elog); slang_string_free (&buffer); if (count == 0) goto error; state.line = results[0] - 1; if (count == 2) state.file = results[1]; } break; } } } /* Check for missing #endifs. */ if (state.cond.top->endif_required) { slang_info_log_error (elog, "#endif expected but end of source found."); goto error; } grammar_alloc_free(prod); pp_state_free (&state); return GL_TRUE; error: grammar_alloc_free(prod); pp_state_free (&state); return GL_FALSE; }