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
@ -56,9 +56,10 @@ struct _CoglBufferVtable
|
|||||||
|
|
||||||
typedef enum _CoglBufferFlags
|
typedef enum _CoglBufferFlags
|
||||||
{
|
{
|
||||||
COGL_BUFFER_FLAG_NONE = 0,
|
COGL_BUFFER_FLAG_NONE = 0,
|
||||||
COGL_BUFFER_FLAG_BUFFER_OBJECT = 1UL << 0, /* real openGL buffer object */
|
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;
|
} CoglBufferFlags;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -145,6 +146,18 @@ _cogl_buffer_immutable_ref (CoglBuffer *buffer);
|
|||||||
void
|
void
|
||||||
_cogl_buffer_immutable_unref (CoglBuffer *buffer);
|
_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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __COGL_BUFFER_PRIVATE_H__ */
|
#endif /* __COGL_BUFFER_PRIVATE_H__ */
|
||||||
|
@ -474,6 +474,57 @@ cogl_buffer_unmap (CoglBuffer *buffer)
|
|||||||
buffer->vtable.unmap (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
|
gboolean
|
||||||
cogl_buffer_set_data (CoglBuffer *buffer,
|
cogl_buffer_set_data (CoglBuffer *buffer,
|
||||||
gsize offset,
|
gsize offset,
|
||||||
|
@ -287,6 +287,9 @@ cogl_create_context (void)
|
|||||||
|
|
||||||
_context->atlases = NULL;
|
_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
|
/* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
|
||||||
unless GL_COORD_REPLACE is enabled for an individual
|
unless GL_COORD_REPLACE is enabled for an individual
|
||||||
layer. Therefore it seems like it should be ok to just leave it
|
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);
|
g_hash_table_unref (_context->arbfp_cache);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
g_byte_array_free (_context->buffer_map_fallback_array, TRUE);
|
||||||
|
|
||||||
g_free (_context);
|
g_free (_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,12 @@ typedef struct
|
|||||||
stencil buffer */
|
stencil buffer */
|
||||||
gboolean current_clip_stack_uses_stencil;
|
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;
|
CoglContextDriver drv;
|
||||||
CoglContextWinsys winsys;
|
CoglContextWinsys winsys;
|
||||||
} CoglContext;
|
} CoglContext;
|
||||||
|
@ -1058,8 +1058,7 @@ upload_vertices (const CoglJournalEntry *entries,
|
|||||||
buffer = COGL_BUFFER (array);
|
buffer = COGL_BUFFER (array);
|
||||||
cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC);
|
cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC);
|
||||||
|
|
||||||
vout = cogl_buffer_map (buffer, COGL_BUFFER_ACCESS_WRITE,
|
vout = _cogl_buffer_map_for_fill_or_fallback (buffer);
|
||||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
|
||||||
vin = &g_array_index (vertices, float, 0);
|
vin = &g_array_index (vertices, float, 0);
|
||||||
|
|
||||||
/* Expand the number of vertices from 2 to 4 while uploading */
|
/* Expand the number of vertices from 2 to 4 while uploading */
|
||||||
@ -1128,7 +1127,7 @@ upload_vertices (const CoglJournalEntry *entries,
|
|||||||
vout += vb_stride * 4;
|
vout += vb_stride * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_buffer_unmap (buffer);
|
_cogl_buffer_unmap_for_fill_or_fallback (buffer);
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
@ -1484,9 +1484,8 @@ _cogl_path_build_stroke_vbo (CoglPath *path)
|
|||||||
sizeof (floatVec2),
|
sizeof (floatVec2),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
vbo_p = cogl_buffer_map (COGL_BUFFER (data->stroke_vbo),
|
vbo_p =
|
||||||
COGL_BUFFER_ACCESS_WRITE,
|
_cogl_buffer_map_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
|
||||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
|
||||||
|
|
||||||
/* Copy the vertices in and count the number of sub paths. Each sub
|
/* 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
|
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++;
|
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);
|
data->stroke_vbo_attributes = g_new (CoglVertexAttribute *, n_attributes);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user