Cleanup: use r_* prefix for return args
[blender.git] / source / blender / editors / screen / glutil.c
index 50430399f095076df102f10f3de276cc63b58789..fd65d81baadcadb331ecbe803355f25dbdaf6dfa 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_userdef_types.h"
 #include "DNA_vec_types.h"
 
+#include "BLI_rect.h"
 #include "BLI_utildefines.h"
-
-#include "BKE_colortools.h"
-
 #include "BLI_math.h"
-#include "BLI_threads.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
@@ -53,7 +59,7 @@
 /* ******************************************** */
 
 /* defined in BIF_gl.h */
-GLubyte stipple_halftone[128] = {
+const GLubyte stipple_halftone[128] = {
        0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
        0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 
        0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
@@ -80,7 +86,7 @@ GLubyte stipple_halftone[128] = {
  *     00000000 */
 
 
-GLubyte stipple_quarttone[128] = { 
+const GLubyte stipple_quarttone[128] = {
        136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
        136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
        136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
@@ -91,8 +97,8 @@ GLubyte stipple_quarttone[128] = {
        136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
 
 
-GLubyte stipple_diag_stripes_pos[128] = {
-    0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
+const GLubyte stipple_diag_stripes_pos[128] = {
+       0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
        0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
        0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
        0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
@@ -110,8 +116,8 @@ GLubyte stipple_diag_stripes_pos[128] = {
        0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
 
 
-GLubyte stipple_diag_stripes_neg[128] = {
-    0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
+const GLubyte stipple_diag_stripes_neg[128] = {
+       0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
        0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
        0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
        0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
@@ -128,22 +134,33 @@ 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;
-       vec[1][1]= vec[0][1];
+       vec[1][0] = vec[0][0] + dist;
+       vec[1][1] = vec[0][1];
        
-       vec[2][0]= vec[3][0]-dist;
-       vec[2][1]= vec[3][1];
+       vec[2][0] = vec[3][0] - dist;
+       vec[2][1] = vec[3][1];
        /* we can reuse the dist variable here to increment the GL curve eval amount*/
-       dist = 1.0f/curve_res;
+       dist = 1.0f / curve_res;
        
        cpack(0x0);
        glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
@@ -158,6 +175,7 @@ void fdrawbezier(float vec[4][3])
        }
        glEnd();
 }
+#endif
 
 void fdrawline(float x1, float y1, float x2, float y2)
 {
@@ -193,40 +211,32 @@ void fdrawbox(float x1, float y1, float x2, float y2)
 
 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};
-       
+       unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50};
+
        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
  *     |  \
@@ -235,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];
-       v[0]= x1; v[1]= y1;
-       glVertex2sv(v);
-       v[0]= x1; v[1]= y2;
-       glVertex2sv(v);
-       v[0]= x2; v[1]= y1;
-       glVertex2sv(v);
+       int v[2];
+       v[0] = x1; v[1] = y1;
+       glVertex2iv(v);
+       v[0] = x1; v[1] = y2;
+       glVertex2iv(v);
+       v[0] = x2; v[1] = y1;
+       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();
 }
@@ -285,30 +296,35 @@ void sdrawbox(short x1, short y1, short x2, short y2)
 
 void setlinestyle(int nr)
 {
-       if (nr==0) {
+       if (nr == 0) {
                glDisable(GL_LINE_STIPPLE);
        }
        else {
                
                glEnable(GL_LINE_STIPPLE);
-               glLineStipple(nr, 0xAAAA);
+               if (U.pixelsize > 1.0f)
+                       glLineStipple(nr, 0xCCCC);
+               else
+                       glLineStipple(nr, 0xAAAA);
        }
 }
 
-       /* Invert line handling */
+/* Invert line handling */
        
-#define glToggle(mode, onoff)  (((onoff)?glEnable:glDisable)(mode))
+#define GL_TOGGLE(mode, onoff)  (((onoff) ? glEnable : glDisable)(mode))
 
 void set_inverted_drawing(int enable) 
 {
-       glLogicOp(enable?GL_INVERT:GL_COPY);
-       glToggle(GL_COLOR_LOGIC_OP, enable);
-       glToggle(GL_DITHER, !enable);
+       glLogicOp(enable ? GL_INVERT : GL_COPY);
+       GL_TOGGLE(GL_COLOR_LOGIC_OP, 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;
+       if (x0 == x1 && y0 == y1) return;
 
        set_inverted_drawing(1);
        
@@ -322,36 +338,36 @@ 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 char flags[4]= {0, 0, 0, 0};
+       static int old[4][2][2];
+       static char flags[4] = {0, 0, 0, 0};
        
-               /* with builtin memory, max 4 lines */
+       /* with builtin memory, max 4 lines */
 
        set_inverted_drawing(1);
                
        glBegin(GL_LINES);
-       if (nr== -1) { /* flush */
-               for (nr=0; nr<4; nr++) {
+       if (nr == -1) { /* flush */
+               for (nr = 0; nr < 4; nr++) {
                        if (flags[nr]) {
-                               glVertex2sv(old[nr][0]);
-                               glVertex2sv(old[nr][1]);
-                               flags[nr]= 0;
+                               glVertex2iv(old[nr][0]);
+                               glVertex2iv(old[nr][1]);
+                               flags[nr] = 0;
                        }
                }
        }
        else {
-               if (nr>=0 && nr<4) {
+               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;
-                       old[nr][0][1]= y0;
-                       old[nr][1][0]= x1;
-                       old[nr][1][1]= y1;
+                       old[nr][0][0] = x0;
+                       old[nr][0][1] = y0;
+                       old[nr][1][0] = x1;
+                       old[nr][1][1] = y1;
                        
-                       flags[nr]= 1;
+                       flags[nr] = 1;
                }
                
                glVertex2i(x0, y0);
@@ -364,25 +380,28 @@ void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
 
 void fdrawXORellipse(float xofs, float yofs, float hw, float hh)
 {
-       if (hw==0) return;
+       if (hw == 0) return;
 
        set_inverted_drawing(1);
 
        glPushMatrix();
        glTranslatef(xofs, yofs, 0.0f);
        glScalef(1.0f, hh / hw, 1.0f);
-       glutil_draw_lined_arc(0.0, M_PI*2.0, hw, 20);
+       glutil_draw_lined_arc(0.0, M_PI * 2.0, hw, 20);
        glPopMatrix();
 
        set_inverted_drawing(0);
 }
+
+#endif
+
 void fdrawXORcirc(float xofs, float yofs, float rad)
 {
        set_inverted_drawing(1);
 
        glPushMatrix();
        glTranslatef(xofs, yofs, 0.0);
-       glutil_draw_lined_arc(0.0, M_PI*2.0, rad, 20);
+       glutil_draw_lined_arc(0.0, M_PI * 2.0, rad, 20);
        glPopMatrix();
 
        set_inverted_drawing(0);
@@ -394,11 +413,11 @@ void glutil_draw_filled_arc(float start, float angle, float radius, int nsegment
        
        glBegin(GL_TRIANGLE_FAN);
        glVertex2f(0.0, 0.0);
-       for (i=0; i<nsegments; i++) {
-               float t= (float) i/(nsegments-1);
-               float cur= start + t*angle;
+       for (i = 0; i < nsegments; i++) {
+               float t = (float) i / (nsegments - 1);
+               float cur = start + t * angle;
                
-               glVertex2f(cosf(cur)*radius, sinf(cur)*radius);
+               glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
        }
        glEnd();
 }
@@ -408,11 +427,11 @@ void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments
        int i;
        
        glBegin(GL_LINE_STRIP);
-       for (i=0; i<nsegments; i++) {
-               float t= (float) i/(nsegments-1);
-               float cur= start + t*angle;
+       for (i = 0; i < nsegments; i++) {
+               float t = (float) i / (nsegments - 1);
+               float cur = start + t * angle;
                
-               glVertex2f(cosf(cur)*radius, sinf(cur)*radius);
+               glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
        }
        glEnd();
 }
@@ -433,29 +452,29 @@ float glaGetOneFloat(int param)
 
 void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y)
 {
-       GLubyte dummy= 0;
+       GLubyte dummy = 0;
 
-               /* As long as known good coordinates are correct
-                * this is guaranteed to generate an ok raster
-                * position (ignoring potential (real) overflow
-                * issues).
-                */
+       /* As long as known good coordinates are correct
+        * this is guaranteed to generate an ok raster
+        * position (ignoring potential (real) overflow
+        * issues).
+        */
        glRasterPos2f(known_good_x, known_good_y);
 
-               /* Now shift the raster position to where we wanted
-                * it in the first place using the glBitmap trick.
-                */
+       /* Now shift the raster position to where we wanted
+        * it in the first place using the glBitmap trick.
+        */
        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;
-       static int tex_h= 256;
+       static GLint texid = -1;
+       static int tex_w = 256;
+       static int tex_h = 256;
 
-       if (texid==-1) {
-               GLint ltexid= glaGetOneInteger(GL_TEXTURE_2D);
+       if (texid == -1) {
+               GLint ltexid = glaGetOneInteger(GL_TEXTURE_2D);
                unsigned char *tbuf;
 
                glGenTextures(1, (GLuint *)&texid);
@@ -465,29 +484,30 @@ static int get_cached_work_texture(int *w_r, int *h_r)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-               tbuf= MEM_callocN(tex_w*tex_h*4, "tbuf");
+               tbuf = MEM_callocN(tex_w * tex_h * 4, "tbuf");
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf);
                MEM_freeN(tbuf);
 
                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;
-       float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y);
-       int ltexid= glaGetOneInteger(GL_TEXTURE_2D);
-       int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
+       unsigned char *uc_rect = (unsigned char *) 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 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()
         */
@@ -498,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 */
@@ -505,66 +526,93 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
 #endif
        
        /* setup seamless 2=on, 0=off */
-       seamless= ((tex_w<img_w || tex_h<img_h) && tex_w>2 && tex_h>2)? 2: 0;
+       seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
        
-       offset_x= tex_w - seamless;
-       offset_y= tex_h - seamless;
+       offset_x = tex_w - seamless;
+       offset_y = tex_h - seamless;
        
-       nsubparts_x= (img_w + (offset_x - 1))/(offset_x);
-       nsubparts_y= (img_h + (offset_y - 1))/(offset_y);
-
-       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;
-                       int remainder_y= img_h-subpart_y*offset_y;
-                       int subpart_w= (remainder_x<tex_w)? remainder_x: tex_w;
-                       int subpart_h= (remainder_y<tex_h)? remainder_y: tex_h;
-                       int offset_left= (seamless && subpart_x!=0)? 1: 0;
-                       int offset_bot= (seamless && subpart_y!=0)? 1: 0;
-                       int offset_right= (seamless && remainder_x>tex_w)? 1: 0;
-                       int offset_top= (seamless && remainder_y>tex_h)? 1: 0;
-                       float rast_x= x+subpart_x*offset_x*xzoom;
-                       float rast_y= y+subpart_y*offset_y*yzoom;
+       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;
+                       int remainder_y = img_h - subpart_y * offset_y;
+                       int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
+                       int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
+                       int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
+                       int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
+                       int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
+                       int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
+                       float rast_x = x + subpart_x * offset_x * xzoom;
+                       float rast_y = y + subpart_y * offset_y * yzoom;
                        
                        /* check if we already got these because we always get 2 more when doing seamless*/
-                       if (subpart_w<=seamless || subpart_h<=seamless)
+                       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]);
-                               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]);
-                               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]);
+                               if (subpart_w < tex_w)
+                                       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, 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, 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]);
-                               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]);
-                               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]);
+                               if (subpart_w < tex_w)
+                                       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, 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, 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);
+                       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 * 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);
+                       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 * 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);
+                       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);
 
