VirtualBox

Changeset 6725 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Feb 1, 2008 4:59:45 PM (17 years ago)
Author:
vboxsync
Message:

A quick implementation sketch of a solution to the SetVisibleRegion vs. paintEvent race.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/include/VBoxFrameBuffer.h

    r6679 r6725  
    509509    ulong mPixelFormat;
    510510    CGImageRef mImage;
     511#if 1
    511512    CGRect *mRegionRects;
    512513    ULONG mRegionCount;
    513 };
    514 
    515 #endif
    516 
    517 #endif // __VBoxFrameBuffer_h__
     514#else
     515    typedef struct
     516    {
     517        /** The size of this structure expressed in rcts entries. */
     518        ULONG allocated;
     519        /** The number of entries in the rcts array. */
     520        ULONG used;
     521        /** Variable sized array of the rectangle that makes up the region. */
     522        CGRECT rcts[1];
     523    } RegionRects;
     524    /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
     525     *
     526     * The protocol for updating and using this has to take into account that
     527     * the producer (SetVisibleRegion) and consumer (paintEvent) are running
     528     * on different threads. Therefore the producer will create a new RegionRects
     529     * structure before atomically replace the existing one. While the consumer
     530     * will read the value by atomically replace it by NULL, and then when its
     531     * done try restore it by cmpxchg. If the producer has already put a new
     532     * region there, it will be discarded (see mRegionUnused).
     533     */
     534    RegionRects volatile *mRegion;
     535    /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
     536     * This is operated with atomic cmpxchg and atomic xchg. */
     537    RegionRects volatile *mRegionUnused;
     538#endif
     539};
     540
     541#endif
     542
     543#endif // !__VBoxFrameBuffer_h__
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQuartz2D.cpp

    r6683 r6725  
    4141    mPixelFormat(FramebufferPixelFormat_FOURCC_RGB),
    4242    mImage(NULL),
     43#if 1
    4344    mRegionRects(NULL),
    4445    mRegionCount(0)
     46#else
     47    mRegion (NULL),
     48    mRegionUnused (NULL)
     49#endif
    4550{
    4651    Log (("Quartz2D: Creating\n"));
     
    8388     * ASMAtomic(Cmp)XchgPtr and a struct { cAllocated; cRects; aRects[1]; }
    8489     * *mRegion, *mUnusedRegion; should suffice (and permit you to reuse allocations). */
     90#if 1
    8591    RTMemFree (mRegionRects);
    8692    mRegionCount = 0;
    8793    mRegionRects = static_cast <CGRect*> (RTMemAlloc (sizeof (CGRect) * aCount));
     94#else
     95    RegionRects *rgnRcts = (RegionRects *) ASMAtomicXchgPtr (&mRegionUnused, NULL);
     96    if (rgnRcts && rgnRcts->allocated < aCount)
     97    {
     98        RTMemFree (rgnRcts);
     99        rgnRcts = NULL;
     100    }
     101    if (!rgnRcts)
     102    {
     103        ULONG allocated = RT_ALIGN_32 (aCount + 1, 32);
     104        allocated = RT_MAX (128, allocated);
     105        rgnRcts = (RegionRects *) RTMemAlloc (RT_OFFSETOF (RgionRects, rcts[allocated]));
     106        if (!rgnRcts)
     107            return E_NOMEM;
     108        rgnRcts->allocated = allocated;
     109    }
     110    rgnRcts->used = 0;
     111#endif
    88112
    89113    QRegion reg;
     
    111135            continue;
    112136
     137#if 1
    113138        mRegionRects[mRegionCount].origin.x = rect.x();
    114139        mRegionRects[mRegionCount].origin.y = rect.y();
     
    117142//        printf ("Region rect[%d - %d]: %d %d %d %d\n", mRegionCount, aCount, rect.x(), rect.y(), rect.height(), rect.width());
    118143        ++mRegionCount;
     144#else
     145        CGRect *cgRct = &rgnRcts->rcts[rgnRcts->used];
     146        cgRct->origin.x = rect.x();
     147        cgRct->origin.y = rect.y();
     148        cgRct->size.width = rect.width();
     149        cgRct->size.height = rect.height();
     150//        printf ("Region rect[%d - %d]: %d %d %d %d\n", rgnRcts->used, aCount, rect.x(), rect.y(), rect.height(), rect.width());
     151        rgnRcts->used++;
     152#endif
    119153    }
    120154//    printf ("..................................\n");
     155#if 0
     156    void *pvOld = ASMAtomicXchgPtr(&mRegion, rgnRcts);
     157    if (    pvOld
     158        &&  !ASMAtomicCmpXchgPtr(*mRegionUnused, pvOld, NULL))
     159        RTMemFree(pvOld);
     160#endif
    121161    QApplication::postEvent (mView, new VBoxSetRegionEvent (reg));
    122162
     
    194234        GetPortBounds (GetWindowPort (window), &winRect);
    195235        CGContextClearRect (ctx, CGRectMake (winRect.left, winRect.top, winRect.right - winRect.left, winRect.bottom - winRect.top));
     236#if 1
    196237        if (mRegionRects && mRegionCount > 0)
     238#else
     239        RegionRects *rgnRcts = (RegionRects *) ASMAtomicXchgPtr (&mRegion, NULL);
     240        if (rgnRcts)
     241#endif
    197242        {
    198243            /* Save state for display fliping */
     
    204249             * SetVisibleRegion. */
    205250            CGContextBeginPath (ctx);
     251#if 1
    206252            CGContextAddRects (ctx, mRegionRects, mRegionCount);
     253#else
     254            CGContextAddRects (ctx, rgnRects->rcts, rgnRects->used);
     255            if (    !ASMAtomicCmpXchgPtr (&mRegion, rgnRects, NULL)
     256                &&  !ASMAtomicCmpXchgPtr (&mRegionUnused, rgnRects, NULL))
     257                RTMemFree(rgnRects);
     258#endif
    207259            /* Restore the context state. Note that the
    208260             * current path isn't destroyed. */
     
    326378        mBitmapData = NULL;
    327379    }
     380#if 1
    328381    if (mRegionRects)
    329382    {
     
    332385        mRegionCount = 0;
    333386    }
     387#else
     388    if (mRegion)
     389    {
     390        RTMemFree (mRegion)
     391        mRegion = NULL;
     392    }
     393    if (mRegionUnused)
     394    {
     395        RTMemFree (mRegionUnused)
     396        mRegionUnused = NULL;
     397    }
     398#endif
    334399}
    335400
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette