From 82ba7220afcb03f87606a0a8800eb067f0962724 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 5 Jul 2010 16:14:00 +0100 Subject: [PATCH] pixel-array: Allow passing of hints to cogl_buffer_map This allows you to tell Cogl that you are planning to replace all the buffer's data once it is mapped with cogl_buffer_map. This means if the buffer is currently being accessed by the GPU then the driver doesn't have to stall and wait for it to finish before it can access it from the CPU and can instead potentially allocate a new buffer with undefined data and map that. --- clutter/cogl/cogl/cogl-buffer-private.h | 3 ++- clutter/cogl/cogl/cogl-buffer.c | 8 +++--- clutter/cogl/cogl/cogl-buffer.h | 36 ++++++++++++++++++++++--- clutter/cogl/cogl/cogl-pixel-array.c | 9 ++++--- tests/conform/test-cogl-pixel-buffer.c | 4 ++- 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/clutter/cogl/cogl/cogl-buffer-private.h b/clutter/cogl/cogl/cogl-buffer-private.h index 49cf0de22..fb56631b7 100644 --- a/clutter/cogl/cogl/cogl-buffer-private.h +++ b/clutter/cogl/cogl/cogl-buffer-private.h @@ -52,7 +52,8 @@ typedef struct _CoglBufferVtable CoglBufferVtable; struct _CoglBufferVtable { guint8 * (* map) (CoglBuffer *buffer, - CoglBufferAccess access); + CoglBufferAccess access, + CoglBufferMapHint hints); void (* unmap) (CoglBuffer *buffer); diff --git a/clutter/cogl/cogl/cogl-buffer.c b/clutter/cogl/cogl/cogl-buffer.c index 2bc76021c..600eefb8c 100644 --- a/clutter/cogl/cogl/cogl-buffer.c +++ b/clutter/cogl/cogl/cogl-buffer.c @@ -22,6 +22,7 @@ * * Authors: * Damien Lespiau + * Robert Bragg */ /* For an overview of the functionality implemented here, please see @@ -228,8 +229,9 @@ cogl_buffer_get_update_hint (CoglBuffer *buffer) } guint8 * -cogl_buffer_map (CoglBuffer *buffer, - CoglBufferAccess access) +cogl_buffer_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints) { if (!cogl_is_buffer (buffer)) return NULL; @@ -237,7 +239,7 @@ cogl_buffer_map (CoglBuffer *buffer, if (COGL_BUFFER_FLAG_IS_SET (buffer, MAPPED)) return buffer->data; - buffer->data = buffer->vtable->map (buffer, access); + buffer->data = buffer->vtable->map (buffer, access, hints); return buffer->data; } diff --git a/clutter/cogl/cogl/cogl-buffer.h b/clutter/cogl/cogl/cogl-buffer.h index 3688c7802..7c61b51dc 100644 --- a/clutter/cogl/cogl/cogl-buffer.h +++ b/clutter/cogl/cogl/cogl-buffer.h @@ -22,6 +22,7 @@ * * Authors: * Damien Lespiau + * Robert Bragg */ #if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION) @@ -157,21 +158,50 @@ typedef enum { /*< prefix=COGL_BUFFER_ACCESS >*/ COGL_BUFFER_ACCESS_WRITE } CoglBufferAccess; + +/** + * CoglBufferMapHint: + * COGL_BUFFER_MAP_HINT_DISCARD: Tells Cogl that you plan to replace + * all the buffer's contents. + * + * Hints to Cogl about how you are planning to modify the data once it + * is mapped. + * + * Since: 1.4 + * Stability: Unstable + */ +typedef enum { /*< prefix=COGL_BUFFER_MAP_HINT >*/ + COGL_BUFFER_MAP_HINT_DISCARD = 1 << 0 +} CoglBufferMapHint; + /** * cogl_buffer_map: * @buffer: a buffer object - * @access: how the mapped buffer will by use by the application + * @access: how the mapped buffer will be used by the application + * @hints: A mask of #CoglBufferMapHints that tell Cogl how + * the data will be modified once mapped. * * Maps the buffer into the application address space for direct access. * + * It is strongly recommended that you pass + * %COGL_BUFFER_MAP_HINT_DISCARD as a hint if you are going to replace + * all the buffer's data. This way if the buffer is currently being + * used by the GPU then the driver won't have to stall the CPU and + * wait for the hardware to finish because it can instead allocate a + * new buffer to map. + * + * The behaviour is undefined if you access the buffer in a way + * conflicting with the @access mask you pass. + * * Return value: A pointer to the mapped memory or %NULL is the call fails * * Since: 1.2 * Stability: Unstable */ guint8 * -cogl_buffer_map (CoglBuffer *buffer, - CoglBufferAccess access); +cogl_buffer_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints); /** * cogl_buffer_unmap: diff --git a/clutter/cogl/cogl/cogl-pixel-array.c b/clutter/cogl/cogl/cogl-pixel-array.c index ba8d60fc2..f158c727f 100644 --- a/clutter/cogl/cogl/cogl-pixel-array.c +++ b/clutter/cogl/cogl/cogl-pixel-array.c @@ -177,7 +177,8 @@ _cogl_pixel_array_free (CoglPixelArray *buffer) #if !defined (COGL_HAS_GLES) static guint8 * _cogl_pixel_array_map (CoglBuffer *buffer, - CoglBufferAccess access) + CoglBufferAccess access, + CoglBufferMapHint hints) { CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer); GLenum gl_target; @@ -194,7 +195,8 @@ _cogl_pixel_array_map (CoglBuffer *buffer, /* create an empty store if we don't have one yet. creating the store * lazily allows the user of the CoglBuffer to set a hint before the * store is created. */ - if (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED)) + if (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED) || + (hints & COGL_BUFFER_MAP_HINT_DISCARD)) { GE( glBufferData (gl_target, buffer->size, @@ -294,7 +296,8 @@ static const CoglBufferVtable cogl_pixel_array_vtable = static guint8 * _cogl_malloc_pixel_array_map (CoglBuffer *buffer, - CoglBufferAccess access) + CoglBufferAccess access, + CoglBufferMapHint hints) { COGL_BUFFER_SET_FLAG (buffer, MAPPED); return buffer->data; diff --git a/tests/conform/test-cogl-pixel-buffer.c b/tests/conform/test-cogl-pixel-buffer.c index 5da9c4b73..20f51b5aa 100644 --- a/tests/conform/test-cogl-pixel-buffer.c +++ b/tests/conform/test-cogl-pixel-buffer.c @@ -78,7 +78,9 @@ create_map_tile (TestTile *tile) ==, COGL_BUFFER_UPDATE_HINT_DYNAMIC); - map = cogl_buffer_map (buffer, COGL_BUFFER_ACCESS_WRITE); + map = cogl_buffer_map (buffer, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); g_assert (map); line = g_alloca (TILE_SIZE * 4);