llvmpipe: Don't use texture transfer internally.
Now that transfers are context objects their sideeffects must happen in order when used by the state tracker, but that synchronization must be bypassed when used inside the driver, or it would cause infinite recursion.
This commit is contained in:
@@ -62,18 +62,20 @@ lp_rast_begin( struct lp_rasterizer *rast,
|
||||
rast->state.write_color = write_color;
|
||||
|
||||
for (i = 0; i < rast->state.nr_cbufs; i++) {
|
||||
struct pipe_surface *cbuf = scene->fb.cbufs[i];
|
||||
rast->cbuf[i].map = scene->cbuf_map[i];
|
||||
rast->cbuf[i].format = scene->cbuf_transfer[i]->texture->format;
|
||||
rast->cbuf[i].width = scene->cbuf_transfer[i]->width;
|
||||
rast->cbuf[i].height = scene->cbuf_transfer[i]->height;
|
||||
rast->cbuf[i].stride = scene->cbuf_transfer[i]->stride;
|
||||
rast->cbuf[i].format = cbuf->texture->format;
|
||||
rast->cbuf[i].width = cbuf->width;
|
||||
rast->cbuf[i].height = cbuf->height;
|
||||
rast->cbuf[i].stride = llvmpipe_texture_stride(cbuf->texture, cbuf->level);
|
||||
}
|
||||
|
||||
if (write_zstencil) {
|
||||
struct pipe_surface *zsbuf = scene->fb.zsbuf;
|
||||
rast->zsbuf.map = scene->zsbuf_map;
|
||||
rast->zsbuf.stride = scene->zsbuf_transfer->stride;
|
||||
rast->zsbuf.stride = llvmpipe_texture_stride(zsbuf->texture, zsbuf->level);
|
||||
rast->zsbuf.blocksize =
|
||||
util_format_get_blocksize(scene->zsbuf_transfer->texture->format);
|
||||
util_format_get_blocksize(zsbuf->texture->format);
|
||||
}
|
||||
|
||||
lp_scene_bin_iter_begin( scene );
|
||||
|
||||
@@ -397,7 +397,6 @@ end:
|
||||
static boolean
|
||||
lp_scene_map_buffers( struct lp_scene *scene )
|
||||
{
|
||||
struct pipe_context *pipe = scene->pipe;
|
||||
struct pipe_surface *cbuf, *zsbuf;
|
||||
int i;
|
||||
|
||||
@@ -409,20 +408,10 @@ lp_scene_map_buffers( struct lp_scene *scene )
|
||||
for (i = 0; i < scene->fb.nr_cbufs; i++) {
|
||||
cbuf = scene->fb.cbufs[i];
|
||||
if (cbuf) {
|
||||
scene->cbuf_transfer[i] = pipe->get_tex_transfer(pipe,
|
||||
cbuf->texture,
|
||||
cbuf->face,
|
||||
cbuf->level,
|
||||
cbuf->zslice,
|
||||
PIPE_TRANSFER_READ_WRITE,
|
||||
0, 0,
|
||||
cbuf->width,
|
||||
cbuf->height);
|
||||
if (!scene->cbuf_transfer[i])
|
||||
goto fail;
|
||||
|
||||
scene->cbuf_map[i] = pipe->transfer_map(pipe,
|
||||
scene->cbuf_transfer[i]);
|
||||
scene->cbuf_map[i] = llvmpipe_texture_map(cbuf->texture,
|
||||
cbuf->face,
|
||||
cbuf->level,
|
||||
cbuf->zslice);
|
||||
if (!scene->cbuf_map[i])
|
||||
goto fail;
|
||||
}
|
||||
@@ -432,20 +421,10 @@ lp_scene_map_buffers( struct lp_scene *scene )
|
||||
*/
|
||||
zsbuf = scene->fb.zsbuf;
|
||||
if (zsbuf) {
|
||||
scene->zsbuf_transfer = pipe->get_tex_transfer(pipe,
|
||||
zsbuf->texture,
|
||||
zsbuf->face,
|
||||
zsbuf->level,
|
||||
zsbuf->zslice,
|
||||
PIPE_TRANSFER_READ_WRITE,
|
||||
0, 0,
|
||||
zsbuf->width,
|
||||
zsbuf->height);
|
||||
if (!scene->zsbuf_transfer)
|
||||
goto fail;
|
||||
|
||||
scene->zsbuf_map = pipe->transfer_map(pipe,
|
||||
scene->zsbuf_transfer);
|
||||
scene->zsbuf_map = llvmpipe_texture_map(zsbuf->texture,
|
||||
zsbuf->face,
|
||||
zsbuf->level,
|
||||
zsbuf->zslice);
|
||||
if (!scene->zsbuf_map)
|
||||
goto fail;
|
||||
}
|
||||
@@ -469,28 +448,27 @@ fail:
|
||||
static void
|
||||
lp_scene_unmap_buffers( struct lp_scene *scene )
|
||||
{
|
||||
struct pipe_context *pipe = scene->pipe;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < scene->fb.nr_cbufs; i++) {
|
||||
if (scene->cbuf_map[i])
|
||||
pipe->transfer_unmap(pipe, scene->cbuf_transfer[i]);
|
||||
|
||||
if (scene->cbuf_transfer[i])
|
||||
pipe->tex_transfer_destroy(pipe, scene->cbuf_transfer[i]);
|
||||
|
||||
scene->cbuf_transfer[i] = NULL;
|
||||
scene->cbuf_map[i] = NULL;
|
||||
if (scene->cbuf_map[i]) {
|
||||
struct pipe_surface *cbuf = scene->fb.cbufs[i];
|
||||
llvmpipe_texture_unmap(cbuf->texture,
|
||||
cbuf->face,
|
||||
cbuf->level,
|
||||
cbuf->zslice);
|
||||
scene->cbuf_map[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (scene->zsbuf_map)
|
||||
pipe->transfer_unmap(pipe, scene->zsbuf_transfer);
|
||||
|
||||
if (scene->zsbuf_transfer)
|
||||
pipe->tex_transfer_destroy(pipe, scene->zsbuf_transfer);
|
||||
|
||||
scene->zsbuf_transfer = NULL;
|
||||
scene->zsbuf_map = NULL;
|
||||
if (scene->zsbuf_map) {
|
||||
struct pipe_surface *zsbuf = scene->fb.zsbuf;
|
||||
llvmpipe_texture_unmap(zsbuf->texture,
|
||||
zsbuf->face,
|
||||
zsbuf->level,
|
||||
zsbuf->zslice);
|
||||
scene->zsbuf_map = NULL;
|
||||
}
|
||||
|
||||
util_unreference_framebuffer_state( &scene->fb );
|
||||
}
|
||||
|
||||
@@ -114,8 +114,6 @@ struct texture_ref {
|
||||
*/
|
||||
struct lp_scene {
|
||||
struct pipe_context *pipe;
|
||||
struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
|
||||
struct pipe_transfer *zsbuf_transfer;
|
||||
|
||||
/* Scene's buffers are mapped at the time the scene is enqueued:
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include "lp_context.h"
|
||||
#include "lp_screen.h"
|
||||
#include "lp_flush.h"
|
||||
#include "lp_texture.h"
|
||||
#include "lp_tile_size.h"
|
||||
#include "state_tracker/sw_winsys.h"
|
||||
@@ -163,6 +164,92 @@ llvmpipe_texture_destroy(struct pipe_texture *pt)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map a texture. Without any synchronization.
|
||||
*/
|
||||
void *
|
||||
llvmpipe_texture_map(struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level,
|
||||
unsigned zslice)
|
||||
{
|
||||
struct llvmpipe_texture *lpt = llvmpipe_texture(texture);
|
||||
uint8_t *map;
|
||||
|
||||
if (lpt->dt) {
|
||||
/* display target */
|
||||
struct llvmpipe_screen *screen = llvmpipe_screen(texture->screen);
|
||||
struct sw_winsys *winsys = screen->winsys;
|
||||
const unsigned usage = PIPE_BUFFER_USAGE_CPU_READ_WRITE;
|
||||
|
||||
assert(face == 0);
|
||||
assert(level == 0);
|
||||
assert(zslice == 0);
|
||||
|
||||
/* FIXME: keep map count? */
|
||||
map = winsys->displaytarget_map(winsys, lpt->dt, usage);
|
||||
}
|
||||
else {
|
||||
/* regular texture */
|
||||
unsigned offset;
|
||||
unsigned stride;
|
||||
|
||||
map = lpt->data;
|
||||
|
||||
assert(level < LP_MAX_TEXTURE_2D_LEVELS);
|
||||
|
||||
offset = lpt->level_offset[level];
|
||||
stride = lpt->stride[level];
|
||||
|
||||
/* XXX shouldn't that rather be
|
||||
tex_height = align(u_minify(texture->height0, level), 2)
|
||||
to account for alignment done in llvmpipe_texture_layout ?
|
||||
*/
|
||||
if (texture->target == PIPE_TEXTURE_CUBE) {
|
||||
unsigned tex_height = u_minify(texture->height0, level);
|
||||
offset += face * util_format_get_nblocksy(texture->format, tex_height) * stride;
|
||||
}
|
||||
else if (texture->target == PIPE_TEXTURE_3D) {
|
||||
unsigned tex_height = u_minify(texture->height0, level);
|
||||
offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * stride;
|
||||
}
|
||||
else {
|
||||
assert(face == 0);
|
||||
assert(zslice == 0);
|
||||
}
|
||||
|
||||
map += offset;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unmap a texture. Without any synchronization.
|
||||
*/
|
||||
void
|
||||
llvmpipe_texture_unmap(struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level,
|
||||
unsigned zslice)
|
||||
{
|
||||
struct llvmpipe_texture *lpt = llvmpipe_texture(texture);
|
||||
|
||||
if (lpt->dt) {
|
||||
/* display target */
|
||||
struct llvmpipe_screen *lp_screen = llvmpipe_screen(texture->screen);
|
||||
struct sw_winsys *winsys = lp_screen->winsys;
|
||||
|
||||
assert(face == 0);
|
||||
assert(level == 0);
|
||||
assert(zslice == 0);
|
||||
|
||||
winsys->displaytarget_unmap(winsys, lpt->dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct pipe_surface *
|
||||
llvmpipe_get_tex_surface(struct pipe_screen *screen,
|
||||
struct pipe_texture *pt,
|
||||
@@ -181,7 +268,6 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen,
|
||||
ps->format = pt->format;
|
||||
ps->width = u_minify(pt->width0, level);
|
||||
ps->height = u_minify(pt->height0, level);
|
||||
ps->offset = lpt->level_offset[level];
|
||||
ps->usage = usage;
|
||||
|
||||
/* Because we are llvmpipe, anything that the state tracker
|
||||
@@ -207,23 +293,6 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen,
|
||||
ps->face = face;
|
||||
ps->level = level;
|
||||
ps->zslice = zslice;
|
||||
|
||||
/* XXX shouldn't that rather be
|
||||
tex_height = align(ps->height, 2);
|
||||
to account for alignment done in llvmpipe_texture_layout ?
|
||||
*/
|
||||
if (pt->target == PIPE_TEXTURE_CUBE) {
|
||||
unsigned tex_height = ps->height;
|
||||
ps->offset += face * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level];
|
||||
}
|
||||
else if (pt->target == PIPE_TEXTURE_3D) {
|
||||
unsigned tex_height = ps->height;
|
||||
ps->offset += zslice * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level];
|
||||
}
|
||||
else {
|
||||
assert(face == 0);
|
||||
assert(zslice == 0);
|
||||
}
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
@@ -269,24 +338,6 @@ llvmpipe_get_tex_transfer(struct pipe_context *pipe,
|
||||
pt->level = level;
|
||||
pt->zslice = zslice;
|
||||
|
||||
lpt->offset = lptex->level_offset[level];
|
||||
|
||||
/* XXX shouldn't that rather be
|
||||
tex_height = align(u_minify(texture->height0, level), 2)
|
||||
to account for alignment done in llvmpipe_texture_layout ?
|
||||
*/
|
||||
if (texture->target == PIPE_TEXTURE_CUBE) {
|
||||
unsigned tex_height = u_minify(texture->height0, level);
|
||||
lpt->offset += face * util_format_get_nblocksy(texture->format, tex_height) * pt->stride;
|
||||
}
|
||||
else if (texture->target == PIPE_TEXTURE_3D) {
|
||||
unsigned tex_height = u_minify(texture->height0, level);
|
||||
lpt->offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * pt->stride;
|
||||
}
|
||||
else {
|
||||
assert(face == 0);
|
||||
assert(zslice == 0);
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
return NULL;
|
||||
@@ -312,7 +363,7 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer )
|
||||
{
|
||||
struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
|
||||
ubyte *map, *xfer_map;
|
||||
ubyte *map;
|
||||
struct llvmpipe_texture *lpt;
|
||||
enum pipe_format format;
|
||||
|
||||
@@ -320,34 +371,24 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
|
||||
lpt = llvmpipe_texture(transfer->texture);
|
||||
format = lpt->base.format;
|
||||
|
||||
if (lpt->dt) {
|
||||
/* display target */
|
||||
struct sw_winsys *winsys = screen->winsys;
|
||||
|
||||
map = winsys->displaytarget_map(winsys, lpt->dt,
|
||||
pipe_transfer_buffer_flags(transfer));
|
||||
if (map == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
/* regular texture */
|
||||
map = lpt->data;
|
||||
}
|
||||
map = llvmpipe_texture_map(transfer->texture,
|
||||
transfer->face, transfer->level, transfer->zslice);
|
||||
|
||||
/* May want to different things here depending on read/write nature
|
||||
* of the map:
|
||||
*/
|
||||
if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE)) {
|
||||
if (transfer->usage & PIPE_TRANSFER_WRITE) {
|
||||
/* Do something to notify sharing contexts of a texture change.
|
||||
*/
|
||||
screen->timestamp++;
|
||||
}
|
||||
|
||||
xfer_map = map + llvmpipe_transfer(transfer)->offset +
|
||||
map +=
|
||||
transfer->y / util_format_get_blockheight(format) * transfer->stride +
|
||||
transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
|
||||
/*printf("map = %p xfer map = %p\n", map, xfer_map);*/
|
||||
return xfer_map;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -355,17 +396,10 @@ static void
|
||||
llvmpipe_transfer_unmap(struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct llvmpipe_screen *lp_screen = llvmpipe_screen(pipe->screen);
|
||||
struct llvmpipe_texture *lpt;
|
||||
|
||||
assert(transfer->texture);
|
||||
lpt = llvmpipe_texture(transfer->texture);
|
||||
|
||||
if (lpt->dt) {
|
||||
/* display target */
|
||||
struct sw_winsys *winsys = lp_screen->winsys;
|
||||
winsys->displaytarget_unmap(winsys, lpt->dt);
|
||||
}
|
||||
llvmpipe_texture_unmap(transfer->texture,
|
||||
transfer->face, transfer->level, transfer->zslice);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -95,6 +95,28 @@ llvmpipe_transfer(struct pipe_transfer *pt)
|
||||
}
|
||||
|
||||
|
||||
static INLINE unsigned
|
||||
llvmpipe_texture_stride(struct pipe_texture *texture,
|
||||
unsigned level)
|
||||
{
|
||||
struct llvmpipe_texture *lpt = llvmpipe_texture(texture);
|
||||
assert(level < LP_MAX_TEXTURE_2D_LEVELS);
|
||||
return lpt->stride[level];
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
llvmpipe_texture_map(struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level,
|
||||
unsigned zslice);
|
||||
|
||||
void
|
||||
llvmpipe_texture_unmap(struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level,
|
||||
unsigned zslice);
|
||||
|
||||
extern void
|
||||
llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user