Canvas: don't crash when getContext("2d") is called on destruction.

We'd assume that a Window existed when that's not always the case.
For example:

import QtQuick 2.4
import QtQuick.Window 2.2
Window {
    Loader {
        sourceComponent: Canvas {
            Component.onDestruction: getContext("2d")
        }
        Component.onCompleted: active = false
    }
}

Change-Id: I5f30876e21ced5658adfa3bac494fd4196e0a7e3
Task-number: QTBUG-42222
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
This commit is contained in:
Mitch Curtis 2015-01-26 15:53:15 +01:00 committed by Mitch Curtis
parent 15ffff51b5
commit 93affd9ff6
3 changed files with 54 additions and 0 deletions

View File

@ -1124,6 +1124,9 @@ bool QQuickCanvasItem::createContext(const QString &contextType)
{
Q_D(QQuickCanvasItem);
if (!window())
return false;
if (contextType == QLatin1String("2d")) {
if (d->contextType.compare(QLatin1String("2d"), Qt::CaseInsensitive) != 0) {
d->contextType = QLatin1String("2d");

View File

@ -25,6 +25,11 @@ TestCase {
return [];
}
function renderStrategyToString(renderStrategy) {
return renderStrategy === Canvas.Immediate ? "Canvas.Immediate" :
(renderStrategy === Canvas.Threaded ? "Canvas.Threaded" : "Canvas.Cooperative");
}
function createCanvasObject(data) {
return component.createObject(testCase, data.properties);
}

View File

@ -595,5 +595,51 @@ CanvasTestCase {
canvas.destroy();
}
function test_getContextOnDestruction_data() {
// We want to test all possible combinations deemed valid by the testcase,
// but we can't test FramebufferObject due to difficulties ignoring the "available" warning.
var allData = testData("2d");
var ourData = [];
for (var i = 0; i < allData.length; ++i) {
if (allData[i].properties.renderTarget !== Canvas.FramebufferObject) {
var row = allData[i].properties;
row.tag = allData[i].tag;
ourData.push(row);
}
}
return ourData;
}
function test_getContextOnDestruction(data) {
try {
var canvasWindow = Qt.createQmlObject("
import QtQuick 2.4\n
import QtQuick.Window 2.2\n
Window {\n
function test() {\n
loader.active = true\n
loader.active = false\n
}\n
Loader {\n
id: loader\n
active: false\n
sourceComponent: Canvas {\n
renderStrategy: " + renderStrategyToString(data.renderStrategy) + "\n
Component.onDestruction: getContext(\"2d\")
}\n
}\n
}\n",
testCase);
verify(canvasWindow);
canvasWindow.test();
// Shouldn't crash when destruction is done.
wait(0);
} catch (exception) {
fail(exception.message);
}
}
}