aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-07-24 03:34:18 +0200
committerMarek Olšák <[email protected]>2010-07-25 10:25:21 +0200
commit065e3f7ff2a9b6170e51b0104036088e8d163ea0 (patch)
tree04060c79de38bb73937803dd48673c617836f366
parent4ce26210842176c4b280b7db85639ced40d4083d (diff)
r300g: reject resources from handles which are not large enough
The driver gets a buffer and its size in resource_from_handle. It computes the required minimum buffer size from given texture properties, and compares the two sizes. This is to early detect DDX bugs.
-rw-r--r--src/gallium/drivers/r300/r300_context.h7
-rw-r--r--src/gallium/drivers/r300/r300_texture.c18
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h7
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_buffer.c2
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_r300.c11
5 files changed, 34 insertions, 11 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index b9c96d5bdd8..7b58587a2a5 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -352,9 +352,14 @@ struct r300_texture {
*/
unsigned stride_override;
- /* Total size of this texture, in bytes. */
+ /* Total size of this texture, in bytes,
+ * derived from the texture properties. */
unsigned size;
+ /* Total size of the buffer backing this texture, in bytes.
+ * It must be >= size. */
+ unsigned buffer_size;
+
/* Whether this texture has non-power-of-two dimensions
* or a user-specified pitch.
* It can be either a regular texture or a rectangle one.
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 176fa769208..711042722cc 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -1022,6 +1022,7 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
tex->buffer = rws->buffer_create(rws, tex->size, 2048, base->bind,
base->usage, tex->domain);
+ tex->buffer_size = tex->size;
if (!tex->buffer) {
FREE(tex);
@@ -1120,7 +1121,7 @@ r300_texture_from_handle(struct pipe_screen* screen,
struct r300_screen* rscreen = r300_screen(screen);
struct r300_winsys_buffer *buffer;
struct r300_texture* tex;
- unsigned stride;
+ unsigned stride, size;
boolean override_zb_flags;
/* Support only 2D textures without mipmaps */
@@ -1130,7 +1131,7 @@ r300_texture_from_handle(struct pipe_screen* screen,
return NULL;
}
- buffer = rws->buffer_from_handle(rws, whandle, &stride);
+ buffer = rws->buffer_from_handle(rws, whandle, &stride, &size);
if (!buffer) {
return NULL;
}
@@ -1150,6 +1151,7 @@ r300_texture_from_handle(struct pipe_screen* screen,
/* one ref already taken */
tex->buffer = buffer;
+ tex->buffer_size = size;
rws->buffer_get_tiling(rws, buffer, &tex->microtile, &tex->macrotile);
r300_setup_flags(tex);
@@ -1186,8 +1188,18 @@ r300_texture_from_handle(struct pipe_screen* screen,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
}
- if (SCREEN_DBG_ON(rscreen, DBG_TEX))
+ /* Make sure the buffer we got is large enough. */
+ if (tex->size > tex->buffer_size) {
+ fprintf(stderr, "r300: texture_from_handle: The buffer is not "
+ "large enough. Got: %i, Need: %i, Info:\n",
+ tex->buffer_size, tex->size);
r300_tex_print_info(rscreen, tex, "texture_from_handle");
+ pipe_resource_reference((struct pipe_resource**)&tex, NULL);
+ return NULL;
+ } else {
+ if (SCREEN_DBG_ON(rscreen, DBG_TEX))
+ r300_tex_print_info(rscreen, tex, "texture_from_handle");
+ }
return (struct pipe_resource*)tex;
}
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index 7e115c2d624..ff11546a647 100644
--- a/src/gallium/drivers/r300/r300_winsys.h
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -184,12 +184,13 @@ struct r300_winsys_screen {
* \param ws The winsys this function is called from.
* \param whandle A winsys handle pointer as was received from a state
* tracker.
- * \param stride A pointer to the stride return variable.
- * The stride is in bytes.
+ * \param stride The returned buffer stride in bytes.
+ * \param size The returned buffer size.
*/
struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws,
struct winsys_handle *whandle,
- unsigned *stride);
+ unsigned *stride,
+ unsigned *size);
/**
* Get a winsys handle from a winsys buffer. The internal structure
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
index 5ea5912089e..017eac8464e 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
@@ -189,7 +189,7 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
pipe_reference_init(&buf->base.base.reference, 1);
buf->base.base.alignment = 0;
buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
- buf->base.base.size = 0;
+ buf->base.base.size = bo->size;
buf->base.vtbl = &radeon_drm_buffer_vtbl;
buf->mgr = mgr;
diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c
index effa27f5c72..55445040671 100644
--- a/src/gallium/winsys/radeon/drm/radeon_r300.c
+++ b/src/gallium/winsys/radeon/drm/radeon_r300.c
@@ -109,14 +109,19 @@ static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
struct winsys_handle *whandle,
- unsigned *stride)
+ unsigned *stride,
+ unsigned *size)
{
struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
struct pb_buffer *_buf;
- *stride = whandle->stride;
-
_buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
+
+ if (stride)
+ *stride = whandle->stride;
+ if (size)
+ *size = _buf->base.size;
+
return radeon_libdrm_winsys_buffer(_buf);
}