Bug 1257939 - initialize BGRX alpha channel to opaque when clearing and ignore uninitialized alpha in texture clients. r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Fri, 18 Mar 2016 16:58:55 -0400
changeset 289412 2da6cf4f1870ed7b69896ba8373c97559f2dad2c
parent 289411 1982db677df6bbcd00dd4bd06ce906050f2576c6
child 289413 3bfa5a8fd0157c3109e39c0c49045aca9fac9d30
push id30102
push userryanvm@gmail.com
push dateSat, 19 Mar 2016 15:23:17 +0000
treeherdermozilla-central@720fb3d55e28 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1257939
milestone48.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 1257939 - initialize BGRX alpha channel to opaque when clearing and ignore uninitialized alpha in texture clients. r=mchang
gfx/2d/2D.h
gfx/2d/DrawTargetSkia.cpp
gfx/2d/DrawTargetSkia.h
gfx/2d/Factory.cpp
gfx/layers/BufferTexture.cpp
gfx/layers/client/TextureClient.cpp
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1250,17 +1250,17 @@ public:
 
   static already_AddRefed<DrawTarget>
     CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
 
   static already_AddRefed<DrawTarget>
     CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT);
 
   static already_AddRefed<DrawTarget>
-    CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
+    CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false);
 
   static already_AddRefed<ScaledFont>
     CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize);
 
   /**
    * This creates a NativeFontResource from TrueType data.
    *
    * @param aData Pointer to the data
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -935,20 +935,20 @@ VerifyRGBXFormat(uint8_t* aData, const I
     aData += aStride;
   }
 
   return true;
 }
 #endif
 
 void
-DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
+DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized)
 {
   MOZ_ASSERT((aFormat != SurfaceFormat::B8G8R8X8) ||
-              VerifyRGBXFormat(aData, aSize, aStride, aFormat));
+              aUninitialized || VerifyRGBXFormat(aData, aSize, aStride, aFormat));
 
   SkBitmap bitmap;
   bitmap.setInfo(MakeSkiaImageInfo(aSize, aFormat), aStride);
   bitmap.setPixels(aData);
 
   mCanvas.adopt(new SkCanvas(bitmap));
 
   mSize = aSize;
--- a/gfx/2d/DrawTargetSkia.h
+++ b/gfx/2d/DrawTargetSkia.h
@@ -106,17 +106,17 @@ public:
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override;
   virtual already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override;
   virtual already_AddRefed<GradientStops> CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
   virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
   virtual void SetTransform(const Matrix &aTransform) override;
   virtual void *GetNativeSurface(NativeSurfaceType aType) override;
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
-  void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
+  void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false);
 
 #ifdef USE_SKIA_GPU
   bool InitWithGrContext(GrContext* aGrContext,
                          const IntSize &aSize,
                          SurfaceFormat aFormat,
                          bool aCached);
   virtual bool
     InitWithGrContext(GrContext* aGrContext,
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -379,33 +379,34 @@ Factory::CreateRecordingDrawTarget(DrawE
   return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT);
 }
 
 already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetForData(BackendType aBackend,
                                  unsigned char *aData,
                                  const IntSize &aSize,
                                  int32_t aStride,
-                                 SurfaceFormat aFormat)
+                                 SurfaceFormat aFormat,
+                                 bool aUninitialized)
 {
   MOZ_ASSERT(aData);
   if (!AllowedSurfaceSize(aSize)) {
     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DTD) " << aSize;
     return nullptr;
   }
 
   RefPtr<DrawTarget> retVal;
 
   switch (aBackend) {
 #ifdef USE_SKIA
   case BackendType::SKIA:
     {
       RefPtr<DrawTargetSkia> newTarget;
       newTarget = new DrawTargetSkia();
-      newTarget->Init(aData, aSize, aStride, aFormat);
+      newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized);
       retVal = newTarget;
       break;
     }
 #endif
 #ifdef XP_DARWIN
   case BackendType::COREGRAPHICS:
     {
       RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
--- a/gfx/layers/BufferTexture.cpp
+++ b/gfx/layers/BufferTexture.cpp
@@ -5,16 +5,17 @@
 
 #include "BufferTexture.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/fallible.h"
+#include <algorithm>
 
 #ifdef MOZ_WIDGET_GTK
 #include "gfxPlatformGtk.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
@@ -240,29 +241,29 @@ BufferTextureData::BorrowDrawTarget()
     return nullptr;
   }
 
   const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
 
   uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
   mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend,
                                                       GetBuffer(), rgb.size(),
-                                                      stride, rgb.format());
+                                                      stride, rgb.format(), true);
 
   if (mDrawTarget) {
     RefPtr<gfx::DrawTarget> dt = mDrawTarget;
     return dt.forget();
   }
 
   // TODO - should we warn? should we really fallback to cairo? perhaps
   // at least update mMoz2DBackend...
   if (mMoz2DBackend != gfx::BackendType::CAIRO) {
     mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
                                                         GetBuffer(), rgb.size(),
-                                                        stride, rgb.format());
+                                                        stride, rgb.format(), true);
   }
 
   if (!mDrawTarget) {
     gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend;
   }
 
   RefPtr<gfx::DrawTarget> dt = mDrawTarget;
   return dt.forget();
@@ -392,26 +393,32 @@ MemoryTextureData::Serialize(SurfaceDesc
   }
 
   uintptr_t ptr = reinterpret_cast<uintptr_t>(mBuffer);
   aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr));
 
   return true;
 }
 
-static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAllocFlags)
+static bool InitBuffer(uint8_t* buf, size_t bufSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aAllocFlags)
 {
   if (!buf) {
     gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes";
     return false;
   }
 
   if ((aAllocFlags & ALLOC_CLEAR_BUFFER) ||
       (aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK)) {
-    memset(buf, 0, bufSize);
+    if (aFormat == gfx::SurfaceFormat::B8G8R8X8) {
+      // Even though BGRX was requested, XRGB_UINT32 is what is meant,
+      // so use 0xFF000000 to put alpha in the right place.
+      std::fill_n(reinterpret_cast<uint32_t*>(buf), bufSize / sizeof(uint32_t), 0xFF000000);
+    } else {
+      memset(buf, 0, bufSize);
+    }
   }
 
   if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) {
     memset(buf, 0xFF, bufSize);
   }
 
   return true;
 }
@@ -431,17 +438,17 @@ MemoryTextureData::Create(gfx::IntSize a
   }
 
   uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
   if (!bufSize) {
     return nullptr;
   }
 
   uint8_t* buf = new (fallible) uint8_t[bufSize];
-  if (!InitBuffer(buf, bufSize, aAllocFlags)) {
+  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags)) {
     return nullptr;
   }
 
   auto fwd = aAllocator ? aAllocator->AsCompositableForwarder() : nullptr;
   bool hasIntermediateBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat,
                                               fwd->GetCompositorBackendType())
                                    : true;
 
@@ -508,17 +515,17 @@ ShmemTextureData::Create(gfx::IntSize aS
   }
 
   mozilla::ipc::Shmem shm;
   if (!aAllocator->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) {
     return nullptr;
   }
 
   uint8_t* buf = shm.get<uint8_t>();
-  if (!InitBuffer(buf, bufSize, aAllocFlags)) {
+  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags)) {
     return nullptr;
   }
 
   auto fwd = aAllocator->AsCompositableForwarder();
   bool hasIntermediateBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat,
                                               fwd->GetCompositorBackendType())
                                    : true;
 
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -847,23 +847,16 @@ TextureClient::CreateForRawBufferAccess(
   if (aAllocFlags & ALLOC_DISALLOW_BUFFERTEXTURECLIENT) {
     return nullptr;
   }
 
   if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
     return nullptr;
   }
 
-  if (aFormat == SurfaceFormat::B8G8R8X8 &&
-      (aAllocFlags != TextureAllocationFlags::ALLOC_CLEAR_BUFFER_BLACK) &&
-      aMoz2DBackend == gfx::BackendType::SKIA) {
-    // skia requires alpha component of RGBX textures to be 255.
-    aAllocFlags = TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE;
-  }
-
   TextureData* texData = BufferTextureData::Create(aSize, aFormat, aMoz2DBackend,
                                                    aTextureFlags, aAllocFlags,
                                                    aAllocator);
   if (!texData) {
     return nullptr;
   }
 
   return MakeAndAddRef<TextureClient>(texData, aTextureFlags, aAllocator);