From 686f6c69bd36c537573f6e8095aaf24ec0ae4047 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Wed, 27 Feb 2013 19:26:01 +0100 Subject: llvmpipe: support rendering to buffer render targets. Unfortunately not usable from OpenGL, and no cap bit. Pretty similar to a 1d texture, though allows specifying a start element. v2: also fix up renderbuffer width (which will get promoted to fb width) to be the number of elements Reviewed-by: Jose Fonseca --- src/gallium/drivers/llvmpipe/lp_rast.c | 25 ++-------------- src/gallium/drivers/llvmpipe/lp_rast_priv.h | 4 +-- src/gallium/drivers/llvmpipe/lp_scene.c | 35 +++++++++++++++-------- src/gallium/drivers/llvmpipe/lp_texture.c | 44 +++++++++++++++++++++-------- 4 files changed, 61 insertions(+), 47 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index b5e5da61c2a..6183f4108d6 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -165,32 +165,13 @@ lp_rast_clear_color(struct lp_rasterizer_task *task, for (i = 0; i < scene->fb.nr_cbufs; i++) { enum pipe_format format = scene->fb.cbufs[i]->format; - /* - * XXX the format_write_4i/ui functions do clamping to max value - * and I'm not sure that's actually right - spec doesn't seem to - * say much about that topic. If it is should probably adjust the - * border color handling to do the same. If not and chopping off - * bits is the way to go, the write_4i and write_4ui functions - * would be identical. - */ - if (util_format_is_pure_sint(format)) { - int rgba[4]; - rgba[0] = arg.clear_color.i[0]; - rgba[1] = arg.clear_color.i[1]; - rgba[2] = arg.clear_color.i[2]; - rgba[3] = arg.clear_color.i[3]; - util_format_write_4i(format, rgba, 0, &uc, 0, 0, 0, 1, 1); + if (util_format_is_pure_sint(format)) { + util_format_write_4i(format, arg.clear_color.i, 0, &uc, 0, 0, 0, 1, 1); } else { - unsigned rgba[4]; - rgba[0] = arg.clear_color.ui[0]; - rgba[1] = arg.clear_color.ui[1]; - rgba[2] = arg.clear_color.ui[2]; - rgba[3] = arg.clear_color.ui[3]; - assert(util_format_is_pure_uint(format)); - util_format_write_4ui(format, rgba, 0, &uc, 0, 0, 0, 1, 1); + util_format_write_4ui(format, arg.clear_color.ui, 0, &uc, 0, 0, 0, 1, 1); } util_fill_rect(scene->cbufs[i].map, diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index 5db8fcd19b2..c0f41f69fe2 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -196,7 +196,7 @@ lp_rast_get_unswizzled_color_tile_pointer(struct lp_rasterizer_task *task, struct pipe_surface *cbuf = scene->fb.cbufs[buf]; assert(cbuf); - format_bytes = util_format_description(cbuf->format)->block.bits / 8; + format_bytes = util_format_get_blocksize(cbuf->format); task->color_tiles[buf] = scene->cbufs[buf].map + scene->cbufs[buf].stride * task->y + format_bytes * task->x; } @@ -221,7 +221,7 @@ lp_rast_get_unswizzled_color_block_pointer(struct lp_rasterizer_task *task, assert((y % TILE_VECTOR_HEIGHT) == 0); assert(buf < task->scene->fb.nr_cbufs); - format_bytes = util_format_description(task->scene->fb.cbufs[buf]->format)->block.bits / 8; + format_bytes = util_format_get_blocksize(task->scene->fb.cbufs[buf]->format); color = lp_rast_get_unswizzled_color_tile_pointer(task, buf, LP_TEX_USAGE_READ_WRITE); assert(color); diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 328c0f74572..fec2f7460b1 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -141,15 +141,24 @@ lp_scene_begin_rasterization(struct lp_scene *scene) for (i = 0; i < scene->fb.nr_cbufs; i++) { struct pipe_surface *cbuf = scene->fb.cbufs[i]; - assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer); - scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture, - cbuf->u.tex.level); - - 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); + if (llvmpipe_resource_is_texture(cbuf->texture)) { + assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer); + scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture, + cbuf->u.tex.level); + + 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); + } + else { + struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture); + unsigned pixstride = util_format_get_blocksize(cbuf->format); + scene->cbufs[i].stride = cbuf->texture->width0; + scene->cbufs[i].map = lpr->data; + scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride; + } } if (fb->zsbuf) { @@ -182,9 +191,11 @@ lp_scene_end_rasterization(struct lp_scene *scene ) for (i = 0; i < scene->fb.nr_cbufs; i++) { if (scene->cbufs[i].map) { struct pipe_surface *cbuf = scene->fb.cbufs[i]; - llvmpipe_resource_unmap(cbuf->texture, - cbuf->u.tex.level, - cbuf->u.tex.first_layer); + if (llvmpipe_resource_is_texture(cbuf->texture)) { + llvmpipe_resource_unmap(cbuf->texture, + cbuf->u.tex.level, + cbuf->u.tex.first_layer); + } scene->cbufs[i].map = NULL; } } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index f9232923733..a64139f1d91 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -297,6 +297,12 @@ llvmpipe_resource_create(struct pipe_screen *_screen, assert(templat->depth0 == 1); assert(templat->last_level == 0); lpr->data = align_malloc(bytes, 16); + /* + * buffers don't really have stride but it's probably safer + * (for code doing same calculations for buffers and textures) + * to put something sane in there. + */ + lpr->row_stride[0] = bytes; if (!lpr->data) goto fail; memset(lpr->data, 0, bytes); @@ -578,12 +584,23 @@ llvmpipe_create_surface(struct pipe_context *pipe, pipe_resource_reference(&ps->texture, pt); ps->context = pipe; ps->format = surf_tmpl->format; - ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); - ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); - - ps->u.tex.level = surf_tmpl->u.tex.level; - ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; - ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; + if (llvmpipe_resource_is_texture(pt)) { + assert(surf_tmpl->u.tex.level <= pt->last_level); + ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); + ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); + ps->u.tex.level = surf_tmpl->u.tex.level; + ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; + } + else { + /* setting width as number of elements should get us correct renderbuffer width */ + ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1; + ps->height = pt->height0; + ps->u.buf.first_element = surf_tmpl->u.buf.first_element; + ps->u.buf.last_element = surf_tmpl->u.buf.last_element; + assert(ps->u.buf.first_element <= ps->u.buf.last_element); + assert(ps->u.buf.last_element < ps->width); + } } return ps; } @@ -1342,12 +1359,17 @@ llvmpipe_resource_size(const struct pipe_resource *resource) const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource); unsigned lvl, size = 0; - for (lvl = 0; lvl <= lpr->base.last_level; lvl++) { - if (lpr->linear_img.data) - size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR); + 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); - if (lpr->tiled_img.data) - size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED); + if (lpr->tiled_img.data) + size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED); + } + } + else { + size = resource->width0; } return size; -- cgit v1.2.3