Expand the buffer manager to include a notion of multiple pools within

a memory space.  Allow some pools to be excluded from the upload/evict
processing, meaning that any buffers within those pools are effectively
fixed.  Add a mechanism to create buffers in those pools.

This allows the legacy fixed front/depth/back buffers to be represented
in this scheme and will allow other future pinned buffers to be allocated
from fixed pools in such a way that they cannot fragment the rest of
the texture memory.
This commit is contained in:
Keith Whitwell 2006-01-26 14:50:02 +00:00
parent 398cb30c72
commit 33ca04f379
9 changed files with 379 additions and 171 deletions

View file

@ -14,29 +14,54 @@ struct bm_buffer_list;
struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel );
/* struct bufmgr *bmCreate( ... ); */
/* struct bufmgr *bmAttach( ... ); */
void bmInitPool( struct bufmgr *,
unsigned pool,
unsigned long low_offset,
unsigned long high_offset,
void *virtual_base );
/* Define an address space. Doesn't really do anything, but the
* information could be used to validate the bmInitPool() requests.
*/
void bmInitMemType( struct bufmgr *,
unsigned mem_type,
unsigned long size );
/* Create a pool of a given memory type, from a certain offset and a
* certain size.
*
* Also passed in is a virtual pointer to the start of the pool. This
* is useful in the faked-out version in i915 so that MapBuffer can
* return a pointer to a buffer residing in AGP space.
*
* Flags passed into a pool are inherited by all buffers allocated in
* that pool. So pools representing the static front,back,depth
* buffer allocations should have MEM_AGP|NO_UPLOAD|NO_EVICT|NO_MOVE to match
* the behaviour of the legacy allocations.
*
* Returns -1 for failure, pool number for success.
*/
int bmInitPool( struct bufmgr *,
unsigned long low_offset,
void *low_virtual,
unsigned long size,
unsigned flags);
/* Flags for validate and other calls. If both NO_UPLOAD and NO_EVICT
* are specified, ValidateBuffers is essentially a query.
*/
#define BM_MEM_LOCAL 0x1
#define BM_MEM_AGP 0x2
#define BM_MEM_VRAM 0x4 /* not used */
#define BM_WRITE 0x100 /* not used */
#define BM_READ 0x200 /* not used */
#define BM_MEM_VRAM 0x4 /* not yet used */
#define BM_WRITE 0x8 /* not yet used */
#define BM_READ 0x10 /* not yet used */
#define BM_NO_UPLOAD 0x20
#define BM_NO_EVICT 0x40
#define BM_NO_MOVE 0x80 /* not yet used */
#define BM_NO_ALLOC 0x100 /* legacy "fixed" buffers only */
/* Flags for validate. If both NO_UPLOAD and NO_EVICT are specified,
* ValidateBuffers is essentially a query.
*/
#define BM_NO_UPLOAD 0x1
#define BM_NO_EVICT 0x2
#define BM_MEM_MASK (BM_MEM_LOCAL|BM_MEM_AGP|BM_MEM_VRAM)
/* Stick closely to ARB_vbo semantics - they're well defined and
@ -46,6 +71,18 @@ void bmInitPool( struct bufmgr *,
void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
/* Hook to inform faked buffer manager about fixed-position
* front,depth,back buffers. These may move to a fully memory-managed
* scheme, or they may continue to be managed as is.
*/
unsigned bmBufferStatic(struct bufmgr *,
unsigned buffer,
unsigned size,
unsigned pool);
/* The driver has more intimate knowledge of the hardare than a GL
* client would, so flags here is more proscriptive than the usage
* values in the ARB_vbo interface:
@ -90,8 +127,7 @@ void bmUnmapBuffer( struct bufmgr *,
*/
struct bm_buffer_list *bmNewBufferList( void );
void bmAddBuffer( struct bufmgr *,
struct bm_buffer_list *list,
void bmAddBuffer( struct bm_buffer_list *list,
unsigned buffer,
unsigned flags,
unsigned *pool_return,

View file

@ -22,6 +22,7 @@ struct _mesa_HashTable;
/* Maximum number of buffers to pass to bmValidateBufferList:
*/
#define BM_LIST_MAX 32
#define BM_POOL_MAX 8
/* Wrapper around mm.c's mem_block, which understands that you must
@ -32,7 +33,8 @@ struct _mesa_HashTable;
*/
struct block {
struct block *next, *prev;
int memType;
int mem_type;
struct pool *pool; /* BM_MEM_AGP */
struct mem_block *mem; /* BM_MEM_AGP */
unsigned fence; /* BM_MEM_AGP, Split to read_fence, write_fence */
void *virtual;
@ -45,50 +47,56 @@ struct buffer {
unsigned size;
unsigned alignment;
unsigned mapped;
unsigned flags;
struct block *block;
};
struct pool {
unsigned size;
unsigned flags;
struct mem_block *heap;
void *virtual;
struct block lru;
struct block freed;
};
/* List of buffers to validate:
*/
struct bm_buffer_list {
struct buffer *buffer[BM_LIST_MAX];
unsigned *offset_return[BM_LIST_MAX];
unsigned nr;
unsigned need_fence;
};
struct bufmgr {
struct intel_context *intel;
struct buffer buffer_list;
struct pool pool;
struct pool pool[BM_POOL_MAX];
unsigned nr_pools;
struct _mesa_HashTable *hash;
unsigned buf_nr; /* for generating ids */
unsigned last_fence;
};
static struct block *alloc_agp( struct bufmgr *bm,
unsigned size,
unsigned align )
/* List of buffers to validate:
*/
struct bm_buffer_list {
struct {
unsigned buffer;
unsigned *offset_return;
unsigned *memtype_return;
} elem[BM_LIST_MAX];
unsigned nr;
};
static struct block *alloc_from_pool( struct bufmgr *bm,
unsigned pool_nr,
unsigned size,
unsigned align )
{
struct pool *pool = &bm->pool[pool_nr];
struct block *block = (struct block *)calloc(sizeof *block, 1);
if (!block)
return NULL;
_mesa_printf("alloc_agp 0x%x\n", size);
_mesa_printf("alloc_from_pool %d sz 0x%x\n", pool_nr, size);
block->mem = mmAllocMem(bm->pool.heap, size, align, 0);
block->mem = mmAllocMem(pool->heap, size, align, 0);
if (!block->mem) {
_mesa_printf("\t- failed\n");
free(block);
@ -96,8 +104,9 @@ static struct block *alloc_agp( struct bufmgr *bm,
}
make_empty_list(block);
block->memType = BM_MEM_AGP;
block->virtual = bm->pool.virtual + block->mem->ofs;
block->pool = pool;
block->mem_type = pool->flags & BM_MEM_MASK;
block->virtual = pool->virtual + block->mem->ofs;
_mesa_printf("\t- offset 0x%x\n", block->mem->ofs);
return block;
@ -112,7 +121,7 @@ static struct block *alloc_local( unsigned size )
_mesa_printf("alloc_local 0x%x\n", size);
block->memType = BM_MEM_LOCAL;
block->mem_type = BM_MEM_LOCAL;
block->virtual = malloc(size);
if (!block->virtual) {
free(block);
@ -123,30 +132,35 @@ static struct block *alloc_local( unsigned size )
}
static struct block *alloc_block( struct bufmgr *bm,
unsigned size,
unsigned align,
int memType )
int flags )
{
switch (memType) {
case BM_MEM_AGP:
return alloc_agp(bm, size, align);
case BM_MEM_LOCAL:
return alloc_local(size);
default:
return NULL;
GLuint i;
for (i = 0; i < bm->nr_pools; i++) {
if (bm->pool[i].flags & BM_NO_ALLOC)
continue;
if ((bm->pool[i].flags & flags & BM_MEM_MASK) == 0)
continue;
return alloc_from_pool(bm, i, size, align);
}
if (flags & BM_MEM_LOCAL)
return alloc_local(size);
return NULL;
}
static int bmAllocMem( struct bufmgr *bm,
struct buffer *buf,
unsigned flags ) /* unused */
struct buffer *buf )
{
if (buf->block == NULL)
buf->block = alloc_block(bm, buf->size, 4, BM_MEM_AGP);
if (buf->block == NULL)
buf->block = alloc_block(bm, buf->size, 4, BM_MEM_LOCAL);
buf->block = alloc_block(bm, buf->size, 4, buf->flags);
if (buf->block)
buf->block->buf = buf;
@ -162,15 +176,16 @@ static void free_block( struct bufmgr *bm, struct block *block )
if (!block)
return;
switch (block->memType) {
switch (block->mem_type) {
case BM_MEM_AGP:
case BM_MEM_VRAM:
if (bmTestFence(bm, block->fence)) {
mmFreeMem(block->mem);
free(block);
}
else {
block->buf = NULL;
move_to_tail(&bm->pool.freed, block);
move_to_tail(&block->pool->freed, block);
}
break;
@ -189,13 +204,16 @@ static int delayed_free( struct bufmgr *bm )
{
struct block *block, *tmp;
int ret = 0;
int i;
foreach_s(block, tmp, &bm->pool.freed ) {
if (bmTestFence(bm, block->fence)) {
ret += block->mem->size;
remove_from_list(block);
mmFreeMem(block->mem);
free(block);
for (i = 0; i < bm->nr_pools; i++) {
foreach_s(block, tmp, &bm->pool[i].freed ) {
if (bmTestFence(bm, block->fence)) {
ret += block->mem->size;
remove_from_list(block);
mmFreeMem(block->mem);
free(block);
}
}
}
@ -206,7 +224,6 @@ static int delayed_free( struct bufmgr *bm )
static int move_buffers( struct bufmgr *bm,
struct buffer *buffers[],
int nr,
int newMemType,
int flags )
{
struct block *newMem[BM_LIST_MAX];
@ -219,22 +236,20 @@ static int move_buffers( struct bufmgr *bm,
/* First do all the allocations (or fail):
*/
for (i = 0; i < nr; i++) {
if (buffers[i]->block->memType != newMemType) {
if (!(buffers[i]->block->mem_type & flags)) {
if (flags & BM_NO_UPLOAD)
goto cleanup;
_mesa_printf("try to move buffer size 0x%x to pool %d\n",
buffers[i]->size, newMemType);
_mesa_printf("try to move buffer %d size 0x%x to pools 0x%x\n",
buffers[i]->id, buffers[i]->size, flags & BM_MEM_MASK);
newMem[i] = alloc_block(bm,
buffers[i]->size,
buffers[i]->alignment,
newMemType);
flags & BM_MEM_MASK);
if (!newMem[i])
goto cleanup;
newMem[i]->buf = buffers[i];
}
}
@ -243,12 +258,15 @@ static int move_buffers( struct bufmgr *bm,
*/
for (i = 0; i < nr; i++) {
if (newMem[i]) {
/* XXX: To be replaced with DMA, GTT bind, and other
* mechanisms in final version. Memcpy (or sse_memcpy) is
* probably pretty good for local->agp uploads.
*/
memcpy(newMem[i]->virtual,
buffers[i]->block->virtual,
buffers[i]->size);
free_block(bm, buffers[i]->block);
buffers[i]->block = newMem[i];
buffers[i]->block->buf = buffers[i];
}
@ -256,7 +274,7 @@ static int move_buffers( struct bufmgr *bm,
/* Tell hardware that its texture and other caches may be invalid:
*/
if (nr)
if (nr && (flags & (BM_MEM_AGP|BM_MEM_VRAM)))
bmFlushReadCaches(bm);
_mesa_printf("%s - success\n", __FUNCTION__);
@ -275,26 +293,36 @@ static int move_buffers( struct bufmgr *bm,
}
static unsigned evict_lru( struct bufmgr *bm )
static unsigned evict_lru( struct bufmgr *bm,
unsigned flags)
{
int ret;
int i;
_mesa_printf("%s\n", __FUNCTION__);
ret = delayed_free(bm);
if (ret)
return ret;
else {
struct block *block = bm->pool.lru.next;
unsigned size = block->buf->size;
if (flags & BM_NO_EVICT)
return 0;
if (block == &bm->pool.lru ||
!bmTestFence(bm, block->fence))
return 0;
/* XXX: this is broken with >1 active pool - all the first pool
* will be evicted before starting on the second. Actually, maybe
* you want that in some situations...
*/
for (i = 0; i < bm->nr_pools; i++) {
if ((bm->pool[i].flags & flags & BM_MEM_MASK) &&
!(bm->pool[i].flags & BM_NO_EVICT)) {
struct block *block = bm->pool[i].lru.next;
unsigned size = block->buf->size;
if (block == &bm->pool[i].lru ||
!bmTestFence(bm, block->fence))
return 0;
move_buffers(bm, &block->buf, 1, BM_MEM_LOCAL, 0);
return size;
move_buffers(bm, &block->buf, 1, BM_MEM_LOCAL);
return size;
}
}
return 0;
}
#if 0
@ -359,27 +387,43 @@ struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel )
}
void bmInitMemType( struct bufmgr *bm,
unsigned mem_type,
unsigned long size )
{
/* Nothing really to do. Could store and use to validate
* bmInitPool requests.
*/
}
/* The virtual pointer would go away in a true implementation.
*/
void bmInitPool( struct bufmgr *bm,
unsigned pool,
unsigned long low_offset,
unsigned long high_offset,
void *virtual_base )
int bmInitPool( struct bufmgr *bm,
unsigned long low_offset,
void *low_virtual,
unsigned long size,
unsigned flags)
{
if (pool > 0 || low_offset >= high_offset)
return;
GLuint i;
_mesa_printf("bmInitPool %d %x..%x\n",
pool, low_offset, high_offset);
if (bm->nr_pools >= BM_POOL_MAX)
return -1;
i = bm->nr_pools++;
bm->pool.size = high_offset - low_offset;
bm->pool.heap = mmInit( low_offset, bm->pool.size );
bm->pool.virtual = virtual_base;
_mesa_printf("bmInitPool %d low_offset %x sz %x\n",
i, low_offset, size);
make_empty_list(&bm->pool.lru);
make_empty_list(&bm->pool.freed);
bm->pool[i].heap = mmInit( low_offset, size );
bm->pool[i].virtual = low_virtual - low_offset;
bm->pool[i].flags = flags;
make_empty_list(&bm->pool[i].lru);
make_empty_list(&bm->pool[i].freed);
return i;
}
@ -390,7 +434,10 @@ void bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
for (i = 0; i < n; i++) {
struct buffer *buf = calloc(sizeof(*buf), 1);
buffers[i] = buf->id = ++bm->buf_nr;
buf->id = ++bm->buf_nr;
buf->alignment = 12; /* page-alignment to fit in with AGP swapping */
buf->flags = BM_MEM_AGP|BM_MEM_VRAM|BM_MEM_LOCAL;
buffers[i] = buf->id;
_mesa_HashInsert(bm->hash, buffers[i], buf);
}
}
@ -410,6 +457,54 @@ void bmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
}
}
/* Hook to inform faked buffer manager about fixed-position
* front,depth,back buffers. These may move to a fully memory-managed
* scheme, or they may continue to be managed as is. It will probably
* be useful to pass a fixed offset here one day.
*/
unsigned bmBufferStatic(struct bufmgr *bm,
unsigned buffer,
unsigned size,
unsigned pool )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
assert(!buf->block);
assert(bm->pool[pool].flags & BM_NO_EVICT);
assert(bm->pool[pool].flags & BM_NO_MOVE);
buf->size = size;
buf->flags = bm->pool[pool].flags;
buf->alignment = 0;
buf->block = alloc_from_pool(bm, pool, buf->size, buf->alignment);
if (!buf->block)
return 0;
buf->block->buf = buf;
return buf->block->mem->ofs;
}
#if 0
/* How wise/useful is this?
*/
void bmBufferSetParams( struct bufmgr *bm,
unsigned buffer,
unsigned flags,
unsigned alignment )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
assert(!buf->block);
buf->flags = flags;
buf->alignment = alignment;
}
#endif
/* If buffer size changes, create new buffer in local memory.
* Otherwise update in place.
*/
@ -424,7 +519,7 @@ void bmBufferData(struct bufmgr *bm,
_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)) ||
if ((buf->block->mem_type != BM_MEM_LOCAL && !bmTestFence(bm, buf->block->fence)) ||
(buf->size && buf->size != size) ||
(data == NULL)) {
free_block(bm, buf->block);
@ -435,7 +530,7 @@ void bmBufferData(struct bufmgr *bm,
buf->size = size;
if (data != NULL) {
bmAllocMem(bm, buf, flags);
bmAllocMem(bm, buf);
memcpy(buf->block->virtual, data, size);
}
}
@ -453,12 +548,13 @@ void bmBufferSubData(struct bufmgr *bm,
_mesa_printf("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
if (buf->block == 0)
bmAllocMem(bm, buf, 0);
bmAllocMem(bm, buf);
if (buf->block->memType == BM_MEM_AGP)
if (buf->block->mem_type != BM_MEM_LOCAL)
bmFinishFence(bm, buf->block->fence);
memcpy(buf->block->virtual + offset, data, size);
if (size)
memcpy(buf->block->virtual + offset, data, size);
}
@ -478,11 +574,11 @@ void *bmMapBuffer( struct bufmgr *bm,
buf->mapped = 1;
if (buf->block == 0)
bmAllocMem(bm, buf, 0);
bmAllocMem(bm, buf);
/* Finish any outstanding operations to/from this memory:
*/
if (buf->block->memType == BM_MEM_AGP)
if (buf->block->mem_type != BM_MEM_LOCAL)
bmFinishFence(bm, buf->block->fence);
return buf->block->virtual;
@ -525,32 +621,27 @@ struct bm_buffer_list *bmNewBufferList( void )
return list;
}
void bmAddBuffer( struct bufmgr *bm,
struct bm_buffer_list *list,
void bmAddBuffer( struct bm_buffer_list *list,
unsigned buffer,
unsigned flags,
unsigned *pool_return,
unsigned *memtype_return,
unsigned *offset_return )
{
assert(list->nr < BM_LIST_MAX);
list->buffer[list->nr] = _mesa_HashLookup(bm->hash, buffer);
list->offset_return[list->nr] = offset_return;
list->elem[list->nr].buffer = buffer;
list->elem[list->nr].memtype_return = memtype_return;
list->elem[list->nr].offset_return = offset_return;
_mesa_printf("bmAddBuffer nr %d buf %d (%p/%d)\n", list->nr, buffer,
list->buffer[list->nr], list->buffer[list->nr]->id);
_mesa_printf("bmAddBuffer nr %d buf %d\n",
list->nr, buffer);
list->nr++;
if (pool_return)
*pool_return = 0;
}
void bmFreeBufferList( struct bm_buffer_list *list )
{
assert(!list->need_fence);
free(list);
}
@ -568,45 +659,39 @@ int bmValidateBufferList( struct bufmgr *bm,
struct bm_buffer_list *list,
unsigned flags )
{
struct buffer *bufs[BM_LIST_MAX];
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;
}
for (i = 0; i < list->nr; i++)
bufs[i] = _mesa_HashLookup(bm->hash, list->elem[i].buffer);
/* Don't need to try allocation in this case:
*/
if (total > bm->pool.size)
return 0;
/* The old story: evict one texture after another until allocation
* succeeds. This is a pretty poor strategy but really hard to do
* better without more infrastucture... Which is coming - hooray!
*/
while (!move_buffers(bm, list->buffer, list->nr, BM_MEM_AGP, flags)) {
if ((flags & BM_NO_EVICT) ||
!evict_lru(bm))
while (!move_buffers(bm, bufs, list->nr, flags)) {
if (!delayed_free(bm) &&
!evict_lru(bm, flags))
return 0;
}
for (i = 0; i < list->nr; i++) {
_mesa_printf("%d: buf %d ofs 0x%x\n",
i, list->buffer[i]->id,
list->buffer[i]->block->mem->ofs);
i, bufs[i]->id, bufs[i]->block->mem->ofs);
list->offset_return[i][0] = list->buffer[i]->block->mem->ofs;
list->elem[i].offset_return[0] = bufs[i]->block->mem->ofs;
if (list->elem[i].memtype_return)
list->elem[i].memtype_return[0] = bufs[i]->block->mem_type;
}
list->need_fence = 1;
return 1;
}
@ -621,26 +706,22 @@ int bmValidateBufferList( struct bufmgr *bm,
*/
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) {
unsigned i;
unsigned fence = bmSetFence( bm );
if (!list->nr)
return;
/* Move all buffers to head of resident list and set their fences
*/
for (i = 0; i < list->nr; i++) {
struct buffer *buf = _mesa_HashLookup(bm->hash, list->elem[i].buffer);
bm->last_fence = bmSetFence( bm );
/* Move all buffers to head of resident list and set their fences
*/
for (i = 0; i < list->nr; i++) {
assert(list->buffer[i]->block->buf == list->buffer[i]);
move_to_head(&bm->pool.lru, list->buffer[i]->block);
list->buffer[i]->block->fence = bm->last_fence;
move_to_head(&buf->block->pool->lru, buf->block);
buf->block->fence = fence;
}
}
}

View file

@ -42,6 +42,7 @@
#include "i915_reg.h"
#include "bufmgr.h"
#include "intel_regions.h"
/***************************************
* Mesa's Driver Functions
@ -103,6 +104,7 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
struct dd_function_table functions;
i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context);
intelContextPtr intel = &i915->intel;
intelScreenPrivate *intelScreen;
GLcontext *ctx = &intel->ctx;
if (!i915) return GL_FALSE;
@ -126,12 +128,49 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
intel->bm = bm_fake_intel_Attach( intel );
bmInitPool(intel->bm,
0,
0, /* low offset */
intel->intelScreen->tex.size, /* high offset */
intel->intelScreen->tex.map); /* virtual base */
intel->intelScreen->tex.offset, /* low offset */
intel->intelScreen->tex.map, /* low virtual */
intel->intelScreen->tex.size,
BM_MEM_AGP);
intelScreen = intel->intelScreen;
/* These are still static, but create regions for them.
*/
intel->front_region =
intel_region_create_static(intel,
BM_MEM_AGP,
intelScreen->front.offset,
intelScreen->front.map,
intelScreen->cpp,
intelScreen->front.pitch / intelScreen->cpp,
intelScreen->front.size / intelScreen->front.pitch);
intel->back_region =
intel_region_create_static(intel,
BM_MEM_AGP,
intelScreen->back.offset,
intelScreen->back.map,
intelScreen->cpp,
intelScreen->back.pitch / intelScreen->cpp,
intelScreen->back.size / intelScreen->back.pitch);
/* Still assuming front.cpp == depth.cpp
*/
intel->depth_region =
intel_region_create_static(intel,
BM_MEM_AGP,
intelScreen->depth.offset,
intelScreen->depth.map,
intelScreen->cpp,
intelScreen->depth.pitch / intelScreen->cpp,
intelScreen->depth.size / intelScreen->depth.pitch);
/* Advertise the full hardware capabilities. The new memory
* manager should cope much better with overload situations:
*/
ctx->Const.MaxTextureLevels = 11;
ctx->Const.Max3DTextureLevels = 8;
ctx->Const.MaxCubeTextureLevels = 11;
@ -142,15 +181,14 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
* validates programs against these, and in any case one ARB
* instruction can translate to more than one HW instruction, so
* we'll still have to check and fallback each time.
*/
*/
ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY;
ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */
ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT;
ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN;
ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN;
ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +
I915_MAX_TEX_INSN);
I915_MAX_TEX_INSN);
ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT;
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */

View file

@ -306,7 +306,6 @@ extern void i915_update_fog( GLcontext *ctx );
*/
extern void i915UpdateTextureState( intelContextPtr intel );
extern void i915InitTextureFuncs( struct dd_function_table *functions );
extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
/*======================================================================
* i915_metaops.c

View file

@ -47,9 +47,9 @@
#define DV_PF_565 (2<<8)
#define DV_PF_8888 (3<<8)
typedef struct intel_context intelContext;
struct intel_region;
typedef struct intel_context *intelContextPtr;
typedef struct intel_texture_object *intelTextureObjectPtr;
typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *,
intelVertex *);
@ -214,6 +214,11 @@ struct intel_context
char *verts; /* points to tnl->clipspace.vertex_buf */
struct intel_region *front_region;
struct intel_region *back_region;
struct intel_region *depth_region;
/* Fallback rasterization functions
*/
intel_point_func draw_point;

View file

@ -102,6 +102,47 @@ void intel_region_release( struct intel_context *intel,
}
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
GLuint size = cpp * pitch * height;
GLint pool;
_mesa_printf("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
/* Recipe for creating a static buffer - create a static pool with
* the right offset and size, generate a buffer and use a special
* call to bind it to all of the memory in that pool.
*/
pool = bmInitPool(intel->bm, offset, virtual, size,
(BM_MEM_AGP |
BM_NO_UPLOAD |
BM_NO_EVICT |
BM_NO_MOVE));
if (pool < 0) {
_mesa_printf("bmInitPool failed for static region\n");
exit(1);
}
bmGenBuffers(intel->bm, 1, &region->buffer);
bmBufferStatic(intel->bm, region->buffer, size, pool);
return region;
}
static void _mesa_copy_rect( GLubyte *dst,
GLuint cpp,
GLuint dst_pitch,
@ -243,11 +284,10 @@ void intel_region_copy( struct intel_context *intel,
assert(src->cpp == dst->cpp);
LOCK_HARDWARE(intel);
bmAddBuffer(intel->bm, list, dst->buffer, BM_WRITE, NULL, &dst_offset);
bmAddBuffer(intel->bm, list, src->buffer, BM_READ, NULL, &src_offset);
bmAddBuffer(list, dst->buffer, BM_WRITE, NULL, &dst_offset);
bmAddBuffer(list, src->buffer, BM_READ, NULL, &src_offset);
/* What I really want to do is query if both buffers are already
* uploaded:
/* Query if both buffers are already uploaded:
*/
if (bmValidateBufferList(intel->bm, list, BM_NO_EVICT|BM_NO_UPLOAD)) {
intelEmitCopyBlitLocked(intel,
@ -293,7 +333,7 @@ void intel_region_fill( struct intel_context *intel,
_mesa_printf("%s\n", __FUNCTION__);
LOCK_HARDWARE(intel);
bmAddBuffer(intel->bm, list, dst->buffer, BM_WRITE, NULL, &dst_offset);
bmAddBuffer(list, dst->buffer, BM_WRITE, NULL, &dst_offset);
if (bmValidateBufferList(intel->bm, list, BM_NO_EVICT)) {
intelEmitFillBlitLocked(intel,

View file

@ -61,6 +61,14 @@ void intel_region_release(struct intel_context *intel,
struct intel_region *ib );
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height );
/* Map/unmap regions. This is refcounted also:
*/
GLubyte *intel_region_map(struct intel_context *intel,

View file

@ -32,6 +32,9 @@
#include "dri_util.h"
#include "xmlconfig.h"
/* XXX: change name or eliminate to avoid conflict with "struct
* intel_region"!!!
*/
typedef struct {
drm_handle_t handle;
drmSize size; /* region size in bytes */

View file

@ -208,8 +208,7 @@ void intel_add_texoffset_fixup( struct intel_context *intel,
f->delta = (intel->intelScreen->tex.offset +
intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel));
#else
*ptr = (intelObj->textureOffset +
intel->intelScreen->tex.offset +
*ptr = (intelObj->textureOffset +
intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel));
#endif
}
@ -270,8 +269,7 @@ GLboolean intel_validate_buffers( struct intel_context *intel )
ok = intel_finalize_mipmap_tree( intel, i );
if (ok) {
bmAddBuffer(intel->bm,
intel->buffer_list,
bmAddBuffer(intel->buffer_list,
intelObj->mt->region->buffer,
BM_READ,
NULL,
@ -280,7 +278,7 @@ GLboolean intel_validate_buffers( struct intel_context *intel )
}
}
ok = bmValidateBufferList(intel->bm, intel->buffer_list, 0);
ok = bmValidateBufferList(intel->bm, intel->buffer_list, BM_MEM_AGP);
assert(ok);
return ok;
}