static void st_background_effect_paint_target (ClutterOffscreenEffect *effect) { StBackgroundEffect *self = ST_BACKGROUND_EFFECT (effect); if ((self->bg_texture != NULL) && (self->opacity == 0xff)) { cogl_push_source (self->pipeline2); cogl_rectangle (0.0f, 0.0f, (self->fg_width_i), (self->fg_height_i)); cogl_pop_source (); CoglOffscreen *vertical_FBO; vertical_FBO = cogl_offscreen_new_to_texture (self->bg_sub_texture); cogl_push_framebuffer ((CoglFramebuffer*)vertical_FBO); cogl_push_source (self->pipeline0); cogl_rectangle (-1.0f, 1.0f, 1.0f, -1.0f); cogl_pop_source (); cogl_pop_framebuffer (); cogl_handle_unref (vertical_FBO); cogl_pipeline_set_layer_texture (self->pipeline1, 0, self->bg_sub_texture); cogl_push_source (self->pipeline1); cogl_rectangle (4.0f, 4.0f, (self->bg_width_i) + 4.0f, (self->bg_height_i) + 4.0f); cogl_pop_source (); } cogl_pipeline_set_color4ub (self->pipeline3, 0x00, 0x00, 0x00, 0x80); cogl_push_source (self->pipeline3); cogl_rectangle (0.0f, 0.0f, (self->fg_width_i), (self->fg_height_i)); cogl_pop_source (); clutter_actor_queue_redraw (self->actor); cogl_pipeline_set_color4ub (self->pipeline4, self->opacity, self->opacity, self->opacity, self->opacity); cogl_push_source (self->pipeline4); cogl_rectangle (0.0f, 0.0f, (self->fg_width_i), (self->fg_height_i)); cogl_pop_source (); clutter_actor_queue_redraw (self->actor); }
static void paint_pipeline (CoglPipeline *pipeline, int pos) { cogl_push_source (pipeline); cogl_rectangle (pos * 10, 0, pos * 10 + 10, 10); cogl_pop_source (); }
static void shell_grid_desaturate_effect_paint_target (ClutterOffscreenEffect *effect) { ShellGridDesaturateEffect *self = SHELL_GRID_DESATURATE_EFFECT (effect); ClutterActor *actor; CoglHandle texture; guint8 paint_opacity; texture = clutter_offscreen_effect_get_texture (effect); cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); paint_opacity = clutter_actor_get_paint_opacity (actor); cogl_pipeline_set_color4ub (self->pipeline, paint_opacity, paint_opacity, paint_opacity, paint_opacity); cogl_push_source (self->pipeline); cogl_rectangle (0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture)); cogl_pop_source (); }
static void _cogl_path_stroke_nodes (CoglPath *path) { CoglPathData *data = path->data; CoglPipeline *copy = NULL; CoglPipeline *source; unsigned int path_start; int path_num = 0; CoglPathNode *node; _COGL_GET_CONTEXT (ctx, NO_RETVAL); source = cogl_get_source (); if (cogl_pipeline_get_n_layers (source) != 0) { copy = cogl_pipeline_copy (source); _cogl_pipeline_prune_to_n_layers (copy, 0); source = copy; } _cogl_path_build_stroke_attribute_buffer (path); cogl_push_source (source); for (path_start = 0; path_start < data->path_nodes->len; path_start += node->path_size) { node = &g_array_index (data->path_nodes, CoglPathNode, path_start); cogl_framebuffer_vdraw_attributes (cogl_get_draw_framebuffer (), source, COGL_VERTICES_MODE_LINE_STRIP, 0, node->path_size, data->stroke_attributes[path_num], NULL); path_num++; } cogl_pop_source (); if (copy) cogl_object_unref (copy); }
static void _cogl_blit_texture_render_end (CoglBlitData *data) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); cogl_pop_source (); cogl_pop_framebuffer (); /* Attach the target texture to the texture render pipeline so that we don't keep a reference to the source texture forever. This is assuming that the destination texture will live for a long time which is currently the case when cogl_blit_* is used from the atlas code. It may be better in future to keep around a set of dummy 1x1 textures for each texture target that we could bind instead. This would also be useful when using a pipeline as a hash table key such as for the ARBfp program cache. */ cogl_pipeline_set_layer_texture (ctx->blit_texture_pipeline, 0, data->dst_tex); }
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); }
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 (); } }
/* Reads back the contents of a texture by rendering it to the framebuffer * and reading back the resulting pixels. * * NB: Normally this approach isn't normally used since we can just use * glGetTexImage, but may be used as a fallback in some circumstances. */ gboolean _cogl_texture_draw_and_read (CoglHandle handle, CoglBitmap *target_bmp, GLuint target_gl_format, GLuint target_gl_type) { int bpp; CoglFramebuffer *framebuffer; int viewport[4]; CoglBitmap *alpha_bmp; CoglMatrixStack *projection_stack; CoglMatrixStack *modelview_stack; int target_width = _cogl_bitmap_get_width (target_bmp); int target_height = _cogl_bitmap_get_height (target_bmp); int target_rowstride = _cogl_bitmap_get_rowstride (target_bmp); _COGL_GET_CONTEXT (ctx, FALSE); bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888); framebuffer = _cogl_get_draw_buffer (); /* Viewport needs to have some size and be inside the window for this */ _cogl_framebuffer_get_viewport4fv (framebuffer, viewport); if (viewport[0] < 0 || viewport[1] < 0 || viewport[2] <= 0 || viewport[3] <= 0) return FALSE; /* Setup orthographic projection into current viewport (0,0 in top-left * corner to draw the texture upside-down so we match the way cogl_read_pixels * works) */ projection_stack = _cogl_framebuffer_get_projection_stack (framebuffer); _cogl_matrix_stack_push (projection_stack); _cogl_matrix_stack_load_identity (projection_stack); _cogl_matrix_stack_ortho (projection_stack, 0, (float)(viewport[2]), (float)(viewport[3]), 0, (float)(0), (float)(100)); modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer); _cogl_matrix_stack_push (modelview_stack); _cogl_matrix_stack_load_identity (modelview_stack); /* Direct copy operation */ if (ctx->texture_download_pipeline == COGL_INVALID_HANDLE) { ctx->texture_download_pipeline = cogl_pipeline_new (); cogl_pipeline_set_blend (ctx->texture_download_pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); } cogl_push_source (ctx->texture_download_pipeline); cogl_pipeline_set_layer_texture (ctx->texture_download_pipeline, 0, handle); cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline, 0, /* layer */ "RGBA = REPLACE (TEXTURE)", NULL); cogl_pipeline_set_layer_filters (ctx->texture_download_pipeline, 0, COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); do_texture_draw_and_read (handle, target_bmp, viewport); /* Check whether texture has alpha and framebuffer not */ /* FIXME: For some reason even if ALPHA_BITS is 8, the framebuffer still doesn't seem to have an alpha buffer. This might be just a PowerVR issue. GLint r_bits, g_bits, b_bits, a_bits; GE( glGetIntegerv (GL_ALPHA_BITS, &a_bits) ); GE( glGetIntegerv (GL_RED_BITS, &r_bits) ); GE( glGetIntegerv (GL_GREEN_BITS, &g_bits) ); GE( glGetIntegerv (GL_BLUE_BITS, &b_bits) ); printf ("R bits: %d\n", r_bits); printf ("G bits: %d\n", g_bits); printf ("B bits: %d\n", b_bits); printf ("A bits: %d\n", a_bits); */ if ((cogl_texture_get_format (handle) & COGL_A_BIT)/* && a_bits == 0*/) { guint8 *srcdata; guint8 *dstdata; guint8 *srcpixel; guint8 *dstpixel; int x,y; int alpha_rowstride = bpp * target_width; if ((dstdata = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD)) == NULL) return FALSE; srcdata = g_malloc (alpha_rowstride * target_height); /* Create temp bitmap for alpha values */ alpha_bmp = _cogl_bitmap_new_from_data (srcdata, COGL_PIXEL_FORMAT_RGBA_8888, target_width, target_height, alpha_rowstride, (CoglBitmapDestroyNotify) g_free, NULL); /* Draw alpha values into RGB channels */ cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline, 0, /* layer */ "RGBA = REPLACE (TEXTURE[A])", NULL); do_texture_draw_and_read (handle, alpha_bmp, viewport); /* Copy temp R to target A */ for (y=0; y<target_height; ++y) { for (x=0; x<target_width; ++x) { srcpixel = srcdata + x*bpp; dstpixel = dstdata + x*bpp; dstpixel[3] = srcpixel[0]; } srcdata += alpha_rowstride; dstdata += target_rowstride; } _cogl_bitmap_unmap (target_bmp); cogl_object_unref (alpha_bmp); } /* Restore old state */ _cogl_matrix_stack_pop (modelview_stack); _cogl_matrix_stack_pop (projection_stack); /* restore the original pipeline */ cogl_pop_source (); return TRUE; }
void cogl_polygon (const CoglTextureVertex *vertices, unsigned int n_vertices, CoglBool use_color) { CoglPipeline *pipeline; ValidateState validate_state; int n_layers; int n_attributes; CoglAttribute **attributes; int i; unsigned int stride; size_t stride_bytes; CoglAttributeBuffer *attribute_buffer; float *v; _COGL_GET_CONTEXT (ctx, NO_RETVAL); pipeline = cogl_get_source (); validate_state.original_pipeline = pipeline; validate_state.pipeline = pipeline; cogl_pipeline_foreach_layer (pipeline, _cogl_polygon_validate_layer_cb, &validate_state); pipeline = validate_state.pipeline; n_layers = cogl_pipeline_get_n_layers (pipeline); n_attributes = 1 + n_layers + (use_color ? 1 : 0); attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes); /* Our data is arranged like: * [X, Y, Z, TX0, TY0, TX1, TY1..., R, G, B, A,...] */ stride = 3 + (2 * n_layers) + (use_color ? 1 : 0); stride_bytes = stride * sizeof (float); /* Make sure there is enough space in the global vertex array. This * is used so we can render the polygon with a single call to OpenGL * but still support any number of vertices */ g_array_set_size (ctx->polygon_vertices, n_vertices * stride); attribute_buffer = cogl_attribute_buffer_new (ctx, n_vertices * stride_bytes, NULL); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", stride_bytes, 0, 3, COGL_ATTRIBUTE_TYPE_FLOAT); for (i = 0; i < n_layers; i++) { static const char *names[] = { "cogl_tex_coord0_in", "cogl_tex_coord1_in", "cogl_tex_coord2_in", "cogl_tex_coord3_in", "cogl_tex_coord4_in", "cogl_tex_coord5_in", "cogl_tex_coord6_in", "cogl_tex_coord7_in" }; char *allocated_name = NULL; const char *name; if (i < 8) name = names[i]; else name = allocated_name = g_strdup_printf ("cogl_tex_coord%d_in", i); attributes[i + 1] = cogl_attribute_new (attribute_buffer, name, stride_bytes, /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ 12 + 8 * i, 2, COGL_ATTRIBUTE_TYPE_FLOAT); g_free (allocated_name); } if (use_color) { attributes[n_attributes - 1] = cogl_attribute_new (attribute_buffer, "cogl_color_in", stride_bytes, /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ 12 + 8 * n_layers, 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); } /* Convert the vertices into an array of float vertex attributes */ v = (float *)ctx->polygon_vertices->data; for (i = 0; i < n_vertices; i++) { AppendTexCoordsState append_tex_coords_state; uint8_t *c; /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ v[0] = vertices[i].x; v[1] = vertices[i].y; v[2] = vertices[i].z; append_tex_coords_state.vertices_in = vertices; append_tex_coords_state.vertex = i; append_tex_coords_state.layer = 0; append_tex_coords_state.vertices_out = v; cogl_pipeline_foreach_layer (pipeline, append_tex_coord_attributes_cb, &append_tex_coords_state); if (use_color) { /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ c = (uint8_t *) (v + 3 + 2 * n_layers); c[0] = cogl_color_get_red_byte (&vertices[i].color); c[1] = cogl_color_get_green_byte (&vertices[i].color); c[2] = cogl_color_get_blue_byte (&vertices[i].color); c[3] = cogl_color_get_alpha_byte (&vertices[i].color); } v += stride; } v = (float *)ctx->polygon_vertices->data; cogl_buffer_set_data (COGL_BUFFER (attribute_buffer), 0, v, ctx->polygon_vertices->len * sizeof (float)); /* XXX: although this may seem redundant, we need to do this since * cogl_polygon() can be used with legacy state and its the source stack * which track whether legacy state is enabled. * * (We only have a CoglDrawFlag to disable legacy state not one * to enable it) */ cogl_push_source (pipeline); _cogl_framebuffer_draw_attributes (cogl_get_draw_framebuffer (), pipeline, COGL_VERTICES_MODE_TRIANGLE_FAN, 0, n_vertices, attributes, n_attributes, 0 /* no draw flags */); cogl_pop_source (); if (pipeline != validate_state.original_pipeline) cogl_object_unref (pipeline); cogl_object_unref (attribute_buffer); for (i = 0; i < n_attributes; i++) cogl_object_unref (attributes[i]); }