Files
palemoon27/gfx/layers/TextureDIB.cpp
T
roytam1 e8f234939e import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 967494 - "Preference Composition/Spelling/Language is ignored, and changing spellcheck language in one composition window affects all open and new compositions" [r=ehsan] Bug 1157421 - Fix typo "suggesteed". r=ehsan (d48b61df9)
- namespaces (c9e3edbf1)
- Bug 1167409 - 3/4 - Change ScriptLoadRequeest::mLoading to mProgress. r=jandem (34377ba15)
- Bug 1104732 - having deferred scripts shouldn't cause async scripts to delay domcontentloaded, r?smaug (f6b3a5ad9)
- Bug 1138395 - Optimize nsDocument::mExpandoAndGeneration.expando out from the cc graphs when possible, r=mccr8 (d944130ab)
- Bug 874838 - Make CreateElem return Element. r=khuey (ac65a35cf)
- Bug 1194619 - fix comment r=dholbert (017a488a2)
- Bug 1137494 - Change the type given to type validation check. r=jgilbert (05885cc7c)
- Bug 1106138 - Remove the early unpremultiply in WebGLContext::SurfaceFromElementResultToImageSurface, and let the texel conversion code handle it instead. r=jgilbert (b8010b16b)
- Bug 1185815 - Hoist generation increment. r=jgilbert (f6a276b5e)
- Bug 1175931 - TexImageFromVideoElement uses GL_HALF_FLOAT if it does not support GL_HALF_FLOAT_OES which would be the case on non-ANGLE systems. Using GL_HALF_FLOAT_OES on a non OES system would result in an error when using TexImage2D. r=jgilbert (d692281f1)
- Bug 1184534 - Add support for target size retrieval to GLX backend. r=jgilbert (0e5ba1f8e)
- bug 1174705 - add GLContext::GetDefaultFramebuffer. r=jgilbert (99c0e70aa)
- Bug 1179935, introduce complex viewport projections to Compositor, remove PrepareViewport; r=mstange (1753d65d3)
- Bug 1184534 - Fetch viewport size from context in CompositorOGL, discard if changed during composition. r=nical (4f57bc4ed)
- Bug 1187440 - Implement GLX shared surfaces on the OpenGL compositor. r=jgilbert,nical (4844e96ce)
- Bug 1033375 - Nudge simple linear gradients with hard stops to half-pixel gradient. r=nical (331ddd4fa)
- Bug 1185636 - Remove hard stop workaround for Cairo due to regressions. r=jrmuizel (ccefe7abc)
- Bug 1177807 - Mark cairo surface dirty in ReleaseBits. r=jrmuizel (ae9d508b9)
- Bug 1170390 - Detect 16bpp cairo xlib surface format. r=jrmuizel (25857ae30)
- Bug 1019063 - Check for ::CreateDCW failing when printing. r=dvander (7f54ba8d2)
- Bug 1170390 - Add gfxASurface::GetSurfaceFormat for retrieving precise surface format where necessary. r=jrmuizel (f70d11b29)
- Bug 1155626 - Don't assume that Factory::GetD2D1Device returns a non-null device and add some gfxCriticalLog. r=Bas (0c896a368)
- Bug 1182209 - Additional info with some critical errors. r=mchang CLOSED TREE (f4841baec)
2021-12-28 09:45:42 +08:00

