CoglPipeline * _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec, ClutterActor *actor) { CoglPipeline *shadow_pipeline = NULL; if (CLUTTER_IS_TEXTURE (actor)) { CoglTexture *texture; texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor)); if (texture) shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, texture); } else { CoglTexture *buffer; CoglOffscreen *offscreen; CoglFramebuffer *fb; ClutterActorBox box; CoglColor clear_color; float width, height; CoglError *catch_error = NULL; clutter_actor_get_allocation_box (actor, &box); clutter_actor_box_get_size (&box, &width, &height); if (width == 0 || height == 0) return NULL; buffer = cogl_texture_new_with_size (width, height, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY); if (buffer == NULL) return NULL; offscreen = cogl_offscreen_new_with_texture (buffer); fb = COGL_FRAMEBUFFER (offscreen); if (!cogl_framebuffer_allocate (fb, &catch_error)) { cogl_error_free (catch_error); cogl_object_unref (offscreen); cogl_object_unref (buffer); return NULL; } cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); /* XXX: There's no way to render a ClutterActor to an offscreen * as it uses the implicit API. */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS; cogl_push_framebuffer (fb); G_GNUC_END_IGNORE_DEPRECATIONS; cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color); cogl_framebuffer_translate (fb, -box.x1, -box.y1, 0); cogl_framebuffer_orthographic (fb, 0, 0, width, height, 0, 1.0); clutter_actor_set_opacity_override (actor, 255); clutter_actor_paint (actor); clutter_actor_set_opacity_override (actor, -1); G_GNUC_BEGIN_IGNORE_DEPRECATIONS; cogl_pop_framebuffer (); G_GNUC_END_IGNORE_DEPRECATIONS; cogl_object_unref (fb); shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, buffer); cogl_object_unref (buffer); } return shadow_pipeline; }
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); }
static void paint (TestState *state) { CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); CoglTexture *tex; CoglColor color; CoglError *error = NULL; CoglHandle shader, program; cogl_color_init_from_4ub (&color, 0, 0, 0, 255); cogl_clear (&color, COGL_BUFFER_BIT_COLOR); /* Set the primary vertex color as red */ cogl_color_set_from_4ub (&color, 0xff, 0x00, 0x00, 0xff); cogl_pipeline_set_color (pipeline, &color); /* Override the vertex color in the texture environment with a constant green color provided by a texture */ tex = create_dummy_texture (); cogl_pipeline_set_layer_texture (pipeline, 0, tex); cogl_object_unref (tex); if (!cogl_pipeline_set_layer_combine (pipeline, 0, "RGBA=REPLACE(TEXTURE)", &error)) { g_warning ("Error setting layer combine: %s", error->message); g_assert_not_reached (); } /* Set up a dummy vertex shader that does nothing but the usual fixed function transform */ shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX); cogl_shader_source (shader, "void\n" "main ()\n" "{\n" " cogl_position_out = " "cogl_modelview_projection_matrix * " "cogl_position_in;\n" " cogl_color_out = cogl_color_in;\n" " cogl_tex_coord_out[0] = cogl_tex_coord_in;\n" "}\n"); cogl_shader_compile (shader); if (!cogl_shader_is_compiled (shader)) { char *log = cogl_shader_get_info_log (shader); g_warning ("Shader compilation failed:\n%s", log); g_free (log); g_assert_not_reached (); } program = cogl_create_program (); cogl_program_attach_shader (program, shader); cogl_program_link (program); cogl_handle_unref (shader); /* Draw something without the program */ cogl_set_source (pipeline); cogl_rectangle (0, 0, 50, 50); /* Draw it again using the program. It should look exactly the same */ cogl_pipeline_set_user_program (pipeline, program); cogl_handle_unref (program); cogl_rectangle (50, 0, 100, 50); cogl_pipeline_set_user_program (pipeline, COGL_INVALID_HANDLE); cogl_object_unref (pipeline); }
void _cogl_pango_display_list_render (CoglPangoDisplayList *dl, const CoglColor *color) { GSList *l; for (l = dl->nodes; l; l = l->next) { CoglPangoDisplayListNode *node = l->data; CoglColor draw_color; if (node->pipeline == NULL) { if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE) node->pipeline = _cogl_pango_pipeline_cache_get (dl->pipeline_cache, node->d.texture.texture); else node->pipeline = _cogl_pango_pipeline_cache_get (dl->pipeline_cache, NULL); } if (node->color_override) /* Use the override color but preserve the alpha from the draw color */ cogl_color_init_from_4ub (&draw_color, cogl_color_get_red_byte (&node->color), cogl_color_get_green_byte (&node->color), cogl_color_get_blue_byte (&node->color), cogl_color_get_alpha_byte (color)); else draw_color = *color; cogl_color_premultiply (&draw_color); cogl_pipeline_set_color (node->pipeline, &draw_color); cogl_push_source (node->pipeline); switch (node->type) { case COGL_PANGO_DISPLAY_LIST_TEXTURE: _cogl_pango_display_list_render_texture (node); break; case COGL_PANGO_DISPLAY_LIST_RECTANGLE: cogl_rectangle (node->d.rectangle.x_1, node->d.rectangle.y_1, node->d.rectangle.x_2, node->d.rectangle.y_2); break; case COGL_PANGO_DISPLAY_LIST_TRAPEZOID: { float points[8]; CoglPath *path; points[0] = node->d.trapezoid.x_11; points[1] = node->d.trapezoid.y_1; points[2] = node->d.trapezoid.x_12; points[3] = node->d.trapezoid.y_2; points[4] = node->d.trapezoid.x_22; points[5] = node->d.trapezoid.y_2; points[6] = node->d.trapezoid.x_21; points[7] = node->d.trapezoid.y_1; path = cogl_path_new (); cogl_path_polygon (path, points, 4); cogl_path_fill (path); cogl_object_unref (path); } break; } cogl_pop_source (); } }
static void clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) { ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); ClutterDeformEffectPrivate *priv = self->priv; CoglHandle material; CoglPipeline *pipeline; CoglDepthState depth_state; CoglFramebuffer *fb = cogl_get_draw_framebuffer (); if (priv->is_dirty) { ClutterRect rect; gboolean mapped_buffer; CoglVertexP3T2C4 *verts; 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_rect (effect, &rect)) { width = clutter_rect_get_width (&rect); height = clutter_rect_get_height (&rect); } else clutter_actor_get_size (actor, &width, &height); /* XXX ideally, 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 */ verts = cogl_buffer_map (COGL_BUFFER (priv->buffer), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD); /* If the map failed then we'll resort to allocating a temporary buffer */ if (verts == NULL) { mapped_buffer = FALSE; verts = g_malloc (sizeof (*verts) * priv->n_vertices); } else mapped_buffer = TRUE; for (i = 0; i < priv->y_tiles + 1; i++) { for (j = 0; j < priv->x_tiles + 1; j++) { CoglVertexP3T2C4 *vertex_out; CoglTextureVertex vertex; /* CoglTextureVertex isn't an ideal structure to use for this because it contains a CoglColor. The internal layout of CoglColor is mean to be private so Clutter can not pass a pointer to it as a vertex attribute. Also it contains padding so we end up storing more data in the vertex buffer than we need to. Instead we let the application modify a dummy vertex and then copy the details back out to a more well-defined struct */ 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); vertex_out = verts + i * (priv->x_tiles + 1) + j; vertex_out->x = vertex.x; vertex_out->y = vertex.y; vertex_out->z = vertex.z; vertex_out->s = vertex.tx; vertex_out->t = vertex.ty; vertex_out->r = cogl_color_get_red_byte (&vertex.color); vertex_out->g = cogl_color_get_green_byte (&vertex.color); vertex_out->b = cogl_color_get_blue_byte (&vertex.color); vertex_out->a = cogl_color_get_alpha_byte (&vertex.color); } } if (mapped_buffer) cogl_buffer_unmap (COGL_BUFFER (priv->buffer)); else { cogl_buffer_set_data (COGL_BUFFER (priv->buffer), 0, /* offset */ verts, sizeof (*verts) * priv->n_vertices); g_free (verts); } priv->is_dirty = FALSE; } material = clutter_offscreen_effect_get_target (effect); pipeline = COGL_PIPELINE (material); /* enable depth testing */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); /* enable backface culling if we have a back material */ if (priv->back_pipeline != NULL) cogl_pipeline_set_cull_face_mode (pipeline, COGL_PIPELINE_CULL_FACE_MODE_BACK); /* draw the front */ if (material != NULL) cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive); /* draw the back */ if (priv->back_pipeline != NULL) { CoglPipeline *back_pipeline; /* We probably shouldn't be modifying the user's material so instead we make a temporary copy */ back_pipeline = cogl_pipeline_copy (priv->back_pipeline); cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL); cogl_pipeline_set_cull_face_mode (pipeline, COGL_PIPELINE_CULL_FACE_MODE_FRONT); cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive); cogl_object_unref (back_pipeline); } if (G_UNLIKELY (priv->lines_primitive != NULL)) { CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0); cogl_framebuffer_draw_primitive (fb, lines_pipeline, priv->lines_primitive); cogl_object_unref (lines_pipeline); } }
static void test_blend (TestState *state, int x, int y, uint32_t src_color, uint32_t dst_color, const char *blend_string, uint32_t blend_constant, uint32_t expected_result) { /* src color */ uint8_t Sr = MASK_RED (src_color); uint8_t Sg = MASK_GREEN (src_color); uint8_t Sb = MASK_BLUE (src_color); uint8_t Sa = MASK_ALPHA (src_color); /* dest color */ uint8_t Dr = MASK_RED (dst_color); uint8_t Dg = MASK_GREEN (dst_color); uint8_t Db = MASK_BLUE (dst_color); uint8_t Da = MASK_ALPHA (dst_color); /* blend constant - when applicable */ uint8_t Br = MASK_RED (blend_constant); uint8_t Bg = MASK_GREEN (blend_constant); uint8_t Bb = MASK_BLUE (blend_constant); uint8_t Ba = MASK_ALPHA (blend_constant); CoglColor blend_const_color; CoglPipeline *pipeline; CoglBool status; CoglError *error = NULL; int y_off; int x_off; /* First write out the destination color without any blending... */ pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, Dr, Dg, Db, Da); cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_object_unref (pipeline); /* * Now blend a rectangle over our well defined destination: */ pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, Sr, Sg, Sb, Sa); status = cogl_pipeline_set_blend (pipeline, blend_string, &error); if (!status) { /* It's not strictly a test failure; you need a more capable GPU or * driver to test this blend string. */ if (cogl_test_verbose ()) { g_debug ("Failed to test blend string %s: %s", blend_string, error->message); g_print ("Skipping\n"); } return; } cogl_color_init_from_4ub (&blend_const_color, Br, Bg, Bb, Ba); cogl_pipeline_set_blend_constant (pipeline, &blend_const_color); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_object_unref (pipeline); /* See what we got... */ y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2); x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2); if (cogl_test_verbose ()) { g_print ("test_blend (%d, %d):\n%s\n", x, y, blend_string); g_print (" src color = %02x, %02x, %02x, %02x\n", Sr, Sg, Sb, Sa); g_print (" dst color = %02x, %02x, %02x, %02x\n", Dr, Dg, Db, Da); if (blend_constant != BLEND_CONSTANT_UNUSED) g_print (" blend constant = %02x, %02x, %02x, %02x\n", Br, Bg, Bb, Ba); else g_print (" blend constant = UNUSED\n"); } test_utils_check_pixel (test_fb, x_off, y_off, expected_result); }
static void test_tex_combine (TestState *state, int x, int y, uint32_t tex0_color, uint32_t tex1_color, uint32_t combine_constant, const char *combine_string, uint32_t expected_result) { CoglTexture *tex0, *tex1; /* combine constant - when applicable */ uint8_t Cr = MASK_RED (combine_constant); uint8_t Cg = MASK_GREEN (combine_constant); uint8_t Cb = MASK_BLUE (combine_constant); uint8_t Ca = MASK_ALPHA (combine_constant); CoglColor combine_const_color; CoglPipeline *pipeline; CoglBool status; CoglError *error = NULL; int y_off; int x_off; tex0 = make_texture (tex0_color); tex1 = make_texture (tex1_color); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, 0x80, 0x80, 0x80, 0x80); cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); cogl_pipeline_set_layer_texture (pipeline, 0, tex0); cogl_pipeline_set_layer_combine (pipeline, 0, "RGBA = REPLACE (TEXTURE)", NULL); cogl_pipeline_set_layer_texture (pipeline, 1, tex1); status = cogl_pipeline_set_layer_combine (pipeline, 1, combine_string, &error); if (!status) { /* It's not strictly a test failure; you need a more capable GPU or * driver to test this texture combine string. */ g_debug ("Failed to test texture combine string %s: %s", combine_string, error->message); } cogl_color_init_from_4ub (&combine_const_color, Cr, Cg, Cb, Ca); cogl_pipeline_set_layer_combine_constant (pipeline, 1, &combine_const_color); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_object_unref (pipeline); cogl_object_unref (tex0); cogl_object_unref (tex1); /* See what we got... */ y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2); x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2); if (cogl_test_verbose ()) { g_print ("test_tex_combine (%d, %d):\n%s\n", x, y, combine_string); g_print (" texture 0 color = 0x%08lX\n", (unsigned long)tex0_color); g_print (" texture 1 color = 0x%08lX\n", (unsigned long)tex1_color); if (combine_constant != TEX_CONSTANT_UNUSED) g_print (" combine constant = %02x, %02x, %02x, %02x\n", Cr, Cg, Cb, Ca); else g_print (" combine constant = UNUSED\n"); } test_utils_check_pixel (test_fb, x_off, y_off, expected_result); }
static void on_paint (ClutterActor *actor, void *state) { float saved_viewport[4]; CoglMatrix saved_projection; CoglMatrix projection; CoglMatrix modelview; guchar *data; CoglHandle tex; CoglHandle offscreen; CoglColor black; float x0; float y0; float width; float height; /* for clearing the offscreen framebuffer to black... */ cogl_color_init_from_4ub (&black, 0x00, 0x00, 0x00, 0xff); cogl_get_viewport (saved_viewport); cogl_get_projection_matrix (&saved_projection); cogl_push_matrix (); cogl_matrix_init_identity (&projection); cogl_matrix_init_identity (&modelview); cogl_set_projection_matrix (&projection); cogl_set_modelview_matrix (&modelview); /* - Create a 100x200 viewport (i.e. smaller than the onscreen framebuffer) * and position it a (20, 10) inside the framebuffer. * - Fill the whole viewport with a purple rectangle * - Verify that the framebuffer is black with a 100x200 purple rectangle at * (20, 10) */ cogl_set_viewport (20, /* x */ 10, /* y */ 100, /* width */ 200); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); /* fill the viewport with purple.. */ cogl_set_source_color4ub (0xff, 0x00, 0xff, 0xff); cogl_rectangle (-1, 1, 1, -1); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0xff, 0x00, 0xff); /* - Create a viewport twice the size of the onscreen framebuffer with * a negative offset positioning it at (-20, -10) relative to the * buffer itself. * - Draw a 100x200 green rectangle at (40, 20) within the viewport (which * is (20, 10) within the framebuffer) * - Verify that the framebuffer is black with a 100x200 green rectangle at * (20, 10) */ cogl_set_viewport (-20, /* x */ -10, /* y */ FRAMEBUFFER_WIDTH * 2, /* width */ FRAMEBUFFER_HEIGHT * 2); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); /* draw a 100x200 green rectangle offset into the viewport such that its * top left corner should be found at (20, 10) in the offscreen buffer */ /* (offset 40 pixels right from the left of the viewport) */ x0 = -1.0f + (1.0f / FRAMEBUFFER_WIDTH) * 40.f; /* (offset 20 pixels down from the top of the viewport) */ y0 = 1.0f - (1.0f / FRAMEBUFFER_HEIGHT) * 20.0f; width = (1.0f / FRAMEBUFFER_WIDTH) * 100; height = (1.0f / FRAMEBUFFER_HEIGHT) * 200; cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff); cogl_rectangle (x0, y0, x0 + width, y0 - height); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0x00, 0xff, 0x00); /* - Create a 200x400 viewport and position it a (20, 10) inside the draw * buffer. * - Push a 100x200 window space clip rectangle at (20, 10) * - Fill the whole viewport with a blue rectangle * - Verify that the framebuffer is black with a 100x200 blue rectangle at * (20, 10) */ cogl_set_viewport (20, /* x */ 10, /* y */ 200, /* width */ 400); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); cogl_clip_push_window_rectangle (20, 10, 100, 200); /* fill the viewport with blue.. */ cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff); cogl_rectangle (-1, 1, 1, -1); cogl_clip_pop (); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0x00, 0x00, 0xff); /* - Create a 200x400 viewport and position it a (20, 10) inside the draw * buffer. * - Push a 100x200 model space clip rectangle at (20, 10) in the viewport * (i.e. (40, 20) inside the framebuffer) * - Fill the whole viewport with a green rectangle * - Verify that the framebuffer is black with a 100x200 green rectangle at * (40, 20) */ cogl_set_viewport (20, /* x */ 10, /* y */ 200, /* width */ 400); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); /* figure out where to position our clip rectangle in model space * coordinates... */ /* (offset 40 pixels right from the left of the viewport) */ x0 = -1.0f + (2.0f / 200) * 20.f; /* (offset 20 pixels down from the top of the viewport) */ y0 = 1.0f - (2.0f / 400) * 10.0f; width = (2.0f / 200) * 100; height = (2.0f / 400) * 200; /* add the clip rectangle... */ cogl_push_matrix (); cogl_translate (x0 + (width/2.0), y0 - (height/2.0), 0); /* XXX: Rotate just enough to stop Cogl from converting our model space * rectangle into a window space rectangle.. */ cogl_rotate (0.1, 0, 0, 1); cogl_clip_push_rectangle (-(width/2.0), -(height/2.0), width/2.0, height/2.0); cogl_pop_matrix (); /* fill the viewport with green.. */ cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff); cogl_rectangle (-1, 1, 1, -1); cogl_clip_pop (); assert_rectangle_color_and_black_border (40, 20, 100, 200, 0x00, 0xff, 0x00); /* Set the viewport to something specific so we can verify that it gets * restored after we are done testing with an offscreen framebuffer... */ cogl_set_viewport (20, 10, 100, 200); /* * Next test offscreen drawing... */ data = g_malloc (FRAMEBUFFER_WIDTH * 4 * FRAMEBUFFER_HEIGHT); tex = cogl_texture_new_from_data (FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888, /* data fmt */ COGL_PIXEL_FORMAT_ANY, /* internal fmt */ FRAMEBUFFER_WIDTH * 4, /* rowstride */ data); g_free (data); offscreen = cogl_offscreen_new_to_texture (tex); cogl_push_framebuffer (offscreen); /* - Create a 100x200 viewport (i.e. smaller than the offscreen framebuffer) * and position it a (20, 10) inside the framebuffer. * - Fill the whole viewport with a blue rectangle * - Verify that the framebuffer is black with a 100x200 blue rectangle at * (20, 10) */ cogl_set_viewport (20, /* x */ 10, /* y */ 100, /* width */ 200); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); /* fill the viewport with blue.. */ cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff); cogl_rectangle (-1, 1, 1, -1); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0x00, 0x00, 0xff); /* - Create a viewport twice the size of the offscreen framebuffer with * a negative offset positioning it at (-20, -10) relative to the * buffer itself. * - Draw a 100x200 red rectangle at (40, 20) within the viewport (which * is (20, 10) within the framebuffer) * - Verify that the framebuffer is black with a 100x200 red rectangle at * (20, 10) */ cogl_set_viewport (-20, /* x */ -10, /* y */ FRAMEBUFFER_WIDTH * 2, /* width */ FRAMEBUFFER_HEIGHT * 2); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); /* draw a 100x200 red rectangle offset into the viewport such that its * top left corner should be found at (20, 10) in the offscreen buffer */ /* (offset 40 pixels right from the left of the viewport) */ x0 = -1.0f + (1.0f / FRAMEBUFFER_WIDTH) * 40.f; /* (offset 20 pixels down from the top of the viewport) */ y0 = 1.0f - (1.0f / FRAMEBUFFER_HEIGHT) * 20.0f; width = (1.0f / FRAMEBUFFER_WIDTH) * 100; height = (1.0f / FRAMEBUFFER_HEIGHT) * 200; cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff); cogl_rectangle (x0, y0, x0 + width, y0 - height); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0xff, 0x00, 0x00); /* - Create a 200x400 viewport and position it a (20, 10) inside the draw * buffer. * - Push a 100x200 window space clip rectangle at (20, 10) * - Fill the whole viewport with a blue rectangle * - Verify that the framebuffer is black with a 100x200 blue rectangle at * (20, 10) */ cogl_set_viewport (20, /* x */ 10, /* y */ 200, /* width */ 400); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); cogl_clip_push_window_rectangle (20, 10, 100, 200); /* fill the viewport with blue.. */ cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff); cogl_rectangle (-1, 1, 1, -1); cogl_clip_pop (); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0x00, 0x00, 0xff); /* - Create a 200x400 viewport and position it a (20, 10) inside the draw * buffer. * - Push a 100x200 model space clip rectangle at (20, 10) in the viewport * (i.e. (40, 20) inside the framebuffer) * - Fill the whole viewport with a green rectangle * - Verify that the framebuffer is black with a 100x200 green rectangle at * (40, 20) */ cogl_set_viewport (20, /* x */ 10, /* y */ 200, /* width */ 400); /* height */ /* clear everything... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); /* figure out where to position our clip rectangle in model space * coordinates... */ /* (offset 40 pixels right from the left of the viewport) */ x0 = -1.0f + (2.0f / 200) * 20.f; /* (offset 20 pixels down from the top of the viewport) */ y0 = 1.0f - (2.0f / 400) * 10.0f; width = (2.0f / 200) * 100; height = (2.0f / 400) * 200; /* add the clip rectangle... */ cogl_push_matrix (); cogl_translate (x0 + (width/2.0), y0 - (height/2.0), 0); /* XXX: Rotate just enough to stop Cogl from converting our model space * rectangle into a window space rectangle.. */ cogl_rotate (0.1, 0, 0, 1); cogl_clip_push_rectangle (-(width/2.0), -(height/2.0), width/2, height/2); cogl_pop_matrix (); /* fill the viewport with green.. */ cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff); cogl_rectangle (-1, 1, 1, -1); cogl_clip_pop (); assert_rectangle_color_and_black_border (40, 20, 100, 200, 0x00, 0xff, 0x00); /* Set the viewport to something obscure to verify that it gets * replace when we switch back to the onscreen framebuffer... */ cogl_set_viewport (0, 0, 10, 10); cogl_pop_framebuffer (); cogl_handle_unref (offscreen); /* * Verify that the previous onscreen framebuffer's viewport was restored * by drawing a white rectangle across the whole viewport. This should * draw a 100x200 rectangle at (20,10) relative to the onscreen draw * buffer... */ cogl_clear (&black, COGL_BUFFER_BIT_COLOR); cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); cogl_rectangle (-1, 1, 1, -1); assert_rectangle_color_and_black_border (20, 10, 100, 200, 0xff, 0xff, 0xff); /* Uncomment to display the last contents of the offscreen framebuffer */ #if 1 cogl_matrix_init_identity (&projection); cogl_matrix_init_identity (&modelview); cogl_set_viewport (0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT); cogl_set_projection_matrix (&projection); cogl_set_modelview_matrix (&modelview); cogl_set_source_texture (tex); cogl_rectangle (-1, 1, 1, -1); #endif cogl_handle_unref (tex); /* Finally restore the stage's original state... */ cogl_pop_matrix (); cogl_set_projection_matrix (&saved_projection); cogl_set_viewport (saved_viewport[0], saved_viewport[1], saved_viewport[2], saved_viewport[3]); /* Comment this out if you want visual feedback of what this test * paints. */ clutter_main_quit (); }
void test_layer_remove (void) { CoglPipeline *pipeline0, *pipeline1; CoglColor color; int pos = 0; cogl_framebuffer_orthographic (test_fb, 0, 0, cogl_framebuffer_get_width (test_fb), cogl_framebuffer_get_height (test_fb), -1, 100); /** TEST 1 **/ /* Basic sanity check that the pipeline combines the two colors * together properly */ pipeline0 = create_two_layer_pipeline (); test_color (pipeline0, 0xffff00ff, pos++); cogl_object_unref (pipeline0); /** TEST 2 **/ /* Check that we can remove the second layer */ pipeline0 = create_two_layer_pipeline (); cogl_pipeline_remove_layer (pipeline0, 1); test_color (pipeline0, 0xff0000ff, pos++); cogl_object_unref (pipeline0); /** TEST 3 **/ /* Check that we can remove the first layer */ pipeline0 = create_two_layer_pipeline (); cogl_pipeline_remove_layer (pipeline0, 0); test_color (pipeline0, 0x00ff00ff, pos++); cogl_object_unref (pipeline0); /** TEST 4 **/ /* Check that we can make a copy and remove a layer from the * original pipeline */ pipeline0 = create_two_layer_pipeline (); pipeline1 = cogl_pipeline_copy (pipeline0); cogl_pipeline_remove_layer (pipeline0, 1); test_color (pipeline0, 0xff0000ff, pos++); test_color (pipeline1, 0xffff00ff, pos++); cogl_object_unref (pipeline0); cogl_object_unref (pipeline1); /** TEST 5 **/ /* Check that we can make a copy and remove the second layer from the * new pipeline */ pipeline0 = create_two_layer_pipeline (); pipeline1 = cogl_pipeline_copy (pipeline0); cogl_pipeline_remove_layer (pipeline1, 1); test_color (pipeline0, 0xffff00ff, pos++); test_color (pipeline1, 0xff0000ff, pos++); cogl_object_unref (pipeline0); cogl_object_unref (pipeline1); /** TEST 6 **/ /* Check that we can make a copy and remove the first layer from the * new pipeline */ pipeline0 = create_two_layer_pipeline (); pipeline1 = cogl_pipeline_copy (pipeline0); cogl_pipeline_remove_layer (pipeline1, 0); test_color (pipeline0, 0xffff00ff, pos++); test_color (pipeline1, 0x00ff00ff, pos++); cogl_object_unref (pipeline0); cogl_object_unref (pipeline1); /** TEST 7 **/ /* Check that we can modify a layer in a child pipeline */ pipeline0 = create_two_layer_pipeline (); pipeline1 = cogl_pipeline_copy (pipeline0); cogl_color_init_from_4ub (&color, 0, 0, 255, 255); cogl_pipeline_set_layer_combine_constant (pipeline1, 0, &color); test_color (pipeline0, 0xffff00ff, pos++); test_color (pipeline1, 0x00ffffff, pos++); cogl_object_unref (pipeline0); cogl_object_unref (pipeline1); /** TEST 8 **/ /* Check that we can modify a layer in a child pipeline but then remove it */ pipeline0 = create_two_layer_pipeline (); pipeline1 = cogl_pipeline_copy (pipeline0); cogl_color_init_from_4ub (&color, 0, 0, 255, 255); cogl_pipeline_set_layer_combine_constant (pipeline1, 0, &color); cogl_pipeline_remove_layer (pipeline1, 0); test_color (pipeline0, 0xffff00ff, pos++); test_color (pipeline1, 0x00ff00ff, pos++); cogl_object_unref (pipeline0); cogl_object_unref (pipeline1); if (cogl_test_verbose ()) g_print ("OK\n"); }
static void mx_fade_effect_update_vbo (MxFadeEffect *self) { guint n_quads; gint bu, br, bb, bl; gfloat x1, y1, x2, y2; CoglColor opaque, color; CoglTextureVertex verts[9*4]; MxFadeEffectPrivate *priv = self->priv; cogl_color_init_from_4ub (&opaque, 0xff, 0xff, 0xff, 0xff); cogl_color_init_from_4ub (&color, priv->color.red, priv->color.green, priv->color.blue, priv->color.alpha); /* Validate the bounds */ x1 = priv->x; y1 = priv->y; x2 = x1 + (priv->bounds_width ? priv->bounds_width : priv->width); y2 = y1 + (priv->bounds_height ? priv->bounds_height : priv->height); if (x1 < 0) x1 = 0; if (x2 > priv->width) x2 = priv->width; if (y1 < 0) y1 = 0; if (y2 > priv->height) y2 = priv->height; /* Validate the border sizes */ /* Note, * bu = Border-up * br = Border-right * bb = Border-bottom * bl = Border-left */ bu = priv->border[0]; br = priv->border[1]; bb = priv->border[2]; bl = priv->border[3]; if (y1 + bu >= y2) bu = y2 - y1 - 1; if (x1 + bl >= x2) bl = x2 - x1 - 1; if (x2 - br <= x1 + bl) br = x2 - (x1 + bl) - 1; if (y2 - bb <= y1 + bu) bb = y2 - (y1 + bu) - 1; n_quads = 0; /* Generate the top-left square */ if (bl && bu) { mx_fade_effect_draw_rect (&verts[n_quads*4], x1, y1, x1 + bl, y1 + bu, priv->width, priv->height, &color, &color, &opaque, &color, FALSE); n_quads ++; } /* Generate the top-middle square */ if (bu) { mx_fade_effect_draw_rect (&verts[n_quads*4], x1 + bl, y1, x2 - br, y1 + bu, priv->width, priv->height, &color, &color, &opaque, &opaque, FALSE); n_quads ++; } /* Generate the top-right square */ if (br && bu) { mx_fade_effect_draw_rect (&verts[n_quads*4], x2 - br, y1, x2, y1 + bu, priv->width, priv->height, &color, &color, &color, &opaque, TRUE); n_quads ++; } /* Generate the left square */ if (bl) { mx_fade_effect_draw_rect (&verts[n_quads*4], x1, y1 + bu, x1 + bl, y2 - bb, priv->width, priv->height, &color, &opaque, &opaque, &color, TRUE); n_quads ++; } /* Generate the middle square */ mx_fade_effect_draw_rect (&verts[n_quads*4], x1 + bl, y1 + bu, x2 - br, y2 - bb, priv->width, priv->height, &opaque, &opaque, &opaque, &opaque, TRUE); n_quads ++; /* Generate the right square */ if (br) { mx_fade_effect_draw_rect (&verts[n_quads*4], x2 - br, y1 + bu, x2, y2 - bb, priv->width, priv->height, &opaque, &color, &color, &opaque, TRUE); n_quads ++; } /* Generate the bottom-left square */ if (bb && bl) { mx_fade_effect_draw_rect (&verts[n_quads*4], x1, y2 - bb, x1 + bl, y2, priv->width, priv->height, &color, &opaque, &color, &color, TRUE); n_quads ++; } /* Generate the bottom-middle square */ if (bb) { mx_fade_effect_draw_rect (&verts[n_quads*4], x1 + bl, y2 - bb, x2 - br, y2, priv->width, priv->height, &opaque, &opaque, &color, &color, FALSE); n_quads ++; } /* Generate the bottom-right square */ if (bb && br) { mx_fade_effect_draw_rect (&verts[n_quads*4], x2 - br, y2 - bb, x2, y2, priv->width, priv->height, &opaque, &color, &color, &color, FALSE); n_quads ++; } /* Unref the old vbo if it's a different size - otherwise we reuse it */ if (priv->vbo && (n_quads != priv->n_quads)) { cogl_handle_unref (priv->vbo); priv->vbo = NULL; } priv->n_quads = n_quads; if (!priv->vbo) { priv->vbo = cogl_vertex_buffer_new (n_quads * 4); if (!priv->vbo) return; priv->indices = cogl_vertex_buffer_indices_get_for_quads (n_quads * 6); if (!priv->indices) return; } cogl_vertex_buffer_add (priv->vbo, "gl_Vertex", 2, COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, sizeof (CoglTextureVertex), &(verts[0].x)); cogl_vertex_buffer_add (priv->vbo, "gl_MultiTexCoord0", 2, COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, sizeof (CoglTextureVertex), &(verts[0].tx)); cogl_vertex_buffer_add (priv->vbo, "gl_Color", 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, FALSE, sizeof (CoglTextureVertex), &(verts[0].color)); cogl_vertex_buffer_submit (priv->vbo); priv->update_vbo = FALSE; }