Fix part #33935: Texture painting slow down with mouse, but not with tablet
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 8 Feb 2013 08:18:44 +0000 (08:18 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 8 Feb 2013 08:18:44 +0000 (08:18 +0000)
Issue is solved for painting on byte buffer with default sRGB display enabled.
In this case it is possible to skip any color space transform and just apply
dither if needed.

Still not sure if there's a regression in painting on flaots or not, will
continue investigation.

source/blender/imbuf/intern/colormanagement.c

index 00a4699..2380429 100644 (file)
@@ -1353,6 +1353,23 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c
                                     display_buffer_init_handle, do_display_buffer_apply_thread);
 }
 
+static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+                                         const ColorManagedDisplaySettings *display_settings)
+{
+       if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 &&
+           view_settings->exposure == 0.0f &&
+           view_settings->gamma == 1.0f)
+       {
+               const char *from_colorspace = ibuf->rect_colorspace->name;
+               const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings);
+
+               if (to_colorspace && !strcmp(from_colorspace, to_colorspace))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
 static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte,
                                                   const ColorManagedViewSettings *view_settings,
                                                   const ColorManagedDisplaySettings *display_settings)
@@ -1366,16 +1383,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu
         * computation noticeable faster
         */
        if (ibuf->rect_float == NULL && ibuf->rect_colorspace) {
-               if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 &&
-                   view_settings->exposure == 0.0f &&
-                   view_settings->gamma == 1.0f)
-               {
-                       const char *from_colorspace = ibuf->rect_colorspace->name;
-                       const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings);
-
-                       if (to_colorspace && !strcmp(from_colorspace, to_colorspace))
-                               skip_transform = TRUE;
-               }
+               skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings);
        }
 
        if (skip_transform == FALSE)
@@ -2332,37 +2340,67 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
        int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
 
        if (dither != 0.0f) {
+               /* cm_processor is NULL in cases byte_buffer's space matches display
+                * buffer's space
+                * in this case we could skip extra transform and only apply dither
+                * use 4 channels for easier byte->float->byte conversion here so
+                * (this is only needed to apply dither, in other cases we'll convert
+                * byte buffer to display directly)
+                */
+               if (!cm_processor)
+                       channels = 4;
+
                display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither");
        }
 
-       for (y = ymin; y < ymax; y++) {
-               for (x = xmin; x < xmax; x++) {
-                       int display_index = (y * display_stride + x) * channels;
-                       int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
-                       float pixel[4];
-
-                       if (linear_buffer) {
-                               copy_v4_v4(pixel, (float *) linear_buffer + linear_index);
-                       }
-                       else if (byte_buffer) {
-                               rgba_uchar_to_float(pixel, byte_buffer + linear_index);
-                               IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
-                               straight_to_premul_v4(pixel);
-                       }
-
-                       if (!is_data) {
-                               IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel);
+       if (cm_processor) {
+               for (y = ymin; y < ymax; y++) {
+                       for (x = xmin; x < xmax; x++) {
+                               int display_index = (y * display_stride + x) * channels;
+                               int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
+                               float pixel[4];
+
+                               if (linear_buffer) {
+                                       copy_v4_v4(pixel, (float *) linear_buffer + linear_index);
+                               }
+                               else if (byte_buffer) {
+                                       rgba_uchar_to_float(pixel, byte_buffer + linear_index);
+                                       IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
+                                       straight_to_premul_v4(pixel);
+                               }
+
+                               if (!is_data) {
+                                       IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel);
+                               }
+
+                               if (display_buffer_float) {
+                                       int index = ((y - ymin) * width + (x - xmin)) * channels;
+
+                                       copy_v4_v4(display_buffer_float + index, pixel);
+                               }
+                               else {
+                                       float pixel_straight[4];
+                                       premul_to_straight_v4_v4(pixel_straight, pixel);
+                                       rgba_float_to_uchar(display_buffer + display_index, pixel_straight);
+                               }
                        }
+               }
+       }
+       else {
+               if (display_buffer_float) {
+                       /* huh, for dither we need float buffer first, no cheaper way. currently */
+                       IMB_buffer_float_from_byte(display_buffer_float, byte_buffer,
+                                                  IB_PROFILE_SRGB, IB_PROFILE_SRGB, TRUE,
+                                                  width, height, width, display_stride);
+               }
+               else {
+                       int i, width = xmax - xmin;
 
-                       if (display_buffer_float) {
-                               int index = ((y - ymin) * width + (x - xmin)) * channels;
+                       for (i = ymin; i < ymax; i++) {
+                               int byte_offset = (linear_stride * i + xmin) * 4;
+                               int display_offset = (display_stride * i + xmin) * 4;
 
-                               copy_v4_v4(display_buffer_float + index, pixel);
-                       }
-                       else {
-                               float pixel_straight[4];
-                               premul_to_straight_v4_v4(pixel_straight, pixel);
-                               rgba_float_to_uchar(display_buffer + display_index, pixel_straight);
+                               memcpy(display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width);
                        }
                }
        }
@@ -2426,14 +2464,24 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
                BLI_unlock_thread(LOCK_COLORMANAGE);
 
                if (display_buffer) {
-                       ColormanageProcessor *cm_processor;
+                       ColormanageProcessor *cm_processor = NULL;
+                       int skip_transform = 0;
+
+                       /* byte buffer is assumed to be in imbuf's rect space, so if byte buffer
+                        * is known we could skip display->linear->display conversion in case
+                        * display color space matches imbuf's rect space
+                        */
+                       if (byte_buffer != NULL)
+                               skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings);
 
-                       cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+                       if (!skip_transform)
+                               cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
 
                        partial_buffer_update_rect(ibuf, display_buffer, linear_buffer, byte_buffer, buffer_width, stride,
-                                                  offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax);
+                                                                          offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax);
 
-                       IMB_colormanagement_processor_free(cm_processor);
+                       if (cm_processor)
+                               IMB_colormanagement_processor_free(cm_processor);
 
                        IMB_display_buffer_release(cache_handle);
                }