Do not use client-side data pointers in qopenglpaintengine

Buffers can be uploaded - no need to keep these in client memory.
Decouple uploading of buffers from the creation of vao.

Fixes: QTBUG-107539
Change-Id: Idf75bd80033a44c34af6837cd4d65b75c183d886
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
(cherry picked from commit e487b07e18f1cb7ff126744be57b2ae1b9839c6c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Mikolaj Boc 2022-10-17 13:24:15 +02:00 committed by Qt Cherry-pick Bot
parent c0b54bf6fa
commit 81252ea92a
2 changed files with 43 additions and 63 deletions

View File

@ -726,11 +726,11 @@ void QOpenGL2PaintEngineExPrivate::resetGLState()
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
funcs.glVertexAttrib4fv(3, color); funcs.glVertexAttrib4fv(3, color);
} }
if (vao.isCreated()) { if (vao.isCreated())
vao.release(); vao.release();
funcs.glBindBuffer(GL_ARRAY_BUFFER, 0);
funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); funcs.glBindBuffer(GL_ARRAY_BUFFER, 0);
} funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void QOpenGL2PaintEngineEx::endNativePainting() void QOpenGL2PaintEngineEx::endNativePainting()
@ -2198,28 +2198,27 @@ bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev)
bool created = d->vao.create(); bool created = d->vao.create();
// If we managed to create it then we have a profile that supports VAOs // If we managed to create it then we have a profile that supports VAOs
if (created) { if (created)
d->vao.bind(); d->vao.bind();
}
// Generate a new Vertex Buffer Object if we don't have one already // Generate a new Vertex Buffer Object if we don't have one already
if (!d->vertexBuffer.isCreated()) { if (!d->vertexBuffer.isCreated()) {
d->vertexBuffer.create(); d->vertexBuffer.create();
// Set its usage to StreamDraw, we will use this buffer only a few times before refilling it // Set its usage to StreamDraw, we will use this buffer only a few times before refilling it
d->vertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); d->vertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
} }
if (!d->texCoordBuffer.isCreated()) { if (!d->texCoordBuffer.isCreated()) {
d->texCoordBuffer.create(); d->texCoordBuffer.create();
d->texCoordBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); d->texCoordBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
} }
if (!d->opacityBuffer.isCreated()) { if (!d->opacityBuffer.isCreated()) {
d->opacityBuffer.create(); d->opacityBuffer.create();
d->opacityBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); d->opacityBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
} }
if (!d->indexBuffer.isCreated()) { if (!d->indexBuffer.isCreated()) {
d->indexBuffer.create(); d->indexBuffer.create();
d->indexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); d->indexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
}
} }
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)

View File

@ -307,51 +307,32 @@ void QOpenGL2PaintEngineExPrivate::uploadData(unsigned int arrayIndex, const GLf
{ {
Q_ASSERT(arrayIndex < 3); Q_ASSERT(arrayIndex < 3);
// If a vertex array object is created we have a profile that supports them if (arrayIndex == QT_VERTEX_COORDS_ATTR) {
// and we will upload the data via a QOpenGLBuffer. Otherwise we will use vertexBuffer.bind();
// the legacy way of uploading the data via glVertexAttribPointer. vertexBuffer.allocate(data, count * sizeof(float));
if (vao.isCreated()) { }
if (arrayIndex == QT_VERTEX_COORDS_ATTR) { if (arrayIndex == QT_TEXTURE_COORDS_ATTR) {
vertexBuffer.bind(); texCoordBuffer.bind();
vertexBuffer.allocate(data, count * sizeof(float)); texCoordBuffer.allocate(data, count * sizeof(float));
} }
if (arrayIndex == QT_TEXTURE_COORDS_ATTR) { if (arrayIndex == QT_OPACITY_ATTR) {
texCoordBuffer.bind(); opacityBuffer.bind();
texCoordBuffer.allocate(data, count * sizeof(float)); opacityBuffer.allocate(data, count * sizeof(float));
}
if (arrayIndex == QT_OPACITY_ATTR) {
opacityBuffer.bind();
opacityBuffer.allocate(data, count * sizeof(float));
}
if (arrayIndex == QT_OPACITY_ATTR)
funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
else
funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
} else {
// If we already uploaded the data we don't have to do it again
if (data == vertexAttribPointers[arrayIndex])
return;
// Store the data in cache and upload it to the graphics card. funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
vertexAttribPointers[arrayIndex] = data; } else {
if (arrayIndex == QT_OPACITY_ATTR) funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, data);
else
funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, data);
} }
} }
bool QOpenGL2PaintEngineExPrivate::uploadIndexData(const void *data, GLenum indexValueType, GLuint count) bool QOpenGL2PaintEngineExPrivate::uploadIndexData(const void *data, GLenum indexValueType, GLuint count)
{ {
// Follow the uploadData() logic: VBOs are used only when VAO support is available. Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT);
// Otherwise the legacy client-side pointer path is used. indexBuffer.bind();
if (vao.isCreated()) { indexBuffer.allocate(
Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT); data,
indexBuffer.bind(); count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32)));
indexBuffer.allocate(data, count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32))); return true;
return true;
}
return false;
} }
QT_END_NAMESPACE QT_END_NAMESPACE