Beispiel #1
0
gboolean
_cogl_texture_2d_gl_can_create (CoglContext *ctx,
                                int width,
                                int height,
                                CoglPixelFormat internal_format)
{
  GLenum gl_intformat;
  GLenum gl_format;
  GLenum gl_type;

  /* If NPOT textures aren't supported then the size must be a power
     of two */
  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
      (!_cogl_util_is_pot (width) ||
       !_cogl_util_is_pot (height)))
    return FALSE;

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          internal_format,
                                          &gl_intformat,
                                          &gl_format,
                                          &gl_type);

  /* Check that the driver can create a texture with that size */
  if (!ctx->texture_driver->size_supported (ctx,
                                            GL_TEXTURE_2D,
                                            gl_intformat,
                                            gl_format,
                                            gl_type,
                                            width,
                                            height))
    return FALSE;

  return TRUE;
}
Beispiel #2
0
static CoglBool
_cogl_texture_3d_can_create (CoglContext *ctx,
                             int width,
                             int height,
                             int depth,
                             CoglPixelFormat internal_format,
                             CoglError **error)
{
  GLenum gl_intformat;
  GLenum gl_type;

  /* This should only happen on GLES */
  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "3D textures are not supported by the GPU");
      return FALSE;
    }

  /* If NPOT textures aren't supported then the size must be a power
     of two */
  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT) &&
      (!_cogl_util_is_pot (width) ||
       !_cogl_util_is_pot (height) ||
       !_cogl_util_is_pot (depth)))
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "A non-power-of-two size was requested but this is not "
                       "supported by the GPU");
      return FALSE;
    }

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          internal_format,
                                          &gl_intformat,
                                          NULL,
                                          &gl_type);

  /* Check that the driver can create a texture with that size */
  if (!ctx->texture_driver->size_supported_3d (ctx,
                                               GL_TEXTURE_3D,
                                               gl_intformat,
                                               gl_type,
                                               width,
                                               height,
                                               depth))
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "The requested dimensions are not supported by the GPU");
      return FALSE;
    }

  return TRUE;
}
Beispiel #3
0
static CoglBool
_cogl_texture_2d_can_hardware_repeat (CoglTexture *tex)
{
    CoglContext *ctx = tex->context;

    if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT) ||
            (_cogl_util_is_pot (tex->width) &&
             _cogl_util_is_pot (tex->height)))
        return TRUE;
    else
        return FALSE;
}
CoglTexture *
cogl_texture_new_with_size (CoglContext *ctx,
                            int width,
			    int height,
                            CoglTextureFlags flags,
			    CoglPixelFormat internal_format)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      /* First try creating a fast-path non-sliced texture */
      tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
                                                         width, height,
                                                         internal_format));

      /* TODO: instead of allocating storage here it would be better
       * if we had some api that let us just check that the size is
       * supported by the hardware so storage could be allocated
       * lazily when uploading data. */
      if (!cogl_texture_allocate (tex, &skip_error))
        {
          cogl_error_free (skip_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (tex)
    {
      CoglBool auto_mipmap = !(flags & COGL_TEXTURE_NO_AUTO_MIPMAP);
      cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex),
                                              auto_mipmap);
    }
  else
    {
      /* If it fails resort to sliced textures */
      int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
      cogl_error_free (skip_error);
      tex = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx,
                                                                width,
                                                                height,
                                                                max_waste,
                                                                internal_format));
    }

  return tex;
}
Beispiel #5
0
static CoglTexture *
create_migration_texture (CoglContext *ctx,
                          int width,
                          int height,
                          CoglPixelFormat internal_format)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      /* First try creating a fast-path non-sliced texture */
      tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
                                                         width, height));

      _cogl_texture_set_internal_format (tex, internal_format);

      /* TODO: instead of allocating storage here it would be better
       * if we had some api that let us just check that the size is
       * supported by the hardware so storage could be allocated
       * lazily when uploading data. */
      if (!cogl_texture_allocate (tex, &skip_error))
        {
          cogl_error_free (skip_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (!tex)
    {
      CoglTexture2DSliced *tex_2ds =
        cogl_texture_2d_sliced_new_with_size (ctx,
                                              width,
                                              height,
                                              COGL_TEXTURE_MAX_WASTE);

      _cogl_texture_set_internal_format (COGL_TEXTURE (tex_2ds),
                                         internal_format);

      tex = COGL_TEXTURE (tex_2ds);
    }

  return tex;
}
Beispiel #6
0
static CoglBool
_cogl_texture_2d_can_create (CoglContext *ctx,
                             unsigned int width,
                             unsigned int height,
                             CoglPixelFormat internal_format)
{
  /* If NPOT textures aren't supported then the size must be a power
     of two */
  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
      (!_cogl_util_is_pot (width) ||
       !_cogl_util_is_pot (height)))
    return FALSE;

  return ctx->driver_vtable->texture_2d_can_create (ctx,
                                                    width,
                                                    height,
                                                    internal_format);
}
Beispiel #7
0
CoglTexture *
cogl_texture_new_with_size (unsigned int width,
			    unsigned int height,
                            CoglTextureFlags flags,
			    CoglPixelFormat internal_format)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  _COGL_GET_CONTEXT (ctx, NULL);

  if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      /* First try creating a fast-path non-sliced texture */
      tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height));

      _cogl_texture_set_internal_format (tex, internal_format);

      if (!cogl_texture_allocate (tex, &skip_error))
        {
          cogl_error_free (skip_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (!tex)
    {
      /* If it fails resort to sliced textures */
      int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
      tex = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx,
                                                                width,
                                                                height,
                                                                max_waste));

      _cogl_texture_set_internal_format (tex, internal_format);
    }

  /* NB: This api existed before Cogl introduced lazy allocation of
   * textures and so we maintain its original synchronous allocation
   * semantics and return NULL if allocation fails... */
  if (!cogl_texture_allocate (tex, &skip_error))
    {
      cogl_error_free (skip_error);
      cogl_object_unref (tex);
      return NULL;
    }

  if (tex &&
      flags & COGL_TEXTURE_NO_AUTO_MIPMAP)
    {
      cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
                                           0, 0, 1, 1,
                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
                                           set_auto_mipmap_cb,
                                           NULL);
    }

  return tex;
}
Beispiel #8
0
static CoglTexture *
_cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
                               CoglTextureFlags flags,
                               CoglPixelFormat internal_format,
                               CoglBool can_convert_in_place,
                               CoglError **error)
{
  CoglContext *ctx = _cogl_bitmap_get_context (bitmap);
  CoglTexture *tex;
  CoglError *internal_error = NULL;

  if (!flags &&
      !COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ATLAS))
    {
      /* First try putting the texture in the atlas */
      CoglAtlasTexture *atlas_tex =
        _cogl_atlas_texture_new_from_bitmap (bitmap,
                                             can_convert_in_place);

      _cogl_texture_set_internal_format (COGL_TEXTURE (atlas_tex),
                                         internal_format);

      if (cogl_texture_allocate (COGL_TEXTURE (atlas_tex), &internal_error))
        return COGL_TEXTURE (atlas_tex);

      cogl_error_free (internal_error);
      internal_error = NULL;
      cogl_object_unref (atlas_tex);
    }

  /* If that doesn't work try a fast path 2D texture */
  if ((_cogl_util_is_pot (bitmap->width) &&
       _cogl_util_is_pot (bitmap->height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      tex = COGL_TEXTURE (_cogl_texture_2d_new_from_bitmap (bitmap,
                                                            can_convert_in_place));

      _cogl_texture_set_internal_format (tex, internal_format);

      if (!cogl_texture_allocate (tex, &internal_error))
        {
          cogl_error_free (internal_error);
          internal_error = NULL;
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (!tex)
    {
      /* Otherwise create a sliced texture */
      int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
      tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_bitmap (bitmap,
                                                             max_waste,
                                                             can_convert_in_place));

      _cogl_texture_set_internal_format (tex, internal_format);

      if (!cogl_texture_allocate (tex, error))
        {
          cogl_object_unref (tex);
          tex = NULL;
        }
    }

  if (tex &&
      flags & COGL_TEXTURE_NO_AUTO_MIPMAP)
    {
      cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
                                           0, 0, 1, 1,
                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
                                           set_auto_mipmap_cb,
                                           NULL);
    }

  return tex;
}
CoglTexture *
cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
                              CoglTextureFlags flags,
                              CoglPixelFormat internal_format,
                              CoglError **error)
{
  CoglContext *ctx = _cogl_bitmap_get_context (bitmap);
  CoglAtlasTexture *atlas_tex;
  CoglTexture *tex;
  CoglError *internal_error = NULL;

  /* First try putting the texture in the atlas */
  if ((atlas_tex = _cogl_atlas_texture_new_from_bitmap (bitmap,
                                                        flags,
                                                        internal_format,
                                                        &internal_error)))
    return COGL_TEXTURE (atlas_tex);

  if (cogl_error_matches (internal_error,
                          COGL_SYSTEM_ERROR,
                          COGL_SYSTEM_ERROR_NO_MEMORY))
    {
      _cogl_propagate_error (error, internal_error);
      return NULL;
    }

  cogl_error_free (internal_error);
  internal_error = NULL;

  /* If that doesn't work try a fast path 2D texture */
  if ((_cogl_util_is_pot (bitmap->width) &&
       _cogl_util_is_pot (bitmap->height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      tex = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap,
                                                           internal_format,
                                                           &internal_error));

      if (cogl_error_matches (internal_error,
                              COGL_SYSTEM_ERROR,
                              COGL_SYSTEM_ERROR_NO_MEMORY))
        {
          _cogl_propagate_error (error, internal_error);
          return NULL;
        }

      if (!tex)
        {
          cogl_error_free (internal_error);
          internal_error = NULL;
        }
    }
  else
    tex = NULL;

  if (tex)
    {
      CoglBool auto_mipmap = !(flags & COGL_TEXTURE_NO_AUTO_MIPMAP);
      cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex),
                                              auto_mipmap);
    }
  else
    {
      /* Otherwise create a sliced texture */
      tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_bitmap (bitmap,
                                                             flags,
                                                             internal_format,
                                                             error));
    }

  return tex;
}