diff options
-rw-r--r-- | src/gallium/drivers/i915/i915_resource_texture.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index aad5235a6a..3de65ac872 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -754,6 +754,27 @@ i915_texture_transfer_map(struct pipe_context *pipe, if (resource->target != PIPE_TEXTURE_3D && resource->target != PIPE_TEXTURE_CUBE) assert(box->z == 0); + + if (resource->target == PIPE_TEXTURE_2D && + resource->usage == PIPE_USAGE_ONCE && + transfer->usage == PIPE_TRANSFER_WRITE) { + size_t size; + + /* We can do the upload in a single write call */ + if (!resource->last_level && + transfer->box.width == resource->width0) { + assert(!transfer->box.x); + transfer->stride = tex->stride; + } else { + transfer->stride = util_format_get_stride(format, transfer->box.width); + } + + size = util_format_get_2d_size(format, transfer->stride, + transfer->box.height); + transfer->data = MALLOC(size); + return transfer->data; + } + offset = i915_texture_offset(tex, transfer->level, box->z); map = iws->buffer_map(iws, tex->buffer, @@ -772,7 +793,41 @@ i915_texture_transfer_unmap(struct pipe_context *pipe, { struct i915_texture *tex = i915_texture(transfer->resource); struct i915_winsys *iws = i915_screen(tex->b.b.screen)->iws; - iws->buffer_unmap(iws, tex->buffer); + enum pipe_format format = tex->b.b.format; + size_t offset; + size_t size; + + if (!transfer->data) { + iws->buffer_unmap(iws, tex->buffer); + return; + } + + offset = i915_texture_offset(tex, transfer->level, transfer->box.z); + + if (!tex->b.b.last_level && + tex->b.b.width0 == transfer->box.width) { + unsigned nby = util_format_get_nblocksy(format, transfer->box.y); + assert(!offset); + assert(!transfer->box.x); + assert(tex->stride == transfer->stride); + + offset += tex->stride * nby; + size = util_format_get_2d_size(format, transfer->stride, + transfer->box.height); + iws->buffer_write(iws, tex->buffer, offset, size, transfer->data); + + } else { + unsigned nby = util_format_get_nblocksy(format, transfer->box.y); + int i; + offset += util_format_get_stride(format, transfer->box.x); + size = transfer->stride; + + for (i = 0; i < nby; i++) { + iws->buffer_write(iws, tex->buffer, offset, size, transfer->data); + offset += tex->stride; + } + } + FREE(transfer->data); } @@ -811,6 +866,8 @@ i915_texture_create(struct pipe_screen *screen, tex->b.b.screen = screen; tex->tiling = i915_texture_tiling(is, tex); + if (template->usage == PIPE_USAGE_ONCE) + tex->tiling = I915_TILE_NONE; if (is->is_i945) { if (!i945_texture_layout(tex)) |