bool SGGeometryExtension::setObject(void* object, const QString& typeName) { if (typeName == "QSGGeometryNode") { m_node = static_cast<QSGGeometryNode*>(object); m_model->setNode(m_node); QSGGeometry *geometry = m_node->geometry(); emit geometryChanged(geometry->drawingMode(), QByteArray::fromRawData(reinterpret_cast<char*>(geometry->indexData()), geometry->indexCount()*geometry->sizeOfIndex()), geometry->indexType()); return true; } return false; }
void Renderer::buildRenderList(QSGNode *node, QSGClipNode *clip) { if (node->isSubtreeBlocked()) return; if (node->type() == QSGNode::GeometryNodeType || node->type() == QSGNode::ClipNodeType) { QSGBasicGeometryNode *gn = static_cast<QSGBasicGeometryNode *>(node); QSGGeometry *g = gn->geometry(); Element e; e.node = gn; if (g->vertexCount() > 0) { e.vboOffset = m_vboSize; int vertexSize = g->sizeOfVertex() * g->vertexCount(); m_vboSize += vertexSize; m_vboData.resize(m_vboSize); memcpy(m_vboData.data() + e.vboOffset, g->vertexData(), vertexSize); } else { e.vboOffset = -1; } if (g->indexCount() > 0) { e.iboOffset = m_iboSize; int indexSize = g->sizeOfIndex() * g->indexCount(); m_iboSize += indexSize; m_iboData.resize(m_iboSize); memcpy(m_iboData.data() + e.iboOffset, g->indexData(), indexSize); } else { e.iboOffset = -1; } m_renderList.add(e); static_cast<BasicGeometryNode_Accessor *>(node)->m_clip_list = clip; if (node->type() == QSGNode::ClipNodeType) clip = static_cast<QSGClipNode *>(node); } QSGNODE_TRAVERSE(node) buildRenderList(child, clip); }
void QSGDefaultImageNode::updateGeometry() { Q_ASSERT(!m_targetRect.isEmpty()); const QSGTexture *t = m_material.texture(); if (!t) { QSGGeometry *g = geometry(); g->allocate(4); g->setDrawingMode(GL_TRIANGLE_STRIP); memset(g->vertexData(), 0, g->sizeOfVertex() * 4); } else { QRectF sourceRect = t->normalizedTextureSubRect(); QRectF innerSourceRect(sourceRect.x() + m_innerSourceRect.x() * sourceRect.width(), sourceRect.y() + m_innerSourceRect.y() * sourceRect.height(), m_innerSourceRect.width() * sourceRect.width(), m_innerSourceRect.height() * sourceRect.height()); bool hasMargins = m_targetRect != m_innerTargetRect; int floorLeft = qFloor(m_subSourceRect.left()); int ceilRight = qCeil(m_subSourceRect.right()); int floorTop = qFloor(m_subSourceRect.top()); int ceilBottom = qCeil(m_subSourceRect.bottom()); int hTiles = ceilRight - floorLeft; int vTiles = ceilBottom - floorTop; bool hasTiles = hTiles != 1 || vTiles != 1; bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1); #ifdef QT_OPENGL_ES_2 QOpenGLContext *ctx = QOpenGLContext::currentContext(); bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); QSize size = t->textureSize(); bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); bool wrapSupported = npotSupported || !isNpot; #else bool wrapSupported = true; #endif // An image can be rendered as a single quad if: // - There are no margins, and either: // - the image isn't repeated // - the source rectangle fills the entire texture so that texture wrapping can be used, // and NPOT is supported if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) { QRectF sr; if (!fullTexture) { sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(), innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height(), m_subSourceRect.width() * innerSourceRect.width(), m_subSourceRect.height() * innerSourceRect.height()); } else { sr = QRectF(m_subSourceRect.left() - floorLeft, m_subSourceRect.top() - floorTop, m_subSourceRect.width(), m_subSourceRect.height()); } if (m_mirror) { qreal oldLeft = sr.left(); sr.setLeft(sr.right()); sr.setRight(oldLeft); } if (m_antialiasing) { QSGGeometry *g = geometry(); Q_ASSERT(g != &m_geometry); g->allocate(8, 14); g->setDrawingMode(GL_TRIANGLE_STRIP); SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData()); float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) ? m_targetRect.width() : m_targetRect.height()) * 0.5f; float sx = float(sr.width() / m_targetRect.width()); float sy = float(sr.height() / m_targetRect.height()); for (int d = -1; d <= 1; d += 2) { for (int j = 0; j < 2; ++j) { for (int i = 0; i < 2; ++i, ++vertices) { vertices->x = m_targetRect.x() + i * m_targetRect.width(); vertices->y = m_targetRect.y() + j * m_targetRect.height(); vertices->u = sr.x() + i * sr.width(); vertices->v = sr.y() + j * sr.height(); vertices->dx = (i == 0 ? delta : -delta) * d; vertices->dy = (j == 0 ? delta : -delta) * d; vertices->du = (d < 0 ? 0 : vertices->dx * sx); vertices->dv = (d < 0 ? 0 : vertices->dy * sy); } } } Q_ASSERT(vertices - g->vertexCount() == g->vertexData()); static const quint16 indices[] = { 0, 4, 1, 5, 3, 7, 2, 6, 0, 4, 4, 6, 5, 7 }; Q_ASSERT(g->sizeOfIndex() * g->indexCount() == sizeof(indices)); memcpy(g->indexDataAsUShort(), indices, sizeof(indices)); } else { m_geometry.allocate(4); m_geometry.setDrawingMode(GL_TRIANGLE_STRIP); QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr); } } else { int hCells = hTiles; int vCells = vTiles; if (m_innerTargetRect.width() == 0) hCells = 0; if (m_innerTargetRect.left() != m_targetRect.left()) ++hCells; if (m_innerTargetRect.right() != m_targetRect.right()) ++hCells; if (m_innerTargetRect.height() == 0) vCells = 0; if (m_innerTargetRect.top() != m_targetRect.top()) ++vCells; if (m_innerTargetRect.bottom() != m_targetRect.bottom()) ++vCells; QVarLengthArray<X, 32> xData(2 * hCells); QVarLengthArray<Y, 32> yData(2 * vCells); X *xs = xData.data(); Y *ys = yData.data(); if (m_innerTargetRect.left() != m_targetRect.left()) { xs[0].x = m_targetRect.left(); xs[0].tx = sourceRect.left(); xs[1].x = m_innerTargetRect.left(); xs[1].tx = innerSourceRect.left(); xs += 2; } if (m_innerTargetRect.width() != 0) { xs[0].x = m_innerTargetRect.left(); xs[0].tx = innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(); ++xs; float b = m_innerTargetRect.width() / m_subSourceRect.width(); float a = m_innerTargetRect.x() - m_subSourceRect.x() * b; for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) { xs[0].x = xs[1].x = a + b * i; xs[0].tx = innerSourceRect.right(); xs[1].tx = innerSourceRect.left(); xs += 2; } xs[0].x = m_innerTargetRect.right(); xs[0].tx = innerSourceRect.x() + (m_subSourceRect.right() - ceilRight + 1) * innerSourceRect.width(); ++xs; } if (m_innerTargetRect.right() != m_targetRect.right()) { xs[0].x = m_innerTargetRect.right(); xs[0].tx = innerSourceRect.right(); xs[1].x = m_targetRect.right(); xs[1].tx = sourceRect.right(); xs += 2; } Q_ASSERT(xs == xData.data() + xData.size()); if (m_mirror) { float leftPlusRight = m_targetRect.left() + m_targetRect.right(); int count = xData.size(); xs = xData.data(); for (int i = 0; i < count >> 1; ++i) qSwap(xs[i], xs[count - 1 - i]); for (int i = 0; i < count; ++i) xs[i].x = leftPlusRight - xs[i].x; } if (m_innerTargetRect.top() != m_targetRect.top()) { ys[0].y = m_targetRect.top(); ys[0].ty = sourceRect.top(); ys[1].y = m_innerTargetRect.top(); ys[1].ty = innerSourceRect.top(); ys += 2; } if (m_innerTargetRect.height() != 0) { ys[0].y = m_innerTargetRect.top(); ys[0].ty = innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height(); ++ys; float b = m_innerTargetRect.height() / m_subSourceRect.height(); float a = m_innerTargetRect.y() - m_subSourceRect.y() * b; for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) { ys[0].y = ys[1].y = a + b * i; ys[0].ty = innerSourceRect.bottom(); ys[1].ty = innerSourceRect.top(); ys += 2; } ys[0].y = m_innerTargetRect.bottom(); ys[0].ty = innerSourceRect.y() + (m_subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height(); ++ys; } if (m_innerTargetRect.bottom() != m_targetRect.bottom()) { ys[0].y = m_innerTargetRect.bottom(); ys[0].ty = innerSourceRect.bottom(); ys[1].y = m_targetRect.bottom(); ys[1].ty = sourceRect.bottom(); ys += 2; } Q_ASSERT(ys == yData.data() + yData.size()); if (m_antialiasing) { QSGGeometry *g = geometry(); Q_ASSERT(g != &m_geometry); g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4, hCells * vCells * 6 + (hCells + vCells) * 12); g->setDrawingMode(GL_TRIANGLES); SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData()); memset(vertices, 0, g->vertexCount() * g->sizeOfVertex()); quint16 *indices = g->indexDataAsUShort(); // The deltas are how much the fuzziness can reach into the image. // Only the border vertices are moved by the vertex shader, so the fuzziness // can't reach further into the image than the closest interior vertices. float leftDx = xData.at(1).x - xData.at(0).x; float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x; float topDy = yData.at(1).y - yData.at(0).y; float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y; float leftDu = xData.at(1).tx - xData.at(0).tx; float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx; float topDv = yData.at(1).ty - yData.at(0).ty; float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty; if (hCells == 1) { leftDx = rightDx *= 0.5f; leftDu = rightDu *= 0.5f; } if (vCells == 1) { topDy = bottomDy *= 0.5f; topDv = bottomDv *= 0.5f; } // This delta is how much the fuzziness can reach out from the image. float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) ? m_targetRect.width() : m_targetRect.height()) * 0.5f; quint16 index = 0; ys = yData.data(); for (int j = 0; j < vCells; ++j, ys += 2) { xs = xData.data(); bool isTop = j == 0; bool isBottom = j == vCells - 1; for (int i = 0; i < hCells; ++i, xs += 2) { bool isLeft = i == 0; bool isRight = i == hCells - 1; SmoothVertex *v = vertices + index; quint16 topLeft = index; for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) { v->x = xs[0].x; v->u = xs[0].tx; v->y = ys[0].y; v->v = ys[0].ty; } quint16 topRight = index; for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) { v->x = xs[1].x; v->u = xs[1].tx; v->y = ys[0].y; v->v = ys[0].ty; } quint16 bottomLeft = index; for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) { v->x = xs[0].x; v->u = xs[0].tx; v->y = ys[1].y; v->v = ys[1].ty; } quint16 bottomRight = index; for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) { v->x = xs[1].x; v->u = xs[1].tx; v->y = ys[1].y; v->v = ys[1].ty; } appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight); if (isTop) { vertices[topLeft].dy = vertices[topRight].dy = topDy; vertices[topLeft].dv = vertices[topRight].dv = topDv; vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta; appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight); } if (isBottom) { vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta; appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1); } if (isLeft) { vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; vertices[topLeft].du = vertices[bottomLeft].du = leftDu; vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta; appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft); } if (isRight) { vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; vertices[topRight].du = vertices[bottomRight].du = -rightDu; vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta; appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1); } } } Q_ASSERT(index == g->vertexCount()); Q_ASSERT(indices - g->indexCount() == g->indexData()); } else { m_geometry.allocate(hCells * vCells * 4, hCells * vCells * 6); m_geometry.setDrawingMode(GL_TRIANGLES); QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D(); ys = yData.data(); for (int j = 0; j < vCells; ++j, ys += 2) { xs = xData.data(); for (int i = 0; i < hCells; ++i, xs += 2) { vertices[0].x = vertices[2].x = xs[0].x; vertices[0].tx = vertices[2].tx = xs[0].tx; vertices[1].x = vertices[3].x = xs[1].x; vertices[1].tx = vertices[3].tx = xs[1].tx; vertices[0].y = vertices[1].y = ys[0].y; vertices[0].ty = vertices[1].ty = ys[0].ty; vertices[2].y = vertices[3].y = ys[1].y; vertices[2].ty = vertices[3].ty = ys[1].ty; vertices += 4; } } quint16 *indices = m_geometry.indexDataAsUShort(); for (int i = 0; i < 4 * vCells * hCells; i += 4) appendQuad(&indices, i, i + 1, i + 2, i + 3); } } } markDirty(DirtyGeometry); m_dirtyGeometry = false; }
QSGGeometry *QSGBasicInternalImageNode::updateGeometry(const QRectF &targetRect, const QRectF &innerTargetRect, const QRectF &sourceRect, const QRectF &innerSourceRect, const QRectF &subSourceRect, QSGGeometry *geometry, bool mirror, bool antialiasing) { int floorLeft = qFloor(subSourceRect.left()); int ceilRight = qCeil(subSourceRect.right()); int floorTop = qFloor(subSourceRect.top()); int ceilBottom = qCeil(subSourceRect.bottom()); int hTiles = ceilRight - floorLeft; int vTiles = ceilBottom - floorTop; int hCells = hTiles; int vCells = vTiles; if (innerTargetRect.width() == 0) hCells = 0; if (innerTargetRect.left() != targetRect.left()) ++hCells; if (innerTargetRect.right() != targetRect.right()) ++hCells; if (innerTargetRect.height() == 0) vCells = 0; if (innerTargetRect.top() != targetRect.top()) ++vCells; if (innerTargetRect.bottom() != targetRect.bottom()) ++vCells; QVarLengthArray<X, 32> xData(2 * hCells); QVarLengthArray<Y, 32> yData(2 * vCells); X *xs = xData.data(); Y *ys = yData.data(); if (innerTargetRect.left() != targetRect.left()) { xs[0].x = targetRect.left(); xs[0].tx = sourceRect.left(); xs[1].x = innerTargetRect.left(); xs[1].tx = innerSourceRect.left(); xs += 2; } if (innerTargetRect.width() != 0) { xs[0].x = innerTargetRect.left(); xs[0].tx = innerSourceRect.x() + (subSourceRect.left() - floorLeft) * innerSourceRect.width(); ++xs; float b = innerTargetRect.width() / subSourceRect.width(); float a = innerTargetRect.x() - subSourceRect.x() * b; for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) { xs[0].x = xs[1].x = a + b * i; xs[0].tx = innerSourceRect.right(); xs[1].tx = innerSourceRect.left(); xs += 2; } xs[0].x = innerTargetRect.right(); xs[0].tx = innerSourceRect.x() + (subSourceRect.right() - ceilRight + 1) * innerSourceRect.width(); ++xs; } if (innerTargetRect.right() != targetRect.right()) { xs[0].x = innerTargetRect.right(); xs[0].tx = innerSourceRect.right(); xs[1].x = targetRect.right(); xs[1].tx = sourceRect.right(); xs += 2; } Q_ASSERT(xs == xData.data() + xData.size()); if (mirror) { float leftPlusRight = targetRect.left() + targetRect.right(); int count = xData.size(); xs = xData.data(); for (int i = 0; i < count >> 1; ++i) qSwap(xs[i], xs[count - 1 - i]); for (int i = 0; i < count; ++i) xs[i].x = leftPlusRight - xs[i].x; } if (innerTargetRect.top() != targetRect.top()) { ys[0].y = targetRect.top(); ys[0].ty = sourceRect.top(); ys[1].y = innerTargetRect.top(); ys[1].ty = innerSourceRect.top(); ys += 2; } if (innerTargetRect.height() != 0) { ys[0].y = innerTargetRect.top(); ys[0].ty = innerSourceRect.y() + (subSourceRect.top() - floorTop) * innerSourceRect.height(); ++ys; float b = innerTargetRect.height() / subSourceRect.height(); float a = innerTargetRect.y() - subSourceRect.y() * b; for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) { ys[0].y = ys[1].y = a + b * i; ys[0].ty = innerSourceRect.bottom(); ys[1].ty = innerSourceRect.top(); ys += 2; } ys[0].y = innerTargetRect.bottom(); ys[0].ty = innerSourceRect.y() + (subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height(); ++ys; } if (innerTargetRect.bottom() != targetRect.bottom()) { ys[0].y = innerTargetRect.bottom(); ys[0].ty = innerSourceRect.bottom(); ys[1].y = targetRect.bottom(); ys[1].ty = sourceRect.bottom(); ys += 2; } Q_ASSERT(ys == yData.data() + yData.size()); if (antialiasing) { QSGGeometry *g = geometry; Q_ASSERT(g); g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4, hCells * vCells * 6 + (hCells + vCells) * 12); g->setDrawingMode(QSGGeometry::DrawTriangles); SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData()); memset(vertices, 0, g->vertexCount() * g->sizeOfVertex()); quint16 *indices = g->indexDataAsUShort(); // The deltas are how much the fuzziness can reach into the image. // Only the border vertices are moved by the vertex shader, so the fuzziness // can't reach further into the image than the closest interior vertices. float leftDx = xData.at(1).x - xData.at(0).x; float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x; float topDy = yData.at(1).y - yData.at(0).y; float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y; float leftDu = xData.at(1).tx - xData.at(0).tx; float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx; float topDv = yData.at(1).ty - yData.at(0).ty; float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty; if (hCells == 1) { leftDx = rightDx *= 0.5f; leftDu = rightDu *= 0.5f; } if (vCells == 1) { topDy = bottomDy *= 0.5f; topDv = bottomDv *= 0.5f; } // This delta is how much the fuzziness can reach out from the image. float delta = float(qAbs(targetRect.width()) < qAbs(targetRect.height()) ? targetRect.width() : targetRect.height()) * 0.5f; quint16 index = 0; ys = yData.data(); for (int j = 0; j < vCells; ++j, ys += 2) { xs = xData.data(); bool isTop = j == 0; bool isBottom = j == vCells - 1; for (int i = 0; i < hCells; ++i, xs += 2) { bool isLeft = i == 0; bool isRight = i == hCells - 1; SmoothVertex *v = vertices + index; quint16 topLeft = index; for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) { v->x = xs[0].x; v->u = xs[0].tx; v->y = ys[0].y; v->v = ys[0].ty; } quint16 topRight = index; for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) { v->x = xs[1].x; v->u = xs[1].tx; v->y = ys[0].y; v->v = ys[0].ty; } quint16 bottomLeft = index; for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) { v->x = xs[0].x; v->u = xs[0].tx; v->y = ys[1].y; v->v = ys[1].ty; } quint16 bottomRight = index; for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) { v->x = xs[1].x; v->u = xs[1].tx; v->y = ys[1].y; v->v = ys[1].ty; } appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight); if (isTop) { vertices[topLeft].dy = vertices[topRight].dy = topDy; vertices[topLeft].dv = vertices[topRight].dv = topDv; vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta; appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight); } if (isBottom) { vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta; appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1); } if (isLeft) { vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; vertices[topLeft].du = vertices[bottomLeft].du = leftDu; vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta; appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft); } if (isRight) { vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; vertices[topRight].du = vertices[bottomRight].du = -rightDu; vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta; appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1); } } } Q_ASSERT(index == g->vertexCount()); Q_ASSERT(indices - g->indexCount() == g->indexData()); } else { if (!geometry) { geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), hCells * vCells * 4, hCells * vCells * 6, QSGGeometry::UnsignedShortType); } else { geometry->allocate(hCells * vCells * 4, hCells * vCells * 6); } geometry->setDrawingMode(QSGGeometry::DrawTriangles); QSGGeometry::TexturedPoint2D *vertices = geometry->vertexDataAsTexturedPoint2D(); ys = yData.data(); for (int j = 0; j < vCells; ++j, ys += 2) { xs = xData.data(); for (int i = 0; i < hCells; ++i, xs += 2) { vertices[0].x = vertices[2].x = xs[0].x; vertices[0].tx = vertices[2].tx = xs[0].tx; vertices[1].x = vertices[3].x = xs[1].x; vertices[1].tx = vertices[3].tx = xs[1].tx; vertices[0].y = vertices[1].y = ys[0].y; vertices[0].ty = vertices[1].ty = ys[0].ty; vertices[2].y = vertices[3].y = ys[1].y; vertices[2].ty = vertices[3].ty = ys[1].ty; vertices += 4; } } quint16 *indices = geometry->indexDataAsUShort(); for (int i = 0; i < 4 * vCells * hCells; i += 4) appendQuad(&indices, i, i + 1, i + 2, i + 3); } return geometry; }
void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node) { if (!node->m_fillNode) return; if (!(d->effectiveDirty & (DirtyFillGeom | DirtyColor | DirtyFillGradient))) return; // Make a copy of the data that will be accessed by the material on // the render thread. This must be done even when we bail out below. QQuickShapeGenericStrokeFillNode *n = node->m_fillNode; updateShadowDataInNode(d, n); QSGGeometry *g = n->geometry(); if (d->fillVertices.isEmpty()) { if (g->vertexCount() || g->indexCount()) { g->allocate(0, 0); n->markDirty(QSGNode::DirtyGeometry); } return; } if (d->fillGradientActive) { QQuickShapeGenericStrokeFillNode::Material gradMat; switch (d->fillGradientActive) { case LinearGradient: gradMat = QQuickShapeGenericStrokeFillNode::MatLinearGradient; break; case RadialGradient: gradMat = QQuickShapeGenericStrokeFillNode::MatRadialGradient; break; case ConicalGradient: gradMat = QQuickShapeGenericStrokeFillNode::MatConicalGradient; break; default: Q_UNREACHABLE(); } n->activateMaterial(m_item->window(), gradMat); if (d->effectiveDirty & DirtyFillGradient) { // Gradients are implemented via a texture-based material. n->markDirty(QSGNode::DirtyMaterial); // stop here if only the gradient changed; no need to touch the geometry if (!(d->effectiveDirty & DirtyFillGeom)) return; } } else { n->activateMaterial(m_item->window(), QQuickShapeGenericStrokeFillNode::MatSolidColor); // fast path for updating only color values when no change in vertex positions if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyFillGeom)) { ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData()); for (int i = 0; i < g->vertexCount(); ++i) vdst[i].set(vdst[i].x, vdst[i].y, d->fillColor); n->markDirty(QSGNode::DirtyGeometry); return; } } const int indexCount = d->indexType == QSGGeometry::UnsignedShortType ? d->fillIndices.count() * 2 : d->fillIndices.count(); if (g->indexType() != d->indexType) { g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), d->fillVertices.count(), indexCount, d->indexType); n->setGeometry(g); } else { g->allocate(d->fillVertices.count(), indexCount); } g->setDrawingMode(QSGGeometry::DrawTriangles); memcpy(g->vertexData(), d->fillVertices.constData(), g->vertexCount() * g->sizeOfVertex()); memcpy(g->indexData(), d->fillIndices.constData(), g->indexCount() * g->sizeOfIndex()); n->markDirty(QSGNode::DirtyGeometry); }