Bug 961714 - Implement RemoteDXGITextureImage::GetAsSourceSurface. r=nical
authorAli Akhtarzada <ali@comoyo.com>
Tue, 28 Jan 2014 09:00:10 -0500
changeset 165608 de0e3bff81d55833e83d841a7f9125e67d999cd5
parent 165607 9f2bf80444ebe28a3482470b3dac6fb22d03b67d
child 165609 2d1fd4b1fdaa6c77df8c7509f36409cc791a7bdd
push id4623
push userryanvm@gmail.com
push dateTue, 28 Jan 2014 21:48:39 +0000
treeherderfx-team@7e79536aca0a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs961714
milestone29.0a1
Bug 961714 - Implement RemoteDXGITextureImage::GetAsSourceSurface. r=nical
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d10/ImageLayerD3D10.h
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -489,16 +489,96 @@ RemoteDXGITextureImage::DeprecatedGetAsS
            mSize.width * 4);
   }
 
   softTexture->Unmap(0);
 
   return surface.forget();
 }
 
+TemporaryRef<gfx::SourceSurface>
+RemoteDXGITextureImage::GetAsSourceSurface()
+{
+  nsRefPtr<ID3D10Device1> device =
+    gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
+  if (!device) {
+    NS_WARNING("Cannot readback from shared texture because no D3D10 device is available.");
+    return nullptr;
+  }
+
+  TextureD3D10BackendData* data = GetD3D10TextureBackendData(device);
+
+  if (!data) {
+    return nullptr;
+  }
+
+  nsRefPtr<IDXGIKeyedMutex> keyedMutex;
+
+  if (FAILED(data->mTexture->QueryInterface(IID_IDXGIKeyedMutex, getter_AddRefs(keyedMutex)))) {
+    NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange.");
+    return nullptr;
+  }
+
+  if (FAILED(keyedMutex->AcquireSync(0, 0))) {
+    NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?");
+    return nullptr;
+  }
+
+  D3D10_TEXTURE2D_DESC desc;
+
+  data->mTexture->GetDesc(&desc);
+
+  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
+  desc.BindFlags = 0;
+  desc.MiscFlags = 0;
+  desc.Usage = D3D10_USAGE_STAGING;
+
+  nsRefPtr<ID3D10Texture2D> softTexture;
+  HRESULT hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexture));
+
+  if (FAILED(hr)) {
+    NS_WARNING("Failed to create 2D staging texture.");
+    return nullptr;
+  }
+
+  device->CopyResource(softTexture, data->mTexture);
+  keyedMutex->ReleaseSync(0);
+
+  RefPtr<gfx::DataSourceSurface> surface
+    = gfx::Factory::CreateDataSourceSurface(mSize,
+                                            mFormat == RemoteImageData::BGRX32
+                                              ? gfx::SurfaceFormat::B8G8R8X8
+                                              : gfx::SurfaceFormat::B8G8R8A8);
+
+  if (!surface) {
+    NS_WARNING("Failed to create SourceSurface for DXGI texture.");
+    return nullptr;
+  }
+
+  gfx::DataSourceSurface::MappedSurface mappedSurface;
+  if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
+    NS_WARNING("Failed to map source surface");
+    return nullptr;
+  }
+
+  D3D10_MAPPED_TEXTURE2D mapped;
+  softTexture->Map(0, D3D10_MAP_READ, 0, &mapped);
+
+  for (int y = 0; y < mSize.height; y++) {
+    memcpy(mappedSurface.mData + mappedSurface.mStride * y,
+           (unsigned char*)(mapped.pData) + mapped.RowPitch * y,
+           mSize.width * 4);
+  }
+
+  softTexture->Unmap(0);
+  surface->Unmap();
+
+  return surface;
+}
+
 TextureD3D10BackendData*
 RemoteDXGITextureImage::GetD3D10TextureBackendData(ID3D10Device *aDevice)
 {
   if (GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) {
     TextureD3D10BackendData *data =
       static_cast<TextureD3D10BackendData*>(GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10));
 
     nsRefPtr<ID3D10Device> device;
--- a/gfx/layers/d3d10/ImageLayerD3D10.h
+++ b/gfx/layers/d3d10/ImageLayerD3D10.h
@@ -56,16 +56,17 @@ struct TextureD3D10BackendData : public 
   nsRefPtr<ID3D10ShaderResourceView> mSRView;
 };
 
 class RemoteDXGITextureImage : public Image {
 public:
   RemoteDXGITextureImage() : Image(nullptr, REMOTE_IMAGE_DXGI_TEXTURE) {}
 
   already_AddRefed<gfxASurface> DeprecatedGetAsSurface();
+  virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
 
   IntSize GetSize() { return mSize; }
 
   TextureD3D10BackendData *GetD3D10TextureBackendData(ID3D10Device *aDevice);
 
   IntSize mSize;
   RemoteImageData::Format mFormat;
   HANDLE mHandle;