Color management: use partial buffer update when painting image
Makes it much more responsible, especially when small brushes are used. Could make sense look into using full multithreaded buffer update when brush is large enough.
This commit is contained in:
@@ -104,6 +104,8 @@
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_extensions.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
#include "paint_intern.h"
|
||||
|
||||
/* Defines and Structs */
|
||||
@@ -4220,8 +4222,11 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w,
|
||||
|
||||
static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
|
||||
{
|
||||
if (ibuf->rect_float)
|
||||
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
|
||||
if (ibuf->rect_float) {
|
||||
IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, ibuf->x, 0, 0,
|
||||
imapaintpartial.x1, imapaintpartial.y1,
|
||||
imapaintpartial.x2, imapaintpartial.y2);
|
||||
}
|
||||
|
||||
if (ibuf->mipmap[0])
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
# include <ocio_capi.h>
|
||||
#else
|
||||
/* so function can accept processor and care about disabled OCIO inside */
|
||||
typedef struct ConstProcessorRcPtr {
|
||||
int pad;
|
||||
} ConstProcessorRcPtr;
|
||||
#endif
|
||||
|
||||
/*********************** Global declarations *************************/
|
||||
@@ -1853,55 +1858,73 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot
|
||||
* ImBuf at the time function is being called.
|
||||
*/
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
static void partial_buffer_update_rect(unsigned char *display_buffer, const float *linear_buffer, int display_stride,
|
||||
int linear_stride, int linear_offset_x, int linear_offset_y,
|
||||
int channels, int dither, int predivide,
|
||||
int channels, int dither, int predivide, int profile_from,
|
||||
ConstProcessorRcPtr *processor, imb_tonecurveCb tonecurve_func,
|
||||
int xmin, int ymin, int xmax, int ymax)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
(void) processor; /* silent down compiler when building without OCIO */
|
||||
|
||||
if (profile_from == IB_PROFILE_NONE)
|
||||
profile_from = IB_PROFILE_SRGB;
|
||||
|
||||
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];
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
if (processor) {
|
||||
float pixel[4];
|
||||
|
||||
copy_v4_v4(pixel, (float *) linear_buffer + linear_index);
|
||||
|
||||
OCIO_processorApplyRGBA(processor, pixel);
|
||||
|
||||
rgba_float_to_uchar(display_buffer + display_index, pixel);
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
if (tonecurve_func) {
|
||||
IMB_buffer_byte_from_float_tonecurve(display_buffer + display_index, linear_buffer + linear_index,
|
||||
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
|
||||
predivide, 1, 1, 1, 1, tonecurve_func);
|
||||
}
|
||||
else {
|
||||
IMB_buffer_byte_from_float(display_buffer + display_index, linear_buffer + linear_index, channels,
|
||||
dither, IB_PROFILE_SRGB, profile_from, predivide, 1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
|
||||
int stride, int offset_x, int offset_y,
|
||||
void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, int stride, int offset_x, int offset_y,
|
||||
int xmin, int ymin, int xmax, int ymax)
|
||||
{
|
||||
int channels = ibuf->channels;
|
||||
int predivide = ibuf->flags & IB_cm_predivide;
|
||||
int dither = ibuf->dither;
|
||||
int profile_from = ibuf->profile;
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
int display;
|
||||
|
||||
int *display_buffer_flags;
|
||||
|
||||
int channels = ibuf->channels;
|
||||
int predivide = ibuf->flags & IB_cm_predivide;
|
||||
int dither = ibuf->dither;
|
||||
|
||||
BLI_lock_thread(LOCK_COLORMANAGE);
|
||||
|
||||
if (!ibuf->display_buffer_flags) {
|
||||
/* there's no cached display buffers, so no need to iterate though bit fields */
|
||||
|
||||
if (ibuf->rect && ibuf->rect_float) {
|
||||
/* update byte buffer created by legacy color management */
|
||||
partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y,
|
||||
channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
||||
BLI_unlock_thread(LOCK_COLORMANAGE);
|
||||
|
||||
return;
|
||||
@@ -1961,7 +1984,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
|
||||
}
|
||||
|
||||
partial_buffer_update_rect(display_buffer, linear_buffer, buffer_width, stride,
|
||||
offset_x, offset_y, channels, dither, predivide,
|
||||
offset_x, offset_y, channels, dither, predivide, profile_from,
|
||||
processor, tonecurve_func, xmin, ymin, xmax, ymax);
|
||||
|
||||
if (processor)
|
||||
@@ -1977,15 +2000,13 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
|
||||
}
|
||||
|
||||
MEM_freeN(display_buffer_flags);
|
||||
#else
|
||||
(void) ibuf;
|
||||
(void) linear_buffer;
|
||||
(void) xmin;
|
||||
(void) ymin;
|
||||
(void) xmax;
|
||||
(void) ymax;
|
||||
(void) stride;
|
||||
(void) offset_x;
|
||||
(void) offset_y;
|
||||
#endif
|
||||
|
||||
BLI_lock_thread(LOCK_COLORMANAGE);
|
||||
if (ibuf->rect && ibuf->rect_float) {
|
||||
/* update byte buffer created by legacy color management */
|
||||
partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y,
|
||||
channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
BLI_unlock_thread(LOCK_COLORMANAGE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user