cleanup: style
[blender-staging.git] / source / blender / editors / screen / glutil.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/screen/glutil.c
27  *  \ingroup edscr
28  */
29
30
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_userdef_types.h"
37 #include "DNA_vec_types.h"
38
39 #include "BLI_rect.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_math.h"
42
43 #include "BKE_context.h"
44
45 #include "BIF_gl.h"
46 #include "BIF_glutil.h"
47
48
49 #include "IMB_colormanagement.h"
50 #include "IMB_imbuf_types.h"
51
52 #include "UI_interface.h"
53
54 #ifndef GL_CLAMP_TO_EDGE
55 #define GL_CLAMP_TO_EDGE                        0x812F
56 #endif
57
58
59 /* ******************************************** */
60
61 /* defined in BIF_gl.h */
62 const GLubyte stipple_halftone[128] = {
63         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
64         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
65         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
66         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
67         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
68         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
69         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
70         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
71         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
72         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
73         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
74         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
75         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
76         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
77         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
78         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
79
80
81 /*  repeat this pattern
82  *
83  *     X000X000
84  *     00000000
85  *     00X000X0
86  *     00000000 */
87
88
89 const GLubyte stipple_quarttone[128] = {
90         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
91         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
92         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
93         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
94         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
95         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
96         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
97         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
98
99
100 const GLubyte stipple_diag_stripes_pos[128] = {
101         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
102         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
103         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
104         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
105         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
106         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
107         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
108         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
109         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
110         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
111         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
112         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
113         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
114         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
115         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
116         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
117
118
119 const GLubyte stipple_diag_stripes_neg[128] = {
120         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
121         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
122         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
123         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
124         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
125         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
126         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
127         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
128         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
129         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
130         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
131         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
132         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
133         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
134         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
135         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80};
136
137 const GLubyte stipple_checker_8px[128] = {
138         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
139         255,  0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
140         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
141         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
142         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
143         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
144         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
145         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
146
147 /* UNUSED */
148 #if 0
149 void fdrawbezier(float vec[4][3])
150 {
151         float dist;
152         float curve_res = 24, spline_step = 0.0f;
153         
154         dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
155         
156         /* check direction later, for top sockets */
157         vec[1][0] = vec[0][0] + dist;
158         vec[1][1] = vec[0][1];
159         
160         vec[2][0] = vec[3][0] - dist;
161         vec[2][1] = vec[3][1];
162         /* we can reuse the dist variable here to increment the GL curve eval amount*/
163         dist = 1.0f / curve_res;
164         
165         cpack(0x0);
166         glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
167         glBegin(GL_LINE_STRIP);
168         while (spline_step < 1.000001f) {
169 #if 0
170                 if (do_shaded)
171                         UI_ThemeColorBlend(th_col1, th_col2, spline_step);
172 #endif
173                 glEvalCoord1f(spline_step);
174                 spline_step += dist;
175         }
176         glEnd();
177 }
178 #endif
179
180 void fdrawline(float x1, float y1, float x2, float y2)
181 {
182         float v[2];
183         
184         glBegin(GL_LINE_STRIP);
185         v[0] = x1; v[1] = y1;
186         glVertex2fv(v);
187         v[0] = x2; v[1] = y2;
188         glVertex2fv(v);
189         glEnd();
190 }
191
192 void fdrawbox(float x1, float y1, float x2, float y2)
193 {
194         float v[2];
195         
196         glBegin(GL_LINE_STRIP);
197         
198         v[0] = x1; v[1] = y1;
199         glVertex2fv(v);
200         v[0] = x1; v[1] = y2;
201         glVertex2fv(v);
202         v[0] = x2; v[1] = y2;
203         glVertex2fv(v);
204         v[0] = x2; v[1] = y1;
205         glVertex2fv(v);
206         v[0] = x1; v[1] = y1;
207         glVertex2fv(v);
208         
209         glEnd();
210 }
211
212 void fdrawcheckerboard(float x1, float y1, float x2, float y2)
213 {
214         unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50};
215
216         glColor3ubv(col1);
217         glRectf(x1, y1, x2, y2);
218         glColor3ubv(col2);
219
220         glEnable(GL_POLYGON_STIPPLE);
221         glPolygonStipple(stipple_checker_8px);
222         glRectf(x1, y1, x2, y2);
223         glDisable(GL_POLYGON_STIPPLE);
224 }
225
226 void sdrawline(int x1, int y1, int x2, int y2)
227 {
228         int v[2];
229         
230         glBegin(GL_LINE_STRIP);
231         v[0] = x1; v[1] = y1;
232         glVertex2iv(v);
233         v[0] = x2; v[1] = y2;
234         glVertex2iv(v);
235         glEnd();
236 }
237
238 /* UNUSED */
239 #if 0
240 /*
241  *     x1,y2
242  *     |  \
243  *     |   \
244  *     |    \
245  *     x1,y1-- x2,y1
246  */
247
248 static void sdrawtripoints(int x1, int y1, int x2, int y2)
249 {
250         int v[2];
251         v[0] = x1; v[1] = y1;
252         glVertex2iv(v);
253         v[0] = x1; v[1] = y2;
254         glVertex2iv(v);
255         v[0] = x2; v[1] = y1;
256         glVertex2iv(v);
257 }
258
259 void sdrawtri(int x1, int y1, int x2, int y2)
260 {
261         glBegin(GL_LINE_STRIP);
262         sdrawtripoints(x1, y1, x2, y2);
263         glEnd();
264 }
265
266 void sdrawtrifill(int x1, int y1, int x2, int y2)
267 {
268         glBegin(GL_TRIANGLES);
269         sdrawtripoints(x1, y1, x2, y2);
270         glEnd();
271 }
272 #endif
273
274 void sdrawbox(int x1, int y1, int x2, int y2)
275 {
276         int v[2];
277         
278         glBegin(GL_LINE_STRIP);
279         
280         v[0] = x1; v[1] = y1;
281         glVertex2iv(v);
282         v[0] = x1; v[1] = y2;
283         glVertex2iv(v);
284         v[0] = x2; v[1] = y2;
285         glVertex2iv(v);
286         v[0] = x2; v[1] = y1;
287         glVertex2iv(v);
288         v[0] = x1; v[1] = y1;
289         glVertex2iv(v);
290         
291         glEnd();
292 }
293
294
295 /* ******************************************** */
296
297 void setlinestyle(int nr)
298 {
299         if (nr == 0) {
300                 glDisable(GL_LINE_STIPPLE);
301         }
302         else {
303                 
304                 glEnable(GL_LINE_STIPPLE);
305                 if (U.pixelsize > 1.0f)
306                         glLineStipple(nr, 0xCCCC);
307                 else
308                         glLineStipple(nr, 0xAAAA);
309         }
310 }
311
312 /* Invert line handling */
313         
314 #define GL_TOGGLE(mode, onoff)  (((onoff) ? glEnable : glDisable)(mode))
315
316 void set_inverted_drawing(int enable) 
317 {
318         glLogicOp(enable ? GL_INVERT : GL_COPY);
319         GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
320         GL_TOGGLE(GL_DITHER, !enable);
321 }
322
323 /* UNUSED */
324 #if 0
325 void sdrawXORline(int x0, int y0, int x1, int y1)
326 {
327         if (x0 == x1 && y0 == y1) return;
328
329         set_inverted_drawing(1);
330         
331         glBegin(GL_LINES);
332         glVertex2i(x0, y0);
333         glVertex2i(x1, y1);
334         glEnd();
335         
336         set_inverted_drawing(0);
337 }
338
339 void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
340 {
341         static int old[4][2][2];
342         static char flags[4] = {0, 0, 0, 0};
343         
344         /* with builtin memory, max 4 lines */
345
346         set_inverted_drawing(1);
347                 
348         glBegin(GL_LINES);
349         if (nr == -1) { /* flush */
350                 for (nr = 0; nr < 4; nr++) {
351                         if (flags[nr]) {
352                                 glVertex2iv(old[nr][0]);
353                                 glVertex2iv(old[nr][1]);
354                                 flags[nr] = 0;
355                         }
356                 }
357         }
358         else {
359                 if (nr >= 0 && nr < 4) {
360                         if (flags[nr]) {
361                                 glVertex2iv(old[nr][0]);
362                                 glVertex2iv(old[nr][1]);
363                         }
364
365                         old[nr][0][0] = x0;
366                         old[nr][0][1] = y0;
367                         old[nr][1][0] = x1;
368                         old[nr][1][1] = y1;
369                         
370                         flags[nr] = 1;
371                 }
372                 
373                 glVertex2i(x0, y0);
374                 glVertex2i(x1, y1);
375         }
376         glEnd();
377         
378         set_inverted_drawing(0);
379 }
380
381 void fdrawXORellipse(float xofs, float yofs, float hw, float hh)
382 {
383         if (hw == 0) return;
384
385         set_inverted_drawing(1);
386
387         glPushMatrix();
388         glTranslatef(xofs, yofs, 0.0f);
389         glScalef(1.0f, hh / hw, 1.0f);
390         glutil_draw_lined_arc(0.0, M_PI * 2.0, hw, 20);
391         glPopMatrix();
392
393         set_inverted_drawing(0);
394 }
395
396 #endif
397
398 void fdrawXORcirc(float xofs, float yofs, float rad)
399 {
400         set_inverted_drawing(1);
401
402         glPushMatrix();
403         glTranslatef(xofs, yofs, 0.0);
404         glutil_draw_lined_arc(0.0, M_PI * 2.0, rad, 20);
405         glPopMatrix();
406
407         set_inverted_drawing(0);
408 }
409
410 void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments)
411 {
412         int i;
413         
414         glBegin(GL_TRIANGLE_FAN);
415         glVertex2f(0.0, 0.0);
416         for (i = 0; i < nsegments; i++) {
417                 float t = (float) i / (nsegments - 1);
418                 float cur = start + t * angle;
419                 
420                 glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
421         }
422         glEnd();
423 }
424
425 void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments)
426 {
427         int i;
428         
429         glBegin(GL_LINE_STRIP);
430         for (i = 0; i < nsegments; i++) {
431                 float t = (float) i / (nsegments - 1);
432                 float cur = start + t * angle;
433                 
434                 glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
435         }
436         glEnd();
437 }
438
439 int glaGetOneInteger(int param)
440 {
441         GLint i;
442         glGetIntegerv(param, &i);
443         return i;
444 }
445
446 float glaGetOneFloat(int param)
447 {
448         GLfloat v;
449         glGetFloatv(param, &v);
450         return v;
451 }
452
453 void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y)
454 {
455         GLubyte dummy = 0;
456
457         /* As long as known good coordinates are correct
458          * this is guaranteed to generate an ok raster
459          * position (ignoring potential (real) overflow
460          * issues).
461          */
462         glRasterPos2f(known_good_x, known_good_y);
463
464         /* Now shift the raster position to where we wanted
465          * it in the first place using the glBitmap trick.
466          */
467         glBitmap(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy);
468 }
469
470 static int get_cached_work_texture(int *r_w, int *r_h)
471 {
472         static GLint texid = -1;
473         static int tex_w = 256;
474         static int tex_h = 256;
475
476         if (texid == -1) {
477                 GLint ltexid = glaGetOneInteger(GL_TEXTURE_2D);
478                 unsigned char *tbuf;
479
480                 glGenTextures(1, (GLuint *)&texid);
481
482                 glBindTexture(GL_TEXTURE_2D, texid);
483
484                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
485                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
486
487                 tbuf = MEM_callocN(tex_w * tex_h * 4, "tbuf");
488                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf);
489                 MEM_freeN(tbuf);
490
491                 glBindTexture(GL_TEXTURE_2D, ltexid);
492         }
493
494         *r_w = tex_w;
495         *r_h = tex_h;
496         return texid;
497 }
498
499 void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY)
500 {
501         unsigned char *uc_rect = (unsigned char *) rect;
502         const float *f_rect = (float *)rect;
503         float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y);
504         int ltexid = glaGetOneInteger(GL_TEXTURE_2D);
505         int lrowlength = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
506         int subpart_x, subpart_y, tex_w, tex_h;
507         int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
508         int texid = get_cached_work_texture(&tex_w, &tex_h);
509         int components;
510
511         /* Specify the color outside this function, and tex will modulate it.
512          * This is useful for changing alpha without using glPixelTransferf()
513          */
514         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
515         glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
516         glBindTexture(GL_TEXTURE_2D, texid);
517
518         /* don't want nasty border artifacts */
519         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
520         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
521         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
522
523 #ifdef __APPLE__
524         /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
525         glPixelZoom(1.f, 1.f);
526 #endif
527         
528         /* setup seamless 2=on, 0=off */
529         seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
530         
531         offset_x = tex_w - seamless;
532         offset_y = tex_h - seamless;
533         
534         nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
535         nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
536
537         if (format == GL_RGBA)
538                 components = 4;
539         else if (format == GL_RGB)
540                 components = 3;
541         else if (ELEM(format,  GL_LUMINANCE, GL_ALPHA))
542                 components = 1;
543         else {
544                 BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
545                 return;
546         }
547
548         if (type == GL_FLOAT) {
549                 /* need to set internal format to higher range float */
550
551                 /* NOTE: this could fail on some drivers, like mesa,
552                  *       but currently this code is only used by color
553                  *       management stuff which already checks on whether
554                  *       it's possible to use GL_RGBA16F_ARB
555                  */
556
557                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
558         }
559         else {
560                 /* switch to 8bit RGBA for byte buffer  */
561                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
562         }
563
564         for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
565                 for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
566                         int remainder_x = img_w - subpart_x * offset_x;
567                         int remainder_y = img_h - subpart_y * offset_y;
568                         int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
569                         int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
570                         int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
571                         int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
572                         int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
573                         int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
574                         float rast_x = x + subpart_x * offset_x * xzoom;
575                         float rast_y = y + subpart_y * offset_y * yzoom;
576                         
577                         /* check if we already got these because we always get 2 more when doing seamless*/
578                         if (subpart_w <= seamless || subpart_h <= seamless)
579                                 continue;
580                         
581                         if (type == GL_FLOAT) {
582                                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
583                                 
584                                 /* add an extra border of pixels so linear looks ok at edges of full image. */
585                                 if (subpart_w < tex_w)
586                                         glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
587                                 if (subpart_h < tex_h)
588                                         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
589                                 if (subpart_w < tex_w && subpart_h < tex_h)
590                                         glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
591                         }
592                         else {
593                                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
594                                 
595                                 if (subpart_w < tex_w)
596                                         glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
597                                 if (subpart_h < tex_h)
598                                         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
599                                 if (subpart_w < tex_w && subpart_h < tex_h)
600                                         glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
601                         }
602
603                         glEnable(GL_TEXTURE_2D);
604                         glBegin(GL_QUADS);
605                         glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
606                         glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
607
608                         glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
609                         glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
610
611                         glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
612                         glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
613
614                         glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
615                         glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
616                         glEnd();
617                         glDisable(GL_TEXTURE_2D);
618                 }
619         }
620
621         glBindTexture(GL_TEXTURE_2D, ltexid);
622         glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength);
623         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
624         
625 #ifdef __APPLE__
626         /* workaround for os x 10.5/10.6 driver bug (above) */
627         glPixelZoom(xzoom, yzoom);
628 #endif
629 }
630
631 void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
632 {
633         glaDrawPixelsTexScaled(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f);
634 }
635
636 void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
637 {
638         float xzoom = glaGetOneFloat(GL_ZOOM_X);
639         float yzoom = glaGetOneFloat(GL_ZOOM_Y);
640
641         /* The pixel space coordinate of the intersection of
642          * the [zoomed] image with the origin.
643          */
644         float ix = -x / xzoom;
645         float iy = -y / yzoom;
646                 
647         /* The maximum pixel amounts the image can be cropped
648          * at the lower left without exceeding the origin.
649          */
650         int off_x = floor(max_ff(ix, 0.0f));
651         int off_y = floor(max_ff(iy, 0.0f));
652
653         /* The zoomed space coordinate of the raster position
654          * (starting at the lower left most unclipped pixel).
655          */
656         float rast_x = x + off_x * xzoom;
657         float rast_y = y + off_y * yzoom;
658
659         GLfloat scissor[4];
660         int draw_w, draw_h;
661
662         /* Determine the smallest number of pixels we need to draw
663          * before the image would go off the upper right corner.
664          *
665          * It may seem this is just an optimization but some graphics
666          * cards (ATI) freak out if there is a large zoom factor and
667          * a large number of pixels off the screen (probably at some
668          * level the number of image pixels to draw is getting multiplied
669          * by the zoom and then clamped). Making sure we draw the
670          * fewest pixels possible keeps everyone mostly happy (still
671          * fails if we zoom in on one really huge pixel so that it
672          * covers the entire screen).
673          */
674         glGetFloatv(GL_SCISSOR_BOX, scissor);
675         draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom));
676         draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));
677
678         if (draw_w > 0 && draw_h > 0) {
679                 int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
680
681                 /* Don't use safe RasterPos (slower) if we can avoid it. */
682                 if (rast_x >= 0 && rast_y >= 0) {
683                         glRasterPos2f(rast_x, rast_y);
684                 }
685                 else {
686                         glaRasterPosSafe2f(rast_x, rast_y, 0, 0);
687                 }
688
689                 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w);
690                 if (format == GL_LUMINANCE || format == GL_RED) {
691                         if (type == GL_FLOAT) {
692                                 const float *f_rect = (float *)rect;
693                                 glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x));
694                         }
695                         else if (type == GL_INT || type == GL_UNSIGNED_INT) {
696                                 const int *i_rect = (int *)rect;
697                                 glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y * row_w + off_x));
698                         }
699                 }
700                 else { /* RGBA */
701                         if (type == GL_FLOAT) {
702                                 const float *f_rect = (float *)rect;
703                                 glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x) * 4);
704                         }
705                         else if (type == GL_UNSIGNED_BYTE) {
706                                 unsigned char *uc_rect = (unsigned char *) rect;
707                                 glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y * row_w + off_x) * 4);
708                         }
709                 }
710                 
711                 glPixelStorei(GL_UNPACK_ROW_LENGTH,  old_row_length);
712         }
713 }
714
715 /* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
716 void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
717 {
718         if (U.image_draw_method != IMAGE_DRAW_METHOD_DRAWPIXELS) {
719                 glColor4f(1.0, 1.0, 1.0, 1.0);
720                 glaDrawPixelsTex(x, y, img_w, img_h, format, type, zoomfilter, rect);
721         }
722         else {
723                 glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect);
724         }
725 }
726
727 /* 2D Drawing Assistance */
728
729 void glaDefine2DArea(rcti *screen_rect)
730 {
731         const int sc_w = BLI_rcti_size_x(screen_rect) + 1;
732         const int sc_h = BLI_rcti_size_y(screen_rect) + 1;
733
734         glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
735         glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
736
737         /* The GLA_PIXEL_OFS magic number is to shift the matrix so that
738          * both raster and vertex integer coordinates fall at pixel
739          * centers properly. For a longer discussion see the OpenGL
740          * Programming Guide, Appendix H, Correctness Tips.
741          */
742
743         glMatrixMode(GL_PROJECTION);
744         glLoadIdentity();
745         glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1);
746         glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0);
747
748         glMatrixMode(GL_MODELVIEW);
749         glLoadIdentity();
750 }
751
752 #if 0 /* UNUSED */
753
754 struct gla2DDrawInfo {
755         int orig_vp[4], orig_sc[4];
756         float orig_projmat[16], orig_viewmat[16];
757
758         rcti screen_rect;
759         rctf world_rect;
760
761         float wo_to_sc[2];
762 };
763
764 void gla2DGetMap(gla2DDrawInfo *di, rctf *rect) 
765 {
766         *rect = di->world_rect;
767 }
768
769 void gla2DSetMap(gla2DDrawInfo *di, rctf *rect) 
770 {
771         int sc_w, sc_h;
772         float wo_w, wo_h;
773
774         di->world_rect = *rect;
775         
776         sc_w = BLI_rcti_size_x(&di->screen_rect);
777         sc_h = BLI_rcti_size_y(&di->screen_rect);
778         wo_w = BLI_rcti_size_x(&di->world_rect);
779         wo_h = BLI_rcti_size_y(&di->world_rect);
780         
781         di->wo_to_sc[0] = sc_w / wo_w;
782         di->wo_to_sc[1] = sc_h / wo_h;
783 }
784
785 /** Save the current OpenGL state and initialize OpenGL for 2D
786  * rendering. glaEnd2DDraw should be called on the returned structure
787  * to free it and to return OpenGL to its previous state. The
788  * scissor rectangle is set to match the viewport.
789  *
790  * See glaDefine2DArea for an explanation of why this function uses integers.
791  *
792  * \param screen_rect The screen rectangle to be used for 2D drawing.
793  * \param world_rect The world rectangle that the 2D area represented
794  * by \a screen_rect is supposed to represent. If NULL it is assumed the
795  * world has a 1 to 1 mapping to the screen.
796  */
797 gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) 
798 {
799         gla2DDrawInfo *di = MEM_mallocN(sizeof(*di), "gla2DDrawInfo");
800         int sc_w, sc_h;
801         float wo_w, wo_h;
802
803         glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp);
804         glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc);
805         glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat);
806         glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat);
807
808         di->screen_rect = *screen_rect;
809         if (world_rect) {
810                 di->world_rect = *world_rect;
811         }
812         else {
813                 di->world_rect.xmin = di->screen_rect.xmin;
814                 di->world_rect.ymin = di->screen_rect.ymin;
815                 di->world_rect.xmax = di->screen_rect.xmax;
816                 di->world_rect.ymax = di->screen_rect.ymax;
817         }
818
819         sc_w = BLI_rcti_size_x(&di->screen_rect);
820         sc_h = BLI_rcti_size_y(&di->screen_rect);
821         wo_w = BLI_rcti_size_x(&di->world_rect);
822         wo_h = BLI_rcti_size_y(&di->world_rect);
823
824         di->wo_to_sc[0] = sc_w / wo_w;
825         di->wo_to_sc[1] = sc_h / wo_h;
826
827         glaDefine2DArea(&di->screen_rect);
828
829         return di;
830 }
831
832 /**
833  * Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space.
834  */
835 void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y)
836 {
837         *r_sc_x = (wo_x - di->world_rect.xmin) * di->wo_to_sc[0];
838         *r_sc_y = (wo_y - di->world_rect.ymin) * di->wo_to_sc[1];
839 }
840
841 /**
842  * Translate the \a world point from world coordiantes into screen space.
843  */
844 void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2])
845 {
846         screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0];
847         screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1];
848 }
849
850 /**
851  * Restores the previous OpenGL state and free's the auxilary gla data.
852  */
853 void glaEnd2DDraw(gla2DDrawInfo *di)
854 {
855         glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
856         glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
857         glMatrixMode(GL_PROJECTION);
858         glLoadMatrixf(di->orig_projmat);
859         glMatrixMode(GL_MODELVIEW);
860         glLoadMatrixf(di->orig_viewmat);
861
862         MEM_freeN(di);
863 }
864 #endif
865
866 /* **************** GL_POINT hack ************************ */
867
868 static int curmode = 0;
869 static int pointhack = 0;
870 static GLubyte Squaredot[16] = {0xff, 0xff, 0xff, 0xff,
871                                 0xff, 0xff, 0xff, 0xff,
872                                 0xff, 0xff, 0xff, 0xff,
873                                 0xff, 0xff, 0xff, 0xff};
874
875 void bglBegin(int mode)
876 {
877         curmode = mode;
878         
879         if (mode == GL_POINTS) {
880                 float value[4];
881                 glGetFloatv(GL_POINT_SIZE_RANGE, value);
882                 if (value[1] < 2.0f) {
883                         glGetFloatv(GL_POINT_SIZE, value);
884                         pointhack = iroundf(value[0]);
885                         if (pointhack > 4) pointhack = 4;
886                 }
887                 else {
888                         glBegin(mode);
889                 }
890         }
891 }
892
893 #if 0 /* UNUSED */
894 int bglPointHack(void)
895 {
896         float value[4];
897         int pointhack_px;
898         glGetFloatv(GL_POINT_SIZE_RANGE, value);
899         if (value[1] < 2.0f) {
900                 glGetFloatv(GL_POINT_SIZE, value);
901                 pointhack_px = floorf(value[0] + 0.5f);
902                 if (pointhack_px > 4) pointhack_px = 4;
903                 return pointhack_px;
904         }
905         return 0;
906 }
907 #endif
908
909 void bglVertex3fv(const float vec[3])
910 {
911         switch (curmode) {
912                 case GL_POINTS:
913                         if (pointhack) {
914                                 glRasterPos3fv(vec);
915                                 glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot);
916                         }
917                         else {
918                                 glVertex3fv(vec);
919                         }
920                         break;
921         }
922 }
923
924 void bglVertex3f(float x, float y, float z)
925 {
926         switch (curmode) {
927                 case GL_POINTS:
928                         if (pointhack) {
929                                 glRasterPos3f(x, y, z);
930                                 glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot);
931                         }
932                         else {
933                                 glVertex3f(x, y, z);
934                         }
935                         break;
936         }
937 }
938
939 void bglVertex2fv(const float vec[2])
940 {
941         switch (curmode) {
942                 case GL_POINTS:
943                         if (pointhack) {
944                                 glRasterPos2fv(vec);
945                                 glBitmap(pointhack, pointhack, (float)pointhack / 2, pointhack / 2, 0.0, 0.0, Squaredot);
946                         }
947                         else {
948                                 glVertex2fv(vec);
949                         }
950                         break;
951         }
952 }
953
954
955 void bglEnd(void)
956 {
957         if (pointhack) pointhack = 0;
958         else glEnd();
959         
960 }
961
962 /* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */
963 void bgl_get_mats(bglMats *mats)
964 {
965         const double badvalue = 1.0e-6;
966
967         glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview);
968         glGetDoublev(GL_PROJECTION_MATRIX, mats->projection);
969         glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport);
970         
971         /* Very strange code here - it seems that certain bad values in the
972          * modelview matrix can cause gluUnProject to give bad results. */
973         if (mats->modelview[0] < badvalue &&
974             mats->modelview[0] > -badvalue)
975         {
976                 mats->modelview[0] = 0;
977         }
978         if (mats->modelview[5] < badvalue &&
979             mats->modelview[5] > -badvalue)
980         {
981                 mats->modelview[5] = 0;
982         }
983         
984         /* Set up viewport so that gluUnProject will give correct values */
985         mats->viewport[0] = 0;
986         mats->viewport[1] = 0;
987 }
988
989 /* *************** glPolygonOffset hack ************* */
990
991 /**
992  * \note \a viewdist is only for ortho at the moment.
993  */
994 void bglPolygonOffset(float viewdist, float dist) 
995 {
996         static float winmat[16], offset = 0.0;
997         
998         if (dist != 0.0f) {
999                 float offs;
1000                 
1001                 // glEnable(GL_POLYGON_OFFSET_FILL);
1002                 // glPolygonOffset(-1.0, -1.0);
1003
1004                 /* hack below is to mimic polygon offset */
1005                 glMatrixMode(GL_PROJECTION);
1006                 glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat);
1007                 
1008                 /* dist is from camera to center point */
1009                 
1010                 if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist;  // ortho tweaking
1011                 else offs = 0.0005f * dist;  // should be clipping value or so...
1012                 
1013                 winmat[14] -= offs;
1014                 offset += offs;
1015                 
1016                 glLoadMatrixf(winmat);
1017                 glMatrixMode(GL_MODELVIEW);
1018         }
1019         else {
1020
1021                 glMatrixMode(GL_PROJECTION);
1022                 winmat[14] += offset;
1023                 offset = 0.0;
1024                 glLoadMatrixf(winmat);
1025                 glMatrixMode(GL_MODELVIEW);
1026         }
1027 }
1028
1029 #if 0 /* UNUSED */
1030 void bglFlush(void) 
1031 {
1032         glFlush();
1033 #ifdef __APPLE__
1034 //      if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL))
1035 // XXX          myswapbuffers(); //hack to get mac intel graphics to show frontbuffer
1036 #endif
1037 }
1038 #endif
1039
1040 /* **** Color management helper functions for GLSL display/transform ***** */
1041
1042 /* Draw given image buffer on a screen using GLSL for display transform */
1043 void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
1044                        ColorManagedViewSettings *view_settings,
1045                        ColorManagedDisplaySettings *display_settings)
1046 {
1047         bool force_fallback = false;
1048         bool need_fallback = true;
1049
1050         /* Early out */
1051         if (ibuf->rect == NULL && ibuf->rect_float == NULL)
1052                 return;
1053
1054         /* Single channel images could not be transformed using GLSL yet */
1055         force_fallback |= ibuf->channels == 1;
1056
1057         /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
1058         force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
1059
1060         /* Try to draw buffer using GLSL display transform */
1061         if (force_fallback == false) {
1062                 int ok;
1063
1064                 if (ibuf->rect_float) {
1065                         if (ibuf->float_colorspace) {
1066                                 ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
1067                                                                                     ibuf->float_colorspace,
1068                                                                                     ibuf->dither, true);
1069                         }
1070                         else {
1071                                 ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
1072                                                                          ibuf->dither, true);
1073                         }
1074                 }
1075                 else {
1076                         ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
1077                                                                             ibuf->rect_colorspace,
1078                                                                             ibuf->dither, false);
1079                 }
1080
1081                 if (ok) {
1082                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1083                         glColor4f(1.0, 1.0, 1.0, 1.0);
1084
1085                         if (ibuf->rect_float) {
1086                                 int format = 0;
1087
1088                                 if (ibuf->channels == 3)
1089                                         format = GL_RGB;
1090                                 else if (ibuf->channels == 4)
1091                                         format = GL_RGBA;
1092                                 else
1093                                         BLI_assert(!"Incompatible number of channels for GLSL display");
1094
1095                                 if (format != 0) {
1096                                         glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
1097                                                          zoomfilter, ibuf->rect_float);
1098                                 }
1099                         }
1100                         else if (ibuf->rect) {
1101                                 /* ibuf->rect is always RGBA */
1102                                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
1103                                                  zoomfilter, ibuf->rect);
1104                         }
1105
1106                         IMB_colormanagement_finish_glsl_draw();
1107
1108                         need_fallback = false;
1109                 }
1110         }
1111
1112         /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
1113         if (need_fallback) {
1114                 unsigned char *display_buffer;
1115                 void *cache_handle;
1116
1117                 display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
1118
1119                 if (display_buffer)
1120                         glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
1121                                           zoomfilter, display_buffer);
1122
1123                 IMB_display_buffer_release(cache_handle);
1124         }
1125 }
1126
1127 void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
1128 {
1129         ColorManagedViewSettings *view_settings;
1130         ColorManagedDisplaySettings *display_settings;
1131
1132         IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
1133
1134         glaDrawImBuf_glsl(ibuf, x, y, zoomfilter, view_settings, display_settings);
1135 }
1136
1137 void cpack(unsigned int x)
1138 {
1139         glColor3ub(( (x)        & 0xFF),
1140                    (((x) >>  8) & 0xFF),
1141                    (((x) >> 16) & 0xFF));
1142 }
1143
1144 void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
1145 {
1146         float delta_x = 4.0f * UI_DPI_FAC / zoomx;
1147         float delta_y = 4.0f * UI_DPI_FAC / zoomy;
1148
1149         delta_x = min_ff(delta_x, border->xmax - border->xmin);
1150         delta_y = min_ff(delta_y, border->ymax - border->ymin);
1151
1152         /* left bottom corner */
1153         glBegin(GL_LINE_STRIP);
1154         glVertex2f(border->xmin, border->ymin + delta_y);
1155         glVertex2f(border->xmin, border->ymin);
1156         glVertex2f(border->xmin + delta_x, border->ymin);
1157         glEnd();
1158
1159         /* left top corner */
1160         glBegin(GL_LINE_STRIP);
1161         glVertex2f(border->xmin, border->ymax - delta_y);
1162         glVertex2f(border->xmin, border->ymax);
1163         glVertex2f(border->xmin + delta_x, border->ymax);
1164         glEnd();
1165
1166         /* right bottom corner */
1167         glBegin(GL_LINE_STRIP);
1168         glVertex2f(border->xmax - delta_x, border->ymin);
1169         glVertex2f(border->xmax, border->ymin);
1170         glVertex2f(border->xmax, border->ymin + delta_y);
1171         glEnd();
1172
1173         /* right top corner */
1174         glBegin(GL_LINE_STRIP);
1175         glVertex2f(border->xmax - delta_x, border->ymax);
1176         glVertex2f(border->xmax, border->ymax);
1177         glVertex2f(border->xmax, border->ymax - delta_y);
1178         glEnd();
1179 }