Backed out 13 changesets (bug 709490) for android webgl-color-test.html failures

Backed out changeset 5be7514914b6 (bug 709490)
Backed out changeset 04b6f94fbe8a (bug 709490)
Backed out changeset 00c0e85dd8cd (bug 709490)
Backed out changeset 221385b7b81a (bug 709490)
Backed out changeset ecc38c18734f (bug 709490)
Backed out changeset 22878c936384 (bug 709490)
Backed out changeset 0edcbb60eee3 (bug 709490)
Backed out changeset 5feceec2014b (bug 709490)
Backed out changeset 835b655cb873 (bug 709490)
Backed out changeset 6fbb4a3f8cf7 (bug 709490)
Backed out changeset a5f8646fa156 (bug 709490)
Backed out changeset 2ae1386916b3 (bug 709490)
Backed out changeset 6b29a2a0a8fb (bug 709490)
This commit is contained in:
Wes Kocher 2015-09-29 08:57:36 -07:00
parent 01eea44f95
commit 6482c81f9b
89 changed files with 705 additions and 4138 deletions

View File

@ -8,7 +8,6 @@
#include "mozilla/dom/CanvasRenderingContext2D.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/RefPtr.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/unused.h"
@ -166,7 +165,6 @@ public:
mSize,
mImage,
nullptr,
nullptr,
getter_AddRefs(stream),
mEncoder);
@ -180,7 +178,6 @@ public:
mSize,
mImage,
nullptr,
nullptr,
getter_AddRefs(stream),
mEncoder);
}
@ -237,7 +234,6 @@ ImageEncoder::ExtractData(nsAString& aType,
const nsAString& aOptions,
const nsIntSize aSize,
nsICanvasRenderingContextInternal* aContext,
layers::AsyncCanvasRenderer* aRenderer,
nsIInputStream** aStream)
{
nsCOMPtr<imgIEncoder> encoder = ImageEncoder::GetImageEncoder(aType);
@ -246,9 +242,10 @@ ImageEncoder::ExtractData(nsAString& aType,
}
return ExtractDataInternal(aType, aOptions, nullptr, 0, aSize, nullptr,
aContext, aRenderer, aStream, encoder);
aContext, aStream, encoder);
}
/* static */
nsresult
ImageEncoder::ExtractDataFromLayersImageAsync(nsAString& aType,
@ -344,7 +341,6 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
const nsIntSize aSize,
layers::Image* aImage,
nsICanvasRenderingContextInternal* aContext,
layers::AsyncCanvasRenderer* aRenderer,
nsIInputStream** aStream,
imgIEncoder* aEncoder)
{
@ -370,11 +366,6 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
rv = aContext->GetInputStream(encoderType.get(),
nsPromiseFlatString(aOptions).get(),
getter_AddRefs(imgStream));
} else if (aRenderer) {
NS_ConvertUTF16toUTF8 encoderType(aType);
rv = aRenderer->GetInputStream(encoderType.get(),
nsPromiseFlatString(aOptions).get(),
getter_AddRefs(imgStream));
} else if (aImage) {
// It is safe to convert PlanarYCbCr format from YUV to RGB off-main-thread.
// Other image formats could have problem to convert format off-main-thread.

View File

@ -19,7 +19,6 @@ class nsICanvasRenderingContextInternal;
namespace mozilla {
namespace layers {
class AsyncCanvasRenderer;
class Image;
} // namespace layers
@ -41,7 +40,6 @@ public:
const nsAString& aOptions,
const nsIntSize aSize,
nsICanvasRenderingContextInternal* aContext,
layers::AsyncCanvasRenderer* aRenderer,
nsIInputStream** aStream);
// Extracts data asynchronously. aType may change to "image/png" if we had to
@ -86,7 +84,7 @@ public:
nsIInputStream** aStream);
private:
// When called asynchronously, aContext and aRenderer are null.
// When called asynchronously, aContext is null.
static nsresult
ExtractDataInternal(const nsAString& aType,
const nsAString& aOptions,
@ -95,7 +93,6 @@ private:
const nsIntSize aSize,
layers::Image* aImage,
nsICanvasRenderingContextInternal* aContext,
layers::AsyncCanvasRenderer* aRenderer,
nsIInputStream** aStream,
imgIEncoder* aEncoder);

View File

@ -21,8 +21,6 @@
#include "mozilla/dom/StructuredClone.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/MessagePortBinding.h"
#include "mozilla/dom/OffscreenCanvas.h"
#include "mozilla/dom/OffscreenCanvasBinding.h"
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/SubtleCryptoBinding.h"
@ -1064,25 +1062,6 @@ StructuredCloneHelper::ReadTransferCallback(JSContext* aCx,
return true;
}
if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mContext == SameProcessSameThread ||
mContext == SameProcessDifferentThread);
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
nsRefPtr<OffscreenCanvas> canvas = OffscreenCanvas::CreateFromCloneData(data);
delete data;
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, canvas, &value)) {
JS_ClearPendingException(aCx);
return false;
}
aReturnObject.set(&value.toObject());
return true;
}
return false;
}
@ -1114,24 +1093,6 @@ StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
return true;
}
if (mContext == SameProcessSameThread ||
mContext == SameProcessDifferentThread) {
OffscreenCanvas* canvas = nullptr;
rv = UNWRAP_OBJECT(OffscreenCanvas, aObj, canvas);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(canvas);
*aExtraData = 0;
*aTag = SCTAG_DOM_CANVAS;
*aOwnership = JS::SCTAG_TMO_CUSTOM;
*aContent = canvas->ToCloneData();
MOZ_ASSERT(*aContent);
canvas->SetNeutered();
return true;
}
}
}
return false;
@ -1149,17 +1110,6 @@ StructuredCloneHelper::FreeTransferCallback(uint32_t aTag,
MOZ_ASSERT(!aContent);
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
return;
}
if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mContext == SameProcessSameThread ||
mContext == SameProcessDifferentThread);
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
delete data;
return;
}
}

View File

@ -48,9 +48,6 @@ enum StructuredCloneTags {
SCTAG_DOM_FORMDATA,
// This tag is for OffscreenCanvas.
SCTAG_DOM_CANVAS,
SCTAG_DOM_MAX
};

View File

@ -1,264 +0,0 @@
/* -*- 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 "CanvasRenderingContextHelper.h"
#include "ImageEncoder.h"
#include "mozilla/dom/CanvasRenderingContext2D.h"
#include "mozilla/Telemetry.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
#include "nsIScriptContext.h"
#include "nsJSUtils.h"
#include "WebGL1Context.h"
#include "WebGL2Context.h"
namespace mozilla {
namespace dom {
void
CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
nsIGlobalObject* aGlobal,
FileCallback& aCallback,
const nsAString& aType,
JS::Handle<JS::Value> aParams,
ErrorResult& aRv)
{
nsAutoString type;
nsContentUtils::ASCIIToLower(aType, type);
nsAutoString params;
bool usingCustomParseOptions;
aRv = ParseParams(aCx, type, aParams, params, &usingCustomParseOptions);
if (aRv.Failed()) {
return;
}
#ifdef DEBUG
if (mCurrentContext) {
// We disallow canvases of width or height zero, and set them to 1, so
// we will have a discrepancy with the sizes of the canvas and the context.
// That discrepancy is OK, the rest are not.
nsIntSize elementSize = GetWidthHeight();
MOZ_ASSERT(elementSize.width == mCurrentContext->GetWidth() ||
(elementSize.width == 0 && mCurrentContext->GetWidth() == 1));
MOZ_ASSERT(elementSize.height == mCurrentContext->GetHeight() ||
(elementSize.height == 0 && mCurrentContext->GetHeight() == 1));
}
#endif
uint8_t* imageBuffer = nullptr;
int32_t format = 0;
if (mCurrentContext) {
mCurrentContext->GetImageBuffer(&imageBuffer, &format);
}
// Encoder callback when encoding is complete.
class EncodeCallback : public EncodeCompleteCallback
{
public:
EncodeCallback(nsIGlobalObject* aGlobal, FileCallback* aCallback)
: mGlobal(aGlobal)
, mFileCallback(aCallback) {}
// This is called on main thread.
nsresult ReceiveBlob(already_AddRefed<Blob> aBlob)
{
nsRefPtr<Blob> blob = aBlob;
ErrorResult rv;
uint64_t size = blob->GetSize(rv);
if (rv.Failed()) {
rv.SuppressException();
} else {
AutoJSAPI jsapi;
if (jsapi.Init(mGlobal)) {
JS_updateMallocCounter(jsapi.cx(), size);
}
}
nsRefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
mFileCallback->Call(*newBlob, rv);
mGlobal = nullptr;
mFileCallback = nullptr;
return rv.StealNSResult();
}
nsCOMPtr<nsIGlobalObject> mGlobal;
nsRefPtr<FileCallback> mFileCallback;
};
nsRefPtr<EncodeCompleteCallback> callback =
new EncodeCallback(aGlobal, &aCallback);
aRv = ImageEncoder::ExtractDataAsync(type,
params,
usingCustomParseOptions,
imageBuffer,
format,
GetWidthHeight(),
callback);
}
already_AddRefed<nsICanvasRenderingContextInternal>
CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
{
MOZ_ASSERT(aContextType != CanvasContextType::NoContext);
nsRefPtr<nsICanvasRenderingContextInternal> ret;
switch (aContextType) {
case CanvasContextType::NoContext:
break;
case CanvasContextType::Canvas2D:
Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
ret = new CanvasRenderingContext2D();
break;
case CanvasContextType::WebGL1:
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL1Context::Create();
if (!ret)
return nullptr;
break;
case CanvasContextType::WebGL2:
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL2Context::Create();
if (!ret)
return nullptr;
break;
}
MOZ_ASSERT(ret);
return ret.forget();
}
already_AddRefed<nsISupports>
CanvasRenderingContextHelper::GetContext(JSContext* aCx,
const nsAString& aContextId,
JS::Handle<JS::Value> aContextOptions,
ErrorResult& aRv)
{
CanvasContextType contextType;
if (!CanvasUtils::GetCanvasContextType(aContextId, &contextType))
return nullptr;
if (!mCurrentContext) {
// This canvas doesn't have a context yet.
nsRefPtr<nsICanvasRenderingContextInternal> context;
context = CreateContext(contextType);
if (!context) {
return nullptr;
}
// Ensure that the context participates in CC. Note that returning a
// CC participant from QI doesn't addref.
nsXPCOMCycleCollectionParticipant* cp = nullptr;
CallQueryInterface(context, &cp);
if (!cp) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
mCurrentContext = context.forget();
mCurrentContextType = contextType;
aRv = UpdateContext(aCx, aContextOptions);
if (aRv.Failed()) {
aRv = NS_OK; // See bug 645792
return nullptr;
}
} else {
// We already have a context of some type.
if (contextType != mCurrentContextType)
return nullptr;
}
nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext;
return context.forget();
}
nsresult
CanvasRenderingContextHelper::UpdateContext(JSContext* aCx,
JS::Handle<JS::Value> aNewContextOptions)
{
if (!mCurrentContext)
return NS_OK;
nsIntSize sz = GetWidthHeight();
nsCOMPtr<nsICanvasRenderingContextInternal> currentContext = mCurrentContext;
nsresult rv = currentContext->SetIsOpaque(GetOpaqueAttr());
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
rv = currentContext->SetContextOptions(aCx, aNewContextOptions);
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
rv = currentContext->SetDimensions(sz.width, sz.height);
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
}
return rv;
}
nsresult
CanvasRenderingContextHelper::ParseParams(JSContext* aCx,
const nsAString& aType,
const JS::Value& aEncoderOptions,
nsAString& outParams,
bool* const outUsingCustomParseOptions)
{
// Quality parameter is only valid for the image/jpeg MIME type
if (aType.EqualsLiteral("image/jpeg")) {
if (aEncoderOptions.isNumber()) {
double quality = aEncoderOptions.toNumber();
// Quality must be between 0.0 and 1.0, inclusive
if (quality >= 0.0 && quality <= 1.0) {
outParams.AppendLiteral("quality=");
outParams.AppendInt(NS_lround(quality * 100.0));
}
}
}
// If we haven't parsed the aParams check for proprietary options.
// The proprietary option -moz-parse-options will take a image lib encoder
// parse options string as is and pass it to the encoder.
*outUsingCustomParseOptions = false;
if (outParams.Length() == 0 && aEncoderOptions.isString()) {
NS_NAMED_LITERAL_STRING(mozParseOptions, "-moz-parse-options:");
nsAutoJSString paramString;
if (!paramString.init(aCx, aEncoderOptions.toString())) {
return NS_ERROR_FAILURE;
}
if (StringBeginsWith(paramString, mozParseOptions)) {
nsDependentSubstring parseOptions = Substring(paramString,
mozParseOptions.Length(),
paramString.Length() -
mozParseOptions.Length());
outParams.Append(parseOptions);
*outUsingCustomParseOptions = true;
}
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla

View File

@ -1,71 +0,0 @@
/* -*- 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/. */
#ifndef MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
#define MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
#include "mozilla/dom/BindingDeclarations.h"
#include "nsSize.h"
class nsICanvasRenderingContextInternal;
class nsIGlobalObject;
namespace mozilla {
class ErrorResult;
namespace dom {
class FileCallback;
enum class CanvasContextType : uint8_t {
NoContext,
Canvas2D,
WebGL1,
WebGL2
};
/**
* Povides common RenderingContext functionality used by both OffscreenCanvas
* and HTMLCanvasElement.
*/
class CanvasRenderingContextHelper
{
public:
virtual already_AddRefed<nsISupports>
GetContext(JSContext* aCx,
const nsAString& aContextId,
JS::Handle<JS::Value> aContextOptions,
ErrorResult& aRv);
virtual bool GetOpaqueAttr() = 0;
protected:
virtual nsresult UpdateContext(JSContext* aCx,
JS::Handle<JS::Value> aNewContextOptions);
virtual nsresult ParseParams(JSContext* aCx,
const nsAString& aType,
const JS::Value& aEncoderOptions,
nsAString& outParams,
bool* const outCustomParseOptions);
void ToBlob(JSContext* aCx, nsIGlobalObject* global, FileCallback& aCallback,
const nsAString& aType, JS::Handle<JS::Value> aParams,
ErrorResult& aRv);
virtual already_AddRefed<nsICanvasRenderingContextInternal>
CreateContext(CanvasContextType aContextType);
virtual nsIntSize GetWidthHeight() = 0;
CanvasContextType mCurrentContextType;
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
};
} // namespace dom
} // namespace mozilla
#endif // MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_

View File

@ -23,47 +23,12 @@
#include "CanvasUtils.h"
#include "mozilla/gfx/Matrix.h"
#include "WebGL2Context.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace CanvasUtils {
bool
GetCanvasContextType(const nsAString& str, dom::CanvasContextType* const out_type)
{
if (str.EqualsLiteral("2d")) {
*out_type = dom::CanvasContextType::Canvas2D;
return true;
}
if (str.EqualsLiteral("experimental-webgl")) {
*out_type = dom::CanvasContextType::WebGL1;
return true;
}
#ifdef MOZ_WEBGL_CONFORMANT
if (str.EqualsLiteral("webgl")) {
/* WebGL 1.0, $2.1 "Context Creation":
* If the user agent supports both the webgl and experimental-webgl
* canvas context types, they shall be treated as aliases.
*/
*out_type = dom::CanvasContextType::WebGL1;
return true;
}
#endif
if (WebGL2Context::IsSupported()) {
if (str.EqualsLiteral("webgl2")) {
*out_type = dom::CanvasContextType::WebGL2;
return true;
}
}
return false;
}
/**
* This security check utility might be called from an source that never taints
* others. For example, while painting a CanvasPattern, which is created from an

View File

@ -21,7 +21,6 @@ class HTMLCanvasElement;
namespace CanvasUtils {
bool GetCanvasContextType(const nsAString& str, dom::CanvasContextType* const out_type);
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]

View File

@ -1,242 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "OffscreenCanvas.h"
#include "mozilla/dom/OffscreenCanvasBinding.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/Telemetry.h"
#include "CanvasRenderingContext2D.h"
#include "CanvasUtils.h"
#include "GLScreenBuffer.h"
#include "WebGL1Context.h"
#include "WebGL2Context.h"
namespace mozilla {
namespace dom {
OffscreenCanvasCloneData::OffscreenCanvasCloneData(layers::AsyncCanvasRenderer* aRenderer,
uint32_t aWidth, uint32_t aHeight,
layers::LayersBackend aCompositorBackend,
bool aNeutered)
: mRenderer(aRenderer)
, mWidth(aWidth)
, mHeight(aHeight)
, mCompositorBackendType(aCompositorBackend)
, mNeutered(aNeutered)
{
}
OffscreenCanvasCloneData::~OffscreenCanvasCloneData()
{
}
OffscreenCanvas::OffscreenCanvas(uint32_t aWidth,
uint32_t aHeight,
layers::LayersBackend aCompositorBackend,
layers::AsyncCanvasRenderer* aRenderer)
: mAttrDirty(false)
, mNeutered(false)
, mWidth(aWidth)
, mHeight(aHeight)
, mCompositorBackendType(aCompositorBackend)
, mCanvasClient(nullptr)
, mCanvasRenderer(aRenderer)
{}
OffscreenCanvas::~OffscreenCanvas()
{
ClearResources();
}
OffscreenCanvas*
OffscreenCanvas::GetParentObject() const
{
return nullptr;
}
JSObject*
OffscreenCanvas::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return OffscreenCanvasBinding::Wrap(aCx, this, aGivenProto);
}
void
OffscreenCanvas::ClearResources()
{
if (mCanvasClient) {
mCanvasClient->Clear();
ImageBridgeChild::DispatchReleaseCanvasClient(mCanvasClient);
mCanvasClient = nullptr;
if (mCanvasRenderer) {
nsCOMPtr<nsIThread> activeThread = mCanvasRenderer->GetActiveThread();
MOZ_RELEASE_ASSERT(activeThread);
MOZ_RELEASE_ASSERT(activeThread == NS_GetCurrentThread());
mCanvasRenderer->SetCanvasClient(nullptr);
mCanvasRenderer->mContext = nullptr;
mCanvasRenderer->mGLContext = nullptr;
mCanvasRenderer->ResetActiveThread();
}
}
}
already_AddRefed<nsISupports>
OffscreenCanvas::GetContext(JSContext* aCx,
const nsAString& aContextId,
JS::Handle<JS::Value> aContextOptions,
ErrorResult& aRv)
{
if (mNeutered) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
// We only support WebGL in workers for now
CanvasContextType contextType;
if (!CanvasUtils::GetCanvasContextType(aContextId, &contextType)) {
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
}
if (!(contextType == CanvasContextType::WebGL1 ||
contextType == CanvasContextType::WebGL2))
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
}
already_AddRefed<nsISupports> result =
CanvasRenderingContextHelper::GetContext(aCx,
aContextId,
aContextOptions,
aRv);
if (!mCurrentContext) {
return nullptr;
}
if (mCanvasRenderer) {
WebGLContext* webGL = static_cast<WebGLContext*>(mCurrentContext.get());
gl::GLContext* gl = webGL->GL();
mCanvasRenderer->mContext = mCurrentContext;
mCanvasRenderer->SetActiveThread();
mCanvasRenderer->mGLContext = gl;
mCanvasRenderer->SetIsAlphaPremultiplied(webGL->IsPremultAlpha() || !gl->Caps().alpha);
if (ImageBridgeChild::IsCreated()) {
TextureFlags flags = TextureFlags::ORIGIN_BOTTOM_LEFT;
mCanvasClient = ImageBridgeChild::GetSingleton()->
CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags).take();
mCanvasRenderer->SetCanvasClient(mCanvasClient);
gl::GLScreenBuffer* screen = gl->Screen();
gl::SurfaceCaps caps = screen->mCaps;
auto forwarder = mCanvasClient->GetForwarder();
UniquePtr<gl::SurfaceFactory> factory =
gl::GLScreenBuffer::CreateFactory(gl, caps, forwarder, flags);
if (factory)
screen->Morph(Move(factory));
}
}
return result;
}
already_AddRefed<nsICanvasRenderingContextInternal>
OffscreenCanvas::CreateContext(CanvasContextType aContextType)
{
nsRefPtr<nsICanvasRenderingContextInternal> ret =
CanvasRenderingContextHelper::CreateContext(aContextType);
ret->SetOffscreenCanvas(this);
return ret.forget();
}
void
OffscreenCanvas::CommitFrameToCompositor()
{
// The attributes has changed, we have to notify main
// thread to change canvas size.
if (mAttrDirty) {
if (mCanvasRenderer) {
mCanvasRenderer->SetWidth(mWidth);
mCanvasRenderer->SetHeight(mHeight);
mCanvasRenderer->NotifyElementAboutAttributesChanged();
}
mAttrDirty = false;
}
if (mCurrentContext) {
static_cast<WebGLContext*>(mCurrentContext.get())->PresentScreenBuffer();
}
if (mCanvasRenderer && mCanvasRenderer->mGLContext) {
mCanvasRenderer->NotifyElementAboutInvalidation();
ImageBridgeChild::GetSingleton()->
UpdateAsyncCanvasRenderer(mCanvasRenderer);
}
}
OffscreenCanvasCloneData*
OffscreenCanvas::ToCloneData()
{
return new OffscreenCanvasCloneData(mCanvasRenderer, mWidth, mHeight,
mCompositorBackendType, mNeutered);
}
/* static */ already_AddRefed<OffscreenCanvas>
OffscreenCanvas::CreateFromCloneData(OffscreenCanvasCloneData* aData)
{
MOZ_ASSERT(aData);
nsRefPtr<OffscreenCanvas> wc =
new OffscreenCanvas(aData->mWidth, aData->mHeight,
aData->mCompositorBackendType, aData->mRenderer);
if (aData->mNeutered) {
wc->SetNeutered();
}
return wc.forget();
}
/* static */ bool
OffscreenCanvas::PrefEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("gfx.offscreencanvas.enabled");
} else {
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
MOZ_ASSERT(workerPrivate);
return workerPrivate->OffscreenCanvasEnabled();
}
}
/* static */ bool
OffscreenCanvas::PrefEnabledOnWorkerThread(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return true;
}
return PrefEnabled(aCx, aObj);
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(OffscreenCanvas, DOMEventTargetHelper, mCurrentContext)
NS_IMPL_ADDREF_INHERITED(OffscreenCanvas, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(OffscreenCanvas, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OffscreenCanvas)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
} // namespace dom
} // namespace mozilla

