Skip to content

Commit

Permalink
Do not use client-side data pointers in qopenglpaintengine
Browse files Browse the repository at this point in the history
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 e487b07)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
  • Loading branch information
mboc-qt authored and Qt Cherry-pick Bot committed Oct 21, 2022
1 parent c0b54bf commit 81252ea
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 63 deletions.
47 changes: 23 additions & 24 deletions src/opengl/qopenglpaintengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,11 +726,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()
Expand Down Expand Up @@ -2198,28 +2198,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)
Expand Down
59 changes: 20 additions & 39 deletions src/opengl/qopenglpaintengine_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
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));

funcs.glVertexAttribPointer(arrayIndex, 1, 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.
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, 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
Expand Down

0 comments on commit 81252ea

Please sign in to comment.