Merge branch 'master' into blender2.8
[blender.git] / source / blender / gpu / intern / gpu_texture.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_image_types.h"
31
32 #include "BLI_blenlib.h"
33 #include "BLI_utildefines.h"
34 #include "BLI_math_base.h"
35 #include "BLI_math_vector.h"
36
37 #include "BKE_global.h"
38
39 #include "GPU_debug.h"
40 #include "GPU_draw.h"
41 #include "GPU_extensions.h"
42 #include "GPU_framebuffer.h"
43 #include "GPU_glew.h"
44 #include "GPU_texture.h"
45
46 static struct GPUTextureGlobal {
47         GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
48         GPUTexture *invalid_tex_2D;
49         GPUTexture *invalid_tex_3D;
50 } GG = {NULL, NULL, NULL};
51
52 /* GPUTexture */
53
54 struct GPUTexture {
55         int w, h;           /* width/height */
56         int number;         /* number for multitexture binding */
57         int refcount;       /* reference count */
58         GLenum target;      /* GL_TEXTURE_* */
59         GLenum target_base; /* same as target, (but no multisample) */
60         GLuint bindcode;    /* opengl identifier for texture */
61         int fromblender;    /* we got the texture from Blender */
62
63         GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
64         int fb_attachment;  /* slot the texture is attached to */
65         int depth;          /* is a depth texture? if 3D how deep? */
66 };
67
68 static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
69 {
70         unsigned char *pixels, *p;
71         const float *fp = fpixels;
72         const int len = 4 * length;
73
74         p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
75
76         for (int a = 0; a < len; a++, p++, fp++)
77                 *p = FTOCHAR((*fp));
78
79         return pixels;
80 }
81
82 static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
83 {
84         void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
85
86         if (target == GL_TEXTURE_1D)
87                 glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
88         else
89                 glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
90         
91         MEM_freeN(pixels);
92 }
93
94 static GPUTexture *GPU_texture_create_nD(
95         int w, int h, int n, const float *fpixels, int depth,
96         GPUHDRType hdr_type, int components, int samples,
97         char err_out[256])
98 {
99         GLenum type, format, internalformat;
100         void *pixels = NULL;
101
102         if (samples) {
103                 CLAMP_MAX(samples, GPU_max_color_texture_samples());
104         }
105
106         GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
107         tex->w = w;
108         tex->h = h;
109         tex->number = -1;
110         tex->refcount = 1;
111         tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
112         tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
113         tex->depth = depth;
114         tex->fb_attachment = -1;
115
116         glGenTextures(1, &tex->bindcode);
117
118         if (!tex->bindcode) {
119                 if (err_out) {
120                         BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
121                                 (int)glGetError());
122                 }
123                 else {
124                         fprintf(stderr, "GPUTexture: texture create failed: %d\n",
125                                 (int)glGetError());
126                 }
127                 GPU_texture_free(tex);
128                 return NULL;
129         }
130
131         if (!GPU_full_non_power_of_two_support()) {
132                 tex->w = power_of_2_max_i(tex->w);
133                 tex->h = power_of_2_max_i(tex->h);
134         }
135
136         tex->number = 0;
137         glBindTexture(tex->target, tex->bindcode);
138
139         if (depth) {
140                 type = GL_UNSIGNED_BYTE;
141                 format = GL_DEPTH_COMPONENT;
142                 internalformat = GL_DEPTH_COMPONENT;
143         }
144         else {
145                 type = GL_FLOAT;
146
147                 if (components == 4) {
148                         format = GL_RGBA;
149                         switch (hdr_type) {
150                                 case GPU_HDR_NONE:
151                                         internalformat = GL_RGBA8;
152                                         break;
153                                 /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
154                                 case GPU_HDR_HALF_FLOAT:
155                                         internalformat = GL_RGBA16F_ARB;
156                                         break;
157                                 case GPU_HDR_FULL_FLOAT:
158                                         internalformat = GL_RGBA32F_ARB;
159                                         break;
160                                 default:
161                                         break;
162                         }
163                 }
164                 else if (components == 2) {
165                         /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
166                         format = GL_RG;
167                         switch (hdr_type) {
168                                 case GPU_HDR_NONE:
169                                         internalformat = GL_RG8;
170                                         break;
171                                 case GPU_HDR_HALF_FLOAT:
172                                         internalformat = GL_RG16F;
173                                         break;
174                                 case GPU_HDR_FULL_FLOAT:
175                                         internalformat = GL_RG32F;
176                                         break;
177                                 default:
178                                         break;
179                         }
180                 }
181
182                 if (fpixels && hdr_type == GPU_HDR_NONE) {
183                         type = GL_UNSIGNED_BYTE;
184                         pixels = GPU_texture_convert_pixels(w * h, fpixels);
185                 }
186         }
187
188         if (tex->target == GL_TEXTURE_1D) {
189                 glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
190
191                 if (fpixels) {
192                         glTexSubImage1D(tex->target, 0, 0, w, format, type,
193                                 pixels ? pixels : fpixels);
194
195                         if (tex->w > w) {
196                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
197                         }
198                 }
199         }
200         else {
201                 if (samples) {
202                         glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
203                 }
204                 else {
205                         glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
206                                      format, type, NULL);
207                 }
208
209                 if (fpixels) {
210                         glTexSubImage2D(tex->target, 0, 0, 0, w, h,
211                                 format, type, pixels ? pixels : fpixels);
212
213                         if (tex->w > w)
214                                 GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
215                         if (tex->h > h)
216                                 GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
217                 }
218         }
219
220         if (pixels)
221                 MEM_freeN(pixels);
222
223         if (depth) {
224                 glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
225                 glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
226                 glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
227                 glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
228                 glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
229         }
230         else {
231                 glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
232                 glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
233         }
234
235         if (tex->target_base != GL_TEXTURE_1D) {
236                 glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237                 glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
238         }
239         else
240                 glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
241
242         return tex;
243 }
244
245
246 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
247 {
248         GLenum type, format, internalformat;
249         void *pixels = NULL;
250
251         GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
252         tex->w = w;
253         tex->h = h;
254         tex->depth = depth;
255         tex->number = -1;
256         tex->refcount = 1;
257         tex->target = GL_TEXTURE_3D;
258         tex->target_base = GL_TEXTURE_3D;
259
260         glGenTextures(1, &tex->bindcode);
261
262         if (!tex->bindcode) {
263                 fprintf(stderr, "GPUTexture: texture create failed: %d\n",
264                         (int)glGetError());
265                 GPU_texture_free(tex);
266                 return NULL;
267         }
268
269         tex->number = 0;
270         glBindTexture(tex->target, tex->bindcode);
271
272         GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
273
274         type = GL_FLOAT;
275         if (channels == 4) {
276                 format = GL_RGBA;
277                 internalformat = GL_RGBA8;
278         }
279         else {
280                 format = GL_RED;
281                 internalformat = GL_INTENSITY8;
282         }
283
284         /* 3D textures are quite heavy, test if it's possible to create them first */
285         glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
286
287         bool rescale = false;
288         int r_width;
289
290         glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
291
292         while (r_width == 0) {
293                 rescale = true;
294                 tex->w /= 2;
295                 tex->h /= 2;
296                 tex->depth /= 2;
297                 glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
298                 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
299         }
300
301         /* really unlikely to happen but keep this just in case */
302         tex->w = max_ii(tex->w, 1);
303         tex->h = max_ii(tex->h, 1);
304         tex->depth = max_ii(tex->depth, 1);
305
306 #if 0
307         if (fpixels)
308                 pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
309 #endif
310
311         GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
312
313         /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
314          * for gooseberry */
315         if (rescale && fpixels) {
316                 /* FIXME: should these be floating point? */
317                 const unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
318                 float *tex3d = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->depth, "tex3d");
319
320                 GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
321
322                 for (unsigned k = 0; k < tex->depth; k++) {
323                         for (unsigned j = 0; j < tex->h; j++) {
324                                 for (unsigned i = 0; i < tex->w; i++) {
325                                         /* obviously doing nearest filtering here,
326                                          * it's going to be slow in any case, let's not make it worse */
327                                         float xb = i * xf;
328                                         float yb = j * yf;
329                                         float zb = k * zf;
330                                         unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
331                                         unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
332
333                                         if (channels == 4) {
334                                                 tex3d[offset * 4] = fpixels[offset_orig * 4];
335                                                 tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
336                                                 tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
337                                                 tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
338                                         }
339                                         else
340                                                 tex3d[offset] = fpixels[offset_orig];
341                                 }
342                         }
343                 }
344
345                 glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
346
347                 MEM_freeN(tex3d);
348         }
349         else {
350                 if (fpixels) {
351                         glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
352                         GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
353                 }
354         }
355
356
357         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
358         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
359         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
360         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
361         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
362
363         if (pixels)
364                 MEM_freeN(pixels);
365
366         GPU_texture_unbind(tex);
367
368         return tex;
369 }
370
371 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double time, int mipmap)
372 {
373         int gputt;
374         /* this binds a texture, so that's why to restore it to 0 */
375         GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, 0, mipmap, is_data);
376         GPU_update_image_time(ima, time);
377
378         if (textarget == GL_TEXTURE_2D)
379                 gputt = TEXTARGET_TEXTURE_2D;
380         else
381                 gputt = TEXTARGET_TEXTURE_CUBE_MAP;
382
383         if (ima->gputexture[gputt]) {
384                 ima->gputexture[gputt]->bindcode = bindcode;
385                 glBindTexture(textarget, 0);
386                 return ima->gputexture[gputt];
387         }
388
389         GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
390         tex->bindcode = bindcode;
391         tex->number = -1;
392         tex->refcount = 1;
393         tex->target = textarget;
394         tex->target_base = GL_TEXTURE_2D;
395         tex->fromblender = 1;
396
397         ima->gputexture[gputt] = tex;
398
399         if (!glIsTexture(tex->bindcode)) {
400                 GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
401         }
402         else {
403                 GLint w, h, border;
404
405                 GLenum gettarget;
406
407                 if (textarget == GL_TEXTURE_2D)
408                         gettarget = GL_TEXTURE_2D;
409                 else
410                         gettarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
411
412                 glBindTexture(textarget, tex->bindcode);
413                 glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w);
414                 glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h);
415                 glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_BORDER, &border);
416
417                 tex->w = w - border;
418                 tex->h = h - border;
419         }
420
421         glBindTexture(textarget, 0);
422
423         return tex;
424 }
425
426 GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
427 {
428         GPUTexture *tex = prv->gputexture[0];
429         GLuint bindcode = 0;
430         
431         if (tex)
432                 bindcode = tex->bindcode;
433         
434         /* this binds a texture, so that's why we restore it to 0 */
435         if (bindcode == 0) {
436                 GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL);
437         }
438         if (tex) {
439                 tex->bindcode = bindcode;
440                 glBindTexture(GL_TEXTURE_2D, 0);
441                 return tex;
442         }
443
444         tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
445         tex->bindcode = bindcode;
446         tex->number = -1;
447         tex->refcount = 1;
448         tex->target = GL_TEXTURE_2D;
449         tex->target_base = GL_TEXTURE_2D;
450         
451         prv->gputexture[0] = tex;
452         
453         if (!glIsTexture(tex->bindcode)) {
454                 GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
455         }
456         else {
457                 GLint w, h;
458
459                 glBindTexture(GL_TEXTURE_2D, tex->bindcode);
460                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
461                 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
462                 
463                 tex->w = w;
464                 tex->h = h;
465         }
466         
467         glBindTexture(GL_TEXTURE_2D, 0);
468         
469         return tex;
470
471 }
472
473 GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
474 {
475         GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
476
477         if (tex)
478                 GPU_texture_unbind(tex);
479         
480         return tex;
481 }
482
483 GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
484 {
485         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
486
487         if (tex)
488                 GPU_texture_unbind(tex);
489         
490         return tex;
491 }
492 GPUTexture *GPU_texture_create_2D_multisample(
493         int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
494 {
495         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
496
497         if (tex)
498                 GPU_texture_unbind(tex);
499
500         return tex;
501 }
502
503 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
504 {
505         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
506
507         if (tex)
508                 GPU_texture_unbind(tex);
509         
510         return tex;
511 }
512 GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
513 {
514         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
515
516         if (tex)
517                 GPU_texture_unbind(tex);
518
519         return tex;
520 }
521
522 /**
523  * A shadow map for VSM needs two components (depth and depth^2)
524  */
525 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
526 {
527         GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
528
529         if (tex) {
530                 /* Now we tweak some of the settings */
531                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
532                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
533
534                 GPU_texture_unbind(tex);
535         }
536
537         return tex;
538 }
539
540 GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
541 {
542         GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
543
544         if (tex) {
545                 /* Now we tweak some of the settings */
546                 if (repeat) {
547                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
548                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
549                 }
550                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
551                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
552
553                 GPU_texture_unbind(tex);
554         }
555
556         return tex;
557 }
558
559 GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
560 {
561         GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
562
563         if (tex) {
564                 /* Now we tweak some of the settings */
565                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
566                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
567                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
568
569                 GPU_texture_unbind(tex);
570         }
571
572         return tex;
573 }
574
575 void GPU_invalid_tex_init(void)
576 {
577         const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
578         GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
579         GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
580         GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
581 }
582
583 void GPU_invalid_tex_bind(int mode)
584 {
585         switch (mode) {
586                 case GL_TEXTURE_1D:
587                         glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
588                         break;
589                 case GL_TEXTURE_2D:
590                         glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
591                         break;
592                 case GL_TEXTURE_3D:
593                         glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
594                         break;
595         }
596 }
597
598 void GPU_invalid_tex_free(void)
599 {
600         if (GG.invalid_tex_1D)
601                 GPU_texture_free(GG.invalid_tex_1D);
602         if (GG.invalid_tex_2D)
603                 GPU_texture_free(GG.invalid_tex_2D);
604         if (GG.invalid_tex_3D)
605                 GPU_texture_free(GG.invalid_tex_3D);
606 }
607
608
609 void GPU_texture_bind(GPUTexture *tex, int number)
610 {
611         if (number >= GPU_max_textures()) {
612                 fprintf(stderr, "Not enough texture slots.\n");
613                 return;
614         }
615
616         if ((G.debug & G_DEBUG)) {
617                 if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
618                         fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
619                 }
620         }
621
622         if (number < 0)
623                 return;
624
625         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
626
627         GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
628         if (number != 0) glActiveTexture(arbnumber);
629         if (tex->bindcode != 0) {
630                 glBindTexture(tex->target, tex->bindcode);
631         }
632         else
633                 GPU_invalid_tex_bind(tex->target);
634         glEnable(tex->target);
635         if (number != 0) glActiveTexture(GL_TEXTURE0);
636
637         tex->number = number;
638
639         GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
640 }
641
642 void GPU_texture_unbind(GPUTexture *tex)
643 {
644         if (tex->number >= GPU_max_textures()) {
645                 fprintf(stderr, "Not enough texture slots.\n");
646                 return;
647         }
648
649         if (tex->number == -1)
650                 return;
651         
652         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
653
654         GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
655         if (tex->number != 0) glActiveTexture(arbnumber);
656         glBindTexture(tex->target, 0);
657         glDisable(tex->target);
658         glBindTexture(tex->target_base, 0);
659         glDisable(tex->target_base);
660         if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
661
662         tex->number = -1;
663
664         GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
665 }
666
667 int GPU_texture_bound_number(GPUTexture *tex)
668 {
669         return tex->number;
670 }
671
672 void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
673 {
674         if (tex->number >= GPU_max_textures()) {
675                 fprintf(stderr, "Not enough texture slots.\n");
676                 return;
677         }
678
679         if (tex->number == -1)
680                 return;
681
682         GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
683
684         GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
685         if (tex->number != 0) glActiveTexture(arbnumber);
686
687         if (tex->depth) {
688                 if (compare)
689                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
690                 else
691                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
692         }
693
694         if (use_filter) {
695                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
696                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
697         }
698         else {
699                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
700                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
701         }
702         if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
703
704         GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
705 }
706
707 void GPU_texture_free(GPUTexture *tex)
708 {
709         tex->refcount--;
710
711         if (tex->refcount < 0)
712                 fprintf(stderr, "GPUTexture: negative refcount\n");
713         
714         if (tex->refcount == 0) {
715                 if (tex->fb)
716                         GPU_framebuffer_texture_detach(tex);
717                 if (tex->bindcode && !tex->fromblender)
718                         glDeleteTextures(1, &tex->bindcode);
719
720                 MEM_freeN(tex);
721         }
722 }
723
724 void GPU_texture_ref(GPUTexture *tex)
725 {
726         tex->refcount++;
727 }
728
729 int GPU_texture_target(const GPUTexture *tex)
730 {
731         return tex->target;
732 }
733
734 int GPU_texture_width(const GPUTexture *tex)
735 {
736         return tex->w;
737 }
738
739 int GPU_texture_height(const GPUTexture *tex)
740 {
741         return tex->h;
742 }
743
744 int GPU_texture_depth(const GPUTexture *tex)
745 {
746         return tex->depth;
747 }
748
749 int GPU_texture_opengl_bindcode(const GPUTexture *tex)
750 {
751         return tex->bindcode;
752 }
753
754 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
755 {
756         return tex->fb;
757 }
758
759 int GPU_texture_framebuffer_attachment(GPUTexture *tex)
760 {
761         return tex->fb_attachment;
762 }
763
764 void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
765 {
766         tex->fb = fb;
767         tex->fb_attachment = attachment;
768 }
769