Files
palemoon27/gfx/layers/TextureDIB.cpp
T
roytam1 67e04cfead import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1236750 - Introduce a new unit type CSSTransformedLayerPixel. r=kats (4e9bba3d19)
- Bug 1236750 - Add a ViewAs() overload for casting (with a justification) one typed matrix to another. r=kats (c48e143508)
- Bug 1236750 - Add some specialized typedefs of Matrix4x4 to represent layer transform matrices. r=kats (cc50113c98)
- Bug 1239300 - reject promise with null while creating imagebitmap from empty blob; r=smaug (bff7483bf1)
- Bug 1233056 - Long tapping on a link will select a different link from the page r=tnikkel (3a727b33c1)
- Bug 1245674. Null-check mGlobal before dereferencing it in one more place in Promise code. r=smaug (68cf5312dc)
- Bug 1236750 - Use strongly-typed matrices to represent layer transforms in APZ code. r=kats (63931eb2a1)
- Bug 1236750 - Add typed getters for layer transform matrices. r=kats (baef978fe1)
- Bug 1147673 - Relax the ancestor transform assertion a little. r=kats (ec9ce47ba4)
- Bug 1154161 Initialize WidgetQueryContentEvent::mReply r=smaug (6086291313)
- Bug 1240921 - Use nsAutoTArray in nsStyleSet::RuleNodeWithReplacement. r=bz. (66f6823b46)
- Bug 1229437 part 1 - Add a helper function to get the float containing block of a given frame. r=dbaron (72de452e5d)
- Bug 1229437 part 2 - Reparent floats inside pulled ruby segment. r=dbaron (82cc44632d)
- Bug 1229437 part 3 - Support iterating frames of RubyColumn. r=dholbert (5d43e7f6ff)
- Bug 1229437 part 4 - Reparent floats inside pulled ruby column. r=dbaron (4c1a7ff20b)
- Bug 1229437 part 5 - Add crashtests for this bug. r=dbaron (6afabe1604)
- Bug 1229437 followup - Fix sign-compare error in RubyColumn::Iterator on CLOSED TREE. (e93453d00a)
- Bug 1229437 followup 2 - Fix another sign-compare error in RubyColumn::Iterator on CLOSED TREE. (c0bf6a2a7b)
- Bug 1229437 followup 3 - Fix a mistake in RubyColumn::Iterator::SkipUntilExistingFrame(). a=me (1ce408e194)
- bits of Bug 1072150 - Use the opt-out for various sloppy consumers (29d97c59ca)
- Make test_bug946632 compatible with asynchronous scrolling. (bug 1140293, r=mstange) (e975a8350c)
- fix misspatch of 1072150 (a3e580fa4b)
- Bug 686281 - Implement nsStyleImageLayers; r=dbaron (85bb33c8e6)
- Bug 686281 - Rename *background* to *imagelayer*; r=dbaron. (36d90f112d)
- Bug 1230034 part 4 - Make FramePropertyDescriptor to be a template. r=froydnj,dbaron (271cd19b6e)
- Bug 1230034 part 5 - Convert all frame properties which use DeleteValue and ReleaseValue as destructor to be typesafe. r=dbaron (efc8d63c9d)
- Bug 1230034 part 6 - Convert all frame properties which do not hold pointer to be typed. r=dbaron (b5541775f7)
- Bug 1230034 part 7 - Convert nsIFrame::GenConProperty to be typed. r=dbaron (2b71527b2c)
- Bug 1230034 part 8 - Convert frame properties which assert on destructor to be typed. r=dbaron (0f125a3414)
- Bug 1230034 part 9 - Convert FrameLayerBuilder::LayerManagerDataProperty to be typed. r=dbaron (1147498c2f)
- Bug 1230034 part 10 - Convert remaining frame properties to by typed and remove the unsafe declaring macro. r=dbaron (d59d94eac4)
- Bug 1072501: Unmap file mapping on source surface destruction. r=jrmuizel (19fd63890a)
- Bug 1235613 - Make gfxCriticalError/Note strings in gfx/ unique. r=jrmuizel (780c6ff862)
- Bug 1247535 - Fix -Wunreachable-code warning in mfbt/Poison.cpp. r=froydnj (0e7cf60b6d)
- Bug 1239479: Add comments to mfbt/XorShift128PlusRNG.h from the RNG's designer. DONTBUILD r=Waldo (bb674b07ce)
- Add an assertion message to the assert-is-empty in LinkedList::~LinkedList, to indicate to users who hit it that it's the fault of the caller, not the fault of MFBT code. No bug, rs=froydnj (4cad80874c)
- Bug 1221103 - Add a comment to nsIChannel::securityInfo noting that this info may appear on non-nsHttpChannels and how that may happen. r=bz IGNORE IDL (cd9cebc3f2)
- Bug 1001765 - Make login credentials in Saved Passwords manager editable. r=MattN (09eec4f6f8)
- Bug 1188478 - Add an Import button to the password manager to open the browser migrator. r=dolske (d1126a89fc)
- Bug 1199382 - Rename some strings from "password" to "login" in preferences and the manager. r=markh (60638f5e2a)
- Bug 1207733 - Update @disabled on the Remove Password button when selection changes. r=MattN (64ac9f22f6)
- bits of 1124472 and 1166840 (26e2681183)
- Bug 1219707 - fix argument passing to migration.js, r=jaws (55d332f5c6)
- bug 1215657 - make AccessibleWrap::get_accSelection work with proxies=davidb (4e72111032)
- fix missing telemetry entry (4fcfabb3e6)
and follow-up API changes of TFF#493.
2023-11-09 16:35:18 +08:00

