Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/openvg/qpixmapdata_vg.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include "qpaintengine_vg_p.h"
    4444#include <QtGui/private/qdrawhelper_p.h>
     45#if !defined(QT_NO_EGL)
     46#include <QtGui/private/qegl_p.h>
     47#endif
    4548#include "qvg_p.h"
    4649#include "qvgimagepool_p.h"
    47 
    48 #if defined(Q_OS_SYMBIAN)
    49 #include <private/qt_s60_p.h>
    50 #include <fbs.h>
    51 #endif
    52 #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
    53 #include <sgresource/sgimage.h>
    54 typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*);
    55 typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
    56 typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR);
    57 #endif // QT_SYMBIAN_SUPPORTS_SGIMAGE
     50#include <QBuffer>
     51#include <QImageReader>
     52#include <QtGui/private/qimage_p.h>
    5853
    5954QT_BEGIN_NAMESPACE
     
    7166    inImagePool = false;
    7267    inLRU = false;
     68    failedToAlloc = false;
    7369#if !defined(QT_NO_EGL)
    7470    context = 0;
     
    161157        (const QImage &image, Qt::ImageConversionFlags flags)
    162158{
     159    if(image.isNull())
     160        return;
     161
     162    QImage img = image;
     163    createPixmapForImage(img, flags, false);
     164}
     165
     166void QVGPixmapData::fromImageReader(QImageReader *imageReader,
     167                                 Qt::ImageConversionFlags flags)
     168{
     169    QImage image = imageReader->read();
     170    if (image.isNull())
     171        return;
     172
     173    createPixmapForImage(image, flags, true);
     174}
     175
     176bool QVGPixmapData::fromFile(const QString &filename, const char *format,
     177                          Qt::ImageConversionFlags flags)
     178{
     179    QImage image = QImageReader(filename, format).read();
     180    if (image.isNull())
     181        return false;
     182
     183    createPixmapForImage(image, flags, true);
     184
     185    return !isNull();
     186}
     187
     188bool QVGPixmapData::fromData(const uchar *buffer, uint len, const char *format,
     189                      Qt::ImageConversionFlags flags)
     190{
     191    QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
     192    QBuffer b(&a);
     193    b.open(QIODevice::ReadOnly);
     194    QImage image = QImageReader(&b, format).read();
     195    if (image.isNull())
     196        return false;
     197
     198    createPixmapForImage(image, flags, true);
     199
     200    return !isNull();
     201}
     202
     203/*!
     204    out-of-place conversion (inPlace == false) will always detach()
     205 */
     206void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
     207{
    163208    if (image.size() == QSize(w, h))
    164209        setSerialNumber(++qt_vg_pixmap_serial);
    165210    else
    166211        resize(image.width(), image.height());
    167     source = image.convertToFormat(sourceFormat(), flags);
     212
     213    QImage::Format format = sourceFormat();
     214    int d = image.depth();
     215    if (d == 1 || d == 16 || d == 24 || (d == 32 && !image.hasAlphaChannel()))
     216        format = QImage::Format_RGB32;
     217    else if (!(flags & Qt::NoOpaqueDetection) && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
     218        format = sourceFormat();
     219    else
     220        format = image.hasAlphaChannel() ? sourceFormat() : QImage::Format_RGB32;
     221
     222    if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
     223        source = image;
     224    } else {
     225        source = image.convertToFormat(format);
     226
     227        // convertToFormat won't detach the image if format stays the same.
     228        if (image.format() == format)
     229            source.detach();
     230    }
     231
    168232    recreate = true;
    169233}
     
    234298}
    235299
    236 // This function works around QImage::bits() making a deep copy if the
    237 // QImage is not const.  We force it to be const and then get the bits.
    238 // XXX: Should add a QImage::constBits() in the future to replace this.
    239 const uchar *qt_vg_imageBits(const QImage& image)
    240 {
    241     return image.bits();
    242 }
    243 
    244300VGImage QVGPixmapData::toVGImage()
    245301{
    246     if (!isValid())
     302    if (!isValid() || failedToAlloc)
    247303        return VG_INVALID_HANDLE;
    248304
     
    260316    if (vgImage == VG_INVALID_HANDLE) {
    261317        vgImage = QVGImagePool::instance()->createImageForPixmap
    262             (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this);
     318            (qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this);
    263319
    264320        // Bail out if we run out of GPU memory - try again next time.
    265         if (vgImage == VG_INVALID_HANDLE)
     321        if (vgImage == VG_INVALID_HANDLE) {
     322            failedToAlloc = true;
    266323            return VG_INVALID_HANDLE;
     324        }
    267325
    268326        inImagePool = true;
     
    274332        vgImageSubData
    275333            (vgImage,
    276              qt_vg_imageBits(source), source.bytesPerLine(),
    277              VG_sARGB_8888_PRE, 0, 0, w, h);
     334             source.constBits(), source.bytesPerLine(),
     335             qt_vg_image_to_vg_format(source.format()), 0, 0, w, h);
    278336    }
    279337
     
    429487}
    430488
    431 #if defined(Q_OS_SYMBIAN)
    432 
    433 static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap)
    434 {
    435       CFbsBitmap *copy = q_check_ptr(new CFbsBitmap);
    436       if(!copy)
    437         return 0;
    438 
    439       if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) {
    440           delete copy;
    441           copy = 0;
    442 
    443           return 0;
    444       }
    445 
    446       CFbsBitmapDevice* bitmapDevice = 0;
    447       CFbsBitGc *bitmapGc = 0;
    448       QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy));
    449       QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL());
    450       bitmapGc->Activate(bitmapDevice);
    451 
    452       bitmapGc->BitBlt(TPoint(), bitmap);
    453 
    454       delete bitmapGc;
    455       delete bitmapDevice;
    456 
    457       return copy;
    458 }
    459 
    460 void QVGPixmapData::cleanup()
    461 {
    462     is_null = w = h = 0;
    463     recreate = false;
    464     source = QImage();
    465 }
    466 
    467 void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
    468 {
    469     if (type == QPixmapData::SgImage && pixmap) {
    470 #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
    471         RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);
    472 
    473         destroyImages();
    474         prevSize = QSize();
    475 
    476         TInt err = 0;
    477 
    478         RSgDriver driver;
    479         err = driver.Open();
    480         if (err != KErrNone) {
    481             cleanup();
    482             return;
    483         }
    484 
    485         if (sgImage->IsNull()) {
    486             cleanup();
    487             driver.Close();
    488             return;
    489         }
    490 
    491         TSgImageInfo sgImageInfo;
    492         err = sgImage->GetInfo(sgImageInfo);
    493         if (err != KErrNone) {
    494             cleanup();
    495             driver.Close();
    496             return;
    497         }
    498 
    499         pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
    500         pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
    501         pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
    502 
    503         if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
    504             cleanup();
    505             driver.Close();
    506             return;
    507         }
    508 
    509         const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE};
    510         EGLImageKHR eglImage = eglCreateImageKHR(QEglContext::display(),
    511                 EGL_NO_CONTEXT,
    512                 EGL_NATIVE_PIXMAP_KHR,
    513                 (EGLClientBuffer)sgImage,
    514                 (EGLint*)KEglImageAttribs);
    515 
    516         if (eglGetError() != EGL_SUCCESS) {
    517             cleanup();
    518             driver.Close();
    519             return;
    520         }
    521 
    522         vgImage = vgCreateEGLImageTargetKHR(eglImage);
    523         if (vgGetError() != VG_NO_ERROR) {
    524             cleanup();
    525             eglDestroyImageKHR(QEglContext::display(), eglImage);
    526             driver.Close();
    527             return;
    528         }
    529 
    530         w = sgImageInfo.iSizeInPixels.iWidth;
    531         h = sgImageInfo.iSizeInPixels.iHeight;
    532         d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
    533         is_null = (w <= 0 || h <= 0);
    534         source = QImage();
    535         recreate = false;
    536         prevSize = QSize(w, h);
    537         setSerialNumber(++qt_vg_pixmap_serial);
    538         // release stuff
    539         eglDestroyImageKHR(QEglContext::display(), eglImage);
    540         driver.Close();
    541 #endif
    542     } else if (type == QPixmapData::FbsBitmap) {
    543         CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
    544 
    545         bool deleteSourceBitmap = false;
    546 
    547 #ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
    548 
    549         // Rasterize extended bitmaps
    550 
    551         TUid extendedBitmapType = bitmap->ExtendedBitmapType();
    552         if (extendedBitmapType != KNullUid) {
    553             bitmap = createBlitCopy(bitmap);
    554             deleteSourceBitmap = true;
    555         }
    556 #endif
    557 
    558         if (bitmap->IsCompressedInRAM()) {
    559             bitmap = createBlitCopy(bitmap);
    560             deleteSourceBitmap = true;
    561         }
    562 
    563         TDisplayMode displayMode = bitmap->DisplayMode();
    564         QImage::Format format = qt_TDisplayMode2Format(displayMode);
    565 
    566         TSize size = bitmap->SizeInPixels();
    567 
    568         bitmap->BeginDataAccess();
    569         uchar *bytes = (uchar*)bitmap->DataAddress();
    570         QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
    571         img = img.copy();
    572         bitmap->EndDataAccess();
    573 
    574         if(displayMode == EGray2) {
    575             //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
    576             //So invert mono bitmaps so that masks work correctly.
    577             img.invertPixels();
    578         } else if(displayMode == EColor16M) {
    579             img = img.rgbSwapped(); // EColor16M is BGR
    580         }
    581 
    582         fromImage(img, Qt::AutoColor);
    583 
    584         if(deleteSourceBitmap)
    585             delete bitmap;
    586     }
    587 }
    588 
    589 void* QVGPixmapData::toNativeType(NativeType type)
    590 {
    591     if (type == QPixmapData::SgImage) {
    592 #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
    593         toVGImage();
    594 
    595         if (!isValid() || vgImage == VG_INVALID_HANDLE)
    596             return 0;
    597 
    598         TInt err = 0;
    599 
    600         RSgDriver driver;
    601         err = driver.Open();
    602         if (err != KErrNone)
    603             return 0;
    604 
    605         TSgImageInfo sgInfo;
    606         sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE;
    607         sgInfo.iSizeInPixels.SetSize(w, h);
    608         sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
    609 
    610         RSgImage *sgImage = q_check_ptr(new RSgImage());
    611         err = sgImage->Create(sgInfo, NULL, NULL);
    612         if (err != KErrNone) {
    613             driver.Close();
    614             return 0;
    615         }
    616 
    617         pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
    618         pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
    619         pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
    620 
    621         if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
    622             driver.Close();
    623             return 0;
    624         }
    625 
    626         const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE};
    627         EGLImageKHR eglImage = eglCreateImageKHR(QEglContext::display(),
    628                 EGL_NO_CONTEXT,
    629                 EGL_NATIVE_PIXMAP_KHR,
    630                 (EGLClientBuffer)sgImage,
    631                 (EGLint*)KEglImageAttribs);
    632         if (eglGetError() != EGL_SUCCESS) {
    633             sgImage->Close();
    634             driver.Close();
    635             return 0;
    636         }
    637 
    638         VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage);
    639         if (vgGetError() != VG_NO_ERROR) {
    640             eglDestroyImageKHR(QEglContext::display(), eglImage);
    641             sgImage->Close();
    642             driver.Close();
    643             return 0;
    644         }
    645 
    646         vgCopyImage(dstVgImage, 0, 0,
    647                 vgImage, 0, 0,
    648                 w, h, VG_FALSE);
    649 
    650         if (vgGetError() != VG_NO_ERROR) {
    651             sgImage->Close();
    652             sgImage = 0;
    653         }
    654         // release stuff
    655         vgDestroyImage(dstVgImage);
    656         eglDestroyImageKHR(QEglContext::display(), eglImage);
    657         driver.Close();
    658         return reinterpret_cast<void*>(sgImage);
    659 #endif
    660     } else if (type == QPixmapData::FbsBitmap) {
    661         CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap);
    662 
    663         if (bitmap) {
    664             if (bitmap->Create(TSize(source.width(), source.height()),
    665                               EColor16MAP) == KErrNone) {
    666                 const uchar *sptr = qt_vg_imageBits(source);
    667                 bitmap->BeginDataAccess();
    668 
    669                 uchar *dptr = (uchar*)bitmap->DataAddress();
    670                 Mem::Copy(dptr, sptr, source.byteCount());
    671 
    672                 bitmap->EndDataAccess();
    673             } else {
    674                 delete bitmap;
    675                 bitmap = 0;
    676             }
    677         }
    678 
    679         return reinterpret_cast<void*>(bitmap);
    680     }
    681     return 0;
    682 }
    683 #endif //Q_OS_SYMBIAN
    684 
    685489QT_END_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.