Back out 9 changesets (bug 801176) for frequent crashes in test_offscreencanvas_dynamic_fallback.html

Backed out changeset 82320c900699 (bug 801176)
Backed out changeset 624fb8512ba5 (bug 801176)
Backed out changeset a2a7b1c4dc5b (bug 801176)
Backed out changeset e210473d793c (bug 801176)
Backed out changeset 0fb279e041e1 (bug 801176)
Backed out changeset c090dc98c670 (bug 801176)
Backed out changeset fc509e59a0cd (bug 801176)
Backed out changeset 134a8c56335a (bug 801176)
Backed out changeset 2022afa9aef2 (bug 801176)
This commit is contained in:
Phil Ringnalda 2016-03-05 07:20:47 -08:00
parent 399d5724c9
commit cabee82044
31 changed files with 488 additions and 950 deletions

View File

@ -97,7 +97,6 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/unused.h"
#include "mozilla/StaticMutex.h"
#include "nsCCUncollectableMarker.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
@ -107,7 +106,6 @@
#include "mozilla/dom/SVGMatrix.h"
#include "mozilla/dom/TextMetrics.h"
#include "mozilla/dom/SVGMatrix.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/FloatingPoint.h"
#include "nsGlobalWindow.h"
#include "GLContext.h"
@ -163,7 +161,6 @@ const Float SIGMA_MAX = 100;
/* Memory reporter stuff */
static int64_t gCanvasAzureMemoryUsed = 0;
static StaticMutex sMemoryReportMutex;
// This is KIND_OTHER because it's not always clear where in memory the pixels
// of a canvas are stored. Furthermore, this memory will be tracked by the
@ -172,7 +169,7 @@ class Canvas2dPixelsReporter final : public nsIMemoryReporter
{
~Canvas2dPixelsReporter() {}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) override
@ -686,9 +683,7 @@ CanvasGradient::AddColorStop(float aOffset, const nsAString& aColorstr, ErrorRes
}
nscolor color;
nsCOMPtr<nsIPresShell> presShell = NS_IsMainThread() && mContext
? mContext->GetPresShell()
: nullptr;
nsCOMPtr<nsIPresShell> presShell = mContext ? mContext->GetPresShell() : nullptr;
if (!nsRuleNode::ComputeColor(value, presShell ? presShell->GetPresContext() : nullptr,
nullptr, color)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
@ -886,7 +881,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CanvasRenderingContext2D)
// since we're logically destructed at this point.
CanvasRenderingContext2D::RemoveDemotableContext(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCanvasElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOffscreenCanvas)
for (uint32_t i = 0; i < tmp->mStyleStack.Length(); i++) {
ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[Style::STROKE]);
ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[Style::FILL]);
@ -904,7 +898,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCanvasElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOffscreenCanvas)
for (uint32_t i = 0; i < tmp->mStyleStack.Length(); i++) {
ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[Style::STROKE], "Stroke CanvasPattern");
ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[Style::FILL], "Fill CanvasPattern");
@ -981,8 +974,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
sNumLivingContexts++;
// The default is to use OpenGL mode
if (NS_IsMainThread() &&
gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) {
if (gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) {
mDrawObserver = new CanvasDrawObserver(this);
} else {
mRenderingMode = RenderingMode::SoftwareBackendMode;
@ -1023,7 +1015,7 @@ bool
CanvasRenderingContext2D::ParseColor(const nsAString& aString,
nscolor* aColor)
{
nsIDocument* document = NS_IsMainThread() && mCanvasElement
nsIDocument* document = mCanvasElement
? mCanvasElement->OwnerDoc()
: nullptr;
@ -1040,11 +1032,8 @@ CanvasRenderingContext2D::ParseColor(const nsAString& aString,
*aColor = value.GetColorValue();
} else {
// otherwise resolve it
nsCOMPtr<nsIPresShell> presShell = NS_IsMainThread()
? GetPresShell()
: nullptr;
RefPtr<nsStyleContext> parentContext = nullptr;
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
RefPtr<nsStyleContext> parentContext;
if (mCanvasElement && mCanvasElement->IsInDoc()) {
// Inherit from the canvas element.
parentContext = nsComputedDOMStyle::GetStyleContextForElement(
@ -1068,7 +1057,6 @@ CanvasRenderingContext2D::Reset()
// only do this for non-docshell created contexts,
// since those are the ones that we created a surface for
if (mTarget && IsTargetValid() && !mDocShell) {
StaticMutexAutoLock lock(sMemoryReportMutex);
gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
}
@ -1150,17 +1138,15 @@ CanvasRenderingContext2D::Redraw()
mIsEntireFrameInvalid = true;
if (NS_IsMainThread()) {
if (!mCanvasElement) {
NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
return NS_OK;
}
nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
mCanvasElement->InvalidateCanvasContent(nullptr);
if (!mCanvasElement) {
NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
return NS_OK;
}
nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
mCanvasElement->InvalidateCanvasContent(nullptr);
return NS_OK;
}
@ -1181,16 +1167,14 @@ CanvasRenderingContext2D::Redraw(const gfx::Rect& aR)
return;
}
if (NS_IsMainThread()) {
if (!mCanvasElement) {
NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
return;
}
nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
mCanvasElement->InvalidateCanvasContent(&aR);
if (!mCanvasElement) {
NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
return;
}
nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
mCanvasElement->InvalidateCanvasContent(&aR);
}
void
@ -1433,35 +1417,32 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
}
if (NS_IsMainThread() &&
mode == RenderingMode::OpenGLBackendMode &&
gfxPlatform::GetPlatform()->UseAcceleratedCanvas() &&
CheckSizeForSkiaGL(size)) {
DemoteOldestContextIfNecessary();
mBufferProvider = nullptr;
if (layerManager) {
if (mode == RenderingMode::OpenGLBackendMode &&
gfxPlatform::GetPlatform()->UseAcceleratedCanvas() &&
CheckSizeForSkiaGL(size)) {
DemoteOldestContextIfNecessary();
mBufferProvider = nullptr;
#if USE_SKIA_GPU
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
if (glue && glue->GetGrContext() && glue->GetGLContext()) {
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
mIsSkiaGL = true;
} else {
gfxCriticalNote << "Failed to create a SkiaGL DrawTarget, falling back to software\n";
mode = RenderingMode::SoftwareBackendMode;
if (glue && glue->GetGrContext() && glue->GetGLContext()) {
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
mIsSkiaGL = true;
} else {
gfxCriticalNote << "Failed to create a SkiaGL DrawTarget, falling back to software\n";
mode = RenderingMode::SoftwareBackendMode;
}
}
}
#endif
}
}
if (!mBufferProvider) {
if (layerManager) {
if (!mBufferProvider) {
mBufferProvider = layerManager->CreatePersistentBufferProvider(size, format);
} else {
mBufferProvider = new PersistentBufferProviderBasic(size, format, gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
}
}
@ -1481,12 +1462,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
}
gCanvasAzureMemoryUsed += mWidth * mHeight * 4;
JSContext* context;
if (NS_IsMainThread()) {
context = nsContentUtils::GetCurrentJSContext();
} else {
context = nsContentUtils::GetDefaultJSContextForThread();
}
JSContext* context = nsContentUtils::GetCurrentJSContext();
if (context) {
JS_updateMallocCounter(context, mWidth * mHeight * 4);
}
@ -3480,43 +3456,6 @@ CanvasRenderingContext2D::GetHitRegionRect(Element* aElement, nsRect& aRect)
return false;
}
/* static */ bool
CanvasRenderingContext2D::PrefCanvasPathEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("canvas.path.enabled");
} else {
workers::WorkerPrivate* workerPrivate = workers::GetWorkerPrivateFromContext(aCx);
MOZ_ASSERT(workerPrivate);
return (workerPrivate->CanvasPathEnabled() && workerPrivate->OffscreenCanvasEnabled());
}
}
void
CanvasRenderingContext2D::GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& aRetval)
{
if (mCanvasElement) {
MOZ_RELEASE_ASSERT(!mOffscreenCanvas);
if (mCanvasElement->IsInNativeAnonymousSubtree()) {
aRetval.SetNull();
} else {
aRetval.SetValue().SetAsHTMLCanvasElement() = mCanvasElement;
}
} else if (mOffscreenCanvas) {
aRetval.SetValue().SetAsOffscreenCanvas() = mOffscreenCanvas;
} else {
aRetval.SetNull();
}
}
void
CanvasRenderingContext2D::Commit()
{
if (mOffscreenCanvas) {
mOffscreenCanvas->CommitFrameToCompositor();
}
}
/**
* Used for nsBidiPresUtils::ProcessText
*/

View File

@ -46,7 +46,6 @@ class OwningStringOrCanvasGradientOrCanvasPattern;
class TextMetrics;
class CanvasFilterChainObserver;
class CanvasPath;
class OwningHTMLCanvasElementOrOffscreenCanvas;
extern const mozilla::gfx::Float SIGMA_MAX;
@ -80,10 +79,6 @@ public:
return mCanvasElement->GetOriginalCanvas();
}
void GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& aRetval);
void Commit();
void Save();
void Restore();
void Scale(double aX, double aY, mozilla::ErrorResult& aError);
@ -548,7 +543,6 @@ public:
// return true and fills in the bound rect if element has a hit region.
bool GetHitRegionRect(Element* aElement, nsRect& aRect) override;
static bool PrefCanvasPathEnabled(JSContext* aCx, JSObject* aObj);
protected:
nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
uint32_t aWidth, uint32_t aHeight,

