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;
}
Example #3
0
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);
    }
}
Example #4
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;
}
Example #5
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;
}
Example #6
0
/* 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);
}