View File

@ -1,179 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef MOZILLA_DOM_OFFSCREENCANVAS_H_
#define MOZILLA_DOM_OFFSCREENCANVAS_H_
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/RefPtr.h"
#include "CanvasRenderingContextHelper.h"
#include "nsCycleCollectionParticipant.h"
struct JSContext;
namespace mozilla {
class ErrorResult;
namespace layers {
class AsyncCanvasRenderer;
class CanvasClient;
} // namespace layers
namespace dom {
// This is helper class for transferring OffscreenCanvas to worker thread.
// Because OffscreenCanvas is not thread-safe. So we cannot pass Offscreen-
// Canvas to worker thread directly. Thus, we create this helper class and
// store necessary data in it then pass it to worker thread.
struct OffscreenCanvasCloneData final
{
OffscreenCanvasCloneData(layers::AsyncCanvasRenderer* aRenderer,
uint32_t aWidth, uint32_t aHeight,
layers::LayersBackend aCompositorBackend,
bool aNeutered);
~OffscreenCanvasCloneData();
RefPtr<layers::AsyncCanvasRenderer> mRenderer;
uint32_t mWidth;
uint32_t mHeight;
layers::LayersBackend mCompositorBackendType;
bool mNeutered;
};
class OffscreenCanvas final : public DOMEventTargetHelper
, public CanvasRenderingContextHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OffscreenCanvas, DOMEventTargetHelper)
OffscreenCanvas(uint32_t aWidth,
uint32_t aHeight,
layers::LayersBackend aCompositorBackend,
layers::AsyncCanvasRenderer* aRenderer);
OffscreenCanvas* GetParentObject() const;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
void ClearResources();
uint32_t Width() const
{
return mWidth;
}
uint32_t Height() const
{
return mHeight;
}
void SetWidth(uint32_t aWidth, ErrorResult& aRv)
{
if (mNeutered) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (mWidth != aWidth) {
mWidth = aWidth;
CanvasAttrChanged();
}
}
void SetHeight(uint32_t aHeight, ErrorResult& aRv)
{
if (mNeutered) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (mHeight != aHeight) {
mHeight = aHeight;
CanvasAttrChanged();
}
}
nsICanvasRenderingContextInternal* GetContext() const
{
return mCurrentContext;
}
static already_AddRefed<OffscreenCanvas>
CreateFromCloneData(OffscreenCanvasCloneData* aData);
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
// Return true on main-thread, and return gfx.offscreencanvas.enabled
// on worker thread.
static bool PrefEnabledOnWorkerThread(JSContext* aCx, JSObject* aObj);
OffscreenCanvasCloneData* ToCloneData();
void CommitFrameToCompositor();
virtual bool GetOpaqueAttr() override
{
return false;
}
virtual nsIntSize GetWidthHeight() override
{
return nsIntSize(mWidth, mHeight);
}
virtual already_AddRefed<nsICanvasRenderingContextInternal>
CreateContext(CanvasContextType aContextType) override;
virtual already_AddRefed<nsISupports>
GetContext(JSContext* aCx,
const nsAString& aContextId,
JS::Handle<JS::Value> aContextOptions,
ErrorResult& aRv) override;
void SetNeutered()
{
mNeutered = true;
}
bool IsNeutered() const
{
return mNeutered;
}
layers::LayersBackend GetCompositorBackendType() const
{
return mCompositorBackendType;
}
private:
~OffscreenCanvas();
void CanvasAttrChanged()
{
mAttrDirty = true;
UpdateContext(nullptr, JS::NullHandleValue);
}
bool mAttrDirty;
bool mNeutered;
uint32_t mWidth;
uint32_t mHeight;
layers::LayersBackend mCompositorBackendType;
layers::CanvasClient* mCanvasClient;
RefPtr<layers::AsyncCanvasRenderer> mCanvasRenderer;
};
} // namespace dom
} // namespace mozilla
#endif // MOZILLA_DOM_OFFSCREENCANVAS_H_

View File

@ -22,7 +22,6 @@
#include "ImageEncoder.h"
#include "Layers.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/EnumeratedArrayCycleCollection.h"
@ -80,6 +79,125 @@ using namespace mozilla::gfx;
using namespace mozilla::gl;
using namespace mozilla::layers;
WebGLObserver::WebGLObserver(WebGLContext* webgl)
: mWebGL(webgl)
{
}
WebGLObserver::~WebGLObserver()
{
}
void
WebGLObserver::Destroy()
{
UnregisterMemoryPressureEvent();
UnregisterVisibilityChangeEvent();
mWebGL = nullptr;
}
void
WebGLObserver::RegisterVisibilityChangeEvent()
{
if (!mWebGL)
return;
HTMLCanvasElement* canvas = mWebGL->GetCanvas();
MOZ_ASSERT(canvas);
if (canvas) {
nsIDocument* document = canvas->OwnerDoc();
document->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
this, true, false);
}
}
void
WebGLObserver::UnregisterVisibilityChangeEvent()
{
if (!mWebGL)
return;
HTMLCanvasElement* canvas = mWebGL->GetCanvas();
if (canvas) {
nsIDocument* document = canvas->OwnerDoc();
document->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
this, true);
}
}
void
WebGLObserver::RegisterMemoryPressureEvent()
{
if (!mWebGL)
return;
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
MOZ_ASSERT(observerService);
if (observerService)
observerService->AddObserver(this, "memory-pressure", false);
}
void
WebGLObserver::UnregisterMemoryPressureEvent()
{
if (!mWebGL)
return;
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
// Do not assert on observerService here. This might be triggered by
// the cycle collector at a late enough time, that XPCOM services are
// no longer available. See bug 1029504.
if (observerService)
observerService->RemoveObserver(this, "memory-pressure");
}
NS_IMETHODIMP
WebGLObserver::Observe(nsISupports*, const char* topic, const char16_t*)
{
if (!mWebGL || strcmp(topic, "memory-pressure")) {
return NS_OK;
}
bool wantToLoseContext = mWebGL->mLoseContextOnMemoryPressure;
if (!mWebGL->mCanLoseContextInForeground &&
ProcessPriorityManager::CurrentProcessIsForeground())
{
wantToLoseContext = false;
}
if (wantToLoseContext)
mWebGL->ForceLoseContext();
return NS_OK;
}
NS_IMETHODIMP
WebGLObserver::HandleEvent(nsIDOMEvent* event)
{
nsAutoString type;
event->GetType(type);
if (!mWebGL || !type.EqualsLiteral("visibilitychange"))
return NS_OK;
HTMLCanvasElement* canvas = mWebGL->GetCanvas();
MOZ_ASSERT(canvas);
if (canvas && !canvas->OwnerDoc()->Hidden())
mWebGL->ForceRestoreContext();
return NS_OK;
}
WebGLContextOptions::WebGLContextOptions()
: alpha(true)
, depth(true)
@ -90,7 +208,7 @@ WebGLContextOptions::WebGLContextOptions()
, failIfMajorPerformanceCaveat(false)
{
// Set default alpha state based on preference.
if (gfxPrefs::WebGLDefaultNoAlpha())
if (Preferences::GetBool("webgl.default-no-alpha", false))
alpha = false;
}
@ -164,10 +282,7 @@ WebGLContext::WebGLContext()
mPixelStorePackAlignment = 4;
mPixelStoreUnpackAlignment = 4;
if (NS_IsMainThread()) {
// XXX mtseng: bug 709490, not thread safe
WebGLMemoryTracker::AddWebGLContext(this);
}
WebGLMemoryTracker::AddWebGLContext(this);
mAllowContextRestore = true;
mLastLossWasSimulated = false;
@ -181,12 +296,15 @@ WebGLContext::WebGLContext()
mAlreadyWarnedAboutFakeVertexAttrib0 = false;
mAlreadyWarnedAboutViewportLargerThanDest = false;
mMaxWarnings = gfxPrefs::WebGLMaxWarningsPerContext();
mMaxWarnings = Preferences::GetInt("webgl.max-warnings-per-context", 32);
if (mMaxWarnings < -1) {
GenerateWarning("webgl.max-warnings-per-context size is too large (seems like a negative value wrapped)");
mMaxWarnings = 0;
}
mContextObserver = new WebGLObserver(this);
MOZ_RELEASE_ASSERT(mContextObserver, "Can't alloc WebGLContextObserver");
mLastUseIndex = 0;
InvalidateBufferFetching();
@ -201,12 +319,10 @@ WebGLContext::WebGLContext()
WebGLContext::~WebGLContext()
{
RemovePostRefreshObserver();
mContextObserver->Destroy();
DestroyResourcesAndContext();
if (NS_IsMainThread()) {
// XXX mtseng: bug 709490, not thread safe
WebGLMemoryTracker::RemoveWebGLContext(this);
}
WebGLMemoryTracker::RemoveWebGLContext(this);
mContextLossHandler->DisableTimer();
mContextLossHandler = nullptr;
@ -215,6 +331,8 @@ WebGLContext::~WebGLContext()
void
WebGLContext::DestroyResourcesAndContext()
{
mContextObserver->UnregisterMemoryPressureEvent();
if (!gl)
return;
@ -313,35 +431,6 @@ WebGLContext::Invalidate()
mCanvasElement->InvalidateCanvasContent(nullptr);
}
void
WebGLContext::OnVisibilityChange()
{
if (!IsContextLost()) {
return;
}
if (!mRestoreWhenVisible || mLastLossWasSimulated) {
return;
}
ForceRestoreContext();
}
void
WebGLContext::OnMemoryPressure()
{
bool shouldLoseContext = mLoseContextOnMemoryPressure;
if (!mCanLoseContextInForeground &&
ProcessPriorityManager::CurrentProcessIsForeground())
{
shouldLoseContext = false;
}
if (shouldLoseContext)
ForceLoseContext();
}
//
// nsICanvasRenderingContextInternal
//
@ -426,7 +515,7 @@ static bool
IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature)
{
int32_t status;
if (!NS_SUCCEEDED(gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, feature, &status)))
if (!NS_SUCCEEDED(gfxInfo->GetFeatureStatus(feature, &status)))
return false;
return status != nsIGfxInfo::FEATURE_STATUS_OK;
@ -437,29 +526,19 @@ HasAcceleratedLayers(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
{
int32_t status;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
&status);
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status);
if (status)
return true;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS,
&status);
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS, &status);
if (status)
return true;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS,
&status);
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS, &status);
if (status)
return true;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
&status);
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status);
if (status)
return true;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_OPENGL_LAYERS,
&status);
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status);
if (status)
return true;
@ -516,14 +595,11 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
// we should really have this behind a
// |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
// for now it's just behind a pref for testing/evaluation.
baseCaps.bpp16 = gfxPrefs::WebGLPrefer16bpp();
baseCaps.bpp16 = Preferences::GetBool("webgl.prefer-16bpp", false);
#ifdef MOZ_WIDGET_GONK
do {
auto canvasElement = webgl->GetCanvas();
if (!canvasElement)
break;
auto ownerDoc = canvasElement->OwnerDoc();
nsIWidget* docWidget = nsContentUtils::WidgetForDocument(ownerDoc);
if (!docWidget)
@ -544,7 +620,7 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
// Done with baseCaps construction.
bool forceAllowAA = gfxPrefs::WebGLForceMSAA();
bool forceAllowAA = Preferences::GetBool("webgl.msaa-force", false);
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
if (!forceAllowAA &&
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA))
@ -664,7 +740,7 @@ bool
WebGLContext::CreateAndInitGL(bool forceEnabled)
{
bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
bool disableANGLE = gfxPrefs::WebGLDisableANGLE();
bool disableANGLE = Preferences::GetBool("webgl.disable-angle", false);
if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
disableANGLE = true;
@ -745,6 +821,10 @@ WebGLContext::ResizeBackbuffer(uint32_t requestedWidth,
NS_IMETHODIMP
WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
{
// Early error return cases
if (!GetCanvas())
return NS_ERROR_FAILURE;
if (signedWidth < 0 || signedHeight < 0) {
GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
return NS_ERROR_OUT_OF_MEMORY;
@ -754,10 +834,7 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
uint32_t height = signedHeight;
// Early success return cases
// May have a OffscreenCanvas instead of an HTMLCanvasElement
if (GetCanvas())
GetCanvas()->InvalidateCanvas();
GetCanvas()->InvalidateCanvas();
// Zero-sized surfaces can cause problems.
if (width == 0)
@ -830,7 +907,10 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
// pick up the old generation.
++mGeneration;
bool disabled = gfxPrefs::WebGLDisabled();
// Get some prefs for some preferred/overriden things
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
bool disabled = Preferences::GetBool("webgl.disabled", false);
// TODO: When we have software webgl support we should use that instead.
disabled |= gfxPlatform::InSafeMode();
@ -853,7 +933,7 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
}
// Alright, now let's start trying.
bool forceEnabled = gfxPrefs::WebGLForceEnabled();
bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false);
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
MOZ_ASSERT(!gl);
@ -974,11 +1054,6 @@ WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
#endif
MOZ_ASSERT(kMaxWebGLContextsPerPrincipal < kMaxWebGLContexts);
if (!NS_IsMainThread()) {
// XXX mtseng: bug 709490, WebGLMemoryTracker is not thread safe.
return;
}
// it's important to update the index on a new context before losing old contexts,
// otherwise new unused contexts would all have index 0 and we couldn't distinguish older ones
// when choosing which one to lose first.
@ -1066,8 +1141,32 @@ WebGLContext::GetImageBuffer(uint8_t** out_imageBuffer, int32_t* out_format)
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
return gfxUtils::GetImageBuffer(dataSurface, mOptions.premultipliedAlpha,
out_imageBuffer, out_format);
DataSourceSurface::MappedSurface map;
if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map))
return;
uint8_t* imageBuffer = new (fallible) uint8_t[mWidth * mHeight * 4];
if (!imageBuffer) {
dataSurface->Unmap();
return;
}
memcpy(imageBuffer, map.mData, mWidth * mHeight * 4);
dataSurface->Unmap();
int32_t format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
if (!mOptions.premultipliedAlpha) {
// We need to convert to INPUT_FORMAT_RGBA, otherwise
// we are automatically considered premult, and unpremult'd.
// Yes, it is THAT silly.
// Except for different lossy conversions by color,
// we could probably just change the label, and not change the data.
gfxUtils::ConvertBGRAtoRGBA(imageBuffer, mWidth * mHeight * 4);
format = imgIEncoder::INPUT_FORMAT_RGBA;
}
*out_imageBuffer = imageBuffer;
*out_format = format;
}
NS_IMETHODIMP
@ -1079,18 +1178,20 @@ WebGLContext::GetInputStream(const char* mimeType,
if (!gl)
return NS_ERROR_FAILURE;
// Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
bool premult;
RefPtr<SourceSurface> snapshot =
GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
if (!snapshot)
nsCString enccid("@mozilla.org/image/encoder;2?type=");
enccid += mimeType;
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(enccid.get());
if (!encoder)
return NS_ERROR_FAILURE;
MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
nsAutoArrayPtr<uint8_t> imageBuffer;
int32_t format = 0;
GetImageBuffer(getter_Transfers(imageBuffer), &format);
if (!imageBuffer)
return NS_ERROR_FAILURE;
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
return gfxUtils::GetInputStream(dataSurface, mOptions.premultipliedAlpha, mimeType,
encoderOptions, out_stream);
return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer, format,
encoder, encoderOptions, out_stream);
}
void
@ -1169,26 +1270,25 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
}
WebGLContextUserData* userData = nullptr;
if (builder->IsPaintingToWindow() && mCanvasElement) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
if (builder->IsPaintingToWindow()) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new WebGLContextUserData(mCanvasElement);
canvasLayer->SetDidTransactionCallback(
WebGLContextUserData::DidTransactionCallback, userData);
canvasLayer->SetPreTransactionCallback(
WebGLContextUserData::PreTransactionCallback, userData);
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new WebGLContextUserData(mCanvasElement);
canvasLayer->SetDidTransactionCallback(
WebGLContextUserData::DidTransactionCallback, userData);
canvasLayer->SetPreTransactionCallback(
WebGLContextUserData::PreTransactionCallback, userData);
}
canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
CanvasLayer::Data data;
@ -1210,36 +1310,14 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
layers::LayersBackend
WebGLContext::GetCompositorBackendType() const
{
if (mCanvasElement) {
return mCanvasElement->GetCompositorBackendType();
} else if (mOffscreenCanvas) {
return mOffscreenCanvas->GetCompositorBackendType();
nsIWidget* docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
if (docWidget) {
layers::LayerManager* layerManager = docWidget->GetLayerManager();
return layerManager->GetCompositorBackendType();
}
return LayersBackend::LAYERS_NONE;
}
void
WebGLContext::Commit()
{
if (mOffscreenCanvas) {
mOffscreenCanvas->CommitFrameToCompositor();
}
}
void
WebGLContext::GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& retval)
{
if (mCanvasElement) {
MOZ_RELEASE_ASSERT(!mOffscreenCanvas);
retval.SetValue().SetAsHTMLCanvasElement() = mCanvasElement;
} else if (mOffscreenCanvas) {
retval.SetValue().SetAsOffscreenCanvas() = mOffscreenCanvas;
} else {
retval.SetNull();
}
}
void
WebGLContext::GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval)
{
@ -1548,7 +1626,7 @@ WebGLContext::RunContextLossTimer()
mContextLossHandler->RunTimer();
}
class UpdateContextLossStatusTask : public nsCancelableRunnable
class UpdateContextLossStatusTask : public nsRunnable
{
nsRefPtr<WebGLContext> mWebGL;
@ -1559,16 +1637,10 @@ public:
}
NS_IMETHOD Run() {
if (mWebGL)
mWebGL->UpdateContextLossStatus();
mWebGL->UpdateContextLossStatus();
return NS_OK;
}
NS_IMETHOD Cancel() {
mWebGL = nullptr;
return NS_OK;
}
};
void
@ -1595,7 +1667,7 @@ WebGLContext::EnqueueUpdateContextLossStatus()
void
WebGLContext::UpdateContextLossStatus()
{
if (!mCanvasElement && !mOffscreenCanvas) {
if (!mCanvasElement) {
// the canvas is gone. That happens when the page was closed before we got
// this timer event. In this case, there's nothing to do here, just don't crash.
return;
@ -1623,23 +1695,12 @@ WebGLContext::UpdateContextLossStatus()
// callback, so do that now.
bool useDefaultHandler;
if (mCanvasElement) {
nsContentUtils::DispatchTrustedEvent(
mCanvasElement->OwnerDoc(),
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
NS_LITERAL_STRING("webglcontextlost"),
true,
true,
&useDefaultHandler);
} else {
// OffscreenCanvas case
nsRefPtr<Event> event = new Event(mOffscreenCanvas, nullptr, nullptr);
event->InitEvent(NS_LITERAL_STRING("webglcontextlost"), true, true);
event->SetTrusted(true);
mOffscreenCanvas->DispatchEvent(event, &useDefaultHandler);
}
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
NS_LITERAL_STRING("webglcontextlost"),
true,
true,
&useDefaultHandler);
// We sent the callback, so we're just 'regular lost' now.
mContextStatus = ContextLost;
// If we're told to use the default handler, it means the script
@ -1691,22 +1752,11 @@ WebGLContext::UpdateContextLossStatus()
// Revival!
mContextStatus = ContextNotLost;
if (mCanvasElement) {
nsContentUtils::DispatchTrustedEvent(
mCanvasElement->OwnerDoc(),
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
NS_LITERAL_STRING("webglcontextrestored"),
true,
true);
} else {
nsRefPtr<Event> event = new Event(mOffscreenCanvas, nullptr, nullptr);
event->InitEvent(NS_LITERAL_STRING("webglcontextrestored"), true, true);
event->SetTrusted(true);
bool unused;
mOffscreenCanvas->DispatchEvent(event, &unused);
}
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
NS_LITERAL_STRING("webglcontextrestored"),
true,
true);
mEmitContextLostErrorOnce = true;
return;
}
@ -1724,6 +1774,12 @@ WebGLContext::ForceLoseContext(bool simulateLosing)
DestroyResourcesAndContext();
mLastLossWasSimulated = simulateLosing;
// Register visibility change observer to defer the context restoring.
// Restore the context when the app is visible.
if (mRestoreWhenVisible && !mLastLossWasSimulated) {
mContextObserver->RegisterVisibilityChangeEvent();
}
// Queue up a task, since we know the status changed.
EnqueueUpdateContextLossStatus();
}
@ -1735,6 +1791,8 @@ WebGLContext::ForceRestoreContext()
mContextStatus = ContextLostAwaitingRestore;
mAllowContextRestore = true; // Hey, you did say 'force'.
mContextObserver->UnregisterVisibilityChangeEvent();
// Queue up a task, since we know the status changed.
EnqueueUpdateContextLossStatus();
}
@ -1869,7 +1927,6 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
mCanvasElement,
mOffscreenCanvas,
mExtensions,
mBound2DTextures,
mBoundCubeMapTextures,

View File

