static void _cogl_texture_pixmap_x11_foreach_sub_texture_in_region (CoglTexture *tex, float virtual_tx_1, float virtual_ty_1, float virtual_tx_2, float virtual_ty_2, CoglMetaTextureCallback callback, void *user_data) { CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); /* Forward on to the child texture */ /* tfp textures may be implemented in terms of a * CoglTextureRectangle texture which uses un-normalized texture * coordinates but we want to consistently deal with normalized * texture coordinates with CoglTexturePixmapX11... */ if (cogl_is_texture_rectangle (child_tex)) { NormalizeCoordsWrapperData data; int width = tex->width; int height = tex->height; virtual_tx_1 *= width; virtual_ty_1 *= height; virtual_tx_2 *= width; virtual_ty_2 *= height; data.width = width; data.height = height; data.callback = callback; data.user_data = user_data; cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (child_tex), virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2, COGL_PIPELINE_WRAP_MODE_REPEAT, COGL_PIPELINE_WRAP_MODE_REPEAT, normalize_coords_wrapper_cb, &data); } else cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (child_tex), virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2, COGL_PIPELINE_WRAP_MODE_REPEAT, COGL_PIPELINE_WRAP_MODE_REPEAT, callback, user_data); }
/* Determines if the given texture is using a rectangle texture as its * primitive texture type. Eventually this function could be replaced * with cogl_texture_get_type if Cogl makes that public. * * http://git.gnome.org/browse/cogl/commit/?h=8012eee31 */ gboolean meta_texture_rectangle_check (CoglTexture *texture) { gboolean result = FALSE; cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture), 0.0f, 0.0f, /* tx_1 / ty_1 */ 1.0f, 1.0f, /* tx_2 / ty_2 */ COGL_PIPELINE_WRAP_MODE_REPEAT, COGL_PIPELINE_WRAP_MODE_REPEAT, texture_rectangle_check_cb, &result); return result; }
static void _cogl_sub_texture_foreach_sub_texture_in_region ( CoglTexture *tex, float virtual_tx_1, float virtual_ty_1, float virtual_tx_2, float virtual_ty_2, CoglMetaTextureCallback callback, void *user_data) { CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); CoglTexture *full_texture = sub_tex->full_texture; float mapped_coords[4] = { virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2}; float virtual_coords[4] = { virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2}; /* map the virtual coordinates to ->full_texture coordinates */ _cogl_sub_texture_map_quad (sub_tex, mapped_coords); /* TODO: Add something like cogl_is_low_level_texture() */ if (cogl_is_texture_2d (full_texture) || cogl_is_texture_rectangle (full_texture)) { callback (sub_tex->full_texture, mapped_coords, virtual_coords, user_data); } else { CoglSubTextureForeachData data; data.sub_tex = sub_tex; data.callback = callback; data.user_data = user_data; cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (full_texture), mapped_coords[0], mapped_coords[1], mapped_coords[2], mapped_coords[3], COGL_PIPELINE_WRAP_MODE_REPEAT, COGL_PIPELINE_WRAP_MODE_REPEAT, unmap_coords_cb, &data); } }
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; }
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; }
/* TODO: support multitexturing */ static void _cogl_texture_quad_multiple_primitives (CoglFramebuffer *framebuffer, CoglPipeline *pipeline, CoglTexture *texture, int layer_index, const float *position, float tx_1, float ty_1, float tx_2, float ty_2) { TextureSlicedQuadState state; CoglBool tex_virtual_flipped_x; CoglBool tex_virtual_flipped_y; CoglBool quad_flipped_x; CoglBool quad_flipped_y; ValidateFirstLayerState validate_first_layer_state; CoglPipelineWrapMode wrap_s, wrap_t; wrap_s = cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index); wrap_t = cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index); validate_first_layer_state.override_pipeline = NULL; cogl_pipeline_foreach_layer (pipeline, validate_first_layer_cb, &validate_first_layer_state); state.framebuffer = framebuffer; state.main_texture = texture; if (validate_first_layer_state.override_pipeline) state.pipeline = validate_first_layer_state.override_pipeline; else state.pipeline = pipeline; /* Get together the data we need to transform the virtual texture * coordinates of each slice into quad coordinates... * * NB: We need to consider that the quad coordinates and the texture * coordinates may be inverted along the x or y axis, and must preserve the * inversions when we emit the final geometry. */ #define X0 0 #define Y0 1 #define X1 2 #define Y1 3 tex_virtual_flipped_x = (tx_1 > tx_2) ? TRUE : FALSE; tex_virtual_flipped_y = (ty_1 > ty_2) ? TRUE : FALSE; state.tex_virtual_origin_x = tex_virtual_flipped_x ? tx_2 : tx_1; state.tex_virtual_origin_y = tex_virtual_flipped_y ? ty_2 : ty_1; quad_flipped_x = (position[X0] > position[X1]) ? TRUE : FALSE; quad_flipped_y = (position[Y0] > position[Y1]) ? TRUE : FALSE; state.quad_origin_x = quad_flipped_x ? position[X1] : position[X0]; state.quad_origin_y = quad_flipped_y ? position[Y1] : position[Y0]; /* flatten the two forms of coordinate inversion into one... */ state.flipped_x = tex_virtual_flipped_x ^ quad_flipped_x; state.flipped_y = tex_virtual_flipped_y ^ quad_flipped_y; /* We use the _len_AXIS naming here instead of _width and _height because * log_quad_slice_cb uses a macro with symbol concatenation to handle both * axis, so this is more convenient... */ state.quad_len_x = fabs (position[X1] - position[X0]); state.quad_len_y = fabs (position[Y1] - position[Y0]); #undef X0 #undef Y0 #undef X1 #undef Y1 state.v_to_q_scale_x = fabs (state.quad_len_x / (tx_2 - tx_1)); state.v_to_q_scale_y = fabs (state.quad_len_y / (ty_2 - ty_1)); /* For backwards compatablity the default wrap mode for cogl_rectangle() is * _REPEAT... */ if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT; if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT; cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture), tx_1, ty_1, tx_2, ty_2, wrap_s, wrap_t, log_quad_sub_textures_cb, &state); if (validate_first_layer_state.override_pipeline) cogl_object_unref (validate_first_layer_state.override_pipeline); }