Cleanup: use r_* prefix for return args
[blender.git] / source / blender / editors / screen / glutil.c
index 0844d63d0b511c99e5b5ac6c9311189ae3e1bf1a..fd65d81baadcadb331ecbe803355f25dbdaf6dfa 100644 (file)
 #include "BLI_rect.h"
 #include "BLI_utildefines.h"
 #include "BLI_math.h"
-#include "BLI_threads.h"
 
-#include "BKE_blender.h"
-#include "BKE_colortools.h"
+#include "BKE_context.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf_types.h"
+
+#include "UI_interface.h"
+
 #ifndef GL_CLAMP_TO_EDGE
 #define GL_CLAMP_TO_EDGE                        0x812F
 #endif
@@ -130,13 +134,24 @@ const GLubyte stipple_diag_stripes_neg[128] = {
        0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
        0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80};
 
-
+const GLubyte stipple_checker_8px[128] = {
+       255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+       255,  0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+       0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+       0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+       255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+       255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+       0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+       0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
+
+/* UNUSED */
+#if 0
 void fdrawbezier(float vec[4][3])
 {
        float dist;
        float curve_res = 24, spline_step = 0.0f;
        
-       dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
+       dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
        
        /* check direction later, for top sockets */
        vec[1][0] = vec[0][0] + dist;
@@ -160,6 +175,7 @@ void fdrawbezier(float vec[4][3])
        }
        glEnd();
 }
+#endif
 
 void fdrawline(float x1, float y1, float x2, float y2)
 {
@@ -197,38 +213,30 @@ void fdrawcheckerboard(float x1, float y1, float x2, float y2)
 {
        unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50};
 
-       GLubyte checker_stipple[32 * 32 / 8] = {
-               255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
-               255,  0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
-               0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
-               0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
-               255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
-               255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
-               0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
-               0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
-       
        glColor3ubv(col1);
        glRectf(x1, y1, x2, y2);
        glColor3ubv(col2);
 
        glEnable(GL_POLYGON_STIPPLE);
-       glPolygonStipple(checker_stipple);
+       glPolygonStipple(stipple_checker_8px);
        glRectf(x1, y1, x2, y2);
        glDisable(GL_POLYGON_STIPPLE);
 }
 
-void sdrawline(short x1, short y1, short x2, short y2)
+void sdrawline(int x1, int y1, int x2, int y2)
 {
-       short v[2];
+       int v[2];
        
        glBegin(GL_LINE_STRIP);
        v[0] = x1; v[1] = y1;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x2; v[1] = y2;
-       glVertex2sv(v);
+       glVertex2iv(v);
        glEnd();
 }
 
+/* UNUSED */
+#if 0
 /*
  *     x1,y2
  *     |  \
@@ -237,47 +245,48 @@ void sdrawline(short x1, short y1, short x2, short y2)
  *     x1,y1-- x2,y1
  */
 
-static void sdrawtripoints(short x1, short y1, short x2, short y2)
+static void sdrawtripoints(int x1, int y1, int x2, int y2)
 {
-       short v[2];
+       int v[2];
        v[0] = x1; v[1] = y1;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x1; v[1] = y2;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x2; v[1] = y1;
-       glVertex2sv(v);
+       glVertex2iv(v);
 }
 
-void sdrawtri(short x1, short y1, short x2, short y2)
+void sdrawtri(int x1, int y1, int x2, int y2)
 {
        glBegin(GL_LINE_STRIP);
        sdrawtripoints(x1, y1, x2, y2);
        glEnd();
 }
 
-void sdrawtrifill(short x1, short y1, short x2, short y2)
+void sdrawtrifill(int x1, int y1, int x2, int y2)
 {
        glBegin(GL_TRIANGLES);
        sdrawtripoints(x1, y1, x2, y2);
        glEnd();
 }
+#endif
 
-void sdrawbox(short x1, short y1, short x2, short y2)
+void sdrawbox(int x1, int y1, int x2, int y2)
 {
-       short v[2];
+       int v[2];
        
        glBegin(GL_LINE_STRIP);
        
        v[0] = x1; v[1] = y1;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x1; v[1] = y2;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x2; v[1] = y2;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x2; v[1] = y1;
-       glVertex2sv(v);
+       glVertex2iv(v);
        v[0] = x1; v[1] = y1;
-       glVertex2sv(v);
+       glVertex2iv(v);
        
        glEnd();
 }
@@ -311,6 +320,8 @@ void set_inverted_drawing(int enable)
        GL_TOGGLE(GL_DITHER, !enable);
 }
 
