r300g: reject resources from handles which are not large enough
authorMarek Olšák <maraeo@gmail.com>
Sat, 24 Jul 2010 01:34:18 +0000 (03:34 +0200)
committerMarek Olšák <maraeo@gmail.com>
Sun, 25 Jul 2010 08:25:21 +0000 (10:25 +0200)
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
src/gallium/drivers/r300/r300_texture.c
src/gallium/drivers/r300/r300_winsys.h
src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
src/gallium/winsys/radeon/drm/radeon_r300.c

index b9c96d5bdd88b9f90ea6d86e74ed309f68ceee32..7b58587a2a5b4ec328571730d6c174967f429eed 100644 (file)
@@ -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.
index 176fa76920819b9ea060bd1bdca80a0d00927601..711042722cca747d4f8fb697deb037869a2fae44 100644 (file)
@@ -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;
 }
index 7e115c2d624592dc69906be266276b84b972da8f..ff11546a647b9bbacf3d94eef1bb1633298062e4 100644 (file)
@@ -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
index 5ea5912089e038324e7beac5c68bca6f99d7c390..017eac8464e16b04d7c0e87ec3bc4ad8559bb1af 100644 (file)
@@ -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;
 
index effa27f5c72982052264b70fd3051905a3092382..554450406710adb33647695a370bc645257defc5 100644 (file)
@@ -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);
 }