diff --git a/src/imports/qtcanvas3d/canvas3d.cpp b/src/imports/qtcanvas3d/canvas3d.cpp
index bd1ff562e98fc6f44f50f031e1960026afa52131..e47a20c500880536d942f7b15b7d78fc383a040f 100644
--- a/src/imports/qtcanvas3d/canvas3d.cpp
+++ b/src/imports/qtcanvas3d/canvas3d.cpp
@@ -243,7 +243,6 @@ QJSValue Canvas::getContext(const QString &type, const QVariantMap &options)
 
         // Ensure ignored attributes are left to their default state
         m_contextAttribs.setPremultipliedAlpha(false);
-        m_contextAttribs.setPreserveDrawingBuffer(false);
         m_contextAttribs.setPreferLowPowerToHighPerformance(false);
         m_contextAttribs.setFailIfMajorPerformanceCaveat(false);
     }
@@ -846,6 +845,20 @@ void Canvas::renderNext()
                                          << m_displayFbo->texture()
                                          << " from FBO:" << m_displayFbo->handle();
 
+    if (m_contextAttribs.preserveDrawingBuffer()) {
+        // Copy the content of display fbo to the render fbo
+        GLint texBinding2D;
+        glGetIntegerv(GL_TEXTURE_BINDING_2D, &texBinding2D);
+
+        m_displayFbo->bind();
+        glBindTexture(GL_TEXTURE_2D, m_renderFbo->texture());
+
+        glCopyTexImage2D(GL_TEXTURE_2D, 0, m_displayFbo->format().internalTextureFormat(),
+                         0, 0, m_fboSize.width(), m_fboSize.height(), 0);
+
+        glBindTexture(GL_TEXTURE_2D, texBinding2D);
+    }
+
     // FBO ids and texture id's have been generated, we can now free the old display FBO
     delete m_oldDisplayFbo;
     m_oldDisplayFbo = 0;
