Another texture manager checkpoint:

- Add code to validate textures before use.
- Simplify vertex paths for now.
- Make vertex paths validate textures.  This is done pretty
  with some pretty heavy-handed use of the dri lock - fixing this is
  a priority.
- Add lots of debug statements

demos/texobj renders, but textures are incorrect.
This commit is contained in:
Keith Whitwell 2006-01-25 15:40:50 +00:00
parent dcfe55539f
commit 696ba32779
21 changed files with 440 additions and 389 deletions

View file

@ -86,8 +86,11 @@ static struct block *alloc_agp( struct bufmgr *bm,
if (!block)
return NULL;
_mesa_printf("alloc_agp 0x%x\n", size);
block->mem = mmAllocMem(bm->pool.heap, size, align, 0);
if (!block->mem) {
_mesa_printf("\t- failed\n");
free(block);
return NULL;
}
@ -96,6 +99,7 @@ static struct block *alloc_agp( struct bufmgr *bm,
block->memType = BM_MEM_AGP;
block->virtual = bm->pool.virtual + block->mem->ofs;
_mesa_printf("\t- offset 0x%x\n", block->mem->ofs);
return block;
}
@ -106,6 +110,8 @@ static struct block *alloc_local( unsigned size )
if (!block)
return NULL;
_mesa_printf("alloc_local 0x%x\n", size);
block->memType = BM_MEM_LOCAL;
block->virtual = malloc(size);
if (!block->virtual) {
@ -136,12 +142,15 @@ static int bmAllocMem( struct bufmgr *bm,
struct buffer *buf,
unsigned flags ) /* unused */
{
if (buf->block == 0)
if (buf->block == NULL)
buf->block = alloc_block(bm, buf->size, 4, BM_MEM_AGP);
if (buf->block == 0)
if (buf->block == NULL)
buf->block = alloc_block(bm, buf->size, 4, BM_MEM_LOCAL);
if (buf->block)
buf->block->buf = buf;
return buf->block != NULL;
}
@ -212,6 +221,9 @@ static int move_buffers( struct bufmgr *bm,
if (flags & BM_NO_UPLOAD)
goto cleanup;
_mesa_printf("try to move buffer size 0x%x to pool %d\n",
buffers[i]->size, newMemType);
newMem[i] = alloc_block(bm,
buffers[i]->size,
buffers[i]->alignment,
@ -219,6 +231,8 @@ static int move_buffers( struct bufmgr *bm,
if (!newMem[i])
goto cleanup;
newMem[i]->buf = buffers[i];
}
}
@ -346,6 +360,9 @@ void bmInitPool( struct bufmgr *bm,
{
if (pool > 0 || low_offset >= high_offset)
return;
_mesa_printf("bmInitPool %d %x..%x\n",
pool, low_offset, high_offset);
bm->pool.size = high_offset - low_offset;
bm->pool.heap = mmInit( low_offset, bm->pool.size );
@ -362,7 +379,7 @@ void bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
unsigned i;
for (i = 0; i < n; i++) {
buffers[i] = bm->buf_nr++;
buffers[i] = ++bm->buf_nr;
_mesa_HashInsert(bm->hash, buffers[i], calloc(sizeof(struct buffer), 1));
}
}
@ -393,6 +410,8 @@ void bmBufferData(struct bufmgr *bm,
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
_mesa_printf("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data);
if (buf->block) {
if ((buf->block->memType == BM_MEM_AGP && !bmTestFence(bm, buf->block->fence)) ||
(buf->size && buf->size != size) ||
@ -420,6 +439,8 @@ void bmBufferSubData(struct bufmgr *bm,
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
_mesa_printf("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
if (buf->block == 0)
bmAllocMem(bm, buf, 0);
@ -438,6 +459,8 @@ void *bmMapBuffer( struct bufmgr *bm,
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
_mesa_printf("bmMapBuffer %d\n", buffer);
if (buf->mapped)
return NULL;
@ -457,6 +480,8 @@ void *bmMapBuffer( struct bufmgr *bm,
void bmUnmapBuffer( struct bufmgr *bm, unsigned buffer )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
_mesa_printf("bmUnmapBuffer %d\n", buffer);
buf->mapped = 0;
}
@ -485,6 +510,7 @@ void bm_fake_SetFixedBufferParams( struct bufmgr *bm
struct bm_buffer_list *bmNewBufferList( void )
{
struct bm_buffer_list *list = calloc(sizeof(*list), 1);
_mesa_printf("bmNewBufferList\n");
return list;
}
@ -497,6 +523,8 @@ void bmAddBuffer( struct bufmgr *bm,
{
assert(list->nr < BM_LIST_MAX);
_mesa_printf("bmAddBuffer %d\n", buffer);
list->buffer[list->nr] = _mesa_HashLookup(bm->hash, buffer);
list->offset_return[list->nr] = offset_return;
list->nr++;
@ -528,11 +556,14 @@ int bmValidateBufferList( struct bufmgr *bm,
unsigned i;
unsigned total = 0;
_mesa_printf("%s\n", __FUNCTION__);
if (list->nr > BM_LIST_MAX)
return 0;
for (i = 0; i < list->nr; i++) {
assert(!list->buffer[i]->mapped);
assert(list->buffer[i]->block);
total += list->buffer[i]->size;
}
@ -568,9 +599,14 @@ void bmFenceBufferList( struct bufmgr *bm, struct bm_buffer_list *list )
{
unsigned i;
_mesa_printf("%s (%d bufs)\n", __FUNCTION__, list->nr);
assert(list->need_fence);
list->need_fence = 0;
if (!list->nr)
return;
bm->last_fence = bmSetFence( bm );
/* Move all buffers to head of resident list and set their fences
@ -635,7 +671,7 @@ void bmFlushReadCaches( struct bufmgr *bm )
* have to emit another fence and wait for the hw queue to drain to be
* sure the caches had flushed.
*
* Strategy:
* A possible strategy:
* - every once in a while, when there is no last_draw_flush_fence outstanding,
* emit a draw-cache flush just prior to the fence.
* - note the fence (last_draw_flush_fence)

View file

@ -295,6 +295,7 @@ static void draw_quad(i830ContextPtr i830,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
{
#if 0
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
PRIM3D_TRIFAN,
@ -350,6 +351,7 @@ static void draw_quad(i830ContextPtr i830,
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
#endif
}
void

View file

@ -107,6 +107,8 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
if (!i915) return GL_FALSE;
_mesa_printf( "\ntexmem branch\n\n");
i915InitVtbl( i915 );
i915InitDriverFunctions( &functions );
@ -129,9 +131,6 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
intel->intelScreen->tex.size, /* high offset */
intel->intelScreen->tex.map); /* virtual base */
/* AGP allocation won't work:
*/
intel->intelScreen->allow_batchbuffer = GL_FALSE;
ctx->Const.MaxTextureLevels = 11;
ctx->Const.Max3DTextureLevels = 8;

View file

@ -387,6 +387,7 @@ static void draw_quad(i915ContextPtr i915,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
{
#if 0
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
PRIM3D_TRIFAN,
@ -440,6 +441,7 @@ static void draw_quad(i915ContextPtr i915,
tmp.v.u0 = s0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
#endif
}
void

View file

@ -55,7 +55,6 @@ static GLuint minify( GLuint d )
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
{
GLint i;
GLint numLevels = mt->last_level - mt->first_level + 1;
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP: {
@ -71,12 +70,12 @@ GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
for (i = 0; i < numLevels; i++) {
for (i = mt->first_level; i <= mt->last_level; i++) {
mt->offset[face][i].x = x;
mt->offset[face][i].y = y;
mt->offset[face][i].width = d;
mt->offset[face][i].height = d;
mt->offset[face][i].depth = 0;
mt->offset[face][i].depth = 1;
d >>= 1;
assert(d > 0);
@ -91,7 +90,6 @@ GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint depth = mt->depth0;
GLuint tmp_numLevels = MAX2(numLevels, 9);
/* Calculate the size of a single slice. Hardware demands a
* minimum of 8 mipmaps, some of which might ultimately not be
@ -100,7 +98,9 @@ GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
mt->total_height = 0;
for ( i = 0 ; i < tmp_numLevels ; i++ ) {
/* XXX: fixme! hardware expects/requires 9 levels at minimum.
*/
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[0][i].x = 0;
mt->offset[0][i].y = mt->total_height;
mt->offset[0][i].width = width;
@ -131,12 +131,12 @@ GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
mt->total_height = 0;
for ( i = 0 ; i < numLevels ; i++ ) {
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[0][i].x = 0;
mt->offset[0][i].y = mt->total_height;
mt->offset[0][i].height = height;
mt->offset[0][i].width = width;
mt->offset[0][i].depth = 0;
mt->offset[0][i].depth = 1;
if (mt->compressed)
@ -157,7 +157,6 @@ GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
{
GLint numLevels = mt->last_level - mt->first_level + 1;
GLint i;
switch (mt->target) {
@ -191,12 +190,12 @@ GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
x = face * 8;
}
for (i = 0; i < numLevels; i++) {
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[face][i].x = x;
mt->offset[face][i].y = y;
mt->offset[face][i].width = d;
mt->offset[face][i].height = d;
mt->offset[face][i].depth = 0;
mt->offset[face][i].depth = 1;
d >>= 1;
assert(d > 0);
@ -251,7 +250,7 @@ GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
depth_pack_pitch = mt->pitch;
for ( i = 0 ; i < numLevels ; i++ ) {
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[0][i].x = 0;
mt->offset[0][i].y = mt->total_height;
@ -291,12 +290,12 @@ GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
mt->total_height = 0;
for ( i = 0 ; i < numLevels ; i++ ) {
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[0][i].x = x;
mt->offset[0][i].y = y;
mt->offset[0][i].height = height;
mt->offset[0][i].width = width;
mt->offset[0][i].depth = 0;
mt->offset[0][i].depth = 1;
/* LPT change: step right after second mipmap.

View file

@ -118,23 +118,11 @@ static GLboolean i915_update_tex_unit( GLcontext *ctx,
struct intel_texture_object *intelObj = intel_texture_object(tObj);
struct i915_context *i915 = i915_context(ctx);
GLuint state[I915_TEX_SETUP_SIZE];
struct gl_texture_image *firstImage;
GLuint firstImageOffset;
struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel];
memset(state, 0, sizeof(state));
/* Will return the offset for the image at intelObj->firstLevel
* (firstLevel and lastLevel are calculated in
* validate_mipmap_tree). We will program the hardware as if this
* is level 0.
*/
firstImageOffset = intel_validate_mipmap_tree( intel_context(ctx), intelObj );
firstImage = tObj->Image[0][intelObj->firstLevel];
if (!firstImageOffset)
return GL_FALSE;
state[I915_TEXREG_MS2] = firstImageOffset;
state[I915_TEXREG_MS2] = 0; /* will fixup later */
state[I915_TEXREG_MS3] =
(((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
((firstImage->Width - 1) << MS3_WIDTH_SHIFT) |
@ -264,17 +252,27 @@ static GLboolean i915_update_tex_unit( GLcontext *ctx,
tObj->_BorderChan[3]);
I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
if (1 || memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
memcpy(i915->state.Tex[unit], state, sizeof(state));
}
_mesa_printf("state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]);
_mesa_printf("state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]);
_mesa_printf("state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]);
_mesa_printf("state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]);
_mesa_printf("state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]);
_mesa_printf("state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
return GL_TRUE;
}
void i915UpdateTextureState( intelContextPtr intel )
{
GLcontext *ctx = &intel->ctx;

View file

@ -37,6 +37,7 @@
#include "tnl/t_vertex.h"
#include "intel_batchbuffer.h"
#include "intel_tex.h"
#include "i915_reg.h"
#include "i915_context.h"
@ -271,7 +272,10 @@ static void i915_emit_state( intelContextPtr intel )
OUT_BATCH((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_BATCH(state->Tex[i][I915_TEXREG_MS2]);
/* Emit zero texture offset, will fixup before firing */
intel_add_texoffset_fixup(intel, i, (GLuint *)batch_ptr);
_mesa_printf("MS2: %x\n", *(GLuint *)batch_ptr);
batch_ptr += 4;
OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
}

View file

@ -40,280 +40,6 @@
/* ================================================================
* Performance monitoring functions
*/
static void intel_fill_box( intelContextPtr intel,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLubyte r, GLubyte g, GLubyte b )
{
intelEmitFillBlitLocked( intel,
intel->intelScreen->cpp,
intel->intelScreen->back.pitch,
intel->intelScreen->front.offset,
x, y, w, h,
INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
r,g,b,0xff));
}
static void intel_draw_performance_boxes( intelContextPtr intel )
{
/* Purple box for page flipping
*/
if ( intel->perf_boxes & I830_BOX_FLIP )
intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
/* Red box if we have to wait for idle at any point
*/
if ( intel->perf_boxes & I830_BOX_WAIT )
intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
/* Blue box: lost context?
*/
if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
/* Yellow box for texture swaps
*/
if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
/* Green box if hardware never idles (as far as we can tell)
*/
if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
/* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
*/
#if 0
if (intel->dma_used) {
int bar = intel->dma_used / 10240;
if (bar > 100) bar = 100;
if (bar < 1) bar = 1;
intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
intel->dma_used = 0;
}
#endif
intel->perf_boxes = 0;
}
static int bad_prim_vertex_nr( int primitive, int nr )
{
switch (primitive & PRIM3D_MASK) {
case PRIM3D_POINTLIST:
return nr < 1;
case PRIM3D_LINELIST:
return (nr & 1) || nr == 0;
case PRIM3D_LINESTRIP:
return nr < 2;
case PRIM3D_TRILIST:
case PRIM3D_RECTLIST:
return nr % 3 || nr == 0;
case PRIM3D_POLY:
case PRIM3D_TRIFAN:
case PRIM3D_TRISTRIP:
case PRIM3D_TRISTRIP_RVRSE:
return nr < 3;
default:
return 1;
}
}
static void intel_flush_inline_primitive( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
GLuint used = intel->batch.ptr - intel->prim.start_ptr;
GLuint vertcount;
assert(intel->prim.primitive != ~0);
if (1) {
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
goto do_discard;
vertcount = (used - 4)/ (intel->vertex_size * 4);
if (!vertcount)
goto do_discard;
if (vertcount * intel->vertex_size * 4 != used - 4) {
fprintf(stderr, "vertex size confusion %d %d\n", used,
intel->vertex_size * vertcount * 4);
goto do_discard;
}
if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
vertcount);
goto do_discard;
}
}
if (used < 8)
goto do_discard;
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
do_discard:
intel->batch.ptr -= used;
intel->batch.space += used;
assert(intel->batch.space >= 0);
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
}
/* Emit a primitive referencing vertices in a vertex buffer.
*/
void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
{
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
/* Finish any in-progress primitive:
*/
INTEL_FIREVERTICES( intel );
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
/* Make sure there is some space in this buffer:
*/
if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
intelFlushBatch(intel, GL_TRUE);
#if 1
if (((int)intel->batch.ptr) & 0x4) {
BEGIN_BATCH(1);
OUT_BATCH(0);
ADVANCE_BATCH();
}
#endif
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2);
OUT_BATCH( 0 );
intel->prim.start_ptr = batch_ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelRestartInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
intel_flush_inline_primitive( &intel->ctx );
if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
intelStartInlinePrimitive( intel, prim );
}
void intelWrapInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel_flush_inline_primitive( &intel->ctx );
intelFlushBatch(intel, GL_TRUE);
intelStartInlinePrimitive( intel, prim );
}
/* Emit a primitive with space for inline vertices.
*/
GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive,
int dwords,
int vertex_size )
{
GLuint *tmp = 0;
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
if (1) {
int used = dwords * 4;
int vertcount;
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
goto do_discard;
vertcount = dwords / vertex_size;
if (dwords % vertex_size) {
fprintf(stderr, "did not request a whole number of vertices\n");
goto do_discard;
}
if (bad_prim_vertex_nr( primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
goto do_discard;
}
if (used < 8)
goto do_discard;
}
/* Emit 3D_PRIMITIVE commands:
*/
BEGIN_BATCH(1 + dwords);
OUT_BATCH( _3DPRIMITIVE |
primitive |
(dwords-1) );
tmp = (GLuint *)batch_ptr;
batch_ptr += dwords * 4;
ADVANCE_BATCH();
do_discard:
return tmp;
}
/*
* Copy the back buffer to the front buffer.
@ -360,9 +86,6 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
break;
}
if (0)
intel_draw_performance_boxes( intel );
for (i = 0 ; i < nbox; i++, pbox++)
{
if (pbox->x1 > pbox->x2 ||
@ -646,7 +369,9 @@ void intelInitBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
/* AGP allocation won't work:
*/
if (1 || !intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
intel->alloc.size = 8 * 1024;
intel->alloc.ptr = malloc( intel->alloc.size );
intel->alloc.offset = 0;

View file

@ -34,10 +34,7 @@
#define BATCH_LOCALS GLubyte *batch_ptr;
/* #define VERBOSE 0 */
#ifndef VERBOSE
extern int VERBOSE;
#endif
#define VERBOSE 1
#define BEGIN_BATCH(n) \
@ -70,7 +67,6 @@ extern void intelDestroyBatchBuffer( GLcontext *ctx );
extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim );
extern void intelWrapInlinePrimitive( intelContextPtr intel );
extern void intelRestartInlinePrimitive( intelContextPtr intel );
extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive, int dwords,
int vertex_size);
@ -99,25 +95,7 @@ extern void intelEmitFillBlitLocked( intelContextPtr intel,
static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
GLuint dwords )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel->batch.space < sz) {
intelWrapInlinePrimitive( intel );
/* assert(intel->batch.space >= sz); */
}
/* assert(intel->prim.primitive != ~0); */
ptr = (GLuint *)intel->batch.ptr;
intel->batch.ptr += sz;
intel->batch.space -= sz;
return ptr;
}
GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
GLuint dwords );
#endif

View file

@ -214,7 +214,7 @@ static const struct tnl_pipeline_stage *intel_pipeline[] = {
&_tnl_point_attenuation_stage,
&_tnl_arb_vertex_program_stage,
&_tnl_vertex_program_stage,
#if 1
#if 0
&_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */
#endif
&_tnl_render_stage,

View file

@ -81,6 +81,10 @@ struct intel_texture_object
GLuint firstLevel;
GLuint lastLevel;
/* Offset for firstLevel image:
*/
GLuint textureOffset;
/* On validation any active images held in main memory or in other
* regions will be copied to this region and the old storage freed.
*/
@ -97,10 +101,22 @@ struct intel_texture_image {
GLuint level;
GLuint face;
/* If intelImage->mt != NULL, image data is stored here.
* Else if intelImage->base.Data != NULL, image is stored there.
* Else there is no image data.
*/
struct intel_mipmap_tree *mt;
};
struct intel_reloc {
GLuint *value;
GLuint delta;
GLuint *dest;
};
#define INTEL_MAX_FIXUP 64
struct intel_context
{
GLcontext ctx; /* the parent class */
@ -182,8 +198,11 @@ struct intel_context
/* AGP memory buffer manager:
*/
struct bufmgr *bm;
struct bm_buffer_list *buffer_list;
struct intel_reloc fixup[INTEL_MAX_FIXUP];
GLuint nr_fixups;
struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
/* State for intelvb.c and inteltris.c.
*/

View file

@ -196,7 +196,7 @@ void intelFlushBatchLocked( intelContextPtr intel,
}
}
if (0)
if (1)
intel_dump_batchbuffer( batch.start,
(int *)(intel->batch.ptr - batch.used),
batch.used );

View file

@ -29,6 +29,7 @@
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "bufmgr.h"
#include "enums.h"
static GLenum target_to_target( GLenum target )
{
@ -59,6 +60,12 @@ struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
_mesa_printf("%s target %s format %s level %d..%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(internal_format),
first_level,
last_level);
mt->target = target_to_target(target);
mt->internal_format = internal_format;
mt->first_level = first_level;
@ -125,6 +132,11 @@ GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
GLuint face,
GLuint level )
{
_mesa_printf("%s %d %d/%d %d/%d\n", __FUNCTION__,
image->Border,
image->InternalFormat, mt->internal_format,
image->IsCompressed, mt->compressed);
/* Images with borders are never pulled into mipmap trees.
*/
if (image->Border)
@ -134,6 +146,11 @@ GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
image->IsCompressed != mt->compressed)
return GL_FALSE;
_mesa_printf("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__,
image->Width, mt->offset[face][level].width,
image->Height, mt->offset[face][level].height,
image->Depth, mt->offset[face][level].depth);
/* Test image dimensions against the base level image adjusted for
* minification. This will also catch images not present in the
* tree, changed targets, etc.
@ -143,34 +160,47 @@ GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
image->Depth != mt->offset[face][level].depth)
return GL_FALSE;
_mesa_printf("%s: success\n", __FUNCTION__);
return GL_TRUE;
}
GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level)
{
return (mt->offset[face][level].x +
mt->offset[face][level].y * mt->pitch) * mt->cpp;
}
GLubyte *intel_miptree_image_map(struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *stride)
{
GLubyte *img = intel_region_map(intel, mt->region);
_mesa_printf("%s\n", __FUNCTION__);
if (stride)
*stride = mt->pitch * mt->cpp;
return img + (mt->offset[face][level].x +
mt->offset[face][level].y * mt->pitch) * mt->cpp;
return (intel_region_map(intel, mt->region) +
intel_miptree_image_offset(mt, face, level));
}
void intel_miptree_image_unmap(struct intel_context *intel,
struct intel_mipmap_tree *mt)
{
_mesa_printf("%s\n", __FUNCTION__);
intel_region_unmap(intel, mt->region);
}
/* Upload data for a particular image.
*
* TODO: 3D textures
@ -181,6 +211,7 @@ void intel_miptree_image_data(struct intel_context *intel,
GLuint level,
void *src, GLuint src_pitch )
{
_mesa_printf("%s\n", __FUNCTION__);
intel_region_data(intel,
dst->region,
dst->offset[face][level].x,
@ -199,6 +230,7 @@ void intel_miptree_image_copy( struct intel_context *intel,
GLuint face, GLuint level,
struct intel_mipmap_tree *src )
{
_mesa_printf("%s\n", __FUNCTION__);
assert(src->offset[face][level].width ==
dst->offset[face][level].width);

View file

@ -131,6 +131,16 @@ GLubyte *intel_miptree_image_map( struct intel_context *intel,
void intel_miptree_image_unmap( struct intel_context *intel,
struct intel_mipmap_tree *mt );
/* Return the linear offset of an image relative to the start of the
* tree:
*/
GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt,
GLuint face,
GLuint level );
/* Upload an image into a tree
*/
void intel_miptree_image_data(struct intel_context *intel,

View file

@ -48,6 +48,7 @@
*/
GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
{
_mesa_printf("%s\n", __FUNCTION__);
if (!region->map_refcount++) {
region->map = bmMapBuffer(intel->bm, region->buffer, 0);
}
@ -58,6 +59,7 @@ GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *regi
void intel_region_unmap(struct intel_context *intel,
struct intel_region *region)
{
_mesa_printf("%s\n", __FUNCTION__);
if (!--region->map_refcount) {
bmUnmapBuffer(intel->bm, region->buffer);
}
@ -70,6 +72,8 @@ struct intel_region *intel_region_alloc( struct intel_context *intel,
{
struct intel_region *region = calloc(sizeof(*region), 1);
_mesa_printf("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
@ -201,6 +205,8 @@ void intel_region_data(struct intel_context *intel,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height)
{
_mesa_printf("%s\n", __FUNCTION__);
LOCK_HARDWARE(intel);
_mesa_copy_rect(intel_region_map(intel, dst),
@ -232,6 +238,8 @@ void intel_region_copy( struct intel_context *intel,
unsigned src_offset;
struct bm_buffer_list *list = bmNewBufferList();
_mesa_printf("%s\n", __FUNCTION__);
assert(src->cpp == dst->cpp);
LOCK_HARDWARE(intel);
@ -282,6 +290,8 @@ void intel_region_fill( struct intel_context *intel,
unsigned dst_offset;
struct bm_buffer_list *list = bmNewBufferList();
_mesa_printf("%s\n", __FUNCTION__);
LOCK_HARDWARE(intel);
bmAddBuffer(intel->bm, list, dst->buffer, BM_WRITE, NULL, &dst_offset);

View file

@ -199,6 +199,10 @@ static GLboolean intel_run_render( GLcontext *ctx,
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
/* disabled
*/
return GL_TRUE;
/* Don't handle clipping or indexed vertices.
*/
if (intel->RenderIndex != 0 ||

View file

@ -82,7 +82,14 @@ void intelTexSubImage1D(GLcontext *ctx,
GLuint intel_validate_mipmap_tree( struct intel_context *intel,
struct intel_texture_object *intelObj );
void intel_add_texoffset_fixup( struct intel_context *intel,
GLuint unit,
GLuint *ptr );
void intel_apply_fixups( struct intel_context *intel );
GLboolean intel_prevalidate_buffers( struct intel_context *intel );
GLboolean intel_validate_buffers( struct intel_context *intel );
void intel_fence_buffers( struct intel_context *intel );
#endif

View file

@ -65,6 +65,8 @@ static void guess_and_alloc_mipmap_tree( struct intel_context *intel,
GLuint l2width, l2height, l2depth;
GLuint i;
_mesa_printf("%s\n", __FUNCTION__);
if (intelImage->base.Border)
return;
@ -121,6 +123,8 @@ static void guess_and_alloc_mipmap_tree( struct intel_context *intel,
depth,
intelImage->base.TexFormat->TexelBytes,
intelImage->base.IsCompressed );
_mesa_printf("%s - success\n", __FUNCTION__);
}
@ -161,6 +165,11 @@ static void intelTexImage(GLcontext *ctx,
GLint texelBytes, sizeInBytes;
GLuint dstRowStride;
_mesa_printf("%s target %s level %d %dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
width, height, border);
intelImage->face = target_to_face( target );
intelImage->level = level;
@ -219,15 +228,23 @@ static void intelTexImage(GLcontext *ctx,
LOCK_HARDWARE(intel);
if (intelObj->mt &&
intelObj->mt != intelImage->mt &&
intel_miptree_match_image(intelObj->mt, &intelImage->base,
intelImage->face, intelImage->level)) {
if (intelImage->mt)
intel_miptree_release(intel, intelImage->mt);
intelImage->mt = intel_miptree_reference(intelObj->mt);
}
if (intelImage->mt) {
texImage->Data = intel_miptree_image_map(intel,
intelObj->mt,
intelImage->mt,
intelImage->face,
intelImage->level,
&dstRowStride);
}
}
else {
/* Allocate regular memory and store the image there temporarily. */
if (texImage->IsCompressed) {

View file

@ -3,6 +3,7 @@
#include "mtypes.h"
#include "texobj.h"
#include "texstore.h"
#include "enums.h"
#include "intel_context.h"
#include "intel_tex.h"
@ -24,6 +25,12 @@ static void intelTexSubimage (GLcontext *ctx,
GLuint dstImageStride = 0;
GLuint dstRowStride;
_mesa_printf("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
xoffset, yoffset,
width, height);
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, format, type,
pixels, packing, "glTexSubImage2D");
if (!pixels)

View file

@ -4,7 +4,7 @@
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "bufmgr.h"
/**
* Compute which mipmap levels that really need to be sent to the hardware.
@ -96,9 +96,11 @@ static void copy_image_data_to_tree( struct intel_context *intel,
/*
*/
GLuint intel_validate_mipmap_tree( struct intel_context *intel,
struct intel_texture_object *intelObj )
static GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit )
{
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
GLuint face, i;
GLuint nr_faces = 0;
struct intel_texture_image *firstImage;
@ -139,6 +141,12 @@ GLuint intel_validate_mipmap_tree( struct intel_context *intel,
/* Check tree can hold all active levels. Check tree matches
* target, imageFormat, etc.
*
* XXX: For some layouts (eg i945?), the test might have to be
* first_level == firstLevel, as the tree isn't valid except at the
* original start level. Hope to get around this by
* programming minLod, maxLod, baseLevel into the hardware and
* leaving the tree alone.
*/
if (intelObj->mt &&
((intelObj->mt->first_level > intelObj->firstLevel) ||
@ -152,7 +160,6 @@ GLuint intel_validate_mipmap_tree( struct intel_context *intel,
/* May need to create a new tree:
*/
if (!intelObj->mt) {
assert(!firstImage->mt);
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
firstImage->base.InternalFormat,
@ -165,13 +172,9 @@ GLuint intel_validate_mipmap_tree( struct intel_context *intel,
firstImage->base.IsCompressed);
}
assert(intelObj->mt);
assert(firstImage->mt == intelObj->mt ||
firstImage->mt == NULL);
/* Pull in any images not in the object's tree:
*/
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
@ -190,9 +193,105 @@ GLuint intel_validate_mipmap_tree( struct intel_context *intel,
return GL_TRUE;
}
void intel_add_texoffset_fixup( struct intel_context *intel,
GLuint unit,
GLuint *ptr )
{
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
#if 0
struct intel_reloc *f = &intel->fixup[intel->nr_fixups++];
assert(intel->nr_fixups <= INTEL_MAX_FIXUP);
f->dest = ptr;
f->value = &intelObj->textureOffset;
f->delta = (intel->intelScreen->tex.offset +
intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel));
#else
*ptr = (intelObj->textureOffset +
intel->intelScreen->tex.offset +
intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel));
*ptr = 9999;
#endif
}
/* Fix up the command buffer:
*/
void intel_apply_fixups( struct intel_context *intel )
{
GLuint i;
for (i = 0; i < intel->nr_fixups; i++) {
struct intel_reloc *f = &intel->fixup[i];
*f->dest = *f->value + f->delta;
}
intel->nr_fixups = 0;
}
/* One upshot of the new manager is that it should be possible to tell
* ahead of time whether a certain set of buffers will cause a
* fallback.
*
* Unless we do this we either have to a) hold the DRI lock
* while emitting all vertices and fire after each vertex buffer, or
* b) build a fallback path that operates on i915 command streams
* rather than the state in the GLcontext.
*/
GLboolean intel_prevalidate_buffers( struct intel_context *intel )
{
return GL_TRUE; /* never fallback */
}
GLboolean intel_validate_buffers( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
GLboolean ok = GL_TRUE;
GLuint i;
_mesa_printf("%s\n", __FUNCTION__);
assert(intel->locked);
assert (!intel->buffer_list);
intel->buffer_list = bmNewBufferList();
/* Add the color and depth buffers:
*/
/* Add each enabled texture:
*/
for (i = 0 ; i < ctx->Const.MaxTextureUnits && ok ; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[i]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
ok = intel_finalize_mipmap_tree( intel, i );
if (ok) {
bmAddBuffer(intel->bm,
intel->buffer_list,
intelObj->mt->region->buffer,
BM_READ,
NULL,
&intelObj->textureOffset);
}
}
}
ok = bmValidateBufferList(intel->bm, intel->buffer_list, 0);
assert(ok);
return ok;
}
void intel_fence_buffers( struct intel_context *intel )
{
assert(intel->locked);
assert(intel->buffer_list);
bmFenceBufferList(intel->bm, intel->buffer_list);
bmFreeBufferList(intel->buffer_list);
intel->buffer_list = NULL;
}

View file

@ -42,10 +42,131 @@
#include "intel_batchbuffer.h"
#include "intel_reg.h"
#include "intel_span.h"
#include "intel_tex.h"
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
/* The simplest but least-good technique for integrating new buffer
* management:
*
* LOCK_HARDWARE
* validate_buffers
* emit_state to batch
* emit_vertices to batch
* flush batch
* fence_buffers
* UNLOCK_HARDWARE
*
* Will look later at ways to get the emit_state and emit_vertices out
* of the locked region - vertex buffers, second batch buffer for
* primitives, relocation fixups for texture addresses.
*/
static void intel_flush_inline_primitive( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
GLuint used = intel->batch.ptr - intel->prim.start_ptr;
assert(intel->prim.primitive != ~0);
if (used < 8)
goto do_discard;
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
do_discard:
intel->batch.ptr -= used;
intel->batch.space += used;
assert(intel->batch.space >= 0);
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
intelFlushBatch(intel, GL_TRUE);
intel_fence_buffers(intel);
UNLOCK_HARDWARE(intel);
}
/* Emit a primitive referencing vertices in a vertex buffer.
*/
void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
{
BATCH_LOCALS;
fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
/* Finish any in-progress primitive:
*/
INTEL_FIREVERTICES( intel );
LOCK_HARDWARE(intel);
intel_validate_buffers( intel );
intel->vtbl.emit_state( intel );
/* Make sure there is some space in this buffer:
*/
if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
intelFlushBatch(intel, GL_TRUE);
if (((int)intel->batch.ptr) & 0x4) {
BEGIN_BATCH(1);
OUT_BATCH(0);
ADVANCE_BATCH();
}
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2);
OUT_BATCH( 0 );
intel->prim.start_ptr = batch_ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelWrapInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
intel_flush_inline_primitive( &intel->ctx );
intelFlushBatch(intel, GL_TRUE);
intelStartInlinePrimitive( intel, prim );
}
GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
GLuint dwords )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel->batch.space < sz) {
intelWrapInlinePrimitive( intel );
}
ptr = (GLuint *)intel->batch.ptr;
intel->batch.ptr += sz;
intel->batch.space -= sz;
return ptr;
}
/***********************************************************************
* Emit primitives as inline vertices *
***********************************************************************/
@ -520,22 +641,6 @@ intel_fallback_line( intelContextPtr intel,
}
static void
intel_fallback_point( intelContextPtr intel,
intelVertex *v0 )
{
GLcontext *ctx = &intel->ctx;
SWvertex v[1];
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
_swsetup_Translate( ctx, v0, &v[0] );
intelSpanRenderStart( ctx );
_swrast_Point( ctx, &v[0] );
intelSpanRenderFinish( ctx );
}
/**********************************************************************/
@ -630,12 +735,8 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
#define POINT_FALLBACK (0)
#define LINE_FALLBACK (DD_LINE_STIPPLE)
#define TRI_FALLBACK (0)
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
DD_TRI_STIPPLE|DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
void intelChooseRenderState(GLcontext *ctx)
{
@ -672,19 +773,14 @@ void intelChooseRenderState(GLcontext *ctx)
intel->draw_tri = intel_draw_triangle;
}
#if 0
/* Hook in fallbacks for specific primitives.
*/
if (flags & ANY_FALLBACK_FLAGS)
{
if (flags & POINT_FALLBACK)
intel->draw_point = intel_fallback_point;
if (flags & LINE_FALLBACK)
if (flags & DD_LINE_STIPPLE)
intel->draw_line = intel_fallback_line;
if (flags & TRI_FALLBACK)
intel->draw_tri = intel_fallback_tri;
if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
intel->draw_tri = intel_fallback_tri;
@ -693,6 +789,8 @@ void intelChooseRenderState(GLcontext *ctx)
index |= INTEL_FALLBACK_BIT;
}
#endif
}
if (intel->RenderIndex != index) {
@ -765,8 +863,13 @@ static void intelRenderStart( GLcontext *ctx )
static void intelRenderFinish( GLcontext *ctx )
{
if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
struct intel_context *intel = intel_context(ctx);
if (intel->RenderIndex & INTEL_FALLBACK_BIT)
_swrast_flush( ctx );
if (intel->prim.flush)
intel->prim.flush(ctx);
}