@ -40,11 +40,7 @@
// Generated
#include "nsIDOMEventListener.h"
#include "nsIDOMWebGLRenderingContext.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsIObserver.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "nsWrapperCache.h"
#include "nsLayoutUtils.h"
class nsIDocShell;
@ -84,6 +80,7 @@ class WebGLContextLossHandler;
class WebGLBuffer;
class WebGLExtensionBase;
class WebGLFramebuffer;
class WebGLObserver;
class WebGLProgram;
class WebGLQuery;
class WebGLRenderbuffer;
@ -98,7 +95,6 @@ class WebGLVertexArray;
namespace dom {
class Element;
class ImageData;
class OwningHTMLCanvasElementOrOffscreenCanvas;
struct WebGLContextAttributes;
template<typename> struct Nullable;
} // namespace dom
@ -188,6 +184,7 @@ class WebGLContext
friend class WebGLExtensionLoseContext;
friend class WebGLExtensionVertexArray;
friend class WebGLMemoryTracker;
friend class WebGLObserver;
enum {
UNPACK_FLIP_Y_WEBGL = 0x9240,
@ -217,9 +214,6 @@ public:
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
virtual void OnVisibilityChange() override;
virtual void OnMemoryPressure() override;
// nsICanvasRenderingContextInternal
#ifdef DEBUG
virtual int32_t GetWidth() const override;
@ -368,11 +362,8 @@ public:
void AssertCachedBindings();
void AssertCachedState();
dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; }
// WebIDL WebGLRenderingContext API
void Commit();
void GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& retval);
dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; }
GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; }
GLsizei DrawingBufferHeight() const {
return IsContextLost() ? 0 : mHeight;
@ -1518,6 +1509,8 @@ protected:
ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
#endif
nsRefPtr<WebGLObserver> mContextObserver;
public:
// console logging helpers
void GenerateWarning(const char* fmt, ...);
@ -1622,6 +1615,32 @@ WebGLContext::ValidateObject(const char* info, ObjectType* object)
return ValidateObjectAssumeNonNull(info, object);
}
// Listen visibilitychange and memory-pressure event for context lose/restore
class WebGLObserver final
: public nsIObserver
, public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMEVENTLISTENER
explicit WebGLObserver(WebGLContext* webgl);
void Destroy();
void RegisterVisibilityChangeEvent();
void UnregisterVisibilityChangeEvent();
void RegisterMemoryPressureEvent();
void UnregisterMemoryPressureEvent();
private:
~WebGLObserver();
WebGLContext* mWebGL;
};
size_t RoundUpToMultipleOf(size_t value, size_t multiple);
bool

View File

@ -6,7 +6,6 @@
#include "WebGLContext.h"
#include "WebGLContextUtils.h"
#include "WebGLExtensions.h"
#include "gfxPrefs.h"
#include "GLContext.h"
#include "nsString.h"
@ -75,15 +74,12 @@ bool WebGLContext::IsExtensionSupported(JSContext* cx,
// Chrome contexts need access to debug information even when
// webgl.disable-extensions is set. This is used in the graphics
// section of about:support
if (NS_IsMainThread() &&
xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
// section of about:support.
if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx)))
allowPrivilegedExts = true;
}
if (gfxPrefs::WebGLPrivilegedExtensionsEnabled()) {
if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
allowPrivilegedExts = true;
}
if (allowPrivilegedExts) {
switch (ext) {
@ -185,7 +181,9 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
break;
}
if (gfxPrefs::WebGLDraftExtensionsEnabled() || IsWebGL2()) {
if (Preferences::GetBool("webgl.enable-draft-extensions", false) ||
IsWebGL2())
{
switch (ext) {
case WebGLExtensionID::EXT_disjoint_timer_query:
return WebGLExtensionDisjointTimerQuery::IsSupported(this);

View File

@ -1390,10 +1390,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (IsContextLost())
return;
if (mCanvasElement &&
mCanvasElement->IsWriteOnly() &&
!nsContentUtils::IsCallerChrome())
{
if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerChrome()) {
GenerateWarning("readPixels: Not allowed");
return rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
}

View File

@ -8,103 +8,15 @@
#include "nsITimer.h"
#include "nsThreadUtils.h"
#include "WebGLContext.h"
#include "mozilla/dom/WorkerPrivate.h"
namespace mozilla {
// -------------------------------------------------------------------
// Begin worker specific code
// -------------------------------------------------------------------
// On workers we can only dispatch CancelableRunnables, so we have to wrap the
// timer's EventTarget to use our own cancelable runnable
class ContextLossWorkerEventTarget final : public nsIEventTarget
{
public:
explicit ContextLossWorkerEventTarget(nsIEventTarget* aEventTarget)
: mEventTarget(aEventTarget)
{
MOZ_ASSERT(aEventTarget);
}
NS_DECL_NSIEVENTTARGET
NS_DECL_THREADSAFE_ISUPPORTS
protected:
~ContextLossWorkerEventTarget() {}
private:
nsCOMPtr<nsIEventTarget> mEventTarget;
};
class ContextLossWorkerRunnable final : public nsICancelableRunnable
{
public:
explicit ContextLossWorkerRunnable(nsIRunnable* aRunnable)
: mRunnable(aRunnable)
{
}
NS_DECL_NSICANCELABLERUNNABLE
NS_DECL_THREADSAFE_ISUPPORTS
NS_FORWARD_NSIRUNNABLE(mRunnable->)
protected:
~ContextLossWorkerRunnable() {}
private:
nsCOMPtr<nsIRunnable> mRunnable;
};
NS_IMPL_ISUPPORTS(ContextLossWorkerEventTarget, nsIEventTarget,
nsISupports)
NS_IMETHODIMP
ContextLossWorkerEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> event(aEvent);
return Dispatch(event.forget(), aFlags);
}
NS_IMETHODIMP
ContextLossWorkerEventTarget::Dispatch(already_AddRefed<nsIRunnable>&& aEvent,
uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> eventRef(aEvent);
nsRefPtr<ContextLossWorkerRunnable> wrappedEvent =
new ContextLossWorkerRunnable(eventRef);
return mEventTarget->Dispatch(wrappedEvent, aFlags);
}
NS_IMETHODIMP
ContextLossWorkerEventTarget::IsOnCurrentThread(bool* aResult)
{
return mEventTarget->IsOnCurrentThread(aResult);
}
NS_IMPL_ISUPPORTS(ContextLossWorkerRunnable, nsICancelableRunnable,
nsIRunnable)
NS_IMETHODIMP
ContextLossWorkerRunnable::Cancel()
{
mRunnable = nullptr;
return NS_OK;
}
// -------------------------------------------------------------------
// End worker-specific code
// -------------------------------------------------------------------
WebGLContextLossHandler::WebGLContextLossHandler(WebGLContext* webgl)
: mWeakWebGL(webgl)
, mTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
, mIsTimerRunning(false)
, mShouldRunTimerAgain(false)
, mIsDisabled(false)
, mFeatureAdded(false)
#ifdef DEBUG
, mThread(NS_GetCurrentThread())
#endif
@ -178,17 +90,6 @@ WebGLContextLossHandler::RunTimer()
return;
}
if (!NS_IsMainThread()) {
dom::workers::WorkerPrivate* workerPrivate =
dom::workers::GetCurrentThreadWorkerPrivate();
nsCOMPtr<nsIEventTarget> target = workerPrivate->GetEventTarget();
mTimer->SetTarget(new ContextLossWorkerEventTarget(target));
if (!mFeatureAdded) {
workerPrivate->AddFeature(workerPrivate->GetJSContext(), this);
mFeatureAdded = true;
}
}
StartTimer(1000);
mIsTimerRunning = true;
@ -203,14 +104,6 @@ WebGLContextLossHandler::DisableTimer()
mIsDisabled = true;
if (mFeatureAdded) {
dom::workers::WorkerPrivate* workerPrivate =
dom::workers::GetCurrentThreadWorkerPrivate();
MOZ_RELEASE_ASSERT(workerPrivate);
workerPrivate->RemoveFeature(workerPrivate->GetJSContext(), this);
mFeatureAdded = false;
}
// We can't just Cancel() the timer, as sometimes we end up
// receiving a callback after calling Cancel(). This could cause us
// to receive the callback after object destruction.
@ -223,16 +116,4 @@ WebGLContextLossHandler::DisableTimer()
mTimer->SetDelay(0);
}
bool
WebGLContextLossHandler::Notify(JSContext* aCx, dom::workers::Status aStatus)
{
bool isWorkerRunning = aStatus < dom::workers::Closing;
if (!isWorkerRunning && mIsTimerRunning) {
mIsTimerRunning = false;
this->Release();
}
return true;
}
} // namespace mozilla

View File

@ -10,7 +10,6 @@
#include "mozilla/WeakPtr.h"
#include "nsCOMPtr.h"
#include "nsISupportsImpl.h"
#include "WorkerFeature.h"
class nsIThread;
class nsITimer;
@ -18,14 +17,13 @@ class nsITimer;
namespace mozilla {
class WebGLContext;
class WebGLContextLossHandler : public dom::workers::WorkerFeature
class WebGLContextLossHandler
{
WeakPtr<WebGLContext> mWeakWebGL;
nsCOMPtr<nsITimer> mTimer;
bool mIsTimerRunning;
bool mShouldRunTimerAgain;
bool mIsDisabled;
bool mFeatureAdded;
DebugOnly<nsIThread*> mThread;
public:
@ -35,7 +33,6 @@ public:
void RunTimer();
void DisableTimer();
bool Notify(JSContext* aCx, dom::workers::Status aStatus) override;
protected:
~WebGLContextLossHandler();

View File

@ -9,6 +9,8 @@
namespace mozilla {
NS_IMPL_ISUPPORTS(WebGLObserver, nsIObserver)
NS_IMETHODIMP
WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* handleReport,
nsISupports* data, bool)

View File

@ -8,7 +8,6 @@
#include <algorithm>
#include "angle/ShaderLang.h"
#include "CanvasUtils.h"
#include "gfxPrefs.h"
#include "GLContext.h"
#include "jsfriendapi.h"
#include "mozilla/CheckedInt.h"
@ -1666,11 +1665,11 @@ WebGLContext::InitAndValidateGL()
return false;
}
mMinCapability = gfxPrefs::WebGLMinCapabilityMode();
mDisableExtensions = gfxPrefs::WebGLDisableExtensions();
mLoseContextOnMemoryPressure = gfxPrefs::WebGLLoseContextOnMemoryPressure();
mCanLoseContextInForeground = gfxPrefs::WebGLCanLoseContextInForeground();
mRestoreWhenVisible = gfxPrefs::WebGLRestoreWhenVisible();
mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
mLoseContextOnMemoryPressure = Preferences::GetBool("webgl.lose-context-on-memory-pressure", false);
mCanLoseContextInForeground = Preferences::GetBool("webgl.can-lose-context-in-foreground", true);
mRestoreWhenVisible = Preferences::GetBool("webgl.restore-context-when-visible", true);
if (MinCapabilityMode())
mDisableFragHighP = true;
@ -1879,7 +1878,10 @@ WebGLContext::InitAndValidateGL()
#endif
// Check the shader validator pref
mBypassShaderValidation = gfxPrefs::WebGLBypassShaderValidator();
NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
mBypassShaderValidation = Preferences::GetBool("webgl.bypass-shader-validation",
mBypassShaderValidation);
// initialize shader translator
if (!ShInitialize()) {
@ -1935,6 +1937,9 @@ WebGLContext::InitAndValidateGL()
mDefaultVertexArray->BindVertexArray();
}
if (mLoseContextOnMemoryPressure)
mContextObserver->RegisterMemoryPressureEvent();
return true;
}

View File

@ -16,6 +16,8 @@
namespace mozilla {
NS_IMPL_ISUPPORTS(WebGLObserver, nsIObserver)
NS_IMETHODIMP
WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* handleReport,
nsISupports* data, bool)

View File

@ -6,7 +6,6 @@
#include "WebGLShaderValidator.h"
#include "angle/ShaderLang.h"
#include "gfxPrefs.h"
#include "GLContext.h"
#include "mozilla/Preferences.h"
#include "MurmurHash3.h"
@ -44,7 +43,7 @@ ChooseValidatorCompileOptions(const ShBuiltInResources& resources,
options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
}
if (gfxPrefs::WebGLAllANGLEOptions()) {
if (Preferences::GetBool("webgl.all-angle-options", false)) {
return options |
SH_VALIDATE_LOOP_INDEXING |
SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX |

View File

@ -28,12 +28,10 @@ EXPORTS.mozilla.dom += [
'CanvasPath.h',
'CanvasPattern.h',
'CanvasRenderingContext2D.h',
'CanvasRenderingContextHelper.h',
'CanvasUtils.h',
'ImageBitmap.h',
'ImageBitmapSource.h',
'ImageData.h',
'OffscreenCanvas.h',
'TextMetrics.h',
'WebGLVertexArrayObject.h',
]
@ -42,13 +40,11 @@ EXPORTS.mozilla.dom += [
UNIFIED_SOURCES += [
'CanvasImageCache.cpp',
'CanvasRenderingContext2D.cpp',
'CanvasRenderingContextHelper.cpp',
'CanvasUtils.cpp',
'DocumentRendererChild.cpp',
'DocumentRendererParent.cpp',
'ImageBitmap.cpp',
'ImageData.cpp',
'OffscreenCanvas.cpp',
]
# WebGL Sources
@ -154,7 +150,6 @@ LOCAL_INCLUDES += [
'/dom/base',
'/dom/html',
'/dom/svg',
'/dom/workers',
'/dom/xul',
'/gfx/gl',
'/image',

View File

@ -12,13 +12,12 @@
#include "nsIDocShell.h"
#include "nsRefreshDriver.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/dom/OffscreenCanvas.h"
#include "GraphicsFilter.h"
#include "mozilla/RefPtr.h"
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
{ 0xb84f2fed, 0x9d4b, 0x430b, \
{ 0xbd, 0xfb, 0x85, 0x57, 0x8a, 0xc2, 0xb4, 0x4b } }
{ 0x3cc9e801, 0x1806, 0x4ff6, \
{ 0x86, 0x14, 0xf9, 0xd0, 0xf4, 0xfb, 0x3b, 0x08 } }
class gfxASurface;
class nsDisplayListBuilder;
@ -81,11 +80,6 @@ public:
return mCanvasElement;
}
void SetOffscreenCanvas(mozilla::dom::OffscreenCanvas* aOffscreenCanvas)
{
mOffscreenCanvas = aOffscreenCanvas;
}
#ifdef DEBUG
// Useful for testing
virtual int32_t GetWidth() const = 0;
@ -160,10 +154,6 @@ public:
// Given a point, return hit region ID if it exists or an empty string if it doesn't
virtual nsString GetHitRegion(const mozilla::gfx::Point& point) { return nsString(); }
virtual void OnVisibilityChange() {}
virtual void OnMemoryPressure() {}
//
// shmem support
//
@ -176,7 +166,6 @@ public:
protected:
nsRefPtr<mozilla::dom::HTMLCanvasElement> mCanvasElement;
nsRefPtr<mozilla::dom::OffscreenCanvas> mOffscreenCanvas;
nsRefPtr<nsRefreshDriver> mRefreshDriver;
};

View File

@ -27,10 +27,6 @@ support-files =
imagebitmap_on_worker.js
imagebitmap_structuredclone.js
imagebitmap_structuredclone_iframe.html
offscreencanvas.js
offscreencanvas_mask.svg
offscreencanvas_neuter.js
offscreencanvas_serviceworker_inner.html
[test_2d.clearRect.image.offscreen.html]
[test_2d.clip.winding.html]
@ -265,22 +261,3 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
[test_createPattern_broken.html]
[test_setlinedash.html]
[test_filter.html]
[test_offscreencanvas_basic_webgl.html]
tags = offscreencanvas
[test_offscreencanvas_dynamic_fallback.html]
tags = offscreencanvas
[test_offscreencanvas_sharedworker.html]
tags = offscreencanvas
[test_offscreencanvas_serviceworker.html]
tags = offscreencanvas
skip-if = buildapp == 'b2g'
[test_offscreencanvas_neuter.html]
tags = offscreencanvas
[test_offscreencanvas_many.html]
tags = offscreencanvas
skip-if = (toolkit == 'android' || toolkit == 'gonk' || toolkit == 'windows' || toolkit == 'gtk2' || toolkit == 'gtk3')
[test_offscreencanvas_sizechange.html]
tags = offscreencanvas
[test_offscreencanvas_subworker.html]
tags = offscreencanvas
skip-if = (toolkit == 'android' || toolkit == 'gonk' || toolkit == 'windows' || toolkit == 'gtk2' || toolkit == 'gtk3')

View File

@ -1,299 +0,0 @@
/* WebWorker for test_offscreencanvas_*.html */
var port = null;
function ok(expect, msg) {
if (port) {
port.postMessage({type: "test", result: !!expect, name: msg});
} else {
postMessage({type: "test", result: !!expect, name: msg});
}
}
function finish() {
if (port) {
port.postMessage({type: "finish"});
} else {
postMessage({type: "finish"});
}
}
function drawCount(count) {
if (port) {
port.postMessage({type: "draw", count: count});
} else {
postMessage({type: "draw", count: count});
}
}
//--------------------------------------------------------------------
// WebGL Drawing Functions
//--------------------------------------------------------------------
function createDrawFunc(canvas) {
var gl;
try {
gl = canvas.getContext("experimental-webgl");
} catch (e) {}
if (!gl) {
ok(false, "WebGL is unavailable");
return null;
}
var vertSrc = "attribute vec2 position; \
void main(void) { \
gl_Position = vec4(position, 0.0, 1.0); \
}";
var fragSrc = "precision mediump float; \
void main(void) { \
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); \
}";
// Returns a valid shader, or null on errors.
var createShader = function(src, t) {
var shader = gl.createShader(t);
gl.shaderSource(shader, src);
gl.compileShader(shader);
return shader;
};
var createProgram = function(vsSrc, fsSrc) {
var vs = createShader(vsSrc, gl.VERTEX_SHADER);
var fs = createShader(fsSrc, gl.FRAGMENT_SHADER);
var prog = gl.createProgram();
gl.attachShader(prog, vs);
gl.attachShader(prog, fs);
gl.linkProgram(prog);
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
var str = "Shader program linking failed:";
str += "\nShader program info log:\n" + gl.getProgramInfoLog(prog);
str += "\n\nVert shader log:\n" + gl.getShaderInfoLog(vs);
str += "\n\nFrag shader log:\n" + gl.getShaderInfoLog(fs);
console.log(str);
ok(false, "Shader program linking failed");
return null;
}
return prog;
};
gl.disable(gl.DEPTH_TEST);
var program = createProgram(vertSrc, fragSrc);
ok(program, "Creating shader program");
program.positionAttr = gl.getAttribLocation(program, "position");
ok(program.positionAttr >= 0, "position attribute should be valid");
var vertCoordArr = new Float32Array([
-1, -1,
1, -1,
-1, 1,
1, 1,
]);
var vertCoordBuff = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertCoordBuff);
gl.bufferData(gl.ARRAY_BUFFER, vertCoordArr, gl.STATIC_DRAW);
var checkGLError = function(prefix, refValue) {
if (!refValue) {
refValue = 0;
}
var error = gl.getError();
ok(error == refValue,
prefix + 'gl.getError should be 0x' + refValue.toString(16) +
', was 0x' + error.toString(16) + '.');
};
var testPixel = function(x, y, refData, infoString) {
var pixel = new Uint8Array(4);
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
var pixelMatches = pixel[0] == refData[0] &&
pixel[1] == refData[1] &&
pixel[2] == refData[2] &&
pixel[3] == refData[3];
ok(pixelMatches, infoString);
};
var preDraw = function(prefix) {
gl.clearColor(1.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
testPixel(0, 0, [255, 0, 0, 255], prefix + 'Should be red before drawing.');
};
var postDraw = function(prefix) {
testPixel(0, 0, [0, 255, 0, 255], prefix + 'Should be green after drawing.');
};
gl.useProgram(program);
gl.enableVertexAttribArray(program.position);
gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
// Start drawing
checkGLError('after setup');
return function(prefix) {
if (prefix) {
prefix = "[" + prefix + "] ";
} else {
prefix = "";
}
gl.viewport(0, 0, canvas.width, canvas.height);
preDraw(prefix);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
postDraw(prefix);
gl.commit();
checkGLError(prefix);
};
}
/* entry point */
function entryFunction(testStr, subtests, offscreenCanvas) {
var test = testStr;
var canvas = offscreenCanvas;
if (test != "subworker") {
ok(canvas, "Canvas successfully transfered to worker");
ok(canvas.getContext, "Canvas has getContext");
ok(canvas.width == 64, "OffscreenCanvas width should be 64");
ok(canvas.height == 64, "OffscreenCanvas height should be 64");
}
var draw;
//------------------------------------------------------------------------
// Basic WebGL test
//------------------------------------------------------------------------
if (test == "webgl") {
draw = createDrawFunc(canvas);
if (!draw) {
finish();
return;
}
var count = 0;
var iid = setInterval(function() {
if (count++ > 20) {
clearInterval(iid);
ok(true, "Worker is done");
finish();
return;
}
draw("loop " +count);
}, 0);
}
//------------------------------------------------------------------------
// Test dynamic fallback
//------------------------------------------------------------------------
else if (test == "webgl_fallback") {
draw = createDrawFunc(canvas);
if (!draw) {
return;
}
var count = 0;
var iid = setInterval(function() {
++count;
draw("loop " + count);
drawCount(count);
}, 0);
}
//------------------------------------------------------------------------
// Canvas Size Change from Worker
//------------------------------------------------------------------------
else if (test == "webgl_changesize") {
draw = createDrawFunc(canvas);
if (!draw) {
finish();
return;
}
draw("64x64");
setTimeout(function() {
canvas.width = 128;
canvas.height = 128;
draw("Increased to 128x128");
setTimeout(function() {
canvas.width = 32;
canvas.width = 32;
draw("Decreased to 32x32");
setTimeout(function() {
canvas.width = 64;
canvas.height = 64;
draw("Increased to 64x64");
ok(true, "Worker is done");
finish();
}, 0);
}, 0);
}, 0);
}
//------------------------------------------------------------------------
// Using OffscreenCanvas from sub workers
//------------------------------------------------------------------------
else if (test == "subworker") {
/* subworker tests take a list of tests to run on children */
var stillRunning = 0;
subtests.forEach(function (subtest) {
++stillRunning;
var subworker = new Worker('offscreencanvas.js');
subworker.onmessage = function(evt) {
/* report finish to parent when all children are finished */
if (evt.data.type == "finish") {
subworker.terminate();
if (--stillRunning == 0) {
ok(true, "Worker is done");
finish();
}
return;
}
/* relay all other messages to parent */
postMessage(evt.data);
};
var findTransferables = function(t) {
if (t.test == "subworker") {
var result = [];
t.subtests.forEach(function(test) {
result = result.concat(findTransferables(test));
});
return result;
} else {
return [t.canvas];
}
};
subworker.postMessage(subtest, findTransferables(subtest));
});
}
};
onmessage = function(evt) {
port = evt.ports[0];
entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
};
onconnect = function(evt) {
port = evt.ports[0];
port.addEventListener('message', function(evt) {
entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
});
port.start();
};

View File

@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<mask id="fade_mask_both" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<linearGradient id="fade_gradient_both" gradientUnits="objectBoundingBox" x2="0" y2="1">
<stop stop-color="white" stop-opacity="0" offset="0"></stop>
<stop stop-color="white" stop-opacity="1" offset="0.2"></stop>
<stop stop-color="white" stop-opacity="1" offset="0.8"></stop>
<stop stop-color="white" stop-opacity="0" offset="1"></stop>
</linearGradient>
<rect x="0" y="0" width="1" height="1" fill="url(#fade_gradient_both)"></rect>
</mask>
</svg>

Before

Width:  |  Height:  |  Size: 638 B

View File

@ -1 +0,0 @@
/* empty worker for test_offscreencanvas_disable.html */

View File

@ -1,32 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<script>
function ok(expect, msg) {
parent.postMessage({type: "test", result: !!expect, name: msg}, "*");
}
var htmlCanvas = document.getElementById("c");
ok(htmlCanvas, "Should have HTML canvas element");
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(evt) {
parent.postMessage(evt.data, "*");
}
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
navigator.serviceWorker.ready.then(function() {
navigator.serviceWorker.controller.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas, messageChannel.port2]);
});
</script>
</body>
</html>

