obs directx11

创建逻辑

obs 在windows 下分为Opengl 和 directx 两种渲染模式,默认使用的是directx ,兼容性更好;

代码路径:

E:\opensrc\obs_studio_src\obs-studio\UI\obs-app.cpp 选择渲染模式

const char* OBSApp::GetRenderModule() const {
  const char* renderer = config_get_string(appConfig, "Video", "Renderer");

  return (astrcmpi(renderer, "Direct3D 11") == 0) ? DL_D3D11 : DL_OPENGL;
}

在ResetVideo中通过obs_video_info ovi 参数graphics_module 传递到底层

int OBSBasic::ResetVideo()
{
	if (outputHandler && outputHandler->Active())
		return OBS_VIDEO_CURRENTLY_ACTIVE;

	ProfileScope("OBSBasic::ResetVideo");

	struct obs_video_info ovi;
	int ret;

	GetConfigFPS(ovi.fps_num, ovi.fps_den);

	const char *colorFormat = config_get_string(activeConfiguration, "Video", "ColorFormat");
	const char *colorSpace = config_get_string(activeConfiguration, "Video", "ColorSpace");
	const char *colorRange = config_get_string(activeConfiguration, "Video", "ColorRange");

	ovi.graphics_module = App()->GetRenderModule();

gs_create(&video->graphics, ovi->graphics_module, ovi->adapter) 通过graphics_module load对应的动态库

static int obs_init_graphics(struct obs_video_info *ovi)
{
	struct obs_core_video *video = &obs->video;
	uint8_t transparent_tex_data[2 * 2 * 4] = {0};
	const uint8_t *transparent_tex = transparent_tex_data;
	struct gs_sampler_info point_sampler = {0};
	bool success = true;
	int errorcode;

	profile_start(obs_init_graphics_name);

	errorcode = gs_create(&video->graphics, ovi->graphics_module, ovi->adapter);

gs_create 完成设备的创建

int gs_create(graphics_t **pgraphics, const char *module, uint32_t adapter)
{
	int errcode = GS_ERROR_FAIL;

	graphics_t *graphics = bzalloc(sizeof(struct graphics_subsystem));
	pthread_mutex_init_value(&graphics->mutex);
	pthread_mutex_init_value(&graphics->effect_mutex);
    //动态库  libobs-d3d11.dll
	graphics->module = os_dlopen(module);
	if (!graphics->module) {
		errcode = GS_ERROR_MODULE_NOT_FOUND;
		goto error;
	}

	if (!load_graphics_imports(&graphics->exports, graphics->module, module))
		goto error;
    //创建设备
	errcode = graphics->exports.device_create(&graphics->device, adapter);
	if (errcode != GS_SUCCESS)
		goto error;

	if (!graphics_init(graphics)) {
		errcode = GS_ERROR_FAIL;
		goto error;
	}

	*pgraphics = graphics;
	return errcode;

error:
	gs_destroy(graphics);
	return errcode;
}

E:\opensrc\obs_studio_src\obs-studio\libobs-d3d11\d3d11-subsystem.cpp

走到d3d11 走的创建设备逻辑

int device_create(gs_device_t **p_device, uint32_t adapter)
{
	gs_device *device = NULL;
	int errorcode = GS_SUCCESS;

	try {
		blog(LOG_INFO, "---------------------------------");
		blog(LOG_INFO, "Initializing D3D11...");
		LogD3DAdapters();
		CreateShaderCacheDirectory();

		device = new gs_device(adapter);

	} catch (const UnsupportedHWError &error) {
		blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str, error.hr);
		errorcode = GS_ERROR_NOT_SUPPORTED;

	} catch (const HRError &error) {
		blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str, error.hr);
		errorcode = GS_ERROR_FAIL;
	}

	*p_device = device;
	return errorcode;
}

