Merging r44227 through r45619 from trunk into soc-2011-tomato
[blender-staging.git] / source / blender / editors / space_clip / clip_editor.c
index 3946d4cc36da31859a90e62ccb4a088b5f33402b..dcc4f66490ae9284a87e770c5d5a32f26ecf8733 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <stddef.h>
 
+#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"
@@ -314,3 +319,148 @@ 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 */
+       int framenr;
+} 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;
+       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;
+
+               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;
+               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);
+}
+
+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);
+       }
+}