Beispiel #1
0
static int get_cached_work_texture(int *w_r, int *h_r)
{
	static GLint texid = -1;
	static int tex_w = 256;
	static int tex_h = 256;

	if (texid == -1) {
		GLint ltexid = glaGetOneInteger(GL_TEXTURE_2D);
		unsigned char *tbuf;

		glGenTextures(1, (GLuint *)&texid);

		glBindTexture(GL_TEXTURE_2D, texid);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		tbuf = MEM_callocN(tex_w * tex_h * 4, "tbuf");
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf);
		MEM_freeN(tbuf);

		glBindTexture(GL_TEXTURE_2D, ltexid);
	}

	*w_r = tex_w;
	*h_r = tex_h;
	return texid;
}
Beispiel #2
0
void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
{
	float xzoom = glaGetOneFloat(GL_ZOOM_X);
	float yzoom = glaGetOneFloat(GL_ZOOM_Y);

	/* The pixel space coordinate of the intersection of
	 * the [zoomed] image with the origin.
	 */
	float ix = -x / xzoom;
	float iy = -y / yzoom;
		
	/* The maximum pixel amounts the image can be cropped
	 * at the lower left without exceeding the origin.
	 */
	int off_x = floor(max_ff(ix, 0.0f));
	int off_y = floor(max_ff(iy, 0.0f));

	/* The zoomed space coordinate of the raster position
	 * (starting at the lower left most unclipped pixel).
	 */
	float rast_x = x + off_x * xzoom;
	float rast_y = y + off_y * yzoom;

	GLfloat scissor[4];
	int draw_w, draw_h;

	/* Determine the smallest number of pixels we need to draw
	 * before the image would go off the upper right corner.
	 *
	 * It may seem this is just an optimization but some graphics
	 * cards (ATI) freak out if there is a large zoom factor and
	 * a large number of pixels off the screen (probably at some
	 * level the number of image pixels to draw is getting multiplied
	 * by the zoom and then clamped). Making sure we draw the
	 * fewest pixels possible keeps everyone mostly happy (still
	 * fails if we zoom in on one really huge pixel so that it
	 * covers the entire screen).
	 */
	glGetFloatv(GL_SCISSOR_BOX, scissor);
	draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom));
	draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));

	if (draw_w > 0 && draw_h > 0) {
		int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);

		/* Don't use safe RasterPos (slower) if we can avoid it. */
		if (rast_x >= 0 && rast_y >= 0) {
			glRasterPos2f(rast_x, rast_y);
		}
		else {
			glaRasterPosSafe2f(rast_x, rast_y, 0, 0);
		}

		glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w);
		if (format == GL_LUMINANCE || format == GL_RED) {
			if (type == GL_FLOAT) {
				float *f_rect = (float *)rect;
				glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x));
			}
			else if (type == GL_INT || type == GL_UNSIGNED_INT) {
				int *i_rect = (int *)rect;
				glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y * row_w + off_x));
			}
		}
		else { /* RGBA */
			if (type == GL_FLOAT) {
				float *f_rect = (float *)rect;
				glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x) * 4);
			}
			else if (type == GL_UNSIGNED_BYTE) {
				unsigned char *uc_rect = (unsigned char *) rect;
				glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y * row_w + off_x) * 4);
			}
		}
		
		glPixelStorei(GL_UNPACK_ROW_LENGTH,  old_row_length);
	}
}
Beispiel #3
0
void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY)
{
	unsigned char *uc_rect = (unsigned char *) rect;
	float *f_rect = (float *)rect;
	float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y);
	int ltexid = glaGetOneInteger(GL_TEXTURE_2D);
	int lrowlength = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
	int subpart_x, subpart_y, tex_w, tex_h;
	int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
	int texid = get_cached_work_texture(&tex_w, &tex_h);
	int components;

	/* Specify the color outside this function, and tex will modulate it.
	 * This is useful for changing alpha without using glPixelTransferf()
	 */
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
	glBindTexture(GL_TEXTURE_2D, texid);

	/* don't want nasty border artifacts */
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);

