Revert "Fix T67040: Undo crashes after renaming"
[blender.git] / source / blender / editors / screen / glutil.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) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edscr
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "DNA_userdef_types.h"
30 #include "DNA_vec_types.h"
31
32 #include "BLI_utildefines.h"
33 #include "BLI_math.h"
34
35 #include "BKE_context.h"
36
37 #include "BIF_glutil.h"
38
39 #include "IMB_colormanagement.h"
40 #include "IMB_imbuf_types.h"
41
42 #include "GPU_immediate.h"
43 #include "GPU_matrix.h"
44 #include "GPU_state.h"
45
46 #include "UI_interface.h"
47
48 /* ******************************************** */
49
50 static int get_cached_work_texture(int *r_w, int *r_h)
51 {
52   static GLint texid = -1;
53   static int tex_w = 256;
54   static int tex_h = 256;
55
56   if (texid == -1) {
57     glGenTextures(1, (GLuint *)&texid);
58
59     glBindTexture(GL_TEXTURE_2D, texid);
60
61     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
62     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
63
64     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
65
66     glBindTexture(GL_TEXTURE_2D, 0);
67   }
68
69   *r_w = tex_w;
70   *r_h = tex_h;
71   return texid;
72 }
73
74 static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
75 {
76   GPUVertFormat *vert_format = immVertexFormat();
77   state->pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
78   state->texco = GPU_vertformat_attr_add(
79       vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
80 }
81
82 /* To be used before calling immDrawPixelsTex
83  * Default shader is GPU_SHADER_2D_IMAGE_COLOR
84  * You can still set uniforms with :
85  * GPU_shader_uniform_int(shader, GPU_shader_get_uniform_ensure(shader, "name"), 0);
86  * */
87 IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
88 {
89   IMMDrawPixelsTexState state;
90   immDrawPixelsTexSetupAttributes(&state);
91
92   state.shader = GPU_shader_get_builtin_shader(builtin);
93
94   /* Shader will be unbind by immUnbindProgram in immDrawPixelsTexScaled_clipping */
95   immBindBuiltinProgram(builtin);
96   immUniform1i("image", 0);
97   state.do_shader_unbind = true;
98
99   return state;
100 }
101
102 /* Use the currently bound shader.
103  *
104  * Use immDrawPixelsTexSetup to bind the shader you
105  * want before calling immDrawPixelsTex.
106  *
107  * If using a special shader double check it uses the same
108  * attributes "pos" "texCoord" and uniform "image".
109  *
110  * If color is NULL then use white by default
111  *
112  * Be also aware that this function unbinds the shader when
113  * it's finished.
114  * */
115 void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
116                                      float x,
117                                      float y,
118                                      int img_w,
119                                      int img_h,
120                                      int format,
121                                      int type,
122                                      int zoomfilter,
123                                      void *rect,
124                                      float scaleX,
125                                      float scaleY,
126                                      float clip_min_x,
127                                      float clip_min_y,
128                                      float clip_max_x,
129                                      float clip_max_y,
130                                      float xzoom,
131                                      float yzoom,
132                                      float color[4])
133 {
134   unsigned char *uc_rect = (unsigned char *)rect;
135   const float *f_rect = (float *)rect;
136   int subpart_x, subpart_y, tex_w, tex_h;
137   int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
138   int texid = get_cached_work_texture(&tex_w, &tex_h);
139   int components;
140   const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
141   float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
142
143   GLint unpack_row_length;
144   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length);
145
146   glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
147   glActiveTexture(GL_TEXTURE0);
148   glBindTexture(GL_TEXTURE_2D, texid);
149
150   /* don't want nasty border artifacts */
151   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
152   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
153   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
154
155   /* setup seamless 2=on, 0=off */
156   seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
157
158   offset_x = tex_w - seamless;
159   offset_y = tex_h - seamless;
160
161   nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
162   nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
163
164   if (format == GL_RGBA) {
165     components = 4;
166   }
167   else if (format == GL_RGB) {
168     components = 3;
169   }
170   else if (format == GL_RED) {
171     components = 1;
172   }
173   else {
174     BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
175     return;
176   }
177
178   if (type == GL_FLOAT) {
179     /* need to set internal format to higher range float */
180     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
181   }
182   else {
183     /* switch to 8bit RGBA for byte buffer */
184     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
185   }
186
187   unsigned int pos = state->pos, texco = state->texco;
188
189   /* optional */
190   /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
191    * it does not need color.
192    */
193   if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) {
194     immUniformColor4fv((color) ? color : white);
195   }
196
197   for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
198     for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
199       int remainder_x = img_w - subpart_x * offset_x;
200       int remainder_y = img_h - subpart_y * offset_y;
201       int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
202       int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
203       int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
204       int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
205       int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
206       int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
207       float rast_x = x + subpart_x * offset_x * xzoom;
208       float rast_y = y + subpart_y * offset_y * yzoom;
209       /* check if we already got these because we always get 2 more when doing seamless */
210       if (subpart_w <= seamless || subpart_h <= seamless) {
211         continue;
212       }
213
214       if (use_clipping) {
215         if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x ||
216             rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y) {
217           continue;
218         }
219         if (rast_x + (float)offset_left * xzoom > clip_max_x ||
220             rast_y + (float)offset_bot * yzoom > clip_max_y) {
221           continue;
222         }
223       }
224
225       if (type == GL_FLOAT) {
226         glTexSubImage2D(GL_TEXTURE_2D,
227                         0,
228                         0,
229                         0,
230                         subpart_w,
231                         subpart_h,
232                         format,
233                         GL_FLOAT,
234                         &f_rect[((size_t)subpart_y) * offset_y * img_w * components +
235                                 subpart_x * offset_x * components]);
236
237         /* add an extra border of pixels so linear looks ok at edges of full image */
238         if (subpart_w < tex_w) {
239           glTexSubImage2D(GL_TEXTURE_2D,
240                           0,
241                           subpart_w,
242                           0,
243                           1,
244                           subpart_h,
245                           format,
246                           GL_FLOAT,
247                           &f_rect[((size_t)subpart_y) * offset_y * img_w * components +
248                                   (subpart_x * offset_x + subpart_w - 1) * components]);
249         }
250         if (subpart_h < tex_h) {
251           glTexSubImage2D(
252               GL_TEXTURE_2D,
253               0,
254               0,
255               subpart_h,
256               subpart_w,
257               1,
258               format,
259               GL_FLOAT,
260               &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
261                       subpart_x * offset_x * components]);
262         }
263         if (subpart_w < tex_w && subpart_h < tex_h) {
264           glTexSubImage2D(
265               GL_TEXTURE_2D,
266               0,
267               subpart_w,
268               subpart_h,
269               1,
270               1,
271               format,
272               GL_FLOAT,
273               &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
274                       (subpart_x * offset_x + subpart_w - 1) * components]);
275         }
276       }
277       else {
278         glTexSubImage2D(GL_TEXTURE_2D,
279                         0,
280                         0,
281                         0,
282                         subpart_w,
283                         subpart_h,
284                         format,
285                         GL_UNSIGNED_BYTE,
286                         &uc_rect[((size_t)subpart_y) * offset_y * img_w * components +
287                                  subpart_x * offset_x * components]);
288
289         if (subpart_w < tex_w) {
290           glTexSubImage2D(GL_TEXTURE_2D,
291                           0,
292                           subpart_w,
293                           0,
294                           1,
295                           subpart_h,
296                           format,
297                           GL_UNSIGNED_BYTE,
298                           &uc_rect[((size_t)subpart_y) * offset_y * img_w * components +
299                                    (subpart_x * offset_x + subpart_w - 1) * components]);
300         }
301         if (subpart_h < tex_h) {
302           glTexSubImage2D(
303               GL_TEXTURE_2D,
304               0,
305               0,
306               subpart_h,
307               subpart_w,
308               1,
309               format,
310               GL_UNSIGNED_BYTE,
311               &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
312                        subpart_x * offset_x * components]);
313         }
314         if (subpart_w < tex_w && subpart_h < tex_h) {
315           glTexSubImage2D(
316               GL_TEXTURE_2D,
317               0,
318               subpart_w,
319               subpart_h,
320               1,
321               1,
322               format,
323               GL_UNSIGNED_BYTE,
324               &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
325                        (subpart_x * offset_x + subpart_w - 1) * components]);
326         }
327       }
328
329       immBegin(GPU_PRIM_TRI_FAN, 4);
330       immAttr2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
331       immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
332
333       immAttr2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
334       immVertex2f(pos,
335                   rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX,
336                   rast_y + (float)offset_bot * yzoom);
337
338       immAttr2f(texco,
339                 (float)(subpart_w - offset_right) / tex_w,
340                 (float)(subpart_h - offset_top) / tex_h);
341       immVertex2f(pos,
342                   rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX,
343                   rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
344
345       immAttr2f(texco, (float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
346       immVertex2f(pos,
347                   rast_x + (float)offset_left * xzoom,
348                   rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
349       immEnd();
350
351       /* NOTE: Weirdly enough this is only required on macOS. Without this there is some sort of
352        * bleeding of data is happening from tiles which are drawn later on.
353        * This doesn't seem to be too slow,
354        * but still would be nice to have fast and nice solution. */
355 #ifdef __APPLE__
356       GPU_flush();
357 #endif
358     }
359   }
360
361   if (state->do_shader_unbind) {
362     immUnbindProgram();
363   }
364
365   glBindTexture(GL_TEXTURE_2D, 0);
366   glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length);
367 }
368
369 void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state,
370                             float x,
371                             float y,
372                             int img_w,
373                             int img_h,
374                             int format,
375                             int type,
376                             int zoomfilter,
377                             void *rect,
378                             float scaleX,
379                             float scaleY,
380                             float xzoom,
381                             float yzoom,
382                             float color[4])
383 {
384   immDrawPixelsTexScaled_clipping(state,
385                                   x,
386                                   y,
387                                   img_w,
388                                   img_h,
389                                   format,
390                                   type,
391                                   zoomfilter,
392                                   rect,
393                                   scaleX,
394                                   scaleY,
395                                   0.0f,
396                                   0.0f,
397                                   0.0f,
398                                   0.0f,
399                                   xzoom,
400                                   yzoom,
401                                   color);
402 }
403
404 void immDrawPixelsTex(IMMDrawPixelsTexState *state,
405                       float x,
406                       float y,
407                       int img_w,
408                       int img_h,
409                       int format,
410                       int type,
411                       int zoomfilter,
412                       void *rect,
413                       float xzoom,
414                       float yzoom,
415                       float color[4])
416 {
417   immDrawPixelsTexScaled_clipping(state,
418                                   x,
419                                   y,
420                                   img_w,
421                                   img_h,
422                                   format,
423                                   type,
424                                   zoomfilter,
425                                   rect,
426                                   1.0f,
427                                   1.0f,
428                                   0.0f,
429                                   0.0f,
430                                   0.0f,
431                                   0.0f,
432                                   xzoom,
433                                   yzoom,
434                                   color);
435 }
436
437 void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
438                                float x,
439                                float y,
440                                int img_w,
441                                int img_h,
442                                int format,
443                                int type,
444                                int zoomfilter,
445                                void *rect,
446                                float clip_min_x,
447                                float clip_min_y,
448                                float clip_max_x,
449                                float clip_max_y,
450                                float xzoom,
451                                float yzoom,
452                                float color[4])
453 {
454   immDrawPixelsTexScaled_clipping(state,
455                                   x,
456                                   y,
457                                   img_w,
458                                   img_h,
459                                   format,
460                                   type,
461                                   zoomfilter,
462                                   rect,
463                                   1.0f,
464                                   1.0f,
465                                   clip_min_x,
466                                   clip_min_y,
467                                   clip_max_x,
468                                   clip_max_y,
469                                   xzoom,
470                                   yzoom,
471                                   color);
472 }
473
474 /* *************** glPolygonOffset hack ************* */
475
476 float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist)
477 {
478   /* Seems like we have a factor of 2 more offset than 2.79 for some reason. Correct for this. */
479   dist *= 0.5f;
480
481   if (winmat[15] > 0.5f) {
482 #if 1
483     return 0.00001f * dist * viewdist;  // ortho tweaking
484 #else
485     static float depth_fac = 0.0f;
486     if (depth_fac == 0.0f) {
487       int depthbits;
488       glGetIntegerv(GL_DEPTH_BITS, &depthbits);
489       depth_fac = 1.0f / (float)((1 << depthbits) - 1);
490     }
491     offs = (-1.0 / winmat[10]) * dist * depth_fac;
492
493     UNUSED_VARS(viewdist);
494 #endif
495   }
496   else {
497     /* This adjustment effectively results in reducing the Z value by 0.25%.
498      *
499      * winmat[14] actually evaluates to `-2 * far * near / (far - near)`,
500      * is very close to -0.2 with default clip range,
501      * and is used as the coefficient multiplied by `w / z`,
502      * thus controlling the z dependent part of the depth value.
503      */
504     return winmat[14] * -0.0025f * dist;
505   }
506 }
507
508 /**
509  * \note \a viewdist is only for ortho at the moment.
510  */
511 void bglPolygonOffset(float viewdist, float dist)
512 {
513   static float winmat[16], offset = 0.0f;
514
515   if (dist != 0.0f) {
516     // glEnable(GL_POLYGON_OFFSET_FILL);
517     // glPolygonOffset(-1.0, -1.0);
518
519     /* hack below is to mimic polygon offset */
520     GPU_matrix_projection_get(winmat);
521
522     /* dist is from camera to center point */
523
524     float offs = bglPolygonOffsetCalc(winmat, viewdist, dist);
525
526     winmat[14] -= offs;
527     offset += offs;
528   }
529   else {
530     winmat[14] += offset;
531     offset = 0.0;
532   }
533
534   GPU_matrix_projection_set(winmat);
535 }
536
537 /* **** Color management helper functions for GLSL display/transform ***** */
538
539 /* Draw given image buffer on a screen using GLSL for display transform */
540 void ED_draw_imbuf_clipping(ImBuf *ibuf,
541                             float x,
542                             float y,
543                             int zoomfilter,
544                             ColorManagedViewSettings *view_settings,
545                             ColorManagedDisplaySettings *display_settings,
546                             float clip_min_x,
547                             float clip_min_y,
548                             float clip_max_x,
549                             float clip_max_y,
550                             float zoom_x,
551                             float zoom_y)
552 {
553   bool force_fallback = false;
554   bool need_fallback = true;
555
556   /* Early out */
557   if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
558     return;
559   }
560
561   /* Single channel images could not be transformed using GLSL yet */
562   force_fallback |= ibuf->channels == 1;
563
564   /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
565   force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
566
567   /* Try to draw buffer using GLSL display transform */
568   if (force_fallback == false) {
569     int ok;
570
571     IMMDrawPixelsTexState state = {0};
572     /* We want GLSL state to be fully handled by OCIO. */
573     state.do_shader_unbind = false;
574     immDrawPixelsTexSetupAttributes(&state);
575
576     if (ibuf->rect_float) {
577       if (ibuf->float_colorspace) {
578         ok = IMB_colormanagement_setup_glsl_draw_from_space(
579             view_settings, display_settings, ibuf->float_colorspace, ibuf->dither, true);
580       }
581       else {
582         ok = IMB_colormanagement_setup_glsl_draw(
583             view_settings, display_settings, ibuf->dither, true);
584       }
585     }
586     else {
587       ok = IMB_colormanagement_setup_glsl_draw_from_space(
588           view_settings, display_settings, ibuf->rect_colorspace, ibuf->dither, false);
589     }
590
591     if (ok) {
592       if (ibuf->rect_float) {
593         int format = 0;
594
595         if (ibuf->channels == 3) {
596           format = GL_RGB;
597         }
598         else if (ibuf->channels == 4) {
599           format = GL_RGBA;
600         }
601         else {
602           BLI_assert(!"Incompatible number of channels for GLSL display");
603         }
604
605         if (format != 0) {
606           immDrawPixelsTex_clipping(&state,
607                                     x,
608                                     y,
609                                     ibuf->x,
610                                     ibuf->y,
611                                     format,
612                                     GL_FLOAT,
613                                     zoomfilter,
614                                     ibuf->rect_float,
615                                     clip_min_x,
616                                     clip_min_y,
617                                     clip_max_x,
618                                     clip_max_y,
619                                     zoom_x,
620                                     zoom_y,
621                                     NULL);
622         }
623       }
624       else if (ibuf->rect) {
625         /* ibuf->rect is always RGBA */
626         immDrawPixelsTex_clipping(&state,
627                                   x,
628                                   y,
629                                   ibuf->x,
630                                   ibuf->y,
631                                   GL_RGBA,
632                                   GL_UNSIGNED_BYTE,
633                                   zoomfilter,
634                                   ibuf->rect,
635                                   clip_min_x,
636                                   clip_min_y,
637                                   clip_max_x,
638                                   clip_max_y,
639                                   zoom_x,
640                                   zoom_y,
641                                   NULL);
642       }
643
644       IMB_colormanagement_finish_glsl_draw();
645
646       need_fallback = false;
647     }
648   }
649
650   /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
651   if (need_fallback) {
652     unsigned char *display_buffer;
653     void *cache_handle;
654
655     display_buffer = IMB_display_buffer_acquire(
656         ibuf, view_settings, display_settings, &cache_handle);
657
658     if (display_buffer) {
659       IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
660       immDrawPixelsTex_clipping(&state,
661                                 x,
662                                 y,
663                                 ibuf->x,
664                                 ibuf->y,
665                                 GL_RGBA,
666                                 GL_UNSIGNED_BYTE,
667                                 zoomfilter,
668                                 display_buffer,
669                                 clip_min_x,
670                                 clip_min_y,
671                                 clip_max_x,
672                                 clip_max_y,
673                                 zoom_x,
674                                 zoom_y,
675                                 NULL);
676     }
677
678     IMB_display_buffer_release(cache_handle);
679   }
680 }
681
682 void ED_draw_imbuf(ImBuf *ibuf,
683                    float x,
684                    float y,
685                    int zoomfilter,
686                    ColorManagedViewSettings *view_settings,
687                    ColorManagedDisplaySettings *display_settings,
688                    float zoom_x,
689                    float zoom_y)
690 {
691   ED_draw_imbuf_clipping(ibuf,
692                          x,
693                          y,
694                          zoomfilter,
695                          view_settings,
696                          display_settings,
697                          0.0f,
698                          0.0f,
699                          0.0f,
700                          0.0f,
701                          zoom_x,
702                          zoom_y);
703 }
704
705 void ED_draw_imbuf_ctx_clipping(const bContext *C,
706                                 ImBuf *ibuf,
707                                 float x,
708                                 float y,
709                                 int zoomfilter,
710                                 float clip_min_x,
711                                 float clip_min_y,
712                                 float clip_max_x,
713                                 float clip_max_y,
714                                 float zoom_x,
715                                 float zoom_y)
716 {
717   ColorManagedViewSettings *view_settings;
718   ColorManagedDisplaySettings *display_settings;
719
720   IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
721
722   ED_draw_imbuf_clipping(ibuf,
723                          x,
724                          y,
725                          zoomfilter,
726                          view_settings,
727                          display_settings,
728                          clip_min_x,
729                          clip_min_y,
730                          clip_max_x,
731                          clip_max_y,
732                          zoom_x,
733                          zoom_y);
734 }
735
736 void ED_draw_imbuf_ctx(
737     const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter, float zoom_x, float zoom_y)
738 {
739   ED_draw_imbuf_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
740 }
741
742 int ED_draw_imbuf_method(ImBuf *ibuf)
743 {
744   if (U.image_draw_method == IMAGE_DRAW_METHOD_AUTO) {
745     /* Use faster GLSL when CPU to GPU transfer is unlikely to be a bottleneck,
746      * otherwise do color management on CPU side. */
747     const size_t threshold = 2048 * 2048 * 4 * sizeof(float);
748     const size_t data_size = (ibuf->rect_float) ? sizeof(float) : sizeof(uchar);
749     const size_t size = ibuf->x * ibuf->y * ibuf->channels * data_size;
750
751     return (size > threshold) ? IMAGE_DRAW_METHOD_2DTEXTURE : IMAGE_DRAW_METHOD_GLSL;
752   }
753   else {
754     return U.image_draw_method;
755   }
756 }
757
758 /* don't move to GPU_immediate_util.h because this uses user-prefs
759  * and isn't very low level */
760 void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy)
761 {
762   float delta_x = 4.0f * UI_DPI_FAC / zoomx;
763   float delta_y = 4.0f * UI_DPI_FAC / zoomy;
764
765   delta_x = min_ff(delta_x, border->xmax - border->xmin);
766   delta_y = min_ff(delta_y, border->ymax - border->ymin);
767
768   /* left bottom corner */
769   immBegin(GPU_PRIM_LINE_STRIP, 3);
770   immVertex2f(pos, border->xmin, border->ymin + delta_y);
771   immVertex2f(pos, border->xmin, border->ymin);
772   immVertex2f(pos, border->xmin + delta_x, border->ymin);
773   immEnd();
774
775   /* left top corner */
776   immBegin(GPU_PRIM_LINE_STRIP, 3);
777   immVertex2f(pos, border->xmin, border->ymax - delta_y);
778   immVertex2f(pos, border->xmin, border->ymax);
779   immVertex2f(pos, border->xmin + delta_x, border->ymax);
780   immEnd();
781
782   /* right bottom corner */
783   immBegin(GPU_PRIM_LINE_STRIP, 3);
784   immVertex2f(pos, border->xmax - delta_x, border->ymin);
785   immVertex2f(pos, border->xmax, border->ymin);
786   immVertex2f(pos, border->xmax, border->ymin + delta_y);
787   immEnd();
788
789   /* right top corner */
790   immBegin(GPU_PRIM_LINE_STRIP, 3);
791   immVertex2f(pos, border->xmax - delta_x, border->ymax);
792   immVertex2f(pos, border->xmax, border->ymax);
793   immVertex2f(pos, border->xmax, border->ymax - delta_y);
794   immEnd();
795 }