Bug 1190950: Check mappings and surfaces for UpdateFromSurface more robustly. r=mattwoodrow

This commit is contained in:
Bas Schouten 2015-08-06 02:29:47 +00:00
parent dc8ea3c68f
commit 4704a4b26b
13 changed files with 107 additions and 50 deletions

View File

@ -646,8 +646,7 @@ CairoImage::GetTextureClient(CompositableClient *aClient)
TextureClientAutoUnlock autoUnlock(textureClient);
RefPtr<DataSourceSurface> dataSurf = surface->GetDataSurface();
textureClient->UpdateFromSurface(dataSurf);
textureClient->UpdateFromSurface(surface);
textureClient->SyncWithObject(forwarder->GetSyncObject());

View File

@ -57,22 +57,29 @@ TextureClientDIB::BorrowDrawTarget()
}
void
TextureClientDIB::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
TextureClientDIB::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
MOZ_ASSERT(mIsLocked && IsAllocated());
nsRefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
DataSourceSurface::MappedSurface sourceMap;
aSurface->Map(DataSourceSurface::READ, &sourceMap);
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
for (int y = 0; y < aSurface->GetSize().height; y++) {
memcpy(imgSurf->Data() + imgSurf->Stride() * y,
sourceMap.mData + sourceMap.mStride * y,
aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat()));
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
}
aSurface->Unmap();
DataSourceSurface::MappedSurface sourceMap;
srcSurf->Map(DataSourceSurface::READ, &sourceMap);
for (int y = 0; y < srcSurf->GetSize().height; y++) {
memcpy(imgSurf->Data() + imgSurf->Stride() * y,
sourceMap.mData + sourceMap.mStride * y,
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
}
srcSurf->Unmap();
}
TextureClientMemoryDIB::TextureClientMemoryDIB(ISurfaceAllocator* aAllocator,

View File

@ -34,7 +34,7 @@ public:
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual bool HasInternalBuffer() const override { return true; }

View File

@ -154,7 +154,7 @@ TextureClientX11::BorrowDrawTarget()
}
void
TextureClientX11::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
TextureClientX11::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
MOZ_ASSERT(CanExposeDrawTarget());

View File

@ -43,7 +43,7 @@ class TextureClientX11 : public TextureClient
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }

View File

@ -830,29 +830,50 @@ BufferTextureClient::BorrowDrawTarget()
}
void
BufferTextureClient::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
BufferTextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
RefPtr<DataSourceSurface> surface = serializer.GetAsSurface();
if (surface->GetSize() != aSurface->GetSize() || surface->GetFormat() != aSurface->GetFormat()) {
if (!surface) {
gfxCriticalError() << "Failed to get serializer as surface!";
return;
}
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
}
if (surface->GetSize() != srcSurf->GetSize() || surface->GetFormat() != srcSurf->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << surface->GetSize() << " " << surface->GetFormat() << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat();
return;
}
DataSourceSurface::MappedSurface sourceMap;
DataSourceSurface::MappedSurface destMap;
aSurface->Map(DataSourceSurface::READ, &sourceMap);
surface->Map(DataSourceSurface::WRITE, &destMap);
for (int y = 0; y < aSurface->GetSize().height; y++) {
memcpy(destMap.mData + destMap.mStride * y,
sourceMap.mData + sourceMap.mStride * y,
aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat()));
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return;
}
aSurface->Unmap();
if (!surface->Map(DataSourceSurface::WRITE, &destMap)) {
srcSurf->Unmap();
gfxCriticalError() << "Failed to map destination surface for UpdateFromSurface.";
return;
}
for (int y = 0; y < srcSurf->GetSize().height; y++) {
memcpy(destMap.mData + destMap.mStride * y,
sourceMap.mData + sourceMap.mStride * y,
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
}
srcSurf->Unmap();
surface->Unmap();
}

View File