+/* UNUSED */
+#if 0
 void sdrawXORline(int x0, int y0, int x1, int y1)
 {
        if (x0 == x1 && y0 == y1) return;
@@ -327,7 +338,7 @@ void sdrawXORline(int x0, int y0, int x1, int y1)
 
 void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
 {
-       static short old[4][2][2];
+       static int old[4][2][2];
        static char flags[4] = {0, 0, 0, 0};
        
        /* with builtin memory, max 4 lines */
@@ -338,8 +349,8 @@ void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
        if (nr == -1) { /* flush */
                for (nr = 0; nr < 4; nr++) {
                        if (flags[nr]) {
-                               glVertex2sv(old[nr][0]);
-                               glVertex2sv(old[nr][1]);
+                               glVertex2iv(old[nr][0]);
+                               glVertex2iv(old[nr][1]);
                                flags[nr] = 0;
                        }
                }
@@ -347,8 +358,8 @@ void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
        else {
                if (nr >= 0 && nr < 4) {
                        if (flags[nr]) {
-                               glVertex2sv(old[nr][0]);
-                               glVertex2sv(old[nr][1]);
+                               glVertex2iv(old[nr][0]);
+                               glVertex2iv(old[nr][1]);
                        }
 
                        old[nr][0][0] = x0;
@@ -381,6 +392,9 @@ void fdrawXORellipse(float xofs, float yofs, float hw, float hh)
 
        set_inverted_drawing(0);
 }
+
+#endif
+
 void fdrawXORcirc(float xofs, float yofs, float rad)
 {
        set_inverted_drawing(1);
@@ -453,7 +467,7 @@ void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y
        glBitmap(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy);
 }
 
-static int get_cached_work_texture(int *w_r, int *h_r)
+static int get_cached_work_texture(int *r_w, int *r_h)
 {
        static GLint texid = -1;
        static int tex_w = 256;
@@ -477,22 +491,23 @@ static int get_cached_work_texture(int *w_r, int *h_r)
                glBindTexture(GL_TEXTURE_2D, ltexid);
        }
 
-       *w_r = tex_w;
-       *h_r = tex_h;
+       *r_w = tex_w;
+       *r_h = tex_h;
        return texid;
 }
 
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY)
+void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY)
 {
        unsigned char *uc_rect = (unsigned char *) rect;
-       float *f_rect = (float *)rect;
+       const float *f_rect = (float *)rect;
        float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y);
        int ltexid = glaGetOneInteger(GL_TEXTURE_2D);
        int lrowlength = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
        int subpart_x, subpart_y, tex_w, tex_h;
        int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
        int texid = get_cached_work_texture(&tex_w, &tex_h);
-       
+       int components;
+
        /* Specify the color outside this function, and tex will modulate it.
         * This is useful for changing alpha without using glPixelTransferf()
         */
@@ -503,6 +518,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
        /* don't want nasty border artifacts */
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
 
 #ifdef __APPLE__
        /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
@@ -518,6 +534,33 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
        nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
        nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
 
+       if (format == GL_RGBA)
+               components = 4;
+       else if (format == GL_RGB)
+               components = 3;
+       else if (ELEM(format,  GL_LUMINANCE, GL_ALPHA))
+               components = 1;
+       else {
+               BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
+               return;
+       }
+
+       if (type == GL_FLOAT) {
+               /* need to set internal format to higher range float */
+
+               /* NOTE: this could fail on some drivers, like mesa,
+                *       but currently this code is only used by color
+                *       management stuff which already checks on whether
+                *       it's possible to use GL_RGBA16F_ARB
+                */
+
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
+       }
+       else {
+               /* switch to 8bit RGBA for byte buffer  */
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
+       }
+
        for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
                for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
                        int remainder_x = img_w - subpart_x * offset_x;
@@ -535,35 +578,35 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
                        if (subpart_w <= seamless || subpart_h <= seamless)
                                continue;
                        
-                       if (format == GL_FLOAT) {
-                               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]);
+                       if (type == GL_FLOAT) {
+                               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]);
                                
                                /* add an extra border of pixels so linear looks ok at edges of full image. */
                                if (subpart_w < tex_w)
-                                       glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+                                       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]);
                                if (subpart_h < tex_h)
-                                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]);
+                                       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]);
                                if (subpart_w < tex_w && subpart_h < tex_h)
-                                       glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+                                       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]);
                        }
                        else {
-                               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]);
+                               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]);
                                
                                if (subpart_w < tex_w)
-                                       glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+                                       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]);
                                if (subpart_h < tex_h)
-                                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]);
+                                       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]);
                                if (subpart_w < tex_w && subpart_h < tex_h)
-                                       glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+                                       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]);
                        }
 
                        glEnable(GL_TEXTURE_2D);
                        glBegin(GL_QUADS);
                        glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
-                       glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * xzoom);
+                       glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
 
                        glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
-                       glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * xzoom);
+                       glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
 
                        glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
                        glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
