cogl: Fallback to set_data when mapping a buffer to fill it
In the journal code and when generating the stroke path the vertices are generated on the fly and stored in a CoglBuffer using cogl_buffer_map. However cogl_buffer_map is allowed to fail but it wasn't checking for a NULL return value. In particular on GLES it will always fail because glMapBuffer is only provided by an extension. This adds a new pair of internal functions called _cogl_buffer_{un,}map_for_fill_or_fallback which wrap cogl_buffer_map. If the map fails then it will instead return a pointer into a GByteArray attached to the context. When the buffer is unmapped the array is copied into the buffer using cogl_buffer_set_data.
This commit is contained in:
parent
ac81f3b936
commit
a8216aff2f
@ -58,7 +58,8 @@ typedef enum _CoglBufferFlags
|
||||
{
|
||||
COGL_BUFFER_FLAG_NONE = 0,
|
||||
COGL_BUFFER_FLAG_BUFFER_OBJECT = 1UL << 0, /* real openGL buffer object */
|
||||
COGL_BUFFER_FLAG_MAPPED = 1UL << 1
|
||||
COGL_BUFFER_FLAG_MAPPED = 1UL << 1,
|
||||
COGL_BUFFER_FLAG_MAPPED_FALLBACK = 1UL << 2
|
||||
} CoglBufferFlags;
|
||||
|
||||
typedef enum {
|
||||
@ -145,6 +146,18 @@ _cogl_buffer_immutable_ref (CoglBuffer *buffer);
|
||||
void
|
||||
_cogl_buffer_immutable_unref (CoglBuffer *buffer);
|
||||
|
||||
/* This is a wrapper around cogl_buffer_map for internal use when we
|
||||
want to map the buffer for write only to replace the entire
|
||||
contents. If the map fails then it will fallback to writing to a
|
||||
temporary buffer. When _cogl_buffer_unmap_for_fill_or_fallback is
|
||||
called the temporary buffer will be copied into the array. Note
|
||||
that these calls share a global array so they can not be nested. */
|
||||
void *
|
||||
_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer);
|
||||
|
||||
void
|
||||
_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_BUFFER_PRIVATE_H__ */
|
||||
|
@ -474,6 +474,57 @@ cogl_buffer_unmap (CoglBuffer *buffer)
|
||||
buffer->vtable.unmap (buffer);
|
||||
}
|
||||
|
||||
void *
|
||||
_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NULL);
|
||||
|
||||
g_return_val_if_fail (!ctx->buffer_map_fallback_in_use, NULL);
|
||||
|
||||
ctx->buffer_map_fallback_in_use = TRUE;
|
||||
|
||||
ret = cogl_buffer_map (buffer,
|
||||
COGL_BUFFER_ACCESS_WRITE,
|
||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
else
|
||||
{
|
||||
/* If the map fails then we'll use a temporary buffer to fill
|
||||
the data and then upload it using cogl_buffer_set_data when
|
||||
the buffer is unmapped. The temporary buffer is shared to
|
||||
avoid reallocating it every time */
|
||||
g_byte_array_set_size (ctx->buffer_map_fallback_array, buffer->size);
|
||||
|
||||
buffer->flags |= COGL_BUFFER_FLAG_MAPPED_FALLBACK;
|
||||
|
||||
return ctx->buffer_map_fallback_array->data;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
g_return_if_fail (ctx->buffer_map_fallback_in_use);
|
||||
|
||||
ctx->buffer_map_fallback_in_use = FALSE;
|
||||
|
||||
if ((buffer->flags & COGL_BUFFER_FLAG_MAPPED_FALLBACK))
|
||||
{
|
||||
cogl_buffer_set_data (buffer, 0,
|
||||
ctx->buffer_map_fallback_array->data,
|
||||
buffer->size);
|
||||
buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED_FALLBACK;
|
||||
}
|
||||
else
|
||||
cogl_buffer_unmap (buffer);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_buffer_set_data (CoglBuffer *buffer,
|
||||
gsize offset,
|
||||
|
@ -287,6 +287,9 @@ cogl_create_context (void)
|
||||
|
||||
_context->atlases = NULL;
|
||||
|
||||
_context->buffer_map_fallback_array = g_byte_array_new ();
|
||||
_context->buffer_map_fallback_in_use = FALSE;
|
||||
|
||||
/* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
|
||||
unless GL_COORD_REPLACE is enabled for an individual
|
||||
layer. Therefore it seems like it should be ok to just leave it
|
||||
@ -385,6 +388,8 @@ _cogl_destroy_context (void)
|
||||
g_hash_table_unref (_context->arbfp_cache);
|
||||
#endif
|
||||
|
||||
g_byte_array_free (_context->buffer_map_fallback_array, TRUE);
|
||||
|
||||
g_free (_context);
|
||||
}
|
||||
|
||||
|
@ -229,6 +229,12 @@ typedef struct
|
||||
stencil buffer */
|
||||
gboolean current_clip_stack_uses_stencil;
|
||||
|
||||
/* This is used as a temporary buffer to fill a CoglBuffer when
|
||||
cogl_buffer_map fails and we only want to map to fill it with new
|
||||
data */
|
||||
GByteArray *buffer_map_fallback_array;
|
||||
gboolean buffer_map_fallback_in_use;
|
||||
|
||||
CoglContextDriver drv;
|
||||
CoglContextWinsys winsys;
|
||||
} CoglContext;
|
||||
|
@ -1058,8 +1058,7 @@ upload_vertices (const CoglJournalEntry *entries,
|
||||
buffer = COGL_BUFFER (array);
|
||||
cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC);
|
||||
|
||||
vout = cogl_buffer_map (buffer, COGL_BUFFER_ACCESS_WRITE,
|
||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||
vout = _cogl_buffer_map_for_fill_or_fallback (buffer);
|
||||
vin = &g_array_index (vertices, float, 0);
|
||||
|
||||
/* Expand the number of vertices from 2 to 4 while uploading */
|
||||
@ -1128,7 +1127,7 @@ upload_vertices (const CoglJournalEntry *entries,
|
||||
vout += vb_stride * 4;
|
||||
}
|
||||
|
||||
cogl_buffer_unmap (buffer);
|
||||
_cogl_buffer_unmap_for_fill_or_fallback (buffer);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
@ -1484,9 +1484,8 @@ _cogl_path_build_stroke_vbo (CoglPath *path)
|
||||
sizeof (floatVec2),
|
||||
NULL);
|
||||
|
||||
vbo_p = cogl_buffer_map (COGL_BUFFER (data->stroke_vbo),
|
||||
COGL_BUFFER_ACCESS_WRITE,
|
||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||
vbo_p =
|
||||
_cogl_buffer_map_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
|
||||
|
||||
/* Copy the vertices in and count the number of sub paths. Each sub
|
||||
path will form a separate attribute so we can paint the disjoint
|
||||
@ -1506,7 +1505,7 @@ _cogl_path_build_stroke_vbo (CoglPath *path)
|
||||
n_attributes++;
|
||||
}
|
||||
|
||||
cogl_buffer_unmap (COGL_BUFFER (data->stroke_vbo));
|
||||
_cogl_buffer_unmap_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
|
||||
|
||||
data->stroke_vbo_attributes = g_new (CoglVertexAttribute *, n_attributes);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user