@ -273,7 +273,7 @@ public:
* This function can be used to update the contents of the TextureClient
* off the main thread.
*/
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) { MOZ_CRASH(); }
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) { MOZ_CRASH(); }
// TextureClients that can expose a DrawTarget should override this method.
virtual gfx::SurfaceFormat GetFormat() const
@ -593,7 +593,7 @@ public:
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;

View File

@ -409,10 +409,14 @@ TextureClientD3D11::BorrowDrawTarget()
}
void
TextureClientD3D11::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
TextureClientD3D11::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
DataSourceSurface::MappedSurface sourceMap;
aSurface->Map(DataSourceSurface::READ, &sourceMap);
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
}
if (mDrawTarget) {
// Ensure unflushed work from our outstanding drawtarget won't override this
@ -420,11 +424,17 @@ TextureClientD3D11::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
mDrawTarget->Flush();
}
if (mSize != aSurface->GetSize() || mFormat != aSurface->GetFormat()) {
if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format!";
return;
}
DataSourceSurface::MappedSurface sourceMap;
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return;
}
if (mTexture) {
RefPtr<ID3D11Device> device;
mTexture->GetDevice(byRef(device));
@ -452,7 +462,7 @@ TextureClientD3D11::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
device->UpdateSubresource(mTexture10, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
}
aSurface->Unmap();
srcSurf->Unmap();
}
static const GUID sD3D11TextureUsage =

View File

@ -64,7 +64,7 @@ public:
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;

View File

@ -585,7 +585,7 @@ TextureClientD3D9::BorrowDrawTarget()
}
void
TextureClientD3D9::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
TextureClientD3D9::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
MOZ_ASSERT(mIsLocked && mD3D9Surface);
@ -599,21 +599,31 @@ TextureClientD3D9::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
return;
}
if (mSize != aSurface->GetSize() || mFormat != aSurface->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << mFormat << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat();
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
}
if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << mFormat << " Other: " << srcSurf->GetSize() << " " << srcSurf->GetFormat();
return;
}
DataSourceSurface::MappedSurface sourceMap;
aSurface->Map(DataSourceSurface::READ, &sourceMap);
for (int y = 0; y < aSurface->GetSize().height; y++) {
memcpy((uint8_t*)rect.pBits + rect.Pitch * y,
sourceMap.mData + sourceMap.mStride * y,
aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat()));
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return;
}
aSurface->Unmap();
for (int y = 0; y < srcSurf->GetSize().height; y++) {
memcpy((uint8_t*)rect.pBits + rect.Pitch * y,
sourceMap.mData + sourceMap.mStride * y,
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
}
srcSurf->Unmap();
mD3D9Surface->UnlockRect();
}

View File

@ -202,7 +202,7 @@ public:
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;

View File

@ -215,7 +215,7 @@ GrallocTextureClientOGL::BorrowDrawTarget()
}
void
GrallocTextureClientOGL::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
GrallocTextureClientOGL::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
@ -224,9 +224,16 @@ GrallocTextureClientOGL::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
return;
}
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
}
gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
if (mSize != aSurface->GetSize() || mFormat != aSurface->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << format << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat();
if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << format << " Other: " << srcSurf->GetSize() << " " << srcSurf->GetFormat();
return;
}
@ -235,17 +242,20 @@ GrallocTextureClientOGL::UpdateFromSurface(gfx::DataSourceSurface* aSurface)
DataSourceSurface::MappedSurface sourceMap;
aSurface->Map(DataSourceSurface::READ, &sourceMap);
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return;
}
uint8_t* buffer = GetBuffer();
for (int y = 0; y < aSurface->GetSize().height; y++) {
for (int y = 0; y < srcSurf->GetSize().height; y++) {
memcpy(buffer + byteStride * y,
sourceMap.mData + sourceMap.mStride * y,
aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat()));
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
}
aSurface->Unmap();
srcSurf->Unmap();
}
bool

View File

@ -82,7 +82,7 @@ public:
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::DataSourceSurface* aSurface) override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;