void XCompcapMain::render(gs_effect_t *effect)
{
	if (!p->win)
		return;

	PLock lock(&p->lock, true);

	effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);

	if (!lock.isLocked() || !p->tex)
		return;

	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, p->tex);

	while (gs_effect_loop(effect, "Draw")) {
		gs_draw_sprite(p->tex, 0, 0, 0);
	}

	if (p->cursor && p->gltex && p->show_cursor && !p->cursor_outside) {
		effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);

		while (gs_effect_loop(effect, "Draw")) {
			xcursor_render(p->cursor);
		}
	}
}
static void duplicator_capture_render(void *data, gs_effect_t *effect)
{
	struct duplicator_capture *capture = data;
	gs_texture_t *texture;
	int rot;

	if (!capture->duplicator)
		return;

	texture = gs_duplicator_get_texture(capture->duplicator);
	if (!texture)
		return;

	effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);

	rot = capture->rot;

	while (gs_effect_loop(effect, "Draw")) {
		if (rot != 0) {
			float x = 0.0f;
			float y = 0.0f;

			switch (rot) {
			case 90:
				x = (float)capture->height;
				break;
			case 180:
				x = (float)capture->width;
				y = (float)capture->height;
				break;
			case 270:
				y = (float)capture->width;
				break;
			}

			gs_matrix_push();
			gs_matrix_translate3f(x, y, 0.0f);
			gs_matrix_rotaa4f(0.0f, 0.0f, 1.0f, RAD((float)rot));
		}

		obs_source_draw(texture, 0, 0, 0, 0, false);

		if (rot != 0)
			gs_matrix_pop();
	}

	if (capture->capture_cursor) {
		effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);

		while (gs_effect_loop(effect, "Draw")) {
			draw_cursor(capture);
		}
	}
}
Exemple #3
0
static inline void render_item(struct obs_scene_item *item)
{
	if (item->crop_render) {
		uint32_t width  = obs_source_get_width(item->source);
		uint32_t height = obs_source_get_height(item->source);
		uint32_t cx = calc_cx(item, width);
		uint32_t cy = calc_cy(item, height);

		if (cx && cy && gs_texrender_begin(item->crop_render, cx, cy)) {
			float cx_scale = (float)width  / (float)cx;
			float cy_scale = (float)height / (float)cy;
			gs_matrix_scale3f(cx_scale, cy_scale, 1.0f);
			gs_matrix_translate3f(
					-(float)item->crop.left,
					-(float)item->crop.top,
					0.0f);

			obs_source_video_render(item->source);
			gs_texrender_end(item->crop_render);
		}
	}

	gs_matrix_push();
	gs_matrix_mul(&item->draw_transform);
	if (item->crop_render) {
		gs_texture_t *tex = gs_texrender_get_texture(item->crop_render);

		while (gs_effect_loop(obs->video.default_effect, "Draw"))
			obs_source_draw(tex, 0, 0, 0, 0, 0);
	} else {
		obs_source_video_render(item->source);
	}
	gs_matrix_pop();
}
void deinterlace_render(obs_source_t *s)
{
	gs_effect_t *effect = s->deinterlace_effect;

	uint64_t frame2_ts;
	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_eparam_t *prev = gs_effect_get_param_by_name(effect,
			"previous_image");
	gs_eparam_t *field = gs_effect_get_param_by_name(effect, "field_order");
	gs_eparam_t *frame2 = gs_effect_get_param_by_name(effect, "frame2");
	gs_eparam_t *dimensions = gs_effect_get_param_by_name(effect,
			"dimensions");
	struct vec2 size = {(float)s->async_width, (float)s->async_height};
	bool yuv = format_is_yuv(s->async_format);
	bool limited_range = yuv && !s->async_full_range;
	const char *tech = yuv ? "DrawMatrix" : "Draw";

	gs_texture_t *cur_tex = s->async_texrender ?
		gs_texrender_get_texture(s->async_texrender) :
		s->async_texture;
	gs_texture_t *prev_tex = s->async_prev_texrender ?
		gs_texrender_get_texture(s->async_prev_texrender) :
		s->async_prev_texture;

	if (!cur_tex || !prev_tex || !s->async_width || !s->async_height)
		return;

	gs_effect_set_texture(image, cur_tex);
	gs_effect_set_texture(prev, prev_tex);
	gs_effect_set_int(field, s->deinterlace_top_first);
	gs_effect_set_vec2(dimensions, &size);

	if (yuv) {
		gs_eparam_t *color_matrix = gs_effect_get_param_by_name(
				effect, "color_matrix");
		gs_effect_set_val(color_matrix, s->async_color_matrix,
				sizeof(float) * 16);
	}
	if (limited_range) {
		const size_t size = sizeof(float) * 3;
		gs_eparam_t *color_range_min = gs_effect_get_param_by_name(
				effect, "color_range_min");
		gs_eparam_t *color_range_max = gs_effect_get_param_by_name(
				effect, "color_range_max");
		gs_effect_set_val(color_range_min, s->async_color_range_min,
				size);
		gs_effect_set_val(color_range_max, s->async_color_range_max,
				size);
	}

	frame2_ts = s->deinterlace_frame_ts + s->deinterlace_offset +
		s->deinterlace_half_duration - TWOX_TOLERANCE;

	gs_effect_set_bool(frame2, obs->video.video_time >= frame2_ts);

	while (gs_effect_loop(effect, tech))
		gs_draw_sprite(NULL, s->async_flip ? GS_FLIP_V : 0,
				s->async_width, s->async_height);
}
Exemple #5
0
static void fade_callback(void *data, gs_texture_t *a, gs_texture_t *b, float t,
                          uint32_t cx, uint32_t cy)
{
    struct fade_info *fade = data;

    gs_effect_set_texture(fade->a_param, a);
    gs_effect_set_texture(fade->b_param, b);
    gs_effect_set_float(fade->fade_param, t);

    while (gs_effect_loop(fade->effect, "Fade"))
        gs_draw_sprite(NULL, 0, cx, cy);
}
Exemple #6
0
/**
 * Render the capture data
 */