@@ -585,9 +628,9 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
 #endif
 }
 
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect)
+void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
 {
-       glaDrawPixelsTexScaled(x, y, img_w, img_h, format, rect, 1.0f, 1.0f);
+       glaDrawPixelsTexScaled(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f);
 }
 
 void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
@@ -646,17 +689,17 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
                glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w);
                if (format == GL_LUMINANCE || format == GL_RED) {
                        if (type == GL_FLOAT) {
-                               float *f_rect = (float *)rect;
+                               const float *f_rect = (float *)rect;
                                glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x));
                        }
                        else if (type == GL_INT || type == GL_UNSIGNED_INT) {
-                               int *i_rect = (int *)rect;
+                               const int *i_rect = (int *)rect;
                                glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y * row_w + off_x));
                        }
                }
                else { /* RGBA */
                        if (type == GL_FLOAT) {
-                               float *f_rect = (float *)rect;
+                               const float *f_rect = (float *)rect;
                                glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x) * 4);
                        }
                        else if (type == GL_UNSIGNED_BYTE) {
@@ -669,6 +712,18 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
        }
 }
 
+/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
+{
+       if (U.image_draw_method != IMAGE_DRAW_METHOD_DRAWPIXELS) {
+               glColor4f(1.0, 1.0, 1.0, 1.0);
+               glaDrawPixelsTex(x, y, img_w, img_h, format, type, zoomfilter, rect);
+       }
+       else {
+               glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect);
+       }
+}
+
 /* 2D Drawing Assistance */
 
 void glaDefine2DArea(rcti *screen_rect)
@@ -727,6 +782,18 @@ void gla2DSetMap(gla2DDrawInfo *di, rctf *rect)
        di->wo_to_sc[1] = sc_h / wo_h;
 }
 
+/** Save the current OpenGL state and initialize OpenGL for 2D
+ * rendering. glaEnd2DDraw should be called on the returned structure
+ * to free it and to return OpenGL to its previous state. The
+ * scissor rectangle is set to match the viewport.
+ *
+ * See glaDefine2DArea for an explanation of why this function uses integers.
+ *
+ * \param screen_rect The screen rectangle to be used for 2D drawing.
+ * \param world_rect The world rectangle that the 2D area represented
+ * by \a screen_rect is supposed to represent. If NULL it is assumed the
+ * world has a 1 to 1 mapping to the screen.
+ */
 gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) 
 {
        gla2DDrawInfo *di = MEM_mallocN(sizeof(*di), "gla2DDrawInfo");
@@ -762,17 +829,27 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
        return di;
 }
 
-void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r)
+/**
+ * Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space.
+ */
+void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y)
 {
-       *sc_x_r = (wo_x - di->world_rect.xmin) * di->wo_to_sc[0];
-       *sc_y_r = (wo_y - di->world_rect.ymin) * di->wo_to_sc[1];
+       *r_sc_x = (wo_x - di->world_rect.xmin) * di->wo_to_sc[0];
+       *r_sc_y = (wo_y - di->world_rect.ymin) * di->wo_to_sc[1];
 }
-void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2])
+
+/**
+ * Translate the \a world point from world coordinates into screen space.
+ */
+void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2])
 {
        screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0];
        screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1];
 }
 
