Changeset 713


Ignore:
Timestamp:
Apr 28, 2010, 6:02:42 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Implemented the direct framebuffer access method in Dive mode (based on the patch by Rudi). It is controlled by the QT_PM_DIVE environment variable (see #101 for details).

Location:
trunk/src/gui/painting
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/painting/qwindowsurface_pm.cpp

    r712 r713  
    193193
    194194static
    195 ULONG (APIENTRY *DiveClose) ( HDIVE hDiveInst );
     195ULONG (APIENTRY *DiveClose) ( HDIVE hDiveInst ) = 0;
     196
     197static
     198ULONG (APIENTRY *DiveAcquireFrameBuffer) ( HDIVE   hDiveInst,
     199                                           PRECTL  prectlDst ) = 0;
     200
     201static
     202ULONG (APIENTRY *DiveDeacquireFrameBuffer) ( HDIVE hDiveInst ) = 0;
    196203
    197204static
     
    230237    FUNC_ENTRY(DiveBlitImage),
    231238    FUNC_ENTRY(DiveClose),
     239    FUNC_ENTRY(DiveAcquireFrameBuffer),
     240    FUNC_ENTRY(DiveDeacquireFrameBuffer),
    232241    FUNC_ENTRY(DiveAllocImageBuffer),
    233242    FUNC_ENTRY(DiveFreeImageBuffer),
     
    241250
    242251static DIVE_CAPS diveCaps = { 0 };
     252static bool diveUseFB = false;
     253static ULONG diveColorMap[3][256] = { { 0 } };
     254static HDIVE diveHandle = NULLHANDLE;
     255static char *diveFrameBuf = NULL;
    243256
    244257////////////////////////////////////////////////////////////////////////////////
    245258
    246259QT_BEGIN_NAMESPACE
     260
     261#ifdef Q_CC_GNU
     262extern inline unsigned bswap32_p(unsigned u)
     263{
     264    __asm__ __volatile__ ("bswap %0\n"
     265                          : "=r" (u)
     266                          : "0" (u));
     267    return u;
     268}
     269#else
     270#define bswap32_p(a) \
     271    ((((ULONG)(a)) >> 24) | (((ULONG)(a)) << 24) | \
     272     (((ULONG)(a) << 8) & 0x00ff0000) | (((ULONG)(a) >> 8) & 0x0000ff00))
     273#endif
    247274
    248275// Returns a directly matching QImage format for the given FOURCC (including
     
    262289// screen FOURCC. Returns 0 (FOURC_SCRN) if there is no suitable conversion,
    263290// otherwise it is guaranteed that the returned value is accepted by
    264 // fourccToFormat().
    265 static FOURCC fourccScreenToBuffer(FOURCC fourcc)
    266 {
     291// fourccToFormat(). If isFB is true, the selection is made for the direct
     292// framebuffer access mode.
     293static FOURCC fourccScreenToBuffer(FOURCC fourcc, bool isFB = false)
     294{
     295    Q_UNUSED(isFB);
     296
    267297    // return it as is if supported by fourccToFormat()
    268298    if (fourccToFormat(fourcc) != QImage::Format_Invalid)
    269299        return fourcc;
    270300
    271     // otherwise, use FOURCC_RGB3 (which in theory should always work; if not,
    272     // we will add exceptions here and return 0 in such cases). Note that
    273     // although working with 32-bit pixels would be faster, we cannot return
    274     // FOURCC_BGR4 here because DiveBlitImage() is known to crahsh when the
    275     // source buffer is BGR4 and the screen is not (at least, it's the case
    276     // with recent SNAP versions)
    277     return FOURCC_RGB3;
    278 }
     301    if (!isFB) {
     302        // otherwise, use FOURCC_RGB3 (which in theory should always work; if not,
     303        // we will add exceptions here and return 0 in such cases). Note that
     304        // although working with 32-bit pixels would be faster, we cannot return
     305        // FOURCC_BGR4 here because DiveBlitImage() is known to crahsh when the
     306        // source buffer is BGR4 and the screen is not (at least, it's the case
     307        // with recent SNAP versions)
     308        return FOURCC_RGB3;
     309    }
     310
     311    // in direct framebuffer access mode, we use BGR4 which should be faster
     312    return FOURCC_BGR4;
     313}
     314
     315class QPMDiveWindowSurfaceFB : public QPMDiveWindowSurface
     316{
     317public:
     318    QPMDiveWindowSurfaceFB(QWidget *widget);
     319    ~QPMDiveWindowSurfaceFB();
     320    void doFlush(const QRect &from, const QPoint &to);
     321};
    279322
    280323struct QPMDiveWindowSurfacePrivate
     
    282325    QImage *image;
    283326    HDIVE hDive;
     327    bool useFB;
    284328    ULONG bufNum;
    285329    bool posDirty;
     
    302346    d->image = 0;
    303347    d->hDive = NULLHANDLE;
     348    d->useFB = false;
    304349    d->bufNum = 0;
    305350    d->posDirty = true;
     
    352397    br.translate(offset);
    353398
    354     wbr.setBottom(widget->height() - wbr.bottom() - 1); // flip y coordinate
    355 
    356399    if (d->vrnDisabled) {
    357400        // defer the flush
    358         QPMDiveWindowSurfacePrivate::FlushArgs args = { br, wbr.bottomLeft() };
     401        QPMDiveWindowSurfacePrivate::FlushArgs args = { br, wbr.topLeft() };
    359402        d->pending.append(args);
    360403        return;
    361404    }
    362405
    363     doFlush(br, wbr.bottomLeft());
    364 }
    365 
    366 void QPMDiveWindowSurface::doFlush(const QRect &from, const QPoint &to)
    367 {
    368     DEBUG(() << "QPMDiveWindowSurface::doFlush:" << window()
    369              << "from" << from << "to" << to);
    370 
    371     // make sure from doesn't exceed the backing storage size (it may happen
    372     // during resize & move due to the different event order)
    373     QRect src = from.intersected(QRect(0, 0, d->image->width(), d->image->height()));
    374     QPoint dst = to + (src.bottomLeft() - from.bottomLeft());
    375 
     406    doFlush(br, wbr.topLeft());
     407}
     408
     409bool QPMDiveWindowSurface::adjustSetup()
     410{
    376411    HWND hwnd = window()->winId();
    377412
     
    384419        d->posDirty = false;
    385420        POINTL ptl = { 0, 0 };
    386         WinMapWindowPoints(window()->winId(), HWND_DESKTOP, &ptl, 1);
     421        WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptl, 1);
    387422        d->setup.lScreenPosX = ptl.x;
    388423        d->setup.lScreenPosY = ptl.y;
    389424        d->setup.ulStructLen = offsetof(SETUP_BLITTER, ulNumDstRects);
    390425
    391         DEBUG(() << "QPMDiveWindowSurface::doFlush:" << "posDirty"
     426        DEBUG(() << "QPMDiveWindowSurface::adjustSetup:" << "posDirty"
    392427                 << ptl.x << ptl.y);
    393428    }
     
    426461
    427462#if defined(QDIVE_DEBUG)
    428         DEBUG(() << "QPMDiveWindowSurface::doFlush:" << "vrnDirty");
     463        DEBUG(() << "QPMDiveWindowSurface::adjustSetup:" << "vrnDirty");
    429464        for (size_t i = 0; i < d->setup.ulNumDstRects; ++i)
    430465            DEBUG(() << " " << i << ":" << d->setup.pVisDstRects[i]);
     
    432467    }
    433468
     469    return setupDirty;
     470}
     471
     472void QPMDiveWindowSurface::doFlush(const QRect &from, const QPoint &to)
     473{
     474    DEBUG(() << "QPMDiveWindowSurface::doFlush:" << window()
     475             << "from" << from << "to" << to);
     476
     477    // make sure from doesn't exceed the backing storage size (it may happen
     478    // during resize & move due to the different event order)
     479    QRect src = from.intersected(QRect(0, 0, d->image->width(), d->image->height()));
     480    QPoint dst = to + (src.topLeft() - from.topLeft());
     481
     482    bool setupDirty = adjustSetup();
     483
    434484    // note that the source image is expected to be top-left oriented
    435485    // by DiveSetupBlitter() so we don't perform y coordinate flip
     486
     487    // flip destination y coordinate
     488    dst.setY(window()->height() - dst.y() - src.height());
    436489
    437490    SETUP_BLITTER setupTmp = d->setup;
     
    522575        d->image = new QImage(width, height, format);
    523576
    524         // associate the image data pointer with the buffer number
    525         DiveFreeImageBuffer(d->hDive, d->bufNum);
    526         d->bufNum = 0;
    527         ULONG rc = DiveAllocImageBuffer(d->hDive, &d->bufNum,
    528                                         d->setup.fccSrcColorFormat,
    529                                         width, height,
    530                                         d->image->bytesPerLine(),
    531                                         (PBYTE)const_cast<const QImage *>(d->image)->bits());
    532         if (rc != DIVE_SUCCESS) {
    533             qWarning("QPMDiveWindowSurface::setGeometry: DiveAllocImageBuffer "
    534                      "returned 0x%08lX", rc);
    535             delete d->image;
    536             delete oldImage;
    537             return;
     577        if (!d->useFB) {
     578            // associate the image data pointer with the buffer number
     579            DiveFreeImageBuffer(d->hDive, d->bufNum);
     580            d->bufNum = 0;
     581            ULONG rc = DiveAllocImageBuffer(d->hDive, &d->bufNum,
     582                                            d->setup.fccSrcColorFormat,
     583                                            width, height,
     584                                            d->image->bytesPerLine(),
     585                                            (PBYTE)const_cast<const QImage *>(d->image)->bits());
     586            if (rc != DIVE_SUCCESS) {
     587                qWarning("QPMDiveWindowSurface::setGeometry: DiveAllocImageBuffer "
     588                         "returned 0x%08lX", rc);
     589                delete d->image;
     590                delete oldImage;
     591                return;
     592            }
    538593        }
    539594
     
    599654    if (!diveDllResolved) {
    600655        diveDllResolved = true;
    601         diveDllOK = true;
    602         for (size_t i = 0; i < sizeof(diveDllFuncs) / sizeof(diveDllFuncs[0]); ++i) {
    603             *diveDllFuncs[i].entry = diveDll.resolve(diveDllFuncs[i].name);
    604             if (!*diveDllFuncs[i].entry) {
    605                 diveDllOK = false;
    606                 break;
    607             }
    608         }
    609 
     656        diveDllOK = qgetenv("QT_PM_NO_DIVE").isEmpty();
    610657        if (diveDllOK) {
    611             diveCaps.ulStructLen = sizeof(diveCaps);
    612             DiveQueryCaps(&diveCaps, DIVE_BUFFER_SCREEN);
    613 
    614             DEBUG_VAR(diveCaps.fScreenDirect);
    615             DEBUG_VAR(diveCaps.fBankSwitched);
    616             DEBUG_VAR(diveCaps.ulDepth);
    617             DEBUG_VAR(diveCaps.ulHorizontalResolution);
    618             DEBUG_VAR(diveCaps.ulVerticalResolution);
    619             DEBUG_VAR(diveCaps.ulScanLineBytes);
    620             DEBUG(() << "diveCaps.fccColorEncoding"
    621                      << ((char*)&diveCaps.fccColorEncoding)[0]
    622                      << ((char*)&diveCaps.fccColorEncoding)[1]
    623                      << ((char*)&diveCaps.fccColorEncoding)[2]
    624                      << ((char*)&diveCaps.fccColorEncoding)[3]);
    625 
    626             FOURCC bestBufFormat = fourccScreenToBuffer(diveCaps.fccColorEncoding);
    627             DEBUG(() << "bestBufFormat"
    628                      << ((char*)&bestBufFormat)[0]
    629                      << ((char*)&bestBufFormat)[1]
    630                      << ((char*)&bestBufFormat)[2]
    631                      << ((char*)&bestBufFormat)[3]);
    632 
    633             if (bestBufFormat == 0) {
    634                 // there is no working pixel format for the buffer for
    635                 // DiveBlitImage() to work correctly with the current screen
    636                 // format, give up
     658            QByteArray diveEnv = qgetenv("QT_PM_DIVE").trimmed().toUpper();
     659            if (diveEnv == "BLIT") {
     660                // use DiveBlitImage()
     661                diveUseFB = false;
     662            } else if (diveEnv == "FB") {
     663                // use direct framebuffer access
     664                diveUseFB = true;
     665            } else {
     666                // disable DIVE by default due to bugs in the Panorama driver
    637667                diveDllOK = false;
    638668            }
    639669        }
    640670
     671        if (diveDllOK) {
     672            // resolve Dive functions
     673            for (size_t i = 0; i < sizeof(diveDllFuncs) / sizeof(diveDllFuncs[0]); ++i) {
     674                *diveDllFuncs[i].entry = diveDll.resolve(diveDllFuncs[i].name);
     675                if (!*diveDllFuncs[i].entry) {
     676                    diveDllOK = false;
     677                    break;
     678                }
     679            }
     680
     681            if (diveDllOK) {
     682                diveCaps.ulStructLen = sizeof(diveCaps);
     683                DiveQueryCaps(&diveCaps, DIVE_BUFFER_SCREEN);
     684
     685                DEBUG_VAR(diveCaps.fScreenDirect);
     686                DEBUG_VAR(diveCaps.fBankSwitched);
     687                DEBUG_VAR(diveCaps.ulDepth);
     688                DEBUG_VAR(diveCaps.ulHorizontalResolution);
     689                DEBUG_VAR(diveCaps.ulVerticalResolution);
     690                DEBUG_VAR(diveCaps.ulScanLineBytes);
     691                DEBUG(() << "diveCaps.fccColorEncoding"
     692                         << ((char*)&diveCaps.fccColorEncoding)[0]
     693                         << ((char*)&diveCaps.fccColorEncoding)[1]
     694                         << ((char*)&diveCaps.fccColorEncoding)[2]
     695                         << ((char*)&diveCaps.fccColorEncoding)[3]);
     696
     697                FOURCC bestBufFormat = fourccScreenToBuffer(diveCaps.fccColorEncoding);
     698                DEBUG(() << "bestBufFormat"
     699                         << ((char*)&bestBufFormat)[0]
     700                         << ((char*)&bestBufFormat)[1]
     701                         << ((char*)&bestBufFormat)[2]
     702                         << ((char*)&bestBufFormat)[3]);
     703
     704                if (diveUseFB) {
     705                    if (!diveCaps.fScreenDirect || diveCaps.fBankSwitched) {
     706                        // direct framebuffer is not supported by the driver
     707                        // (and switching banks is not supported by our code)
     708                        diveUseFB = false;
     709                    } else {
     710                        if (bestBufFormat == diveCaps.fccColorEncoding) {
     711                            // no color conversion is required
     712                        } else if (bestBufFormat == FOURCC_BGR4) {
     713                            // build the color conversion table
     714                            switch (diveCaps.fccColorEncoding) {
     715#if 0
     716                            // FOURCC_R565/FOURCC_R555 should be handled directly
     717                            case FOURCC_R565: {
     718                                for (ULONG u = 0; u < 256; ++u) {
     719                                    diveColorMap[0][u] = (u >> 3) << 0;
     720                                    diveColorMap[1][u] = (u >> 2) << 5;
     721                                    diveColorMap[2][u] = (u >> 3) << 11;
     722                                }
     723                                break;
     724                            }
     725                            case FOURCC_R555: {
     726                                for (ULONG u = 0; u < 256; ++u) {
     727                                    diveColorMap[0][u] = (u >> 3) << 0;
     728                                    diveColorMap[1][u] = (u >> 3) << 5;
     729                                    diveColorMap[2][u] = (u >> 3) << 10;
     730                                }
     731                                break;
     732                            }
     733#endif
     734                            case FOURCC_R664: {
     735                                for (ULONG u = 0; u < 256; ++u) {
     736                                    diveColorMap[0][u] = (u >> 2) << 0;
     737                                    diveColorMap[1][u] = (u >> 2) << 6;
     738                                    diveColorMap[2][u] = (u >> 4) << 12;
     739                                }
     740                                break;
     741                            }
     742#if 0
     743                            // FOURCC_BGR4 should be handled directly
     744                            case FOURCC_BGR4:
     745#endif
     746                            case FOURCC_RGB4:
     747                            case FOURCC_BGR3:
     748                            case FOURCC_RGB3:
     749                                break;
     750                            default:
     751                                // screen pixel format is not supported
     752                                diveUseFB = false;
     753                                break;
     754                            }
     755                        } else {
     756                            Q_ASSERT(false);
     757                            diveUseFB = false;
     758                        }
     759                    }
     760                }
     761
     762                if (!diveUseFB) {
     763                    FOURCC bestBufFormat =
     764                        fourccScreenToBuffer(diveCaps.fccColorEncoding);
     765                    DEBUG(() << "bestBufFormat"
     766                             << ((char*)&bestBufFormat)[0]
     767                             << ((char*)&bestBufFormat)[1]
     768                             << ((char*)&bestBufFormat)[2]
     769                             << ((char*)&bestBufFormat)[3]);
     770
     771                    if (bestBufFormat == 0) {
     772                        // there is no working pixel format for the buffer for
     773                        // DiveBlitImage() to work correctly with the current screen
     774                        // format, give up
     775                        diveDllOK = false;
     776                    }
     777                }
     778            }
     779        }
     780
    641781        DEBUG_VAR(diveDllOK);
     782        DEBUG_VAR(diveUseFB);
    642783    }
    643784
     
    648789        return 0;
    649790
    650     // Attempt to create a new DIVE instance for this widget
    651791    HDIVE hDive = NULLHANDLE;
    652     ULONG rc = DiveOpen(&hDive, FALSE, 0);
     792    ULONG rc = DIVE_SUCCESS;
     793
     794    if (diveUseFB) {
     795        // we use a shared DIVE instance for all widgets
     796        if (diveHandle == NULLHANDLE)
     797            rc = DiveOpen(&diveHandle, FALSE, &diveFrameBuf);
     798        hDive = diveHandle;
     799    } else {
     800        // we need a new DIVE instance to reduce the number of calls to
     801        // DiveSetupBlitter() (as recommended by MMAPG)
     802        rc = DiveOpen(&hDive, FALSE, 0);
     803    }
     804
    653805    if (rc != DIVE_SUCCESS) {
    654806        qWarning("QPMDiveWindowSurface::create: DiveOpen returned 0x%08lX", rc);
     
    656808    }
    657809
    658     QPMDiveWindowSurface *surface = new QPMDiveWindowSurface(widget);
     810    QPMDiveWindowSurface *surface = diveUseFB ?
     811        new QPMDiveWindowSurfaceFB(widget) : new QPMDiveWindowSurface(widget);
     812
    659813    if (surface)
    660814        surface->d->hDive = hDive;
     
    665819}
    666820
     821////////////////////////////////////////////////////////////////////////////////
     822
     823QPMDiveWindowSurfaceFB::QPMDiveWindowSurfaceFB(QWidget* widget)
     824    : QPMDiveWindowSurface(widget)
     825{
     826    d->useFB = true;
     827}
     828
     829QPMDiveWindowSurfaceFB::~QPMDiveWindowSurfaceFB()
     830{
     831    // prevent the shared DIVE handle from closing
     832    d->hDive = NULLHANDLE;
     833}
     834
     835void QPMDiveWindowSurfaceFB::doFlush(const QRect &from, const QPoint &to)
     836{
     837    DEBUG(() << "QPMDiveWindowSurfaceFB::doFlush:" << window()
     838             << "from" << from << "to" << to);
     839
     840    // make sure from doesn't exceed the backing storage size (it may happen
     841    // during resize & move due to the different event order)
     842    QRect src = from.intersected(QRect(0, 0, d->image->width(), d->image->height()));
     843
     844    // convert the "to" coordinate to the delta
     845    QPoint dstDelta = from.topLeft() - to;
     846
     847    bool wasPosDirty = d->posDirty;
     848    bool wasVrnDirty = d->vrnDirty;
     849
     850    adjustSetup();
     851
     852    const int windowHeight = window()->height();
     853
     854    if (wasVrnDirty) {
     855        // flip the y coordinate of all rectangles (both the image and the frame
     856        // buffer are top-left oriented) and also make all points inclusive
     857        for (ULONG i = 0; i < d->setup.ulNumDstRects; ++i) {
     858            RECTL &rcl = d->setup.pVisDstRects[i];
     859            --rcl.xRight;
     860            --rcl.yTop;
     861            rcl.yBottom = windowHeight - rcl.yBottom - 1;
     862            rcl.yTop = windowHeight - rcl.yTop - 1;
     863        }
     864    }
     865    if (wasPosDirty || wasVrnDirty) {
     866        // the same flip for the window position
     867        d->setup.lScreenPosY = diveCaps.ulVerticalResolution -
     868                               d->setup.lScreenPosY - windowHeight;
     869    }
     870
     871    // just assume that the rectangle in DiveAcquireFrameBuffer() is in PM
     872    // coordinates (bottom-left based, top-right exclusive), MMREF doesn't
     873    // mention anything particular...
     874    RECTL rclDst = { src.left(),
     875                     diveCaps.ulVerticalResolution -
     876                     (d->setup.lScreenPosY + src.bottom() + dstDelta.y()) - 1,
     877                     src.right() + 1,
     878                     diveCaps.ulVerticalResolution -
     879                     (d->setup.lScreenPosY + src.top() + dstDelta.y()) };
     880
     881    const int srcBpp = d->image->depth() >> 3;
     882    const int dstBpp = diveCaps.ulDepth >> 3;
     883    Q_ASSERT(srcBpp > 0); // we don't expect color depths < 1 byte here
     884
     885    const int srcBytesPerLine = d->image->bytesPerLine();
     886
     887    if (DiveAcquireFrameBuffer(d->hDive, &rclDst) == DIVE_SUCCESS) {
     888        // take each visible rectangle and blit it
     889        for (ULONG i = 0; i < d->setup.ulNumDstRects; ++i) {
     890            RECTL rcl = d->setup.pVisDstRects[i];
     891
     892            if (rcl.xLeft < src.left())
     893              rcl.xLeft = src.left();
     894            if (rcl.xRight > src.right())
     895              rcl.xRight = src.right();
     896            if (rcl.yTop < src.top())
     897              rcl.yTop = src.top();
     898            if (rcl.yBottom > src.bottom())
     899              rcl.yBottom = src.bottom();
     900
     901            int rows = rcl.yBottom - rcl.yTop + 1;
     902            int cols = rcl.xRight - rcl.xLeft + 1;
     903            int i;
     904
     905            if (cols > 0 && rows > 0) {
     906                const uchar *srcBits =
     907                    d->image->scanLine(rcl.yTop) + rcl.xLeft * srcBpp;
     908                char *dstBits = diveFrameBuf +
     909                    (d->setup.lScreenPosY + rcl.yTop + dstDelta.y()) * diveCaps.ulScanLineBytes +
     910                    (d->setup.lScreenPosX + rcl.xLeft + dstDelta.x()) * dstBpp;
     911
     912                if (d->setup.fccSrcColorFormat == diveCaps.fccColorEncoding) {
     913                    // no color conversion is required
     914                    do {
     915                        memcpy(dstBits, srcBits, srcBpp * cols);
     916                        srcBits += srcBytesPerLine;
     917                        dstBits += diveCaps.ulScanLineBytes;
     918                    } while (--rows);
     919                } else {
     920                    Q_ASSERT(d->setup.fccSrcColorFormat == FOURCC_BGR4);
     921                    Q_ASSERT(d->image->format() == QImage::Format_RGB32);
     922                    Q_ASSERT(srcBpp == 4);
     923                    switch (diveCaps.fccColorEncoding) {
     924
     925#if 0
     926                    // FOURCC_BGR4 is covered by memcpy()
     927                    case FOURCC_BGR4:
     928                        do {
     929                            for (i = 0; i < cols; i++ ) {
     930                                *(PULONG)dstBits = *(PULONG)srcBits;
     931                                srcBits += 4;
     932                                dstBits += 4;
     933                            }
     934                            srcBits += srcBytesPerLine - (cols * 4);
     935                            dstBits += diveCaps.ulScanLineBytes - (cols * 4);
     936                        } while (--rows);
     937                        break;
     938#endif
     939
     940                    case FOURCC_RGB4:
     941                        do {
     942                            for (i = 0; i < cols; i++ ) {
     943                                *(PULONG)dstBits = bswap32_p(*(PULONG)srcBits) >> 8;
     944                                srcBits += 4;
     945                                dstBits += 4;
     946                            }
     947                            srcBits += srcBytesPerLine - (cols * 4);
     948                            dstBits += diveCaps.ulScanLineBytes - (cols * 4);
     949                        } while (--rows);
     950                        break;
     951
     952                    case FOURCC_BGR3:
     953                        do {
     954                            // copy in batches by 4 pixels
     955                            for (i = cols; i >= 4; i -= 4) {
     956                                *(PULONG)&dstBits[0] =
     957                                    (*(PULONG)&srcBits[0] & 0x00ffffff) |
     958                                    (*(PUCHAR)&srcBits[4] << 24);
     959                                *(PULONG)&dstBits[4] =
     960                                    (*(PUSHORT)&srcBits[5]) |
     961                                    (*(PUSHORT)&srcBits[8] << 16);
     962                                *(PULONG)&dstBits[8] =
     963                                    (*(PUCHAR)&srcBits[10]) |
     964                                    (*(PULONG)&srcBits[12] << 8);
     965                                srcBits += 16;
     966                                dstBits += 12;
     967                            }
     968                            // copy the rest
     969                            while (i--) {
     970                                dstBits[0] = srcBits[0];
     971                                dstBits[1] = srcBits[1];
     972                                dstBits[2] = srcBits[2];
     973                                srcBits += 4;
     974                                dstBits += 3;
     975                            }
     976                            srcBits += srcBytesPerLine - (cols * 4);
     977                            dstBits += diveCaps.ulScanLineBytes - (cols * 3);
     978                        } while (--rows);
     979                        break;
     980
     981                    case FOURCC_RGB3:
     982                        do {
     983                            // copy in batches by 4 pixels
     984                            for (i = cols; i >= 4; i -= 4) {
     985                                *(PULONG)&dstBits[0] =
     986                                    (*(PUCHAR)&srcBits[6] << 24) |
     987                                    (bswap32_p(*(PULONG)srcBits) >> 8);
     988                                *(PULONG)&dstBits[4] =
     989                                    bswap32_p(*(PUSHORT)&srcBits[9]) |
     990                                    (bswap32_p(*(PUSHORT)&srcBits[4]) >> 16);
     991                                *(PULONG)&dstBits[8] =
     992                                    (*(PUCHAR)&srcBits[8]) |
     993                                    (bswap32_p(*(PULONG)&srcBits[12]) & 0xffffff00);
     994                                srcBits += 16;
     995                                dstBits += 12;
     996                            }
     997                            // copy the rest
     998                            while (i--) {
     999                                dstBits[2] = srcBits[0];
     1000                                dstBits[1] = srcBits[1];
     1001                                dstBits[0] = srcBits[2];
     1002                                srcBits += 4;
     1003                                dstBits += 3;
     1004                            }
     1005                            srcBits += srcBytesPerLine - (cols * 4);
     1006                            dstBits += diveCaps.ulScanLineBytes - (cols * 3);
     1007                        } while (--rows);
     1008                        break;
     1009
     1010                    default:
     1011                        // assumes that we initialized the diveColorMap table
     1012                        Q_ASSERT(dstBpp == 2);
     1013                        do {
     1014                            PUSHORT temp = (PUSHORT)dstBits;
     1015                            for (i = 0; i < cols; ++i) {
     1016                               *temp++ = (USHORT)
     1017                                    (diveColorMap[0][srcBits[0]] |
     1018                                     diveColorMap[1][srcBits[1]] |
     1019                                     diveColorMap[2][srcBits[2]]);
     1020                               srcBits += 4;
     1021                            }
     1022                            srcBits += srcBytesPerLine - (cols * 4);
     1023                            dstBits += diveCaps.ulScanLineBytes;
     1024                        } while(--rows);
     1025                        break;
     1026                    }
     1027                }
     1028            }
     1029        }
     1030
     1031        DiveDeacquireFrameBuffer(d->hDive);
     1032    }
     1033}
     1034
    6671035QT_END_NAMESPACE
    6681036
  • trunk/src/gui/painting/qwindowsurface_pm_p.h

    r707 r713  
    7171    QPaintDevice *paintDevice();
    7272    void flush(QWidget *widget, const QRegion &rgn, const QPoint &offset);
    73     void doFlush(const QRect &from, const QPoint &to);
    7473    void setGeometry(const QRect &rect);
    7574    bool scroll(const QRegion &area, int dx, int dy);
     
    7776    static QPMDiveWindowSurface *create(QWidget *widget);
    7877
    79 private:
     78protected:
     79    bool adjustSetup();
     80    virtual void doFlush(const QRect &from, const QPoint &to);
    8081    bool pmEventFilter(QMSG *msg, MRESULT *result);
    8182
Note: See TracChangeset for help on using the changeset viewer.