diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-02-24 03:22:58 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-02-24 03:26:45 +0300 |
commit | ab8958bbd585997e5121d46f38ef3a35173bfe5f (patch) | |
tree | 4b590a8c97c1a63a05814c2940401fd05cec2369 /source/blender/editors/space_image | |
parent | 2ea544619718796a7cb07558b680a7fe7716e877 (diff) |
Opengl glaDrawPixels removal: image_draw.c
Using float buffer is still laggy because of the data volume we have to transfer to the GC.
Diffstat (limited to 'source/blender/editors/space_image')
-rw-r--r-- | source/blender/editors/space_image/image_draw.c | 286 |
1 files changed, 115 insertions, 171 deletions
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 1f97bf6f255..00b28457987 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -71,6 +71,8 @@ #include "ED_render.h" #include "ED_screen.h" +#include "GPU_shader.h" + #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -406,63 +408,36 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d } /* image drawing */ - -static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti) +static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *rect, + float zoomx, float zoomy) { - - /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ - if (ENDIAN_ORDER == B_ENDIAN) - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); + float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti); - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); -} + /* Slowwww */ + int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp"); + for (int a = rectx * recty - 1; a >= 0; a--) { + /* zbuffer values are signed, so we need to shift color range */ + recti[a] = rect[a] * 0.5f + 0.5f; + } -static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf) -{ - float *trectf = MEM_mallocN(rectx * recty * 4, "temp"); - int a, b; - - for (a = rectx * recty - 1, b = 4 * a + 3; a >= 0; a--, b -= 4) - trectf[a] = rectf[b]; - - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf); - MEM_freeN(trectf); - /* ogl trick below is slower... (on ATI 9600) */ -// glColorMask(1, 0, 0, 0); -// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 3); -// glColorMask(0, 1, 0, 0); -// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 2); -// glColorMask(0, 0, 1, 0); -// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 1); -// glColorMask(1, 1, 1, 1); -} + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_bind(shader); + GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red); -static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti) -{ - /* zbuffer values are signed, so we need to shift color range */ - glPixelTransferf(GL_RED_SCALE, 0.5f); - glPixelTransferf(GL_GREEN_SCALE, 0.5f); - glPixelTransferf(GL_BLUE_SCALE, 0.5f); - glPixelTransferf(GL_RED_BIAS, 0.5f); - glPixelTransferf(GL_GREEN_BIAS, 0.5f); - glPixelTransferf(GL_BLUE_BIAS, 0.5f); - - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti); - - glPixelTransferf(GL_RED_SCALE, 1.0f); - glPixelTransferf(GL_GREEN_SCALE, 1.0f); - glPixelTransferf(GL_BLUE_SCALE, 1.0f); - glPixelTransferf(GL_RED_BIAS, 0.0f); - glPixelTransferf(GL_GREEN_BIAS, 0.0f); - glPixelTransferf(GL_BLUE_BIAS, 0.0f); + immDrawPixelsTex(x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL); + + GPU_shader_unbind(); + + MEM_freeN(recti); } -static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, float *rect_float) +static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, + float *rect_float, float zoomx, float zoomy) { float bias, scale, *rectf, clipend; int a; - + float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + if (scene->camera && scene->camera->type == OB_CAMERA) { bias = ((Camera *)scene->camera->data)->clipsta; clipend = ((Camera *)scene->camera->data)->clipend; @@ -473,8 +448,8 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec scale = 0.01f; clipend = 100.0f; } - - rectf = MEM_mallocN(rectx * recty * 4, "temp"); + + rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp"); for (a = rectx * recty - 1; a >= 0; a--) { if (rect_float[a] > clipend) rectf[a] = 0.0f; @@ -485,22 +460,16 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec rectf[a] *= rectf[a]; } } - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf); - - MEM_freeN(rectf); -} -static int draw_image_channel_offset(SpaceImage *sima) -{ -#ifdef __BIG_ENDIAN__ - if (sima->flag & SI_SHOW_R) return 0; - else if (sima->flag & SI_SHOW_G) return 1; - else return 2; -#else - if (sima->flag & SI_SHOW_R) return 1; - else if (sima->flag & SI_SHOW_G) return 2; - else return 3; -#endif + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_bind(shader); + GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red); + + immDrawPixelsTex(x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL); + + GPU_shader_unbind(); + + MEM_freeN(rectf); } static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) @@ -508,61 +477,70 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, int x, y; /* set zoom */ - glPixelZoom(zoomx, zoomy); - glaDefine2DArea(&ar->winrct); /* find window pixel coordinates of origin */ UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y); /* this part is generic image display */ - if (sima->flag & SI_SHOW_ALPHA) { - if (ibuf->rect) - sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect); - else if (ibuf->rect_float && ibuf->channels == 4) - sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float); - } - else if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { + if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { if (ibuf->zbuf) - sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf); + sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy); else if (ibuf->zbuf_float) - sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float); + sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy); else if (ibuf->channels == 1) - sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float); + sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy); } else { + int clip_max_x, clip_max_y; + UI_view2d_view_to_region(&ar->v2d, + ar->v2d.cur.xmax, ar->v2d.cur.ymax, + &clip_max_x, &clip_max_y); + if (sima->flag & SI_USE_ALPHA) { + imm_draw_checker_box(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); } - if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) == 0) { - int clip_max_x, clip_max_y; - UI_view2d_view_to_region(&ar->v2d, - ar->v2d.cur.xmax, ar->v2d.cur.ymax, - &clip_max_x, &clip_max_y); + /* If RGBA display with color management */ + if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) { + glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, GL_NEAREST, 0, 0, clip_max_x, clip_max_y, zoomx, zoomy); } else { + float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; unsigned char *display_buffer; void *cache_handle; + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; + + if (sima->flag & SI_SHOW_R) + shuffle[0] = 1.0f; + else if (sima->flag & SI_SHOW_G) + shuffle[1] = 1.0f; + else if (sima->flag & SI_SHOW_B) + shuffle[2] = 1.0f; + else if (sima->flag & SI_SHOW_ALPHA) + shuffle[3] = 1.0f; + + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_bind(shader); + GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle); + + IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); + display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle); + + if (display_buffer) { + immDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, + 0, 0, clip_max_x, clip_max_y, zoomx, zoomy, NULL); + } - /* TODO(sergey): Ideally GLSL shading should be capable of either - * disabling some channels or displaying buffer with custom offset. - */ - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + IMB_display_buffer_release(cache_handle); - if (display_buffer != NULL) { - int channel_offset = draw_image_channel_offset(sima); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, - display_buffer - (4 - channel_offset)); - } - if (cache_handle != NULL) { - IMB_display_buffer_release(cache_handle); - } + GPU_shader_unbind(); } if (sima->flag & SI_USE_ALPHA) @@ -601,7 +579,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, unsigned int *rect; int dx, dy, sx, sy, x, y; void *cache_handle; - int channel_offset = -1; + float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* verify valid values, just leave this a while */ if (ima->xrep < 1) return; @@ -615,8 +593,6 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, if (!display_buffer) return; - glPixelZoom(zoomx, zoomy); - if (sima->curtile >= ima->xrep * ima->yrep) sima->curtile = ima->xrep * ima->yrep - 1; @@ -628,24 +604,39 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); /* draw repeated */ - if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) != 0) { - channel_offset = draw_image_channel_offset(sima); + if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) != 0) { + if (sima->flag & SI_SHOW_R) + shuffle[0] = 1.0f; + else if (sima->flag & SI_SHOW_G) + shuffle[1] = 1.0f; + else if (sima->flag & SI_SHOW_B) + shuffle[2] = 1.0f; + else if (sima->flag & SI_SHOW_ALPHA) + shuffle[3] = 1.0f; } + + /* To make sure no program is bound */ + GPU_shader_unbind(); + for (sy = 0; sy + dy <= ibuf->y; sy += dy) { for (sx = 0; sx + dx <= ibuf->x; sx += dx) { UI_view2d_view_to_region(&ar->v2d, fx + (float)sx / (float)ibuf->x, fy + (float)sy / (float)ibuf->y, &x, &y); - if (channel_offset == -1) { - glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect); + + if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) { + immDrawPixelsTex(x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL); } else { - glaDrawPixelsSafe(x, y, dx, dy, dx, GL_LUMINANCE, GL_UNSIGNED_INT, - (unsigned char *)rect - (4 - channel_offset)); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_bind(shader); + GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle); + + immDrawPixelsTex(x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL); + + GPU_shader_unbind(); } } } - glPixelZoom(1.0f, 1.0f); - IMB_display_buffer_release(cache_handle); MEM_freeN(rect); @@ -718,84 +709,37 @@ void draw_image_sample_line(SpaceImage *sima) } } -static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height) -{ - Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint); - ImBuf *ibuf; - unsigned int size, alpha; - unsigned char *display_buffer; - unsigned char *rect, *cp; - void *cache_handle; - - if (!brush || !brush->clone.image) - return NULL; - - ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); - - if (!ibuf) - return NULL; - - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - if (!display_buffer) { - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - IMB_display_buffer_release(cache_handle); - - return NULL; - } - - rect = MEM_dupallocN(display_buffer); - - IMB_display_buffer_release(cache_handle); - - if (!rect) { - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - return NULL; - } - - *width = ibuf->x; - *height = ibuf->y; - - size = (*width) * (*height); - alpha = (unsigned char)255 * brush->clone.alpha; - cp = rect; - - while (size-- > 0) { - cp[3] = alpha; - cp += 4; - } - - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - - return rect; -} - static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy) { Brush *brush; - int x, y, w, h; - unsigned char *clonerect; + int x, y; + ImBuf *ibuf; brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint); - if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) { - /* this is not very efficient, but glDrawPixels doesn't allow - * drawing with alpha */ - clonerect = get_alpha_clone_image(C, scene, &w, &h); + if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) { + ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); - if (clonerect) { + if (ibuf) { + void *cache_handle = NULL; + float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha}; UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); - glPixelZoom(zoomx, zoomy); + unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + + if (!display_buffer) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + IMB_display_buffer_release(cache_handle); + return; + } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect); + immDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col); glDisable(GL_BLEND); - glPixelZoom(1.0, 1.0); - - MEM_freeN(clonerect); + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + IMB_display_buffer_release(cache_handle); } } } |