+/**
+ * Restores the previous OpenGL state and frees the auxiliary gla data.
+ */
 void glaEnd2DDraw(gla2DDrawInfo *di)
 {
        glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
@@ -804,7 +881,7 @@ void bglBegin(int mode)
                glGetFloatv(GL_POINT_SIZE_RANGE, value);
                if (value[1] < 2.0f) {
                        glGetFloatv(GL_POINT_SIZE, value);
-                       pointhack = floor(value[0] + 0.5f);
+                       pointhack = iroundf(value[0]);
                        if (pointhack > 4) pointhack = 4;
                }
                else {
@@ -911,8 +988,10 @@ void bgl_get_mats(bglMats *mats)
 
 /* *************** glPolygonOffset hack ************* */
 
-/* dist is only for ortho now... */
-void bglPolygonOffset(float viewdist, float dist) 
+/**
+ * \note \a viewdist is only for ortho at the moment.
+ */
+void bglPolygonOffset(float viewdist, float dist)
 {
        static float winmat[16], offset = 0.0;
        
@@ -928,8 +1007,25 @@ void bglPolygonOffset(float viewdist, float dist)
                
                /* dist is from camera to center point */
                
-               if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist;  // ortho tweaking
-               else offs = 0.0005f * dist;  // should be clipping value or so...
+               if (winmat[15] > 0.5f) {
+#if 1
+                       offs = 0.00001f * dist * viewdist;  // ortho tweaking
+#else
+                       static float depth_fac = 0.0f;
+                       if (depth_fac == 0.0f) {
+                               int depthbits;
+                               glGetIntegerv(GL_DEPTH_BITS, &depthbits);
+                               depth_fac = 1.0f / (float)((1 << depthbits) - 1);
+                       }
+                       offs = (-1.0 / winmat[10]) * dist * depth_fac;
+
+                       UNUSED_VARS(viewdist);
+#endif
+               }
+               else {
+                       /* should be clipping value or so... */
+                       offs = 0.0005f * dist;
+               }
                
                winmat[14] -= offs;
                offset += offs;
@@ -957,3 +1053,144 @@ void bglFlush(void)
 #endif
 }
 #endif
+
+/* **** Color management helper functions for GLSL display/transform ***** */
+
+/* Draw given image buffer on a screen using GLSL for display transform */
+void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
+                       ColorManagedViewSettings *view_settings,
+                       ColorManagedDisplaySettings *display_settings)
+{
+       bool force_fallback = false;
+       bool need_fallback = true;
+
+       /* Early out */
+       if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+               return;
+
+       /* Single channel images could not be transformed using GLSL yet */
+       force_fallback |= ibuf->channels == 1;
+
+       /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
+       force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
+
+       /* Try to draw buffer using GLSL display transform */
+       if (force_fallback == false) {
+               int ok;
+
+               if (ibuf->rect_float) {
+                       if (ibuf->float_colorspace) {
+                               ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
+                                                                                   ibuf->float_colorspace,
+                                                                                   ibuf->dither, true);
+                       }
+                       else {
+                               ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
+                                                                        ibuf->dither, true);
+                       }
+               }
+               else {
+                       ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
+                                                                           ibuf->rect_colorspace,
+                                                                           ibuf->dither, false);
+               }
+
+               if (ok) {
+                       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+                       glColor4f(1.0, 1.0, 1.0, 1.0);
+
+                       if (ibuf->rect_float) {
+                               int format = 0;
+
+                               if (ibuf->channels == 3)
+                                       format = GL_RGB;
+                               else if (ibuf->channels == 4)
+                                       format = GL_RGBA;
+                               else
+                                       BLI_assert(!"Incompatible number of channels for GLSL display");
+
+                               if (format != 0) {
+                                       glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
+                                                        zoomfilter, ibuf->rect_float);
+                               }
+                       }
+                       else if (ibuf->rect) {
+                               /* ibuf->rect is always RGBA */
+                               glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+                                                zoomfilter, ibuf->rect);
+                       }
+
+                       IMB_colormanagement_finish_glsl_draw();
+
+                       need_fallback = false;
+               }
+       }
+
+       /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
+       if (need_fallback) {
+               unsigned char *display_buffer;
+               void *cache_handle;
+
+               display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
+
+               if (display_buffer)
+                       glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+                                         zoomfilter, display_buffer);
+
+               IMB_display_buffer_release(cache_handle);
+       }
+}
+
+void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
+{
+       ColorManagedViewSettings *view_settings;
+       ColorManagedDisplaySettings *display_settings;
+
+       IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
+
+       glaDrawImBuf_glsl(ibuf, x, y, zoomfilter, view_settings, display_settings);
+}
+
+void cpack(unsigned int x)
+{
+       glColor3ub(( (x)        & 0xFF),
+                  (((x) >>  8) & 0xFF),
+                  (((x) >> 16) & 0xFF));
+}
+
+void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
+{
+       float delta_x = 4.0f * UI_DPI_FAC / zoomx;
+       float delta_y = 4.0f * UI_DPI_FAC / zoomy;
+
+       delta_x = min_ff(delta_x, border->xmax - border->xmin);
+       delta_y = min_ff(delta_y, border->ymax - border->ymin);
+
+       /* left bottom corner */
+       glBegin(GL_LINE_STRIP);
+       glVertex2f(border->xmin, border->ymin + delta_y);
+       glVertex2f(border->xmin, border->ymin);
+       glVertex2f(border->xmin + delta_x, border->ymin);
+       glEnd();
+
+       /* left top corner */
+       glBegin(GL_LINE_STRIP);
+       glVertex2f(border->xmin, border->ymax - delta_y);
+       glVertex2f(border->xmin, border->ymax);
+       glVertex2f(border->xmin + delta_x, border->ymax);
+       glEnd();
+
+       /* right bottom corner */
+       glBegin(GL_LINE_STRIP);
+       glVertex2f(border->xmax - delta_x, border->ymin);
+       glVertex2f(border->xmax, border->ymin);
+       glVertex2f(border->xmax, border->ymin + delta_y);
+       glEnd();
+
+       /* right top corner */
+       glBegin(GL_LINE_STRIP);
+       glVertex2f(border->xmax - delta_x, border->ymax);
+       glVertex2f(border->xmax, border->ymax);
+       glVertex2f(border->xmax, border->ymax - delta_y);
+       glEnd();
+}