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;

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

        pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");

        if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) {
            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,
                (EGLint*)KEglImageAttribs);
        if (eglGetError() != EGL_SUCCESS) {
            sgImage->Close();
            driver.Close();
            return 0;
        }

        VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage);
        if (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 = 0;
        }
        // release stuff
        vgDestroyImage(dstVgImage);
        QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
        driver.Close();
        return reinterpret_cast<void*>(sgImage);
#endif
    } else if (type == QPixmapData::FbsBitmap) {
        CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap);

        if (bitmap) {
            if (bitmap->Create(TSize(source.width(), source.height()),
                              EColor16MAP) == KErrNone) {
                const uchar *sptr = source.constBits();
                bitmap->BeginDataAccess();

                uchar *dptr = (uchar*)bitmap->DataAddress();
                Mem::Copy(dptr, sptr, source.byteCount());

                bitmap->EndDataAccess();
            } else {
                delete bitmap;
                bitmap = 0;
            }
        }

        return reinterpret_cast<void*>(bitmap);
    }
    return 0;
}
Beispiel #2
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
}
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();

        TInt err = 0;

        RSgDriver driver;
        err = driver.Open();
        if (err != KErrNone) {
            cleanup();
            return;
        }

        if (sgImage->IsNull()) {
            cleanup();
            driver.Close();
            return;
        }

        TSgImageInfo sgImageInfo;
        err = sgImage->GetInfo(sgImageInfo);
        if (err != KErrNone) {
            cleanup();
            driver.Close();
            return;
        }

        pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");

        if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) {
            cleanup();
            driver.Close();
            return;
        }

        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,
                (EGLint*)KEglImageAttribs);

        if (eglGetError() != EGL_SUCCESS) {
            cleanup();
            driver.Close();
            return;
        }

        vgImage = vgCreateEGLImageTargetKHR(eglImage);
        if (vgGetError() != VG_NO_ERROR) {
            cleanup();
            QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
            driver.Close();
            return;
        }

        w = sgImageInfo.iSizeInPixels.iWidth;
        h = sgImageInfo.iSizeInPixels.iHeight;
        d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
        is_null = (w <= 0 || h <= 0);
        source = QImage();
        recreate = false;
        prevSize = QSize(w, h);
        setSerialNumber(++qt_vg_pixmap_serial);
        // release stuff
        QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
        driver.Close();
#endif
    } else if (type == QPixmapData::FbsBitmap) {
        CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);

        bool deleteSourceBitmap = false;

#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE

        // Rasterize extended bitmaps

        TUid extendedBitmapType = bitmap->ExtendedBitmapType();
        if (extendedBitmapType != KNullUid) {
            bitmap = createBlitCopy(bitmap);
            deleteSourceBitmap = true;
        }
#endif

        if (bitmap->IsCompressedInRAM()) {
            bitmap = createBlitCopy(bitmap);
            deleteSourceBitmap = true;
        }

        TDisplayMode displayMode = bitmap->DisplayMode();
        QImage::Format format = qt_TDisplayMode2Format(displayMode);

        TSize size = bitmap->SizeInPixels();

        bitmap->BeginDataAccess();
        uchar *bytes = (uchar*)bitmap->DataAddress();
        QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
        img = img.copy();
        bitmap->EndDataAccess();

        if(displayMode == EGray2) {
            //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
            //So invert mono bitmaps so that masks work correctly.
            img.invertPixels();
        } else if(displayMode == EColor16M) {
            img = img.rgbSwapped(); // EColor16M is BGR
        }

        fromImage(img, Qt::AutoColor);

        if(deleteSourceBitmap)
            delete bitmap;
    }
}