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