呈现目标、设备和资源

呈现目标只是程序将绘制的位置。 通常,呈现目标是窗口 (具体来说,是窗口的工作区) 。 它也可能是内存中未显示的位图。 呈现目标由 ID2D1RenderTarget 接口表示。

设备是一种抽象,表示实际绘制像素的任何对象。 硬件设备使用 GPU 来提高性能,而软件设备使用 CPU。 应用程序不会创建设备。 相反,当应用程序创建呈现器目标时,会隐式创建设备。 每个呈现目标都与特定设备(硬件或软件)相关联。

显示呈现器目标与设备之间的关系的关系图。

资源是程序用于绘制的对象。 下面是 Direct2D 中定义的一些资源示例:

  • 画笔。 控制线条和区域的绘制方式。 画笔类型包括纯色画笔和渐变画笔。
  • 笔划样式。 控制线条的外观,例如虚线或实线。
  • 几何图形。 表示线条和曲线的集合。
  • 网格。 由三角形构成的形状。 网格数据可以直接由 GPU 使用,这与几何图形数据不同,几何图形数据必须在呈现之前进行转换。

呈现目标也被视为一种资源。

某些资源受益于硬件加速。 此类型的资源始终与特定设备相关联,无论是硬件 (GPU) 还是软件 (CPU) 。 这种类型的资源称为 依赖于设备的资源。 画笔和网格是依赖于设备的资源的示例。 如果设备不可用,则必须为新设备重新创建资源。

无论使用哪种设备,其他资源都保留在 CPU 内存中。 这些资源与 设备无关,因为它们不与特定设备关联。 当设备更改时,无需重新创建与设备无关的资源。 笔划样式和几何图形是独立于设备的资源。

每个资源的 MSDN 文档指出资源是依赖于设备还是与设备无关。 每个资源类型都由派生自 ID2D1Resource 的接口表示。 例如,画笔由 ID2D1Brush 接口表示。

Direct2D 工厂对象

使用 Direct2D 的第一步是创建 Direct2D 工厂对象的实例。 在计算机编程中, 工厂 是创建其他对象的对象。 Direct2D 工厂创建以下类型的对象:

  • 呈现目标。
  • 与设备无关的资源,例如笔划样式和几何图形。

与设备相关的资源(如画笔和位图)由呈现器目标对象创建。

显示 direct2d 工厂的关系图。

若要创建 Direct2D 工厂对象,请调用 D2D1CreateFactory 函数。

ID2D1Factory *pFactory = NULL;

HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);

第一个参数是指定创建选项的标志。 D2D1_FACTORY_TYPE_SINGLE_THREADED标志表示不会从多个线程调用 Direct2D。 若要支持来自多个线程的调用, 请指定 D2D1_FACTORY_TYPE_MULTI_THREADED。 如果程序使用单个线程调用 Direct2D,则单线程选项更有效。

D2D1CreateFactory 函数的第二个参数接收指向 ID2D1Factory 接口的指针。

应在第一个 WM_PAINT 消息之前创建 Direct2D 工厂对象。 WM_CREATE消息处理程序是创建工厂的好地方:

    case WM_CREATE:
        if (FAILED(D2D1CreateFactory(
                D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
        {
            return -1;  // Fail CreateWindowEx.
        }
        return 0;

创建 Direct2D 资源

Circle 程序使用以下依赖于设备的资源:

  • 与应用程序窗口关联的呈现目标。
  • 用于绘制圆圈的纯色画笔。

其中每个资源都由 COM 接口表示:

Circle 程序将指向这些接口的指针存储为 类的成员 MainWindow 变量:

ID2D1HwndRenderTarget   *pRenderTarget;
ID2D1SolidColorBrush    *pBrush;

以下代码创建这两个资源。

HRESULT MainWindow::CreateGraphicsResources()
{
    HRESULT hr = S_OK;
    if (pRenderTarget == NULL)
    {
        RECT rc;
        GetClientRect(m_hwnd, &rc);

        D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);

        hr = pFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(m_hwnd, size),
            &pRenderTarget);

        if (SUCCEEDED(hr))
        {
            const D2D1_COLOR_F color = D2D1::ColorF(1.0f, 1.0f, 0);
            hr = pRenderTarget->CreateSolidColorBrush(color, &pBrush);

            if (SUCCEEDED(hr))
            {
                CalculateLayout();
            }
        }
    }
    return hr;
}

若要为窗口创建呈现目标,请在 Direct2D 工厂上调用 ID2D1Factory::CreateHwndRenderTarget 方法。

  • 第一个参数指定任何类型的呈现器目标通用的选项。 在这里,我们通过调用帮助程序函数 D2D1::RenderTargetProperties 传入默认选项。
  • 第二个参数指定窗口的句柄以及呈现器目标的大小(以像素为单位)。
  • 第三个参数接收 ID2D1HwndRenderTarget 指针。

若要创建纯色画笔,请在呈现目标上调用 ID2D1RenderTarget::CreateSolidColorBrush 方法。 颜色以 D2D1_COLOR_F 值提供。 有关 Direct2D 中颜色的详细信息,请参阅 在 Direct2D 中使用颜色

另请注意,如果呈现器目标已存在,该方法 CreateGraphicsResources 将返回 S_OK 而不执行任何操作。 下一主题中将明确此设计的原因。

下一步

用 Direct2D 进行绘制