View File

@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<canvas id="c-ref" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function testToDataURL() {
// testing toDataURL
// Fill c-ref with green color.
var c = document.getElementById("c-ref");
var ctx = c.getContext("2d");
ctx.rect(0, 0, 64, 64);
ctx.fillStyle = "#00FF00";
ctx.fill();
var htmlCanvas = document.getElementById("c");
ok(c.toDataURL() == htmlCanvas.toDataURL(), "toDataURL should return a 64x64 green square");
}
function runTest() {
var htmlCanvas = document.getElementById("c");
var worker = new Worker("offscreencanvas.js");
ok(htmlCanvas, "Should have HTML canvas element");
ok(worker, "Web worker successfully created");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "finish") {
testToDataURL();
worker.terminate();
SimpleTest.finish();
}
}
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
worker.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
</script>
</body>
</html>

View File

@ -1,80 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
SimpleTest.waitForExplicitFinish();
function createCanvas(initWithMask) {
var canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;
document.body.appendChild(canvas);
if (initWithMask) {
canvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
}
return canvas;
}
function getRefSnapshot(initWithMask) {
var refCanvas = createCanvas(!initWithMask);
var ctx = refCanvas.getContext("2d");
ctx.rect(0, 0, 64, 64);
ctx.fillStyle = "#00FF00";
ctx.fill();
var result = snapshotWindow(window);
document.body.removeChild(refCanvas);
return result;
}
function runTest(initWithMask) {
var htmlCanvas = createCanvas(initWithMask);
var worker = new Worker("offscreencanvas.js");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "draw") {
if (msg.count === 10) {
// Change the fallback state dynamically when drawing count reaches 10.
if (initWithMask) {
htmlCanvas.style.mask = "";
} else {
htmlCanvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
}
} else if (msg.count === 20) {
var snapshotFallback = snapshotWindow(window);
worker.terminate();
document.body.removeChild(htmlCanvas);
var results = compareSnapshots(snapshotFallback, getRefSnapshot(initWithMask), true);
ok(results[0], "after dynamic fallback, screenshots should be the same");
if (initWithMask) {
SimpleTest.finish();
} else {
runTest(true);
}
}
}
}
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
worker.postMessage({test: 'webgl_fallback', canvas: offscreenCanvas}, [offscreenCanvas]);
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest.bind(false));
</script>
</body>
</html>

View File

@ -1,67 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<!--
This test needs several workers run offscreen canvas simultaneously.
So we choose 8 workers, 4 of them run basic webgl drawing test and
others run size changing test.
-->
<script>
SimpleTest.waitForExplicitFinish();
function createCanvas() {
var htmlCanvas = document.createElement('canvas');
htmlCanvas.width = 64;
htmlCanvas.height = 64;
document.body.appendChild(htmlCanvas);
return htmlCanvas;
}
function runTest() {
var stillRunning = 0;
var startWorker = function(canvas, test) {
stillRunning++;
var worker = new Worker("offscreencanvas.js");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "finish") {
worker.terminate();
if (--stillRunning == 0)
SimpleTest.finish();
}
}
var offscreenCanvas = canvas.transferControlToOffscreen();
worker.postMessage({test: test, canvas: offscreenCanvas}, [offscreenCanvas]);
}
/* create 4 workers that do the regular drawing test and 4 workers
that do the size change test */
for (var i = 0; i < 4; i++) {
startWorker(createCanvas(), 'webgl');
}
for (var i = 0; i < 4; i++) {
startWorker(createCanvas(), 'webgl_changesize');
}
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true]
]}, runTest);
</script>
</body>
</html>

View File

@ -1,78 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>OffscreenCanvas: Test neutering</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function runTest() {
var htmlCanvas = document.getElementById("c");
var worker = new Worker("offscreencanvas_neuter.js");
ok(htmlCanvas, "Should have HTML canvas element");
ok(worker, "Web worker successfully created");
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
/* check html canvas is neuterd */
is(htmlCanvas.width, 64, "HTML canvas has correct width");
SimpleTest.doesThrow(
function() { htmlCanvas.width = 128; },
"Can't change html canvas' width after transferControlToOffscreen");
SimpleTest.doesThrow(
function() { htmlCanvas.height = 128; },
"Can't change html canvas' height after transferControlToOffscreen");
ok(!htmlCanvas.getContext("2d"), "Can't getContext after transferControlToOffscreen");
ok(!htmlCanvas.getContext("webgl"), "Can't getContext after transferControlToOffscreen");
ok(!htmlCanvas.getContext("webgl2"), "Can't getContext after transferControlToOffscreen");
worker.postMessage(offscreenCanvas, [offscreenCanvas]);
/* check parent offscreencanvas is neutered after being transfered */
SimpleTest.doesThrow(
function() { offscreenCanvas.width = 128; },
"Can't change transfered worker canvas width");
SimpleTest.doesThrow(
function() { offscreenCanvas.height = 128; },
"Can't change transfered worker canvas height");
SimpleTest.doesThrow(
function() { offscreenCanvas.getContext("2d") },
"Can't getContext on transfered worker canvas");
SimpleTest.doesThrow(
function() { offscreenCanvas.getContext("webgl") },
"Can't getContext on transfered worker canvas");
SimpleTest.doesThrow(
function() { offscreenCanvas.getContext("webgl2") },
"Can't getContext on transfered worker canvas");
// Transfer a neutered offscreencanvas should be ok.
worker.postMessage(offscreenCanvas, [offscreenCanvas]);
worker.terminate();
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
</script>
</body>
</html>

View File

@ -1,46 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
SimpleTest.waitForExplicitFinish();
function runTest() {
window.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "finish") {
SimpleTest.finish();
}
}
navigator.serviceWorker.register('offscreencanvas.js', { scope: "."})
// Wait until the service worker is active.
.then(navigator.serviceWorker.ready)
// ...and then show the interface for the commands once it's ready.
.then(function() {
iframe = document.createElement("iframe");
iframe.setAttribute('src', "offscreencanvas_serviceworker_inner.html");
document.body.appendChild(iframe);
})
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.interception.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
</script>
</body>
</html>

View File

@ -1,47 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function runTest() {
var htmlCanvas = document.getElementById("c");
var worker = new SharedWorker("offscreencanvas.js");
ok(htmlCanvas, "Should have HTML canvas element");
ok(worker, "Web worker successfully created");
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
worker.port.start();
// We don't support transferring OffscreenCanvas via shared worker.
SimpleTest.doesThrow(
function() {
worker.port.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
},
"OffscreenCanvas cannot transfer to shared worker"
);
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
</script>
</body>
</html>

View File

@ -1,41 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function runTest() {
var htmlCanvas = document.getElementById("c");
var worker = new Worker("offscreencanvas.js");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "finish") {
worker.terminate();
SimpleTest.finish();
}
}
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
worker.postMessage({test: 'webgl_changesize', canvas: offscreenCanvas}, [offscreenCanvas]);
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
</script>
</body>
</html>

View File

@ -1,90 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>OffscreenCanvas: Test subworkers</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<!--
We want to test offscreen canvas works well when it running on worker
and nested worker simultaneously. So we create 10 canvas and dispatch
it to different workers and sub-workers.
-->
<script>
SimpleTest.waitForExplicitFinish();
function createCanvas() {
var htmlCanvas = document.createElement('canvas');
htmlCanvas.width = 64;
htmlCanvas.height = 64;
document.body.appendChild(htmlCanvas);
return htmlCanvas.transferControlToOffscreen();
}
function runTest() {
var worker = new Worker("offscreencanvas.js");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "finish") {
worker.terminate();
SimpleTest.finish();
}
}
var findTransferables = function(t) {
if (t.test == "subworker") {
var result = [];
t.subtests.forEach(function(test) {
result = result.concat(findTransferables(test));
});
return result;
} else {
return [t.canvas];
}
};
var testData =
{test: 'subworker', subtests: [
{test: 'webgl', canvas: createCanvas()},
{test: 'subworker', subtests: [
{test: 'webgl', canvas: createCanvas()},
{test: 'webgl_changesize', canvas: createCanvas()},
{test: 'webgl', canvas: createCanvas()}
]},
{test: 'subworker', subtests: [
{test: 'webgl', canvas: createCanvas()},
{test: 'webgl_changesize', canvas: createCanvas()},
{test: 'subworker', subtests: [
{test: 'webgl_changesize', canvas: createCanvas()},
{test: 'webgl', canvas: createCanvas()}
]},
{test: 'subworker', subtests: [
{test: 'webgl_changesize', canvas: createCanvas()},
{test: 'subworker', subtests: [
{test: 'subworker', subtests: [
{test: 'webgl_changesize', canvas: createCanvas()}
]}
]}
]},
]}
]};
worker.postMessage(testData, findTransferables(testData));
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
</script>
</body>
</html>

View File

@ -19,10 +19,8 @@
#include "mozilla/dom/File.h"
#include "mozilla/dom/HTMLCanvasElementBinding.h"
#include "mozilla/dom/MouseEvent.h"
#include "mozilla/dom/OffscreenCanvas.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
@ -241,135 +239,18 @@ HTMLCanvasPrintState::NotifyDone()
// ---------------------------------------------------------------------------
HTMLCanvasElementObserver::HTMLCanvasElementObserver(HTMLCanvasElement* aElement)
: mElement(aElement)
{
RegisterVisibilityChangeEvent();
RegisterMemoryPressureEvent();
}
HTMLCanvasElementObserver::~HTMLCanvasElementObserver()
{
Destroy();
}
void
HTMLCanvasElementObserver::Destroy()
{
UnregisterMemoryPressureEvent();
UnregisterVisibilityChangeEvent();
mElement = nullptr;
}
void
HTMLCanvasElementObserver::RegisterVisibilityChangeEvent()
{
if (!mElement) {
return;
}
nsIDocument* document = mElement->OwnerDoc();
document->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
this, true, false);
}
void
HTMLCanvasElementObserver::UnregisterVisibilityChangeEvent()
{
if (!mElement) {
return;
}
nsIDocument* document = mElement->OwnerDoc();
document->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
this, true);
}
void
HTMLCanvasElementObserver::RegisterMemoryPressureEvent()
{
if (!mElement) {
return;
}
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
MOZ_ASSERT(observerService);
if (observerService)
observerService->AddObserver(this, "memory-pressure", false);
}
void
HTMLCanvasElementObserver::UnregisterMemoryPressureEvent()
{
if (!mElement) {
return;
}
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
// Do not assert on observerService here. This might be triggered by
// the cycle collector at a late enough time, that XPCOM services are
// no longer available. See bug 1029504.
if (observerService)
observerService->RemoveObserver(this, "memory-pressure");
}
NS_IMETHODIMP
HTMLCanvasElementObserver::Observe(nsISupports*, const char* aTopic, const char16_t*)
{
if (!mElement || strcmp(aTopic, "memory-pressure")) {
return NS_OK;
}
mElement->OnMemoryPressure();
return NS_OK;
}
NS_IMETHODIMP
HTMLCanvasElementObserver::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString type;
aEvent->GetType(type);
if (!mElement || !type.EqualsLiteral("visibilitychange")) {
return NS_OK;
}
mElement->OnVisibilityChange();
return NS_OK;
}
NS_IMPL_ISUPPORTS(HTMLCanvasElementObserver, nsIObserver)
// ---------------------------------------------------------------------------
HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mResetLayer(true) ,
mWriteOnly(false)
{
}
HTMLCanvasElement::~HTMLCanvasElement()
{
if (mContextObserver) {
mContextObserver->Destroy();
mContextObserver = nullptr;
}
ResetPrintCallback();
if (mRequestedFrameRefreshObserver) {
mRequestedFrameRefreshObserver->DetachFromRefreshDriver();
}
if (mAsyncCanvasRenderer) {
mAsyncCanvasRenderer->mHTMLCanvasElement = nullptr;
}
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLCanvasElement, nsGenericHTMLElement,
@ -391,22 +272,6 @@ HTMLCanvasElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return HTMLCanvasElementBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<nsICanvasRenderingContextInternal>
HTMLCanvasElement::CreateContext(CanvasContextType aContextType)
{
nsRefPtr<nsICanvasRenderingContextInternal> ret =
CanvasRenderingContextHelper::CreateContext(aContextType);
// Add Observer for webgl canvas.
if (aContextType == CanvasContextType::WebGL1 ||
aContextType == CanvasContextType::WebGL2) {
mContextObserver = new HTMLCanvasElementObserver(this);
}
ret->SetCanvasElement(this);
return ret.forget();
}
nsIntSize
HTMLCanvasElement::GetWidthHeight()
{
@ -691,10 +556,51 @@ HTMLCanvasElement::ExtractData(nsAString& aType,
aOptions,
GetSize(),
mCurrentContext,
mAsyncCanvasRenderer,
aStream);
}
nsresult
HTMLCanvasElement::ParseParams(JSContext* aCx,
const nsAString& aType,
const JS::Value& aEncoderOptions,
nsAString& aParams,
bool* usingCustomParseOptions)
{
// Quality parameter is only valid for the image/jpeg MIME type
if (aType.EqualsLiteral("image/jpeg")) {
if (aEncoderOptions.isNumber()) {
double quality = aEncoderOptions.toNumber();
// Quality must be between 0.0 and 1.0, inclusive
if (quality >= 0.0 && quality <= 1.0) {
aParams.AppendLiteral("quality=");
aParams.AppendInt(NS_lround(quality * 100.0));
}
}
}
// If we haven't parsed the aParams check for proprietary options.
// The proprietary option -moz-parse-options will take a image lib encoder
// parse options string as is and pass it to the encoder.
*usingCustomParseOptions = false;
if (aParams.Length() == 0 && aEncoderOptions.isString()) {
NS_NAMED_LITERAL_STRING(mozParseOptions, "-moz-parse-options:");
nsAutoJSString paramString;
if (!paramString.init(aCx, aEncoderOptions.toString())) {
return NS_ERROR_FAILURE;
}
if (StringBeginsWith(paramString, mozParseOptions)) {
nsDependentSubstring parseOptions = Substring(paramString,
mozParseOptions.Length(),
paramString.Length() -
mozParseOptions.Length());
aParams.Append(parseOptions);
*usingCustomParseOptions = true;
}
}
return NS_OK;
}
nsresult
HTMLCanvasElement::ToDataURLImpl(JSContext* aCx,
const nsAString& aMimeType,
@ -753,38 +659,83 @@ HTMLCanvasElement::ToBlob(JSContext* aCx,
return;
}
nsAutoString type;
nsContentUtils::ASCIIToLower(aType, type);
nsAutoString params;
bool usingCustomParseOptions;
aRv = ParseParams(aCx, type, aParams, params, &usingCustomParseOptions);
if (aRv.Failed()) {
return;
}
#ifdef DEBUG
if (mCurrentContext) {
// We disallow canvases of width or height zero, and set them to 1, so
// we will have a discrepancy with the sizes of the canvas and the context.
// That discrepancy is OK, the rest are not.
nsIntSize elementSize = GetWidthHeight();
MOZ_ASSERT(elementSize.width == mCurrentContext->GetWidth() ||
(elementSize.width == 0 && mCurrentContext->GetWidth() == 1));
MOZ_ASSERT(elementSize.height == mCurrentContext->GetHeight() ||
(elementSize.height == 0 && mCurrentContext->GetHeight() == 1));
}
#endif
uint8_t* imageBuffer = nullptr;
int32_t format = 0;
if (mCurrentContext) {
mCurrentContext->GetImageBuffer(&imageBuffer, &format);
}
// Encoder callback when encoding is complete.
class EncodeCallback : public EncodeCompleteCallback
{
public:
EncodeCallback(nsIGlobalObject* aGlobal, FileCallback* aCallback)
: mGlobal(aGlobal)
, mFileCallback(aCallback) {}
// This is called on main thread.
nsresult ReceiveBlob(already_AddRefed<Blob> aBlob)
{
nsRefPtr<Blob> blob = aBlob;
ErrorResult rv;
uint64_t size = blob->GetSize(rv);
if (rv.Failed()) {
rv.SuppressException();
} else {
AutoJSAPI jsapi;
if (jsapi.Init(mGlobal)) {
JS_updateMallocCounter(jsapi.cx(), size);
}
}
nsRefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
mFileCallback->Call(*newBlob, rv);
mGlobal = nullptr;
mFileCallback = nullptr;
return rv.StealNSResult();
}
nsCOMPtr<nsIGlobalObject> mGlobal;
nsRefPtr<FileCallback> mFileCallback;
};
nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
MOZ_ASSERT(global);
CanvasRenderingContextHelper::ToBlob(aCx, global, aCallback, aType,
aParams, aRv);
}
OffscreenCanvas*
HTMLCanvasElement::TransferControlToOffscreen(ErrorResult& aRv)
{
if (mCurrentContext) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
if (!mOffscreenCanvas) {
nsIntSize sz = GetWidthHeight();
nsRefPtr<AsyncCanvasRenderer> renderer = GetAsyncCanvasRenderer();
renderer->SetWidth(sz.width);
renderer->SetHeight(sz.height);
mOffscreenCanvas = new OffscreenCanvas(sz.width,
sz.height,
GetCompositorBackendType(),
renderer);
mContextObserver = new HTMLCanvasElementObserver(this);
} else {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
}
return mOffscreenCanvas;
nsRefPtr<EncodeCompleteCallback> callback = new EncodeCallback(global, &aCallback);
aRv = ImageEncoder::ExtractDataAsync(type,
params,
usingCustomParseOptions,
imageBuffer,
format,
GetSize(),
callback);
}
already_AddRefed<File>
@ -855,6 +806,76 @@ HTMLCanvasElement::MozGetAsBlobImpl(const nsAString& aName,
return NS_OK;
}
static bool
GetCanvasContextType(const nsAString& str, CanvasContextType* const out_type)
{
if (str.EqualsLiteral("2d")) {
*out_type = CanvasContextType::Canvas2D;
return true;
}
if (str.EqualsLiteral("experimental-webgl")) {
*out_type = CanvasContextType::WebGL1;
return true;
}
#ifdef MOZ_WEBGL_CONFORMANT
if (str.EqualsLiteral("webgl")) {
/* WebGL 1.0, $2.1 "Context Creation":
* If the user agent supports both the webgl and experimental-webgl
* canvas context types, they shall be treated as aliases.
*/
*out_type = CanvasContextType::WebGL1;
return true;
}
#endif
if (WebGL2Context::IsSupported()) {
if (str.EqualsLiteral("webgl2")) {
*out_type = CanvasContextType::WebGL2;
return true;
}
}
return false;
}
static already_AddRefed<nsICanvasRenderingContextInternal>
CreateContextForCanvas(CanvasContextType contextType, HTMLCanvasElement* canvas)
{
MOZ_ASSERT(contextType != CanvasContextType::NoContext);
nsRefPtr<nsICanvasRenderingContextInternal> ret;
switch (contextType) {
case CanvasContextType::NoContext:
break;
case CanvasContextType::Canvas2D:
Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
ret = new CanvasRenderingContext2D();
break;
case CanvasContextType::WebGL1:
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL1Context::Create();
if (!ret)
return nullptr;
break;
case CanvasContextType::WebGL2:
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL2Context::Create();
if (!ret)
return nullptr;
break;
}
MOZ_ASSERT(ret);
ret->SetCanvasElement(canvas);
return ret.forget();
}
nsresult
HTMLCanvasElement::GetContext(const nsAString& aContextId,
nsISupports** aContext)
@ -868,14 +889,45 @@ already_AddRefed<nsISupports>
HTMLCanvasElement::GetContext(JSContext* aCx,
const nsAString& aContextId,
JS::Handle<JS::Value> aContextOptions,
ErrorResult& aRv)
ErrorResult& rv)
{
if (mOffscreenCanvas) {
CanvasContextType contextType;
if (!GetCanvasContextType(aContextId, &contextType))
return nullptr;
if (!mCurrentContext) {
// This canvas doesn't have a context yet.
nsRefPtr<nsICanvasRenderingContextInternal> context;
context = CreateContextForCanvas(contextType, this);
if (!context)
return nullptr;
// Ensure that the context participates in CC. Note that returning a
// CC participant from QI doesn't addref.
nsXPCOMCycleCollectionParticipant* cp = nullptr;
CallQueryInterface(context, &cp);
if (!cp) {
rv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
mCurrentContext = context.forget();
mCurrentContextType = contextType;
rv = UpdateContext(aCx, aContextOptions);
if (rv.Failed()) {
rv = NS_OK; // See bug 645792
return nullptr;
}
} else {
// We already have a context of some type.
if (contextType != mCurrentContextType)
return nullptr;
}
return CanvasRenderingContextHelper::GetContext(aCx, aContextId,
aContextOptions, aRv);
nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext;
return context.forget();
}
NS_IMETHODIMP
@ -897,7 +949,7 @@ HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId,
// This canvas doesn't have a context yet.
nsRefPtr<nsICanvasRenderingContextInternal> context;
context = CreateContext(contextType);
context = CreateContextForCanvas(contextType, this);
if (!context) {
*aContext = nullptr;
return NS_OK;
@ -919,6 +971,36 @@ HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId,
return NS_OK;
}
nsresult
HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewContextOptions)
{
if (!mCurrentContext)
return NS_OK;
nsIntSize sz = GetWidthHeight();
nsCOMPtr<nsICanvasRenderingContextInternal> currentContext = mCurrentContext;
nsresult rv = currentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
rv = currentContext->SetContextOptions(aCx, aNewContextOptions);
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
rv = currentContext->SetDimensions(sz.width, sz.height);
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
return rv;
}
nsIntSize
HTMLCanvasElement::GetSize()
@ -1022,12 +1104,6 @@ HTMLCanvasElement::GetIsOpaque()
return mCurrentContext->GetIsOpaque();
}
return GetOpaqueAttr();
}
bool
HTMLCanvasElement::GetOpaqueAttr()
{
return HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque);
}
@ -1036,57 +1112,16 @@ HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager)
{
// The address of sOffscreenCanvasLayerUserDataDummy is used as the user
// data key for retained LayerManagers managed by FrameLayerBuilder.
// We don't much care about what value in it, so just assign a dummy
// value for it.
static uint8_t sOffscreenCanvasLayerUserDataDummy = 0;
if (!mCurrentContext)
return nullptr;
if (mCurrentContext) {
return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
}
if (mOffscreenCanvas) {
if (!mResetLayer &&
aOldLayer && aOldLayer->HasUserData(&sOffscreenCanvasLayerUserDataDummy)) {
nsRefPtr<CanvasLayer> ret = aOldLayer;
return ret.forget();
}
nsRefPtr<CanvasLayer> layer = aManager->CreateCanvasLayer();
if (!layer) {
NS_WARNING("CreateCanvasLayer failed!");
return nullptr;
}
LayerUserData* userData = nullptr;
layer->SetUserData(&sOffscreenCanvasLayerUserDataDummy, userData);
CanvasLayer::Data data;
data.mRenderer = GetAsyncCanvasRenderer();
data.mSize = GetWidthHeight();
layer->Initialize(data);
layer->Updated();
return layer.forget();
}
return nullptr;
return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
}
bool
HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager* aManager)
HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager *aManager)
{
if (mCurrentContext) {
return mCurrentContext->ShouldForceInactiveLayer(aManager);
}
if (mOffscreenCanvas) {
// TODO: We should handle offscreen canvas case.
return false;
}
return true;
return !mCurrentContext || mCurrentContext->ShouldForceInactiveLayer(aManager);
}
void
@ -1201,155 +1236,5 @@ HTMLCanvasElement::GetSurfaceSnapshot(bool* aPremultAlpha)
return mCurrentContext->GetSurfaceSnapshot(aPremultAlpha);
}
AsyncCanvasRenderer*
HTMLCanvasElement::GetAsyncCanvasRenderer()
{
if (!mAsyncCanvasRenderer) {
mAsyncCanvasRenderer = new AsyncCanvasRenderer();
mAsyncCanvasRenderer->mHTMLCanvasElement = this;
}
return mAsyncCanvasRenderer;
}
layers::LayersBackend
HTMLCanvasElement::GetCompositorBackendType() const
{
nsIWidget* docWidget = nsContentUtils::WidgetForDocument(OwnerDoc());
if (docWidget) {
layers::LayerManager* layerManager = docWidget->GetLayerManager();
return layerManager->GetCompositorBackendType();
}
return LayersBackend::LAYERS_NONE;
}
void
HTMLCanvasElement::OnVisibilityChange()
{
if (OwnerDoc()->Hidden()) {
return;
}
if (mOffscreenCanvas) {
class Runnable final : public nsCancelableRunnable
{
public:
explicit Runnable(AsyncCanvasRenderer* aRenderer)
: mRenderer(aRenderer)
{}
NS_IMETHOD Run()
{
if (mRenderer && mRenderer->mContext) {
mRenderer->mContext->OnVisibilityChange();
}
return NS_OK;
}
void Revoke()
{
mRenderer = nullptr;
}
private:
nsRefPtr<AsyncCanvasRenderer> mRenderer;
};
nsRefPtr<nsIRunnable> runnable = new Runnable(mAsyncCanvasRenderer);
nsCOMPtr<nsIThread> activeThread = mAsyncCanvasRenderer->GetActiveThread();
if (activeThread) {
activeThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
}
return;
}
if (mCurrentContext) {
mCurrentContext->OnVisibilityChange();
}
}
void
HTMLCanvasElement::OnMemoryPressure()
{
if (mOffscreenCanvas) {
class Runnable final : public nsCancelableRunnable
{
public:
explicit Runnable(AsyncCanvasRenderer* aRenderer)
: mRenderer(aRenderer)
{}
NS_IMETHOD Run()
{
if (mRenderer && mRenderer->mContext) {
mRenderer->mContext->OnMemoryPressure();
}
return NS_OK;
}
void Revoke()
{
mRenderer = nullptr;
}
private:
nsRefPtr<AsyncCanvasRenderer> mRenderer;
};
nsRefPtr<nsIRunnable> runnable = new Runnable(mAsyncCanvasRenderer);
nsCOMPtr<nsIThread> activeThread = mAsyncCanvasRenderer->GetActiveThread();
if (activeThread) {
activeThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
}
return;
}
if (mCurrentContext) {
mCurrentContext->OnMemoryPressure();
}
}
/* static */ void
HTMLCanvasElement::SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer)
{
HTMLCanvasElement *element = aRenderer->mHTMLCanvasElement;
if (!element) {
return;
}
if (element->GetWidthHeight() == aRenderer->GetSize()) {
return;
}
gfx::IntSize asyncCanvasSize = aRenderer->GetSize();
ErrorResult rv;
element->SetUnsignedIntAttr(nsGkAtoms::width, asyncCanvasSize.width, rv);
if (rv.Failed()) {
NS_WARNING("Failed to set width attribute to a canvas element asynchronously.");
}
element->SetUnsignedIntAttr(nsGkAtoms::height, asyncCanvasSize.height, rv);
if (rv.Failed()) {
NS_WARNING("Failed to set height attribute to a canvas element asynchronously.");
}
element->mResetLayer = true;
}
/* static */ void
HTMLCanvasElement::InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer)
{
HTMLCanvasElement *element = aRenderer->mHTMLCanvasElement;
if (!element) {
return;
}
element->InvalidateCanvasContent(nullptr);
}
} // namespace dom
} // namespace mozilla

