summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/i915/i915_resource_texture.c59
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))