From d7983e3638896e5742fcf1bafe49c49a6b0aa08f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 12 Oct 2013 14:09:05 +0000 Subject: Option to overlay mask over the footage Currently supports only two modes: - Show alpha channel of the mask - Multiply footage by the mask, which will give you final-looking combined image. TODO: Currently rasterization happens on every redraw, need to cache rasterized mask somewhere to make redraw more realtime. --- source/blender/editors/include/ED_mask.h | 2 +- source/blender/editors/mask/mask_draw.c | 118 ++++++++++++++++++++- source/blender/editors/screen/glutil.c | 2 +- source/blender/editors/space_clip/space_clip.c | 4 +- source/blender/editors/space_image/space_image.c | 7 +- .../editors/space_sequencer/sequencer_draw.c | 2 +- 6 files changed, 128 insertions(+), 7 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 3e2dbe255df..8da36f015dc 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -57,7 +57,7 @@ void ED_operatormacros_mask(void); /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); void ED_mask_draw_region(struct Mask *mask, struct ARegion *ar, - const char draw_flag, const char draw_type, + const char draw_flag, const char draw_type, const char overlay_mode, const int width_i, const int height_i, const float aspx, const float aspy, const short do_scale_applied, const short do_draw_cb, diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index fec4ab87996..50d8e653737 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -35,6 +35,7 @@ #include "BLI_utildefines.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_mask.h" @@ -48,6 +49,7 @@ #include "ED_mask.h" /* own include */ #include "ED_space_api.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -535,10 +537,93 @@ void ED_mask_draw(const bContext *C, draw_masklays(C, mask, draw_flag, draw_type, width, height); } +typedef struct ThreadedMaskRasterizeState { + MaskRasterHandle *handle; + float *buffer; + int width, height; +} ThreadedMaskRasterizeState; + +typedef struct ThreadedMaskRasterizeData { + int start_scanline; + int num_scanlines; +} ThreadedMaskRasterizeData; + +static void mask_rasterize_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) +{ + ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool); + ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata; + int scanline; + + for (scanline = 0; scanline < data->num_scanlines; scanline++) { + int x, y = data->start_scanline + scanline; + for (x = 0; x < state->width; x++) { + int index = y * state->width + x; + float xy[2]; + + xy[0] = (float) x / state->width; + xy[1] = (float) y / state->height; + + state->buffer[index] = BKE_maskrasterize_handle_sample(state->handle, xy); + } + } +} + +static float *threaded_mask_rasterize(Mask *mask, const int width, const int height) +{ + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool; + MaskRasterHandle *handle; + ThreadedMaskRasterizeState state; + float *buffer; + int i, num_threads = BLI_task_scheduler_num_threads(task_scheduler), scanlines_per_thread; + + buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer"); + + /* Initialize rasterization handle. */ + handle = BKE_maskrasterize_handle_new(); + BKE_maskrasterize_handle_init(handle, mask, width, height, TRUE, TRUE, TRUE); + + state.handle = handle; + state.buffer = buffer; + state.width = width; + state.height = height; + + task_pool = BLI_task_pool_create(task_scheduler, &state); + + BLI_begin_threaded_malloc(); + + scanlines_per_thread = height / num_threads; + for (i = 0; i < num_threads; i++) { + ThreadedMaskRasterizeData *data = MEM_mallocN(sizeof(ThreadedMaskRasterizeData), + "threaded mask rasterize data"); + + data->start_scanline = i * scanlines_per_thread; + + if (i < num_threads - 1) { + data->num_scanlines = scanlines_per_thread; + } + else { + data->num_scanlines = height - data->start_scanline; + } + + BLI_task_pool_push(task_pool, mask_rasterize_func, data, true, TASK_PRIORITY_LOW); + } + + /* work and wait until tasks are done */ + BLI_task_pool_work_and_wait(task_pool); + + /* Free memory. */ + BLI_task_pool_free(task_pool); + BLI_end_threaded_malloc(); + BKE_maskrasterize_handle_free(handle); + + return buffer; +} + /* sets up the opengl context. * width, height are to match the values from ED_mask_get_size() */ void ED_mask_draw_region(Mask *mask, ARegion *ar, - const char draw_flag, const char draw_type, + const char draw_flag, const char draw_type, const char overlay_mode, const int width_i, const int height_i, /* convert directly into aspect corrected vars */ const float aspx, const float aspy, const short do_scale_applied, const short do_draw_cb, @@ -592,6 +677,37 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, yofs = ((width - height) / -2.0f) * zoomy; } + if (draw_flag & MASK_DRAWFLAG_OVERLAY) { + float *buffer = threaded_mask_rasterize(mask, width, height); + int format; + + if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) { + glColor3f(1.0f, 1.0f, 1.0f); + format = GL_LUMINANCE; + } + else { + /* More blending types could be supported in the future. */ + glEnable(GL_BLEND); + glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); + format = GL_ALPHA; + } + + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(zoomx, zoomy, 0); + if (stabmat) { + glMultMatrixf(stabmat); + } + glaDrawPixelsTex(0.0f, 0.0f, width, height, format, GL_FLOAT, GL_NEAREST, buffer); + glPopMatrix(); + + if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { + glDisable(GL_BLEND); + } + + MEM_freeN(buffer); + } + /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ glPushMatrix(); glTranslatef(x + xofs, y + yofs, 0); diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index b70b06f2aa4..d356c3d8de3 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -531,7 +531,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, components = 4; else if (format == GL_RGB) components = 3; - else if (format == GL_LUMINANCE) + else if (ELEM(format, GL_LUMINANCE, GL_ALPHA)) components = 1; else { BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 3ede63adb72..adc902bf4ba 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1191,7 +1191,9 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) int mask_width, mask_height; ED_mask_get_size(sa, &mask_width, &mask_height); ED_mask_draw_region(mask, ar, - sc->mask_info.draw_flag, sc->mask_info.draw_type, + sc->mask_info.draw_flag, + sc->mask_info.draw_type, + sc->mask_info.overlay_mode, mask_width, mask_height, aspx, aspy, TRUE, TRUE, diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 5a8292abcab..7b20af340ae 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -674,7 +674,6 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) } else if (sima->mode == SI_MODE_MASK) { mask = ED_space_image_get_mask(sima); - draw_image_cursor(ar, sima->cursor); } ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); @@ -715,7 +714,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) BLI_unlock_thread(LOCK_DRAW_IMAGE); ED_mask_draw_region(mask, ar, - sima->mask_info.draw_flag, sima->mask_info.draw_type, + sima->mask_info.draw_flag, + sima->mask_info.draw_type, + sima->mask_info.overlay_mode, width, height, aspx, aspy, TRUE, FALSE, @@ -723,7 +724,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) ED_mask_draw_frames(mask, ar, CFRA, mask->sfra, mask->efra); + UI_view2d_view_ortho(v2d); draw_image_cursor(ar, sima->cursor); + UI_view2d_view_restore(C); } /* scrollers? */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index dca1b481334..cb69a7fe654 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1251,7 +1251,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq height = (scene->r.size * scene->r.ysch) / 100; ED_mask_draw_region(mask, ar, - 0, 0, /* TODO */ + 0, 0, 0, /* TODO */ width, height, aspx, aspy, FALSE, TRUE, -- cgit v1.2.3