Changeset 713 for trunk


Ignore:
Timestamp:
Apr 28, 2010, 6:02:42 PM (16 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
     240
    232241    FUNC_ENTRY(DiveAllocImageBuffer),
    233242    FUNC_ENTRY(DiveFreeImageBuffer),
     
    241250
    242251static DIVE_CAPS diveCaps = { 0 };
     252
     253
     254
     255
    243256
    244257////////////////////////////////////////////////////////////////////////////////
    245258
    246259QT_BEGIN_NAMESPACE
     260
     261
     262
     263
     264
     265
     266
     267
     268
     269
     270
     271
     272
     273
    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
    284328    ULONG bufNum;
    285329    bool posDirty;
     
    302346    d->image = 0;
    303347    d->hDive = NULLHANDLE;
     348
    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.Left() };
    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_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:::" << "posDirty"
    392427                 << ptl.x << ptl.y);
    393428    }
     
    426461
    427462#if defined(QDIVE_DEBUG)
    428         DEBUG(() << "QPMDiveWindowSurface::doFlush:" << "vrnDirty");
     463        DEBUG(() << "QPMDiveWindowSurface:::" << "vrnDirty");
    429464        for (size_t i = 0; i < d->setup.ulNumDstRects; ++i)
    430465            DEBUG(() << " " << i << ":" << d->setup.pVisDstRects[i]);
     
    432467    }
    433468
     469
     470
     471
     472
     473
     474
     475
     476
     477
     478
     479
     480
     481
     482
     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
     488
    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
     672
     673
     674
     675
     676
     677
     678
     679
     680
     681
     682
     683
     684
     685
     686
     687
     688
     689
     690
     691
     692
     693
     694
     695
     696
     697
     698
     699
     700
     701
     702
     703
     704
     705
     706
     707
     708
     709
     710
     711
     712
     713
     714
     715
     716
     717
     718
     719
     720
     721
     722
     723
     724
     725
     726
     727
     728
     729
     730
     731
     732
     733
     734
     735
     736
     737
     738
     739
     740
     741
     742
     743
     744
     745
     746
     747
     748
     749
     750
     751
     752
     753
     754
     755
     756
     757
     758
     759
     760
     761
     762
     763
     764
     765
     766
     767
     768
     769
     770
     771
     772
     773
     774
     775
     776
     777
     778
     779
     780
    641781        DEBUG_VAR(diveDllOK);
     782
    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
     823
     824
     825
     826
     827
     828
     829
     830
     831
     832
     833
     834
     835
     836
     837
     838
     839
     840
     841
     842
     843
     844
     845
     846
     847
     848
     849
     850
     851
     852
     853
     854
     855
     856
     857
     858
     859
     860
     861
     862
     863
     864
     865
     866
     867
     868
     869
     870
     871
     872
     873
     874
     875
     876
     877
     878
     879
     880
     881
     882
     883
     884
     885
     886
     887
     888
     889
     890
     891
     892
     893
     894
     895
     896
     897
     898
     899
     900
     901
     902
     903
     904
     905
     906
     907
     908
     909
     910
     911
     912
     913
     914
     915
     916
     917
     918
     919
     920
     921
     922
     923
     924
     925
     926
     927
     928
     929
     930
     931
     932
     933
     934
     935
     936
     937
     938
     939
     940
     941
     942
     943
     944
     945
     946
     947
     948
     949
     950
     951
     952
     953
     954
     955
     956
     957
     958
     959
     960
     961
     962
     963
     964
     965
     966
     967
     968
     969
     970
     971
     972
     973
     974
     975
     976
     977
     978
     979
     980
     981
     982
     983
     984
     985
     986
     987
     988
     989
     990
     991
     992
     993
     994
     995
     996
     997
     998
     999
     1000
     1001
     1002
     1003
     1004
     1005
     1006
     1007
     1008
     1009
     1010
     1011
     1012
     1013
     1014
     1015
     1016
     1017
     1018
     1019
     1020
     1021
     1022
     1023
     1024
     1025
     1026
     1027
     1028
     1029
     1030
     1031
     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.