Esempio n. 1
0
static void
test_pipeline (CoglPipeline *pipeline,
               int x_offset,
               int y_offset,
               const uint8_t expected_colors[9])
{
  float x1 = x_offset;
  float y1 = y_offset;
  float x2 = x1 + DRAW_SIZE;
  float y2 = y1 + DRAW_SIZE;
  int y, x;

  cogl_framebuffer_draw_textured_rectangle (test_fb,
                                            pipeline,
                                            x1, y1,
                                            x2, y2,
                                            -0.5f, /* s1 */
                                            -0.5f, /* t1 */
                                            1.5f, /* s2 */
                                            1.5f /* t2 */);

  check_colors (x_offset, y_offset, expected_colors);

  /* Also try drawing each quadrant of the rectangle with a small
   * rectangle */

  for (y = -1; y < 3; y++)
    for (x = -1; x < 3; x++)
      {
        x1 = x_offset + (x + 1) * DRAW_SIZE / 4 + DRAW_SIZE;
        y1 = y_offset + (y + 1) * DRAW_SIZE / 4;
        x2 = x1 + DRAW_SIZE / 4;
        y2 = y1 + DRAW_SIZE / 4;

        cogl_framebuffer_draw_textured_rectangle (test_fb,
                                                  pipeline,
                                                  x1, y1,
                                                  x2, y2,
                                                  x / 2.0f, /* s1 */
                                                  y / 2.0f, /* t1 */
                                                  (x + 1) / 2.0f, /* s2 */
                                                  (y + 1) / 2.0f /* t2 */);
      }

  check_colors (x_offset + DRAW_SIZE, y_offset, expected_colors);
}
Esempio n. 2
0
static void
texture_tower_revalidate_fbo (MetaTextureTower *tower,
                              int               level)
{
  CoglTexture *source_texture = tower->textures[level - 1];
  int source_texture_width = cogl_texture_get_width (source_texture);
  int source_texture_height = cogl_texture_get_height (source_texture);
  CoglTexture *dest_texture = tower->textures[level];
  int dest_texture_width = cogl_texture_get_width (dest_texture);
  int dest_texture_height = cogl_texture_get_height (dest_texture);
  Box *invalid = &tower->invalid[level];
  CoglFramebuffer *fb;
  CoglError *catch_error = NULL;
  CoglPipeline *pipeline;

  if (tower->fbos[level] == NULL)
    tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);

  fb = COGL_FRAMEBUFFER (tower->fbos[level]);

  if (!cogl_framebuffer_allocate (fb, &catch_error))
    {
      cogl_error_free (catch_error);
      return;
    }

  cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);

  if (!tower->pipeline_template)
    {
      CoglContext *ctx =
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
      tower->pipeline_template = cogl_pipeline_new (ctx);
      cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
    }

  pipeline = cogl_pipeline_copy (tower->pipeline_template);
  cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);

  cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
                                            invalid->x1, invalid->y1,
                                            invalid->x2, invalid->y2,
                                            (2. * invalid->x1) / source_texture_width,
                                            (2. * invalid->y1) / source_texture_height,
                                            (2. * invalid->x2) / source_texture_width,
                                            (2. * invalid->y2) / source_texture_height);

  cogl_object_unref (pipeline);
}
Esempio n. 3
0
static void
paint_test_backface_culling (TestState *state,
                             CoglFramebuffer *framebuffer)
{
  int draw_num;
  CoglPipeline *base_pipeline = cogl_pipeline_new (test_ctx);

  cogl_framebuffer_orthographic (framebuffer,
                                 0, 0,
                                 state->width,
                                 state->height,
                                 -1,
                                 100);

  cogl_framebuffer_clear4f (framebuffer,
                            COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL,
                            0, 0, 0, 1);

  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 eight times to test all of the combinations of
     cull face mode and winding orders */
  for (draw_num = 0; draw_num < 8; draw_num++)
    {
      float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
      CoglTextureVertex verts[4];
      CoglPipeline *pipeline;

      cogl_framebuffer_push_matrix (framebuffer);
      cogl_framebuffer_translate (framebuffer,
                                  0, TEXTURE_RENDER_SIZE * draw_num, 0);

      pipeline = cogl_pipeline_copy (base_pipeline);

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

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

      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

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

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

      /* Draw a front-facing texture with flipped texcoords */
      cogl_framebuffer_draw_textured_rectangle (framebuffer,
                                                pipeline,
                                                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_framebuffer_draw_rectangle (framebuffer, pipeline, x2, y1, x1, y2);

      cogl_framebuffer_pop_matrix (framebuffer);

      cogl_object_unref (pipeline);
    }

  cogl_object_unref (base_pipeline);
}
Esempio n. 4
0
static void
draw_frame (TestState *state)
{
  CoglTexture *tex = create_texture_3d (test_ctx);
  CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
  typedef struct { float x, y, s, t, r; } Vert;
  CoglPrimitive *primitive;
  CoglAttributeBuffer *attribute_buffer;
  CoglAttribute *attributes[2];
  Vert *verts, *v;
  int i;

  cogl_pipeline_set_layer_texture (pipeline, 0, tex);
  cogl_object_unref (tex);
  cogl_pipeline_set_layer_filters (pipeline, 0,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  /* Render the texture repeated horizontally twice using a regular
     cogl rectangle. This should end up with the r texture coordinates
     as zero */
  cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline,
                                            0.0f, 0.0f, TEX_WIDTH * 2, TEX_HEIGHT,
                                            0.0f, 0.0f, 2.0f, 1.0f);

  /* Render all of the images in the texture using coordinates from a
     CoglPrimitive */
  v = verts = g_new (Vert, 4 * TEX_DEPTH);
  for (i = 0; i < TEX_DEPTH; i++)
    {
      float r = (i + 0.5f) / TEX_DEPTH;

      v->x = i * TEX_WIDTH;
      v->y = TEX_HEIGHT;
      v->s = 0;
      v->t = 0;
      v->r = r;
      v++;

      v->x = i * TEX_WIDTH;
      v->y = TEX_HEIGHT * 2;
      v->s = 0;
      v->t = 1;
      v->r = r;
      v++;

      v->x = i * TEX_WIDTH + TEX_WIDTH;
      v->y = TEX_HEIGHT * 2;
      v->s = 1;
      v->t = 1;
      v->r = r;
      v++;

      v->x = i * TEX_WIDTH + TEX_WIDTH;
      v->y = TEX_HEIGHT;
      v->s = 1;
      v->t = 0;
      v->r = r;
      v++;
    }

  attribute_buffer = cogl_attribute_buffer_new (test_ctx,
                                                4 * TEX_DEPTH * sizeof (Vert),
                                                verts);
  attributes[0] = cogl_attribute_new (attribute_buffer,
                                      "cogl_position_in",
                                      sizeof (Vert),
                                      G_STRUCT_OFFSET (Vert, x),
                                      2, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_FLOAT);
  attributes[1] = cogl_attribute_new (attribute_buffer,
                                      "cogl_tex_coord_in",
                                      sizeof (Vert),
                                      G_STRUCT_OFFSET (Vert, s),
                                      3, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_FLOAT);
  primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
                                                  6 * TEX_DEPTH,
                                                  attributes,
                                                  2 /* n_attributes */);

  cogl_primitive_set_indices (primitive,
                              cogl_get_rectangle_indices (test_ctx,
                                                          TEX_DEPTH),
                              6 * TEX_DEPTH);

  cogl_primitive_draw (primitive, test_fb, pipeline);

  g_free (verts);

  cogl_object_unref (primitive);
  cogl_object_unref (attributes[0]);
  cogl_object_unref (attributes[1]);
  cogl_object_unref (attribute_buffer);
  cogl_object_unref (pipeline);
}
Esempio n. 5
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: (nullable): 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,
                   CoglFramebuffer *framebuffer,
                   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;
  gboolean source_updated = FALSE;

  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;

          if (overlap == CAIRO_REGION_OVERLAP_OUT)
            continue;

          if (!source_updated)
            {
              cogl_pipeline_set_color4ub (shadow->pipeline,
                                          opacity, opacity, opacity, opacity);
              cogl_set_source (shadow->pipeline);
              source_updated = TRUE;
            }

          /* 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_framebuffer_draw_textured_rectangle (framebuffer,
                                                        shadow->pipeline,
                                                        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_framebuffer_draw_textured_rectangle (framebuffer,
                                                            shadow->pipeline,
                                                            rect.x, rect.y,
                                                            rect.x + rect.width, rect.y + rect.height,
                                                            src_x1, src_y1, src_x2, src_y2);
                }

              cairo_region_destroy (intersection);
            }
        }
    }
}