-                       glTexCoord2f((float)(0 + offset_left)/tex_w, (float)(subpart_h - offset_top)/tex_h);
-                       glVertex2f(rast_x + (float)offset_left*xzoom, rast_y + (float)(subpart_h - offset_top)*yzoom*scaleY);
+                       glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
+                       glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
                        glEnd();
                        glDisable(GL_TEXTURE_2D);
                }
@@ -580,58 +628,58 @@ 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)
 {
-       float xzoom= glaGetOneFloat(GL_ZOOM_X);
-       float yzoom= glaGetOneFloat(GL_ZOOM_Y);
-               
-               /* The pixel space coordinate of the intersection of
-                * the [zoomed] image with the origin.
-                */
-       float ix= -x/xzoom;
-       float iy= -y/yzoom;
-       
-               /* The maximum pixel amounts the image can be cropped
-                * at the lower left without exceeding the origin.
-                */
-       int off_x= floor(MAX2(ix, 0));
-       int off_y= floor(MAX2(iy, 0));
+       float xzoom = glaGetOneFloat(GL_ZOOM_X);
+       float yzoom = glaGetOneFloat(GL_ZOOM_Y);
+
+       /* The pixel space coordinate of the intersection of
+        * the [zoomed] image with the origin.
+        */
+       float ix = -x / xzoom;
+       float iy = -y / yzoom;
                
-               /* The zoomed space coordinate of the raster position 
-                * (starting at the lower left most unclipped pixel).
-                */
-       float rast_x= x + off_x*xzoom;
-       float rast_y= y + off_y*yzoom;
+       /* The maximum pixel amounts the image can be cropped
+        * at the lower left without exceeding the origin.
+        */
+       int off_x = floor(max_ff(ix, 0.0f));
+       int off_y = floor(max_ff(iy, 0.0f));
+
+       /* The zoomed space coordinate of the raster position
+        * (starting at the lower left most unclipped pixel).
+        */
+       float rast_x = x + off_x * xzoom;
+       float rast_y = y + off_y * yzoom;
 
        GLfloat scissor[4];
        int draw_w, draw_h;
 
-               /* Determine the smallest number of pixels we need to draw
-                * before the image would go off the upper right corner.
-                * 
-                * It may seem this is just an optimization but some graphics 
-                * cards (ATI) freak out if there is a large zoom factor and
-                * a large number of pixels off the screen (probably at some
-                * level the number of image pixels to draw is getting multiplied
-                * by the zoom and then clamped). Making sure we draw the
-                * fewest pixels possible keeps everyone mostly happy (still
-                * fails if we zoom in on one really huge pixel so that it
-                * covers the entire screen).
-                */
+       /* Determine the smallest number of pixels we need to draw
+        * before the image would go off the upper right corner.
+        *
+        * It may seem this is just an optimization but some graphics
+        * cards (ATI) freak out if there is a large zoom factor and
+        * a large number of pixels off the screen (probably at some
+        * level the number of image pixels to draw is getting multiplied
+        * by the zoom and then clamped). Making sure we draw the
+        * fewest pixels possible keeps everyone mostly happy (still
+        * fails if we zoom in on one really huge pixel so that it
+        * covers the entire screen).
+        */
        glGetFloatv(GL_SCISSOR_BOX, scissor);
-       draw_w = MIN2(img_w-off_x, ceil((scissor[2]-rast_x)/xzoom));
-       draw_h = MIN2(img_h-off_y, ceil((scissor[3]-rast_y)/yzoom));
+       draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom));
+       draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));
 
