/*
* Mesa 3-D graphics library
- * Version: 5.1
*
- * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2007 Brian Paul 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"),
* 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
- * BRIAN PAUL 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.
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/**
* \file arbprogram.c
- * \brief ARB_vertex/fragment_program state management functions.
+ * ARB_vertex/fragment_program state management functions.
* \author Brian Paul
*/
-#include "glheader.h"
-#include "context.h"
-#include "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
-#include "arbprogram.h"
-
-
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/arbprogram.h"
+#include "main/shaderapi.h"
+#include "program/arbprogparse.h"
+#include "program/program.h"
+#include "program/prog_print.h"
+
+#ifdef _MSC_VER
+#include <stdlib.h>
+#define PATH_MAX _MAX_PATH
+#endif
-void
-_mesa_VertexAttrib1sARB(GLuint index, GLshort x)
+/**
+ * Bind a program (make it current)
+ * \note Called from the GL API dispatcher by both glBindProgramNV
+ * and glBindProgramARB.
+ */
+void GLAPIENTRY
+_mesa_BindProgramARB(GLenum target, GLuint id)
{
-}
+ struct gl_program *curProg, *newProg;
+ GET_CURRENT_CONTEXT(ctx);
-void
-_mesa_VertexAttrib1fARB(GLuint index, GLfloat x)
-{
-}
+ /* Error-check target and get curProg */
+ if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
+ curProg = &ctx->VertexProgram.Current->Base;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ curProg = &ctx->FragmentProgram.Current->Base;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)");
+ return;
+ }
-void
-_mesa_VertexAttrib1dARB(GLuint index, GLdouble x)
-{
-}
+ /*
+ * Get pointer to new program to bind.
+ * NOTE: binding to a non-existant program is not an error.
+ * That's supposed to be caught in glBegin.
+ */
+ if (id == 0) {
+ /* Bind a default program */
+ newProg = NULL;
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ newProg = &ctx->Shared->DefaultVertexProgram->Base;
+ else
+ newProg = &ctx->Shared->DefaultFragmentProgram->Base;
+ }
+ else {
+ /* Bind a user program */
+ newProg = _mesa_lookup_program(ctx, id);
+ if (!newProg || newProg == &_mesa_DummyProgram) {
+ /* allocate a new program now */
+ newProg = ctx->Driver.NewProgram(ctx, target, id);
+ if (!newProg) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramARB");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
+ }
+ else if (newProg->Target != target) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindProgramARB(target mismatch)");
+ return;
+ }
+ }
-void
-_mesa_VertexAttrib2sARB(GLuint index, GLshort x, GLshort y)
-{
-}
+ /** All error checking is complete now **/
-void
-_mesa_VertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y)
-{
-}
+ if (curProg->Id == id) {
+ /* binding same program - no change */
+ return;
+ }
-void
-_mesa_VertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y)
-{
-}
+ /* signal new program (and its new constants) */
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-void
-_mesa_VertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z)
-{
-}
+ /* bind newProg */
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ gl_vertex_program(newProg));
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ gl_fragment_program(newProg));
+ }
-void
-_mesa_VertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z)
-{
-}
+ /* Never null pointers */
+ assert(ctx->VertexProgram.Current);
+ assert(ctx->FragmentProgram.Current);
-void
-_mesa_VertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z)
-{
+ if (ctx->Driver.BindProgram)
+ ctx->Driver.BindProgram(ctx, target, newProg);
}
-void
-_mesa_VertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
-{
-}
-void
-_mesa_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
-}
-
-void
-_mesa_VertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+/**
+ * Delete a list of programs.
+ * \note Not compiled into display lists.
+ * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
+ */
+void GLAPIENTRY
+_mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids)
{
-}
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
-void
-_mesa_VertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
-{
-}
+ FLUSH_VERTICES(ctx, 0);
-void
-_mesa_VertexAttrib1svARB(GLuint index, const GLshort *v)
-{
-}
+ if (n < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
+ return;
+ }
-void
-_mesa_VertexAttrib1fvARB(GLuint index, const GLfloat *v)
-{
+ for (i = 0; i < n; i++) {
+ if (ids[i] != 0) {
+ struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
+ if (prog == &_mesa_DummyProgram) {
+ _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+ }
+ else if (prog) {
+ /* Unbind program if necessary */
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ if (ctx->VertexProgram.Current &&
+ ctx->VertexProgram.Current->Base.Id == ids[i]) {
+ /* unbind this currently bound program */
+ _mesa_BindProgramARB(prog->Target, 0);
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ if (ctx->FragmentProgram.Current &&
+ ctx->FragmentProgram.Current->Base.Id == ids[i]) {
+ /* unbind this currently bound program */
+ _mesa_BindProgramARB(prog->Target, 0);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
+ return;
+ }
+ /* The ID is immediately available for re-use now */
+ _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+ _mesa_reference_program(ctx, &prog, NULL);
+ }
+ }
+ }
}
-void
-_mesa_VertexAttrib1dvARB(GLuint index, const GLdouble *v)
-{
-}
-void
-_mesa_VertexAttrib2svARB(GLuint index, const GLshort *v)
+/**
+ * Generate a list of new program identifiers.
+ * \note Not compiled into display lists.
+ * \note Called by both glGenProgramsNV and glGenProgramsARB.
+ */
+void GLAPIENTRY
+_mesa_GenProgramsARB(GLsizei n, GLuint *ids)
{
-}
+ GLuint first;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
-void
-_mesa_VertexAttrib2fvARB(GLuint index, const GLfloat *v)
-{
-}
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
+ return;
+ }
-void
-_mesa_VertexAttrib2dvARB(GLuint index, const GLdouble *v)
-{
-}
+ if (!ids)
+ return;
-void
-_mesa_VertexAttrib3svARB(GLuint index, const GLshort *v)
-{
-}
+ _mesa_HashLockMutex(ctx->Shared->Programs);
-void
-_mesa_VertexAttrib3fvARB(GLuint index, const GLfloat *v)
-{
-}
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
-void
-_mesa_VertexAttrib3dvARB(GLuint index, const GLdouble *v)
-{
-}
+ /* Insert pointer to dummy program as placeholder */
+ for (i = 0; i < (GLuint) n; i++) {
+ _mesa_HashInsertLocked(ctx->Shared->Programs, first + i,
+ &_mesa_DummyProgram);
+ }
-void
-_mesa_VertexAttrib4bvARB(GLuint index, const GLbyte *v)
-{
-}
+ _mesa_HashUnlockMutex(ctx->Shared->Programs);
-void
-_mesa_VertexAttrib4svARB(GLuint index, const GLshort *v)
-{
+ /* Return the program names */
+ for (i = 0; i < (GLuint) n; i++) {
+ ids[i] = first + i;
+ }
}
-void
-_mesa_VertexAttrib4ivARB(GLuint index, const GLint *v)
-{
-}
-void
-_mesa_VertexAttrib4ubvARB(GLuint index, const GLubyte *v)
+/**
+ * Determine if id names a vertex or fragment program.
+ * \note Not compiled into display lists.
+ * \note Called from both glIsProgramNV and glIsProgramARB.
+ * \param id is the program identifier
+ * \return GL_TRUE if id is a program, else GL_FALSE.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsProgramARB(GLuint id)
{
-}
+ struct gl_program *prog = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-void
-_mesa_VertexAttrib4usvARB(GLuint index, const GLushort *v)
-{
-}
+ if (id == 0)
+ return GL_FALSE;
-void
-_mesa_VertexAttrib4uivARB(GLuint index, const GLuint *v)
-{
+ prog = _mesa_lookup_program(ctx, id);
+ if (prog && (prog != &_mesa_DummyProgram))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
}
-void
-_mesa_VertexAttrib4fvARB(GLuint index, const GLfloat *v)
+static GLboolean
+get_local_param_pointer(struct gl_context *ctx, const char *func,
+ GLenum target, GLuint index, GLfloat **param)
{
-}
+ struct gl_program *prog;
+ GLuint maxParams;
-void
-_mesa_VertexAttrib4dvARB(GLuint index, const GLdouble *v)
-{
-}
+ if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ prog = &(ctx->VertexProgram.Current->Base);
+ maxParams = ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ prog = &(ctx->FragmentProgram.Current->Base);
+ maxParams = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(target)", func);
+ return GL_FALSE;
+ }
-void
-_mesa_VertexAttrib4NbvARB(GLuint index, const GLbyte *v)
-{
-}
+ if (index >= maxParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return GL_FALSE;
+ }
-void
-_mesa_VertexAttrib4NsvARB(GLuint index, const GLshort *v)
-{
-}
+ if (!prog->LocalParams) {
+ prog->LocalParams = calloc(maxParams, sizeof(float[4]));
+ if (!prog->LocalParams)
+ return GL_FALSE;
+ }
-void
-_mesa_VertexAttrib4NivARB(GLuint index, const GLint *v)
-{
+ *param = prog->LocalParams[index];
+ return GL_TRUE;
}
-void
-_mesa_VertexAttrib4NubvARB(GLuint index, const GLubyte *v)
-{
-}
-void
-_mesa_VertexAttrib4NusvARB(GLuint index, const GLushort *v)
+static GLboolean
+get_env_param_pointer(struct gl_context *ctx, const char *func,
+ GLenum target, GLuint index, GLfloat **param)
{
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ if (index >= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return GL_FALSE;
+ }
+ *param = ctx->FragmentProgram.Parameters[index];
+ return GL_TRUE;
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB &&
+ ctx->Extensions.ARB_vertex_program) {
+ if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return GL_FALSE;
+ }
+ *param = ctx->VertexProgram.Parameters[index];
+ return GL_TRUE;
+ } else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
+ return GL_FALSE;
+ }
}
-void
-_mesa_VertexAttrib4NuivARB(GLuint index, const GLuint *v)
+void GLAPIENTRY
+_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
+ const GLvoid *string)
{
-}
+ struct gl_program *base;
+ bool failed;
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-void
-_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
- GLboolean normalized, GLsizei stride,
- const GLvoid *pointer)
-{
-}
+ if (!ctx->Extensions.ARB_vertex_program
+ && !ctx->Extensions.ARB_fragment_program) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
+ return;
+ }
+ if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
+ return;
+ }
-void
-_mesa_EnableVertexAttribArrayARB(GLuint index)
-{
-}
+ if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
+ struct gl_vertex_program *prog = ctx->VertexProgram.Current;
+ _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
+ base = & prog->Base;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
+ _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
-void
-_mesa_DisableVertexAttribArrayARB(GLuint index)
-{
-}
+ base = & prog->Base;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
+ return;
+ }
+ failed = ctx->Program.ErrorPos != -1;
-void
-_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
-{
-}
+ if (!failed) {
+ /* finally, give the program to the driver for translation/checking */
+ if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
+ failed = true;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glProgramStringARB(rejected by driver");
+ }
+ }
+ if (ctx->_Shader->Flags & GLSL_DUMP) {
+ const char *shader_type =
+ target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
+
+ fprintf(stderr, "ARB_%s_program source for program %d:\n",
+ shader_type, base->Id);
+ fprintf(stderr, "%s\n", (const char *) string);
+
+ if (failed) {
+ fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
+ shader_type, base->Id);
+ } else {
+ fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
+ shader_type, base->Id);
+ _mesa_print_program(base);
+ fprintf(stderr, "\n");
+ }
+ fflush(stderr);
+ }
-void
-_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
-{
+ /* Capture vp-*.shader_test/fp-*.shader_test files. */
+ const char *capture_path = _mesa_get_shader_capture_path();
+ if (capture_path != NULL) {
+ FILE *file;
+ char filename[PATH_MAX];
+ const char *shader_type =
+ target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
+
+ _mesa_snprintf(filename, sizeof(filename), "%s/%cp-%u.shader_test",
+ capture_path, shader_type[0], base->Id);
+ file = fopen(filename, "w");
+ if (file) {
+ fprintf(file,
+ "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
+ shader_type, shader_type, (const char *) string);
+ fclose(file);
+ } else {
+ _mesa_warning(ctx, "Failed to open %s", filename);
+ }
+ }
}
-void
-_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w)
{
+ _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
+ (GLfloat) z, (GLfloat) w);
}
-void
-_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params)
{
+ _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
+ (GLfloat) params[1], (GLfloat) params[2],
+ (GLfloat) params[3]);
}
-void
-_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
- const GLvoid *string)
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
-}
-
+ GLfloat *param;
-void
-_mesa_BindProgramARB(GLenum target, GLuint program)
-{
-}
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
-void
-_mesa_DeleteProgramsARB(GLsizei n, const GLuint *programs)
-{
+ if (get_env_param_pointer(ctx, "glProgramEnvParameter",
+ target, index, ¶m)) {
+ ASSIGN_4V(param, x, y, z, w);
+ }
}
-void
-_mesa_GenProgramsARB(GLsizei n, GLuint *programs)
-{
-}
-
-void
-_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
- GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params)
{
-}
+ GLfloat *param;
+ GET_CURRENT_CONTEXT(ctx);
-void
-_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
- const GLdouble *params)
-{
-}
-
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
-void
-_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
- GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
+ if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
+ target, index, ¶m)) {
+ memcpy(param, params, 4 * sizeof(GLfloat));
+ }
}
-void
-_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
- const GLfloat *params)
+void GLAPIENTRY
+_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params)
{
-}
-
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat * dest;
-#if 111
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
-void
-_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
- GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ if (count <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
+ }
- if (target == GL_FRAGMENT_PROGRAM_NV) {
- struct fragment_program *fprog = ctx->FragmentProgram.Current;
- if (!fprog) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
return;
}
- if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
+ dest = ctx->FragmentProgram.Parameters[index];
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
return;
}
- fprog->Base.LocalParams[index][0] = x;
- fprog->Base.LocalParams[index][1] = y;
- fprog->Base.LocalParams[index][2] = z;
- fprog->Base.LocalParams[index][3] = w;
+ dest = ctx->VertexProgram.Parameters[index];
}
else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
return;
}
+
+ memcpy(dest, params, count * 4 * sizeof(GLfloat));
}
-void
-_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
- const GLfloat *params)
+void GLAPIENTRY
+_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
+ GLdouble *params)
{
- glProgramLocalParameter4fARB(target, index, params[0], params[1],
- params[2], params[3]);
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *fparam;
+
+ if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
+ target, index, &fparam)) {
+ COPY_4V(params, fparam);
+ }
}
-void
-_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
- GLdouble x, GLdouble y,
- GLdouble z, GLdouble w)
+void GLAPIENTRY
+_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
+ GLfloat *params)
{
- glProgramLocalParameter4fARB(target, index, (GLfloat)x, (GLfloat)y,
- (GLfloat)z, (GLfloat)w);
-}
+ GLfloat *param;
+ GET_CURRENT_CONTEXT(ctx);
-void
-_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
- const GLdouble *params)
-{
- glProgramLocalParameter4fARB(target, index, (GLfloat)params[0],
- (GLfloat)params[1], (GLfloat)params[2],
- (GLfloat)params[3]);
+ if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
+ target, index, ¶m)) {
+ COPY_4V(params, param);
+ }
}
-void
-_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
- GLfloat *params)
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
- struct program *prog;
- GLuint maxParams;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ GLfloat *param;
- if (target == GL_VERTEX_PROGRAM_ARB
- && ctx->Extensions.ARB_vertex_program) {
- prog = &(ctx->VertexProgram.Current->Base);
- maxParams = ctx->Const.MaxVertexProgramParams;
- }
- else if ((target == GL_FRAGMENT_PROGRAM_ARB
- && ctx->Extensions.ARB_fragment_program) ||
- (target == GL_FRAGMENT_PROGRAM_NV
- && ctx->Extensions.NV_fragment_program)) {
- prog = &(ctx->FragmentProgram.Current->Base);
- maxParams = ctx->Const.MaxFragmentProgramParams;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetProgramLocalParameterARB(target)");
- return;
- }
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
- if (index >= maxParams) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramLocalParameterARB(index)");
- return;
+ if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
+ target, index, ¶m)) {
+ assert(index < MAX_PROGRAM_LOCAL_PARAMS);
+ ASSIGN_4V(param, x, y, z, w);
}
-
- ASSERT(prog);
- params[0] = prog->LocalParams[index][0];
- params[1] = prog->LocalParams[index][1];
- params[2] = prog->LocalParams[index][2];
- params[3] = prog->LocalParams[index][3];
}
-void
-_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
- GLdouble *params)
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params)
{
- GLfloat floatParams[4];
- glGetProgramLocalParameterfvARB(target, index, floatParams);
- COPY_4V(params, floatParams);
+ _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
+ params[2], params[3]);
}
-#else
-
-void
-_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
- GLdouble x, GLdouble y,
- GLdouble z, GLdouble w)
+void GLAPIENTRY
+_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params)
{
-}
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
-void
-_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
- const GLdouble *params)
-{
-}
+ if (count <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
+ }
+ if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
+ target, index, &dest)) {
+ GLuint maxParams = target == GL_FRAGMENT_PROGRAM_ARB ?
+ ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams :
+ ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
-void
-_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
- GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
+ if ((index + count) > maxParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glProgramLocalParameters4fvEXT(index + count)");
+ return;
+ }
+
+ memcpy(dest, params, count * 4 * sizeof(GLfloat));
+ }
}
-void
-_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
- const GLfloat *params)
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y,
+ GLdouble z, GLdouble w)
{
+ _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
+ (GLfloat) z, (GLfloat) w);
}
-#endif
-void
-_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
- GLdouble *params)
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params)
{
+ _mesa_ProgramLocalParameter4fARB(target, index,
+ (GLfloat) params[0], (GLfloat) params[1],
+ (GLfloat) params[2], (GLfloat) params[3]);
}
-void
-_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
- GLfloat *params)
+void GLAPIENTRY
+_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
+ GLfloat *params)
{
+ GLfloat *param;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
+ target, index, ¶m)) {
+ COPY_4V(params, param);
+ }
}
-#if 000
-void
+void GLAPIENTRY
_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
GLdouble *params)
{
-}
-
+ GLfloat *param;
+ GET_CURRENT_CONTEXT(ctx);
-void
-_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
- GLfloat *params)
-{
+ if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
+ target, index, ¶m)) {
+ COPY_4V(params, param);
+ }
}
-#endif
-
-void
+void GLAPIENTRY
_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
{
- struct program *prog;
+ 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) {
+ if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
prog = &(ctx->VertexProgram.Current->Base);
+ limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
}
- else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
prog = &(ctx->FragmentProgram.Current->Base);
+ limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
return;
}
- ASSERT(prog);
+ assert(prog);
+ assert(limits);
+ /* Queries supported for both vertex and fragment programs */
switch (pname) {
case GL_PROGRAM_LENGTH_ARB:
- *params = prog->String ? _mesa_strlen((char *) prog->String) : 0;
- break;
+ *params
+ = prog->String ? (GLint) strlen((char *) prog->String) : 0;
+ return;
case GL_PROGRAM_FORMAT_ARB:
*params = prog->Format;
- break;
+ return;
case GL_PROGRAM_BINDING_ARB:
*params = prog->Id;
- break;
+ return;
case GL_PROGRAM_INSTRUCTIONS_ARB:
*params = prog->NumInstructions;
- break;
+ 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:
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
+ /*
+ * 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;
}
}
-void
+void GLAPIENTRY
_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
{
- struct program *prog;
+ 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);
return;
}
- ASSERT(prog);
+ assert(prog);
if (pname != GL_PROGRAM_STRING_ARB) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
return;
}
- MEMCPY(string, prog->String, _mesa_strlen((char *) prog->String));
-}
-
-
-GLboolean
-_mesa_IsProgramARB(GLuint program)
-{
- struct program *prog;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
- if (program == 0)
- return GL_FALSE;
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, program);
- if (prog && prog->Target)
- return GL_TRUE;
+ if (prog->String)
+ memcpy(dst, prog->String, strlen((char *) prog->String));
else
- return GL_FALSE;
+ *dst = '\0';
}