View File

@ -89,13 +89,11 @@ OffscreenCanvas::ClearResources()
mCanvasClient = nullptr;
if (mCanvasRenderer) {
if (mCanvasRenderer->mGLContext) {
nsCOMPtr<nsIThread> activeThread = mCanvasRenderer->GetActiveThread();
MOZ_RELEASE_ASSERT(activeThread);
bool current;
activeThread->IsOnCurrentThread(&current);
MOZ_RELEASE_ASSERT(current);
}
nsCOMPtr<nsIThread> activeThread = mCanvasRenderer->GetActiveThread();
MOZ_RELEASE_ASSERT(activeThread);
bool current;
activeThread->IsOnCurrentThread(&current);
MOZ_RELEASE_ASSERT(current);
mCanvasRenderer->SetCanvasClient(nullptr);
mCanvasRenderer->mContext = nullptr;
mCanvasRenderer->mGLContext = nullptr;
@ -115,6 +113,7 @@ OffscreenCanvas::GetContext(JSContext* aCx,
return nullptr;
}
// We only support WebGL in workers for now
CanvasContextType contextType;
if (!CanvasUtils::GetCanvasContextType(aContextId, &contextType)) {
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
@ -123,7 +122,6 @@ OffscreenCanvas::GetContext(JSContext* aCx,
if (!(contextType == CanvasContextType::WebGL1 ||
contextType == CanvasContextType::WebGL2 ||
contextType == CanvasContextType::Canvas2D ||
contextType == CanvasContextType::ImageBitmap))
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
@ -140,37 +138,33 @@ OffscreenCanvas::GetContext(JSContext* aCx,
return nullptr;
}
if (mCanvasRenderer && ImageBridgeChild::IsCreated()) {
mCanvasRenderer->mContext = mCurrentContext;
TextureFlags flags = TextureFlags::ORIGIN_BOTTOM_LEFT;
if (mCanvasRenderer) {
if (contextType == CanvasContextType::WebGL1 ||
contextType == CanvasContextType::WebGL2) {
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);
mCanvasClient = ImageBridgeChild::GetSingleton()->
CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags).take();
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();
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);
UniquePtr<gl::SurfaceFactory> factory =
gl::GLScreenBuffer::CreateFactory(gl, caps, forwarder, flags);
if (factory)
screen->Morph(Move(factory));
} else if (contextType == CanvasContextType::Canvas2D) {
mCanvasRenderer->mGLContext = nullptr;
mCanvasClient = ImageBridgeChild::GetSingleton()->
CreateCanvasClient(CanvasClient::CanvasClientSurface, flags).take();
if (factory)
screen->Morph(Move(factory));
}
}
mCanvasRenderer->SetCanvasClient(mCanvasClient);
}
return result;
@ -206,11 +200,11 @@ OffscreenCanvas::CommitFrameToCompositor()
mAttrDirty = false;
}
if (mCurrentContext && mCanvasRenderer) {
if (mCanvasRenderer->mGLContext) {
static_cast<WebGLContext*>(mCurrentContext.get())->PresentScreenBuffer();
}
if (mCurrentContext) {
static_cast<WebGLContext*>(mCurrentContext.get())->PresentScreenBuffer();
}
if (mCanvasRenderer && mCanvasRenderer->mGLContext) {
mCanvasRenderer->NotifyElementAboutInvalidation();
ImageBridgeChild::GetSingleton()->
UpdateAsyncCanvasRenderer(mCanvasRenderer);

View File

@ -293,7 +293,7 @@ skip-if = (e10s && debug && os == 'win')
tags = offscreencanvas
[test_offscreencanvas_toimagebitmap.html]
tags = offscreencanvas
[test_offscreencanvas_basic_operations.html]
[test_offscreencanvas_basic_webgl.html]
tags = offscreencanvas
[test_offscreencanvas_dynamic_fallback.html]
tags = offscreencanvas

View File

@ -2,8 +2,6 @@
(function(){
var port = null;
var INIT_CONST_CANVAS_SIZE = 64;
var COUNT_FOR_SIZE_CHANGE = 3;
function isInWorker() {
try {
@ -37,8 +35,8 @@ function drawCount(count) {
postMessageGeneral({type: "draw", count: count});
}
function sendBlob(canvasType, blob) {
postMessageGeneral({type: "blob", canvasType: canvasType, blob: blob});
function sendBlob(blob) {
postMessageGeneral({type: "blob", blob: blob});
}
function sendImageBitmap(img) {
@ -49,41 +47,6 @@ function sendImageBitmap(img) {
}
}
function sendImageBitmapWithSize(img, size) {
postMessage({type: "imagebitmapwithsize", bitmap: img, size: size});
}
//--------------------------------------------------------------------
// Canvas 2D Drawing Functions
//--------------------------------------------------------------------
function createDrawFunc2D(canvas) {
var context2d;
try {
context2d = canvas.getContext("2d");
} catch (e) {}
if (!context2d) {
ok(false, "Canvas 2D is unavailable");
return null;
}
return function(prefix, needCommitFrame) {
if (prefix) {
prefix = "[" + prefix + "] ";
} else {
prefix = "";
}
context2d.rect(0, 0, canvas.width, canvas.height);
context2d.fillStyle = "#00FF00";
context2d.fill();
if (needCommitFrame) {
context2d.commit();
ok(true, prefix + 'Frame is committed');
}
};
}
//--------------------------------------------------------------------
// WebGL Drawing Functions
//--------------------------------------------------------------------
@ -219,43 +182,33 @@ function createDrawFunc(canvas) {
}
/* entry point */
function entryFunction(canvasTypeStr, testTypeStr, subtests, offscreenCanvas) {
var canvasType = canvasTypeStr;
var testType = testTypeStr;
function entryFunction(testStr, subtests, offscreenCanvas) {
var test = testStr;
var canvas = offscreenCanvas;
if ((testType == "imagebitmap") || (testType == "changesize")) {
canvas = new OffscreenCanvas(INIT_CONST_CANVAS_SIZE, INIT_CONST_CANVAS_SIZE);
if (test == "webgl_imagebitmap") {
canvas = new OffscreenCanvas(64, 64);
}
if (testType != "subworker") {
if (test != "subworker") {
ok(canvas, "Canvas successfully transfered to worker");
ok(canvas.getContext, "Canvas has getContext");
ok(canvas.width == INIT_CONST_CANVAS_SIZE,
"OffscreenCanvas width should be " + INIT_CONST_CANVAS_SIZE);
ok(canvas.height == INIT_CONST_CANVAS_SIZE,
"OffscreenCanvas height should be " + INIT_CONST_CANVAS_SIZE);
ok(canvas.width == 64, "OffscreenCanvas width should be 64");
ok(canvas.height == 64, "OffscreenCanvas height should be 64");
}
var draw;
if (testType != "subworker") {
if (canvasType == "2d") {
draw = createDrawFunc2D(canvas);
} else if (canvasType == "webgl") {
draw = createDrawFunc(canvas);
} else {
ok(false, "Unexpected canvasType");
}
//------------------------------------------------------------------------
// Basic WebGL test
//------------------------------------------------------------------------
if (test == "webgl") {
draw = createDrawFunc(canvas);
if (!draw) {
finish();
return;
}
}
//------------------------------------------------------------------------
// Basic test
//------------------------------------------------------------------------
if (testType == "basic") {
var count = 0;
var iid = setInterval(function() {
if (count++ > 20) {
@ -270,7 +223,12 @@ function entryFunction(canvasTypeStr, testTypeStr, subtests, offscreenCanvas) {
//------------------------------------------------------------------------
// Test dynamic fallback
//------------------------------------------------------------------------
else if (testType == "fallback") {
else if (test == "webgl_fallback") {
draw = createDrawFunc(canvas);
if (!draw) {
return;
}
var count = 0;
var iid = setInterval(function() {
++count;
@ -281,44 +239,67 @@ function entryFunction(canvasTypeStr, testTypeStr, subtests, offscreenCanvas) {
//------------------------------------------------------------------------
// Test toBlob
//------------------------------------------------------------------------
else if (testType == "toblob") {
else if (test == "webgl_toblob") {
draw = createDrawFunc(canvas);
if (!draw) {
return;
}
draw("", false);
canvas.toBlob().then(function(blob) {
sendBlob(canvasType, blob);
sendBlob(blob);
});
}
//------------------------------------------------------------------------
// Test toImageBitmap
//------------------------------------------------------------------------
else if (testType == "imagebitmap") {
else if (test == "webgl_imagebitmap") {
draw = createDrawFunc(canvas);
if (!draw) {
return;
}
draw("", false);
var imgBitmap = canvas.transferToImageBitmap();
sendImageBitmap(imgBitmap);
finish();
}
//------------------------------------------------------------------------
// Canvas Size Change from Worker
//------------------------------------------------------------------------
else if (testType == "changesize") {
var count = 0;
var iid = setInterval(function() {
if (count++ > COUNT_FOR_SIZE_CHANGE) {
finish();
clearInterval(iid);
return;
}
else if (test == "webgl_changesize") {
draw = createDrawFunc(canvas);
if (!draw) {
finish();
return;
}
canvas.width = INIT_CONST_CANVAS_SIZE * count;
canvas.height = INIT_CONST_CANVAS_SIZE * count;
draw("loop " + count, true);
var imgBitmap = canvas.transferToImageBitmap();
sendImageBitmapWithSize(imgBitmap, INIT_CONST_CANVAS_SIZE * count);
draw("64x64", true);
setTimeout(function() {
canvas.width = 128;
canvas.height = 128;
draw("Increased to 128x128", true);
setTimeout(function() {
canvas.width = 32;
canvas.width = 32;
draw("Decreased to 32x32", true);
setTimeout(function() {
canvas.width = 64;
canvas.height = 64;
draw("Increased to 64x64", true);
ok(true, "Worker is done");
finish();
}, 0);
}, 0);
}, 0);
}
//------------------------------------------------------------------------
// Using OffscreenCanvas from sub workers
//------------------------------------------------------------------------
else if (testType == "subworker") {
else if (test == "subworker") {
/* subworker tests take a list of tests to run on children */
var stillRunning = 0;
subtests.forEach(function (subtest) {
@ -339,10 +320,10 @@ function entryFunction(canvasTypeStr, testTypeStr, subtests, offscreenCanvas) {
};
var findTransferables = function(t) {
if (t.testType == "subworker") {
if (t.test == "subworker") {
var result = [];
t.subtests.forEach(function(testType) {
result = result.concat(findTransferables(testType));
t.subtests.forEach(function(test) {
result = result.concat(findTransferables(test));
});
return result;
@ -358,16 +339,14 @@ function entryFunction(canvasTypeStr, testTypeStr, subtests, offscreenCanvas) {
onmessage = function(evt) {
port = evt.ports[0];
entryFunction(evt.data.canvasType, evt.data.testType, evt.data.subtests,
evt.data.canvas);
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.canvasType, evt.data.testType, evt.data.subtests,
evt.data.canvas);
entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
});
port.start();

View File

@ -4,58 +4,28 @@
<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}, "*");
}
function countTest(count) {
parent.postMessage({type: "countTest", count: count}, "*");
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, "*");
}
function createCanvas() {
countTest(1);
var htmlCanvas = document.createElement('canvas');
ok(htmlCanvas, "Should have HTML canvas element");
ok(htmlCanvas.transferControlToOffscreen,
"HTMLCanvasElement has transferControlToOffscreen function");
htmlCanvas.width = 64;
htmlCanvas.height = 64;
document.body.appendChild(htmlCanvas);
return htmlCanvas;
}
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
function transferCtrlToOffscreen(canvas) {
var offscreencanvas = canvas.transferControlToOffscreen();
ok(offscreencanvas, "Expected transferControlToOffscreen to succeed");
return offscreencanvas;
}
function CreateMessagChannel () {
var msgChannel = new MessageChannel();
msgChannel.port1.onmessage = function(evt) {
parent.postMessage(evt.data, "*");
}
return msgChannel;
}
var offscreen2dCanvas = transferCtrlToOffscreen(createCanvas());
var msgChannel2d = CreateMessagChannel();
var offscreenWebGLCanvas = transferCtrlToOffscreen(createCanvas());
var msgChannelwebgl = CreateMessagChannel();
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
navigator.serviceWorker.ready.then(function() {
navigator.serviceWorker.controller.postMessage({canvasType: '2d',
testType: 'basic',
canvas: offscreen2dCanvas},
[offscreen2dCanvas,
msgChannel2d.port2]);
});
navigator.serviceWorker.ready.then(function() {
navigator.serviceWorker.controller.postMessage({canvasType: 'webgl',
testType: 'basic',
canvas: offscreenWebGLCanvas},
[offscreenWebGLCanvas,
msgChannelwebgl.port2]);
navigator.serviceWorker.controller.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas, messageChannel.port2]);
});
</script>
</body>

View File

@ -1,80 +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-ref" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function createCanvas() {
var htmlCanvas = document.createElement('canvas');
htmlCanvas.width = 64;
htmlCanvas.height = 64;
document.body.appendChild(htmlCanvas);
return htmlCanvas;
}
function testToDataURL(canvas, test) {
// 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();
ok(c.toDataURL() == canvas.toDataURL(), "[" + test + "]" +
"toDataURL should return a 64x64 green square");
}
function runTest() {
var stillRunning = 0;
var startWorker = function(canvas, canvasType) {
stillRunning++;
var worker = new Worker("offscreencanvas.js");
ok(canvas, "[" + canvasType + "]" + "Should have HTML canvas element");
ok(worker, "[" + canvasType + "]" + "Web worker successfully created");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, "[" + canvasType + "]" + msg.name);
}
if (msg.type == "finish") {
testToDataURL(canvas, canvasType);
worker.terminate();
if (--stillRunning == 0) {
SimpleTest.finish();
}
}
}
ok(canvas.transferControlToOffscreen, "[" + canvasType + "]" +
"HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = canvas.transferControlToOffscreen();
ok(offscreenCanvas, "[" + canvasType + "]" +
"Expected transferControlToOffscreen to succeed");
worker.postMessage({canvasType: canvasType, testType: 'basic',
canvas: offscreenCanvas}, [offscreenCanvas]);
}
startWorker(createCanvas(), '2d');
startWorker(createCanvas(), 'webgl');
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
</script>
</body>
</html>

View File

@ -0,0 +1,62 @@
<!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

@ -34,64 +34,46 @@ function getRefSnapshot(initWithMask) {
return result;
}
function runTest() {
var startWorker = function(canvas, canvasType, testType, initWithMask) {
var canvas = createCanvas(initWithMask);
var worker = new Worker("offscreencanvas.js");
function runTest(initWithMask) {
var htmlCanvas = createCanvas(initWithMask);
var worker = new Worker("offscreencanvas.js");
ok(canvas.transferControlToOffscreen, "[" + canvasType + "]" +
"HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = canvas.transferControlToOffscreen();
ok(offscreenCanvas, "[" + canvasType + "]" +
"Expected transferControlToOffscreen to succeed");
worker.postMessage({canvasType: canvasType, testType: testType,
canvas: offscreenCanvas}, [offscreenCanvas]);
return new Promise(function(resolved) {
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, "[" + canvasType + "]" + msg.name);
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')";
}
if (msg.type == "draw") {
if (msg.count === 10) {
// Change the fallback state dynamically when drawing count reaches 10.
if (initWithMask) {
canvas.style.mask = "";
} else {
canvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
}
} else if (msg.count === 20) {
var snapshotFallback = snapshotWindow(window);
worker.terminate();
document.body.removeChild(canvas);
} 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], "[" + canvasType + "]" +
"after dynamic fallback, screenshots should be the same");
var results = compareSnapshots(snapshotFallback, getRefSnapshot(initWithMask), true);
ok(results[0], "after dynamic fallback, screenshots should be the same");
resolved();
}
if (initWithMask) {
SimpleTest.finish();
} else {
runTest(true);
}
}
});
}
}
startWorker(createCanvas(false), '2d', 'fallback', false).then(function () {
startWorker(createCanvas(true), '2d', 'fallback', true).then(function () {
startWorker(createCanvas(false), 'webgl', 'fallback', false).then(function () {
startWorker(createCanvas(true), 'webgl', 'fallback', true).then(function () {
SimpleTest.finish();
})})})});
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
worker.postMessage({test: 'webgl_fallback', canvas: offscreenCanvas}, [offscreenCanvas]);
}
SpecialPowers.pushPrefEnv({'set': [
['gfx.offscreencanvas.enabled', true],
['webgl.force-enabled', true],
]}, runTest);
]}, runTest.bind(false));
</script>
</body>

View File

@ -11,8 +11,6 @@
So we choose 8 workers, 4 of them run basic webgl drawing test and
others run size changing test.
-->
<canvas id="c1" width="64" height="64"></canvas>
<canvas id="c-ref" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
@ -28,60 +26,34 @@ function createCanvas() {
function runTest() {
var stillRunning = 0;
var startWorker = function(canvas, canvasType, testType) {
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, "[" + canvasType + "]" + msg.name);
}
if (msg.type == "imagebitmapwithsize") {
// Fill c-ref with green color.
var c = document.getElementById("c-ref");
var ctx = c.getContext("2d");
c.width = msg.size;
c.height = msg.size;
ctx.rect(0, 0, c.width, c.height);
ctx.fillStyle = "#00FF00";
ctx.fill();
// The ownership of msg.bitmap should be transferred to canvas when we
// called transferImageBitmap. So we test if the ownership is actually
// transferred here.
var htmlCanvas = document.getElementById("c1");
htmlCanvas.width = msg.size;
htmlCanvas.height = msg.size;
var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
bitmapRenderer.transferImageBitmap(msg.bitmap);
ok(c.toDataURL() == htmlCanvas.toDataURL(), "[" + canvasType + "]" +
"toDataURL should return a " + msg.size + "x" + msg.size +
" green square");
ok(msg.result, msg.name);
}
if (msg.type == "finish") {
worker.terminate();
if (--stillRunning == 0) {
if (--stillRunning == 0)
SimpleTest.finish();
}
}
}
var offscreenCanvas = canvas.transferControlToOffscreen();
worker.postMessage({canvasType: canvasType, testType: testType,
canvas: offscreenCanvas}, [offscreenCanvas]);
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(), '2d', 'basic');
startWorker(createCanvas(), 'webgl', 'basic');
startWorker(createCanvas(), 'webgl');
}
for (var i = 0; i < 4; i++) {
startWorker(createCanvas(), '2d', 'changesize');
startWorker(createCanvas(), 'webgl', 'changesize');
startWorker(createCanvas(), 'webgl_changesize');
}
}

View File

@ -34,38 +34,32 @@ function runTest() {
function() { htmlCanvas.height = 128; },
"Can't change html canvas' height after transferControlToOffscreen");
ok(!htmlCanvas.getContext("2d"), "Can't get 2d Context after transferControlToOffscreen");
ok(!htmlCanvas.getContext("webgl"), "Can't get webgl Context after transferControlToOffscreen");
ok(!htmlCanvas.getContext("webgl2"), "Can't get webgl2 Context after transferControlToOffscreen");
ok(!htmlCanvas.getContext("bitmaprenderer"),
"Can't get bitmaprenderer Context 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.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.height = 128; },
"Can't change transfered worker canvas height");
SimpleTest.doesThrow(function() {
offscreenCanvas.getContext("2d");
}, "Can't get 2d Context on transfered worker canvas");
SimpleTest.doesThrow(
function() { offscreenCanvas.getContext("2d") },
"Can't getContext on transfered worker canvas");
SimpleTest.doesThrow(function() {
offscreenCanvas.getContext("webgl");
}, "Can't get webgl Context 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 get webgl2 Context on transfered worker canvas");
SimpleTest.doesThrow(function() {
offscreenCanvas.getContext("bitmaprenderer");
}, "Can't get bitmaprenderer Context 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]);

View File

@ -11,7 +11,6 @@
SimpleTest.waitForExplicitFinish();
function runTest() {
var stillRunning = 0;
var registration;
window.onmessage = function(evt) {
@ -19,14 +18,9 @@ function runTest() {
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "countTest") {
stillRunning++;
}
if (msg.type == "finish") {
registration.unregister().then(function() {
if (--stillRunning == 0) {
SimpleTest.finish();
}
SimpleTest.finish();
});
}
}

View File

@ -6,47 +6,33 @@
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function createCanvas() {
var htmlCanvas = document.createElement('canvas');
function runTest() {
var htmlCanvas = document.getElementById("c");
var worker = new SharedWorker("offscreencanvas.js");
ok(htmlCanvas, "Should have HTML canvas element");
ok(htmlCanvas.transferControlToOffscreen,
"HTMLCanvasElement has transferControlToOffscreen function");
htmlCanvas.width = 64;
htmlCanvas.height = 64;
document.body.appendChild(htmlCanvas);
return htmlCanvas;
}
ok(worker, "Web worker successfully created");
function transferCtrlToOffscreen(canvas) {
var offscreencanvas = canvas.transferControlToOffscreen();
ok(offscreencanvas, "Expected transferControlToOffscreen to succeed");
return offscreencanvas;
}
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
function testShareWorker(worker, canvasType) {
var offscreenCanvas = transferCtrlToOffscreen(createCanvas());
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({canvasType: canvasType, testType: 'basic',
canvas: offscreenCanvas}, [offscreenCanvas]);
worker.port.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
},
"OffscreenCanvas cannot transfer to shared worker"
);
}
function runTest() {
var worker = new SharedWorker("offscreencanvas.js");
ok(worker, "Web worker successfully created");
worker.port.start();
testShareWorker(worker, '2d');
testShareWorker(worker, 'webgl');
SimpleTest.finish();
}

View File

@ -6,70 +6,29 @@
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c1" width="64" height="64"></canvas>
<canvas id="c-ref" width="64" height="64"></canvas>
<canvas id="c" width="64" height="64"></canvas>
<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(canvasType) {
stillRunning++;
var worker = new Worker("offscreencanvas.js");
ok(worker, "[" + canvasType + "]" + "Web worker successfully created");
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, "[" + canvasType + "]" + msg.name);
}
if (msg.type == "imagebitmapwithsize") {
// Fill c-ref with green color.
var c = document.getElementById("c-ref");
var ctx = c.getContext("2d");
c.width = msg.size;
c.height = msg.size;
ctx.rect(0, 0, c.width, c.height);
ctx.fillStyle = "#00FF00";
ctx.fill();
// The ownership of msg.bitmap should be transferred to canvas when we
// called transferImageBitmap. So we test if the ownership is actually
// transferred here.
var htmlCanvas = document.getElementById("c1");
htmlCanvas.width = msg.size;
htmlCanvas.height = msg.size;
var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
bitmapRenderer.transferImageBitmap(msg.bitmap);
console.log("rawm = " + c.toDataURL());
console.log("raww = " + htmlCanvas.toDataURL());
ok(c.toDataURL() == htmlCanvas.toDataURL(), "[" + canvasType + "]" +
"toDataURL should return a " + msg.size + "x" + msg.size +
" green square");
}
if (msg.type == "finish") {
worker.terminate();
if (--stillRunning == 0) {
SimpleTest.finish();
}
}
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();
}
worker.postMessage({canvasType: canvasType, testType: 'changesize'});
}
startWorker('2d');
startWorker('webgl');
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
worker.postMessage({test: 'webgl_changesize', canvas: offscreenCanvas}, [offscreenCanvas]);
}
SpecialPowers.pushPrefEnv({'set': [

View File

@ -24,68 +24,60 @@ function createCanvas() {
}
function runTest() {
var subworkerRunning = 0;
var startWorker = function(canvasType) {
subworkerRunning++;
var worker = new Worker("offscreencanvas.js");
var worker = new Worker("offscreencanvas.js");
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, "[" + canvasType + "]" + msg.name);
}
if (msg.type == "finish") {
worker.terminate();
if (--subworkerRunning == 0) {
SimpleTest.finish();
}
}
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.testType == "subworker") {
var result = [];
t.subtests.forEach(function(testType) {
result = result.concat(findTransferables(testType));
});
return result;
} else {
return [t.canvas];
}
};
var testData =
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'basic', canvas: createCanvas()},
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'basic', canvas: createCanvas()},
{canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
{canvasType: canvasType, testType: 'basic', canvas: createCanvas()}
]},
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'basic', canvas: createCanvas()},
{canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
{canvasType: canvasType, testType: 'basic', canvas: createCanvas()}
]},
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'changesize', canvas: createCanvas()},
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'subworker', subtests: [
{canvasType: canvasType, testType: 'changesize', canvas: createCanvas()}
]}
]}
]},
]}
]};
worker.postMessage(testData, findTransferables(testData));
}
startWorker('2d');
startWorker('webgl');
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': [

