summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/softpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/softpipe')
-rw-r--r--src/gallium/drivers/softpipe/sp_clear.c10
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.c68
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.h17
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c75
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_tile_cache.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c144
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.c12
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.h2
8 files changed, 227 insertions, 104 deletions
diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c
index 5f130453c3..ae3f00f338 100644
--- a/src/gallium/drivers/softpipe/sp_clear.c
+++ b/src/gallium/drivers/softpipe/sp_clear.c
@@ -69,11 +69,6 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
util_pack_color(rgba, ps->format, &uc);
sp_tile_cache_clear(softpipe->cbuf_cache[i], rgba, uc.ui);
-
-#if !TILE_CLEAR_OPTIMIZATION
- /* non-cached surface */
- pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, uc.ui);
-#endif
}
}
@@ -83,11 +78,6 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
cv = util_pack_z_stencil(ps->format, depth, stencil);
sp_tile_cache_clear(softpipe->zsbuf_cache, zero, cv);
-
-#if !TILE_CLEAR_OPTIMIZATION
- /* non-cached surface */
- pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
-#endif
}
softpipe->dirty_render_cache = TRUE;
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
index 508fe8f764..5024fc8a81 100644
--- a/src/gallium/drivers/softpipe/sp_flush.c
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -104,3 +104,71 @@ softpipe_flush( struct pipe_context *pipe,
*fence = NULL;
}
+
+/**
+ * Flush context if necessary.
+ *
+ * Returns FALSE if it would have block, but do_not_block was set, TRUE
+ * otherwise.
+ *
+ * TODO: move this logic to an auxiliary library?
+ */
+boolean
+softpipe_flush_resource(struct pipe_context *pipe,
+ struct pipe_resource *texture,
+ unsigned face,
+ unsigned level,
+ unsigned flush_flags,
+ boolean read_only,
+ boolean cpu_access,
+ boolean do_not_block)
+{
+ unsigned referenced;
+
+ referenced = pipe->is_resource_referenced(pipe, texture, face, level);
+
+ if ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) {
+
+ /*
+ * TODO: The semantics of these flush flags are too obtuse. They should
+ * disappear and the pipe driver should just ensure that all visible
+ * side-effects happen when they need to happen.
+ */
+ if (referenced & PIPE_REFERENCED_FOR_WRITE)
+ flush_flags |= PIPE_FLUSH_RENDER_CACHE;
+
+ if (referenced & PIPE_REFERENCED_FOR_READ)
+ flush_flags |= PIPE_FLUSH_TEXTURE_CACHE;
+
+ if (cpu_access) {
+ /*
+ * Flush and wait.
+ */
+
+ struct pipe_fence_handle *fence = NULL;
+
+ if (do_not_block)
+ return FALSE;
+
+ pipe->flush(pipe, flush_flags, &fence);
+
+ if (fence) {
+ /*
+ * This is for illustrative purposes only, as softpipe does not
+ * have fences.
+ */
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ }
+ } else {
+ /*
+ * Just flush.
+ */
+
+ pipe->flush(pipe, flush_flags, NULL);
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/gallium/drivers/softpipe/sp_flush.h b/src/gallium/drivers/softpipe/sp_flush.h
index 68d9b5fa83..cb97482a71 100644
--- a/src/gallium/drivers/softpipe/sp_flush.h
+++ b/src/gallium/drivers/softpipe/sp_flush.h
@@ -28,10 +28,23 @@
#ifndef SP_FLUSH_H
#define SP_FLUSH_H
+#include "pipe/p_compiler.h"
+
struct pipe_context;
struct pipe_fence_handle;
-void softpipe_flush(struct pipe_context *pipe, unsigned flags,
- struct pipe_fence_handle **fence);
+void
+softpipe_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence);
+
+boolean
+softpipe_flush_resource(struct pipe_context *pipe,
+ struct pipe_resource *texture,
+ unsigned face,
+ unsigned level,
+ unsigned flush_flags,
+ boolean read_only,
+ boolean cpu_access,
+ boolean do_not_block);
#endif
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 7b1e058ac8..8bb0294238 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -27,6 +27,7 @@
#include "util/u_memory.h"
+#include "util/u_format.h"
#include "util/u_format_s3tc.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
@@ -70,6 +71,8 @@ softpipe_get_param(struct pipe_screen *screen, int param)
return 1;
case PIPE_CAP_GLSL:
return 1;
+ case PIPE_CAP_SM3:
+ return 1;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 0;
case PIPE_CAP_POINT_SPRITE:
@@ -144,43 +147,77 @@ static boolean
softpipe_is_format_supported( struct pipe_screen *screen,
enum pipe_format format,
enum pipe_texture_target target,
- unsigned tex_usage,
+ unsigned bind,
unsigned geom_flags )
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
+ const struct util_format_description *format_desc;
assert(target == PIPE_TEXTURE_1D ||
target == PIPE_TEXTURE_2D ||
target == PIPE_TEXTURE_3D ||
target == PIPE_TEXTURE_CUBE);
- switch(format) {
- case PIPE_FORMAT_YUYV:
- case PIPE_FORMAT_UYVY:
+ format_desc = util_format_description(format);
+ if (!format_desc)
return FALSE;
- case PIPE_FORMAT_DXT1_RGB:
- case PIPE_FORMAT_DXT1_RGBA:
- case PIPE_FORMAT_DXT3_RGBA:
- case PIPE_FORMAT_DXT5_RGBA:
- return util_format_s3tc_enabled;
+ if (bind & (PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SCANOUT |
+ PIPE_BIND_SHARED)) {
+ if(!winsys->is_displaytarget_format_supported(winsys, bind, format))
+ return FALSE;
+ }
- case PIPE_FORMAT_Z32_FLOAT:
- case PIPE_FORMAT_NONE:
- return FALSE;
+ if (bind & PIPE_BIND_RENDER_TARGET) {
+ if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
+ return FALSE;
- default:
- break;
+ /*
+ * Although possible, it is unnatural to render into compressed or YUV
+ * surfaces. So disable these here to avoid going into weird paths
+ * inside the state trackers.
+ */
+ if (format_desc->block.width != 1 ||
+ format_desc->block.height != 1)
+ return FALSE;
+
+ /*
+ * TODO: Unfortunately we cannot render into anything more than 32 bits
+ * because we encode color clear values into a 32bit word.
+ */
+ if (format_desc->block.bits > 32)
+ return FALSE;
}
- if(tex_usage & (PIPE_BIND_DISPLAY_TARGET |
- PIPE_BIND_SCANOUT |
- PIPE_BIND_SHARED)) {
- if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
+ if (bind & PIPE_BIND_DEPTH_STENCIL) {
+ if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
return FALSE;
+
+ /*
+ * TODO: Unfortunately we cannot render into anything more than 32 bits
+ * because we encode depth and stencil clear values into a 32bit word.
+ */
+ if (format_desc->block.bits > 32)
+ return FALSE;
+
+ /*
+ * TODO: eliminate this restriction
+ */
+ if (format == PIPE_FORMAT_Z32_FLOAT)
+ return FALSE;
+ }
+
+ /*
+ * All other operations (sampling, transfer, etc).
+ */
+
+ if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+ return util_format_s3tc_enabled;
}
- /* XXX: this is often a lie. Pull in logic from llvmpipe to fix.
+ /*
+ * Everything else should be supported by u_format.
*/
return TRUE;
}
diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
index c79f5fb05a..fbce9e042b 100644
--- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
@@ -248,7 +248,8 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
addr.bits.face,
addr.bits.level,
addr.bits.z,
- PIPE_TRANSFER_READ, 0, 0,
+ PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
+ 0, 0,
u_minify(tc->texture->width0, addr.bits.level),
u_minify(tc->texture->height0, addr.bits.level));
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index 167b6b1161..7aa85559b2 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -39,6 +39,7 @@
#include "util/u_transfer.h"
#include "sp_context.h"
+#include "sp_flush.h"
#include "sp_texture.h"
#include "sp_screen.h"
@@ -214,6 +215,35 @@ softpipe_resource_get_handle(struct pipe_screen *screen,
/**
+ * Helper function to compute offset (in bytes) for a particular
+ * texture level/face/slice from the start of the buffer.
+ */
+static unsigned
+sp_get_tex_image_offset(const struct softpipe_resource *spr,
+ unsigned level, unsigned face, unsigned zslice)
+{
+ const unsigned hgt = u_minify(spr->base.height0, level);
+ const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt);
+ unsigned offset = spr->level_offset[level];
+
+ if (spr->base.target == PIPE_TEXTURE_CUBE) {
+ assert(zslice == 0);
+ offset += face * nblocksy * spr->stride[level];
+ }
+ else if (spr->base.target == PIPE_TEXTURE_3D) {
+ assert(face == 0);
+ offset += zslice * nblocksy * spr->stride[level];
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ return offset;
+}
+
+
+/**
* Get a pipe_surface "view" into a texture resource.
*/
static struct pipe_surface *
@@ -234,25 +264,12 @@ softpipe_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 = spr->level_offset[level];
+ ps->offset = sp_get_tex_image_offset(spr, level, face, zslice);
ps->usage = usage;
ps->face = face;
ps->level = level;
ps->zslice = zslice;
-
- if (pt->target == PIPE_TEXTURE_CUBE) {
- ps->offset += face * util_format_get_nblocksy(pt->format, u_minify(pt->height0, level)) *
- spr->stride[level];
- }
- else if (pt->target == PIPE_TEXTURE_3D) {
- ps->offset += zslice * util_format_get_nblocksy(pt->format, u_minify(pt->height0, level)) *
- spr->stride[level];
- }
- else {
- assert(face == 0);
- assert(zslice == 0);
- }
}
return ps;
}
@@ -290,8 +307,8 @@ softpipe_get_transfer(struct pipe_context *pipe,
unsigned usage,
const struct pipe_box *box)
{
- struct softpipe_resource *sprex = softpipe_resource(resource);
- struct softpipe_transfer *spr;
+ struct softpipe_resource *spr = softpipe_resource(resource);
+ struct softpipe_transfer *spt;
assert(resource);
assert(sr.level <= resource->last_level);
@@ -301,33 +318,41 @@ softpipe_get_transfer(struct pipe_context *pipe,
assert(box->y + box->height <= u_minify(resource->height0, sr.level));
assert(box->z + box->depth <= u_minify(resource->depth0, sr.level));
- spr = CALLOC_STRUCT(softpipe_transfer);
- if (spr) {
- struct pipe_transfer *pt = &spr->base;
+ /*
+ * Transfers, like other pipe operations, must happen in order, so flush the
+ * context if necessary.
+ */
+ if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
+ boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
+ boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
+ if (!softpipe_flush_resource(pipe, resource,
+ sr.face, sr.level,
+ 0, /* flush_flags */
+ read_only,
+ TRUE, /* cpu_access */
+ do_not_block)) {
+ /*
+ * It would have blocked, but state tracker requested no to.
+ */
+ assert(do_not_block);
+ return NULL;
+ }
+ }
+
+ spt = CALLOC_STRUCT(softpipe_transfer);
+ if (spt) {
+ struct pipe_transfer *pt = &spt->base;
enum pipe_format format = resource->format;
- int nblocksy = util_format_get_nblocksy(resource->format,
- u_minify(resource->height0, sr.level));
pipe_resource_reference(&pt->resource, resource);
pt->sr = sr;
pt->usage = usage;
pt->box = *box;
- pt->stride = sprex->stride[sr.level];
+ pt->stride = spr->stride[sr.level];
- spr->offset = sprex->level_offset[sr.level];
-
- if (resource->target == PIPE_TEXTURE_CUBE) {
- spr->offset += sr.face * nblocksy * pt->stride;
- }
- else if (resource->target == PIPE_TEXTURE_3D) {
- spr->offset += box->z * nblocksy * pt->stride;
- }
- else {
- assert(sr.face == 0);
- assert(box->z == 0);
- }
-
- spr->offset +=
- box->y / util_format_get_blockheight(format) * spr->base.stride +
+ spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z);
+
+ spt->offset +=
+ box->y / util_format_get_blockheight(format) * spt->base.stride +
box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
return pt;
@@ -356,26 +381,24 @@ static void *
softpipe_transfer_map(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
- struct softpipe_transfer *sp_transfer = softpipe_transfer(transfer);
- struct softpipe_resource *sp_resource = softpipe_resource(transfer->resource);
+ struct softpipe_transfer *spt = softpipe_transfer(transfer);
+ struct softpipe_resource *spr = softpipe_resource(transfer->resource);
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
uint8_t *map;
/* resources backed by display target treated specially:
*/
- if (sp_resource->dt) {
- map = winsys->displaytarget_map(winsys,
- sp_resource->dt,
- transfer->usage);
+ if (spr->dt) {
+ map = winsys->displaytarget_map(winsys, spr->dt, transfer->usage);
}
else {
- map = sp_resource->data;
+ map = spr->data;
}
if (map == NULL)
return NULL;
else
- return map + sp_transfer->offset;
+ return map + spt->offset;
}
@@ -412,26 +435,25 @@ softpipe_user_buffer_create(struct pipe_screen *screen,
unsigned bytes,
unsigned bind_flags)
{
- struct softpipe_resource *buffer;
+ struct softpipe_resource *spr;
- buffer = CALLOC_STRUCT(softpipe_resource);
- if(!buffer)
+ spr = CALLOC_STRUCT(softpipe_resource);
+ if (!spr)
return NULL;
-
- pipe_reference_init(&buffer->base.reference, 1);
- buffer->base.screen = screen;
- buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
- buffer->base.bind = bind_flags;
- buffer->base.usage = PIPE_USAGE_IMMUTABLE;
- buffer->base.flags = 0;
- buffer->base.width0 = bytes;
- buffer->base.height0 = 1;
- buffer->base.depth0 = 1;
- buffer->userBuffer = TRUE;
- buffer->data = ptr;
+ pipe_reference_init(&spr->base.reference, 1);
+ spr->base.screen = screen;
+ spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
+ spr->base.bind = bind_flags;
+ spr->base.usage = PIPE_USAGE_IMMUTABLE;
+ spr->base.flags = 0;
+ spr->base.width0 = bytes;
+ spr->base.height0 = 1;
+ spr->base.depth0 = 1;
+ spr->userBuffer = TRUE;
+ spr->data = ptr;
- return &buffer->base;
+ return &spr->base;
}
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c
index d996c2a342..f4db6f6ef0 100644
--- a/src/gallium/drivers/softpipe/sp_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.c
@@ -103,7 +103,7 @@ sp_create_tile_cache( struct pipe_context *pipe )
* However, it breaks clearing in other situations (such as in
* progs/tests/drawbuffers, see bug 24402).
*/
-#if 0 && TILE_CLEAR_OPTIMIZATION
+#if 0
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
#endif
@@ -155,7 +155,8 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
if (ps) {
tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->face,
ps->level, ps->zslice,
- PIPE_TRANSFER_READ_WRITE,
+ PIPE_TRANSFER_READ_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED,
0, 0, ps->width, ps->height);
tc->depth_stencil = (ps->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
@@ -344,9 +345,7 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc)
}
}
-#if TILE_CLEAR_OPTIMIZATION
sp_tile_cache_flush_clear(tc);
-#endif
}
#if 0
@@ -448,13 +447,8 @@ sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba,
tc->clear_val = clearValue;
-#if TILE_CLEAR_OPTIMIZATION
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
-#else
- /* disable the optimization */
- memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
-#endif
for (pos = 0; pos < NUM_ENTRIES; pos++) {
struct softpipe_cached_tile *tile = tc->entries + pos;
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h
index 753d8c0daa..e03d53eb24 100644
--- a/src/gallium/drivers/softpipe/sp_tile_cache.h
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.h
@@ -28,8 +28,6 @@
#ifndef SP_TILE_CACHE_H
#define SP_TILE_CACHE_H
-#define TILE_CLEAR_OPTIMIZATION 1
-
#include "pipe/p_compiler.h"