llvmpipe: support rendering to buffer render targets.
authorRoland Scheidegger <sroland@vmware.com>
Wed, 27 Feb 2013 18:26:01 +0000 (19:26 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Thu, 28 Feb 2013 02:39:54 +0000 (03:39 +0100)
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 <jfonseca@vmware.com>
src/gallium/drivers/llvmpipe/lp_rast.c
src/gallium/drivers/llvmpipe/lp_rast_priv.h
src/gallium/drivers/llvmpipe/lp_scene.c
src/gallium/drivers/llvmpipe/lp_texture.c

index b5e5da61c2a2d74a13a498cfc6a9fb38f10d93e0..6183f4108d60c0d685d83a17c69f5ddef340b3fe 100644 (file)
@@ -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,
index 5db8fcd19b21181b56670a260ffedcc7db5790e8..c0f41f69fe29a5497f15bb64d487ad236005c230 100644 (file)
@@ -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);
index 328c0f74572c4481619d3efcad795af6e7698071..fec2f7460b117e2efd2c24861686b91432e4209c 100644 (file)
@@ -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;
       }
    }
index f92329237339b83dcf24826714716b7cb4ab0a63..a64139f1d9136c16b824d55e09c9775c5d289919 100644 (file)
@@ -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;