View File

@ -8,27 +8,20 @@
#include "mozilla/Attributes.h"
#include "mozilla/WeakPtr.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMHTMLCanvasElement.h"
#include "nsIObserver.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsSize.h"
#include "nsError.h"
#include "mozilla/dom/CanvasRenderingContextHelper.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/layers/LayersTypes.h"
class nsICanvasRenderingContextInternal;
class nsITimerCallback;
namespace mozilla {
class WebGLContext;
namespace layers {
class AsyncCanvasRenderer;
class CanvasLayer;
class Image;
class LayerManager;
@ -42,33 +35,14 @@ class CanvasCaptureMediaStream;
class File;
class FileCallback;
class HTMLCanvasPrintState;
class OffscreenCanvas;
class PrintCallback;
class RequestedFrameRefreshObserver;
// Listen visibilitychange and memory-pressure event and inform
// context when event is fired.
class HTMLCanvasElementObserver final : public nsIObserver
, public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMEVENTLISTENER
explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement);
void Destroy();
void RegisterVisibilityChangeEvent();
void UnregisterVisibilityChangeEvent();
void RegisterMemoryPressureEvent();
void UnregisterMemoryPressureEvent();
private:
~HTMLCanvasElementObserver();
HTMLCanvasElement* mElement;
enum class CanvasContextType : uint8_t {
NoContext,
Canvas2D,
WebGL1,
WebGL2
};
/*
@ -110,15 +84,13 @@ protected:
};
class HTMLCanvasElement final : public nsGenericHTMLElement,
public nsIDOMHTMLCanvasElement,
public CanvasRenderingContextHelper
public nsIDOMHTMLCanvasElement
{
enum {
DEFAULT_CANVAS_WIDTH = 300,
DEFAULT_CANVAS_HEIGHT = 150
};
typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
typedef layers::CanvasLayer CanvasLayer;
typedef layers::LayerManager LayerManager;
@ -144,11 +116,6 @@ public:
}
void SetHeight(uint32_t aHeight, ErrorResult& aRv)
{
if (mOffscreenCanvas) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
SetUnsignedIntAttr(nsGkAtoms::height, aHeight, aRv);
}
uint32_t Width()
@ -157,45 +124,30 @@ public:
}
void SetWidth(uint32_t aWidth, ErrorResult& aRv)
{
if (mOffscreenCanvas) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
SetUnsignedIntAttr(nsGkAtoms::width, aWidth, aRv);
}
virtual already_AddRefed<nsISupports>
already_AddRefed<nsISupports>
GetContext(JSContext* aCx, const nsAString& aContextId,
JS::Handle<JS::Value> aContextOptions,
ErrorResult& aRv) override;
ErrorResult& aRv);
void ToDataURL(JSContext* aCx, const nsAString& aType,
JS::Handle<JS::Value> aParams,
nsAString& aDataURL, ErrorResult& aRv)
{
aRv = ToDataURL(aType, aParams, aCx, aDataURL);
}
void ToBlob(JSContext* aCx,
FileCallback& aCallback,
const nsAString& aType,
JS::Handle<JS::Value> aParams,
ErrorResult& aRv);
OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
bool MozOpaque() const
{
return GetBoolAttr(nsGkAtoms::moz_opaque);
}
void SetMozOpaque(bool aValue, ErrorResult& aRv)
{
if (mOffscreenCanvas) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
}
already_AddRefed<File> MozGetAsFile(const nsAString& aName,
@ -252,7 +204,6 @@ public:
* across its entire area.
*/
bool GetIsOpaque();
virtual bool GetOpaqueAttr() override;
virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr);
@ -331,25 +282,19 @@ public:
nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
layers::LayersBackend GetCompositorBackendType() const;
void OnVisibilityChange();
void OnMemoryPressure();
static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
protected:
virtual ~HTMLCanvasElement();
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
virtual nsIntSize GetWidthHeight() override;
virtual already_AddRefed<nsICanvasRenderingContextInternal>
CreateContext(CanvasContextType aContextType) override;
nsIntSize GetWidthHeight();
nsresult UpdateContext(JSContext* aCx, JS::Handle<JS::Value> options);
nsresult ParseParams(JSContext* aCx,
const nsAString& aType,
const JS::Value& aEncoderOptions,
nsAString& aParams,
bool* usingCustomParseOptions);
nsresult ExtractData(nsAString& aType,
const nsAString& aOptions,
nsIInputStream** aStream);
@ -362,17 +307,13 @@ protected:
nsISupports** aResult);
void CallPrintCallback();
AsyncCanvasRenderer* GetAsyncCanvasRenderer();
bool mResetLayer;
CanvasContextType mCurrentContextType;
nsRefPtr<HTMLCanvasElement> mOriginalCanvas;
nsRefPtr<PrintCallback> mPrintCallback;
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
nsRefPtr<HTMLCanvasPrintState> mPrintState;
nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
nsRefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
nsRefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer;
nsRefPtr<OffscreenCanvas> mOffscreenCanvas;
nsRefPtr<HTMLCanvasElementObserver> mContextObserver;
public:
// Record whether this canvas should be write-only or not.

View File

