static void
meta_background_actor_paint (ClutterActor *actor)
{
  MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
  MetaBackgroundActorPrivate *priv = self->priv;
  guint8 opacity = clutter_actor_get_paint_opacity (actor);
  guint8 color_component;
  int width, height;

  meta_screen_get_size (priv->background->screen, &width, &height);

  color_component = (int)(0.5 + opacity * priv->dim_factor);

  cogl_material_set_color4ub (priv->material,
                              color_component,
                              color_component,
                              color_component,
                              opacity);

  cogl_set_source (priv->material);

  if (priv->visible_region)
    {
      int n_rectangles = cairo_region_num_rectangles (priv->visible_region);
      int i;

      for (i = 0; i < n_rectangles; i++)
        {
          cairo_rectangle_int_t rect;
          cairo_region_get_rectangle (priv->visible_region, i, &rect);

          cogl_rectangle_with_texture_coords (rect.x, rect.y,
                                              rect.x + rect.width, rect.y + rect.height,
                                              rect.x / priv->background->texture_width,
                                              rect.y / priv->background->texture_height,
                                              (rect.x + rect.width) / priv->background->texture_width,
                                              (rect.y + rect.height) / priv->background->texture_height);
        }
    }
  else
    {
      cogl_rectangle_with_texture_coords (0.0f, 0.0f,
                                          width, height,
                                          0.0f, 0.0f,
                                          width / priv->background->texture_width,
                                          height / priv->background->texture_height);
    }
}
Beispiel #2
0
void
_st_paint_shadow_with_opacity (StShadow        *shadow_spec,
                               CoglHandle       shadow_material,
                               ClutterActorBox *box,
                               guint8           paint_opacity)
{
  ClutterActorBox shadow_box;
  CoglColor       color;

  g_return_if_fail (shadow_spec != NULL);
  g_return_if_fail (shadow_material != COGL_INVALID_HANDLE);

  st_shadow_get_box (shadow_spec, box, &shadow_box);

  cogl_color_set_from_4ub (&color,
                           shadow_spec->color.red   * paint_opacity / 255,
                           shadow_spec->color.green * paint_opacity / 255,
                           shadow_spec->color.blue  * paint_opacity / 255,
                           shadow_spec->color.alpha * paint_opacity / 255);
  cogl_color_premultiply (&color);

  cogl_material_set_layer_combine_constant (shadow_material, 0, &color);

  cogl_set_source (shadow_material);
  cogl_rectangle_with_texture_coords (shadow_box.x1, shadow_box.y1,
                                      shadow_box.x2, shadow_box.y2,
                                      0, 0, 1, 1);
}
Beispiel #3
0
static void
glide_image_paint (ClutterActor *self)
{
  GlideImage *image = GLIDE_IMAGE (self);
  GlideImagePrivate *priv = image->priv;
  ClutterActorBox box = {0, };
  gfloat t_w, t_h;
  guint8 paint_opacity = clutter_actor_get_paint_opacity (self);

  if (paint_opacity == 0)
    {
      return;
    }
  
  GLIDE_NOTE (PAINT,
	      "painting image '%s'",
	      GLIDE_ACTOR_DISPLAY_NAME (self));
  
  cogl_material_set_color4ub (priv->material, paint_opacity, paint_opacity, paint_opacity, paint_opacity);
  clutter_actor_get_allocation_box (self, &box);
  
  GLIDE_NOTE (PAINT, "paint to x1: %f, y1: %f x2: %f, y2: %f "
	      "opacity: %i",
	      box.x1, box.y1, box.x2, box.y2,
	      clutter_actor_get_opacity (self));
  
  t_w = 1.0;
  t_h = 1.0;
  
  cogl_set_source (priv->material);
  cogl_rectangle_with_texture_coords (0, 0,
				      box.x2 - box.x1, box.y2 - box.y1,
				      0, 0, t_w, t_h);
}
static void
penge_magic_texture_paint (ClutterActor *actor)
{
  ClutterActorBox box;
  CoglHandle *material, *tex;
  float bw, bh;
  float aw, ah;
  float v;
  float tx1, tx2, ty1, ty2;
  guint8 alpha;

  clutter_actor_get_allocation_box (actor, &box);
  material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (actor));
  tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));

  bw = (float) cogl_texture_get_width (tex); /* base texture width */
  bh = (float) cogl_texture_get_height (tex); /* base texture height */

  aw = (float) (box.x2 - box.x1); /* allocation width */
  ah = (float) (box.y2 - box.y1); /* allocation height */

  /* no comment */
  if ((float)bw/bh < (float)aw/ah)
  {
    /* fit width */
    v = (((float)ah * bw) / ((float)aw * bh)) / 2;
    tx1 = 0;
    tx2 = 1;
    ty1 = (0.5 - v);
    ty2 = (0.5 + v);
  } else {
    /* fit height */
    v = (((float)aw * bh) / ((float)ah * bw)) / 2;
    tx1 = (0.5 - v);
    tx2 = (0.5 + v);
    ty1 = 0;
    ty2 = 1;
  }

  alpha = clutter_actor_get_paint_opacity (actor);

  cogl_material_set_color4ub (material,
                              alpha,
                              alpha,
                              alpha,
                              alpha);

  cogl_set_source (material);
  cogl_rectangle_with_texture_coords (0, 0,
                                      aw, ah,
                                      tx1, ty1,
                                      tx2, ty2);
}
Beispiel #5
0
static void
mnb_spinner_paint (ClutterActor *self)
{
  MnbSpinnerPrivate *priv   = MNB_SPINNER (self)->priv;
  MxWidget          *widget = MX_WIDGET (self);
  ClutterTexture    *background;

  /*
   * This paints border-image.
   */
  CLUTTER_ACTOR_CLASS (mnb_spinner_parent_class)->paint (self);

  if ((background = (ClutterTexture *) mx_widget_get_background_image (widget)))
    {
      gint            tx_w, tx_h;
      gfloat          tf_x, tf_y, tf_w, tf_h;
      guint8          opacity;
      ClutterActorBox box = { 0, };
      CoglHandle      material;

      if (!CLUTTER_IS_TEXTURE (background))
        return;

      opacity = clutter_actor_get_paint_opacity (self);

      if (opacity == 0)
        return;

      clutter_texture_get_base_size (background, &tx_w, &tx_h);

      material = clutter_texture_get_cogl_material (background);

      cogl_material_set_color4ub (material, opacity, opacity, opacity, opacity);

      clutter_actor_get_allocation_box (self, &box);

      tf_x = (gfloat)priv->frame / (gfloat) priv->n_frames;
      tf_y = 0.0;
      tf_w = tf_x + 1.0 / priv->n_frames;
      tf_h = 1.0;

      /* Paint will have translated us */
      cogl_set_source (material);
      cogl_rectangle_with_texture_coords (0.0, 0.0,
                                          box.x2 - box.x1,
                                          box.y2 - box.y1,
                                          tf_x, tf_y, tf_w, tf_h);
    }
}
static void
emit_rectangles_through_journal (CoglPangoDisplayListNode *node)
{
  int i;

  for (i = 0; i < node->d.texture.verts->len; i += 4)
    {
      CoglPangoDisplayListVertex *v0 =
        &g_array_index (node->d.texture.verts,
                        CoglPangoDisplayListVertex, i);
      CoglPangoDisplayListVertex *v1 =
        &g_array_index (node->d.texture.verts,
                        CoglPangoDisplayListVertex, i + 2);
      cogl_rectangle_with_texture_coords (v0->x, v0->y, v1->x, v1->y,
                                          v0->t_x, v0->t_y,
                                          v1->t_x, v1->t_y);
    }
}
Beispiel #7
0
static void
_cogl_blit_texture_render_blit (CoglBlitData *data,
                                unsigned int src_x,
                                unsigned int src_y,
                                unsigned int dst_x,
                                unsigned int dst_y,
                                unsigned int width,
                                unsigned int height)
{
  cogl_rectangle_with_texture_coords (dst_x, dst_y,
                                      dst_x + width,
                                      dst_y + height,
                                      src_x / (float) data->src_width,
                                      src_y / (float) data->src_height,
                                      (src_x + width) /
                                      (float) data->src_width,
                                      (src_y + height) /
                                      (float) data->src_height);
}
Beispiel #8
0
static void trickplay_webgl_canvas_paint (ClutterActor *self)
{
  ClutterTexture *texture = CLUTTER_TEXTURE (self);
  guint8 paint_opacity = clutter_actor_get_paint_opacity (self);

  CoglMaterial * material = ( CoglMaterial * ) clutter_texture_get_cogl_material( texture );

  cogl_material_set_color4ub (material,
			      paint_opacity,
                              paint_opacity,
                              paint_opacity,
                              paint_opacity);

  cogl_set_source (material);

  ClutterActorBox box;

  clutter_actor_get_allocation_box (self, &box);

  cogl_rectangle_with_texture_coords ( 0 , 0 , box.x2 - box.x1 , box.y2 - box.y1 ,
			              0, 1, 1, 0);
}
Beispiel #9
0
static void
on_paint (ClutterActor *actor, CallbackData *data)
{
  int i;
  ClutterGeometry stage_size;
  gint hand_width, hand_height;
  GSList *node;

  clutter_actor_get_allocation_geometry (data->stage, &stage_size);

  hand_width = cogl_texture_get_width (data->hand);
  hand_height = cogl_texture_get_height (data->hand);

  /* Setup the clipping */
  for (node = data->clips; node; node = node->next)
    {
      Clip *clip = (Clip *) node->data;

      if (clip->type == CLIP_RECTANGLE)
        cogl_clip_push_rectangle (clip->x1,
                                  clip->y1,
                                  clip->x2,
                                  clip->y2);
      else if (clip->type == CLIP_ROTATED_RECTANGLE)
        {
          float size = MIN (ABS (clip->x2 - clip->x1),
                            ABS (clip->y2 - clip->y1));
          int cx = (clip->x1 + clip->x2) / 2;
          int cy = (clip->y1 + clip->y2) / 2;

          size = sqrtf ((size / 2) * (size / 2) * 2);

          cogl_push_matrix ();

          /* Rotate 45° about the centre point */
          cogl_translate (cx, cy, 0.0f);
          cogl_rotate (45.0f, 0.0f, 0.0f, 1.0f);
          cogl_clip_push_rectangle (-size / 2, -size / 2, size / 2, size / 2);

          cogl_pop_matrix ();
        }
      else
        {
          make_clip_path (clip);
          cogl_clip_push_from_path ();
        }
    }

  /* Draw a rectangle filling the entire stage */
  cogl_set_source_color4ub (0x80, 0x80, 0xff, 0xff);
  cogl_rectangle (0, 0, stage_size.width, stage_size.height);

  draw_shapes (10, 10);

  /* Draw the hand at different rotations */
  for (i = -2; i <= 2; i++)
    {
      cogl_push_matrix ();

      cogl_translate (stage_size.width / 2 + stage_size.width / 6 * i,
                      stage_size.height / 2, 0);

      cogl_rotate (i * 40, 0, 1, 0);

      cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);

      cogl_set_source_texture (data->hand);
      cogl_rectangle_with_texture_coords ((-hand_width / 2),
                                          (-hand_height / 2),
                                          (hand_width / 2),
                                          (hand_height / 2),
                                          0, 0, 1, 1);

      cogl_pop_matrix ();
    }

  draw_shapes (stage_size.width - 310, stage_size.height - 110);

  /* Remove all of the clipping */
  g_slist_foreach (data->clips, (GFunc) cogl_clip_pop, NULL);

  /* Draw the bounding box for each of the clips */
  for (node = data->clips; node; node = node->next)
    {
      Clip *clip = (Clip *) node->data;

      make_clip_path (clip);
      cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
      cogl_path_stroke ();
    }

  /* Draw the bounding box for the pending new clip */
  if (data->current_clip.type != CLIP_NONE)
    {
      make_clip_path (&data->current_clip);
      cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
      cogl_path_stroke ();
    }
}
static void
st_drawing_area_paint (ClutterActor *self)
{
  StDrawingArea *area = ST_DRAWING_AREA (self);
  StDrawingAreaPrivate *priv = area->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
  ClutterActorBox allocation_box;
  ClutterActorBox content_box;
  int width, height;
  CoglColor color;
  guint8 paint_opacity;

  (CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class))->paint (self);

  clutter_actor_get_allocation_box (self, &allocation_box);
  st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);

  width = (int)(0.5 + content_box.x2 - content_box.x1);
  height = (int)(0.5 + content_box.y2 - content_box.y1);

  if (priv->material == COGL_INVALID_HANDLE)
    priv->material = cogl_material_new ();

  if (priv->texture != COGL_INVALID_HANDLE &&
      (width != cogl_texture_get_width (priv->texture) ||
       height != cogl_texture_get_height (priv->texture)))
    {
      cogl_handle_unref (priv->texture);
      priv->texture = COGL_INVALID_HANDLE;
    }

  if (width > 0 && height > 0)
    {
      if (priv->texture == COGL_INVALID_HANDLE)
        {
          priv->texture = cogl_texture_new_with_size (width, height,
                                                      COGL_TEXTURE_NONE,
                                                      CLUTTER_CAIRO_FORMAT_ARGB32);
          priv->needs_repaint = TRUE;
        }

      if (priv->needs_repaint)
        {
          cairo_surface_t *surface;

          surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
          priv->context = cairo_create (surface);
          priv->in_repaint = TRUE;
          priv->needs_repaint = FALSE;

          g_signal_emit ((GObject*)area, st_drawing_area_signals[REPAINT], 0);

          priv->in_repaint = FALSE;
          cairo_destroy (priv->context);
          priv->context = NULL;

          cogl_texture_set_region (priv->texture, 0, 0, 0, 0, width, height, width, height,
                                   CLUTTER_CAIRO_FORMAT_ARGB32,
                                   cairo_image_surface_get_stride (surface),
                                   cairo_image_surface_get_data (surface));

          cairo_surface_destroy (surface);
        }
    }

  cogl_material_set_layer (priv->material, 0, priv->texture);

  if (priv->texture)
    {
      paint_opacity = clutter_actor_get_paint_opacity (self);
      cogl_color_set_from_4ub (&color,
                               paint_opacity, paint_opacity, paint_opacity, paint_opacity);
      cogl_material_set_color (priv->material, &color);

      cogl_set_source (priv->material);
      cogl_rectangle_with_texture_coords (content_box.x1, content_box.y1,
                                          width, height,
                                          0.0f, 0.0f, 1.0f, 1.0f);
    }
}
Beispiel #11
0
static void
paint_test_backface_culling (TestState *state)
{
  int draw_num;
  CoglPipeline *base_pipeline = cogl_pipeline_new ();
  CoglColor clear_color;

  cogl_ortho (0, state->width, /* left, right */
              state->height, 0, /* bottom, top */
              -1, 100 /* z near, far */);

  cogl_color_init_from_4ub (&clear_color, 0x00, 0x00, 0x00, 0xff);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL);

  cogl_pipeline_set_layer_texture (base_pipeline, 0, state->texture);

  cogl_pipeline_set_layer_filters (base_pipeline, 0,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  /* Render the scene sixteen times to test all of the combinations of
     cull face mode, legacy state and winding orders */
  for (draw_num = 0; draw_num < 16; draw_num++)
    {
      float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
      CoglTextureVertex verts[4];
      CoglPipeline *pipeline;

      cogl_push_matrix ();
      cogl_translate (0, TEXTURE_RENDER_SIZE * draw_num, 0);

      pipeline = cogl_pipeline_copy (base_pipeline);

      cogl_set_backface_culling_enabled (USE_LEGACY_STATE (draw_num));
      cogl_pipeline_set_front_face_winding (pipeline, FRONT_WINDING (draw_num));
      cogl_pipeline_set_cull_face_mode (pipeline, CULL_FACE_MODE (draw_num));

      cogl_push_source (pipeline);

      memset (verts, 0, sizeof (verts));

      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture */
      cogl_rectangle (x1, y1, x2, y2);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture with flipped texcoords */
      cogl_rectangle_with_texture_coords (x1, y1, x2, y2,
                                          1.0, 0.0, 0.0, 1.0);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a back-facing texture */
      cogl_rectangle (x2, y1, x1, y2);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* If the texture is sliced then cogl_polygon doesn't work so
         we'll just use a solid color instead */
      if (cogl_texture_is_sliced (state->texture))
        cogl_set_source_color4ub (255, 0, 0, 255);

      /* Draw a front-facing polygon */
      verts[0].x = x1;    verts[0].y = y2;
      verts[1].x = x2;    verts[1].y = y2;
      verts[2].x = x2;    verts[2].y = y1;
      verts[3].x = x1;    verts[3].y = y1;
      verts[0].tx = 0;    verts[0].ty = 0;
      verts[1].tx = 1.0;  verts[1].ty = 0;
      verts[2].tx = 1.0;  verts[2].ty = 1.0;
      verts[3].tx = 0;    verts[3].ty = 1.0;
      cogl_polygon (verts, 4, FALSE);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a back-facing polygon */
      verts[0].x = x1;    verts[0].y = y1;
      verts[1].x = x2;    verts[1].y = y1;
      verts[2].x = x2;    verts[2].y = y2;
      verts[3].x = x1;    verts[3].y = y2;
      verts[0].tx = 0;    verts[0].ty = 0;
      verts[1].tx = 1.0;  verts[1].ty = 0;
      verts[2].tx = 1.0;  verts[2].ty = 1.0;
      verts[3].tx = 0;    verts[3].ty = 1.0;
      cogl_polygon (verts, 4, FALSE);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      cogl_pop_matrix ();

      cogl_pop_source ();
      cogl_object_unref (pipeline);
    }

  cogl_object_unref (base_pipeline);
}
Beispiel #12
0
/**
 * meta_shadow_paint:
 * @window_x: x position of the region to paint a shadow for
 * @window_y: y position of the region to paint a shadow for
 * @window_width: actual width of the region to paint a shadow for
 * @window_height: actual height of the region to paint a shadow for
 * @clip: (allow-none): if non-%NULL specifies the visible portion
 *   of the shadow.
 * @clip_strictly: if %TRUE, drawing will be clipped strictly
 *   to @clip, otherwise, it will be only used to optimize
 *   drawing.
 *
 * Paints the shadow at the given position, for the specified actual
 * size of the region. (Since a #MetaShadow can be shared between
 * different sizes with the same extracted #MetaWindowShape the
 * size needs to be passed in here.)
 */
