QImage QEglGLPixmapData::toImage() const { TRACE(); // We should not do so many toImage calls alltogether. This is what is slowing us down right now. // QWK should keep a cache of transformed images instead of re-doing it every frame. // FIXME make QWebKit not do so many QPixmap(QImage(pixmap.toImage).transform()) style transformations. if (!isValid()) return QImage(); if (!m_source.isNull()) { return m_source; } else if (m_dirty || m_hasFillColor) { m_source = fillImage(m_fillColor); return m_source; } else { ensureCreated(); } // read the image from the FBO to memory if(m_fbo) { // we read the data back from the fbo m_ctx->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); // this does glReadPixels - not very fast! QImage temp=qt_gl_read_framebuffer(QSize(w, h), true, true); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); m_source=temp; m_ctx->doneCurrent(); return temp; } else if (m_texture.id) { // we read back from the texture by binding its id as a framebuffer // is this in the OpenGL standard? It seems to work m_ctx->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_texture.id); // this does glReadPixels - not very fast QImage temp=qt_gl_read_framebuffer(QSize(w, h), true, true); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); // should we cache the fetched image locally to speed up future access? // m_source=temp; m_ctx->doneCurrent(); return temp; } else { QImage temp(w,h, QImage::Format_ARGB32_Premultiplied); // FIXME indicating something went wrong, neither of above cases worked - look out for yellow images temp.fill(Qt::yellow); m_source=temp; return temp; } }
QImage QGLPixmapData::toImage() const { if (!isValid()) return QImage(); if (m_renderFbo) { copyBackFromRenderFbo(true); } else if (!m_source.isNull()) { // QVolatileImage::toImage() will make a copy always so no check // for active painting is needed. QImage img = m_source.toImage(); if (img.format() == QImage::Format_MonoLSB) { img.setColorCount(2); img.setColor(0, QColor(Qt::color0).rgba()); img.setColor(1, QColor(Qt::color1).rgba()); } return img; } else if (m_dirty || m_hasFillColor) { return fillImage(m_fillColor); } else { ensureCreated(); } QGLShareContextScope ctx(qt_gl_share_widget()->context()); glBindTexture(GL_TEXTURE_2D, m_texture.id); return qt_gl_read_texture(QSize(w, h), true, true); }
void QGLPixmapData::resize(int width, int height) { if (width == w && height == h) return; if (width <= 0 || height <= 0) { width = 0; height = 0; } w = width; h = height; is_null = (w <= 0 || h <= 0); d = pixelType() == QPixmapData::PixmapType ? 32 : 1; if (m_texture.id) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); glDeleteTextures(1, &m_texture.id); m_texture.id = 0; } m_source = QImage(); m_dirty = isValid(); setSerialNumber(++qt_gl_pixmap_serial); }
Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); glFinish(); QGLPixmapData pixmapData(QPixmapData::PixmapType); pixmapData.fromImage(image, 0); GLuint textureId = pixmapData.bind(); glFinish(); EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) textureId, preserved_image_attribs); glFinish(); if (eglimage) { EGLNativeSharedImageTypeNOK handle = QMeeGoExtensions::eglCreateSharedImageNOK(QEgl::display(), eglimage, NULL); QEgl::eglDestroyImageKHR(QEgl::display(), eglimage); glFinish(); return (Qt::HANDLE) handle; } else { qWarning("Failed to create shared image from pixmap/texture!"); return 0; } }
bool QGLPixmapData::fromFile(const QString &filename, const char *format, Qt::ImageConversionFlags flags) { if (pixelType() == QPixmapData::BitmapType) return QPixmapData::fromFile(filename, format, flags); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) return false; QByteArray data = file.peek(64); bool alpha; if (m_texture.canBindCompressedTexture (data.constData(), data.size(), format, &alpha)) { resize(0, 0); data = file.readAll(); file.close(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QSize size = m_texture.bindCompressedTexture (data.constData(), data.size(), format); if (!size.isEmpty()) { w = size.width(); h = size.height(); is_null = false; d = 32; m_hasAlpha = alpha; m_source = QImage(); m_dirty = isValid(); return true; } return false; } fromImage(QImageReader(&file, format).read(), flags); return !isNull(); }
void QMeeGoLivePixmapData::initializeThroughEGLImage() { if (texture()->id != 0) return; QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); EGLImageKHR eglImage = EGL_NO_IMAGE_KHR; GLuint newTextureId = 0; eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer) backingX11Pixmap->handle(), preserved_attribs); if (eglImage == EGL_NO_IMAGE_KHR) { qWarning("eglCreateImageKHR failed (live texture)!"); return; } glGenTextures(1, &newTextureId); glBindTexture(GL_TEXTURE_2D, newTextureId); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (EGLImageKHR) eglImage); if (glGetError() == GL_NO_ERROR) { resize(backingX11Pixmap->width(), backingX11Pixmap->height()); texture()->id = newTextureId; texture()->options &= ~QGLContext::InvertedYBindOption; m_hasAlpha = backingX11Pixmap->hasAlphaChannel(); } else { qWarning("Failed to create a texture from an egl image (live texture)!"); glDeleteTextures(1, &newTextureId); } QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); }
bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags) { bool alpha; const char *buf = reinterpret_cast<const char *>(buffer); if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { resize(0, 0); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QSize size = m_texture.bindCompressedTexture(buf, int(len), format); if (!size.isEmpty()) { w = size.width(); h = size.height(); is_null = false; d = 32; m_hasAlpha = alpha; m_source = QVolatileImage(); m_dirty = isValid(); return true; } } QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len); QBuffer b(&a); b.open(QIODevice::ReadOnly); QImage image = QImageReader(&b, format).read(); if (image.isNull()) return false; createPixmapForImage(image, flags, true); return !isNull(); }
void QEglGLPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags flags) { TRACE(); resize(image.width(), image.height()); if (pixelType() == BitmapType) { m_source = image.convertToFormat(QImage::Format_MonoLSB); } else { QImage::Format format = QImage::Format_RGB32; if (qApp->desktop()->depth() == 16) format = QImage::Format_RGB16; if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) format = QImage::Format_ARGB32_Premultiplied;; m_source = image.convertToFormat(format); } m_dirty = true; m_hasFillColor = false; m_hasAlpha = m_source.hasAlphaChannel(); w = image.width(); h = image.height(); is_null = (w <= 0 || h <= 0); d = m_source.depth(); if (m_texture.id) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); glDeleteTextures(1, &m_texture.id); m_texture.id = 0; } }
bool QGLPixmapData::isValidContext(const QGLContext *ctx) const { if (ctx == m_ctx) return true; const QGLContext *share_ctx = qt_gl_share_widget()->context(); return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); }
bool QEglGLPixmapData::isValidContext(const QGLContext *ctx) const { TRACE(); if (ctx == m_ctx) return true; const QGLContext *share_ctx = qt_gl_share_widget()->context(); bool ret = ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); return ret; }
QPaintEngine* QGLPixmapData::paintEngine() const { if (!isValid()) return 0; if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) qt_gl_share_widget()->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(4); format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { if (!m_engine) m_engine = new QGL2PaintEngineEx; return m_engine; } qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; } // If the application wants to paint into the QPixmap, we first // force it to QImage format and then paint into that. // This is simpler than juggling multiple GL contexts. const_cast<QGLPixmapData *>(this)->forceToImage(); if (m_hasFillColor) { m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } return m_source.paintEngine(); }
void QGLPixmapData::ensureCreated() const { if (!m_dirty) return; m_dirty = false; if (nativeImageHandleProvider && !nativeImageHandle) const_cast<QGLPixmapData *>(this)->createFromNativeImageHandleProvider(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); m_ctx = ctx; #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE if (m_sgImage) { qt_resolve_eglimage_gl_extensions(ctx); // ensure initialized bool textureIsBound = false; GLuint newTextureId; EGLint imgAttr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display() , EGL_NO_CONTEXT , EGL_NATIVE_PIXMAP_KHR , (EGLClientBuffer)m_sgImage , imgAttr); glGenTextures(1, &newTextureId); glBindTexture( GL_TEXTURE_2D, newTextureId); if (image != EGL_NO_IMAGE_KHR) { glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); GLint err = glGetError(); if (err == GL_NO_ERROR) textureIsBound = true; QEgl::eglDestroyImageKHR(QEgl::display(), image); } if (textureIsBound) { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); m_texture.id = newTextureId; m_texture.boundPixmap = const_cast<QGLPixmapData*>(this); QGLSgImageTextureCleanup::cleanupForContext(m_ctx)->insert(m_texture.id, const_cast<QGLPixmapData*>(this)); } else { qWarning("QGLPixmapData: Failed to create texture from a SgImage image of size %dx%d", w, h); glDeleteTextures(1, &newTextureId); } } #endif }
void QGLTexturePool::releaseTexture(QGLPixmapData *data, GLuint texture) { // Very simple strategy at the moment: just destroy the texture. if (data) removeFromLRU(data); QGLWidget *shareWidget = qt_gl_share_widget(); if (shareWidget) { QGLShareContextScope ctx(shareWidget->context()); glDeleteTextures(1, &texture); } }
QPaintEngine* QGLPixmapData::paintEngine() const { if (!isValid()) return 0; if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) qt_gl_share_widget()->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(4); format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { if (!m_engine) m_engine = new QGL2PaintEngineEx; return m_engine; } qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; } m_dirty = true; if (m_source.size() != size()) m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied); if (m_hasFillColor) { m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } return m_source.paintEngine(); }
QImage* QMeeGoLivePixmapData::lock(EGLSyncKHR fenceSync) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); if (fenceSync) { QMeeGoExtensions::eglClientWaitSyncKHR(QEgl::display(), fenceSync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); } void *data = 0; int pitch = 0; int surfaceWidth = 0; int surfaceHeight = 0; EGLSurface surface = 0; QImage::Format format; lockedImage = QImage(); surface = getSurfaceForBackingPixmap(); if (! QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, lock_attribs)) { qWarning("Failed to lock surface (live texture)!"); return &lockedImage; } eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) &data); eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) &pitch); eglQuerySurface(QEgl::display(), surface, EGL_WIDTH, (EGLint*) &surfaceWidth); eglQuerySurface(QEgl::display(), surface, EGL_HEIGHT, (EGLint*) &surfaceHeight); // Ok, here we know we just support those two formats. Real solution would be: // query also the format. if (backingX11Pixmap->depth() > 16) format = QImage::Format_ARGB32_Premultiplied; else format = QImage::Format_RGB16; if (data == NULL || pitch == 0) { qWarning("Failed to query the live texture!"); return &lockedImage; } if (width() != surfaceWidth || height() != surfaceHeight) { qWarning("Live texture dimensions don't match!"); QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), surface); return &lockedImage; } lockedImage = QImage((uchar *) data, width(), height(), pitch, format); return &lockedImage; }
QGLPixmapData::~QGLPixmapData() { QGLWidget *shareWidget = qt_gl_share_widget(); if (!shareWidget) return; delete m_engine; if (m_texture.id) { QGLShareContextScope ctx(shareWidget->context()); glDeleteTextures(1, &m_texture.id); } }
bool QMeeGoLivePixmapData::release(QImage* /*img*/) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), getSurfaceForBackingPixmap())) { lockedImage = QImage(); return true; } else { lockedImage = QImage(); return false; } }
bool QMeeGoPixmapData::destroyEGLSharedImage(Qt::HANDLE h) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); QMutableHashIterator <void*, QMeeGoImageInfo*> i(sharedImagesMap); while (i.hasNext()) { i.next(); if (i.value()->handle == h) i.remove(); } return QMeeGoExtensions::eglDestroySharedImageNOK(QEgl::display(), (EGLNativeSharedImageTypeNOK) h); }
void QEglGLPixmapData::ensureCreated() const { TRACE(); if (!m_dirty) return; m_dirty = false; QGLShareContextScope ctx(qt_gl_share_widget()->context()); m_ctx = ctx; const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB; const GLenum external_format = internal_format; const GLenum target = GL_TEXTURE_2D; TRACE(); if (!m_texture.id) { TRACE(); glGenTextures(1, &m_texture.id); glBindTexture(target, m_texture.id); glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } if (!m_source.isNull()) { TRACE(); if (external_format == GL_RGB) { const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true); glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, external_format, GL_UNSIGNED_BYTE, tx.bits()); } else { const QImage tx = m_ctx->d_func()->convertToGLFormat(m_source, true, external_format); glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, external_format, GL_UNSIGNED_BYTE, tx.bits()); } m_source = QImage(); } m_texture.options &= ~QGLContext::MemoryManagedBindOption; }
void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) { if (si.isNull()) qFatal("Trying to build pixmap with an empty/null softimage!"); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); bool textureIsBound = false; GLuint newTextureId; GLint newWidth, newHeight; glGenTextures(1, &newTextureId); glBindTexture(GL_TEXTURE_2D, newTextureId); glFinish(); EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_SHARED_IMAGE_NOK, (EGLClientBuffer)handle, preserved_image_attribs); if (image != EGL_NO_IMAGE_KHR) { glFinish(); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); GLint err = glGetError(); if (err == GL_NO_ERROR) textureIsBound = true; QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), image, EGL_WIDTH, &newWidth); QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), image, EGL_HEIGHT, &newHeight); QEgl::eglDestroyImageKHR(QEgl::display(), image); glFinish(); } if (textureIsBound) { // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix // for QGLPixmapData. fromTexture(newTextureId, newWidth, newHeight, (si.hasAlphaChannel() && const_cast<QImage &>(si).data_ptr()->checkForAlphaPixels())); softImage = si; QMeeGoPixmapData::registerSharedImage(handle, softImage); } else { qWarning("Failed to create a texture from a shared image!"); glDeleteTextures(1, &newTextureId); } }
void QGLPixmapData::destroyTexture() { if (m_texture.id) { QGLWidget *shareWidget = qt_gl_share_widget(); if (shareWidget) { m_texture.options |= QGLContext::MemoryManagedBindOption; m_texture.freeTexture(); m_texture.options &= ~QGLContext::MemoryManagedBindOption; } else if(QGLContext::currentContext()) { glDeleteTextures(1, &m_texture.id); m_texture.id = 0; m_texture.boundPixmap = 0; m_texture.boundKey = 0; } m_ctx = 0; m_dirty = true; } }
QImage QGLPixmapData::toImage() const { if (!isValid()) return QImage(); if (m_renderFbo) { copyBackFromRenderFbo(true); } else if (!m_source.isNull()) { return m_source; } else if (m_dirty || m_hasFillColor) { return fillImage(m_fillColor); } else { ensureCreated(); } QGLShareContextScope ctx(qt_gl_share_widget()->context()); glBindTexture(GL_TEXTURE_2D, m_texture.id); return qt_gl_read_texture(QSize(w, h), true, true); }
bool QGLPixmapData::isValidContext(const QGLContext *ctx) const { // On Symbian, we usually want to treat QGLPixmapData as // raster pixmap data because that's well known and tested // execution path which is used on other platforms as well. // That's why if source pixels are valid we return false // to simulate raster pixmaps. Only QPixmaps created from // SgImage will enable usage of QGLPixmapData. #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE if (m_sgImage) { // SgImage texture if (ctx == m_ctx) return true; const QGLContext *share_ctx = qt_gl_share_widget()->context(); return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); } #endif return false; }
QEglGLPixmapData::~QEglGLPixmapData() { TRACE(); QGLWidget *shareWidget = qt_gl_share_widget(); if (!shareWidget) return; delete m_engine; if (m_fbo) { QGLShareContextScope ctx(shareWidget->context()); glDeleteFramebuffers(1, &m_fbo); } if (m_texture.id) { QGLShareContextScope ctx(shareWidget->context()); glDeleteTextures(1, &m_texture.id); } }
void QGLPixmapData::destroyTexture() { if (inTexturePool) { QGLTexturePool *pool = QGLTexturePool::instance(); if (m_texture.id) pool->releaseTexture(this, m_texture.id); } else { if (m_texture.id) { QGLWidget *shareWidget = qt_gl_share_widget(); if (shareWidget) { QGLShareContextScope ctx(shareWidget->context()); glDeleteTextures(1, &m_texture.id); } } } m_texture.id = 0; inTexturePool = false; releaseNativeImageHandle(); }
void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const { if (!isValid()) return; m_hasFillColor = false; const QGLContext *share_ctx = qt_gl_share_widget()->context(); QGLShareContextScope ctx(share_ctx); ensureCreated(); if (!ctx->d_ptr->fbo) glGenFramebuffers(1, &ctx->d_ptr->fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture.id, 0); const int x0 = 0; const int x1 = w; const int y0 = 0; const int y1 = h; if (!m_renderFbo->isBound()) glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle()); glDisable(GL_SCISSOR_TEST); glBlitFramebufferEXT(x0, y0, x1, y1, x0, y0, x1, y1, GL_COLOR_BUFFER_BIT, GL_NEAREST); if (keepCurrentFboBound) { glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); } else { glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle()); ctx->d_ptr->current_fbo = m_renderFbo->handle(); } }
Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); GLuint textureId; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) { void *converted = convertBGRA32_to_RGBA32(image.bits(), image.width(), image.height(), image.bytesPerLine()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, converted); free(converted); } else { void *converted = convertRGB32_to_RGB565(image.bits(), image.width(), image.height(), image.bytesPerLine()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, converted); free(converted); } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) textureId, preserved_image_attribs); glDeleteTextures(1, &textureId); if (eglimage) { EGLNativeSharedImageTypeNOK handle = QMeeGoExtensions::eglCreateSharedImageNOK(QEgl::display(), eglimage, NULL); QEgl::eglDestroyImageKHR(QEgl::display(), eglimage); return (Qt::HANDLE) handle; } else { qWarning("Failed to create shared image from pixmap/texture!"); return 0; } }
void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) { if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) { QPixmapData::copy(data, rect); return; } const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data); if (other->m_renderFbo) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); resize(rect.width(), rect.height()); m_hasAlpha = other->m_hasAlpha; ensureCreated(); if (!ctx->d_ptr->fbo) glGenFramebuffers(1, &ctx->d_ptr->fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture.id, 0); if (!other->m_renderFbo->isBound()) glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle()); glDisable(GL_SCISSOR_TEST); if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2) static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState(); glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(), 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); } else { QPixmapData::copy(data, rect); } }
bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags) { bool alpha; const char *buf = reinterpret_cast<const char *>(buffer); if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { resize(0, 0); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QSize size = m_texture.bindCompressedTexture(buf, int(len), format); if (!size.isEmpty()) { w = size.width(); h = size.height(); is_null = false; d = 32; m_hasAlpha = alpha; m_source = QImage(); m_dirty = isValid(); return true; } } return QPixmapData::fromData(buffer, len, format, flags); }
void QGLWidget::resizeEvent(QResizeEvent *e) { Q_D(QGLWidget); if (!isValid()) return; // Shared widget can ignore resize events which // may happen due to orientation change if (this == qt_gl_share_widget()) return; if (!d->surfaceSizeInitialized || e->oldSize() != e->size()) { // On Symbian we need to recreate the surface on resize. d->recreateEglSurface(); d->surfaceSizeInitialized = true; } makeCurrent(); if (!d->glcx->initialized()) glInit(); resizeGL(width(), height()); }