void QGLPixmapData::fromNativeType(void* pixmap, NativeType type)
{
    if (type == QPixmapData::SgImage && pixmap) {
#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
        RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);

        m_sgImage = new RSgImage;
        m_sgImage->Open(sgImage->Id());

        TSgImageInfo info;
        sgImage->GetInfo(info);

        w = info.iSizeInPixels.iWidth;
        h = info.iSizeInPixels.iHeight;
        d = symbianPixeFormatBitsPerPixel((TUidPixelFormat)info.iPixelFormat);

        m_source = QVolatileImage();
        m_hasAlpha = true;
        m_hasFillColor = false;
        m_dirty = true;
        is_null = (w <= 0 || h <= 0);
#endif
    } else if (type == QPixmapData::FbsBitmap && pixmap) {
        CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap);
        QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight);
        if (size.width() == w && size.height() == h)
            setSerialNumber(++qt_gl_pixmap_serial);
        resize(size.width(), size.height());
        m_source = QVolatileImage(bitmap);
        if (pixelType() == BitmapType) {
            m_source.ensureFormat(QImage::Format_MonoLSB);
        } else if (!knownGoodFormat(m_source.format())) {
            m_source.beginDataAccess();
            QImage::Format format = idealFormat(m_source.imageRef(), Qt::AutoColor);
            m_source.endDataAccess(true);
            m_source.ensureFormat(format);
        }
        m_hasAlpha = m_source.hasAlphaChannel();
        m_hasFillColor = false;
        m_dirty = true;
        d = m_source.depth();
    } else if (type == QPixmapData::VolatileImage && pixmap) {
        // Support QS60Style in more efficient skin graphics retrieval.
        QVolatileImage *img = static_cast<QVolatileImage *>(pixmap);
        if (img->width() == w && img->height() == h)
            setSerialNumber(++qt_gl_pixmap_serial);
        resize(img->width(), img->height());
        m_source = *img;
        m_hasAlpha = m_source.hasAlphaChannel();
        m_hasFillColor = false;
        m_dirty = true;
        d = m_source.depth();
    } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) {
        destroyTexture();
        nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap);
        // Cannot defer the retrieval, we need at least the size right away.
        createFromNativeImageHandleProvider();
    }
}
예제 #2
0
void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
{
    if (type == QPixmapData::SgImage && pixmap) {
#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
        RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);
        destroyImages();
        prevSize = QSize();

        vgImage = sgImageToVGImage(context, *sgImage);
        if (vgImage != VG_INVALID_HANDLE) {
            w = vgGetParameteri(vgImage, VG_IMAGE_WIDTH);
            h = vgGetParameteri(vgImage, VG_IMAGE_HEIGHT);
            d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
        }

        is_null = (w <= 0 || h <= 0);
        source = QVolatileImage(); // readback will be done later, only when needed
        recreate = false;
        prevSize = QSize(w, h);
        updateSerial();
#endif
    } else if (type == QPixmapData::FbsBitmap && pixmap) {
        CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap);
        QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight);
        resize(size.width(), size.height());
        source = QVolatileImage(bitmap); // duplicates only, if possible
        if (source.isNull())
            return;
        if (!conversionLessFormat(source.format())) {
            // Here we may need to copy if the formats do not match.
            // (e.g. for display modes other than EColor16MAP and EColor16MU)
            source.beginDataAccess();
            QImage::Format format = idealFormat(&source.imageRef(), Qt::AutoColor);
            source.endDataAccess(true);
            source.ensureFormat(format);
        }
        recreate = true;
    } else if (type == QPixmapData::VolatileImage && pixmap) {
        QVolatileImage *img = static_cast<QVolatileImage *>(pixmap);
        resize(img->width(), img->height());
        source = *img;
        recreate = true;
    } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) {
        destroyImages();
        nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap);
        // Cannot defer the retrieval, we need at least the size right away.
        createFromNativeImageHandleProvider();
    }
}
예제 #3
0
// If copyBack is true, bind will copy the contents of the render
// FBO to the texture (which is not bound to the texture, as it's
// a multisample FBO).
GLuint QGLPixmapData::bind(bool copyBack) const
{
    if (m_renderFbo && copyBack) {
        copyBackFromRenderFbo(true);
    } else {
        ensureCreated();
    }

    GLuint id = m_texture.id;
    glBindTexture(GL_TEXTURE_2D, id);

    if (m_hasFillColor) {
        if (!useFramebufferObjects()) {
            m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
            m_source.fill(PREMUL(m_fillColor.rgba()));
        }

        m_hasFillColor = false;

        GLenum format = qt_gl_preferredTextureFormat();
        QImage tx(w, h, QImage::Format_ARGB32_Premultiplied);
        tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format));
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.constBits());
    }

    return id;
}
예제 #4
0
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();
}
예제 #5
0
void QVGPixmapData::ensureReadback(bool readOnly) const
{
    if (vgImage != VG_INVALID_HANDLE && source.isNull()) {
        source = QVolatileImage(w, h, sourceFormat());
        source.beginDataAccess();
        vgGetImageSubData(vgImage, source.bits(), source.bytesPerLine(),
                          qt_vg_image_to_vg_format(source.format()),
                          0, 0, w, h);
        source.endDataAccess();
        if (readOnly) {
            recreate = false;
        } else {
            // Once we did a readback, the original VGImage must be destroyed
            // because it may be shared (e.g. created via SgImage) and a subsequent
            // upload of the image data may produce unexpected results.
            const_cast<QVGPixmapData *>(this)->destroyImages();
#if defined(Q_OS_SYMBIAN)
            // There is now an own copy of the data so drop the handle provider,
            // otherwise toVGImage() would request the handle again, which is wrong.
            nativeImageHandleProvider = 0;
#endif
            recreate = true;
        }
    }
}
예제 #6
0
void QGLPixmapData::fill(const QColor &color)
{
    if (!isValid())
        return;

    bool hasAlpha = color.alpha() != 255;
    if (hasAlpha && !m_hasAlpha) {
        if (m_texture.id) {
            destroyTexture();
            m_dirty = true;
        }
        m_hasAlpha = color.alpha() != 255;
    }

    if (useFramebufferObjects()) {
        m_source = QVolatileImage();
        m_hasFillColor = true;
        m_fillColor = color;
    } else {
        forceToImage();

        if (m_source.depth() == 32) {
            m_source.fill(PREMUL(color.rgba()));

        } else if (m_source.depth() == 1) {
            if (color == Qt::color1)
                m_source.fill(1);
            else
                m_source.fill(0);
        }
    }
}
예제 #7
0
void tst_QVolatileImage::create()
{
    QVolatileImage nullImg;
    QVERIFY(nullImg.isNull());

    QVolatileImage img(100, 200, QImage::Format_ARGB32);
    QVERIFY(!img.isNull());
    QCOMPARE(img.width(), 100);
    QCOMPARE(img.height(), 200);
    QCOMPARE(img.format(), QImage::Format_ARGB32);
    QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height());
    QCOMPARE(img.hasAlphaChannel(), true);
    QCOMPARE(img.depth(), 32);

    QImage source(12, 23, QImage::Format_ARGB32_Premultiplied);
    img = QVolatileImage(source);
    QVERIFY(!img.isNull());
    QCOMPARE(img.width(), 12);
    QCOMPARE(img.height(), 23);
    QCOMPARE(img.format(), source.format());
    QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height());
    QVERIFY(img.imageRef() == source);
    QVERIFY(img.toImage() == source);
    QCOMPARE(img.hasAlphaChannel(), true);
    QCOMPARE(img.hasAlphaChannel(), img.imageRef().hasAlphaChannel());
    QCOMPARE(img.hasAlphaChannel(), img.toImage().hasAlphaChannel());
    QCOMPARE(img.depth(), 32);
}
void* QGLPixmapData::toNativeType(NativeType type)
{
    if (type == QPixmapData::FbsBitmap) {
        if (m_source.isNull())
            m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
        return m_source.duplicateNativeImage();
    }

    return 0;
}
예제 #9
0
void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
{
    resize(image.width(), image.height());

    QImage::Format format = idealFormat(&image, flags);

    if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
        source = QVolatileImage(image);
    } else {
        QImage convertedImage = image.convertToFormat(format);
        // convertToFormat won't detach the image if format stays the
        // same. Detaching is needed to prevent issues with painting
        // onto this QPixmap later on.
        convertedImage.detach();
        source = QVolatileImage(convertedImage);
    }

    recreate = true;
}
예제 #10
0
QImage QVGPixmapData::toImage() const
{
    if (!isValid())
        return QImage();
    ensureReadback(true);
    if (source.isNull()) {
        source = QVolatileImage(w, h, sourceFormat());
        recreate = true;
    }
    return source.toImage();
}
예제 #11
0
void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
{
    if (image.size() == QSize(w, h))
        setSerialNumber(++qt_gl_pixmap_serial);

    resize(image.width(), image.height());

    if (pixelType() == BitmapType) {
        QImage convertedImage = image.convertToFormat(QImage::Format_MonoLSB);
        if (image.format() == QImage::Format_MonoLSB)
            convertedImage.detach();

        m_source = QVolatileImage(convertedImage);

    } else {
        QImage::Format format = idealFormat(image, flags);

        if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
            m_source = QVolatileImage(image);
        } else {
            QImage convertedImage = image.convertToFormat(format);

            // convertToFormat won't detach the image if format stays the same.
            if (image.format() == format)
                convertedImage.detach();

            m_source = QVolatileImage(convertedImage);
        }
    }

    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();

    destroyTexture();
}
예제 #12
0
// Ensures that the pixmap is backed by some valid data and forces the data to
// be re-uploaded to the VGImage when toVGImage() is called next time.
void QVGPixmapData::forceToImage(bool allowReadback)
{
    if (!isValid())
        return;

    if (allowReadback)
        ensureReadback(false);

    if (source.isNull())
        source = QVolatileImage(w, h, sourceFormat());

    recreate = true;
}
예제 #13
0
// Force the pixmap data to be backed by some valid data.
void QGLPixmapData::forceToImage()
{
    if (!isValid())
        return;

    if (m_source.isNull()) {
        QImage::Format format = QImage::Format_ARGB32_Premultiplied;
        if (pixelType() == BitmapType)
            format = QImage::Format_MonoLSB;
        m_source = QVolatileImage(w, h, format);
    }

    m_dirty = true;
}
예제 #14
0
void QVGPixmapData::resize(int wid, int ht)
{
    if (w == wid && h == ht) {
        updateSerial();
        return;
    }

    w = wid;
    h = ht;
    d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
    is_null = (w <= 0 || h <= 0);
    source = QVolatileImage();
    recreate = true;

    updateSerial();
}
예제 #15
0
void tst_QVolatileImage::dataAccess()
{
    QImage source(12, 23, QImage::Format_ARGB32_Premultiplied);
    QVolatileImage img(source);
    QVERIFY(!img.isNull());
    img.beginDataAccess();
    QVERIFY(img.constBits());
    QVERIFY(img.imageRef().constBits());
    QVERIFY(img.bits());
    QVERIFY(img.imageRef().bits());
    img.endDataAccess();

    img = QVolatileImage(12, 23, QImage::Format_ARGB32);
    img.beginDataAccess();
    QVERIFY(img.constBits() && img.bits());
    img.endDataAccess();
}
예제 #16
0
void tst_QVolatileImage::create()
{
    QVolatileImage nullImg;
    QVERIFY(nullImg.isNull());

    QVolatileImage img(100, 200, QImage::Format_ARGB32);
    QVERIFY(!img.isNull());
    QCOMPARE(img.width(), 100);
    QCOMPARE(img.height(), 200);
    QCOMPARE(img.format(), QImage::Format_ARGB32);
    QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height());
    QCOMPARE(img.hasAlphaChannel(), true);
    QCOMPARE(img.depth(), 32);

    QImage source(12, 23, QImage::Format_ARGB32_Premultiplied);
    img = QVolatileImage(source);
    QVERIFY(!img.isNull());
    QCOMPARE(img.width(), 12);
    QCOMPARE(img.height(), 23);
    QCOMPARE(img.format(), source.format());
    QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height());
    QVERIFY(img.imageRef() == source);
    QVERIFY(img.toImage() == source);
    QCOMPARE(img.hasAlphaChannel(), true);
    QCOMPARE(img.hasAlphaChannel(), img.imageRef().hasAlphaChannel());
    QCOMPARE(img.hasAlphaChannel(), img.toImage().hasAlphaChannel());
    QCOMPARE(img.depth(), 32);

