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); }
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); }