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