#ifdef Q_OS_SYMBIAN
    CFbsBitmap *bmp = new CFbsBitmap;
    QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone);
    QVolatileImage bmpimg(bmp);
    QVERIFY(!bmpimg.isNull());
    QCOMPARE(bmpimg.width(), 100);
    QCOMPARE(bmpimg.height(), 50);
    // Verify that we only did handle duplication, not pixel data copying.
    QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
    delete bmp;
    // Check if content is still valid.
    QImage copyimg = bmpimg.toImage();
    QCOMPARE(copyimg.format(), QImage::Format_ARGB32_Premultiplied);
#endif
}
예제 #17
0
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;

    destroyTexture();

    m_source = QVolatileImage();
    m_dirty = isValid();
    setSerialNumber(++qt_gl_pixmap_serial);
}
예제 #18
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)) {
        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 = QVolatileImage();
                m_dirty = isValid();
                return true;
            }
            return false;
        }
    }

    QImage image = QImageReader(filename, format).read();
    if (image.isNull())
        return false;

    createPixmapForImage(image, flags, true);

    return !isNull();
}
예제 #19
0
void QVGPixmapData::copy(const QPixmapData *data, const QRect &rect)
{
    // toImage() is potentially expensive with QVolatileImage so provide a
    // more efficient implementation of copy() that does not rely on it.
    if (!data) {
        return;
    }
    if (data->classId() != OpenVGClass) {
        fromImage(data->toImage(rect), Qt::NoOpaqueDetection);
        return;
    }
    const QVGPixmapData *pd = static_cast<const QVGPixmapData *>(data);
    QRect r = rect;
    if (r.isNull() || r.contains(QRect(0, 0, pd->w, pd->h))) {
        r = QRect(0, 0, pd->w, pd->h);
    }
    resize(r.width(), r.height());
    recreate = true;
    if (!pd->source.isNull()) {
        source = QVolatileImage(r.width(), r.height(), pd->source.format());
        source.copyFrom(&pd->source, r);
    }
}
예제 #20
0
void tst_QVolatileImage::copy()
{
    QVolatileImage img(100, 100, QImage::Format_RGB32);
    img.beginDataAccess();
    img.imageRef().fill(QColor(Qt::green).rgba());
    QPainter p(&img.imageRef());
    p.drawRect(10, 10, 50, 50);
    p.end();
    img.endDataAccess();

    QVolatileImage img2(100, 100, QImage::Format_RGB32);
    img2.copyFrom(&img, QRect());
    QImage imgA = img.toImage();
    QImage imgB = img2.toImage();
    QCOMPARE(imgA.size(), imgB.size());
    QVERIFY(fuzzyCompareImages(imgA, imgB, 0));

    img2 = QVolatileImage(20, 20, QImage::Format_RGB32);
    img2.copyFrom(&img, QRect(5, 5, 20, 20));
    imgA = img.toImage().copy(5, 5, 20, 20);
    imgB = img2.toImage();
    QCOMPARE(imgA.size(), imgB.size());
    QVERIFY(fuzzyCompareImages(imgA, imgB, 0));
}
예제 #21
0
void* QVGPixmapData::toNativeType(NativeType type)
{
    if (type == QPixmapData::SgImage) {
#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
        toVGImage();

        if (!isValid() || vgImage == VG_INVALID_HANDLE)
            return 0;

        TInt err = 0;

        RSgDriver driver;
        err = driver.Open();
        if (err != KErrNone)
            return 0;

        TSgImageInfo sgInfo;
        sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE;
        sgInfo.iSizeInPixels.SetSize(w, h);
        sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;

        QScopedPointer<RSgImage> sgImage(new RSgImage());
        err = sgImage->Create(sgInfo, NULL, NULL);
        if (err != KErrNone) {
            driver.Close();
            return 0;
        }

        const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE};
        EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(),
                EGL_NO_CONTEXT,
                EGL_NATIVE_PIXMAP_KHR,
                (EGLClientBuffer)sgImage.data(),
                (EGLint*)KEglImageAttribs);
        if (!eglImage || eglGetError() != EGL_SUCCESS) {
            sgImage->Close();
            driver.Close();
            return 0;
        }

        VGImage dstVgImage = QVG::vgCreateEGLImageTargetKHR(eglImage);
        if (!dstVgImage || vgGetError() != VG_NO_ERROR) {
            QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
            sgImage->Close();
            driver.Close();
            return 0;
        }

        vgCopyImage(dstVgImage, 0, 0,
                vgImage, 0, 0,
                w, h, VG_FALSE);

        if (vgGetError() != VG_NO_ERROR) {
            sgImage->Close();
            sgImage.reset();
        }

        // release stuff
        vgDestroyImage(dstVgImage);
        QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
        driver.Close();
        return reinterpret_cast<void*>(sgImage.take());
