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