DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface) : mTexture(nullptr) , mFormat(aSourceSurface->mFormat) , mSize(aSourceSurface->mSize) , mMapped(false) { // We allocate ourselves a regular D3D surface (sourceTexture) and paint the // D2D bitmap into it via a DXGI render target. Then we need to copy // sourceTexture into a staging texture (mTexture), which we will lazily map // to get the data. CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height); desc.MipLevels = 1; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; RefPtr<ID3D10Texture2D> sourceTexture; HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(sourceTexture)); if (FAILED(hr)) { gfxWarning() << "Failed to create texture. Code: " << hr; return; } RefPtr<IDXGISurface> dxgiSurface; hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface)); if (FAILED(hr)) { gfxWarning() << "Failed to create DXGI surface. Code: " << hr; return; } D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)); RefPtr<ID2D1RenderTarget> renderTarget; hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface, &rtProps, byRef(renderTarget)); if (FAILED(hr)) { gfxWarning() << "Failed to create render target. Code: " << hr; return; } renderTarget->BeginDraw(); renderTarget->DrawBitmap(aSourceSurface->mBitmap, D2D1::RectF(0, 0, Float(mSize.width), Float(mSize.height))); renderTarget->EndDraw(); desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; desc.Usage = D3D10_USAGE_STAGING; desc.BindFlags = 0; hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture)); if (FAILED(hr)) { gfxWarning() << "Failed to create staging texture. Code: " << hr; mTexture = nullptr; return; } aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture); }
DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface) : mTexture(nullptr) , mFormat(aSourceSurface->mFormat) , mSize(aSourceSurface->mSize) , mMapped(false) { // We allocate ourselves a regular D3D surface (sourceTexture) and paint the // D2D bitmap into it via a DXGI render target. Then we need to copy // sourceTexture into a staging texture (mTexture), which we will lazily map // to get the data. CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height); desc.MipLevels = 1; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; RefPtr<ID3D10Texture2D> sourceTexture; HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(sourceTexture)); if (FAILED(hr)) { gfxWarning() << "Failed to create texture. Code: " << hexa(hr); return; } RefPtr<IDXGISurface> dxgiSurface; hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface)); if (FAILED(hr)) { gfxWarning() << "Failed to create DXGI surface. Code: " << hexa(hr); return; } D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)); RefPtr<ID2D1RenderTarget> renderTarget; hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface, &rtProps, byRef(renderTarget)); if (FAILED(hr)) { gfxWarning() << "Failed to create render target. Code: " << hexa(hr); return; } renderTarget->BeginDraw(); renderTarget->Clear(D2D1::ColorF(0, 0.0f)); if (aSourceSurface->GetFormat() != SurfaceFormat::A8) { renderTarget->DrawBitmap(aSourceSurface->mBitmap, D2D1::RectF(0, 0, Float(mSize.width), Float(mSize.height))); } else { RefPtr<ID2D1SolidColorBrush> brush; renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), byRef(brush)); renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); renderTarget->FillOpacityMask(aSourceSurface->mBitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS); } hr = renderTarget->EndDraw(); if (FAILED(hr)) { gfxWarning() << "Failed to draw bitmap. Code: " << hexa(hr); return; } desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; desc.Usage = D3D10_USAGE_STAGING; desc.BindFlags = 0; hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture)); if (FAILED(hr)) { gfxWarning() << "Failed to create staging texture. Code: " << hexa(hr); mTexture = nullptr; return; } aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture); }
ID2D1Bitmap* SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT) { if (mBitmap) { return mBitmap; } HRESULT hr; D3D10_TEXTURE2D_DESC desc; mTexture->GetDesc(&desc); IntSize size(desc.Width, desc.Height); RefPtr<IDXGISurface> surf; hr = mTexture->QueryInterface((IDXGISurface**)byRef(surf)); if (FAILED(hr)) { gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hr; return NULL; } D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(mFormat), AlphaMode(mFormat))); hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap)); if (FAILED(hr)) { // This seems to happen for FORMAT_A8 sometimes... aRT->CreateBitmap(D2D1::SizeU(desc.Width, desc.Height), D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(mFormat), AlphaMode(mFormat))), byRef(mBitmap)); RefPtr<ID2D1RenderTarget> rt; if (mDrawTarget) { rt = mDrawTarget->mRT; } if (!rt) { // Okay, we already separated from our drawtarget. And we're an A8 // surface the only way we can get to a bitmap is by creating a // a rendertarget and from there copying to a bitmap! Terrible! RefPtr<IDXGISurface> surface; hr = mTexture->QueryInterface((IDXGISurface**)byRef(surface)); if (FAILED(hr)) { gfxWarning() << "Failed to QI texture to surface."; return NULL; } D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGIFormat(mFormat), AlphaMode(mFormat))); hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt)); if (FAILED(hr)) { gfxWarning() << "Failed to create D2D render target for texture."; return NULL; } } mBitmap->CopyFromRenderTarget(NULL, rt, NULL); return mBitmap; } return mBitmap; }