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