Example #1
0
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);
}
Example #2
0
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;
}