obs_core_video_mix
+ -

render_main_texture

2024-07-01 12 0

render_main_texture函数中比较重要的是:

static inline void render_main_texture(struct obs_core_video_mix *video)
{
...
//设置背景颜色
    struct vec4 clear_color;
    vec4_set(&clear_color, 0.0f, 0.0f, 0.0f, 0.0f);

//设置颜色空间
    gs_set_render_target_with_color_space(video->render_texture, NULL, video->render_space);

//使用颜色清除背景空间
    gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0);

//设置尺寸
    set_render_size(base_width, base_height);

//draw_callbacks
    pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
    for (size_t i = obs->data.draw_callbacks.num; i > 0; i--)
    {
        struct draw_callback *const callback =    obs->data.draw_callbacks.array + (i - 1);
        callback->draw(callback->param, base_width, base_height);
    }
    pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);

    /* In some cases we can reuse a previous mix's texture and save re-rendering everything */
    size_t reuse_idx;
    if (can_reuse_mix_texture(video, &reuse_idx))
        draw_mix_texture(reuse_idx);
    else
        obs_view_render(video->view);

    video->texture_rendered = true;

//rendered_callbacks
    pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
    for (size_t i = 0; i < obs->data.rendered_callbacks.num; ++i)
    {
        struct rendered_callback *const callback =    &obs->data.rendered_callbacks.array[i];
        callback->rendered(callback->param);
    }
    pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);

}

gs_set_render_target_with_color_space

gs_set_render_target_with_color_space其实是调用device_set_render_target_internal函数,设置当前的texture为video->render_texture,并设置基本的信息。所以这一步其实是渲染的条件准备。

static void device_set_render_target_internal(gs_device_t *device,
                          gs_texture_t *tex,
                          gs_zstencil_t *zstencil,
                          enum gs_color_space space)
{
    if (device->curSwapChain) {
        if (!tex)
            tex = &device->curSwapChain->target;
        if (!zstencil)
            zstencil = &device->curSwapChain->zs;
    }

    if (device->curRenderTarget == tex && device->curZStencilBuffer == zstencil)
    {
        device->curColorSpace = space;
    }

    if (tex && tex->type != GS_TEXTURE_2D) {
        blog(LOG_ERROR,   "device_set_render_target_internal (D3D11): texture is not a 2D texture");
        return;
    }

    gs_texture_2d *const tex2d = static_cast<gs_texture_2d *>(tex);
    if (device->curRenderTarget != tex2d || device->curRenderSide != 0 ||
        device->curZStencilBuffer != zstencil)
    {
        device->curRenderTarget = tex2d;  //当前渲染纹理
        device->curZStencilBuffer = zstencil; //为NULL
        device->curRenderSide = 0;
        device->curColorSpace = space;
        device->curFramebufferInvalidate = true;
    }
}

所以对于gs_clear使用背景色清除背景,就是针对当前的curRenderTarget。

void device_clear(gs_device_t *device, uint32_t clear_flags,
          const struct vec4 *color, float depth, uint8_t stencil)
{
    if (clear_flags & GS_CLEAR_COLOR)
    {
        gs_texture_2d *const tex = device->curRenderTarget;
        if (tex)
        {
            const int side = device->curRenderSide;
            ID3D11RenderTargetView *const rtv = device->curFramebufferSrgb    ? tex->renderTargetLinear[side]    : tex->renderTarget[side];
            device->context->ClearRenderTargetView(rtv, color->ptr);
        }
    }

//深度模版为NULL
    if (device->curZStencilBuffer) 
    {
        uint32_t flags = 0;
        if ((clear_flags & GS_CLEAR_DEPTH) != 0)
            flags |= D3D11_CLEAR_DEPTH;
        if ((clear_flags & GS_CLEAR_STENCIL) != 0)
            flags |= D3D11_CLEAR_STENCIL;

        if (flags && device->curZStencilBuffer->view)
            device->context->ClearDepthStencilView(device->curZStencilBuffer->view, flags, depth,stencil);
    }
}

set_render_size

用于设置窗口及矩阵

static inline void set_render_size(uint32_t width, uint32_t height)
{
    gs_enable_depth_test(false);
    gs_set_cull_mode(GS_NEITHER);

    gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f);
    gs_set_viewport(0, 0, width, height);
}
void device_ortho(gs_device_t *device, float left, float right, float top,
          float bottom, float zNear, float zFar)
{
    matrix4 *dst = &device->curProjMatrix;

    float rml = right - left;
    float bmt = bottom - top;
    float fmn = zFar - zNear;

    vec4_zero(&dst->x);
    vec4_zero(&dst->y);
    vec4_zero(&dst->z);
    vec4_zero(&dst->t);

    dst->x.x = 2.0f / rml;
    dst->t.x = (left + right) / -rml;

    dst->y.y = 2.0f / -bmt;
    dst->t.y = (bottom + top) / bmt;

    dst->z.z = 1.0f / fmn;
    dst->t.z = zNear / -fmn;

    dst->t.w = 1.0f;
}

draw_callbacks和rendered_callbacks

这两个分别使用obs_add_main_render_callback和obs_add_main_rendered_callback添加的回调函数。

//draw_callbacks
void obs_add_main_render_callback(void (*draw)(void *param, uint32_t cx,uint32_t cy), void *param)
{
    struct draw_callback data = {draw, param};

    pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
    da_insert(obs->data.draw_callbacks, 0, &data);
    pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);
}

//rendered_callbacks
void obs_add_main_rendered_callback(void (*rendered)(void *param), void *param)
{
    struct rendered_callback data = {rendered, param};

    pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
    da_insert(obs->data.rendered_callbacks, 0, &data);
    pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);
}

从名字和先顺序序来看,一个是渲染前的渲染,一个是渲染后的渲染,都是进行渲染。
而中间的就是obs_view_render。

obs_view_render

obs_view_render是对当前view中所有通道的源进行渲染。

void obs_view_render(obs_view_t *view)
{
    if (!view)
        return;

    pthread_mutex_lock(&view->channels_mutex);
    for (size_t i = 0; i < MAX_CHANNELS; i++) 
    {
        struct obs_source *source = view->channels[i];
        if (source)
        {
            if (source->removed)
            {
                obs_source_release(source);
                view->channels[i] = NULL;
            } 
            else 
            {
                obs_source_video_render(source);
            }
        }
    }
    pthread_mutex_unloc

当需要与其它obs_core_video_mixs混合时,则不会使用本obs_core_video_mixs,使用can_reuse_mix_texture函数返回它的索引之后,调用draw_mix_texture进行混合。

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!