static void xshm_video_render(void *vptr, gs_effect_t *effect)
{
	XSHM_DATA(vptr);

	effect = obs_get_opaque_effect();

	if (!data->texture)
		return;

	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, data->texture);

	while (gs_effect_loop(effect, "Draw")) {
		gs_draw_sprite(data->texture, 0, 0, 0);
	}

	if (data->show_cursor) {
		effect = obs_get_default_effect();

		while (gs_effect_loop(effect, "Draw")) {
			xcb_xcursor_render(data->cursor);
		}
	}
}
Exemple #7
0
static void render_item_texture(struct obs_scene_item *item)
{
	gs_texture_t *tex = gs_texrender_get_texture(item->item_render);
	gs_effect_t *effect = obs->video.default_effect;
	enum obs_scale_type type = item->scale_filter;
	uint32_t cx = gs_texture_get_width(tex);
	uint32_t cy = gs_texture_get_height(tex);

	if (type != OBS_SCALE_DISABLE) {
		if (type == OBS_SCALE_POINT) {
			gs_eparam_t *image = gs_effect_get_param_by_name(
					effect, "image");
			gs_effect_set_next_sampler(image,
					obs->video.point_sampler);

		} else if (!close_float(item->output_scale.x, 1.0f, EPSILON) ||
		           !close_float(item->output_scale.y, 1.0f, EPSILON)) {
			gs_eparam_t *scale_param;

			if (item->output_scale.x < 0.5f ||
			    item->output_scale.y < 0.5f) {
				effect = obs->video.bilinear_lowres_effect;
			} else if (type == OBS_SCALE_BICUBIC) {
				effect = obs->video.bicubic_effect;
			} else if (type == OBS_SCALE_LANCZOS) {
				effect = obs->video.lanczos_effect;
			}

			scale_param = gs_effect_get_param_by_name(effect,
					"base_dimension_i");
			if (scale_param) {
				struct vec2 base_res_i = {
					1.0f / (float)cx,
					1.0f / (float)cy
				};

				gs_effect_set_vec2(scale_param, &base_res_i);
			}
		}
	}

	while (gs_effect_loop(effect, "Draw"))
		obs_source_draw(tex, 0, 0, 0, 0, 0);
}
static inline void renderVB(gs_effect_t *effect, gs_vertbuffer_t *vb,
		int cx, int cy)
{
	if (!vb)
		return;

	matrix4 transform;
	matrix4_identity(&transform);
	transform.x.x = cx;
	transform.y.y = cy;

	gs_load_vertexbuffer(vb);

	gs_matrix_push();
	gs_matrix_mul(&transform);

	while (gs_effect_loop(effect, "Solid"))
		gs_draw(GS_LINESTRIP, 0, 0);

	gs_matrix_pop();
}
void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
{
	OBSProjector *window = (OBSProjector *)data;

	if (updatingMultiview || !window->ready)
		return;

	OBSBasic     *main   = (OBSBasic *)obs_frontend_get_main_window();
	uint32_t     targetCX, targetCY;
	int          x, y;
	float        scale;

	targetCX = (uint32_t)window->fw;
	targetCY = (uint32_t)window->fh;

	GetScaleAndCenterPos(targetCX, targetCY, cx, cy, x, y, scale);

	OBSSource previewSrc = main->GetCurrentSceneSource();
	OBSSource programSrc = main->GetProgramSource();
	bool studioMode = main->IsPreviewProgramMode();

	auto renderVB = [&](gs_vertbuffer_t *vb, int cx, int cy,
			uint32_t colorVal)
	{
		if (!vb)
			return;

		matrix4 transform;
		matrix4_identity(&transform);
		transform.x.x = cx;
		transform.y.y = cy;

		gs_load_vertexbuffer(vb);

		gs_matrix_push();
		gs_matrix_mul(&transform);

		gs_effect_set_color(window->color, colorVal);
		while (gs_effect_loop(window->solid, "Solid"))
			gs_draw(GS_LINESTRIP, 0, 0);

		gs_matrix_pop();
	};

	auto drawBox = [&](float cx, float cy, uint32_t colorVal)
	{
		gs_effect_set_color(window->color, colorVal);
		while (gs_effect_loop(window->solid, "Solid"))
			gs_draw_sprite(nullptr, 0, (uint32_t)cx, (uint32_t)cy);
	};

	auto setRegion = [&](float bx, float by, float cx,
			float cy)
	{
		float vX  = int(x + bx * scale);
		float vY  = int(y + by * scale);
		float vCX = int(cx * scale);
		float vCY = int(cy * scale);

		float oL = bx;
		float oT = by;
		float oR = (bx + cx);
		float oB = (by + cy);

		startRegion(vX, vY, vCX, vCY, oL, oR, oT, oB);
	};

	auto calcBaseSource = [&](size_t i)
	{
		switch (multiviewLayout) {
		case MultiviewLayout::HORIZONTAL_TOP_24_SCENES:
			window->sourceX = (i % 6) * window->scenesCX;
			window->sourceY = window->pvwprgCY +
					(i / 6) * window->scenesCY;
			break;
		case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
			window->sourceX = window->pvwprgCX;
			window->sourceY = (i / 2 ) * window->scenesCY;
			if (i % 2 != 0)
				window->sourceX += window->scenesCX;
			break;
		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
			window->sourceX = 0;
			window->sourceY = (i / 2 ) * window->scenesCY;
			if (i % 2 != 0)
				window->sourceX = window->scenesCX;
			break;
		case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
			if (i < 4) {
				window->sourceX = (float(i) * window->scenesCX);
				window->sourceY = 0;
			} else {
				window->sourceX = (float(i - 4) *
						window->scenesCX);
				window->sourceY = window->scenesCY;
			}
			break;
		default: // MultiviewLayout::HORIZONTAL_TOP_8_SCENES:
			if (i < 4) {
				window->sourceX = (float(i) * window->scenesCX);
				window->sourceY = window->pvwprgCY;
			} else {
				window->sourceX = (float(i - 4) *
						window->scenesCX);
				window->sourceY = window->pvwprgCY +
						window->scenesCY;
			}
		}
		window->siX = window->sourceX + window->thickness;
		window->siY = window->sourceY + window->thickness;
	};

	auto calcPreviewProgram = [&](bool program)
	{
		switch (multiviewLayout) {
		case MultiviewLayout::HORIZONTAL_TOP_24_SCENES:
			window->sourceX = window->thickness +
					window->pvwprgCX / 2;
			window->sourceY = window->thickness;
			window->labelX = window->offset + window->pvwprgCX / 2;
			window->labelY = window->pvwprgCY * 0.85f;
			if (program) {
				window->sourceX += window->pvwprgCX;
				window->labelX += window->pvwprgCX;
			}
			break;
		case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
			window->sourceX = window->thickness;
			window->sourceY = window->pvwprgCY + window->thickness;
			window->labelX = window->offset;
			window->labelY = window->pvwprgCY * 1.85f;
			if (program) {
				window->sourceY = window->thickness;
				window->labelY = window->pvwprgCY * 0.85f;
			}
			break;
		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
			window->sourceX = window->pvwprgCX + window->thickness;
			window->sourceY = window->pvwprgCY + window->thickness;
			window->labelX = window->pvwprgCX + window->offset;
			window->labelY = window->pvwprgCY * 1.85f;
			if (program) {
				window->sourceY = window->thickness;
				window->labelY = window->pvwprgCY * 0.85f;
			}
			break;
		case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
			window->sourceX = window->thickness;
			window->sourceY = window->pvwprgCY + window->thickness;
			window->labelX = window->offset;
			window->labelY = window->pvwprgCY * 1.85f;
			if (program) {
				window->sourceX += window->pvwprgCX;
				window->labelX += window->pvwprgCX;
			}
			break;
		default: // MultiviewLayout::HORIZONTAL_TOP_8_SCENES:
			window->sourceX = window->thickness;
			window->sourceY = window->thickness;
			window->labelX = window->offset;
			window->labelY = window->pvwprgCY * 0.85f;
			if (program) {
				window->sourceX += window->pvwprgCX;
				window->labelX += window->pvwprgCX;
			}
		}
	};

	auto paintAreaWithColor = [&](float tx, float ty, float cx, float cy,
			uint32_t color)
	{
		gs_matrix_push();
		gs_matrix_translate3f(tx, ty, 0.0f);
		drawBox(cx, cy, color);
		gs_matrix_pop();
	};

	// Define the whole usable region for the multiview
	startRegion(x, y, targetCX * scale, targetCY * scale, 0.0f, window->fw,
			0.0f, window->fh);

	// Change the background color to highlight all sources
	drawBox(window->fw, window->fh, outerColor);

	/* ----------------------------- */
	/* draw sources                  */

	for (size_t i = 0; i < maxSrcs; i++) {
		// Handle all the offsets
		calcBaseSource(i);

		if (i >= numSrcs) {
			// Just paint the background and continue
			paintAreaWithColor(window->sourceX, window->sourceY,
					window->scenesCX, window->scenesCY,
					outerColor);
			paintAreaWithColor(window->siX, window->siY,
					window->siCX, window->siCY,
					backgroundColor);
			continue;
		}

		OBSSource src = OBSGetStrongRef(window->multiviewScenes[i]);

		// We have a source. Now chose the proper highlight color
		uint32_t colorVal = outerColor;
		if (src == programSrc)
			colorVal = programColor;
		else if (src == previewSrc)
			colorVal = studioMode ? previewColor : programColor;

		// Paint the background
		paintAreaWithColor(window->sourceX, window->sourceY,
				window->scenesCX, window->scenesCY, colorVal);
		paintAreaWithColor(window->siX, window->siY, window->siCX,
				window->siCY, backgroundColor);

		/* ----------- */

		// Render the source
		gs_matrix_push();
		gs_matrix_translate3f(window->siX, window->siY, 0.0f);
		gs_matrix_scale3f(window->siScaleX, window->siScaleY, 1.0f);
		setRegion(window->siX, window->siY, window->siCX, window->siCY);
		obs_source_video_render(src);
		endRegion();
		gs_matrix_pop();

		/* ----------- */

		// Render the label
		if (!drawLabel)
			continue;

		obs_source *label = window->multiviewLabels[i + 2];
		if (!label)
			continue;

		window->offset = labelOffset(label, window->scenesCX);

		gs_matrix_push();
		gs_matrix_translate3f(window->sourceX + window->offset,
				(window->scenesCY * 0.85f) + window->sourceY,
				0.0f);
		gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
		drawBox(obs_source_get_width(label),
				obs_source_get_height(label) +
				int(window->sourceY * 0.015f), labelColor);
		obs_source_video_render(label);
		gs_matrix_pop();
	}

	/* ----------------------------- */
	/* draw preview                  */

	obs_source_t *previewLabel = window->multiviewLabels[0];
	window->offset = labelOffset(previewLabel, window->pvwprgCX);
	calcPreviewProgram(false);

	// Paint the background
	paintAreaWithColor(window->sourceX, window->sourceY, window->ppiCX,
			window->ppiCY, backgroundColor);

	// Scale and Draw the preview
	gs_matrix_push();
	gs_matrix_translate3f(window->sourceX, window->sourceY, 0.0f);
	gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
	setRegion(window->sourceX, window->sourceY, window->ppiCX,
			window->ppiCY);
	if (studioMode)
		obs_source_video_render(previewSrc);
	else
		obs_render_main_texture();
	if (drawSafeArea) {
		renderVB(window->actionSafeMargin, targetCX, targetCY,
				outerColor);
		renderVB(window->graphicsSafeMargin, targetCX, targetCY,
				outerColor);
		renderVB(window->fourByThreeSafeMargin, targetCX, targetCY,
				outerColor);
		renderVB(window->leftLine, targetCX, targetCY, outerColor);
		renderVB(window->topLine, targetCX, targetCY, outerColor);
		renderVB(window->rightLine, targetCX, targetCY, outerColor);
	}
	endRegion();
	gs_matrix_pop();

	/* ----------- */

	// Draw the Label
	if (drawLabel) {
		gs_matrix_push();
		gs_matrix_translate3f(window->labelX, window->labelY, 0.0f);
		gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
		drawBox(obs_source_get_width(previewLabel),
				obs_source_get_height(previewLabel) +
				int(window->pvwprgCX * 0.015f), labelColor);
		obs_source_video_render(previewLabel);
		gs_matrix_pop();
	}

	/* ----------------------------- */
	/* draw program                  */

	obs_source_t *programLabel = window->multiviewLabels[1];
	window->offset = labelOffset(programLabel, window->pvwprgCX);
	calcPreviewProgram(true);

	paintAreaWithColor(window->sourceX, window->sourceY, window->ppiCX,
		window->ppiCY, backgroundColor);

	// Scale and Draw the program
	gs_matrix_push();
	gs_matrix_translate3f(window->sourceX, window->sourceY, 0.0f);
	gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
	setRegion(window->sourceX, window->sourceY, window->ppiCX,
			window->ppiCY);
	obs_render_main_texture();
	endRegion();
	gs_matrix_pop();

	/* ----------- */

	// Draw the Label
	if (drawLabel) {
		gs_matrix_push();
		gs_matrix_translate3f(window->labelX, window->labelY, 0.0f);
		gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
		drawBox(obs_source_get_width(programLabel),
				obs_source_get_height(programLabel) +
				int(window->pvwprgCX * 0.015f), labelColor);
		obs_source_video_render(programLabel);
		gs_matrix_pop();
	}

	// Region for future usage with aditional info.
	if (multiviewLayout == MultiviewLayout::HORIZONTAL_TOP_24_SCENES) {
		// Just paint the background for now
		paintAreaWithColor(window->thickness, window->thickness,
				window->siCX, window->siCY * 2 +
				window->thicknessx2, backgroundColor);
		paintAreaWithColor(window->thickness + 2.5 * (
				window->thicknessx2 + window->ppiCX),
				window->thickness, window->siCX,
				window->siCY * 2 + window->thicknessx2,
				backgroundColor);
	}

	endRegion();
}