Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/screen/glutil.c')
-rw-r--r--source/blender/editors/screen/glutil.c140
1 files changed, 108 insertions, 32 deletions
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();