61 Q_ASSERT(type == QPixmapData::PixmapType); |
62 Q_ASSERT(type == QPixmapData::PixmapType); |
62 vgImage = VG_INVALID_HANDLE; |
63 vgImage = VG_INVALID_HANDLE; |
63 vgImageOpacity = VG_INVALID_HANDLE; |
64 vgImageOpacity = VG_INVALID_HANDLE; |
64 cachedOpacity = 1.0f; |
65 cachedOpacity = 1.0f; |
65 recreate = true; |
66 recreate = true; |
|
67 inImagePool = false; |
|
68 inLRU = false; |
66 #if !defined(QT_NO_EGL) |
69 #if !defined(QT_NO_EGL) |
67 context = 0; |
70 context = 0; |
|
71 qt_vg_register_pixmap(this); |
68 #endif |
72 #endif |
69 setSerialNumber(++qt_vg_pixmap_serial); |
73 setSerialNumber(++qt_vg_pixmap_serial); |
70 } |
74 } |
71 |
75 |
72 QVGPixmapData::~QVGPixmapData() |
76 QVGPixmapData::~QVGPixmapData() |
|
77 { |
|
78 destroyImageAndContext(); |
|
79 #if !defined(QT_NO_EGL) |
|
80 qt_vg_unregister_pixmap(this); |
|
81 #endif |
|
82 } |
|
83 |
|
84 void QVGPixmapData::destroyImages() |
|
85 { |
|
86 if (inImagePool) { |
|
87 QVGImagePool *pool = QVGImagePool::instance(); |
|
88 if (vgImage != VG_INVALID_HANDLE) |
|
89 pool->releaseImage(this, vgImage); |
|
90 if (vgImageOpacity != VG_INVALID_HANDLE) |
|
91 pool->releaseImage(this, vgImageOpacity); |
|
92 } else { |
|
93 if (vgImage != VG_INVALID_HANDLE) |
|
94 vgDestroyImage(vgImage); |
|
95 if (vgImageOpacity != VG_INVALID_HANDLE) |
|
96 vgDestroyImage(vgImageOpacity); |
|
97 } |
|
98 vgImage = VG_INVALID_HANDLE; |
|
99 vgImageOpacity = VG_INVALID_HANDLE; |
|
100 inImagePool = false; |
|
101 } |
|
102 |
|
103 void QVGPixmapData::destroyImageAndContext() |
73 { |
104 { |
74 if (vgImage != VG_INVALID_HANDLE) { |
105 if (vgImage != VG_INVALID_HANDLE) { |
75 // We need to have a context current to destroy the image. |
106 // We need to have a context current to destroy the image. |
76 #if !defined(QT_NO_EGL) |
107 #if !defined(QT_NO_EGL) |
77 if (context->isCurrent()) { |
108 if (context->isCurrent()) { |
78 vgDestroyImage(vgImage); |
109 destroyImages(); |
79 if (vgImageOpacity != VG_INVALID_HANDLE) |
|
80 vgDestroyImage(vgImageOpacity); |
|
81 } else { |
110 } else { |
82 // We don't currently have a widget surface active, but we |
111 // We don't currently have a widget surface active, but we |
83 // need a surface to make the context current. So use the |
112 // need a surface to make the context current. So use the |
84 // shared pbuffer surface instead. |
113 // shared pbuffer surface instead. |
85 context->makeCurrent(qt_vg_shared_surface()); |
114 context->makeCurrent(qt_vg_shared_surface()); |
86 vgDestroyImage(vgImage); |
115 destroyImages(); |
87 if (vgImageOpacity != VG_INVALID_HANDLE) |
|
88 vgDestroyImage(vgImageOpacity); |
|
89 context->lazyDoneCurrent(); |
116 context->lazyDoneCurrent(); |
90 } |
117 } |
91 #else |
118 #else |
92 vgDestroyImage(vgImage); |
119 destroyImages(); |
93 if (vgImageOpacity != VG_INVALID_HANDLE) |
|
94 vgDestroyImage(vgImageOpacity); |
|
95 } else { |
|
96 #endif |
120 #endif |
97 } |
121 } |
98 #if !defined(QT_NO_EGL) |
122 #if !defined(QT_NO_EGL) |
99 if (context) |
123 if (context) { |
100 qt_vg_destroy_context(context); |
124 qt_vg_destroy_context(context, QInternal::Pixmap); |
101 #endif |
125 context = 0; |
|
126 } |
|
127 #endif |
|
128 recreate = true; |
102 } |
129 } |
103 |
130 |
104 QPixmapData *QVGPixmapData::createCompatiblePixmapData() const |
131 QPixmapData *QVGPixmapData::createCompatiblePixmapData() const |
105 { |
132 { |
106 return new QVGPixmapData(pixelType()); |
133 return new QVGPixmapData(pixelType()); |
200 // This is simpler than juggling multiple VG contexts. |
227 // This is simpler than juggling multiple VG contexts. |
201 const_cast<QVGPixmapData *>(this)->forceToImage(); |
228 const_cast<QVGPixmapData *>(this)->forceToImage(); |
202 return source.paintEngine(); |
229 return source.paintEngine(); |
203 } |
230 } |
204 |
231 |
|
232 // This function works around QImage::bits() making a deep copy if the |
|
233 // QImage is not const. We force it to be const and then get the bits. |
|
234 // XXX: Should add a QImage::constBits() in the future to replace this. |
|
235 static inline const uchar *qt_vg_imageBits(const QImage& image) |
|
236 { |
|
237 return image.bits(); |
|
238 } |
|
239 |
205 VGImage QVGPixmapData::toVGImage() |
240 VGImage QVGPixmapData::toVGImage() |
206 { |
241 { |
207 if (!isValid()) |
242 if (!isValid()) |
208 return VG_INVALID_HANDLE; |
243 return VG_INVALID_HANDLE; |
209 |
244 |
210 #if !defined(QT_NO_EGL) |
245 #if !defined(QT_NO_EGL) |
211 // Increase the reference count on the shared context. |
246 // Increase the reference count on the shared context. |
212 if (!context) |
247 if (!context) |
213 context = qt_vg_create_context(0); |
248 context = qt_vg_create_context(0, QInternal::Pixmap); |
214 #endif |
249 #endif |
215 |
250 |
216 if (recreate) { |
251 if (recreate && prevSize != QSize(w, h)) |
217 if (vgImage != VG_INVALID_HANDLE) { |
252 destroyImages(); |
218 vgDestroyImage(vgImage); |
253 else if (recreate) |
219 vgImage = VG_INVALID_HANDLE; |
254 cachedOpacity = -1.0f; // Force opacity image to be refreshed later. |
220 } |
|
221 if (vgImageOpacity != VG_INVALID_HANDLE) { |
|
222 vgDestroyImage(vgImageOpacity); |
|
223 vgImageOpacity = VG_INVALID_HANDLE; |
|
224 } |
|
225 } |
|
226 |
255 |
227 if (vgImage == VG_INVALID_HANDLE) { |
256 if (vgImage == VG_INVALID_HANDLE) { |
228 vgImage = vgCreateImage |
257 vgImage = QVGImagePool::instance()->createImageForPixmap |
229 (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); |
258 (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this); |
|
259 |
|
260 // Bail out if we run out of GPU memory - try again next time. |
|
261 if (vgImage == VG_INVALID_HANDLE) |
|
262 return VG_INVALID_HANDLE; |
|
263 |
|
264 inImagePool = true; |
|
265 } else if (inImagePool) { |
|
266 QVGImagePool::instance()->useImage(this); |
230 } |
267 } |
231 |
268 |
232 if (!source.isNull() && recreate) { |
269 if (!source.isNull() && recreate) { |
233 vgImageSubData |
270 vgImageSubData |
234 (vgImage, |
271 (vgImage, |
235 source.bits(), source.bytesPerLine(), |
272 qt_vg_imageBits(source), source.bytesPerLine(), |
236 VG_sARGB_8888_PRE, 0, 0, w, h); |
273 VG_sARGB_8888_PRE, 0, 0, w, h); |
237 } |
274 } |
238 |
275 |
239 recreate = false; |
276 recreate = false; |
|
277 prevSize = QSize(w, h); |
240 |
278 |
241 return vgImage; |
279 return vgImage; |
242 } |
280 } |
243 |
281 |
244 VGImage QVGPixmapData::toVGImage(qreal opacity) |
282 VGImage QVGPixmapData::toVGImage(qreal opacity) |
245 { |
283 { |
246 #if !defined(QT_SHIVAVG) |
284 #if !defined(QT_SHIVAVG) |
247 if (!isValid()) |
285 // Force the primary VG image to be recreated if necessary. |
|
286 if (toVGImage() == VG_INVALID_HANDLE) |
248 return VG_INVALID_HANDLE; |
287 return VG_INVALID_HANDLE; |
249 |
|
250 #if !defined(QT_NO_EGL) |
|
251 // Increase the reference count on the shared context. |
|
252 if (!context) |
|
253 context = qt_vg_create_context(0); |
|
254 #endif |
|
255 |
|
256 if (recreate) { |
|
257 if (vgImage != VG_INVALID_HANDLE) { |
|
258 vgDestroyImage(vgImage); |
|
259 vgImage = VG_INVALID_HANDLE; |
|
260 } |
|
261 if (vgImageOpacity != VG_INVALID_HANDLE) { |
|
262 vgDestroyImage(vgImageOpacity); |
|
263 vgImageOpacity = VG_INVALID_HANDLE; |
|
264 } |
|
265 } |
|
266 |
|
267 if (vgImage == VG_INVALID_HANDLE) { |
|
268 vgImage = vgCreateImage |
|
269 (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); |
|
270 } |
|
271 |
|
272 if (!source.isNull() && recreate) { |
|
273 vgImageSubData |
|
274 (vgImage, |
|
275 source.bits(), source.bytesPerLine(), |
|
276 VG_sARGB_8888_PRE, 0, 0, w, h); |
|
277 } |
|
278 |
|
279 recreate = false; |
|
280 |
288 |
281 if (opacity == 1.0f) |
289 if (opacity == 1.0f) |
282 return vgImage; |
290 return vgImage; |
283 |
291 |
|
292 // Create an alternative image for the selected opacity. |
284 if (vgImageOpacity == VG_INVALID_HANDLE || cachedOpacity != opacity) { |
293 if (vgImageOpacity == VG_INVALID_HANDLE || cachedOpacity != opacity) { |
285 if (vgImageOpacity == VG_INVALID_HANDLE) { |
294 if (vgImageOpacity == VG_INVALID_HANDLE) { |
286 vgImageOpacity = vgCreateImage |
295 if (inImagePool) { |
287 (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); |
296 vgImageOpacity = QVGImagePool::instance()->createImageForPixmap |
|
297 (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this); |
|
298 } else { |
|
299 vgImageOpacity = vgCreateImage |
|
300 (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); |
|
301 } |
|
302 |
|
303 // Bail out if we run out of GPU memory - try again next time. |
|
304 if (vgImageOpacity == VG_INVALID_HANDLE) |
|
305 return VG_INVALID_HANDLE; |
288 } |
306 } |
289 VGfloat matrix[20] = { |
307 VGfloat matrix[20] = { |
290 1.0f, 0.0f, 0.0f, 0.0f, |
308 1.0f, 0.0f, 0.0f, 0.0f, |
291 0.0f, 1.0f, 0.0f, 0.0f, |
309 0.0f, 1.0f, 0.0f, 0.0f, |
292 0.0f, 0.0f, 1.0f, 0.0f, |
310 0.0f, 0.0f, 1.0f, 0.0f, |