@ -872,8 +872,6 @@ var interfaceNamesInGlobalScope =
"Notification",
// IMPORTANT: Do not change this list without review from a DOM peer!
"NotifyPaintEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "OffscreenCanvas", disabled: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
"OfflineAudioCompletionEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -46,13 +46,6 @@ partial interface HTMLCanvasElement {
CanvasCaptureMediaStream captureStream(optional double frameRate);
};
// For OffscreenCanvas
// Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
partial interface HTMLCanvasElement {
[Pref="gfx.offscreencanvas.enabled", Throws]
OffscreenCanvas transferControlToOffscreen();
};
[ChromeOnly]
interface MozCanvasPrintState
{

View File

@ -1,28 +0,0 @@
/* -*- Mode: IDL; 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/.
*
* For more information on this interface, please see
* https://wiki.whatwg.org/wiki/OffscreenCanvas
*
* Current implementation focus on transfer canvas from main thread to worker.
* So there are some spec doesn't implement, such as [Constructor], toBlob() and
* transferToImageBitmap in OffscreenCanvas. Bug 1172796 will implement
* remaining spec.
*/
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabled"]
interface OffscreenCanvas : EventTarget {
[Pure, SetterThrows]
attribute unsigned long width;
[Pure, SetterThrows]
attribute unsigned long height;
[Throws]
nsISupports? getContext(DOMString contextId,
optional any contextOptions = null);
};
// OffscreenCanvas implements Transferable;

View File

@ -45,38 +45,24 @@ dictionary WebGLContextAttributes {
boolean failIfMajorPerformanceCaveat = false;
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLBuffer {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLFramebuffer {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLProgram {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLRenderbuffer {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLShader {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLTexture {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLUniformLocation {
};
@ -84,24 +70,18 @@ interface WebGLUniformLocation {
interface WebGLVertexArrayObjectOES {
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLActiveInfo {
readonly attribute GLint size;
readonly attribute GLenum type;
readonly attribute DOMString name;
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLShaderPrecisionFormat {
readonly attribute GLint rangeMin;
readonly attribute GLint rangeMax;
readonly attribute GLint precision;
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface WebGLRenderingContext {
/* ClearBufferMask */
@ -524,7 +504,7 @@ interface WebGLRenderingContext {
const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
// The canvas might actually be null in some cases, apparently.
readonly attribute (HTMLCanvasElement or OffscreenCanvas)? canvas;
readonly attribute HTMLCanvasElement? canvas;
readonly attribute GLsizei drawingBufferWidth;
readonly attribute GLsizei drawingBufferHeight;
@ -786,14 +766,6 @@ interface WebGLRenderingContext {
void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
};
// For OffscreenCanvas
// Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
[Exposed=(Window,Worker)]
partial interface WebGLRenderingContext {
[Func="mozilla::dom::OffscreenCanvas::PrefEnabled"]
void commit();
};
/*[Constructor(DOMString type, optional WebGLContextEventInit eventInit)]
interface WebGLContextEvent : Event {
readonly attribute DOMString statusMessage;

View File

@ -344,7 +344,6 @@ WEBIDL_FILES = [
'OfflineAudioCompletionEvent.webidl',
'OfflineAudioContext.webidl',
'OfflineResourceList.webidl',
'OffscreenCanvas.webidl',
'OscillatorNode.webidl',
'PaintRequest.webidl',
'PaintRequestList.webidl',

View File

@ -170,7 +170,6 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
#define PREF_PUSH_ENABLED "dom.push.enabled"
#define PREF_REQUESTCONTEXT_ENABLED "dom.requestcontext.enabled"
#define PREF_OFFSCREENCANVAS_ENABLED "gfx.offscreencanvas.enabled"
namespace {
@ -1971,10 +1970,6 @@ RuntimeService::Init()
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_OFFSCREENCANVAS_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OFFSCREENCANVAS))) ||
NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
@ -2214,10 +2209,6 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_OFFSCREENCANVAS_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OFFSCREENCANVAS))) ||
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
@ -2779,7 +2770,6 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
case WORKERPREF_SERVICEWORKERS_TESTING:
case WORKERPREF_PUSH:
case WORKERPREF_REQUESTCONTEXT:
case WORKERPREF_OFFSCREENCANVAS:
sDefaultPreferences[key] = Preferences::GetBool(aPrefName, false);
break;

View File

@ -1313,13 +1313,6 @@ public:
return mPreferences[WORKERPREF_REQUESTCONTEXT];
}
bool
OffscreenCanvasEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_OFFSCREENCANVAS];
}
bool
OnLine() const
{

View File

@ -209,7 +209,6 @@ enum WorkerPreference
WORKERPREF_PERFORMANCE_LOGGING_ENABLED, // dom.performance.enable_user_timing_logging
WORKERPREF_PUSH, // dom.push.enabled
WORKERPREF_REQUESTCONTEXT, // dom.requestcontext.enabled
WORKERPREF_OFFSCREENCANVAS, // gfx.offscreencanvas.enabled
WORKERPREF_COUNT
};

View File

@ -155,8 +155,6 @@ var interfaceNamesInGlobalScope =
"MessagePort",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Notification",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "OffscreenCanvas", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
"Performance",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -191,26 +189,6 @@ var interfaceNamesInGlobalScope =
"URL",
// IMPORTANT: Do not change this list without review from a DOM peer!
"URLSearchParams",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLActiveInfo", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLBuffer", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLFramebuffer", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLProgram", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLRenderbuffer", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLRenderingContext", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLShader", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLShaderPrecisionFormat", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLTexture", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebGLUniformLocation", disabled: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
"WebSocket",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -2650,7 +2650,6 @@ GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
}
GLuint tempFB = 0;
GLuint tempTex = 0;
{
ScopedBindFramebuffer autoFB(this);
@ -2682,24 +2681,6 @@ GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
}
if (src->NeedsIndirectReads()) {
fGenTextures(1, &tempTex);
{
ScopedBindTexture autoTex(this, tempTex);
GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA
: LOCAL_GL_RGB;
auto width = src->mSize.width;
auto height = src->mSize.height;
fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width,
height, 0);
}
fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_TEXTURE_2D, tempTex, 0);
}
ReadPixelsIntoDataSurface(this, dest);
src->ProducerReadRelease();
@ -2708,10 +2689,6 @@ GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
if (tempFB)
fDeleteFramebuffers(1, &tempFB);
if (tempTex) {
fDeleteTextures(1, &tempTex);
}
if (needsSwap) {
src->UnlockProd();
if (prev)

View File

@ -5,7 +5,6 @@
#include "GLLibraryEGL.h"
#include "gfxCrashReporterUtils.h"
#include "gfxUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Assertions.h"
#include "nsDirectoryServiceDefs.h"
@ -15,17 +14,13 @@
#ifdef XP_WIN
#include "nsWindowsHelpers.h"
#endif
#include "OGLShaderProgram.h"
#include "prenv.h"
#include "GLContext.h"
#include "GLContextProvider.h"
#include "gfxPrefs.h"
#include "ScopedGLHelpers.h"
namespace mozilla {
namespace gl {
StaticMutex GLLibraryEGL::sMutex;
GLLibraryEGL sEGLLibrary;
#ifdef MOZ_B2G
ThreadLocal<EGLContext> GLLibraryEGL::sCurrentContext;
@ -133,9 +128,7 @@ static bool
IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
{
int32_t angleSupport;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_WEBGL_ANGLE,
&angleSupport);
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_ANGLE, &angleSupport);
return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
}
@ -152,32 +145,6 @@ GetAndInitDisplay(GLLibraryEGL& egl, void* displayType)
return display;
}
bool
GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface)
{
StaticMutexAutoUnlock lock(sMutex);
if (!mReadbackGL) {
mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE);
}
ScopedTexture destTex(mReadbackGL);
const GLuint target = LOCAL_GL_TEXTURE_EXTERNAL;
ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
mReadbackGL->fEGLImageTargetTexture2D(target, image);
ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(target,
out_surface->GetFormat());
int shaderConfig = config.mFeatures;
mReadbackGL->ReadTexImageHelper()->ReadTexImage(out_surface, 0, target,
out_surface->GetSize(), shaderConfig);
return true;
}
bool
GLLibraryEGL::EnsureInitialized(bool forceAccel)
{

View File

@ -10,7 +10,6 @@
#endif
#include "GLLibraryLoader.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/ThreadLocal.h"
#include "nsIFile.h"
#include "GeckoProfiler.h"
@ -53,11 +52,6 @@
#endif
namespace mozilla {
namespace gfx {
class DataSourceSurface;
}
namespace gl {
#undef BEFORE_GL_CALL
@ -100,8 +94,6 @@ namespace gl {
#define AFTER_GL_CALL
#endif
class GLContext;
class GLLibraryEGL
{
public:
@ -486,8 +478,6 @@ public:
return IsExtensionSupported(EXT_create_context_robustness);
}
bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
bool EnsureInitialized(bool forceAccel = false);
void DumpEGLConfig(EGLConfig cfg);
@ -613,11 +603,9 @@ private:
bool mInitialized;
PRLibrary* mEGLLibrary;
EGLDisplay mEGLDisplay;
RefPtr<GLContext> mReadbackGL;
bool mIsANGLE;
bool mIsWARP;
static StaticMutex sMutex;
};
extern GLLibraryEGL sEGLLibrary;

View File

@ -214,7 +214,7 @@ GetActualReadFormats(GLContext* gl,
}
}
void
static void
SwapRAndBComponents(DataSourceSurface* surf)
{
DataSourceSurface::MappedSurface map;
@ -533,8 +533,8 @@ ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest)
#endif
}
already_AddRefed<gfx::DataSourceSurface>
YInvertImageSurface(gfx::DataSourceSurface* aSurf)
static already_AddRefed<DataSourceSurface>
YInvertImageSurface(DataSourceSurface* aSurf)
{
RefPtr<DataSourceSurface> temp =
Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
@ -560,8 +560,8 @@ YInvertImageSurface(gfx::DataSourceSurface* aSurf)
return nullptr;
}
dt->SetTransform(Matrix::Scaling(1.0, -1.0) *
Matrix::Translation(0.0, aSurf->GetSize().height));
dt->SetTransform(Matrix::Translation(0.0, aSurf->GetSize().height) *
Matrix::Scaling(1.0, -1.0));
Rect rect(0, 0, aSurf->GetSize().width, aSurf->GetSize().height);
dt->DrawSurface(aSurf, rect, rect, DrawSurfaceOptions(),
DrawOptions(1.0, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
@ -614,7 +614,8 @@ ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFo
#define CLEANUP_IF_GLERROR_OCCURRED(x) \
if (DidGLErrorOccur(x)) { \
return false; \
isurf = nullptr; \
break; \
}
already_AddRefed<DataSourceSurface>
@ -623,31 +624,6 @@ GLReadTexImageHelper::ReadTexImage(GLuint aTextureId,
const gfx::IntSize& aSize,
/* ShaderConfigOGL.mFeature */ int aConfig,
bool aYInvert)
{
/* Allocate resulting image surface */
int32_t stride = aSize.width * BytesPerPixel(SurfaceFormat::R8G8B8A8);
RefPtr<DataSourceSurface> isurf =
Factory::CreateDataSourceSurfaceWithStride(aSize,
SurfaceFormat::R8G8B8A8,
stride);
if (NS_WARN_IF(!isurf)) {
return nullptr;
}
if (!ReadTexImage(isurf, aTextureId, aTextureTarget, aSize, aConfig, aYInvert)) {
return nullptr;
}
return isurf.forget();
}
bool
GLReadTexImageHelper::ReadTexImage(DataSourceSurface* aDest,
GLuint aTextureId,
GLenum aTextureTarget,
const gfx::IntSize& aSize,
/* ShaderConfigOGL.mFeature */ int aConfig,
bool aYInvert)
{
MOZ_ASSERT(aTextureTarget == LOCAL_GL_TEXTURE_2D ||
aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL ||
@ -655,6 +631,16 @@ GLReadTexImageHelper::ReadTexImage(DataSourceSurface* aDest,
mGL->MakeCurrent();
/* Allocate resulting image surface */
int32_t stride = aSize.width * BytesPerPixel(SurfaceFormat::R8G8B8A8);
RefPtr<DataSourceSurface> isurf =
Factory::CreateDataSourceSurfaceWithStride(aSize,
SurfaceFormat::R8G8B8A8,
stride);
if (NS_WARN_IF(!isurf)) {
return nullptr;
}
GLint oldrb, oldfb, oldprog, oldTexUnit, oldTex;
GLuint rb, fb;
@ -751,7 +737,7 @@ GLReadTexImageHelper::ReadTexImage(DataSourceSurface* aDest,
CLEANUP_IF_GLERROR_OCCURRED("when drawing texture");
/* Read-back draw results */
ReadPixelsIntoDataSurface(mGL, aDest);
ReadPixelsIntoDataSurface(mGL, isurf);
CLEANUP_IF_GLERROR_OCCURRED("when reading pixels into surface");
} while (false);
@ -770,7 +756,7 @@ GLReadTexImageHelper::ReadTexImage(DataSourceSurface* aDest,
if (oldTexUnit != LOCAL_GL_TEXTURE0)
mGL->fActiveTexture(oldTexUnit);
return true;
return isurf.forget();
}
#undef CLEANUP_IF_GLERROR_OCCURRED

View File

@ -34,12 +34,6 @@ void ReadPixelsIntoDataSurface(GLContext* aGL,
already_AddRefed<gfx::DataSourceSurface>
ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
already_AddRefed<gfx::DataSourceSurface>
YInvertImageSurface(gfx::DataSourceSurface* aSurf);
void
SwapRAndBComponents(gfx::DataSourceSurface* surf);
class GLReadTexImageHelper final
{
// The GLContext is the sole owner of the GLBlitHelper.
@ -71,17 +65,12 @@ public:
* passed as int to eliminate including LayerManagerOGLProgram.h here.
*/
already_AddRefed<gfx::DataSourceSurface> ReadTexImage(GLuint aTextureId,
GLenum aTextureTarget,
const gfx::IntSize& aSize,
/* ShaderProgramType */ int aShaderProgram,
bool aYInvert = false);
GLenum aTextureTarget,
const gfx::IntSize& aSize,
/* ShaderProgramType */ int aShaderProgram,
bool aYInvert = false);
bool ReadTexImage(gfx::DataSourceSurface* aDest,
GLuint aTextureId,
GLenum aTextureTarget,
const gfx::IntSize& aSize,
int aShaderProgram,
bool aYInvert = false);
};
} // namespace gl

View File

@ -10,32 +10,18 @@
#include "GLContext.h"
#include "GLBlitHelper.h"
#include "GLReadTexImageHelper.h"
#include "SharedSurfaceEGL.h"
#include "SharedSurfaceGL.h"
#include "ScopedGLHelpers.h"
#include "gfx2DGlue.h"
#include "../layers/ipc/ShadowLayers.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#ifdef XP_WIN
#include "SharedSurfaceANGLE.h" // for SurfaceFactory_ANGLEShareHandle
#include "gfxWindowsPlatform.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "SharedSurfaceGralloc.h"
#include "nsXULAppAPI.h"
#endif
#ifdef XP_MACOSX
#include "SharedSurfaceIO.h"
#endif
#ifdef GL_PROVIDER_GLX
#include "GLXLibrary.h"
#include "SharedSurfaceGLX.h"
#endif
#include "ScopedGLHelpers.h"
#include "gfx2DGlue.h"
#include "../layers/ipc/ShadowLayers.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
namespace mozilla {
namespace gl {
@ -65,53 +51,6 @@ GLScreenBuffer::Create(GLContext* gl,
return Move(ret);
}
/* static */ UniquePtr<SurfaceFactory>
GLScreenBuffer::CreateFactory(GLContext* gl,
const SurfaceCaps& caps,
const RefPtr<layers::CompositableForwarder>& forwarder,
const layers::TextureFlags& flags)
{
UniquePtr<SurfaceFactory> factory = nullptr;
if (!gfxPrefs::WebGLForceLayersReadback()) {
switch (forwarder->GetCompositorBackendType()) {
case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX)
factory = SurfaceFactory_IOSurface::Create(gl, caps, forwarder, flags);
#elif defined(MOZ_WIDGET_GONK)
factory = MakeUnique<SurfaceFactory_Gralloc>(gl, caps, forwarder, flags);
#elif defined(GL_PROVIDER_GLX)
if (sGLXLibrary.UseSurfaceSharing())
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, forwarder, flags);
#else
if (gl->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, forwarder, flags);
}
}
#endif
break;
}
case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
// Enable surface sharing only if ANGLE and compositing devices
// are both WARP or both not WARP
if (gl->IsANGLE() &&
(gl->IsWARP() == gfxWindowsPlatform::GetPlatform()->IsWARP()) &&
gfxWindowsPlatform::GetPlatform()->CompositorD3D11TextureSharingWorks())
{
factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, forwarder, flags);
}
#endif
break;
}
default:
break;
}
}
return factory;
}
GLScreenBuffer::GLScreenBuffer(GLContext* gl,
const SurfaceCaps& caps,
UniquePtr<SurfaceFactory> factory)

View File

@ -25,7 +25,6 @@
namespace mozilla {
namespace layers {
class CompositableForwarder;
class SharedSurfaceTextureClient;
} // namespace layers
@ -134,12 +133,6 @@ public:
const gfx::IntSize& size,
const SurfaceCaps& caps);
static UniquePtr<SurfaceFactory>
CreateFactory(GLContext* gl,
const SurfaceCaps& caps,
const RefPtr<layers::CompositableForwarder>& forwarder,
const layers::TextureFlags& flags);
protected:
GLContext* const mGL; // Owns us.
public:

View File

@ -311,7 +311,6 @@ SurfaceFactory::SurfaceFactory(SharedSurfaceType type, GLContext* gl,
, mAllocator(allocator)
, mFlags(flags)
, mFormats(gl->ChooseGLFormats(caps))
, mMutex("SurfaceFactor::mMutex")
{
ChooseBufferBits(mCaps, &mDrawCaps, &mReadCaps);
}
@ -369,7 +368,6 @@ SurfaceFactory::StartRecycling(layers::SharedSurfaceTextureClient* tc)
void
SurfaceFactory::StopRecycling(layers::SharedSurfaceTextureClient* tc)
{
MutexAutoLock autoLock(mMutex);
// Must clear before releasing ref.
tc->ClearRecycleCallback();
@ -381,8 +379,11 @@ SurfaceFactory::StopRecycling(layers::SharedSurfaceTextureClient* tc)
/*static*/ void
SurfaceFactory::RecycleCallback(layers::TextureClient* rawTC, void* rawFactory)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<layers::SharedSurfaceTextureClient> tc;
tc = static_cast<layers::SharedSurfaceTextureClient*>(rawTC);
SurfaceFactory* factory = static_cast<SurfaceFactory*>(rawFactory);
if (tc->mSurf->mCanRecycle) {
@ -398,7 +399,6 @@ bool
SurfaceFactory::Recycle(layers::SharedSurfaceTextureClient* texClient)
{
MOZ_ASSERT(texClient);
MutexAutoLock autoLock(mMutex);
if (mRecycleFreePool.size() >= 2) {
return false;

View File

@ -24,7 +24,6 @@
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "ScopedGLHelpers.h"
@ -34,7 +33,6 @@ class nsIThread;
namespace mozilla {
namespace gfx {
class DataSourceSurface;
class DrawTarget;
} // namespace gfx
@ -201,10 +199,6 @@ public:
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) = 0;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) {
return false;
}
};
template<typename T>
@ -304,7 +298,6 @@ public:
const RefPtr<layers::ISurfaceAllocator> mAllocator;
const layers::TextureFlags mFlags;
const GLFormats mFormats;
Mutex mMutex;
protected:
SurfaceCaps mDrawCaps;
SurfaceCaps mReadCaps;

View File

@ -273,138 +273,6 @@ SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* c
return true;
}
class ScopedLockTexture final
{
public:
explicit ScopedLockTexture(ID3D11Texture2D* texture, bool* succeeded)
: mIsLocked(false)
, mTexture(texture)
{
MOZ_ASSERT(mTexture);
MOZ_ASSERT(succeeded);
*succeeded = false;
HRESULT hr;
mTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mMutex));
if (mMutex) {
hr = mMutex->AcquireSync(0, 10000);
if (hr == WAIT_TIMEOUT) {
MOZ_CRASH();
}
if (FAILED(hr)) {
NS_WARNING("Failed to lock the texture");
return;
}
}
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
device->GetImmediateContext(byRef(mDeviceContext));
mTexture->GetDesc(&mDesc);
mDesc.BindFlags = 0;
mDesc.Usage = D3D11_USAGE_STAGING;
mDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
mDesc.MiscFlags = 0;
hr = device->CreateTexture2D(&mDesc, nullptr, byRef(mCopiedTexture));
if (FAILED(hr)) {
return;
}
mDeviceContext->CopyResource(mCopiedTexture, mTexture);
hr = mDeviceContext->Map(mCopiedTexture, 0, D3D11_MAP_READ, 0, &mSubresource);
if (FAILED(hr)) {
return;
}
*succeeded = true;
mIsLocked = true;
}
~ScopedLockTexture()
{
mDeviceContext->Unmap(mCopiedTexture, 0);
if (mMutex) {
HRESULT hr = mMutex->ReleaseSync(0);
if (FAILED(hr)) {
NS_WARNING("Failed to unlock the texture");
}
}
mIsLocked = false;
}
bool mIsLocked;
RefPtr<ID3D11Texture2D> mTexture;
RefPtr<ID3D11Texture2D> mCopiedTexture;
RefPtr<IDXGIKeyedMutex> mMutex;
RefPtr<ID3D11DeviceContext> mDeviceContext;
D3D11_TEXTURE2D_DESC mDesc;
D3D11_MAPPED_SUBRESOURCE mSubresource;
};
bool
SharedSurface_ANGLEShareHandle::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
MOZ_ASSERT(out_surface);
RefPtr<ID3D11Texture2D> tex;
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
HRESULT hr = device->OpenSharedResource(mShareHandle,
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)byRef(tex));
if (FAILED(hr)) {
return false;
}
bool succeeded = false;
ScopedLockTexture scopedLock(tex, &succeeded);
if (!succeeded) {
return false;
}
const uint8_t* data = reinterpret_cast<uint8_t*>(scopedLock.mSubresource.pData);
uint32_t srcStride = scopedLock.mSubresource.RowPitch;
gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE);
if (!map.IsMapped()) {
return false;
}
if (map.GetStride() == srcStride) {
memcpy(map.GetData(), data, out_surface->GetSize().height * map.GetStride());
} else {
const uint8_t bytesPerPixel = BytesPerPixel(out_surface->GetFormat());
for (int32_t i = 0; i < out_surface->GetSize().height; i++) {
memcpy(map.GetData() + i * map.GetStride(),
data + i * srcStride,
bytesPerPixel * out_surface->GetSize().width);
}
}
DXGI_FORMAT srcFormat = scopedLock.mDesc.Format;
MOZ_ASSERT(srcFormat == DXGI_FORMAT_B8G8R8A8_UNORM ||
srcFormat == DXGI_FORMAT_B8G8R8X8_UNORM ||
srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM);
bool isSrcRGB = srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM;
gfx::SurfaceFormat destFormat = out_surface->GetFormat();
MOZ_ASSERT(destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
destFormat == gfx::SurfaceFormat::R8G8B8A8 ||
destFormat == gfx::SurfaceFormat::B8G8R8X8 ||
destFormat == gfx::SurfaceFormat::B8G8R8A8);
bool isDestRGB = destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
destFormat == gfx::SurfaceFormat::R8G8B8A8;
if (isSrcRGB != isDestRGB) {
SwapRAndBComponents(out_surface);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Factory

View File

@ -81,8 +81,6 @@ public:
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
};

View File

@ -10,6 +10,7 @@
#include "GLLibraryEGL.h"
#include "GLReadTexImageHelper.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "ScopedGLHelpers.h"
#include "SharedSurface.h"
#include "TextureGarbageBin.h"
@ -212,14 +213,6 @@ SharedSurface_EGLImage::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out
return true;
}
bool
SharedSurface_EGLImage::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
MOZ_ASSERT(out_surface);
MOZ_ASSERT(NS_IsMainThread());
return sEGLLibrary.ReadbackEGLImage(mImage, out_surface);
}
////////////////////////////////////////////////////////////////////////
/*static*/ UniquePtr<SurfaceFactory_EGLImage>

View File

@ -79,8 +79,6 @@ public:
void AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target);
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
};

View File

@ -9,7 +9,6 @@
#include "GLContextProvider.h"
#include "GLContextGLX.h"
#include "GLScreenBuffer.h"
#include "mozilla/gfx/SourceSurfaceCairo.h"
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/layers/ShadowLayerUtilsX11.h"
#include "mozilla/layers/ISurfaceAllocator.h"
@ -84,38 +83,6 @@ SharedSurface_GLXDrawable::ToSurfaceDescriptor(layers::SurfaceDescriptor* const
return true;
}
bool
SharedSurface_GLXDrawable::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
MOZ_ASSERT(out_surface);
RefPtr<gfx::DataSourceSurface> dataSurf =
new gfx::DataSourceSurfaceCairo(mXlibSurface->CairoSurface());
gfx::DataSourceSurface::ScopedMap mapSrc(dataSurf, gfx::DataSourceSurface::READ);
if (!mapSrc.IsMapped()) {
return false;
}
gfx::DataSourceSurface::ScopedMap mapDest(out_surface, gfx::DataSourceSurface::WRITE);
if (!mapDest.IsMapped()) {
return false;
}
if (mapDest.GetStride() == mapSrc.GetStride()) {
memcpy(mapDest.GetData(),
mapSrc.GetData(),
out_surface->GetSize().height * mapDest.GetStride());
} else {
for (int32_t i = 0; i < dataSurf->GetSize().height; i++) {
memcpy(mapDest.GetData() + i * mapDest.GetStride(),
mapSrc.GetData() + i * mapSrc.GetStride(),
std::min(mapSrc.GetStride(), mapDest.GetStride()));
}
}
return true;
}
/* static */
UniquePtr<SurfaceFactory_GLXDrawable>
SurfaceFactory_GLXDrawable::Create(GLContext* prodGL,

View File

@ -32,8 +32,6 @@ public:
virtual void UnlockProdImpl() override;
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
private:
SharedSurface_GLXDrawable(GLContext* gl,
const gfx::IntSize& size,

View File

@ -283,58 +283,5 @@ SharedSurface_Gralloc::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_
return mTextureClient->ToSurfaceDescriptor(*out_descriptor);
}
bool
SharedSurface_Gralloc::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
MOZ_ASSERT(out_surface);
sp<GraphicBuffer> buffer = mTextureClient->GetGraphicBuffer();
const uint8_t* grallocData = nullptr;
auto result = buffer->lock(
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
const_cast<void**>(reinterpret_cast<const void**>(&grallocData))
);
if (result == BAD_VALUE) {
return false;
}
gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE);
if (!map.IsMapped()) {
buffer->unlock();
return false;
}
uint32_t stride = buffer->getStride() * android::bytesPerPixel(buffer->getPixelFormat());
uint32_t height = buffer->getHeight();
uint32_t width = buffer->getWidth();
for (uint32_t i = 0; i < height; i++) {
memcpy(map.GetData() + i * map.GetStride(),
grallocData + i * stride, width * 4);
}
buffer->unlock();
android::PixelFormat srcFormat = buffer->getPixelFormat();
MOZ_ASSERT(srcFormat == PIXEL_FORMAT_RGBA_8888 ||
srcFormat == PIXEL_FORMAT_BGRA_8888 ||
srcFormat == PIXEL_FORMAT_RGBX_8888);
bool isSrcRGB = srcFormat == PIXEL_FORMAT_RGBA_8888 ||
srcFormat == PIXEL_FORMAT_RGBX_8888;
gfx::SurfaceFormat destFormat = out_surface->GetFormat();
MOZ_ASSERT(destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
destFormat == gfx::SurfaceFormat::R8G8B8A8 ||
destFormat == gfx::SurfaceFormat::B8G8R8X8 ||
destFormat == gfx::SurfaceFormat::B8G8R8A8);
bool isDestRGB = destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
destFormat == gfx::SurfaceFormat::R8G8B8A8;
if (isSrcRGB != isDestRGB) {
SwapRAndBComponents(out_surface);
}
return true;
}
} // namespace gl
} // namespace mozilla

View File

@ -75,8 +75,6 @@ public:
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
};
class SurfaceFactory_Gralloc

View File

@ -182,31 +182,6 @@ SharedSurface_IOSurface::ToSurfaceDescriptor(layers::SurfaceDescriptor* const ou
return true;
}
bool
SharedSurface_IOSurface::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
MOZ_ASSERT(out_surface);
mIOSurf->Lock();
size_t bytesPerRow = mIOSurf->GetBytesPerRow();
size_t ioWidth = mIOSurf->GetDevicePixelWidth();
size_t ioHeight = mIOSurf->GetDevicePixelHeight();
const unsigned char* ioData = (unsigned char*)mIOSurf->GetBaseAddress();
gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE);
if (!map.IsMapped()) {
mIOSurf->Unlock();
return false;
}
for (size_t i = 0; i < ioHeight; i++) {
memcpy(map.GetData() + i * map.GetStride(),
ioData + i * bytesPerRow, ioWidth * 4);
}
mIOSurf->Unlock();
return true;
}
////////////////////////////////////////////////////////////////////////
// SurfaceFactory_IOSurface

View File

@ -68,8 +68,6 @@ public:
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
};
class SurfaceFactory_IOSurface : public SurfaceFactory

View File

@ -1,279 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "AsyncCanvasRenderer.h"
#include "gfxUtils.h"
#include "GLContext.h"
#include "GLReadTexImageHelper.h"
#include "GLScreenBuffer.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsIRunnable.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace layers {
AsyncCanvasRenderer::AsyncCanvasRenderer()
: mHTMLCanvasElement(nullptr)
, mContext(nullptr)
, mGLContext(nullptr)
, mIsAlphaPremultiplied(true)
, mWidth(0)
, mHeight(0)
, mCanvasClientAsyncID(0)
, mCanvasClient(nullptr)
, mMutex("AsyncCanvasRenderer::mMutex")
{
MOZ_COUNT_CTOR(AsyncCanvasRenderer);
}
AsyncCanvasRenderer::~AsyncCanvasRenderer()
{
MOZ_COUNT_DTOR(AsyncCanvasRenderer);
}
void
AsyncCanvasRenderer::NotifyElementAboutAttributesChanged()
{
class Runnable final : public nsRunnable
{
public:
explicit Runnable(AsyncCanvasRenderer* aRenderer)
: mRenderer(aRenderer)
{}
NS_IMETHOD Run()
{
if (mRenderer) {
dom::HTMLCanvasElement::SetAttrFromAsyncCanvasRenderer(mRenderer);
}
return NS_OK;
}
void Revoke()
{
mRenderer = nullptr;
}
private:
nsRefPtr<AsyncCanvasRenderer> mRenderer;
};
nsRefPtr<nsRunnable> runnable = new Runnable(this);
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch a runnable to the main-thread.");
}
}
void
AsyncCanvasRenderer::NotifyElementAboutInvalidation()
{
class Runnable final : public nsRunnable
{
public:
explicit Runnable(AsyncCanvasRenderer* aRenderer)
: mRenderer(aRenderer)
{}
NS_IMETHOD Run()
{
if (mRenderer) {
dom::HTMLCanvasElement::InvalidateFromAsyncCanvasRenderer(mRenderer);
}
return NS_OK;
}
void Revoke()
{
mRenderer = nullptr;
}
private:
nsRefPtr<AsyncCanvasRenderer> mRenderer;
};
nsRefPtr<nsRunnable> runnable = new Runnable(this);
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch a runnable to the main-thread.");
}
}
void
AsyncCanvasRenderer::SetCanvasClient(CanvasClient* aClient)
{
mCanvasClient = aClient;
if (aClient) {
mCanvasClientAsyncID = aClient->GetAsyncID();
} else {
mCanvasClientAsyncID = 0;
}
}
void
AsyncCanvasRenderer::SetActiveThread()
{
MutexAutoLock lock(mMutex);
mActiveThread = NS_GetCurrentThread();
}
void
AsyncCanvasRenderer::ResetActiveThread()
{
MutexAutoLock lock(mMutex);
mActiveThread = nullptr;
}
already_AddRefed<nsIThread>
AsyncCanvasRenderer::GetActiveThread()
{
MutexAutoLock lock(mMutex);
nsCOMPtr<nsIThread> result = mActiveThread;
return result.forget();
}
void
AsyncCanvasRenderer::CopyFromTextureClient(TextureClient* aTextureClient)
{
MutexAutoLock lock(mMutex);
RefPtr<BufferTextureClient> buffer = static_cast<BufferTextureClient*>(aTextureClient);
if (!buffer->Lock(layers::OpenMode::OPEN_READ)) {
return;
}
const gfx::IntSize& size = aTextureClient->GetSize();
// This buffer would be used later for content rendering. So we choose
// B8G8R8A8 format here.
const gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
// Avoid to create buffer every time.
if (!mSurfaceForBasic ||
size != mSurfaceForBasic->GetSize() ||
format != mSurfaceForBasic->GetFormat())
{
uint32_t stride = gfx::GetAlignedStride<8>(size.width * BytesPerPixel(format));
mSurfaceForBasic = gfx::Factory::CreateDataSourceSurfaceWithStride(size, format, stride);
}
const uint8_t* lockedBytes = buffer->GetLockedData();
gfx::DataSourceSurface::ScopedMap map(mSurfaceForBasic,
gfx::DataSourceSurface::MapType::WRITE);
if (!map.IsMapped()) {
buffer->Unlock();
return;
}
memcpy(map.GetData(), lockedBytes, map.GetStride() * mSurfaceForBasic->GetSize().height);
buffer->Unlock();
if (mSurfaceForBasic->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
mSurfaceForBasic->GetFormat() == gfx::SurfaceFormat::R8G8B8X8) {
gl::SwapRAndBComponents(mSurfaceForBasic);
}
}
already_AddRefed<gfx::DataSourceSurface>
AsyncCanvasRenderer::UpdateTarget()
{
if (!mGLContext) {
return nullptr;
}
gl::SharedSurface* frontbuffer = nullptr;
gl::GLScreenBuffer* screen = mGLContext->Screen();
const auto& front = screen->Front();
if (front) {
frontbuffer = front->Surf();
}
if (!frontbuffer) {
return nullptr;
}
if (frontbuffer->mType == gl::SharedSurfaceType::Basic) {
return nullptr;
}
const gfx::IntSize& size = frontbuffer->mSize;
// This buffer would be used later for content rendering. So we choose
// B8G8R8A8 format here.
const gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
uint32_t stride = gfx::GetAlignedStride<8>(size.width * BytesPerPixel(format));
RefPtr<gfx::DataSourceSurface> surface =
gfx::Factory::CreateDataSourceSurfaceWithStride(size, format, stride);
if (NS_WARN_IF(!surface)) {
return nullptr;
}
if (!frontbuffer->ReadbackBySharedHandle(surface)) {
return nullptr;
}
bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
if (needsPremult) {
gfxUtils::PremultiplyDataSurface(surface, surface);
}
return surface.forget();
}
already_AddRefed<gfx::DataSourceSurface>
AsyncCanvasRenderer::GetSurface()
{
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mMutex);
if (mSurfaceForBasic) {
// Since SourceSurface isn't thread-safe, we need copy to a new SourceSurface.
RefPtr<gfx::DataSourceSurface> result =
gfx::Factory::CreateDataSourceSurfaceWithStride(mSurfaceForBasic->GetSize(),
mSurfaceForBasic->GetFormat(),
mSurfaceForBasic->Stride());
gfx::DataSourceSurface::ScopedMap srcMap(mSurfaceForBasic, gfx::DataSourceSurface::READ);
gfx::DataSourceSurface::ScopedMap dstMap(result, gfx::DataSourceSurface::WRITE);
if (NS_WARN_IF(!srcMap.IsMapped()) ||
NS_WARN_IF(!dstMap.IsMapped())) {
return nullptr;
}
memcpy(dstMap.GetData(),
srcMap.GetData(),
srcMap.GetStride() * mSurfaceForBasic->GetSize().height);
return result.forget();
} else {
return UpdateTarget();
}
}
nsresult
AsyncCanvasRenderer::GetInputStream(const char *aMimeType,
const char16_t *aEncoderOptions,
nsIInputStream **aStream)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<gfx::DataSourceSurface> surface = GetSurface();
if (!surface) {
return NS_ERROR_FAILURE;
}
// Handle y flip.
RefPtr<gfx::DataSourceSurface> dataSurf = gl::YInvertImageSurface(surface);
return gfxUtils::GetInputStream(dataSurf, false, aMimeType, aEncoderOptions, aStream);
}
} // namespace layers
} // namespace mozilla

