diff options
Diffstat (limited to 'src/gallium/drivers/nv20/nv20_miptree.c')
-rw-r--r-- | src/gallium/drivers/nv20/nv20_miptree.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/src/gallium/drivers/nv20/nv20_miptree.c b/src/gallium/drivers/nv20/nv20_miptree.c index 8e4cc809027..ef7e9c5428e 100644 --- a/src/gallium/drivers/nv20/nv20_miptree.c +++ b/src/gallium/drivers/nv20/nv20_miptree.c @@ -51,10 +51,37 @@ nv20_miptree_layout(struct nv20_miptree *nv20mt) } static struct pipe_texture * +nv20_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, + const unsigned *stride, struct pipe_buffer *pb) +{ + struct nv20_miptree *mt; + + /* Only supports 2D, non-mipmapped textures for the moment */ + if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || + pt->depth[0] != 1) + return NULL; + + mt = CALLOC_STRUCT(nv20_miptree); + if (!mt) + return NULL; + + mt->base = *pt; + mt->base.refcount = 1; + mt->base.screen = pscreen; + mt->level[0].pitch = stride[0]; + mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); + + pipe_buffer_reference(pscreen, &mt->buffer, pb); + return &mt->base; +} + +static struct pipe_texture * nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) { struct pipe_winsys *ws = screen->winsys; struct nv20_miptree *mt; + unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | + NOUVEAU_BUFFER_USAGE_TEXTURE; mt = MALLOC(sizeof(struct nv20_miptree)); if (!mt) @@ -63,10 +90,35 @@ nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) mt->base.refcount = 1; mt->base.screen = screen; + /* Swizzled textures must be POT */ + if (pt->width[0] & (pt->width[0] - 1) || + pt->height[0] & (pt->height[0] - 1)) + mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + else + if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | + PIPE_TEXTURE_USAGE_DISPLAY_TARGET)) + mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + else + if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) + mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + else { + switch (pt->format) { + /* TODO: Figure out which formats can be swizzled */ + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_R16_SNORM: + break; + default: + mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + } + } + + if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) + buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE; + nv20_miptree_layout(mt); - mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL, - mt->total_size); + mt->buffer = ws->buffer_create(ws, 256, buf_usage, mt->total_size); if (!mt->buffer) { FREE(mt); return NULL; @@ -146,6 +198,7 @@ nv20_miptree_surface_release(struct pipe_screen *pscreen, void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen) { pscreen->texture_create = nv20_miptree_create; + pscreen->texture_blanket = nv20_miptree_blanket; pscreen->texture_release = nv20_miptree_release; pscreen->get_tex_surface = nv20_miptree_surface_get; pscreen->tex_surface_release = nv20_miptree_surface_release; |