#endif
    } else if (type == QPixmapData::FbsBitmap && isValid()) {
        ensureReadback(true);
        if (source.isNull()) {
            source = QVolatileImage(w, h, sourceFormat());
        }
        // Just duplicate the bitmap handle, no data copying happens.
        return source.duplicateNativeImage();
    }
    return 0;
}
예제 #22
0
void QVGPixmapData::cleanup()
{
    is_null = w = h = 0;
    recreate = false;
    source = QVolatileImage();
}
예제 #23
0
void tst_QVolatileImage::bitmap()
{
#ifdef Q_OS_SYMBIAN
    CFbsBitmap *bmp = new CFbsBitmap;
    QVERIFY(bmp->Create(TSize(100, 50), EColor64K) == KErrNone);
    QVolatileImage bmpimg(bmp);
    CFbsBitmap *dupbmp = static_cast<CFbsBitmap *>(bmpimg.duplicateNativeImage());
    QVERIFY(dupbmp);
    QVERIFY(dupbmp != bmp);
    QCOMPARE(dupbmp->DataAddress(), bmp->DataAddress());
    delete dupbmp;
    delete bmp;
    bmpimg.beginDataAccess();
    qMemSet(bmpimg.bits(), 0, bmpimg.byteCount());
    qMemSet(bmpimg.bits(), 1, bmpimg.bytesPerLine() * bmpimg.height());
    bmpimg.endDataAccess();

    // Test bgr->rgb conversion in case of EColor16M.
    bmp = new CFbsBitmap;
    QVERIFY(bmp->Create(TSize(101, 89), EColor16M) == KErrNone);
    bmp->BeginDataAccess();
    TUint32 *addr = bmp->DataAddress();
    uint rgb = QColor(10, 20, 30).rgb();
    qMemCopy(bmp->DataAddress(), &rgb, 3);
    bmp->EndDataAccess();
    TRgb symrgb;
    bmp->GetPixel(symrgb, TPoint(0, 0));
    QVERIFY(symrgb.Red() == 10 && symrgb.Green() == 20 && symrgb.Blue() == 30);
    bmpimg = QVolatileImage(bmp);
    QVERIFY(bmpimg.toImage().pixel(0, 0) == rgb);
    // check if there really was a conversion
    bmp->BeginDataAccess();
    bmpimg.beginDataAccess();
    qMemCopy(&rgb, bmpimg.constBits(), 3);
    uint rgb2 = rgb;
    qMemCopy(&rgb2, bmp->DataAddress(), 3);
    QVERIFY(rgb != rgb2);
    bmpimg.endDataAccess(true);
    bmp->EndDataAccess(true);
    delete bmp;

    bmp = new CFbsBitmap;
    QVERIFY(bmp->Create(TSize(101, 89), EGray2) == KErrNone);
    bmpimg = QVolatileImage(bmp); // inverts pixels, but should do it in place
    QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
    QCOMPARE(bmpimg.format(), QImage::Format_MonoLSB);
    bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied);
    QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress());
    QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied);
    delete bmp;

    // The following two formats must be optimal always.
    bmp = new CFbsBitmap;
    QVERIFY(bmp->Create(TSize(101, 89), EColor16MAP) == KErrNone);
    bmpimg = QVolatileImage(bmp);
    QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied);
    QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
    bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied);
    QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
    delete bmp;
    bmp = new CFbsBitmap;
    QVERIFY(bmp->Create(TSize(101, 89), EColor16MU) == KErrNone);
    bmpimg = QVolatileImage(bmp);
    QCOMPARE(bmpimg.format(), QImage::Format_RGB32);
    QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
    bmpimg.ensureFormat(QImage::Format_RGB32);
    QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress());
    delete bmp;

