aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@digia.com>2013-11-06 10:06:27 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-09 22:46:47 +0100
commitafee694ce5d65518e5908b97e9a691c03fe0a844 (patch)
treebe6e714703b799791cdacbea4b315471ab9b6a03 /src
parent7b75c3e63e7842c2667f58d43d44e21ff57ac0c8 (diff)
Avoid using huge floating point values in the renderer.
We pretransform vertices relative to their batch root and upload these using single-precision floats. If the offsets are huge then the floating point numbers start to get unstable and we get rendering artifacts as a result. This typically happens for lists/tables with huge models. Task-number: QTBUG-34312 Change-Id: I2516f2b4fa93f44a1288659d05458fb1af0df943 Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp24
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h13
2 files changed, 32 insertions, 5 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index bb98682b20..3ea4b2ee1e 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -562,6 +562,8 @@ void Element::computeBounds()
bounds.br.x = FLT_MAX;
if (!qIsFinite(bounds.br.y))
bounds.br.y = FLT_MAX;
+
+ boundsOutsideFloatRange = bounds.isOutsideFloatRange();
}
RenderNodeElement::~RenderNodeElement()
@@ -662,12 +664,26 @@ bool Batch::isTranslateOnlyToRoot() const {
/*
* Iterates through all the nodes in the batch and returns true if the
- * nodes are all "2D safe" meaning that they can be merged and that
- * the value in the z coordinate is of no consequence.
+ * nodes are all safe to batch. There are two separate criteria:
+ *
+ * - The matrix is such that the z component of the result is of no
+ * consequence.
+ *
+ * - The bounds are inside the stable floating point range. This applies
+ * to desktop only where we in this case can trigger a fallback to
+ * unmerged in which case we pass the geometry straight through and
+ * just apply the matrix.
+ *
+ * NOTE: This also means a slight performance impact for geometries which
+ * are defined to be outside the stable floating point range and still
+ * use single precision float, but given that this implicitly fixes
+ * huge lists and tables, it is worth it.
*/
-bool Batch::allMatricesAre2DSafe() const {
+bool Batch::isSafeToBatch() const {
Element *e = first;
while (e) {
+ if (e->boundsOutsideFloatRange)
+ return false;
if (!QMatrix4x4_Accessor::is2DSafe(*e->node->matrix()))
return false;
e = e->nextInBatch;
@@ -1637,7 +1653,7 @@ void Renderer::uploadBatch(Batch *b)
&& (((gn->activeMaterial()->flags() & QSGMaterial::RequiresDeterminant) == 0)
|| (((gn->activeMaterial()->flags() & QSGMaterial_RequiresFullMatrixBit) == 0) && b->isTranslateOnlyToRoot())
)
- && b->allMatricesAre2DSafe();
+ && b->isSafeToBatch();
b->merged = canMerge;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 23985729ef..6d95f83d7a 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE
namespace QSGBatchRenderer
{
+#define QSG_RENDERER_COORD_LIMIT 1000000.0f
+
struct Vec;
struct Rect;
struct Buffer;
@@ -136,6 +138,13 @@ struct Rect {
bool yOverlap = r.tl.y < br.y && r.br.y > tl.y;
return xOverlap && yOverlap;
}
+
+ bool isOutsideFloatRange() const {
+ return tl.x < -QSG_RENDERER_COORD_LIMIT
+ || tl.y < -QSG_RENDERER_COORD_LIMIT
+ || br.x > QSG_RENDERER_COORD_LIMIT
+ || br.y > QSG_RENDERER_COORD_LIMIT;
+ }
};
inline QDebug operator << (QDebug d, const Rect &r) {
@@ -158,6 +167,7 @@ struct Element {
, root(0)
, order(0)
, boundsComputed(false)
+ , boundsOutsideFloatRange(false)
, translateOnlyToRoot(false)
, removed(false)
, orphaned(false)
@@ -181,6 +191,7 @@ struct Element {
int order;
uint boundsComputed : 1;
+ uint boundsOutsideFloatRange : 1;
uint translateOnlyToRoot : 1;
uint removed : 1;
uint orphaned : 1;
@@ -242,7 +253,7 @@ struct Batch
void cleanupRemovedElements();
bool isTranslateOnlyToRoot() const;
- bool allMatricesAre2DSafe() const;
+ bool isSafeToBatch() const;
// pseudo-constructor...
void init() {