#ifdef __APPLE__
	/* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
	glPixelZoom(1.f, 1.f);
#endif
	
	/* setup seamless 2=on, 0=off */
	seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
	
	offset_x = tex_w - seamless;
	offset_y = tex_h - seamless;
	
	nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
	nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);

	if (format == GL_RGBA)
		components = 4;
	else if (format == GL_RGB)
		components = 3;
	else if (format == GL_LUMINANCE)
		components = 1;
	else {
		BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
		return;
	}

	if (type == GL_FLOAT) {
		/* need to set internal format to higher range float */

		/* NOTE: this could fail on some drivers, like mesa,
		 *       but currently this code is only used by color
		 *       management stuff which already checks on whether
		 *       it's possible to use GL_RGBA16F_ARB
		 */

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
	}
	else {
		/* switch to 8bit RGBA for byte buffer  */
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
	}

	for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
		for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
			int remainder_x = img_w - subpart_x * offset_x;
			int remainder_y = img_h - subpart_y * offset_y;
			int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
			int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
			int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
			int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
			int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
			int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
			float rast_x = x + subpart_x * offset_x * xzoom;
			float rast_y = y + subpart_y * offset_y * yzoom;
			
			/* check if we already got these because we always get 2 more when doing seamless*/
			if (subpart_w <= seamless || subpart_h <= seamless)
				continue;
			
			if (type == GL_FLOAT) {
				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
				
				/* add an extra border of pixels so linear looks ok at edges of full image. */
				if (subpart_w < tex_w)
					glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
				if (subpart_h < tex_h)
					glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
				if (subpart_w < tex_w && subpart_h < tex_h)
					glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
			}
			else {
				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
				
				if (subpart_w < tex_w)
					glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
				if (subpart_h < tex_h)
					glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
				if (subpart_w < tex_w && subpart_h < tex_h)
					glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
			}

			glEnable(GL_TEXTURE_2D);
			glBegin(GL_QUADS);
			glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
			glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);

			glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
			glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);

			glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
			glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);

			glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
			glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
			glEnd();
			glDisable(GL_TEXTURE_2D);
		}
	}

	glBindTexture(GL_TEXTURE_2D, ltexid);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	
#ifdef __APPLE__
	/* workaround for os x 10.5/10.6 driver bug (above) */
	glPixelZoom(xzoom, yzoom);
