static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock, DWORD flags, IWICBitmapLock **ppILock) { BitmapImpl *This = impl_from_IWICBitmap(iface); BitmapLockImpl *result; WICRect rc; TRACE("(%p,%p,%x,%p)\n", iface, prcLock, flags, ppILock); if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock) return E_INVALIDARG; if (!prcLock) { rc.X = rc.Y = 0; rc.Width = This->width; rc.Height = This->height; prcLock = &rc; } else if (prcLock->X >= This->width || prcLock->Y >= This->height || prcLock->X + prcLock->Width > This->width || prcLock->Y + prcLock->Height > This->height || prcLock->Width <= 0 || prcLock->Height <= 0) return E_INVALIDARG; else if (((prcLock->X * This->bpp) % 8) != 0) { FIXME("Cannot lock at an X coordinate not at a full byte\n"); return E_FAIL; } result = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl)); if (!result) return E_OUTOFMEMORY; if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite)) { HeapFree(GetProcessHeap(), 0, result); return WINCODEC_ERR_ALREADYLOCKED; } result->IWICBitmapLock_iface.lpVtbl = &BitmapLockImpl_Vtbl; result->ref = 1; result->parent = This; result->width = prcLock->Width; result->height = prcLock->Height; result->data = This->data + This->stride * prcLock->Y + (This->bpp * prcLock->X)/8; IWICBitmap_AddRef(&This->IWICBitmap_iface); *ppILock = &result->IWICBitmapLock_iface; return S_OK; }
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; }
static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface) { BitmapImpl *This = impl_from_IMILUnknown2(iface); return IWICBitmap_AddRef(&This->IWICBitmap_iface); }
static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmapSource *iface) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); return IWICBitmap_AddRef(&This->IWICBitmap_iface); }