-       if (draw_w>0 && draw_h>0) {
+       if (draw_w > 0 && draw_h > 0) {
                int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
 
-                       /* Don't use safe RasterPos (slower) if we can avoid it. */
-               if (rast_x>=0 && rast_y>=0) {
+               /* Don't use safe RasterPos (slower) if we can avoid it. */
+               if (rast_x >= 0 && rast_y >= 0) {
                        glRasterPos2f(rast_x, rast_y);
                }
                else {
@@ -639,24 +687,24 @@ 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;
-                               glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x));
+               if (format == GL_LUMINANCE || format == GL_RED) {
+                       if (type == GL_FLOAT) {
+                               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;
-                               glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y*row_w + off_x));
+                       else if (type == GL_INT || type == GL_UNSIGNED_INT) {
+                               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;
-                               glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x)*4);
+                       if (type == GL_FLOAT) {
+                               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) {
-                               unsigned char *uc_rect= (unsigned char *) rect;
-                               glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y*row_w + off_x)*4);
+                       else if (type == GL_UNSIGNED_BYTE) {
+                               unsigned char *uc_rect = (unsigned char *) rect;
+                               glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y * row_w + off_x) * 4);
                        }
                }
                
@@ -664,26 +712,38 @@ 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)
 {
-       int sc_w= screen_rect->xmax - screen_rect->xmin + 1;
-       int sc_h= screen_rect->ymax - screen_rect->ymin + 1;
+       const int sc_w = BLI_rcti_size_x(screen_rect) + 1;
+       const int sc_h = BLI_rcti_size_y(screen_rect) + 1;
 
        glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
        glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
 
-               /* The 0.375 magic number is to shift the matrix so that
-                * both raster and vertex integer coordinates fall at pixel
-                * centers properly. For a longer discussion see the OpenGL
-                * Programming Guide, Appendix H, Correctness Tips.
-                */
+       /* The GLA_PIXEL_OFS magic number is to shift the matrix so that
+        * both raster and vertex integer coordinates fall at pixel
+        * centers properly. For a longer discussion see the OpenGL
+        * Programming Guide, Appendix H, Correctness Tips.
+        */
 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1);
