Commit 51c25117 authored by Keith Whitwell's avatar Keith Whitwell

gallium: work in progress on layering resources on top of old textures

Helper code in an aux module to avoid rewriting all the drivers.
parent fb6764d3
......@@ -64,6 +64,8 @@ C_SOURCES = \
pipebuffer/pb_bufmgr_pool.c \
pipebuffer/pb_bufmgr_slab.c \
pipebuffer/pb_validate.c \
piperesource/rm_context.c \
piperesource/rm_screen.c \
rbug/rbug_connection.c \
rbug/rbug_core.c \
rbug/rbug_texture.c \
......
......@@ -642,11 +642,11 @@ enum pipe_error cso_set_sampler_textures( struct cso_context *ctx,
textures[i],
&templ);
pipe_texture_reference(&ctx->textures[i], textures[i]);
pipe_resource_reference(&ctx->textures[i], textures[i]);
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], view);
}
for ( ; i < PIPE_MAX_SAMPLERS; i++) {
pipe_texture_reference(&ctx->textures[i], NULL);
pipe_resource_reference(&ctx->textures[i], NULL);
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL);
}
......@@ -666,7 +666,7 @@ void cso_save_sampler_textures( struct cso_context *ctx )
assert(!ctx->textures_saved[i]);
assert(!ctx->fragment_sampler_views_saved[i]);
pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]);
pipe_resource_reference(&ctx->textures_saved[i], ctx->textures[i]);
pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i],
ctx->fragment_sampler_views[i]);
}
......@@ -679,7 +679,7 @@ void cso_restore_sampler_textures( struct cso_context *ctx )
ctx->nr_textures = ctx->nr_textures_saved;
for (i = 0; i < ctx->nr_textures; i++) {
pipe_texture_reference(&ctx->textures[i], NULL);
pipe_resource_reference(&ctx->textures[i], NULL);
ctx->textures[i] = ctx->textures_saved[i];
ctx->textures_saved[i] = NULL;
......@@ -688,7 +688,7 @@ void cso_restore_sampler_textures( struct cso_context *ctx )
ctx->fragment_sampler_views_saved[i] = NULL;
}
for ( ; i < PIPE_MAX_SAMPLERS; i++) {
pipe_texture_reference(&ctx->textures[i], NULL);
pipe_resource_reference(&ctx->textures[i], NULL);
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL);
}
......
#ifndef RM_PRIVATE_H
#define RM_PRIVATE_H
#include "rm_public.h"
struct rm_screen {
struct pipe_screen *screen;
struct rm_screen_callbacks cb;
unsigned default_buffer_alignment;
};
struct rm_context {
struct pipe_context *pipe;
struct rm_screen *rm_screen; /* ? */
struct rm_context_callbacks cb;
};
#endif
#include "rm.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
struct rm_transfer {
struct pipe_transfer base;
struct pipe_tex_transfer *tex_transfer;
struct pipe_buffer *buffer;
unsigned buffer_usage;
};
static INLINE struct rm_transfer *rm_transfer( struct pipe_transfer *t )
{
return (struct rm_transfer *)t;
}
struct pipe_transfer *rm_get_transfer(struct rm_context *rm_ctx,
struct pipe_resource *resource,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box)
{
struct rm_transfer *transfer;
struct rm_resource *rmr = rm_resource(resource);
transfer = CALLOC_STRUCT(rm_transfer);
if (transfer == NULL)
return NULL;
transfer->base.resource = resource;
if (rmr->texture && box->depth == 1) {
transfer->tex_transfer = rm_ctx->cb.get_tex_transfer(rm_ctx->pipe,
rmr->texture,
sr.face,
sr.level,
box->z,
usage,
box->x,
box->y,
box->width,
box->height);
}
else if (rmr->texture && box->depth > 1) {
/* TBD. Nobody is using this yet, hopefully can migrate drivers
* to new interfaces before I have to implement some sort of a
* workaround here.
*/
assert(0);
}
else {
transfer->buffer = rm_resource(resource)->buffer;
transfer->buffer_usage = buffer_usage(usage);
}
assert(transfer->buffer || transfer->tex_transfer);
return &transfer->base;
}
void rm_transfer_destroy(struct rm_context *rm_ctx,
struct pipe_transfer *transfer)
{
struct rm_transfer *rmt = rm_transfer(transfer);
if (rmt->tex_transfer)
rm_ctx->cb.transfer_destroy( rm_ctx->pipe, rmt->tex_transfer );
FREE(rmt);
}
void *rm_transfer_map( struct rm_context *rm_ctx,
struct pipe_transfer *transfer )
{
struct rm_transfer *rmt = rm_transfer(transfer);
if (rmt->tex_transfer) {
return rm_ctx->cb.transfer_map( rm_ctx->pipe,
rmt->tex_transfer );
}
else {
return rm_ctx->rm_screen->cb.buffer_map( rm_ctx->rm_screen->screen,
rmt->buffer,
rmt->buffer_usage );
}
}
/* If transfer was created with WRITE|FLUSH_EXPLICIT, only the
* regions specified with this call are guaranteed to be written to
* the resource.
*/
void rm_transfer_flush_region( struct rm_context *rm_ctx,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
struct rm_transfer *rmt = rm_transfer(transfer);
if (rmt->tex_transfer) {
/* no such action */
}
else if (rm_ctx->rm_screen->cb.buffer_flush_mapped_range) {
rm_ctx->rm_screen->cb.buffer_flush_mapped_range( rm_ctx->rm_screen->screen,
rmt->buffer,
box->x,
box->width);
}
else {
/* no such action */
}
}
void rm_transfer_unmap( struct rm_context *rm_ctx,
struct pipe_transfer *transfer )
{
struct rm_transfer *rmt = rm_transfer(transfer);
if (rmt->tex_transfer) {
rm_ctx->cb.transfer_unmap( rm_ctx->pipe,
rmt->tex_transfer );
}
else {
struct pipe_buffer *buffer = rmt->buffer;
rm_ctx->rm_screen->cb.buffer_unmap( rm_ctx->rm_screen->screen,
buffer );
}
}
/* One-shot transfer operation with data supplied in a user
* pointer. XXX: strides??
*/
void rm_transfer_inline_write( struct rm_context *rm_ctx,
struct pipe_resource *resource,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box,
const void *data )
{
struct pipe_transfer *transfer = NULL;
char *map = NULL;
transfer = rm_get_transfer(rm_ctx,
resource,
sr,
usage,
box );
if (transfer == NULL)
goto out;
map = rm_transfer_map(rm_ctx, transfer);
if (map == NULL)
goto out;
assert(box->depth == 1); /* XXX: fix me */
util_copy_rect(map,
resource->format,
transfer->stride, /* bytes? */
0, 0,
box->width,
box->height,
data,
box->width, /* bytes? texels? */
0, 0);
out:
if (map)
rm_transfer_unmap(rm_ctx, transfer);
if (transfer)
rm_transfer_destroy(rm_ctx, transfer);
}
/* One-shot read transfer operation with data returned in a user
* pointer. XXX: strides??
*/
void rm_transfer_inline_read( struct rm_context *rm_ctx,
struct pipe_resource *resource,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box,
void *data )
{
struct pipe_transfer *transfer = NULL;
char *map = NULL;
transfer = rm_get_transfer(rm_ctx,
resource,
sr,
usage,
box );
if (transfer == NULL)
goto out;
map = rm_transfer_map(rm_ctx, transfer);
if (map == NULL)
goto out;
assert(box->depth == 1); /* XXX: fix me */
util_copy_rect(data,
resource->format,
transfer->stride, /* bytes? */
0, 0,
box->width,
box->height,
map,
box->width, /* bytes? texels? */
0, 0);
out:
if (map)
rm_transfer_unmap(rm_ctx, transfer);
if (transfer)
rm_transfer_destroy(rm_ctx, transfer);
}
struct rm_context *
rm_context_create( struct pipe_context *pipe,
struct rm_screen *rm_screen,
struct rm_context_callbacks *cb)
{
struct rm_context *rm_context;
rm_context = CALLOC_STRUCT(rm_context);
if (rm_context == NULL)
return NULL;
rm_context->cb = *cb;
rm_context->rm_screen = rm_screen;
rm_context->pipe = pipe;
return rm_context;
}
#ifndef RM_PUBLIC_H
#define RM_PUBLIC_H
#include "pipe/p_state.h"
/* Here are the old pipe_buffer and pipe_texture structs, almost as
* they were. Old pre-resources driver code that creates and
* manipulates these structs can be used to implement the new
* pipe_resource behaviour using this adaptor module.
*/
struct pipe_buffer
{
struct pipe_reference reference;
struct rm_screen *screen; /* Note! */
unsigned size;
unsigned alignment;
unsigned usage;
};
struct pipe_texture
{
struct pipe_reference reference;
struct rm_screen *screen; /* Note! */
enum pipe_texture_target target;
enum pipe_format format;
unsigned width0;
unsigned height0;
unsigned depth0;
unsigned last_level:8;
unsigned nr_samples:8;
unsigned tex_usage; /**< bitmask of PIPE_TEXTURE_USAGE_* */
};
/* Have to give the legacy transfer struct a new name to avoid
* conflicts.
*/
struct pipe_tex_transfer
{
unsigned x; /**< x offset from start of texture image */
unsigned y; /**< y offset from start of texture image */
unsigned width; /**< logical width in pixels */
unsigned height; /**< logical height in pixels */
unsigned stride; /**< stride in bytes between rows of blocks */
enum pipe_transfer_usage usage; /**< PIPE_TRANSFER_* */
struct pipe_texture *texture; /**< texture to transfer to/from */
unsigned face;
unsigned level;
unsigned zslice;
};
struct rm_resource {
struct pipe_resource base;
struct pipe_buffer *buffer;
struct pipe_texture *texture;
};
static INLINE struct rm_resource *
rm_resource( struct pipe_resource *resource )
{
return (struct rm_resource *)resource;
}
static INLINE struct pipe_texture *
rm_texture( struct pipe_resource *resource )
{
return rm_resource(resource)->texture;
}
static INLINE struct pipe_buffer *
rm_buffer( struct pipe_resource *resource )
{
return rm_resource(resource)->buffer;
}
struct rm_screen_callbacks {
struct pipe_texture * (*texture_create)(struct pipe_screen *,
const struct pipe_texture *templat);
struct pipe_texture * (*texture_from_handle)(struct pipe_screen *,
const struct pipe_texture *templat,
struct winsys_handle *handle);
boolean (*texture_get_handle)(struct pipe_screen *,
struct pipe_texture *tex,
struct winsys_handle *handle);
void (*texture_destroy)(struct pipe_screen *,
struct pipe_texture *pt);
struct pipe_surface *(*get_tex_surface)(struct pipe_screen *,
struct pipe_texture *texture,
unsigned face, unsigned level,
unsigned zslice,
unsigned usage );
void (*tex_surface_destroy)(struct pipe_surface *);
/* Buffer functions:
*/
struct pipe_buffer *(*buffer_create)( struct pipe_screen *screen,
unsigned alignment,
unsigned usage,
unsigned size );
struct pipe_buffer *(*user_buffer_create)(struct pipe_screen *screen,
void *ptr,
unsigned bytes);
void *(*buffer_map)( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned usage );
void *(*buffer_map_range)( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned offset,
unsigned length,
unsigned usage);
void (*buffer_flush_mapped_range)( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned offset,
unsigned length);
void (*buffer_unmap)( struct pipe_screen *screen,
struct pipe_buffer *buf );
void (*buffer_destroy)( struct pipe_screen *screen,
struct pipe_buffer *buf );
};
struct rm_context_callbacks {
unsigned int (*is_texture_referenced)(struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face, unsigned level);
unsigned int (*is_buffer_referenced)(struct pipe_context *pipe,
struct pipe_buffer *buf);
struct pipe_tex_transfer *(*get_tex_transfer)(struct pipe_context *,
struct pipe_texture *texture,
unsigned face, unsigned level,
unsigned zslice,
enum pipe_transfer_usage usage,
unsigned x, unsigned y,
unsigned w, unsigned h);
void (*transfer_destroy)(struct pipe_context *,
struct pipe_tex_transfer *);
void *(*transfer_map)( struct pipe_context *,
struct pipe_tex_transfer *transfer );
void (*transfer_unmap)( struct pipe_context *,
struct pipe_tex_transfer *transfer );
};
struct rm_screen *
rm_screen_create( struct pipe_screen *screen,
struct rm_screen_callbacks *callbacks,
unsigned default_buffer_alignment);
struct rm_context *
rm_context_create( struct pipe_context *context,
struct rm_screen *rm_screen,
struct rm_context_callbacks *callbacks );
/* This module implements the following new-style driver functions in
* terms of the old ones that are still present in most pipe drivers.
*/
struct pipe_resource *rm_resource_create(struct rm_screen *,
const struct pipe_resource *template);
struct pipe_resource *rm_resource_from_handle(struct rm_screen *,
const struct pipe_resource *template,
struct winsys_handle *handle);
boolean rm_resource_get_handle(struct rm_screen *,
struct pipe_resource *tex,
struct winsys_handle *handle);
void rm_resource_destroy(struct rm_screen *,
struct pipe_resource *pt);
struct pipe_transfer *rm_get_transfer(struct rm_context *,
struct pipe_resource *resource,
struct pipe_subresource,
enum pipe_transfer_usage,
const struct pipe_box *);
void rm_transfer_destroy(struct rm_context *,
struct pipe_transfer *);
void *rm_transfer_map( struct rm_context *,
struct pipe_transfer *transfer );
void rm_transfer_flush_region( struct rm_context *,
struct pipe_transfer *transfer,
const struct pipe_box *);
void rm_transfer_unmap( struct rm_context *,
struct pipe_transfer *transfer );
void rm_transfer_inline_write( struct rm_context *,
struct pipe_resource *,
struct pipe_subresource,
enum pipe_transfer_usage,
const struct pipe_box *,
const void *data );
void rm_transfer_inline_read( struct rm_context *,
struct pipe_resource *,
struct pipe_subresource,
enum pipe_transfer_usage,
const struct pipe_box *,
void *data );
#endif
#include "rm.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
static void translate_template( const struct pipe_resource *template,
struct pipe_texture *tex )
{
tex->tex_usage = template->tex_usage;
}
/* This module implements the following new-style driver functions in
* terms of the old ones that are still present in most pipe drivers.
*/
struct pipe_resource *rm_resource_create(struct rm_screen *rm_screen,
const struct pipe_resource *template)
{
struct rm_resource *resource;
resource = CALLOC_STRUCT(rm_resource);
if (resource == NULL)
goto fail;
pipe_reference_init(&resource->base.reference, 1);
resource->base.screen = rm_screen->screen;
if (template->target == PIPE_BUFFER) {
struct pipe_texture tex_template;
translate_template(template, &tex_template);
resource->texture = rm_screen->cb.texture_create(rm_screen->screen,
&tex_template);
if (resource->texture == NULL)
goto fail;
}
else {
resource->buffer = rm_screen->cb.buffer_create(rm_screen->screen,
rm_screen->default_buffer_alignment,
template->usage,
template->width0);
if (resource->buffer == NULL)
goto fail;
}
return &resource->base;
fail:
FREE(resource);
return NULL;
}
struct pipe_resource *rm_resource_from_handle(struct rm_screen *rm_screen,
const struct pipe_resource *template,
struct winsys_handle *handle)
{
struct rm_resource *resource;
struct pipe_texture tex_template;
assert(template->target != PIPE_BUFFER);
resource = CALLOC_STRUCT(rm_resource);
if (resource == NULL)
goto fail;
translate_template(template, &tex_template);
pipe_reference_init(&resource->base.reference, 1);
resource->base.screen = rm_screen->screen;
resource->texture = rm_screen->cb.texture_from_handle(rm_screen->screen,
&tex_template,
handle);
if (resource->texture == NULL)
goto fail;
return &resource->base;
fail:
FREE(resource);
return NULL;
}
boolean rm_resource_get_handle(struct rm_screen *rm_screen,
struct pipe_resource *resource,
struct winsys_handle *handle)
{
struct rm_resource *rmr = rm_resource(resource);
assert(rmr->texture);
return rm_screen->cb.texture_get_handle(rm_screen->screen,
rmr->texture,
handle);
}
void rm_resource_destroy(struct rm_screen *rm_screen,
struct pipe_resource *resource)
{
struct rm_resource *rmr = rm_resource(resource);
if (rmr->texture) {
rm_screen->cb.texture_destroy(rm_screen->screen,
rmr->texture);
}
if (rmr->buffer) {
rm_screen->cb.buffer_destroy(rm_screen->screen,
rmr->buffer);
}
FREE(rmr);
}
struct rm_screen *
rm_screen_create( struct pipe_screen *screen,
struct rm_screen_callbacks *cb,
unsigned default_buffer_alignment)
{
struct rm_screen *rm_screen;
rm_screen = CALLOC_STRUCT(rm_screen);
if (rm_screen == NULL)
return NULL;
rm_screen->cb = *cb;
rm_screen->screen = screen;
rm_screen->default_buffer_alignment = default_buffer_alignment;
return rm_screen;
}
......@@ -222,16 +222,12 @@ pipe_buffer_write(struct pipe_context *pipe,
const void *data)