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