cg_indices_t * cg_get_rectangle_indices(cg_device_t *dev, int n_rectangles) { int n_indices = n_rectangles * 6; /* Check if the largest index required will fit in a byte array... */ if (n_indices <= 256 / 4 * 6) { /* Generate the byte array if we haven't already */ if (dev->rectangle_byte_indices == NULL) { uint8_t *byte_array = c_malloc(256 / 4 * 6 * sizeof(uint8_t)); uint8_t *p = byte_array; int i, vert_num = 0; for (i = 0; i < 256 / 4; i++) { *(p++) = vert_num + 0; *(p++) = vert_num + 1; *(p++) = vert_num + 2; *(p++) = vert_num + 0; *(p++) = vert_num + 2; *(p++) = vert_num + 3; vert_num += 4; } dev->rectangle_byte_indices = cg_indices_new(dev, CG_INDICES_TYPE_UNSIGNED_BYTE, byte_array, 256 / 4 * 6); c_free(byte_array); } return dev->rectangle_byte_indices; } else { if (dev->rectangle_short_indices_len < n_indices) { uint16_t *short_array; uint16_t *p; int i, vert_num = 0; if (dev->rectangle_short_indices != NULL) cg_object_unref(dev->rectangle_short_indices); /* Pick a power of two >= MAX (512, n_indices) */ if (dev->rectangle_short_indices_len == 0) dev->rectangle_short_indices_len = 512; while (dev->rectangle_short_indices_len < n_indices) dev->rectangle_short_indices_len *= 2; /* Over-allocate to generate a whole number of quads */ p = short_array = c_malloc((dev->rectangle_short_indices_len + 5) / 6 * 6 * sizeof(uint16_t)); /* Fill in the complete quads */ for (i = 0; i < dev->rectangle_short_indices_len; i += 6) { *(p++) = vert_num + 0; *(p++) = vert_num + 1; *(p++) = vert_num + 2; *(p++) = vert_num + 0; *(p++) = vert_num + 2; *(p++) = vert_num + 3; vert_num += 4; } dev->rectangle_short_indices = cg_indices_new(dev, CG_INDICES_TYPE_UNSIGNED_SHORT, short_array, dev->rectangle_short_indices_len); c_free(short_array); } return dev->rectangle_short_indices; } }
cg_primitive_t * rut_mesh_create_primitive(rut_shell_t *shell, rut_mesh_t *mesh) { int n_attributes = mesh->n_attributes; rut_buffer_t **buffers; int n_buffers = 0; cg_attribute_buffer_t **attribute_buffers; cg_attribute_buffer_t **attribute_buffers_map; cg_attribute_t **attributes; cg_primitive_t *primitive; int i; buffers = c_alloca(sizeof(void *) * n_attributes); attribute_buffers = c_alloca(sizeof(void *) * n_attributes); attribute_buffers_map = c_alloca(sizeof(void *) * n_attributes); /* NB: * attributes may refer to shared buffers so we need to first * figure out how many unique buffers the mesh refers too... */ for (i = 0; i < n_attributes; i++) { int j; if (!mesh->attributes[i]->is_buffered) continue; for (j = 0; i < n_buffers; j++) if (buffers[j] == mesh->attributes[i]->buffered.buffer) break; if (j < n_buffers) attribute_buffers_map[i] = attribute_buffers[j]; else { attribute_buffers[n_buffers] = cg_attribute_buffer_new(shell->cg_device, mesh->attributes[i]->buffered.buffer->size, mesh->attributes[i]->buffered.buffer->data); attribute_buffers_map[i] = attribute_buffers[n_buffers]; buffers[n_buffers++] = mesh->attributes[i]->buffered.buffer; } } attributes = c_alloca(sizeof(void *) * mesh->n_attributes); for (i = 0; i < n_attributes; i++) { if (mesh->attributes[i]->is_buffered) { cg_attribute_type_t type = get_cg_attribute_type(mesh->attributes[i]->buffered.type); attributes[i] = cg_attribute_new(attribute_buffers_map[i], mesh->attributes[i]->name, mesh->attributes[i]->buffered.stride, mesh->attributes[i]->buffered.offset, mesh->attributes[i]->buffered.n_components, type); } else { attributes[i] = cg_attribute_new_const(shell->cg_device, mesh->attributes[i]->name, mesh->attributes[i]->constant.n_components, mesh->attributes[i]->constant.n_columns, mesh->attributes[i]->constant.transpose, mesh->attributes[i]->constant.value); } cg_attribute_set_normalized(attributes[i], mesh->attributes[i]->normalized); cg_attribute_set_instance_stride(attributes[i], mesh->attributes[i]->instance_stride); } for (i = 0; i < n_buffers; i++) cg_object_unref(attribute_buffers[i]); primitive = cg_primitive_new_with_attributes( mesh->mode, mesh->n_vertices, attributes, mesh->n_attributes); for (i = 0; i < n_attributes; i++) cg_object_unref(attributes[i]); if (mesh->indices_buffer) { cg_indices_t *indices = cg_indices_new(shell->cg_device, mesh->indices_type, mesh->indices_buffer->data, mesh->n_indices); cg_primitive_set_indices(primitive, indices, mesh->n_indices); cg_object_unref(indices); } return primitive; }