From c8f5dac11bb67aa005502d62855292e41252bbb4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 3 Feb 2012 19:13:31 +0000 Subject: Movie Clip Editor: implemented option to display frame using OpenGL textures Initial idea was to perform bilinear filtering for displaying proxied frame to make it looking a bit smoother. It was done but it was also discovered that using such kind of texture buffers helps on some crappy videocards when playing $k footage. Currently check for NPOT support is disabled, so use this option with care. --- release/scripts/startup/bl_ui/space_clip.py | 2 + source/blender/blenloader/intern/readfile.c | 1 + source/blender/editors/include/ED_clip.h | 4 + source/blender/editors/space_clip/CMakeLists.txt | 1 + source/blender/editors/space_clip/SConscript | 2 +- source/blender/editors/space_clip/clip_draw.c | 39 ++++-- source/blender/editors/space_clip/clip_editor.c | 147 +++++++++++++++++++++++ source/blender/editors/space_clip/space_clip.c | 3 + source/blender/makesdna/DNA_space_types.h | 3 + source/blender/makesrna/intern/rna_space.c | 5 + 10 files changed, 197 insertions(+), 10 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 3499249a8f9..3799361d3de 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -559,6 +559,8 @@ class CLIP_PT_display(Panel): elif sc.mode == 'RECONSTRUCTION': col.prop(sc, "show_stable", text="Stable") + col.prop(sc, "use_texture_buffer") + clip = sc.clip if clip: col.label(text="Display Aspect Ratio:") diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6bd12e8d3f6..b30d04b31cc 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5273,6 +5273,7 @@ static void lib_link_screen(FileData *fd, Main *main) sclip->clip= newlibadr_us(fd, sc->id.lib, sclip->clip); sclip->scopes.track_preview = NULL; + sclip->draw_context = NULL; sclip->scopes.ok = 0; } } diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 7d36159f47e..004fd7ceef7 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -58,6 +58,10 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, float co[2], float nco[2]); void ED_clip_point_stable_pos(struct bContext *C, float x, float y, float *xr, float *yr); void ED_clip_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); +void ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf); +void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc); +void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); + /* clip_ops.c */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 4f9819e8e77..30d2fe57c10 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager + ../../gpu ../../../../intern/guardedalloc ${GLEW_INCLUDE_PATH} ) diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript index 70331b0ec4a..c9c82aea68e 100644 --- a/source/blender/editors/space_clip/SConscript +++ b/source/blender/editors/space_clip/SConscript @@ -4,6 +4,6 @@ Import ('env') sources = env.Glob('*.c') defs = [] incs = '../include ../../blenkernel ../../blenloader ../../blenfont ../../blenlib ../../imbuf ../../makesdna' -incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include' +incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../gpu' env.BlenderLib ( 'bf_editors_space_clip', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index de43b30d4f4..2533629c4fb 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -216,9 +216,6 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int x, y; MovieClip *clip= ED_space_clip(sc); - /* set zoom */ - glPixelZoom(zoomx*width/ibuf->x, zoomy*height/ibuf->y); - /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -230,8 +227,36 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, IMB_rect_from_float(ibuf); } - if(ibuf->rect) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + if(ibuf->rect) { + if(sc->flag & SC_TEXTURE_BUFFER) { + ED_space_clip_load_movieclip_buffer(sc, ibuf); + + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(zoomx, zoomy, 1.0f); + glMultMatrixf(sc->stabmat); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); + glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f); + glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height); + glEnd(); + + glPopMatrix(); + + ED_space_clip_unload_movieclip_buffer(sc); + } + else { + /* set zoom */ + glPixelZoom(zoomx*width/ibuf->x, zoomy*height/ibuf->y); + + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + + /* reset zoom */ + glPixelZoom(1.0f, 1.0f); + } + } } /* draw boundary border for frame if stabilization is enabled */ @@ -260,10 +285,6 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_LINE_STIPPLE); } - - - /* reset zoom */ - glPixelZoom(1.0f, 1.0f); } static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track) diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 35d870022a4..9835a1cf43b 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -31,6 +31,8 @@ #include +#include "MEM_guardedalloc.h" + #include "BKE_main.h" #include "BKE_movieclip.h" #include "BKE_context.h" @@ -40,6 +42,8 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "GPU_extensions.h" + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -47,6 +51,7 @@ #include "ED_clip.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -309,3 +314,145 @@ 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 { + 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 */ +} SpaceClipDrawContext; + +void 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; + + if (!context) { + context = MEM_callocN(sizeof(SpaceClipDrawContext), "SpaceClipDrawContext"); + sc->draw_context = context; + } + + 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; + + 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; + + 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 0 + /* disabled for now because current tracking users have got NPOT textures + * working smoothly on their computers and forcing re-scaling during playback + * slows down playback a lot */ + + /* if videocard doesn't support NPOT textures, need to do rescaling */ + if (!GPU_non_power_of_two_support()) { + if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) { + width = power_of_2_max_i(width); + height = power_of_2_max_i(height); + + if (ibuf->x != width || ibuf->y != height) { + if (frect) { + fscalerect= MEM_mallocN(width*width*sizeof(*fscalerect)*4, "fscalerect"); + gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float, width, height, GL_FLOAT, fscalerect); + + frect = fscalerect; + } + else { + scalerect= MEM_mallocN(width*height*sizeof(*scalerect), "scalerect"); + gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect, width, height, GL_UNSIGNED_BYTE, scalerect); + + rect = scalerect; + } + } + } + } +#endif + + 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; + + 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); +} + +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); + } +} diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 5abdafbfffc..7cd7060e1d4 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -214,6 +214,8 @@ static void clip_free(SpaceLink *sl) if(sc->scopes.track_preview) IMB_freeImBuf(sc->scopes.track_preview); + + ED_space_clip_free_texture_buffer(sc); } /* spacetype; init callback */ @@ -229,6 +231,7 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ scn->scopes.track_preview= NULL; scn->scopes.ok= 0; + scn->draw_context= NULL; return (SpaceLink *)scn; } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 64d858bbcee..f5ca88d9391 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -521,6 +521,8 @@ typedef struct SpaceClip { /* movie postprocessing */ int postproc_flag, pad2; + + void *draw_context; } SpaceClip; /* view3d Now in DNA_view3d_types.h */ @@ -902,6 +904,7 @@ enum { #define SC_SHOW_GRAPH_TRACKS (1<<15) /*#define SC_SHOW_PYRAMID_LEVELS (1<<16) */ /* UNUSED */ #define SC_LOCK_TIMECURSOR (1<<17) +#define SC_TEXTURE_BUFFER (1<<18) /* SpaceClip->mode */ #define SC_MODE_TRACKING 0 diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8499e2fa111..cb4151d8aee 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2985,6 +2985,11 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Tracks", "Display the speed curves (in \"x\" direction red, in \"y\" direction green) for the selected tracks"); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + prop= RNA_def_property(srna, "use_texture_buffer", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Use Texture Buffer", "Use texture buffer to display o,age frames frame on screen"); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_TEXTURE_BUFFER); + RNA_def_property_update(prop, NC_WINDOW, NULL); + /* ** channels ** */ /* show_red_channel */ -- cgit v1.2.3