#endif
}
static void draw_plane_marker_image(Scene *scene,
                                    MovieTrackingPlaneTrack *plane_track,
                                    MovieTrackingPlaneMarker *plane_marker)
{
	Image *image = plane_track->image;
	ImBuf *ibuf;
	void *lock;

	if (image == NULL) {
		return;
	}

	ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);

	if (ibuf) {
		unsigned char *display_buffer;
		void *cache_handle;

		if (image->flag & IMA_VIEW_AS_RENDER) {
			display_buffer = IMB_display_buffer_acquire(ibuf,
			                                            &scene->view_settings,
			                                            &scene->display_settings,
			                                            &cache_handle);
		}
		else {
			display_buffer = IMB_display_buffer_acquire(ibuf, NULL,
			                                            &scene->display_settings,
			                                            &cache_handle);
		}

		if (display_buffer) {
			GLuint texid, last_texid;
			float frame_corners[4][2] = {{0.0f, 0.0f},
			                             {1.0f, 0.0f},
			                             {1.0f, 1.0f},
			                             {0.0f, 1.0f}};
			float perspective_matrix[3][3];
			float gl_matrix[4][4];
			bool transparent = false;
			BKE_tracking_homography_between_two_quads(frame_corners,
			                                          plane_marker->corners,
			                                          perspective_matrix);

			homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);

			if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
				transparent = true;
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
			}

			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);

			last_texid = glaGetOneInteger(GL_TEXTURE_2D);
			glEnable(GL_TEXTURE_2D);
			glGenTextures(1, (GLuint *)&texid);

			glBindTexture(GL_TEXTURE_2D, texid);

			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
			             GL_UNSIGNED_BYTE, display_buffer);

			glPushMatrix();
			glMultMatrixf(gl_matrix);

			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
			glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
			glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
			glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
			glEnd();

			glPopMatrix();

			glBindTexture(GL_TEXTURE_2D, last_texid);
			glDisable(GL_TEXTURE_2D);

			if (transparent) {
				glDisable(GL_BLEND);
			}
		}

		IMB_display_buffer_release(cache_handle);
	}

	BKE_image_release_ibuf(image, ibuf, lock);
}
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, int draw_overlay)
{
	struct Main *bmain = CTX_data_main(C);
	struct ImBuf *ibuf = NULL;
	struct ImBuf *scope = NULL;
	struct View2D *v2d = &ar->v2d;
	/* int rectx, recty; */ /* UNUSED */
	float viewrectx, viewrecty;
	float render_size = 0.0;
	float proxy_size = 100.0;
	float col[3];
	GLuint texid;
	GLuint last_texid;
	void *display_buffer;
	void *cache_handle = NULL;
	const int is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
	int format, type;
	bool glsl_used = false;

	if (G.is_rendering == FALSE && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
		/* stop all running jobs, except screen one. currently previews frustrate Render
		 * needed to make so sequencer's rendering doesn't conflict with compositor
		 */
		WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE);

		if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
			/* in case of final rendering used for preview, kill all previews,
			 * otherwise threading conflict will happen in rendering module
			 */
			WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_RENDER_PREVIEW);
		}
	}

	render_size = sseq->render_size;
	if (render_size == 0) {
		render_size = scene->r.size;
	}
	else {
		proxy_size = render_size;
	}
	if (render_size < 0) {
		return;
	}

	viewrectx = (render_size * (float)scene->r.xsch) / 100.0f;
	viewrecty = (render_size * (float)scene->r.ysch) / 100.0f;

	/* rectx = viewrectx + 0.5f; */ /* UNUSED */
	/* recty = viewrecty + 0.5f; */ /* UNUSED */

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		viewrectx *= scene->r.xasp / scene->r.yasp;
		viewrectx /= proxy_size / 100.0f;
		viewrecty /= proxy_size / 100.0f;
	}

	if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
		UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
		glClearColor(col[0], col[1], col[2], 0.0);
		glClear(GL_COLOR_BUFFER_BIT);
	}

	/* without this colors can flicker from previous opengl state */
	glColor4ub(255, 255, 255, 255);

	UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
	UI_view2d_curRect_validate(v2d);

	/* only initialize the preview if a render is in progress */
	if (G.is_rendering)
		return;

	ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs);
	
	if (ibuf == NULL)
		return;

	if (ibuf->rect == NULL && ibuf->rect_float == NULL)
		return;

	if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) {
		SequencerScopes *scopes = &sseq->scopes;

		sequencer_check_scopes(scopes, ibuf);

		switch (sseq->mainb) {
			case SEQ_DRAW_IMG_IMBUF:
				if (!scopes->zebra_ibuf) {
					ImBuf *display_ibuf = IMB_dupImBuf(ibuf);

					if (display_ibuf->rect_float) {
						IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
						                                             &scene->display_settings);
					}
					scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
					IMB_freeImBuf(display_ibuf);
				}
				scope = scopes->zebra_ibuf;
				break;
			case SEQ_DRAW_IMG_WAVEFORM:
				if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
					if (!scopes->sep_waveform_ibuf)
						scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf);
					scope = scopes->sep_waveform_ibuf;
				}
				else {
					if (!scopes->waveform_ibuf)
						scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
					scope = scopes->waveform_ibuf;
				}
				break;
			case SEQ_DRAW_IMG_VECTORSCOPE:
				if (!scopes->vector_ibuf)
					scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
				scope = scopes->vector_ibuf;
				break;
			case SEQ_DRAW_IMG_HISTOGRAM:
				if (!scopes->histogram_ibuf)
					scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf);
				scope = scopes->histogram_ibuf;
				break;
		}

		scopes->reference_ibuf = ibuf;
	}

	/* setting up the view - actual drawing starts here */
	UI_view2d_view_ortho(v2d);

	/* only draw alpha for main buffer */
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		if (sseq->flag & SEQ_USE_ALPHA) {
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
			glColor4f(1.0, 1.0, 1.0, 1.0);
		}
	}

	if (scope) {
		IMB_freeImBuf(ibuf);
		ibuf = scope;

		if (ibuf->rect_float && ibuf->rect == NULL) {
			IMB_rect_from_float(ibuf);
		}

		display_buffer = (unsigned char *)ibuf->rect;
		format = GL_RGBA;
		type = GL_UNSIGNED_BYTE;
	}
	else {
		bool force_fallback = false;

		force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
		force_fallback |= (ibuf->dither != 0.0f);

		if (force_fallback) {
			/* Fallback to CPU based color space conversion */
			glsl_used = false;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}
		else if (ibuf->rect_float) {
			display_buffer = ibuf->rect_float;

			if (ibuf->channels == 4) {
				format = GL_RGBA;
			}
			else if (ibuf->channels == 3) {
				format = GL_RGB;
			}
			else {
				BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
				format = GL_RGBA;
				display_buffer = NULL;
			}

			type = GL_FLOAT;

			if (ibuf->float_colorspace) {
				glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true);
			}
			else {
				glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true);
			}
		}
		else if (ibuf->rect) {
			display_buffer = ibuf->rect;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;

			glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false);
		}
		else {
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}

		/* there's a data to be displayed, but GLSL is not initialized
		 * properly, in this case we fallback to CPU-based display transform
		 */
		if ((ibuf->rect || ibuf->rect_float) && !glsl_used) {
			display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
		}
	}

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glColor4f(1.0, 1.0, 1.0, 1.0);

	last_texid = glaGetOneInteger(GL_TEXTURE_2D);
	glEnable(GL_TEXTURE_2D);
	glGenTextures(1, (GLuint *)&texid);

	glBindTexture(GL_TEXTURE_2D, texid);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	if (type == GL_FLOAT)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer);
	else
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);

	glBegin(GL_QUADS);

	if (draw_overlay) {
		if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
			rctf tot_clip;
			tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
			tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin);
			tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
			tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);

			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
		}
		else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
			glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
			glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
			glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
			glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
		}
	}
	else {
		glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
	}
	glEnd();
	glBindTexture(GL_TEXTURE_2D, last_texid);
	glDisable(GL_TEXTURE_2D);
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
		glDisable(GL_BLEND);
	glDeleteTextures(1, &texid);

	if (glsl_used)
		IMB_colormanagement_finish_glsl_draw();

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {

		float x1 = v2d->tot.xmin;
		float y1 = v2d->tot.ymin;
		float x2 = v2d->tot.xmax;
		float y2 = v2d->tot.ymax;

		/* border */
		setlinestyle(3);

		UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);

		glBegin(GL_LINE_LOOP);
		glVertex2f(x1 - 0.5f, y1 - 0.5f);
		glVertex2f(x1 - 0.5f, y2 + 0.5f);
		glVertex2f(x2 + 0.5f, y2 + 0.5f);
		glVertex2f(x2 + 0.5f, y1 - 0.5f);
		glEnd();

		/* safety border */
		if ((sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
			float fac = 0.1;

			float a = fac * (x2 - x1);
			x1 += a;
			x2 -= a;

			a = fac * (y2 - y1);
			y1 += a;
			y2 -= a;

			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

			uiSetRoundBox(UI_CNR_ALL);
			uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);

			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

		}

		setlinestyle(0);
	}
	
	if (sseq->flag & SEQ_SHOW_GPENCIL) {
		if (is_imbuf) {
			/* draw grease-pencil (image aligned) */
			draw_gpencil_2dimage(C);
		}
	}

	if (!scope)
		IMB_freeImBuf(ibuf);
	
	/* ortho at pixel level */
	UI_view2d_view_restore(C);
	
	if (sseq->flag & SEQ_SHOW_GPENCIL) {
		if (is_imbuf) {
			/* draw grease-pencil (screen aligned) */
			draw_gpencil_view2d(C, 0);
		}
	}


	/* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not,
	 * for now just disable drawing since the strip frame will likely be offset */

	//if (sc->mode == SC_MODE_MASKEDIT) {
	if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		Mask *mask = BKE_sequencer_mask_get(scene);

		if (mask) {
			int width, height;
			float aspx = 1.0f, aspy = 1.0f;
			// ED_mask_get_size(C, &width, &height);

			//Scene *scene = CTX_data_scene(C);
			width = (scene->r.size * scene->r.xsch) / 100;
			height = (scene->r.size * scene->r.ysch) / 100;

			ED_mask_draw_region(mask, ar,
			                    0, 0,  /* TODO */
			                    width, height,
			                    aspx, aspy,
			                    FALSE, TRUE,
			                    NULL, C);
		}
	}

	if (cache_handle)
		IMB_display_buffer_release(cache_handle);
}
Beispiel #6
0
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
{
	struct Main *bmain = CTX_data_main(C);
	struct ImBuf *ibuf = NULL;
	struct ImBuf *scope = NULL;
	struct View2D *v2d = &ar->v2d;
	/* int rectx, recty; */ /* UNUSED */
	float viewrect[2];
	float col[3];
	GLuint texid;
	GLuint last_texid;
	void *display_buffer;
	void *cache_handle = NULL;
	const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
	int format, type;
	bool glsl_used = false;
	const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd);
	const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
	bool draw_metadata = false;

	if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
		/* stop all running jobs, except screen one. currently previews frustrate Render
		 * needed to make so sequencer's rendering doesn't conflict with compositor
		 */
		WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE);

		if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
			/* in case of final rendering used for preview, kill all previews,
			 * otherwise threading conflict will happen in rendering module
			 */
			WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
		}
	}

	if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
		UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
		glClearColor(col[0], col[1], col[2], 0.0);
		glClear(GL_COLOR_BUFFER_BIT);
	}

	/* without this colors can flicker from previous opengl state */
	glColor4ub(255, 255, 255, 255);

	/* only initialize the preview if a render is in progress */
	if (G.is_rendering)
		return;

	if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
		return;
	}

	/* for now we only support Left/Right */
	ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);

	if ((ibuf == NULL) ||
	    (ibuf->rect == NULL && ibuf->rect_float == NULL))
	{
		/* gpencil can also be drawn without a valid imbuf */
		if (draw_gpencil && is_imbuf) {
			sequencer_display_size(scene, sseq, viewrect);

			sequencer_draw_background(sseq, v2d, viewrect);
			sequencer_draw_borders(sseq, v2d, scene);

			sequencer_draw_gpencil(C);
		}
		return;
	}

	sequencer_display_size(scene, sseq, viewrect);

	if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
		SequencerScopes *scopes = &sseq->scopes;

		sequencer_check_scopes(scopes, ibuf);

		switch (sseq->mainb) {
			case SEQ_DRAW_IMG_IMBUF:
				if (!scopes->zebra_ibuf) {
					ImBuf *display_ibuf = IMB_dupImBuf(ibuf);

					if (display_ibuf->rect_float) {
						IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
						                                             &scene->display_settings);
					}
					scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
					IMB_freeImBuf(display_ibuf);
				}
				scope = scopes->zebra_ibuf;
				break;
			case SEQ_DRAW_IMG_WAVEFORM:
				if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
					if (!scopes->sep_waveform_ibuf)
						scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf);
					scope = scopes->sep_waveform_ibuf;
				}
				else {
					if (!scopes->waveform_ibuf)
						scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
					scope = scopes->waveform_ibuf;
				}
				break;
			case SEQ_DRAW_IMG_VECTORSCOPE:
				if (!scopes->vector_ibuf)
					scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
				scope = scopes->vector_ibuf;
				break;
			case SEQ_DRAW_IMG_HISTOGRAM:
				if (!scopes->histogram_ibuf)
					scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf);
				scope = scopes->histogram_ibuf;
				break;
		}

		/* future files may have new scopes we don't catch above */
		if (scope) {
			scopes->reference_ibuf = ibuf;
			if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
				/* scopes drawn in image preview use viewrect from orig ibuf - currently that's only zebra */
			}
			else {
				viewrect[0] = scope->x;
				viewrect[1] = scope->y;
			}
		}
		else {
			scopes->reference_ibuf = NULL;
		}
	}

	if (!draw_backdrop) {
		sequencer_draw_background(sseq, v2d, viewrect);
	}

	if (scope) {
		IMB_freeImBuf(ibuf);
		ibuf = scope;

		if (ibuf->rect_float && ibuf->rect == NULL) {
			IMB_rect_from_float(ibuf);
		}

		display_buffer = (unsigned char *)ibuf->rect;
		format = GL_RGBA;
		type = GL_UNSIGNED_BYTE;
	}
	else {
		bool force_fallback = false;

		force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
		force_fallback |= (ibuf->dither != 0.0f);

		if (force_fallback) {
			/* Fallback to CPU based color space conversion */
			glsl_used = false;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}
		else if (ibuf->rect_float) {
			display_buffer = ibuf->rect_float;

			if (ibuf->channels == 4) {
				format = GL_RGBA;
			}
			else if (ibuf->channels == 3) {
				format = GL_RGB;
			}
			else {
				BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
				format = GL_RGBA;
				display_buffer = NULL;
			}

			type = GL_FLOAT;

			if (ibuf->float_colorspace) {
				glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, ibuf->dither, true);
			}
			else {
				glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true);
			}
		}
		else if (ibuf->rect) {
			display_buffer = ibuf->rect;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;

			glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, ibuf->dither, false);
		}
		else {
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}

		/* there's a data to be displayed, but GLSL is not initialized
		 * properly, in this case we fallback to CPU-based display transform
		 */
		if ((ibuf->rect || ibuf->rect_float) && !glsl_used) {
			display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
		}
	}

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glColor4f(1.0, 1.0, 1.0, 1.0);

	last_texid = glaGetOneInteger(GL_TEXTURE_2D);
	glEnable(GL_TEXTURE_2D);
	glGenTextures(1, (GLuint *)&texid);

	glBindTexture(GL_TEXTURE_2D, texid);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	if (type == GL_FLOAT)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer);
	else
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);

	if (draw_backdrop) {
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();
	}
	glBegin(GL_QUADS);

	if (draw_overlay) {
		if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
			rctf tot_clip;
			tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
			tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin);
			tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
			tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);

			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
		}
		else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
			glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
			glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
			glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
			glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
		}
	}
	else if (draw_backdrop) {
		float aspect;
		float image_aspect = viewrect[0] / viewrect[1];
		float imagex, imagey;

		aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);

		if (aspect >= image_aspect) {
			imagex = image_aspect / aspect;
			imagey = 1.0f;
		}
		else {
			imagex = 1.0f;
			imagey = aspect / image_aspect;
		}

		glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
	}
	else {
		draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0);

		glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
	}
	glEnd();

	glBindTexture(GL_TEXTURE_2D, last_texid);
	glDisable(GL_TEXTURE_2D);
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
		glDisable(GL_BLEND);
	glDeleteTextures(1, &texid);

	if (glsl_used)
		IMB_colormanagement_finish_glsl_draw();

	if (cache_handle)
		IMB_display_buffer_release(cache_handle);

	if (!scope)
		IMB_freeImBuf(ibuf);

	if (draw_metadata) {
		ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
	}

	if (draw_backdrop) {
		glPopMatrix();
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		return;
	}

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		sequencer_draw_borders(sseq, v2d, scene);
	}

	if (draw_gpencil && is_imbuf) {
		sequencer_draw_gpencil(C);
	}
	else {
		/* ortho at pixel level */
		UI_view2d_view_restore(C);
	}


	/* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not,
	 * for now just disable drawing since the strip frame will likely be offset */

	//if (sc->mode == SC_MODE_MASKEDIT) {
	if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		Mask *mask = BKE_sequencer_mask_get(scene);

		if (mask) {
			int width, height;
			float aspx = 1.0f, aspy = 1.0f;
			// ED_mask_get_size(C, &width, &height);

			//Scene *scene = CTX_data_scene(C);
			width = (scene->r.size * scene->r.xsch) / 100;
			height = (scene->r.size * scene->r.ysch) / 100;

			ED_mask_draw_region(mask, ar,
			                    0, 0, 0,  /* TODO */
			                    width, height,
			                    aspx, aspy,
			                    false, true,
			                    NULL, C);
		}
	}
}
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs)
{
	struct Main *bmain = CTX_data_main(C);
	struct ImBuf *ibuf = NULL;
	struct ImBuf *scope = NULL;
	struct View2D *v2d = &ar->v2d;
	int rectx, recty;
	float viewrectx, viewrecty;
	float render_size = 0.0;
	float proxy_size = 100.0;
	float col[3];
	GLuint texid;
	GLuint last_texid;
	SeqRenderData context;

	render_size = sseq->render_size;
	if (render_size == 0) {
		render_size = scene->r.size;
	}
	else {
		proxy_size = render_size;
	}
	if (render_size < 0) {
		return;
	}

	viewrectx = (render_size * (float)scene->r.xsch) / 100.0f;
	viewrecty = (render_size * (float)scene->r.ysch) / 100.0f;

	rectx = viewrectx + 0.5f;
	recty = viewrecty + 0.5f;

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		viewrectx *= scene->r.xasp / scene->r.yasp;
		viewrectx /= proxy_size / 100.0f;
		viewrecty /= proxy_size / 100.0f;
	}

	if (frame_ofs == 0) {
		UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
		glClearColor(col[0], col[1], col[2], 0.0);
		glClear(GL_COLOR_BUFFER_BIT);
	}

	/* without this colors can flicker from previous opengl state */
	glColor4ub(255, 255, 255, 255);

	UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
	UI_view2d_curRect_validate(v2d);

	/* only initialize the preview if a render is in progress */
	if (G.rendering)
		return;

	context = seq_new_render_data(bmain, scene, rectx, recty, proxy_size);

	if (special_seq_update)
		ibuf = give_ibuf_seq_direct(context, cfra + frame_ofs, special_seq_update);
	else if (!U.prefetchframes) // XXX || (G.f & G_PLAYANIM) == 0) {
		ibuf = give_ibuf_seq(context, cfra + frame_ofs, sseq->chanshown);
	else
		ibuf = give_ibuf_seq_threaded(context, cfra + frame_ofs, sseq->chanshown);
	
	if (ibuf == NULL)
		return;

	if (ibuf->rect == NULL && ibuf->rect_float == NULL)
		return;
	
	switch (sseq->mainb) {
		case SEQ_DRAW_IMG_IMBUF:
			if (sseq->zebra != 0) {
				scope = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
			}
			break;
		case SEQ_DRAW_IMG_WAVEFORM:
			if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
				scope = make_sep_waveform_view_from_ibuf(ibuf);
			}
			else {
				scope = make_waveform_view_from_ibuf(ibuf);
			}
			break;
		case SEQ_DRAW_IMG_VECTORSCOPE:
			scope = make_vectorscope_view_from_ibuf(ibuf);
			break;
		case SEQ_DRAW_IMG_HISTOGRAM:
			scope = make_histogram_view_from_ibuf(ibuf);
			break;
	}

	if (scope) {
		IMB_freeImBuf(ibuf);
		ibuf = scope;
	}

	if (ibuf->rect_float && ibuf->rect == NULL) {
		IMB_rect_from_float(ibuf);	
	}
	
	/* setting up the view - actual drawing starts here */
	UI_view2d_view_ortho(v2d);

	last_texid = glaGetOneInteger(GL_TEXTURE_2D);
	glEnable(GL_TEXTURE_2D);
	glGenTextures(1, (GLuint *)&texid);

	glBindTexture(GL_TEXTURE_2D, texid);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
	glBegin(GL_QUADS);

	if (frame_ofs) {
		rctf tot_clip;
		tot_clip.xmin = v2d->tot.xmin + (ABS(v2d->tot.xmax - v2d->tot.xmin) * scene->ed->over_border.xmin);
		tot_clip.ymin = v2d->tot.ymin + (ABS(v2d->tot.ymax - v2d->tot.ymin) * scene->ed->over_border.ymin);
		tot_clip.xmax = v2d->tot.xmin + (ABS(v2d->tot.xmax - v2d->tot.xmin) * scene->ed->over_border.xmax);
		tot_clip.ymax = v2d->tot.ymin + (ABS(v2d->tot.ymax - v2d->tot.ymin) * scene->ed->over_border.ymax);

		glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
		glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
		glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
		glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
	}
	else {
		glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
	}
	glEnd();
	glBindTexture(GL_TEXTURE_2D, last_texid);
	glDisable(GL_TEXTURE_2D);
	glDeleteTextures(1, &texid);

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {

		float x1 = v2d->tot.xmin;
		float y1 = v2d->tot.ymin;
		float x2 = v2d->tot.xmax;
		float y2 = v2d->tot.ymax;

		/* border */
		setlinestyle(3);

		UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);

		glBegin(GL_LINE_LOOP);
		glVertex2f(x1 - 0.5f, y1 - 0.5f);
		glVertex2f(x1 - 0.5f, y2 + 0.5f);
		glVertex2f(x2 + 0.5f, y2 + 0.5f);
		glVertex2f(x2 + 0.5f, y1 - 0.5f);
		glEnd();

		/* safety border */
		if ((sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
			float fac = 0.1;

			float a = fac * (x2 - x1);
			x1 += a;
			x2 -= a;

			a = fac * (y2 - y1);
			y1 += a;
			y2 -= a;

			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

			uiSetRoundBox(UI_CNR_ALL);
			uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);

			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

		}

		setlinestyle(0);
	}
	
	/* draw grease-pencil (image aligned) */
	draw_gpencil_2dimage(C);

	IMB_freeImBuf(ibuf);
	
	/* ortho at pixel level */
	UI_view2d_view_restore(C);
	
	/* draw grease-pencil (screen aligned) */
	draw_gpencil_view2d(C, 0);

	//if (sc->mode == SC_MODE_MASKEDIT) {
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		Mask *mask = BKE_sequencer_mask_get(scene);

		if (mask) {
			int width, height;
			// ED_mask_get_size(C, &width, &height);

			//Scene *scene = CTX_data_scene(C);
			width = (scene->r.size * scene->r.xsch) / 100;
			height = (scene->r.size * scene->r.ysch) / 100;

			ED_mask_draw_region(mask, ar,
			                    0, 0,  /* TODO */
			                    width, height,
			                    FALSE, TRUE,
			                    NULL, C);
		}
	}

}