Color management: multithreaded transformation apply

Since RRT can't be baked into 3D LUT it's the only way to increase
speed of transformation and make image / clip loading in acceptable
time.
This commit is contained in:
Sergey Sharybin
2012-06-30 12:36:41 +00:00
parent b984fdf393
commit 74df85d032

View File

@@ -50,6 +50,7 @@
#include "BLI_math_color.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BKE_utildefines.h"
#include "BKE_main.h"
@@ -429,14 +430,125 @@ void IMB_colormanagement_exit(void)
/*********************** Public display buffers interfaces *************************/
#ifdef WITH_OCIO
typedef struct DisplayBufferThread {
void *processor;
float *buffer;
unsigned char *display_buffer;
int width;
int start_line;
int tot_line;
int channels;
int dither;
int predivide;
} DisplayBufferThread;
static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *display_buffer,
void *processor, void *(do_thread) (void *))
{
DisplayBufferThread handles[BLENDER_MAX_THREADS];
ListBase threads;
int predivide = ibuf->flags & IB_cm_predivide;
int i, tot_thread = BLI_system_thread_count();
int start_line, tot_line;
BLI_init_threads(&threads, do_thread, tot_thread);
start_line = 0;
tot_line = ((float)(ibuf->y / tot_thread)) + 0.5f;
for (i = 0; i < tot_thread; i++) {
int offset = ibuf->channels * start_line * ibuf->x;
handles[i].processor = processor;
handles[i].buffer = buffer + offset;
handles[i].display_buffer = display_buffer + offset;
handles[i].width = ibuf->x;
handles[i].start_line = start_line;
if (i < tot_thread - 1) {
handles[i].tot_line = tot_line;
}
else {
handles[i].tot_line = ibuf->y - start_line;
}
handles[i].channels = ibuf->channels;
handles[i].dither = ibuf->dither;
handles[i].predivide = predivide;
if (tot_thread > 1)
BLI_insert_thread(&threads, &handles[i]);
start_line += tot_line;
}
if (tot_thread > 1)
BLI_end_threads(&threads);
else
do_thread(&handles[0]);
}
static void *do_display_buffer_apply_tonemap_thread(void *handle_v)
{
DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
imb_tonecurveCb tonecurve_func = (imb_tonecurveCb) handle->processor;
float *buffer = handle->buffer;
unsigned char *display_buffer = handle->display_buffer;
int channels = handle->channels;
int width = handle->width;
int height = handle->tot_line;
int dither = handle->dither;
int predivide = handle->predivide;
IMB_buffer_byte_from_float_tonecurve(display_buffer, buffer, channels, dither,
IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
predivide, width, height, width, width,
tonecurve_func);
return NULL;
}
static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer,
imb_tonecurveCb tonecurve_func)
{
int predivide = ibuf->flags & IB_cm_predivide;
display_buffer_apply_threaded(ibuf, ibuf->rect_float, display_buffer, tonecurve_func,
do_display_buffer_apply_tonemap_thread);
}
IMB_buffer_byte_from_float_tonecurve(display_buffer, ibuf->rect_float,
ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x, tonecurve_func);
static void *do_display_buffer_apply_ocio_thread(void *handle_v)
{
DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor;
PackedImageDesc *img;
float *buffer = handle->buffer;
unsigned char *display_buffer = handle->display_buffer;
int channels = handle->channels;
int width = handle->width;
int height = handle->tot_line;
int dither = handle->dither;
int predivide = handle->predivide;
img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float),
channels * sizeof(float), channels * sizeof(float) * width);
OCIO_processorApply(processor, img);
OCIO_packedImageDescRelease(img);
/* do conversion */
IMB_buffer_byte_from_float(display_buffer, buffer,
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
predivide, width, height, width, width);
return NULL;
}
static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer,
@@ -445,13 +557,10 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer
ConstConfigRcPtr *config = OCIO_getCurrentConfig();
DisplayTransformRcPtr *dt = OCIO_createDisplayTransform();
ConstProcessorRcPtr *processor;
float *rect_float;
int predivide = ibuf->flags & IB_cm_predivide;
PackedImageDesc *img;
rect_float = MEM_dupallocN(ibuf->rect_float);
img = OCIO_createPackedImageDesc(rect_float, ibuf->x, ibuf->y, ibuf->channels, sizeof(float),
ibuf->channels * sizeof(float), ibuf->channels * sizeof(float)*ibuf->x);
/* OCIO_TODO: get rid of hardcoded input and display spaces */
OCIO_displayTransformSetInputColorSpaceName(dt, "aces");
@@ -459,18 +568,13 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr*)dt);
processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt);
if (processor) {
OCIO_processorApply(processor, img);
/* do conversion */
IMB_buffer_byte_from_float(display_buffer, rect_float,
ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
display_buffer_apply_threaded(ibuf, rect_float, display_buffer, processor,
do_display_buffer_apply_ocio_thread);
}
OCIO_packedImageDescRelease(img);
OCIO_displayTransformRelease(dt);
OCIO_processorRelease(processor);
OCIO_configRelease(config);