Bug 757346; Use A8 textures (DX9). r=roc
authorNicholas Cameron <ncameron@mozilla.com>
Tue, 26 Jun 2012 14:43:31 +1200
changeset 97637 5a327af385df375579deb9533b9be9ab098e0f5b
parent 97636 ec5d136e203d0445d73a2f2e1cf5859f71b69bcf
child 97638 d5a60bfaa968a61c19be72124afda82c23b12b3a
push id22986
push useremorley@mozilla.com
push dateTue, 26 Jun 2012 08:55:07 +0000
treeherdermozilla-central@74e503bfa575 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs757346
milestone16.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 757346; Use A8 textures (DX9). r=roc
gfx/layers/d3d9/ImageLayerD3D9.cpp
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -15,83 +15,93 @@
 #include "yuv_convert.h"
 #include "nsIServiceManager.h" 
 #include "nsIConsoleService.h" 
 #include "Nv3DVUtils.h"
 
 namespace mozilla {
 namespace layers {
 
+static inline _D3DFORMAT
+D3dFormatForGfxFormat(gfxImageFormat aFormat)
+{
+  if (aFormat == gfxASurface::ImageFormatA8) {
+    return D3DFMT_A8;
+  }
+
+  return D3DFMT_A8R8G8B8;
+}
+
 static already_AddRefed<IDirect3DTexture9>
 DataToTexture(IDirect3DDevice9 *aDevice,
               unsigned char *aData,
               int aStride,
-              const gfxIntSize &aSize)
+              const gfxIntSize &aSize,
+              _D3DFORMAT aFormat)
 {
   nsRefPtr<IDirect3DTexture9> texture;
   nsRefPtr<IDirect3DDevice9Ex> deviceEx;
   aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
                           (void**)getter_AddRefs(deviceEx));
 
+  nsRefPtr<IDirect3DSurface9> surface;
+  D3DLOCKED_RECT lockedRect;
   if (deviceEx) {
     // D3D9Ex doesn't support managed textures. We could use dynamic textures
     // here but since Images are immutable that probably isn't such a great
     // idea.
     if (FAILED(aDevice->
                CreateTexture(aSize.width, aSize.height,
-                             1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
+                             1, 0, aFormat, D3DPOOL_DEFAULT,
                              getter_AddRefs(texture), NULL)))
     {
       return NULL;
     }
 
-    nsRefPtr<IDirect3DSurface9> surface;
+    nsRefPtr<IDirect3DTexture9> tmpTexture;
     if (FAILED(aDevice->
-               CreateOffscreenPlainSurface(aSize.width,
-                                           aSize.height,
-                                           D3DFMT_A8R8G8B8,
-                                           D3DPOOL_SYSTEMMEM,
-                                           getter_AddRefs(surface),
-                                           NULL)))
+               CreateTexture(aSize.width, aSize.height,
+                             1, 0, aFormat, D3DPOOL_SYSTEMMEM,
+                             getter_AddRefs(tmpTexture), NULL)))
     {
       return NULL;
     }
 
-    D3DLOCKED_RECT lockedRect;
+    tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surface));
     surface->LockRect(&lockedRect, NULL, 0);
-    for (int y = 0; y < aSize.height; y++) {
-      memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
-             aData + aStride * y,
-             aSize.width * 4);
+    NS_ASSERTION(lockedRect.pBits, "Could not lock surface");
+  } else {
+    if (FAILED(aDevice->
+               CreateTexture(aSize.width, aSize.height,
+                             1, 0, aFormat, D3DPOOL_MANAGED,
+                             getter_AddRefs(texture), NULL)))
+    {
+      return NULL;
     }
+
+    /* lock the entire texture */
+    texture->LockRect(0, &lockedRect, NULL, 0);
+  }
+
+  PRUint32 width = aSize.width;
+  if (aFormat == D3DFMT_A8R8G8B8) {
+    width *= 4;
+  }
+  for (int y = 0; y < aSize.height; y++) {
+    memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
+            aData + aStride * y,
+            width);
+  }
+
+  if (deviceEx) {
     surface->UnlockRect();
     nsRefPtr<IDirect3DSurface9> dstSurface;
     texture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
     aDevice->UpdateSurface(surface, NULL, dstSurface, NULL);
   } else {
-    if (FAILED(aDevice->
-               CreateTexture(aSize.width, aSize.height,
-                             1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
-                             getter_AddRefs(texture), NULL)))
-    {
-      return NULL;
-    }
-
-    D3DLOCKED_RECT lockrect;
-    /* lock the entire texture */
-    texture->LockRect(0, &lockrect, NULL, 0);
-
-    // copy over data. If we don't need to do any swaping we can
-    // use memcpy
-    for (int y = 0; y < aSize.height; y++) {
-      memcpy((char*)lockrect.pBits + lockrect.Pitch * y,
-             aData + aStride * y,
-             aSize.width * 4);
-    }
-
     texture->UnlockRect(0);
   }
 
   return texture.forget();
 }
 
 static already_AddRefed<IDirect3DTexture9>
 SurfaceToTexture(IDirect3DDevice9 *aDevice,
@@ -106,17 +116,18 @@ SurfaceToTexture(IDirect3DDevice9 *aDevi
                                        gfxASurface::ImageFormatARGB32);
     
     nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
     context->SetSource(aSurface);
     context->SetOperator(gfxContext::OPERATOR_SOURCE);
     context->Paint();
   }
 
-  return DataToTexture(aDevice, imageSurface->Data(), imageSurface->Stride(), aSize);
+  return DataToTexture(aDevice, imageSurface->Data(), imageSurface->Stride(),
+                       aSize, D3dFormatForGfxFormat(imageSurface->Format()));
 }
 
 static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage,
                                   IDirect3DDevice9 *aDevice,
                                   LayerManagerD3D9 *aManager)
 {
   nsAutoPtr<PlanarYCbCrD3D9BackendData> backendData(
     new PlanarYCbCrD3D9BackendData);
@@ -289,17 +300,17 @@ ImageLayerD3D9::GetTexture(Image *aImage
   NS_ASSERTION(aImage, "Null image.");
 
   if (aImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
     RemoteBitmapImage *remoteImage =
       static_cast<RemoteBitmapImage*>(aImage);
       
     if (!aImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
       nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData());
-      dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
+      dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize, D3DFMT_A8R8G8B8);
       if (dat->mTexture) {
         aImage->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
       }
     }
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
   } else if (aImage->GetFormat() == Image::CAIRO_SURFACE) {
     CairoImage *cairoImage =