-       glTranslatef(0.375, 0.375, 0.0);
+       glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0);
 
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
@@ -703,7 +763,7 @@ struct gla2DDrawInfo {
 
 void gla2DGetMap(gla2DDrawInfo *di, rctf *rect) 
 {
-       *rect= di->world_rect;
+       *rect = di->world_rect;
 }
 
 void gla2DSetMap(gla2DDrawInfo *di, rctf *rect) 
@@ -711,20 +771,32 @@ void gla2DSetMap(gla2DDrawInfo *di, rctf *rect)
        int sc_w, sc_h;
        float wo_w, wo_h;
 
-       di->world_rect= *rect;
+       di->world_rect = *rect;
        
-       sc_w= (di->screen_rect.xmax-di->screen_rect.xmin);
-       sc_h= (di->screen_rect.ymax-di->screen_rect.ymin);
-       wo_w= (di->world_rect.xmax-di->world_rect.xmin);
-       wo_h= (di->world_rect.ymax-di->world_rect.ymin);
+       sc_w = BLI_rcti_size_x(&di->screen_rect);
+       sc_h = BLI_rcti_size_y(&di->screen_rect);
+       wo_w = BLI_rcti_size_x(&di->world_rect);
+       wo_h = BLI_rcti_size_y(&di->world_rect);
        
-       di->wo_to_sc[0]= sc_w/wo_w;
-       di->wo_to_sc[1]= sc_h/wo_h;
+       di->wo_to_sc[0] = sc_w / wo_w;
+       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");
+       gla2DDrawInfo *di = MEM_mallocN(sizeof(*di), "gla2DDrawInfo");
        int sc_w, sc_h;
        float wo_w, wo_h;
 
@@ -733,9 +805,9 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
        glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat);
        glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat);
 
