Merge branch 'blender2.7'
[blender.git] / source / blender / gpu / intern / gpu_framebuffer.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 "BLI_blenlib.h"
31 #include "BLI_threads.h"
32 #include "BLI_utildefines.h"
33 #include "BLI_math_base.h"
34
35 #include "BKE_global.h"
36
37 #include "GPU_batch.h"
38 #include "GPU_draw.h"
39 #include "GPU_extensions.h"
40 #include "GPU_framebuffer.h"
41 #include "GPU_matrix.h"
42 #include "GPU_shader.h"
43 #include "GPU_texture.h"
44
45 #include "gpu_private.h"
46 #include "gpu_context_private.h"
47
48 typedef enum {
49         GPU_FB_DEPTH_ATTACHMENT = 0,
50         GPU_FB_DEPTH_STENCIL_ATTACHMENT,
51         GPU_FB_COLOR_ATTACHMENT0,
52         GPU_FB_COLOR_ATTACHMENT1,
53         GPU_FB_COLOR_ATTACHMENT2,
54         GPU_FB_COLOR_ATTACHMENT3,
55         GPU_FB_COLOR_ATTACHMENT4,
56         /* Number of maximum output slots.
57          * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */
58         /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
59          * the maximum number of COLOR attachments specified by glDrawBuffers. */
60         GPU_FB_MAX_ATTACHEMENT
61 } GPUAttachmentType;
62
63 #define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0)
64
65 #define GPU_FB_DIRTY_DRAWBUFFER (1 << 15)
66
67 #define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0)
68 #define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
69
70 struct GPUFrameBuffer {
71         GPUContext *ctx;
72         GLuint object;
73         GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
74         uint16_t dirty_flag;
75         int width, height;
76         bool multisample;
77         /* TODO Check that we always use the right context when binding
78          * (FBOs are not shared across ogl contexts). */
79         // void *ctx;
80 };
81
82 static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
83 {
84         static const GLenum table[] = {
85                 [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
86                 [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
87                 [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
88                 [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
89                 [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
90                 [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
91                 [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4
92         };
93         return table[type];
94 }
95
96 static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot)
97 {
98         switch (GPU_texture_format(tex)) {
99                 case GPU_DEPTH_COMPONENT32F:
100                 case GPU_DEPTH_COMPONENT24:
101                 case GPU_DEPTH_COMPONENT16:
102                         return GPU_FB_DEPTH_ATTACHMENT;
103                 case GPU_DEPTH24_STENCIL8:
104                 case GPU_DEPTH32F_STENCIL8:
105                         return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
106                 default:
107                         return GPU_FB_COLOR_ATTACHMENT0 + slot;
108         }
109 }
110
111 static GLenum convert_buffer_bits_to_gl(GPUFrameBufferBits bits)
112 {
113         GLbitfield mask = 0;
114         mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0;
115         mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0;
116         mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0;
117         return mask;
118 }
119
120 static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb)
121 {
122         if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
123                 return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
124         else
125                 return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;
126 }
127
128 static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot)
129 {
130         return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
131 }
132
133 static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
134 {
135         const char *format = "GPUFrameBuffer: framebuffer status %s\n";
136         const char *err = "unknown";
137
138 #define format_status(X) \
139         case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \
140                 break;
141
142         switch (status) {
143                 /* success */
144                 format_status(COMPLETE)
145                 /* errors shared by OpenGL desktop & ES */
146                 format_status(INCOMPLETE_ATTACHMENT)
147                 format_status(INCOMPLETE_MISSING_ATTACHMENT)
148                 format_status(UNSUPPORTED)
149 #if 0 /* for OpenGL ES only */
150                 format_status(INCOMPLETE_DIMENSIONS)
151 #else /* for desktop GL only */
152                 format_status(INCOMPLETE_DRAW_BUFFER)
153                 format_status(INCOMPLETE_READ_BUFFER)
154                 format_status(INCOMPLETE_MULTISAMPLE)
155                 format_status(UNDEFINED)
156 #endif
157         }
158
159 #undef format_status
160
161         if (err_out) {
162                 BLI_snprintf(err_out, 256, format, err);
163         }
164         else {
165                 fprintf(stderr, format, err);
166         }
167 }
168
169 void gpu_framebuffer_module_init(void)
170 {
171 }
172
173 void gpu_framebuffer_module_exit(void)
174 {
175 }
176
177 GPUFrameBuffer *GPU_framebuffer_active_get(void)
178 {
179         GPUContext *ctx = GPU_context_active_get();
180         if (ctx) {
181                 return gpu_context_active_framebuffer_get(ctx);
182         }
183         else {
184                 return 0;
185         }
186 }
187
188 static void gpu_framebuffer_current_set(GPUFrameBuffer *fb)
189 {
190         GPUContext *ctx = GPU_context_active_get();
191         if (ctx) {
192                 gpu_context_active_framebuffer_set(ctx, fb);
193         }
194 }
195
196 /* GPUFrameBuffer */
197
198 GPUFrameBuffer *GPU_framebuffer_create(void)
199 {
200         /* We generate the FB object later at first use in order to
201          * create the framebuffer in the right opengl context. */
202         return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
203 }
204
205 static void gpu_framebuffer_init(GPUFrameBuffer *fb)
206 {
207         fb->object = GPU_fbo_alloc();
208         fb->ctx = GPU_context_active_get();
209         gpu_context_add_framebuffer(fb->ctx, fb);
210 }
211
212 void GPU_framebuffer_free(GPUFrameBuffer *fb)
213 {
214         for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
215                 if (fb->attachments[type].tex != NULL) {
216                         GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex);
217                 }
218         }
219
220         if (fb->object != 0) {
221                 /* This restores the framebuffer if it was bound */
222                 GPU_fbo_free(fb->object, fb->ctx);
223                 gpu_context_remove_framebuffer(fb->ctx, fb);
224         }
225
226         if (GPU_framebuffer_active_get() == fb) {
227                 gpu_framebuffer_current_set(NULL);
228         }
229
230         MEM_freeN(fb);
231 }
232
233 /* ---------- Attach ----------- */
234
235 static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
236 {
237         if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
238                 fprintf(stderr,
239                         "Attaching to index %d framebuffer slot unsupported. "
240                         "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT);
241                 return;
242         }
243
244         GPUAttachmentType type = attachment_type_from_tex(tex, slot);
245         GPUAttachment *attachment = &fb->attachments[type];
246
247         if ((attachment->tex == tex) &&
248             (attachment->mip == mip) &&
249             (attachment->layer == layer))
250         {
251                 return; /* Exact same texture already bound here. */
252         }
253         else if (attachment->tex != NULL) {
254                 GPU_framebuffer_texture_detach(fb, attachment->tex);
255         }
256
257         if (attachment->tex == NULL) {
258                 GPU_texture_attach_framebuffer(tex, fb, type);
259         }
260
261         attachment->tex = tex;
262         attachment->mip = mip;
263         attachment->layer = layer;
264         GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
265 }
266
267 void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
268 {
269         gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip);
270 }
271
272 void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
273 {
274         /* NOTE: We could support 1D ARRAY texture. */
275         BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY);
276         gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip);
277 }
278
279 void GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
280 {
281         BLI_assert(GPU_texture_cube(tex));
282         gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip);
283 }
284
285 /* ---------- Detach ----------- */
286
287 void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type)
288 {
289         GPUAttachment *attachment = &fb->attachments[type];
290
291         if (attachment->tex != tex) {
292                 fprintf(stderr,
293                         "Warning, attempting to detach Texture %p from framebuffer %p "
294                         "but texture is not attached.\n", tex, fb);
295                 return;
296         }
297
298         attachment->tex = NULL;
299         GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
300 }
301
302 void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
303 {
304         GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
305         GPU_framebuffer_texture_detach_slot(fb, tex, type);
306 }
307
308 /* ---------- Config (Attach & Detach) ----------- */
309
310 /**
311  * First GPUAttachment in *config is always the depth/depth_stencil buffer.
312  * Following GPUAttachments are color buffers.
313  * Setting GPUAttachment.mip to -1 will leave the texture in this slot.
314  * Setting GPUAttachment.tex to NULL will detach the texture in this slot.
315  **/
316 void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_len)
317 {
318         if (config[0].tex) {
319                 BLI_assert(GPU_texture_depth(config[0].tex));
320                 gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip);
321         }
322         else if (config[0].mip == -1) {
323                 /* Leave texture attached */
324         }
325         else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) {
326                 GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex);
327         }
328         else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
329                 GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
330         }
331
332         int slot = 0;
333         for (int i = 1; i < config_len; ++i, ++slot) {
334                 if (config[i].tex != NULL) {
335                         BLI_assert(GPU_texture_depth(config[i].tex) == false);
336                         gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip);
337                 }
338                 else if (config[i].mip != -1) {
339                         GPUTexture *tex = framebuffer_get_color_tex(fb, slot);
340                         if (tex != NULL) {
341                                 GPU_framebuffer_texture_detach(fb, tex);
342                         }
343                 }
344         }
345 }
346
347 /* ---------- Bind / Restore ----------- */
348
349 static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type)
350 {
351         int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
352         GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
353
354         if (attach->layer > -1) {
355                 if (GPU_texture_cube(attach->tex)) {
356                         glFramebufferTexture2D(
357                                 GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
358                                 tex_bind, attach->mip);
359                 }
360                 else {
361                         glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
362                 }
363         }
364         else {
365                 glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
366         }
367 }
368
369 static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type)
370 {
371         GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
372         glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
373 }
374
375 static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
376 {
377         GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
378         int numslots = 0;
379
380         BLI_assert(GPU_framebuffer_active_get() == fb);
381
382         /* Update attachments */
383         for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
384
385                 if (type >= GPU_FB_COLOR_ATTACHMENT0) {
386                         if (fb->attachments[type].tex) {
387                                 gl_attachments[numslots] = convert_attachment_type_to_gl(type);
388                         }
389                         else {
390                                 gl_attachments[numslots] = GL_NONE;
391                         }
392                         numslots++;
393                 }
394
395                 if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
396                         continue;
397                 }
398                 else if (fb->attachments[type].tex != NULL) {
399                         gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
400
401                         fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
402                         fb->width = GPU_texture_width(fb->attachments[type].tex);
403                         fb->height = GPU_texture_height(fb->attachments[type].tex);
404                 }
405                 else {
406                         gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
407                 }
408         }
409         fb->dirty_flag = 0;
410
411         /* Update draw buffers (color targets)
412          * This state is saved in the FBO */
413         if (numslots)
414                 glDrawBuffers(numslots, gl_attachments);
415         else
416                 glDrawBuffer(GL_NONE);
417 }
418
419 /**
420  * Hack to solve the problem of some bugged AMD GPUs (see `GPU_unused_fb_slot_workaround`).
421  * If there is an empty color slot between the color slots,
422  * all textures after this slot are apparently skipped/discarded.
423  **/
424 static void gpu_framebuffer_update_attachments_and_fill_empty_slots(GPUFrameBuffer *fb)
425 {
426         GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
427         int dummy_tex = 0;
428
429         BLI_assert(GPU_framebuffer_active_get() == fb);
430
431         /* Update attachments */
432         for (GPUAttachmentType type = GPU_FB_MAX_ATTACHEMENT; type--;) {
433                 GPUTexture *tex = fb->attachments[type].tex;
434
435                 if (type >= GPU_FB_COLOR_ATTACHMENT0) {
436                         int slot = type - GPU_FB_COLOR_ATTACHMENT0;
437                         if (tex != NULL || (dummy_tex != 0)) {
438                                 gl_attachments[slot] = convert_attachment_type_to_gl(type);
439
440                                 if (dummy_tex == 0) {
441                                         dummy_tex = GPU_texture_opengl_bindcode(tex);
442                                 }
443                         }
444                         else {
445                                 gl_attachments[slot] = GL_NONE;
446                         }
447                 }
448                 else {
449                         dummy_tex = 0;
450                 }
451
452                 if ((dummy_tex != 0) && tex == NULL) {
453                         /* Fill empty slot */
454                         glFramebufferTexture(GL_FRAMEBUFFER, convert_attachment_type_to_gl(type), dummy_tex, 0);
455                 }
456                 else if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type)) {
457                         if (tex != NULL) {
458                                 gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
459
460                                 fb->multisample = (GPU_texture_samples(tex) > 0);
461                                 fb->width = GPU_texture_width(tex);
462                                 fb->height = GPU_texture_height(tex);
463                         }
464                         else {
465                                 gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
466                         }
467                 }
468         }
469         fb->dirty_flag = 0;
470
471         /* Update draw buffers (color targets)
472          * This state is saved in the FBO */
473         glDrawBuffers(GPU_FB_MAX_COLOR_ATTACHMENT, gl_attachments);
474 }
475
476
477 #define FRAMEBUFFER_STACK_DEPTH 16
478
479 static struct {
480         GPUFrameBuffer *framebuffers[FRAMEBUFFER_STACK_DEPTH];
481         uint top;
482 } FrameBufferStack = {{0}};
483
484 static void gpuPushFrameBuffer(GPUFrameBuffer *fbo)
485 {
486         BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH);
487         FrameBufferStack.framebuffers[FrameBufferStack.top] = fbo;
488         FrameBufferStack.top++;
489 }
490
491 static GPUFrameBuffer *gpuPopFrameBuffer(void)
492 {
493         BLI_assert(FrameBufferStack.top > 0);
494         FrameBufferStack.top--;
495         return FrameBufferStack.framebuffers[FrameBufferStack.top];
496 }
497
498 #undef FRAMEBUFFER_STACK_DEPTH
499
500
501 void GPU_framebuffer_bind(GPUFrameBuffer *fb)
502 {
503         if (fb->object == 0)
504                 gpu_framebuffer_init(fb);
505
506         if (GPU_framebuffer_active_get() != fb)
507                 glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
508
509         gpu_framebuffer_current_set(fb);
510
511         if (fb->dirty_flag != 0) {
512                 if (GPU_unused_fb_slot_workaround()) {
513                         /* XXX: Please AMD, fix this. */
514                         gpu_framebuffer_update_attachments_and_fill_empty_slots(fb);
515                 }
516                 else {
517                         gpu_framebuffer_update_attachments(fb);
518                 }
519         }
520
521         /* TODO manually check for errors? */
522 #if 0
523         char err_out[256];
524         if (!GPU_framebuffer_check_valid(fb, err_out)) {
525                 printf("Invalid %s\n", err_out);
526         }
527 #endif
528
529         if (fb->multisample)
530                 glEnable(GL_MULTISAMPLE);
531
532         glViewport(0, 0, fb->width, fb->height);
533 }
534
535 void GPU_framebuffer_restore(void)
536 {
537         if (GPU_framebuffer_active_get() != NULL) {
538                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
539                 gpu_framebuffer_current_set(NULL);
540         }
541 }
542
543 bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
544 {
545         return (fb == GPU_framebuffer_active_get()) && (fb->object != 0);
546 }
547
548 bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
549 {
550         if (!GPU_framebuffer_bound(fb))
551                 GPU_framebuffer_bind(fb);
552
553         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
554
555         if (status != GL_FRAMEBUFFER_COMPLETE) {
556                 GPU_framebuffer_restore();
557                 gpu_print_framebuffer_error(status, err_out);
558                 return false;
559         }
560
561         return true;
562 }
563
564 /* ---------- Framebuffer Operations ----------- */
565
566 #define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \
567         BLI_assert(GPU_framebuffer_bound(_fb)); \
568         UNUSED_VARS_NDEBUG(_fb);
569
570 /* Needs to be done after binding. */
571 void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h)
572 {
573         CHECK_FRAMEBUFFER_IS_BOUND(fb);
574
575         glViewport(x, y, w, h);
576 }
577
578 void GPU_framebuffer_clear(
579         GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
580         const float clear_col[4], float clear_depth, uint clear_stencil)
581 {
582         CHECK_FRAMEBUFFER_IS_BOUND(fb);
583
584         if (buffers & GPU_COLOR_BIT) {
585                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
586                 glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
587         }
588         if (buffers & GPU_DEPTH_BIT) {
589                 glDepthMask(GL_TRUE);
590                 glClearDepth(clear_depth);
591         }
592         if (buffers & GPU_STENCIL_BIT) {
593                 glStencilMask(0xFF);
594                 glClearStencil(clear_stencil);
595         }
596
597         GLbitfield mask = convert_buffer_bits_to_gl(buffers);
598         glClear(mask);
599 }
600
601 void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
602 {
603         CHECK_FRAMEBUFFER_IS_BOUND(fb);
604
605         GLenum type = GL_DEPTH_COMPONENT;
606         glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
607         glReadPixels(x, y, w, h, type, GL_FLOAT, data);
608 }
609
610 void GPU_framebuffer_read_color(
611         GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
612 {
613         CHECK_FRAMEBUFFER_IS_BOUND(fb);
614
615         GLenum type;
616         switch (channels) {
617                 case 1: type = GL_RED; break;
618                 case 2: type = GL_RG; break;
619                 case 3: type = GL_RGB; break;
620                 case 4: type = GL_RGBA; break;
621                 default:
622                         BLI_assert(false && "wrong number of read channels");
623                         return;
624         }
625         glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
626         glReadPixels(x, y, w, h, type, GL_FLOAT, data);
627 }
628
629 /* read_slot and write_slot are only used for color buffers. */
630 void GPU_framebuffer_blit(
631         GPUFrameBuffer *fb_read, int read_slot,
632         GPUFrameBuffer *fb_write, int write_slot,
633         GPUFrameBufferBits blit_buffers)
634 {
635         BLI_assert(blit_buffers != 0);
636
637         GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
638
639         /* Framebuffers must be up to date. This simplify this function. */
640         if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
641                 GPU_framebuffer_bind(fb_read);
642         }
643         if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
644                 GPU_framebuffer_bind(fb_write);
645         }
646
647         const bool do_color = (blit_buffers & GPU_COLOR_BIT);
648         const bool do_depth = (blit_buffers & GPU_DEPTH_BIT);
649         const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT);
650
651         GPUTexture *read_tex = (
652                 (do_depth || do_stencil) ?
653                 framebuffer_get_depth_tex(fb_read) :
654                 framebuffer_get_color_tex(fb_read, read_slot));
655         GPUTexture *write_tex = (
656                 (do_depth || do_stencil) ?
657                 framebuffer_get_depth_tex(fb_write) :
658                 framebuffer_get_color_tex(fb_write, read_slot));
659
660         if (do_depth) {
661                 BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
662                 BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
663         }
664         if (do_stencil) {
665                 BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
666                 BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
667         }
668         if (GPU_texture_samples(write_tex) != 0 ||
669             GPU_texture_samples(read_tex) != 0)
670         {
671                 /* Can only blit multisample textures to another texture of the same size. */
672                 BLI_assert((fb_read->width == fb_write->width) &&
673                            (fb_read->height == fb_write->height));
674         }
675
676         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
677         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
678
679         if (do_color) {
680                 glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
681                 glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
682                 /* XXX we messed with the glDrawBuffer, this will reset the
683                  * glDrawBuffers the next time we bind fb_write. */
684                 fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
685         }
686
687         GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
688
689         glBlitFramebuffer(
690                 0, 0, fb_read->width, fb_read->height,
691                 0, 0, fb_write->width, fb_write->height,
692                 mask, GL_NEAREST);
693
694         /* Restore previous framebuffer */
695         if (fb_write == prev_fb) {
696                 GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
697         }
698         else if (prev_fb) {
699                 glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object);
700                 gpu_framebuffer_current_set(prev_fb);
701         }
702         else {
703                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
704                 gpu_framebuffer_current_set(NULL);
705         }
706 }
707
708 /**
709  * Use this if you need to custom downsample your texture and use the previous mip level as input.
710  * This function only takes care of the correct texture handling. It execute the callback for each texture level.
711  **/
712 void GPU_framebuffer_recursive_downsample(
713         GPUFrameBuffer *fb, int max_lvl,
714         void (*callback)(void *userData, int level), void *userData)
715 {
716         /* Framebuffer must be up to date and bound. This simplify this function. */
717         if (GPU_framebuffer_active_get() != fb || fb->dirty_flag != 0 || fb->object == 0) {
718                 GPU_framebuffer_bind(fb);
719         }
720         /* HACK: We make the framebuffer appear not bound in order to
721          * not trigger any error in GPU_texture_bind().  */
722         GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
723         gpu_framebuffer_current_set(NULL);
724
725         int levels = floor(log2(max_ii(fb->width, fb->height)));
726         max_lvl = min_ii(max_lvl, levels);
727
728         int i;
729         int current_dim[2] = {fb->width, fb->height};
730         for (i = 1; i < max_lvl + 1; i++) {
731                 /* calculate next viewport size */
732                 current_dim[0] = max_ii(current_dim[0] / 2, 1);
733                 current_dim[1] = max_ii(current_dim[1] / 2, 1);
734
735                 for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
736                         if (fb->attachments[type].tex != NULL) {
737                                 /* Some Intel HDXXX have issue with rendering to a mipmap that is below
738                                  * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case
739                                  * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */
740                                 int next_lvl = (GPU_mip_render_workaround()) ? i : i - 1;
741                                 /* bind next level for rendering but first restrict fetches only to previous level */
742                                 GPUTexture *tex = fb->attachments[type].tex;
743                                 GPU_texture_bind(tex, 0);
744                                 glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
745                                 glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, next_lvl);
746                                 GPU_texture_unbind(tex);
747                                 /* copy attachment and replace miplevel. */
748                                 GPUAttachment attachment = fb->attachments[type];
749                                 attachment.mip = i;
750                                 gpu_framebuffer_attachment_attach(&attachment, type);
751                         }
752                 }
753
754                 BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
755
756                 glViewport(0, 0, current_dim[0], current_dim[1]);
757                 callback(userData, i);
758
759                 if (current_dim[0] == 1 && current_dim[1] == 1)
760                         break;
761         }
762
763         for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
764                 if (fb->attachments[type].tex != NULL) {
765                         /* reset mipmap level range */
766                         GPUTexture *tex = fb->attachments[type].tex;
767                         GPU_texture_bind(tex, 0);
768                         glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
769                         glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
770                         GPU_texture_unbind(tex);
771                         /* Reattach original level */
772                         /* NOTE: This is not necessary but this makes the FBO config
773                          *       remain in sync with the GPUFrameBuffer config. */
774                         gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
775                 }
776         }
777
778         gpu_framebuffer_current_set(prev_fb);
779 }
780
781 /* GPUOffScreen */
782
783 struct GPUOffScreen {
784         GPUFrameBuffer *fb;
785         GPUTexture *color;
786         GPUTexture *depth;
787 };
788
789 GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
790 {
791         GPUOffScreen *ofs;
792
793         ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
794
795         ofs->color = GPU_texture_create_2D_multisample(
796                 width, height,
797                 (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
798
799         if (depth) {
800                 ofs->depth = GPU_texture_create_2D_multisample(width, height, GPU_DEPTH24_STENCIL8, NULL, samples, err_out);
801         }
802
803         if ((depth && !ofs->depth) || !ofs->color) {
804                 GPU_offscreen_free(ofs);
805                 return NULL;
806         }
807
808         gpuPushAttrib(GPU_VIEWPORT_BIT);
809
810         GPU_framebuffer_ensure_config(&ofs->fb, {
811                 GPU_ATTACHMENT_TEXTURE(ofs->depth),
812                 GPU_ATTACHMENT_TEXTURE(ofs->color)
813         });
814
815         /* check validity at the very end! */
816         if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
817                 GPU_offscreen_free(ofs);
818                 gpuPopAttrib();
819                 return NULL;
820         }
821
822         GPU_framebuffer_restore();
823
824         gpuPopAttrib();
825
826         return ofs;
827 }
828
829 void GPU_offscreen_free(GPUOffScreen *ofs)
830 {
831         if (ofs->fb)
832                 GPU_framebuffer_free(ofs->fb);
833         if (ofs->color)
834                 GPU_texture_free(ofs->color);
835         if (ofs->depth)
836                 GPU_texture_free(ofs->depth);
837
838         MEM_freeN(ofs);
839 }
840
841 void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
842 {
843         if (save) {
844                 gpuPushAttrib(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
845                 GPUFrameBuffer *fb = GPU_framebuffer_active_get();
846                 gpuPushFrameBuffer(fb);
847         }
848         glDisable(GL_SCISSOR_TEST);
849         GPU_framebuffer_bind(ofs->fb);
850 }
851
852 void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
853 {
854         GPUFrameBuffer *fb = NULL;
855
856         if (restore) {
857                 gpuPopAttrib();
858                 fb = gpuPopFrameBuffer();
859         }
860
861         if (fb) {
862                 GPU_framebuffer_bind(fb);
863         }
864         else {
865                 GPU_framebuffer_restore();
866         }
867 }
868
869 void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y)
870 {
871         const int w = GPU_texture_width(ofs->color);
872         const int h = GPU_texture_height(ofs->color);
873
874         glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object);
875         GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
876
877         if (status == GL_FRAMEBUFFER_COMPLETE) {
878                 glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
879         }
880         else {
881                 gpu_print_framebuffer_error(status, NULL);
882         }
883
884         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
885 }
886
887 void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
888 {
889         const int w = GPU_texture_width(ofs->color);
890         const int h = GPU_texture_height(ofs->color);
891
892         BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
893
894         if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
895                 /* For a multi-sample texture,
896                  * we need to create an intermediate buffer to blit to,
897                  * before its copied using 'glReadPixels' */
898                 GLuint fbo_blit = 0;
899                 GLuint tex_blit = 0;
900
901                 /* create texture for new 'fbo_blit' */
902                 glGenTextures(1, &tex_blit);
903                 glBindTexture(GL_TEXTURE_2D, tex_blit);
904                 glTexImage2D(
905                         GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
906                         w, h, 0, GL_RGBA, type, 0);
907
908                 /* write into new single-sample buffer */
909                 glGenFramebuffers(1, &fbo_blit);
910                 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
911                 glFramebufferTexture2D(
912                         GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
913                         GL_TEXTURE_2D, tex_blit, 0);
914
915                 GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
916                 if (status != GL_FRAMEBUFFER_COMPLETE) {
917                         goto finally;
918                 }
919
920                 /* perform the copy */
921                 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
922
923                 /* read the results */
924                 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
925                 glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
926
927                 /* restore the original frame-bufer */
928                 glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
929
930 finally:
931                 /* cleanup */
932                 glDeleteTextures(1, &tex_blit);
933                 glDeleteFramebuffers(1, &fbo_blit);
934         }
935         else {
936                 glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
937         }
938 }
939
940 int GPU_offscreen_width(const GPUOffScreen *ofs)
941 {
942         return GPU_texture_width(ofs->color);
943 }
944
945 int GPU_offscreen_height(const GPUOffScreen *ofs)
946 {
947         return GPU_texture_height(ofs->color);
948 }
949
950 GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
951 {
952         return ofs->color;
953 }
954
955 /* only to be used by viewport code! */
956 void GPU_offscreen_viewport_data_get(
957         GPUOffScreen *ofs,
958         GPUFrameBuffer **r_fb, GPUTexture **r_color, GPUTexture **r_depth)
959 {
960         *r_fb = ofs->fb;
961         *r_color = ofs->color;
962         *r_depth = ofs->depth;
963 }
964
965 void GPU_clear_color(float red, float green, float blue, float alpha)
966 {
967         glClearColor(red, green, blue, alpha);
968 }
969
970 void GPU_clear(GPUFrameBufferBits flags)
971 {
972         glClear(convert_buffer_bits_to_gl(flags));
973 }