mesa: move fixed function vertex program builder from tnl to core mesa

Also unify caching of fragment and vertex programs in shader/prog_cache.c`

Brought across from gallium-0.2
This commit is contained in:
Keith Whitwell
2008-09-20 08:26:11 -07:00
parent e019ead5d7
commit 32ef6e7583
17 changed files with 2209 additions and 1799 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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, sub license, 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 (including the
* next paragraph) 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
*
**************************************************************************/
#ifndef FFVERTEX_PROG_H
#define FFVERTEX_PROG_H
#include "main/mtypes.h"
struct gl_vertex_program *
_mesa_get_fixed_func_vertex_program(GLcontext *ctx);
#endif /* FFVERTEX_PROG_H */

View File

@@ -123,6 +123,7 @@ typedef int GLfixed;
/*@{*/ /*@{*/
struct _mesa_HashTable; struct _mesa_HashTable;
struct gl_pixelstore_attrib; struct gl_pixelstore_attrib;
struct gl_program_cache;
struct gl_texture_format; struct gl_texture_format;
struct gl_texture_image; struct gl_texture_image;
struct gl_texture_object; struct gl_texture_object;
@@ -149,6 +150,7 @@ enum
VERT_ATTRIB_COLOR1 = 4, VERT_ATTRIB_COLOR1 = 4,
VERT_ATTRIB_FOG = 5, VERT_ATTRIB_FOG = 5,
VERT_ATTRIB_COLOR_INDEX = 6, VERT_ATTRIB_COLOR_INDEX = 6,
VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
VERT_ATTRIB_EDGEFLAG = 7, VERT_ATTRIB_EDGEFLAG = 7,
VERT_ATTRIB_TEX0 = 8, VERT_ATTRIB_TEX0 = 8,
VERT_ATTRIB_TEX1 = 9, VERT_ATTRIB_TEX1 = 9,
@@ -1546,15 +1548,6 @@ struct gl_texture_unit
}; };
struct texenvprog_cache_item;
struct texenvprog_cache
{
struct texenvprog_cache_item **items;
GLuint size, n_items;
GLcontext *ctx;
};
/** /**
* Texture attribute group (GL_TEXTURE_BIT). * Texture attribute group (GL_TEXTURE_BIT).
@@ -1581,9 +1574,6 @@ struct gl_texture_attrib
/** GL_EXT_shared_texture_palette */ /** GL_EXT_shared_texture_palette */
GLboolean SharedPalette; GLboolean SharedPalette;
struct gl_color_table Palette; struct gl_color_table Palette;
/** Cached texenv fragment programs */
struct texenvprog_cache env_fp_cache;
}; };
@@ -1984,6 +1974,9 @@ struct gl_vertex_program_state
/** Program to emulate fixed-function T&L (see above) */ /** Program to emulate fixed-function T&L (see above) */
struct gl_vertex_program *_TnlProgram; struct gl_vertex_program *_TnlProgram;
/** Cache of fixed-function programs */
struct gl_program_cache *Cache;
#if FEATURE_MESA_program_debug #if FEATURE_MESA_program_debug
GLprogramcallbackMESA Callback; GLprogramcallbackMESA Callback;
GLvoid *CallbackData; GLvoid *CallbackData;
@@ -2017,6 +2010,9 @@ struct gl_fragment_program_state
/** Program to emulate fixed-function texture env/combine (see above) */ /** Program to emulate fixed-function texture env/combine (see above) */
struct gl_fragment_program *_TexEnvProgram; struct gl_fragment_program *_TexEnvProgram;
/** Cache of fixed-function programs */
struct gl_program_cache *Cache;
#if FEATURE_MESA_program_debug #if FEATURE_MESA_program_debug
GLprogramcallbackMESA Callback; GLprogramcallbackMESA Callback;
GLvoid *CallbackData; GLvoid *CallbackData;

View File

@@ -62,6 +62,7 @@
#if FEATURE_EXT_framebuffer_object #if FEATURE_EXT_framebuffer_object
#include "fbobject.h" #include "fbobject.h"
#endif #endif
#include "ffvertex_prog.h"
#include "framebuffer.h" #include "framebuffer.h"
#include "hint.h" #include "hint.h"
#include "histogram.h" #include "histogram.h"
@@ -951,13 +952,12 @@ update_arrays( GLcontext *ctx )
} }
/**
* Update derived vertex/fragment program state.
*/
static void static void
update_program(GLcontext *ctx) update_program(GLcontext *ctx)
{ {
const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
/* These _Enabled flags indicate if the program is enabled AND valid. */ /* These _Enabled flags indicate if the program is enabled AND valid. */
ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled
@@ -969,13 +969,18 @@ update_program(GLcontext *ctx)
/* /*
* Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
* pointers to the programs that should be enabled/used. * pointers to the programs that should be enabled/used. These will only
* be NULL if we need to use the fixed-function code.
* *
* These programs may come from several sources. The priority is as * These programs may come from several sources. The priority is as
* follows: * follows:
* 1. OpenGL 2.0/ARB vertex/fragment shaders * 1. OpenGL 2.0/ARB vertex/fragment shaders
* 2. ARB/NV vertex/fragment programs * 2. ARB/NV vertex/fragment programs
* 3. Programs derived from fixed-function state. * 3. Programs derived from fixed-function state.
*
* Note: it's possible for a vertex shader to get used with a fragment
* program (and vice versa) here, but in practice that shouldn't ever
* come up, or matter.
*/ */
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
@@ -991,23 +996,6 @@ update_program(GLcontext *ctx)
shProg->FragmentProgram); shProg->FragmentProgram);
} }
else { else {
if (ctx->VertexProgram._Enabled) {
/* use user-defined vertex program */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
ctx->VertexProgram.Current);
}
else if (ctx->VertexProgram._MaintainTnlProgram) {
/* Use vertex program generated from fixed-function state.
* The _Current pointer will get set in
* _tnl_UpdateFixedFunctionProgram() later if appropriate.
*/
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
}
else {
/* no vertex program */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
}
if (ctx->FragmentProgram._Enabled) { if (ctx->FragmentProgram._Enabled) {
/* use user-defined vertex program */ /* use user-defined vertex program */
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
@@ -1015,15 +1003,38 @@ update_program(GLcontext *ctx)
} }
else if (ctx->FragmentProgram._MaintainTexEnvProgram) { else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
/* Use fragment program generated from fixed-function state. /* Use fragment program generated from fixed-function state.
* The _Current pointer will get set in _mesa_UpdateTexEnvProgram()
* later if appropriate.
*/ */
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
_mesa_get_fixed_func_fragment_program(ctx));
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
ctx->FragmentProgram._Current);
} }
else { else {
/* no fragment program */ /* no fragment program */
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
} }
/* Examine vertex program after fragment program as
* _mesa_get_fixed_func_vertex_program() needs to know active
* fragprog inputs.
*/
if (ctx->VertexProgram._Enabled) {
/* use user-defined vertex program */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
ctx->VertexProgram.Current);
}
else if (ctx->VertexProgram._MaintainTnlProgram) {
/* Use vertex program generated from fixed-function state.
*/
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
_mesa_get_fixed_func_vertex_program(ctx));
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram,
ctx->VertexProgram._Current);
}
else {
/* no vertex program */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
}
} }
if (ctx->VertexProgram._Current) if (ctx->VertexProgram._Current)
@@ -1032,12 +1043,28 @@ update_program(GLcontext *ctx)
assert(ctx->FragmentProgram._Current->Base.Parameters); assert(ctx->FragmentProgram._Current->Base.Parameters);
/* XXX: get rid of _Active flag.
*/
#if 1
ctx->FragmentProgram._Active = ctx->FragmentProgram._Enabled; ctx->FragmentProgram._Active = ctx->FragmentProgram._Enabled;
if (ctx->FragmentProgram._MaintainTexEnvProgram && if (ctx->FragmentProgram._MaintainTexEnvProgram &&
!ctx->FragmentProgram._Enabled) { !ctx->FragmentProgram._Enabled) {
if (ctx->FragmentProgram._UseTexEnvProgram) if (ctx->FragmentProgram._UseTexEnvProgram)
ctx->FragmentProgram._Active = GL_TRUE; ctx->FragmentProgram._Active = GL_TRUE;
} }
#endif
/* Let the driver know what's happening:
*/
if (ctx->FragmentProgram._Current != prevFP && ctx->Driver.BindProgram) {
ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
(struct gl_program *) ctx->FragmentProgram._Current);
}
if (ctx->VertexProgram._Current != prevVP && ctx->Driver.BindProgram) {
ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
(struct gl_program *) ctx->VertexProgram._Current);
}
} }
@@ -1197,13 +1224,11 @@ void
_mesa_update_state_locked( GLcontext *ctx ) _mesa_update_state_locked( GLcontext *ctx )
{ {
GLbitfield new_state = ctx->NewState; GLbitfield new_state = ctx->NewState;
GLbitfield prog_flags = _NEW_PROGRAM;
if (MESA_VERBOSE & VERBOSE_STATE) if (MESA_VERBOSE & VERBOSE_STATE)
_mesa_print_state("_mesa_update_state", new_state); _mesa_print_state("_mesa_update_state", new_state);
if (new_state & _NEW_PROGRAM)
update_program( ctx );
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
_mesa_update_modelview_project( ctx, new_state ); _mesa_update_modelview_project( ctx, new_state );
@@ -1249,11 +1274,6 @@ _mesa_update_state_locked( GLcontext *ctx )
update_tricaps( ctx, new_state ); update_tricaps( ctx, new_state );
#endif #endif
if (ctx->FragmentProgram._MaintainTexEnvProgram) {
if (new_state & (_NEW_TEXTURE | _DD_NEW_SEPARATE_SPECULAR | _NEW_FOG))
_mesa_UpdateTexEnvProgram(ctx);
}
/* ctx->_NeedEyeCoords is now up to date. /* ctx->_NeedEyeCoords is now up to date.
* *
* If the truth value of this variable has changed, update for the * If the truth value of this variable has changed, update for the
@@ -1266,6 +1286,20 @@ _mesa_update_state_locked( GLcontext *ctx )
if (new_state & _MESA_NEW_NEED_EYE_COORDS) if (new_state & _MESA_NEW_NEED_EYE_COORDS)
_mesa_update_tnl_spaces( ctx, new_state ); _mesa_update_tnl_spaces( ctx, new_state );
if (ctx->FragmentProgram._MaintainTexEnvProgram) {
prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR);
}
if (ctx->VertexProgram._MaintainTnlProgram) {
prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
_NEW_TRANSFORM | _NEW_POINT |
_NEW_FOG | _NEW_LIGHT |
_MESA_NEW_NEED_EYE_COORDS);
}
if (new_state & prog_flags)
update_program( ctx );
/* /*
* Give the driver a chance to act upon the new_state flags. * Give the driver a chance to act upon the new_state flags.
* The driver might plug in different span functions, for example. * The driver might plug in different span functions, for example.

View File

@@ -1,6 +1,6 @@
/************************************************************************** /**************************************************************************
* *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved. * All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@@ -30,6 +30,7 @@
#include "enums.h" #include "enums.h"
#include "shader/program.h" #include "shader/program.h"
#include "shader/prog_parameter.h" #include "shader/prog_parameter.h"
#include "shader/prog_cache.h"
#include "shader/prog_instruction.h" #include "shader/prog_instruction.h"
#include "shader/prog_print.h" #include "shader/prog_print.h"
#include "shader/prog_statevars.h" #include "shader/prog_statevars.h"
@@ -1138,106 +1139,35 @@ create_new_program(GLcontext *ctx, struct state_key *key,
} }
static struct gl_fragment_program * /**
search_cache(const struct texenvprog_cache *cache, * Return a fragment program which implements the current
GLuint hash, * fixed-function texture, fog and color-sum operations.
const void *key, */
GLuint keysize) struct gl_fragment_program *
_mesa_get_fixed_func_fragment_program(GLcontext *ctx)
{ {
struct texenvprog_cache_item *c; struct gl_fragment_program *prog;
struct state_key key;
for (c = cache->items[hash % cache->size]; c; c = c->next) { make_state_key(ctx, &key);
if (c->hash == hash && memcmp(c->key, key, keysize) == 0)
return c->data; prog = (struct gl_fragment_program *)
_mesa_search_program_cache(ctx->FragmentProgram.Cache,
&key, sizeof(key));
if (!prog) {
prog = (struct gl_fragment_program *)
ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
create_new_program(ctx, &key, prog);
_mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
&key, sizeof(key), &prog->Base);
} }
return NULL; return prog;
} }
static void rehash( struct texenvprog_cache *cache )
{
struct texenvprog_cache_item **items;
struct texenvprog_cache_item *c, *next;
GLuint size, i;
size = cache->size * 3;
items = (struct texenvprog_cache_item**) _mesa_malloc(size * sizeof(*items));
_mesa_memset(items, 0, size * sizeof(*items));
for (i = 0; i < cache->size; i++)
for (c = cache->items[i]; c; c = next) {
next = c->next;
c->next = items[c->hash % size];
items[c->hash % size] = c;
}
_mesa_free(cache->items);
cache->items = items;
cache->size = size;
}
static void clear_cache(GLcontext *ctx, struct texenvprog_cache *cache)
{
struct texenvprog_cache_item *c, *next;
GLuint i;
for (i = 0; i < cache->size; i++) {
for (c = cache->items[i]; c; c = next) {
next = c->next;
_mesa_free(c->key);
_mesa_reference_fragprog(ctx, &c->data, NULL);
_mesa_free(c);
}
cache->items[i] = NULL;
}
cache->n_items = 0;
}
static void cache_item( GLcontext *ctx,
struct texenvprog_cache *cache,
GLuint hash,
const struct state_key *key,
struct gl_fragment_program *prog)
{
struct texenvprog_cache_item *c = CALLOC_STRUCT(texenvprog_cache_item);
c->hash = hash;
c->key = _mesa_malloc(sizeof(*key));
memcpy(c->key, key, sizeof(*key));
c->data = prog;
if (cache->n_items > cache->size * 1.5) {
if (cache->size < 1000)
rehash(cache);
else
clear_cache(ctx, cache);
}
cache->n_items++;
c->next = cache->items[hash % cache->size];
cache->items[hash % cache->size] = c;
}
static GLuint hash_key( const struct state_key *key )
{
GLuint *ikey = (GLuint *)key;
GLuint hash = 0, i;
/* Make a slightly better attempt at a hash function:
*/
for (i = 0; i < sizeof(*key)/sizeof(*ikey); i++)
{
hash += ikey[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash;
}
/** /**
@@ -1248,44 +1178,22 @@ static GLuint hash_key( const struct state_key *key )
void void
_mesa_UpdateTexEnvProgram( GLcontext *ctx ) _mesa_UpdateTexEnvProgram( GLcontext *ctx )
{ {
struct state_key key;
GLuint hash;
const struct gl_fragment_program *prev = ctx->FragmentProgram._Current; const struct gl_fragment_program *prev = ctx->FragmentProgram._Current;
ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram); ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram);
/* If a conventional fragment program/shader isn't in effect... */ /* If a conventional fragment program/shader isn't in effect... */
if (!ctx->FragmentProgram._Enabled && if (!ctx->FragmentProgram._Enabled &&
(!ctx->Shader.CurrentProgram || !ctx->Shader.CurrentProgram->FragmentProgram)) { (!ctx->Shader.CurrentProgram ||
!ctx->Shader.CurrentProgram->FragmentProgram) )
{
struct gl_fragment_program *newProg; struct gl_fragment_program *newProg;
make_state_key(ctx, &key); newProg = _mesa_get_fixed_func_fragment_program(ctx);
hash = hash_key(&key);
newProg = search_cache(&ctx->Texture.env_fp_cache, hash, &key, sizeof(key));
if (!newProg) {
/* create new tex env program */
if (0)
_mesa_printf("Building new texenv proggy for key %x\n", hash);
newProg = (struct gl_fragment_program *)
ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
create_new_program(ctx, &key, newProg);
/* Our ownership of newProg is transferred to the cache */
cache_item(ctx, &ctx->Texture.env_fp_cache, hash, &key, newProg);
}
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, newProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, newProg);
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, newProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, newProg);
} }
else {
/* _Current pointer has been updated in update_program */
/* ctx->FragmentProgram._Current = ctx->FragmentProgram.Current; */
}
/* Tell the driver about the change. Could define a new target for /* Tell the driver about the change. Could define a new target for
* this? * this?
@@ -1295,21 +1203,3 @@ _mesa_UpdateTexEnvProgram( GLcontext *ctx )
(struct gl_program *) ctx->FragmentProgram._Current); (struct gl_program *) ctx->FragmentProgram._Current);
} }
} }
void _mesa_TexEnvProgramCacheInit( GLcontext *ctx )
{
ctx->Texture.env_fp_cache.ctx = ctx;
ctx->Texture.env_fp_cache.size = 17;
ctx->Texture.env_fp_cache.n_items = 0;
ctx->Texture.env_fp_cache.items = (struct texenvprog_cache_item **)
_mesa_calloc(ctx->Texture.env_fp_cache.size *
sizeof(struct texenvprog_cache_item));
}
void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
{
clear_cache(ctx, &ctx->Texture.env_fp_cache);
_mesa_free(ctx->Texture.env_fp_cache.items);
}

View File

@@ -1,13 +1,8 @@
/**
* \file texenvprogram.h
* Texture state management.
*/
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
* Version: 5.1 * Version: 7.1
* *
* Copyright (C) 1999-2002 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 * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -34,8 +29,9 @@
#include "mtypes.h" #include "mtypes.h"
extern struct gl_fragment_program *
_mesa_get_fixed_func_fragment_program(GLcontext *ctx);
extern void _mesa_UpdateTexEnvProgram( GLcontext *ctx ); extern void _mesa_UpdateTexEnvProgram( GLcontext *ctx );
extern void _mesa_TexEnvProgramCacheInit( GLcontext *ctx );
extern void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx );
#endif #endif

View File

@@ -3177,8 +3177,6 @@ _mesa_init_texture(GLcontext *ctx)
*/ */
assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1); assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1);
_mesa_TexEnvProgramCacheInit( ctx );
/* Allocate proxy textures */ /* Allocate proxy textures */
if (!alloc_proxy_textures( ctx )) if (!alloc_proxy_textures( ctx ))
return GL_FALSE; return GL_FALSE;
@@ -3214,7 +3212,6 @@ _mesa_free_texture_data(GLcontext *ctx)
for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++)
_mesa_free_colortable_data( &ctx->Texture.Unit[u].ColorTable ); _mesa_free_colortable_data( &ctx->Texture.Unit[u].ColorTable );
_mesa_TexEnvProgramCacheDestroy( ctx );
} }

View File

@@ -0,0 +1,193 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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, sub license, 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 (including the
* next paragraph) 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 "main/glheader.h"
#include "main/mtypes.h"
#include "main/imports.h"
#include "shader/prog_cache.h"
#include "shader/program.h"
struct cache_item
{
GLuint hash;
void *key;
struct gl_program *program;
struct cache_item *next;
};
struct gl_program_cache
{
struct cache_item **items;
GLuint size, n_items;
};
/**
* Compute hash index from state key.
*/
static GLuint
hash_key(const void *key, GLuint key_size)
{
const GLuint *ikey = (const GLuint *) key;
GLuint hash = 0, i;
assert(key_size >= 4);
/* Make a slightly better attempt at a hash function:
*/
for (i = 0; i < key_size / sizeof(*ikey); i++)
{
hash += ikey[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash;
}
/**
* Rebuild/expand the hash table to accomodate more entries
*/
static void
rehash(struct gl_program_cache *cache)
{
struct cache_item **items;
struct cache_item *c, *next;
GLuint size, i;
size = cache->size * 3;
items = (struct cache_item**) _mesa_malloc(size * sizeof(*items));
_mesa_memset(items, 0, size * sizeof(*items));
for (i = 0; i < cache->size; i++)
for (c = cache->items[i]; c; c = next) {
next = c->next;
c->next = items[c->hash % size];
items[c->hash % size] = c;
}
_mesa_free(cache->items);
cache->items = items;
cache->size = size;
}
static void
clear_cache(GLcontext *ctx, struct gl_program_cache *cache)
{
struct cache_item *c, *next;
GLuint i;
for (i = 0; i < cache->size; i++) {
for (c = cache->items[i]; c; c = next) {
next = c->next;
_mesa_free(c->key);
_mesa_reference_program(ctx, &c->program, NULL);
_mesa_free(c);
}
cache->items[i] = NULL;
}
cache->n_items = 0;
}
struct gl_program_cache *
_mesa_new_program_cache(void)
{
struct gl_program_cache *cache = CALLOC_STRUCT(gl_program_cache);
if (cache) {
cache->size = 17;
cache->items = (struct cache_item **)
_mesa_calloc(cache->size * sizeof(struct cache_item));
if (!cache->items) {
_mesa_free(cache);
return NULL;
}
}
return cache;
}
void
_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *cache)
{
clear_cache(ctx, cache);
_mesa_free(cache->items);
_mesa_free(cache);
}
struct gl_program *
_mesa_search_program_cache(const struct gl_program_cache *cache,
const void *key, GLuint keysize)
{
const GLuint hash = hash_key(key, keysize);
struct cache_item *c;
for (c = cache->items[hash % cache->size]; c; c = c->next) {
if (c->hash == hash && memcmp(c->key, key, keysize) == 0)
return c->program;
}
return NULL;
}
void
_mesa_program_cache_insert(GLcontext *ctx,
struct gl_program_cache *cache,
const void *key, GLuint keysize,
struct gl_program *program)
{
const GLuint hash = hash_key(key, keysize);
struct cache_item *c = CALLOC_STRUCT(cache_item);
c->hash = hash;
c->key = _mesa_malloc(keysize);
memcpy(c->key, key, keysize);
c->program = program; /* no refcount change */
if (cache->n_items > cache->size * 1.5) {
if (cache->size < 1000)
rehash(cache);
else
clear_cache(ctx, cache);
}
cache->n_items++;
c->next = cache->items[hash % cache->size];
cache->items[hash % cache->size] = c;
}

View File

@@ -0,0 +1,55 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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, sub license, 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 (including the
* next paragraph) 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
*
**************************************************************************/
#ifndef PROG_CACHE_H
#define PROG_CACHE_H
/** Opaque type */
struct gl_program_cache;
extern struct gl_program_cache *
_mesa_new_program_cache(void);
extern void
_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *pc);
extern struct gl_program *
_mesa_search_program_cache(const struct gl_program_cache *cache,
const void *key, GLuint keysize);
extern void
_mesa_program_cache_insert(GLcontext *ctx,
struct gl_program_cache *cache,
const void *key, GLuint keysize,
struct gl_program *program);
#endif /* PROG_CACHE_H */

View File

@@ -134,10 +134,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[3] = 1.0; value[3] = 1.0;
} }
return; return;
case STATE_POSITION_NORMALIZED:
COPY_4V(value, ctx->Light.Light[ln].EyePosition);
NORMALIZE_3FV( value );
return;
default: default:
_mesa_problem(ctx, "Invalid light state in fetch_state"); _mesa_problem(ctx, "Invalid light state in fetch_state");
return; return;
@@ -401,7 +397,11 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
case STATE_INTERNAL: case STATE_INTERNAL:
switch (state[1]) { switch (state[1]) {
case STATE_NORMAL_SCALE: case STATE_NORMAL_SCALE:
ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); ASSIGN_4V(value,
ctx->_ModelViewInvScale,
ctx->_ModelViewInvScale,
ctx->_ModelViewInvScale,
1);
return; return;
case STATE_TEXRECT_SCALE: case STATE_TEXRECT_SCALE:
{ {
@@ -431,15 +431,45 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[2] = ctx->Fog.Density * ONE_DIV_LN2; value[2] = ctx->Fog.Density * ONE_DIV_LN2;
value[3] = ctx->Fog.Density * ONE_DIV_SQRT_LN2; value[3] = ctx->Fog.Density * ONE_DIV_SQRT_LN2;
return; return;
case STATE_SPOT_DIR_NORMALIZED: {
case STATE_LIGHT_SPOT_DIR_NORMALIZED: {
/* here, state[2] is the light number */ /* here, state[2] is the light number */
/* pre-normalize spot dir */ /* pre-normalize spot dir */
const GLuint ln = (GLuint) state[2]; const GLuint ln = (GLuint) state[2];
COPY_3V(value, ctx->Light.Light[ln].EyeDirection); COPY_3V(value, ctx->Light.Light[ln]._NormDirection);
NORMALIZE_3FV(value);
value[3] = ctx->Light.Light[ln]._CosCutoff; value[3] = ctx->Light.Light[ln]._CosCutoff;
return; return;
} }
case STATE_LIGHT_POSITION: {
const GLuint ln = (GLuint) state[2];
COPY_4V(value, ctx->Light.Light[ln]._Position);
return;
}
case STATE_LIGHT_POSITION_NORMALIZED: {
const GLuint ln = (GLuint) state[2];
COPY_4V(value, ctx->Light.Light[ln]._Position);
NORMALIZE_3FV( value );
return;
}
case STATE_LIGHT_HALF_VECTOR: {
const GLuint ln = (GLuint) state[2];
GLfloat p[3];
/* Compute infinite half angle vector:
* halfVector = normalize(normalize(lightPos) + (0, 0, 1))
* light.EyePosition.w should be 0 for infinite lights.
*/
COPY_3V(p, ctx->Light.Light[ln]._Position);
NORMALIZE_3FV(p);
ADD_3V(value, p, ctx->_EyeZDir);
NORMALIZE_3FV(value);
value[3] = 1.0;
return;
}
case STATE_PT_SCALE: case STATE_PT_SCALE:
value[0] = ctx->Pixel.RedScale; value[0] = ctx->Pixel.RedScale;
value[1] = ctx->Pixel.GreenScale; value[1] = ctx->Pixel.GreenScale;
@@ -711,7 +741,6 @@ append_token(char *dst, gl_state_index k)
append(dst, "normalScale"); append(dst, "normalScale");
break; break;
case STATE_INTERNAL: case STATE_INTERNAL:
case STATE_POSITION_NORMALIZED:
append(dst, "(internal)"); append(dst, "(internal)");
break; break;
case STATE_PT_SCALE: case STATE_PT_SCALE:

View File

@@ -106,9 +106,11 @@ typedef enum gl_state_index_ {
STATE_INTERNAL, /* Mesa additions */ STATE_INTERNAL, /* Mesa additions */
STATE_NORMAL_SCALE, STATE_NORMAL_SCALE,
STATE_TEXRECT_SCALE, STATE_TEXRECT_SCALE,
STATE_POSITION_NORMALIZED, /* normalized light position */
STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */ STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */
STATE_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */ STATE_LIGHT_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */
STATE_LIGHT_POSITION, /* object vs eye space */
STATE_LIGHT_POSITION_NORMALIZED, /* object vs eye space */
STATE_LIGHT_HALF_VECTOR, /* object vs eye space */
STATE_PT_SCALE, /**< Pixel transfer RGBA scale */ STATE_PT_SCALE, /**< Pixel transfer RGBA scale */
STATE_PT_BIAS, /**< Pixel transfer RGBA bias */ STATE_PT_BIAS, /**< Pixel transfer RGBA bias */
STATE_PCM_SCALE, /**< Post color matrix RGBA scale */ STATE_PCM_SCALE, /**< Post color matrix RGBA scale */

View File

@@ -33,6 +33,7 @@
#include "main/context.h" #include "main/context.h"
#include "main/hash.h" #include "main/hash.h"
#include "program.h" #include "program.h"
#include "prog_cache.h"
#include "prog_parameter.h" #include "prog_parameter.h"
#include "prog_instruction.h" #include "prog_instruction.h"
@@ -66,6 +67,7 @@ _mesa_init_program(GLcontext *ctx)
ctx->VertexProgram.TrackMatrix[i] = GL_NONE; ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV; ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
} }
ctx->VertexProgram.Cache = _mesa_new_program_cache();
#endif #endif
#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
@@ -73,8 +75,10 @@ _mesa_init_program(GLcontext *ctx)
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
ctx->Shared->DefaultFragmentProgram); ctx->Shared->DefaultFragmentProgram);
assert(ctx->FragmentProgram.Current); assert(ctx->FragmentProgram.Current);
ctx->FragmentProgram.Cache = _mesa_new_program_cache();
#endif #endif
/* XXX probably move this stuff */ /* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader #if FEATURE_ATI_fragment_shader
ctx->ATIFragmentShader.Enabled = GL_FALSE; ctx->ATIFragmentShader.Enabled = GL_FALSE;
@@ -93,9 +97,11 @@ _mesa_free_program_data(GLcontext *ctx)
{ {
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
_mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
#endif #endif
#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
_mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache);
#endif #endif
/* XXX probably move this stuff */ /* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader #if FEATURE_ATI_fragment_shader

View File

@@ -27,6 +27,7 @@ MAIN_SOURCES = \
main/extensions.c \ main/extensions.c \
main/fbobject.c \ main/fbobject.c \
main/feedback.c \ main/feedback.c \
main/ffvertex_prog.c \
main/fog.c \ main/fog.c \
main/framebuffer.c \ main/framebuffer.c \
main/get.c \ main/get.c \
@@ -160,6 +161,7 @@ SHADER_SOURCES = \
shader/nvprogram.c \ shader/nvprogram.c \
shader/nvvertparse.c \ shader/nvvertparse.c \
shader/program.c \ shader/program.c \
shader/prog_cache.c \
shader/prog_debug.c \ shader/prog_debug.c \
shader/prog_execute.c \ shader/prog_execute.c \
shader/prog_instruction.c \ shader/prog_instruction.c \

View File

@@ -61,7 +61,6 @@ _tnl_CreateContext( GLcontext *ctx )
/* Initialize tnl state. /* Initialize tnl state.
*/ */
if (ctx->VertexProgram._MaintainTnlProgram) { if (ctx->VertexProgram._MaintainTnlProgram) {
_tnl_ProgramCacheInit( ctx );
_tnl_install_pipeline( ctx, _tnl_vp_pipeline ); _tnl_install_pipeline( ctx, _tnl_vp_pipeline );
} else { } else {
_tnl_install_pipeline( ctx, _tnl_default_pipeline ); _tnl_install_pipeline( ctx, _tnl_default_pipeline );
@@ -90,9 +89,6 @@ _tnl_DestroyContext( GLcontext *ctx )
_tnl_destroy_pipeline( ctx ); _tnl_destroy_pipeline( ctx );
if (ctx->VertexProgram._MaintainTnlProgram)
_tnl_ProgramCacheDestroy( ctx );
FREE(tnl); FREE(tnl);
ctx->swtnl_context = NULL; ctx->swtnl_context = NULL;
} }

View File

@@ -385,19 +385,6 @@ struct tnl_clipspace
}; };
struct tnl_cache_item {
GLuint hash;
void *key;
struct gl_vertex_program *prog;
struct tnl_cache_item *next;
};
struct tnl_cache {
struct tnl_cache_item **items;
GLuint size, n_items;
};
struct tnl_device_driver struct tnl_device_driver
{ {
/*** /***
@@ -549,10 +536,6 @@ typedef struct
GLubyte *block[VERT_ATTRIB_MAX]; GLubyte *block[VERT_ATTRIB_MAX];
GLuint nr_blocks; GLuint nr_blocks;
/* Cache of fixed-function-replacing vertex programs:
*/
struct tnl_cache *vp_cache;
} TNLcontext; } TNLcontext;

File diff suppressed because it is too large Load Diff

View File

@@ -17,20 +17,19 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 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. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#ifndef _T_ARB_BUILD_H #ifndef T_VP_BUILD_H
#define _T_ARB_BUILD_H #define T_VP_BUILD_H
#include "main/mtypes.h" #include "main/mtypes.h"
extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ); extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );
extern void _tnl_ProgramCacheInit( GLcontext *ctx );
extern void _tnl_ProgramCacheDestroy( GLcontext *ctx );
#endif #endif