Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}