source: trunk/src/opengl/qpixmapdata_gl.cpp@ 134

Last change on this file since 134 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 8.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtOpenGL module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qpixmap.h"
43
44#include <private/qpaintengine_raster_p.h>
45
46#include "qpixmapdata_gl_p.h"
47
48#include <private/qgl_p.h>
49#include <private/qdrawhelper_p.h>
50
51QT_BEGIN_NAMESPACE
52
53extern QGLWidget* qt_gl_share_widget();
54
55class QGLShareContextScope
56{
57public:
58 QGLShareContextScope(const QGLContext *ctx)
59 : m_oldContext(0)
60 , m_ctx(const_cast<QGLContext *>(ctx))
61 {
62 const QGLContext *currentContext = QGLContext::currentContext();
63 if (currentContext != ctx && !qgl_share_reg()->checkSharing(ctx, currentContext)) {
64 m_oldContext = const_cast<QGLContext *>(currentContext);
65 m_ctx->makeCurrent();
66 }
67 }
68
69 operator QGLContext *()
70 {
71 return m_ctx;
72 }
73
74 QGLContext *operator->()
75 {
76 return m_ctx;
77 }
78
79 ~QGLShareContextScope()
80 {
81 if (m_oldContext)
82 m_oldContext->makeCurrent();
83 }
84
85private:
86 QGLContext *m_oldContext;
87 QGLContext *m_ctx;
88};
89
90void qt_gl_convertFromGLImage(QImage *img)
91{
92 const int w = img->width();
93 const int h = img->height();
94
95 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
96 uint *p = (uint*)img->bits();
97 uint *end = p + w*h;
98
99 while (p < end) {
100 uint a = *p << 24;
101 *p = (*p >> 8) | a;
102 p++;
103 }
104
105 *img = img->mirrored();
106 } else {
107 // mirror image
108 uint *data = (uint *)img->bits();
109
110 const int mid = h/2;
111
112 for (int y = 0; y < mid; ++y) {
113 uint *p = data + y * w;
114 uint *end = p + w;
115 uint *q = data + (h - y - 1) * w;
116
117 while (p < end)
118 qSwap(*p++, *q++);
119 }
120 }
121}
122
123
124static int qt_gl_pixmap_serial = 0;
125
126QGLPixmapData::QGLPixmapData(PixelType type)
127 : QPixmapData(type, OpenGLClass)
128 , m_width(0)
129 , m_height(0)
130 , m_texture(0)
131 , m_dirty(false)
132{
133 setSerialNumber(++qt_gl_pixmap_serial);
134}
135
136QGLPixmapData::~QGLPixmapData()
137{
138 if (m_texture && qt_gl_share_widget()) {
139 QGLShareContextScope ctx(qt_gl_share_widget()->context());
140 glDeleteTextures(1, &m_texture);
141 }
142}
143
144bool QGLPixmapData::isValid() const
145{
146 return m_width > 0 && m_height > 0;
147}
148
149bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
150{
151 const QGLContext *share_ctx = qt_gl_share_widget()->context();
152 return ctx == share_ctx || qgl_share_reg()->checkSharing(ctx, share_ctx);
153}
154
155void QGLPixmapData::resize(int width, int height)
156{
157 if (width == m_width && height == m_height)
158 return;
159
160 m_width = width;
161 m_height = height;
162
163 m_source = QImage();
164 m_dirty = isValid();
165 setSerialNumber(++qt_gl_pixmap_serial);
166}
167
168void QGLPixmapData::ensureCreated() const
169{
170 if (!m_dirty)
171 return;
172
173 m_dirty = false;
174
175 QGLShareContextScope ctx(qt_gl_share_widget()->context());
176
177 const GLenum format = qt_gl_preferredTextureFormat();
178 const GLenum target = qt_gl_preferredTextureTarget();
179
180 if (!m_texture)
181 glGenTextures(1, &m_texture);
182
183 glBindTexture(target, m_texture);
184
185 if (m_source.isNull()) {
186 glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format, GL_UNSIGNED_BYTE, 0);
187 } else {
188 const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format);
189
190 glBindTexture(target, m_texture);
191 glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format,
192 GL_UNSIGNED_BYTE, tx.bits());
193
194 m_source = QImage();
195 }
196}
197
198void QGLPixmapData::fromImage(const QImage &image,
199 Qt::ImageConversionFlags)
200{
201 if (image.size() == QSize(m_width, m_height))
202 setSerialNumber(++qt_gl_pixmap_serial);
203 resize(image.width(), image.height());
204 m_source = image;
205 m_dirty = true;
206}
207
208void QGLPixmapData::fill(const QColor &color)
209{
210 if (!isValid())
211 return;
212
213 if (!m_source.isNull()) {
214 m_source.fill(PREMUL(color.rgba()));
215 } else {
216 // ## TODO: improve performance here
217 QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
218 img.fill(PREMUL(color.rgba()));
219
220 fromImage(img, 0);
221 }
222}
223
224bool QGLPixmapData::hasAlphaChannel() const
225{
226 return true;
227}
228
229QImage QGLPixmapData::toImage() const
230{
231 if (!isValid())
232 return QImage();
233
234 if (!m_source.isNull())
235 return m_source;
236 else if (m_dirty)
237 return QImage(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
238
239 ensureCreated();
240
241 QGLShareContextScope ctx(qt_gl_share_widget()->context());
242 QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
243
244 GLenum format = qt_gl_preferredTextureFormat();
245 GLenum target = qt_gl_preferredTextureTarget();
246
247 glBindTexture(target, m_texture);
248#ifndef QT_OPENGL_ES
249 glGetTexImage(target, 0, format, GL_UNSIGNED_BYTE, img.bits());
250#else
251 // XXX - cannot download textures this way on OpenGL/ES.
252#endif
253
254 qt_gl_convertFromGLImage(&img);
255
256 return img;
257}
258
259QPaintEngine* QGLPixmapData::paintEngine() const
260{
261 if (!isValid())
262 return 0;
263
264 m_source = toImage();
265 m_dirty = true;
266
267 return m_source.paintEngine();
268}
269
270GLuint QGLPixmapData::bind() const
271{
272 ensureCreated();
273 glBindTexture(qt_gl_preferredTextureTarget(), m_texture);
274 return m_texture;
275}
276
277GLuint QGLPixmapData::textureId() const
278{
279 ensureCreated();
280 return m_texture;
281}
282
283extern int qt_defaultDpiX();
284extern int qt_defaultDpiY();
285
286int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
287{
288 switch (metric) {
289 case QPaintDevice::PdmWidth:
290 return m_width;
291 case QPaintDevice::PdmHeight:
292 return m_height;
293 case QPaintDevice::PdmNumColors:
294 return 0;
295 case QPaintDevice::PdmDepth:
296 return pixelType() == QPixmapData::PixmapType ? 32 : 1;
297 case QPaintDevice::PdmWidthMM:
298 return qRound(m_width * 25.4 / qt_defaultDpiX());
299 case QPaintDevice::PdmHeightMM:
300 return qRound(m_height * 25.4 / qt_defaultDpiY());
301 case QPaintDevice::PdmDpiX:
302 case QPaintDevice::PdmPhysicalDpiX:
303 return qt_defaultDpiX();
304 case QPaintDevice::PdmDpiY:
305 case QPaintDevice::PdmPhysicalDpiY:
306 return qt_defaultDpiY();
307 default:
308 qWarning("QGLPixmapData::metric(): Invalid metric");
309 return 0;
310 }
311}
312
313QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.