Files
palemoon27/gfx/layers/CopyableCanvasLayer.cpp
T
roytam1 3b276a5398 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1077651 Measure frame uniformity by synthesizing native events. r=kats,mrbkap (95a796145)
- Bug 1154231 - Part 2. Reclaim cached resources when memory-pressure occurs. r=mattwoodrow (cff6ac1f9)
- fix build (15112d396)
- Bug 1155649 - XFlush at the end of frames when OMTC is enabled on Linux. r=jrmuizel (8bc22dd42)
- Bug 1158120 - Edit include and comments that contained gfxIntSize and nsIntSize. r=nical (fc25c0c96)
- Bug 1167235 - Part 1: Add code exposing a PersistentBufferProvider. r=nical (8340f8ede)
- Bug 1134251 - Disable broken B2G Desktop tests on Mulet. r=jmaher, r=jgilbert (db4d4253c)
- Bug 1134271 - Skip conformance/canvas/buffer-offscreen-test.html on Android; r=jgilbert (2fe8d8623)
- Bug 1124996 - Remove expected fail on OSX 10.10. r=jgilbert (388438a7e)
- Bug 1145492 - Update FramebufferTexture2D to allow binding mipmaps. r=jgilbert (5e4c6bf95)
- Bug 1158089 - Remove LAYERS_D3D10 enum value since it's unused. r=Bas (720d3b3b4)
- Bug 1156058 - Null pointer check. r=jgilbert (f9b9c6ca6)
- Bug 1131463 - Report AtomicRefCounterWithFinalize doing the wrong thing with AddRef and Release in release build as well. r=sotaro (7c009766e)
- Bug 1142071 - Re-add WaitForBufferOwnership() r=jgilbert (0753bcd25)
- partial revert of patch not found... (4ed1e76f1)
- Bug 1143979 - Use RAII local instead of useless temporary. - r=kamidphish (d8a50143f)
- Bug 1017865 - Refactor attach/detach for FB attachments. - r=kamidphish (9c7e41065)
- Bug 1144906 - Add accel E10S backend for WebGL compositing. - r=jrmuizel,mattwoodrow,nical,sotaro (559ab767f)
- Bug 1167235 - Part 2: Add support for the basic buffer provider to CanvasLayer. r=nical (4ac399c16)
- Bug 1155252 - Add a pref to control the maximum canvas 2d size and set it to 0x7ff. r=jrmuizel (7ae6cde3f)
- Bug 1167235 - Part 3: Switch CanvasRenderingContext2D to use the new BufferProvider API. r=nical (f678c14ab)
- Bug 1192159: Do not forget about the transform when not using an active target. r=jrmuizel (a4bd28a75)
- Bug 1167235 - Part 4: Remove DrawTarget as a possible means of initializing Canvas layers. r=nical (dbd153cfb)
- Bug 1167235 - Part 5: Make CanvasLayerComposite ImageHost type agnostic. r=nical (df15bd85d)
- Bug 1167235 - Part 6: Fix up HasInternalBuffer return value on TextureHostDirectUpload. r=nical (437cd1680)
- Bug 1091851 - Fix a race condition in Sqlite.jsm shutdown. r=mak (8b6ac8848)
2020-12-09 23:03:57 +08:00

