diff options
author | José Fonseca <[email protected]> | 2009-03-02 13:27:46 +0000 |
---|---|---|
committer | José Fonseca <[email protected]> | 2009-03-02 13:27:46 +0000 |
commit | 97a1fd158c9acfaa3a8deda7eb5bf0b253e85c15 (patch) | |
tree | 37e6c11507c1ef044aa8f0ee009136bb1d8b5bbc /src/gallium/drivers | |
parent | 60e5fe65067da76dea816535bec1e9073adc0ba7 (diff) | |
parent | b70f344e223fc10df8df08a6d82a813505225712 (diff) |
Merge commit 'origin/master' into gallium-map-range
Diffstat (limited to 'src/gallium/drivers')
66 files changed, 2177 insertions, 1183 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index ca03dc15111..5c3188e7f9d 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -127,15 +127,9 @@ struct cell_context struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; uint num_vertex_elements; - struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS]; - struct pipe_transfer *zsbuf_transfer; - ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS]; ubyte *zsbuf_map; - struct pipe_surface *tex_surf; - uint *tex_map; - uint dirty; uint dirty_textures; /* bitmask of texture units */ uint dirty_samplers; /* bitmask of sampler units */ diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c index 867b5dcaa09..32dbf5706c7 100644 --- a/src/gallium/drivers/cell/ppu/cell_fence.c +++ b/src/gallium/drivers/cell/ppu/cell_fence.c @@ -153,16 +153,12 @@ cell_add_fenced_textures(struct cell_context *cell) for (i = 0; i < cell->num_textures; i++) { struct cell_texture *ct = cell->texture[i]; if (ct) { - uint level; - for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) { - if (ct->tiled_buffer[level]) { #if 0 - printf("Adding texture %p buffer %p to list\n", - ct, ct->tiled_buffer[level]); + printf("Adding texture %p buffer %p to list\n", + ct, ct->tiled_buffer[level]); #endif - cell_add_buffer_to_list(cell, list, ct->tiled_buffer[level]); - } - } + if (ct->buffer) + cell_add_buffer_to_list(cell, list, ct->buffer); } } } diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index facd9551fe7..ccd0fef6e84 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -285,28 +285,22 @@ cell_map_surfaces(struct cell_context *cell) for (i = 0; i < 1; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps) { - cell->cbuf_transfer[i] = - screen->get_tex_transfer(screen, ps->texture, ps->face, - ps->level, ps->zslice, - PIPE_TRANSFER_READ_WRITE, - 0, 0, ps->width, ps->height); - - cell->cbuf_map[i] = - screen->transfer_map(screen, cell->cbuf_transfer[i]); + struct cell_texture *ct = cell_texture(ps->texture); + cell->cbuf_map[i] = screen->buffer_map(screen, + ct->buffer, + (PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE)); } } { struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps) { - cell->zsbuf_transfer = - screen->get_tex_transfer(screen, ps->texture, ps->face, - ps->level, ps->zslice, - PIPE_TRANSFER_READ_WRITE, - 0, 0, ps->width, ps->height); - - cell->zsbuf_map = - screen->transfer_map(screen, cell->zsbuf_transfer); + struct cell_texture *ct = cell_texture(ps->texture); + cell->zsbuf_map = screen->buffer_map(screen, + ct->buffer, + (PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE)); } } } @@ -322,24 +316,24 @@ cell_unmap_surfaces(struct cell_context *cell) uint i; for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - if (cell->cbuf_transfer[i] && cell->cbuf_map[i]) { - /* unmap color buffer/surface [i] */ - screen->transfer_unmap(screen, cell->cbuf_transfer[i]); - cell->cbuf_map[i] = NULL; + struct pipe_surface *ps = cell->framebuffer.cbufs[i]; + if (ps && cell->cbuf_map[i]) { + struct cell_texture *ct = cell_texture(ps->texture); + assert(ps->texture); + assert(ct->buffer); - /* get rid of transfer object [i] */ - screen->tex_transfer_release(screen, &cell->cbuf_transfer[i]); - assert(cell->cbuf_transfer[i] == NULL); + screen->buffer_unmap(screen, ct->buffer); + cell->cbuf_map[i] = NULL; } } - if (cell->zsbuf_transfer && cell->zsbuf_map) { - screen->transfer_unmap(screen, cell->zsbuf_transfer); - cell->zsbuf_map = NULL; - - /* get rid of transfer object */ - screen->tex_transfer_release(screen, &cell->zsbuf_transfer); - assert(cell->zsbuf_transfer == NULL); + { + struct pipe_surface *ps = cell->framebuffer.zsbuf; + if (ps && cell->zsbuf_map) { + struct cell_texture *ct = cell_texture(ps->texture); + screen->buffer_unmap(screen, ct->buffer); + cell->zsbuf_map = NULL; + } } } diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index ff529fe22cb..9479c0898fd 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -287,19 +287,23 @@ cell_emit_state(struct cell_context *cell) for (i = 0;i < CELL_MAX_SAMPLERS; i++) { if (cell->dirty_textures & (1 << i)) { STATIC_ASSERT(sizeof(struct cell_command_texture) % 16 == 0); - struct cell_command_texture *texture - = (struct cell_command_texture *)cell_batch_alloc16(cell, sizeof(*texture)); + struct cell_command_texture *texture = + (struct cell_command_texture *) + cell_batch_alloc16(cell, sizeof(*texture)); + texture->opcode[0] = CELL_CMD_STATE_TEXTURE; texture->unit = i; if (cell->texture[i]) { + struct cell_texture *ct = cell->texture[i]; uint level; for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) { - texture->start[level] = cell->texture[i]->tiled_mapped[level]; - texture->width[level] = cell->texture[i]->base.width[level]; - texture->height[level] = cell->texture[i]->base.height[level]; - texture->depth[level] = cell->texture[i]->base.depth[level]; + texture->start[level] = (ct->mapped + + ct->level_offset[level]); + texture->width[level] = ct->base.width[level]; + texture->height[level] = ct->base.height[level]; + texture->depth[level] = ct->base.depth[level]; } - texture->target = cell->texture[i]->base.target; + texture->target = ct->base.target; } else { uint level; diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index fa52e2cbea4..74724393f78 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -62,7 +62,7 @@ cell_texture_layout(struct cell_texture *ct) ct->buffer_size = 0; - for ( level = 0 ; level <= pt->last_level ; level++ ) { + for (level = 0; level <= pt->last_level; level++) { unsigned size; unsigned w_tile, h_tile; @@ -90,7 +90,7 @@ cell_texture_layout(struct cell_texture *ct) ct->buffer_size += size; - width = minify(width); + width = minify(width); height = minify(height); depth = minify(depth); } @@ -131,33 +131,19 @@ cell_texture_release(struct pipe_screen *screen, if (!*pt) return; - /* - DBG("%s %p refcount will be %d\n", - __FUNCTION__, (void *) *pt, (*pt)->refcount - 1); - */ if (--(*pt)->refcount <= 0) { /* Delete this texture now. * But note that the underlying pipe_buffer may linger... */ struct cell_texture *ct = cell_texture(*pt); - uint i; - /* - DBG("%s deleting %p\n", __FUNCTION__, (void *) ct); - */ + if (ct->mapped) { + pipe_buffer_unmap(screen, ct->buffer); + ct->mapped = NULL; + } pipe_buffer_reference(screen, &ct->buffer, NULL); - for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) { - /* Unreference the tiled image buffer. - * It may not actually be deleted until a fence is hit. - */ - if (ct->tiled_buffer[i]) { - ct->tiled_mapped[i] = NULL; - pipe_buffer_reference(screen, &ct->tiled_buffer[i], NULL); - } - } - FREE(ct); } *pt = NULL; @@ -294,107 +280,6 @@ untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst, } -/** - * Convert linear texture image data to tiled format for SPU usage. - */ -static void -cell_twiddle_texture(struct pipe_screen *screen, - struct pipe_surface *surface) -{ -#if 0 // XXX fix me - struct cell_texture *ct = cell_texture(surface->texture); - const uint level = surface->level; - const uint texWidth = ct->base.width[level]; - const uint texHeight = ct->base.height[level]; - const uint bufWidth = align(texWidth, TILE_SIZE); - const uint bufHeight = align(texHeight, TILE_SIZE); - const void *map = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_READ); - const uint *src = (const uint *) map; - - switch (ct->base.format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_S8Z24_UNORM: - { - int numFaces = ct->base.target == PIPE_TEXTURE_CUBE ? 6 : 1; - int offset = bufWidth * bufHeight * 4 * surface->face; - uint *dst; - - if (!ct->tiled_buffer[level]) { - /* allocate buffer for tiled data now */ - struct pipe_winsys *ws = screen->winsys; - uint bytes = bufWidth * bufHeight * 4 * numFaces; - ct->tiled_buffer[level] = - ws->buffer_create(ws, 16, PIPE_BUFFER_USAGE_PIXEL, bytes); - /* and map it */ - ct->tiled_mapped[level] = - ws->buffer_map(ws, ct->tiled_buffer[level], - PIPE_BUFFER_USAGE_GPU_READ); - } - dst = (uint *) ((ubyte *) ct->tiled_mapped[level] + offset); - - twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, - surface->stride, src); - } - break; - default: - printf("Cell: twiddle unsupported texture format %s\n", - pf_name(ct->base.format)); - } - - screen->surface_unmap(screen, surface); -#endif -} - - -/** - * Convert SPU tiled texture image data to linear format for app usage. - */ -static void -cell_untwiddle_texture(struct pipe_screen *screen, - struct pipe_surface *surface) -{ -#if 0 // XXX fix me - struct cell_texture *ct = cell_texture(surface->texture); - const uint level = surface->level; - const uint texWidth = ct->base.width[level]; - const uint texHeight = ct->base.height[level]; - const void *map = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_READ); - const uint *src = (const uint *) ((const ubyte *) map + surface->offset); - - switch (ct->base.format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_S8Z24_UNORM: - { - int numFaces = ct->base.target == PIPE_TEXTURE_CUBE ? 6 : 1; - int offset = surface->stride * texHeight * 4 * surface->face; - uint *dst; - - if (!ct->untiled_data[level]) { - ct->untiled_data[level] = - align_malloc(surface->stride * texHeight * 4 * numFaces, 16); - } - - dst = (uint *) ((ubyte *) ct->untiled_data[level] + offset); - - untwiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, - surface->stride, src); - } - break; - default: - { - ct->untiled_data[level] = NULL; - printf("Cell: untwiddle unsupported texture format %s\n", - pf_name(ct->base.format)); - } - } - - screen->surface_unmap(screen, surface); -#endif -} - - static struct pipe_surface * cell_get_tex_surface(struct pipe_screen *screen, struct pipe_texture *pt, @@ -409,38 +294,25 @@ cell_get_tex_surface(struct pipe_screen *screen, ps->refcount = 1; pipe_texture_reference(&ps->texture, pt); ps->format = pt->format; - //ps->block = pt->block; ps->width = pt->width[level]; ps->height = pt->height[level]; - //ps->nblocksx = pt->nblocksx[level]; - //ps->nblocksy = pt->nblocksy[level]; - //ps->stride = ct->stride[level]; ps->offset = ct->level_offset[level]; - ps->usage = usage; - /* XXX may need to override usage flags (see sp_texture.c) */ - - pipe_texture_reference(&ps->texture, pt); + ps->usage = usage; ps->face = face; ps->level = level; ps->zslice = zslice; - if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) { -#if 0 // XXX fix me - ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) * - ps->nblocksy * - ps->stride; -#endif + if (pt->target == PIPE_TEXTURE_CUBE) { + ps->offset += face * pt->nblocksy[level] * ct->stride[level]; + } + else if (pt->target == PIPE_TEXTURE_3D) { + ps->offset += zslice * pt->nblocksy[level] * ct->stride[level]; } else { assert(face == 0); assert(zslice == 0); } - - if (ps->usage & PIPE_BUFFER_USAGE_CPU_READ) { - /* convert from tiled to linear layout */ - cell_untwiddle_texture(screen, ps); - } } return ps; } @@ -450,24 +322,8 @@ static void cell_tex_surface_release(struct pipe_screen *screen, struct pipe_surface **s) { - struct cell_texture *ct = cell_texture((*s)->texture); - const uint level = (*s)->level; struct pipe_surface *surf = *s; - if ((surf->usage & PIPE_BUFFER_USAGE_CPU_READ) && (ct->untiled_data[level])) - { - align_free(ct->untiled_data[level]); - ct->untiled_data[level] = NULL; - } - - if ((ct->base.tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) && - (surf->usage & PIPE_BUFFER_USAGE_CPU_WRITE)) { - /* convert from linear to tiled layout */ - cell_twiddle_texture(screen, surf); - } - - /* XXX if done rendering to teximage, re-tile */ - if (--surf->refcount == 0) { pipe_texture_reference(&surf->texture, NULL); FREE(surf); @@ -476,6 +332,11 @@ cell_tex_surface_release(struct pipe_screen *screen, } +/** + * Create new pipe_transfer object. + * This is used by the user to put tex data into a texture (and get it + * back out for glGetTexImage). + */ static struct pipe_transfer * cell_get_tex_transfer(struct pipe_screen *screen, struct pipe_texture *texture, @@ -485,14 +346,13 @@ cell_get_tex_transfer(struct pipe_screen *screen, { struct cell_texture *ct = cell_texture(texture); struct cell_transfer *ctrans; - struct pipe_transfer *pt; assert(texture); assert(level <= texture->last_level); ctrans = CALLOC_STRUCT(cell_transfer); - pt = &ctrans->base; if (ctrans) { + struct pipe_transfer *pt = &ctrans->base; pt->refcount = 1; pipe_texture_reference(&pt->texture, texture); pt->format = texture->format; @@ -504,23 +364,26 @@ cell_get_tex_transfer(struct pipe_screen *screen, pt->nblocksx = texture->nblocksx[level]; pt->nblocksy = texture->nblocksy[level]; pt->stride = ct->stride[level]; - ctrans->offset = ct->level_offset[level]; pt->usage = usage; pt->face = face; pt->level = level; pt->zslice = zslice; - if (texture->target == PIPE_TEXTURE_CUBE || - texture->target == PIPE_TEXTURE_3D) { - ctrans->offset += ((texture->target == PIPE_TEXTURE_CUBE) ? face : - zslice) * pt->nblocksy * pt->stride; + ctrans->offset = ct->level_offset[level]; + + if (texture->target == PIPE_TEXTURE_CUBE) { + ctrans->offset += face * pt->nblocksy * pt->stride; + } + else if (texture->target == PIPE_TEXTURE_3D) { + ctrans->offset += zslice * pt->nblocksy * pt->stride; } else { assert(face == 0); assert(zslice == 0); } + return pt; } - return pt; + return NULL; } @@ -542,16 +405,23 @@ cell_tex_transfer_release(struct pipe_screen *screen, } +/** + * Return pointer to texture image data in linear layout. + */ static void * -cell_transfer_map( struct pipe_screen *screen, - struct pipe_transfer *transfer ) +cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) { - ubyte *map; - struct cell_texture *spt; - unsigned flags = 0; + struct cell_transfer *ctrans = cell_transfer(transfer); + struct pipe_texture *pt = transfer->texture; + struct cell_texture *ct = cell_texture(pt); + const uint level = ctrans->base.level; + const uint texWidth = pt->width[level]; + const uint texHeight = pt->height[level]; + const uint stride = ct->stride[level]; + unsigned flags = 0x0; + unsigned size; assert(transfer->texture); - spt = cell_texture(transfer->texture); if (transfer->usage != PIPE_TRANSFER_READ) { flags |= PIPE_BUFFER_USAGE_CPU_WRITE; @@ -561,89 +431,82 @@ cell_transfer_map( struct pipe_screen *screen, flags |= PIPE_BUFFER_USAGE_CPU_READ; } - map = pipe_buffer_map(screen, spt->buffer, flags); - if (map == NULL) - return NULL; + if (!ct->mapped) { + /* map now */ + ct->mapped = pipe_buffer_map(screen, ct->buffer, flags); + } - /* May want to different things here depending on read/write nature - * of the map: + /* + * Create a buffer of ordinary memory for the linear texture. + * This is the memory that the user will read/write. */ - if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ) - { - /* Do something to notify sharing contexts of a texture change. - * In cell, that would mean flushing the texture cache. - */ -#if 00 - cell_screen(screen)->timestamp++; -#endif + size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size; + + ctrans->map = align_malloc(size, 16); + if (!ctrans->map) + return NULL; /* out of memory */ + + if (transfer->usage & PIPE_TRANSFER_READ) { + /* need to untwiddle the texture to make a linear version */ + const uint bpp = pf_get_size(ct->base.format); + if (bpp == 4) { + const uint *src = (uint *) (ct->mapped + ctrans->offset); + uint *dst = ctrans->map; + untwiddle_image_uint(texWidth, texHeight, TILE_SIZE, + dst, stride, src); + } + else { + // xxx fix + } } - - return map + cell_transfer(transfer)->offset + - transfer->y / transfer->block.height * transfer->stride + - transfer->x / transfer->block.width * transfer->block.size; + + return ctrans->map; } +/** + * Called when user is done reading/writing texture data. + * If new data was written, this is where we convert the linear data + * to tiled data. + */ static void cell_transfer_unmap(struct pipe_screen *screen, - struct pipe_transfer *transfer) + struct pipe_transfer *transfer) { - struct cell_texture *spt; - - assert(transfer->texture); - spt = cell_texture(transfer->texture); - - pipe_buffer_unmap( screen, spt->buffer ); -} - - -static void * -cell_surface_map(struct pipe_screen *screen, - struct pipe_surface *surface, - unsigned flags) -{ - ubyte *map; - struct cell_texture *ct = cell_texture(surface->texture); - const uint level = surface->level; - - assert(ct); - -#if 0 - if (flags & ~surface->usage) { - assert(0); - return NULL; + struct cell_transfer *ctrans = cell_transfer(transfer); + struct pipe_texture *pt = transfer->texture; + struct cell_texture *ct = cell_texture(pt); + const uint level = ctrans->base.level; + const uint texWidth = pt->width[level]; + const uint texHeight = pt->height[level]; + const uint stride = ct->stride[level]; + + if (!ct->mapped) { + /* map now */ + ct->mapped = pipe_buffer_map(screen, ct->buffer, + PIPE_BUFFER_USAGE_CPU_READ); } -#endif - map = pipe_buffer_map( screen, ct->buffer, flags ); - if (map == NULL) { - return NULL; - } - else { - if ((surface->usage & PIPE_BUFFER_USAGE_CPU_READ) && - (ct->untiled_data[level])) { - return (void *) ((ubyte *) ct->untiled_data[level] + surface->offset); + if (transfer->usage & PIPE_TRANSFER_WRITE) { + /* The user wrote new texture data into the mapped buffer. + * We need to convert the new linear data into the twiddled/tiled format. + */ + const uint bpp = pf_get_size(ct->base.format); + if (bpp == 4) { + const uint *src = ctrans->map; + uint *dst = (uint *) (ct->mapped + ctrans->offset); + twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src); } else { - return (void *) (map + surface->offset); + // xxx fix } } -} - - -static void -cell_surface_unmap(struct pipe_screen *screen, - struct pipe_surface *surface) -{ - struct cell_texture *ct = cell_texture(surface->texture); - - assert(ct); - pipe_buffer_unmap( screen, ct->buffer ); + align_free(ctrans->map); + ctrans->map = NULL; } - void cell_init_screen_texture_funcs(struct pipe_screen *screen) { @@ -655,6 +518,7 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen) screen->get_tex_transfer = cell_get_tex_transfer; screen->tex_transfer_release = cell_tex_transfer_release; + screen->transfer_map = cell_transfer_map; screen->transfer_unmap = cell_transfer_unmap; } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index fc6486adbe6..3ffc0bfdb51 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -43,20 +43,14 @@ struct cell_texture unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS]; unsigned long stride[CELL_MAX_TEXTURE_LEVELS]; - /* The data is held here: - */ + /** The tiled texture data is held in this buffer */ struct pipe_buffer *buffer; unsigned long buffer_size; - /** Texture data in tiled layout is held here */ - struct pipe_buffer *tiled_buffer[CELL_MAX_TEXTURE_LEVELS]; - /** Mapped, tiled texture data */ - void *tiled_mapped[CELL_MAX_TEXTURE_LEVELS]; - - struct pipe_transfer *transfer; - - /** The original, linear texture data */ - void *untiled_data[CELL_MAX_TEXTURE_LEVELS]; + /** The buffer above, mapped. This is the memory from which the + * SPUs will fetch texels. This texture data is in the tiled layout. + */ + ubyte *mapped; }; @@ -65,6 +59,7 @@ struct cell_transfer struct pipe_transfer base; unsigned long offset; + void *map; }; diff --git a/src/gallium/drivers/i915simple/i915_screen.c b/src/gallium/drivers/i915simple/i915_screen.c index b7bd3b3b748..49471287a2e 100644 --- a/src/gallium/drivers/i915simple/i915_screen.c +++ b/src/gallium/drivers/i915simple/i915_screen.c @@ -36,6 +36,7 @@ #include "i915_context.h" #include "i915_screen.h" #include "i915_texture.h" +#include "i915_winsys.h" static const char * diff --git a/src/gallium/drivers/i915simple/i915_screen.h b/src/gallium/drivers/i915simple/i915_screen.h index a371663453c..5284c325951 100644 --- a/src/gallium/drivers/i915simple/i915_screen.h +++ b/src/gallium/drivers/i915simple/i915_screen.h @@ -75,10 +75,6 @@ i915_transfer( struct pipe_transfer *transfer ) } -extern struct pipe_screen * -i915_create_screen(struct pipe_winsys *winsys, uint pci_id); - - #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/i915simple/i915_state_emit.c b/src/gallium/drivers/i915simple/i915_state_emit.c index 26e03f5127f..1e1fb968b47 100644 --- a/src/gallium/drivers/i915simple/i915_state_emit.c +++ b/src/gallium/drivers/i915simple/i915_state_emit.c @@ -214,7 +214,6 @@ i915_emit_hardware_state(struct i915_context *i915 ) unsigned ctile = BUF_3D_USE_FENCE; struct i915_texture *tex = (struct i915_texture *) cbuf_surface->texture; - struct pipe_buffer *buffer = tex->buffer; assert(tex); if (tex && tex->tiled) { @@ -238,7 +237,6 @@ i915_emit_hardware_state(struct i915_context *i915 ) unsigned ztile = BUF_3D_USE_FENCE; struct i915_texture *tex = (struct i915_texture *) depth_surface->texture; - struct pipe_buffer *buffer = tex->buffer; assert(tex); if (tex && tex->tiled) { diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c index 957726523fa..6aead3e75e9 100644 --- a/src/gallium/drivers/i915simple/i915_texture.c +++ b/src/gallium/drivers/i915simple/i915_texture.c @@ -42,6 +42,7 @@ #include "i915_texture.h" #include "i915_debug.h" #include "i915_screen.h" +#include "i915_winsys.h" /* * Helper function and arrays @@ -765,3 +766,20 @@ i915_init_screen_texture_functions(struct pipe_screen *screen) screen->texture_blanket = i915_texture_blanket; screen->tex_surface_release = i915_tex_surface_release; } + +boolean i915_get_texture_buffer( struct pipe_texture *texture, + struct pipe_buffer **buf, + unsigned *stride ) +{ + struct i915_texture *tex = (struct i915_texture *)texture; + + if (!tex) + return FALSE; + + pipe_buffer_reference(texture->screen, buf, tex->buffer); + + if (stride) + *stride = tex->stride; + + return TRUE; +} diff --git a/src/gallium/drivers/i915simple/i915_winsys.h b/src/gallium/drivers/i915simple/i915_winsys.h index 81904c2a742..ff5b34f193a 100644 --- a/src/gallium/drivers/i915simple/i915_winsys.h +++ b/src/gallium/drivers/i915simple/i915_winsys.h @@ -30,7 +30,8 @@ * This is the interface that i915simple requires any window system * hosting it to implement. This is the only include file in i915simple * which is public. - * + * + * This isn't currently true as the winsys needs i915_batchbuffer.h */ #ifndef I915_WINSYS_H @@ -45,10 +46,9 @@ extern "C" { #endif -/* Pipe drivers are (meant to be!) independent of both GL and the - * window system. The window system provides a buffer manager and a - * set of additional hooks for things like command buffer submission, - * etc. +/* Pipe drivers are independent of both GL and the window system. + * The window system provides a buffer manager and a set of additional + * hooks for things like command buffer submission, etc. * * There clearly has to be some agreement between the window system * driver and the hardware driver about the format of command buffers, @@ -56,6 +56,7 @@ extern "C" { */ struct i915_batchbuffer; +struct pipe_texture; struct pipe_buffer; struct pipe_fence_handle; struct pipe_winsys; @@ -64,7 +65,7 @@ struct pipe_screen; /** * Additional winsys interface for i915simple. - * + * * It is an over-simple batchbuffer mechanism. Will want to improve the * performance of this, perhaps based on the cmdstream stuff. It * would be pretty impossible to implement swz on top of this @@ -110,12 +111,33 @@ struct i915_winsys { #define I915_BUFFER_USAGE_LIT_VERTEX (PIPE_BUFFER_USAGE_CUSTOM << 0) -struct pipe_context *i915_create_context( struct pipe_screen *, - struct pipe_winsys *, - struct i915_winsys * ); +/** + * Create i915 pipe_screen. + */ +struct pipe_screen *i915_create_screen( struct pipe_winsys *winsys, + uint pci_id ); + +/** + * Create a i915 pipe_context. + */ +struct pipe_context *i915_create_context( struct pipe_screen *screen, + struct pipe_winsys *winsys, + struct i915_winsys *i915 ); + +/** + * Used for the winsys to get the buffer used for a texture + * and also the stride used for the texture. + * + * Buffer is referenced for you so you need to unref after use. + * + * This is needed for example kms. + */ +boolean i915_get_texture_buffer( struct pipe_texture *texture, + struct pipe_buffer **buf, + unsigned *stride ); #ifdef __cplusplus } #endif -#endif +#endif diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile index cf9deea8519..7c14bacb1de 100644 --- a/src/gallium/drivers/nv04/Makefile +++ b/src/gallium/drivers/nv04/Makefile @@ -15,6 +15,7 @@ C_SOURCES = \ nv04_state.c \ nv04_state_emit.c \ nv04_surface.c \ + nv04_transfer.c \ nv04_vbo.c include ../../Makefile.template diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c index 993c5ef5dd2..9acd613e2e4 100644 --- a/src/gallium/drivers/nv04/nv04_miptree.c +++ b/src/gallium/drivers/nv04/nv04_miptree.c @@ -50,8 +50,6 @@ nv04_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) mt->base = *pt; mt->base.refcount = 1; mt->base.screen = pscreen; - mt->shadow_tex = NULL; - mt->shadow_surface = NULL; //mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; @@ -111,12 +109,6 @@ nv04_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) FREE(mt->level[l].image_offset); } - if (mt->shadow_tex) { - assert(mt->shadow_surface); - pscreen->tex_surface_release(pscreen, &mt->shadow_surface); - nv04_miptree_release(pscreen, &mt->shadow_tex); - } - FREE(mt); } @@ -126,29 +118,26 @@ nv04_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned flags) { struct nv04_miptree *nv04mt = (struct nv04_miptree *)pt; - struct pipe_surface *ps; + struct nv04_surface *ns; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) return NULL; - pipe_texture_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = pt->width[level]; - ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = nv04mt->level[level].pitch; - ps->usage = flags; - ps->status = PIPE_SURFACE_STATUS_DEFINED; - ps->refcount = 1; - ps->face = face; - ps->level = level; - ps->zslice = zslice; - - ps->offset = nv04mt->level[level].image_offset; - - return ps; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + ns->base.status = PIPE_SURFACE_STATUS_DEFINED; + ns->base.refcount = 1; + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = nv04mt->level[level].pitch; + + ns->base.offset = nv04mt->level[level].image_offset; + + return &ns->base; } static void diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c index 9ef38bc244c..f9f6d974264 100644 --- a/src/gallium/drivers/nv04/nv04_screen.c +++ b/src/gallium/drivers/nv04/nv04_screen.c @@ -119,28 +119,6 @@ nv04_screen_is_format_supported(struct pipe_screen *screen, return FALSE; } -static void * -nv04_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - void *map; - struct nv04_miptree *nv04mt = (struct nv04_miptree *)surface->texture; - - map = pipe_buffer_map(screen, nv04mt->buffer, flags); - if (!map) - return NULL; - - return map + surface->offset; -} - -static void -nv04_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) -{ - struct nv04_miptree *nv04mt = (struct nv04_miptree *)surface->texture; - - pipe_buffer_unmap(screen, nv04mt->buffer); -} - static void nv04_screen_destroy(struct pipe_screen *pscreen) { @@ -226,10 +204,8 @@ nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv04_screen_is_format_supported; - screen->pipe.surface_map = nv04_surface_map; - screen->pipe.surface_unmap = nv04_surface_unmap; - nv04_screen_init_miptree_functions(&screen->pipe); + nv04_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h index 540aec907bf..ee6fb6db44a 100644 --- a/src/gallium/drivers/nv04/nv04_screen.h +++ b/src/gallium/drivers/nv04/nv04_screen.h @@ -24,4 +24,7 @@ nv04_screen(struct pipe_screen *screen) return (struct nv04_screen *)screen; } +void +nv04_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h index 15d4685ec1a..0d51439e3ff 100644 --- a/src/gallium/drivers/nv04/nv04_state.h +++ b/src/gallium/drivers/nv04/nv04_state.h @@ -35,9 +35,6 @@ struct nv04_miptree { struct pipe_buffer *buffer; uint total_size; - struct pipe_texture *shadow_tex; - struct pipe_surface *shadow_surface; - struct { uint pitch; uint image_offset; diff --git a/src/gallium/drivers/nv04/nv04_state_emit.c b/src/gallium/drivers/nv04/nv04_state_emit.c index bd8ef1adbff..eb2c1c57c67 100644 --- a/src/gallium/drivers/nv04/nv04_state_emit.c +++ b/src/gallium/drivers/nv04/nv04_state_emit.c @@ -93,7 +93,7 @@ static void nv04_emit_sampler(struct nv04_context *nv04, int unit) static void nv04_state_emit_framebuffer(struct nv04_context* nv04) { struct pipe_framebuffer_state* fb = nv04->framebuffer; - struct pipe_surface *rt, *zeta; + struct nv04_surface *rt, *zeta; uint32_t rt_format, w, h; int colour_format = 0, zeta_format = 0; struct nv04_miptree *nv04mt = 0; @@ -101,7 +101,7 @@ static void nv04_state_emit_framebuffer(struct nv04_context* nv04) w = fb->cbufs[0]->width; h = fb->cbufs[0]->height; colour_format = fb->cbufs[0]->format; - rt = fb->cbufs[0]; + rt = (struct nv04_surface *)fb->cbufs[0]; if (fb->zsbuf) { if (colour_format) { @@ -113,7 +113,7 @@ static void nv04_state_emit_framebuffer(struct nv04_context* nv04) } zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } switch (colour_format) { @@ -131,13 +131,13 @@ static void nv04_state_emit_framebuffer(struct nv04_context* nv04) BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1); OUT_RING(rt_format); - nv04mt = (struct nv04_miptree *)rt->texture; + nv04mt = (struct nv04_miptree *)rt->base.texture; /* FIXME pitches have to be aligned ! */ BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2); - OUT_RING(rt->stride|(zeta->stride<<16)); + OUT_RING(rt->pitch|(zeta->pitch<<16)); OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); if (fb->zsbuf) { - nv04mt = (struct nv04_miptree *)zeta->texture; + nv04mt = (struct nv04_miptree *)zeta->base.texture; BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); } @@ -202,8 +202,11 @@ nv04_emit_hw_state(struct nv04_context *nv04) */ /* Render target */ + unsigned rt_pitch = ((struct nv04_surface *)nv04->rt)->pitch; + unsigned zeta_pitch = ((struct nv04_surface *)nv04->zeta)->pitch; + BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2); - OUT_RING(nv04->rt->stride|(nv04->zeta->stride<<16)); + OUT_RING(rt_pitch|(zeta_pitch<<16)); OUT_RELOCl(nv04->rt, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); if (nv04->zeta) { BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c index 230cfd17dd9..e8fd3166ab8 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.c +++ b/src/gallium/drivers/nv04/nv04_surface_2d.c @@ -101,6 +101,7 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, struct nouveau_grobj *sifm = ctx->sifm; struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + const unsigned src_pitch = ((struct nv04_surface *)src)->pitch; const unsigned max_w = 1024; const unsigned max_h = 1024; const unsigned sub_w = w > max_w ? max_w : w; @@ -110,6 +111,8 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, /* POT or GTFO */ assert(!(w & (w - 1)) && !(h & (h - 1))); + /* That's the way she likes it */ + assert(src_pitch == ((struct nv04_surface *)dst)->pitch); BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1); OUT_RELOCo(chan, dst_bo, @@ -130,7 +133,7 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, for (cx = 0; cx < w; cx += sub_w) { BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1); OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx, cy) * - dst->block.size, NOUVEAU_BO_GART | + dst->texture->block.size, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9); @@ -146,11 +149,11 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4); OUT_RING (chan, sub_h << 16 | sub_w); - OUT_RING (chan, src->stride | + OUT_RING (chan, src_pitch | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); - OUT_RELOCl(chan, src_bo, src->offset + cy * src->stride + - cx * src->block.size, NOUVEAU_BO_GART | + OUT_RELOCl(chan, src_bo, src->offset + cy * src_pitch + + cx * src->texture->block.size, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); OUT_RING (chan, 0); } @@ -168,10 +171,12 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, struct nouveau_grobj *m2mf = ctx->m2mf; struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); - unsigned dst_offset, src_offset; - - dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size); - src_offset = src->offset + (sy * src->stride) + (sx * src->block.size); + unsigned src_pitch = ((struct nv04_surface *)src)->pitch; + unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; + unsigned dst_offset = dst->offset + dy * dst_pitch + + dx * dst->texture->block.size; + unsigned src_offset = src->offset + sy * src_pitch + + sx * src->texture->block.size; WAIT_RING (chan, 3 + ((h / 2047) + 1) * 9); BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); @@ -188,16 +193,16 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); OUT_RELOCl(chan, dst_bo, dst_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR); - OUT_RING (chan, src->stride); - OUT_RING (chan, dst->stride); - OUT_RING (chan, w * src->block.size); + OUT_RING (chan, src_pitch); + OUT_RING (chan, dst_pitch); + OUT_RING (chan, w * src->texture->block.size); OUT_RING (chan, count); OUT_RING (chan, 0x0101); OUT_RING (chan, 0); h -= count; - src_offset += src->stride * count; - dst_offset += dst->stride * count; + src_offset += src_pitch * count; + dst_offset += dst_pitch * count; } return 0; @@ -213,6 +218,8 @@ nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst, struct nouveau_grobj *blit = ctx->blit; struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + unsigned src_pitch = ((struct nv04_surface *)src)->pitch; + unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int format; format = nv04_surface_format(dst->format); @@ -225,7 +232,7 @@ nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst, OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4); OUT_RING (chan, format); - OUT_RING (chan, (dst->stride << 16) | src->stride); + OUT_RING (chan, (dst_pitch << 16) | src_pitch); OUT_RELOCl(chan, src_bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); @@ -242,6 +249,8 @@ nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst, int dx, int dy, struct pipe_surface *src, int sx, int sy, int w, int h) { + unsigned src_pitch = ((struct nv04_surface *)src)->pitch; + unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int src_linear = src->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR; int dst_linear = dst->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR; @@ -257,7 +266,8 @@ nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst, * to NV_MEMORY_TO_MEMORY_FORMAT in this case. */ if ((src->offset & 63) || (dst->offset & 63) || - (src->stride & 63) || (dst->stride & 63)) { + (src_pitch & 63) || (dst_pitch & 63) || + debug_get_bool_option("NOUVEAU_NO_COPYBLIT", FALSE)) { nv04_surface_copy_m2mf(ctx, dst, dx, dy, src, sx, sy, w, h); return; } @@ -273,6 +283,7 @@ nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst, struct nouveau_grobj *surf2d = ctx->surf2d; struct nouveau_grobj *rect = ctx->rect; struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int cs2d_format, gdirect_format; cs2d_format = nv04_surface_format(dst->format); @@ -287,7 +298,7 @@ nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst, OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4); OUT_RING (chan, cs2d_format); - OUT_RING (chan, (dst->stride << 16) | dst->stride); + OUT_RING (chan, (dst_pitch << 16) | dst_pitch); OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nv04/nv04_surface_2d.h index 21b8f869606..82ce7189c8b 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.h +++ b/src/gallium/drivers/nv04/nv04_surface_2d.h @@ -1,6 +1,11 @@ #ifndef __NV04_SURFACE_2D_H__ #define __NV04_SURFACE_2D_H__ +struct nv04_surface { + struct pipe_surface base; + unsigned pitch; +}; + struct nv04_surface_2d { struct nouveau_winsys *nvws; struct nouveau_notifier *ntfy; diff --git a/src/gallium/drivers/nv04/nv04_transfer.c b/src/gallium/drivers/nv04/nv04_transfer.c new file mode 100644 index 00000000000..314d2045f76 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_transfer.c @@ -0,0 +1,201 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv04_context.h" +#include "nv04_screen.h" +#include "nv04_state.h" + +struct nv04_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv04_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv04_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->compressed = pt->compressed; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv04_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv04_miptree *mt = (struct nv04_miptree *)pt; + struct nv04_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv04_transfer); + if (!tx) + return NULL; + + tx->base.refcount = 1; + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + nv04_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv04_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv04_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv04_screen *nvscreen = nv04_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv04_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv04_transfer *tx = (struct nv04_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv04_screen *nvscreen = nv04_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + *pptx = NULL; + if (--ptx->refcount) + return; + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv04_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv04_transfer *tx = (struct nv04_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv04_miptree *mt = (struct nv04_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv04_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv04_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv04_transfer *tx = (struct nv04_transfer *)ptx; + struct nv04_miptree *mt = (struct nv04_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv04_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv04_transfer_new; + pscreen->tex_transfer_release = nv04_transfer_del; + pscreen->transfer_map = nv04_transfer_map; + pscreen->transfer_unmap = nv04_transfer_unmap; +} diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile index 2b5fbd4f5a6..62677f5194a 100644 --- a/src/gallium/drivers/nv10/Makefile +++ b/src/gallium/drivers/nv10/Makefile @@ -14,6 +14,7 @@ C_SOURCES = \ nv10_state.c \ nv10_state_emit.c \ nv10_surface.c \ + nv10_transfer.c \ nv10_vbo.c include ../../Makefile.template diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c index 96161354617..4747868a508 100644 --- a/src/gallium/drivers/nv10/nv10_miptree.c +++ b/src/gallium/drivers/nv10/nv10_miptree.c @@ -131,30 +131,31 @@ nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { - struct pipe_winsys *ws = screen->winsys; struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; - struct pipe_surface *ps; + struct nv04_surface *ns; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) return NULL; - pipe_texture_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = pt->width[level]; - ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = nv10mt->level[level].pitch; - ps->refcount = 1; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + ns->base.status = PIPE_SURFACE_STATUS_DEFINED; + ns->base.refcount = 1; + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = nv10mt->level[level].pitch; if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset = nv10mt->level[level].image_offset[face]; + ns->base.offset = nv10mt->level[level].image_offset[face]; } else { - ps->offset = nv10mt->level[level].image_offset[0]; + ns->base.offset = nv10mt->level[level].image_offset[0]; } - return ps; + return &ns->base; } static void diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index f417b06c944..6532a93c7ba 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -116,30 +116,6 @@ nv10_screen_is_format_supported(struct pipe_screen *screen, return FALSE; } -static void * -nv10_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - struct pipe_winsys *ws = screen->winsys; - void *map; - struct nv10_miptree *nv10mt = (struct nv10_miptree *)surface->texture; - - map = ws->buffer_map(ws, nv10mt->buffer, flags); - if (!map) - return NULL; - - return map + surface->offset; -} - -static void -nv10_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) -{ - struct pipe_winsys *ws = screen->winsys; - struct nv10_miptree *nv10mt = (struct nv10_miptree *)surface->texture; - - ws->buffer_unmap(ws, nv10mt->buffer); -} - static void nv10_screen_destroy(struct pipe_screen *pscreen) { @@ -215,10 +191,8 @@ nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv10_screen_is_format_supported; - screen->pipe.surface_map = nv10_surface_map; - screen->pipe.surface_unmap = nv10_surface_unmap; - nv10_screen_init_miptree_functions(&screen->pipe); + nv10_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h index 60102a369a9..ad829ee3fd4 100644 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -21,4 +21,8 @@ nv10_screen(struct pipe_screen *screen) return (struct nv10_screen *)screen; } + +void +nv10_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c index 5dec618b933..d8691ef9c67 100644 --- a/src/gallium/drivers/nv10/nv10_state_emit.c +++ b/src/gallium/drivers/nv10/nv10_state_emit.c @@ -103,7 +103,7 @@ static void nv10_state_emit_scissor(struct nv10_context* nv10) static void nv10_state_emit_framebuffer(struct nv10_context* nv10) { struct pipe_framebuffer_state* fb = nv10->framebuffer; - struct pipe_surface *rt, *zeta = NULL; + struct nv04_surface *rt, *zeta = NULL; uint32_t rt_format, w, h; int colour_format = 0, zeta_format = 0; struct nv10_miptree *nv10mt = 0; @@ -111,7 +111,7 @@ static void nv10_state_emit_framebuffer(struct nv10_context* nv10) w = fb->cbufs[0]->width; h = fb->cbufs[0]->height; colour_format = fb->cbufs[0]->format; - rt = fb->cbufs[0]; + rt = (struct nv04_surface *)fb->cbufs[0]; if (fb->zsbuf) { if (colour_format) { @@ -123,7 +123,7 @@ static void nv10_state_emit_framebuffer(struct nv10_context* nv10) } zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR; @@ -142,18 +142,18 @@ static void nv10_state_emit_framebuffer(struct nv10_context* nv10) if (zeta) { BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); - OUT_RING (rt->stride | (zeta->stride << 16)); + OUT_RING (rt->pitch | (zeta->pitch << 16)); } else { BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); - OUT_RING (rt->stride | (rt->stride << 16)); + OUT_RING (rt->pitch | (rt->pitch << 16)); } - nv10mt = (struct nv10_miptree *)rt->texture; + nv10mt = (struct nv10_miptree *)rt->base.texture; nv10->rt[0] = nv10mt->buffer; if (zeta_format) { - nv10mt = (struct nv10_miptree *)zeta->texture; + nv10mt = (struct nv10_miptree *)zeta->base.texture; nv10->zeta = nv10mt->buffer; } diff --git a/src/gallium/drivers/nv10/nv10_transfer.c b/src/gallium/drivers/nv10/nv10_transfer.c new file mode 100644 index 00000000000..967e2cc20ce --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_transfer.c @@ -0,0 +1,201 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv10_context.h" +#include "nv10_screen.h" +#include "nv10_state.h" + +struct nv10_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv10_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv10_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->compressed = pt->compressed; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv10_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv10_miptree *mt = (struct nv10_miptree *)pt; + struct nv10_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv10_transfer); + if (!tx) + return NULL; + + tx->base.refcount = 1; + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + nv10_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv10_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv10_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv10_screen *nvscreen = nv10_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv10_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv10_screen *nvscreen = nv10_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + *pptx = NULL; + if (--ptx->refcount) + return; + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv10_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv10_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv10_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv10_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv10_transfer_new; + pscreen->tex_transfer_release = nv10_transfer_del; + pscreen->transfer_map = nv10_transfer_map; + pscreen->transfer_unmap = nv10_transfer_unmap; +} diff --git a/src/gallium/drivers/nv20/Makefile b/src/gallium/drivers/nv20/Makefile index 93e34f8e92a..1305f26c591 100644 --- a/src/gallium/drivers/nv20/Makefile +++ b/src/gallium/drivers/nv20/Makefile @@ -14,6 +14,7 @@ C_SOURCES = \ nv20_state.c \ nv20_state_emit.c \ nv20_surface.c \ + nv20_transfer.c \ nv20_vbo.c # nv20_vertprog.c diff --git a/src/gallium/drivers/nv20/nv20_miptree.c b/src/gallium/drivers/nv20/nv20_miptree.c index ef7e9c5428e..29462408970 100644 --- a/src/gallium/drivers/nv20/nv20_miptree.c +++ b/src/gallium/drivers/nv20/nv20_miptree.c @@ -9,10 +9,14 @@ static void nv20_miptree_layout(struct nv20_miptree *nv20mt) { struct pipe_texture *pt = &nv20mt->base; - boolean swizzled = FALSE; uint width = pt->width[0], height = pt->height[0]; uint offset = 0; int nr_faces, l, f; + uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER | + PIPE_TEXTURE_USAGE_DEPTH_STENCIL | + PIPE_TEXTURE_USAGE_RENDER_TARGET | + PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_PRIMARY); if (pt->target == PIPE_TEXTURE_CUBE) { nr_faces = 6; @@ -26,25 +30,31 @@ nv20_miptree_layout(struct nv20_miptree *nv20mt) pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); - if (swizzled) - nv20mt->level[l].pitch = pt->nblocksx[l] * pt->block.size; + if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) + nv20mt->level[l].pitch = align(pt->width[0] * pt->block.size, 64); else - nv20mt->level[l].pitch = pt->nblocksx[0] * pt->block.size; - nv20mt->level[l].pitch = (nv20mt->level[l].pitch + 63) & ~63; + nv20mt->level[l].pitch = pt->width[l] * pt->block.size; nv20mt->level[l].image_offset = CALLOC(nr_faces, sizeof(unsigned)); width = MAX2(1, width >> 1); height = MAX2(1, height >> 1); - } for (f = 0; f < nr_faces; f++) { - for (l = 0; l <= pt->last_level; l++) { + for (l = 0; l < pt->last_level; l++) { nv20mt->level[l].image_offset[f] = offset; - offset += nv20mt->level[l].pitch * pt->height[l]; + + if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) && + pt->width[l + 1] > 1 && pt->height[l + 1] > 1) + offset += align(nv20mt->level[l].pitch * pt->height[l], 64); + else + offset += nv20mt->level[l].pitch * pt->height[l]; } + + nv20mt->level[l].image_offset[f] = offset; + offset += nv20mt->level[l].pitch * pt->height[l]; } nv20mt->total_size = offset; @@ -96,7 +106,8 @@ nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET)) + PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) @@ -107,7 +118,11 @@ nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_X8R8G8B8_UNORM: case PIPE_FORMAT_R16_SNORM: + { + if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE)) + mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; break; + } default: mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; } @@ -152,33 +167,33 @@ nv20_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, unsigned flags) { struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt; - struct pipe_surface *ps; + struct nv04_surface *ns; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) return NULL; - pipe_texture_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = pt->width[level]; - ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = nv20mt->level[level].pitch; - ps->usage = flags; - ps->status = PIPE_SURFACE_STATUS_DEFINED; - ps->refcount = 1; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + ns->base.status = PIPE_SURFACE_STATUS_DEFINED; + ns->base.refcount = 1; + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = nv20mt->level[level].pitch; if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset = nv20mt->level[level].image_offset[face]; + ns->base.offset = nv20mt->level[level].image_offset[face]; } else if (pt->target == PIPE_TEXTURE_3D) { - ps->offset = nv20mt->level[level].image_offset[zslice]; + ns->base.offset = nv20mt->level[level].image_offset[zslice]; } else { - ps->offset = nv20mt->level[level].image_offset[0]; + ns->base.offset = nv20mt->level[level].image_offset[0]; } - return ps; + return &ns->base; } static void diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c index 5f2b7b4f71f..7760ae27c0e 100644 --- a/src/gallium/drivers/nv20/nv20_screen.c +++ b/src/gallium/drivers/nv20/nv20_screen.c @@ -116,30 +116,6 @@ nv20_screen_is_format_supported(struct pipe_screen *screen, return FALSE; } -static void * -nv20_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - struct pipe_winsys *ws = screen->winsys; - void *map; - struct nv20_miptree *nv20mt = (struct nv20_miptree *)surface->texture; - - map = ws->buffer_map(ws, nv20mt->buffer, flags); - if (!map) - return NULL; - - return map + surface->offset; -} - -static void -nv20_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) -{ - struct pipe_winsys *ws = screen->winsys; - struct nv20_miptree *nv20mt = (struct nv20_miptree *)surface->texture; - - ws->buffer_unmap(ws, nv20mt->buffer); -} - static void nv20_screen_destroy(struct pipe_screen *pscreen) { @@ -211,10 +187,8 @@ nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv20_screen_is_format_supported; - screen->pipe.surface_map = nv20_surface_map; - screen->pipe.surface_unmap = nv20_surface_unmap; - nv20_screen_init_miptree_functions(&screen->pipe); + nv20_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h index bf2f2c0d9fb..d9fce2bced8 100644 --- a/src/gallium/drivers/nv20/nv20_screen.h +++ b/src/gallium/drivers/nv20/nv20_screen.h @@ -21,4 +21,8 @@ nv20_screen(struct pipe_screen *screen) return (struct nv20_screen *)screen; } + +void +nv20_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv20/nv20_state_emit.c b/src/gallium/drivers/nv20/nv20_state_emit.c index 0f4df9ca317..4042f46d053 100644 --- a/src/gallium/drivers/nv20/nv20_state_emit.c +++ b/src/gallium/drivers/nv20/nv20_state_emit.c @@ -109,7 +109,7 @@ static void nv20_state_emit_scissor(struct nv20_context* nv20) static void nv20_state_emit_framebuffer(struct nv20_context* nv20) { struct pipe_framebuffer_state* fb = nv20->framebuffer; - struct pipe_surface *rt, *zeta = NULL; + struct nv04_surface *rt, *zeta = NULL; uint32_t rt_format, w, h; int colour_format = 0, zeta_format = 0; struct nv20_miptree *nv20mt = 0; @@ -117,7 +117,7 @@ static void nv20_state_emit_framebuffer(struct nv20_context* nv20) w = fb->cbufs[0]->width; h = fb->cbufs[0]->height; colour_format = fb->cbufs[0]->format; - rt = fb->cbufs[0]; + rt = (struct nv04_surface *)fb->cbufs[0]; if (fb->zsbuf) { if (colour_format) { @@ -129,7 +129,7 @@ static void nv20_state_emit_framebuffer(struct nv20_context* nv20) } zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } rt_format = NV20TCL_RT_FORMAT_TYPE_LINEAR | 0x20; @@ -148,18 +148,18 @@ static void nv20_state_emit_framebuffer(struct nv20_context* nv20) if (zeta) { BEGIN_RING(kelvin, NV20TCL_RT_PITCH, 1); - OUT_RING (rt->stride | (zeta->stride << 16)); + OUT_RING (rt->pitch | (zeta->pitch << 16)); } else { BEGIN_RING(kelvin, NV20TCL_RT_PITCH, 1); - OUT_RING (rt->stride | (rt->stride << 16)); + OUT_RING (rt->pitch | (rt->pitch << 16)); } - nv20mt = (struct nv20_miptree *)rt->texture; + nv20mt = (struct nv20_miptree *)rt->base.texture; nv20->rt[0] = nv20mt->buffer; if (zeta_format) { - nv20mt = (struct nv20_miptree *)zeta->texture; + nv20mt = (struct nv20_miptree *)zeta->base.texture; nv20->zeta = nv20mt->buffer; } diff --git a/src/gallium/drivers/nv20/nv20_transfer.c b/src/gallium/drivers/nv20/nv20_transfer.c new file mode 100644 index 00000000000..19de09486d3 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_transfer.c @@ -0,0 +1,201 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv20_context.h" +#include "nv20_screen.h" +#include "nv20_state.h" + +struct nv20_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv20_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv20_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->compressed = pt->compressed; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv20_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv20_miptree *mt = (struct nv20_miptree *)pt; + struct nv20_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv20_transfer); + if (!tx) + return NULL; + + tx->base.refcount = 1; + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + nv20_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv20_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv20_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv20_screen *nvscreen = nv20_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv20_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv20_transfer *tx = (struct nv20_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv20_screen *nvscreen = nv20_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + *pptx = NULL; + if (--ptx->refcount) + return; + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv20_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv20_transfer *tx = (struct nv20_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv20_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv20_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv20_transfer *tx = (struct nv20_transfer *)ptx; + struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv20_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv20_transfer_new; + pscreen->tex_transfer_release = nv20_transfer_del; + pscreen->transfer_map = nv20_transfer_map; + pscreen->transfer_unmap = nv20_transfer_unmap; +} diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile index 4c29e2eab31..364c80d8f3e 100644 --- a/src/gallium/drivers/nv30/Makefile +++ b/src/gallium/drivers/nv30/Makefile @@ -22,6 +22,7 @@ C_SOURCES = \ nv30_state_viewport.c \ nv30_state_zsa.c \ nv30_surface.c \ + nv30_transfer.c \ nv30_vbo.c \ nv30_vertprog.c diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c index b11ed8c24e2..ec0a8b8438c 100644 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nv30/nv30_miptree.c @@ -69,6 +69,8 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) { struct pipe_winsys *ws = pscreen->winsys; struct nv30_miptree *mt; + unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | + NOUVEAU_BUFFER_USAGE_TEXTURE; mt = MALLOC(sizeof(struct nv30_miptree)); if (!mt) @@ -76,8 +78,6 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) mt->base = *pt; mt->base.refcount = 1; mt->base.screen = pscreen; - mt->shadow_tex = NULL; - mt->shadow_surface = NULL; /* Swizzled textures must be POT */ if (pt->width[0] & (pt->width[0] - 1) || @@ -107,11 +107,12 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) } } + if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) + buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE; + nv30_miptree_layout(mt); - mt->buffer = ws->buffer_create(ws, 256, - PIPE_BUFFER_USAGE_PIXEL | - NOUVEAU_BUFFER_USAGE_TEXTURE, + mt->buffer = ws->buffer_create(ws, 256, buf_usage, mt->total_size); if (!mt->buffer) { FREE(mt); @@ -163,12 +164,6 @@ nv30_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) FREE(mt->level[l].image_offset); } - if (mt->shadow_tex) { - if (mt->shadow_surface) - pscreen->tex_surface_release(pscreen, &mt->shadow_surface); - nv30_miptree_release(pscreen, &mt->shadow_tex); - } - FREE(mt); } @@ -178,36 +173,33 @@ nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned flags) { struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt; - struct pipe_surface *ps; + struct nv04_surface *ns; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) return NULL; - pipe_texture_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = pt->width[level]; - ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = nv30mt->level[level].pitch; - ps->usage = flags; - ps->status = PIPE_SURFACE_STATUS_DEFINED; - ps->refcount = 1; - ps->face = face; - ps->level = level; - ps->zslice = zslice; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + ns->base.status = PIPE_SURFACE_STATUS_DEFINED; + ns->base.refcount = 1; + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = nv30mt->level[level].pitch; if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset = nv30mt->level[level].image_offset[face]; + ns->base.offset = nv30mt->level[level].image_offset[face]; } else if (pt->target == PIPE_TEXTURE_3D) { - ps->offset = nv30mt->level[level].image_offset[zslice]; + ns->base.offset = nv30mt->level[level].image_offset[zslice]; } else { - ps->offset = nv30mt->level[level].image_offset[0]; + ns->base.offset = nv30mt->level[level].image_offset[0]; } - return ps; + return &ns->base; } static void diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index c97a73f0b1a..d395c5e1b7f 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -135,82 +135,6 @@ nv30_surface_buffer(struct pipe_surface *surf) return mt->buffer; } -static void * -nv30_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - struct pipe_winsys *ws = screen->winsys; - struct pipe_surface *surface_to_map; - void *map; - - if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - struct nv30_miptree *mt = (struct nv30_miptree *)surface->texture; - - if (!mt->shadow_tex) { - unsigned old_tex_usage = surface->texture->tex_usage; - surface->texture->tex_usage = NOUVEAU_TEXTURE_USAGE_LINEAR | - PIPE_TEXTURE_USAGE_DYNAMIC; - mt->shadow_tex = screen->texture_create(screen, surface->texture); - surface->texture->tex_usage = old_tex_usage; - - assert(mt->shadow_tex->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR); - } - - mt->shadow_surface = screen->get_tex_surface - ( - screen, mt->shadow_tex, - surface->face, surface->level, surface->zslice, - surface->usage - ); - - surface_to_map = mt->shadow_surface; - } - else - surface_to_map = surface; - - assert(surface_to_map); - - map = ws->buffer_map(ws, nv30_surface_buffer(surface_to_map), flags); - if (!map) - return NULL; - - return map + surface_to_map->offset; -} - -static void -nv30_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) -{ - struct pipe_winsys *ws = screen->winsys; - struct pipe_surface *surface_to_unmap; - - /* TODO: Copy from shadow just before push buffer is flushed instead. - There are probably some programs that map/unmap excessively - before rendering. */ - if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - struct nv30_miptree *mt = (struct nv30_miptree *)surface->texture; - - assert(mt->shadow_tex); - - surface_to_unmap = mt->shadow_surface; - } - else - surface_to_unmap = surface; - - assert(surface_to_unmap); - - ws->buffer_unmap(ws, nv30_surface_buffer(surface_to_unmap)); - - if (surface_to_unmap != surface) { - struct nv30_screen *nvscreen = nv30_screen(screen); - - nvscreen->eng2d->copy(nvscreen->eng2d, surface, 0, 0, - surface_to_unmap, 0, 0, - surface->width, surface->height); - - screen->tex_surface_release(screen, &surface_to_unmap); - } -} - static void nv30_screen_destroy(struct pipe_screen *pscreen) { @@ -391,10 +315,8 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv30_screen_surface_format_supported; - screen->pipe.surface_map = nv30_surface_map; - screen->pipe.surface_unmap = nv30_surface_unmap; - nv30_screen_init_miptree_functions(&screen->pipe); + nv30_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index b11e470f949..8e368839759 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -34,4 +34,7 @@ nv30_screen(struct pipe_screen *screen) return (struct nv30_screen *)screen; } +void +nv30_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h index 2023278e377..e6f23bf1667 100644 --- a/src/gallium/drivers/nv30/nv30_state.h +++ b/src/gallium/drivers/nv30/nv30_state.h @@ -76,9 +76,6 @@ struct nv30_miptree { struct pipe_buffer *buffer; uint total_size; - struct pipe_texture *shadow_tex; - struct pipe_surface *shadow_surface; - struct { uint pitch; uint *image_offset; diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c index 77368cb2055..ee0326011ca 100644 --- a/src/gallium/drivers/nv30/nv30_state_fb.c +++ b/src/gallium/drivers/nv30/nv30_state_fb.c @@ -5,7 +5,7 @@ static boolean nv30_state_framebuffer_validate(struct nv30_context *nv30) { struct pipe_framebuffer_state *fb = &nv30->framebuffer; - struct pipe_surface *rt[2], *zeta = NULL; + struct nv04_surface *rt[2], *zeta = NULL; uint32_t rt_enable, rt_format; int i, colour_format = 0, zeta_format = 0; struct nouveau_stateobj *so = so_new(64, 10); @@ -21,7 +21,7 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30) } else { colour_format = fb->cbufs[i]->format; rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); - rt[i] = fb->cbufs[i]; + rt[i] = (struct nv04_surface *)fb->cbufs[i]; } } @@ -30,13 +30,13 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30) if (fb->zsbuf) { zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } - if (!(rt[0]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); + assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); /* FIXME: NV34TCL_RT_FORMAT_LOG2_[WIDTH/HEIGHT] */ rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | @@ -71,44 +71,44 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30) } if (rt_enable & NV34TCL_RT_ENABLE_COLOR0) { - uint32_t pitch = rt[0]->stride; + uint32_t pitch = rt[0]->pitch; if (zeta) { - pitch |= (zeta->stride << 16); + pitch |= (zeta->pitch << 16); } else { pitch |= (pitch << 16); } - nv30mt = (struct nv30_miptree *)rt[0]->texture; + nv30mt = (struct nv30_miptree *)rt[0]->base.texture; so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR0, 1); so_reloc (so, nv30mt->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv30->nvws->channel->vram->handle, nv30->nvws->channel->gart->handle); so_method(so, nv30->screen->rankine, NV34TCL_COLOR0_PITCH, 2); so_data (so, pitch); - so_reloc (so, nv30mt->buffer, rt[0]->offset, rt_flags | + so_reloc (so, nv30mt->buffer, rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); } if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { - nv30mt = (struct nv30_miptree *)rt[1]->texture; + nv30mt = (struct nv30_miptree *)rt[1]->base.texture; so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR1, 1); so_reloc (so, nv30mt->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv30->nvws->channel->vram->handle, nv30->nvws->channel->gart->handle); so_method(so, nv30->screen->rankine, NV34TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv30mt->buffer, rt[1]->offset, rt_flags | + so_reloc (so, nv30mt->buffer, rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_data (so, rt[1]->stride); + so_data (so, rt[1]->pitch); } if (zeta_format) { - nv30mt = (struct nv30_miptree *)zeta->texture; + nv30mt = (struct nv30_miptree *)zeta->base.texture; so_method(so, nv30->screen->rankine, NV34TCL_DMA_ZETA, 1); so_reloc (so, nv30mt->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv30->nvws->channel->vram->handle, nv30->nvws->channel->gart->handle); so_method(so, nv30->screen->rankine, NV34TCL_ZETA_OFFSET, 1); - so_reloc (so, nv30mt->buffer, zeta->offset, rt_flags | + so_reloc (so, nv30mt->buffer, zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); /* TODO: allocate LMA depth buffer */ } diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c new file mode 100644 index 00000000000..df4dc4b1f68 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_transfer.c @@ -0,0 +1,201 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv30_context.h" +#include "nv30_screen.h" +#include "nv30_state.h" + +struct nv30_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv30_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->compressed = pt->compressed; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv30_miptree *mt = (struct nv30_miptree *)pt; + struct nv30_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv30_transfer); + if (!tx) + return NULL; + + tx->base.refcount = 1; + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + nv30_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv30_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv30_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv30_screen *nvscreen = nv30_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv30_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv30_transfer *tx = (struct nv30_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv30_screen *nvscreen = nv30_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + *pptx = NULL; + if (--ptx->refcount) + return; + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv30_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv30_transfer *tx = (struct nv30_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv30_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv30_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv30_transfer *tx = (struct nv30_transfer *)ptx; + struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv30_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv30_transfer_new; + pscreen->tex_transfer_release = nv30_transfer_del; + pscreen->transfer_map = nv30_transfer_map; + pscreen->transfer_unmap = nv30_transfer_unmap; +} diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile index 8c738aefa6a..0ecae2b4913 100644 --- a/src/gallium/drivers/nv40/Makefile +++ b/src/gallium/drivers/nv40/Makefile @@ -22,6 +22,7 @@ C_SOURCES = \ nv40_state_viewport.c \ nv40_state_zsa.c \ nv40_surface.c \ + nv40_transfer.c \ nv40_vbo.c \ nv40_vertprog.c diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c index e38b1e7f5ca..638d279aa5a 100644 --- a/src/gallium/drivers/nv40/nv40_miptree.c +++ b/src/gallium/drivers/nv40/nv40_miptree.c @@ -78,8 +78,6 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) mt->base = *pt; mt->base.refcount = 1; mt->base.screen = pscreen; - mt->shadow_tex = NULL; - mt->shadow_surface = NULL; /* Swizzled textures must be POT */ if (pt->width[0] & (pt->width[0] - 1) || @@ -165,12 +163,6 @@ nv40_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) FREE(mt->level[l].image_offset); } - if (mt->shadow_tex) { - if (mt->shadow_surface) - pscreen->tex_surface_release(pscreen, &mt->shadow_surface); - nv40_miptree_release(pscreen, &mt->shadow_tex); - } - FREE(mt); } @@ -180,36 +172,33 @@ nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned flags) { struct nv40_miptree *mt = (struct nv40_miptree *)pt; - struct pipe_surface *ps; + struct nv04_surface *ns; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) return NULL; - pipe_texture_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = pt->width[level]; - ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = mt->level[level].pitch; - ps->usage = flags; - ps->status = PIPE_SURFACE_STATUS_DEFINED; - ps->refcount = 1; - ps->face = face; - ps->level = level; - ps->zslice = zslice; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + ns->base.status = PIPE_SURFACE_STATUS_DEFINED; + ns->base.refcount = 1; + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = mt->level[level].pitch; if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset = mt->level[level].image_offset[face]; + ns->base.offset = mt->level[level].image_offset[face]; } else if (pt->target == PIPE_TEXTURE_3D) { - ps->offset = mt->level[level].image_offset[zslice]; + ns->base.offset = mt->level[level].image_offset[zslice]; } else { - ps->offset = mt->level[level].image_offset[0]; + ns->base.offset = mt->level[level].image_offset[0]; } - return ps; + return &ns->base; } static void diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 2372bc84410..0d4baefaea3 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -144,81 +144,6 @@ nv40_surface_buffer(struct pipe_surface *surf) return mt->buffer; } -static void * -nv40_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - struct pipe_winsys *ws = screen->winsys; - struct pipe_surface *surface_to_map; - void *map; - - if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture; - - if (!mt->shadow_tex) { - unsigned old_tex_usage = surface->texture->tex_usage; - surface->texture->tex_usage = NOUVEAU_TEXTURE_USAGE_LINEAR | - PIPE_TEXTURE_USAGE_DYNAMIC; - mt->shadow_tex = screen->texture_create(screen, surface->texture); - surface->texture->tex_usage = old_tex_usage; - - assert(mt->shadow_tex->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR); - } - - mt->shadow_surface = screen->get_tex_surface - ( - screen, mt->shadow_tex, - surface->face, surface->level, surface->zslice, - surface->usage - ); - - surface_to_map = mt->shadow_surface; - } - else - surface_to_map = surface; - - assert(surface_to_map); - map = ws->buffer_map(ws, nv40_surface_buffer(surface_to_map), flags); - if (!map) - return NULL; - - return map + surface_to_map->offset; -} - -static void -nv40_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) -{ - struct pipe_winsys *ws = screen->winsys; - struct pipe_surface *surface_to_unmap; - - /* TODO: Copy from shadow just before push buffer is flushed instead. - There are probably some programs that map/unmap excessively - before rendering. */ - if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture; - - assert(mt->shadow_tex); - - surface_to_unmap = mt->shadow_surface; - } - else - surface_to_unmap = surface; - - assert(surface_to_unmap); - - ws->buffer_unmap(ws, nv40_surface_buffer(surface_to_unmap)); - - if (surface_to_unmap != surface) { - struct nv40_screen *nvscreen = nv40_screen(screen); - - nvscreen->eng2d->copy(nvscreen->eng2d, surface, 0, 0, - surface_to_unmap, 0, 0, - surface->width, surface->height); - - screen->tex_surface_release(screen, &surface_to_unmap); - } -} - static void nv40_screen_destroy(struct pipe_screen *pscreen) { @@ -240,7 +165,7 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) { struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); struct nouveau_stateobj *so; - unsigned curie_class; + unsigned curie_class = 0; unsigned chipset = nvws->channel->device->chipset; int ret; @@ -265,8 +190,6 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) curie_class = NV44TCL; break; - default: - break; } if (!curie_class) { @@ -372,10 +295,8 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv40_screen_surface_format_supported; - screen->pipe.surface_map = nv40_surface_map; - screen->pipe.surface_unmap = nv40_surface_unmap; - nv40_screen_init_miptree_functions(&screen->pipe); + nv40_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 4500aa0e5cc..7b503bd207d 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -34,4 +34,7 @@ nv40_screen(struct pipe_screen *screen) return (struct nv40_screen *)screen; } +void +nv40_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h index 9c55903ae30..8a9d8c8fdf6 100644 --- a/src/gallium/drivers/nv40/nv40_state.h +++ b/src/gallium/drivers/nv40/nv40_state.h @@ -79,9 +79,6 @@ struct nv40_miptree { struct pipe_buffer *buffer; uint total_size; - struct pipe_texture *shadow_tex; - struct pipe_surface *shadow_surface; - struct { uint pitch; uint *image_offset; diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c index 454abad31f4..5ebd3a1a56b 100644 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ b/src/gallium/drivers/nv40/nv40_state_fb.c @@ -12,7 +12,7 @@ static boolean nv40_state_framebuffer_validate(struct nv40_context *nv40) { struct pipe_framebuffer_state *fb = &nv40->framebuffer; - struct pipe_surface *rt[4], *zeta; + struct nv04_surface *rt[4], *zeta; uint32_t rt_enable, rt_format; int i, colour_format = 0, zeta_format = 0; struct nouveau_stateobj *so = so_new(64, 10); @@ -27,7 +27,7 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) } else { colour_format = fb->cbufs[i]->format; rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i); - rt[i] = fb->cbufs[i]; + rt[i] = (struct nv04_surface *)fb->cbufs[i]; } } @@ -37,13 +37,13 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) if (fb->zsbuf) { zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } - if (!(rt[0]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); + assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); rt_format = NV40TCL_RT_FORMAT_TYPE_SWIZZLED | log2i(fb->width) << NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT | @@ -78,60 +78,60 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1); - so_reloc (so, nv40_surface_buffer(rt[0]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2); - so_data (so, rt[0]->stride); - so_reloc (so, nv40_surface_buffer(rt[0]), rt[0]->offset, rt_flags | + so_data (so, rt[0]->pitch); + so_reloc (so, nv40_surface_buffer(&rt[0]->base), rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1); - so_reloc (so, nv40_surface_buffer(rt[1]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv40_surface_buffer(rt[1]), rt[1]->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&rt[1]->base), rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_data (so, rt[1]->stride); + so_data (so, rt[1]->pitch); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1); - so_reloc (so, nv40_surface_buffer(rt[2]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(rt[2]), rt[2]->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&rt[2]->base), rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1); - so_data (so, rt[2]->stride); + so_data (so, rt[2]->pitch); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1); - so_reloc (so, nv40_surface_buffer(rt[3]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(rt[3]), rt[3]->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&rt[3]->base), rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1); - so_data (so, rt[3]->stride); + so_data (so, rt[3]->pitch); } if (zeta_format) { so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1); - so_reloc (so, nv40_surface_buffer(zeta), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&zeta->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(zeta), zeta->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&zeta->base), zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1); - so_data (so, zeta->stride); + so_data (so, zeta->pitch); } so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1); diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c new file mode 100644 index 00000000000..b090f2238e4 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_transfer.c @@ -0,0 +1,201 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv40_context.h" +#include "nv40_screen.h" +#include "nv40_state.h" + +struct nv40_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv40_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->compressed = pt->compressed; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv40_miptree *mt = (struct nv40_miptree *)pt; + struct nv40_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv40_transfer); + if (!tx) + return NULL; + + tx->base.refcount = 1; + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + nv40_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv40_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv40_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv40_screen *nvscreen = nv40_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv40_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv40_screen *nvscreen = nv40_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + *pptx = NULL; + if (--ptx->refcount) + return; + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv40_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv40_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv40_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv40_transfer_new; + pscreen->tex_transfer_release = nv40_transfer_del; + pscreen->transfer_map = nv40_transfer_map; + pscreen->transfer_unmap = nv40_transfer_unmap; +} diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 9b7524b523a..a0fd17bd59b 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -12,6 +12,7 @@ C_SOURCES = \ r300_screen.c \ r300_state.c \ r300_state_derived.c \ + r300_state_invariant.c \ r300_state_shader.c \ r300_surface.c \ r300_swtcl_emit.c \ diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 196537a432d..e01a0546b22 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -30,7 +30,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) { /* Reasonable defaults */ - caps->has_tcl = TRUE; + caps->has_tcl = getenv("RADEON_NO_TCL") ? TRUE : FALSE; caps->is_r500 = FALSE; caps->num_vert_fpus = 4; @@ -204,6 +204,13 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->has_tcl = FALSE; break; + case 0x793F: + case 0x7941: + case 0x7942: + caps->family = CHIP_FAMILY_RS600; + caps->has_tcl = FALSE; + break; + case 0x796C: case 0x796D: case 0x796E: diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index a9cd372ec55..21eebeae600 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -64,6 +64,7 @@ enum { CHIP_FAMILY_RC410, CHIP_FAMILY_RS480, CHIP_FAMILY_RS482, + CHIP_FAMILY_RS600, CHIP_FAMILY_RS690, CHIP_FAMILY_RS740, CHIP_FAMILY_RV515, diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 15a87515494..a9811501435 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -73,7 +73,7 @@ static boolean r300_draw_range_elements(struct pipe_context* pipe, start + count - 1, NULL); } - return true; + return TRUE; } static boolean r300_draw_elements(struct pipe_context* pipe, @@ -97,6 +97,7 @@ static void r300_destroy_context(struct pipe_context* context) { draw_destroy(r300->draw); FREE(r300->blend_color_state); + FREE(r300->rs_block); FREE(r300->scissor_state); FREE(r300); } @@ -126,6 +127,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_set_rasterize_stage(r300->draw, r300_draw_swtcl_stage(r300)); r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); + r300->rs_block = CALLOC_STRUCT(r300_rs_block); r300->scissor_state = CALLOC_STRUCT(r300_scissor_state); r300_init_flush_functions(r300); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index aaab1dd2bcb..5247901be5b 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -75,6 +75,13 @@ struct r300_rs_state { uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ }; +struct r300_rs_block { + uint32_t ip[8]; /* R300_RS_IP_[0-7], R500_RS_IP_[0-7] */ + uint32_t count; /* R300_RS_COUNT */ + uint32_t inst_count; /* R300_RS_INST_COUNT */ + uint32_t inst[8]; /* R300_RS_INST_[0-7] */ +}; + struct r300_sampler_state { uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ @@ -96,12 +103,13 @@ struct r300_texture_state { #define R300_NEW_FRAMEBUFFERS 0x0000010 #define R300_NEW_FRAGMENT_SHADER 0x0000020 #define R300_NEW_RASTERIZER 0x0000040 -#define R300_NEW_SAMPLER 0x0000080 -#define R300_NEW_SCISSOR 0x0008000 -#define R300_NEW_TEXTURE 0x0010000 -#define R300_NEW_VERTEX_FORMAT 0x1000000 -#define R300_NEW_VERTEX_SHADER 0x2000000 -#define R300_NEW_KITCHEN_SINK 0x3ffffff +#define R300_NEW_RS_BLOCK 0x0000080 +#define R300_NEW_SAMPLER 0x0000100 +#define R300_NEW_SCISSOR 0x0010000 +#define R300_NEW_TEXTURE 0x0020000 +#define R300_NEW_VERTEX_FORMAT 0x2000000 +#define R300_NEW_VERTEX_SHADER 0x4000000 +#define R300_NEW_KITCHEN_SINK 0x7ffffff /* The next several objects are not pure Radeon state; they inherit from * various Gallium classes. */ @@ -224,6 +232,8 @@ struct r300_context { struct pipe_framebuffer_state framebuffer_state; /* Rasterizer state. */ struct r300_rs_state* rs_state; + /* RS block state. */ + struct r300_rs_block* rs_block; /* Sampler states. */ struct r300_sampler_state* sampler_states[8]; int sampler_count; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 960f45f651f..91fac62cbe6 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -40,9 +40,9 @@ void r300_emit_blend_state(struct r300_context* r300, void r300_emit_blend_color_state(struct r300_context* r300, struct r300_blend_color_state* bc) { - struct r300_screen* r300screen = - (struct r300_screen*)r300->context.screen; + struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); + if (r300screen->caps->is_r500) { BEGIN_CS(3); OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); @@ -59,9 +59,9 @@ void r300_emit_blend_color_state(struct r300_context* r300, void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa) { - struct r300_screen* r300screen = - (struct r300_screen*)r300->context.screen; + struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); + BEGIN_CS(r300screen->caps->is_r500 ? 8 : 8); OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); /* XXX figure out the r300 counterpart for this */ @@ -84,6 +84,7 @@ void r300_emit_fragment_shader(struct r300_context* r300, { CS_LOCALS(r300); int i; + BEGIN_CS(22); OUT_CS_REG(R300_US_CONFIG, MAX2(fs->indirections - 1, 0)); @@ -114,7 +115,8 @@ void r500_emit_fragment_shader(struct r300_context* r300, struct r500_fragment_shader* fs) { CS_LOCALS(r300); - int i = 0; + int i; + BEGIN_CS(9 + (fs->instruction_count * 6)); OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); OUT_CS_REG(R500_US_PIXSIZE, fs->shader.stack_size); @@ -191,9 +193,9 @@ void r300_emit_fb_state(struct r300_context* r300, void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs) { - struct r300_screen* r300screen = - (struct r300_screen*)r300->context.screen; + struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); + BEGIN_CS(13); OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status); OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 6); @@ -208,10 +210,44 @@ void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs) END_CS; } +void r300_emit_rs_block_state(struct r300_context* r300, + struct r300_rs_block* rs) +{ + struct r300_screen* r300screen = r300_screen(r300->context.screen); + CS_LOCALS(r300); + int i; + + BEGIN_CS(21); + if (r300screen->caps->is_r500) { + OUT_CS_REG_SEQ(R500_RS_IP_0, 8); + } else { + OUT_CS_REG_SEQ(R300_RS_IP_0, 8); + } + for (i = 0; i < 8; i++) { + OUT_CS(rs->ip[i]); + } + + OUT_CS_REG_SEQ(R300_RS_COUNT, 2); + OUT_CS(rs->count); + OUT_CS(rs->inst_count); + + if (r300screen->caps->is_r500) { + OUT_CS_REG_SEQ(R500_RS_INST_0, 8); + } else { + OUT_CS_REG_SEQ(R300_RS_INST_0, 8); + } + for (i = 0; i < 8; i++) { + OUT_CS(rs->inst[i]); + } + + END_CS; +} + void r300_emit_scissor_state(struct r300_context* r300, struct r300_scissor_state* scissor) { CS_LOCALS(r300); + BEGIN_CS(3); OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); OUT_CS(scissor->scissor_top_left); @@ -248,8 +284,7 @@ void r300_emit_vertex_format_state(struct r300_context* r300) /* Emit all dirty state. */ void r300_emit_dirty_state(struct r300_context* r300) { - struct r300_screen* r300screen = - (struct r300_screen*)r300->context.screen; + struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); if (!(r300->dirty_state) && !(r300->dirty_hw)) { diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 8888b39a2f9..e0da9d361e4 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -732,6 +732,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R500_RS_IP_TEX_PTR_Q_SHIFT 18 #define R500_RS_IP_COL_PTR_SHIFT 24 #define R500_RS_IP_COL_FMT_SHIFT 27 +# define R500_RS_SEL_S(x) ((x) << 0) +# define R500_RS_SEL_T(x) ((x) << 6) +# define R500_RS_SEL_R(x) ((x) << 12) +# define R500_RS_SEL_Q(x) ((x) << 18) # define R500_RS_COL_PTR(x) ((x) << 24) # define R500_RS_COL_FMT(x) ((x) << 27) /* gap */ @@ -1216,14 +1220,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R500_RS_INST_14 0x4358 #define R500_RS_INST_15 0x435c #define R500_RS_INST_TEX_ID_SHIFT 0 +# define R500_RS_INST_TEX_ID(x) ((x) << 0) #define R500_RS_INST_TEX_CN_WRITE (1 << 4) #define R500_RS_INST_TEX_ADDR_SHIFT 5 +# define R500_RS_INST_TEX_ADDR(x) ((x) << 0) #define R500_RS_INST_COL_ID_SHIFT 12 +# define R500_RS_INST_COL_ID(x) ((x) << 12) #define R500_RS_INST_COL_CN_NO_WRITE (0 << 16) #define R500_RS_INST_COL_CN_WRITE (1 << 16) #define R500_RS_INST_COL_CN_WRITE_FBUFFER (2 << 16) #define R500_RS_INST_COL_CN_WRITE_BACKFACE (3 << 16) #define R500_RS_INST_COL_ADDR_SHIFT 18 +# define R500_RS_INST_COL_ADDR(x) ((x) << 18) #define R500_RS_INST_TEX_ADJ (1 << 25) #define R500_RS_INST_W_CN (1 << 26) @@ -1240,9 +1248,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R300_RS_INST_7 0x434C # define R300_RS_INST_TEX_ID(x) ((x) << 0) # define R300_RS_INST_TEX_CN_WRITE (1 << 3) +# define R300_RS_INST_TEX_ADDR(x) ((x) << 6) # define R300_RS_INST_TEX_ADDR_SHIFT 6 # define R300_RS_INST_COL_ID(x) ((x) << 11) # define R300_RS_INST_COL_CN_WRITE (1 << 14) +# define R300_RS_INST_COL_ADDR(x) ((x) << 17) # define R300_RS_INST_COL_ADDR_SHIFT 17 # define R300_RS_INST_TEX_ADJ (1 << 22) # define R300_RS_COL_BIAS_UNUSED_SHIFT 23 diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 5ff9015a7bf..2fcd5048128 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -50,6 +50,7 @@ static const char* chip_families[] = { "RC410", "RS480", "RS482", + "RS600", "RS690", "RS740", "RV515", @@ -178,8 +179,11 @@ static boolean check_tex_2d_format(enum pipe_format format, boolean is_r500) { switch (format) { /* Colorbuffer */ + case PIPE_FORMAT_A4R4G4B4_UNORM: + case PIPE_FORMAT_R5G6B5_UNORM: + case PIPE_FORMAT_A1R5G5B5_UNORM: case PIPE_FORMAT_A8R8G8B8_UNORM: - /* Texture */ + /* Colorbuffer or texture */ case PIPE_FORMAT_I8_UNORM: /* Z buffer */ case PIPE_FORMAT_Z16_UNORM: @@ -187,29 +191,25 @@ static boolean check_tex_2d_format(enum pipe_format format, boolean is_r500) case PIPE_FORMAT_Z24S8_UNORM: return TRUE; - /* XXX Supported yet unimplemented formats: */ - case PIPE_FORMAT_A1R5G5B5_UNORM: - case PIPE_FORMAT_R5G6B5_UNORM: /* XXX These don't even exist case PIPE_FORMAT_A32R32G32B32: case PIPE_FORMAT_A16R16G16B16: */ /* XXX Insert YUV422 packed VYUY and YVYU here */ - /* XXX What the deuce is UV88? (r3xx accel page 14) */ - case PIPE_FORMAT_A4R4G4B4_UNORM: + /* XXX What the deuce is UV88? (r3xx accel page 14) debug_printf("r300: Warning: Got unimplemented format: %s in %s\n", pf_name(format), __FUNCTION__); - return FALSE; + return FALSE; */ /* XXX Supported yet unimplemented r5xx formats: */ /* XXX Again, what is UV1010 this time? (r5xx accel page 148) */ /* XXX Even more that don't exist case PIPE_FORMAT_A10R10G10B10_UNORM: case PIPE_FORMAT_A2R10G10B10_UNORM: - case PIPE_FORMAT_I10_UNORM: */ + case PIPE_FORMAT_I10_UNORM: debug_printf( "r300: Warning: Got unimplemented r500 format: %s in %s\n", pf_name(format), __FUNCTION__); - return FALSE; + return FALSE; */ default: debug_printf("r300: Warning: Got unsupported format: %s in %s\n", diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index da99a3be6b6..6e64ad2dc35 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -28,89 +28,11 @@ #include "r300_context.h" #include "r300_reg.h" +#include "r300_state_inlines.h" #include "r300_state_shader.h" /* r300_state: Functions used to intialize state context by translating - * Gallium state objects into semi-native r300 state objects. - * - * XXX break this file up into pieces if it gets too big! */ - -/* Pack a float into a dword. */ -static uint32_t pack_float_32(float f) -{ - union { - float f; - uint32_t u; - } u; - - u.f = f; - return u.u; -} - -static uint32_t translate_blend_function(int blend_func) { - switch (blend_func) { - case PIPE_BLEND_ADD: - return R300_COMB_FCN_ADD_CLAMP; - case PIPE_BLEND_SUBTRACT: - return R300_COMB_FCN_SUB_CLAMP; - case PIPE_BLEND_REVERSE_SUBTRACT: - return R300_COMB_FCN_RSUB_CLAMP; - case PIPE_BLEND_MIN: - return R300_COMB_FCN_MIN; - case PIPE_BLEND_MAX: - return R300_COMB_FCN_MAX; - default: - debug_printf("r300: Unknown blend function %d\n", blend_func); - break; - } - return 0; -} - -/* XXX we can also offer the D3D versions of some of these... */ -static uint32_t translate_blend_factor(int blend_fact) { - switch (blend_fact) { - case PIPE_BLENDFACTOR_ONE: - return R300_BLEND_GL_ONE; - case PIPE_BLENDFACTOR_SRC_COLOR: - return R300_BLEND_GL_SRC_COLOR; - case PIPE_BLENDFACTOR_SRC_ALPHA: - return R300_BLEND_GL_SRC_ALPHA; - case PIPE_BLENDFACTOR_DST_ALPHA: - return R300_BLEND_GL_DST_ALPHA; - case PIPE_BLENDFACTOR_DST_COLOR: - return R300_BLEND_GL_DST_COLOR; - case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: - return R300_BLEND_GL_SRC_ALPHA_SATURATE; - case PIPE_BLENDFACTOR_CONST_COLOR: - return R300_BLEND_GL_CONST_COLOR; - case PIPE_BLENDFACTOR_CONST_ALPHA: - return R300_BLEND_GL_CONST_ALPHA; - /* XXX WTF are these? - case PIPE_BLENDFACTOR_SRC1_COLOR: - case PIPE_BLENDFACTOR_SRC1_ALPHA: */ - case PIPE_BLENDFACTOR_ZERO: - return R300_BLEND_GL_ZERO; - case PIPE_BLENDFACTOR_INV_SRC_COLOR: - return R300_BLEND_GL_ONE_MINUS_SRC_COLOR; - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: - return R300_BLEND_GL_ONE_MINUS_SRC_ALPHA; - case PIPE_BLENDFACTOR_INV_DST_ALPHA: - return R300_BLEND_GL_ONE_MINUS_DST_ALPHA; - case PIPE_BLENDFACTOR_INV_DST_COLOR: - return R300_BLEND_GL_ONE_MINUS_DST_COLOR; - case PIPE_BLENDFACTOR_INV_CONST_COLOR: - return R300_BLEND_GL_ONE_MINUS_CONST_COLOR; - case PIPE_BLENDFACTOR_INV_CONST_ALPHA: - return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA; - /* XXX see above - case PIPE_BLENDFACTOR_INV_SRC1_COLOR: - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */ - default: - debug_printf("r300: Unknown blend factor %d\n", blend_fact); - break; - } - return 0; -} + * Gallium state objects into semi-native r300 state objects. */ /* Create a new blend state based on the CSO blend state. * @@ -126,16 +48,16 @@ static void* r300_create_blend_state(struct pipe_context* pipe, blend->blend_control = R300_ALPHA_BLEND_ENABLE | R300_SEPARATE_ALPHA_ENABLE | R300_READ_ENABLE | - translate_blend_function(state->rgb_func) | - (translate_blend_factor(state->rgb_src_factor) << + r300_translate_blend_function(state->rgb_func) | + (r300_translate_blend_factor(state->rgb_src_factor) << R300_SRC_BLEND_SHIFT) | - (translate_blend_factor(state->rgb_dst_factor) << + (r300_translate_blend_factor(state->rgb_dst_factor) << R300_DST_BLEND_SHIFT); blend->alpha_blend_control = - translate_blend_function(state->alpha_func) | - (translate_blend_factor(state->alpha_src_factor) << + r300_translate_blend_function(state->alpha_func) | + (r300_translate_blend_factor(state->alpha_src_factor) << R300_SRC_BLEND_SHIFT) | - (translate_blend_factor(state->alpha_dst_factor) << + (r300_translate_blend_factor(state->alpha_dst_factor) << R300_DST_BLEND_SHIFT); } @@ -178,21 +100,17 @@ static void r300_set_blend_color(struct pipe_context* pipe, const struct pipe_blend_color* color) { struct r300_context* r300 = r300_context(pipe); - uint32_t r, g, b, a; ubyte ur, ug, ub, ua; - r = util_iround(color->color[0] * 1023.0f); - g = util_iround(color->color[1] * 1023.0f); - b = util_iround(color->color[2] * 1023.0f); - a = util_iround(color->color[3] * 1023.0f); - ur = float_to_ubyte(color->color[0]); ug = float_to_ubyte(color->color[1]); ub = float_to_ubyte(color->color[2]); ua = float_to_ubyte(color->color[3]); - r300->blend_color_state->blend_color = (a << 24) | (r << 16) | (g << 8) | b; + util_pack_color(color->color, PIPE_FORMAT_A8R8G8B8_UNORM, + &r300->blend_color_state->blend_color); + /* XXX this is wrong */ r300->blend_color_state->blend_color_red_alpha = ur | (ua << 16); r300->blend_color_state->blend_color_green_blue = ub | (ug << 16); @@ -233,82 +151,6 @@ static void r300->dirty_state |= R300_NEW_CONSTANTS; } -static uint32_t translate_depth_stencil_function(int zs_func) { - switch (zs_func) { - case PIPE_FUNC_NEVER: - return R300_ZS_NEVER; - case PIPE_FUNC_LESS: - return R300_ZS_LESS; - case PIPE_FUNC_EQUAL: - return R300_ZS_EQUAL; - case PIPE_FUNC_LEQUAL: - return R300_ZS_LEQUAL; - case PIPE_FUNC_GREATER: - return R300_ZS_GREATER; - case PIPE_FUNC_NOTEQUAL: - return R300_ZS_NOTEQUAL; - case PIPE_FUNC_GEQUAL: - return R300_ZS_GEQUAL; - case PIPE_FUNC_ALWAYS: - return R300_ZS_ALWAYS; - default: - debug_printf("r300: Unknown depth/stencil function %d\n", - zs_func); - break; - } - return 0; -} - -static uint32_t translate_stencil_op(int s_op) { - switch (s_op) { - case PIPE_STENCIL_OP_KEEP: - return R300_ZS_KEEP; - case PIPE_STENCIL_OP_ZERO: - return R300_ZS_ZERO; - case PIPE_STENCIL_OP_REPLACE: - return R300_ZS_REPLACE; - case PIPE_STENCIL_OP_INCR: - return R300_ZS_INCR; - case PIPE_STENCIL_OP_DECR: - return R300_ZS_DECR; - case PIPE_STENCIL_OP_INCR_WRAP: - return R300_ZS_INCR_WRAP; - case PIPE_STENCIL_OP_DECR_WRAP: - return R300_ZS_DECR_WRAP; - case PIPE_STENCIL_OP_INVERT: - return R300_ZS_INVERT; - default: - debug_printf("r300: Unknown stencil op %d", s_op); - break; - } - return 0; -} - -static uint32_t translate_alpha_function(int alpha_func) { - switch (alpha_func) { - case PIPE_FUNC_NEVER: - return R300_FG_ALPHA_FUNC_NEVER; - case PIPE_FUNC_LESS: - return R300_FG_ALPHA_FUNC_LESS; - case PIPE_FUNC_EQUAL: - return R300_FG_ALPHA_FUNC_EQUAL; - case PIPE_FUNC_LEQUAL: - return R300_FG_ALPHA_FUNC_LE; - case PIPE_FUNC_GREATER: - return R300_FG_ALPHA_FUNC_GREATER; - case PIPE_FUNC_NOTEQUAL: - return R300_FG_ALPHA_FUNC_NOTEQUAL; - case PIPE_FUNC_GEQUAL: - return R300_FG_ALPHA_FUNC_GE; - case PIPE_FUNC_ALWAYS: - return R300_FG_ALPHA_FUNC_ALWAYS; - default: - debug_printf("r300: Unknown alpha function %d", alpha_func); - break; - } - return 0; -} - /* Create a new depth, stencil, and alpha state based on the CSO dsa state. * * This contains the depth buffer, stencil buffer, alpha test, and such. @@ -329,7 +171,7 @@ static void* } dsa->z_stencil_control |= - (translate_depth_stencil_function(state->depth.func) << + (r300_translate_depth_stencil_function(state->depth.func) << R300_Z_FUNC_SHIFT); } @@ -337,14 +179,14 @@ static void* if (state->stencil[0].enabled) { dsa->z_buffer_control |= R300_STENCIL_ENABLE; dsa->z_stencil_control |= - (translate_depth_stencil_function(state->stencil[0].func) << - R300_S_FRONT_FUNC_SHIFT) | - (translate_stencil_op(state->stencil[0].fail_op) << - R300_S_FRONT_SFAIL_OP_SHIFT) | - (translate_stencil_op(state->stencil[0].zpass_op) << - R300_S_FRONT_ZPASS_OP_SHIFT) | - (translate_stencil_op(state->stencil[0].zfail_op) << - R300_S_FRONT_ZFAIL_OP_SHIFT); + (r300_translate_depth_stencil_function(state->stencil[0].func) << + R300_S_FRONT_FUNC_SHIFT) | + (r300_translate_stencil_op(state->stencil[0].fail_op) << + R300_S_FRONT_SFAIL_OP_SHIFT) | + (r300_translate_stencil_op(state->stencil[0].zpass_op) << + R300_S_FRONT_ZPASS_OP_SHIFT) | + (r300_translate_stencil_op(state->stencil[0].zfail_op) << + R300_S_FRONT_ZFAIL_OP_SHIFT); dsa->stencil_ref_mask = (state->stencil[0].ref_value) | (state->stencil[0].valuemask << R300_STENCILMASK_SHIFT) | @@ -353,14 +195,14 @@ static void* if (state->stencil[1].enabled) { dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK; dsa->z_stencil_control |= - (translate_depth_stencil_function(state->stencil[1].func) << - R300_S_BACK_FUNC_SHIFT) | - (translate_stencil_op(state->stencil[1].fail_op) << - R300_S_BACK_SFAIL_OP_SHIFT) | - (translate_stencil_op(state->stencil[1].zpass_op) << - R300_S_BACK_ZPASS_OP_SHIFT) | - (translate_stencil_op(state->stencil[1].zfail_op) << - R300_S_BACK_ZFAIL_OP_SHIFT); + (r300_translate_depth_stencil_function(state->stencil[1].func) << + R300_S_BACK_FUNC_SHIFT) | + (r300_translate_stencil_op(state->stencil[1].fail_op) << + R300_S_BACK_SFAIL_OP_SHIFT) | + (r300_translate_stencil_op(state->stencil[1].zpass_op) << + R300_S_BACK_ZPASS_OP_SHIFT) | + (r300_translate_stencil_op(state->stencil[1].zfail_op) << + R300_S_BACK_ZFAIL_OP_SHIFT); dsa->stencil_ref_bf = (state->stencil[1].ref_value) | (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | @@ -370,7 +212,8 @@ static void* /* Alpha test setup. */ if (state->alpha.enabled) { - dsa->alpha_function = translate_alpha_function(state->alpha.func) | + dsa->alpha_function = + r300_translate_alpha_function(state->alpha.func) | R300_FG_ALPHA_FUNC_ENABLE; dsa->alpha_reference = CLAMP(state->alpha.ref_value * 1023.0f, 0, 1023); @@ -457,7 +300,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) } } - fs->translated = true; + fs->translated = TRUE; r300->fs = fs; r300->dirty_state |= R300_NEW_FRAGMENT_SHADER; @@ -475,10 +318,6 @@ static void r300_set_polygon_stipple(struct pipe_context* pipe, /* XXX */ } -static INLINE int pack_float_16_6x(float f) { - return ((int)(f * 6.0) & 0xffff); -} - /* Create a new rasterizer state based on the CSO rasterizer state. * * This is a very large chunk of state, and covers most of the graphics @@ -530,15 +369,15 @@ static void* r300_create_rs_state(struct pipe_context* pipe, if (rs->polygon_offset_enable) { rs->depth_offset_front = rs->depth_offset_back = - pack_float_32(state->offset_units); + fui(state->offset_units); rs->depth_scale_front = rs->depth_scale_back = - pack_float_32(state->offset_scale); + fui(state->offset_scale); } if (state->line_stipple_enable) { rs->line_stipple_config = R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_LINE | - (pack_float_32((float)state->line_stipple_factor) & + (fui((float)state->line_stipple_factor) & R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_MASK); /* XXX this might need to be scaled up */ rs->line_stipple_value = state->line_stipple_pattern; @@ -567,83 +406,6 @@ static void r300_delete_rs_state(struct pipe_context* pipe, void* state) FREE(state); } -static uint32_t translate_wrap(int wrap) { - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - return R300_TX_REPEAT; - case PIPE_TEX_WRAP_CLAMP: - return R300_TX_CLAMP; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - return R300_TX_CLAMP_TO_EDGE; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - return R300_TX_CLAMP_TO_BORDER; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - return R300_TX_REPEAT | R300_TX_MIRRORED; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - return R300_TX_CLAMP | R300_TX_MIRRORED; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; - default: - debug_printf("r300: Unknown texture wrap %d", wrap); - return 0; - } -} - -static uint32_t translate_tex_filters(int min, int mag, int mip) { - uint32_t retval = 0; - switch (min) { - case PIPE_TEX_FILTER_NEAREST: - retval |= R300_TX_MIN_FILTER_NEAREST; - case PIPE_TEX_FILTER_LINEAR: - retval |= R300_TX_MIN_FILTER_LINEAR; - case PIPE_TEX_FILTER_ANISO: - retval |= R300_TX_MIN_FILTER_ANISO; - default: - debug_printf("r300: Unknown texture filter %d", min); - break; - } - switch (mag) { - case PIPE_TEX_FILTER_NEAREST: - retval |= R300_TX_MAG_FILTER_NEAREST; - case PIPE_TEX_FILTER_LINEAR: - retval |= R300_TX_MAG_FILTER_LINEAR; - case PIPE_TEX_FILTER_ANISO: - retval |= R300_TX_MAG_FILTER_ANISO; - default: - debug_printf("r300: Unknown texture filter %d", mag); - break; - } - switch (mip) { - case PIPE_TEX_MIPFILTER_NONE: - retval |= R300_TX_MIN_FILTER_MIP_NONE; - case PIPE_TEX_MIPFILTER_NEAREST: - retval |= R300_TX_MIN_FILTER_MIP_NEAREST; - case PIPE_TEX_MIPFILTER_LINEAR: - retval |= R300_TX_MIN_FILTER_MIP_LINEAR; - default: - debug_printf("r300: Unknown texture filter %d", mip); - break; - } - - return retval; -} - -static uint32_t anisotropy(float max_aniso) { - if (max_aniso >= 16.0f) { - return R300_TX_MAX_ANISO_16_TO_1; - } else if (max_aniso >= 8.0f) { - return R300_TX_MAX_ANISO_8_TO_1; - } else if (max_aniso >= 4.0f) { - return R300_TX_MAX_ANISO_4_TO_1; - } else if (max_aniso >= 2.0f) { - return R300_TX_MAX_ANISO_2_TO_1; - } else { - return R300_TX_MAX_ANISO_1_TO_1; - } -} - static void* r300_create_sampler_state(struct pipe_context* pipe, const struct pipe_sampler_state* state) @@ -653,19 +415,19 @@ static void* int lod_bias; sampler->filter0 |= - (translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) | - (translate_wrap(state->wrap_t) << R300_TX_WRAP_T_SHIFT) | - (translate_wrap(state->wrap_r) << R300_TX_WRAP_R_SHIFT); + (r300_translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) | + (r300_translate_wrap(state->wrap_t) << R300_TX_WRAP_T_SHIFT) | + (r300_translate_wrap(state->wrap_r) << R300_TX_WRAP_R_SHIFT); - sampler->filter0 |= translate_tex_filters(state->min_img_filter, - state->mag_img_filter, - state->min_mip_filter); + sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter, + state->mag_img_filter, + state->min_mip_filter); lod_bias = CLAMP((int)(state->lod_bias * 32), -(1 << 9), (1 << 9) - 1); sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT; - sampler->filter1 |= anisotropy(state->max_anisotropy); + sampler->filter1 |= r300_anisotropy(state->max_anisotropy); util_pack_color(state->border_color, PIPE_FORMAT_A8R8G8B8_UNORM, &sampler->border_color); diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index a51904096f2..548a840f25d 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -57,34 +57,40 @@ static uint32_t translate_vertex_data_type(int type) { /* XXX this function should be able to handle vert shaders as well as draw */ static void r300_update_vertex_layout(struct r300_context* r300) { + struct r300_vertex_format vformat; struct vertex_info vinfo; - boolean pos = false, psize = false, fog = false; + boolean pos = FALSE, psize = FALSE, fog = FALSE; int i, texs = 0, cols = 0; + int tab[16]; struct tgsi_shader_info* info = &r300->fs->info; + memset(&vinfo, 0, sizeof(vinfo)); + for (i = 0; i < 16; i++) { + tab[i] = -1; + } assert(info->num_inputs <= 16); - /* This is rather lame. Since draw_find_vs_output doesn't return an error - * when it can't find an output, we have to pre-iterate and count each - * output ourselves. */ for (i = 0; i < info->num_inputs; i++) { switch (info->input_semantic_name[i]) { case TGSI_SEMANTIC_POSITION: - pos = true; + pos = TRUE; + tab[i] = 0; break; case TGSI_SEMANTIC_COLOR: - cols++; + tab[i] = 2 + cols++; break; case TGSI_SEMANTIC_FOG: - fog = true; + fog = TRUE; + tab[i] = 6 + texs++; break; case TGSI_SEMANTIC_PSIZE: - psize = true; + psize = TRUE; + tab[i] = 1; break; case TGSI_SEMANTIC_GENERIC: - texs++; + tab[i] = 6 + texs++; break; default: debug_printf("r300: Unknown vertex input %d\n", @@ -105,6 +111,12 @@ static void r300_update_vertex_layout(struct r300_context* r300) if (!pos) { debug_printf("r300: Forcing vertex position attribute emit...\n"); + /* Make room for the position attribute + * at the beginning of the tab. */ + for (i = 1; i < 16; i++) { + tab[i] = tab[i-1]; + } + tab[0] = 0; } draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_POS, @@ -125,16 +137,17 @@ static void r300_update_vertex_layout(struct r300_context* r300) vinfo.hwfmt[2] |= (R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i); } - if (fog) { + for (i = 0; i < texs; i++) { draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_FOG, 0)); - vinfo.hwfmt[2] |= - (R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << cols); + draw_find_vs_output(r300->draw, TGSI_SEMANTIC_GENERIC, i)); + vinfo.hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i); + vinfo.hwfmt[3] |= (4 << (3 * i)); } - for (i = 0; i < texs; i++) { - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_GENERIC, i)); + if (fog) { + i++; + draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, + draw_find_vs_output(r300->draw, TGSI_SEMANTIC_FOG, 0)); vinfo.hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i); vinfo.hwfmt[3] |= (4 << (3 * i)); } @@ -152,18 +165,29 @@ static void r300_update_vertex_layout(struct r300_context* r300) (0xf << R300_WRITE_ENA_SHIFT)) for (i = 0; i < vinfo.num_attribs; i++) { + /* Make sure we have a proper destination for our attribute */ + if (tab[i] == -1) { + debug_printf("attrib count: %d, fp input count: %d\n", + vinfo.num_attribs, info->num_inputs); + for (i = 0; i < vinfo.num_attribs; i++) { + debug_printf("attrib: offset %d, interp %d, size %d," + " tab %d\n", vinfo.attrib[i].src_index, + vinfo.attrib[i].interp_mode, vinfo.attrib[i].emit, + tab[i]); + } + assert(0); + } + temp = translate_vertex_data_type(vinfo.attrib[i].emit) | - R300_SIGNED; + (tab[i] << R300_DST_VEC_LOC_SHIFT) | R300_SIGNED; if (i & 1) { r300->vertex_info.vap_prog_stream_cntl[i >> 1] &= 0xffff0000; r300->vertex_info.vap_prog_stream_cntl[i >> 1] |= - (translate_vertex_data_type(vinfo.attrib[i].emit) | - R300_SIGNED) << 16; + temp << 16; } else { r300->vertex_info.vap_prog_stream_cntl[i >> 1] &= 0xffff; r300->vertex_info.vap_prog_stream_cntl[i >> 1] |= - translate_vertex_data_type(vinfo.attrib[i].emit) | - R300_SIGNED; + temp; } r300->vertex_info.vap_prog_stream_cntl_ext[i >> 1] |= @@ -180,8 +204,85 @@ static void r300_update_vertex_layout(struct r300_context* r300) /* Set up the RS block. This is the part of the chipset that actually does * the rasterization of vertices into fragments. This is also the part of the * chipset that locks up if any part of it is even slightly wrong. */ -void r300_update_rs_block(struct r300_context* r300) +static void r300_update_rs_block(struct r300_context* r300) { + struct r300_rs_block* rs = r300->rs_block; + struct vertex_info* vinfo = &r300->vertex_info.vinfo; + int col_count = 0, fp_offset = 0, i, tex_count = 0; + + memset(rs, 0, sizeof(struct r300_rs_block)); + + if (r300_screen(r300->context.screen)->caps->is_r500) { + for (i = 0; i < vinfo->num_attribs; i++) { + switch (vinfo->attrib[i].interp_mode) { + case INTERP_LINEAR: + rs->ip[col_count] |= + R500_RS_COL_PTR(vinfo->attrib[i].src_index) | + R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA); + col_count++; + break; + case INTERP_PERSPECTIVE: + rs->ip[tex_count] |= + R500_RS_SEL_S(vinfo->attrib[i].src_index) | + R500_RS_SEL_T(vinfo->attrib[i].src_index + 1) | + R500_RS_SEL_R(vinfo->attrib[i].src_index + 2) | + R500_RS_SEL_Q(vinfo->attrib[i].src_index + 3); + tex_count++; + break; + } + } + + for (i = 0; i < tex_count; i++) { + rs->inst[i] |= R500_RS_INST_TEX_ID(i) | R500_RS_INST_TEX_CN_WRITE | + R500_RS_INST_TEX_ADDR(fp_offset); + fp_offset++; + } + + for (i = 0; i < col_count; i++) { + rs->inst[i] |= R500_RS_INST_COL_ID(i) | R500_RS_INST_COL_CN_WRITE | + R500_RS_INST_COL_ADDR(fp_offset); + fp_offset++; + } + + rs->inst_count = MAX2(col_count, tex_count); + } else { + for (i = 0; i < vinfo->num_attribs; i++) { + switch (vinfo->attrib[i].interp_mode) { + case INTERP_LINEAR: + rs->ip[col_count] |= + R300_RS_COL_PTR(vinfo->attrib[i].src_index) | + R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA); + col_count++; + break; + case INTERP_PERSPECTIVE: + rs->ip[tex_count] |= + R300_RS_TEX_PTR(vinfo->attrib[i].src_index) | + R300_RS_SEL_S(R300_RS_SEL_C0) | + R300_RS_SEL_T(R300_RS_SEL_C1) | + R300_RS_SEL_R(R300_RS_SEL_C2) | + R300_RS_SEL_Q(R300_RS_SEL_C3); + tex_count += 4; + break; + } + } + + for (i = 0; i < tex_count; i++) { + rs->inst[i] |= R300_RS_INST_TEX_ID(i) | R300_RS_INST_TEX_CN_WRITE | + R300_RS_INST_TEX_ADDR(fp_offset); + fp_offset++; + } + + for (i = 0; i < col_count; i++) { + rs->inst[i] |= R300_RS_INST_COL_ID(i) | R300_RS_INST_COL_CN_WRITE | + R300_RS_INST_COL_ADDR(fp_offset); + fp_offset++; + } + } + + rs->count = (tex_count * 4) | (col_count << R300_IC_COUNT_SHIFT) | + R300_HIRES_EN; + + rs->inst_count = MAX2(col_count, tex_count); } void r300_update_derived_state(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 005fb74ed6c..630ac3b2fc4 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -1,5 +1,6 @@ /* * Copyright 2009 Joakim Sindholt <[email protected]> + * Corbin Simpson <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,56 +28,319 @@ #include "r300_reg.h" +/* Some maths. These should probably find their way to u_math, if needed. */ + +static INLINE int pack_float_16_6x(float f) { + return ((int)(f * 6.0) & 0xffff); +} + +/* Blend state. */ + +static INLINE uint32_t r300_translate_blend_function(int blend_func) +{ + switch (blend_func) { + case PIPE_BLEND_ADD: + return R300_COMB_FCN_ADD_CLAMP; + case PIPE_BLEND_SUBTRACT: + return R300_COMB_FCN_SUB_CLAMP; + case PIPE_BLEND_REVERSE_SUBTRACT: + return R300_COMB_FCN_RSUB_CLAMP; + case PIPE_BLEND_MIN: + return R300_COMB_FCN_MIN; + case PIPE_BLEND_MAX: + return R300_COMB_FCN_MAX; + default: + debug_printf("r300: Unknown blend function %d\n", blend_func); + break; + } + return 0; +} + +/* XXX we can also offer the D3D versions of some of these... */ +static INLINE uint32_t r300_translate_blend_factor(int blend_fact) +{ + switch (blend_fact) { + case PIPE_BLENDFACTOR_ONE: + return R300_BLEND_GL_ONE; + case PIPE_BLENDFACTOR_SRC_COLOR: + return R300_BLEND_GL_SRC_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA: + return R300_BLEND_GL_SRC_ALPHA; + case PIPE_BLENDFACTOR_DST_ALPHA: + return R300_BLEND_GL_DST_ALPHA; + case PIPE_BLENDFACTOR_DST_COLOR: + return R300_BLEND_GL_DST_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: + return R300_BLEND_GL_SRC_ALPHA_SATURATE; + case PIPE_BLENDFACTOR_CONST_COLOR: + return R300_BLEND_GL_CONST_COLOR; + case PIPE_BLENDFACTOR_CONST_ALPHA: + return R300_BLEND_GL_CONST_ALPHA; + /* XXX WTF are these? + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: */ + case PIPE_BLENDFACTOR_ZERO: + return R300_BLEND_GL_ZERO; + case PIPE_BLENDFACTOR_INV_SRC_COLOR: + return R300_BLEND_GL_ONE_MINUS_SRC_COLOR; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: + return R300_BLEND_GL_ONE_MINUS_SRC_ALPHA; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + return R300_BLEND_GL_ONE_MINUS_DST_ALPHA; + case PIPE_BLENDFACTOR_INV_DST_COLOR: + return R300_BLEND_GL_ONE_MINUS_DST_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_COLOR: + return R300_BLEND_GL_ONE_MINUS_CONST_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: + return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA; + /* XXX see above + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */ + default: + debug_printf("r300: Unknown blend factor %d\n", blend_fact); + break; + } + return 0; +} + +/* DSA state. */ + +static INLINE uint32_t r300_translate_depth_stencil_function(int zs_func) +{ + switch (zs_func) { + case PIPE_FUNC_NEVER: + return R300_ZS_NEVER; + case PIPE_FUNC_LESS: + return R300_ZS_LESS; + case PIPE_FUNC_EQUAL: + return R300_ZS_EQUAL; + case PIPE_FUNC_LEQUAL: + return R300_ZS_LEQUAL; + case PIPE_FUNC_GREATER: + return R300_ZS_GREATER; + case PIPE_FUNC_NOTEQUAL: + return R300_ZS_NOTEQUAL; + case PIPE_FUNC_GEQUAL: + return R300_ZS_GEQUAL; + case PIPE_FUNC_ALWAYS: + return R300_ZS_ALWAYS; + default: + debug_printf("r300: Unknown depth/stencil function %d\n", + zs_func); + break; + } + return 0; +} + +static INLINE uint32_t r300_translate_stencil_op(int s_op) +{ + switch (s_op) { + case PIPE_STENCIL_OP_KEEP: + return R300_ZS_KEEP; + case PIPE_STENCIL_OP_ZERO: + return R300_ZS_ZERO; + case PIPE_STENCIL_OP_REPLACE: + return R300_ZS_REPLACE; + case PIPE_STENCIL_OP_INCR: + return R300_ZS_INCR; + case PIPE_STENCIL_OP_DECR: + return R300_ZS_DECR; + case PIPE_STENCIL_OP_INCR_WRAP: + return R300_ZS_INCR_WRAP; + case PIPE_STENCIL_OP_DECR_WRAP: + return R300_ZS_DECR_WRAP; + case PIPE_STENCIL_OP_INVERT: + return R300_ZS_INVERT; + default: + debug_printf("r300: Unknown stencil op %d", s_op); + break; + } + return 0; +} + +static INLINE uint32_t r300_translate_alpha_function(int alpha_func) +{ + switch (alpha_func) { + case PIPE_FUNC_NEVER: + return R300_FG_ALPHA_FUNC_NEVER; + case PIPE_FUNC_LESS: + return R300_FG_ALPHA_FUNC_LESS; + case PIPE_FUNC_EQUAL: + return R300_FG_ALPHA_FUNC_EQUAL; + case PIPE_FUNC_LEQUAL: + return R300_FG_ALPHA_FUNC_LE; + case PIPE_FUNC_GREATER: + return R300_FG_ALPHA_FUNC_GREATER; + case PIPE_FUNC_NOTEQUAL: + return R300_FG_ALPHA_FUNC_NOTEQUAL; + case PIPE_FUNC_GEQUAL: + return R300_FG_ALPHA_FUNC_GE; + case PIPE_FUNC_ALWAYS: + return R300_FG_ALPHA_FUNC_ALWAYS; + default: + debug_printf("r300: Unknown alpha function %d", alpha_func); + break; + } + return 0; +} + +/* Texture sampler state. */ + +static INLINE uint32_t r300_translate_wrap(int wrap) +{ + switch (wrap) { + case PIPE_TEX_WRAP_REPEAT: + return R300_TX_REPEAT; + case PIPE_TEX_WRAP_CLAMP: + return R300_TX_CLAMP; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + return R300_TX_CLAMP_TO_EDGE; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + return R300_TX_CLAMP_TO_BORDER; + case PIPE_TEX_WRAP_MIRROR_REPEAT: + return R300_TX_REPEAT | R300_TX_MIRRORED; + case PIPE_TEX_WRAP_MIRROR_CLAMP: + return R300_TX_CLAMP | R300_TX_MIRRORED; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; + default: + debug_printf("r300: Unknown texture wrap %d", wrap); + return 0; + } +} + +static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip) +{ + uint32_t retval = 0; + switch (min) { + case PIPE_TEX_FILTER_NEAREST: + retval |= R300_TX_MIN_FILTER_NEAREST; + case PIPE_TEX_FILTER_LINEAR: + retval |= R300_TX_MIN_FILTER_LINEAR; + case PIPE_TEX_FILTER_ANISO: + retval |= R300_TX_MIN_FILTER_ANISO; + default: + debug_printf("r300: Unknown texture filter %d", min); + break; + } + switch (mag) { + case PIPE_TEX_FILTER_NEAREST: + retval |= R300_TX_MAG_FILTER_NEAREST; + case PIPE_TEX_FILTER_LINEAR: + retval |= R300_TX_MAG_FILTER_LINEAR; + case PIPE_TEX_FILTER_ANISO: + retval |= R300_TX_MAG_FILTER_ANISO; + default: + debug_printf("r300: Unknown texture filter %d", mag); + break; + } + switch (mip) { + case PIPE_TEX_MIPFILTER_NONE: + retval |= R300_TX_MIN_FILTER_MIP_NONE; + case PIPE_TEX_MIPFILTER_NEAREST: + retval |= R300_TX_MIN_FILTER_MIP_NEAREST; + case PIPE_TEX_MIPFILTER_LINEAR: + retval |= R300_TX_MIN_FILTER_MIP_LINEAR; + default: + debug_printf("r300: Unknown texture filter %d", mip); + break; + } + + return retval; +} + +static INLINE uint32_t r300_anisotropy(float max_aniso) +{ + if (max_aniso >= 16.0f) { + return R300_TX_MAX_ANISO_16_TO_1; + } else if (max_aniso >= 8.0f) { + return R300_TX_MAX_ANISO_8_TO_1; + } else if (max_aniso >= 4.0f) { + return R300_TX_MAX_ANISO_4_TO_1; + } else if (max_aniso >= 2.0f) { + return R300_TX_MAX_ANISO_2_TO_1; + } else { + return R300_TX_MAX_ANISO_1_TO_1; + } +} + +/* Buffer formats. */ + static INLINE uint32_t r300_translate_colorformat(enum pipe_format format) { switch (format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - return R300_COLOR_FORMAT_ARGB8888; - case PIPE_FORMAT_I8_UNORM: - return R300_COLOR_FORMAT_I8; - case PIPE_FORMAT_A1R5G5B5_UNORM: - return R300_COLOR_FORMAT_ARGB1555; - case PIPE_FORMAT_R5G6B5_UNORM: - return R300_COLOR_FORMAT_RGB565; - /* XXX Not in pipe_format - case PIPE_FORMAT_A32R32G32B32: - return R300_COLOR_FORMAT_ARGB32323232; - case PIPE_FORMAT_A16R16G16B16: - return R300_COLOR_FORMAT_ARGB16161616; */ - case PIPE_FORMAT_A4R4G4B4_UNORM: - return R300_COLOR_FORMAT_ARGB4444; - /* XXX Not in pipe_format - case PIPE_FORMAT_A10R10G10B10_UNORM: - return R500_COLOR_FORMAT_ARGB10101010; - case PIPE_FORMAT_A2R10G10B10_UNORM: - return R500_COLOR_FORMAT_ARGB2101010; - case PIPE_FORMAT_I10_UNORM: - return R500_COLOR_FORMAT_I10; */ - default: - debug_printf("r300: Implementation error: " \ - "Got unsupported color format %s in %s\n", - pf_name(format), __FUNCTION__); - break; + /* 8-bit buffers */ + case PIPE_FORMAT_I8_UNORM: + return R300_COLOR_FORMAT_I8; + /* 16-bit buffers */ + case PIPE_FORMAT_R5G6B5_UNORM: + return R300_COLOR_FORMAT_RGB565; + case PIPE_FORMAT_A1R5G5B5_UNORM: + return R300_COLOR_FORMAT_ARGB1555; + case PIPE_FORMAT_A4R4G4B4_UNORM: + return R300_COLOR_FORMAT_ARGB4444; + /* 32-bit buffers */ + case PIPE_FORMAT_A8R8G8B8_UNORM: + return R300_COLOR_FORMAT_ARGB8888; + /* XXX Not in pipe_format + case PIPE_FORMAT_A32R32G32B32: + return R300_COLOR_FORMAT_ARGB32323232; + case PIPE_FORMAT_A16R16G16B16: + return R300_COLOR_FORMAT_ARGB16161616; */ + /* XXX Not in pipe_format + case PIPE_FORMAT_A10R10G10B10_UNORM: + return R500_COLOR_FORMAT_ARGB10101010; + case PIPE_FORMAT_A2R10G10B10_UNORM: + return R500_COLOR_FORMAT_ARGB2101010; + case PIPE_FORMAT_I10_UNORM: + return R500_COLOR_FORMAT_I10; */ + default: + debug_printf("r300: Implementation error: " \ + "Got unsupported color format %s in %s\n", + pf_name(format), __FUNCTION__); + break; } - return 0; } static INLINE uint32_t r300_translate_zsformat(enum pipe_format format) { switch (format) { - case PIPE_FORMAT_Z16_UNORM: - return R300_DEPTHFORMAT_16BIT_INT_Z; - /* XXX R300_DEPTHFORMAT_16BIT_13E3 anyone? */ - case PIPE_FORMAT_Z24S8_UNORM: - return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL; - default: - debug_printf("r300: Implementation error: " \ - "Got unsupported ZS format %s in %s\n", - pf_name(format), __FUNCTION__); - break; + /* 16-bit depth, no stencil */ + case PIPE_FORMAT_Z16_UNORM: + return R300_DEPTHFORMAT_16BIT_INT_Z; + /* 24-bit depth, 8-bit stencil */ + case PIPE_FORMAT_Z24S8_UNORM: + return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL; + default: + debug_printf("r300: Implementation error: " \ + "Got unsupported ZS format %s in %s\n", + pf_name(format), __FUNCTION__); + break; + } + return 0; +} + +/* Non-CSO state. (For now.) */ + +static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) +{ + switch (pipe_count) { + case 1: + return R300_GB_TILE_PIPE_COUNT_RV300; + break; + case 2: + return R300_GB_TILE_PIPE_COUNT_R300; + break; + case 3: + return R300_GB_TILE_PIPE_COUNT_R420_3P; + break; + case 4: + return R300_GB_TILE_PIPE_COUNT_R420; + break; } - return 0; } diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c new file mode 100644 index 00000000000..7fd7aefeb72 --- /dev/null +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -0,0 +1,54 @@ +/* + * Copyright 2009 Joakim Sindholt <[email protected]> + * Corbin Simpson <[email protected]> + * + * 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 + * on 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 + * THE AUTHOR(S) AND/OR THEIR 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 "r300_state_invariant.h" + +/* Calculate and emit invariant state. This is data that the 3D engine + * will probably want at the beginning of every CS, but it's not currently + * handled by any CSO setup, and in addition it doesn't really change much. + * + * Note that eventually this should be empty, but it's useful for development + * and general unduplication of code. */ +void r300_emit_invariant_state(struct r300_context* r300) +{ + struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; + CS_LOCALS(r300); + + BEGIN_CS(14); + /* Amount of time to wait for vertex fetches in PVS */ + OUT_CS_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff); + /* Various GB enables */ + OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | + R300_GB_LINE_STUFF_ENABLE | R300_GB_TRIANGLE_STUFF_ENABLE); + /* Subpixel multisampling for AA */ + OUT_CS_REG(R300_GB_MSPOS0, 0x66666666); + OUT_CS_REG(R300_GB_MSPOS1, 0x66666666); + /* GB tile config and pipe setup */ + OUT_CS_REG(R300_GB_TILE_CONFIG, R300_GB_TILE_DISABLE | + r300_translate_gb_pipes(caps->num_frag_pipes)); + /* Source of fog depth */ + OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W); + /* AA enable */ + OUT_CS_REG(R300_GB_AA_CONFIG, 0x0); + END_CS; +} diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h new file mode 100644 index 00000000000..8204bf9588b --- /dev/null +++ b/src/gallium/drivers/r300/r300_state_invariant.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * + * 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 + * on 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 + * THE AUTHOR(S) AND/OR THEIR 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 R300_STATE_INVARIANT_H +#define R300_STATE_INVARIANT_H + +#include "r300_context.h" +#include "r300_cs.h" +#include "r300_reg.h" +#include "r300_state_inlines.h" + +void r300_emit_invariant_state(struct r300_context* r300); + +#endif /* R300_STATE_INVARIANT_H */ diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c index 49e4a96f833..288d8dea15e 100644 --- a/src/gallium/drivers/r300/r300_surface.c +++ b/src/gallium/drivers/r300/r300_surface.c @@ -33,9 +33,10 @@ static void r300_surface_fill(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); CS_LOCALS(r300); - struct r300_capabilities* caps = ((struct r300_screen*)pipe->screen)->caps; + struct r300_capabilities* caps = r300_screen(pipe->screen)->caps; struct r300_texture* tex = (struct r300_texture*)dest->texture; int i; + float r, g, b, a; unsigned pixpitch = tex->stride / tex->tex.block.size; r = (float)((color >> 16) & 0xff) / 255.0f; @@ -55,7 +56,14 @@ static void r300_surface_fill(struct pipe_context* pipe, return; }*/ - BEGIN_CS(163 + (caps->is_r500 ? 22 : 14) + (caps->has_tcl ? 4 : 2)); + r300_emit_invariant_state(r300); + + r300_emit_blend_state(r300, &blend_clear_state); + r300_emit_blend_color_state(r300, &blend_color_clear_state); + r300_emit_dsa_state(r300, &dsa_clear_state); + r300_emit_rs_state(r300, &rs_clear_state); + + BEGIN_CS(129 + (caps->is_r500 ? 22 : 14) + (caps->has_tcl ? 4 : 2)); /* Flush PVS. */ OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); @@ -69,7 +77,12 @@ static void r300_surface_fill(struct pipe_context* pipe, OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, 0xFFFFFF); OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0x0); /* XXX endian */ - OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VC_NO_SWAP); + if (caps->has_tcl) { + OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VC_NO_SWAP); + } else { + OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VC_NO_SWAP | + R300_VAP_TCL_BYPASS); + } OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0, 0x0); /* XXX magic number not in r300_reg */ OUT_CS_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0xAAAAAAAA); @@ -79,18 +92,6 @@ static void r300_surface_fill(struct pipe_context* pipe, OUT_CS_32F(1.0); OUT_CS_32F(1.0); OUT_CS_32F(1.0); - /* XXX is this too long? */ - OUT_CS_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xFFFF); - OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | - R300_GB_LINE_STUFF_ENABLE | R300_GB_TRIANGLE_STUFF_ENABLE); - /* XXX more magic numbers */ - OUT_CS_REG(R300_GB_MSPOS0, 0x66666666); - OUT_CS_REG(R300_GB_MSPOS1, 0x66666666); - /* XXX why doesn't classic Mesa write the number of pipes, too? */ - OUT_CS_REG(R300_GB_TILE_CONFIG, R300_GB_TILE_ENABLE | - R300_GB_TILE_SIZE_16); - OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W); - OUT_CS_REG(R300_GB_AA_CONFIG, 0x0); /* XXX point tex stuffing */ OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1); OUT_CS_32F(0.0); @@ -102,9 +103,6 @@ static void r300_surface_fill(struct pipe_context* pipe, OUT_CS_REG(R300_GA_POINT_MINMAX, 0x6 | (0x1800 << R300_GA_POINT_MINMAX_MAX_SHIFT)); /* XXX this big chunk should be refactored into rs_state */ - OUT_CS_REG(R300_GA_LINE_CNTL, 0x00030006); - OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, 0x3BAAAAAB); - OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, 0x00000000); OUT_CS_REG(R300_GA_LINE_S0, 0x00000000); OUT_CS_REG(R300_GA_LINE_S1, 0x3F800000); OUT_CS_REG(R300_GA_ENHANCE, 0x00000002); @@ -117,12 +115,6 @@ static void r300_surface_fill(struct pipe_context* pipe, OUT_CS_REG(R300_GA_FOG_SCALE, 0x3DBF1412); OUT_CS_REG(R300_GA_FOG_OFFSET, 0x00000000); OUT_CS_REG(R300_SU_TEX_WRAP, 0x00000000); - OUT_CS_REG(R300_SU_POLY_OFFSET_FRONT_SCALE, 0x00000000); - OUT_CS_REG(R300_SU_POLY_OFFSET_FRONT_OFFSET, 0x00000000); - OUT_CS_REG(R300_SU_POLY_OFFSET_BACK_SCALE, 0x00000000); - OUT_CS_REG(R300_SU_POLY_OFFSET_BACK_OFFSET, 0x00000000); - OUT_CS_REG(R300_SU_POLY_OFFSET_ENABLE, 0x00000000); - OUT_CS_REG(R300_SU_CULL_MODE, 0x00000000); OUT_CS_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF); OUT_CS_REG(R300_SU_DEPTH_OFFSET, 0x00000000); OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C); @@ -190,11 +182,6 @@ static void r300_surface_fill(struct pipe_context* pipe, R300_PS_UCP_MODE_CLIP_AS_TRIFAN); } - /* The size of the point we're about to draw, in sixths of pixels */ - OUT_CS_REG(R300_GA_POINT_SIZE, - ((h * 6) & R300_POINTSIZE_Y_MASK) | - ((w * 6) << R300_POINTSIZE_X_SHIFT)); - /* XXX */ OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa); @@ -240,7 +227,7 @@ static void r300_surface_fill(struct pipe_context* pipe, r300_emit_fragment_shader(r300, &r300_passthrough_fragment_shader); } - BEGIN_CS(8 + (caps->has_tcl ? 20 : 2)); + BEGIN_CS(7 + (caps->has_tcl ? 21 : 2)); OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); OUT_CS(R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A); OUT_CS(R300_US_OUT_FMT_UNUSED); @@ -277,9 +264,10 @@ static void r300_surface_fill(struct pipe_context* pipe, } END_CS; - r300_emit_blend_state(r300, &blend_clear_state); - r300_emit_blend_color_state(r300, &blend_color_clear_state); - r300_emit_dsa_state(r300, &dsa_clear_state); + /* The size of the point we're about to draw, in sixths of pixels */ + OUT_CS_REG(R300_GA_POINT_SIZE, + ((h * 6) & R300_POINTSIZE_Y_MASK) | + ((w * 6) << R300_POINTSIZE_X_SHIFT)); BEGIN_CS(24); /* Flush colorbuffer and blend caches. */ diff --git a/src/gallium/drivers/r300/r300_surface.h b/src/gallium/drivers/r300/r300_surface.h index 442eac2cf2e..807aad39e49 100644 --- a/src/gallium/drivers/r300/r300_surface.h +++ b/src/gallium/drivers/r300/r300_surface.h @@ -57,4 +57,16 @@ const struct r300_dsa_state dsa_clear_state = { .stencil_ref_bf = 0x0, }; +const struct r300_rs_state rs_clear_state = { + .line_control = 0x00030006, + .depth_scale_front = 0x0, + .depth_offset_front = 0x0, + .depth_scale_back = 0x0, + .depth_offset_back = 0x0, + .polygon_offset_enable = 0x0, + .cull_mode = 0x0, + .line_stipple_config = 0x3BAAAAAB, + .line_stipple_value = 0x0, +}; + #endif /* R300_SURFACE_H */ diff --git a/src/gallium/drivers/r300/r300_swtcl_emit.c b/src/gallium/drivers/r300/r300_swtcl_emit.c index 5b028aaf7b7..f9baaade1e3 100644 --- a/src/gallium/drivers/r300/r300_swtcl_emit.c +++ b/src/gallium/drivers/r300/r300_swtcl_emit.c @@ -27,6 +27,7 @@ #include "r300_cs.h" #include "r300_context.h" #include "r300_reg.h" +#include "r300_state_derived.h" /* r300_swtcl_emit: Vertex and index buffer primitive emission. No HW TCL. */ @@ -91,9 +92,9 @@ static boolean r300_swtcl_render_allocate_vertices(struct vbuf_render* render, r300render->vertex_size = vertex_size; if (r300render->vbo) { - return true; + return TRUE; } else { - return false; + return FALSE; } } @@ -167,11 +168,11 @@ static boolean r300_swtcl_render_set_primitive(struct vbuf_render* render, r300render->hwprim = R300_VAP_VF_CNTL__PRIM_POLYGON; break; default: - return false; + return FALSE; break; } - return true; + return TRUE; } static void prepare_render(struct r300_swtcl_render* render) @@ -191,12 +192,15 @@ static void prepare_render(struct r300_swtcl_render* render) * PACKET3 [3D_LOAD_VBPNTR] * COUNT [1] * FORMAT [size | stride << 8] + * OFFSET [0] * VBPNTR [relocated BO] */ BEGIN_CS(5); OUT_CS(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, 3)); OUT_CS(1); - OUT_CS(r300->vertex_info.vinfo.size | (r300->vertex_info.vinfo.size << 8)); + OUT_CS(r300->vertex_info.vinfo.size | + (r300->vertex_info.vinfo.size << 8)); + OUT_CS(render->vbo_offset); OUT_CS_RELOC(render->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; } @@ -218,7 +222,7 @@ static void r300_swtcl_render_draw_arrays(struct vbuf_render* render, BEGIN_CS(2); OUT_CS(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0)); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | - r300render->hwprim | R300_VAP_VF_CNTL__INDEX_SIZE_32bit); + r300render->hwprim); END_CS; } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index edd43706634..8251a597eab 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -31,8 +31,9 @@ static void r300_setup_miptree(struct r300_texture* tex) { struct pipe_texture* base = &tex->tex; int stride, size, offset; + int i; - for (int i = 0; i <= base->last_level; i++) { + for (i = 0; i <= base->last_level; i++) { if (i > 0) { base->width[i] = minify(base->width[i-1]); base->height[i] = minify(base->height[i-1]); diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index d56eed80a4f..eef6e5806c9 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -60,6 +60,7 @@ struct softpipe_vbuf_render struct softpipe_context *softpipe; uint prim; uint vertex_size; + uint nr_vertices; uint vertex_buffer_size; void *vertex_buffer; }; @@ -95,12 +96,44 @@ sp_vbuf_allocate_vertices(struct vbuf_render *vbr, } cvbr->vertex_size = vertex_size; + cvbr->nr_vertices = nr_vertices; + return cvbr->vertex_buffer != NULL; } static void sp_vbuf_release_vertices(struct vbuf_render *vbr) { +#if 0 + { + struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); + const struct vertex_info *info = + softpipe_get_vbuf_vertex_info(cvbr->softpipe); + const float *vtx = (const float *) cvbr->vertex_buffer; + uint i, j; + debug_printf("%s (vtx_size = %u, vtx_used = %u)\n", + __FUNCTION__, cvbr->vertex_size, cvbr->nr_vertices); + for (i = 0; i < cvbr->nr_vertices; i++) { + for (j = 0; j < info->num_attribs; j++) { + uint k; + switch (info->attrib[j].emit) { + case EMIT_4F: k = 4; break; + case EMIT_3F: k = 3; break; + case EMIT_2F: k = 2; break; + case EMIT_1F: k = 1; break; + default: assert(0); + } + debug_printf("Vert %u attr %u: ", i, j); + while (k-- > 0) { + debug_printf("%g ", vtx[0]); + vtx++; + } + debug_printf("\n"); + } + } + } +#endif + /* keep the old allocation for next time */ } diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 28a9784b164..142ce230fc0 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -243,9 +243,11 @@ softpipe_get_tex_surface(struct pipe_screen *screen, ps->level = level; ps->zslice = zslice; - if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) { - ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) * - pt->nblocksy[level] * spt->stride[level]; + if (pt->target == PIPE_TEXTURE_CUBE) { + ps->offset += face * pt->nblocksy[level] * spt->stride[level]; + } + else if (pt->target == PIPE_TEXTURE_3D) { + ps->offset += zslice * pt->nblocksy[level] * spt->stride[level]; } else { assert(face == 0); @@ -283,14 +285,13 @@ softpipe_get_tex_transfer(struct pipe_screen *screen, { struct softpipe_texture *sptex = softpipe_texture(texture); struct softpipe_transfer *spt; - struct pipe_transfer *pt; assert(texture); assert(level <= texture->last_level); spt = CALLOC_STRUCT(softpipe_transfer); - pt = &spt->base; if (spt) { + struct pipe_transfer *pt = &spt->base; pt->refcount = 1; pipe_texture_reference(&pt->texture, texture); pt->format = texture->format; @@ -302,23 +303,26 @@ softpipe_get_tex_transfer(struct pipe_screen *screen, pt->nblocksx = texture->nblocksx[level]; pt->nblocksy = texture->nblocksy[level]; pt->stride = sptex->stride[level]; - spt->offset = sptex->level_offset[level]; pt->usage = usage; pt->face = face; pt->level = level; pt->zslice = zslice; - if (texture->target == PIPE_TEXTURE_CUBE || - texture->target == PIPE_TEXTURE_3D) { - spt->offset += ((texture->target == PIPE_TEXTURE_CUBE) ? face : - zslice) * pt->nblocksy * pt->stride; + spt->offset = sptex->level_offset[level]; + + if (texture->target == PIPE_TEXTURE_CUBE) { + spt->offset += face * pt->nblocksy * pt->stride; + } + else if (texture->target == PIPE_TEXTURE_3D) { + spt->offset += zslice * pt->nblocksy * pt->stride; } else { assert(face == 0); assert(zslice == 0); } + return pt; } - return pt; + return NULL; } diff --git a/src/gallium/drivers/trace/tr_dump.c b/src/gallium/drivers/trace/tr_dump.c index d98cef221b7..8757ac8bec9 100644 --- a/src/gallium/drivers/trace/tr_dump.c +++ b/src/gallium/drivers/trace/tr_dump.c @@ -40,7 +40,7 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) #include <stdlib.h> #endif @@ -236,7 +236,7 @@ boolean trace_dump_trace_begin() trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n"); trace_dump_writes("<trace version='0.1'>\n"); -#if defined(PIPE_OS_LINUX) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) /* Linux applications rarely cleanup GL / Gallium resources so catch * application exit here */ atexit(trace_dump_trace_close); |