388 lines
10 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 {
bool
TextureClientDIB::Lock(OpenMode)
{
MOZ_ASSERT(!mIsLocked);
if (!IsValid()) {
return false;
}
mIsLocked = true;
return true;
}
void
TextureClientDIB::Unlock()
{
MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
if (mDrawTarget) {
if (mReadbackSink) {
RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
RefPtr<DataSourceSurface> dataSurf = snapshot->GetDataSurface();
mReadbackSink->ProcessReadback(dataSurf);
}
mDrawTarget->Flush();
mDrawTarget = nullptr;
}
mIsLocked = false;
}
gfx::DrawTarget*
TextureClientDIB::BorrowDrawTarget()
{
MOZ_ASSERT(mIsLocked && IsAllocated());
if (!mDrawTarget) {
mDrawTarget =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
}
return mDrawTarget;
}
void
TextureClientDIB::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
MOZ_ASSERT(mIsLocked && IsAllocated());
nsRefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
}
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,
gfx::SurfaceFormat aFormat,
TextureFlags aFlags)
: TextureClientDIB(aAllocator, aFormat, aFlags)
{
MOZ_COUNT_CTOR(TextureClientMemoryDIB);
}
TextureClientMemoryDIB::~TextureClientMemoryDIB()
{
MOZ_COUNT_DTOR(TextureClientMemoryDIB);
}
already_AddRefed<TextureClient>
TextureClientMemoryDIB::CreateSimilar(TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
RefPtr<TextureClient> tex = new TextureClientMemoryDIB(mAllocator, mFormat,
mFlags | aFlags);
if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
return nullptr;
}
return tex.forget();
}
bool
TextureClientMemoryDIB::ToSurfaceDescriptor(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.
aOutDescriptor = SurfaceDescriptorDIB(reinterpret_cast<uintptr_t>(mSurface.get()));
mSurface->AddRef();
return true;
}
bool
TextureClientMemoryDIB::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
{
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<TextureClient>
TextureClientShmemDIB::CreateSimilar(TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
RefPtr<TextureClient> tex = new TextureClientShmemDIB(mAllocator, mFormat,
mFlags | aFlags);
if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
return nullptr;
}
return tex.forget();
}
bool
TextureClientShmemDIB::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mAllocator->ParentPid() != base::ProcessId());
if (!IsAllocated() || GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
return false;
}
::GdiFlush();
aOutDescriptor = SurfaceDescriptorFileMapping((WindowsHandle)mHostHandle, mFormat, mSize);
return true;
}
bool
TextureClientShmemDIB::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
{
MOZ_ASSERT(!IsAllocated());
MOZ_ASSERT(mAllocator->ParentPid() != base::ProcessId());
mSize = aSize;
DWORD mapSize = mSize.width * mSize.height * BytesPerPixel(mFormat);
mFileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL);
if (!mFileMapping) {
gfxCriticalError() << "Failed to create memory file mapping for " << mapSize << " bytes.";
return false;
}
uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, mSize.width * mSize.height * BytesPerPixel(mFormat));
memset(data, 0x80, mSize.width * mSize.height * BytesPerPixel(mFormat));
::UnmapViewOfFile(mFileMapping);
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.bV4Planes = 1;
header.bV4BitCount = 32;
header.bV4V4Compression = BI_BITFIELDS;
header.bV4RedMask = 0x00FF0000;
header.bV4GreenMask = 0x0000FF00;
header.bV4BlueMask = 0x000000FF;
mDC = ::CreateCompatibleDC(::GetDC(NULL));
if (!mDC) {
::CloseHandle(mFileMapping);
gfxCriticalError() << "Failed to create DC for bitmap.";
return false;
}
void* bits;
mBitmap = ::CreateDIBSection(mDC, (BITMAPINFO*)&header, DIB_RGB_COLORS, &bits, mFileMapping, 0);
if (!mBitmap) {
gfxCriticalError() << "Failed to create DIB section for a bitmap of size " << mSize;
::CloseHandle(mFileMapping);
::DeleteDC(mDC);
return false;
}
::SelectObject(mDC, mBitmap);
mSurface = new gfxWindowsSurface(mDC, 0);
if (mSurface->CairoStatus())
{
::DeleteObject(mBitmap);
::DeleteDC(mDC);
::CloseHandle(mFileMapping);
gfxCriticalError() << "Could not create surface, status: " << mSurface->CairoStatus();
mSurface = nullptr;
return false;
}
if (!ipc::DuplicateHandle(mFileMapping, mAllocator->ParentPid(), &mHostHandle, 0, DUPLICATE_SAME_ACCESS)) {
gfxCriticalError() << "Failed to duplicate handle to parent process for surface.";
::DeleteObject(mBitmap);
::DeleteDC(mDC);
::CloseHandle(mFileMapping);
return false;
}
return true;
}
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);
}
nsRefPtr<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);
}
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);
if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
mTextureSource = nullptr;
}
} else {
mTextureSource = nullptr;
}
::UnmapViewOfFile(data);
}
}
}