static CoglTexture2D * _cogl_atlas_create_texture (CoglAtlas *atlas, int width, int height) { CoglTexture2D *tex; CoglError *ignore_error = NULL; _COGL_GET_CONTEXT (ctx, NULL); if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE)) { uint8_t *clear_data; CoglBitmap *clear_bmp; int bpp = _cogl_pixel_format_get_bytes_per_pixel (atlas->texture_format); /* Create a buffer of zeroes to initially clear the texture */ clear_data = g_malloc0 (width * height * bpp); clear_bmp = cogl_bitmap_new_for_data (ctx, width, height, atlas->texture_format, width * bpp, clear_data); tex = cogl_texture_2d_new_from_bitmap (clear_bmp); _cogl_texture_set_internal_format (COGL_TEXTURE (tex), atlas->texture_format); if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error)) { cogl_error_free (ignore_error); cogl_object_unref (tex); tex = NULL; } cogl_object_unref (clear_bmp); g_free (clear_data); } else { tex = cogl_texture_2d_new_with_size (ctx, width, height); _cogl_texture_set_internal_format (COGL_TEXTURE (tex), atlas->texture_format); if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error)) { cogl_error_free (ignore_error); cogl_object_unref (tex); tex = NULL; } } return tex; }
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; }
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; }
CoglTexture * cogl_texture_new_from_foreign (GLuint gl_handle, GLenum gl_target, GLuint width, GLuint height, GLuint x_pot_waste, GLuint y_pot_waste, CoglPixelFormat format) { _COGL_GET_CONTEXT (ctx, NULL); #ifdef HAVE_COGL_GL if (gl_target == GL_TEXTURE_RECTANGLE_ARB) { CoglTextureRectangle *texture_rectangle; CoglSubTexture *sub_texture; if (x_pot_waste != 0 || y_pot_waste != 0) { /* It shouldn't be necessary to have waste in this case since * the texture isn't limited to power of two sizes. */ g_warning ("You can't create a foreign GL_TEXTURE_RECTANGLE cogl " "texture with waste\n"); return NULL; } texture_rectangle = cogl_texture_rectangle_new_from_foreign (ctx, gl_handle, width, height, format); _cogl_texture_set_internal_format (COGL_TEXTURE (texture_rectangle), format); /* CoglTextureRectangle textures work with non-normalized * coordinates, but the semantics for this function that people * depend on are that all returned texture works with normalized * coordinates so we wrap with a CoglSubTexture... */ sub_texture = cogl_sub_texture_new (ctx, COGL_TEXTURE (texture_rectangle), 0, 0, width, height); return COGL_TEXTURE (sub_texture); } #endif if (x_pot_waste != 0 || y_pot_waste != 0) { CoglTexture *tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_foreign (ctx, gl_handle, gl_target, width, height, x_pot_waste, y_pot_waste, format)); _cogl_texture_set_internal_format (tex, format); cogl_texture_allocate (tex, NULL); return tex; } else { CoglTexture *tex = COGL_TEXTURE (cogl_texture_2d_gl_new_from_foreign (ctx, gl_handle, width, height, format)); _cogl_texture_set_internal_format (tex, format); cogl_texture_allocate (tex, NULL); return tex; } }
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; }