74 static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) |
76 static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) |
75 { |
77 { |
76 return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); |
78 return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); |
77 } |
79 } |
78 |
80 |
79 QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat) |
81 extern int qt_next_power_of_two(int v); |
|
82 |
|
83 static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz) |
|
84 { |
|
85 #ifdef QT_OPENGL_ES_2 |
|
86 QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height())); |
|
87 if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height()) |
|
88 return rounded; |
|
89 #endif |
|
90 return sz; |
|
91 } |
|
92 |
|
93 |
|
94 QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize) |
80 { |
95 { |
81 QGLFramebufferObject *chosen = 0; |
96 QGLFramebufferObject *chosen = 0; |
82 QGLFramebufferObject *candidate = 0; |
97 QGLFramebufferObject *candidate = 0; |
83 for (int i = 0; !chosen && i < m_fbos.size(); ++i) { |
98 for (int i = 0; !chosen && i < m_fbos.size(); ++i) { |
84 QGLFramebufferObject *fbo = m_fbos.at(i); |
99 QGLFramebufferObject *fbo = m_fbos.at(i); |
85 |
100 |
|
101 if (strictSize) { |
|
102 if (fbo->size() == requestSize && fbo->format() == requestFormat) { |
|
103 chosen = fbo; |
|
104 break; |
|
105 } else { |
|
106 continue; |
|
107 } |
|
108 } |
|
109 |
86 if (fbo->format() == requestFormat) { |
110 if (fbo->format() == requestFormat) { |
87 // choose the fbo with a matching format and the closest size |
111 // choose the fbo with a matching format and the closest size |
88 if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo)) |
112 if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo)) |
89 candidate = fbo; |
113 candidate = fbo; |
90 } |
114 } |
293 m_dirty = false; |
321 m_dirty = false; |
294 |
322 |
295 QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
323 QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
296 m_ctx = ctx; |
324 m_ctx = ctx; |
297 |
325 |
298 const GLenum format = qt_gl_preferredTextureFormat(); |
326 const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB; |
|
327 #ifdef QT_OPENGL_ES_2 |
|
328 const GLenum external_format = internal_format; |
|
329 #else |
|
330 const GLenum external_format = qt_gl_preferredTextureFormat(); |
|
331 #endif |
299 const GLenum target = GL_TEXTURE_2D; |
332 const GLenum target = GL_TEXTURE_2D; |
300 |
333 |
301 if (!m_texture.id) { |
334 if (!m_texture.id) { |
302 glGenTextures(1, &m_texture.id); |
335 glGenTextures(1, &m_texture.id); |
303 glBindTexture(target, m_texture.id); |
336 glBindTexture(target, m_texture.id); |
304 GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB; |
337 glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0); |
305 glTexImage2D(target, 0, format, w, h, 0, |
|
306 GL_RGBA, GL_UNSIGNED_BYTE, 0); |
|
307 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
338 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
308 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
339 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
309 } |
340 } |
310 |
341 |
311 if (!m_source.isNull()) { |
342 if (!m_source.isNull()) { |
312 const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format); |
343 if (external_format == GL_RGB) { |
313 |
344 const QImage tx = m_source.convertToFormat(QImage::Format_RGB888); |
314 glBindTexture(target, m_texture.id); |
345 |
315 glTexSubImage2D(target, 0, 0, 0, w, h, format, |
346 glBindTexture(target, m_texture.id); |
316 GL_UNSIGNED_BYTE, tx.bits()); |
347 glTexSubImage2D(target, 0, 0, 0, w, h, external_format, |
|
348 GL_UNSIGNED_BYTE, tx.bits()); |
|
349 } else { |
|
350 const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format); |
|
351 |
|
352 glBindTexture(target, m_texture.id); |
|
353 glTexSubImage2D(target, 0, 0, 0, w, h, external_format, |
|
354 GL_UNSIGNED_BYTE, tx.bits()); |
|
355 } |
317 |
356 |
318 if (useFramebufferObjects()) |
357 if (useFramebufferObjects()) |
319 m_source = QImage(); |
358 m_source = QImage(); |
320 } |
359 } |
321 |
360 |
355 if (m_texture.id) { |
394 if (m_texture.id) { |
356 QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
395 QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
357 glDeleteTextures(1, &m_texture.id); |
396 glDeleteTextures(1, &m_texture.id); |
358 m_texture.id = 0; |
397 m_texture.id = 0; |
359 } |
398 } |
|
399 } |
|
400 |
|
401 bool QGLPixmapData::fromFile(const QString &filename, const char *format, |
|
402 Qt::ImageConversionFlags flags) |
|
403 { |
|
404 if (pixelType() == QPixmapData::BitmapType) |
|
405 return QPixmapData::fromFile(filename, format, flags); |
|
406 QFile file(filename); |
|
407 if (!file.open(QIODevice::ReadOnly)) |
|
408 return false; |
|
409 QByteArray data = file.peek(64); |
|
410 bool alpha; |
|
411 if (m_texture.canBindCompressedTexture |
|
412 (data.constData(), data.size(), format, &alpha)) { |
|
413 resize(0, 0); |
|
414 data = file.readAll(); |
|
415 file.close(); |
|
416 QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
|
417 QSize size = m_texture.bindCompressedTexture |
|
418 (data.constData(), data.size(), format); |
|
419 if (!size.isEmpty()) { |
|
420 w = size.width(); |
|
421 h = size.height(); |
|
422 is_null = false; |
|
423 d = 32; |
|
424 m_hasAlpha = alpha; |
|
425 m_source = QImage(); |
|
426 m_dirty = isValid(); |
|
427 return true; |
|
428 } |
|
429 return false; |
|
430 } |
|
431 fromImage(QImageReader(&file, format).read(), flags); |
|
432 return !isNull(); |
|
433 } |
|
434 |
|
435 bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, |
|
436 Qt::ImageConversionFlags flags) |
|
437 { |
|
438 bool alpha; |
|
439 const char *buf = reinterpret_cast<const char *>(buffer); |
|
440 if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { |
|
441 resize(0, 0); |
|
442 QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
|
443 QSize size = m_texture.bindCompressedTexture(buf, int(len), format); |
|
444 if (!size.isEmpty()) { |
|
445 w = size.width(); |
|
446 h = size.height(); |
|
447 is_null = false; |
|
448 d = 32; |
|
449 m_hasAlpha = alpha; |
|
450 m_source = QImage(); |
|
451 m_dirty = isValid(); |
|
452 return true; |
|
453 } |
|
454 } |
|
455 return QPixmapData::fromData(buffer, len, format, flags); |
360 } |
456 } |
361 |
457 |
362 bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) |
458 bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) |
363 { |
459 { |
364 Q_UNUSED(dx); |
460 Q_UNUSED(dx); |
424 { |
520 { |
425 QImage img; |
521 QImage img; |
426 if (pixelType() == BitmapType) { |
522 if (pixelType() == BitmapType) { |
427 img = QImage(w, h, QImage::Format_MonoLSB); |
523 img = QImage(w, h, QImage::Format_MonoLSB); |
428 |
524 |
429 img.setNumColors(2); |
525 img.setColorCount(2); |
430 img.setColor(0, QColor(Qt::color0).rgba()); |
526 img.setColor(0, QColor(Qt::color0).rgba()); |
431 img.setColor(1, QColor(Qt::color1).rgba()); |
527 img.setColor(1, QColor(Qt::color1).rgba()); |
432 |
528 |
433 if (color == Qt::color1) |
529 if (color == Qt::color1) |
434 img.fill(1); |
530 img.fill(1); |