Clip invisible parts of image when drawing in 2D textures and GLSL Modes
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 6 May 2016 14:54:07 +0000 (16:54 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 6 May 2016 14:54:07 +0000 (16:54 +0200)
This commit avoids draw of invisible parts of image in image editor,
making it faster to re-draw the image.

Especially handy when painting on a high-res image when zoomed-in.

source/blender/editors/include/BIF_glutil.h
source/blender/editors/screen/glutil.c
source/blender/editors/space_image/image_draw.c

index e45e5f5e7abeaa3c0ed34c75e7fcfbe28230a5ac..0ac5c17a55242e6f35b6279341ae5eb37c273d0d 100644 (file)
@@ -143,6 +143,8 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
  */
 
 void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
+void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
+                               float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
 
 /**
  * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
@@ -150,9 +152,13 @@ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int ty
  * needs glaDefine2DArea to be set.
  */
 void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
+void glaDrawPixelsAuto_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
+                                float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
 
 
 void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY);
+void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
+                                     float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
 
 /* 2D Drawing Assistance */
 
@@ -205,9 +211,21 @@ void bgl_get_mats(bglMats *mats);
 void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter,
                        struct ColorManagedViewSettings *view_settings,
                        struct ColorManagedDisplaySettings *display_settings);
+void glaDrawImBuf_glsl_clipping(struct ImBuf *ibuf, float x, float y, int zoomfilter,
+                                struct ColorManagedViewSettings *view_settings,
+                                struct ColorManagedDisplaySettings *display_settings,
+                                float clip_min_x, float clip_min_y,
+                                float clip_max_x, float clip_max_y);
+
 
 /* Draw imbuf on a screen, preferably using GLSL display transform */
 void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter);
+void glaDrawImBuf_glsl_ctx_clipping(const struct bContext *C,
+                                    struct ImBuf *ibuf,
+                                    float x, float y,
+                                    int zoomfilter,
+                                    float clip_min_x, float clip_min_y,
+                                    float clip_max_x, float clip_max_y);
 
 void glaDrawBorderCorners(const struct rcti *border, float zoomx, float zoomy);
 
index a1c330d9dfff2df80c3d7c586a6b3b7c547f3b31..cbf87062955f29dbf49851e366aaa62c1e810508 100644 (file)
@@ -368,7 +368,11 @@ static int get_cached_work_texture(int *r_w, int *r_h)
        return texid;
 }
 
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY)
+void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
+                                     int format, int type, int zoomfilter, void *rect,
+                                     float scaleX, float scaleY,
+                                     float clip_min_x, float clip_min_y,
+                                     float clip_max_x, float clip_max_y)
 {
        unsigned char *uc_rect = (unsigned char *) rect;
        const float *f_rect = (float *)rect;
@@ -377,6 +381,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
        int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
        int texid = get_cached_work_texture(&tex_w, &tex_h);
        int components;
+       const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
 
        /* Specify the color outside this function, and tex will modulate it.
         * This is useful for changing alpha without using glPixelTransferf()
@@ -443,11 +448,23 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
                        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)
                                continue;
-                       
+
+                       if (use_clipping) {
+                               if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x ||
+                                   rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y)
+                               {
+                                       continue;
+                               }
+                               if (rast_x + (float)offset_left * xzoom > clip_max_x ||
+                                   rast_y + (float)offset_bot * yzoom > clip_max_y)
+                               {
+                                       continue;
+                               }
+                       }
+
                        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]);
                                
@@ -497,9 +514,26 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
 #endif
 }
 
+void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
+                            int format, int type, int zoomfilter, void *rect,
+                            float scaleX, float scaleY)
+{
+       glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
+                                       scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f);
+}
+
 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, type, zoomfilter, rect, 1.0f, 1.0f);
+       glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
+                                       0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h,
+                               int format, int type, int zoomfilter, void *rect,
+                               float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y)
+{
+       glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
+                                       clip_min_x, clip_min_y, clip_max_x, clip_max_y);
 }
 
 void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
@@ -580,17 +614,27 @@ 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)
+void glaDrawPixelsAuto_clipping(float x, float y, int img_w, int img_h,
+                                int format, int type, int zoomfilter, void *rect,
+                                float clip_min_x, float clip_min_y,
+                                float clip_max_x, float clip_max_y)
 {
        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);
+               glaDrawPixelsTex_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
+                                         clip_min_x, clip_min_y, clip_max_x, clip_max_y);
        }
        else {
                glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect);
        }
 }
 
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
+{
+       glaDrawPixelsAuto_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
+                                  0.0f, 0.0f, 0.0f, 0.0f);
+}
+
 /* 2D Drawing Assistance */
 
 void glaDefine2DArea(rcti *screen_rect)
@@ -822,9 +866,11 @@ void bglPolygonOffset(float viewdist, float dist)
 /* **** 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)
+void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
+                                ColorManagedViewSettings *view_settings,
+                                ColorManagedDisplaySettings *display_settings,
+                                float clip_min_x, float clip_min_y,
+                                float clip_max_x, float clip_max_y)
 {
        bool force_fallback = false;
        bool need_fallback = true;
@@ -874,14 +920,16 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
                                        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);
+                                       glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
+                                                                 zoomfilter, ibuf->rect_float,
+                                                                 clip_min_x, clip_min_y, clip_max_x, clip_max_y);
                                }
                        }
                        else if (ibuf->rect) {
                                /* ibuf->rect is always RGBA */
-                               glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
-                                                zoomfilter, ibuf->rect);
+                               glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+                                                         zoomfilter, ibuf->rect,
+                                                         clip_min_x, clip_min_y, clip_max_x, clip_max_y);
                        }
 
                        IMB_colormanagement_finish_glsl_draw();
@@ -897,21 +945,43 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
 
                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);
+               if (display_buffer) {
+                       glaDrawPixelsAuto_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+                                                  zoomfilter, display_buffer,
+                                                  clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+               }
 
                IMB_display_buffer_release(cache_handle);
        }
 }
 
-void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
+void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
+                       ColorManagedViewSettings *view_settings,
+                       ColorManagedDisplaySettings *display_settings)
+{
+       glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
+                                  0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
+                                    ImBuf *ibuf,
+                                    float x, float y,
+                                    int zoomfilter,
+                                    float clip_min_x, float clip_min_y,
+                                    float clip_max_x, float clip_max_y)
 {
        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);
+       glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
+                                  clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+}
+
+void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
+{
+       glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f);
 }
 
 void cpack(unsigned int x)
index 0ddbb1153c0ae88d8d0f3f01c35e2f6f571507b6..aff0a4c3d44035e6528ca83b3bc601c4ba7392bf 100644 (file)
@@ -526,7 +526,12 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
                }
 
                if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) == 0) {
-                       glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
+                       int clip_max_x, clip_max_y;
+                       UI_view2d_view_to_region(&ar->v2d,
+                                                ar->v2d.cur.xmax, ar->v2d.cur.ymax,
+                                                &clip_max_x, &clip_max_y);
+                       glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, GL_NEAREST,
+                                                      0, 0, clip_max_x, clip_max_y);
                }
                else {
                        unsigned char *display_buffer;