mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
e8f234939e
- 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)
388 lines
10 KiB
C++
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);
|
|
}
|
|
|
|
}
|
|
}
|