llvmpipe: get rid of tiled/linear layout remains

Eliminate the rest of the no longer needed layout logic.
(It is possible some code could be simplified a bit further still.)

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
Roland Scheidegger 2013-05-28 02:34:27 +02:00
parent b3abc93f47
commit 33fcce3682
6 changed files with 47 additions and 226 deletions

View File

@ -163,8 +163,7 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
cbuf->u.tex.level,
cbuf->u.tex.first_layer,
LP_TEX_USAGE_READ_WRITE,
LP_TEX_LAYOUT_LINEAR);
LP_TEX_USAGE_READ_WRITE);
}
else {
struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
@ -184,8 +183,7 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture,
zsbuf->u.tex.level,
zsbuf->u.tex.first_layer,
LP_TEX_USAGE_READ_WRITE,
LP_TEX_LAYOUT_LINEAR);
LP_TEX_USAGE_READ_WRITE);
}
}

View File

@ -704,8 +704,7 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
* still are tiled.
*/
mip_ptr = llvmpipe_get_texture_image_all(lp_tex, first_level,
LP_TEX_USAGE_READ,
LP_TEX_LAYOUT_LINEAR);
LP_TEX_USAGE_READ);
jit_tex->base = lp_tex->linear_img.data;
}
else {
@ -736,8 +735,7 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
if (llvmpipe_resource_is_texture(res)) {
for (j = first_level; j <= last_level; j++) {
mip_ptr = llvmpipe_get_texture_image_all(lp_tex, j,
LP_TEX_USAGE_READ,
LP_TEX_LAYOUT_LINEAR);
LP_TEX_USAGE_READ);
jit_tex->mip_offsets[j] = (uint8_t *)mip_ptr - (uint8_t *)jit_tex->base;
/*
* could get mip offset directly but need call above to

View File

@ -300,14 +300,12 @@ prepare_shader_sampling(
/* must trigger allocation first before we can get base ptr */
/* XXX this may fail due to OOM ? */
mip_ptr = llvmpipe_get_texture_image_all(lp_tex, view->u.tex.first_level,
LP_TEX_USAGE_READ,
LP_TEX_LAYOUT_LINEAR);
LP_TEX_USAGE_READ);
addr = lp_tex->linear_img.data;
for (j = first_level; j <= last_level; j++) {
mip_ptr = llvmpipe_get_texture_image_all(lp_tex, j,
LP_TEX_USAGE_READ,
LP_TEX_LAYOUT_LINEAR);
LP_TEX_USAGE_READ);
mip_offsets[j] = (uint8_t *)mip_ptr - (uint8_t *)addr;
/*
* could get mip offset directly but need call above to

View File

@ -153,12 +153,10 @@ lp_resource_copy(struct pipe_context *pipe,
{
const ubyte *src_linear_ptr
= llvmpipe_get_texture_image_address(src_tex, src_box->z,
src_level,
LP_TEX_LAYOUT_LINEAR);
src_level);
ubyte *dst_linear_ptr
= llvmpipe_get_texture_image_address(dst_tex, dstz,
dst_level,
LP_TEX_LAYOUT_LINEAR);
dst_level);
if (dst_linear_ptr && src_linear_ptr) {
util_copy_box(dst_linear_ptr, format,

View File

@ -59,33 +59,13 @@ static struct llvmpipe_resource resource_list;
static unsigned id_counter = 0;
/**
* Allocate storage for llvmpipe_texture::layout array.
* The number of elements is width_in_tiles * height_in_tiles.
*/
static enum lp_texture_layout *
alloc_layout_array(unsigned num_slices, unsigned width, unsigned height)
{
const unsigned tx = align(width, TILE_SIZE) / TILE_SIZE;
const unsigned ty = align(height, TILE_SIZE) / TILE_SIZE;
assert(num_slices * tx * ty > 0);
assert(LP_TEX_LAYOUT_NONE == 0); /* calloc'ing LP_TEX_LAYOUT_NONE here */
return (enum lp_texture_layout *)
CALLOC(num_slices * tx * ty, sizeof(enum lp_texture_layout));
}
/**
* Conventional allocation path for non-display textures:
* Just compute row strides here. Storage is allocated on demand later.
*/
static boolean
llvmpipe_texture_layout(struct llvmpipe_screen *screen,
struct llvmpipe_resource *lpr,
boolean allocate)
struct llvmpipe_resource *lpr)
{
struct pipe_resource *pt = &lpr->base;
unsigned level;
@ -100,7 +80,7 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
for (level = 0; level <= pt->last_level; level++) {
/* Row stride and image stride (for linear layout) */
/* Row stride and image stride */
{
unsigned alignment, nblocksx, nblocksy, block_size;
@ -131,14 +111,6 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
}
/* Size of the image in tiles (for tiled layout) */
{
const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
lpr->tiles_per_row[level] = width_t;
lpr->tiles_per_image[level] = width_t * height_t;
}
/* Number of 3D image slices, cube faces or texture array layers */
{
unsigned num_slices;
@ -154,13 +126,6 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
num_slices = 1;
lpr->num_slices_faces[level] = num_slices;
if (allocate) {
lpr->layout[level] = alloc_layout_array(num_slices, width, height);
if (!lpr->layout[level]) {
goto fail;
}
}
}
/* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */
@ -185,10 +150,6 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
return TRUE;
fail:
for (level = 0; level <= pt->last_level; level++) {
FREE(lpr->layout[level]);
}
return FALSE;
}
@ -204,7 +165,7 @@ llvmpipe_can_create_resource(struct pipe_screen *screen,
struct llvmpipe_resource lpr;
memset(&lpr, 0, sizeof(lpr));
lpr.base = *res;
return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, FALSE);
return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr);
}
@ -219,19 +180,10 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
*/
const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
const unsigned width_t = width / TILE_SIZE;
const unsigned height_t = height / TILE_SIZE;
lpr->tiles_per_row[0] = width_t;
lpr->tiles_per_image[0] = width_t * height_t;
lpr->num_slices_faces[0] = 1;
lpr->img_stride[0] = 0;
lpr->layout[0] = alloc_layout_array(1, width, height);
if (!lpr->layout[0]) {
return FALSE;
}
lpr->dt = winsys->displaytarget_create(winsys,
lpr->base.bind,
lpr->base.format,
@ -278,15 +230,12 @@ llvmpipe_resource_create(struct pipe_screen *_screen,
/* displayable surface */
if (!llvmpipe_displaytarget_layout(screen, lpr))
goto fail;
assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
}
else {
/* texture map */
if (!llvmpipe_texture_layout(screen, lpr, TRUE))
if (!llvmpipe_texture_layout(screen, lpr))
goto fail;
assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
}
assert(lpr->layout[0]);
}
else {
/* other data (vertex buffer, const buffer, etc) */
@ -332,24 +281,13 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen,
/* display target */
struct sw_winsys *winsys = screen->winsys;
winsys->displaytarget_destroy(winsys, lpr->dt);
FREE(lpr->layout[0]);
}
else if (llvmpipe_resource_is_texture(pt)) {
/* regular texture */
uint level;
/* free linear image data */
if (lpr->linear_img.data) {
align_free(lpr->linear_img.data);
lpr->linear_img.data = NULL;
}
/* free layout flag arrays */
for (level = 0; level < Elements(lpr->layout); level++) {
FREE(lpr->layout[level]);
lpr->layout[level] = NULL;
}
}
else if (!lpr->userBuffer) {
assert(lpr->data);
@ -372,8 +310,7 @@ void *
llvmpipe_resource_map(struct pipe_resource *resource,
unsigned level,
unsigned layer,
enum lp_texture_usage tex_usage,
enum lp_texture_layout layout)
enum lp_texture_usage tex_usage)
{
struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
uint8_t *map;
@ -385,9 +322,6 @@ llvmpipe_resource_map(struct pipe_resource *resource,
tex_usage == LP_TEX_USAGE_READ_WRITE ||
tex_usage == LP_TEX_USAGE_WRITE_ALL);
assert(layout == LP_TEX_LAYOUT_NONE ||
layout == LP_TEX_LAYOUT_LINEAR);
if (lpr->dt) {
/* display target */
struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
@ -412,16 +346,13 @@ llvmpipe_resource_map(struct pipe_resource *resource,
lpr->linear_img.data = map;
/* make sure tiled data gets converted to linear data */
map2 = llvmpipe_get_texture_image(lpr, 0, 0, tex_usage, layout);
if (layout == LP_TEX_LAYOUT_LINEAR)
assert(map == map2);
map2 = llvmpipe_get_texture_image(lpr, 0, 0, tex_usage);
return map2;
}
else if (llvmpipe_resource_is_texture(resource)) {
map = llvmpipe_get_texture_image(lpr, layer, level,
tex_usage, layout);
tex_usage);
return map;
}
else {
@ -448,11 +379,6 @@ llvmpipe_resource_unmap(struct pipe_resource *resource,
assert(level == 0);
assert(layer == 0);
/* make sure linear image is up to date */
(void) llvmpipe_get_texture_image(lpr, layer, level,
LP_TEX_USAGE_READ,
LP_TEX_LAYOUT_LINEAR);
winsys->displaytarget_unmap(winsys, lpr->dt);
}
}
@ -476,7 +402,6 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
{
struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
struct llvmpipe_resource *lpr;
unsigned width, height, width_t, height_t;
/* XXX Seems like from_handled depth textures doesn't work that well */
@ -489,11 +414,6 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
pipe_reference_init(&lpr->base.reference, 1);
lpr->base.screen = screen;
width = align(lpr->base.width0, TILE_SIZE);
height = align(lpr->base.height0, TILE_SIZE);
width_t = width / TILE_SIZE;
height_t = height / TILE_SIZE;
/*
* Looks like unaligned displaytargets work just fine,
* at least sampler/render ones.
@ -503,8 +423,6 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
assert(lpr->base.height0 == height);
#endif
lpr->tiles_per_row[0] = width_t;
lpr->tiles_per_image[0] = width_t * height_t;
lpr->num_slices_faces[0] = 1;
lpr->img_stride[0] = 0;
@ -516,13 +434,6 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
goto no_dt;
}
lpr->layout[0] = alloc_layout_array(1, lpr->base.width0, lpr->base.height0);
if (!lpr->layout[0]) {
goto no_layout_0;
}
assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
lpr->id = id_counter++;
#ifdef DEBUG
@ -531,8 +442,6 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
return &lpr->base;
no_layout_0:
winsys->displaytarget_destroy(winsys, lpr->dt);
no_dt:
FREE(lpr);
no_lpr:
@ -707,7 +616,7 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
map = llvmpipe_resource_map(resource,
level,
box->z,
tex_usage, LP_TEX_LAYOUT_LINEAR);
tex_usage);
/* May want to do different things here depending on read/write nature
@ -834,12 +743,8 @@ llvmpipe_user_buffer_create(struct pipe_screen *screen,
* for just one cube face, one array layer or one 3D texture slice
*/
static unsigned
tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level,
enum lp_texture_layout layout)
tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
{
assert(layout == LP_TEX_LAYOUT_LINEAR);
/* we already computed this */
return lpr->img_stride[level];
}
@ -849,10 +754,9 @@ tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level,
* including all cube faces or 3D image slices
*/
static unsigned
tex_image_size(const struct llvmpipe_resource *lpr, unsigned level,
enum lp_texture_layout layout)
tex_image_size(const struct llvmpipe_resource *lpr, unsigned level)
{
const unsigned buf_size = tex_image_face_size(lpr, level, layout);
const unsigned buf_size = tex_image_face_size(lpr, level);
return buf_size * lpr->num_slices_faces[level];
}
@ -863,57 +767,32 @@ tex_image_size(const struct llvmpipe_resource *lpr, unsigned level,
*/
ubyte *
llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
unsigned face_slice, unsigned level,
enum lp_texture_layout layout)
unsigned face_slice, unsigned level)
{
struct llvmpipe_texture_image *img;
unsigned offset;
assert (layout == LP_TEX_LAYOUT_LINEAR);
img = &lpr->linear_img;
offset = lpr->linear_mip_offsets[level];
if (face_slice > 0)
offset += face_slice * tex_image_face_size(lpr, level, layout);
offset += face_slice * tex_image_face_size(lpr, level);
return (ubyte *) img->data + offset;
}
/**
* Set the layout mode for all tiles in a particular image.
*/
static INLINE void
llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr,
unsigned face_slice, unsigned level,
unsigned width_t, unsigned height_t,
enum lp_texture_layout layout)
{
const unsigned start = face_slice * lpr->tiles_per_image[level];
unsigned i;
for (i = 0; i < width_t * height_t; i++) {
lpr->layout[level][start + i] = layout;
}
}
/**
* Allocate storage for a linear or tile texture image (all cube
* faces and all 3D slices, all levels).
* Allocate storage for a linear image
* (all cube faces and all 3D slices, all levels).
*/
static void
alloc_image_data(struct llvmpipe_resource *lpr,
enum lp_texture_layout layout)
alloc_image_data(struct llvmpipe_resource *lpr)
{
uint alignment = MAX2(16, util_cpu_caps.cacheline);
uint level;
uint offset = 0;
assert(layout == LP_TEX_LAYOUT_LINEAR);
if (lpr->dt) {
/* we get the linear memory from the winsys, and it has
* already been zeroed
@ -934,7 +813,7 @@ alloc_image_data(struct llvmpipe_resource *lpr,
* offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer
*/
for (level = 0; level <= lpr->base.last_level; level++) {
uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR);
uint buffer_size = tex_image_size(lpr, level);
lpr->linear_mip_offsets[level] = offset;
offset += align(buffer_size, alignment);
}
@ -953,36 +832,21 @@ alloc_image_data(struct llvmpipe_resource *lpr,
*
* \param face_slice the cube face or 3D slice of interest
* \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE
* \param layout should be LP_TEX_LAYOUT_LINEAR
*/
void *
llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
unsigned face_slice, unsigned level,
enum lp_texture_usage usage,
enum lp_texture_layout layout)
enum lp_texture_usage usage)
{
struct llvmpipe_texture_image *target_img;
void *target_data;
const unsigned width = u_minify(lpr->base.width0, level);
const unsigned height = u_minify(lpr->base.height0, level);
const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
unsigned target_offset;
unsigned *target_off_ptr;
assert(layout == LP_TEX_LAYOUT_NONE ||
layout == LP_TEX_LAYOUT_LINEAR);
assert(usage == LP_TEX_USAGE_READ ||
usage == LP_TEX_USAGE_READ_WRITE ||
usage == LP_TEX_USAGE_WRITE_ALL);
/* check for the special case of layout == LP_TEX_LAYOUT_NONE */
if (layout == LP_TEX_LAYOUT_NONE) {
/* XXX can still get LAYOUT_NONE ? */
layout = LP_TEX_LAYOUT_LINEAR;
}
if (lpr->dt) {
assert(lpr->linear_img.data);
}
@ -993,38 +857,32 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
if (!target_data) {
/* allocate memory for the target image now */
alloc_image_data(lpr, layout);
alloc_image_data(lpr);
target_data = target_img->data;
}
target_offset = target_off_ptr[level];
if (face_slice > 0) {
target_offset += face_slice * tex_image_face_size(lpr, level, layout);
target_offset += face_slice * tex_image_face_size(lpr, level);
}
if (target_data) {
target_data = (uint8_t *) target_data + target_offset;
}
llvmpipe_set_texture_image_layout(lpr, face_slice, level,
width_t, height_t, layout);
return target_data;
}
/**
* Return pointer to start of a texture image (1D, 2D, 3D, CUBE).
* All cube faces and 3D slices will be converted to the requested
* layout if needed.
* This is typically used when we're about to sample from a texture.
*/
void *
llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
unsigned level,
enum lp_texture_usage usage,
enum lp_texture_layout layout)
enum lp_texture_usage usage)
{
const int slices = lpr->num_slices_faces[level];
int slice;
@ -1033,7 +891,7 @@ llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
assert(slices > 0);
for (slice = slices - 1; slice >= 0; slice--) {
map = llvmpipe_get_texture_image(lpr, slice, level, usage, layout);
map = llvmpipe_get_texture_image(lpr, slice, level, usage);
}
return map;
@ -1041,9 +899,7 @@ llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
/**
* Get pointer to a linear image (not the tile!) where the tile at (x,y)
* is known to be in linear layout.
* Conversion from tiled to linear will be done if necessary.
* Get pointer to a linear image (not the tile!) at tile (x,y).
* \return pointer to start of image/face (not the tile)
*/
ubyte *
@ -1062,13 +918,12 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
if (!linear_img->data) {
/* allocate memory for the linear image now */
/* XXX should probably not do that here? */
alloc_image_data(lpr, LP_TEX_LAYOUT_LINEAR);
alloc_image_data(lpr);
}
assert(linear_img->data);
/* compute address of the slice/face of the image that contains the tile */
linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
LP_TEX_LAYOUT_LINEAR);
linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level);
return linear_image;
}
@ -1086,7 +941,7 @@ llvmpipe_resource_size(const struct pipe_resource *resource)
if (llvmpipe_resource_is_texture(resource)) {
for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
if (lpr->linear_img.data)
size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR);
size += tex_image_size(lpr, lvl);
}
}
else {

View File

@ -42,14 +42,6 @@ enum lp_texture_usage
};
/** Per-tile layout mode */
enum lp_texture_layout
{
LP_TEX_LAYOUT_NONE = 0, /**< no layout for the tile data yet */
LP_TEX_LAYOUT_LINEAR, /**< the tile data is in linear layout */
};
struct pipe_context;
struct pipe_screen;
struct llvmpipe_context;
@ -57,14 +49,6 @@ struct llvmpipe_context;
struct sw_displaytarget;
/**
* We keep one or two copies of the texture image data: one in a simple
* linear layout (for texture sampling) and another in a tiled layout (for
* render targets). We keep track of whether each image tile is linear
* or tiled on a per-tile basis.
*/
/** A 1D/2D/3D image, one mipmap level */
struct llvmpipe_texture_image
{
@ -75,10 +59,9 @@ struct llvmpipe_texture_image
/**
* llvmpipe subclass of pipe_resource. A texture, drawing surface,
* vertex buffer, const buffer, etc.
* Textures are stored differently than othere types of objects such as
* Textures are stored differently than other types of objects such as
* vertex buffers and const buffers.
* The former are tiled and have per-tile layout flags.
* The later are simple malloc'd blocks of memory.
* The latter are simple malloc'd blocks of memory.
*/
struct llvmpipe_resource
{
@ -88,8 +71,6 @@ struct llvmpipe_resource
unsigned row_stride[LP_MAX_TEXTURE_LEVELS];
/** Image stride (for cube maps, array or 3D textures) in bytes */
unsigned img_stride[LP_MAX_TEXTURE_LEVELS];
unsigned tiles_per_row[LP_MAX_TEXTURE_LEVELS];
unsigned tiles_per_image[LP_MAX_TEXTURE_LEVELS];
/** Number of 3D slices or cube faces per level */
unsigned num_slices_faces[LP_MAX_TEXTURE_LEVELS];
/** Offset to start of mipmap level, in bytes */
@ -111,9 +92,6 @@ struct llvmpipe_resource
*/
void *data;
/** array [level][face or slice][tile_y][tile_x] of layout values) */
enum lp_texture_layout *layout[LP_MAX_TEXTURE_LEVELS];
boolean userBuffer; /** Is this a user-space buffer? */
unsigned timestamp;
@ -183,7 +161,7 @@ llvmpipe_resource_is_texture(const struct pipe_resource *resource)
static INLINE unsigned
llvmpipe_resource_stride(struct pipe_resource *resource,
unsigned level)
unsigned level)
{
struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
assert(level < LP_MAX_TEXTURE_2D_LEVELS);
@ -195,13 +173,12 @@ void *
llvmpipe_resource_map(struct pipe_resource *resource,
unsigned level,
unsigned layer,
enum lp_texture_usage tex_usage,
enum lp_texture_layout layout);
enum lp_texture_usage tex_usage);
void
llvmpipe_resource_unmap(struct pipe_resource *resource,
unsigned level,
unsigned layer);
unsigned level,
unsigned layer);
void *
@ -214,26 +191,23 @@ llvmpipe_resource_size(const struct pipe_resource *resource);
ubyte *
llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
unsigned face_slice, unsigned level,
enum lp_texture_layout layout);
unsigned face_slice, unsigned level);
void *
llvmpipe_get_texture_image(struct llvmpipe_resource *resource,
unsigned face_slice, unsigned level,
enum lp_texture_usage usage,
enum lp_texture_layout layout);
unsigned face_slice, unsigned level,
enum lp_texture_usage usage);
void *
llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
unsigned level,
enum lp_texture_usage usage,
enum lp_texture_layout layout);
enum lp_texture_usage usage);
ubyte *
llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
unsigned face_slice, unsigned level,
enum lp_texture_usage usage,
unsigned x, unsigned y);
unsigned face_slice, unsigned level,
enum lp_texture_usage usage,
unsigned x, unsigned y);
extern void