Bug 1239152 Memset RGBX surfaces to opaque white. r=nical
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -904,23 +904,45 @@ DrawTargetSkia::InitWithGrContext(GrCont
mCanvas = gpuSurface->getCanvas();
return true;
}
#endif
+#ifdef DEBUG
+bool
+VerifyRGBXFormat(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat)
+{
+ // We should've initialized the data to be opaque already
+ // On debug builds, verify that this is actually true.
+ int height = aSize.height;
+ int width = aSize.width;
+
+ for (int row = 0; row < height; ++row) {
+ for (int column = 0; column < width; column += 4) {
+#ifdef IS_BIG_ENDIAN
+ MOZ_ASSERT(aData[column] == 0xFF);
+#else
+ MOZ_ASSERT(aData[column + 3] == 0xFF);
+#endif
+ }
+ aData += aStride;
+ }
+
+ return true;
+}
+#endif
+
void
DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
{
- if (aFormat == SurfaceFormat::B8G8R8X8) {
- // We have to manually set the A channel to be 255 as Skia doesn't understand BGRX
- ConvertBGRXToBGRA(aData, aSize, aStride);
- }
+ MOZ_ASSERT((aFormat != SurfaceFormat::B8G8R8X8) ||
+ 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/layers/BufferTexture.cpp
+++ b/gfx/layers/BufferTexture.cpp
@@ -364,19 +364,21 @@ MemoryTextureData::Serialize(SurfaceDesc
static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAllocFlags)
{
if (!buf) {
gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes";
return false;
}
- if (aAllocFlags & ALLOC_CLEAR_BUFFER) {
+ if ((aAllocFlags & ALLOC_CLEAR_BUFFER) ||
+ (aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK)) {
memset(buf, 0, bufSize);
}
+
if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) {
memset(buf, 0xFF, bufSize);
}
return true;
}
MemoryTextureData*
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -285,20 +285,25 @@ ContentClientRemoteBuffer::BuildTextureC
CreateBackBuffer(mBufferRect);
}
void
ContentClientRemoteBuffer::CreateBackBuffer(const IntRect& aBufferRect)
{
// gfx::BackendType::NONE means fallback to the content backend
+ TextureAllocationFlags textureAllocFlags
+ = (mTextureFlags & TextureFlags::COMPONENT_ALPHA) ?
+ TextureAllocationFlags::ALLOC_CLEAR_BUFFER_BLACK :
+ TextureAllocationFlags::ALLOC_CLEAR_BUFFER;
+
mTextureClient = CreateTextureClientForDrawing(
mSurfaceFormat, mSize, BackendSelector::Content,
mTextureFlags | ExtraTextureFlags(),
- TextureAllocationFlags::ALLOC_CLEAR_BUFFER
+ textureAllocFlags
);
if (!mTextureClient || !AddTextureClient(mTextureClient)) {
AbortTextureClientCreation();
return;
}
if (mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
mTextureClientOnWhite = mTextureClient->CreateSimilar(
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -828,16 +828,23 @@ 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);
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -64,25 +64,26 @@ class TextureClientPool;
class KeepAlive;
/**
* TextureClient is the abstraction that allows us to share data between the
* content and the compositor side.
*/
enum TextureAllocationFlags {
- ALLOC_DEFAULT = 0x0,
- ALLOC_CLEAR_BUFFER = 0x1,
- ALLOC_CLEAR_BUFFER_WHITE = 0x2,
- ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 0x4,
+ ALLOC_DEFAULT = 0,
+ ALLOC_CLEAR_BUFFER = 1 << 1, // Clear the buffer to whatever is best for the draw target
+ ALLOC_CLEAR_BUFFER_WHITE = 1 << 2, // explicit all white
+ ALLOC_CLEAR_BUFFER_BLACK = 1 << 3, // explicit all black
+ ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 1 << 4,
// Allocate the texture for out-of-band content updates. This is mostly for
// TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex
// surfaces when used on the main thread.
- ALLOC_FOR_OUT_OF_BAND_CONTENT = 0x8
+ ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5,
};
#ifdef XP_WIN
typedef void* SyncHandle;
#else
typedef uintptr_t SyncHandle;
#endif // XP_WIN
--- a/widget/nsShmImage.cpp
+++ b/widget/nsShmImage.cpp
@@ -94,30 +94,33 @@ nsShmImage::Create(const LayoutDeviceInt
shm->mXAttached = true;
shm->mSize = aSize;
switch (shm->mImage->depth) {
case 32:
if ((shm->mImage->red_mask == 0xff0000) &&
(shm->mImage->green_mask == 0xff00) &&
(shm->mImage->blue_mask == 0xff)) {
shm->mFormat = SurfaceFormat::B8G8R8A8;
+ memset(shm->mSegment->memory(), 0, size);
break;
}
goto unsupported;
case 24:
// Only xRGB is supported.
if ((shm->mImage->red_mask == 0xff0000) &&
(shm->mImage->green_mask == 0xff00) &&
(shm->mImage->blue_mask == 0xff)) {
shm->mFormat = SurfaceFormat::B8G8R8X8;
+ memset(shm->mSegment->memory(), 0xFF, size);
break;
}
goto unsupported;
case 16:
shm->mFormat = SurfaceFormat::R5G6B5_UINT16;
+ memset(shm->mSegment->memory(), 0, size);
break;
unsupported:
default:
NS_WARNING("Unsupported XShm Image format!");
gShmAvailable = false;
return nullptr;
}
return shm.forget();