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.

Pick-to: 6.4 6.4.0
Fixes: QTBUG-107539
Change-Id: Idf75bd80033a44c34af6837cd4d65b75c183d886
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Mikolaj Boc 2022-10-17 13:24:15 +02:00 committed by Mikołaj Boc
parent 3f8e3c3335
commit e487b07e18
2 changed files with 43 additions and 63 deletions

View File

@ -735,11 +735,11 @@ void QOpenGL2PaintEngineExPrivate::resetGLState()
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
funcs.glVertexAttrib4fv(3, color);
}
if (vao.isCreated()) {
if (vao.isCreated())
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()
@ -2207,28 +2207,27 @@ bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev)
bool created = d->vao.create();
// If we managed to create it then we have a profile that supports VAOs
if (created) {
if (created)
d->vao.bind();
}
// Generate a new Vertex Buffer Object if we don't have one already
if (!d->vertexBuffer.isCreated()) {
d->vertexBuffer.create();
// Set its usage to StreamDraw, we will use this buffer only a few times before refilling it
d->vertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
if (!d->texCoordBuffer.isCreated()) {
d->texCoordBuffer.create();
d->texCoordBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
if (!d->opacityBuffer.isCreated()) {
d->opacityBuffer.create();
d->opacityBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
if (!d->indexBuffer.isCreated()) {
d->indexBuffer.create();
d->indexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
}
// Generate a new Vertex Buffer Object if we don't have one already
if (!d->vertexBuffer.isCreated()) {
d->vertexBuffer.create();
// Set its usage to StreamDraw, we will use this buffer only a few times before refilling it
d->vertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
if (!d->texCoordBuffer.isCreated()) {
d->texCoordBuffer.create();
d->texCoordBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
if (!d->opacityBuffer.isCreated()) {
d->opacityBuffer.create();
d->opacityBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
if (!d->indexBuffer.isCreated()) {
d->indexBuffer.create();
d->indexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
}
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);
// If a vertex array object is created we have a profile that supports them
// and we will upload the data via a QOpenGLBuffer. Otherwise we will use
// the legacy way of uploading the data via glVertexAttribPointer.
if (vao.isCreated()) {
if (arrayIndex == QT_VERTEX_COORDS_ATTR) {
vertexBuffer.bind();
vertexBuffer.allocate(data, count * sizeof(float));
}
if (arrayIndex == QT_TEXTURE_COORDS_ATTR) {
texCoordBuffer.bind();
texCoordBuffer.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;
if (arrayIndex == QT_VERTEX_COORDS_ATTR) {
vertexBuffer.bind();
vertexBuffer.allocate(data, count * sizeof(float));
}
if (arrayIndex == QT_TEXTURE_COORDS_ATTR) {
texCoordBuffer.bind();
texCoordBuffer.allocate(data, count * sizeof(float));
}
if (arrayIndex == QT_OPACITY_ATTR) {
opacityBuffer.bind();
opacityBuffer.allocate(data, count * sizeof(float));
// Store the data in cache and upload it to the graphics card.
vertexAttribPointers[arrayIndex] = data;
if (arrayIndex == QT_OPACITY_ATTR)
funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, data);
else
funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, data);
funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
} else {
funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
}
}
bool QOpenGL2PaintEngineExPrivate::uploadIndexData(const void *data, GLenum indexValueType, GLuint count)
{
// Follow the uploadData() logic: VBOs are used only when VAO support is available.
// Otherwise the legacy client-side pointer path is used.
if (vao.isCreated()) {
Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT);
indexBuffer.bind();
indexBuffer.allocate(data, count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32)));
return true;
}
return false;
Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT);
indexBuffer.bind();
indexBuffer.allocate(
data,
count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32)));
return true;
}
QT_END_NAMESPACE