HRESULT d2d_wic_render_target_init(struct d2d_wic_render_target *render_target, ID2D1Factory1 *factory, ID3D10Device1 *d3d_device, IWICBitmap *bitmap, const D2D1_RENDER_TARGET_PROPERTIES *desc) { D3D10_TEXTURE2D_DESC texture_desc; ID3D10Texture2D *texture; IDXGIDevice *dxgi_device; ID2D1Device *device; HRESULT hr; render_target->IUnknown_iface.lpVtbl = &d2d_wic_render_target_vtbl; if (FAILED(hr = IWICBitmap_GetSize(bitmap, &render_target->width, &render_target->height))) { WARN("Failed to get bitmap dimensions, hr %#x.\n", hr); return hr; } texture_desc.Width = render_target->width; texture_desc.Height = render_target->height; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = desc->pixelFormat.format; if (texture_desc.Format == DXGI_FORMAT_UNKNOWN) { WICPixelFormatGUID bitmap_format; if (FAILED(hr = IWICBitmap_GetPixelFormat(bitmap, &bitmap_format))) { WARN("Failed to get bitmap format, hr %#x.\n", hr); return hr; } if (IsEqualGUID(&bitmap_format, &GUID_WICPixelFormat32bppPBGRA) || IsEqualGUID(&bitmap_format, &GUID_WICPixelFormat32bppBGR)) { texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; } else { WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&bitmap_format)); return D2DERR_UNSUPPORTED_PIXEL_FORMAT; } } switch (texture_desc.Format) { case DXGI_FORMAT_B8G8R8A8_UNORM: render_target->bpp = 4; break; default: FIXME("Unhandled format %#x.\n", texture_desc.Format); return D2DERR_UNSUPPORTED_PIXEL_FORMAT; } texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D10_USAGE_DEFAULT; texture_desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = desc->usage & D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE ? D3D10_RESOURCE_MISC_GDI_COMPATIBLE : 0; if (FAILED(hr = ID3D10Device1_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture))) { WARN("Failed to create texture, hr %#x.\n", hr); return hr; } hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&render_target->dxgi_surface); ID3D10Texture2D_Release(texture); if (FAILED(hr)) { WARN("Failed to get DXGI surface interface, hr %#x.\n", hr); return hr; } texture_desc.Usage = D3D10_USAGE_STAGING; texture_desc.BindFlags = 0; texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; texture_desc.MiscFlags = 0; if (FAILED(hr = ID3D10Device1_CreateTexture2D(d3d_device, &texture_desc, NULL, &render_target->readback_texture))) { WARN("Failed to create readback texture, hr %#x.\n", hr); IDXGISurface_Release(render_target->dxgi_surface); return hr; } if (FAILED(hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device))) { WARN("Failed to get DXGI device, hr %#x.\n", hr); IDXGISurface_Release(render_target->dxgi_surface); return hr; } hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device); IDXGIDevice_Release(dxgi_device); if (FAILED(hr)) { WARN("Failed to create D2D device, hr %#x.\n", hr); IDXGISurface_Release(render_target->dxgi_surface); return hr; } hr = d2d_d3d_create_render_target(device, render_target->dxgi_surface, &render_target->IUnknown_iface, &d2d_wic_render_target_ops, desc, (void **)&render_target->dxgi_inner); ID2D1Device_Release(device); if (FAILED(hr)) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); ID3D10Texture2D_Release(render_target->readback_texture); IDXGISurface_Release(render_target->dxgi_surface); return hr; } if (FAILED(hr = IUnknown_QueryInterface(render_target->dxgi_inner, &IID_ID2D1RenderTarget, (void **)&render_target->dxgi_target))) { WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); IUnknown_Release(render_target->dxgi_inner); ID3D10Texture2D_Release(render_target->readback_texture); IDXGISurface_Release(render_target->dxgi_surface); return hr; } render_target->bitmap = bitmap; IWICBitmap_AddRef(bitmap); return S_OK; }
HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID2D1Factory1 *factory, ID3D10Device1 *d3d_device, const D2D1_RENDER_TARGET_PROPERTIES *desc) { IDXGIDevice *dxgi_device; ID2D1Device *device; HRESULT hr; render_target->ID2D1DCRenderTarget_iface.lpVtbl = &d2d_dc_render_target_vtbl; /* Set with BindDC(). */ SetRectEmpty(&render_target->dst_rect); render_target->hdc = NULL; render_target->pixel_format = desc->pixelFormat; switch (desc->pixelFormat.format) { case DXGI_FORMAT_B8G8R8A8_UNORM: if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED || desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE) break; default: FIXME("Unhandled format %#x, alpha mode %u.\n", desc->pixelFormat.format, desc->pixelFormat.alphaMode); return D2DERR_UNSUPPORTED_PIXEL_FORMAT; } if (FAILED(hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device))) { WARN("Failed to get DXGI device interface, hr %#x.\n", hr); return hr; } hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device); IDXGIDevice_Release(dxgi_device); if (FAILED(hr)) { WARN("Failed to create D2D device, hr %#x.\n", hr); return hr; } hr = d2d_d3d_create_render_target(device, NULL, (IUnknown *)&render_target->ID2D1DCRenderTarget_iface, &d2d_dc_render_target_ops, desc, (void **)&render_target->dxgi_inner); ID2D1Device_Release(device); if (FAILED(hr)) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); return hr; } if (FAILED(hr = IUnknown_QueryInterface(render_target->dxgi_inner, &IID_ID2D1RenderTarget, (void **)&render_target->dxgi_target))) { WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); IUnknown_Release(render_target->dxgi_inner); return hr; } render_target->d3d_device = d3d_device; ID3D10Device1_AddRef(render_target->d3d_device); return S_OK; }