Created
April 26, 2018 16:42
Half-float VSE hack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc | |
index c8716d5..d0ed642 100644 | |
--- a/source/blender/alembic/intern/abc_object.cc | |
+++ b/source/blender/alembic/intern/abc_object.cc | |
@@ -286,7 +286,7 @@ void AbcObjectReader::read_matrix(float r_mat[4][4], const float time, | |
has_alembic_parent = false; | |
} | |
else { | |
- has_alembic_parent = ixform_parent && schema.getInheritsXforms(); | |
+ //has_alembic_parent = ixform_parent && schema.getInheritsXforms(); | |
if (has_alembic_parent && m_object->parent == NULL) { | |
/* TODO Sybren: This happened in some files. I think I solved it, | |
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c | |
index 298671b..6a3bd16 100644 | |
--- a/source/blender/blenkernel/intern/seqeffects.c | |
+++ b/source/blender/blenkernel/intern/seqeffects.c | |
@@ -59,6 +59,38 @@ | |
#include "BLF_api.h" | |
+/* Funkster: pasted here from util_half.h so I don't have to faff with include paths. HACK. */ | |
+static half_float float_to_half(float f) | |
+{ | |
+ uint32_t const *u = (uint32_t *)&f; | |
+ /* Sign bit, shifted to it's position. */ | |
+ uint32_t sign_bit = *u & 0x80000000; | |
+ sign_bit >>= 16; | |
+ /* Exponent. */ | |
+ uint32_t exponent_bits = *u & 0x7f800000; | |
+ /* Non-sign bits. */ | |
+ uint32_t value_bits = *u & 0x7fffffff; | |
+ value_bits >>= 13; /* Align mantissa on MSB. */ | |
+ value_bits -= 0x1c000; /* Adjust bias. */ | |
+ /* Flush-to-zero. */ | |
+ value_bits = (exponent_bits < 0x38800000) ? 0 : value_bits; | |
+ /* Clamp-to-max. */ | |
+ value_bits = (exponent_bits > 0x47000000) ? 0x7bff : value_bits; | |
+ /* Denormals-as-zero. */ | |
+ value_bits = (exponent_bits == 0 ? 0 : value_bits); | |
+ /* Re-insert sign bit and return. */ | |
+ return (value_bits | sign_bit); | |
+} | |
+ | |
+static float half_to_float(half_float h) | |
+{ | |
+ float f; | |
+ | |
+ *((int*) &f) = ((h & 0x8000) << 16) | (((h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13); | |
+ | |
+ return f; | |
+} | |
+ | |
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, | |
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1, | |
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out) | |
@@ -75,6 +107,22 @@ static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ib | |
*rect3 = (unsigned char *)ibuf3->rect + offset; | |
} | |
+static void slice_get_half_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, | |
+ const ImBuf *ibuf3, const ImBuf *out, int start_line, | |
+ half_float **rect1, half_float **rect2, half_float **rect3, half_float **rect_out) | |
+{ | |
+ int offset = 4 * start_line * context->rectx; | |
+ | |
+ *rect1 = ibuf1->rect_half + offset; | |
+ *rect_out = out->rect_half + offset; | |
+ | |
+ if (ibuf2) | |
+ *rect2 = ibuf2->rect_half + offset; | |
+ | |
+ if (ibuf3) | |
+ *rect3 = ibuf3->rect_half + offset; | |
+} | |
+ | |
static void slice_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, | |
const ImBuf *ibuf3, const ImBuf *out, int start_line, | |
float **rect1, float **rect2, float **rect3, float **rect_out) | |
@@ -109,7 +157,9 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1, | |
if (!ibuf1 && !ibuf2 && !ibuf3) { | |
/* hmmm, global float option ? */ | |
- out = IMB_allocImBuf(x, y, 32, IB_rect); | |
+ //out = IMB_allocImBuf(x, y, 32, IB_rect); | |
+ //out = IMB_allocImBuf(x, y, 32, IB_rectfloat); | |
+ out = IMB_allocImBuf(x, y, 32, IB_recthalf); | |
} | |
else if ((ibuf1 && ibuf1->rect_float) || | |
(ibuf2 && ibuf2->rect_float) || | |
@@ -119,6 +169,14 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1, | |
out = IMB_allocImBuf(x, y, 32, IB_rectfloat); | |
} | |
+ else if ((ibuf1 && ibuf1->rect_half) || | |
+ (ibuf2 && ibuf2->rect_half) || | |
+ (ibuf3 && ibuf3->rect_half)) | |
+ { | |
+ /* if any inputs are recthalf, output is half too */ | |
+ | |
+ out = IMB_allocImBuf(x, y, 32, IB_recthalf); | |
+ } | |
else { | |
out = IMB_allocImBuf(x, y, 32, IB_rect); | |
} | |
@@ -138,6 +196,21 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1, | |
IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name); | |
} | |
+ else if (out->rect_half) { | |
+ if (ibuf1 && !ibuf1->rect_half) { | |
+ // Funkster TODO BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true); | |
+ } | |
+ | |
+ if (ibuf2 && !ibuf2->rect_half) { | |
+ // Funkster TODO BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true); | |
+ } | |
+ | |
+ if (ibuf3 && !ibuf3->rect_half) { | |
+ // Funkster TODO BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true); | |
+ } | |
+ | |
+ IMB_colormanagement_assign_half_colorspace(out, scene->sequencer_colorspace_settings.name); | |
+ } | |
else { | |
if (ibuf1 && !ibuf1->rect) { | |
IMB_rect_from_float(ibuf1); | |
@@ -577,6 +650,50 @@ static void do_cross_effect_float(float facf0, float facf1, int x, int y, float | |
} | |
} | |
+static void do_cross_effect_half(float facf0, float facf1, int x, int y, half_float *rect1, half_float *rect2, half_float *out) | |
+{ | |
+ float fac1, fac2, fac3, fac4; | |
+ int xo; | |
+ half_float *rt1, *rt2, *rt; | |
+ | |
+ xo = x; | |
+ rt1 = rect1; | |
+ rt2 = rect2; | |
+ rt = out; | |
+ | |
+ fac2 = facf0; | |
+ fac1 = 1.0f - fac2; | |
+ fac4 = facf1; | |
+ fac3 = 1.0f - fac4; | |
+ | |
+ while (y--) { | |
+ x = xo; | |
+ while (x--) { | |
+ rt[0] = float_to_half(fac1 * half_to_float(rt1[0]) + fac2 * half_to_float(rt2[0])); | |
+ rt[1] = float_to_half(fac1 * half_to_float(rt1[1]) + fac2 * half_to_float(rt2[1])); | |
+ rt[2] = float_to_half(fac1 * half_to_float(rt1[2]) + fac2 * half_to_float(rt2[2])); | |
+ rt[3] = float_to_half(fac1 * half_to_float(rt1[3]) + fac2 * half_to_float(rt2[3])); | |
+ | |
+ rt1 += 4; rt2 += 4; rt += 4; | |
+ } | |
+ | |
+ if (y == 0) | |
+ break; | |
+ y--; | |
+ | |
+ x = xo; | |
+ while (x--) { | |
+ rt[0] = float_to_half(fac3 * half_to_float(rt1[0]) + fac4 * half_to_float(rt2[0])); | |
+ rt[1] = float_to_half(fac3 * half_to_float(rt1[1]) + fac4 * half_to_float(rt2[1])); | |
+ rt[2] = float_to_half(fac3 * half_to_float(rt1[2]) + fac4 * half_to_float(rt2[2])); | |
+ rt[3] = float_to_half(fac3 * half_to_float(rt1[3]) + fac4 * half_to_float(rt2[3])); | |
+ | |
+ rt1 += 4; rt2 += 4; rt += 4; | |
+ } | |
+ | |
+ } | |
+} | |
+ | |
static void do_cross_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra), | |
float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), | |
int start_line, int total_lines, ImBuf *out) | |
@@ -588,6 +705,13 @@ static void do_cross_effect(const SeqRenderData *context, Sequence *UNUSED(seq), | |
do_cross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out); | |
} | |
+ else if (out->rect_half) { | |
+ float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; | |
+ | |
+ slice_get_half_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); | |
+ | |
+ do_cross_effect_half(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out); | |
+ } | |
else { | |
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; | |
@@ -2188,6 +2312,7 @@ static ImBuf *do_solid_color(const SeqRenderData *context, Sequence *seq, float | |
SolidColorVars *cv = (SolidColorVars *)seq->effectdata; | |
unsigned char *rect; | |
+ half_float *rect_half; | |
float *rect_float; | |
int x; /*= context->rectx;*/ /*UNUSED*/ | |
int y; /*= context->recty;*/ /*UNUSED*/ | |
@@ -2225,6 +2350,38 @@ static ImBuf *do_solid_color(const SeqRenderData *context, Sequence *seq, float | |
} | |
} | |
+ else if (out->rect_half) { | |
+ half_float col0[3]; | |
+ half_float col1[3]; | |
+ | |
+ col0[0] = float_to_half(facf0 * cv->col[0]); | |
+ col0[1] = float_to_half(facf0 * cv->col[1]); | |
+ col0[2] = float_to_half(facf0 * cv->col[2]); | |
+ | |
+ col1[0] = float_to_half(facf1 * cv->col[0]); | |
+ col1[1] = float_to_half(facf1 * cv->col[1]); | |
+ col1[2] = float_to_half(facf1 * cv->col[2]); | |
+ | |
+ rect_half = out->rect_half; | |
+ | |
+ for (y = 0; y < out->y; y++) { | |
+ for (x = 0; x < out->x; x++, rect_half += 4) { | |
+ rect_half[0] = col0[0]; | |
+ rect_half[1] = col0[1]; | |
+ rect_half[2] = col0[2]; | |
+ rect_half[3] = float_to_half(1.0); | |
+ } | |
+ y++; | |
+ if (y < out->y) { | |
+ for (x = 0; x < out->x; x++, rect_half += 4) { | |
+ rect_half[0] = col1[0]; | |
+ rect_half[1] = col1[1]; | |
+ rect_half[2] = col1[2]; | |
+ rect_half[3] = float_to_half(1.0); | |
+ } | |
+ } | |
+ } | |
+ } | |
else if (out->rect_float) { | |
float col0[3]; | |
float col1[3]; | |
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c | |
index 2de7cd4..31f2dac 100644 | |
--- a/source/blender/blenkernel/intern/sequencer.c | |
+++ b/source/blender/blenkernel/intern/sequencer.c | |
@@ -497,7 +497,44 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make | |
/* Get common conversion settings. */ | |
const char *to_colorspace = scene->sequencer_colorspace_settings.name; | |
/* Perform actual conversion logic. */ | |
- if (ibuf->rect_float == NULL) { | |
+ if (ibuf->rect_float != NULL) { | |
+ const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); | |
+ /* Unknown input color space, can't perform conversion. */ | |
+ if (from_colorspace == NULL || from_colorspace[0] == '\0') { | |
+ return; | |
+ } | |
+ /* We don't want both byte and float buffers around: they'll either run | |
+ * out of sync or conversion of byte buffer will loose precision in there. | |
+ */ | |
+ if (ibuf->rect != NULL) { | |
+ imb_freerectImBuf(ibuf); | |
+ } | |
+ IMB_colormanagement_transform_threaded(ibuf->rect_float, | |
+ ibuf->x, ibuf->y, ibuf->channels, | |
+ from_colorspace, to_colorspace, | |
+ true); | |
+ } | |
+ else if (ibuf->rect_half != NULL) { | |
+ const char *from_colorspace = IMB_colormanagement_get_half_colorspace(ibuf); | |
+ /* Unknown input color space, can't perform conversion. */ | |
+ if (from_colorspace == NULL || from_colorspace[0] == '\0') { | |
+ return; | |
+ } | |
+ /* We don't want both byte and float buffers around: they'll either run | |
+ * out of sync or conversion of byte buffer will loose precision in there. | |
+ */ | |
+ if (ibuf->rect != NULL) { | |
+ imb_freerectImBuf(ibuf); | |
+ } | |
+ /* Funkster TODO IMB_colormanagement_transform_threaded_half | |
+ | |
+ IMB_colormanagement_transform_threaded(ibuf->rect_half, | |
+ ibuf->x, ibuf->y, ibuf->channels, | |
+ from_colorspace, to_colorspace, | |
+ true); | |
+ */ | |
+ } | |
+ else { | |
/* We are not requested to give float buffer and byte buffer is already | |
* in thee required colorspace. Can skip doing anything here. | |
*/ | |
@@ -530,23 +567,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make | |
imb_freerectImBuf(ibuf); | |
} | |
} | |
- else { | |
- const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); | |
- /* Unknown input color space, can't perform conversion. */ | |
- if (from_colorspace == NULL || from_colorspace[0] == '\0') { | |
- return; | |
- } | |
- /* We don't want both byte and float buffers around: they'll either run | |
- * out of sync or conversion of byte buffer will loose precision in there. | |
- */ | |
- if (ibuf->rect != NULL) { | |
- imb_freerectImBuf(ibuf); | |
- } | |
- IMB_colormanagement_transform_threaded(ibuf->rect_float, | |
- ibuf->x, ibuf->y, ibuf->channels, | |
- from_colorspace, to_colorspace, | |
- true); | |
- } | |
sequencer_imbuf_assign_spaces(scene, ibuf); | |
} | |
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c | |
index 1d0f433..e4f45cc 100644 | |
--- a/source/blender/editors/render/render_opengl.c | |
+++ b/source/blender/editors/render/render_opengl.c | |
@@ -311,6 +311,10 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) | |
IMB_rect_from_float(out); | |
imb_freerectfloatImBuf(out); | |
} | |
+ if (out->rect_half != NULL) { | |
+ // Funkster TODO IMB_rect_from_half(out); | |
+ imb_freerecthalfImBuf(out); | |
+ } | |
BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); | |
RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id); | |
IMB_freeImBuf(out); | |
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c | |
index 70a6e6d..0ea74ca 100644 | |
--- a/source/blender/editors/space_sequencer/sequencer_draw.c | |
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c | |
@@ -1151,7 +1151,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq | |
ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]); | |
if ((ibuf == NULL) || | |
- (ibuf->rect == NULL && ibuf->rect_float == NULL)) | |
+ (ibuf->rect == NULL && ibuf->rect_half == NULL && ibuf->rect_float == NULL)) | |
{ | |
/* gpencil can also be drawn without a valid imbuf */ | |
if ((draw_gpencil && is_imbuf) && !draw_overlay) { | |
@@ -1279,6 +1279,30 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq | |
glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true); | |
} | |
} | |
+ else if (ibuf->rect_half) { | |
+ display_buffer = ibuf->rect_half; | |
+ | |
+ if (ibuf->channels == 4) { | |
+ format = GL_RGBA; | |
+ } | |
+ else if (ibuf->channels == 3) { | |
+ format = GL_RGB; | |
+ } | |
+ else { | |
+ BLI_assert(!"Incompatible number of channels for half buffer in sequencer"); | |
+ format = GL_RGBA; | |
+ display_buffer = NULL; | |
+ } | |
+ | |
+ type = GL_HALF_FLOAT; | |
+ | |
+ if (ibuf->half_colorspace) { | |
+ glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->half_colorspace, ibuf->dither, true); | |
+ } | |
+ else { | |
+ glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true); | |
+ } | |
+ } | |
else if (ibuf->rect) { | |
display_buffer = ibuf->rect; | |
format = GL_RGBA; | |
@@ -1295,7 +1319,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq | |
/* there's a data to be displayed, but GLSL is not initialized | |
* properly, in this case we fallback to CPU-based display transform | |
*/ | |
- if ((ibuf->rect || ibuf->rect_float) && !glsl_used) { | |
+ if ((ibuf->rect || ibuf->rect_half || ibuf->rect_float) && !glsl_used) { | |
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); | |
format = GL_RGBA; | |
type = GL_UNSIGNED_BYTE; | |
@@ -1312,11 +1336,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
- if (type == GL_FLOAT) | |
+ if ((type == GL_FLOAT) || (type == GL_HALF_FLOAT)) { | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer); | |
- else | |
+ } | |
+ else { | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer); | |
- | |
+ } | |
+ | |
if (draw_backdrop) { | |
glMatrixMode(GL_PROJECTION); | |
glPushMatrix(); | |
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h | |
index 4164f5f..bd6d6ae 100644 | |
--- a/source/blender/imbuf/IMB_colormanagement.h | |
+++ b/source/blender/imbuf/IMB_colormanagement.h | |
@@ -64,9 +64,11 @@ void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *d | |
const char *IMB_colormanagement_role_colorspace_name_get(int role); | |
void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name); | |
void IMB_colormanagement_assign_float_colorspace(struct ImBuf *ibuf, const char *name); | |
+void IMB_colormanagement_assign_half_colorspace(struct ImBuf *ibuf, const char *name); | |
void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name); | |
const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf); | |
+const char *IMB_colormanagement_get_half_colorspace(struct ImBuf *ibuf); | |
const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf); | |
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3]); | |
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h | |
index 93d2b3e..a04f9c9 100644 | |
--- a/source/blender/imbuf/IMB_imbuf.h | |
+++ b/source/blender/imbuf/IMB_imbuf.h | |
@@ -585,6 +585,9 @@ void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb); | |
bool imb_addrectImBuf(struct ImBuf *ibuf); | |
void imb_freerectImBuf(struct ImBuf *ibuf); | |
+bool imb_addrecthalfImBuf(struct ImBuf *ibuf); | |
+void imb_freerecthalfImBuf(struct ImBuf *ibuf); | |
+ | |
bool imb_addrectfloatImBuf(struct ImBuf *ibuf); | |
void imb_freerectfloatImBuf(struct ImBuf *ibuf); | |
void imb_freemipmapImBuf(struct ImBuf *ibuf); | |
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h | |
index f4b2539..e2bb1ae 100644 | |
--- a/source/blender/imbuf/IMB_imbuf_types.h | |
+++ b/source/blender/imbuf/IMB_imbuf_types.h | |
@@ -30,6 +30,7 @@ | |
#include "DNA_vec_types.h" /* for rcti */ | |
+ | |
/** | |
* \file IMB_imbuf_types.h | |
* \ingroup imbuf | |
@@ -50,6 +51,9 @@ | |
#define IMB_MIPMAP_LEVELS 20 | |
#define IMB_FILENAME_SIZE 1024 | |
+/* Funkster: just typedef this here for ease of nasty hacking */ | |
+typedef unsigned short half_float; | |
+ | |
typedef struct DDSData { | |
unsigned int fourcc; /* DDS fourcc info */ | |
unsigned int nummipmaps; /* The number of mipmaps in the dds file */ | |
@@ -162,6 +166,13 @@ typedef struct ImBuf { | |
* - alpha defaults to 'straight'. | |
*/ | |
unsigned int *rect; | |
+ /** Image pixel buffer (half float representation): | |
+ * - color space defaults to 'linear' (`rec709`). | |
+ * - alpha defaults to 'premul'. | |
+ * \note May need gamma correction to `sRGB` when generating 8bit representations. | |
+ */ | |
+ half_float *rect_half; | |
+ | |
/** Image pixel buffer (float representation): | |
* - color space defaults to 'linear' (`rec709`). | |
* - alpha defaults to 'premul'. | |
@@ -212,6 +223,7 @@ typedef struct ImBuf { | |
/* color management */ | |
struct ColorSpace *rect_colorspace; /* color space of byte buffer */ | |
+ struct ColorSpace *half_colorspace; /* color space of half float buffer, used by sequencer only */ | |
struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */ | |
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ | |
struct ColormanageCache *colormanage_cache; /* cache used by color management */ | |
@@ -258,6 +270,7 @@ typedef struct ImBuf { | |
#define IB_ignore_alpha (1 << 14) /* ignore alpha on load and substitude it with 1.0f */ | |
#define IB_thumbnail (1 << 15) | |
#define IB_multiview (1 << 16) | |
+#define IB_recthalf (1 << 17) | |
/** | |
* \name Imbuf preset profile tags | |
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c | |
index 3375047..4131c83 100644 | |
--- a/source/blender/imbuf/intern/allocimbuf.c | |
+++ b/source/blender/imbuf/intern/allocimbuf.c | |
@@ -119,6 +119,22 @@ void imb_freerectfloatImBuf(ImBuf *ibuf) | |
} | |
/* any free rect frees mipmaps to be sure, creation is in render on first request */ | |
+void imb_freerecthalfImBuf(ImBuf *ibuf) | |
+{ | |
+ if (ibuf == NULL) return; | |
+ | |
+ if (ibuf->rect_half && (ibuf->mall & IB_recthalf)) { | |
+ MEM_freeN(ibuf->rect_half); | |
+ ibuf->rect_half = NULL; | |
+ } | |
+ | |
+ imb_freemipmapImBuf(ibuf); | |
+ | |
+ ibuf->rect_half = NULL; | |
+ ibuf->mall &= ~IB_recthalf; | |
+} | |
+ | |
+/* any free rect frees mipmaps to be sure, creation is in render on first request */ | |
void imb_freerectImBuf(ImBuf *ibuf) | |
{ | |
if (ibuf == NULL) return; | |
@@ -213,6 +229,7 @@ void IMB_freeImBuf(ImBuf *ibuf) | |
if (needs_free) { | |
imb_freerectImBuf(ibuf); | |
+ imb_freerecthalfImBuf(ibuf); | |
imb_freerectfloatImBuf(ibuf); | |
imb_freetilesImBuf(ibuf); | |
imb_free_bitmap_font(ibuf); | |
@@ -361,6 +378,27 @@ bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf) | |
return true; | |
} | |
+bool imb_addrecthalfImBuf(ImBuf *ibuf) | |
+{ | |
+ size_t size; | |
+ | |
+ if (ibuf == NULL) return false; | |
+ | |
+ if (ibuf->rect_half) | |
+ imb_freerecthalfImBuf(ibuf); /* frees mipmap too, hrm */ | |
+ | |
+ size = (size_t)ibuf->x * (size_t)ibuf->y * sizeof(half_float[4]); | |
+ | |
+ ibuf->channels = 4; | |
+ if ((ibuf->rect_half = MEM_mapallocN(size, __func__))) { | |
+ ibuf->mall |= IB_recthalf; | |
+ ibuf->flags |= IB_recthalf; | |
+ return true; | |
+ } | |
+ | |
+ return false; | |
+} | |
+ | |
bool imb_addrectfloatImBuf(ImBuf *ibuf) | |
{ | |
size_t size; | |
@@ -481,6 +519,12 @@ bool IMB_initImBuf(struct ImBuf *ibuf, | |
} | |
} | |
+ if (flags & IB_recthalf) { | |
+ if (imb_addrecthalfImBuf(ibuf) == false) { | |
+ return false; | |
+ } | |
+ } | |
+ | |
if (flags & IB_rectfloat) { | |
if (imb_addrectfloatImBuf(ibuf) == false) { | |
return false; | |
@@ -585,6 +629,7 @@ static void imbuf_cache_destructor(void *data) | |
ImBuf *ibuf = (ImBuf *) data; | |
imb_freerectImBuf(ibuf); | |
+ imb_freerecthalfImBuf(ibuf); | |
imb_freerectfloatImBuf(ibuf); | |
IMB_freezbufImBuf(ibuf); | |
IMB_freezbuffloatImBuf(ibuf); | |
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c | |
index 0881a24..fbbb186 100644 | |
--- a/source/blender/imbuf/intern/colormanagement.c | |
+++ b/source/blender/imbuf/intern/colormanagement.c | |
@@ -1203,6 +1203,18 @@ void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) | |
ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; | |
} | |
+void IMB_colormanagement_assign_half_colorspace(ImBuf *ibuf, const char *name) | |
+{ | |
+ ColorSpace *colorspace = colormanage_colorspace_get_named(name); | |
+ | |
+ ibuf->half_colorspace = colorspace; | |
+ | |
+ if (colorspace && colorspace->is_data) | |
+ ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; | |
+ else | |
+ ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; | |
+} | |
+ | |
void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) | |
{ | |
ColorSpace *colorspace = colormanage_colorspace_get_named(name); | |
@@ -1225,6 +1237,16 @@ const char *IMB_colormanagement_get_float_colorspace(ImBuf *ibuf) | |
} | |
} | |
+const char *IMB_colormanagement_get_half_colorspace(ImBuf *ibuf) | |
+{ | |
+ if (ibuf->half_colorspace) { | |
+ return ibuf->half_colorspace->name; | |
+ } | |
+ else { | |
+ return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); | |
+ } | |
+} | |
+ | |
const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf) | |
{ | |
if (ibuf->rect_colorspace) { | |
@@ -1759,9 +1781,14 @@ void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsig | |
return; | |
} | |
if (STREQ(from_colorspace, to_colorspace)) { | |
- /* If source and destination color spaces are identical, skip | |
- * threading overhead and simply do nothing | |
+ /* Because this function always takes a byte buffer and returns a float buffer, it must | |
+ * always do byte-to-float conversion of some kind. To avoid threading overhead | |
+ * IMB_buffer_float_from_byte is used when color spaces are identical. See T51002. | |
*/ | |
+ IMB_buffer_float_from_byte(float_buffer, byte_buffer, | |
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB, | |
+ true, | |
+ width, height, width, width); | |
return; | |
} | |
cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment