From fa8030a935acaacee570eee320e7510a4cfdc853 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 11:36:40 +0200 Subject: Speed up QPixmap::width(), height(), isNull() and depth(). This change moves the w, h, d variables to QPixmapData and introduces is_null to keep track of nullness. This is possible only because QPixmapData is internal API; otherwise we'd have to be smarter. The optimization makes the QPixmap::width() function take 7 instructions, down from 34 before. For the calculator demo in the declarative ui branch this reduces a block of 750000 instructions (out of 30000000) to around 100000-150000 instructions. Tested on Windows, Linux, Mac. Raster, X11 and OpenGL paint engines. Have not tested the DirectFB engine. Reviewed-by: Trond --- src/gui/image/qpixmap.cpp | 2 +- src/gui/image/qpixmap.h | 6 +-- src/gui/image/qpixmap_mac.cpp | 5 +- src/gui/image/qpixmap_mac_p.h | 1 - src/gui/image/qpixmap_raster.cpp | 14 +++-- src/gui/image/qpixmap_x11.cpp | 10 +++- src/gui/image/qpixmap_x11_p.h | 2 - src/gui/image/qpixmapdata.cpp | 12 ++++- src/gui/image/qpixmapdata_p.h | 13 +++-- src/opengl/qpixmapdata_gl.cpp | 60 ++++++++++++---------- src/opengl/qpixmapdata_gl_p.h | 7 +-- .../gfxdrivers/directfb/qdirectfbpixmap.cpp | 8 +++ 12 files changed, 88 insertions(+), 52 deletions(-) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 6da291c..56c3a29 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -552,7 +552,7 @@ bool QPixmap::isQBitmap() const */ bool QPixmap::isNull() const { - return data->width() == 0; + return data->isNull(); } /*! diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index e4faebd..d1e2ecb 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -79,11 +79,11 @@ public: QPixmap &operator=(const QPixmap &); operator QVariant() const; - bool isNull() const; + bool isNull() const; // ### Qt 5: make inline int devType() const; - int width() const; - int height() const; + int width() const; // ### Qt 5: make inline + int height() const; // ### Qt 5: make inline QSize size() const; QRect rect() const; int depth() const; diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index ca9d497..b40694a 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -168,7 +168,7 @@ static inline QRgb qt_conv16ToRgb(ushort c) { QSet QMacPixmapData::validDataPointers; QMacPixmapData::QMacPixmapData(PixelType type) - : QPixmapData(type, MacClass), w(0), h(0), d(0), has_alpha(0), has_mask(0), + : QPixmapData(type, MacClass), has_alpha(0), has_mask(0), uninit(true), pixels(0), pixelsToFree(0), bytesPerRow(0), cg_data(0), cg_dataBeingReleased(0), cg_mask(0), #ifndef QT_MAC_NO_QUICKDRAW @@ -188,11 +188,13 @@ void QMacPixmapData::resize(int width, int height) w = width; h = height; + is_null = (w <= 0 || h <= 0); d = (pixelType() == BitmapType ? 1 : 32); bool make_null = w <= 0 || h <= 0; // create null pixmap if (make_null || d == 0) { w = 0; h = 0; + is_null = true; d = 0; if (!make_null) qWarning("Qt: QPixmap: Invalid pixmap parameters"); @@ -231,6 +233,7 @@ void QMacPixmapData::fromImage(const QImage &img, w = img.width(); h = img.height(); + is_null = (w <= 0 || h <= 0); d = (pixelType() == BitmapType ? 1 : img.depth()); QImage image = img; diff --git a/src/gui/image/qpixmap_mac_p.h b/src/gui/image/qpixmap_mac_p.h index 66797ed..a3ff0d3 100644 --- a/src/gui/image/qpixmap_mac_p.h +++ b/src/gui/image/qpixmap_mac_p.h @@ -83,7 +83,6 @@ public: QPaintEngine* paintEngine() const; private: - int w, h, d; uint has_alpha : 1, has_mask : 1, uninit : 1; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 2c57ede..9cc896b 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -85,6 +85,10 @@ void QRasterPixmapData::resize(int width, int height) #endif image = QImage(width, height, format); + w = width; + h = height; + d = image.depth(); + is_null = (w <= 0 || h <= 0); if (pixelType() == BitmapType && !image.isNull()) { image.setNumColors(2); @@ -168,6 +172,10 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage, } } #endif + w = image.d->width; + h = image.d->height; + d = image.d->depth; + is_null = (w <= 0 || h <= 0); setSerialNumber(image.serialNumber()); } @@ -329,9 +337,9 @@ int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const // override the image dpi with the screen dpi when rendering to a pixmap switch (metric) { case QPaintDevice::PdmWidth: - return d->width; + return w; case QPaintDevice::PdmHeight: - return d->height; + return h; case QPaintDevice::PdmWidthMM: return qRound(d->width * 25.4 / qt_defaultDpiX()); case QPaintDevice::PdmHeightMM: @@ -339,7 +347,7 @@ int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const case QPaintDevice::PdmNumColors: return d->colortable.size(); case QPaintDevice::PdmDepth: - return d->depth; + return this->d; case QPaintDevice::PdmDpiX: // fall-through case QPaintDevice::PdmPhysicalDpiX: return qt_defaultDpiX(); diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index b7fe92a..86cf515 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -312,7 +312,7 @@ static int qt_pixmap_serial = 0; int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0; QX11PixmapData::QX11PixmapData(PixelType type) - : QPixmapData(type, X11Class), hd(0), w(0), h(0), d(0), + : QPixmapData(type, X11Class), hd(0), uninit(true), read_only(false), x11_mask(0), picture(0), mask_picture(0), hd2(0), share_mode(QPixmap::ImplicitlyShared), pengine(0) { @@ -324,6 +324,7 @@ void QX11PixmapData::resize(int width, int height) w = width; h = height; + is_null = (w <= 0 || h <= 0); if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) { QX11InfoData* xd = xinfo.getX11Data(true); @@ -347,6 +348,7 @@ void QX11PixmapData::resize(int width, int height) if (make_null || d == 0) { w = 0; h = 0; + is_null = true; hd = 0; picture = 0; d = 0; @@ -375,6 +377,7 @@ void QX11PixmapData::fromImage(const QImage &img, w = img.width(); h = img.height(); d = img.depth(); + is_null = (w <= 0 || h <= 0); if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) { QX11InfoData* xd = xinfo.getX11Data(true); @@ -395,6 +398,7 @@ void QX11PixmapData::fromImage(const QImage &img, if (uint(w) >= 32768 || uint(h) >= 32768) { w = h = 0; + is_null = true; return; } @@ -1109,6 +1113,7 @@ void QX11PixmapData::bitmapFromImage(const QImage &image) w = img.width(); h = img.height(); d = 1; + is_null = (w <= 0 || h <= 0); int bpl = (w + 7) / 8; int ibpl = img.bytesPerLine(); if (bpl != ibpl) { @@ -1876,6 +1881,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform, x11Data->d = d; x11Data->w = w; x11Data->h = h; + x11Data->is_null = (w <= 0 || h <= 0); x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), w, h, d); @@ -2132,6 +2138,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect) d = x11Data->d; w = rect.width(); h = rect.height(); + is_null = (w <= 0 || h <= 0); hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, x11Data->xinfo.screen()), w, h, d); @@ -2250,6 +2257,7 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode) data->uninit = false; data->w = width; data->h = height; + data->is_null = (width <= 0 || height <= 0); data->d = depth; data->hd = pixmap; diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h index addcc7c..3de9a0f 100644 --- a/src/gui/image/qpixmap_x11_p.h +++ b/src/gui/image/qpixmap_x11_p.h @@ -108,8 +108,6 @@ private: Qt::HANDLE hd; - int w, h; - short d; uint uninit : 1; uint read_only : 1; diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index 094d7e4..b50d664 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -49,9 +49,17 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; QPixmapData::QPixmapData(PixelType pixelType, int objectId) - : ref(0), detach_no(0), type(pixelType), id(objectId), ser_no(0), is_cached(false) + : w(0), + h(0), + d(0), + is_null(true), + ref(0), + detach_no(0), + type(pixelType), + id(objectId), + ser_no(0), + is_cached(false) { - } QPixmapData::~QPixmapData() diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 4c49dd2..29dafaf 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -99,13 +99,18 @@ public: virtual QImage* buffer(); - int width() const { return metric(QPaintDevice::PdmWidth); } - int height() const { return metric(QPaintDevice::PdmHeight); } - int numColors() const { return metric(QPaintDevice::PdmNumColors); } - int depth() const { return metric(QPaintDevice::PdmDepth); } + inline int width() const { return w; } + inline int height() const { return h; } + inline int numColors() const { return metric(QPaintDevice::PdmNumColors); } + inline int depth() const { return d; } + inline bool isNull() const { return is_null; } protected: void setSerialNumber(int serNo); + int w; + int h; + int d; + bool is_null; private: friend class QPixmap; diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index f745aae..8a2187c 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -96,8 +96,6 @@ static int qt_gl_pixmap_serial = 0; QGLPixmapData::QGLPixmapData(PixelType type) : QPixmapData(type, OpenGLClass) - , m_width(0) - , m_height(0) , m_renderFbo(0) , m_textureId(0) , m_engine(0) @@ -123,7 +121,7 @@ QGLPixmapData::~QGLPixmapData() bool QGLPixmapData::isValid() const { - return m_width > 0 && m_height > 0; + return w > 0 && h > 0; } bool QGLPixmapData::isValidContext(const QGLContext *ctx) const @@ -137,7 +135,7 @@ bool QGLPixmapData::isValidContext(const QGLContext *ctx) const void QGLPixmapData::resize(int width, int height) { - if (width == m_width && height == m_height) + if (width == w && height == h) return; if (width <= 0 || height <= 0) { @@ -145,8 +143,10 @@ void QGLPixmapData::resize(int width, int height) height = 0; } - m_width = width; - m_height = height; + w = width; + h = height; + is_null = (w <= 0 || h <= 0); + d = pixelType() == QPixmapData::PixmapType ? 32 : 1; if (m_textureId) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); @@ -176,7 +176,7 @@ void QGLPixmapData::ensureCreated() const glGenTextures(1, &m_textureId); glBindTexture(target, m_textureId); GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB; - glTexImage2D(target, 0, format, m_width, m_height, 0, + glTexImage2D(target, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -186,7 +186,7 @@ void QGLPixmapData::ensureCreated() const const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format); glBindTexture(target, m_textureId); - glTexSubImage2D(target, 0, 0, 0, m_width, m_height, format, + glTexSubImage2D(target, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits()); if (useFramebufferObjects()) @@ -202,7 +202,7 @@ QGLFramebufferObject *QGLPixmapData::fbo() const void QGLPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags) { - if (image.size() == QSize(m_width, m_height)) + if (image.size() == QSize(w, h)) setSerialNumber(++qt_gl_pixmap_serial); resize(image.width(), image.height()); @@ -218,6 +218,10 @@ void QGLPixmapData::fromImage(const QImage &image, m_hasFillColor = false; m_hasAlpha = image.hasAlphaChannel(); + w = image.width(); + h = image.height(); + is_null = (w <= 0 || h <= 0); + d = pixelType() == QPixmapData::PixmapType ? 32 : 1; if (m_textureId) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); @@ -272,7 +276,7 @@ QImage QGLPixmapData::fillImage(const QColor &color) const { QImage img; if (pixelType() == BitmapType) { - img = QImage(m_width, m_height, QImage::Format_MonoLSB); + img = QImage(w, h, QImage::Format_MonoLSB); img.setNumColors(2); img.setColor(0, QColor(Qt::color0).rgba()); img.setColor(1, QColor(Qt::color1).rgba()); @@ -283,7 +287,7 @@ QImage QGLPixmapData::fillImage(const QColor &color) const else img.fill(1); } else { - img = QImage(m_width, m_height, + img = QImage(w, h, m_hasAlpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); @@ -310,7 +314,7 @@ QImage QGLPixmapData::toImage() const QGLShareContextScope ctx(qt_gl_share_widget()->context()); extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); glBindTexture(GL_TEXTURE_2D, m_textureId); - return qt_gl_read_texture(QSize(m_width, m_height), true, true); + return qt_gl_read_texture(QSize(w, h), true, true); } struct TextureBuffer @@ -342,9 +346,9 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const GL_TEXTURE_2D, m_textureId, 0); const int x0 = 0; - const int x1 = m_width; + const int x1 = w; const int y0 = 0; - const int y1 = m_height; + const int y1 = h; glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle()); @@ -424,15 +428,15 @@ QPaintEngine* QGLPixmapData::paintEngine() const textureBufferStack << createTextureBuffer(size()); } else { QSize sz = textureBufferStack.at(currentTextureBuffer).fbo->size(); - if (sz.width() < m_width || sz.height() < m_height) { - if (sz.width() < m_width) - sz.setWidth(qMax(m_width, qRound(sz.width() * 1.5))); - if (sz.height() < m_height) - sz.setHeight(qMax(m_height, qRound(sz.height() * 1.5))); + if (sz.width() < w || sz.height() < h) { + if (sz.width() < w) + sz.setWidth(qMax(w, qRound(sz.width() * 1.5))); + if (sz.height() < h) + sz.setHeight(qMax(h, qRound(sz.height() * 1.5))); // wasting too much space? - if (sz.width() * sz.height() > m_width * m_height * 2.5) - sz = QSize(m_width, m_height); + if (sz.width() * sz.height() > w * h * 2.5) + sz = QSize(w, h); delete textureBufferStack.at(currentTextureBuffer).fbo; textureBufferStack[currentTextureBuffer] = @@ -470,7 +474,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const } else { if (m_hasFillColor) { m_dirty = true; - m_source = QImage(m_width, m_height, QImage::Format_ARGB32_Premultiplied); + m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied); m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } @@ -493,22 +497,22 @@ extern int qt_defaultDpiY(); int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { - if (m_width == 0) + if (w == 0) return 0; switch (metric) { case QPaintDevice::PdmWidth: - return m_width; + return w; case QPaintDevice::PdmHeight: - return m_height; + return h; case QPaintDevice::PdmNumColors: return 0; case QPaintDevice::PdmDepth: - return pixelType() == QPixmapData::PixmapType ? 32 : 1; + return d; case QPaintDevice::PdmWidthMM: - return qRound(m_width * 25.4 / qt_defaultDpiX()); + return qRound(w * 25.4 / qt_defaultDpiX()); case QPaintDevice::PdmHeightMM: - return qRound(m_height * 25.4 / qt_defaultDpiY()); + return qRound(h * 25.4 / qt_defaultDpiY()); case QPaintDevice::PdmDpiX: case QPaintDevice::PdmPhysicalDpiX: return qt_defaultDpiX(); diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 605b25b..a6aa22d 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -94,9 +94,7 @@ public: bool needsFill() const { return m_hasFillColor; } QColor fillColor() const { return m_fillColor; } - QSize size() const { return QSize(m_width, m_height); } - int width() const { return m_width; } - int height() const { return m_height; } + QSize size() const { return QSize(w, h); } QGLFramebufferObject *fbo() const; @@ -117,9 +115,6 @@ private: QImage fillImage(const QColor &color) const; - int m_width; - int m_height; - mutable QGLFramebufferObject *m_renderFbo; mutable GLuint m_textureId; mutable QPaintEngine *m_engine; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index c2048d8..c239248 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -82,6 +82,10 @@ void QDirectFBPixmapData::resize(int width, int height) return; } + w = width; + h = height; + is_null = (w <= 0 || h <= 0); + d = metric(QPaintDevice::PdmDepth); setSerialNumber(++global_ser_no); } @@ -191,6 +195,10 @@ void QDirectFBPixmapData::fromImage(const QImage &i, invalidate(); return; } + w = metric(QPaintDevice::PdmWidth); + h = metric(QPaintDevice::PdmHeight); + is_null = (w <= 0 || h <= 0); + d = metric(QPaintDevice::PdmDepth); setSerialNumber(++global_ser_no); } -- cgit v0.12