31
31
#include "cogl-texture-private.h"
32
32
#include "cogl-texture-3d-private.h"
33
33
#include "cogl-texture-3d.h"
34
#include "cogl-texture-gl-private.h"
34
35
#include "cogl-texture-driver.h"
35
36
#include "cogl-context-private.h"
36
37
#include "cogl-object-private.h"
37
38
#include "cogl-journal-private.h"
38
39
#include "cogl-pipeline-private.h"
39
40
#include "cogl-pipeline-opengl-private.h"
41
#include "cogl-error-private.h"
42
#include "cogl-util-gl-private.h"
41
44
#include <string.h>
56
59
static const CoglTextureVtable cogl_texture_3d_vtable;
59
_cogl_texture_3d_set_wrap_mode_parameters (CoglTexture *tex,
62
_cogl_texture_3d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
64
67
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
65
68
CoglContext *ctx = tex->context;
67
70
/* Only set the wrap mode if it's different from the current value
68
71
to avoid too many GL calls. */
69
if (tex_3d->wrap_mode_s != wrap_mode_s ||
70
tex_3d->wrap_mode_t != wrap_mode_t ||
71
tex_3d->wrap_mode_p != wrap_mode_p)
72
if (tex_3d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s ||
73
tex_3d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t ||
74
tex_3d->gl_legacy_texobj_wrap_mode_p != wrap_mode_p)
73
76
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
74
77
tex_3d->gl_texture,
86
tex_3d->wrap_mode_s = wrap_mode_s;
87
tex_3d->wrap_mode_t = wrap_mode_t;
88
tex_3d->wrap_mode_p = wrap_mode_p;
89
tex_3d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s;
90
tex_3d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
91
tex_3d->gl_legacy_texobj_wrap_mode_p = wrap_mode_p;
93
96
_cogl_texture_3d_free (CoglTexture3D *tex_3d)
95
_cogl_delete_gl_texture (tex_3d->gl_texture);
98
if (tex_3d->gl_texture)
99
_cogl_delete_gl_texture (tex_3d->gl_texture);
98
102
_cogl_texture_free (COGL_TEXTURE (tex_3d));
117
121
CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1);
118
122
CoglTexture *tex = COGL_TEXTURE (tex_3d);
120
_cogl_texture_init (tex, ctx, &cogl_texture_3d_vtable);
122
tex_3d->width = width;
123
tex_3d->height = height;
124
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_3d_vtable);
126
tex_3d->gl_texture = 0;
124
128
tex_3d->depth = depth;
125
129
tex_3d->mipmaps_dirty = TRUE;
126
130
tex_3d->auto_mipmap = TRUE;
128
132
/* We default to GL_LINEAR for both filters */
129
tex_3d->min_filter = GL_LINEAR;
130
tex_3d->mag_filter = GL_LINEAR;
133
tex_3d->gl_legacy_texobj_min_filter = GL_LINEAR;
134
tex_3d->gl_legacy_texobj_mag_filter = GL_LINEAR;
132
136
/* Wrap mode not yet set */
133
tex_3d->wrap_mode_s = GL_FALSE;
134
tex_3d->wrap_mode_t = GL_FALSE;
135
tex_3d->wrap_mode_p = GL_FALSE;
137
tex_3d->format = internal_format;
137
tex_3d->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
138
tex_3d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
139
tex_3d->gl_legacy_texobj_wrap_mode_p = GL_FALSE;
141
tex_3d->internal_format = internal_format;
143
return _cogl_texture_3d_object_new (tex_3d);
153
157
/* This should only happen on GLES */
154
158
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
158
COGL_ERROR_UNSUPPORTED,
159
"3D textures are not supported by the GPU");
160
_cogl_set_error (error,
162
COGL_SYSTEM_ERROR_UNSUPPORTED,
163
"3D textures are not supported by the GPU");
167
171
!_cogl_util_is_pot (height) ||
168
172
!_cogl_util_is_pot (depth)))
172
COGL_ERROR_UNSUPPORTED,
173
"A non-power-of-two size was requested but this is not "
174
"supported by the GPU");
174
_cogl_set_error (error,
176
COGL_SYSTEM_ERROR_UNSUPPORTED,
177
"A non-power-of-two size was requested but this is not "
178
"supported by the GPU");
208
CoglPixelFormat internal_format,
212
CoglPixelFormat internal_format)
211
CoglTexture3D *tex_3d;
216
214
/* Since no data, we need some internal format */
217
215
if (internal_format == COGL_PIXEL_FORMAT_ANY)
218
216
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
218
return _cogl_texture_3d_create_base (ctx,
219
width, height, depth,
224
_cogl_texture_3d_allocate (CoglTexture *tex,
227
CoglContext *ctx = tex->context;
228
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
220
235
if (!_cogl_texture_3d_can_create (ctx,
221
width, height, depth,
239
tex_3d->internal_format,
226
internal_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
232
tex_3d = _cogl_texture_3d_create_base (ctx,
233
width, height, depth,
236
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
243
ctx->driver_vtable->pixel_format_to_gl (ctx,
244
tex_3d->internal_format,
250
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, tex_3d->internal_format);
237
251
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
240
GE( ctx, glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
241
width, height, depth, 0, gl_format, gl_type, NULL) );
243
return _cogl_texture_3d_object_new (tex_3d);
254
/* Clear any GL errors */
255
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
258
ctx->glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
259
tex->width, tex->height, tex_3d->depth,
260
0, gl_format, gl_type, NULL);
262
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
264
GE( ctx, glDeleteTextures (1, &gl_texture) );
268
tex_3d->gl_texture = gl_texture;
269
tex_3d->gl_format = gl_intformat;
279
306
&internal_format,
284
311
if (dst_bmp == NULL)
286
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
287
"Bitmap conversion failed");
291
314
tex_3d = _cogl_texture_3d_create_base (ctx,
292
315
bmp_width, height, depth,
295
318
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
296
319
supported we can fallback to using GL_GENERATE_MIPMAP */
297
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
298
(data = _cogl_bitmap_map (dst_bmp,
299
COGL_BUFFER_ACCESS_READ, 0)))
320
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
322
CoglError *ignore = NULL;
323
uint8_t *data = _cogl_bitmap_map (dst_bmp,
324
COGL_BUFFER_ACCESS_READ, 0,
301
327
CoglPixelFormat format = cogl_bitmap_get_format (dst_bmp);
302
329
tex_3d->first_pixel.gl_format = gl_format;
303
330
tex_3d->first_pixel.gl_type = gl_type;
304
memcpy (tex_3d->first_pixel.data, data,
305
_cogl_pixel_format_get_bytes_per_pixel (format));
307
_cogl_bitmap_unmap (dst_bmp);
310
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
312
ctx->texture_driver->upload_to_gl_3d (ctx,
315
FALSE, /* is_foreign */
334
memcpy (tex_3d->first_pixel.data, data,
335
_cogl_pixel_format_get_bytes_per_pixel (format));
336
_cogl_bitmap_unmap (dst_bmp);
340
g_warning ("Failed to read first pixel of bitmap for "
341
"glGenerateMipmap fallback");
342
cogl_error_free (ignore);
343
memset (tex_3d->first_pixel.data, 0,
344
_cogl_pixel_format_get_bytes_per_pixel (format));
349
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format);
351
if (!ctx->texture_driver->upload_to_gl_3d (ctx,
354
FALSE, /* is_foreign */
363
cogl_object_unref (dst_bmp);
364
cogl_object_unref (tex_3d);
323
368
tex_3d->gl_format = gl_intformat;
325
370
cogl_object_unref (dst_bmp);
327
return _cogl_texture_3d_object_new (tex_3d);
372
_cogl_texture_set_allocated (COGL_TEXTURE (tex_3d), TRUE);
374
421
bitmap = _cogl_bitmap_new_with_malloc_buffer (context,
379
429
bmp_data = _cogl_bitmap_map (bitmap,
380
430
COGL_BUFFER_ACCESS_WRITE,
381
COGL_BUFFER_MAP_HINT_DISCARD);
431
COGL_BUFFER_MAP_HINT_DISCARD,
383
434
if (bmp_data == NULL)
482
_cogl_texture_3d_set_filters (CoglTexture *tex,
533
_cogl_texture_3d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
486
537
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
487
538
CoglContext *ctx = tex->context;
489
if (min_filter == tex_3d->min_filter
490
&& mag_filter == tex_3d->mag_filter)
540
if (min_filter == tex_3d->gl_legacy_texobj_min_filter
541
&& mag_filter == tex_3d->gl_legacy_texobj_mag_filter)
493
544
/* Store new values */
494
tex_3d->min_filter = min_filter;
495
tex_3d->mag_filter = mag_filter;
545
tex_3d->gl_legacy_texobj_min_filter = min_filter;
546
tex_3d->gl_legacy_texobj_mag_filter = mag_filter;
497
548
/* Apply new filters to the texture */
498
549
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
512
563
if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
513
564
tex_3d->auto_mipmap && tex_3d->mipmaps_dirty)
515
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
518
566
/* glGenerateMipmap is defined in the FBO extension. If it's not
519
567
available we'll fallback to temporarily enabling
520
568
GL_GENERATE_MIPMAP and reuploading the first pixel */
521
569
if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
522
ctx->texture_driver->gl_generate_mipmaps (ctx, GL_TEXTURE_3D);
570
_cogl_texture_gl_generate_mipmaps (tex);
523
571
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
524
572
else if (ctx->driver != COGL_DRIVER_GLES2)
574
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
526
578
GE( ctx, glTexParameteri (GL_TEXTURE_3D,
527
579
GL_GENERATE_MIPMAP,
557
_cogl_texture_3d_set_region (CoglTexture *tex,
562
unsigned int dst_width,
563
unsigned int dst_height,
609
_cogl_texture_3d_set_region (CoglTexture *tex,
566
620
/* This function doesn't really make sense for 3D textures because
567
621
it can't specify which image to upload to */
622
_cogl_set_error (error,
624
COGL_SYSTEM_ERROR_UNSUPPORTED,
625
"Setting a 2D region on a 3D texture isn't "
626
"currently supported");
572
632
_cogl_texture_3d_get_data (CoglTexture *tex,
573
633
CoglPixelFormat format,
574
unsigned int rowstride,
577
637
/* FIXME: we could probably implement this by assuming the data is
594
654
return COGL_TEXTURE_3D (tex)->gl_format;
598
_cogl_texture_3d_get_width (CoglTexture *tex)
600
return COGL_TEXTURE_3D (tex)->width;
604
_cogl_texture_3d_get_height (CoglTexture *tex)
606
return COGL_TEXTURE_3D (tex)->height;
609
657
static CoglTextureType
610
658
_cogl_texture_3d_get_type (CoglTexture *tex)
616
664
cogl_texture_3d_vtable =
618
666
TRUE, /* primitive */
667
_cogl_texture_3d_allocate,
619
668
_cogl_texture_3d_set_region,
620
669
_cogl_texture_3d_get_data,
621
670
NULL, /* foreach_sub_texture_in_region */
625
674
_cogl_texture_3d_transform_coords_to_gl,
626
675
_cogl_texture_3d_transform_quad_coords_to_gl,
627
676
_cogl_texture_3d_get_gl_texture,
628
_cogl_texture_3d_set_filters,
677
_cogl_texture_3d_gl_flush_legacy_texobj_filters,
629
678
_cogl_texture_3d_pre_paint,
630
679
_cogl_texture_3d_ensure_non_quad_rendering,
631
_cogl_texture_3d_set_wrap_mode_parameters,
680
_cogl_texture_3d_gl_flush_legacy_texobj_wrap_modes,
632
681
_cogl_texture_3d_get_format,
633
682
_cogl_texture_3d_get_gl_format,
634
_cogl_texture_3d_get_width,
635
_cogl_texture_3d_get_height,
636
683
_cogl_texture_3d_get_type,
637
684
NULL, /* is_foreign */
638
685
_cogl_texture_3d_set_auto_mipmap