Avoid image copy in toTexture() on GLES 3.0 as well
The default backingstore implementation is now cleaned for ES_2 ifdefs. All the checks are now done at runtime and ES 3.0+ is included as well for the efficient, QImage::copy()-less path. For embedded a customized backingstore is used so the change has to be done separately there. This should result in a slight improvement for QOpenGLWidget/QQuickWidget when running on GLES 3.x. Task-number: QTBUG-37624 Change-Id: I107330c25a993c5cdcd92e4ebdc17ae172a03da8 Reviewed-by: Paul Olav Tvete <paul.tvete@theqtcompany.com>
This commit is contained in:
parent
2811216973
commit
715a8e6f4e
@ -48,6 +48,16 @@
|
|||||||
#include <qpa/qplatformgraphicsbuffer.h>
|
#include <qpa/qplatformgraphicsbuffer.h>
|
||||||
#include <qpa/qplatformgraphicsbufferhelper.h>
|
#include <qpa/qplatformgraphicsbufferhelper.h>
|
||||||
|
|
||||||
|
#ifndef GL_TEXTURE_BASE_LEVEL
|
||||||
|
#define GL_TEXTURE_BASE_LEVEL 0x813C
|
||||||
|
#endif
|
||||||
|
#ifndef GL_TEXTURE_MAX_LEVEL
|
||||||
|
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||||
|
#endif
|
||||||
|
#ifndef GL_UNPACK_ROW_LENGTH
|
||||||
|
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QPlatformBackingStorePrivate
|
class QPlatformBackingStorePrivate
|
||||||
@ -311,12 +321,11 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
|
|||||||
funcs->glDeleteTextures(1, &d_ptr->textureId);
|
funcs->glDeleteTextures(1, &d_ptr->textureId);
|
||||||
funcs->glGenTextures(1, &d_ptr->textureId);
|
funcs->glGenTextures(1, &d_ptr->textureId);
|
||||||
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
||||||
#ifndef QT_OPENGL_ES_2
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||||
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
|
||||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
@ -435,18 +444,16 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
|
|||||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||||
|
|
||||||
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
|
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
|
||||||
|
|
||||||
if (resized) {
|
if (resized) {
|
||||||
if (d_ptr->textureId)
|
if (d_ptr->textureId)
|
||||||
funcs->glDeleteTextures(1, &d_ptr->textureId);
|
funcs->glDeleteTextures(1, &d_ptr->textureId);
|
||||||
funcs->glGenTextures(1, &d_ptr->textureId);
|
funcs->glGenTextures(1, &d_ptr->textureId);
|
||||||
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
||||||
#ifndef QT_OPENGL_ES_2
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||||
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
|
||||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
@ -459,15 +466,13 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
|
|||||||
QRect imageRect = image.rect();
|
QRect imageRect = image.rect();
|
||||||
QRect rect = dirtyRegion.boundingRect() & imageRect;
|
QRect rect = dirtyRegion.boundingRect() & imageRect;
|
||||||
|
|
||||||
#ifndef QT_OPENGL_ES_2
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||||
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
|
||||||
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width());
|
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width());
|
||||||
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
image.constScanLine(rect.y()) + rect.x() * 4);
|
image.constScanLine(rect.y()) + rect.x() * 4);
|
||||||
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
} else
|
} else {
|
||||||
#endif
|
|
||||||
{
|
|
||||||
// if the rect is wide enough it's cheaper to just
|
// if the rect is wide enough it's cheaper to just
|
||||||
// extend it instead of doing an image copy
|
// extend it instead of doing an image copy
|
||||||
if (rect.width() >= imageRect.width() / 2) {
|
if (rect.width() >= imageRect.width() / 2) {
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
#include "qopenglcompositorbackingstore_p.h"
|
#include "qopenglcompositorbackingstore_p.h"
|
||||||
#include "qopenglcompositor_p.h"
|
#include "qopenglcompositor_p.h"
|
||||||
|
|
||||||
|
#ifndef GL_UNPACK_ROW_LENGTH
|
||||||
|
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -100,29 +104,39 @@ void QOpenGLCompositorBackingStore::updateTexture()
|
|||||||
QRegion fixed;
|
QRegion fixed;
|
||||||
QRect imageRect = m_image.rect();
|
QRect imageRect = m_image.rect();
|
||||||
|
|
||||||
foreach (const QRect &rect, m_dirty.rects()) {
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||||
// intersect with image rect to be sure
|
if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
|
||||||
QRect r = imageRect & rect;
|
foreach (const QRect &rect, m_dirty.rects()) {
|
||||||
|
QRect r = imageRect & rect;
|
||||||
// if the rect is wide enough it's cheaper to just
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image.width());
|
||||||
// extend it instead of doing an image copy
|
glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
if (r.width() >= imageRect.width() / 2) {
|
m_image.constScanLine(r.y()) + r.x() * 4);
|
||||||
r.setX(0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
r.setWidth(imageRect.width());
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
foreach (const QRect &rect, m_dirty.rects()) {
|
||||||
|
// intersect with image rect to be sure
|
||||||
|
QRect r = imageRect & rect;
|
||||||
|
|
||||||
fixed |= r;
|
// if the rect is wide enough it's cheaper to just
|
||||||
}
|
// extend it instead of doing an image copy
|
||||||
|
if (r.width() >= imageRect.width() / 2) {
|
||||||
|
r.setX(0);
|
||||||
|
r.setWidth(imageRect.width());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (const QRect &rect, fixed.rects()) {
|
fixed |= r;
|
||||||
// if the sub-rect is full-width we can pass the image data directly to
|
}
|
||||||
// OpenGL instead of copying, since there's no gap between scanlines
|
foreach (const QRect &rect, fixed.rects()) {
|
||||||
if (rect.width() == imageRect.width()) {
|
// if the sub-rect is full-width we can pass the image data directly to
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
// OpenGL instead of copying, since there's no gap between scanlines
|
||||||
m_image.constScanLine(rect.y()));
|
if (rect.width() == imageRect.width()) {
|
||||||
} else {
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
m_image.constScanLine(rect.y()));
|
||||||
m_image.copy(rect).constBits());
|
} else {
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
m_image.copy(rect).constBits());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user