static guint8 * _cogl_pixel_buffer_map (CoglBuffer *buffer, CoglBufferAccess access) { CoglPixelBuffer *pixel_buffer = COGL_PIXEL_BUFFER (buffer); GLenum gl_target; guint8 *data; _COGL_GET_CONTEXT (ctx, NULL); /* we determine the target lazily, on the first map */ gl_target = GL_PIXEL_UNPACK_BUFFER; pixel_buffer->gl_target = gl_target; _cogl_buffer_bind (buffer, gl_target); /* 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_BUFFER_FLAG_IS_SET (pixel_buffer, STORE_CREATED)) { GE( glBufferData (gl_target, buffer->size, NULL, _cogl_buffer_hints_to_gl_enum (buffer->usage_hint, buffer->update_hint)) ); COGL_PIXEL_BUFFER_SET_FLAG (pixel_buffer, STORE_CREATED); } GE_RET( data, glMapBuffer (gl_target, _cogl_buffer_access_to_gl_enum (access)) ); if (data) COGL_BUFFER_SET_FLAG (buffer, MAPPED); _cogl_buffer_bind (NULL, gl_target); return data; }
static void * bo_map (CoglBuffer *buffer, CoglBufferAccess access, CoglBufferMapHint hints) { uint8_t *data; CoglBufferBindTarget target; GLenum gl_target; CoglContext *ctx = buffer->context; if ((access & COGL_BUFFER_ACCESS_READ) && !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ)) return NULL; if ((access & COGL_BUFFER_ACCESS_WRITE) && !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE)) return NULL; target = buffer->last_target; _cogl_buffer_bind_no_create (buffer, target); gl_target = convert_bind_target_to_gl_target (target); /* 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 (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD)) bo_recreate_store (buffer); GE_RET( data, ctx, glMapBuffer (gl_target, _cogl_buffer_access_to_gl_enum (access)) ); if (data) buffer->flags |= COGL_BUFFER_FLAG_MAPPED; _cogl_buffer_unbind (buffer); return data; }
void * _cogl_buffer_gl_map_range (CoglBuffer *buffer, size_t offset, size_t size, CoglBufferAccess access, CoglBufferMapHint hints, CoglError **error) { uint8_t *data; CoglBufferBindTarget target; GLenum gl_target; CoglContext *ctx = buffer->context; GLenum gl_error; if (((access & COGL_BUFFER_ACCESS_READ) && !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ)) || ((access & COGL_BUFFER_ACCESS_WRITE) && !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE))) { _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Tried to map a buffer with unsupported access mode"); return NULL; } target = buffer->last_target; _cogl_buffer_bind_no_create (buffer, target); gl_target = convert_bind_target_to_gl_target (target); if ((hints & COGL_BUFFER_MAP_HINT_DISCARD_RANGE) && offset == 0 && size >= buffer->size) hints |= COGL_BUFFER_MAP_HINT_DISCARD; /* If the map buffer range extension is supported then we will * always use it even if we are mapping the full range because the * normal mapping function doesn't support passing the discard * hints */ if (ctx->glMapBufferRange) { GLbitfield gl_access = 0; CoglBool should_recreate_store = !buffer->store_created; if ((access & COGL_BUFFER_ACCESS_READ)) gl_access |= GL_MAP_READ_BIT; if ((access & COGL_BUFFER_ACCESS_WRITE)) gl_access |= GL_MAP_WRITE_BIT; if ((hints & COGL_BUFFER_MAP_HINT_DISCARD)) { /* glMapBufferRange generates an error if you pass the * discard hint along with asking for read access. However * it can make sense to ask for both if write access is also * requested so that the application can immediately read * back what it just wrote. To work around the restriction * in GL we just recreate the buffer storage in that case * which is an alternative way to indicate that the buffer * contents can be discarded. */ if ((access & COGL_BUFFER_ACCESS_READ)) should_recreate_store = TRUE; else gl_access |= GL_MAP_INVALIDATE_BUFFER_BIT; } else if ((hints & COGL_BUFFER_MAP_HINT_DISCARD_RANGE) && !(access & COGL_BUFFER_ACCESS_READ)) gl_access |= GL_MAP_INVALIDATE_RANGE_BIT; if (should_recreate_store) { if (!recreate_store (buffer, error)) { _cogl_buffer_gl_unbind (buffer); return NULL; } } /* Clear any GL errors */ while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR) ; data = ctx->glMapBufferRange (gl_target, offset, size, gl_access); if (_cogl_gl_util_catch_out_of_memory (ctx, error)) { _cogl_buffer_gl_unbind (buffer); return NULL; } _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); } else { /* 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 (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD)) { if (!recreate_store (buffer, error)) { _cogl_buffer_gl_unbind (buffer); return NULL; } } /* Clear any GL errors */ while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR) ; data = ctx->glMapBuffer (gl_target, _cogl_buffer_access_to_gl_enum (access)); if (_cogl_gl_util_catch_out_of_memory (ctx, error)) { _cogl_buffer_gl_unbind (buffer); return NULL; } _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); data += offset; } if (data) buffer->flags |= COGL_BUFFER_FLAG_MAPPED; _cogl_buffer_gl_unbind (buffer); return data; }