196 lines
6.2 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "CopyableCanvasLayer.h"
#include "BasicLayersImpl.h" // for FillWithMask, etc
#include "GLContext.h" // for GLContext
#include "GLScreenBuffer.h" // for GLScreenBuffer
#include "SharedSurface.h" // for SharedSurface
#include "SharedSurfaceGL.h" // for SharedSurface
#include "gfxPattern.h" // for gfxPattern, etc
#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
#include "gfxRect.h" // for gfxRect
#include "gfxUtils.h" // for gfxUtils
#include "gfx2DGlue.h" // for thebes --> moz2d transition
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/PersistentBufferProvider.h"
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "gfxUtils.h"
#include "client/TextureClientSharedSurface.h"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
using namespace mozilla::gl;
CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
CanvasLayer(aLayerManager, aImplData)
, mGLFrontbuffer(nullptr)
, mIsAlphaPremultiplied(true)
, mOriginPos(gl::OriginPos::TopLeft)
{
MOZ_COUNT_CTOR(CopyableCanvasLayer);
}
CopyableCanvasLayer::~CopyableCanvasLayer()
{
MOZ_COUNT_DTOR(CopyableCanvasLayer);
}
void
CopyableCanvasLayer::Initialize(const Data& aData)
{
NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
if (aData.mGLContext) {
mGLContext = aData.mGLContext;
mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
mOriginPos = gl::OriginPos::BottomLeft;
MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
if (aData.mFrontbufferGLTex) {
gfx::IntSize size(aData.mSize.width, aData.mSize.height);
mGLFrontbuffer = SharedSurface_Basic::Wrap(aData.mGLContext, size, aData.mHasAlpha,
aData.mFrontbufferGLTex);
}
} else if (aData.mBufferProvider) {
mBufferProvider = aData.mBufferProvider;
} else {
MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
}
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
}
bool
CopyableCanvasLayer::IsDataValid(const Data& aData)
{
return mGLContext == aData.mGLContext;
}
void
CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
{
if (mBufferProvider) {
mSurface = mBufferProvider->GetSnapshot();
}
if (!mGLContext && aDestTarget) {
NS_ASSERTION(mSurface, "Must have surface to draw!");
if (mSurface) {
aDestTarget->CopySurface(mSurface,
IntRect(0, 0, mBounds.width, mBounds.height),
IntPoint(0, 0));
mSurface = nullptr;
}
return;
}
if (mBufferProvider) {
return;
}
MOZ_ASSERT(mGLContext);
SharedSurface* frontbuffer = nullptr;
if (mGLFrontbuffer) {
frontbuffer = mGLFrontbuffer.get();
} else {
GLScreenBuffer* screen = mGLContext->Screen();
const auto& front = screen->Front();
if (front) {
frontbuffer = front->Surf();
}
}
if (!frontbuffer) {
NS_WARNING("Null frame received.");
return;
}
IntSize readSize(frontbuffer->mSize);
SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
? SurfaceFormat::B8G8R8X8
: SurfaceFormat::B8G8R8A8;
bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
// Try to read back directly into aDestTarget's output buffer
if (aDestTarget) {
uint8_t* destData;
IntSize destSize;
int32_t destStride;
SurfaceFormat destFormat;
if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
if (destSize == readSize && destFormat == format) {
RefPtr<DataSourceSurface> data =
Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
mGLContext->Readback(frontbuffer, data);
if (needsPremult) {
gfxUtils::PremultiplyDataSurface(data, data);
}
aDestTarget->ReleaseBits(destData);
return;
}
aDestTarget->ReleaseBits(destData);
}
}
RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
// There will already be a warning from inside of GetTempSurface, but
// it doesn't hurt to complain:
if (NS_WARN_IF(!resultSurf)) {
return;
}
// Readback handles Flush/MarkDirty.
mGLContext->Readback(frontbuffer, resultSurf);
if (needsPremult) {
gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
}
MOZ_ASSERT(resultSurf);
if (aDestTarget) {
aDestTarget->CopySurface(resultSurf,
IntRect(0, 0, readSize.width, readSize.height),
IntPoint(0, 0));
} else {
// If !aDestSurface then we will end up painting using mSurface, so
// stick our surface into mSurface, so that the Paint() path is the same.
mSurface = resultSurf;
}
}
DataSourceSurface*
CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
const SurfaceFormat aFormat)
{
if (!mCachedTempSurface ||
aSize != mCachedTempSurface->GetSize() ||
aFormat != mCachedTempSurface->GetFormat())
{
// Create a surface aligned to 8 bytes since that's the highest alignment WebGL can handle.
uint32_t stride = GetAlignedStride<8>(aSize.width * BytesPerPixel(aFormat));
mCachedTempSurface = Factory::CreateDataSourceSurfaceWithStride(aSize, aFormat, stride);
}
return mCachedTempSurface;
}
void
CopyableCanvasLayer::DiscardTempSurface()
{
mCachedTempSurface = nullptr;
}
} // namespace layers
} // namespace mozilla