예제 #1
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);
}
예제 #2
0
static void
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
{
  ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
  ClutterDeformEffectPrivate *priv = self->priv;
  gboolean is_depth_enabled, is_cull_enabled;
  CoglHandle material;
  gint n_tiles;

  if (priv->is_dirty)
    {
      ClutterActor *actor;
      gfloat width, height;
      guint opacity;
      gint i, j;

      actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
      opacity = clutter_actor_get_paint_opacity (actor);

      /* if we don't have a target size, fall back to the actor's
       * allocation, though wrong it might be
       */
      if (!clutter_offscreen_effect_get_target_size (effect, &width, &height))
        clutter_actor_get_size (actor, &width, &height);

      for (i = 0; i < priv->y_tiles + 1; i++)
        {
          for (j = 0; j < priv->x_tiles + 1; j++)
            {
              CoglTextureVertex *vertex;

              vertex = &priv->vertices[(i * (priv->x_tiles + 1)) + j];

              vertex->tx = (float) j / priv->x_tiles;
              vertex->ty = (float) i / priv->y_tiles;

              vertex->x = width * vertex->tx;
              vertex->y = height * vertex->ty;
              vertex->z = 0.0f;

              cogl_color_init_from_4ub (&vertex->color, 255, 255, 255, opacity);

              _clutter_deform_effect_deform_vertex (self, width, height, vertex);
            }
        }

      /* XXX in theory, the sub-classes should tell us what they changed
       * in the texture vertices; we then would be able to avoid resubmitting
       * the same data, if it did not change. for the time being, we resubmit
       * everything
       */
      cogl_vertex_buffer_add (priv->vbo, "gl_Vertex",
                              3,
                              COGL_ATTRIBUTE_TYPE_FLOAT,
                              FALSE,
                              sizeof (CoglTextureVertex),
                              &priv->vertices->x);
      cogl_vertex_buffer_add (priv->vbo, "gl_MultiTexCoord0",
                              2,
                              COGL_ATTRIBUTE_TYPE_FLOAT,
                              FALSE,
                              sizeof (CoglTextureVertex),
                              &priv->vertices->tx);
      cogl_vertex_buffer_add (priv->vbo, "gl_Color",
                              4,
                              COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE,
                              FALSE,
                              sizeof (CoglTextureVertex),
                              &priv->vertices->color);

      priv->is_dirty = FALSE;
    }

  /* enable depth test, if it's not already enabled */
  is_depth_enabled = cogl_get_depth_test_enabled ();
  if (!is_depth_enabled)
    cogl_set_depth_test_enabled (TRUE);

  /* enable backface culling if it's not already enabled and if
   * we have a back material
   */
  is_cull_enabled = cogl_get_backface_culling_enabled ();
  if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled)
    cogl_set_backface_culling_enabled (TRUE);
  else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled)
    cogl_set_backface_culling_enabled (FALSE);

  n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1);

  /* draw the front */
  material = clutter_offscreen_effect_get_target (effect);
  if (material != COGL_INVALID_HANDLE)
    {
      cogl_set_source (material);
      cogl_vertex_buffer_draw_elements (priv->vbo,
                                        COGL_VERTICES_MODE_TRIANGLE_STRIP,
                                        priv->indices,
                                        0,
                                        n_tiles,
                                        0,
                                        priv->n_indices);
    }

  /* draw the back */
  material = priv->back_material;
  if (material != COGL_INVALID_HANDLE)
    {
      cogl_set_source (priv->back_material);
      cogl_vertex_buffer_draw_elements (priv->vbo,
                                        COGL_VERTICES_MODE_TRIANGLE_STRIP,
                                        priv->back_indices,
                                        0,
                                        n_tiles,
                                        0,
                                        priv->n_indices);
    }

  /* restore the previous state */
  if (!is_depth_enabled)
    cogl_set_depth_test_enabled (FALSE);

  if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled)
    cogl_set_backface_culling_enabled (FALSE);
  else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled)
    cogl_set_backface_culling_enabled (TRUE);
}