-       di->screen_rect= *screen_rect;
+       di->screen_rect = *screen_rect;
        if (world_rect) {
-               di->world_rect= *world_rect;
+               di->world_rect = *world_rect;
        }
        else {
                di->world_rect.xmin = di->screen_rect.xmin;
@@ -744,30 +816,40 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
                di->world_rect.ymax = di->screen_rect.ymax;
        }
 
-       sc_w= (di->screen_rect.xmax-di->screen_rect.xmin);
-       sc_h= (di->screen_rect.ymax-di->screen_rect.ymin);
-       wo_w= (di->world_rect.xmax-di->world_rect.xmin);
-       wo_h= (di->world_rect.ymax-di->world_rect.ymin);
+       sc_w = BLI_rcti_size_x(&di->screen_rect);
+       sc_h = BLI_rcti_size_y(&di->screen_rect);
+       wo_w = BLI_rcti_size_x(&di->world_rect);
+       wo_h = BLI_rcti_size_y(&di->world_rect);
 
-       di->wo_to_sc[0]= sc_w/wo_w;
-       di->wo_to_sc[1]= sc_h/wo_h;
+       di->wo_to_sc[0] = sc_w / wo_w;
+       di->wo_to_sc[1] = sc_h / wo_h;
 
        glaDefine2DArea(&di->screen_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];
+       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]);
@@ -781,10 +863,10 @@ void glaEnd2DDraw(gla2DDrawInfo *di)
 }
 #endif
 
-/* **************** glPoint hack ************************ */
+/* **************** GL_POINT hack ************************ */
 