void
meta_shadow_paint (MetaShadow     *shadow,
                   int             window_x,
                   int             window_y,
                   int             window_width,
                   int             window_height,
                   guint8          opacity,
                   cairo_region_t *clip,
                   gboolean        clip_strictly)
{
  float texture_width = cogl_texture_get_width (shadow->texture);
  float texture_height = cogl_texture_get_height (shadow->texture);
  int i, j;
  float src_x[4];
  float src_y[4];
  int dest_x[4];
  int dest_y[4];
  int n_x, n_y;

  cogl_material_set_color4ub (shadow->material,
                              opacity, opacity, opacity, opacity);

  cogl_set_source (shadow->material);

  if (shadow->scale_width)
    {
      n_x = 3;

      src_x[0] = 0.0;
      src_x[1] = (shadow->inner_border_left + shadow->outer_border_left) / texture_width;
      src_x[2] = (texture_width - (shadow->inner_border_right + shadow->outer_border_right)) / texture_width;
      src_x[3] = 1.0;

      dest_x[0] = window_x - shadow->outer_border_left;
      dest_x[1] = window_x + shadow->inner_border_left;
      dest_x[2] = window_x + window_width - shadow->inner_border_right;
      dest_x[3] = window_x + window_width + shadow->outer_border_right;
    }
  else
    {
      n_x = 1;

      src_x[0] = 0.0;
      src_x[1] = 1.0;

      dest_x[0] = window_x - shadow->outer_border_left;
      dest_x[1] = window_x + window_width + shadow->outer_border_right;
    }

  if (shadow->scale_height)
    {
      n_y = 3;

      src_y[0] = 0.0;
      src_y[1] = (shadow->inner_border_top + shadow->outer_border_top) / texture_height;
      src_y[2] = (texture_height - (shadow->inner_border_bottom + shadow->outer_border_bottom)) / texture_height;
      src_y[3] = 1.0;

      dest_y[0] = window_y - shadow->outer_border_top;
      dest_y[1] = window_y + shadow->inner_border_top;
      dest_y[2] = window_y + window_height - shadow->inner_border_bottom;
      dest_y[3] = window_y + window_height + shadow->outer_border_bottom;
    }
  else
    {
      n_y = 1;

      src_y[0] = 0.0;
      src_y[1] = 1.0;

      dest_y[0] = window_y - shadow->outer_border_top;
      dest_y[1] = window_y + window_height + shadow->outer_border_bottom;
    }

  for (j = 0; j < n_y; j++)
    {
      cairo_rectangle_int_t dest_rect;
      dest_rect.y = dest_y[j];
      dest_rect.height = dest_y[j + 1] - dest_y[j];

      if (dest_rect.height == 0)
        continue;

      for (i = 0; i < n_x; i++)
        {
          cairo_region_overlap_t overlap;

          dest_rect.x = dest_x[i];
          dest_rect.width = dest_x[i + 1] - dest_x[i];

          if (dest_rect.width == 0)
            continue;

          if (clip)
            overlap = cairo_region_contains_rectangle (clip, &dest_rect);
          else
            overlap = CAIRO_REGION_OVERLAP_IN;

          /* There's quite a bit of overhead from allocating a new
           * region in order to find an exact intersection and
           * generating more geometry - we make the assumption that
           * unless we have to clip strictly it will be cheaper to
           * just draw the entire rectangle.
           */
          if (overlap == CAIRO_REGION_OVERLAP_IN ||
              (overlap == CAIRO_REGION_OVERLAP_PART && !clip_strictly))
            {
              cogl_rectangle_with_texture_coords (dest_x[i], dest_y[j],
                                                  dest_x[i + 1], dest_y[j + 1],
                                                  src_x[i], src_y[j],
                                                  src_x[i + 1], src_y[j + 1]);
            }
          else if (overlap == CAIRO_REGION_OVERLAP_PART)
            {
              cairo_region_t *intersection;
              int n_rectangles, k;

              intersection = cairo_region_create_rectangle (&dest_rect);
              cairo_region_intersect (intersection, clip);

              n_rectangles = cairo_region_num_rectangles (intersection);
              for (k = 0; k < n_rectangles; k++)
                {
                  cairo_rectangle_int_t rect;
                  float src_x1, src_x2, src_y1, src_y2;

                  cairo_region_get_rectangle (intersection, k, &rect);

                  /* Separately linear interpolate X and Y coordinates in the source
                   * based on the destination X and Y coordinates */

                  src_x1 = (src_x[i] * (dest_rect.x + dest_rect.width - rect.x) +
                            src_x[i + 1] * (rect.x - dest_rect.x)) / dest_rect.width;
                  src_x2 = (src_x[i] * (dest_rect.x + dest_rect.width - (rect.x + rect.width)) +
                            src_x[i + 1] * (rect.x + rect.width - dest_rect.x)) / dest_rect.width;

                  src_y1 = (src_y[j] * (dest_rect.y + dest_rect.height - rect.y) +
                            src_y[j + 1] * (rect.y - dest_rect.y)) / dest_rect.height;
                  src_y2 = (src_y[j] * (dest_rect.y + dest_rect.height - (rect.y + rect.height)) +
                            src_y[j + 1] * (rect.y + rect.height - dest_rect.y)) / dest_rect.height;

                  cogl_rectangle_with_texture_coords (rect.x, rect.y,
                                                      rect.x + rect.width, rect.y + rect.height,
                                                      src_x1, src_y1, src_x2, src_y2);
                }

              cairo_region_destroy (intersection);
            }
        }
    }
}
Beispiel #13
0
/* Reads back the contents of a texture by rendering it to the framebuffer
 * and reading back the resulting pixels.
 *
 * It will perform multiple renders if the texture is larger than the
 * current glViewport.
 *
 * It assumes the projection and modelview have already been setup so
 * that rendering to 0,0 with the same width and height of the viewport
 * will exactly cover the viewport.
 *
 * NB: Normally this approach isn't normally used since we can just use
 * glGetTexImage, but may be used as a fallback in some circumstances.
 */
