/* Allocates a region from rmesa->dma.current. If there isn't enough * space in current, grab a new buffer (and discard what was left of current) */ void r200AllocDmaRegion( r200ContextPtr rmesa, struct r200_dma_region *region, int bytes, int alignment ) { if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); if (rmesa->dma.flush) rmesa->dma.flush( rmesa ); if (region->buf) r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ ); alignment--; rmesa->dma.current.start = rmesa->dma.current.ptr = (rmesa->dma.current.ptr + alignment) & ~alignment; if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) r200RefillCurrentDmaRegion( rmesa ); region->start = rmesa->dma.current.start; region->ptr = rmesa->dma.current.start; region->end = rmesa->dma.current.start + bytes; region->address = rmesa->dma.current.address; region->buf = rmesa->dma.current.buf; region->buf->refcount++; rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */ rmesa->dma.current.start = rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7; assert( rmesa->dma.current.ptr <= rmesa->dma.current.end ); }
/* Begin/End */ static void r200_Begin( GLenum mode ) { GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa = R200_CONTEXT(ctx); if (R200_DEBUG & DEBUG_VFMT) fprintf(stderr, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( mode )); if (mode > GL_POLYGON) { _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); return; } if (rmesa->vb.prim[0] != GL_POLYGON+1) { _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); return; } if (ctx->NewState) _mesa_update_state( ctx ); if (rmesa->NewGLState) r200ValidateState( ctx ); if (rmesa->vb.recheck) r200VtxfmtValidate( ctx ); if (!rmesa->vb.installed) { CALL_Begin(GET_DISPATCH(), (mode)); return; } if (rmesa->dma.flush && rmesa->vb.counter < 12) { if (R200_DEBUG & DEBUG_VFMT) fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__); flush_prims( rmesa ); } /* Need to arrange to save vertices here? Or always copy from dma (yuk)? */ if (!rmesa->dma.flush) { if (rmesa->dma.current.ptr + 12*rmesa->vb.vertex_size*4 > rmesa->dma.current.end) { R200_NEWPRIM( rmesa ); r200RefillCurrentDmaRegion( rmesa ); } rmesa->vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr); rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / (rmesa->vb.vertex_size * 4); rmesa->vb.counter--; rmesa->vb.initial_counter = rmesa->vb.counter; rmesa->vb.notify = wrap_buffer; rmesa->dma.flush = flush_prims; ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; } rmesa->vb.prim[0] = mode; start_prim( rmesa, mode | PRIM_BEGIN ); }
static void wrap_buffer( void ) { GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa = R200_CONTEXT(ctx); GLfloat tmp[3][R200_MAX_VERTEX_SIZE]; GLuint i, nrverts; if (R200_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS)) fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter); /* Don't deal with parity. */ if ((((rmesa->vb.initial_counter - rmesa->vb.counter) - rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) { rmesa->vb.counter++; rmesa->vb.initial_counter++; return; } /* Copy vertices out of dma: */ if (rmesa->vb.prim[0] == GL_POLYGON+1) nrverts = 0; else { nrverts = copy_dma_verts( rmesa, tmp ); if (R200_DEBUG & DEBUG_VFMT) fprintf(stderr, "%d vertices to copy\n", nrverts); /* Finish the prim at this point: */ note_last_prim( rmesa, 0 ); } /* Fire any buffered primitives */ flush_prims( rmesa ); /* Get new buffer */ r200RefillCurrentDmaRegion( rmesa ); /* Reset counter, dmaptr */ rmesa->vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address); rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / (rmesa->vb.vertex_size * 4); rmesa->vb.counter--; rmesa->vb.initial_counter = rmesa->vb.counter; rmesa->vb.notify = wrap_buffer; rmesa->dma.flush = flush_prims; /* Restart wrapped primitive: */ if (rmesa->vb.prim[0] != GL_POLYGON+1) start_prim( rmesa, rmesa->vb.prim[0] ); /* Reemit saved vertices */ for (i = 0 ; i < nrverts; i++) { if (R200_DEBUG & DEBUG_VERTS) { int j; fprintf(stderr, "re-emit vertex %d to %p\n", i, (void *)rmesa->vb.dmaptr); if (R200_DEBUG & DEBUG_VERBOSE) for (j = 0 ; j < rmesa->vb.vertex_size; j++) fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]); } memcpy( rmesa->vb.dmaptr, tmp[i], rmesa->vb.vertex_size * 4 ); rmesa->vb.dmaptr += rmesa->vb.vertex_size; rmesa->vb.counter--; } }