diff options
-rw-r--r-- | intern/opencolorio/fallback_impl.cc | 2 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.cc | 4 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.h | 2 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.h | 6 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl_glsl.cc | 25 | ||||
-rw-r--r-- | source/blender/editors/include/BIF_glutil.h | 6 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/render/render_internal.c | 30 | ||||
-rw-r--r-- | source/blender/editors/screen/glutil.c | 140 | ||||
-rw-r--r-- | source/blender/editors/space_file/file_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 2 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_colormanagement.h | 16 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 67 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_dragdrop.c | 2 |
17 files changed, 235 insertions, 79 deletions
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 4c19c454aee..37f624e1f8b 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -381,7 +381,7 @@ void FallbackImpl::matrixTransformScale(float * , float * , const float *) { } -bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) +bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) { return false; } diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index 8e831bb0736..c8db2c2b531 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -283,9 +283,9 @@ void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4 impl->matrixTransformScale(m44, offset4, scale4f); } -int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) +int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide) { - return (int) impl->setupGLSLDraw(state_r, processor); + return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide); } void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 8d8db161077..3632a0da1c6 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -121,7 +121,7 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4); -int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor); +int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide); void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state); void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state); diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index 3a1207d0870..a328470ccb5 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -96,7 +96,7 @@ public: virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0; - virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) = 0; + virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) = 0; virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0; virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0; }; @@ -169,7 +169,7 @@ public: void matrixTransformScale(float * m44, float * offset4, const float * scale4); - bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor); + bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide); void finishGLSLDraw(struct OCIO_GLSLDrawState *state); void freeGLState(struct OCIO_GLSLDrawState *state_r); }; @@ -243,7 +243,7 @@ public: void matrixTransformScale(float * m44, float * offset4, const float * scale4); - bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor); + bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide); void finishGLSLDraw(struct OCIO_GLSLDrawState *state); void freeGLState(struct OCIO_GLSLDrawState *state_r); }; diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 59845abca33..9343a13e888 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -77,15 +77,33 @@ typedef struct OCIO_GLSLDrawState { GLint last_texture, last_texture_unit; } OCIO_GLSLDrawState; -static const char * g_fragShaderText = "" +/* Hardcoded to do alpha predivide before color space conversion */ +static const char *g_fragShaderText = "" "\n" "uniform sampler2D tex1;\n" "uniform sampler3D tex2;\n" +"uniform bool predivide;\n" "\n" "void main()\n" "{\n" " vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n" -" gl_FragColor = OCIODisplay(col, tex2);\n" +" if (predivide == false || col[3] == 1.0f || col[3] == 0.0f) {\n" +" gl_FragColor = OCIODisplay(col, tex2);\n" +" } else {\n" +" float alpha = col[3];\n" +" float inv_alpha = 1.0f / alpha;\n" +"\n" +" col[0] *= inv_alpha;\n" +" col[1] *= inv_alpha;\n" +" col[2] *= inv_alpha;\n" +"\n" +" gl_FragColor = OCIODisplay(col, tex2);\n" +"\n" +" col[0] *= alpha;\n" +" col[1] *= alpha;\n" +" col[2] *= alpha;\n" +" }\n" +"\n" "}\n"; static GLuint compileShaderText(GLenum shaderType, const char *text) @@ -187,7 +205,7 @@ static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state) * When all drawing is finished, finishGLSLDraw shall be called to * restore OpenGL context to it's pre-GLSL draw state. */ -bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) +bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) { ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor; @@ -252,6 +270,7 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc glUseProgram(state->program); glUniform1i(glGetUniformLocation(state->program, "tex1"), 0); glUniform1i(glGetUniformLocation(state->program, "tex2"), 1); + glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide); return true; } diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index a356821fb53..af2dc884508 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -144,17 +144,17 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo * 1-to-1 mapping to screen space. */ -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect); +void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect); /** * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef. * only RGBA * needs glaDefine2DArea to be set. */ -void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect); +void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect); -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY); +void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY); /* 2D Drawing Assistance */ diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 6edbb90febe..c0f1ed28b3f 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -454,7 +454,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w float facy = (float)h / (float)ibuf->y; glPixelZoom(facx, facy); } - glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); + glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); glPixelZoom(1.0f, 1.0f); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 90c80cae1ad..6832cd5baa0 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -429,10 +429,38 @@ static void render_endjob(void *rjv) nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } - + /* XXX render stability hack */ G.is_rendering = FALSE; WM_main_add_notifier(NC_WINDOW, NULL); + + /* Partial render result will always update display buffer + * for first render layer only. This is nice because you'll + * see render progress during rendering, but it ends up in + * wrong display buffer shown after rendering. + * + * The code below will mark display buffer as invalid after + * rendering in case multiple layers were rendered, which + * ensures display buffer matches render layer after + * rendering. + * + * Perhaps proper way would be to toggle active render + * layer in image editor and job, so we always display + * layer being currently rendered. But this is not so much + * trivial at this moment, especially because of external + * engine API, so lets use simple and robust way for now + * - sergey - + */ + if (rj->scene->r.layers.first != rj->scene->r.layers.last) { + void *lock; + Image *ima = rj->image; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); + + if (ibuf) + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(ima, ibuf, lock); + } } /* called by render, check job 'stop' value or the global */ diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index b5c2b106a15..ec1a085f9da 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -42,6 +42,7 @@ #include "BLI_threads.h" #include "BKE_blender.h" +#include "BKE_global.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -488,7 +489,7 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY) +void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY) { unsigned char *uc_rect = (unsigned char *) rect; float *f_rect = (float *)rect; @@ -498,7 +499,8 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int subpart_x, subpart_y, tex_w, tex_h; int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; int texid = get_cached_work_texture(&tex_w, &tex_h); - + int components; + /* Specify the color outside this function, and tex will modulate it. * This is useful for changing alpha without using glPixelTransferf() */ @@ -525,13 +527,22 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, nsubparts_x = (img_w + (offset_x - 1)) / (offset_x); nsubparts_y = (img_h + (offset_y - 1)) / (offset_y); - if (format == GL_FLOAT) { + if (format == GL_RGBA) + components = 4; + else if (format == GL_RGB) + components = 3; + else if (format == GL_LUMINANCE) + components = 1; + else + BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); + + if (type == GL_FLOAT) { /* need to set internal format to higher range float */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL); } else { /* switch to 8bit RGBA for byte buffer */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL); } for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) { @@ -551,26 +562,26 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, if (subpart_w <= seamless || subpart_h <= seamless) continue; - if (format == GL_FLOAT) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]); + if (type == GL_FLOAT) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); /* add an extra border of pixels so linear looks ok at edges of full image. */ if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } glEnable(GL_TEXTURE_2D); @@ -601,9 +612,9 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, #endif } -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect) +void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) { - glaDrawPixelsTexScaled(x, y, img_w, img_h, format, zoomfilter, rect, 1.0f, 1.0f); + glaDrawPixelsTexScaled(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f); } void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect) @@ -686,7 +697,7 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo } /* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */ -void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect) +void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) { if (U.image_gpubuffer_limit) { /* Megapixels, use float math to prevent overflow */ @@ -694,11 +705,11 @@ void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int z if (U.image_gpubuffer_limit > (int)img_size) { glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTex(x, y, img_w, img_h, format, zoomfilter, rect); + glaDrawPixelsTex(x, y, img_w, img_h, format, type, zoomfilter, rect); return; } } - glaDrawPixelsSafe(x, y, img_w, img_h, img_w, GL_RGBA, format, rect); + glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect); } /* 2D Drawing Assistance */ @@ -1017,22 +1028,83 @@ void bglFlush(void) /* Draw given image buffer on a screen using GLSL for display transform */ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter) { + bool force_fallback = false; bool need_fallback = true; - /* Bytes and dithering are not supported on GLSL yet */ + /* Early out */ + if (ibuf->rect == NULL && ibuf->rect_float == NULL) + return; + + /* Dithering is not supported on GLSL yet */ + force_fallback = ibuf->dither != 0.0f; + + /* Single channel images could not be transformed using GLSL yet */ + force_fallback = ibuf->channels == 1; - /* WORKAROUND: only use GLSL if there's no byte buffer at all, - * this is because of how render results are handled, - * they're not updating image buffer's float buffer, - * but writes data directly to it's byte buffer and - * modifies display buffer. + /* This is actually lots of crap, but currently not sure about + * more clear way to bypass partial buffer update crappyness + * while rendering. + * + * The thing is -- render engines are only updating byte and + * display buffers for active render result opened in image + * editor. This works fine to show render progress without + * switching render layers in image editor user, but this is + * completely useless for GLSL display, where we need to have + * original buffer which we could color manage. + * + * For the time of rendering, we'll stick back to slower CPU + * display buffer update. GLSL could be used as soon as some + * fixes (?) are done in render itself, so we'll always have + * image buffer with relevant float buffer opened while + * rendering. + * + * On the other hand, when using Cycles, stressing GPU with + * GLSL could backfire on a performance. + * - sergey - */ - if (ibuf->rect == NULL && ibuf->rect_float && ibuf->dither == 0.0f) { - if (IMB_colormanagement_setup_glsl_draw_from_ctx(C)) { + if (G.is_rendering) { + /* Try to detect whether we're drawing render result, + * other images could have both rect and rect_float + * but they'll be synchronized + */ + if (ibuf->rect_float && ibuf->rect && + ((ibuf->mall & IB_rectfloat) == 0)) + { + force_fallback = true; + } + } + + /* Try to draw buffer using GLSL display transform */ + if (force_fallback == false) { + int ok; + + if (ibuf->rect_float) + ok = IMB_colormanagement_setup_glsl_draw_ctx(C, TRUE); + else + ok = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, FALSE); + + if (ok) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, zoomfilter, ibuf->rect_float); + if (ibuf->rect_float) { + int format; + + if (ibuf->channels == 3) + format = GL_RGB; + else if (ibuf->channels == 4) + format = GL_RGBA; + else + BLI_assert(!"Incompatible number of channels for GLSL display"); + + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, format, GL_FLOAT, + zoomfilter, ibuf->rect_float); + } + else if (ibuf->rect) { + /* ibuf->rect is always RGBA */ + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + zoomfilter, ibuf->rect); + } IMB_colormanagement_finish_glsl_draw(); @@ -1040,6 +1112,7 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int } } + /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */ if (need_fallback) { unsigned char *display_buffer; void *cache_handle; @@ -1047,7 +1120,8 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, zoomfilter, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + zoomfilter, display_buffer); IMB_display_buffer_release(cache_handle); } @@ -1057,6 +1131,8 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int * * See IMB_colormanagement_setup_transform_from_role_glsl description for * some more details + * + * NOTE: this only works for RGBA buffers! */ int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role) { @@ -1071,7 +1147,7 @@ int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int ro GPU_offscreen_bind(ofs); - if (!IMB_colormanagement_setup_transform_from_role_glsl(role)) { + if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) { GPU_offscreen_unbind(ofs); GPU_offscreen_free(ofs); return FALSE; @@ -1085,9 +1161,9 @@ int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int ro glPushMatrix(); glaDefine2DArea(&display_rect); - glLoadIdentity(); - glaDrawPixelsTex(0, 0, width, height, GL_FLOAT, GL_NEAREST, buffer); + glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT, + GL_NEAREST, buffer); glMatrixMode(GL_PROJECTION); glPopMatrix(); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 1c677d7c006..601c86b3029 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -376,7 +376,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int /* the image */ glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); + glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); /* border */ if (dropshadow) { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 5e5b2ece8c9..d7206c9b111 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3011,7 +3011,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); @@ -3019,7 +3019,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) else { glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); glPixelZoom(1.0f, 1.0f); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index f1915a82f69..39b12b321dd 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -710,7 +710,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) glColor4f(1.0, 1.0, 1.0, 1.0); glPixelZoom(scale, scale); - glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); + glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 2f0a2b7cb7a..6a450f6415e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -618,7 +618,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char glColor4fv(ob->col); /* Draw the Image on the screen */ - glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); + glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); glDisable(GL_BLEND); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index b6d46f82e6a..d0437c77af7 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1831,7 +1831,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, * glaDrawPixelsSafe in some cases, which will end up in misssing * alpha transparency for the background image (sergey) */ - glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); + glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); glPixelZoom(1.0, 1.0); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index a758cfa04f0..203d01cab67 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -152,14 +152,22 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo /* Configures GLSL shader for conversion from scene linear to display space */ int IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); -/* Same as above, but color management settings are guessing from a given context */ -int IMB_colormanagement_setup_glsl_draw_from_ctx(const struct bContext *C); + const struct ColorManagedDisplaySettings *display_settings, + int predivide); +/* Same as above, but display space conversion happens from a specified space */ +int IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + struct ColorSpace *colorspace, + int predivide); +/* Same as setup_glsl_draw, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, int predivide); +/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, int predivide); /* Finish GLSL-based display space conversion */ void IMB_colormanagement_finish_glsl_draw(void); /* Configures GLSL shader for conversion from space defined by role to scene linear space */ -int IMB_colormanagement_setup_transform_from_role_glsl(int role); +int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide); /* Finish GLSL-based color space conversion */ void IMB_colormanagement_finish_glsl_transform(void); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 3ed69550873..1e6fac4f4f0 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -109,6 +109,7 @@ static struct global_glsl_state { /* Settings of processor for comparison. */ char view[MAX_COLORSPACE_NAME]; char display[MAX_COLORSPACE_NAME]; + char input[MAX_COLORSPACE_NAME]; float exposure, gamma; /* Container for GLSL state needed for OCIO module. */ @@ -703,8 +704,10 @@ static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettin return NULL; } -static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, - float exposure, float gamma) +static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, + const char *display, + float exposure, float gamma, + const char *from_colorspace) { OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); OCIO_DisplayTransformRcPtr *dt; @@ -712,8 +715,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie dt = OCIO_createDisplayTransform(); - /* assuming handling buffer was already converted to scene linear space */ - OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear); + OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace); OCIO_displayTransformSetView(dt, view_transform); OCIO_displayTransformSetDisplay(dt, display); @@ -2621,7 +2623,8 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag cm_processor->is_data_result = display_space->is_data; cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, - applied_view_settings->exposure, applied_view_settings->gamma); + applied_view_settings->exposure, applied_view_settings->gamma, + global_role_scene_linear); if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); @@ -2718,26 +2721,30 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) /* **** OpenGL drawing routines using GLSL for color space transform ***** */ static bool check_glsl_display_processor_changed(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) + const ColorManagedDisplaySettings *display_settings, + const char *from_colorspace) { return !(global_glsl_state.exposure == view_settings->exposure && global_glsl_state.gamma == view_settings->gamma && STREQ(global_glsl_state.view, view_settings->view_transform) && - STREQ(global_glsl_state.display, display_settings->display_device)); + STREQ(global_glsl_state.display, display_settings->display_device) && + STREQ(global_glsl_state.input, from_colorspace)); } static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) + const ColorManagedDisplaySettings *display_settings, + const char *from_colorspace) { /* Update state if there's no processor yet or * processor settings has been changed. */ if (global_glsl_state.processor == NULL || - check_glsl_display_processor_changed(view_settings, display_settings)) + check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace)) { /* Store settings of processor for further comparison. */ strcpy(global_glsl_state.view, view_settings->view_transform); strcpy(global_glsl_state.display, display_settings->display_device); + strcpy(global_glsl_state.input, from_colorspace); global_glsl_state.exposure = view_settings->exposure; global_glsl_state.gamma = view_settings->gamma; @@ -2750,13 +2757,14 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s create_display_buffer_processor(global_glsl_state.view, global_glsl_state.display, global_glsl_state.exposure, - global_glsl_state.gamma); + global_glsl_state.gamma, + global_glsl_state.input); } } /** - * Configures GLSL shader for conversion from scene linear - * to display space + * Configures GLSL shader for conversion from specified to + * display color space * * Will create appropriate OCIO processor and setup GLSL shader, * so further 2D texture usage will use this conversion. @@ -2767,8 +2775,9 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s * This is low-level function, use glaDrawImBuf_glsl_ctx if you * only need to display given image buffer */ -int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + struct ColorSpace *from_colorspace, int predivide) { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -2790,20 +2799,36 @@ int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_set return FALSE; /* Make sure OCIO processor is up-to-date. */ - update_glsl_display_processor(applied_view_settings, display_settings); + update_glsl_display_processor(applied_view_settings, display_settings, + from_colorspace ? from_colorspace->name : global_role_scene_linear); + + return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, predivide); +} - return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor); +/* Configures GLSL shader for conversion from scene linear to display space */ +int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + int predivide) +{ + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, + NULL, predivide); } -/* Same as above, but color management settings are guessing from a given context */ -int IMB_colormanagement_setup_glsl_draw_from_ctx(const bContext *C) +/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, int predivide) { ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; display_transform_get_from_ctx(C, &view_settings, &display_settings); - return IMB_colormanagement_setup_glsl_draw(view_settings, display_settings); + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide); +} + +/* Same as setup_glsl_draw, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, int predivide) +{ + return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, predivide); } /* Finish GLSL-based display space conversion */ @@ -2827,7 +2852,7 @@ void IMB_colormanagement_finish_glsl_draw(void) * When there's no need to apply transform on 2D textures, use * IMB_colormanagement_finish_glsl_transform(). */ -int IMB_colormanagement_setup_transform_from_role_glsl(int role) +int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide) { OCIO_ConstProcessorRcPtr *processor; ColorSpace *colorspace; @@ -2836,7 +2861,7 @@ int IMB_colormanagement_setup_transform_from_role_glsl(int role) processor = colorspace_to_scene_linear_processor(colorspace); - return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor); + return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, predivide); } /* Finish GLSL-based color space conversion */ diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index ed066117b28..0c78338c18a 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -323,7 +323,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy); else { glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */ - glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale); + glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale); } } else { |