创建逻辑
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.dllgraphics->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;//创建 displaydisplay = 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;
}