CoglPrimitive * cogl_primitive_new_p3t2 (CoglContext *ctx, CoglVerticesMode mode, int n_vertices, const CoglVertexP3T2 *data) { CoglAttributeBuffer *attribute_buffer = cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3T2), data); CoglAttribute *attributes[2]; attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (CoglVertexP3T2), offsetof (CoglVertexP3T2, x), 3, COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP3T2), offsetof (CoglVertexP3T2, s), 2, COGL_ATTRIBUTE_TYPE_FLOAT); cogl_object_unref (attribute_buffer); return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, attributes, 2); }
static void create_primitive (Data *data) { CoglAttribute *attributes[2]; int i; data->attribute_buffer = cogl_attribute_buffer_new_with_size (data->context, sizeof (data->sparks)); cogl_buffer_set_update_hint (data->attribute_buffer, COGL_BUFFER_UPDATE_HINT_DYNAMIC); attributes[0] = cogl_attribute_new (data->attribute_buffer, "cogl_position_in", sizeof (Spark), G_STRUCT_OFFSET (Spark, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (data->attribute_buffer, "cogl_color_in", sizeof (Spark), G_STRUCT_OFFSET (Spark, color), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); data->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_POINTS, N_SPARKS, attributes, G_N_ELEMENTS (attributes)); for (i = 0; i < G_N_ELEMENTS (attributes); i++) cogl_object_unref (attributes[i]); }
CoglPrimitive * cogl_primitive_new_p3c4 (CoglContext *ctx, CoglVerticesMode mode, int n_vertices, const CoglVertexP3C4 *data) { CoglAttributeBuffer *attribute_buffer = cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3C4), data); CoglAttribute *attributes[2]; attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (CoglVertexP3C4), offsetof (CoglVertexP3C4, x), 3, COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (attribute_buffer, "cogl_color_in", sizeof (CoglVertexP3C4), offsetof (CoglVertexP3C4, r), 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); cogl_object_unref (attribute_buffer); return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, attributes, 2); }
static void test_float_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer; static const FloatVert float_verts[] = { { 0, 10, /**/ 1, 0, 0, 1 }, { 10, 10, /**/ 1, 0, 0, 1 }, { 5, 0, /**/ 1, 0, 0, 1 }, { 10, 10, /**/ 0, 1, 0, 1 }, { 20, 10, /**/ 0, 1, 0, 1 }, { 15, 0, /**/ 0, 1, 0, 1 } }; buffer = cogl_attribute_buffer_new (test_ctx, sizeof (float_verts), float_verts); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (FloatVert), G_STRUCT_OFFSET (FloatVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); attributes[1] = cogl_attribute_new (buffer, "color", sizeof (FloatVert), G_STRUCT_OFFSET (FloatVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x, offset_y, 0.0f); cogl_framebuffer_draw_attributes (test_fb, state->pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 6, /* n_vertices */ attributes, 2 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[1]); cogl_object_unref (attributes[0]); cogl_object_unref (buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); }
void _cogl_rectangle_immediate (CoglFramebuffer *framebuffer, CoglPipeline *pipeline, float x_1, float y_1, float x_2, float y_2) { /* Draw a rectangle using the vertex array API to avoid going through the journal. This should only be used in cases where the code might be called while the journal is already being flushed such as when flushing the clip state */ CoglContext *ctx = framebuffer->context; float vertices[8] = { x_1, y_1, x_1, y_2, x_2, y_1, x_2, y_2 }; CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[1]; attribute_buffer = cogl_attribute_buffer_new (ctx, sizeof (vertices), vertices); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (float) * 2, /* stride */ 0, /* offset */ 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); _cogl_framebuffer_draw_attributes (framebuffer, pipeline, COGL_VERTICES_MODE_TRIANGLE_STRIP, 0, /* first_index */ 4, /* n_vertices */ attributes, 1, COGL_DRAW_SKIP_JOURNAL_FLUSH | COGL_DRAW_SKIP_PIPELINE_VALIDATION | COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH | COGL_DRAW_SKIP_LEGACY_STATE); cogl_object_unref (attributes[0]); cogl_object_unref (attribute_buffer); }
static void _cogl_path_build_fill_attribute_buffer (CoglPath *path) { CoglPathTesselator tess; unsigned int path_start = 0; CoglPathData *data = path->data; int i; /* If we've already got a vbo then we don't need to do anything */ if (data->fill_attribute_buffer) return; tess.primitive_type = FALSE; /* Generate a vertex for each point on the path */ tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex)); g_array_set_size (tess.vertices, data->path_nodes->len); for (i = 0; i < data->path_nodes->len; i++) { CoglPathNode *node = &g_array_index (data->path_nodes, CoglPathNode, i); CoglPathTesselatorVertex *vertex = &g_array_index (tess.vertices, CoglPathTesselatorVertex, i); vertex->x = node->x; vertex->y = node->y; /* Add texture coordinates so that a texture would be drawn to fit the bounding box of the path and then cropped by the path */ if (data->path_nodes_min.x == data->path_nodes_max.x) vertex->s = 0.0f; else vertex->s = ((node->x - data->path_nodes_min.x) / (data->path_nodes_max.x - data->path_nodes_min.x)); if (data->path_nodes_min.y == data->path_nodes_max.y) vertex->t = 0.0f; else vertex->t = ((node->y - data->path_nodes_min.y) / (data->path_nodes_max.y - data->path_nodes_min.y)); } tess.indices_type = _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len); _cogl_path_tesselator_allocate_indices_array (&tess); tess.glu_tess = gluNewTess (); if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD) gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); else gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); /* All vertices are on the xy-plane */ gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0); gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA, _cogl_path_tesselator_begin); gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA, _cogl_path_tesselator_vertex); gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA, _cogl_path_tesselator_end); gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA, _cogl_path_tesselator_combine); gluTessBeginPolygon (tess.glu_tess, &tess); while (path_start < data->path_nodes->len) { CoglPathNode *node = &g_array_index (data->path_nodes, CoglPathNode, path_start); gluTessBeginContour (tess.glu_tess); for (i = 0; i < node->path_size; i++) { double vertex[3] = { node[i].x, node[i].y, 0.0 }; gluTessVertex (tess.glu_tess, vertex, GINT_TO_POINTER (i + path_start)); } gluTessEndContour (tess.glu_tess); path_start += node->path_size; } gluTessEndPolygon (tess.glu_tess); gluDeleteTess (tess.glu_tess); data->fill_attribute_buffer = cogl_attribute_buffer_new (data->context, sizeof (CoglPathTesselatorVertex) * tess.vertices->len, tess.vertices->data); g_array_free (tess.vertices, TRUE); data->fill_attributes[0] = cogl_attribute_new (data->fill_attribute_buffer, "cogl_position_in", sizeof (CoglPathTesselatorVertex), G_STRUCT_OFFSET (CoglPathTesselatorVertex, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); data->fill_attributes[1] = cogl_attribute_new (data->fill_attribute_buffer, "cogl_tex_coord0_in", sizeof (CoglPathTesselatorVertex), G_STRUCT_OFFSET (CoglPathTesselatorVertex, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); data->fill_vbo_indices = cogl_indices_new (data->context, tess.indices_type, tess.indices->data, tess.indices->len); data->fill_vbo_n_indices = tess.indices->len; g_array_free (tess.indices, TRUE); }
static void emit_vertex_buffer_geometry (CoglFramebuffer *fb, CoglPipeline *pipeline, CoglPangoDisplayListNode *node) { CoglContext *ctx = fb->context; /* It's expensive to go through the Cogl journal for large runs * of text in part because the journal transforms the quads in software * to avoid changing the modelview matrix. So for larger runs of text * we load the vertices into a VBO, and this has the added advantage * that if the text doesn't change from frame to frame the VBO can * be re-used avoiding the repeated cost of validating the data and * mapping it into the GPU... */ if (node->d.texture.primitive == NULL) { CoglAttributeBuffer *buffer; CoglVertexP2T2 *verts, *v; int n_verts; CoglBool allocated = FALSE; CoglAttribute *attributes[2]; CoglPrimitive *prim; int i; CoglError *ignore_error = NULL; n_verts = node->d.texture.rectangles->len * 4; buffer = cogl_attribute_buffer_new_with_size (ctx, n_verts * sizeof (CoglVertexP2T2)); if ((verts = cogl_buffer_map (COGL_BUFFER (buffer), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD, &ignore_error)) == NULL) { cogl_error_free (ignore_error); verts = g_new (CoglVertexP2T2, n_verts); allocated = TRUE; } v = verts; /* Copy the rectangles into the buffer and expand into four vertices instead of just two */ for (i = 0; i < node->d.texture.rectangles->len; i++) { const CoglPangoDisplayListRectangle *rectangle = &g_array_index (node->d.texture.rectangles, CoglPangoDisplayListRectangle, i); v->x = rectangle->x_1; v->y = rectangle->y_1; v->s = rectangle->s_1; v->t = rectangle->t_1; v++; v->x = rectangle->x_1; v->y = rectangle->y_2; v->s = rectangle->s_1; v->t = rectangle->t_2; v++; v->x = rectangle->x_2; v->y = rectangle->y_2; v->s = rectangle->s_2; v->t = rectangle->t_2; v++; v->x = rectangle->x_2; v->y = rectangle->y_1; v->s = rectangle->s_2; v->t = rectangle->t_1; v++; } if (allocated) { cogl_buffer_set_data (COGL_BUFFER (buffer), 0, /* offset */ verts, sizeof (CoglVertexP2T2) * n_verts, NULL); g_free (verts); } else cogl_buffer_unmap (COGL_BUFFER (buffer)); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (CoglVertexP2T2), G_STRUCT_OFFSET (CoglVertexP2T2, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP2T2), G_STRUCT_OFFSET (CoglVertexP2T2, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, n_verts, attributes, 2 /* n_attributes */); #ifdef CLUTTER_COGL_HAS_GL if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS)) cogl_primitive_set_mode (prim, GL_QUADS); else #endif { /* GLES doesn't support GL_QUADS so instead we use a VBO with indexed vertices to generate GL_TRIANGLES from the quads */ CoglIndices *indices = cogl_get_rectangle_indices (ctx, node->d.texture.rectangles->len); cogl_primitive_set_indices (prim, indices, node->d.texture.rectangles->len * 6); } node->d.texture.primitive = prim; cogl_object_unref (buffer); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); } cogl_primitive_draw (node->d.texture.primitive, fb, pipeline); }
static CoglPrimitive * primitive_new_p2t2t2 (CoglContext *ctx, CoglVerticesMode mode, int n_vertices, const VertexP2T2T2 *data) { CoglAttributeBuffer *attribute_buffer = cogl_attribute_buffer_new (ctx, n_vertices * sizeof (VertexP2T2T2), data); int n_attributes = 7; CoglAttribute *attributes[n_attributes]; CoglPrimitive *primitive; #ifndef MESA_CONST_ATTRIB_BUG_WORKAROUND const float normal[3] = { 0, 0, 1 }; const float tangent[3] = { 1, 0, 0 }; #endif int i; attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, x), 2, COGL_ATTRIBUTE_TYPE_FLOAT); /* coords for shape mask, for rounded corners */ attributes[1] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord0_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, s0), 2, COGL_ATTRIBUTE_TYPE_FLOAT); /* coords for primary texture */ attributes[2] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord1_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, s1), 2, COGL_ATTRIBUTE_TYPE_FLOAT); /* coords for alpha mask texture */ attributes[3] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord4_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, s1), 2, COGL_ATTRIBUTE_TYPE_FLOAT); /* coords for normal map */ attributes[4] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord7_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, s1), 2, COGL_ATTRIBUTE_TYPE_FLOAT); #ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND attributes[5] = cogl_attribute_new (attribute_buffer, "cogl_normal_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, Nx), 3, COGL_ATTRIBUTE_TYPE_FLOAT); attributes[6] = cogl_attribute_new (attribute_buffer, "tangent_in", sizeof (VertexP2T2T2), offsetof (VertexP2T2T2, Tx), 3, COGL_ATTRIBUTE_TYPE_FLOAT); #else attributes[5] = cogl_attribute_new_const_3fv (ctx, "cogl_normal_in", normal); attributes[6] = cogl_attribute_new_const_3fv (ctx, "tangent_in", tangent); #endif cogl_object_unref (attribute_buffer); primitive = cogl_primitive_new_with_attributes (mode, n_vertices, attributes, n_attributes); for (i = 0; i < n_attributes; i++) cogl_object_unref (attributes[i]); return primitive; }
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); }
CoglPrimitive * rut_camera_create_frustum_primitive (RutCamera *camera) { RutVertex4 vertices[8] = { /* near plane in projection space */ {-1, -1, -1, 1, }, { 1, -1, -1, 1, }, { 1, 1, -1, 1, }, {-1, 1, -1, 1, }, /* far plane in projection space */ {-1, -1, 1, 1, }, { 1, -1, 1, 1, }, { 1, 1, 1, 1, }, {-1, 1, 1, 1, } }; const CoglMatrix *projection_inv; CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[1]; CoglPrimitive *primitive; CoglIndices *indices; unsigned char indices_data[24] = { 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7 }; int i; projection_inv = rut_camera_get_inverse_projection (camera); for (i = 0; i < 8; i++) { cogl_matrix_transform_point (projection_inv, &vertices[i].x, &vertices[i].y, &vertices[i].z, &vertices[i].w); vertices[i].x /= vertices[i].w; vertices[i].y /= vertices[i].w; vertices[i].z /= vertices[i].w; vertices[i].w /= 1.0f; } attribute_buffer = cogl_attribute_buffer_new (rut_cogl_context, 8 * sizeof (RutVertex4), vertices); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (RutVertex4), offsetof (RutVertex4, x), 3, COGL_ATTRIBUTE_TYPE_FLOAT); indices = cogl_indices_new (rut_cogl_context, COGL_INDICES_TYPE_UNSIGNED_BYTE, indices_data, G_N_ELEMENTS (indices_data)); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINES, 8, attributes, 1); cogl_primitive_set_indices (primitive, indices, G_N_ELEMENTS(indices_data)); cogl_object_unref (attribute_buffer); cogl_object_unref (attributes[0]); cogl_object_unref (indices); return primitive; }
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]); }
void test_map_buffer_range (void) { CoglTexture2D *tex; CoglPipeline *pipeline; int fb_width, fb_height; CoglAttributeBuffer *buffer; CoglVertexP2T2 *data; CoglAttribute *pos_attribute; CoglAttribute *tex_coord_attribute; CoglPrimitive *primitive; tex = cogl_texture_2d_new_from_data (test_ctx, 2, 2, /* width/height */ COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_PIXEL_FORMAT_ANY, 2 * 4, /* rowstride */ tex_data, NULL /* error */); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_layer_texture (pipeline, 0, COGL_TEXTURE (tex)); cogl_pipeline_set_layer_filters (pipeline, 0, /* layer */ COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, /* layer */ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); fb_width = cogl_framebuffer_get_width (test_fb); fb_height = cogl_framebuffer_get_height (test_fb); buffer = cogl_attribute_buffer_new (test_ctx, sizeof (vertex_data), vertex_data); /* Replace the texture coordinates of the third vertex with the * coordinates for a green texel */ data = cogl_buffer_map_range (COGL_BUFFER (buffer), sizeof (vertex_data[0]) * 2, sizeof (vertex_data[0]), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD_RANGE, NULL); /* don't catch errors */ g_assert (data != NULL); data->x = vertex_data[2].x; data->y = vertex_data[2].y; data->s = 1.0f; data->t = 0.0f; cogl_buffer_unmap (COGL_BUFFER (buffer)); pos_attribute = cogl_attribute_new (buffer, "cogl_position_in", sizeof (vertex_data[0]), offsetof (CoglVertexP2T2, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); tex_coord_attribute = cogl_attribute_new (buffer, "cogl_tex_coord_in", sizeof (vertex_data[0]), offsetof (CoglVertexP2T2, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); primitive = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLE_STRIP, 4, /* n_vertices */ pos_attribute, tex_coord_attribute, NULL); cogl_primitive_draw (primitive, test_fb, pipeline); cogl_object_unref (primitive); /* Top left pixel should be the one that is replaced to be green */ test_utils_check_pixel (test_fb, 1, 1, 0x00ff00ff); /* The other three corners should be left as red */ test_utils_check_pixel (test_fb, fb_width - 2, 1, 0xff0000ff); test_utils_check_pixel (test_fb, 1, fb_height - 2, 0xff0000ff); test_utils_check_pixel (test_fb, fb_width - 2, fb_height - 2, 0xff0000ff); cogl_object_unref (buffer); cogl_object_unref (pos_attribute); cogl_object_unref (tex_coord_attribute); cogl_object_unref (pipeline); cogl_object_unref (tex); if (cogl_test_verbose ()) g_print ("OK\n"); }
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGtk3Cogl_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); cogl_framebuffer_orthographic(g_Framebuffer, 0, 0, io.DisplaySize.x, io.DisplaySize.y, -1, 1); CoglContext *context = cogl_framebuffer_get_context(g_Framebuffer); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; int idx_buffer_offset = 0; CoglAttributeBuffer *vertices = cogl_attribute_buffer_new(context, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), cmd_list->VtxBuffer.Data); #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) CoglAttribute *attrs[3] = { cogl_attribute_new(vertices, "cogl_position_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, pos), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_tex_coord0_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, uv), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_color_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, col), 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE) }; #undef OFFSETOF CoglPrimitive *primitive = cogl_primitive_new_with_attributes(COGL_VERTICES_MODE_TRIANGLES, cmd_list->VtxBuffer.Size, attrs, 3); CoglIndices *indices = cogl_indices_new(context, sizeof(ImDrawIdx) == 2 ? COGL_INDICES_TYPE_UNSIGNED_SHORT : COGL_INDICES_TYPE_UNSIGNED_INT, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; cogl_indices_set_offset(indices, sizeof(ImDrawIdx) * idx_buffer_offset); cogl_primitive_set_indices(primitive, indices, pcmd->ElemCount); if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { bool has_texture = pcmd->TextureId != NULL; CoglPipeline *pipeline = has_texture ? (cogl_is_pipeline(pcmd->TextureId) ? (CoglPipeline *) pcmd->TextureId : g_ImagePipeline) : g_ColorPipeline; if (has_texture && pipeline == g_ImagePipeline) { cogl_pipeline_set_layer_texture(g_ImagePipeline, 0, COGL_TEXTURE(pcmd->TextureId)); } cogl_framebuffer_push_scissor_clip(g_Framebuffer, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); cogl_primitive_draw(primitive, g_Framebuffer, pipeline); cogl_framebuffer_pop_clip(g_Framebuffer); } idx_buffer_offset += pcmd->ElemCount; } for (int i = 0; i < 3; i++) cogl_object_unref(attrs[i]); cogl_object_unref(primitive); cogl_object_unref(vertices); cogl_object_unref(indices); } }
static void _cogl_path_build_stroke_attribute_buffer (CoglPath *path) { CoglPathData *data = path->data; CoglBuffer *buffer; unsigned int n_attributes = 0; unsigned int path_start; CoglPathNode *node; floatVec2 *buffer_p; unsigned int i; /* If we've already got a cached vbo then we don't need to do anything */ if (data->stroke_attribute_buffer) return; data->stroke_attribute_buffer = cogl_attribute_buffer_new_with_size (data->context, data->path_nodes->len * sizeof (floatVec2)); buffer = COGL_BUFFER (data->stroke_attribute_buffer); buffer_p = _cogl_buffer_map_for_fill_or_fallback (buffer); /* Copy the vertices in and count the number of sub paths. Each sub path will form a separate attribute so we can paint the disjoint line strips */ 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); for (i = 0; i < node->path_size; i++) { buffer_p[path_start + i].x = node[i].x; buffer_p[path_start + i].y = node[i].y; } n_attributes++; } _cogl_buffer_unmap_for_fill_or_fallback (buffer); data->stroke_attributes = g_new (CoglAttribute *, n_attributes); /* Now we can loop the sub paths again to create the attributes */ for (i = 0, path_start = 0; path_start < data->path_nodes->len; i++, path_start += node->path_size) { node = &g_array_index (data->path_nodes, CoglPathNode, path_start); data->stroke_attributes[i] = cogl_attribute_new (data->stroke_attribute_buffer, "cogl_position_in", sizeof (floatVec2), path_start * sizeof (floatVec2), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); } data->stroke_n_attributes = n_attributes; }
static void test_short_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer; CoglPipeline *pipeline, *pipeline2; CoglSnippet *snippet; CoglPrimitive *primitive; static const ShortVert short_verts[] = { { -10, -10, /**/ 0xffff, 0, 0, 0xffff }, { -1, -10, /**/ 0xffff, 0, 0, 0xffff }, { -5, -1, /**/ 0xffff, 0, 0, 0xffff } }; pipeline = cogl_pipeline_copy (state->pipeline); cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); buffer = cogl_attribute_buffer_new (test_ctx, sizeof (short_verts), short_verts); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); attributes[1] = cogl_attribute_new (buffer, "color", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); cogl_attribute_set_normalized (attributes[1], TRUE); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f, offset_y + 10.0f, 0.0f); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 3, /* n_vertices */ attributes, 2); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, pipeline); cogl_object_unref (primitive); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); /* Test again treating the attribute as unsigned */ attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); /* XXX: this is a hack to force the pipeline to use the glsl backend * because we know it's not possible to test short vertex position * components with the legacy GL backend since which might otherwise * be used internally... */ pipeline2 = cogl_pipeline_new (test_ctx); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, "attribute vec4 color;", "cogl_color_out = vec4 (0.0, 1.0, 0.0, 1.0);"); cogl_pipeline_add_snippet (pipeline2, snippet); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f - 65525.0f, offset_y - 65525, 0.0f); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 3, /* n_vertices */ attributes, 1); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, pipeline2); cogl_object_unref (primitive); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); cogl_object_unref (pipeline2); cogl_object_unref (pipeline); cogl_object_unref (buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); }
static void test_short_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[1]; CoglAttributeBuffer *buffer; CoglPipeline *pipeline, *pipeline2; CoglSnippet *snippet; static const ShortVert short_verts[] = { { -10, -10 }, { -1, -10 }, { -5, -1 } }; pipeline = cogl_pipeline_new (test_ctx); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_TRANSFORM, "attribute vec2 pos;", NULL); cogl_snippet_set_replace (snippet, "cogl_position_out = " "cogl_modelview_projection_matrix * " "vec4 (pos, 0.0, 1.0);"); cogl_pipeline_add_snippet (pipeline, snippet); cogl_object_unref (snippet); cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); buffer = cogl_attribute_buffer_new (test_ctx, sizeof (short_verts), short_verts); attributes[0] = cogl_attribute_new (buffer, "pos", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f, offset_y + 10.0f, 0.0f); cogl_framebuffer_draw_attributes (test_fb, pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 3, /* n_vertices */ attributes, 1 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); /* Test again treating the attribute as unsigned */ attributes[0] = cogl_attribute_new (buffer, "pos", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); pipeline2 = cogl_pipeline_copy (pipeline); cogl_pipeline_set_color4ub (pipeline2, 0, 255, 0, 255); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f - 65525.0f, offset_y - 65525, 0.0f); cogl_framebuffer_draw_attributes (test_fb, pipeline2, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 3, /* n_vertices */ attributes, 1 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); cogl_object_unref (pipeline2); cogl_object_unref (pipeline); cogl_object_unref (buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); }
static void clutter_deform_effect_init_arrays (ClutterDeformEffect *self) { ClutterDeformEffectPrivate *priv = self->priv; gint x, y, direction, n_indices; CoglAttribute *attributes[3]; guint16 *static_indices; CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglIndices *indices; guint16 *idx; int i; clutter_deform_effect_free_arrays (self); n_indices = ((2 + 2 * priv->x_tiles) * priv->y_tiles + (priv->y_tiles - 1)); static_indices = g_new (guint16, n_indices); #define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) /* compute all the triangles from the various tiles */ direction = 1; idx = static_indices; idx[0] = MESH_INDEX (0, 0); idx[1] = MESH_INDEX (0, 1); idx += 2; for (y = 0; y < priv->y_tiles; y++) { for (x = 0; x < priv->x_tiles; x++) { if (direction) { idx[0] = MESH_INDEX (x + 1, y); idx[1] = MESH_INDEX (x + 1, y + 1); } else { idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); } idx += 2; } if (y == (priv->y_tiles - 1)) break; if (direction) { idx[0] = MESH_INDEX (priv->x_tiles, y + 1); idx[1] = MESH_INDEX (priv->x_tiles, y + 1); idx[2] = MESH_INDEX (priv->x_tiles, y + 2); } else { idx[0] = MESH_INDEX (0, y + 1); idx[1] = MESH_INDEX (0, y + 1); idx[2] = MESH_INDEX (0, y + 2); } idx += 3; direction = !direction; } #undef MESH_INDEX indices = cogl_indices_new (ctx, COGL_INDICES_TYPE_UNSIGNED_SHORT, static_indices, n_indices); g_free (static_indices); priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1); priv->buffer = cogl_attribute_buffer_new (ctx, sizeof (CoglVertexP3T2C4) * priv->n_vertices, NULL); /* The application is expected to continuously modify the vertices so we should give a hint to Cogl about that */ cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer), COGL_BUFFER_UPDATE_HINT_DYNAMIC); attributes[0] = cogl_attribute_new (priv->buffer, "cogl_position_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, x), 3, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (priv->buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[2] = cogl_attribute_new (priv->buffer, "cogl_color_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP, priv->n_vertices, attributes, 3 /* n_attributes */); cogl_primitive_set_indices (priv->primitive, indices, n_indices); if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES)) { priv->lines_primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, priv->n_vertices, attributes, 2 /* n_attributes */); cogl_primitive_set_indices (priv->lines_primitive, indices, n_indices); } cogl_object_unref (indices); for (i = 0; i < 3; i++) cogl_object_unref (attributes[i]); priv->is_dirty = TRUE; }
static void test_byte_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer, *unnorm_buffer; static const ByteVert norm_verts[] = { { 0, 10, /**/ 255, 0, 0, 255 }, { 10, 10, /**/ 255, 0, 0, 255 }, { 5, 0, /**/ 255, 0, 0, 255 }, { 10, 10, /**/ 0, 255, 0, 255 }, { 20, 10, /**/ 0, 255, 0, 255 }, { 15, 0, /**/ 0, 255, 0, 255 } }; static const ByteVert unnorm_verts[] = { { 0, 0, /**/ 0, 0, 1, 1 }, { 0, 0, /**/ 0, 0, 1, 1 }, { 0, 0, /**/ 0, 0, 1, 1 }, }; buffer = cogl_attribute_buffer_new (test_ctx, sizeof (norm_verts), norm_verts); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (ByteVert), G_STRUCT_OFFSET (ByteVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); attributes[1] = cogl_attribute_new (buffer, "color", sizeof (ByteVert), G_STRUCT_OFFSET (ByteVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); cogl_attribute_set_normalized (attributes[1], TRUE); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x, offset_y, 0.0f); cogl_framebuffer_draw_attributes (test_fb, state->pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 6, /* n_vertices */ attributes, 2 /* n_attributes */); cogl_object_unref (attributes[1]); /* Test again with unnormalized attributes */ unnorm_buffer = cogl_attribute_buffer_new (test_ctx, sizeof (unnorm_verts), unnorm_verts); attributes[1] = cogl_attribute_new (unnorm_buffer, "color", sizeof (ByteVert), G_STRUCT_OFFSET (ByteVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_BYTE); cogl_framebuffer_translate (test_fb, 20, 0, 0); cogl_framebuffer_draw_attributes (test_fb, state->pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 3, /* n_vertices */ attributes, 2 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); cogl_object_unref (buffer); cogl_object_unref (unnorm_buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); test_utils_check_pixel (test_fb, offset_x + 25, offset_y + 5, 0x0000ffff); }
static gboolean mash_ply_loader_load (MashDataLoader *data_loader, MashDataFlags flags, const gchar *filename, GError **error) { CoglContext *context; CoglIndices *indices; MashPlyLoader *self = MASH_PLY_LOADER (data_loader); MashPlyLoaderPrivate *priv; MashPlyLoaderData data; gchar *display_name; gboolean ret; priv = self->priv; context = es_get_cogl_context (); data.error = NULL; data.n_vertex_bytes = 0; data.available_props = 0; data.got_props = 0; data.vertices = g_byte_array_new (); data.faces = NULL; data.min_vertex.x = G_MAXFLOAT; data.min_vertex.y = G_MAXFLOAT; data.min_vertex.z = G_MAXFLOAT; data.max_vertex.x = -G_MAXFLOAT; data.max_vertex.y = -G_MAXFLOAT; data.max_vertex.z = -G_MAXFLOAT; data.flags = flags; display_name = g_filename_display_name (filename); if ((data.ply = ply_open (filename, mash_ply_loader_error_cb, &data)) == NULL) mash_ply_loader_check_unknown_error (&data); else { if (!ply_read_header (data.ply)) mash_ply_loader_check_unknown_error (&data); else { int i; for (i = 0; i < G_N_ELEMENTS (mash_ply_loader_properties); i++) if (ply_set_read_cb (data.ply, "vertex", mash_ply_loader_properties[i].name, mash_ply_loader_vertex_read_cb, &data, i)) { data.prop_map[i] = data.n_vertex_bytes; data.n_vertex_bytes += mash_ply_loader_properties[i].size; data.available_props |= 1 << i; } /* Align the size of a vertex to 32 bits */ data.n_vertex_bytes = (data.n_vertex_bytes + 3) & ~(guint) 3; if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) != MASH_PLY_LOADER_VERTEX_PROPS) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing the vertex properties", display_name); else if (!ply_set_read_cb (data.ply, "face", "vertex_indices", mash_ply_loader_face_read_cb, &data, i)) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing face property " "'vertex_indices'", display_name); else if (mash_ply_loader_get_indices_type (&data, &data.error) && !ply_read (data.ply)) mash_ply_loader_check_unknown_error (&data); } ply_close (data.ply); } if (data.error) { g_propagate_error (error, data.error); ret = FALSE; } else if (data.faces->len < 3) { g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_INVALID, "No faces found in %s", display_name); ret = FALSE; } else { CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[4]; int n_attributes = 0, i; /* Get rid of the old primitive (if any) */ mash_ply_loader_free_primitive (self); /* Create a new attribute buffer for the vertices */ attribute_buffer = cogl_attribute_buffer_new (context, data.vertices->len, data.vertices->data); /* And describe the attributes */ if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) == MASH_PLY_LOADER_VERTEX_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_position_in", data.n_vertex_bytes, data.prop_map[0], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_NORMAL_PROPS) == MASH_PLY_LOADER_NORMAL_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_normal_in", data.n_vertex_bytes, data.prop_map[3], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_TEX_COORD_PROPS) == MASH_PLY_LOADER_TEX_COORD_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord0_in", data.n_vertex_bytes, data.prop_map[6], 2, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_COLOR_PROPS) == MASH_PLY_LOADER_COLOR_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_color_in", data.n_vertex_bytes, data.prop_map[8], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, data.vertices->len, attributes, n_attributes); for (i = 0; i < n_attributes; i++) cogl_object_unref (attributes[i]); indices = cogl_indices_new (context, data.indices_type, data.faces->data, data.faces->len); cogl_primitive_set_indices (priv->primitive, indices, data.faces->len); cogl_object_unref (indices); priv->min_vertex = data.min_vertex; priv->max_vertex = data.max_vertex; ret = TRUE; } g_free (display_name); g_byte_array_free (data.vertices, TRUE); if (data.faces) g_array_free (data.faces, TRUE); return ret; }