diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2007-03-16 12:17:52 +0000 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2007-03-16 12:17:52 +0000 |
commit | 83b7647450b860f1e282d3db22edf206373583bc (patch) | |
tree | f2af08650a9dca236a707f7553caf5393bce2d02 | |
parent | 891050ea33c71aec14bd65fc42eef95d4b459013 (diff) |
Reorganize state to match indirect state types.
Indirect state emit support added, but disabled.
Trivial tri.c works.
26 files changed, 2441 insertions, 1309 deletions
diff --git a/src/mesa/drivers/dri/i915tex/Makefile b/src/mesa/drivers/dri/i915tex/Makefile index c8fee7dfb5..7c7ad84d51 100644 --- a/src/mesa/drivers/dri/i915tex/Makefile +++ b/src/mesa/drivers/dri/i915tex/Makefile @@ -7,6 +7,7 @@ LIBNAME = i915tex_dri.so MINIGLX_SOURCES = server/intel_dri.c DRIVER_SOURCES = \ + i915_cache.c \ i915_context.c \ i915_fpc.c \ i915_fpc_debug.c \ @@ -14,14 +15,15 @@ DRIVER_SOURCES = \ i915_fpc_translate.c \ i915_program.c \ i915_state.c \ - i915_state_fp.c \ - i915_state_fp_inputs.c \ + i915_state_constants.c \ + i915_state_dynamic.c \ i915_state_fallback.c \ - i915_state_invarient.c \ i915_state_immediate.c \ i915_state_map.c \ - i915_state_misc.c \ + i915_state_program.c \ i915_state_sampler.c \ + i915_state_static.c \ + i915_state_vertex.c \ i915_tex_layout.c \ i915_vtbl.c \ intel_render.c \ diff --git a/src/mesa/drivers/dri/i915tex/i915_cache.c b/src/mesa/drivers/dri/i915tex/i915_cache.c new file mode 100644 index 0000000000..45644d77e4 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_cache.c @@ -0,0 +1,396 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "i915_context.h" +#include "i915_cache.h" +#include "i915_reg.h" +#include "intel_batchbuffer.h" + +/* Currently things are just being stuffed into the end of the + * batchbuffer. That's not great, but it works well for relocations. + * + * In future, keep non-relocation structs elsewhere, but want a way to + * be able to emit more (ie map a referenced buffer) without waiting + * on the fence - this should be possible as we currently do this with + * batchbuffers. + */ + +struct i915_cache_item { + GLuint hash; + GLuint size; + const void *data; + GLuint offset; /* relative to the batchbuffer start */ + struct i915_cache_item *next; +}; + +struct i915_cache { + GLuint id; + const char *name; + GLuint state_type; + struct i915_cache_item **items; + GLuint size, n_items; + GLuint force_load_flag; + GLuint last_addr; +}; + +struct i915_cache_context { + struct i915_context *i915; + struct i915_cache cache[I915_MAX_CACHE]; +}; + + +static void emit_load_indirect( struct intel_context *intel, + GLuint state_type, + GLuint force_load_flag, + GLuint offset, + GLuint size ) +{ + BEGIN_BATCH(3,0); + OUT_BATCH( _3DSTATE_LOAD_INDIRECT | state_type | (1<<14) | 1); + OUT_RELOC( intel->batch->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE, + ( offset | force_load_flag | SIS0_BUFFER_VALID ) ); + OUT_BATCH( (size/4)-1 ); + ADVANCE_BATCH(); +} + + +static GLuint emit_packet( struct intel_context *intel, + const struct i915_cache_packet *packet, + GLuint size ) +{ + GLuint segment = SEGMENT_OTHER_INDIRECT; + GLuint offset = intel->batch->segment_finish_offset[segment]; + GLuint i; + + /* XXX: + */ + assert(intel->batch->segment_finish_offset[segment] + size < + intel->batch->segment_max_offset[segment]); + + intel->batch->segment_finish_offset[segment] += size; + + memcpy(intel->batch->map + offset, + &packet->dword[0], + size ); + + for (i = 0; i < packet->nr_relocs; i++) { + intel_batchbuffer_set_reloc( intel->batch, + offset + packet->reloc[i].dword * sizeof(GLuint), + packet->reloc[i].buffer, + packet->reloc[i].flags, + packet->reloc[i].mask, + packet->dword[packet->reloc[i].dword].u ); + } + + return offset; +} + + +/* A cache for packets of variable sizes which are held in one of the + * indirect state bins. + * + * Note that dynamic indirect state is special and handled elsewhere. + */ +static GLuint hash_packet( const void *packet, GLuint size ) +{ + GLuint hash = 0, i; + + assert(size % 4 == 0); + + /* I'm sure this can be improved on: + */ + for (i = 0; i < size/4; i++) + hash += ((GLuint *)packet)[i]; + + return hash; +} + + +static void rehash( struct i915_cache *cache ) +{ + struct i915_cache_item **items; + struct i915_cache_item *c, *next; + const GLuint size = cache->size * 2; + GLuint i; + + items = (struct i915_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-1)]; + items[c->hash & (size-1)] = c; + } + } + + FREE(cache->items); + cache->items = items; + cache->size = size; +} + + + +static GLuint search_cache( struct i915_cache *cache, + GLuint hash, + const void *data, + GLuint size) +{ + struct i915_cache_item *c; + GLuint mask = cache->size - 1; + + for (c = cache->items[hash & mask]; c; c = c->next) { + if (c->hash == hash && + c->size == size && + memcmp(c->data, data, size) == 0) + { + return c->offset; + } + } + + return 0; +} + + +static GLuint upload_cache( struct i915_cache *cache, + struct intel_context *intel, + GLuint hash, + const struct i915_cache_packet *packet, + GLuint size ) +{ + struct i915_cache_item *item = CALLOC_STRUCT(i915_cache_item); + void *data = _mesa_malloc(size); + + memcpy(data, packet->dword, size); + + item->data = data; + item->hash = hash; + item->size = size; + + if (++cache->n_items > cache->size) + rehash(cache); + + hash &= cache->size - 1; + item->next = cache->items[hash]; + cache->items[hash] = item; + + /* Copy data to the buffer and emit relocations: + */ + item->offset = emit_packet( intel, packet, size ); + + if (INTEL_DEBUG & DEBUG_STATE) + _mesa_printf("upload %s: %d bytes to batchbuffer offset %x\n", + cache->name, + size, + item->offset); + + return item->offset; +} + + +/* Returns the size of the in-use packet: + */ +static GLuint packet_size( const struct i915_cache_packet *packet ) +{ + return ((const char *)(packet->reloc + packet->nr_relocs) - + (const char *)packet); +} + + +void i915_cache_emit(struct i915_cache_context *cctx, + const struct i915_cache_packet *packet ) +{ + struct intel_context *intel = &cctx->i915->intel; + GLuint size = packet_size( packet ); +#if 0 + GLuint hash = hash_packet( packet, size ); + struct i915_cache *cache = &cctx->cache[packet->cache_id]; + GLuint addr; + + addr = search_cache( cache, hash, packet->dword, size ); + if (addr == 0) + addr = upload_cache( cache, intel, hash, packet, size ); + + /* Always have to tell the hardware about it, unless this is the + * same as last time! + */ + if (addr != cache->last_addr) { + emit_load_indirect( intel, cache->state_type, + cache->force_load_flag, + addr, size ); + + cache->force_load_flag = 0; + cache->last_addr = addr; + } +#else + GLuint i; + + BEGIN_BATCH(packet->nr_dwords, 0); + for (i = 0; i < packet->nr_relocs; i++) + intel_batchbuffer_set_reloc( intel->batch, + ( intel->batch->segment_finish_offset[0] + + packet->reloc[i].dword * sizeof(GLuint) ), + packet->reloc[i].buffer, + packet->reloc[i].flags, + packet->reloc[i].mask, + packet->dword[packet->reloc[i].dword].u ); + + for (i = 0; i < packet->nr_dwords; i++) + OUT_BATCH(packet->dword[i].u); + + ADVANCE_BATCH(); +#endif +} + + + +/* When we lose hardware context, need to invalidate the surface cache + * as these structs must be explicitly re-uploaded. They are subject + * to fixup by the memory manager as they contain absolute agp + * offsets, so we need to ensure there is a fresh version of the + * struct available to receive the fixup. + */ +static void clear_cache( struct i915_cache *cache ) +{ + struct i915_cache_item *c, *next; + GLuint i; + + for (i = 0; i < cache->size; i++) { + for (c = cache->items[i]; c; c = next) { + next = c->next; + free((void *)c->data); + free(c); + } + cache->items[i] = NULL; + } + + cache->n_items = 0; + + /* Make sure hardware knows we've abandoned old data: + */ + cache->force_load_flag = SIS0_FORCE_LOAD; + cache->last_addr = ~0; +} + + + +static void init_cache( struct i915_cache_context *cctx, + const char *name, + GLuint id, + GLuint state_type ) +{ + struct i915_cache *cache = &cctx->cache[id]; + + cache->id = id; + cache->name = name; + cache->state_type = state_type; + cache->size = 32; + cache->n_items = 0; + cache->items = ((struct i915_cache_item **) + _mesa_calloc(cache->size * sizeof(cache->items[0]))); +} + +struct i915_cache_context *i915_create_caches( struct i915_context *i915 ) +{ + struct i915_cache_context *cctx = CALLOC_STRUCT(i915_cache_context); + + cctx->i915 = i915; + + init_cache( cctx, + "SAMPLER", + I915_CACHE_SAMPLER, + LI0_STATE_SAMPLER ); + + init_cache( cctx, + "PROGRAM", + I915_CACHE_PROGRAM, + LI0_STATE_PROGRAM ); + + init_cache( cctx, + "CONSTANTS", + I915_CACHE_CONSTANTS, + LI0_STATE_CONSTANTS ); + + init_cache( cctx, + "MAP", + I915_CACHE_MAP, + LI0_STATE_MAP ); + + /* These are all part of the LI0_STATIC_INDIRECT bucket. Not + * really sure how to handle these. + */ + init_cache( cctx, + "BUFFERS", + I915_CACHE_BUFFERS, + LI0_STATE_STATIC_INDIRECT ); + + init_cache( cctx, + "STIPPLE", + I915_CACHE_STIPPLE, + LI0_STATE_STATIC_INDIRECT ); + + init_cache( cctx, + "SCISSOR", + I915_CACHE_SCISSOR, + LI0_STATE_STATIC_INDIRECT ); + + init_cache( cctx, + "INVARIENT", + I915_CACHE_INVARIENT, + LI0_STATE_STATIC_INDIRECT ); + + return cctx; +} + + +void i915_clear_caches( struct i915_cache_context *cctx ) +{ + GLint i; + + for (i = 0; i < I915_MAX_CACHE; i++) + clear_cache(&cctx->cache[i]); +} + + +void i915_destroy_caches( struct i915_cache_context *cctx ) +{ + GLint i; + + for (i = 0; i < I915_MAX_CACHE; i++) { + clear_cache(&cctx->cache[i]); + FREE(cctx->cache[i].items); + } + + FREE(cctx); +} diff --git a/src/mesa/drivers/dri/i915tex/i915_cache.h b/src/mesa/drivers/dri/i915tex/i915_cache.h new file mode 100644 index 0000000000..ca48b2daa1 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_cache.h @@ -0,0 +1,140 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef I915_CACHE_H +#define I915_CACHE_H + +struct i915_cache_context; +struct i915_cache_packet; +struct i915_context; + +enum { + I915_CACHE_SAMPLER, + I915_CACHE_PROGRAM, + I915_CACHE_CONSTANTS, + I915_CACHE_MAP, + I915_CACHE_BUFFERS, + I915_CACHE_STIPPLE, + I915_CACHE_SCISSOR, + I915_CACHE_INVARIENT, + I915_MAX_CACHE +}; + +struct i915_cache_context *i915_create_caches( struct i915_context *i915 ); + +void i915_destroy_caches( struct i915_cache_context *cctx ); +void i915_clear_caches( struct i915_cache_context *cctx ); + +void i915_cache_emit( struct i915_cache_context *cctx, + const struct i915_cache_packet *packet ); + + +/* A much of helpers for building packets containing relocation + * information. + * + * Initially allocate and fill in a maximally sized packet, as big as + * any that we ever submit to hardware. + * + * Once cached, we will store a compacted version of this packet, but + * this is a convient interface for clients to build & submit packets. + */ +#define PACKET_MAX_DWORDS (I915_MAX_CONSTANT * 4 + 4) +#define PACKET_MAX_RELOCS (I915_TEX_UNITS) + +struct i915_cache_reloc { + struct _DriBufferObject *buffer; + GLuint flags; + GLuint mask; + GLuint dword; +}; + +union fi { + GLfloat f; + GLuint u; + GLint i; +}; + +struct i915_cache_packet { + GLuint nr_dwords; + GLuint nr_relocs; + GLuint max_dwords; + GLuint cache_id; + + union fi dword[PACKET_MAX_DWORDS + + PACKET_MAX_RELOCS * sizeof(struct i915_cache_reloc) / sizeof(GLuint)]; + + struct i915_cache_reloc *reloc; +} packet; + + +static inline void packet_init( struct i915_cache_packet *packet, + GLuint cache_id, + GLuint nr_dwords, + GLuint nr_relocs ) +{ + packet->nr_dwords = 0; + packet->nr_relocs = 0; + packet->reloc = (struct i915_cache_reloc *)&packet->dword[nr_dwords]; + packet->max_dwords = nr_dwords; + packet->cache_id = cache_id; +} + +static inline void packet_dword( struct i915_cache_packet *packet, GLuint d ) +{ + assert(packet->nr_dwords < packet->max_dwords); + packet->dword[packet->nr_dwords++].u = d; +} + +static inline void packet_float( struct i915_cache_packet *packet, GLfloat f ) +{ + assert(packet->nr_dwords < packet->max_dwords); + packet->dword[packet->nr_dwords++].f = f; +} + +static inline void packet_reloc( struct i915_cache_packet *packet, + struct _DriBufferObject *buf, + GLuint flags, + GLuint mask, + GLuint delta ) +{ + packet->reloc[packet->nr_relocs].buffer = buf; + packet->reloc[packet->nr_relocs].flags = flags; + packet->reloc[packet->nr_relocs].mask = mask; + packet->reloc[packet->nr_relocs].dword = packet->nr_dwords; + packet->dword[packet->nr_dwords].u = delta; + packet->nr_relocs++; + packet->nr_dwords++; +} + + + +#endif diff --git a/src/mesa/drivers/dri/i915tex/i915_context.c b/src/mesa/drivers/dri/i915tex/i915_context.c index 4ea8d1d1df..bf4e7b7f2f 100644 --- a/src/mesa/drivers/dri/i915tex/i915_context.c +++ b/src/mesa/drivers/dri/i915tex/i915_context.c @@ -40,6 +40,7 @@ #include "utils.h" #include "i915_reg.h" #include "i915_state.h" +#include "i915_cache.h" #include "intel_regions.h" #include "intel_batchbuffer.h" @@ -69,31 +70,9 @@ i915InitDriverFunctions(struct dd_function_table *functions) i915InitFragProgFuncs(functions); } - - -GLboolean -i915CreateContext(const __GLcontextModes * mesaVis, - __DRIcontextPrivate * driContextPriv, - void *sharedContextPrivate) +static void i915_init_gl_constants( struct i915_context *i915 ) { - struct dd_function_table functions; - struct i915_context *i915 = - (struct i915_context *) CALLOC_STRUCT(i915_context); - struct intel_context *intel = &i915->intel; - GLcontext *ctx = &intel->ctx; - - if (!i915) - return GL_FALSE; - - i915InitVtbl(i915); - i915InitDriverFunctions(&functions); - i915_init_state(i915); - - if (!intelInitContext(intel, mesaVis, driContextPriv, - sharedContextPrivate, &functions)) { - FREE(i915); - return GL_FALSE; - } + GLcontext *ctx = &i915->intel.ctx; ctx->Const.MaxTextureUnits = I915_TEX_UNITS; ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; @@ -121,9 +100,37 @@ i915CreateContext(const __GLcontextModes * mesaVis, ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN + I915_MAX_TEX_INSN); - ctx->Const.FragmentProgram.MaxNativeTexIndirections = - I915_MAX_TEX_INDIRECT; + ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT; ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ +} + + +GLboolean +i915CreateContext(const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + struct dd_function_table functions; + struct i915_context *i915 = CALLOC_STRUCT(i915_context); + struct intel_context *intel = &i915->intel; + GLcontext *ctx = &intel->ctx; + + if (!i915) + goto bad; + + i915InitVtbl(i915); + i915InitDriverFunctions(&functions); + i915_init_state(i915); + + i915->cctx = i915_create_caches( i915 ); + if (!i915->cctx) + goto bad; + + if (!intelInitContext(intel, mesaVis, driContextPriv, + sharedContextPrivate, &functions)) + goto bad; + + i915_init_gl_constants( i915 ); ctx->_MaintainTexEnvProgram = 1; ctx->_UseTexEnvProgram = 1; @@ -135,11 +142,19 @@ i915CreateContext(const __GLcontextModes * mesaVis, */ _tnl_allow_vertex_fog( ctx, 0 ); _tnl_allow_pixel_fog( ctx, 1 ); - _tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12, 36 * sizeof(GLfloat)); intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf; return GL_TRUE; + + bad: + if (i915->cctx) + i915_destroy_caches( i915->cctx ); + + if (i915) + FREE(i915); + + return GL_FALSE; } diff --git a/src/mesa/drivers/dri/i915tex/i915_context.h b/src/mesa/drivers/dri/i915tex/i915_context.h index 2af65a1151..024d8f3c61 100644 --- a/src/mesa/drivers/dri/i915tex/i915_context.h +++ b/src/mesa/drivers/dri/i915tex/i915_context.h @@ -36,8 +36,9 @@ #define I915_PROGRAM_SIZE 192 -#define I915_NEW_INPUT_SIZES (INTEL_NEW_DRIVER0<<0) -#define I915_NEW_VERTEX_FORMAT (INTEL_NEW_DRIVER0<<1) +#define I915_NEW_INPUT_SIZES (INTEL_NEW_DRIVER0<<0) +#define I915_NEW_VERTEX_FORMAT (INTEL_NEW_DRIVER0<<1) +#define I915_NEW_DYNAMIC_INDIRECT (INTEL_NEW_DRIVER0<<2) @@ -85,11 +86,24 @@ struct i915_fragment_program +#define I915_DYNAMIC_MODES4 0 +#define I915_DYNAMIC_DEPTHSCALE_0 1 +#define I915_DYNAMIC_DEPTHSCALE_1 2 +#define I915_DYNAMIC_IAB 3 +#define I915_DYNAMIC_BC_0 4 +#define I915_DYNAMIC_BC_1 5 +#define I915_DYNAMIC_BFO_0 6 +#define I915_DYNAMIC_BFO_1 7 +#define I915_DYNAMIC_SIZE 8 + + +struct i915_cache_context; struct i915_context { struct intel_context intel; + struct i915_cache_context *cctx; struct i915_fragment_program *fragment_program; @@ -104,22 +118,24 @@ struct i915_context struct { struct intel_tracked_state tracked_state; - - /* For short-circuiting - */ - GLfloat last_buf[I915_MAX_CONSTANT][4]; - GLuint last_bufsz; } constants; struct { - /* I915_NEW_INPUT_DIMENSIONS + /* I915_NEW_VERTEX_FORMAT */ - GLubyte input_sizes[FRAG_ATTRIB_MAX]; - GLuint LIS2; GLuint LIS4; - } fragprog; + } vertex_format; + /* Used for short-circuiting packets. Won't work for packets + * containing relocations. This is zero'd out after lost_context + * events. + */ + struct { + GLuint buf[I915_DYNAMIC_SIZE]; + GLboolean done_reset; + } dyn_indirect; + GLuint program_id; }; diff --git a/src/mesa/drivers/dri/i915tex/i915_fpc.h b/src/mesa/drivers/dri/i915tex/i915_fpc.h new file mode 100644 index 0000000000..61ccdda6b1 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fpc.h @@ -0,0 +1,217 @@ +/************************************************************************** + * + * 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 I915_PROGRAM_H +#define I915_PROGRAM_H + +#include "i915_context.h" +#include "i915_reg.h" + +/*********************************************************************** + * Public interface for the compiler + */ + +void i915_compile_fragment_program( struct i915_context *i915, + struct i915_fragment_program *fp ); + + +/*********************************************************************** + * Private details of the compiler + */ + +struct i915_fp_compile { + struct i915_fragment_program *fp; + + GLuint declarations[I915_PROGRAM_SIZE]; + GLuint program[I915_PROGRAM_SIZE]; + + GLuint constant_flags[I915_MAX_CONSTANT]; + + + GLuint *csr; /* Cursor, points into program. + */ + + GLuint *decl; /* Cursor, points into declarations. + */ + + GLuint decl_s; /* flags for which s regs need to be decl'd */ + GLuint decl_t; /* flags for which t regs need to be decl'd */ + + GLuint temp_flag; /* Tracks temporary regs which are in + * use. + */ + + GLuint utemp_flag; /* Tracks TYPE_U temporary regs which are in + * use. + */ + + GLuint nr_tex_indirect; + GLuint nr_tex_insn; + GLuint nr_alu_insn; + GLuint nr_decl_insn; + + + GLfloat (*env_param)[4]; +}; + + +/* Having zero and one in here makes the definition of swizzle a lot + * easier. + */ +#define UREG_TYPE_SHIFT 29 +#define UREG_NR_SHIFT 24 +#define UREG_CHANNEL_X_NEGATE_SHIFT 23 +#define UREG_CHANNEL_X_SHIFT 20 +#define UREG_CHANNEL_Y_NEGATE_SHIFT 19 +#define UREG_CHANNEL_Y_SHIFT 16 +#define UREG_CHANNEL_Z_NEGATE_SHIFT 15 +#define UREG_CHANNEL_Z_SHIFT 12 +#define UREG_CHANNEL_W_NEGATE_SHIFT 11 +#define UREG_CHANNEL_W_SHIFT 8 +#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5 +#define UREG_CHANNEL_ZERO_SHIFT 4 +#define UREG_CHANNEL_ONE_NEGATE_MBZ 1 +#define UREG_CHANNEL_ONE_SHIFT 0 + +#define UREG_BAD 0xffffffff /* not a valid ureg */ + +#define X SRC_X +#define Y SRC_Y +#define Z SRC_Z +#define W SRC_W +#define ZERO SRC_ZERO +#define ONE SRC_ONE + +/* Construct a ureg: + */ +#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \ + ((nr) << UREG_NR_SHIFT) | \ + (X << UREG_CHANNEL_X_SHIFT) | \ + (Y << UREG_CHANNEL_Y_SHIFT) | \ + (Z << UREG_CHANNEL_Z_SHIFT) | \ + (W << UREG_CHANNEL_W_SHIFT) | \ + (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \ + (ONE << UREG_CHANNEL_ONE_SHIFT)) + +#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20)) +#define CHANNEL_SRC( src, channel ) (src>>(channel*4)) + +#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)®_TYPE_MASK) +#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)®_NR_MASK) + + + +#define UREG_XYZW_CHANNEL_MASK 0x00ffff00 + +/* One neat thing about the UREG representation: + */ +static INLINE int +swizzle(int reg, int x, int y, int z, int w) +{ + return ((reg & ~UREG_XYZW_CHANNEL_MASK) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3)); +} + +/* Another neat thing about the UREG representation: + */ +static INLINE int +negate(int reg, int x, int y, int z, int w) +{ + return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) | + ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) | + ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) | + ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT)); +} + + +extern GLuint i915_get_temp(struct i915_fp_compile *p); +extern GLuint i915_get_utemp(struct i915_fp_compile *p); +extern void i915_release_utemps(struct i915_fp_compile *p); + + +extern GLuint i915_emit_texld(struct i915_fp_compile *p, + GLuint dest, + GLuint destmask, + GLuint sampler, GLuint coord, GLuint op); + +extern GLuint i915_emit_arith(struct i915_fp_compile *p, + GLuint op, + GLuint dest, + GLuint mask, + GLuint saturate, + GLuint src0, GLuint src1, GLuint src2); + +extern GLuint i915_emit_decl(struct i915_fp_compile *p, + GLuint type, GLuint nr, GLuint d0_flags); + + +extern GLuint i915_emit_const1f(struct i915_fp_compile *p, GLfloat c0); + +extern GLuint i915_emit_const2f(struct i915_fp_compile *p, + GLfloat c0, GLfloat c1); + +extern GLuint i915_emit_const4fv(struct i915_fp_compile *p, + const GLfloat * c); + +extern GLuint i915_emit_const4f(struct i915_fp_compile *p, + GLfloat c0, GLfloat c1, + GLfloat c2, GLfloat c3); + + +extern GLuint i915_emit_param4fv(struct i915_fp_compile *p, + const GLfloat * values); + + + +/*====================================================================== + * i915_fpc_debug.c + */ +extern void i915_program_error(struct i915_fp_compile *p, + const char *msg); + + +/*====================================================================== + * i915_fpc_debug.c + */ +extern void i915_disassemble_program(const GLuint * program, GLuint sz); + +extern void i915_print_mesa_instructions( const struct prog_instruction *insn, + GLuint nr ); + +/*====================================================================== + * i915_fpc_translate.c + */ +void i915_fixup_depth_write(struct i915_fp_compile *p); +void i915_translate_program(struct i915_fp_compile *p); + + + +#endif diff --git a/src/mesa/drivers/dri/i915tex/i915_state_indirect.c b/src/mesa/drivers/dri/i915tex/i915_indirect.c index 0445f8e6f7..9c3f6aaf2c 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_indirect.c +++ b/src/mesa/drivers/dri/i915tex/i915_indirect.c @@ -6,10 +6,10 @@ -static GLuint emit_indirect(struct intel_context *intel, - GLuint flag, - const GLuint *state, - GLuint size ) +static GLuint i915_emit_indirect(struct intel_context *intel, + GLuint flag, + const GLuint *state, + GLuint size ) { GLuint delta; GLuint segment; @@ -127,3 +127,33 @@ const struct i915_tracked_state i915_indirect_state = { }, .update = upload_indirect_state }; + + +#if 0 + GLuint size = I915_DYNAMIC_SIZE * 4; + GLuint flag = i915->dyn_indirect.done_reset ? 0 : DIS0_BUFFER_RESET; + + GLuint delta = ( (intel->batch->segment_finish_offset[segment] + size - 4) | + DIS0_BUFFER_VALID | + flag ); + + BEGIN_BATCH(2,0); + OUT_BATCH( _3DSTATE_LOAD_INDIRECT | LI0_STATE_DYNAMIC_INDIRECT | (1<<14) | 0); + OUT_RELOC( intel->batch->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE, + delta ); + ADVANCE_BATCH(); + + + { + GLuint segment = SEGMENT_DYNAMIC_INDIRECT; + GLuint offset = intel->batch->segment_finish_offset[segment]; + intel->batch->segment_finish_offset[segment] += size; + + if (state != NULL) + memcpy(intel->batch->map + offset, state, size); + + return offset; + } +#endif diff --git a/src/mesa/drivers/dri/i915tex/i915_state.c b/src/mesa/drivers/dri/i915tex/i915_state.c index e21237400f..b680d4fb49 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state.c +++ b/src/mesa/drivers/dri/i915tex/i915_state.c @@ -46,20 +46,10 @@ const struct intel_tracked_state *atoms[] = { &i915_check_fallback, - &i915_invarient_state, - &intel_update_viewport, &intel_update_render_index, - /* - */ -/* &i915_fp_choose_prog, */ - - /* Scan VB: - */ -/* &i915_vb_output_sizes, */ - /* Get compiled version of the fragment program which is mildly * optimized according to input sizes. This will be cached, but * for now recompile on all changes. @@ -67,41 +57,41 @@ const struct intel_tracked_state *atoms[] = * Also calculate vertex layout, immediate (S2,S4) state, vertex * size. */ - &i915_fp_compile_and_upload, + &i915_upload_program, /* Calculate vertex format, program t_vertex.c, etc: */ &i915_vertex_format, - /* Immediate state. Don't make any effort to combine packets yet. */ - &i915_upload_MODES4, + &i915_upload_S0S1, &i915_upload_S2S4, &i915_upload_S5, &i915_upload_S6, - &i915_upload_IAB, + &i915_upload_S7, + + /* Dynamic indirect. Packets are combined in a final step. + */ + &i915_upload_BFO, &i915_upload_BLENDCOLOR, + &i915_upload_DEPTHSCALE, + &i915_upload_IAB, + &i915_upload_MODES4, + &i915_upload_dynamic_indirect, - /* Other state. This will eventually be able to emit itself either - * to the batchbuffer directly, or as indirect state. Indirect - * state will be subject to caching so that we get something like - * constant state objects from the i965 driver. + /* Static indirect state. */ + &i915_upload_invarient, &i915_upload_buffers, &i915_upload_scissor, + &i915_upload_stipple, - /* Note this packet has a dependency on the current primitive: + /* Other indirect state. Also includes program state, above. */ - &i915_upload_stipple, - &i915_upload_maps, /* must do before samplers */ &i915_upload_samplers, - - NULL, /* i915_fp_constants */ - - &i915_upload_BFO, - &i915_upload_S0S1 + &i915_upload_constants /* will be patched out at runtime */ }; @@ -117,12 +107,12 @@ void i915_init_state( struct i915_context *i915 ) /* Patch in a pointer to the dynamic state atom: */ for (i = 0; i < intel->driver_state.nr_atoms; i++) - if (intel->driver_state.atoms[i] == NULL) + if (intel->driver_state.atoms[i] == &i915_upload_constants) intel->driver_state.atoms[i] = &i915->constants.tracked_state; _mesa_memcpy(&i915->constants.tracked_state, - &i915_fp_constants, - sizeof(i915_fp_constants)); + &i915_upload_constants, + sizeof(i915_upload_constants)); } diff --git a/src/mesa/drivers/dri/i915tex/i915_state.h b/src/mesa/drivers/dri/i915tex/i915_state.h index 4ba0d8b775..0f8464fdd7 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state.h +++ b/src/mesa/drivers/dri/i915tex/i915_state.h @@ -34,29 +34,65 @@ #define I915_STATE_H #include "i915_context.h" +#include "i915_reg.h" + void i915_init_state( struct i915_context *i915 ); void i915_destroy_state( struct i915_context *i915 ); const struct intel_tracked_state i915_check_fallback; -const struct intel_tracked_state i915_fp_constants; -const struct intel_tracked_state i915_fp_compile_and_upload; const struct intel_tracked_state i915_vertex_format; -const struct intel_tracked_state i915_invarient_state; -const struct intel_tracked_state i915_upload_BFO; -const struct intel_tracked_state i915_upload_BLENDCOLOR; -const struct intel_tracked_state i915_upload_IAB; -const struct intel_tracked_state i915_upload_MODES4; + +/* Immediate state: + */ const struct intel_tracked_state i915_upload_S0S1; const struct intel_tracked_state i915_upload_S2S4; const struct intel_tracked_state i915_upload_S5; const struct intel_tracked_state i915_upload_S6; +const struct intel_tracked_state i915_upload_S7; + +/* Dynamic indirect: + */ +const struct intel_tracked_state i915_upload_BFO; +const struct intel_tracked_state i915_upload_BLENDCOLOR; +const struct intel_tracked_state i915_upload_DEPTHSCALE; +const struct intel_tracked_state i915_upload_IAB; +const struct intel_tracked_state i915_upload_MODES4; +const struct intel_tracked_state i915_upload_dynamic_indirect; + +/* Static indirect: + */ +const struct intel_tracked_state i915_upload_invarient; const struct intel_tracked_state i915_upload_buffers; -const struct intel_tracked_state i915_upload_maps; -const struct intel_tracked_state i915_upload_samplers; const struct intel_tracked_state i915_upload_scissor; const struct intel_tracked_state i915_upload_stipple; +/* Other indirect: + */ +const struct intel_tracked_state i915_upload_constants; +const struct intel_tracked_state i915_upload_program; +const struct intel_tracked_state i915_upload_maps; +const struct intel_tracked_state i915_upload_samplers; + + +static INLINE GLuint +i915_translate_blend_equation(GLenum mode) +{ + switch (mode) { + case GL_FUNC_ADD: + return BLENDFUNC_ADD; + case GL_MIN: + return BLENDFUNC_MIN; + case GL_MAX: + return BLENDFUNC_MAX; + case GL_FUNC_SUBTRACT: + return BLENDFUNC_SUBTRACT; + case GL_FUNC_REVERSE_SUBTRACT: + return BLENDFUNC_REVERSE_SUBTRACT; + default: + return 0; + } +} #endif diff --git a/src/mesa/drivers/dri/i915tex/i915_state_fp.c b/src/mesa/drivers/dri/i915tex/i915_state_constants.c index e8a768c2e3..630f2418b9 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_fp.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_constants.c @@ -32,69 +32,11 @@ #include "intel_batchbuffer.h" #include "i915_context.h" -#include "i915_fpc.h" +#include "i915_cache.h" +#include "i915_reg.h" - - -/********************************************************************************* - * Program instructions (and decls) - */ - - -static void i915_upload_fp( struct intel_context *intel ) -{ - struct i915_context *i915 = i915_context( &intel->ctx ); - struct i915_fragment_program *fp = i915->fragment_program; - GLuint i; - - if (&fp->Base != intel->state.FragmentProgram->_Current) { - i915->fragment_program = (struct i915_fragment_program *) - intel->state.FragmentProgram->_Current; - - fp = i915->fragment_program; - /* This is stupid - */ - intel->state.dirty.intel |= INTEL_NEW_FRAGMENT_PROGRAM; - } - - /* As the compiled program depends only on the original program - * text (??? for now at least ???), there is no need for a compiled - * program cache, just store the compiled version with the original - * text. - */ - if (!fp->translated) { - i915_compile_fragment_program(i915, fp); - } - - BEGIN_BATCH( fp->program_size, 0 ); - - for (i = 0; i < fp->program_size; i++) - OUT_BATCH( fp->program[i] ); - - ADVANCE_BATCH(); - -#if 0 - emit_indirect(intel, LI0_STATE_PROGRAM, - state->Program, state->ProgramSize * sizeof(GLuint)); -#endif - -} - - -/* See i915_wm.c: - */ -const struct intel_tracked_state i915_fp_compile_and_upload = { - .dirty = { - .mesa = (0), - .intel = (INTEL_NEW_FRAGMENT_PROGRAM), /* ?? Is this all ?? */ - .extra = 0 - }, - .update = i915_upload_fp -}; - - /********************************************************************************* * Program constants and state parameters */ @@ -105,40 +47,39 @@ upload_constants(struct intel_context *intel) struct i915_fragment_program *p = i915->fragment_program; GLint i; - /* XXX: Pull from state, not ctx!!! + /* XXX: Pull from state, not ctx!!! Luckily no metaops programs + * have parameters, yet... */ - if (p->nr_params) + if (p->nr_params) { + assert(!intel->metaops.active); _mesa_load_state_parameters(&intel->ctx, p->Base.Base.Parameters); - for (i = 0; i < p->nr_params; i++) { - GLint reg = p->param[i].reg; - COPY_4V(p->constant[reg], p->param[i].values); + for (i = 0; i < p->nr_params; i++) { + GLint reg = p->param[i].reg; + COPY_4V(p->constant[reg], p->param[i].values); + } } - /* Always seemed to get a failure if I used memcmp() to - * shortcircuit this state upload. Needs further investigation? + /* Another fairly pointless copy - need a better interface to the + * cache. */ if (p->nr_constants) { GLuint nr = p->nr_constants; + struct i915_cache_packet packet; - BEGIN_BATCH( nr * 4 + 2, 0 ); - OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) ); - OUT_BATCH( (1 << (nr - 1)) | ((1 << (nr - 1)) - 1) ); + packet_init( &packet, I915_CACHE_CONSTANTS, nr * 4 + 2, 0 ); + packet_dword( &packet, _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) ); + packet_dword( &packet, (1 << (nr - 1)) | ((1 << (nr - 1)) - 1) ); for (i = 0; i < nr; i++) { - OUT_BATCH_F(p->constant[i][0]); - OUT_BATCH_F(p->constant[i][1]); - OUT_BATCH_F(p->constant[i][2]); - OUT_BATCH_F(p->constant[i][3]); + packet_float(&packet, p->constant[i][0]); + packet_float(&packet, p->constant[i][1]); + packet_float(&packet, p->constant[i][2]); + packet_float(&packet, p->constant[i][3]); } - ADVANCE_BATCH(); + i915_cache_emit( i915->cctx, &packet ); } - -#if 0 - emit_indirect(intel, LI0_STATE_CONSTANTS, - state->Constant, state->ConstantSize * sizeof(GLuint)); -#endif } diff --git a/src/mesa/drivers/dri/i915tex/i915_state_dynamic.c b/src/mesa/drivers/dri/i915tex/i915_state_dynamic.c new file mode 100644 index 0000000000..8239976ce5 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_dynamic.c @@ -0,0 +1,413 @@ +/************************************************************************** + * + * 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 "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" + +#include "intel_fbo.h" +#include "intel_batchbuffer.h" +#include "intel_regions.h" +#include "intel_state_inlines.h" + +#include "i915_context.h" +#include "i915_reg.h" +#include "i915_state.h" + +#define FILE_DEBUG_FLAG DEBUG_STATE + +/* State that we have chosen to store in the DYNAMIC segment of the + * i915 indirect state mechanism. + * + * It is very nice to note that in normal rendering, none of these + * packets will end up being emitted. + * + * Can't cache these in the way we do the static state, as there is no + * start/size in the command packet, instead an 'end' value that gets + * incremented. + * + * Additionally, there seems to be a requirement to re-issue the full + * (active) state every time a 4kb boundary is crossed. + * + * Simplest implementation is probably just to emit the full active + * state every time. Next would be to diff against previous, but note + */ + +static void set_dynamic_indirect( struct intel_context *intel, + GLuint offset, + const GLuint *src, + GLuint size ) +{ +#if 0 + struct i915_context *i915 = i915_context( &intel->ctx ); + GLuint *dest = i915->dyn_indirect.buf + offset; + GLuint i; + + for (i = 0; i < size; i++) { + if (dest[i] != src[i]) { + dest[i] = src[i]; + intel->state.dirty.intel |= I915_NEW_DYNAMIC_INDIRECT; + } + } +#else + GLuint i; + BEGIN_BATCH(size, 0); + for (i = 0; i < size; i++) + OUT_BATCH(src[i]); + ADVANCE_BATCH(); +#endif +} + + +/*********************************************************************** + * Modes4: stencil masks and logicop + */ +static void upload_MODES4( struct intel_context *intel ) +{ + GLuint modes4 = 0; + + /* _NEW_STENCIL */ + if (intel->state.Stencil->Enabled) { + GLint testmask = intel->state.Stencil->ValueMask[0] & 0xff; + GLint writemask = intel->state.Stencil->WriteMask[0] & 0xff; + + modes4 |= (_3DSTATE_MODES_4_CMD | + ENABLE_STENCIL_TEST_MASK | + STENCIL_TEST_MASK(testmask) | + ENABLE_STENCIL_WRITE_MASK | + STENCIL_WRITE_MASK(writemask)); + } + + /* _NEW_COLOR */ + if (intel->state.Color->_LogicOpEnabled) { + modes4 |= (_3DSTATE_MODES_4_CMD | + ENABLE_LOGIC_OP_FUNC | + LOGIC_OP_FUNC(intel_translate_logic_op(intel->state.Color->LogicOp))); + } + + /* Always, so that we know when state is in-active: + */ + set_dynamic_indirect( intel, + I915_DYNAMIC_MODES4, + &modes4, + 1 ); +} + +const struct intel_tracked_state i915_upload_MODES4 = { + .dirty = { + .mesa = _NEW_COLOR | _NEW_STENCIL, + .intel = 0, + .extra = 0 + }, + .update = upload_MODES4 +}; + + +/*********************************************************************** + */ + +static void upload_BFO( struct intel_context *intel ) +{ + GLuint bf[2]; + + bf[0] = 0; + bf[1] = 0; + + + /* _NEW_STENCIL + */ + if (intel->state.Stencil->Enabled) { + if (intel->state.Stencil->TestTwoSide) { + GLint test = intel_translate_compare_func(intel->state.Stencil->Function[1]); + GLint fop = intel_translate_stencil_op(intel->state.Stencil->FailFunc[1]); + GLint dfop = intel_translate_stencil_op(intel->state.Stencil->ZFailFunc[1]); + GLint dpop = intel_translate_stencil_op(intel->state.Stencil->ZPassFunc[1]); + GLint ref = intel->state.Stencil->Ref[1] & 0xff; + GLint wmask = intel->state.Stencil->WriteMask[1] & 0xff; + GLint tmask = intel->state.Stencil->ValueMask[1] & 0xff; + + bf[0] = (_3DSTATE_BACKFACE_STENCIL_OPS | + BFO_ENABLE_STENCIL_FUNCS | + BFO_ENABLE_STENCIL_TWO_SIDE | + BFO_ENABLE_STENCIL_REF | + BFO_STENCIL_TWO_SIDE | + (ref << BFO_STENCIL_REF_SHIFT) | + (test << BFO_STENCIL_TEST_SHIFT) | + (fop << BFO_STENCIL_FAIL_SHIFT) | + (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) | + (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT)); + + bf[1] = (_3DSTATE_BACKFACE_STENCIL_MASKS | + BFM_ENABLE_STENCIL_TEST_MASK | + BFM_ENABLE_STENCIL_WRITE_MASK | + (tmask << BFM_STENCIL_TEST_MASK_SHIFT) | + (wmask << BFM_STENCIL_WRITE_MASK_SHIFT)); + } + else { + /* This actually disables two-side stencil: The bit set is a + * modify-enable bit to indicate we are changing the two-side + * setting. Then there is a symbolic zero to show that we are + * setting the flag to zero/off. + */ + bf[0] = (_3DSTATE_BACKFACE_STENCIL_OPS | + BFO_ENABLE_STENCIL_TWO_SIDE | + 0); + bf[1] = 0; + } + } + + + set_dynamic_indirect( intel, + I915_DYNAMIC_BFO_0, + &bf[0], + 2 ); +} + +const struct intel_tracked_state i915_upload_BFO = { + .dirty = { + .mesa = _NEW_STENCIL, + .intel = 0, + .extra = 0 + }, + .update = upload_BFO +}; + + +/*********************************************************************** + */ + + +static void upload_BLENDCOLOR( struct intel_context *intel ) +{ + GLuint bc[2]; + + /* _NEW_COLOR + */ + if (intel->state.Color->BlendEnabled) { + const GLfloat *color = intel->state.Color->BlendColor; + GLubyte r, g, b, a; + + UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); + + bc[0] = (_3DSTATE_CONST_BLEND_COLOR_CMD); + bc[1] = (a << 24) | (r << 16) | (g << 8) | b; + + } + else { + bc[0] = 0; + bc[1] = 0; + } + + set_dynamic_indirect( intel, + I915_DYNAMIC_BC_0, + bc, + 2 ); +} + +const struct intel_tracked_state i915_upload_BLENDCOLOR = { + .dirty = { + .mesa = _NEW_COLOR, + .intel = 0, + .extra = 0 + }, + .update = upload_BLENDCOLOR +}; + +/*********************************************************************** + */ + + +static void upload_IAB( struct intel_context *intel ) +{ + GLuint iab = 0; + + if (intel->state.Color->BlendEnabled) { + GLuint eqRGB = intel->state.Color->BlendEquationRGB; + GLuint eqA = intel->state.Color->BlendEquationA; + GLuint srcRGB = intel->state.Color->BlendSrcRGB; + GLuint dstRGB = intel->state.Color->BlendDstRGB; + GLuint srcA = intel->state.Color->BlendSrcA; + GLuint dstA = intel->state.Color->BlendDstA; + + if (eqA == GL_MIN || eqA == GL_MAX) { + srcA = dstA = GL_ONE; + } + + if (eqRGB == GL_MIN || eqRGB == GL_MAX) { + srcRGB = dstRGB = GL_ONE; + } + + if (srcA != srcRGB || + dstA != dstRGB || + eqA != eqRGB) { + + iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | + IAB_MODIFY_ENABLE | + IAB_ENABLE | + IAB_MODIFY_FUNC | + IAB_MODIFY_SRC_FACTOR | + IAB_MODIFY_DST_FACTOR | + SRC_ABLND_FACT(intel_translate_blend_factor(srcA)) | + DST_ABLND_FACT(intel_translate_blend_factor(dstA)) | + (i915_translate_blend_equation(eqA) << IAB_FUNC_SHIFT)); + } + else { + iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | + IAB_MODIFY_ENABLE | + 0); + } + } + + + set_dynamic_indirect( intel, + I915_DYNAMIC_IAB, + &iab, + 1 ); +} + +const struct intel_tracked_state i915_upload_IAB = { + .dirty = { + .mesa = _NEW_COLOR, + .intel = 0, + .extra = 0 + }, + .update = upload_IAB +}; + + +/*********************************************************************** + */ + + + +static void upload_DEPTHSCALE( struct intel_context *intel ) +{ + union { GLfloat f; GLuint u; } ds[2]; + + ds[0].u = 0; + ds[1].u = 0; + + if (intel->state.Polygon->OffsetFill) { + + ds[0].u = (_3DSTATE_DEPTH_OFFSET_SCALE); + ds[1].f = 0; /* XXX */ + + } + + set_dynamic_indirect( intel, + I915_DYNAMIC_DEPTHSCALE_0, + &ds[0].u, + 2 ); +} + +const struct intel_tracked_state i915_upload_DEPTHSCALE = { + .dirty = { + .mesa = _NEW_POLYGON, + .intel = 0, + .extra = 0 + }, + .update = upload_DEPTHSCALE +}; + +/*********************************************************************** + * Do the group emit in a single packet. + */ + +#define CHECK( idx, nr ) do { \ + if (i915->dyn_indirect.buf[idx] != 0) { \ + GLint i; \ + for (i = 0; i < nr; i++) \ + buf[count++] = i915->dyn_indirect.buf[idx+i]; \ + } \ +} while (0) + + + +static void emit_indirect( struct intel_context *intel ) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + GLuint buf[I915_DYNAMIC_SIZE], count = 0; + + return; + + CHECK( I915_DYNAMIC_MODES4, 1 ); + CHECK( I915_DYNAMIC_DEPTHSCALE_0, 2 ); + CHECK( I915_DYNAMIC_IAB, 1 ); + CHECK( I915_DYNAMIC_BC_0, 2 ); + CHECK( I915_DYNAMIC_BFO_0, 2 ); + + /* XXX: need to check if we wrap 4kb and if so pad. + */ + /* Or just emit the whole lot, zeros and all (fix later...): + */ + /* Also - want to check that something has changed & we're not just + * re-emitting the same stuff. + */ + if (count) { + GLuint size = I915_DYNAMIC_SIZE * 4; + GLuint flag = i915->dyn_indirect.done_reset ? 0 : DIS0_BUFFER_RESET; + GLuint segment = SEGMENT_DYNAMIC_INDIRECT; + GLuint offset = intel->batch->segment_finish_offset[segment]; + + i915->dyn_indirect.done_reset = 1; + + BEGIN_BATCH(2,0); + OUT_BATCH( _3DSTATE_LOAD_INDIRECT | LI0_STATE_DYNAMIC_INDIRECT | (1<<14) | 0); + OUT_RELOC( intel->batch->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE, + ((offset + size - 4) | DIS0_BUFFER_VALID | flag) ); + ADVANCE_BATCH(); + + /* XXX: + */ + assert( offset + size < intel->batch->segment_max_offset[segment]); + intel->batch->segment_finish_offset[segment] += size; + + /* Just emit the original buffer, zeros and all as this will + * avoid wrapping issues. This is usually not emitted at all, + * so not urgent to fix: + */ + memcpy(intel->batch->map + offset, i915->dyn_indirect.buf, size ); + } +} + +const struct intel_tracked_state i915_upload_dynamic_indirect = { + .dirty = { + .mesa = 0, + .intel = I915_NEW_DYNAMIC_INDIRECT, + .extra = 0 + }, + .update = emit_indirect +}; + + + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_fallback.c b/src/mesa/drivers/dri/i915tex/i915_state_fallback.c index c327e19c44..a559037916 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_fallback.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_fallback.c @@ -1,29 +1,30 @@ -/* - Copyright (C) Intel Corp. 2006. All Rights Reserved. - Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - develop this 3D driver. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice (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 NONINFRINGEMENT. - IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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. - - **********************************************************************/ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + /* * Authors: * Keith Whitwell <keith@tungstengraphics.com> diff --git a/src/mesa/drivers/dri/i915tex/i915_state_immediate.c b/src/mesa/drivers/dri/i915tex/i915_state_immediate.c index e08748ad96..495f8fe903 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_immediate.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_immediate.c @@ -38,10 +38,15 @@ #include "i915_context.h" #include "i915_state.h" -#include "i915_state_inlines.h" #include "i915_reg.h" +/* All state expressable with the LOAD_STATE_IMMEDIATE_1 packet. + * Would like to opportunistically recombine all these fragments into + * a single packet containing only what has changed, but for now emit + * as multiple packets. + */ + #define STATE_LOGICOP_ENABLED(state) \ ((state)->Color->ColorLogicOpEnabled || \ ((state)->Color->BlendEnabled && (state)->Color->BlendEquationRGB == GL_LOGIC_OP)) @@ -99,8 +104,8 @@ static void upload_S2S4(struct intel_context *intel) GLuint LIS2, LIS4; /* I915_NEW_VERTEX_FORMAT */ - LIS2 = i915->fragprog.LIS2; - LIS4 = i915->fragprog.LIS4; + LIS2 = i915->vertex_format.LIS2; + LIS4 = i915->vertex_format.LIS4; /* _NEW_POLYGON, _NEW_BUFFERS */ @@ -216,6 +221,12 @@ static void upload_S5( struct intel_context *intel ) LIS5 |= S5_COLOR_DITHER_ENABLE; } + /* _NEW_POLYGON */ + if (intel->state.Polygon->OffsetFill) { + LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE; + } + + { const GLubyte *mask = intel->state.Color->ColorMask; @@ -326,3 +337,32 @@ const struct intel_tracked_state i915_upload_S6 = { .update = upload_S6 }; + +/*********************************************************************** + */ +static void upload_S7( struct intel_context *intel ) +{ + GLfloat LIS7; + + /* _NEW_POLYGON + */ +/* LIS7 = intel->state.Polygon->OffsetUnits * DEPTH_SCALE; */ + LIS7 = 0; + + BEGIN_BATCH(2, 0); + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(7) | + 0); + OUT_BATCH_F(LIS7); + ADVANCE_BATCH(); + +} + +const struct intel_tracked_state i915_upload_S7 = { + .dirty = { + .mesa = (_NEW_POLYGON), + .intel = 0, + .extra = 0 + }, + .update = upload_S7 +}; diff --git a/src/mesa/drivers/dri/i915tex/i915_state_invarient.c b/src/mesa/drivers/dri/i915tex/i915_state_invarient.c deleted file mode 100644 index ecca70aad0..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_state_invarient.c +++ /dev/null @@ -1,143 +0,0 @@ -/************************************************************************** - * - * 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 "glheader.h" -#include "macros.h" -#include "enums.h" -#include "program.h" - -#include "intel_batchbuffer.h" -#include "i915_context.h" -#include "i915_reg.h" - - - - -/*********************************************************************** - * Misc invarient state packets - */ - -static void upload_invarient_state( struct intel_context *intel ) -{ - static GLuint invarient_state[] = { - - (_3DSTATE_AA_CMD | - AA_LINE_ECAAR_WIDTH_ENABLE | - AA_LINE_ECAAR_WIDTH_1_0 | - AA_LINE_REGION_WIDTH_ENABLE | - AA_LINE_REGION_WIDTH_1_0), - - /* Could use these to reduce the size of vertices when the incoming - * array is constant. - */ - (_3DSTATE_DFLT_DIFFUSE_CMD), - (0), - - (_3DSTATE_DFLT_SPEC_CMD), - (0), - - (_3DSTATE_DFLT_Z_CMD), - (0), - - /* We support texture crossbar via the fragment shader, rather than - * with this mechanism. - */ - (_3DSTATE_COORD_SET_BINDINGS | - CSB_TCB(0, 0) | - CSB_TCB(1, 1) | - CSB_TCB(2, 2) | - CSB_TCB(3, 3) | - CSB_TCB(4, 4) | - CSB_TCB(5, 5) | - CSB_TCB(6, 6) | - CSB_TCB(7, 7)), - - /* Setup OpenGL rasterization state: - */ - (_3DSTATE_RASTER_RULES_CMD | - ENABLE_POINT_RASTER_RULE | - OGL_POINT_RASTER_RULE | - ENABLE_LINE_STRIP_PROVOKE_VRTX | - ENABLE_TRI_FAN_PROVOKE_VRTX | - LINE_STRIP_PROVOKE_VRTX(1) | - TRI_FAN_PROVOKE_VRTX(2) | - ENABLE_TEXKILL_3D_4D | - TEXKILL_4D), - - /* Need to initialize this to zero. - */ - (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(3) | - (0)), - (0), - - (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT), - (_3DSTATE_SCISSOR_RECT_0_CMD), - (0), - (0), - - - /* For private depth buffers but shared color buffers, eg - * front-buffer rendering with a private depthbuffer. We don't do - * this. - */ - (_3DSTATE_DEPTH_SUBRECT_DISABLE), - - (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0) - }; - - /* Disable indirect state for now. - */ - BEGIN_BATCH(2, 0); - OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); - OUT_BATCH(0); - ADVANCE_BATCH(); - - - { - GLuint i; - - BEGIN_BATCH(sizeof(invarient_state)/4, 0); - - for (i = 0; i < sizeof(invarient_state)/4; i++) - OUT_BATCH( invarient_state[i] ); - - ADVANCE_BATCH(); - } -} - -const struct intel_tracked_state i915_invarient_state = { - .dirty = { - .mesa = 0, - .intel = INTEL_NEW_CONTEXT, /* or less frequently? */ - .extra = 0 - }, - .update = upload_invarient_state -}; - - - diff --git a/src/mesa/drivers/dri/i915tex/i915_state_map.c b/src/mesa/drivers/dri/i915tex/i915_state_map.c index ea01c54777..5f2f727374 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_map.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_map.c @@ -36,6 +36,7 @@ #include "i915_context.h" #include "i915_reg.h" +#include "i915_cache.h" static GLuint @@ -141,33 +142,30 @@ upload_maps( struct intel_context *intel ) } if (nr) { - BEGIN_BATCH(2 + nr * 3, 0); - OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); - OUT_BATCH(dirty); + struct i915_cache_packet packet; + + packet_init( &packet, I915_CACHE_MAP, nr * 3 + 2, 0 ); + packet_dword( &packet, _3DSTATE_MAP_STATE | (3 * nr)); + packet_dword( &packet, dirty); for (i = 0; i < I915_TEX_UNITS; i++) { if (dirty & (1<<i)) { - if (i915->state.tex_buffer[i]) { - OUT_RELOC(i915->state.tex_buffer[i], - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, - i915->state.tex_offset[i]); - } - else { - assert(i == 0); - assert(intel->metaops.active); /* when does this happen? */ - OUT_BATCH(0); - } - - OUT_BATCH(state[i][0]); - OUT_BATCH(state[i][1]); + assert (i915->state.tex_buffer[i]); + + packet_reloc( &packet, + i915->state.tex_buffer[i], + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, + i915->state.tex_offset[i] ); + + packet_dword( &packet, state[i][0] ); + packet_dword( &packet, state[i][1] ); } } - ADVANCE_BATCH(); - } -/* return GL_TRUE; */ + i915_cache_emit( i915->cctx, &packet ); + } } diff --git a/src/mesa/drivers/dri/i915tex/i915_state_misc.c b/src/mesa/drivers/dri/i915tex/i915_state_misc.c deleted file mode 100644 index 1c97d4d975..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_state_misc.c +++ /dev/null @@ -1,448 +0,0 @@ -/************************************************************************** - * - * 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 "glheader.h" -#include "context.h" -#include "macros.h" -#include "enums.h" - -#include "intel_fbo.h" -#include "intel_batchbuffer.h" -#include "intel_regions.h" -#include "intel_state_inlines.h" - -#include "i915_context.h" -#include "i915_reg.h" -#include "i915_state.h" -#include "i915_state_inlines.h" - -#define FILE_DEBUG_FLAG DEBUG_STATE - -/*********************************************************************** - * Modes4: stencil masks and logicop - */ -static void upload_MODES4( struct intel_context *intel ) -{ - GLuint modes4 = _3DSTATE_MODES_4_CMD; - - /* _NEW_STENCIL */ - if (1||intel->state.Stencil->Enabled) { - GLint testmask = intel->state.Stencil->ValueMask[0] & 0xff; - GLint writemask = intel->state.Stencil->WriteMask[0] & 0xff; - - modes4 |= (ENABLE_STENCIL_TEST_MASK | - STENCIL_TEST_MASK(testmask) | - ENABLE_STENCIL_WRITE_MASK | - STENCIL_WRITE_MASK(writemask)); - } - - /* _NEW_COLOR */ - if (1 || intel->state.Color->_LogicOpEnabled) - { - modes4 |= (ENABLE_LOGIC_OP_FUNC | - LOGIC_OP_FUNC(intel_translate_logic_op(intel->state.Color->LogicOp))); - } - else { - /* This seems to be the only way to turn off logicop. The - * ENABLE_LOGIC_OP_FUNC is just a modify-enable bit to say this - * field is present in the instruction. - */ - modes4 |= (ENABLE_LOGIC_OP_FUNC | - LOGICOP_COPY); - } - - /* This needs to be sent in all states (subject eventually to - * caching to avoid duplicate emits, and later to indirect state - * management) - */ - BEGIN_BATCH(1,0); - OUT_BATCH(modes4); - ADVANCE_BATCH(); -} - -const struct intel_tracked_state i915_upload_MODES4 = { - .dirty = { - .mesa = _NEW_STENCIL | _NEW_COLOR, - .intel = 0, - .extra = 0 - }, - .update = upload_MODES4 -}; - - -/*********************************************************************** - * BFO: Backface stencil - */ - -static void upload_BFO( struct intel_context *intel ) -{ - GLuint bfo; - - /* _NEW_STENCIL - */ - if (intel->state.Stencil->Enabled) { - GLint test = intel_translate_compare_func(intel->state.Stencil->Function[1]); - GLint fop = intel_translate_stencil_op(intel->state.Stencil->FailFunc[1]); - GLint dfop = intel_translate_stencil_op(intel->state.Stencil->ZFailFunc[1]); - GLint dpop = intel_translate_stencil_op(intel->state.Stencil->ZPassFunc[1]); - GLint ref = intel->state.Stencil->Ref[1] & 0xff; - - bfo = (_3DSTATE_BACKFACE_STENCIL_OPS | - BFO_ENABLE_STENCIL_FUNCS | - BFO_ENABLE_STENCIL_TWO_SIDE | - BFO_ENABLE_STENCIL_REF | - BFO_STENCIL_TWO_SIDE | - (ref << BFO_STENCIL_REF_SHIFT) | - (test << BFO_STENCIL_TEST_SHIFT) | - (fop << BFO_STENCIL_FAIL_SHIFT) | - (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) | - (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT)); - } - else { - /* This actually disables two-side stencil: The bit set is a - * modify-enable bit to indicate we are changing the two-side - * setting. Then there is a symbolic zero to show that we are - * setting the flag to zero/off. - */ - bfo = (_3DSTATE_BACKFACE_STENCIL_OPS | - BFO_ENABLE_STENCIL_TWO_SIDE | - 0); - } - - BEGIN_BATCH(1,0); - OUT_BATCH(bfo); - ADVANCE_BATCH(); -} - -const struct intel_tracked_state i915_upload_BFO = { - .dirty = { - .mesa = _NEW_STENCIL, - .intel = 0, - .extra = 0 - }, - .update = upload_BFO -}; - - -/*********************************************************************** - * BLENDCOLOR - */ -static void upload_BLENDCOLOR( struct intel_context *intel ) -{ - /* _NEW_COLOR - */ - if (1 || intel->state.Color->BlendEnabled) { - const GLfloat *color = intel->state.Color->BlendColor; - GLubyte r, g, b, a; - - UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); - - /* Only needs to be sent when blend is enabled - */ - BEGIN_BATCH(2, 0); - OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD); - OUT_BATCH( (a << 24) | (r << 16) | (g << 8) | b ); - ADVANCE_BATCH(); - } -} - -const struct intel_tracked_state i915_upload_BLENDCOLOR = { - .dirty = { - .mesa = _NEW_COLOR, - .intel = 0, - .extra = 0 - }, - .update = upload_BLENDCOLOR -}; - - -/*********************************************************************** - * IAB: Independent Alpha Blend - */ -static void upload_IAB( struct intel_context *intel ) -{ - GLuint iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | - IAB_MODIFY_ENABLE | - 0); - - if (1) { - GLuint eqRGB = intel->state.Color->BlendEquationRGB; - GLuint eqA = intel->state.Color->BlendEquationA; - GLuint srcRGB = intel->state.Color->BlendSrcRGB; - GLuint dstRGB = intel->state.Color->BlendDstRGB; - GLuint srcA = intel->state.Color->BlendSrcA; - GLuint dstA = intel->state.Color->BlendDstA; - - iab |= (IAB_MODIFY_FUNC | - IAB_MODIFY_SRC_FACTOR | - IAB_MODIFY_DST_FACTOR | - SRC_ABLND_FACT(intel_translate_blend_factor(srcA)) | - DST_ABLND_FACT(intel_translate_blend_factor(dstA)) | - (i915_translate_blend_equation(eqA) << IAB_FUNC_SHIFT)); - - if (srcA != srcRGB || - dstA != dstRGB || - eqA != eqRGB) { - -#if 0 - /* later */ - if (eqA == GL_MIN || eqA == GL_MAX) { - srcA = dstA = GL_ONE; - } -#endif - - - if (intel->state.Color->BlendEnabled) - iab |= IAB_ENABLE; - } - } - - BEGIN_BATCH(1, 0); - OUT_BATCH( iab ); - ADVANCE_BATCH(); -} - -const struct intel_tracked_state i915_upload_IAB = { - .dirty = { - .mesa = _NEW_COLOR, - .intel = 0, - .extra = 0 - }, - .update = upload_IAB -}; - - -/*********************************************************************** - * Depthbuffer - currently constant, but rotation would change that. - */ - - -static void upload_buffers(struct intel_context *intel) -{ - struct intel_region *color_region = intel->state.draw_region; - struct intel_region *depth_region = intel->state.depth_region; - - if (color_region) { - BEGIN_BATCH(4, 0); - OUT_BATCH( _3DSTATE_BUF_INFO_CMD ); - OUT_BATCH( BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(color_region->pitch * color_region->cpp) | - BUF_3D_USE_FENCE); - OUT_RELOC(intel->state.draw_region->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - intel->state.draw_region->draw_offset); - ADVANCE_BATCH(); - } - - if (depth_region) { - BEGIN_BATCH(4, 0); - OUT_BATCH( _3DSTATE_BUF_INFO_CMD ); - OUT_BATCH( BUF_3D_ID_DEPTH | - BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) | - BUF_3D_USE_FENCE ); - OUT_RELOC(intel->state.depth_region->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - intel->state.depth_region->draw_offset); - ADVANCE_BATCH(); - } - - /* - * Compute/set I915_DESTREG_DV1 value - */ - BEGIN_BATCH(2, 0); - OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); - - OUT_BATCH( DSTORG_HORT_BIAS(0x8) | /* .5 */ - DSTORG_VERT_BIAS(0x8) | /* .5 */ - LOD_PRECLAMP_OGL | - TEX_DEFAULT_COLOR_OGL | - DITHER_FULL_ALWAYS | - (color_region && color_region->cpp == 4 - ? DV_PF_8888 - : DV_PF_565) | - (depth_region && depth_region->cpp == 4 - ? DEPTH_FRMT_24_FIXED_8_OTHER - : DEPTH_FRMT_16_FIXED) ); - - ADVANCE_BATCH(); -} - -const struct intel_tracked_state i915_upload_buffers = { - .dirty = { - .mesa = 0, - .intel = INTEL_NEW_CBUF | INTEL_NEW_ZBUF | INTEL_NEW_FENCE, - .extra = 0 - }, - .update = upload_buffers -}; - - - -/*********************************************************************** - * Polygon stipple - * - * The i915 supports a 4x4 stipple natively, GL wants 32x32. - * Fortunately stipple is usually a repeating pattern. - * - * XXX: does stipple pattern need to be adjusted according to - * the window position? - * - * XXX: possibly need workaround for conform paths test. - */ - -static void upload_stipple( struct intel_context *intel ) -{ - GLuint st0 = _3DSTATE_STIPPLE; - GLuint st1 = 0; - - GLboolean hw_stipple_fallback = 0; - - /* _NEW_POLYGON, INTEL_NEW_REDUCED_PRIMITIVE - */ - if (intel->state.Polygon->StippleFlag && - intel->reduced_primitive == GL_TRIANGLES) { - - /* _NEW_POLYGONSTIPPLE - */ - const GLubyte *mask = (const GLubyte *)intel->state.PolygonStipple; - GLubyte p[4]; - GLint i, j, k; - - p[0] = mask[12] & 0xf; - p[0] |= p[0] << 4; - p[1] = mask[8] & 0xf; - p[1] |= p[1] << 4; - p[2] = mask[4] & 0xf; - p[2] |= p[2] << 4; - p[3] = mask[0] & 0xf; - p[3] |= p[3] << 4; - - st1 |= ST1_ENABLE; - - for (k = 0; k < 8; k++) { - for (j = 3; j >= 0; j--) { - for (i = 0; i < 4; i++, mask++) { - if (*mask != p[j]) { - hw_stipple_fallback = 1; - st1 &= ~ST1_ENABLE; - } - } - } - } - - st1 |= (((p[0] & 0xf) << 0) | - ((p[1] & 0xf) << 4) | - ((p[2] & 0xf) << 8) | - ((p[3] & 0xf) << 12)); - } - - assert(!hw_stipple_fallback); /* TODO */ - - BEGIN_BATCH(2, 0); - OUT_BATCH(st0); - OUT_BATCH(st1); - ADVANCE_BATCH(); -} - - -const struct intel_tracked_state i915_upload_stipple = { - .dirty = { - .mesa = _NEW_POLYGONSTIPPLE, _NEW_POLYGON, - .intel = INTEL_NEW_REDUCED_PRIMITIVE, - .extra = 0 - }, - .update = upload_stipple -}; - - - -/*********************************************************************** - * Scissor. - */ - -static void upload_scissor( struct intel_context *intel ) -{ - /* _NEW_SCISSOR, _NEW_BUFFERS - */ - if (intel->state.Scissor->Enabled && - intel->state.DrawBuffer) { - - GLint x = intel->state.Scissor->X; - GLint y = intel->state.Scissor->Y; - GLint w = intel->state.Scissor->Width; - GLint h = intel->state.Scissor->Height; - - GLint x1, y1, x2, y2; - - if (intel->state.DrawBuffer->Name == 0) { - x1 = x; - y1 = intel->state.DrawBuffer->Height - (y + h); - x2 = x + w - 1; - y2 = y1 + h - 1; - } - else { - /* FBO - not inverted - */ - x1 = x; - y1 = y; - x2 = x + w - 1; - y2 = y + h - 1; - } - - x1 = CLAMP(x1, 0, intel->state.DrawBuffer->Width - 1); - y1 = CLAMP(y1, 0, intel->state.DrawBuffer->Height - 1); - x2 = CLAMP(x2, 0, intel->state.DrawBuffer->Width - 1); - y2 = CLAMP(y2, 0, intel->state.DrawBuffer->Height - 1); - - BEGIN_BATCH(4, 0); - OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); - OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); - OUT_BATCH((y1 << 16) | (x1 & 0xffff)); - OUT_BATCH((y2 << 16) | (x2 & 0xffff)); - ADVANCE_BATCH(); - } - else { - BEGIN_BATCH(1, 0); - OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); - ADVANCE_BATCH(); - } -} - -const struct intel_tracked_state i915_upload_scissor = { - .dirty = { - .mesa = _NEW_SCISSOR | _NEW_BUFFERS, - .intel = 0, - .extra = 0 - }, - .update = upload_scissor -}; - diff --git a/src/mesa/drivers/dri/i915tex/i915_state_program.c b/src/mesa/drivers/dri/i915tex/i915_state_program.c new file mode 100644 index 0000000000..17ac40c3c5 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_program.c @@ -0,0 +1,96 @@ +/************************************************************************** + * + * 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 "glheader.h" +#include "macros.h" +#include "enums.h" +#include "program.h" + +#include "i915_context.h" +#include "i915_fpc.h" +#include "i915_cache.h" + + + + + +/********************************************************************************* + * Program instructions (and decls) + */ + + +static void upload_program( struct intel_context *intel ) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + struct i915_fragment_program *fp = i915->fragment_program; + GLuint i; + + if (&fp->Base != intel->state.FragmentProgram->_Current) { + i915->fragment_program = (struct i915_fragment_program *) + intel->state.FragmentProgram->_Current; + + fp = i915->fragment_program; + /* This is stupid + */ + intel->state.dirty.intel |= INTEL_NEW_FRAGMENT_PROGRAM; + } + + /* As the compiled program depends only on the original program + * text, just store the compiled version in the fragment program + * struct. + */ + if (!fp->translated) { + i915_compile_fragment_program(i915, fp); + } + + /* This is an unnnecessary copy - fix the interface... + */ + { + struct i915_cache_packet packet; + + packet_init( &packet, I915_CACHE_PROGRAM, fp->program_size, 0 ); + + for (i = 0; i < fp->program_size; i++) + packet_dword( &packet, fp->program[i] ); + + i915_cache_emit( i915->cctx, &packet ); + } +} + + +/* See i915_wm.c: + */ +const struct intel_tracked_state i915_upload_program = { + .dirty = { + .mesa = (0), + .intel = (INTEL_NEW_FRAGMENT_PROGRAM), /* ?? Is this all ?? */ + .extra = 0 + }, + .update = upload_program +}; + + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_sampler.c b/src/mesa/drivers/dri/i915tex/i915_state_sampler.c index 5eba939e46..539fe77903 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_sampler.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_sampler.c @@ -33,11 +33,11 @@ #include "intel_mipmap_tree.h" #include "intel_tex.h" -#include "intel_batchbuffer.h" #include "intel_state_inlines.h" #include "i915_context.h" #include "i915_reg.h" +#include "i915_cache.h" @@ -221,6 +221,7 @@ static void update_sampler(struct intel_context *intel, static void upload_samplers( struct intel_context *intel ) { + struct i915_context *i915 = i915_context( &intel->ctx ); GLint i, dirty = 0, nr = 0; GLuint state[I915_TEX_UNITS][3]; @@ -233,17 +234,21 @@ static void upload_samplers( struct intel_context *intel ) } if (nr) { - BEGIN_BATCH(2 + nr * 3, 0); - OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); - OUT_BATCH(dirty); + struct i915_cache_packet packet; + + packet_init( &packet, I915_CACHE_SAMPLER, 2 + nr * 3, 0 ); + packet_dword( &packet, _3DSTATE_SAMPLER_STATE | (3 * nr) ); + packet_dword( &packet, dirty ); + for (i = 0; i < I915_TEX_UNITS; i++) { if (intel->state.Texture->Unit[i]._ReallyEnabled) { - OUT_BATCH(state[i][0]); - OUT_BATCH(state[i][1]); - OUT_BATCH(state[i][2]); + packet_dword( &packet, state[i][0] ); + packet_dword( &packet, state[i][1] ); + packet_dword( &packet, state[i][2] ); } } - ADVANCE_BATCH(); + + i915_cache_emit( i915->cctx, &packet ); } } diff --git a/src/mesa/drivers/dri/i915tex/i915_state_static.c b/src/mesa/drivers/dri/i915tex/i915_state_static.c new file mode 100644 index 0000000000..ebbcfd7b8b --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_static.c @@ -0,0 +1,393 @@ +/************************************************************************** + * + * 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 "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" + +#include "intel_fbo.h" +#include "intel_regions.h" +#include "intel_state_inlines.h" + +#include "i915_context.h" +#include "i915_reg.h" +#include "i915_state.h" +#include "i915_cache.h" + +#define FILE_DEBUG_FLAG DEBUG_STATE + +/* State that we have chosen to store in the STATIC segment of the + * i915 indirect state mechanism. + * + * There is a lot of flexibility for breaking state up between dynamic + * & static buckets of the indirect mechanism. + * + * At a hardware level they are treated slightly differently, dynamic + * state supports an incremental update model, whereas static is + * better suited to usage where the same set of packets are present + * every static state emit. This isn't enforced though, and in normal + * operations there is nothing preventing arbitary usage of either + * bucket. + */ + + +/*********************************************************************** + * Depthbuffer - currently constant, but rotation would change that. + */ + + +static void upload_buffers(struct intel_context *intel) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + struct intel_region *color_region = intel->state.draw_region; + struct intel_region *depth_region = intel->state.depth_region; + + GLuint dwords = ((color_region ? 3 : 0) + + (depth_region ? 3 : 0) + + 2); + + GLuint relocs = ((color_region ? 1 : 0) + + (depth_region ? 1 : 0)); + + struct i915_cache_packet packet; + + packet_init( &packet, I915_CACHE_BUFFERS, dwords, relocs ); + + if (color_region) { + packet_dword( &packet, _3DSTATE_BUF_INFO_CMD ); + packet_dword( &packet, BUF_3D_ID_COLOR_BACK | + BUF_3D_PITCH(color_region->pitch * color_region->cpp) | + BUF_3D_USE_FENCE); + + packet_reloc( &packet, color_region->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, + color_region->draw_offset); + } + + if (depth_region) { + packet_dword( &packet, _3DSTATE_BUF_INFO_CMD ); + packet_dword( &packet, BUF_3D_ID_DEPTH | + BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) | + BUF_3D_USE_FENCE ); + packet_reloc( &packet, depth_region->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, + depth_region->draw_offset); + } + + + packet_dword( &packet,_3DSTATE_DST_BUF_VARS_CMD); + packet_dword( &packet, DSTORG_HORT_BIAS(0x8) | /* .5 */ + DSTORG_VERT_BIAS(0x8) | /* .5 */ + LOD_PRECLAMP_OGL | + TEX_DEFAULT_COLOR_OGL | + DITHER_FULL_ALWAYS | + (color_region && color_region->cpp == 4 + ? DV_PF_8888 + : DV_PF_565) | + (depth_region && depth_region->cpp == 4 + ? DEPTH_FRMT_24_FIXED_8_OTHER + : DEPTH_FRMT_16_FIXED) ); + + i915_cache_emit( i915->cctx, &packet ); +} + +const struct intel_tracked_state i915_upload_buffers = { + .dirty = { + .mesa = 0, + .intel = INTEL_NEW_CBUF | INTEL_NEW_ZBUF | INTEL_NEW_FENCE, + .extra = 0 + }, + .update = upload_buffers +}; + + + +/*********************************************************************** + * Polygon stipple + * + * The i915 supports a 4x4 stipple natively, GL wants 32x32. + * Fortunately stipple is usually a repeating pattern. + * + * XXX: does stipple pattern need to be adjusted according to + * the window position? + * + * XXX: possibly need workaround for conform paths test. + */ + +static void upload_stipple( struct intel_context *intel ) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + GLuint st0 = _3DSTATE_STIPPLE; + GLuint st1 = 0; + + GLboolean hw_stipple_fallback = 0; + + /* _NEW_POLYGON, INTEL_NEW_REDUCED_PRIMITIVE + */ + if (intel->state.Polygon->StippleFlag && + intel->reduced_primitive == GL_TRIANGLES) { + + /* _NEW_POLYGONSTIPPLE + */ + const GLubyte *mask = (const GLubyte *)intel->state.PolygonStipple; + GLubyte p[4]; + GLint i, j, k; + + p[0] = mask[12] & 0xf; + p[0] |= p[0] << 4; + p[1] = mask[8] & 0xf; + p[1] |= p[1] << 4; + p[2] = mask[4] & 0xf; + p[2] |= p[2] << 4; + p[3] = mask[0] & 0xf; + p[3] |= p[3] << 4; + + st1 |= ST1_ENABLE; + + for (k = 0; k < 8; k++) { + for (j = 3; j >= 0; j--) { + for (i = 0; i < 4; i++, mask++) { + if (*mask != p[j]) { + hw_stipple_fallback = 1; + st1 &= ~ST1_ENABLE; + } + } + } + } + + st1 |= (((p[0] & 0xf) << 0) | + ((p[1] & 0xf) << 4) | + ((p[2] & 0xf) << 8) | + ((p[3] & 0xf) << 12)); + } + + assert(!hw_stipple_fallback); /* TODO */ + + { + struct i915_cache_packet packet; + + packet_init( &packet, I915_CACHE_STIPPLE, 2, 0 ); + packet_dword( &packet,st0); + packet_dword( &packet,st1); + i915_cache_emit( i915->cctx, &packet ); + } +} + + +const struct intel_tracked_state i915_upload_stipple = { + .dirty = { + .mesa = _NEW_POLYGONSTIPPLE, _NEW_POLYGON, + .intel = INTEL_NEW_REDUCED_PRIMITIVE, + .extra = 0 + }, + .update = upload_stipple +}; + + + +/*********************************************************************** + * Scissor. + */ + +static void upload_scissor( struct intel_context *intel ) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + struct i915_cache_packet packet; + + /* _NEW_SCISSOR, _NEW_BUFFERS + */ + if (intel->state.Scissor->Enabled && + intel->state.DrawBuffer) { + + GLint x = intel->state.Scissor->X; + GLint y = intel->state.Scissor->Y; + GLint w = intel->state.Scissor->Width; + GLint h = intel->state.Scissor->Height; + + GLint x1, y1, x2, y2; + + if (intel->state.DrawBuffer->Name == 0) { + x1 = x; + y1 = intel->state.DrawBuffer->Height - (y + h); + x2 = x + w - 1; + y2 = y1 + h - 1; + } + else { + /* FBO - not inverted + */ + x1 = x; + y1 = y; + x2 = x + w - 1; + y2 = y + h - 1; + } + + x1 = CLAMP(x1, 0, intel->state.DrawBuffer->Width - 1); + y1 = CLAMP(y1, 0, intel->state.DrawBuffer->Height - 1); + x2 = CLAMP(x2, 0, intel->state.DrawBuffer->Width - 1); + y2 = CLAMP(y2, 0, intel->state.DrawBuffer->Height - 1); + + packet_init( &packet, I915_CACHE_SCISSOR, 4, 0 ); + packet_dword( &packet,_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); + packet_dword( &packet,_3DSTATE_SCISSOR_RECT_0_CMD); + packet_dword( &packet,(y1 << 16) | (x1 & 0xffff)); + packet_dword( &packet,(y2 << 16) | (x2 & 0xffff)); + i915_cache_emit( i915->cctx, &packet ); + } + else { + packet_init( &packet, I915_CACHE_SCISSOR, 1, 0 ); + packet_dword( &packet,_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); + i915_cache_emit( i915->cctx, &packet ); + } +} + +const struct intel_tracked_state i915_upload_scissor = { + .dirty = { + .mesa = _NEW_SCISSOR | _NEW_BUFFERS, + .intel = 0, + .extra = 0 + }, + .update = upload_scissor +}; + + + + + + +/*********************************************************************** + * Misc invarient state packets + */ + +static void upload_invarient( struct intel_context *intel ) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + GLuint i; + + static GLuint invarient_state[] = { + + (_3DSTATE_AA_CMD | + AA_LINE_ECAAR_WIDTH_ENABLE | + AA_LINE_ECAAR_WIDTH_1_0 | + AA_LINE_REGION_WIDTH_ENABLE | + AA_LINE_REGION_WIDTH_1_0), + + /* Could use these to reduce the size of vertices when the incoming + * array is constant. + */ + (_3DSTATE_DFLT_DIFFUSE_CMD), + (0), + + (_3DSTATE_DFLT_SPEC_CMD), + (0), + + (_3DSTATE_DFLT_Z_CMD), + (0), + + /* We support texture crossbar via the fragment shader, rather than + * with this mechanism. + */ + (_3DSTATE_COORD_SET_BINDINGS | + CSB_TCB(0, 0) | + CSB_TCB(1, 1) | + CSB_TCB(2, 2) | + CSB_TCB(3, 3) | + CSB_TCB(4, 4) | + CSB_TCB(5, 5) | + CSB_TCB(6, 6) | + CSB_TCB(7, 7)), + + /* Setup OpenGL rasterization state: + */ + (_3DSTATE_RASTER_RULES_CMD | + ENABLE_POINT_RASTER_RULE | + OGL_POINT_RASTER_RULE | + ENABLE_LINE_STRIP_PROVOKE_VRTX | + ENABLE_TRI_FAN_PROVOKE_VRTX | + LINE_STRIP_PROVOKE_VRTX(1) | + TRI_FAN_PROVOKE_VRTX(2) | + ENABLE_TEXKILL_3D_4D | + TEXKILL_4D), + + /* Need to initialize this to zero. + */ + (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(3) | + (0)), + (0), + + (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT), + (_3DSTATE_SCISSOR_RECT_0_CMD), + (0), + (0), + + + /* For private depth buffers but shared color buffers, eg + * front-buffer rendering with a private depthbuffer. We don't do + * this. + */ + (_3DSTATE_DEPTH_SUBRECT_DISABLE), + + (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0) + }; + + /* Disable indirect state for now. + */ +#if 0 + BEGIN_BATCH(2, 0); + OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); + OUT_BATCH(0); + ADVANCE_BATCH(); +#endif + + /* Will be nice if this can be preserved over several frames. I + * guess logical contexts would do much the same thing. + */ + { + struct i915_cache_packet packet; + + packet_init( &packet, I915_CACHE_INVARIENT, sizeof(invarient_state)/4, 0); + for (i = 0; i < sizeof(invarient_state)/4; i++) + packet_dword( &packet, invarient_state[i] ); + + i915_cache_emit( i915->cctx, &packet ); + } +} + +const struct intel_tracked_state i915_upload_invarient = { + .dirty = { + .mesa = 0, + .intel = INTEL_NEW_CONTEXT, /* or less frequently? */ + .extra = 0 + }, + .update = upload_invarient +}; + + + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_fp_inputs.c b/src/mesa/drivers/dri/i915tex/i915_state_vertex.c index 8bbdc0f29a..0cd0e69237 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_fp_inputs.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_vertex.c @@ -173,8 +173,8 @@ static void i915_calculate_vertex_format( struct intel_context *intel ) } } - if (s2 != i915->fragprog.LIS2 || - s4 != i915->fragprog.LIS4) { + if (s2 != i915->vertex_format.LIS2 || + s4 != i915->vertex_format.LIS4) { GLuint vs = _tnl_install_attrs(&intel->ctx, intel->vertex_attrs, @@ -186,8 +186,8 @@ static void i915_calculate_vertex_format( struct intel_context *intel ) _mesa_printf("inputs %x vertex size %d\n", inputsRead, intel->vertex_size); - i915->fragprog.LIS2 = s2; - i915->fragprog.LIS4 = s4; + i915->vertex_format.LIS2 = s2; + i915->vertex_format.LIS4 = s4; intel->state.dirty.intel |= I915_NEW_VERTEX_FORMAT; } } diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c index 14b9c50ace..0e0f926a31 100644 --- a/src/mesa/drivers/dri/i915tex/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915tex/i915_vtbl.c @@ -42,228 +42,35 @@ #include "i915_reg.h" #include "i915_context.h" +#include "i915_cache.h" -#if 0 - - - -#define OUT(x) do { \ - if (0) _mesa_printf("OUT(0x%08x)\n", x); \ - *p++ = (x); \ -} while(0) - -/* Push the state into the sarea and/or texture memory. - */ -static void -i915_emit_state(struct intel_context *intel) +static void i915_destroy_context(struct intel_context *intel) { - struct i915_context *i915 = i915_context(&intel->ctx); - struct i915_hw_state *state = i915->current; - GLuint dirty; - BATCH_LOCALS; - - /* We don't hold the lock at this point, so want to make sure that - * there won't be a buffer wrap. - * - * It might be better to talk about explicit places where - * scheduling is allowed, rather than assume that it is whenever a - * batchbuffer fills up. - */ - intel_batchbuffer_require_space(intel->batch, 0, - get_state_size(state), 0); - - /* Do this here as we may have flushed the batchbuffer above, - * causing more state to be dirty! - */ - dirty = get_dirty(state); - - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); - - /* This should not change during a scene for HWZ, correct? - * - * If it does change, we probably have to flush everything and - * restart. - */ - if (dirty & (I915_UPLOAD_INVARIENT | I915_UPLOAD_BUFFERS)) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); - - i915_emit_invarient_state(intel); - - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); - - /* Does this go in dynamic indirect state, or static indirect - * state??? - */ - BEGIN_BATCH(3, 0); - OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); - OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); - OUT_RELOC(state->draw_region->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - state->draw_region->draw_offset); - ADVANCE_BATCH(); - - if (state->depth_region) { - BEGIN_BATCH(3, 0); - OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); - OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); - OUT_RELOC(state->depth_region->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - state->depth_region->draw_offset); - ADVANCE_BATCH(); - } - - BEGIN_BATCH(2, 0); - OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); - OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); - ADVANCE_BATCH(); - -#if 0 - /* Where does scissor go? - */ - OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); - OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); - OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); - OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); -#endif - } - - if (dirty & I915_UPLOAD_CTX) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_CTX:\n"); - - /* Immediate state: always goes in the batchbuffer. - */ - BEGIN_BATCH(5, 0); - OUT_BATCH(state->Ctx[I915_CTXREG_LI]); - OUT_BATCH(state->Ctx[I915_CTXREG_LIS2]); - OUT_BATCH(state->Ctx[I915_CTXREG_LIS4]); - OUT_BATCH(state->Ctx[I915_CTXREG_LIS5]); - OUT_BATCH(state->Ctx[I915_CTXREG_LIS6]); - ADVANCE_BATCH(); - - emit_indirect(intel, - LI0_STATE_DYNAMIC_INDIRECT, - state->Ctx + I915_CTXREG_STATE4, - 4 * sizeof(GLuint) ); - } - - - /* Combine all the dirty texture state into a single command to - * avoid lockups on I915 hardware. - */ - if (dirty & I915_UPLOAD_TEX_ALL) { - GLuint offset; - GLuint *p; - int i, nr = 0; - - for (i = 0; i < I915_TEX_UNITS; i++) - if (dirty & I915_UPLOAD_TEX(i)) - nr++; - - /* A bit of a nasty kludge so that we can setup the relocation - * information for the buffer address in the indirect state - * packet: - */ - offset = emit_indirect(intel, - LI0_STATE_MAP, - NULL, - (2 + nr * 3) * sizeof(GLuint) ); - - p = (GLuint *)(intel->batch->map + offset); - - OUT(_3DSTATE_MAP_STATE | (3 * nr)); - OUT((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); + struct i915_context *i915 = i915_context( &intel->ctx ); - for (i = 0; i < I915_TEX_UNITS; i++) - if (dirty & I915_UPLOAD_TEX(i)) { - if (state->tex_buffer[i]) { - intel_batchbuffer_set_reloc( intel->batch, - ((GLubyte *)p) - intel->batch->map, - state->tex_buffer[i], - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, - state->tex_offset[i]); - OUT(0); /* placeholder */ - } - else { - assert(i == 0); - assert(state == &i915->meta); - OUT(0); - } + if (i915->cctx) + i915_destroy_caches( i915->cctx ); - OUT(state->Tex[i][I915_TEXREG_MS3]); - OUT(state->Tex[i][I915_TEXREG_MS4]); - } - - - - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "UPLOAD SAMPLERS:\n"); - - offset = emit_indirect(intel, - LI0_STATE_SAMPLER, - NULL, - (2 + nr * 3) * sizeof(GLuint) ); - - - p = (GLuint *)(intel->batch->map + offset); - - - OUT(_3DSTATE_SAMPLER_STATE | (3 * nr)); - OUT((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); - for (i = 0; i < I915_TEX_UNITS; i++) { - if (dirty & I915_UPLOAD_TEX(i)) { - OUT(state->Tex[i][I915_TEXREG_SS2]); - OUT(state->Tex[i][I915_TEXREG_SS3]); - OUT(state->Tex[i][I915_TEXREG_SS4]); - } - } - } - - if (dirty & I915_UPLOAD_PROGRAM) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_PROGRAM:\n"); - - assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize); - - if (INTEL_DEBUG & DEBUG_STATE) - i915_disassemble_program(state->Program, state->ProgramSize); - } - - - if (dirty & I915_UPLOAD_CONSTANTS) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n"); - - } - - - state->emitted |= dirty; + FREE( i915 ); } -#endif -static void -i915_destroy_context(struct intel_context *intel) +static GLuint i915_flush_cmd(void) { - _tnl_free_vertices(&intel->ctx); + return MI_FLUSH | FLUSH_MAP_CACHE; } +static void i915_lost_hardware( struct intel_context *intel ) +{ + struct i915_context *i915 = i915_context( &intel->ctx ); + i915_clear_caches( i915->cctx ); -static GLuint -i915_flush_cmd(void) -{ - return MI_FLUSH | FLUSH_MAP_CACHE; + memset(&i915->dyn_indirect, 0, sizeof(i915->dyn_indirect)); } @@ -272,4 +79,5 @@ i915InitVtbl(struct i915_context *i915) { i915->intel.vtbl.destroy = i915_destroy_context; i915->intel.vtbl.flush_cmd = i915_flush_cmd; + i915->intel.vtbl.lost_hardware = i915_lost_hardware; } diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c index d63d9ba086..7537251f9a 100644 --- a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c @@ -242,8 +242,8 @@ do_flush_locked(struct intel_batchbuffer *batch, r->offset, driBOOffset(r->buf), r->delta); } - if (INTEL_DEBUG & DEBUG_BATCH) - intel_dump_batchbuffer(batch, ptr); +/* if (INTEL_DEBUG & DEBUG_BATCH) */ + intel_dump_batchbuffer(batch, (GLubyte *)ptr); driBOUnmap(batch->buffer); batch->map = NULL; diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index ad4b9b0053..871eae86bb 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -264,6 +264,7 @@ void intel_lost_hardware( struct intel_context *intel ) { intel->state.dirty.intel |= ~0; intel->state.dirty.mesa |= ~0; + intel->vtbl.lost_hardware( intel ); } @@ -520,21 +521,14 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) assert(intel); /* should never be null */ if (intel) { - GLboolean release_texture_heaps; - INTEL_FIREVERTICES(intel); intel_idx_destroy(intel); - intel->vtbl.destroy(intel); - - release_texture_heaps = (intel->ctx.Shared->RefCount == 1); _swsetup_DestroyContext(&intel->ctx); _tnl_DestroyContext(&intel->ctx); _vbo_DestroyContext(&intel->ctx); - _swrast_DestroyContext(&intel->ctx); - intel->Fallback = 0; /* don't call _swrast_Flush later */ intel_batchbuffer_free(intel->batch); @@ -543,23 +537,17 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) driFenceUnReference(intel->last_swap_fence); intel->last_swap_fence = NULL; } + if (intel->first_swap_fence) { driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); driFenceUnReference(intel->first_swap_fence); intel->first_swap_fence = NULL; } - - if (release_texture_heaps) { - /* This share group is about to go away, free our private - * texture object data. - */ - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "do something to free texture heaps\n"); - } - /* free the Mesa context */ _mesa_free_context_data(&intel->ctx); + + intel->vtbl.destroy(intel); } } diff --git a/src/mesa/drivers/dri/i915tex/intel_idx_render.c b/src/mesa/drivers/dri/i915tex/intel_idx_render.c new file mode 100644 index 0000000000..3a6b6c061c --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_idx_render.c @@ -0,0 +1,430 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/* + * Render vertex buffers by emitting vertices directly to dma buffers. + */ +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" +#include "enums.h" + +#include "tnl/t_context.h" +#include "tnl/t_vertex.h" + +#include "intel_screen.h" +#include "intel_context.h" +#include "intel_tris.h" +#include "intel_batchbuffer.h" +#include "intel_buffer_objects.h" +#include "intel_reg.h" +#include "intel_state.h" +#include "intel_idx_render.h" + + +#define FILE_DEBUG_FLAG DEBUG_IDX + + + +#define MAX_VBO 32 /* XXX: make dynamic */ +#define VBO_SIZE (128*1024) + + +/* Basically limited to what is addressable by the 16-bit indices, + * and the number of indices we can fit in a batchbuffer after + * making room for state. + */ +#define HW_MAX_INDEXABLE_VERTS 0xfffe +#define HW_MAX_INDICES ((BATCH_SZ - 1024) / 2) + + + +struct intel_vb { + struct intel_context *intel; + + struct intel_buffer_object *vbo[MAX_VBO]; + GLuint nr_vbo; + + struct intel_buffer_object *current_vbo; + + GLuint current_vbo_size; + GLuint current_vbo_used; + void *current_vbo_ptr; + + GLuint hw_vbo_offset; + GLuint hw_vbo_delta; + GLuint vertex_size; + + GLuint dirty; +}; + + +/* Have to fallback for: + * - points (needs different viewport) + * - twoside light + * - z offset + * - unfilled prims + * - lines && linestipple + * - tris && tristipple && !hwstipple + * - point attenuation (bug!) + * - aa tris && strict-conformance + * - aa points && strict-conformance + * - PLUS: any fallback-to-swrast condition (intel->Fallback) + * + * If binning, need to flush bins and fall + */ +static GLboolean check_idx_render(GLcontext *ctx, + struct vertex_buffer *VB, + GLuint *max_nr_verts, + GLuint *max_nr_indices ) + +{ + struct intel_context *intel = intel_context(ctx); + GLuint i; + + if (intel->Fallback != 0 || + intel->RenderIndex != 0) + return GL_FALSE; + + /* These are constant, but for some hardware they might vary + * depending on the state, eg. according to vertex size. + */ + *max_nr_verts = HW_MAX_INDEXABLE_VERTS; + *max_nr_indices = HW_MAX_INDICES; + + /* Fix points with different dstorg bias state?? or use different + * viewport transform in this case only (requires flush at level + * above). + */ + for (i = 0; i < VB->PrimitiveCount; i++) { + if (VB->Primitive[i].mode == GL_POINTS) + return GL_FALSE; + } + + return GL_TRUE; +} + +static void +emit_vb_state( struct intel_vb *vb ) +{ + struct intel_context *intel = vb->intel; + + DBG("%s\n", __FUNCTION__); + + intel->state.vbo = vb->current_vbo->buffer; + intel->state.vbo_offset = vb->hw_vbo_offset; + intel->state.dirty.intel |= INTEL_NEW_VBO; + + vb->dirty = 0; +} + +static void +release_current_vbo( struct intel_vb *vb ) +{ + GLcontext *ctx = &vb->intel->ctx; + + DBG("%s\n", __FUNCTION__); + + if (vb->current_vbo_ptr) + ctx->Driver.UnmapBuffer( ctx, + GL_ARRAY_BUFFER_ARB, + &vb->current_vbo->Base ); + + vb->current_vbo = NULL; + vb->current_vbo_ptr = NULL; + vb->current_vbo_size = 0; + vb->current_vbo_used = 0; + vb->dirty = 0; +} + +static void +reset_vbo( struct intel_vb *vb ) +{ + DBG("%s\n", __FUNCTION__); + + if (vb->current_vbo) + release_current_vbo( vb ); + + vb->nr_vbo = 0; +} + + + + +static void +get_next_vbo( struct intel_vb *vb, GLuint size ) +{ + GLcontext *ctx = &vb->intel->ctx; + + DBG("%s\n", __FUNCTION__); + + /* XXX: just allocate more vbos here: + */ + if (vb->nr_vbo == MAX_VBO) { + DBG("XXX: out of vbo's, flushing\n"); + INTEL_FIREVERTICES(vb->intel); + intel_batchbuffer_flush(vb->intel->batch); + reset_vbo(vb); + } + + /* Unmap current vbo: + */ + if (vb->current_vbo) + release_current_vbo( vb ); + + if (size < VBO_SIZE) + size = VBO_SIZE; + + vb->current_vbo = vb->vbo[vb->nr_vbo++]; + vb->current_vbo_size = size; + vb->current_vbo_used = 0; + vb->hw_vbo_offset = 0; + vb->dirty = 1; + + /* Clear out buffer contents and break any hardware dependency on + * the old memory: + */ + ctx->Driver.BufferData( ctx, + GL_ARRAY_BUFFER_ARB, + vb->current_vbo_size, + NULL, + GL_DYNAMIC_DRAW_ARB, + &vb->current_vbo->Base ); + +} + +static void *get_space( struct intel_vb *vb, GLuint nr, GLuint vertex_size ) +{ + GLcontext *ctx = &vb->intel->ctx; + void *ptr; + GLuint space = nr * vertex_size * 4; + + DBG("%s %d*%d, vbo %d\n", __FUNCTION__, nr, vertex_size, vb->nr_vbo); + + if (vb->current_vbo_used + space > vb->current_vbo_size || !vb->current_vbo_ptr) + get_next_vbo( vb, space ); + + if (vb->vertex_size != vertex_size) { + vb->vertex_size = vertex_size; + vb->hw_vbo_offset = vb->current_vbo_used; + vb->dirty = 1; + } + + if (!vb->current_vbo_ptr) { + DBG("%s map vbo %d\n", __FUNCTION__, vb->nr_vbo); + + /* Map the vbo now, will be unmapped in release_current_vbo, above. + */ + vb->current_vbo_ptr = ctx->Driver.MapBuffer( ctx, + GL_ARRAY_BUFFER_ARB, + GL_WRITE_ONLY, + &vb->current_vbo->Base ); + } + + + /* Hmm, could just re-emit the vertex buffer packet & avoid this: + */ + vb->hw_vbo_delta = (vb->current_vbo_used - vb->hw_vbo_offset) / (vb->vertex_size * 4); + + ptr = vb->current_vbo_ptr + vb->current_vbo_used; + vb->current_vbo_used += space; + + return ptr; +} + + +static void +build_and_emit_vertices(GLcontext * ctx, GLuint nr) +{ + struct intel_context *intel = intel_context(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + void *ptr = get_space(intel->vb, nr, intel->vertex_size ); + + DBG("%s %d\n", __FUNCTION__, nr); + + assert(tnl->clipspace.vertex_size == intel->vertex_size * 4); + + tnl->clipspace.new_inputs |= VERT_BIT_POS; + _tnl_emit_vertices_to_buffer( ctx, 0, nr, ptr ); +} + +/* Emits vertices previously built by a call to BuildVertices. + * + * XXX: have t_vertex.c use our buffer to build into and avoid the + * copy (assuming our buffer is cached...) + */ +static void emit_built_vertices( GLcontext *ctx, GLuint nr ) +{ + struct intel_context *intel = intel_context(ctx); + void *ptr = get_space(intel->vb, nr, intel->vertex_size ); + + DBG("%s %d\n", __FUNCTION__, nr); + + memcpy(ptr, _tnl_get_vertex(ctx, 0), + nr * intel->vertex_size * sizeof(GLuint)); +} + +/* Emit primitives and indices referencing the previously emitted + * vertex buffer. + */ +static void emit_prims( GLcontext *ctx, + const struct _mesa_prim *prim, + GLuint nr_prims, + const GLuint *indices, + GLuint nr_indices ) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_vb *vb = intel->vb; + GLuint i, j; + + assert(indices); + + DBG("%s - start\n", __FUNCTION__); + + + for (i = 0; i < nr_prims; i++) { + GLuint nr, hw_prim; + GLuint start = prim[i].start; + GLuint offset = vb->hw_vbo_delta; + + switch (prim[i].mode) { + case GL_TRIANGLES: + hw_prim = PRIM3D_TRILIST; + nr = prim[i].count - prim[i].count % 3; + break; + case GL_LINES: + hw_prim = PRIM3D_LINELIST; + nr = prim[i].count - prim[i].count % 2; + break; + default: + assert(0); + continue; + } + + if (nr == 0) + continue; + + /* XXX: Need to ensure that both the state and the primitive + * command below end up in the same batchbuffer, otherwise there + * is a risk that another context might interpose a batchbuffer + * containing different statesetting commands. Using logical + * contexts would fix this, as would the BRW scheme of only + * emitting batch commands while holding the lock. + */ + if (vb->dirty) + emit_vb_state( vb ); + + intel_emit_state(intel); + + /* XXX: Can emit upto 64k indices, need to split larger prims + */ + BEGIN_BATCH(2 + (nr+1)/2, INTEL_BATCH_CLIPRECTS); + + OUT_BATCH(0); + OUT_BATCH( _3DPRIMITIVE | + hw_prim | + PRIM_INDIRECT | + PRIM_INDIRECT_ELTS | + nr ); + + /* Pack indices into 16bits + */ + for (j = 0; j < nr-1; j += 2) { + OUT_BATCH( (offset + indices[start+j]) | ((offset + indices[start+j+1])<<16) ); + } + + if (j < nr) + OUT_BATCH( (offset + indices[start+j]) ); + + ADVANCE_BATCH(); + } + + + DBG("%s - done\n", __FUNCTION__); +} + + +/* Callback from (eventually) intel_batchbuffer_flush() + */ +void intel_idx_lost_hardware( struct intel_context *intel ) +{ + GLcontext *ctx = &intel->ctx; + struct intel_vb *vb = intel->vb; + + DBG("%s\n", __FUNCTION__); + + if (vb->current_vbo_ptr) { + ctx->Driver.UnmapBuffer( ctx, + GL_ARRAY_BUFFER_ARB, + &vb->current_vbo->Base ); + vb->current_vbo_ptr = NULL; + } +} + +void intel_idx_init( struct intel_context *intel ) +{ + GLcontext *ctx = &intel->ctx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint i; + + tnl->Driver.Render.CheckIdxRender = check_idx_render; + tnl->Driver.Render.BuildAndEmitVertices = build_and_emit_vertices; + tnl->Driver.Render.EmitBuiltVertices = emit_built_vertices; + tnl->Driver.Render.EmitPrims = emit_prims; + + + /* Create the vb context: + */ + intel->vb = CALLOC_STRUCT( intel_vb ); + intel->vb->intel = intel; + + for (i = 0; i < MAX_VBO; i++) { + intel->vb->vbo[i] = (struct intel_buffer_object *) + ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); + } +} + +void intel_idx_destroy( struct intel_context *intel ) +{ + GLcontext *ctx = &intel->ctx; + struct intel_vb *vb = intel->vb; + GLuint i; + + if (vb) { + reset_vbo( vb ); + + /* Destroy the vbo: + */ + for (i = 0; i < MAX_VBO; i++) + if (vb->vbo[i]) + ctx->Driver.DeleteBuffer( ctx, &vb->vbo[i]->Base ); + + FREE( intel->vb ); + } +} diff --git a/src/mesa/drivers/dri/i915tex/intel_idx_render.h b/src/mesa/drivers/dri/i915tex/intel_idx_render.h new file mode 100644 index 0000000000..6639bf5507 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_idx_render.h @@ -0,0 +1,37 @@ +/************************************************************************** + * + * 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 INTEL_IDX_H +#define INTEL_IDX_H + +#include "intel_context.h" + +void intel_idx_init( struct intel_context *intel ); +void intel_idx_destroy( struct intel_context *intel ); +void intel_idx_lost_hardware( struct intel_context *intel ); + +#endif diff --git a/src/mesa/drivers/dri/i915tex/intel_program.c b/src/mesa/drivers/dri/i915tex/intel_program.c deleted file mode 100644 index e54b600667..0000000000 --- a/src/mesa/drivers/dri/i915tex/intel_program.c +++ /dev/null @@ -1,269 +0,0 @@ -/************************************************************************** - * - * 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 "glheader.h" -#include "macros.h" -#include "enums.h" - -#include "tnl/tnl.h" -#include "tnl/t_context.h" -#include "intel_batchbuffer.h" - -#include "i915_reg.h" -#include "i915_context.h" -#include "i915_fp.h" - -#include "program_instruction.h" -#include "program.h" -#include "programopt.h" - - -static void brwBindProgram( GLcontext *ctx, - GLenum target, - struct gl_program *prog ) -{ - struct brw_context *brw = brw_context(ctx); - - switch (target) { - case GL_VERTEX_PROGRAM_ARB: - brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; - break; - case GL_FRAGMENT_PROGRAM_ARB: - brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; - break; - } -} - -static struct gl_program *brwNewProgram( GLcontext *ctx, - GLenum target, - GLuint id ) -{ - struct brw_context *brw = brw_context(ctx); - - switch (target) { - case GL_VERTEX_PROGRAM_ARB: { - struct brw_vertex_program *prog = CALLOC_STRUCT(brw_vertex_program); - if (prog) { - prog->id = brw->program_id++; - - return _mesa_init_vertex_program( ctx, &prog->program, - target, id ); - } - else - return NULL; - } - - case GL_FRAGMENT_PROGRAM_ARB: { - struct brw_fragment_program *prog = CALLOC_STRUCT(brw_fragment_program); - if (prog) { - prog->id = brw->program_id++; - - return _mesa_init_fragment_program( ctx, &prog->program, - target, id ); - } - else - return NULL; - } - - default: - return _mesa_new_program(ctx, target, id); - } -} - -static void brwDeleteProgram( GLcontext *ctx, - struct gl_program *prog ) -{ - - _mesa_delete_program( ctx, prog ); -} - - -static GLboolean brwIsProgramNative( GLcontext *ctx, - GLenum target, - struct gl_program *prog ) -{ - return GL_TRUE; -} - -static void brwProgramStringNotify( GLcontext *ctx, - GLenum target, - struct gl_program *prog ) -{ - if (target == GL_FRAGMENT_PROGRAM_ARB) { - struct brw_context *brw = brw_context(ctx); - struct brw_fragment_program *p = (struct brw_fragment_program *)prog; - struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program; - if (p == fp) - brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; - p->id = brw->program_id++; - p->param_state = brw_parameter_list_state_flags(p->program.Base.Parameters); - } - else if (target == GL_VERTEX_PROGRAM_ARB) { - struct brw_context *brw = brw_context(ctx); - struct brw_vertex_program *p = (struct brw_vertex_program *)prog; - struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; - if (p == vp) - brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; - p->id = brw->program_id++; - p->param_state = brw_parameter_list_state_flags(p->program.Base.Parameters); - - /* Also tell tnl about it: - */ - _tnl_program_string(ctx, target, prog); - } -} - -void brwInitFragProgFuncs( struct dd_function_table *functions ) -{ - assert(functions->ProgramStringNotify == _tnl_program_string); - - functions->BindProgram = brwBindProgram; - functions->NewProgram = brwNewProgram; - functions->DeleteProgram = brwDeleteProgram; - functions->IsProgramNative = brwIsProgramNative; - functions->ProgramStringNotify = brwProgramStringNotify; -} - - - - -static void -i915BindProgram(GLcontext * ctx, GLenum target, struct gl_program *prog) -{ - if (target == GL_FRAGMENT_PROGRAM_ARB) { - struct i915_context *i915 = I915_CONTEXT(ctx); - struct i915_fragment_program *p = (struct i915_fragment_program *) prog; - - if (i915->current_program == p) - return; - - i915->current_program = p; - - assert(p->on_hardware == 0); - assert(p->params_uptodate == 0); - - /* Hack: make sure fog is correctly enabled according to this - * fragment program's fog options. - */ - ctx->Driver.Enable(ctx, GL_FRAGMENT_PROGRAM_ARB, - ctx->FragmentProgram.Enabled); - } -} - -static struct gl_program * -i915NewProgram(GLcontext * ctx, GLenum target, GLuint id) -{ - switch (target) { - case GL_VERTEX_PROGRAM_ARB: - return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), - target, id); - - case GL_FRAGMENT_PROGRAM_ARB:{ - struct i915_fragment_program *prog = - CALLOC_STRUCT(i915_fragment_program); - if (prog) { - i915_init_program(I915_CONTEXT(ctx), prog); - - return _mesa_init_fragment_program(ctx, &prog->FragProg, - target, id); - } - else - return NULL; - } - - default: - /* Just fallback: - */ - return _mesa_new_program(ctx, target, id); - } -} - -static void -i915DeleteProgram(GLcontext * ctx, struct gl_program *prog) -{ - if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) { - struct i915_context *i915 = I915_CONTEXT(ctx); - struct i915_fragment_program *p = (struct i915_fragment_program *) prog; - - if (i915->current_program == p) - i915->current_program = 0; - } - - _mesa_delete_program(ctx, prog); -} - - -static GLboolean -i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) -{ - if (target == GL_FRAGMENT_PROGRAM_ARB) { - struct i915_fragment_program *p = (struct i915_fragment_program *) prog; - - if (!p->translated) - translate_program(p); - - return !p->error; - } - else - return GL_TRUE; -} - -static void -i915ProgramStringNotify(GLcontext * ctx, - GLenum target, struct gl_program *prog) -{ - if (target == GL_FRAGMENT_PROGRAM_ARB) { - struct i915_fragment_program *p = (struct i915_fragment_program *) prog; - p->translated = 0; - - /* Hack: make sure fog is correctly enabled according to this - * fragment program's fog options. - */ - ctx->Driver.Enable(ctx, GL_FRAGMENT_PROGRAM_ARB, - ctx->FragmentProgram.Enabled); - - if (p->FragProg.FogOption) { - /* add extra instructions to do fog, then turn off FogOption field */ - _mesa_append_fog_code(ctx, &p->FragProg); - p->FragProg.FogOption = GL_NONE; - } - } - - _tnl_program_string(ctx, target, prog); -} - - - -void -i915InitFragProgFuncs(struct dd_function_table *functions) -{ - functions->BindProgram = i915BindProgram; - functions->NewProgram = i915NewProgram; - functions->DeleteProgram = i915DeleteProgram; - functions->IsProgramNative = i915IsProgramNative; - functions->ProgramStringNotify = i915ProgramStringNotify; -} |