View File

@ -1,169 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
#define MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
#include "LayersTypes.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h" // for nsAutoPtr, nsRefPtr, etc
#include "nsCOMPtr.h" // for nsCOMPtr
class nsICanvasRenderingContextInternal;
class nsIInputStream;
class nsIThread;
namespace mozilla {
namespace gfx {
class DataSourceSurface;
}
namespace gl {
class GLContext;
}
namespace dom {
class HTMLCanvasElement;
}
namespace layers {
class CanvasClient;
class TextureClient;
/**
* Since HTMLCanvasElement and OffscreenCanvas are not thread-safe, we create
* AsyncCanvasRenderer which is thread-safe wrapper object for communicating
* among main, worker and ImageBridgeChild threads.
*
* Each HTMLCanvasElement object is responsible for creating
* AsyncCanvasRenderer object. Once Canvas is transfered to worker,
* OffscreenCanvas will keep reference pointer of this object.
*
* Sometimes main thread needs AsyncCanvasRenderer's result, such as layers
* fallback to BasicLayerManager or calling toDataURL in Javascript. Simply call
* GetSurface() in main thread will readback the result to mSurface.
*
* If layers backend is LAYERS_CLIENT, this object will pass to ImageBridgeChild
* for submitting frames to Compositor.
*/
class AsyncCanvasRenderer final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncCanvasRenderer)
public:
AsyncCanvasRenderer();
void NotifyElementAboutAttributesChanged();
void NotifyElementAboutInvalidation();
void SetCanvasClient(CanvasClient* aClient);
void SetWidth(uint32_t aWidth)
{
mWidth = aWidth;
}
void SetHeight(uint32_t aHeight)
{
mHeight = aHeight;
}
void SetIsAlphaPremultiplied(bool aIsAlphaPremultiplied)
{
mIsAlphaPremultiplied = aIsAlphaPremultiplied;
}
// Active thread means the thread which spawns GLContext.
void SetActiveThread();
void ResetActiveThread();
// This will readback surface and return the surface
// in the DataSourceSurface.
// Can be called in main thread only.
already_AddRefed<gfx::DataSourceSurface> GetSurface();
// For SharedSurface_Basic case, before the frame sending to the compositor,
// we readback it to a texture client because SharedSurface_Basic cannot shared.
// We don't want to readback it again here, so just copy the content of that
// texture client here to avoid readback again.
void CopyFromTextureClient(TextureClient *aClient);
// Readback current WebGL's content and convert it to InputStream. This
// function called GetSurface implicitly and GetSurface handles only get
// called in the main thread. So this function can be called in main thread.
nsresult
GetInputStream(const char *aMimeType,
const char16_t *aEncoderOptions,
nsIInputStream **aStream);
gfx::IntSize GetSize() const
{
return gfx::IntSize(mWidth, mHeight);
}
uint64_t GetCanvasClientAsyncID() const
{
return mCanvasClientAsyncID;
}
CanvasClient* GetCanvasClient() const
{
return mCanvasClient;
}
already_AddRefed<nsIThread> GetActiveThread();
// The lifetime is controllered by HTMLCanvasElement.
// Only accessed in main thread.
dom::HTMLCanvasElement* mHTMLCanvasElement;
// Only accessed in active thread.
nsICanvasRenderingContextInternal* mContext;
// We need to keep a reference to the context around here, otherwise the
// canvas' surface texture destructor will deref and destroy it too early
// Only accessed in active thread.
RefPtr<gl::GLContext> mGLContext;
private:
virtual ~AsyncCanvasRenderer();
// Readback current WebGL's content and return it as DataSourceSurface.
already_AddRefed<gfx::DataSourceSurface> UpdateTarget();
bool mIsAlphaPremultiplied;
uint32_t mWidth;
uint32_t mHeight;
uint64_t mCanvasClientAsyncID;
// The lifetime of this pointer is controlled by OffscreenCanvas
// Can be accessed in active thread and ImageBridge thread.
// But we never accessed it at the same time on both thread. So no
// need to protect this member.
CanvasClient* mCanvasClient;
// When backend is LAYER_BASIC and SharedSurface type is Basic.
// CanvasClient will readback the GLContext to a TextureClient
// in order to send frame to compositor. To avoid readback again,
// we copy from this TextureClient to this mSurfaceForBasic directly
// by calling CopyFromTextureClient().
RefPtr<gfx::DataSourceSurface> mSurfaceForBasic;
// Protect non thread-safe objects.
Mutex mMutex;
// Can be accessed in any thread, need protect by mutex.
nsCOMPtr<nsIThread> mActiveThread;
};
} // namespace layers
} // namespace mozilla
#endif // MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_

View File

@ -64,9 +64,6 @@ CopyableCanvasLayer::Initialize(const Data& aData)
}
} else if (aData.mBufferProvider) {
mBufferProvider = aData.mBufferProvider;
} else if (aData.mRenderer) {
mAsyncRenderer = aData.mRenderer;
mOriginPos = gl::OriginPos::BottomLeft;
} else {
MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
}
@ -83,9 +80,7 @@ CopyableCanvasLayer::IsDataValid(const Data& aData)
void
CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
{
if (mAsyncRenderer) {
mSurface = mAsyncRenderer->GetSurface();
} else if (mBufferProvider) {
if (mBufferProvider) {
mSurface = mBufferProvider->GetSnapshot();
}
@ -100,7 +95,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
return;
}
if (mBufferProvider || mAsyncRenderer) {
if (mBufferProvider) {
return;
}

View File

@ -385,7 +385,7 @@ struct ColorLayerProperties : public LayerPropertiesBase
IntRect mBounds;
};
static ImageHost* GetImageHost(Layer* aLayer)
static ImageHost* GetImageHost(ImageLayer* aLayer)
{
LayerComposite* composite = aLayer->AsLayerComposite();
if (composite) {
@ -465,34 +465,6 @@ struct ImageLayerProperties : public LayerPropertiesBase
bool mIsMask;
};
struct CanvasLayerProperties : public LayerPropertiesBase
{
explicit CanvasLayerProperties(CanvasLayer* aCanvas)
: LayerPropertiesBase(aCanvas)
, mImageHost(GetImageHost(aCanvas))
{
mFrameID = mImageHost ? mImageHost->GetFrameID() : -1;
}
virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback,
bool& aGeometryChanged)
{
CanvasLayer* canvasLayer = static_cast<CanvasLayer*>(mLayer.get());
ImageHost* host = GetImageHost(canvasLayer);
if (host && host->GetFrameID() != mFrameID) {
aGeometryChanged = true;
return NewTransformedBounds();
}
return IntRect();
}
nsRefPtr<ImageHost> mImageHost;
int32_t mFrameID;
};
UniquePtr<LayerPropertiesBase>
CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask /* = false */)
{
@ -511,7 +483,6 @@ CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask /* = false */)
case Layer::TYPE_IMAGE:
return MakeUnique<ImageLayerProperties>(static_cast<ImageLayer*>(aRoot), aIsMask);
case Layer::TYPE_CANVAS:
return MakeUnique<CanvasLayerProperties>(static_cast<CanvasLayer*>(aRoot));
case Layer::TYPE_READBACK:
case Layer::TYPE_SHADOW:
case Layer::TYPE_PAINTED:

View File

@ -25,7 +25,6 @@
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite
@ -2105,19 +2104,6 @@ ColorLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
layer->set_color(mColor.ToABGR());
}
CanvasLayer::CanvasLayer(LayerManager* aManager, void* aImplData)
: Layer(aManager, aImplData)
, mPreTransCallback(nullptr)
, mPreTransCallbackData(nullptr)
, mPostTransCallback(nullptr)
, mPostTransCallbackData(nullptr)
, mFilter(GraphicsFilter::FILTER_GOOD)
, mDirty(false)
{}
CanvasLayer::~CanvasLayer()
{}
void
CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{

View File

@ -74,7 +74,6 @@ namespace layers {
class Animation;
class AnimationData;
class AsyncCanvasRenderer;
class AsyncPanZoomController;
class ClientLayerManager;
class Layer;
@ -2269,17 +2268,15 @@ public:
Data()
: mBufferProvider(nullptr)
, mGLContext(nullptr)
, mRenderer(nullptr)
, mFrontbufferGLTex(0)
, mSize(0,0)
, mHasAlpha(false)
, mIsGLAlphaPremult(true)
{ }
// One of these three must be specified for Canvas2D, but never more than one
// One of these two must be specified for Canvas2D, but never both
PersistentBufferProvider* mBufferProvider; // A BufferProvider for the Canvas contents
mozilla::gl::GLContext* mGLContext; // or this, for GL.
AsyncCanvasRenderer* mRenderer; // or this, for OffscreenCanvas
// Frontbuffer override
uint32_t mFrontbufferGLTex;
@ -2395,14 +2392,16 @@ public:
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
bool GetIsAsyncRenderer() const
{
return !!mAsyncRenderer;
}
protected:
CanvasLayer(LayerManager* aManager, void* aImplData);
virtual ~CanvasLayer();
CanvasLayer(LayerManager* aManager, void* aImplData)
: Layer(aManager, aImplData)
, mPreTransCallback(nullptr)
, mPreTransCallbackData(nullptr)
, mPostTransCallback(nullptr)
, mPostTransCallbackData(nullptr)
, mFilter(GraphicsFilter::FILTER_GOOD)
, mDirty(false)
{}
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
@ -2424,7 +2423,6 @@ protected:
DidTransactionCallback mPostTransCallback;
void* mPostTransCallbackData;
GraphicsFilter mFilter;
nsRefPtr<AsyncCanvasRenderer> mAsyncRenderer;
private:
/**

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BasicCanvasLayer.h"
#include "AsyncCanvasRenderer.h"
#include "basic/BasicLayers.h" // for BasicLayerManager
#include "basic/BasicLayersImpl.h" // for GetEffectiveOperator
#include "mozilla/mozalloc.h" // for operator new

View File

@ -13,7 +13,6 @@
#include "gfxPlatform.h" // for gfxPlatform
#include "GLReadTexImageHelper.h"
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorChild.h" // for CompositorChild
#include "mozilla/layers/GrallocTextureClient.h"
@ -39,32 +38,14 @@ CanvasClient::CreateCanvasClient(CanvasClientType aType,
switch (aType) {
case CanvasClientTypeShSurf:
return MakeAndAddRef<CanvasClientSharedSurface>(aForwarder, aFlags);
case CanvasClientAsync:
return MakeAndAddRef<CanvasClientBridge>(aForwarder, aFlags);
break;
default:
return MakeAndAddRef<CanvasClient2D>(aForwarder, aFlags);
break;
}
}
void
CanvasClientBridge::UpdateAsync(AsyncCanvasRenderer* aRenderer)
{
if (!GetForwarder() || !mLayer || !aRenderer ||
!aRenderer->GetCanvasClient()) {
return;
}
uint64_t asyncID = aRenderer->GetCanvasClientAsyncID();
if (asyncID == 0 || mAsyncID == asyncID) {
return;
}
static_cast<ShadowLayerForwarder*>(GetForwarder())
->AttachAsyncCompositable(asyncID, mLayer);
mAsyncID = asyncID;
}
void
CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
@ -125,7 +106,6 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
t->mTextureClient = mBuffer;
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize());
t->mFrameID = mFrameID;
GetForwarder()->UseTextures(this, textures);
mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
}
@ -341,38 +321,13 @@ CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory)
void
CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
Renderer renderer;
renderer.construct<ClientCanvasLayer*>(aLayer);
UpdateRenderer(aSize, renderer);
}
void
CanvasClientSharedSurface::UpdateAsync(AsyncCanvasRenderer* aRenderer)
{
Renderer renderer;
renderer.construct<AsyncCanvasRenderer*>(aRenderer);
UpdateRenderer(aRenderer->GetSize(), renderer);
}
void
CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
{
GLContext* gl = nullptr;
ClientCanvasLayer* layer = nullptr;
AsyncCanvasRenderer* asyncRenderer = nullptr;
if (aRenderer.constructed<ClientCanvasLayer*>()) {
layer = aRenderer.ref<ClientCanvasLayer*>();
gl = layer->mGLContext;
} else {
asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
gl = asyncRenderer->mGLContext;
}
auto gl = aLayer->mGLContext;
gl->MakeCurrent();
RefPtr<TextureClient> newFront;
if (layer && layer->mGLFrontbuffer) {
mShSurfClient = CloneSurface(layer->mGLFrontbuffer.get(), layer->mFactory.get());
if (aLayer->mGLFrontbuffer) {
mShSurfClient = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
if (!mShSurfClient) {
gfxCriticalError() << "Invalid canvas front buffer";
return;
@ -396,30 +351,14 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
if (needsReadback) {
TextureFlags flags = TextureFlags::IMMUTABLE;
CompositableForwarder* shadowForwarder = nullptr;
if (layer) {
flags |= layer->Flags();
shadowForwarder = layer->ClientManager()->AsShadowForwarder();
} else {
MOZ_ASSERT(asyncRenderer);
flags |= mTextureFlags;
shadowForwarder = GetForwarder();
}
TextureFlags flags = aLayer->Flags() |
TextureFlags::IMMUTABLE;
auto manager = aLayer->ClientManager();
auto shadowForwarder = manager->AsShadowForwarder();
auto layersBackend = shadowForwarder->GetCompositorBackendType();
mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
if (asyncRenderer) {
// Above codes will readback the GLContext to mReadbackClient
// in order to send frame to compositor. We copy from this
// TextureClient directly by calling CopyFromTextureClient().
// Therefore, if main-thread want the content of GLContext,
// it don't have to readback it again.
asyncRenderer->CopyFromTextureClient(mReadbackClient);
}
newFront = mReadbackClient;
} else {
mReadbackClient = nullptr;
@ -432,14 +371,6 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
return;
}
mNewFront = newFront;
}
void
CanvasClientSharedSurface::Updated()
{
auto forwarder = GetForwarder();
#ifndef MOZ_WIDGET_GONK
if (mFront) {
if (mFront->GetFlags() & TextureFlags::RECYCLE) {
@ -454,13 +385,12 @@ CanvasClientSharedSurface::Updated()
// - Call RemoveTexture() after newFront's UseTextures() call.
// It could improve performance of Host side's EGL handling on gonk
AutoRemoveTexture autoRemove(this);
if (mFront && mFront != mNewFront) {
if (mFront && mFront != newFront) {
autoRemove.mTexture = mFront;
}
#endif
mFront = mNewFront;
mNewFront = nullptr;
mFront = newFront;
// Add the new TexClient.
MOZ_ALWAYS_TRUE( AddTextureClient(mFront) );
@ -469,7 +399,6 @@ CanvasClientSharedSurface::Updated()
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
t->mTextureClient = mFront;
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
t->mFrameID = mFrameID;
forwarder->UseTextures(this, textures);
}
@ -477,7 +406,6 @@ void
CanvasClientSharedSurface::ClearSurfaces()
{
mFront = nullptr;
mNewFront = nullptr;
mShSurfClient = nullptr;
mReadbackClient = nullptr;
}

View File

@ -13,11 +13,6 @@
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
// Fix X11 header brain damage that conflicts with MaybeOneOf::None
#undef None
#include "mozilla/MaybeOneOf.h"
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/gfx/Point.h" // for IntSize
@ -26,10 +21,8 @@
namespace mozilla {
namespace layers {
class AsyncCanvasRenderer;
class ClientCanvasLayer;
class CompositableForwarder;
class ShadowableLayer;
class SharedSurfaceTextureClient;
/**
@ -38,8 +31,6 @@ class SharedSurfaceTextureClient;
class CanvasClient : public CompositableClient
{
public:
typedef MaybeOneOf<ClientCanvasLayer*, AsyncCanvasRenderer*> Renderer;
/**
* Creates, configures, and returns a new canvas client. If necessary, a
* message will be sent to the compositor to create a corresponding image
@ -49,7 +40,6 @@ public:
CanvasClientSurface,
CanvasClientGLContext,
CanvasClientTypeShSurf,
CanvasClientAsync, // webgl on workers
};
static already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClientType aType,
CompositableForwarder* aFwd,
@ -57,7 +47,6 @@ public:
CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
: CompositableClient(aFwd, aFlags)
, mFrameID(0)
{
mTextureFlags = aFlags;
}
@ -68,18 +57,7 @@ public:
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) = 0;
virtual bool AddTextureClient(TextureClient* aTexture) override
{
++mFrameID;
return CompositableClient::AddTextureClient(aTexture);
}
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
virtual void Updated() { }
protected:
int32_t mFrameID;
};
// Used for 2D canvases and WebGL canvas on non-GL systems where readback is requried.
@ -107,7 +85,7 @@ public:
virtual bool AddTextureClient(TextureClient* aTexture) override
{
MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
return CanvasClient::AddTextureClient(aTexture);
return CompositableClient::AddTextureClient(aTexture);
}
virtual void OnDetach() override
@ -133,7 +111,6 @@ private:
RefPtr<SharedSurfaceTextureClient> mShSurfClient;
RefPtr<TextureClient> mReadbackClient;
RefPtr<TextureClient> mFront;
RefPtr<TextureClient> mNewFront;
void ClearSurfaces();
@ -153,54 +130,12 @@ public:
virtual void Update(gfx::IntSize aSize,
ClientCanvasLayer* aLayer) override;
void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
virtual void Updated() override;
virtual void OnDetach() override {
ClearSurfaces();
}
};
/**
* Used for OMT<canvas> uploads using the image bridge protocol.
* Actual CanvasClient is on the ImageBridgeChild thread, so we
* only forward its AsyncID here
*/
class CanvasClientBridge final : public CanvasClient
{
public:
CanvasClientBridge(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags)
: CanvasClient(aLayerForwarder, aFlags)
, mAsyncID(0)
, mLayer(nullptr)
{
}
TextureInfo GetTextureInfo() const override
{
return TextureInfo(CompositableType::IMAGE);
}
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override
{
}
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
void SetLayer(ShadowableLayer* aLayer)
{
mLayer = aLayer;
}
protected:
uint64_t mAsyncID;
ShadowableLayer* mLayer;
};
} // namespace layers
} // namespace mozilla

View File

