cleanup specfile for packaging
[profile/ivi/cogl.git] / cogl / cogl-indices.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2010 Intel Corporation.
7  *
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.
12  *
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.
17  *
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/>.
21  *
22  *
23  *
24  * Authors:
25  *   Robert Bragg <robert@linux.intel.com>
26  *   Neil Roberts <neil@linux.intel.com>
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "cogl-util.h"
34 #include "cogl-object-private.h"
35 #include "cogl-context-private.h"
36 #include "cogl-indices.h"
37 #include "cogl-indices-private.h"
38 #include "cogl-index-buffer.h"
39
40 #include <stdarg.h>
41
42 static void _cogl_indices_free (CoglIndices *indices);
43
44 COGL_OBJECT_DEFINE (Indices, indices);
45
46 static size_t
47 sizeof_indices_type (CoglIndicesType type)
48 {
49   switch (type)
50     {
51     case COGL_INDICES_TYPE_UNSIGNED_BYTE:
52       return 1;
53     case COGL_INDICES_TYPE_UNSIGNED_SHORT:
54       return 2;
55     case COGL_INDICES_TYPE_UNSIGNED_INT:
56       return 4;
57     }
58   g_return_val_if_reached (0);
59 }
60
61 CoglIndices *
62 cogl_indices_new_for_buffer (CoglIndicesType type,
63                              CoglIndexBuffer *buffer,
64                              gsize offset)
65 {
66   CoglIndices *indices = g_slice_new (CoglIndices);
67
68   indices->buffer = cogl_object_ref (buffer);
69   indices->offset = offset;
70
71   indices->type = type;
72
73   indices->immutable_ref = 0;
74
75   return _cogl_indices_object_new (indices);
76 }
77
78 CoglIndices *
79 cogl_indices_new (CoglContext *context,
80                   CoglIndicesType type,
81                   const void *indices_data,
82                   int n_indices)
83 {
84   size_t buffer_bytes = sizeof_indices_type (type) * n_indices;
85   CoglIndexBuffer *index_buffer = cogl_index_buffer_new (context, buffer_bytes);
86   CoglBuffer *buffer = COGL_BUFFER (index_buffer);
87   CoglIndices *indices;
88
89   cogl_buffer_set_data (buffer,
90                         0,
91                         indices_data,
92                         buffer_bytes);
93
94   indices = cogl_indices_new_for_buffer (type, index_buffer, 0);
95   cogl_object_unref (index_buffer);
96
97   return indices;
98 }
99
100 CoglIndexBuffer *
101 cogl_indices_get_buffer (CoglIndices *indices)
102 {
103   return indices->buffer;
104 }
105
106 CoglIndicesType
107 cogl_indices_get_type (CoglIndices *indices)
108 {
109   _COGL_RETURN_VAL_IF_FAIL (cogl_is_indices (indices),
110                             COGL_INDICES_TYPE_UNSIGNED_BYTE);
111   return indices->type;
112 }
113
114 gsize
115 cogl_indices_get_offset (CoglIndices *indices)
116 {
117   _COGL_RETURN_VAL_IF_FAIL (cogl_is_indices (indices), 0);
118
119   return indices->offset;
120 }
121
122 static void
123 warn_about_midscene_changes (void)
124 {
125   static gboolean seen = FALSE;
126   if (!seen)
127     {
128       g_warning ("Mid-scene modification of indices has "
129                  "undefined results\n");
130       seen = TRUE;
131     }
132 }
133
134 void
135 cogl_indices_set_offset (CoglIndices *indices,
136                          gsize offset)
137 {
138   _COGL_RETURN_IF_FAIL (cogl_is_indices (indices));
139
140   if (G_UNLIKELY (indices->immutable_ref))
141     warn_about_midscene_changes ();
142
143   indices->offset = offset;
144 }
145
146 static void
147 _cogl_indices_free (CoglIndices *indices)
148 {
149   cogl_object_unref (indices->buffer);
150   g_slice_free (CoglIndices, indices);
151 }
152
153 CoglIndices *
154 _cogl_indices_immutable_ref (CoglIndices *indices)
155 {
156   _COGL_RETURN_VAL_IF_FAIL (cogl_is_indices (indices), NULL);
157
158   indices->immutable_ref++;
159   _cogl_buffer_immutable_ref (COGL_BUFFER (indices->buffer));
160   return indices;
161 }
162
163 void
164 _cogl_indices_immutable_unref (CoglIndices *indices)
165 {
166   _COGL_RETURN_IF_FAIL (cogl_is_indices (indices));
167   _COGL_RETURN_IF_FAIL (indices->immutable_ref > 0);
168
169   indices->immutable_ref--;
170   _cogl_buffer_immutable_unref (COGL_BUFFER (indices->buffer));
171 }
172
173 CoglIndices *
174 cogl_get_rectangle_indices (CoglContext *ctx, int n_rectangles)
175 {
176   int n_indices = n_rectangles * 6;
177
178   /* Check if the largest index required will fit in a byte array... */
179   if (n_indices <= 256 / 4 * 6)
180     {
181       /* Generate the byte array if we haven't already */
182       if (ctx->rectangle_byte_indices == NULL)
183         {
184           guint8 *byte_array = g_malloc (256 / 4 * 6 * sizeof (guint8));
185           guint8 *p = byte_array;
186           int i, vert_num = 0;
187
188           for (i = 0; i < 256 / 4; i++)
189             {
190               *(p++) = vert_num + 0;
191               *(p++) = vert_num + 1;
192               *(p++) = vert_num + 2;
193               *(p++) = vert_num + 0;
194               *(p++) = vert_num + 2;
195               *(p++) = vert_num + 3;
196               vert_num += 4;
197             }
198
199           ctx->rectangle_byte_indices
200             = cogl_indices_new (ctx,
201                                 COGL_INDICES_TYPE_UNSIGNED_BYTE,
202                                 byte_array,
203                                 256 / 4 * 6);
204
205           g_free (byte_array);
206         }
207
208       return ctx->rectangle_byte_indices;
209     }
210   else
211     {
212       if (ctx->rectangle_short_indices_len < n_indices)
213         {
214           guint16 *short_array;
215           guint16 *p;
216           int i, vert_num = 0;
217
218           if (ctx->rectangle_short_indices != NULL)
219             cogl_object_unref (ctx->rectangle_short_indices);
220           /* Pick a power of two >= MAX (512, n_indices) */
221           if (ctx->rectangle_short_indices_len == 0)
222             ctx->rectangle_short_indices_len = 512;
223           while (ctx->rectangle_short_indices_len < n_indices)
224             ctx->rectangle_short_indices_len *= 2;
225
226           /* Over-allocate to generate a whole number of quads */
227           p = short_array = g_malloc ((ctx->rectangle_short_indices_len
228                                        + 5) / 6 * 6
229                                       * sizeof (guint16));
230
231           /* Fill in the complete quads */
232           for (i = 0; i < ctx->rectangle_short_indices_len; i += 6)
233             {
234               *(p++) = vert_num + 0;
235               *(p++) = vert_num + 1;
236               *(p++) = vert_num + 2;
237               *(p++) = vert_num + 0;
238               *(p++) = vert_num + 2;
239               *(p++) = vert_num + 3;
240               vert_num += 4;
241             }
242
243           ctx->rectangle_short_indices
244             = cogl_indices_new (ctx,
245                                 COGL_INDICES_TYPE_UNSIGNED_SHORT,
246                                 short_array,
247                                 ctx->rectangle_short_indices_len);
248
249           g_free (short_array);
250         }
251
252       return ctx->rectangle_short_indices;
253     }
254 }
255