Skip to content

Instantly share code, notes, and snippets.

@sobotka
Created April 19, 2018 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sobotka/d6d86f72216c126a3711fdd05ef56598 to your computer and use it in GitHub Desktop.
Save sobotka/d6d86f72216c126a3711fdd05ef56598 to your computer and use it in GitHub Desktop.
half_float_hackeroonie_here_be_dragons.diff
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