Browse Source

mesa: refactor: move _mesa_Bind/Gen/DeleteProgram() to arbprogram.c

No API-level functions now in program.c.
tags/mesa_7_1_rc4
Brian Paul 17 years ago
parent
commit
b7eea9a1ce
4 changed files with 213 additions and 226 deletions
  1. 202
    0
      src/mesa/shader/arbprogram.c
  2. 10
    0
      src/mesa/shader/arbprogram.h
  3. 1
    208
      src/mesa/shader/program.c
  4. 0
    18
      src/mesa/shader/program.h

+ 202
- 0
src/mesa/shader/arbprogram.c View File

@@ -33,12 +33,214 @@
#include "arbprogram.h"
#include "arbprogparse.h"
#include "context.h"
#include "hash.h"
#include "imports.h"
#include "macros.h"
#include "mtypes.h"
#include "program.h"



/**
* Mixing ARB and NV vertex/fragment programs can be tricky.
* Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
* but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
* The two different fragment program targets are supposed to be compatible
* to some extent (see GL_ARB_fragment_program spec).
* This function does the compatibility check.
*/
static GLboolean
compatible_program_targets(GLenum t1, GLenum t2)
{
if (t1 == t2)
return GL_TRUE;
if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV)
return GL_TRUE;
if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB)
return GL_TRUE;
return GL_FALSE;
}


/**
* Bind a program (make it current)
* \note Called from the GL API dispatcher by both glBindProgramNV
* and glBindProgramARB.
*/
void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id)
{
struct gl_program *curProg, *newProg;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);

FLUSH_VERTICES(ctx, _NEW_PROGRAM);

/* Error-check target and get curProg */
if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
(ctx->Extensions.NV_vertex_program ||
ctx->Extensions.ARB_vertex_program)) {
curProg = &ctx->VertexProgram.Current->Base;
}
else if ((target == GL_FRAGMENT_PROGRAM_NV
&& ctx->Extensions.NV_fragment_program) ||
(target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program)) {
curProg = &ctx->FragmentProgram.Current->Base;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
return;
}

/*
* 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) /* == GL_VERTEX_PROGRAM_NV */
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, "glBindProgramNV/ARB");
return;
}
_mesa_HashInsert(ctx->Shared->Programs, id, newProg);
}
else if (!compatible_program_targets(newProg->Target, target)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindProgramNV/ARB(target mismatch)");
return;
}
}

/** All error checking is complete now **/

if (curProg->Id == id) {
/* binding same program - no change */
return;
}

/* bind newProg */
if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
(struct gl_vertex_program *) newProg);
}
else if (target == GL_FRAGMENT_PROGRAM_NV ||
target == GL_FRAGMENT_PROGRAM_ARB) {
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
(struct gl_fragment_program *) newProg);
}

/* Never null pointers */
ASSERT(ctx->VertexProgram.Current);
ASSERT(ctx->FragmentProgram.Current);

if (ctx->Driver.BindProgram)
ctx->Driver.BindProgram(ctx, target, newProg);
}


/**
* Delete a list of programs.
* \note Not compiled into display lists.
* \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
*/
void GLAPIENTRY
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
GLint i;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

if (n < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
return;
}

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 */
if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */
prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
if (ctx->VertexProgram.Current &&
ctx->VertexProgram.Current->Base.Id == ids[i]) {
/* unbind this currently bound program */
_mesa_BindProgram(prog->Target, 0);
}
}
else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
if (ctx->FragmentProgram.Current &&
ctx->FragmentProgram.Current->Base.Id == ids[i]) {
/* unbind this currently bound program */
_mesa_BindProgram(prog->Target, 0);
}
}
else {
_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);
}
}
}
}


/**
* Generate a list of new program identifiers.
* \note Not compiled into display lists.
* \note Called by both glGenProgramsNV and glGenProgramsARB.
*/
void GLAPIENTRY
_mesa_GenPrograms(GLsizei n, GLuint *ids)
{
GLuint first;
GLuint i;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);

if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
return;
}

if (!ids)
return;

first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);

/* Insert pointer to dummy program as placeholder */
for (i = 0; i < (GLuint) n; i++) {
_mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
}

/* Return the program names */
for (i = 0; i < (GLuint) n; i++) {
ids[i] = first + i;
}
}


void GLAPIENTRY
_mesa_EnableVertexAttribArrayARB(GLuint index)
{

+ 10
- 0
src/mesa/shader/arbprogram.h View File

@@ -27,6 +27,16 @@
#define ARBPROGRAM_H


extern void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id);

extern void GLAPIENTRY
_mesa_DeletePrograms(GLsizei n, const GLuint *ids);

extern void GLAPIENTRY
_mesa_GenPrograms(GLsizei n, GLuint *ids);


extern void GLAPIENTRY
_mesa_EnableVertexAttribArrayARB(GLuint index);


+ 1
- 208
src/mesa/shader/program.c View File

@@ -78,7 +78,7 @@ _mesa_init_program(GLcontext *ctx)
/* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader
ctx->ATIFragmentShader.Enabled = GL_FALSE;
ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
assert(ctx->ATIFragmentShader.Current);
ctx->ATIFragmentShader.Current->RefCount++;
#endif
@@ -766,210 +766,3 @@ _mesa_find_free_register(const struct gl_program *prog, GLuint regFile)

return -1;
}



/**
* Mixing ARB and NV vertex/fragment programs can be tricky.
* Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
* but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
* The two different fragment program targets are supposed to be compatible
* to some extent (see GL_ARB_fragment_program spec).
* This function does the compatibility check.
*/
static GLboolean
compatible_program_targets(GLenum t1, GLenum t2)
{
if (t1 == t2)
return GL_TRUE;
if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV)
return GL_TRUE;
if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB)
return GL_TRUE;
return GL_FALSE;
}



/**********************************************************************/
/* API functions */
/**********************************************************************/


/**
* Bind a program (make it current)
* \note Called from the GL API dispatcher by both glBindProgramNV
* and glBindProgramARB.
*/
void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id)
{
struct gl_program *curProg, *newProg;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);

FLUSH_VERTICES(ctx, _NEW_PROGRAM);

/* Error-check target and get curProg */
if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
(ctx->Extensions.NV_vertex_program ||
ctx->Extensions.ARB_vertex_program)) {
curProg = &ctx->VertexProgram.Current->Base;
}
else if ((target == GL_FRAGMENT_PROGRAM_NV
&& ctx->Extensions.NV_fragment_program) ||
(target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program)) {
curProg = &ctx->FragmentProgram.Current->Base;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
return;
}

/*
* 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) /* == GL_VERTEX_PROGRAM_NV */
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, "glBindProgramNV/ARB");
return;
}
_mesa_HashInsert(ctx->Shared->Programs, id, newProg);
}
else if (!compatible_program_targets(newProg->Target, target)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindProgramNV/ARB(target mismatch)");
return;
}
}

/** All error checking is complete now **/

if (curProg->Id == id) {
/* binding same program - no change */
return;
}

/* bind newProg */
if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
(struct gl_vertex_program *) newProg);
}
else if (target == GL_FRAGMENT_PROGRAM_NV ||
target == GL_FRAGMENT_PROGRAM_ARB) {
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
(struct gl_fragment_program *) newProg);
}

/* Never null pointers */
ASSERT(ctx->VertexProgram.Current);
ASSERT(ctx->FragmentProgram.Current);

if (ctx->Driver.BindProgram)
ctx->Driver.BindProgram(ctx, target, newProg);
}


/**
* Delete a list of programs.
* \note Not compiled into display lists.
* \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
*/
void GLAPIENTRY
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
GLint i;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

if (n < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
return;
}

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 */
if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */
prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
if (ctx->VertexProgram.Current &&
ctx->VertexProgram.Current->Base.Id == ids[i]) {
/* unbind this currently bound program */
_mesa_BindProgram(prog->Target, 0);
}
}
else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
if (ctx->FragmentProgram.Current &&
ctx->FragmentProgram.Current->Base.Id == ids[i]) {
/* unbind this currently bound program */
_mesa_BindProgram(prog->Target, 0);
}
}
else {
_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);
}
}
}
}


/**
* Generate a list of new program identifiers.
* \note Not compiled into display lists.
* \note Called by both glGenProgramsNV and glGenProgramsARB.
*/
void GLAPIENTRY
_mesa_GenPrograms(GLsizei n, GLuint *ids)
{
GLuint first;
GLuint i;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);

if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
return;
}

if (!ids)
return;

first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);

/* Insert pointer to dummy program as placeholder */
for (i = 0; i < (GLuint) n; i++) {
_mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
}

/* Return the program names */
for (i = 0; i < (GLuint) n; i++) {
ids[i] = first + i;
}
}

+ 0
- 18
src/mesa/shader/program.h View File

@@ -46,10 +46,6 @@
extern struct gl_program _mesa_DummyProgram;


/*
* Internal functions
*/

extern void
_mesa_init_program(GLcontext *ctx);

@@ -127,19 +123,5 @@ extern GLint
_mesa_find_free_register(const struct gl_program *prog, GLuint regFile);


/*
* API functions common to ARB/NV_vertex/fragment_program
*/

extern void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id);

extern void GLAPIENTRY
_mesa_DeletePrograms(GLsizei n, const GLuint *ids);

extern void GLAPIENTRY
_mesa_GenPrograms(GLsizei n, GLuint *ids);



#endif /* PROGRAM_H */

Loading…
Cancel
Save