@ -11,7 +11,6 @@
#include "SharedSurfaceGL.h" // for SurfaceFactory_GLTexture, etc
#include "ClientLayerManager.h" // for ClientLayerManager, etc
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/LayersTypes.h"
#include "nsCOMPtr.h" // for already_AddRefed
@ -20,6 +19,24 @@
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
#include "gfxPrefs.h" // for WebGLForceLayersReadback
#ifdef XP_WIN
#include "SharedSurfaceANGLE.h" // for SurfaceFactory_ANGLEShareHandle
#include "gfxWindowsPlatform.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "SharedSurfaceGralloc.h"
#endif
#ifdef XP_MACOSX
#include "SharedSurfaceIO.h"
#endif
#ifdef GL_PROVIDER_GLX
#include "GLXLibrary.h"
#include "SharedSurfaceGLX.h"
#endif
using namespace mozilla::gfx;
using namespace mozilla::gl;
@ -65,7 +82,46 @@ ClientCanvasLayer::Initialize(const Data& aData)
mFlags |= TextureFlags::NON_PREMULTIPLIED;
}
UniquePtr<SurfaceFactory> factory = GLScreenBuffer::CreateFactory(mGLContext, caps, forwarder, mFlags);
UniquePtr<SurfaceFactory> factory;
if (!gfxPrefs::WebGLForceLayersReadback()) {
switch (forwarder->GetCompositorBackendType()) {
case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX)
factory = SurfaceFactory_IOSurface::Create(mGLContext, caps, forwarder, mFlags);
#elif defined(MOZ_WIDGET_GONK)
factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
#elif defined(GL_PROVIDER_GLX)
if (sGLXLibrary.UseSurfaceSharing())
factory = SurfaceFactory_GLXDrawable::Create(mGLContext, caps, forwarder, mFlags);
#else
if (mGLContext->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(mGLContext, caps, forwarder,
mFlags);
}
}
#endif
break;
}
case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
// Enable surface sharing only if ANGLE and compositing devices
// are both WARP or both not WARP
if (mGLContext->IsANGLE() &&
(mGLContext->IsWARP() == gfxWindowsPlatform::GetPlatform()->IsWARP()) &&
gfxWindowsPlatform::GetPlatform()->CompositorD3D11TextureSharingWorks())
{
factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps, forwarder,
mFlags);
}
#endif
break;
}
default:
break;
}
}
if (mGLFrontbuffer) {
// We're using a source other than the one in the default screen.
@ -89,6 +145,11 @@ ClientCanvasLayer::RenderLayer()
RenderMaskLayers(this);
if (!IsDirty()) {
return;
}
Painted();
if (!mCanvasClient) {
TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
if (mOriginPos == gl::OriginPos::BottomLeft) {
@ -111,24 +172,11 @@ ClientCanvasLayer::RenderLayer()
return;
}
if (HasShadow()) {
if (mAsyncRenderer) {
static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(this);
} else {
mCanvasClient->Connect();
ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
}
mCanvasClient->Connect();
ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
}
}
if (mCanvasClient && mAsyncRenderer) {
mCanvasClient->UpdateAsync(mAsyncRenderer);
}
if (!IsDirty()) {
return;
}
Painted();
FirePreTransactionCallback();
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
@ -141,10 +189,6 @@ ClientCanvasLayer::RenderLayer()
CanvasClient::CanvasClientType
ClientCanvasLayer::GetCanvasClientType()
{
if (mAsyncRenderer) {
return CanvasClient::CanvasClientAsync;
}
if (mGLContext) {
return CanvasClient::CanvasClientTypeShSurf;
}

View File

@ -97,6 +97,7 @@ protected:
TextureFlags mFlags;
friend class DeprecatedCanvasClient2D;
friend class CanvasClient2D;
friend class CanvasClientSharedSurface;
};

View File

@ -169,7 +169,6 @@ TextureChild::ActorDestroy(ActorDestroyReason why)
{
if (mTextureClient) {
mTextureClient->mActor = nullptr;
mTextureClient->mAllocator = nullptr;
}
mWaitForRecycle = nullptr;
mKeep = nullptr;

View File

@ -21,7 +21,6 @@
#include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
#include "mozilla/ipc/Transport.h" // for Transport
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
#include "mozilla/media/MediaSystemResourceManagerChild.h" // for MediaSystemResourceManagerChild
#include "mozilla/layers/CompositableClient.h" // for CompositableChild, etc
@ -232,19 +231,6 @@ static void CreateImageClientSync(RefPtr<ImageClient>* result,
barrier->NotifyAll();
}
// dispatched function
static void CreateCanvasClientSync(ReentrantMonitor* aBarrier,
CanvasClient::CanvasClientType aType,
TextureFlags aFlags,
RefPtr<CanvasClient>* const outResult,
bool* aDone)
{
ReentrantMonitorAutoEnter autoMon(*aBarrier);
*outResult = sImageBridgeChildSingleton->CreateCanvasClientNow(aType, aFlags);
*aDone = true;
aBarrier->NotifyAll();
}
static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
{
MessageLoop *parentMsgLoop = parent->GetMessageLoop();
@ -283,14 +269,9 @@ ImageBridgeChild::Connect(CompositableClient* aCompositable,
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(!mShuttingDown);
uint64_t id = 0;
PImageContainerChild* imageContainerChild = nullptr;
if (aImageContainer)
imageContainerChild = aImageContainer->GetPImageContainerChild();
PCompositableChild* child =
SendPCompositableConstructor(aCompositable->GetTextureInfo(),
imageContainerChild, &id);
aImageContainer->GetPImageContainerChild(), &id);
MOZ_ASSERT(child);
aCompositable->InitIPDLActor(child, id);
}
@ -393,35 +374,6 @@ void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient,
NewRunnableFunction(&ReleaseImageClientNow, aClient, aChild));
}
static void ReleaseCanvasClientNow(CanvasClient* aClient)
{
MOZ_ASSERT(InImageBridgeChildThread());
aClient->Release();
}
// static
void ImageBridgeChild::DispatchReleaseCanvasClient(CanvasClient* aClient)
{
if (!aClient) {
return;
}
if (!IsCreated()) {
// CompositableClient::Release should normally happen in the ImageBridgeChild
// thread because it usually generate some IPDL messages.
// However, if we take this branch it means that the ImageBridgeChild
// has already shut down, along with the CompositableChild, which means no
// message will be sent and it is safe to run this code from any thread.
MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
aClient->Release();
return;
}
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(&ReleaseCanvasClientNow, aClient));
}
static void ReleaseTextureClientNow(TextureClient* aClient)
{
MOZ_ASSERT(InImageBridgeChildThread());
@ -460,7 +412,7 @@ static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContaine
sImageBridgeChildSingleton->EndTransaction();
}
// static
//static
void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
ImageContainer* aContainer)
{
@ -480,51 +432,6 @@ void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
}
static void UpdateAsyncCanvasRendererSync(AsyncCanvasRenderer* aWrapper,
ReentrantMonitor* aBarrier,
bool* const outDone)
{
ImageBridgeChild::UpdateAsyncCanvasRendererNow(aWrapper);
ReentrantMonitorAutoEnter autoMon(*aBarrier);
*outDone = true;
aBarrier->NotifyAll();
}
// static
void ImageBridgeChild::UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aWrapper)
{
aWrapper->GetCanvasClient()->UpdateAsync(aWrapper);
if (InImageBridgeChildThread()) {
UpdateAsyncCanvasRendererNow(aWrapper);
return;
}
ReentrantMonitor barrier("UpdateAsyncCanvasRenderer Lock");
ReentrantMonitorAutoEnter autoMon(barrier);
bool done = false;
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(&UpdateAsyncCanvasRendererSync, aWrapper, &barrier, &done));
// should stop the thread until the CanvasClient has been created on
// the other thread
while (!done) {
barrier.Wait();
}
}
// static
void ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
{
MOZ_ASSERT(aWrapper);
sImageBridgeChildSingleton->BeginTransaction();
aWrapper->GetCanvasClient()->Updated();
sImageBridgeChildSingleton->EndTransaction();
}
static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer,
AsyncTransactionWaiter* aWaiter)
{
@ -542,7 +449,7 @@ static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer,
aWaiter->DecrementWaitCount();
}
// static
//static
void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
ImageContainer* aContainer)
{
@ -798,42 +705,6 @@ ImageBridgeChild::CreateImageClientNow(CompositableType aType,
return client.forget();
}
already_AddRefed<CanvasClient>
ImageBridgeChild::CreateCanvasClient(CanvasClient::CanvasClientType aType,
TextureFlags aFlag)
{
if (InImageBridgeChildThread()) {
return CreateCanvasClientNow(aType, aFlag);
}
ReentrantMonitor barrier("CreateCanvasClient Lock");
ReentrantMonitorAutoEnter autoMon(barrier);
bool done = false;
RefPtr<CanvasClient> result = nullptr;
GetMessageLoop()->PostTask(FROM_HERE,
NewRunnableFunction(&CreateCanvasClientSync,
&barrier, aType, aFlag, &result, &done));
// should stop the thread until the CanvasClient has been created on the
// other thread
while (!done) {
barrier.Wait();
}
return result.forget();
}
already_AddRefed<CanvasClient>
ImageBridgeChild::CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
TextureFlags aFlag)
{
RefPtr<CanvasClient> client
= CanvasClient::CreateCanvasClient(aType, this, aFlag);
MOZ_ASSERT(client, "failed to create CanvasClient");
if (client) {
client->Connect();
}
return client.forget();
}
bool
ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,

View File

@ -12,7 +12,6 @@
#include "mozilla/RefPtr.h" // for already_AddRefed
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTrackerHolder
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/PImageBridgeChild.h"
@ -33,7 +32,6 @@ class Shmem;
namespace layers {
class AsyncCanvasRenderer;
class AsyncTransactionTracker;
class ImageClient;
class ImageContainer;
@ -212,20 +210,12 @@ public:
ImageContainer* aImageContainer);
already_AddRefed<ImageClient> CreateImageClientNow(CompositableType aType,
ImageContainer* aImageContainer);
already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClient::CanvasClientType aType,
TextureFlags aFlag);
already_AddRefed<CanvasClient> CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
TextureFlags aFlag);
static void DispatchReleaseImageClient(ImageClient* aClient,
PImageContainerChild* aChild = nullptr);
static void DispatchReleaseCanvasClient(CanvasClient* aClient);
static void DispatchReleaseTextureClient(TextureClient* aClient);
static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer);
static void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient);
static void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient);
/**
* Flush all Images sent to CompositableHost.
*/

View File

@ -58,7 +58,7 @@ parent:
sync Stop();
sync PCompositable(TextureInfo aInfo,
nullable PImageContainer aImageContainer) returns (uint64_t id);
PImageContainer aImageContainer) returns (uint64_t id);
async PTexture(SurfaceDescriptor aSharedData, TextureFlags aTextureFlags);
async PMediaSystemResourceManager();
async PImageContainer();

View File

@ -107,7 +107,6 @@ EXPORTS.mozilla.layers += [
'apz/util/ChromeProcessController.h',
'apz/util/DoubleTapToZoom.h',
'apz/util/InputAPZContext.h',
'AsyncCanvasRenderer.h',
'AtomicRefCountedWithFinalize.h',
'AxisPhysicsModel.h',
'AxisPhysicsMSDModel.h',
@ -253,7 +252,6 @@ UNIFIED_SOURCES += [
'apz/util/ChromeProcessController.cpp',
'apz/util/DoubleTapToZoom.cpp',
'apz/util/InputAPZContext.cpp',
'AsyncCanvasRenderer.cpp',
'AxisPhysicsModel.cpp',
'AxisPhysicsMSDModel.cpp',
'basic/BasicCanvasLayer.cpp',

View File

@ -84,22 +84,6 @@ public:
}
};
class AppendAppNotesRunnable : public nsCancelableRunnable {
public:
explicit AppendAppNotesRunnable(nsAutoCString aFeatureStr)
: mFeatureString(aFeatureStr)
{
}
NS_IMETHOD Run() override {
CrashReporter::AppendAppNotesToCrashReport(mFeatureString);
return NS_OK;
}
private:
nsCString mFeatureString;
};
void
ScopedGfxFeatureReporter::WriteAppNote(char statusChar)
{
@ -118,8 +102,7 @@ ScopedGfxFeatureReporter::WriteAppNote(char statusChar)
if (!gFeaturesAlreadyReported->Contains(featureString)) {
gFeaturesAlreadyReported->AppendElement(featureString);
nsCOMPtr<nsIRunnable> r = new AppendAppNotesRunnable(featureString);
NS_DispatchToMainThread(r);
CrashReporter::AppendAppNotesToCrashReport(featureString);
}
}

View File

@ -387,32 +387,12 @@ private:
DECL_GFX_PREF(Live, "test.mousescroll", MouseScrollTestingEnabled, bool, false);
DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay", UiClickHoldContextMenusDelay, int32_t, 500);
// WebGL (for pref access from Worker threads)
DECL_GFX_PREF(Live, "webgl.all-angle-options", WebGLAllANGLEOptions, bool, false);
DECL_GFX_PREF(Live, "webgl.angle.force-d3d11", WebGLANGLEForceD3D11, bool, false);
DECL_GFX_PREF(Live, "webgl.angle.try-d3d11", WebGLANGLETryD3D11, bool, false);
DECL_GFX_PREF(Once, "webgl.angle.force-d3d11", WebGLANGLEForceD3D11, bool, false);
DECL_GFX_PREF(Once, "webgl.angle.try-d3d11", WebGLANGLETryD3D11, bool, false);
DECL_GFX_PREF(Once, "webgl.angle.force-warp", WebGLANGLEForceWARP, bool, false);
DECL_GFX_PREF(Live, "webgl.bypass-shader-validation", WebGLBypassShaderValidator, bool, true);
DECL_GFX_PREF(Live, "webgl.can-lose-context-in-foreground", WebGLCanLoseContextInForeground, bool, true);
DECL_GFX_PREF(Live, "webgl.default-no-alpha", WebGLDefaultNoAlpha, bool, false);
DECL_GFX_PREF(Live, "webgl.disable-angle", WebGLDisableANGLE, bool, false);
DECL_GFX_PREF(Live, "webgl.disable-extensions", WebGLDisableExtensions, bool, false);
DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat",
WebGLDisableFailIfMajorPerformanceCaveat, bool, false);
DECL_GFX_PREF(Live, "webgl.disabled", WebGLDisabled, bool, false);
DECL_GFX_PREF(Live, "webgl.enable-draft-extensions", WebGLDraftExtensionsEnabled, bool, false);
DECL_GFX_PREF(Live, "webgl.enable-privileged-extensions", WebGLPrivilegedExtensionsEnabled, bool, false);
DECL_GFX_PREF(Live, "webgl.force-enabled", WebGLForceEnabled, bool, false);
DECL_GFX_PREF(Live, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false);
DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false);
DECL_GFX_PREF(Live, "webgl.max-warnings-per-context", WebGLMaxWarningsPerContext, uint32_t, 32);
DECL_GFX_PREF(Live, "webgl.min_capability_mode", WebGLMinCapabilityMode, bool, false);
DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false);
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false);
// WARNING:
// Please make sure that you've added your new preference to the list above in alphabetical order.

View File

@ -12,9 +12,6 @@
#include "gfxDrawable.h"
#include "imgIEncoder.h"
#include "mozilla/Base64.h"
#include "mozilla/dom/ImageEncoder.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/gfx/Logging.h"
@ -24,7 +21,6 @@
#include "nsComponentManagerUtils.h"
#include "nsIClipboardHelper.h"
#include "nsIFile.h"
#include "nsIGfxInfo.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsRegion.h"
@ -1547,125 +1543,6 @@ gfxUtils::CopyAsDataURI(DrawTarget* aDT)
}
}
/* static */ void
gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
uint8_t** outImageBuffer,
int32_t* outFormat)
{
*outImageBuffer = nullptr;
*outFormat = 0;
DataSourceSurface::MappedSurface map;
if (!aSurface->Map(DataSourceSurface::MapType::READ, &map))
return;
uint32_t bufferSize = aSurface->GetSize().width * aSurface->GetSize().height * 4;
uint8_t* imageBuffer = new (fallible) uint8_t[bufferSize];
if (!imageBuffer) {
aSurface->Unmap();
return;
}
memcpy(imageBuffer, map.mData, bufferSize);
aSurface->Unmap();
int32_t format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
if (!aIsAlphaPremultiplied) {
// We need to convert to INPUT_FORMAT_RGBA, otherwise
// we are automatically considered premult, and unpremult'd.
// Yes, it is THAT silly.
// Except for different lossy conversions by color,
// we could probably just change the label, and not change the data.
gfxUtils::ConvertBGRAtoRGBA(imageBuffer, bufferSize);
format = imgIEncoder::INPUT_FORMAT_RGBA;
}
*outImageBuffer = imageBuffer;
*outFormat = format;
}
/* static */ nsresult
gfxUtils::GetInputStream(gfx::DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
const char* aMimeType,
const char16_t* aEncoderOptions,
nsIInputStream** outStream)
{
nsCString enccid("@mozilla.org/image/encoder;2?type=");
enccid += aMimeType;
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(enccid.get());
if (!encoder)
return NS_ERROR_FAILURE;
nsAutoArrayPtr<uint8_t> imageBuffer;
int32_t format = 0;
GetImageBuffer(aSurface, aIsAlphaPremultiplied, getter_Transfers(imageBuffer), &format);
if (!imageBuffer)
return NS_ERROR_FAILURE;
return dom::ImageEncoder::GetInputStream(aSurface->GetSize().width,
aSurface->GetSize().height,
imageBuffer, format,
encoder, aEncoderOptions, outStream);
}
class GetFeatureStatusRunnable final : public dom::workers::WorkerMainThreadRunnable
{
public:
GetFeatureStatusRunnable(dom::workers::WorkerPrivate* workerPrivate,
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
int32_t feature,
int32_t* status)
: WorkerMainThreadRunnable(workerPrivate)
, mGfxInfo(gfxInfo)
, mFeature(feature)
, mStatus(status)
, mNSResult(NS_OK)
{
}
bool MainThreadRun() override
{
if (mGfxInfo) {
mNSResult = mGfxInfo->GetFeatureStatus(mFeature, mStatus);
}
return true;
}
nsresult GetNSResult() const
{
return mNSResult;
}
protected:
~GetFeatureStatusRunnable() {}
private:
nsCOMPtr<nsIGfxInfo> mGfxInfo;
int32_t mFeature;
int32_t* mStatus;
nsresult mNSResult;
};
/* static */ nsresult
gfxUtils::ThreadSafeGetFeatureStatus(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
int32_t feature, int32_t* status)
{
if (!NS_IsMainThread()) {
dom::workers::WorkerPrivate* workerPrivate =
dom::workers::GetCurrentThreadWorkerPrivate();
nsRefPtr<GetFeatureStatusRunnable> runnable =
new GetFeatureStatusRunnable(workerPrivate, gfxInfo, feature, status);
runnable->Dispatch(workerPrivate->GetJSContext());
return runnable->GetNSResult();
}
return gfxInfo->GetFeatureStatus(feature, status);
}
/* static */ bool
gfxUtils::DumpDisplayList() {
return gfxPrefs::LayoutDumpDisplayList();

View File

@ -17,8 +17,6 @@
class gfxASurface;
class gfxDrawable;
class nsIInputStream;
class nsIGfxInfo;
class nsIntRegion;
class nsIPresShell;
@ -283,21 +281,6 @@ public:
static nsCString GetAsDataURI(DrawTarget* aDT);
static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface);
static void GetImageBuffer(DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
uint8_t** outImageBuffer,
int32_t* outFormat);
static nsresult GetInputStream(DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
const char* aMimeType,
const char16_t* aEncoderOptions,
nsIInputStream** outStream);
static nsresult ThreadSafeGetFeatureStatus(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
int32_t feature,
int32_t* status);
/**
* Copy to the clipboard as a PNG encoded Data URL.
*/

View File

@ -272,7 +272,6 @@ GENERATED_FILES = [
]
LOCAL_INCLUDES += [
'/dom/workers',
'/dom/xml',
]

View File

@ -195,20 +195,17 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
// Copy some memory. It will be automatically freed by the destructor.
bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
// Adopt some memory. It will be automatically freed by the destructor.
// data must have been allocated by the JS engine (e.g., extracted via
// JSAutoStructuredCloneBuffer::steal).
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
// Release the buffer and transfer ownership to the caller. The caller is
// responsible for calling JS_ClearStructuredClone or feeding the memory
// back to JSAutoStructuredCloneBuffer::adopt.
void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr,
const JSStructuredCloneCallbacks** callbacks=nullptr, void** closure=nullptr);
void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr);
// Abandon ownership of any transferable objects stored in the buffer,
// without freeing the buffer itself. Useful when copying the data out into

View File

@ -2054,7 +2054,7 @@ JS_StructuredClone(JSContext* cx, HandleValue value, MutableHandleValue vp,
JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other)
{
ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
other.steal(&data_, &nbytes_, &version_);
}
JSAutoStructuredCloneBuffer&
@ -2063,7 +2063,7 @@ JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other)
MOZ_ASSERT(&other != this);
clear();
ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
other.steal(&data_, &nbytes_, &version_);
return *this;
}
@ -2088,9 +2088,7 @@ JSAutoStructuredCloneBuffer::clear(const JSStructuredCloneCallbacks* optionalCal
}
bool
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version,
const JSStructuredCloneCallbacks* callbacks,
void* closure)
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version)
{
// transferable objects cannot be copied
if (StructuredCloneHasTransferObjects(data_, nbytes_))
@ -2106,45 +2104,31 @@ JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32
data_ = newData;
nbytes_ = nbytes;
version_ = version;
callbacks_ = callbacks;
closure_ = closure;
ownTransferables_ = NoTransferables;
return true;
}
void
JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t version,
const JSStructuredCloneCallbacks* callbacks,
void* closure)
JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t version)
{
clear();
data_ = data;
nbytes_ = nbytes;
version_ = version;
callbacks_ = callbacks;
closure_ = closure;
ownTransferables_ = OwnsTransferablesIfAny;
}
void
JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp,
const JSStructuredCloneCallbacks** callbacks,
void** closure)
JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp)
{
*datap = data_;
*nbytesp = nbytes_;
if (versionp)
*versionp = version_;
if (callbacks)
*callbacks = callbacks_;
if (closure)
*closure = closure_;
data_ = nullptr;
nbytes_ = 0;
version_ = 0;
callbacks_ = 0;
closure_ = 0;
ownTransferables_ = NoTransferables;
}

View File

@ -4166,8 +4166,6 @@ pref("webgl.angle.force-d3d11", false);
pref("webgl.angle.force-warp", false);
#endif
pref("gfx.offscreencanvas.enabled", false);
#ifdef MOZ_WIDGET_GONK
pref("gfx.gralloc.fence-with-readpixels", false);
#endif