gs_device::gs_device(uint32_t adapterIdx) : curToplogy(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
{
	matrix4_identity(&curProjMatrix);
	matrix4_identity(&curViewMatrix);
	matrix4_identity(&curViewProjMatrix);

	memset(&viewport, 0, sizeof(viewport));

	for (size_t i = 0; i < GS_MAX_TEXTURES; i++) {
		curTextures[i] = NULL;
		curSamplers[i] = NULL;
	}

	InitFactory();
	InitAdapter(adapterIdx);
	InitDevice(adapterIdx);
	device_set_render_target(this, NULL, NULL);
}

渲染逻辑

通过qtobsdisplay 的CreateDisplay获得到原生窗口句柄 ;并且将句柄最终设置到交换链中desc.OutputWindow = hwnd

static inline enum gs_color_space make_swap_desc(gs_device *device, DXGI_SWAP_CHAIN_DESC &desc,
						 const gs_init_data *data, DXGI_SWAP_EFFECT effect, UINT flags)
{
	const HWND hwnd = (HWND)data->window.hwnd;
	const enum gs_color_space space = get_next_space(device, hwnd, effect);
	const gs_color_format format = get_swap_format_from_space(space, data->format);

	memset(&desc, 0, sizeof(desc));
	desc.BufferDesc.Width = data->cx;
	desc.BufferDesc.Height = data->cy;
	desc.BufferDesc.Format = ConvertGSTextureFormatView(format);
	desc.SampleDesc.Count = 1;
	desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	desc.BufferCount = data->num_backbuffers;
	desc.OutputWindow = hwnd;
	desc.Windowed = TRUE;
	desc.SwapEffect = effect;
	desc.Flags = flags;

	return space;
}

OBSQTDisplay 中通过 OBSDisplay display;

using OBSDisplay = OBSPtr<obs_display_t *, obs_display_destroy>;

与底层沟通:

void OBSQTDisplay::CreateDisplay()
{
	if (display)
		return;

	if (destroying)
		return;

	if (!windowHandle()->isExposed())
		return;

	QSize size = GetPixelSize(this);

	gs_init_data info = {};
	info.cx = size.width();
	info.cy = size.height();
	info.format = GS_BGRA;
	info.zsformat = GS_ZS_NONE;

	if (!QTToGSWindow(windowHandle(), info.window))
		return;
    //创建 display
	display = obs_display_create(&info, backgroundColor);

	emit DisplayCreated(this);
}


obs_display_t *obs_display_create(const struct gs_init_data *graphics_data, uint32_t background_color)
{
	struct obs_display *display = bzalloc(sizeof(struct obs_display));

	gs_enter_context(obs->video.graphics);

	display->background_color = background_color;
    //创建交换链
	if (!obs_display_init(display, graphics_data)) {
		obs_display_destroy(display);
		display = NULL;
	} else {
		pthread_mutex_lock(&obs->data.displays_mutex);
		display->prev_next = &obs->data.first_display;
		display->next = obs->data.first_display;
		obs->data.first_display = display;
		if (display->next)
			display->next->prev_next = &display->next;
		pthread_mutex_unlock(&obs->data.displays_mutex);
	}

	gs_leave_context();

	return display;
}

当发生原生创建的resizeEvent事件时:

void OBSQTDisplay::resizeEvent(QResizeEvent *event)
{
	QWidget::resizeEvent(event);

	CreateDisplay();

	if (isVisible() && display) {
		QSize size = GetPixelSize(this);
		obs_display_resize(display, size.width(), size.height());
	}

	emit DisplayResized();
}

通过obs_display_resize 接口更新渲染尺寸

void obs_display_resize(obs_display_t *display, uint32_t cx, uint32_t cy)
{
	if (!display)
		return;

	pthread_mutex_lock(&display->draw_info_mutex);

	display->next_cx = cx;
	display->next_cy = cy;

	pthread_mutex_unlock(&display->draw_info_mutex);
}

因此在graphics thread线程的render_display函数中

void render_display(struct obs_display *display)
{
	uint32_t cx, cy;
	bool update_color_space;

	if (!display || !display->enabled)
		return;

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

	pthread_mutex_lock(&display->draw_info_mutex);
    //渲染尺寸
	cx = display->next_cx;
	cy = display->next_cy;
	update_color_space = display->update_color_space;

	display->update_color_space = false;

	pthread_mutex_unlock(&display->draw_info_mutex);

	/* -------------------------------------------- */
    //d3d 渲染接口
	if (render_display_begin(display, cx, cy, update_color_space)) {
		GS_DEBUG_MARKER_BEGIN(GS_DEBUG_COLOR_DISPLAY, "obs_display");

		pthread_mutex_lock(&display->draw_callbacks_mutex);

		for (size_t i = 0; i < display->draw_callbacks.num; i++) {
			struct draw_callback *callback;
			callback = display->draw_callbacks.array + i;
            //上层回调通知
			callback->draw(callback->param, cx, cy);
		}

		pthread_mutex_unlock(&display->draw_callbacks_mutex);

		render_display_end();

		GS_DEBUG_MARKER_END();

		gs_present();
	}
}








最终调用到 render_display_begin 设置渲染视口
void device_set_viewport(gs_device_t *device, int x, int y, int width, int height)
{
	D3D11_VIEWPORT vp;
	memset(&vp, 0, sizeof(vp));
	vp.MaxDepth = 1.0f;
	vp.TopLeftX = (float)x;
	vp.TopLeftY = (float)y;
	vp.Width = (float)width;
	vp.Height = (float)height;
	device->context->RSSetViewports(1, &vp);

	device->viewport.x = x;
	device->viewport.y = y;
	device->viewport.cx = width;
	device->viewport.cy = height;
}
相关推荐
萌の鱼15 分钟前
leetcode 2279. 装满石头的背包的最大数量
数据结构·c++·算法·leetcode
--Ekko--16 分钟前
嵌入式入门Day38
c++
sun00770027 分钟前
C++中,typename
开发语言·c++
毒丐1 小时前
GCC使用说明
linux·c语言·c++
强大的RGG1 小时前
从源码编译Qt5
开发语言·c++·qt
(❁´◡`❁)Jimmy(❁´◡`❁)1 小时前
3103: 【基础】既生瑜,何生亮!
c++
s.feng1 小时前
00_basic_gemm
c++
oulaqiao3 小时前
以C++为基础快速了解C#
开发语言·c++·c#
Vec[95]4 小时前
如何将光源视角的深度贴图应用于摄像机视角的渲染
c++·算法·3d·贴图
AI+程序员在路上5 小时前
OpenCV轮廓相关操作API (C++)
c++·人工智能·opencv