summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/i915simple/i915_texture.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/i915simple/i915_texture.c')
-rw-r--r--src/gallium/drivers/i915simple/i915_texture.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c
index 1ed38563a05..7f0a4dbd932 100644
--- a/src/gallium/drivers/i915simple/i915_texture.c
+++ b/src/gallium/drivers/i915simple/i915_texture.c
@@ -738,6 +738,95 @@ i915_tex_surface_destroy(struct pipe_surface *surf)
/*
+ * Screen transfer functions
+ */
+
+
+static struct pipe_transfer*
+i915_get_tex_transfer(struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage, unsigned x, unsigned y,
+ unsigned w, unsigned h)
+{
+ struct i915_texture *tex = (struct i915_texture *)texture;
+ struct i915_transfer *trans;
+ unsigned offset; /* in bytes */
+
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ offset = tex->image_offset[level][face];
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ offset = tex->image_offset[level][zslice];
+ }
+ else {
+ offset = tex->image_offset[level][0];
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ trans = CALLOC_STRUCT(i915_transfer);
+ if (trans) {
+ pipe_texture_reference(&trans->base.texture, texture);
+ trans->base.format = trans->base.format;
+ trans->base.x = x;
+ trans->base.y = y;
+ trans->base.width = w;
+ trans->base.height = h;
+ trans->base.block = texture->block;
+ trans->base.nblocksx = texture->nblocksx[level];
+ trans->base.nblocksy = texture->nblocksy[level];
+ trans->base.stride = tex->stride;
+ trans->offset = offset;
+ trans->base.usage = usage;
+ }
+ return &trans->base;
+}
+
+static void *
+i915_transfer_map(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
+{
+ struct i915_texture *tex = (struct i915_texture *)transfer->texture;
+ char *map;
+ unsigned flags = 0;
+
+ if (transfer->usage != PIPE_TRANSFER_WRITE)
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+
+ if (transfer->usage != PIPE_TRANSFER_READ)
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+
+ map = pipe_buffer_map(screen, tex->buffer, flags);
+ if (map == NULL)
+ return NULL;
+
+ if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
+ /* XXX Do something to notify contexts of a texture change. */
+ }
+
+ return map + i915_transfer(transfer)->offset +
+ transfer->y / transfer->block.height * transfer->stride +
+ transfer->x / transfer->block.width * transfer->block.size;
+}
+
+static void
+i915_transfer_unmap(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
+{
+ struct i915_texture *tex = (struct i915_texture *)transfer->texture;
+ pipe_buffer_unmap(screen, tex->buffer);
+}
+
+static void
+i915_tex_transfer_destroy(struct pipe_transfer *trans)
+{
+ pipe_texture_reference(&trans->texture, NULL);
+ FREE(trans);
+}
+
+
+/*
* Other texture functions
*/
@@ -750,6 +839,10 @@ i915_init_screen_texture_functions(struct i915_screen *is)
is->base.texture_destroy = i915_texture_destroy;
is->base.get_tex_surface = i915_get_tex_surface;
is->base.tex_surface_destroy = i915_tex_surface_destroy;
+ is->base.get_tex_transfer = i915_get_tex_transfer;
+ is->base.transfer_map = i915_transfer_map;
+ is->base.transfer_unmap = i915_transfer_unmap;
+ is->base.tex_transfer_destroy = i915_tex_transfer_destroy;
}
boolean i915_get_texture_buffer(struct pipe_texture *texture,