480 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TextureDIB.h"
#include "gfx2DGlue.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/ipc/ProtocolUtils.h"
namespace mozilla {
using namespace gfx;
namespace layers {
/**
* Can only be drawn into through Cairo.
* The coresponding TextureHost depends on the compositor
*/
class MemoryDIBTextureData : public DIBTextureData
{
public:
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
virtual TextureData*
CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) 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
{
public:
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
virtual TextureData*
CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) 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;
}
}
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);
// The host side has its own references and handles to this data, we can
// safely clear ours.
DeallocateData();
}
HANDLE mFileMapping;
HANDLE mHostHandle;
HDC mDC;
HBITMAP mBitmap;
};
already_AddRefed<gfx::DrawTarget>
DIBTextureData::BorrowDrawTarget()
{
return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
}
DIBTextureData*
DIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ISurfaceAllocator* aAllocator)
{
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);
}
}
TextureData*
MemoryDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
if (!aAllocator) {
return nullptr;
}
return MemoryDIBTextureData::Create(mSize, mFormat);
}
bool
MemoryDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
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.
aOutDescriptor = SurfaceDescriptorDIB(reinterpret_cast<uintptr_t>(mSurface.get()));
mSurface->AddRef();
return true;
}
DIBTextureData*
MemoryDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat)
{
RefPtr<gfxWindowsSurface> surface
= new gfxWindowsSurface(aSize, SurfaceFormatToImageFormat(aFormat));
if (!surface || surface->CairoStatus()) {
NS_WARNING("Could not create DIB surface");
return nullptr;
}
return new MemoryDIBTextureData(aSize, aFormat, surface);
}
bool
MemoryDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
RefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (DIB).";
return false;
}
DataSourceSurface::MappedSurface sourceMap;
if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return false;
}
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();
return true;
}
TextureData*
ShmemDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
if (!aAllocator) {
return nullptr;
}
return ShmemDIBTextureData::Create(mSize, mFormat, aAllocator);
}
bool
ShmemDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (DTD).";
return false;
}
DataSourceSurface::MappedSurface sourceMap;
if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return false;
}
GdiFlush();
uint32_t stride = mSize.width * BytesPerPixel(mFormat);
uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_WRITE, 0, 0, stride * mSize.height);
if (!data) {
gfxCriticalError() << "Failed to map view of file for UpdateFromSurface.";
srcSurf->Unmap();
return false;
}
for (int y = 0; y < srcSurf->GetSize().height; y++) {
memcpy(data + stride * y,
sourceMap.mData + sourceMap.mStride * y,
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
}
::UnmapViewOfFile(data);
srcSurf->Unmap();
return true;
}
bool
ShmemDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
return false;
}
::GdiFlush();
aOutDescriptor = SurfaceDescriptorFileMapping((WindowsHandle)mHostHandle, mFormat, mSize);
return true;
}
DIBTextureData*
ShmemDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ISurfaceAllocator* aAllocator)
{
MOZ_ASSERT(aAllocator->ParentPid() != base::ProcessId());
DWORD mapSize = aSize.width * aSize.height * BytesPerPixel(aFormat);
HANDLE fileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL);
if (!fileMapping) {
gfxCriticalError() << "Failed to create memory file mapping for " << mapSize << " bytes.";
return nullptr;
}
BITMAPV4HEADER header;
memset(&header, 0, sizeof(BITMAPV4HEADER));
header.bV4Size = sizeof(BITMAPV4HEADER);
header.bV4Width = aSize.width;
header.bV4Height = -LONG(aSize.height); // top-to-buttom DIB
header.bV4Planes = 1;
header.bV4BitCount = 32;
header.bV4V4Compression = BI_BITFIELDS;
header.bV4RedMask = 0x00FF0000;
header.bV4GreenMask = 0x0000FF00;
header.bV4BlueMask = 0x000000FF;
HDC nulldc = ::GetDC(NULL);
HDC dc = ::CreateCompatibleDC(nulldc);
::ReleaseDC(nullptr, nulldc);
if (!dc) {
::CloseHandle(fileMapping);
gfxCriticalError() << "Failed to create DC for bitmap.";
return nullptr;
}
void* bits;
HBITMAP bitmap = ::CreateDIBSection(dc, (BITMAPINFO*)&header,
DIB_RGB_COLORS, &bits,
fileMapping, 0);
if (!bitmap) {
gfxCriticalError() << "Failed to create DIB section for a bitmap of size "
<< aSize << " and mapSize " << mapSize;
::CloseHandle(fileMapping);
::DeleteDC(dc);
return nullptr;
}
::SelectObject(dc, bitmap);
RefPtr<gfxWindowsSurface> surface = new gfxWindowsSurface(dc, 0);
if (surface->CairoStatus())
{
::DeleteObject(bitmap);
::DeleteDC(dc);
::CloseHandle(fileMapping);
gfxCriticalError() << "Could not create surface, status: "
<< surface->CairoStatus();
return nullptr;
}
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(bitmap);
::DeleteDC(dc);
::CloseHandle(fileMapping);
return nullptr;
}
return new ShmemDIBTextureData(aSize, aFormat, surface,
fileMapping, hostHandle,
dc, bitmap);
}
bool
TextureHostDirectUpload::Lock()
{
MOZ_ASSERT(!mIsLocked);
mIsLocked = true;
return true;
}
void
TextureHostDirectUpload::Unlock()
{
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
}
void
TextureHostDirectUpload::SetCompositor(Compositor* aCompositor)
{
mCompositor = aCompositor;
}
void
TextureHostDirectUpload::DeallocateDeviceData()
{
if (mTextureSource) {
mTextureSource->DeallocateDeviceData();
}
}
bool
TextureHostDirectUpload::BindTextureSource(CompositableTextureSourceRef& aTexture)
{
if (!mTextureSource) {
Updated();
}
aTexture = mTextureSource;
return !!aTexture;
}
DIBTextureHost::DIBTextureHost(TextureFlags aFlags,
const SurfaceDescriptorDIB& aDescriptor)
: TextureHostDirectUpload(aFlags, SurfaceFormat::B8G8R8X8, IntSize())
{
// We added an extra ref for transport, so we shouldn't AddRef now.
mSurface =
dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aDescriptor.surface()));
MOZ_ASSERT(mSurface);
mSize = mSurface->GetSize();
mFormat = mSurface->GetSurfaceFormat();
}
void
DIBTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
{
if (!mCompositor) {
// This can happen if we send textures to a compositable that isn't yet
// attached to a layer.
return;
}
if (!mTextureSource) {
mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
}
if (mSurface->CairoStatus()) {
gfxWarning() << "Bad Cairo surface internal update " << mSurface->CairoStatus();
mTextureSource = nullptr;
return;
}
RefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
RefPtr<DataSourceSurface> surf = Factory::CreateWrappingDataSourceSurface(imgSurf->Data(), imgSurf->Stride(), mSize, mFormat);
if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
mTextureSource = nullptr;
}
}
TextureHostFileMapping::TextureHostFileMapping(TextureFlags aFlags,
const SurfaceDescriptorFileMapping& aDescriptor)
: TextureHostDirectUpload(aFlags, aDescriptor.format(), aDescriptor.size())
, mFileMapping((HANDLE)aDescriptor.handle())
{
}
TextureHostFileMapping::~TextureHostFileMapping()
{
::CloseHandle(mFileMapping);
}
UserDataKey kFileMappingKey;
static void UnmapFileData(void* aData)
{
MOZ_ASSERT(aData);
::UnmapViewOfFile(aData);
}
void
TextureHostFileMapping::UpdatedInternal(const nsIntRegion* aRegion)
{
if (!mCompositor) {
// This can happen if we send textures to a compositable that isn't yet
// attached to a layer.
return;
}
if (!mTextureSource) {
mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
}
uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_READ, 0, 0, mSize.width * mSize.height * BytesPerPixel(mFormat));
if (data) {
RefPtr<DataSourceSurface> surf = Factory::CreateWrappingDataSourceSurface(data, mSize.width * BytesPerPixel(mFormat), mSize, mFormat);
surf->AddUserData(&kFileMappingKey, data, UnmapFileData);
if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
mTextureSource = nullptr;
}
} else {
mTextureSource = nullptr;
}
}
}
}