diff options
Diffstat (limited to 'source/blender/editors/space_clip/clip_editor.c')
-rw-r--r-- | source/blender/editors/space_clip/clip_editor.c | 244 |
1 files changed, 241 insertions, 3 deletions
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 3946d4cc36d..bd34a51819c 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -31,15 +31,20 @@ #include <stddef.h> +#include "MEM_guardedalloc.h" + #include "BKE_main.h" #include "BKE_movieclip.h" #include "BKE_context.h" #include "BKE_tracking.h" + #include "DNA_object_types.h" /* SELECT */ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "GPU_extensions.h" + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -47,6 +52,7 @@ #include "ED_clip.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -55,6 +61,8 @@ #include "clip_intern.h" // own include +/* ******** operactor poll functions ******** */ + int ED_space_clip_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -65,13 +73,94 @@ int ED_space_clip_poll(bContext *C) return FALSE; } -void ED_space_clip_set(bContext *C, SpaceClip *sc, MovieClip *clip) +int ED_space_clip_view_clip_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc && sc->clip) { + return sc->view == SC_VIEW_CLIP; + } + + return FALSE; +} + +int ED_space_clip_tracking_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc && sc->clip) + return ED_space_clip_show_trackedit(sc); + + return FALSE; +} + +int ED_space_clip_tracking_size_poll(bContext *C) +{ + if (ED_space_clip_tracking_poll(C)) { + MovieClip *clip = CTX_data_edit_movieclip(C); + + if (clip) { + SpaceClip *sc = CTX_wm_space_clip(C); + int width, height; + + BKE_movieclip_get_size(clip, &sc->user, &width, &height); + + return width > 0 && height > 0; + } + } + + return FALSE; +} + +int ED_space_clip_tracking_frame_poll(bContext *C) +{ + if (ED_space_clip_tracking_poll(C)) { + MovieClip *clip = CTX_data_edit_movieclip(C); + + if (clip) { + SpaceClip *sc = CTX_wm_space_clip(C); + + return BKE_movieclip_has_frame(clip, &sc->user); + } + } + + return FALSE; +} + +/* ******** editing functions ******** */ + +void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip) { + MovieClip *old_clip; + + if (!screen && C) + screen = CTX_wm_screen(C); + + old_clip = sc->clip; sc->clip = clip; - if (sc->clip && sc->clip->id.us==0) + if (sc->clip && sc->clip->id.us == 0) sc->clip->id.us = 1; + if (screen) { + ScrArea *area; + SpaceLink *sl; + + for (area = screen->areabase.first; area; area = area->next) { + for (sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *cur_sc = (SpaceClip *) sl; + + if (cur_sc != sc) { + if (cur_sc->clip == old_clip || cur_sc->clip == NULL) { + cur_sc->clip = clip; + } + } + } + } + } + } + if (C) WM_event_add_notifier(C, NC_MOVIECLIP|NA_SELECTED, sc->clip); } @@ -173,7 +262,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) MovieClip *clip = ED_space_clip(sc); MovieTrackingTrack *track; int width, height, ok = FALSE; - ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); + ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); INIT_MINMAX2(min, max); @@ -314,3 +403,152 @@ void ED_clip_mouse_pos(bContext *C, wmEvent *event, float co[2]) { ED_clip_point_stable_pos(C, event->mval[0], event->mval[1], &co[0], &co[1]); } + +/* OpenGL draw context */ + +typedef struct SpaceClipDrawContext { + int support_checked, buffers_supported; + + GLuint texture; /* OGL texture ID */ + short texture_allocated; /* flag if texture was allocated by glGenTextures */ + struct ImBuf *texture_ibuf; /* image buffer for which texture was created */ + int image_width, image_height; /* image width and height for which texture was created */ + unsigned last_texture; /* ID of previously used texture, so it'll be restored after clip drawing */ + int framenr; +} SpaceClipDrawContext; + +int ED_space_clip_texture_buffer_supported(SpaceClip *sc) +{ + SpaceClipDrawContext *context = sc->draw_context; + + if (!context) { + context = MEM_callocN(sizeof(SpaceClipDrawContext), "SpaceClipDrawContext"); + sc->draw_context = context; + } + + if (!context->support_checked) { + context->support_checked = TRUE; + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + context->buffers_supported = FALSE; + } + else { + context->buffers_supported = GPU_non_power_of_two_support(); + } + } + + return context->buffers_supported; +} + +int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) +{ + SpaceClipDrawContext *context = sc->draw_context; + MovieClip *clip = ED_space_clip(sc); + int need_rebind = 0; + + context->last_texture = glaGetOneInteger(GL_TEXTURE_2D); + + /* image texture need to be rebinded if displaying another image buffer + * assuming displaying happens of footage frames only on which painting doesn't heppen. + * so not changed image buffer pointer means unchanged image content */ + need_rebind |= context->texture_ibuf != ibuf; + need_rebind |= context->framenr != sc->user.framenr; + + if (need_rebind) { + int width = ibuf->x, height = ibuf->y; + float *frect = NULL, *fscalerect = NULL; + unsigned int *rect = NULL, *scalerect = NULL; + int need_recreate = 0; + + if (width > GL_MAX_TEXTURE_SIZE || height > GL_MAX_TEXTURE_SIZE) + return 0; + + rect = ibuf->rect; + frect = ibuf->rect_float; + + /* if image resolution changed (e.g. switched to proxy display) texture need to be recreated */ + need_recreate = context->image_width != ibuf->x || context->image_height != ibuf->y; + + if (context->texture_ibuf && need_recreate) { + glDeleteTextures(1, &context->texture); + context->texture_allocated = 0; + } + + if (need_recreate || !context->texture_allocated) { + /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */ + int filter = GL_LINEAR; + + /* non-scaled proxy shouldn;t use diltering */ + if ((clip->flag & MCLIP_USE_PROXY) == 0 || + ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100)) + { + filter = GL_NEAREST; + } + + glGenTextures(1, &context->texture); + glBindTexture(GL_TEXTURE_2D, context->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + } + else { + /* if texture doesn't need to be reallocated itself, just bind it so + * loading of image will happen to a proper texture */ + glBindTexture(GL_TEXTURE_2D, context->texture); + } + + if (frect) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, width, height, 0, GL_RGBA, GL_FLOAT, frect); + else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + + /* store settings */ + context->texture_allocated = 1; + context->texture_ibuf = ibuf; + context->image_width = ibuf->x; + context->image_height = ibuf->y; + context->framenr = sc->user.framenr; + + if (fscalerect) + MEM_freeN(fscalerect); + if (scalerect) + MEM_freeN(scalerect); + } + else { + /* displaying exactly the same image which was loaded t oa texture, + * just bint texture in this case */ + glBindTexture(GL_TEXTURE_2D, context->texture); + } + + glEnable(GL_TEXTURE_2D); + + return TRUE; +} + +void ED_space_clip_unload_movieclip_buffer(SpaceClip *sc) +{ + SpaceClipDrawContext *context = sc->draw_context; + + glBindTexture(GL_TEXTURE_2D, context->last_texture); + glDisable(GL_TEXTURE_2D); +} + +void ED_space_clip_free_texture_buffer(SpaceClip *sc) +{ + SpaceClipDrawContext *context = sc->draw_context; + + if (context) { + glDeleteTextures(1, &context->texture); + + MEM_freeN(context); + } +} + +int ED_space_clip_show_trackedit(SpaceClip *sc) +{ + if (sc) { + return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION); + } + + return FALSE; +} |