4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2010 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see
20 * <http://www.gnu.org/licenses/>.
25 * Robert Bragg <robert@linux.intel.com>
32 #include "cogl-util.h"
33 #include "cogl-object-private.h"
34 #include "cogl-primitive.h"
35 #include "cogl-primitive-private.h"
36 #include "cogl-attribute-private.h"
41 static void _cogl_primitive_free (CoglPrimitive *primitive);
43 COGL_OBJECT_DEFINE (Primitive, primitive);
46 cogl_primitive_new_with_attributes (CoglVerticesMode mode,
48 CoglAttribute **attributes,
51 CoglPrimitive *primitive;
54 primitive = g_slice_alloc (sizeof (CoglPrimitive) +
55 sizeof (CoglAttribute *) * (n_attributes - 1));
56 primitive->mode = mode;
57 primitive->first_vertex = 0;
58 primitive->n_vertices = n_vertices;
59 primitive->indices = NULL;
60 primitive->immutable_ref = 0;
62 primitive->n_attributes = n_attributes;
63 primitive->n_embedded_attributes = n_attributes;
64 primitive->attributes = &primitive->embedded_attribute;
65 for (i = 0; i < n_attributes; i++)
67 CoglAttribute *attribute = attributes[i];
68 cogl_object_ref (attribute);
70 _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), NULL);
72 primitive->attributes[i] = attribute;
75 return _cogl_primitive_object_new (primitive);
78 /* This is just an internal convenience wrapper around
79 new_with_attributes that also unrefs the attributes. It is just
80 used for the builtin struct constructors */
81 static CoglPrimitive *
82 _cogl_primitive_new_with_attributes_unref (CoglVerticesMode mode,
84 CoglAttribute **attributes,
87 CoglPrimitive *primitive;
90 primitive = cogl_primitive_new_with_attributes (mode,
95 for (i = 0; i < n_attributes; i++)
96 cogl_object_unref (attributes[i]);
102 cogl_primitive_new (CoglVerticesMode mode,
108 CoglAttribute **attributes;
110 CoglAttribute *attribute;
112 va_start (ap, n_vertices);
113 for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
117 attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes);
119 va_start (ap, n_vertices);
120 for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
121 attributes[i] = attribute;
124 return cogl_primitive_new_with_attributes (mode, n_vertices,
130 cogl_primitive_new_p2 (CoglContext *ctx,
131 CoglVerticesMode mode,
133 const CoglVertexP2 *data)
135 CoglAttributeBuffer *attribute_buffer =
136 cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP2), data);
137 CoglAttribute *attributes[1];
139 attributes[0] = cogl_attribute_new (attribute_buffer,
141 sizeof (CoglVertexP2),
142 offsetof (CoglVertexP2, x),
144 COGL_ATTRIBUTE_TYPE_FLOAT);
146 cogl_object_unref (attribute_buffer);
148 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
154 cogl_primitive_new_p3 (CoglContext *ctx,
155 CoglVerticesMode mode,
157 const CoglVertexP3 *data)
159 CoglAttributeBuffer *attribute_buffer =
160 cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3), data);
161 CoglAttribute *attributes[1];
163 attributes[0] = cogl_attribute_new (attribute_buffer,
165 sizeof (CoglVertexP3),
166 offsetof (CoglVertexP3, x),
168 COGL_ATTRIBUTE_TYPE_FLOAT);
170 cogl_object_unref (attribute_buffer);
172 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
178 cogl_primitive_new_p2c4 (CoglContext *ctx,
179 CoglVerticesMode mode,
181 const CoglVertexP2C4 *data)
183 CoglAttributeBuffer *attribute_buffer =
184 cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP2C4), data);
185 CoglAttribute *attributes[2];
187 attributes[0] = cogl_attribute_new (attribute_buffer,
189 sizeof (CoglVertexP2C4),
190 offsetof (CoglVertexP2C4, x),
192 COGL_ATTRIBUTE_TYPE_FLOAT);
193 attributes[1] = cogl_attribute_new (attribute_buffer,
195 sizeof (CoglVertexP2C4),
196 offsetof (CoglVertexP2C4, r),
198 COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
200 cogl_object_unref (attribute_buffer);
202 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
208 cogl_primitive_new_p3c4 (CoglContext *ctx,
209 CoglVerticesMode mode,
211 const CoglVertexP3C4 *data)
213 CoglAttributeBuffer *attribute_buffer =
214 cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3C4), data);
215 CoglAttribute *attributes[2];
217 attributes[0] = cogl_attribute_new (attribute_buffer,
219 sizeof (CoglVertexP3C4),
220 offsetof (CoglVertexP3C4, x),
222 COGL_ATTRIBUTE_TYPE_FLOAT);
223 attributes[1] = cogl_attribute_new (attribute_buffer,
225 sizeof (CoglVertexP3C4),
226 offsetof (CoglVertexP3C4, r),
228 COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
230 cogl_object_unref (attribute_buffer);
232 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
238 cogl_primitive_new_p2t2 (CoglContext *ctx,
239 CoglVerticesMode mode,
241 const CoglVertexP2T2 *data)
243 CoglAttributeBuffer *attribute_buffer =
244 cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP2T2), data);
245 CoglAttribute *attributes[2];
247 attributes[0] = cogl_attribute_new (attribute_buffer,
249 sizeof (CoglVertexP2T2),
250 offsetof (CoglVertexP2T2, x),
252 COGL_ATTRIBUTE_TYPE_FLOAT);
253 attributes[1] = cogl_attribute_new (attribute_buffer,
254 "cogl_tex_coord0_in",
255 sizeof (CoglVertexP2T2),
256 offsetof (CoglVertexP2T2, s),
258 COGL_ATTRIBUTE_TYPE_FLOAT);
260 cogl_object_unref (attribute_buffer);
262 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
268 cogl_primitive_new_p3t2 (CoglContext *ctx,
269 CoglVerticesMode mode,
271 const CoglVertexP3T2 *data)
273 CoglAttributeBuffer *attribute_buffer =
274 cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3T2), data);
275 CoglAttribute *attributes[2];
277 attributes[0] = cogl_attribute_new (attribute_buffer,
279 sizeof (CoglVertexP3T2),
280 offsetof (CoglVertexP3T2, x),
282 COGL_ATTRIBUTE_TYPE_FLOAT);
283 attributes[1] = cogl_attribute_new (attribute_buffer,
284 "cogl_tex_coord0_in",
285 sizeof (CoglVertexP3T2),
286 offsetof (CoglVertexP3T2, s),
288 COGL_ATTRIBUTE_TYPE_FLOAT);
290 cogl_object_unref (attribute_buffer);
292 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
298 cogl_primitive_new_p2t2c4 (CoglContext *ctx,
299 CoglVerticesMode mode,
301 const CoglVertexP2T2C4 *data)
303 CoglAttributeBuffer *attribute_buffer =
304 cogl_attribute_buffer_new (ctx,
305 n_vertices * sizeof (CoglVertexP2T2C4), data);
306 CoglAttribute *attributes[3];
308 attributes[0] = cogl_attribute_new (attribute_buffer,
310 sizeof (CoglVertexP2T2C4),
311 offsetof (CoglVertexP2T2C4, x),
313 COGL_ATTRIBUTE_TYPE_FLOAT);
314 attributes[1] = cogl_attribute_new (attribute_buffer,
315 "cogl_tex_coord0_in",
316 sizeof (CoglVertexP2T2C4),
317 offsetof (CoglVertexP2T2C4, s),
319 COGL_ATTRIBUTE_TYPE_FLOAT);
320 attributes[2] = cogl_attribute_new (attribute_buffer,
322 sizeof (CoglVertexP2T2C4),
323 offsetof (CoglVertexP2T2C4, r),
325 COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
327 cogl_object_unref (attribute_buffer);
329 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
335 cogl_primitive_new_p3t2c4 (CoglContext *ctx,
336 CoglVerticesMode mode,
338 const CoglVertexP3T2C4 *data)
340 CoglAttributeBuffer *attribute_buffer =
341 cogl_attribute_buffer_new (ctx,
342 n_vertices * sizeof (CoglVertexP3T2C4), data);
343 CoglAttribute *attributes[3];
345 attributes[0] = cogl_attribute_new (attribute_buffer,
347 sizeof (CoglVertexP3T2C4),
348 offsetof (CoglVertexP3T2C4, x),
350 COGL_ATTRIBUTE_TYPE_FLOAT);
351 attributes[1] = cogl_attribute_new (attribute_buffer,
352 "cogl_tex_coord0_in",
353 sizeof (CoglVertexP3T2C4),
354 offsetof (CoglVertexP3T2C4, s),
356 COGL_ATTRIBUTE_TYPE_FLOAT);
357 attributes[2] = cogl_attribute_new (attribute_buffer,
359 sizeof (CoglVertexP3T2C4),
360 offsetof (CoglVertexP3T2C4, r),
362 COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
364 cogl_object_unref (attribute_buffer);
366 return _cogl_primitive_new_with_attributes_unref (mode, n_vertices,
372 _cogl_primitive_free (CoglPrimitive *primitive)
376 for (i = 0; i < primitive->n_attributes; i++)
377 cogl_object_unref (primitive->attributes[i]);
379 if (primitive->attributes != &primitive->embedded_attribute)
380 g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes,
381 primitive->attributes);
383 g_slice_free1 (sizeof (CoglPrimitive) +
384 sizeof (CoglAttribute *) *
385 (primitive->n_embedded_attributes - 1), primitive);
389 warn_about_midscene_changes (void)
391 static gboolean seen = FALSE;
394 g_warning ("Mid-scene modification of primitives has "
395 "undefined results\n");
401 cogl_primitive_set_attributes (CoglPrimitive *primitive,
402 CoglAttribute **attributes,
407 _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive));
409 if (G_UNLIKELY (primitive->immutable_ref))
411 warn_about_midscene_changes ();
415 /* NB: we don't unref the previous attributes before refing the new
416 * in case we would end up releasing the last reference for an
417 * attribute thats actually in the new list too. */
418 for (i = 0; i < n_attributes; i++)
420 _COGL_RETURN_IF_FAIL (cogl_is_attribute (attributes[i]));
421 cogl_object_ref (attributes[i]);
424 for (i = 0; i < primitive->n_attributes; i++)
425 cogl_object_unref (primitive->attributes[i]);
427 /* First try to use the embedded storage assocated with the
428 * primitive, else fallback to slice allocating separate storage for
429 * the attribute pointers... */
431 if (n_attributes <= primitive->n_embedded_attributes)
433 if (primitive->attributes != &primitive->embedded_attribute)
434 g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes,
435 primitive->attributes);
436 primitive->attributes = &primitive->embedded_attribute;
440 if (primitive->attributes != &primitive->embedded_attribute)
441 g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes,
442 primitive->attributes);
443 primitive->attributes =
444 g_slice_alloc (sizeof (CoglAttribute *) * n_attributes);
447 memcpy (primitive->attributes, attributes,
448 sizeof (CoglAttribute *) * n_attributes);
450 primitive->n_attributes = n_attributes;
454 cogl_primitive_get_first_vertex (CoglPrimitive *primitive)
456 _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), 0);
458 return primitive->first_vertex;
462 cogl_primitive_set_first_vertex (CoglPrimitive *primitive,
465 _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive));
467 if (G_UNLIKELY (primitive->immutable_ref))
469 warn_about_midscene_changes ();
473 primitive->first_vertex = first_vertex;
477 cogl_primitive_get_n_vertices (CoglPrimitive *primitive)
479 _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), 0);
481 return primitive->n_vertices;
485 cogl_primitive_set_n_vertices (CoglPrimitive *primitive,
488 _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive));
490 primitive->n_vertices = n_vertices;
494 cogl_primitive_get_mode (CoglPrimitive *primitive)
496 _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), 0);
498 return primitive->mode;
502 cogl_primitive_set_mode (CoglPrimitive *primitive,
503 CoglVerticesMode mode)
505 _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive));
507 if (G_UNLIKELY (primitive->immutable_ref))
509 warn_about_midscene_changes ();
513 primitive->mode = mode;
517 cogl_primitive_set_indices (CoglPrimitive *primitive,
518 CoglIndices *indices,
521 _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive));
523 if (G_UNLIKELY (primitive->immutable_ref))
525 warn_about_midscene_changes ();
530 cogl_object_ref (indices);
531 if (primitive->indices)
532 cogl_object_unref (primitive->indices);
533 primitive->indices = indices;
534 primitive->n_vertices = n_indices;
538 cogl_primitive_get_indices (CoglPrimitive *primitive)
540 return primitive->indices;
544 cogl_primitive_copy (CoglPrimitive *primitive)
548 copy = cogl_primitive_new_with_attributes (primitive->mode,
549 primitive->n_vertices,
550 primitive->attributes,
551 primitive->n_attributes);
553 cogl_primitive_set_indices (copy, primitive->indices, primitive->n_vertices);
554 cogl_primitive_set_first_vertex (copy, primitive->first_vertex);
560 _cogl_primitive_immutable_ref (CoglPrimitive *primitive)
564 _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), NULL);
566 primitive->immutable_ref++;
568 for (i = 0; i < primitive->n_attributes; i++)
569 _cogl_attribute_immutable_ref (primitive->attributes[i]);
575 _cogl_primitive_immutable_unref (CoglPrimitive *primitive)
579 _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive));
580 _COGL_RETURN_IF_FAIL (primitive->immutable_ref > 0);
582 primitive->immutable_ref--;
584 for (i = 0; i < primitive->n_attributes; i++)
585 _cogl_attribute_immutable_unref (primitive->attributes[i]);
589 cogl_primitive_foreach_attribute (CoglPrimitive *primitive,
590 CoglPrimitiveAttributeCallback callback,
595 for (i = 0; i < primitive->n_attributes; i++)
596 if (!callback (primitive, primitive->attributes[i], user_data))