-static int curmode=0;
-static int pointhack=0;
+static int curmode = 0;
+static int pointhack = 0;
 static GLubyte Squaredot[16] = {0xff, 0xff, 0xff, 0xff,
                                 0xff, 0xff, 0xff, 0xff,
                                 0xff, 0xff, 0xff, 0xff,
@@ -792,17 +874,19 @@ static GLubyte Squaredot[16] = {0xff, 0xff, 0xff, 0xff,
 
 void bglBegin(int mode)
 {
-       curmode= mode;
+       curmode = mode;
        
-       if (mode==GL_POINTS) {
+       if (mode == GL_POINTS) {
                float value[4];
                glGetFloatv(GL_POINT_SIZE_RANGE, value);
                if (value[1] < 2.0f) {
                        glGetFloatv(GL_POINT_SIZE, value);
-                       pointhack= floor(value[0] + 0.5f);
-                       if (pointhack>4) pointhack= 4;
+                       pointhack = iroundf(value[0]);
+                       if (pointhack > 4) pointhack = 4;
+               }
+               else {
+                       glBegin(mode);
                }
-               else glBegin(mode);
        }
 }
 
@@ -814,8 +898,8 @@ int bglPointHack(void)
        glGetFloatv(GL_POINT_SIZE_RANGE, value);
        if (value[1] < 2.0f) {
                glGetFloatv(GL_POINT_SIZE, value);
-               pointhack_px= floorf(value[0]+0.5f);
-               if (pointhack_px>4) pointhack_px= 4;
+               pointhack_px = floorf(value[0] + 0.5f);
+               if (pointhack_px > 4) pointhack_px = 4;
                return pointhack_px;
        }
        return 0;
@@ -825,46 +909,52 @@ int bglPointHack(void)
 void bglVertex3fv(const float vec[3])
 {
        switch (curmode) {
-       case GL_POINTS:
-               if (pointhack) {
-                       glRasterPos3fv(vec);
-                       glBitmap(pointhack, pointhack, (float)pointhack/2.0f, (float)pointhack/2.0f, 0.0, 0.0, Squaredot);
-               }
-               else glVertex3fv(vec);
-               break;
+               case GL_POINTS:
+                       if (pointhack) {
+                               glRasterPos3fv(vec);
+                               glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot);
+                       }
+                       else {
+                               glVertex3fv(vec);
+                       }
+                       break;
        }
 }
 
 void bglVertex3f(float x, float y, float z)
 {
        switch (curmode) {
-       case GL_POINTS:
-               if (pointhack) {
-                       glRasterPos3f(x, y, z);
-                       glBitmap(pointhack, pointhack, (float)pointhack/2.0f, (float)pointhack/2.0f, 0.0, 0.0, Squaredot);
-               }
-               else glVertex3f(x, y, z);
-               break;
+               case GL_POINTS:
+                       if (pointhack) {
+                               glRasterPos3f(x, y, z);
+                               glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot);
+                       }
+                       else {
+                               glVertex3f(x, y, z);
+                       }
+                       break;
        }
 }
 
 void bglVertex2fv(const float vec[2])
 {
        switch (curmode) {
-       case GL_POINTS:
-               if (pointhack) {
-                       glRasterPos2fv(vec);
-                       glBitmap(pointhack, pointhack, (float)pointhack/2, pointhack/2, 0.0, 0.0, Squaredot);
-               }
-               else glVertex2fv(vec);
-               break;
+               case GL_POINTS:
+                       if (pointhack) {
+                               glRasterPos2fv(vec);
+                               glBitmap(pointhack, pointhack, (float)pointhack / 2, pointhack / 2, 0.0, 0.0, Squaredot);
+                       }
+                       else {
+                               glVertex2fv(vec);
+                       }
+                       break;
        }
 }
 
 
 void bglEnd(void)
 {
-       if (pointhack) pointhack= 0;
+       if (pointhack) pointhack = 0;
        else glEnd();
        
 }
@@ -872,7 +962,7 @@ void bglEnd(void)
 /* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */
 void bgl_get_mats(bglMats *mats)
 {
-       const double badvalue= 1.0e-6;
+       const double badvalue = 1.0e-6;
 
        glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview);
        glGetDoublev(GL_PROJECTION_MATRIX, mats->projection);
@@ -898,10 +988,12 @@ 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;    
+       static float winmat[16], offset = 0.0;
        
        if (dist != 0.0f) {
                float offs;
@@ -915,11 +1007,28 @@ 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;
+               winmat[14] -= offs;
+               offset += offs;
                
                glLoadMatrixf(winmat);
                glMatrixMode(GL_MODELVIEW);
@@ -927,8 +1036,8 @@ void bglPolygonOffset(float viewdist, float dist)
        else {
 
                glMatrixMode(GL_PROJECTION);
-               winmat[14]+= offset;
-               offset= 0.0;
+               winmat[14] += offset;
+               offset = 0.0;
                glLoadMatrixf(winmat);
                glMatrixMode(GL_MODELVIEW);
        }
@@ -944,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();
+}