View File

@ -7,26 +7,13 @@
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c" width="64" height="64"></canvas>
<canvas id="c-mt" width="64" height="64"></canvas>
<canvas id="c-ref" width="64" height="64"></canvas>
<script>
SimpleTest.waitForExplicitFinish();
function createCanvas() {
var htmlCanvas = document.createElement('canvas');
htmlCanvas.width = 64;
htmlCanvas.height = 64;
document.body.appendChild(htmlCanvas);
return htmlCanvas;
}
function TransferCtrlToOffscreen(canvas) {
ok(canvas, "Should have HTML canvas element");
ok(canvas.transferControlToOffscreen,
"HTMLCanvasElement has transferControlToOffscreen function");
return canvas.transferControlToOffscreen();
}
function testBlob(blob, callback) {
// testing toBlob
// Fill c-ref with green color.
@ -37,14 +24,15 @@ function testBlob(blob, callback) {
ctx.fill();
var reader = new FileReader();
reader.onload = function(e) {
ok(c.toDataURL() == e.target.result,
"toBlob should return a 64x64 green square");
ok(c.toDataURL() == e.target.result, "toBlob should return a 64x64 green square");
callback();
};
reader.readAsDataURL(blob);
}
function runTestOnMainThread() {
var htmlCanvas = document.getElementById("c-mt");
ok(htmlCanvas, "Should have HTML canvas element");
window.onmessage = function(evt) {
var msg = evt.data || {};
@ -56,15 +44,22 @@ function runTestOnMainThread() {
}
}
var offscreenCanvas = TransferCtrlToOffscreen(createCanvas());
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
entryFunction('webgl', 'toblob', '', offscreenCanvas);
entryFunction('webgl_toblob', '', offscreenCanvas);
}
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") {
@ -72,27 +67,18 @@ function runTest() {
}
if (msg.type == "blob") {
testBlob(msg.blob, function() {
if (msg.canvasType == "webgl") {
worker.terminate();
runTestOnMainThread();
} else {
// Start to test toblob for webgl
offscreenCanvas = TransferCtrlToOffscreen(createCanvas());
worker.postMessage({canvasType: 'webgl', testType: 'toblob',
canvas: offscreenCanvas}, [offscreenCanvas]);
}
worker.terminate();
runTestOnMainThread();
});
}
}
ok(worker, "Web worker successfully created");
ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
var offscreenCanvas = TransferCtrlToOffscreen(createCanvas());
var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
// Start to test toblob for 2d
worker.postMessage({canvasType: '2d', testType: 'toblob',
canvas: offscreenCanvas}, [offscreenCanvas]);
worker.postMessage({test: 'webgl_toblob', canvas: offscreenCanvas}, [offscreenCanvas]);
}
SpecialPowers.pushPrefEnv({'set': [

View File

@ -14,58 +14,49 @@
SimpleTest.waitForExplicitFinish();
function runTest() {
var startWorker = function(canvasType) {
var worker = new Worker("offscreencanvas.js");
ok(worker, "Web worker successfully created");
var worker = new Worker("offscreencanvas.js");
worker.postMessage({canvasType: canvasType, testType: 'imagebitmap'});
ok(worker, "Web worker successfully created");
return new Promise(function(resolved) {
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "imagebitmap") {
// testing toBlob
// 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();
worker.onmessage = function(evt) {
var msg = evt.data || {};
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "imagebitmap") {
// testing toBlob
// 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");
var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
bitmapRenderer.transferImageBitmap(msg.bitmap);
var htmlCanvas = document.getElementById("c");
var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
bitmapRenderer.transferImageBitmap(msg.bitmap);
ok(c.toDataURL() == htmlCanvas.toDataURL(),
"imagebitmap should return a 64x64 green square");
ok(c.toDataURL() == htmlCanvas.toDataURL(),
"imagebitmap should return a 64x64 green square");
// The ownership of msg.bitmap should be transferred to canvas "c" when
// we called transferImageBitmap. So we test if the ownership is actually
// transferred here.
var htmlCanvas = document.getElementById("c2");
var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
bitmapRenderer.transferImageBitmap(msg.bitmap);
// The ownership of msg.bitmap should be transferred to canvas "c" when
// we called transferImageBitmap. So we test if the ownership is actually
// transferred here.
var htmlCanvas = document.getElementById("c2");
var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
bitmapRenderer.transferImageBitmap(msg.bitmap);
SimpleTest.doesThrow(
function() { c2.toDataURL(); },
"ImageBitmap has been transferred, toDataURL will throw.");
}
if (msg.type == "finish") {
worker.terminate();
resolved();
}
}
});
SimpleTest.doesThrow(
function() { c2.toDataURL(); },
"ImageBitmap has been transferred, toDataURL will throw.");
worker.terminate();
SimpleTest.finish();
}
}
startWorker('2d').then(function () {
startWorker('webgl').then(function () {
SimpleTest.finish();
})});
worker.postMessage({test: 'webgl_imagebitmap'});
}
SpecialPowers.pushPrefEnv({'set': [

View File

@ -785,7 +785,6 @@ HTMLCanvasElement::TransferControlToOffscreen(ErrorResult& aRv)
RefPtr<AsyncCanvasRenderer> renderer = GetAsyncCanvasRenderer();
renderer->SetWidth(sz.width);
renderer->SetHeight(sz.height);
renderer->SetOpaque(GetIsOpaque());
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(OwnerDoc()->GetInnerWindow());

View File

@ -31,15 +31,11 @@ typedef (HTMLImageElement or
HTMLVideoElement or
ImageBitmap) CanvasImageSource;
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface CanvasRenderingContext2D {
// back-reference to the canvas. Might be null if we're not
// associated with a canvas.
readonly attribute CanvasObj? canvas;
void commit();
readonly attribute HTMLCanvasElement? canvas;
// state
void save(); // push state on state stack
@ -65,9 +61,6 @@ interface CanvasRenderingContext2D {
[Throws]
attribute DOMString globalCompositeOperation; // (default source-over)
// drawing images
// NOT IMPLEMENTED attribute boolean imageSmoothingEnabled; // (default true)
// colors and styles (see also the CanvasDrawingStyles interface)
attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black)
attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black)
@ -87,6 +80,9 @@ interface CanvasRenderingContext2D {
attribute double shadowBlur; // (default 0)
attribute DOMString shadowColor; // (default transparent black)
[Pref="canvas.filters.enabled", SetterThrows]
attribute DOMString filter; // (default empty string = no filter)
// rects
[LenientFloat]
void clearRect(double x, double y, double w, double h);
@ -101,7 +97,10 @@ interface CanvasRenderingContext2D {
void fill(Path2D path, optional CanvasWindingRule winding = "nonzero");
void stroke();
void stroke(Path2D path);
[Exposed=Window, Pref="canvas.focusring.enabled", Throws] void drawFocusIfNeeded(Element element);
[Pref="canvas.focusring.enabled", Throws] void drawFocusIfNeeded(Element element);
// NOT IMPLEMENTED void drawSystemFocusRing(Path path, HTMLElement element);
[Pref="canvas.customfocusring.enabled"] boolean drawCustomFocusRing(Element element);
// NOT IMPLEMENTED boolean drawCustomFocusRing(Path path, HTMLElement element);
// NOT IMPLEMENTED void scrollPathIntoView();
// NOT IMPLEMENTED void scrollPathIntoView(Path path);
void clip(optional CanvasWindingRule winding = "nonzero");
@ -113,13 +112,16 @@ interface CanvasRenderingContext2D {
boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
// text (see also the CanvasDrawingStyles interface)
[Exposed=Window, Throws, LenientFloat]
[Throws, LenientFloat]
void fillText(DOMString text, double x, double y, optional double maxWidth);
[Exposed=Window, Throws, LenientFloat]
[Throws, LenientFloat]
void strokeText(DOMString text, double x, double y, optional double maxWidth);
[Exposed=Window, NewObject, Throws]
[NewObject, Throws]
TextMetrics measureText(DOMString text);
// drawing images
// NOT IMPLEMENTED attribute boolean imageSmoothingEnabled; // (default true)
[Throws, LenientFloat]
void drawImage(CanvasImageSource image, double dx, double dy);
[Throws, LenientFloat]
@ -128,9 +130,9 @@ interface CanvasRenderingContext2D {
void drawImage(CanvasImageSource image, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh);
// hit regions
[Exposed=Window, Pref="canvas.hitregions.enabled", Throws] void addHitRegion(optional HitRegionOptions options);
[Exposed=Window, Pref="canvas.hitregions.enabled"] void removeHitRegion(DOMString id);
[Exposed=Window, Pref="canvas.hitregions.enabled"] void clearHitRegions();
[Pref="canvas.hitregions.enabled", Throws] void addHitRegion(optional HitRegionOptions options);
[Pref="canvas.hitregions.enabled"] void removeHitRegion(DOMString id);
[Pref="canvas.hitregions.enabled"] void clearHitRegions();
// pixel manipulation
[NewObject, Throws]
@ -143,27 +145,6 @@ interface CanvasRenderingContext2D {
void putImageData(ImageData imagedata, double dx, double dy);
[Throws]
void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
};
CanvasRenderingContext2D implements CanvasDrawingStyles;
CanvasRenderingContext2D implements CanvasPathMethods;
[Exposed=(Window,Worker)]
partial interface CanvasRenderingContext2D {
[Throws]
attribute any mozDash; /* default |null| */
[LenientFloat]
attribute double mozDashOffset; /* default 0.0 */
};
[Exposed=Window]
partial interface CanvasRenderingContext2D {
[Pref="canvas.filters.enabled", SetterThrows]
attribute DOMString filter; // (default empty string = no filter)
// NOT IMPLEMENTED void drawSystemFocusRing(Path path, HTMLElement element);
[Pref="canvas.customfocusring.enabled"] boolean drawCustomFocusRing(Element element);
// NOT IMPLEMENTED boolean drawCustomFocusRing(Path path, HTMLElement element);
// Mozilla-specific stuff
// FIXME Bug 768048 mozCurrentTransform/mozCurrentTransformInverse should return a WebIDL array.
@ -174,6 +155,12 @@ partial interface CanvasRenderingContext2D {
attribute DOMString mozFillRule; /* "evenodd", "nonzero" (default) */
[Throws]
attribute any mozDash; /* default |null| */
[LenientFloat]
attribute double mozDashOffset; /* default 0.0 */
[SetterThrows]
attribute DOMString mozTextStyle;
@ -262,8 +249,10 @@ partial interface CanvasRenderingContext2D {
[ChromeOnly]
void demote();
};
CanvasRenderingContext2D implements CanvasDrawingStyles;
CanvasRenderingContext2D implements CanvasPathMethods;
[NoInterfaceObject, Exposed=(Window,Worker)]
[NoInterfaceObject]
interface CanvasDrawingStyles {
// line caps/joins
[LenientFloat]
@ -280,15 +269,13 @@ interface CanvasDrawingStyles {
[LenientFloat] attribute double lineDashOffset;
// text
[Exposed=Window, SetterThrows]
[SetterThrows]
attribute DOMString font; // (default 10px sans-serif)
[Exposed=Window]
attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start")
[Exposed=Window]
attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic")
};
[NoInterfaceObject, Exposed=(Window,Worker)]
[NoInterfaceObject]
interface CanvasPathMethods {
// shared path API methods
void closePath();
@ -314,8 +301,6 @@ interface CanvasPathMethods {
// NOT IMPLEMENTED [LenientFloat] void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, boolean anticlockwise);
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface CanvasGradient {
// opaque object
[Throws]
@ -323,8 +308,6 @@ interface CanvasGradient {
void addColorStop(float offset, DOMString color);
};
[Exposed=(Window,Worker),
Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
interface CanvasPattern {
// opaque object
// [Throws, LenientFloat] - could not do this overload because of bug 1020975
@ -359,8 +342,7 @@ interface TextMetrics {
};
[Exposed=(Window,Worker),
Func="CanvasRenderingContext2D::PrefCanvasPathEnabled",
[Pref="canvas.path.enabled",
Constructor,
Constructor(Path2D other),
Constructor(DOMString pathString)]

View File

@ -63,8 +63,6 @@ interface MozCanvasPrintState
void done();
};
typedef (HTMLCanvasElement or OffscreenCanvas) CanvasObj;
callback PrintCallback = void(MozCanvasPrintState ctx);
callback FileCallback = void(Blob file);

View File

@ -524,7 +524,7 @@ interface WebGLRenderingContext {
const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
// The canvas might actually be null in some cases, apparently.
readonly attribute CanvasObj? canvas;
readonly attribute (HTMLCanvasElement or OffscreenCanvas)? canvas;
readonly attribute GLsizei drawingBufferWidth;
readonly attribute GLsizei drawingBufferHeight;

View File

@ -36,7 +36,6 @@ WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcache.enabled", RequestCacheEnabled, REQUESTCACHE_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
WORKER_SIMPLE_PREF("canvas.path.enabled", CanvasPathEnabled, CANVASPATH_ENABLED)
WORKER_PREF("dom.workers.latestJSVersion", JSVersionChanged)
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)

View File

@ -11,7 +11,6 @@
#include "GLReadTexImageHelper.h"
#include "GLScreenBuffer.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/dom/CanvasRenderingContext2D.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/layers/TextureClient.h"
@ -19,14 +18,8 @@
#include "mozilla/ReentrantMonitor.h"
#include "nsIRunnable.h"
#include "nsThreadUtils.h"
#include "PersistentBufferProvider.h"
namespace mozilla {
namespace dom {
class CanvasRenderingContext2D;
}
namespace layers {
AsyncCanvasRenderer::AsyncCanvasRenderer()
@ -241,85 +234,32 @@ AsyncCanvasRenderer::UpdateTarget()
return surface.forget();
}
void
AsyncCanvasRenderer::UpdateTarget(TextureClient* aTexture)
{
if (!mContext) {
return;
}
mBufferProvider = nullptr;
dom::CanvasRenderingContext2D* context2D = static_cast<dom::CanvasRenderingContext2D*>(mContext);
if (!context2D) {
return;
}
mBufferProvider = context2D->GetBufferProvider(nullptr);
if (!mBufferProvider) {
return;
}
RefPtr<gfx::SourceSurface> surface = mBufferProvider->GetSnapshot();
if (surface) {
NS_ASSERTION(surface, "Must have surface to draw!");
aTexture->UpdateFromSurface(surface);
surface = nullptr;
}
}
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());
if (!mContext) {
return nullptr;
}
gfx::DataSourceSurface::ScopedMap srcMap(mSurfaceForBasic, gfx::DataSourceSurface::READ);
gfx::DataSourceSurface::ScopedMap dstMap(result, gfx::DataSourceSurface::WRITE);
if (mGLContext) {
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();
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 {
dom::CanvasRenderingContext2D* context2D = static_cast<dom::CanvasRenderingContext2D*>(mContext);
if (!context2D) {
return nullptr;
}
mBufferProvider = context2D->GetBufferProvider(nullptr);
if (!mBufferProvider) {
return nullptr;
}
RefPtr<gfx::SourceSurface> sourceSurface = mBufferProvider->GetSnapshot();
if (!sourceSurface) {
return nullptr;
}
return sourceSurface->GetDataSurface();
return UpdateTarget();
}
}
@ -334,10 +274,8 @@ AsyncCanvasRenderer::GetInputStream(const char *aMimeType,
return NS_ERROR_FAILURE;
}
// Only handle y flip in webgl.
RefPtr<gfx::DataSourceSurface> dataSurf = mGLContext
? gl::YInvertImageSurface(surface)
: surface;
// Handle y flip.
RefPtr<gfx::DataSourceSurface> dataSurf = gl::YInvertImageSurface(surface);
return gfxUtils::GetInputStream(dataSurf, false, aMimeType, aEncoderOptions, aStream);
}

View File

@ -21,7 +21,6 @@ namespace mozilla {
namespace gfx {
class DataSourceSurface;
class DrawTarget;
}
namespace gl {
@ -30,13 +29,11 @@ class GLContext;
namespace dom {
class HTMLCanvasElement;
class CanvasRenderingContext2D;
}
namespace layers {
class CanvasClient;
class PersistentBufferProvider;
class TextureClient;
/**
@ -77,23 +74,11 @@ public:
mHeight = aHeight;
}
bool GetOpaque()
{
return mOpaque;
}
void SetOpaque(bool aOpaque)
{
mOpaque = aOpaque;
}
void SetIsAlphaPremultiplied(bool aIsAlphaPremultiplied)
{
mIsAlphaPremultiplied = aIsAlphaPremultiplied;
}
void UpdateTarget(TextureClient* aTexture);
// Active thread means the thread which spawns GLContext.
void SetActiveThread();
void ResetActiveThread();
@ -145,7 +130,6 @@ public:
// canvas' surface texture destructor will deref and destroy it too early
// Only accessed in active thread.
RefPtr<gl::GLContext> mGLContext;
PersistentBufferProvider* mBufferProvider;
private:
virtual ~AsyncCanvasRenderer();
@ -154,7 +138,6 @@ private:
already_AddRefed<gfx::DataSourceSurface> UpdateTarget();
bool mIsAlphaPremultiplied;
bool mOpaque;
uint32_t mWidth;
uint32_t mHeight;

View File

@ -9,9 +9,6 @@
#include "nsPrintfCString.h" // for nsPrintfCString
#include "nsString.h" // for nsAutoCString
namespace mozilla {
namespace layers {
using namespace mozilla::layers;
void
@ -79,6 +76,3 @@ EffectVRDistortion::PrintInfo(std::stringstream& aStream, const char* aPrefix)
aStream << nsPrintfCString("EffectVRDistortion (0x%p) [hmd=%p] [render-target=%p] [texture=%p]",
this, mHMD.get(), mRenderTarget.get(), mTexture).get();
}
} // namespace layers
} // namespace mozilla

View File

@ -8,11 +8,12 @@
#include "GLReadTexImageHelper.h"
#include "GLLibraryEGL.h"
using namespace mozilla;
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
using namespace mozilla;
using namespace mozilla::gl;
static RefPtr<GLContext> sSnapshotContext;
EGLImageImage::EGLImageImage(EGLImage aImage, EGLSync aSync,

View File

@ -26,7 +26,6 @@
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
#include "TextureClientSharedSurface.h"
#include "VRManagerChild.h"
#include "gfxUtils.h"
using namespace mozilla::gfx;
using namespace mozilla::gl;
@ -71,67 +70,37 @@ CanvasClientBridge::UpdateAsync(AsyncCanvasRenderer* aRenderer)
void
CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
Renderer renderer;
renderer.construct<ClientCanvasLayer*>(aLayer);
UpdateRenderer(aSize, renderer);
}
void
CanvasClient2D::UpdateAsync(AsyncCanvasRenderer* aRenderer)
{
Renderer renderer;
renderer.construct<AsyncCanvasRenderer*>(aRenderer);
UpdateRenderer(aRenderer->GetSize(), renderer);
}
void
CanvasClient2D::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
{
ClientCanvasLayer* layer = nullptr;
AsyncCanvasRenderer* asyncRenderer = nullptr;
if (aRenderer.constructed<ClientCanvasLayer*>()) {
layer = aRenderer.ref<ClientCanvasLayer*>();
} else {
asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
}
AutoRemoveTexture autoRemove(this);
if (mBuffer &&
(mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
mPrevBuffer = mBuffer;
autoRemove.mTexture = mBuffer;
mBuffer = nullptr;
}
mBufferCreated = false;
bool bufferCreated = false;
if (!mBuffer) {
bool isOpaque;
gfxContentType contentType;
if (layer) {
isOpaque = (layer->GetContentFlags() & Layer::CONTENT_OPAQUE);
} else {
isOpaque = (asyncRenderer->GetOpaque() & Layer::CONTENT_OPAQUE);
}
contentType = isOpaque
? gfxContentType::COLOR
: gfxContentType::COLOR_ALPHA;
gfx::SurfaceFormat surfaceFormat =
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
gfxContentType contentType = isOpaque
? gfxContentType::COLOR
: gfxContentType::COLOR_ALPHA;
gfx::SurfaceFormat surfaceFormat
= gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
TextureFlags flags = TextureFlags::DEFAULT;
if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
}
flags = TextureFlags::NO_FLAGS;
mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, layer);
mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
if (!mBuffer) {
NS_WARNING("Failed to allocate the TextureClient");
return;
}
MOZ_ASSERT(mBuffer->CanExposeDrawTarget());
mBufferCreated = true;
bufferCreated = true;
}
mUpdated = false;
bool updated = false;
{
TextureClientAutoLock autoLock(mBuffer, OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
@ -139,34 +108,19 @@ CanvasClient2D::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
return;
}
if (layer) {
RefPtr<DrawTarget> target = mBuffer->BorrowDrawTarget();
if (target) {
layer->UpdateTarget(target);
}
} else {
asyncRenderer->UpdateTarget(mBuffer);
RefPtr<DrawTarget> target = mBuffer->BorrowDrawTarget();
if (target) {
aLayer->UpdateTarget(target);
updated = true;
}
mUpdated = true;
}
}
void
CanvasClient2D::Updated()
{
AutoRemoveTexture autoRemove(this);
if (mPrevBuffer) {
autoRemove.mTexture = mPrevBuffer;
mPrevBuffer = nullptr;
}
if (mBufferCreated && !AddTextureClient(mBuffer)) {
if (bufferCreated && !AddTextureClient(mBuffer)) {
mBuffer = nullptr;
return;
}
if (mUpdated) {
if (updated) {
AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
t->mTextureClient = mBuffer;
@ -184,7 +138,7 @@ CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
TextureFlags aFlags,
ClientCanvasLayer* aLayer)
{
if (aLayer && aLayer->IsGLLayer()) {
if (aLayer->IsGLLayer()) {
// We want a cairo backend here as we don't want to be copying into
// an accelerated backend and we like LockBits to work. This is currently
// the most effective way to make this work.

View File

@ -88,10 +88,7 @@ class CanvasClient2D : public CanvasClient
public:
CanvasClient2D(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags)
: CanvasClient(aLayerForwarder, aFlags),
mPrevBuffer(nullptr),
mBufferCreated(false),
mUpdated(false)
: CanvasClient(aLayerForwarder, aFlags)
{
}
@ -106,8 +103,6 @@ public:
}
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override;
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
virtual bool AddTextureClient(TextureClient* aTexture) override
{
@ -115,8 +110,6 @@ public:
return CanvasClient::AddTextureClient(aTexture);
}
virtual void Updated() override;
virtual void OnDetach() override
{
mBuffer = nullptr;
@ -129,10 +122,7 @@ private:
TextureFlags aFlags,
ClientCanvasLayer* aLayer);
RefPtr<TextureClient> mPrevBuffer;
RefPtr<TextureClient> mBuffer;
bool mBufferCreated;
bool mUpdated;
};
// Used for GL canvases where we don't need to do any readback, i.e., with a

View File

@ -112,12 +112,6 @@ InitGlobals()
static inline bool
ShouldReportErrors()
{
// we only need to do CSS parsing off the main thread for canvas-on-workers currently,
// where we don't need to report any CSS parser errors
if (!NS_IsMainThread()) {
return false;
}
if (!sConsoleService) {
if (!InitGlobals()) {
return false;
@ -153,8 +147,7 @@ ErrorReporter::~ErrorReporter()
// Schedule deferred cleanup for cached data. We want to strike a
// balance between performance and memory usage, so we only allow
// short-term caching.
if (NS_IsMainThread() && sSpecCache && sSpecCache->IsInUse() &&
!sSpecCache->IsPending()) {
if (sSpecCache && sSpecCache->IsInUse() && !sSpecCache->IsPending()) {
if (NS_FAILED(NS_DispatchToCurrentThread(sSpecCache))) {
// Peform the "deferred" cleanup immediately if the dispatch fails.
sSpecCache->Run();

View File

@ -1534,14 +1534,12 @@ CSSParserImpl::CSSParserImpl()
mWebkitBoxUnprefixState(eNotParsingDecls),
mNextFree(nullptr)
{
MOZ_COUNT_CTOR(CSSParserImpl);
}
CSSParserImpl::~CSSParserImpl()
{
mData.AssertInitialState();
mTempData.AssertInitialState();
MOZ_COUNT_DTOR(CSSParserImpl);
}
nsresult
@ -17173,29 +17171,23 @@ nsCSSParser::Startup()
nsCSSParser::nsCSSParser(mozilla::css::Loader* aLoader,
CSSStyleSheet* aSheet)
{
CSSParserImpl *impl;
if (NS_IsMainThread()) {
impl = gFreeList;
if (impl) {
gFreeList = impl->mNextFree;
impl->mNextFree = nullptr;
} else {
impl = new CSSParserImpl();
}
if (aLoader) {
impl->SetChildLoader(aLoader);
impl->SetQuirkMode(aLoader->GetCompatibilityMode() ==
eCompatibility_NavQuirks);
}
if (aSheet) {
impl->SetStyleSheet(aSheet);
}
CSSParserImpl *impl = gFreeList;
if (impl) {
gFreeList = impl->mNextFree;
impl->mNextFree = nullptr;
} else {
MOZ_ASSERT(!aLoader);
MOZ_ASSERT(!aSheet);
impl = new CSSParserImpl();
}
if (aLoader) {
impl->SetChildLoader(aLoader);
impl->SetQuirkMode(aLoader->GetCompatibilityMode() ==
eCompatibility_NavQuirks);
}
if (aSheet) {
impl->SetStyleSheet(aSheet);
}
mImpl = static_cast<void*>(impl);
}
@ -17203,26 +17195,21 @@ nsCSSParser::~nsCSSParser()
{
CSSParserImpl *impl = static_cast<CSSParserImpl*>(mImpl);
impl->Reset();
if (NS_IsMainThread()) {
impl->mNextFree = gFreeList;
gFreeList = impl;
} else {
delete impl;
}
impl->mNextFree = gFreeList;
gFreeList = impl;
}
/* static */ void
nsCSSParser::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
CSSParserImpl *tofree = gFreeList;
CSSParserImpl *next;
while (tofree)
{
next = tofree->mNextFree;
delete tofree;
tofree = next;
}
{
next = tofree->mNextFree;
delete tofree;
tofree = next;
}
}
// Wrapper methods

View File

@ -1663,6 +1663,9 @@
[CanvasRenderingContext2D interface: attribute height]
expected: FAIL
[CanvasRenderingContext2D interface: operation commit()]
expected: FAIL
[CanvasRenderingContext2D interface: attribute currentTransform]
expected: FAIL
@ -1708,6 +1711,9 @@
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "height" with the proper type (2)]
expected: FAIL
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "commit" with the proper type (3)]
expected: FAIL
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "currentTransform" with the proper type (6)]
expected: FAIL