From 9f234899f5e2cbd51ee21b183370017099bc1226 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen <miikka.heikkinen@theqtcompany.com> Date: Wed, 22 Apr 2015 11:52:36 +0300 Subject: [PATCH] Fix readPixels to work with custom framebuffer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ReadPixels always read from renderFbo if context had antialiasing specified. Also added buffer initialization to zero so pixels that fall outside the framebuffer contain correct value. Change-Id: I58b9fda18bc56a64346f83ccda575c758e9eaac5 Reviewed-by: Tomi Korpipää <tomi.korpipaa@theqtcompany.com> Reviewed-by: Pasi Keränen <pasi.keranen@digia.com> --- src/imports/qtcanvas3d/context3d.cpp | 7 ++- .../canvas3d/tst_render_checkresult.js | 35 +++++++++-- .../canvas3d/tst_render_checkresult.qml | 63 ++++++++++++++++++- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/src/imports/qtcanvas3d/context3d.cpp b/src/imports/qtcanvas3d/context3d.cpp index 38e0487..52777a5 100644 --- a/src/imports/qtcanvas3d/context3d.cpp +++ b/src/imports/qtcanvas3d/context3d.cpp @@ -5214,16 +5214,19 @@ void CanvasContext::readPixels(int x, int y, long width, long height, glEnums fo return; } + // Zero out the buffer (WebGL conformance requires pixels outside the framebuffer to be 0) + memset(bufferPtr, 0, width * height * 4); + // Check if the buffer is antialiased. If it is, we need to blit to the final buffer before // reading the value. - if (m_contextAttributes.antialias()) { + if (m_contextAttributes.antialias() && !m_currentFramebuffer) { GLuint readFbo = m_canvas->resolveMSAAFbo(); glBindFramebuffer(GL_FRAMEBUFFER, readFbo); } glReadPixels(x, y, width, height, format, type, bufferPtr); - if (m_contextAttributes.antialias()) + if (m_contextAttributes.antialias() && !m_currentFramebuffer) m_canvas->bindCurrentRenderTarget(); logAllGLErrors(__FUNCTION__); diff --git a/tests/auto/qmltest/canvas3d/tst_render_checkresult.js b/tests/auto/qmltest/canvas3d/tst_render_checkresult.js index 0eac410..94f2395 100644 --- a/tests/auto/qmltest/canvas3d/tst_render_checkresult.js +++ b/tests/auto/qmltest/canvas3d/tst_render_checkresult.js @@ -52,13 +52,13 @@ var textureCoordAttribute; var vertexColorAttribute; var colorFlagUniform; +var customFbo; function initializeGL(canvas) { gl = canvas.getContext(""); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); var pixelRatio = canvas.devicePixelRatio; gl.viewport(0, 0, pixelRatio * canvas.width, pixelRatio * canvas.height); - gl.clearColor(1.0, 0.0, 0.0, 1.0); initShaders(); initBuffers(); @@ -73,14 +73,29 @@ function initializeGL(canvas) { } function paintGL() { + gl.clearColor(1.0, 0.0, 0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); } -function paintGL(x, y) { - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); +function paintGL(x, y, separateFbo) { + if (separateFbo) { + gl.bindFramebuffer(gl.FRAMEBUFFER, customFbo); + gl.clearColor(0.0, 1.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + } else { + gl.clearColor(1.0, 0.0, 0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); - return checkPixel(x, y); + + var pixels = checkPixel(x, y); + + if (separateFbo) + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + return pixels; } function checkPixel(x, y) { @@ -172,6 +187,18 @@ function initBuffers() new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW); + + // Custom framebuffer + customFbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, customFbo); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.canvas.width, gl.canvas.height, 0, gl.RGBA, + gl.UNSIGNED_BYTE, null); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } function initShaders() diff --git a/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml b/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml index 350d2fd..935d1f7 100644 --- a/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml +++ b/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml @@ -54,6 +54,7 @@ Item { property int blue: -1 property int alpha: -1 property bool renderOk: false + property bool separateFbo: false Canvas3D { id: render_check_result @@ -62,7 +63,7 @@ Item { onInitializeGL: Content.initializeGL(this) onPaintGL: { if (checkResult) { - pixels = Content.paintGL(xpos, ypos) + pixels = Content.paintGL(xpos, ypos, separateFbo) red = pixels[0] green = pixels[1] blue = pixels[2] @@ -89,6 +90,7 @@ Item { ypos = 150 checkResult = true renderOk = false + separateFbo = false waitForRendering(render_check_result) tryCompare(top, "renderOk", true) tryCompare(top, "red", 0x00) @@ -123,6 +125,7 @@ Item { ypos = 150 checkResult = true renderOk = false + separateFbo = false waitForRendering(render_check_result) tryCompare(top, "renderOk", true) tryCompare(render_check_result, "textureLoaded", true, 10000) @@ -144,6 +147,7 @@ Item { ypos = 150 checkResult = true renderOk = false + separateFbo = false waitForRendering(render_check_result) tryCompare(top, "renderOk", true) tryCompare(top, "red", 0x22) @@ -154,5 +158,62 @@ Item { waitForRendering(render_check_result) } + + function test_render_4_checkresult() { + // Render to separate FBO. + waitForRendering(render_check_result) + Content.setColor(0x40, 0x60, 0x80, 0xff) + + // Check color in the center of the square + xpos = 150 + ypos = 150 + checkResult = true + renderOk = false + separateFbo = true + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(top, "red", 0x40) + tryCompare(top, "green", 0x60) + tryCompare(top, "blue", 0x80) + tryCompare(top, "alpha", 0xff) + checkResult = false + + waitForRendering(render_check_result) + + // Check color in the corner of the screen, which is cleared with green + xpos = 0 + ypos = 0 + checkResult = true + renderOk = false + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(top, "red", 0x00) + tryCompare(top, "green", 0xff) + tryCompare(top, "blue", 0x00) + tryCompare(top, "alpha", 0xff) + checkResult = false + + waitForRendering(render_check_result) + } + + function test_render_5_checkresult() { + // Check that pixels outside framebuffer are zero + waitForRendering(render_check_result) + Content.setColor(0x22, 0x99, 0xff, 0x80) + xpos = 9999 + ypos = 9999 + checkResult = true + renderOk = false + separateFbo = false + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(top, "red", 0x0) + tryCompare(top, "green", 0x0) + tryCompare(top, "blue", 0x0) + tryCompare(top, "alpha", 0x0) + checkResult = false + + waitForRendering(render_check_result) + } } } -- GitLab