Bug 961715 - Implement D3D9SurfaceImage::GetAsSourceSurface. r=nical
authorAli Akhtarzada <ali@comoyo.com>
Tue, 28 Jan 2014 09:14:10 -0500
changeset 165615 6589f6ec3b6ead02ee964e69d659d770246c5827
parent 165614 3fcffaa2a46da4e8eb7895738f50cb5346bf1731
child 165616 1a7b4c02f2f839b2a0b48e319979cde0ddc71608
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
bugs961715
milestone29.0a1
Bug 961715 - Implement D3D9SurfaceImage::GetAsSourceSurface. r=nical
gfx/layers/D3D9SurfaceImage.cpp
gfx/layers/D3D9SurfaceImage.h
--- a/gfx/layers/D3D9SurfaceImage.cpp
+++ b/gfx/layers/D3D9SurfaceImage.cpp
@@ -167,10 +167,72 @@ D3D9SurfaceImage::DeprecatedGetAsSurface
            mSize.width * 4);
   }
 
   systemMemorySurface->UnlockRect();
 
   return surface.forget();
 }
 
+TemporaryRef<gfx::SourceSurface>
+D3D9SurfaceImage::GetAsSourceSurface()
+{
+  NS_ENSURE_TRUE(mTexture, nullptr);
+
+  HRESULT hr;
+  RefPtr<gfx::DataSourceSurface> surface = gfx::Factory::CreateDataSourceSurface(mSize, gfx::SurfaceFormat::B8G8R8X8);
+
+  if (!surface) {
+    NS_WARNING("Failed to created SourceSurface for D3D9SurfaceImage.");
+    return nullptr;
+  }
+
+  // Ensure that the texture is ready to be used.
+  EnsureSynchronized();
+
+  // Readback the texture from GPU memory into system memory, so that
+  // we can copy it into the Cairo image. This is expensive.
+  RefPtr<IDirect3DSurface9> textureSurface;
+  hr = mTexture->GetSurfaceLevel(0, byRef(textureSurface));
+  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+
+  RefPtr<IDirect3DDevice9> device;
+  hr = mTexture->GetDevice(byRef(device));
+  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+
+  RefPtr<IDirect3DSurface9> systemMemorySurface;
+  hr = device->CreateOffscreenPlainSurface(mDesc.Width,
+                                           mDesc.Height,
+                                           D3DFMT_X8R8G8B8,
+                                           D3DPOOL_SYSTEMMEM,
+                                           byRef(systemMemorySurface),
+                                           0);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+
+  hr = device->GetRenderTargetData(textureSurface, systemMemorySurface);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+
+  D3DLOCKED_RECT rect;
+  hr = systemMemorySurface->LockRect(&rect, nullptr, 0);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+
+  gfx::DataSourceSurface::MappedSurface mappedSurface;
+  if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
+    systemMemorySurface->UnlockRect();
+    return nullptr;
+  }
+
+  const unsigned char* src = (const unsigned char*)(rect.pBits);
+  const unsigned srcPitch = rect.Pitch;
+  for (int y = 0; y < mSize.height; y++) {
+    memcpy(mappedSurface.mData + mappedSurface.mStride * y,
+           (unsigned char*)(src) + srcPitch * y,
+           mSize.width * 4);
+  }
+
+  systemMemorySurface->UnlockRect();
+  surface->Unmap();
+
+  return surface;
+}
+
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/D3D9SurfaceImage.h
+++ b/gfx/layers/D3D9SurfaceImage.h
@@ -42,16 +42,17 @@ public:
   // If the operation to copy the original resource to the shared resource
   // hasn't finished yet, this function blocks until the synchronization is
   // complete.
   HANDLE GetShareHandle();
 
   gfx::IntSize GetSize() MOZ_OVERRIDE;
 
   already_AddRefed<gfxASurface> DeprecatedGetAsSurface() MOZ_OVERRIDE;
+  virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
 
 private:
 
   // Blocks the calling thread until the copy operation started in SetData()
   // is complete, whereupon the texture is safe to use.
   void EnsureSynchronized();
 
   gfx::IntSize mSize;