Bug 961714 - Implement RemoteDXGITextureImage::GetAsSourceSurface. r=nical
authorAli Akhtarzada <ali@comoyo.com>
Tue, 28 Jan 2014 09:00:10 -0500
changeset 181618 de0e3bff81d55833e83d841a7f9125e67d999cd5
parent 181617 9f2bf80444ebe28a3482470b3dac6fb22d03b67d
child 181619 2d1fd4b1fdaa6c77df8c7509f36409cc791a7bdd
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs961714
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;