static void
do_texture_draw_and_read (CoglHandle   handle,
                          CoglBitmap  *target_bmp,
                          GLint       *viewport)
{
  int         bpp;
  float       rx1, ry1;
  float       rx2, ry2;
  float       tx1, ty1;
  float       tx2, ty2;
  int         bw,  bh;
  CoglBitmap  *rect_bmp;
  unsigned int  tex_width, tex_height;

  bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);

  tex_width = cogl_texture_get_width (handle);
  tex_height = cogl_texture_get_height (handle);

  ry2 = 0;
  ty2 = 0;

  /* Walk Y axis until whole bitmap height consumed */
  for (bh = tex_height; bh > 0; bh -= viewport[3])
    {
      /* Rectangle Y coords */
      ry1 = ry2;
      ry2 += (bh < viewport[3]) ? bh : viewport[3];

      /* Normalized texture Y coords */
      ty1 = ty2;
      ty2 = (ry2 / (float) tex_height);

      rx2 = 0;
      tx2 = 0;

      /* Walk X axis until whole bitmap width consumed */
      for (bw = tex_width; bw > 0; bw-=viewport[2])
        {
          int width;
          int height;
          int rowstride;
          guint8 *data;

          /* Rectangle X coords */
          rx1 = rx2;
          rx2 += (bw < viewport[2]) ? bw : viewport[2];

          width = rx2 - rx1;
          height = ry2 - ry1;
          rowstride = width * bpp;

          /* Normalized texture X coords */
          tx1 = tx2;
          tx2 = (rx2 / (float) tex_width);

          /* Draw a portion of texture */
          cogl_rectangle_with_texture_coords (0, 0,
                                              rx2 - rx1,
                                              ry2 - ry1,
                                              tx1, ty1,
                                              tx2, ty2);

          data = g_malloc (height * rowstride);

          /* Read into a temporary bitmap */
          rect_bmp =
            _cogl_bitmap_new_from_data (data,
                                        COGL_PIXEL_FORMAT_RGBA_8888,
                                        width,
                                        height,
                                        rowstride,
                                        (CoglBitmapDestroyNotify) g_free,
                                        NULL);

          cogl_read_pixels (viewport[0], viewport[1],
                            width,
                            height,
                            COGL_READ_PIXELS_COLOR_BUFFER,
                            COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                            data);

          /* Copy to target bitmap */
          _cogl_bitmap_copy_subregion (rect_bmp,
                                       target_bmp,
                                       0,0,
                                       rx1,ry1,
                                       width,
                                       height);

          /* Free temp bitmap */
          cogl_object_unref (rect_bmp);
        }
    }
}