diff --git a/tests/auto/qmltest/canvas3d/tst_render_preserve.js b/tests/auto/qmltest/canvas3d/tst_render_preserve.js
new file mode 100644
index 0000000000000000000000000000000000000000..f2cbe4400bc1d1379c4b1aa127d2ce7b636102cd
--- /dev/null
+++ b/tests/auto/qmltest/canvas3d/tst_render_preserve.js
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCanvas3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var gl;
+
+var colorBuffer;
+
+var vertexPositionAttribute;
+var vertexColorAttribute;
+
+var vertexBuffer;
+
+function initializeGL(canvas) {
+    gl = canvas.getContext("", {preserveDrawingBuffer:true});
+    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+    var pixelRatio = canvas.devicePixelRatio;
+    gl.viewport(0, 0, pixelRatio * canvas.width, pixelRatio * canvas.height);
+
+    initShaders();
+    initBuffers();
+}
+
+function paintGL() {
+    gl.clearColor(1.0, 0.0, 0.0, 1.0);
+    gl.clear(gl.COLOR_BUFFER_BIT);
+    gl.drawArrays(gl.TRIANGLES, 0, 3);
+}
+
+function checkPixel(x, y) {
+    var pixels = new Uint8Array(4);
+    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+    return pixels;
+}
+
+function setColor(r, g, b, a) {
+    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+    var colors = [r / 255.0, g / 255.0, b / 255.0, a / 255.0];
+    var generatedColors = [];
+    for (var i = 0; i < 4; i++)
+        generatedColors = generatedColors.concat(colors);
+    gl.bufferData(gl.ARRAY_BUFFER,
+                  new Float32Array(generatedColors),
+                  gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(vertexColorAttribute);
+    gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
+}
+
+function initBuffers()
+{
+    vertexBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+    gl.bufferData(
+                gl.ARRAY_BUFFER, new Float32Array(
+                    [-1.0, -1.0,
+                     1.0, -1.0,
+                     -1.0,  1.0
+                    ]),
+                gl.STATIC_DRAW);
+
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+    gl.vertexAttribPointer(vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
+    gl.enableVertexAttribArray(vertexPositionAttribute);
+
+    colorBuffer = gl.createBuffer();
+    setColor(0.0, 0.0, 255.0, 255.0);
+}
+
+function initShaders()
+{
+    var vertexShader = getShader(
+                gl,
+                "attribute highp vec2 aVertexPosition;                 \
+                attribute mediump vec4 aVertexColor;                   \
+                varying mediump vec4 vColor;                           \
+                void main(void) {                                      \
+                    gl_Position = vec4(aVertexPosition, 0.0, 1.0); \
+                    vColor = aVertexColor;                             \
+                }",
+                gl.VERTEX_SHADER);
+    var fragmentShader = getShader(
+                gl,
+                "varying mediump vec4 vColor;                   \
+                void main(void) {                               \
+                    gl_FragColor = vColor;                      \
+                }",
+                gl.FRAGMENT_SHADER);
+
+    var shaderProgram = gl.createProgram();
+    gl.attachShader(shaderProgram, vertexShader);
+    gl.attachShader(shaderProgram, fragmentShader);
+    gl.linkProgram(shaderProgram);
+    gl.deleteShader(vertexShader);
+    gl.deleteShader(fragmentShader);
+
+    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
+        console.log("Could not initialize shaders");
+        console.log(gl.getProgramInfoLog(shaderProgram));
+    }
+
+    gl.useProgram(shaderProgram);
+
+    vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
+    gl.enableVertexAttribArray(vertexPositionAttribute);
+    vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
+    gl.enableVertexAttribArray(vertexColorAttribute);
+}
+
+function getShader(gl, str, type) {
+    var shader = gl.createShader(type);
+    gl.shaderSource(shader, str);
+    gl.compileShader(shader);
+
+    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+        console.log("JS:Shader compile failed");
+        console.log(gl.getShaderInfoLog(shader));
+        return null;
+    }
+
+    return shader;
+}
diff --git a/tests/auto/qmltest/canvas3d/tst_render_preserve.qml b/tests/auto/qmltest/canvas3d/tst_render_preserve.qml
new file mode 100644
index 0000000000000000000000000000000000000000..5a1c25737dfa6f2a6c21d17ff2e7150110b470b9
--- /dev/null
+++ b/tests/auto/qmltest/canvas3d/tst_render_preserve.qml
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCanvas3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtCanvas3D 1.0
+import QtTest 1.0
+
+import "tst_render_preserve.js" as Content
+
+Item {
+    id: top
+    height: 300
+    width: 300
+
+    property int xpos: 0
+    property int ypos: 0
+    property var pixels
+    property int red: -1
+    property int green: -1
+    property int blue: -1
+    property int alpha: -1
+    property bool paintDone: true
+    property bool checkDone: true
+    property bool initDone: false
+
+    Canvas3D {
+        id: render_preserve
+        property bool textureLoaded: false
+        anchors.fill: parent
+        onInitializeGL: {
+            Content.initializeGL(this)
+            initDone = true
+        }
+        onPaintGL: {
+            if (!paintDone) {
+                Content.paintGL()
+                paintDone = true
+            }
+
+            if (!checkDone) {
+                pixels = Content.checkPixel(xpos, ypos)
+                red = pixels[0]
+                green = pixels[1]
+                blue = pixels[2]
+                alpha = pixels[3]
+                delete pixels
+                checkDone = true
+            }
+        }
+    }
+
+    TestCase {
+        name: "Canvas3D_render_preserve"
+        when: windowShown
+
+        function test_render_1_preserve() {
+            tryCompare(top, "initDone", true)
+            Content.setColor(0x00, 0x00, 0xff, 0xff)
+            // Draw the frame exactly once. That way one of the framebuffers has our scene and
+            // the other is default empty.
+            paintDone = false;
+            tryCompare(top, "paintDone", true)
+
+            // We cannot control if we are reading from the first or second framebuffer, since we
+            // cannot actually reliably sync with the render loop. We work around this issue
+            // by doing the pixel checks multiple times. That way at least one of the checks
+            // is likely to target the framebuffer we didn't draw our frame to, and therefore
+            // fails if the preserve is not working.
+            for (var i = 0; i < 10; i++) {
+                // Check color in the left side (part of the triangle)
+                xpos = 75
+                ypos = 150
+                checkDone = false
+                tryCompare(top, "checkDone", true)
+                compare(top.red, 0x00)
+                compare(top.green, 0x00)
+                compare(top.blue, 0xff)
+                compare(top.alpha, 0xff)
+
+                // Check color in the right part of the screen, which is cleared with red
+                xpos = 225
+                ypos = 150
+                checkDone = false
+                tryCompare(top, "checkDone", true)
+                compare(top.red, 0xff)
+                compare(top.green, 0x00)
+                compare(top.blue, 0x00)
+                compare(top.alpha, 0xff)
+            }
+
+            Content.setColor(0x00, 0xcc, 0x00, 0xff)
+            paintDone = false;
+            tryCompare(top, "paintDone", true)
+
+            for (var j = 0; j < 10; j++) {
+                // Check color in the left side (part of the triangle)
+                xpos = 75
+                ypos = 150
+                checkDone = false
+                tryCompare(top, "checkDone", true)
+                compare(top.red, 0x00)
+                compare(top.green, 0xcc)
+                compare(top.blue, 0x00)
+                compare(top.alpha, 0xff)
+            }
+        }
+    }
+}