From be9ee98a4ce58531771c189c291d6959a77acda7 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 20 Nov 2015 14:24:58 +0100 Subject: [PATCH] Bug 1200595 - DIB TextureData implementation. r=Bas --- gfx/layers/TextureDIB.cpp | 348 +++++++++++++++------------- gfx/layers/TextureDIB.h | 95 ++------ gfx/layers/client/TextureClient.cpp | 7 +- 3 files changed, 209 insertions(+), 241 deletions(-) diff --git a/gfx/layers/TextureDIB.cpp b/gfx/layers/TextureDIB.cpp index fc0610d92612..7dcaf3c21439 100644 --- a/gfx/layers/TextureDIB.cpp +++ b/gfx/layers/TextureDIB.cpp @@ -14,64 +14,117 @@ using namespace gfx; namespace layers { -bool -TextureClientDIB::Lock(OpenMode) +/** + * Can only be drawn into through Cairo. + * The coresponding TextureHost depends on the compositor + */ +class MemoryDIBTextureData : public DIBTextureData { - MOZ_ASSERT(!mIsLocked); - if (!IsValid()) { - return false; - } - mIsLocked = true; - return true; -} +public: + virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; -void -TextureClientDIB::Unlock() + virtual TextureData* + CreateSimilar(ISurfaceAllocator* aAllocator, + TextureFlags aFlags = TextureFlags::DEFAULT, + TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; + + static + DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat); + + virtual void Deallocate(ISurfaceAllocator* aAllocator) override + { + mSurface = nullptr; + } + + MemoryDIBTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + gfxWindowsSurface* aSurface) + : DIBTextureData(aSize, aFormat, aSurface) + { + MOZ_COUNT_CTOR(MemoryDIBTextureData); + } + + virtual ~MemoryDIBTextureData() + { + MOZ_COUNT_DTOR(MemoryDIBTextureData); + } +}; + +/** + * Can only be drawn into through Cairo. + * The coresponding TextureHost depends on the compositor + */ +class ShmemDIBTextureData : public DIBTextureData { - MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!"); - if (mDrawTarget) { - if (mReadbackSink) { - RefPtr snapshot = mDrawTarget->Snapshot(); - RefPtr dataSurf = snapshot->GetDataSurface(); - mReadbackSink->ProcessReadback(dataSurf); +public: + virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; + + virtual TextureData* + CreateSimilar(ISurfaceAllocator* aAllocator, + TextureFlags aFlags = TextureFlags::DEFAULT, + TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; + + static + DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + ISurfaceAllocator* aAllocator); + + void DeallocateData() + { + if (mSurface) { + ::DeleteObject(mBitmap); + ::DeleteDC(mDC); + ::CloseHandle(mFileMapping); + mBitmap = NULL; + mDC = NULL; + mFileMapping = NULL; + mSurface = nullptr; } - - mDrawTarget->Flush(); - mDrawTarget = nullptr; } - mIsLocked = false; + virtual void Deallocate(ISurfaceAllocator* aAllocator) override + { + DeallocateData(); + } + + ShmemDIBTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + gfxWindowsSurface* aSurface, + HANDLE aFileMapping, HANDLE aHostHandle, + HDC aDC, HBITMAP aBitmap) + : DIBTextureData(aSize, aFormat, aSurface) + , mFileMapping(aFileMapping) + , mHostHandle(aHostHandle) + , mDC(aDC) + , mBitmap(aBitmap) + { + MOZ_COUNT_CTOR(ShmemDIBTextureData); + } + + virtual ~ShmemDIBTextureData() + { + MOZ_COUNT_DTOR(ShmemDIBTextureData); + } + + HANDLE mFileMapping; + HANDLE mHostHandle; + HDC mDC; + HBITMAP mBitmap; +}; + +already_AddRefed +DIBTextureData::BorrowDrawTarget() +{ + return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize); } -gfx::DrawTarget* -TextureClientDIB::BorrowDrawTarget() +bool +DIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) { - MOZ_ASSERT(mIsLocked && IsAllocated()); - - if (!mDrawTarget) { - mDrawTarget = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize); - } - - if (!mDrawTarget) { - gfxCriticalNote << "DIB failed draw target surface " << mSize << ", " << (int)mIsLocked << ", " << IsAllocated(); - } - - return mDrawTarget; -} - -void -TextureClientDIB::UpdateFromSurface(gfx::SourceSurface* aSurface) -{ - MOZ_ASSERT(mIsLocked && IsAllocated()); - RefPtr imgSurf = mSurface->GetAsImageSurface(); RefPtr srcSurf = aSurface->GetDataSurface(); if (!srcSurf) { gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface."; - return; + return false; } DataSourceSurface::MappedSurface sourceMap; @@ -84,43 +137,40 @@ TextureClientDIB::UpdateFromSurface(gfx::SourceSurface* aSurface) } srcSurf->Unmap(); + return true; } -TextureClientMemoryDIB::TextureClientMemoryDIB(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - TextureFlags aFlags) - : TextureClientDIB(aAllocator, aFormat, aFlags) +DIBTextureData* +DIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + ISurfaceAllocator* aAllocator) { - MOZ_COUNT_CTOR(TextureClientMemoryDIB); -} - -TextureClientMemoryDIB::~TextureClientMemoryDIB() -{ - MOZ_COUNT_DTOR(TextureClientMemoryDIB); -} - -already_AddRefed -TextureClientMemoryDIB::CreateSimilar(TextureFlags aFlags, - TextureAllocationFlags aAllocFlags) const -{ - RefPtr tex = new TextureClientMemoryDIB(mAllocator, mFormat, - mFlags | aFlags); - - if (!tex->AllocateForSurface(mSize, aAllocFlags)) { + if (!aAllocator) { return nullptr; } + if (aFormat == gfx::SurfaceFormat::UNKNOWN) { + return nullptr; + } + if (aAllocator->IsSameProcess()) { + return MemoryDIBTextureData::Create(aSize, aFormat); + } else { + return ShmemDIBTextureData::Create(aSize, aFormat, aAllocator); + } +} - return tex.forget(); +TextureData* +MemoryDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, + TextureFlags aFlags, + TextureAllocationFlags aAllocFlags) const +{ + if (!aAllocator) { + return nullptr; + } + return MemoryDIBTextureData::Create(mSize, mFormat); } bool -TextureClientMemoryDIB::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) +MemoryDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) { - MOZ_ASSERT(IsValid()); - if (!IsAllocated()) { - return false; - } - MOZ_ASSERT(mSurface); // The host will release this ref when it receives the surface descriptor. // We AddRef in case we die before the host receives the pointer. @@ -129,64 +179,34 @@ TextureClientMemoryDIB::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) return true; } -bool -TextureClientMemoryDIB::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) +DIBTextureData* +MemoryDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat) { - MOZ_ASSERT(!IsAllocated()); - mSize = aSize; - - mSurface = new gfxWindowsSurface(aSize, SurfaceFormatToImageFormat(mFormat)); - if (!mSurface || mSurface->CairoStatus()) - { - NS_WARNING("Could not create surface"); - mSurface = nullptr; - return false; - } - - return true; -} - -TextureClientShmemDIB::TextureClientShmemDIB(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - TextureFlags aFlags) - : TextureClientDIB(aAllocator, aFormat, aFlags) - , mFileMapping(NULL) - , mHostHandle(NULL) - , mDC(NULL) - , mBitmap(NULL) -{ - MOZ_COUNT_CTOR(TextureClientShmemDIB); -} - -TextureClientShmemDIB::~TextureClientShmemDIB() -{ - MOZ_COUNT_DTOR(TextureClientShmemDIB); - - ::DeleteObject(mBitmap); - ::DeleteDC(mDC); - ::CloseHandle(mFileMapping); -} - -already_AddRefed -TextureClientShmemDIB::CreateSimilar(TextureFlags aFlags, - TextureAllocationFlags aAllocFlags) const -{ - RefPtr tex = new TextureClientShmemDIB(mAllocator, mFormat, - mFlags | aFlags); - - if (!tex->AllocateForSurface(mSize, aAllocFlags)) { + RefPtr surface + = new gfxWindowsSurface(aSize, SurfaceFormatToImageFormat(aFormat)); + if (!surface || surface->CairoStatus()) { + NS_WARNING("Could not create DIB surface"); return nullptr; } - return tex.forget(); + return new MemoryDIBTextureData(aSize, aFormat, surface); +} + +TextureData* +ShmemDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, + TextureFlags aFlags, + TextureAllocationFlags aAllocFlags) const +{ + if (!aAllocator) { + return nullptr; + } + return ShmemDIBTextureData::Create(mSize, mFormat, aAllocator); } bool -TextureClientShmemDIB::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) +ShmemDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) { - MOZ_ASSERT(IsValid()); - MOZ_ASSERT(mAllocator->ParentPid() != base::ProcessId()); - if (!IsAllocated() || GetFormat() == gfx::SurfaceFormat::UNKNOWN) { + if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) { return false; } @@ -195,33 +215,33 @@ TextureClientShmemDIB::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) return true; } -bool -TextureClientShmemDIB::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) +DIBTextureData* +ShmemDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + ISurfaceAllocator* aAllocator) { - MOZ_ASSERT(!IsAllocated()); - MOZ_ASSERT(mAllocator->ParentPid() != base::ProcessId()); + MOZ_ASSERT(aAllocator->ParentPid() != base::ProcessId()); - mSize = aSize; + DWORD mapSize = aSize.width * aSize.height * BytesPerPixel(aFormat); + HANDLE fileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL); - DWORD mapSize = mSize.width * mSize.height * BytesPerPixel(mFormat); - mFileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL); - - if (!mFileMapping) { + if (!fileMapping) { gfxCriticalError() << "Failed to create memory file mapping for " << mapSize << " bytes."; - return false; + return nullptr; } - uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, mSize.width * mSize.height * BytesPerPixel(mFormat)); + uint8_t* data = (uint8_t*)::MapViewOfFile(fileMapping, FILE_MAP_WRITE | FILE_MAP_READ, + 0, 0, aSize.width * aSize.height + * BytesPerPixel(aFormat)); - memset(data, 0x80, mSize.width * mSize.height * BytesPerPixel(mFormat)); + memset(data, 0x80, aSize.width * aSize.height * BytesPerPixel(aFormat)); - ::UnmapViewOfFile(mFileMapping); + ::UnmapViewOfFile(fileMapping); BITMAPV4HEADER header; memset(&header, 0, sizeof(BITMAPV4HEADER)); header.bV4Size = sizeof(BITMAPV4HEADER); - header.bV4Width = mSize.width; - header.bV4Height = -LONG(mSize.height); // top-to-buttom DIB + header.bV4Width = aSize.width; + header.bV4Height = -LONG(aSize.height); // top-to-buttom DIB header.bV4Planes = 1; header.bV4BitCount = 32; header.bV4V4Compression = BI_BITFIELDS; @@ -229,46 +249,54 @@ TextureClientShmemDIB::AllocateForSurface(gfx::IntSize aSize, TextureAllocationF header.bV4GreenMask = 0x0000FF00; header.bV4BlueMask = 0x000000FF; - mDC = ::CreateCompatibleDC(::GetDC(NULL)); + HDC dc = ::CreateCompatibleDC(::GetDC(NULL)); - if (!mDC) { - ::CloseHandle(mFileMapping); + if (!dc) { + ::CloseHandle(fileMapping); gfxCriticalError() << "Failed to create DC for bitmap."; - return false; + return nullptr; } void* bits; - mBitmap = ::CreateDIBSection(mDC, (BITMAPINFO*)&header, DIB_RGB_COLORS, &bits, mFileMapping, 0); + HBITMAP bitmap = ::CreateDIBSection(dc, (BITMAPINFO*)&header, + DIB_RGB_COLORS, &bits, + fileMapping, 0); - if (!mBitmap) { - gfxCriticalError() << "Failed to create DIB section for a bitmap of size " << mSize; - ::CloseHandle(mFileMapping); - ::DeleteDC(mDC); - return false; + if (!bitmap) { + gfxCriticalError() << "Failed to create DIB section for a bitmap of size " + << aSize; + ::CloseHandle(fileMapping); + ::DeleteDC(dc); + return nullptr; } - ::SelectObject(mDC, mBitmap); + ::SelectObject(dc, bitmap); - mSurface = new gfxWindowsSurface(mDC, 0); - if (mSurface->CairoStatus()) + RefPtr surface = new gfxWindowsSurface(dc, 0); + if (surface->CairoStatus()) { - ::DeleteObject(mBitmap); - ::DeleteDC(mDC); - ::CloseHandle(mFileMapping); - gfxCriticalError() << "Could not create surface, status: " << mSurface->CairoStatus(); - mSurface = nullptr; - return false; + ::DeleteObject(bitmap); + ::DeleteDC(dc); + ::CloseHandle(fileMapping); + gfxCriticalError() << "Could not create surface, status: " + << surface->CairoStatus(); + return nullptr; } - if (!ipc::DuplicateHandle(mFileMapping, mAllocator->ParentPid(), &mHostHandle, 0, DUPLICATE_SAME_ACCESS)) { + HANDLE hostHandle = NULL; + + if (!ipc::DuplicateHandle(fileMapping, aAllocator->ParentPid(), + &hostHandle, 0, DUPLICATE_SAME_ACCESS)) { gfxCriticalError() << "Failed to duplicate handle to parent process for surface."; - ::DeleteObject(mBitmap); - ::DeleteDC(mDC); - ::CloseHandle(mFileMapping); - return false; + ::DeleteObject(bitmap); + ::DeleteDC(dc); + ::CloseHandle(fileMapping); + return nullptr; } - return true; + return new ShmemDIBTextureData(aSize, aFormat, surface, + fileMapping, hostHandle, + dc, bitmap); } diff --git a/gfx/layers/TextureDIB.h b/gfx/layers/TextureDIB.h index 9c2eaba588c3..9f42f900d55b 100644 --- a/gfx/layers/TextureDIB.h +++ b/gfx/layers/TextureDIB.h @@ -15,101 +15,42 @@ namespace mozilla { namespace layers { -class TextureClientDIB : public TextureClient +class DIBTextureData : public TextureData { public: - virtual bool IsAllocated() const override { return !!mSurface; } + virtual bool Lock(OpenMode, FenceHandle*) override { return true; } - virtual bool Lock(OpenMode aOpenMode) override; - - virtual void Unlock() override; - - virtual bool IsLocked() const override{ return mIsLocked; } + virtual void Unlock() override {} virtual gfx::IntSize GetSize() const override { return mSize; } virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; } - virtual bool CanExposeDrawTarget() const override { return true; } + virtual bool SupportsMoz2D() const override { return true; } - virtual gfx::DrawTarget* BorrowDrawTarget() override; + virtual already_AddRefed BorrowDrawTarget() override; - virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override; + virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override; virtual bool HasInternalBuffer() const override { return true; } + static + DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + ISurfaceAllocator* aAllocator); + protected: - TextureClientDIB(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, TextureFlags aFlags) - : TextureClient(aAllocator, aFlags) - , mFormat(aFormat) - , mIsLocked(false) - { } + DIBTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + gfxWindowsSurface* aSurface) + : mSurface(aSurface) + , mSize(aSize) + , mFormat(aFormat) + { + MOZ_ASSERT(aSurface); + } RefPtr mSurface; - RefPtr mDrawTarget; gfx::IntSize mSize; gfx::SurfaceFormat mFormat; - bool mIsLocked; -}; - -/** - * Can only be drawn into through Cairo. - * Prefer CairoTextureClient when possible. - * The coresponding TextureHost depends on the compositor - */ -class TextureClientMemoryDIB : public TextureClientDIB -{ -public: - TextureClientMemoryDIB(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - TextureFlags aFlags); - - virtual ~TextureClientMemoryDIB(); - - // TextureClient - - virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override; - - virtual bool AllocateForSurface(gfx::IntSize aSize, - TextureAllocationFlags aFlags = ALLOC_DEFAULT) override; - - virtual already_AddRefed - CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, - TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; - - -}; - -/** - * Can only be drawn into through Cairo. - * Prefer CairoTextureClient when possible. - * The coresponding TextureHost depends on the compositor - */ -class TextureClientShmemDIB : public TextureClientDIB -{ -public: - TextureClientShmemDIB(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - TextureFlags aFlags); - - virtual ~TextureClientShmemDIB(); - - // TextureClient - - virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override; - - virtual bool AllocateForSurface(gfx::IntSize aSize, - TextureAllocationFlags aFlags = ALLOC_DEFAULT) override; - - virtual already_AddRefed - CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, - TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; - -protected: - HANDLE mFileMapping; - HANDLE mHostHandle; - HDC mDC; - HBITMAP mBitmap; }; /** diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 0e30283bfcf3..22386137d528 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -593,10 +593,9 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator, aAllocator->IsSameProcess() && moz2DBackend == gfx::BackendType::CAIRO && NS_IsMainThread()) { - if (aAllocator->IsSameProcess()) { - texture = new TextureClientMemoryDIB(aAllocator, aFormat, aTextureFlags); - } else { - texture = new TextureClientShmemDIB(aAllocator, aFormat, aTextureFlags); + TextureData* data = DIBTextureData::Create(aSize, aFormat, aAllocator); + if (data) { + return MakeAndAddRef(data, aTextureFlags, aAllocator); } } #endif