b495ca3281387e9930bdb6fc276f98255c95fabe
[blender.git] / source / blender / editors / space_clip / clip_editor.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_clip/clip_editor.c
29  *  \ingroup spclip
30  */
31
32 #include <stddef.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BKE_main.h"
37 #include "BKE_mask.h"
38 #include "BKE_movieclip.h"
39 #include "BKE_context.h"
40 #include "BKE_tracking.h"
41
42 #include "DNA_mask_types.h"
43 #include "DNA_object_types.h"   /* SELECT */
44
45 #include "BLI_utildefines.h"
46 #include "BLI_math.h"
47 #include "BLI_string.h"
48 #include "BLI_rect.h"
49
50 #include "GPU_extensions.h"
51
52 #include "IMB_imbuf_types.h"
53 #include "IMB_imbuf.h"
54
55 #include "ED_screen.h"
56 #include "ED_clip.h"
57
58 #include "BIF_gl.h"
59 #include "BIF_glutil.h"
60
61 #include "WM_api.h"
62 #include "WM_types.h"
63
64 #include "UI_view2d.h"
65
66 #include "clip_intern.h"        // own include
67
68 /* ******** operactor poll functions ******** */
69
70 int ED_space_clip_poll(bContext *C)
71 {
72         SpaceClip *sc = CTX_wm_space_clip(C);
73
74         if (sc && sc->clip)
75                 return TRUE;
76
77         return FALSE;
78 }
79
80 int ED_space_clip_view_clip_poll(bContext *C)
81 {
82         SpaceClip *sc = CTX_wm_space_clip(C);
83
84         if (sc && sc->clip) {
85                 return sc->view == SC_VIEW_CLIP;
86         }
87
88         return FALSE;
89 }
90
91 int ED_space_clip_tracking_poll(bContext *C)
92 {
93         SpaceClip *sc = CTX_wm_space_clip(C);
94
95         if (sc && sc->clip)
96                 return ED_space_clip_check_show_trackedit(sc);
97
98         return FALSE;
99 }
100
101 int ED_space_clip_maskedit_poll(bContext *C)
102 {
103         SpaceClip *sc = CTX_wm_space_clip(C);
104
105         if (sc && sc->clip) {
106                 return ED_space_clip_check_show_maskedit(sc);
107         }
108
109         return FALSE;
110 }
111
112 int ED_space_clip_maskedit_mask_poll(bContext *C)
113 {
114         if (ED_space_clip_maskedit_poll(C)) {
115                 MovieClip *clip = CTX_data_edit_movieclip(C);
116
117                 if (clip) {
118                         SpaceClip *sc = CTX_wm_space_clip(C);
119
120                         return sc->mask_info.mask != NULL;
121                 }
122         }
123
124         return FALSE;
125 }
126
127 /* ******** common editing functions ******** */
128
129 void ED_space_clip_get_size(SpaceClip *sc, int *width, int *height)
130 {
131         if (sc->clip) {
132                 BKE_movieclip_get_size(sc->clip, &sc->user, width, height);
133         }
134         else {
135                 *width = *height = IMG_SIZE_FALLBACK;
136         }
137 }
138
139 void ED_space_clip_get_size_fl(SpaceClip *sc, float size[2])
140 {
141         int size_i[2];
142         ED_space_clip_get_size(sc, &size_i[0], &size_i[1]);
143         size[0] = size_i[0];
144         size[1] = size_i[1];
145 }
146
147 void ED_space_clip_get_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy)
148 {
149         int width, height;
150
151         ED_space_clip_get_size(sc, &width, &height);
152
153         *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / (BLI_rctf_size_x(&ar->v2d.cur) * width);
154         *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / (BLI_rctf_size_y(&ar->v2d.cur) * height);
155 }
156
157 void ED_space_clip_get_aspect(SpaceClip *sc, float *aspx, float *aspy)
158 {
159         MovieClip *clip = ED_space_clip_get_clip(sc);
160
161         if (clip)
162                 BKE_movieclip_get_aspect(clip, aspx, aspy);
163         else
164                 *aspx = *aspy = 1.0f;
165
166         if (*aspx < *aspy) {
167                 *aspy = *aspy / *aspx;
168                 *aspx = 1.0f;
169         }
170         else {
171                 *aspx = *aspx / *aspy;
172                 *aspy = 1.0f;
173         }
174 }
175
176 void ED_space_clip_get_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy)
177 {
178         int w, h;
179
180         /* most of tools does not require aspect to be returned with dimensions correction
181          * due to they're invariant to this stuff, but some transformation tools like rotation
182          * should be aware of aspect correction caused by different resolution in different
183          * directions.
184          * mainly this is sued for transformation stuff
185          */
186
187         if (!sc->clip) {
188                 *aspx = 1.0f;
189                 *aspy = 1.0f;
190
191                 return;
192         }
193
194         ED_space_clip_get_aspect(sc, aspx, aspy);
195         BKE_movieclip_get_size(sc->clip, &sc->user, &w, &h);
196
197         *aspx *= (float) w;
198         *aspy *= (float) h;
199
200         if (*aspx < *aspy) {
201                 *aspy = *aspy / *aspx;
202                 *aspx = 1.0f;
203         }
204         else {
205                 *aspx = *aspx / *aspy;
206                 *aspy = 1.0f;
207         }
208 }
209
210 /* return current frame number in clip space */
211 int ED_space_clip_get_clip_frame_number(SpaceClip *sc)
212 {
213         MovieClip *clip = ED_space_clip_get_clip(sc);
214
215         return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
216 }
217
218 ImBuf *ED_space_clip_get_buffer(SpaceClip *sc)
219 {
220         if (sc->clip) {
221                 ImBuf *ibuf;
222
223                 ibuf = BKE_movieclip_get_postprocessed_ibuf(sc->clip, &sc->user, sc->postproc_flag);
224
225                 if (ibuf && (ibuf->rect || ibuf->rect_float))
226                         return ibuf;
227
228                 if (ibuf)
229                         IMB_freeImBuf(ibuf);
230         }
231
232         return NULL;
233 }
234
235 ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale, float *angle)
236 {
237         if (sc->clip) {
238                 ImBuf *ibuf;
239
240                 ibuf = BKE_movieclip_get_stable_ibuf(sc->clip, &sc->user, loc, scale, angle, sc->postproc_flag);
241
242                 if (ibuf && (ibuf->rect || ibuf->rect_float))
243                         return ibuf;
244
245                 if (ibuf)
246                         IMB_freeImBuf(ibuf);
247         }
248
249         return NULL;
250 }
251
252 /* returns color in SRGB */
253 /* matching ED_space_image_color_sample() */
254 int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
255 {
256         ImBuf *ibuf;
257         float fx, fy, co[2];
258         int ret = FALSE;
259
260         ibuf = ED_space_clip_get_buffer(sc);
261         if (!ibuf) {
262                 return FALSE;
263         }
264
265         /* map the mouse coords to the backdrop image space */
266         ED_clip_mouse_pos(sc, ar, mval, co);
267
268         fx = co[0];
269         fy = co[1];
270
271         if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
272                 float *fp;
273                 unsigned char *cp;
274                 int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
275
276                 CLAMP(x, 0, ibuf->x - 1);
277                 CLAMP(y, 0, ibuf->y - 1);
278
279                 if (ibuf->rect_float) {
280                         fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
281                         linearrgb_to_srgb_v3_v3(r_col, fp);
282                         ret = TRUE;
283                 }
284                 else if (ibuf->rect) {
285                         cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
286                         rgb_uchar_to_float(r_col, cp);
287                         ret = TRUE;
288                 }
289         }
290
291         return ret;
292 }
293
294 void ED_clip_update_frame(const Main *mainp, int cfra)
295 {
296         wmWindowManager *wm;
297         wmWindow *win;
298
299         /* image window, compo node users */
300         for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
301                 for (win = wm->windows.first; win; win = win->next) {
302                         ScrArea *sa;
303
304                         for (sa = win->screen->areabase.first; sa; sa = sa->next) {
305                                 if (sa->spacetype == SPACE_CLIP) {
306                                         SpaceClip *sc = sa->spacedata.first;
307
308                                         sc->scopes.ok = FALSE;
309
310                                         BKE_movieclip_user_set_frame(&sc->user, cfra);
311                                 }
312                         }
313                 }
314         }
315 }
316
317 static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
318 {
319         MovieClip *clip = ED_space_clip_get_clip(sc);
320         MovieTrackingTrack *track;
321         int width, height, ok = FALSE;
322         ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
323         int framenr = ED_space_clip_get_clip_frame_number(sc);
324
325         INIT_MINMAX2(min, max);
326
327         ED_space_clip_get_size(sc, &width, &height);
328
329         track = tracksbase->first;
330         while (track) {
331                 if (TRACK_VIEW_SELECTED(sc, track)) {
332                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
333
334                         if (marker) {
335                                 float pos[3];
336
337                                 pos[0] = marker->pos[0] + track->offset[0];
338                                 pos[1] = marker->pos[1] + track->offset[1];
339                                 pos[2] = 0.0f;
340
341                                 /* undistortion happens for normalized coords */
342                                 if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
343                                         /* undistortion happens for normalized coords */
344                                         ED_clip_point_undistorted_pos(sc, pos, pos);
345                                 }
346
347                                 pos[0] *= width;
348                                 pos[1] *= height;
349
350                                 mul_v3_m4v3(pos, sc->stabmat, pos);
351
352                                 DO_MINMAX2(pos, min, max);
353
354                                 ok = TRUE;
355                         }
356                 }
357
358                 track = track->next;
359         }
360
361         return ok;
362 }
363
364 int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
365 {
366         SpaceClip *sc = CTX_wm_space_clip(C);
367         int w, h, frame_width, frame_height;
368         float min[2], max[2];
369
370         ED_space_clip_get_size(sc, &frame_width, &frame_height);
371
372         if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL))
373                 return FALSE;
374
375         if (!selected_boundbox(sc, min, max))
376                 return FALSE;
377
378         /* center view */
379         clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width),
380                                       (max[1] + min[1]) / (2 * frame_height));
381
382         w = max[0] - min[0];
383         h = max[1] - min[1];
384
385         /* set zoom to see all selection */
386         if (w > 0 && h > 0) {
387                 int width, height;
388                 float zoomx, zoomy, newzoom, aspx, aspy;
389
390                 ED_space_clip_get_aspect(sc, &aspx, &aspy);
391
392                 width  = BLI_rcti_size_x(&ar->winrct) + 1;
393                 height = BLI_rcti_size_y(&ar->winrct) + 1;
394
395                 zoomx = (float)width / w / aspx;
396                 zoomy = (float)height / h / aspy;
397
398                 newzoom = 1.0f / power_of_2(1.0f / minf(zoomx, zoomy));
399
400                 if (fit || sc->zoom > newzoom)
401                         sc->zoom = newzoom;
402         }
403
404         return TRUE;
405 }
406
407 void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2])
408 {
409         copy_v2_v2(r_co, co);
410
411         if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
412                 MovieClip *clip = ED_space_clip_get_clip(sc);
413                 float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
414                 int width, height;
415
416                 BKE_movieclip_get_size(sc->clip, &sc->user, &width, &height);
417
418                 r_co[0] *= width;
419                 r_co[1] *= height * aspy;
420
421                 BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co);
422
423                 r_co[0] /= width;
424                 r_co[1] /= height * aspy;
425         }
426 }
427
428 void ED_clip_point_stable_pos(SpaceClip *sc, ARegion *ar, float x, float y, float *xr, float *yr)
429 {
430         int sx, sy, width, height;
431         float zoomx, zoomy, pos[3], imat[4][4];
432
433         ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
434         ED_space_clip_get_size(sc, &width, &height);
435
436         UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
437
438         pos[0] = (x - sx) / zoomx;
439         pos[1] = (y - sy) / zoomy;
440         pos[2] = 0.0f;
441
442         invert_m4_m4(imat, sc->stabmat);
443         mul_v3_m4v3(pos, imat, pos);
444
445         *xr = pos[0] / width;
446         *yr = pos[1] / height;
447
448         if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
449                 MovieClip *clip = ED_space_clip_get_clip(sc);
450                 MovieTracking *tracking = &clip->tracking;
451                 float aspy = 1.0f / tracking->camera.pixel_aspect;
452                 float tmp[2] = {*xr * width, *yr * height * aspy};
453
454                 BKE_tracking_distort_v2(tracking, tmp, tmp);
455
456                 *xr = tmp[0] / width;
457                 *yr = tmp[1] / (height * aspy);
458         }
459 }
460
461 /**
462  * \brief the reverse of ED_clip_point_stable_pos(), gets the marker region coords.
463  * better name here? view_to_track / track_to_view or so?
464  */
465 void ED_clip_point_stable_pos__reverse(SpaceClip *sc, ARegion *ar, const float co[2], float r_co[2])
466 {
467         float zoomx, zoomy;
468         float pos[3];
469         int width, height;
470         int sx, sy;
471
472         UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
473         ED_space_clip_get_size(sc, &width, &height);
474         ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
475
476         ED_clip_point_undistorted_pos(sc, co, pos);
477         pos[2] = 0.0f;
478
479         /* untested */
480         mul_v3_m4v3(pos, sc->stabmat, pos);
481
482         r_co[0] = (pos[0] * width  * zoomx) + (float)sx;
483         r_co[1] = (pos[1] * height * zoomy) + (float)sy;
484 }
485
486 /* takes event->mval */
487 void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, const int mval[2], float co[2])
488 {
489         ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &co[0], &co[1]);
490 }
491
492 int ED_space_clip_check_show_trackedit(SpaceClip *sc)
493 {
494         if (sc) {
495                 return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION);
496         }
497
498         return FALSE;
499 }
500
501 int ED_space_clip_check_show_maskedit(SpaceClip *sc)
502 {
503         if (sc) {
504                 return sc->mode == SC_MODE_MASKEDIT;
505         }
506
507         return FALSE;
508 }
509
510 /* ******** clip editing functions ******** */
511
512 MovieClip *ED_space_clip_get_clip(SpaceClip *sc)
513 {
514         return sc->clip;
515 }
516
517 void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip)
518 {
519         MovieClip *old_clip;
520
521         if (!screen && C)
522                 screen = CTX_wm_screen(C);
523
524         old_clip = sc->clip;
525         sc->clip = clip;
526
527         if (sc->clip && sc->clip->id.us == 0)
528                 sc->clip->id.us = 1;
529
530         if (screen && sc->view == SC_VIEW_CLIP) {
531                 ScrArea *area;
532                 SpaceLink *sl;
533
534                 for (area = screen->areabase.first; area; area = area->next) {
535                         for (sl = area->spacedata.first; sl; sl = sl->next) {
536                                 if (sl->spacetype == SPACE_CLIP) {
537                                         SpaceClip *cur_sc = (SpaceClip *) sl;
538
539                                         if (cur_sc != sc && cur_sc->view != SC_VIEW_CLIP) {
540                                                 if (cur_sc->clip == old_clip || cur_sc->clip == NULL) {
541                                                         cur_sc->clip = clip;
542                                                 }
543                                         }
544                                 }
545                         }
546                 }
547         }
548
549         if (C)
550                 WM_event_add_notifier(C, NC_MOVIECLIP | NA_SELECTED, sc->clip);
551 }
552
553 /* ******** masking editing functions ******** */
554
555 Mask *ED_space_clip_get_mask(SpaceClip *sc)
556 {
557         return sc->mask_info.mask;
558 }
559
560 void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
561 {
562         sc->mask_info.mask = mask;
563
564         if (sc->mask_info.mask && sc->mask_info.mask->id.us == 0) {
565                 sc->mask_info.mask->id.us = 1;
566         }
567
568         if (C) {
569                 WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
570         }
571 }
572
573 /* OpenGL draw context */
574
575 typedef struct SpaceClipDrawContext {
576         int support_checked, buffers_supported;
577
578         GLuint texture;                 /* OGL texture ID */
579         short texture_allocated;        /* flag if texture was allocated by glGenTextures */
580         struct ImBuf *texture_ibuf;     /* image buffer for which texture was created */
581         const unsigned char *display_buffer; /* display buffer for which texture was created */
582         int image_width, image_height;  /* image width and height for which texture was created */
583         unsigned last_texture;          /* ID of previously used texture, so it'll be restored after clip drawing */
584
585         /* fields to check if cache is still valid */
586         int framenr, start_frame, frame_offset;
587         short render_size, render_flag;
588
589         char colorspace[64];
590 } SpaceClipDrawContext;
591
592 int ED_space_clip_texture_buffer_supported(SpaceClip *sc)
593 {
594         SpaceClipDrawContext *context = sc->draw_context;
595
596         if (!context) {
597                 context = MEM_callocN(sizeof(SpaceClipDrawContext), "SpaceClipDrawContext");
598                 sc->draw_context = context;
599         }
600
601         if (!context->support_checked) {
602                 context->support_checked = TRUE;
603                 if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
604                         context->buffers_supported = FALSE;
605                 }
606                 else {
607                         context->buffers_supported = GPU_non_power_of_two_support();
608                 }
609         }
610
611         return context->buffers_supported;
612 }
613
614 int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsigned char *display_buffer)
615 {
616         SpaceClipDrawContext *context = sc->draw_context;
617         MovieClip *clip = ED_space_clip_get_clip(sc);
618         int need_rebind = 0;
619
620         context->last_texture = glaGetOneInteger(GL_TEXTURE_2D);
621
622         /* image texture need to be rebinded if displaying another image buffer
623          * assuming displaying happens of footage frames only on which painting doesn't heppen.
624          * so not changed image buffer pointer means unchanged image content */
625         need_rebind |= context->texture_ibuf != ibuf;
626         need_rebind |= context->display_buffer != display_buffer;
627         need_rebind |= context->framenr != sc->user.framenr;
628         need_rebind |= context->render_size != sc->user.render_size;
629         need_rebind |= context->render_flag != sc->user.render_flag;
630         need_rebind |= context->start_frame != clip->start_frame;
631         need_rebind |= context->frame_offset != clip->frame_offset;
632
633         if (!need_rebind) {
634                 /* OCIO_TODO: not entirely nice, but currently it seems to be easiest way
635                  *            to deal with changing input color space settings
636                  *            pointer-based check could fail due to new buffers could be
637                  *            be allocated on on old memory
638                  */
639                 need_rebind = strcmp(context->colorspace, clip->colorspace_settings.name) != 0;
640         }
641
642         if (need_rebind) {
643                 int width = ibuf->x, height = ibuf->y;
644                 int need_recreate = 0;
645
646                 if (width > GL_MAX_TEXTURE_SIZE || height > GL_MAX_TEXTURE_SIZE)
647                         return 0;
648
649                 /* if image resolution changed (e.g. switched to proxy display) texture need to be recreated */
650                 need_recreate = context->image_width != ibuf->x || context->image_height != ibuf->y;
651
652                 if (context->texture_ibuf && need_recreate) {
653                         glDeleteTextures(1, &context->texture);
654                         context->texture_allocated = 0;
655                 }
656
657                 if (need_recreate || !context->texture_allocated) {
658                         /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */
659                         int filter = GL_LINEAR;
660
661                         /* non-scaled proxy shouldn;t use diltering */
662                         if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
663                             ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
664                         {
665                                 filter = GL_NEAREST;
666                         }
667
668                         glGenTextures(1, &context->texture);
669                         glBindTexture(GL_TEXTURE_2D, context->texture);
670                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
671                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
672                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
673                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
674                 }
675                 else {
676                         /* if texture doesn't need to be reallocated itself, just bind it so
677                          * loading of image will happen to a proper texture */
678                         glBindTexture(GL_TEXTURE_2D, context->texture);
679                 }
680
681                 if (display_buffer)
682                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
683
684                 /* store settings */
685                 context->texture_allocated = 1;
686                 context->display_buffer = display_buffer;
687                 context->texture_ibuf = ibuf;
688                 context->image_width = ibuf->x;
689                 context->image_height = ibuf->y;
690                 context->framenr = sc->user.framenr;
691                 context->render_size = sc->user.render_size;
692                 context->render_flag = sc->user.render_flag;
693                 context->start_frame = clip->start_frame;
694                 context->frame_offset = clip->frame_offset;
695
696                 BLI_strncpy(context->colorspace, clip->colorspace_settings.name, sizeof(context->colorspace));
697         }
698         else {
699                 /* displaying exactly the same image which was loaded t oa texture,
700                  * just bint texture in this case */
701                 glBindTexture(GL_TEXTURE_2D, context->texture);
702         }
703
704         glEnable(GL_TEXTURE_2D);
705
706         return TRUE;
707 }
708
709 void ED_space_clip_unload_movieclip_buffer(SpaceClip *sc)
710 {
711         SpaceClipDrawContext *context = sc->draw_context;
712
713         glBindTexture(GL_TEXTURE_2D, context->last_texture);
714         glDisable(GL_TEXTURE_2D);
715 }
716
717 void ED_space_clip_free_texture_buffer(SpaceClip *sc)
718 {
719         SpaceClipDrawContext *context = sc->draw_context;
720
721         if (context) {
722                 glDeleteTextures(1, &context->texture);
723
724                 MEM_freeN(context);
725         }
726 }