#else
    QSKIP("CFbsBitmap is only available on Symbian, skipping bitmap test", SkipSingle);
#endif
}
예제 #24
0
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;

    const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
#ifdef QT_OPENGL_ES_2
    const GLenum external_format = internal_format;
#else
    const GLenum external_format = qt_gl_preferredTextureFormat();
#endif
    const GLenum target = GL_TEXTURE_2D;

    GLenum type = GL_UNSIGNED_BYTE;
    // Avoid conversion when pixmap is created from CFbsBitmap of EColor64K.
    if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16)
        type = GL_UNSIGNED_SHORT_5_6_5;

    m_texture.options &= ~QGLContext::MemoryManagedBindOption;

    if (!m_texture.id) {
        m_texture.id = QGLTexturePool::instance()->createTextureForPixmap(
                                                                target,
                                                                0, internal_format,
                                                                w, h,
                                                                external_format,
                                                                type,
                                                                const_cast<QGLPixmapData*>(this));
        if (!m_texture.id) {
            failedToAlloc = true;
            return;
        }
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

        inTexturePool = true;
    } else if (inTexturePool) {
        glBindTexture(target, m_texture.id);
        QGLTexturePool::instance()->useTexture(const_cast<QGLPixmapData*>(this));
    }

    if (!m_source.isNull() && m_texture.id) {
        if (external_format == GL_RGB) {
            m_source.beginDataAccess();
            QImage tx;
            if (type == GL_UNSIGNED_BYTE)
                tx = m_source.imageRef().convertToFormat(QImage::Format_RGB888).mirrored(false, true);
            else if (type == GL_UNSIGNED_SHORT_5_6_5)
                tx = m_source.imageRef().mirrored(false, true);
            m_source.endDataAccess(true);

            glBindTexture(target, m_texture.id);
            if (!tx.isNull())
                glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
                                type, tx.constBits());
            else
                qWarning("QGLPixmapData: Failed to create GL_RGB image of size %dx%d", w, h);
        } else {
            // do byte swizzling ARGB -> RGBA
            m_source.beginDataAccess();
            const QImage tx = ctx->d_func()->convertToGLFormat(m_source.imageRef(), true, external_format);
            m_source.endDataAccess(true);
            glBindTexture(target, m_texture.id);
            if (!tx.isNull())
                glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
                                type, tx.constBits());
            else
                qWarning("QGLPixmapData: Failed to create GL_RGBA image of size %dx%d", w, h);
        }

        if (useFramebufferObjects())
            m_source = QVolatileImage();
    }
}