From 065e3f7ff2a9b6170e51b0104036088e8d163ea0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 24 Jul 2010 03:34:18 +0200 Subject: [PATCH] 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. --- src/gallium/drivers/r300/r300_context.h | 7 ++++++- src/gallium/drivers/r300/r300_texture.c | 18 +++++++++++++++--- src/gallium/drivers/r300/r300_winsys.h | 7 ++++--- .../winsys/radeon/drm/radeon_drm_buffer.c | 2 +- src/gallium/winsys/radeon/drm/radeon_r300.c | 11 ++++++++--- 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); } -- 2.30.2