From 2cfe93e7804edb2817dba26ba9b908efbfa80b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 4 Dec 2006 22:25:17 +0000 Subject: [PATCH] * renamed HWInterface locking to LockParallelAccess() and LockExclusiveAccess() (meaning more or less access to the frame buffer) * extracted the AGGTextRenderer to be a global instance used by each Painter instance (currently, it is thread safe because of the global font lock, so there is some work left in this regard) * gave every ServerWindow it's own DrawingEngine instance, this is work in progress. So far, there doesn't seem to be a regression, but less fighting over the exclusive access to the frame buffer, now each ServerWindow thread can draw in parallel. There is room for improvement, plus I think I'm leaking the DrawingEngine... * changed the locking for the software cursor. ShowSoftwareCursor() can only be called if HideSoftwareCursor(BRect) returned true, or if you called the generic HideSoftwareCursor(), since it needs to keep the cursor lock and unlocks in Show...! * some clean up and renaming in Decorator and friends * moved PatternHandler.h to live along with the .cpp git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19427 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Angle.cpp | 8 +- src/servers/app/DecorManager.cpp | 2 +- src/servers/app/Decorator.cpp | 78 +- src/servers/app/Decorator.h | 22 +- src/servers/app/DefaultDecorator.cpp | 286 +++---- src/servers/app/Desktop.cpp | 4 +- src/servers/app/Jamfile | 1 + src/servers/app/MultiLocker.h | 14 +- src/servers/app/OffscreenWindowLayer.cpp | 4 +- src/servers/app/ServerWindow.cpp | 15 +- src/servers/app/ViewLayer.cpp | 9 +- src/servers/app/WindowLayer.cpp | 50 +- .../app/drawing/AccelerantHWInterface.cpp | 16 +- src/servers/app/drawing/DrawingEngine.cpp | 807 +++++++++--------- src/servers/app/drawing/DrawingEngine.h | 17 +- src/servers/app/drawing/HWInterface.cpp | 215 ++--- src/servers/app/drawing/HWInterface.h | 13 +- src/servers/app/drawing/Painter/Painter.cpp | 17 +- src/servers/app/drawing/Painter/Painter.h | 2 +- .../Painter/font_support/AGGTextRenderer.cpp | 11 + .../Painter/font_support/AGGTextRenderer.h | 10 + .../app/{ => drawing}/PatternHandler.h | 0 src/servers/app/drawing/UpdateQueue.cpp | 4 +- 23 files changed, 819 insertions(+), 786 deletions(-) rename src/servers/app/{ => drawing}/PatternHandler.h (100%) diff --git a/src/servers/app/Angle.cpp b/src/servers/app/Angle.cpp index dc69327dfa..04cb17968a 100644 --- a/src/servers/app/Angle.cpp +++ b/src/servers/app/Angle.cpp @@ -31,10 +31,10 @@ #define ANGLE_PI 3.14159265358979323846 #endif -bool sTablesInitialized = false; -float sSinTable[360]; -float sCosTable[360]; -float sTanTable[360]; +static bool sTablesInitialized = false; +static float sSinTable[360]; +static float sCosTable[360]; +static float sTanTable[360]; /*! \brief Constructor diff --git a/src/servers/app/DecorManager.cpp b/src/servers/app/DecorManager.cpp index dd735689c6..623a9fe8ae 100644 --- a/src/servers/app/DecorManager.cpp +++ b/src/servers/app/DecorManager.cpp @@ -92,7 +92,7 @@ DecorInfo::Instantiate(Desktop* desktop, BRect rect, const char *title, desktop->UnlockSingleWindow(); - decorator->SetDriver(desktop->GetDrawingEngine()); + decorator->SetDrawingEngine(desktop->GetDrawingEngine()); decorator->SetTitle(title); return decorator; diff --git a/src/servers/app/Decorator.cpp b/src/servers/app/Decorator.cpp index 0d16dd8258..d4db393884 100644 --- a/src/servers/app/Decorator.cpp +++ b/src/servers/app/Decorator.cpp @@ -30,19 +30,19 @@ Decorator::Decorator(DesktopSettings& settings, BRect rect, window_look look, uint32 flags) : - _driver(NULL), + fDrawingEngine(NULL), fDrawState(), fLook(look), fFlags(flags), - _zoomrect(), - _closerect(), - _minimizerect(), - _tabrect(), - _frame(rect), - _resizerect(), - _borderrect(), + fZoomRect(), + fCloseRect(), + fMinimizeRect(), + fTabRect(), + fFrame(rect), + fResizeRect(), + fBorderRect(), fClosePressed(false), fZoomPressed(false), @@ -68,12 +68,12 @@ Decorator::~Decorator() \param driver A valid DrawingEngine object */ void -Decorator::SetDriver(DrawingEngine *driver) +Decorator::SetDrawingEngine(DrawingEngine* engine) { - _driver = driver; + fDrawingEngine = engine; // lots of subclasses will depend on the driver for text support, so call // _DoLayout() after we have it - if (_driver) { + if (fDrawingEngine) { _DoLayout(); } } @@ -227,7 +227,7 @@ Decorator::Title() const BRect Decorator::BorderRect() const { - return _borderrect; + return fBorderRect; } @@ -238,7 +238,7 @@ Decorator::BorderRect() const BRect Decorator::TabRect() const { - return _tabrect; + return fTabRect; } /*! @@ -373,14 +373,14 @@ Decorator::MoveBy(float x, float y) void Decorator::MoveBy(BPoint pt) { - _zoomrect.OffsetBy(pt); - _closerect.OffsetBy(pt); - _minimizerect.OffsetBy(pt); - _minimizerect.OffsetBy(pt); - _tabrect.OffsetBy(pt); - _frame.OffsetBy(pt); - _resizerect.OffsetBy(pt); - _borderrect.OffsetBy(pt); + fZoomRect.OffsetBy(pt); + fCloseRect.OffsetBy(pt); + fMinimizeRect.OffsetBy(pt); + fMinimizeRect.OffsetBy(pt); + fTabRect.OffsetBy(pt); + fFrame.OffsetBy(pt); + fResizeRect.OffsetBy(pt); + fBorderRect.OffsetBy(pt); } /*! @@ -389,7 +389,7 @@ Decorator::MoveBy(BPoint pt) \param dy y offset This is a required function for subclasses to implement - the default does nothing. - Note that window resize flags should be followed and _frame should be resized + Note that window resize flags should be followed and fFrame should be resized accordingly. It would also be a wise idea to ensure that the window's rectangles are not inverted. */ @@ -423,62 +423,62 @@ Decorator::GetSettings(BMessage* settings) const void Decorator::Draw(BRect r) { - _DrawFrame(r & _frame); - _DrawTab(r & _tabrect); + _DrawFrame(r & fFrame); + _DrawTab(r & fTabRect); } //! Forces a complete decorator update void Decorator::Draw() { - _DrawFrame(_frame); - _DrawTab(_tabrect); + _DrawFrame(fFrame); + _DrawTab(fTabRect); } //! Draws the close button void Decorator::DrawClose() { - _DrawClose(_closerect); + _DrawClose(fCloseRect); } //! draws the frame void Decorator::DrawFrame() { - _DrawFrame(_frame); + _DrawFrame(fFrame); } //! draws the minimize button void Decorator::DrawMinimize(void) { - _DrawTab(_minimizerect); + _DrawTab(fMinimizeRect); } //! draws the tab, title, and buttons void Decorator::DrawTab() { - _DrawTab(_tabrect); - _DrawZoom(_zoomrect); - _DrawMinimize(_minimizerect); - _DrawTitle(_tabrect); - _DrawClose(_closerect); + _DrawTab(fTabRect); + _DrawZoom(fZoomRect); + _DrawMinimize(fMinimizeRect); + _DrawTitle(fTabRect); + _DrawClose(fCloseRect); } // draws the title void Decorator::DrawTitle() { - _DrawTitle(_tabrect); + _DrawTitle(fTabRect); } //! draws the zoom button void Decorator::DrawZoom(void) { - _DrawZoom(_zoomrect); + _DrawZoom(fZoomRect); } @@ -501,16 +501,16 @@ Decorator::_ClipTitle(float width) { // TODO: eventually, use ServerFont::TruncateString() // when it exists (if it doesn't already) - if (_driver) { + if (fDrawingEngine) { int32 strlength = fTitle.CountChars(); - float pixwidth=_driver->StringWidth(fTitle.String(),strlength,&fDrawState); + float pixwidth=fDrawingEngine->StringWidth(fTitle.String(),strlength,&fDrawState); while (strlength >= 0) { if (pixwidth < width) return strlength; strlength--; - pixwidth=_driver->StringWidth(fTitle.String(), strlength, &fDrawState); + pixwidth=fDrawingEngine->StringWidth(fTitle.String(), strlength, &fDrawState); } } return 0; diff --git a/src/servers/app/Decorator.h b/src/servers/app/Decorator.h index 92481fd366..d33a988ff7 100644 --- a/src/servers/app/Decorator.h +++ b/src/servers/app/Decorator.h @@ -50,7 +50,9 @@ class Decorator { window_look look, uint32 flags); virtual ~Decorator(); - void SetDriver(DrawingEngine *driver); + void SetDrawingEngine(DrawingEngine *driver); + inline DrawingEngine* GetDrawingEngine() const + { return fDrawingEngine; } void SetFont(ServerFont *font); virtual void SetLook(DesktopSettings& settings, @@ -68,7 +70,7 @@ class Decorator { const char* Title() const; - // we need to know its border(frame). WinBorder's _frame rect + // we need to know its border(frame). WinBorder's fFrame rect // must expand to include Decorator borders. Otherwise we can't // draw the border. We also add TabRect because I feel we'll need it BRect BorderRect() const; @@ -138,19 +140,19 @@ class Decorator { virtual void _SetFocus(); - DrawingEngine* _driver; + DrawingEngine* fDrawingEngine; DrawState fDrawState; window_look fLook; uint32 fFlags; - BRect _zoomrect; - BRect _closerect; - BRect _minimizerect; - BRect _tabrect; - BRect _frame; - BRect _resizerect; - BRect _borderrect; + BRect fZoomRect; + BRect fCloseRect; + BRect fMinimizeRect; + BRect fTabRect; + BRect fFrame; + BRect fResizeRect; + BRect fBorderRect; private: bool fClosePressed; diff --git a/src/servers/app/DefaultDecorator.cpp b/src/servers/app/DefaultDecorator.cpp index 165b59c0a1..517243206a 100644 --- a/src/servers/app/DefaultDecorator.cpp +++ b/src/servers/app/DefaultDecorator.cpp @@ -207,12 +207,12 @@ DefaultDecorator::MoveBy(BPoint pt) { STRACE(("DefaultDecorator: Move By (%.1f, %.1f)\n",pt.x,pt.y)); // Move all internal rectangles the appropriate amount - _frame.OffsetBy(pt); - _closerect.OffsetBy(pt); - _tabrect.OffsetBy(pt); - _resizerect.OffsetBy(pt); - _zoomrect.OffsetBy(pt); - _borderrect.OffsetBy(pt); + fFrame.OffsetBy(pt); + fCloseRect.OffsetBy(pt); + fTabRect.OffsetBy(pt); + fResizeRect.OffsetBy(pt); + fZoomRect.OffsetBy(pt); + fBorderRect.OffsetBy(pt); fLeftBorder.OffsetBy(pt); fRightBorder.OffsetBy(pt); @@ -226,15 +226,15 @@ DefaultDecorator::ResizeBy(BPoint pt, BRegion* dirty) { STRACE(("DefaultDecorator: Resize By (%.1f, %.1f)\n", pt.x, pt.y)); // Move all internal rectangles the appropriate amount - _frame.right += pt.x; - _frame.bottom += pt.y; + fFrame.right += pt.x; + fFrame.bottom += pt.y; // handle invalidation of resize rect if (dirty && !(fFlags & B_NOT_RESIZABLE)) { BRect realResizeRect; switch (fLook) { case B_DOCUMENT_WINDOW_LOOK: - realResizeRect = _resizerect; + realResizeRect = fResizeRect; // resize rect at old location dirty->Include(realResizeRect); realResizeRect.OffsetBy(pt); @@ -266,10 +266,10 @@ DefaultDecorator::ResizeBy(BPoint pt, BRegion* dirty) } } - _resizerect.OffsetBy(pt); + fResizeRect.OffsetBy(pt); - _borderrect.right += pt.x; - _borderrect.bottom += pt.y; + fBorderRect.right += pt.x; + fBorderRect.bottom += pt.y; fLeftBorder.bottom += pt.y; fTopBorder.right += pt.x; @@ -307,8 +307,8 @@ DefaultDecorator::ResizeBy(BPoint pt, BRegion* dirty) } // resize tab and layout tab items - if (_tabrect.IsValid()) { - BRect oldTabRect(_tabrect); + if (fTabRect.IsValid()) { + BRect oldTabRect(fTabRect); float tabSize; float maxLocation; @@ -325,30 +325,30 @@ DefaultDecorator::ResizeBy(BPoint pt, BRegion* dirty) float delta = tabOffset - fTabOffset; fTabOffset = (uint32)tabOffset; if (fLook != kLeftTitledWindowLook) - _tabrect.OffsetBy(delta, 0.0); + fTabRect.OffsetBy(delta, 0.0); else - _tabrect.OffsetBy(0.0, delta); + fTabRect.OffsetBy(0.0, delta); if (tabSize < fMinTabSize) tabSize = fMinTabSize; if (tabSize > fMaxTabSize) tabSize = fMaxTabSize; - if (fLook != kLeftTitledWindowLook && tabSize != _tabrect.Width()) { - _tabrect.right = _tabrect.left + tabSize; - } else if (fLook == kLeftTitledWindowLook && tabSize != _tabrect.Height()) { - _tabrect.bottom = _tabrect.top + tabSize; + if (fLook != kLeftTitledWindowLook && tabSize != fTabRect.Width()) { + fTabRect.right = fTabRect.left + tabSize; + } else if (fLook == kLeftTitledWindowLook && tabSize != fTabRect.Height()) { + fTabRect.bottom = fTabRect.top + tabSize; } - if (oldTabRect != _tabrect) { - _LayoutTabItems(_tabrect); + if (oldTabRect != fTabRect) { + _LayoutTabItems(fTabRect); if (dirty) { // NOTE: the tab rect becoming smaller only would // handled be the Desktop anyways, so it is sufficient // to include it into the dirty region in it's // final state - BRect redraw(_tabrect); + BRect redraw(fTabRect); if (delta != 0.0) { redraw = redraw | oldTabRect; if (fLook != kLeftTitledWindowLook) @@ -367,13 +367,13 @@ bool DefaultDecorator::SetTabLocation(float location, BRegion* updateRegion) { STRACE(("DefaultDecorator: Set Tab Location(%.1f)\n", location)); - if (!_tabrect.IsValid()) + if (!fTabRect.IsValid()) return false; if (location < 0) location = 0; - float maxLocation = fRightBorder.right - fLeftBorder.left - _tabrect.Width(); + float maxLocation = fRightBorder.right - fLeftBorder.left - fTabRect.Width(); if (location > maxLocation) location = maxLocation; @@ -382,18 +382,18 @@ DefaultDecorator::SetTabLocation(float location, BRegion* updateRegion) return false; // redraw old rect (1 pix on the border also must be updated) - BRect trect(_tabrect); + BRect trect(fTabRect); trect.bottom++; updateRegion->Include(trect); - _tabrect.OffsetBy(delta, 0); + fTabRect.OffsetBy(delta, 0); fTabOffset = (int32)location; - _LayoutTabItems(_tabrect); + _LayoutTabItems(fTabRect); fTabLocation = maxLocation > 0.0 ? fTabOffset / maxLocation : 0.0; // redraw new rect as well - trect = _tabrect; + trect = fTabRect; trect.bottom++; updateRegion->Include(trect); return true; @@ -414,7 +414,7 @@ DefaultDecorator::SetSettings(const BMessage& settings, BRegion* updateRegion) bool DefaultDecorator::GetSettings(BMessage* settings) const { - if (!_tabrect.IsValid()) + if (!fTabRect.IsValid()) return false; return settings->AddFloat("tab location", (float)fTabOffset) == B_OK; @@ -445,7 +445,7 @@ DefaultDecorator::Draw() // things _DrawFrame(BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom())); - _DrawTab(_tabrect); + _DrawTab(fTabRect); } // GetSizeLimits @@ -453,10 +453,10 @@ void DefaultDecorator::GetSizeLimits(int32* minWidth, int32* minHeight, int32* maxWidth, int32* maxHeight) const { - if (_tabrect.IsValid()) + if (fTabRect.IsValid()) *minWidth = (int32)roundf(max_c(*minWidth, fMinTabSize - 2 * fBorderWidth)); - if (_resizerect.IsValid()) - *minHeight = (int32)roundf(max_c(*minHeight, _resizerect.Height() - fBorderWidth)); + if (fResizeRect.IsValid()) + *minHeight = (int32)roundf(max_c(*minHeight, fResizeRect.Height() - fBorderWidth)); } // GetFootprint @@ -483,12 +483,12 @@ DefaultDecorator::GetFootprint(BRegion *region) if (fLook == B_BORDERED_WINDOW_LOOK) return; - region->Include(_tabrect); + region->Include(fTabRect); if (fLook == B_DOCUMENT_WINDOW_LOOK) { // include the rectangular resize knob on the bottom right - region->Include(BRect(_frame.right - 13.0f, _frame.bottom - 13.0f, - _frame.right, _frame.bottom)); + region->Include(BRect(fFrame.right - 13.0f, fFrame.bottom - 13.0f, + fFrame.right, fFrame.bottom)); } } @@ -511,19 +511,19 @@ DefaultDecorator::Clicked(BPoint pt, int32 buttons, int32 modifiers) // In checking for hit test stuff, we start with the smallest rectangles the user might // be clicking on and gradually work our way out into larger rectangles. - if (!(fFlags & B_NOT_CLOSABLE) && _closerect.Contains(pt)) + if (!(fFlags & B_NOT_CLOSABLE) && fCloseRect.Contains(pt)) return DEC_CLOSE; - if (!(fFlags & B_NOT_ZOOMABLE) && _zoomrect.Contains(pt)) + if (!(fFlags & B_NOT_ZOOMABLE) && fZoomRect.Contains(pt)) return DEC_ZOOM; - if (fLook == B_DOCUMENT_WINDOW_LOOK && _resizerect.Contains(pt)) + if (fLook == B_DOCUMENT_WINDOW_LOOK && fResizeRect.Contains(pt)) return DEC_RESIZE; bool clicked = false; // Clicking in the tab? - if (_tabrect.Contains(pt)) { + if (fTabRect.Contains(pt)) { // tab sliding in any case if either shift key is held down // except sliding up-down by moving mouse left-right would look strange if ((modifiers & B_SHIFT_KEY) && (fLook != kLeftTitledWindowLook)) @@ -610,26 +610,26 @@ DefaultDecorator::_DoLayout() fDrawState.Font().GetHeight(fontHeight); if (fLook != kLeftTitledWindowLook) { - _tabrect.Set(_frame.left - fBorderWidth, - _frame.top - fBorderWidth - ceilf(fontHeight.ascent + fontHeight.descent + 7.0), - ((_frame.right - _frame.left) < 35.0 ? - _frame.left + 35.0 : _frame.right) + fBorderWidth, - _frame.top - fBorderWidth); + fTabRect.Set(fFrame.left - fBorderWidth, + fFrame.top - fBorderWidth - ceilf(fontHeight.ascent + fontHeight.descent + 7.0), + ((fFrame.right - fFrame.left) < 35.0 ? + fFrame.left + 35.0 : fFrame.right) + fBorderWidth, + fFrame.top - fBorderWidth); } else { - _tabrect.Set(_frame.left - fBorderWidth - ceilf(fontHeight.ascent + fontHeight.descent + 5.0), - _frame.top - fBorderWidth, _frame.left - fBorderWidth, - _frame.bottom + fBorderWidth); + fTabRect.Set(fFrame.left - fBorderWidth - ceilf(fontHeight.ascent + fontHeight.descent + 5.0), + fFrame.top - fBorderWidth, fFrame.left - fBorderWidth, + fFrame.bottom + fBorderWidth); } // format tab rect for a floating window - make the rect smaller if (fLook == B_FLOATING_WINDOW_LOOK) { - _tabrect.InsetBy(0, 2); - _tabrect.OffsetBy(0, 2); + fTabRect.InsetBy(0, 2); + fTabRect.OffsetBy(0, 2); } float offset; float size; - _GetButtonSizeAndOffset(_tabrect, &offset, &size); + _GetButtonSizeAndOffset(fTabRect, &offset, &size); // fMinTabSize contains just the room for the buttons fMinTabSize = 4.0 + fTextOffset; @@ -639,13 +639,13 @@ DefaultDecorator::_DoLayout() fMinTabSize += offset + size; // fMaxTabSize contains fMinWidth + the width required for the title - fMaxTabSize = _driver ? ceilf(_driver->StringWidth(Title(), strlen(Title()), + fMaxTabSize = fDrawingEngine ? ceilf(fDrawingEngine->StringWidth(Title(), strlen(Title()), &fDrawState)) : 0.0; if (fMaxTabSize > 0.0) fMaxTabSize += fTextOffset; fMaxTabSize += fMinTabSize; - float tabSize = fLook != kLeftTitledWindowLook ? _frame.Width() : _frame.Height(); + float tabSize = fLook != kLeftTitledWindowLook ? fFrame.Width() : fFrame.Height(); if (tabSize < fMinTabSize) tabSize = fMinTabSize; if (tabSize > fMaxTabSize) @@ -653,33 +653,33 @@ DefaultDecorator::_DoLayout() // layout buttons and truncate text if (fLook != kLeftTitledWindowLook) - _tabrect.right = _tabrect.left + tabSize; + fTabRect.right = fTabRect.left + tabSize; else - _tabrect.bottom = _tabrect.top + tabSize; + fTabRect.bottom = fTabRect.top + tabSize; } else { // no tab fMinTabSize = 0.0; fMaxTabSize = 0.0; - _tabrect.Set(0.0, 0.0, -1.0, -1.0); - _closerect.Set(0.0, 0.0, -1.0, -1.0); - _zoomrect.Set(0.0, 0.0, -1.0, -1.0); + fTabRect.Set(0.0, 0.0, -1.0, -1.0); + fCloseRect.Set(0.0, 0.0, -1.0, -1.0); + fZoomRect.Set(0.0, 0.0, -1.0, -1.0); } // calculate left/top/right/bottom borders if (fBorderWidth > 0) { // NOTE: no overlapping, the left and right border rects // don't include the corners! - fLeftBorder.Set(_frame.left - fBorderWidth, _frame.top, - _frame.left - 1, _frame.bottom); + fLeftBorder.Set(fFrame.left - fBorderWidth, fFrame.top, + fFrame.left - 1, fFrame.bottom); - fRightBorder.Set(_frame.right + 1, _frame.top , - _frame.right + fBorderWidth, _frame.bottom); + fRightBorder.Set(fFrame.right + 1, fFrame.top , + fFrame.right + fBorderWidth, fFrame.bottom); - fTopBorder.Set(_frame.left - fBorderWidth, _frame.top - fBorderWidth, - _frame.right + fBorderWidth, _frame.top - 1); + fTopBorder.Set(fFrame.left - fBorderWidth, fFrame.top - fBorderWidth, + fFrame.right + fBorderWidth, fFrame.top - 1); - fBottomBorder.Set(_frame.left - fBorderWidth, _frame.bottom + 1, - _frame.right + fBorderWidth, _frame.bottom + fBorderWidth); + fBottomBorder.Set(fFrame.left - fBorderWidth, fFrame.bottom + 1, + fFrame.right + fBorderWidth, fFrame.bottom + fBorderWidth); } else { // no border fLeftBorder.Set(0.0, 0.0, -1.0, -1.0); @@ -689,21 +689,21 @@ DefaultDecorator::_DoLayout() } // calculate resize rect - _resizerect.Set(fBottomBorder.right - 18.0, fBottomBorder.bottom - 18.0, + fResizeRect.Set(fBottomBorder.right - 18.0, fBottomBorder.bottom - 18.0, fBottomBorder.right, fBottomBorder.bottom); if (hasTab) { // make sure fTabOffset is within limits and apply it to - // the _tabrect + // the fTabRect if (fTabOffset < 0) fTabOffset = 0; if (fTabLocation != 0.0 - && fTabOffset > (fRightBorder.right - fLeftBorder.left - _tabrect.Width())) - fTabOffset = uint32(fRightBorder.right - fLeftBorder.left - _tabrect.Width()); - _tabrect.OffsetBy(fTabOffset, 0); + && fTabOffset > (fRightBorder.right - fLeftBorder.left - fTabRect.Width())) + fTabOffset = uint32(fRightBorder.right - fLeftBorder.left - fTabRect.Width()); + fTabRect.OffsetBy(fTabOffset, 0); // finally, layout the buttons and text within the tab rect - _LayoutTabItems(_tabrect); + _LayoutTabItems(fTabRect); } } @@ -733,21 +733,21 @@ DefaultDecorator::_DrawFrame(BRect invalid) // top if (invalid.Intersects(fTopBorder)) { for (int8 i = 0; i < 5; i++) { - _driver->StrokeLine(BPoint(r.left + i, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), BPoint(r.right - i, r.top + i), fFrameColors[i]); } - if (_tabrect.IsValid()) { + if (fTabRect.IsValid()) { // grey along the bottom of the tab (overwrites "white" from frame) - _driver->StrokeLine(BPoint(_tabrect.left + 2, _tabrect.bottom + 1), - BPoint(_tabrect.right - 2, _tabrect.bottom + 1), + fDrawingEngine->StrokeLine(BPoint(fTabRect.left + 2, fTabRect.bottom + 1), + BPoint(fTabRect.right - 2, fTabRect.bottom + 1), fFrameColors[2]); } } // left if (invalid.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) { for (int8 i = 0; i < 5; i++) { - _driver->StrokeLine(BPoint(r.left + i, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), BPoint(r.left + i, r.bottom - i), fFrameColors[i]); } @@ -755,7 +755,7 @@ DefaultDecorator::_DrawFrame(BRect invalid) // bottom if (invalid.Intersects(fBottomBorder)) { for (int8 i = 0; i < 5; i++) { - _driver->StrokeLine(BPoint(r.left + i, r.bottom - i), + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i), BPoint(r.right - i, r.bottom - i), fFrameColors[(4 - i) == 4 ? 5 : (4 - i)]); } @@ -763,7 +763,7 @@ DefaultDecorator::_DrawFrame(BRect invalid) // right if (invalid.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) { for (int8 i = 0; i < 5; i++) { - _driver->StrokeLine(BPoint(r.right - i, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i), BPoint(r.right - i, r.bottom - i), fFrameColors[(4 - i) == 4 ? 5 : (4 - i)]); } @@ -777,35 +777,35 @@ DefaultDecorator::_DrawFrame(BRect invalid) // top if (invalid.Intersects(fTopBorder)) { for (int8 i = 0; i < 3; i++) { - _driver->StrokeLine(BPoint(r.left + i, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), BPoint(r.right - i, r.top + i), fFrameColors[i * 2]); } - if (_tabrect.IsValid() && fLook != kLeftTitledWindowLook) { + if (fTabRect.IsValid() && fLook != kLeftTitledWindowLook) { // grey along the bottom of the tab (overwrites "white" from frame) - _driver->StrokeLine(BPoint(_tabrect.left + 2, _tabrect.bottom + 1), - BPoint(_tabrect.right - 2, _tabrect.bottom + 1), + fDrawingEngine->StrokeLine(BPoint(fTabRect.left + 2, fTabRect.bottom + 1), + BPoint(fTabRect.right - 2, fTabRect.bottom + 1), fFrameColors[2]); } } // left if (invalid.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) { for (int8 i = 0; i < 3; i++) { - _driver->StrokeLine(BPoint(r.left + i, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), BPoint(r.left + i, r.bottom - i), fFrameColors[i * 2]); } - if (fLook == kLeftTitledWindowLook && _tabrect.IsValid()) { + if (fLook == kLeftTitledWindowLook && fTabRect.IsValid()) { // grey along the right side of the tab (overwrites "white" from frame) - _driver->StrokeLine(BPoint(_tabrect.right + 1, _tabrect.top + 2), - BPoint(_tabrect.right + 1, _tabrect.bottom - 2), + fDrawingEngine->StrokeLine(BPoint(fTabRect.right + 1, fTabRect.top + 2), + BPoint(fTabRect.right + 1, fTabRect.bottom - 2), fFrameColors[2]); } } // bottom if (invalid.Intersects(fBottomBorder)) { for (int8 i = 0; i < 3; i++) { - _driver->StrokeLine(BPoint(r.left + i, r.bottom - i), + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i), BPoint(r.right - i, r.bottom - i), fFrameColors[(2 - i) == 2 ? 5 : (2 - i) * 2]); } @@ -813,7 +813,7 @@ DefaultDecorator::_DrawFrame(BRect invalid) // right if (invalid.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) { for (int8 i = 0; i < 3; i++) { - _driver->StrokeLine(BPoint(r.right - i, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i), BPoint(r.right - i, r.bottom - i), fFrameColors[(2 - i) == 2 ? 5 : (2 - i) * 2]); } @@ -822,7 +822,7 @@ DefaultDecorator::_DrawFrame(BRect invalid) } case B_BORDERED_WINDOW_LOOK: - _driver->StrokeRect(r, fFrameColors[5]); + fDrawingEngine->StrokeRect(r, fFrameColors[5]); break; default: @@ -832,7 +832,7 @@ DefaultDecorator::_DrawFrame(BRect invalid) // Draw the resize thumb if we're supposed to if (!(fFlags & B_NOT_RESIZABLE)) { - r = _resizerect; + r = fResizeRect; switch (fLook) { case B_DOCUMENT_WINDOW_LOOK: @@ -843,14 +843,14 @@ DefaultDecorator::_DrawFrame(BRect invalid) float x = r.right - 3; float y = r.bottom - 3; - _driver->FillRect(BRect(x - 13, y - 13, x, y), fFrameColors[2]); - _driver->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - 15, y - 2), + fDrawingEngine->FillRect(BRect(x - 13, y - 13, x, y), fFrameColors[2]); + fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - 15, y - 2), fFrameColors[0]); - _driver->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 14, y - 1), + fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 14, y - 1), fFrameColors[1]); - _driver->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - 2, y - 15), + fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - 2, y - 15), fFrameColors[0]); - _driver->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 1, y - 14), + fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 1, y - 14), fFrameColors[1]); if (!IsFocus()) @@ -860,8 +860,8 @@ DefaultDecorator::_DrawFrame(BRect invalid) for (int8 j = 1; j <= i; j++) { BPoint pt1(x - (3 * j) + 1, y - (3 * (5 - i)) + 1); BPoint pt2(x - (3 * j) + 2, y - (3 * (5 - i)) + 2); - _driver->StrokePoint(pt1, fFrameColors[0]); - _driver->StrokePoint(pt2, fFrameColors[1]); + fDrawingEngine->StrokePoint(pt1, fFrameColors[0]); + fDrawingEngine->StrokePoint(pt2, fFrameColors[1]); } } break; @@ -877,10 +877,10 @@ DefaultDecorator::_DrawFrame(BRect invalid) fBottomBorder.bottom - 1))) break; - _driver->StrokeLine(BPoint(fRightBorder.left, fBottomBorder.bottom - 22), + fDrawingEngine->StrokeLine(BPoint(fRightBorder.left, fBottomBorder.bottom - 22), BPoint(fRightBorder.right - 1, fBottomBorder.bottom - 22), fFrameColors[0]); - _driver->StrokeLine(BPoint(fRightBorder.right - 22, fBottomBorder.top), + fDrawingEngine->StrokeLine(BPoint(fRightBorder.right - 22, fBottomBorder.top), BPoint(fRightBorder.right - 22, fBottomBorder.bottom - 1), fFrameColors[0]); break; @@ -901,7 +901,7 @@ DefaultDecorator::_DrawTab(BRect invalid) invalid.left, invalid.top, invalid.right, invalid.bottom)); // If a window has a tab, this will draw it and any buttons which are // in it. - if (!_tabrect.IsValid() || !invalid.Intersects(_tabrect)) + if (!fTabRect.IsValid() || !invalid.Intersects(fTabRect)) return; // TODO: cache these @@ -911,45 +911,45 @@ DefaultDecorator::_DrawTab(BRect invalid) B_DARKEN_2_TINT)); // outer frame - _driver->StrokeLine(_tabrect.LeftTop(), _tabrect.LeftBottom(), fFrameColors[0]); - _driver->StrokeLine(_tabrect.LeftTop(), _tabrect.RightTop(), fFrameColors[0]); + fDrawingEngine->StrokeLine(fTabRect.LeftTop(), fTabRect.LeftBottom(), fFrameColors[0]); + fDrawingEngine->StrokeLine(fTabRect.LeftTop(), fTabRect.RightTop(), fFrameColors[0]); if (fLook != kLeftTitledWindowLook) - _driver->StrokeLine(_tabrect.RightTop(),_tabrect.RightBottom(), fFrameColors[5]); + fDrawingEngine->StrokeLine(fTabRect.RightTop(),fTabRect.RightBottom(), fFrameColors[5]); else - _driver->StrokeLine(_tabrect.LeftBottom(),_tabrect.RightBottom(), fFrameColors[5]); + fDrawingEngine->StrokeLine(fTabRect.LeftBottom(),fTabRect.RightBottom(), fFrameColors[5]); // bevel - _driver->StrokeLine(BPoint(_tabrect.left + 1, _tabrect.top + 1), - BPoint(_tabrect.left + 1, _tabrect.bottom - (fLook == kLeftTitledWindowLook ? 1 : 0)), + fDrawingEngine->StrokeLine(BPoint(fTabRect.left + 1, fTabRect.top + 1), + BPoint(fTabRect.left + 1, fTabRect.bottom - (fLook == kLeftTitledWindowLook ? 1 : 0)), tabColorLight); - _driver->StrokeLine(BPoint(_tabrect.left + 1, _tabrect.top + 1), - BPoint(_tabrect.right - (fLook == kLeftTitledWindowLook ? 0 : 1), _tabrect.top + 1), + fDrawingEngine->StrokeLine(BPoint(fTabRect.left + 1, fTabRect.top + 1), + BPoint(fTabRect.right - (fLook == kLeftTitledWindowLook ? 0 : 1), fTabRect.top + 1), tabColorLight); if (fLook != kLeftTitledWindowLook) { - _driver->StrokeLine(BPoint(_tabrect.right - 1, _tabrect.top + 2), - BPoint(_tabrect.right - 1, _tabrect.bottom), tabColorShadow); + fDrawingEngine->StrokeLine(BPoint(fTabRect.right - 1, fTabRect.top + 2), + BPoint(fTabRect.right - 1, fTabRect.bottom), tabColorShadow); } else { - _driver->StrokeLine(BPoint(_tabrect.left + 2, _tabrect.bottom - 1), - BPoint(_tabrect.right, _tabrect.bottom - 1), tabColorShadow); + fDrawingEngine->StrokeLine(BPoint(fTabRect.left + 2, fTabRect.bottom - 1), + BPoint(fTabRect.right, fTabRect.bottom - 1), tabColorShadow); } // fill if (fLook != kLeftTitledWindowLook) { - _driver->FillRect(BRect(_tabrect.left + 2, _tabrect.top + 2, - _tabrect.right - 2, _tabrect.bottom), fTabColor); + fDrawingEngine->FillRect(BRect(fTabRect.left + 2, fTabRect.top + 2, + fTabRect.right - 2, fTabRect.bottom), fTabColor); } else { - _driver->FillRect(BRect(_tabrect.left + 2, _tabrect.top + 2, - _tabrect.right, _tabrect.bottom - 2), fTabColor); + fDrawingEngine->FillRect(BRect(fTabRect.left + 2, fTabRect.top + 2, + fTabRect.right, fTabRect.bottom - 2), fTabColor); } - _DrawTitle(_tabrect); + _DrawTitle(fTabRect); // Draw the buttons if we're supposed to - if (!(fFlags & B_NOT_CLOSABLE) && invalid.Intersects(_closerect)) - _DrawClose(_closerect); - if (!(fFlags & B_NOT_ZOOMABLE) && invalid.Intersects(_zoomrect)) - _DrawZoom(_zoomrect); + if (!(fFlags & B_NOT_CLOSABLE) && invalid.Intersects(fCloseRect)) + _DrawClose(fCloseRect); + if (!(fFlags & B_NOT_ZOOMABLE) && invalid.Intersects(fZoomRect)) + _DrawZoom(fZoomRect); } // _DrawClose @@ -976,18 +976,18 @@ DefaultDecorator::_DrawTitle(BRect r) BPoint titlePos; if (fLook != kLeftTitledWindowLook) { - titlePos.x = _closerect.IsValid() ? _closerect.right + fTextOffset - : _tabrect.left + fTextOffset; - titlePos.y = floorf(((_tabrect.top + 2.0) + _tabrect.bottom + fontHeight.ascent + titlePos.x = fCloseRect.IsValid() ? fCloseRect.right + fTextOffset + : fTabRect.left + fTextOffset; + titlePos.y = floorf(((fTabRect.top + 2.0) + fTabRect.bottom + fontHeight.ascent + fontHeight.descent) / 2.0 - fontHeight.descent + 0.5); } else { - titlePos.x = floorf(((_tabrect.left + 2.0) + _tabrect.right + fontHeight.ascent + titlePos.x = floorf(((fTabRect.left + 2.0) + fTabRect.right + fontHeight.ascent + fontHeight.descent) / 2.0 - fontHeight.descent + 0.5); - titlePos.y = _zoomrect.IsValid() ? _zoomrect.top - fTextOffset - : _tabrect.bottom - fTextOffset; + titlePos.y = fZoomRect.IsValid() ? fZoomRect.top - fTextOffset + : fTabRect.bottom - fTextOffset; } - _driver->DrawString(fTruncatedTitle.String(), fTruncatedTitleLength, titlePos, &fDrawState); + fDrawingEngine->DrawString(fTruncatedTitle.String(), fTruncatedTitleLength, titlePos, &fDrawState); } // _DrawZoom @@ -1088,17 +1088,17 @@ DefaultDecorator::_DrawBlendedRect(BRect r, bool down) uint8(startColor.green - (i * gstep)), uint8(startColor.blue - (i * bstep))); - _driver->StrokeLine(BPoint(r.left, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.left, r.top + i), BPoint(r.left + i, r.top), temprgbcol); temprgbcol.SetColor(uint8(halfColor.red - (i * rstep)), uint8(halfColor.green - (i * gstep)), uint8(halfColor.blue - (i * bstep))); - _driver->StrokeLine(BPoint(r.left + steps, r.top + i), + fDrawingEngine->StrokeLine(BPoint(r.left + steps, r.top + i), BPoint(r.left + i, r.top + steps), temprgbcol); } - _driver->StrokeRect(r, fFrameColors[3]); + fDrawingEngine->StrokeRect(r, fFrameColors[3]); } // _GetButtonSizeAndOffset @@ -1126,29 +1126,29 @@ DefaultDecorator::_LayoutTabItems(const BRect& tabRect) // calulate close rect based on the tab rectangle if (fLook != kLeftTitledWindowLook) { - _closerect.Set(tabRect.left + offset, tabRect.top + offset, + fCloseRect.Set(tabRect.left + offset, tabRect.top + offset, tabRect.left + offset + size, tabRect.top + offset + size); - _zoomrect.Set(tabRect.right - offset - size, tabRect.top + offset, + fZoomRect.Set(tabRect.right - offset - size, tabRect.top + offset, tabRect.right - offset, tabRect.top + offset + size); // hidden buttons have no width if ((Flags() & B_NOT_CLOSABLE) != 0) - _closerect.right = _closerect.left - offset; + fCloseRect.right = fCloseRect.left - offset; if ((Flags() & B_NOT_ZOOMABLE) != 0) - _zoomrect.left = _zoomrect.right + offset; + fZoomRect.left = fZoomRect.right + offset; } else { - _closerect.Set(tabRect.left + offset, tabRect.top + offset, + fCloseRect.Set(tabRect.left + offset, tabRect.top + offset, tabRect.left + offset + size, tabRect.top + offset + size); - _zoomrect.Set(tabRect.left + offset, tabRect.bottom - offset - size, + fZoomRect.Set(tabRect.left + offset, tabRect.bottom - offset - size, tabRect.left + size + offset, tabRect.bottom - offset); // hidden buttons have no height if ((Flags() & B_NOT_CLOSABLE) != 0) - _closerect.bottom = _closerect.top - offset; + fCloseRect.bottom = fCloseRect.top - offset; if ((Flags() & B_NOT_ZOOMABLE) != 0) - _zoomrect.top = _zoomrect.bottom + offset; + fZoomRect.top = fZoomRect.bottom + offset; } // calculate room for title @@ -1156,9 +1156,9 @@ DefaultDecorator::_LayoutTabItems(const BRect& tabRect) // truncated for no apparent reason - OTOH the title does // also not appear perfectly in the middle if (fLook != kLeftTitledWindowLook) - size = (_zoomrect.left - _closerect.right) - fTextOffset * 2 + 2; + size = (fZoomRect.left - fCloseRect.right) - fTextOffset * 2 + 2; else - size = (_zoomrect.top - _closerect.bottom) - fTextOffset * 2 + 2; + size = (fZoomRect.top - fCloseRect.bottom) - fTextOffset * 2 + 2; fTruncatedTitle = Title(); fDrawState.Font().TruncateString(&fTruncatedTitle, B_TRUNCATE_END, size); diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 2d4dadef42..7a7c874bc2 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -2315,11 +2315,11 @@ Desktop::_SetBackground(BRegion& background) dirtyBackground.IntersectWith(&background); fBackgroundRegion = background; if (dirtyBackground.Frame().IsValid()) { - if (GetDrawingEngine()->Lock()) { + if (GetDrawingEngine()->LockParallelAccess()) { GetDrawingEngine()->FillRegion(dirtyBackground, fWorkspaces[fCurrentWorkspace].Color()); - GetDrawingEngine()->Unlock(); + GetDrawingEngine()->UnlockParallelAccess(); } } } diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index 86a3830b5e..c1c5fd6919 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -10,6 +10,7 @@ UseFreeTypeHeaders ; Server app_server : Angle.cpp AppServer.cpp + BitfieldRegion.cpp BitmapManager.cpp ClientMemoryAllocator.cpp CursorData.cpp diff --git a/src/servers/app/MultiLocker.h b/src/servers/app/MultiLocker.h index 9a55090fbc..58530d7742 100644 --- a/src/servers/app/MultiLocker.h +++ b/src/servers/app/MultiLocker.h @@ -115,19 +115,27 @@ class AutoReadLocker { AutoReadLocker(MultiLocker* lock) : fLock(*lock) { - fLock.ReadLock(); + fLocked = fLock.ReadLock(); } AutoReadLocker(MultiLocker& lock) : fLock(lock) { - fLock.ReadLock(); + fLocked = fLock.ReadLock(); } ~AutoReadLocker() { - fLock.ReadUnlock(); + Unlock(); + } + void Unlock() + { + if (fLocked) { + fLock.ReadUnlock(); + fLocked = false; + } } private: MultiLocker& fLock; + bool fLocked; }; diff --git a/src/servers/app/OffscreenWindowLayer.cpp b/src/servers/app/OffscreenWindowLayer.cpp index 1a1bf146ff..b51bb50da3 100644 --- a/src/servers/app/OffscreenWindowLayer.cpp +++ b/src/servers/app/OffscreenWindowLayer.cpp @@ -39,11 +39,11 @@ OffscreenWindowLayer::OffscreenWindowLayer(ServerBitmap* bitmap, OffscreenWindowLayer::~OffscreenWindowLayer() { - fHWInterface->WriteLock(); + fHWInterface->LockExclusiveAccess(); // Unlike normal Layers, we own the DrawingEngine instance delete GetDrawingEngine(); fHWInterface->Shutdown(); - fHWInterface->WriteUnlock(); + fHWInterface->UnlockExclusiveAccess(); delete fHWInterface; } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 71a1decc3e..b9bd8f8f85 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1966,10 +1966,8 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li return; } - // prevent other ServerWindows from messing with the drawing engine - // as long as each uses the same instance... TODO: remove the locking - // when each has its own - drawingEngine->Lock(); + drawingEngine->LockParallelAccess(); + // TODO: avoid setting the region each time drawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion); switch (code) { @@ -2288,7 +2286,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li break; } - drawingEngine->Unlock(); + drawingEngine->UnlockParallelAccess(); } @@ -2698,7 +2696,8 @@ ServerWindow::MakeWindowLayer(BRect frame, const char* name, { // The non-offscreen ServerWindow uses the DrawingEngine instance from the desktop. return new (nothrow) WindowLayer(frame, name, look, feel, flags, - workspace, this, fDesktop->GetDrawingEngine()); +// workspace, this, fDesktop->GetDrawingEngine()); + workspace, this, new DrawingEngine(fDesktop->HWInterface())); } @@ -2830,7 +2829,7 @@ ServerWindow::_SetCurrentLayer(ViewLayer* layer) #if DELAYED_BACKGROUND_CLEARING if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty() && fWindowLayer->InUpdate()) { DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine(); - if (drawingEngine->Lock()) { + if (drawingEngine->LockParallelAccess()) { fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion); fCurrentDrawingRegionValid = true; @@ -2841,7 +2840,7 @@ ServerWindow::_SetCurrentLayer(ViewLayer* layer) fCurrentLayer->Draw(drawingEngine, &dirty, &content, false); - drawingEngine->Unlock(); + drawingEngine->UnlockParallelAccess(); } } #endif diff --git a/src/servers/app/ViewLayer.cpp b/src/servers/app/ViewLayer.cpp index d82bd6209b..82910c2742 100644 --- a/src/servers/app/ViewLayer.cpp +++ b/src/servers/app/ViewLayer.cpp @@ -1354,8 +1354,13 @@ ViewLayer::AddTokensForLayersInRegion(BPrivate::PortLink& link, if (!fVisible) return; - if (region.Intersects(ScreenClipping(windowContentClipping).Frame())) - link.Attach(fToken); +// if (region.Intersects(ScreenClipping(windowContentClipping).Frame())) + IntRect screenBounds(Bounds()); + ConvertToScreen(&screenBounds); + if (!region.Intersects((clipping_rect)screenBounds)) + return; + + link.Attach(fToken); for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) child->AddTokensForLayersInRegion(link, region, diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index 7b65c54020..d7da0ac2fe 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -796,8 +796,9 @@ WindowLayer::MouseDown(BMessage* message, BPoint where, int32* _viewToken) GetBorderRegion(visibleBorder); visibleBorder->IntersectWith(&VisibleRegion()); - fDrawingEngine->Lock(); - fDrawingEngine->ConstrainClippingRegion(visibleBorder); + DrawingEngine* engine = fDecorator->GetDrawingEngine(); + engine->LockExclusiveAccess(); + engine->ConstrainClippingRegion(visibleBorder); if (fIsZooming) { fDecorator->SetZoom(true); @@ -807,7 +808,7 @@ WindowLayer::MouseDown(BMessage* message, BPoint where, int32* _viewToken) fDecorator->SetMinimize(true); } - fDrawingEngine->Unlock(); + engine->UnlockExclusiveAccess(); fRegionPool.Recycle(visibleBorder); @@ -872,8 +873,9 @@ WindowLayer::MouseUp(BMessage* message, BPoint where, int32* _viewToken) GetBorderRegion(visibleBorder); visibleBorder->IntersectWith(&VisibleRegion()); - fDrawingEngine->Lock(); - fDrawingEngine->ConstrainClippingRegion(visibleBorder); + DrawingEngine* engine = fDecorator->GetDrawingEngine(); + engine->LockExclusiveAccess(); + engine->ConstrainClippingRegion(visibleBorder); if (fIsZooming) { fIsZooming = false; @@ -900,7 +902,7 @@ WindowLayer::MouseUp(BMessage* message, BPoint where, int32* _viewToken) } } - fDrawingEngine->Unlock(); + engine->UnlockExclusiveAccess(); fRegionPool.Recycle(visibleBorder); } @@ -959,8 +961,9 @@ WindowLayer::MouseMoved(BMessage *message, BPoint where, int32* _viewToken, GetBorderRegion(visibleBorder); visibleBorder->IntersectWith(&VisibleRegion()); - fDrawingEngine->Lock(); - fDrawingEngine->ConstrainClippingRegion(visibleBorder); + DrawingEngine* engine = fDecorator->GetDrawingEngine(); + engine->LockExclusiveAccess(); + engine->ConstrainClippingRegion(visibleBorder); if (fIsZooming) { fDecorator->SetZoom(_ActionFor(message) == DEC_ZOOM); @@ -970,7 +973,7 @@ WindowLayer::MouseMoved(BMessage *message, BPoint where, int32* _viewToken, fDecorator->SetMinimize(_ActionFor(message) == DEC_MINIMIZE); } - fDrawingEngine->Unlock(); + engine->UnlockExclusiveAccess(); fRegionPool.Recycle(visibleBorder); } @@ -1737,14 +1740,14 @@ WindowLayer::_TriggerContentRedraw(BRegion& dirtyContentRegion) backgroundClearingRegion = &fPendingUpdateSession.DirtyRegion(); } - if (fDrawingEngine->Lock()) { + if (fDrawingEngine->LockParallelAccess()) { fDrawingEngine->SuspendAutoSync(); fTopLayer->Draw(fDrawingEngine, backgroundClearingRegion, &fContentRegion, true); fDrawingEngine->Sync(); - fDrawingEngine->Unlock(); + fDrawingEngine->UnlockParallelAccess(); } } } @@ -1771,16 +1774,20 @@ WindowLayer::_DrawBorder() // intersect with the dirty region dirtyBorderRegion->IntersectWith(&fDirtyRegion); - if (dirtyBorderRegion->CountRects() > 0 && fDrawingEngine->Lock()) { - fDrawingEngine->ConstrainClippingRegion(dirtyBorderRegion); + DrawingEngine* engine = fDecorator->GetDrawingEngine(); + if (dirtyBorderRegion->CountRects() > 0 && engine->LockExclusiveAccess()) { + engine->ConstrainClippingRegion(dirtyBorderRegion); fDecorator->Draw(dirtyBorderRegion->Frame()); - fDrawingEngine->Unlock(); + engine->UnlockExclusiveAccess(); } fRegionPool.Recycle(dirtyBorderRegion); } +//static rgb_color sPendingColor; +//static rgb_color sCurrentColor; + /*! pre: the clipping is readlocked (this function is only called from _TriggerContentRedraw()), which @@ -1793,7 +1800,7 @@ WindowLayer::_TransferToUpdateSession(BRegion* contentDirtyRegion) if (contentDirtyRegion->CountRects() <= 0) return; -//fDrawingEngine->FillRegion(*contentDirtyRegion, RGBColor(255, 255, 0, 255)); +//fDrawingEngine->FillRegion(*contentDirtyRegion, RGBColor(sPendingColor)); //snooze(10000); // add to pending @@ -1873,6 +1880,15 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link) dirty->IntersectWith(&VisibleContentRegion()); +//sCurrentColor.red = rand() % 255; +//sCurrentColor.green = rand() % 255; +//sCurrentColor.blue = rand() % 255; +//sPendingColor.red = rand() % 255; +//sPendingColor.green = rand() % 255; +//sPendingColor.blue = rand() % 255; +//fDrawingEngine->FillRegion(*dirty, RGBColor(sCurrentColor)); +//snooze(10000); + link.StartMessage(B_OK); // append the current window geometry to the // message, the client will need it @@ -1888,7 +1904,7 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link) link.Attach(B_NULL_TOKEN); link.Flush(); - if (!fCurrentUpdateSession.IsExpose() && fDrawingEngine->Lock()) { + if (!fCurrentUpdateSession.IsExpose() && fDrawingEngine->LockParallelAccess()) { //fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 0, 255)); fDrawingEngine->SuspendAutoSync(); @@ -1896,7 +1912,7 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link) &fContentRegion, true); fDrawingEngine->Sync(); - fDrawingEngine->Unlock(); + fDrawingEngine->UnlockParallelAccess(); } // else the background was cleared already fRegionPool.Recycle(dirty); diff --git a/src/servers/app/drawing/AccelerantHWInterface.cpp b/src/servers/app/drawing/AccelerantHWInterface.cpp index 68a19aaf93..eec1be2251 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.cpp +++ b/src/servers/app/drawing/AccelerantHWInterface.cpp @@ -545,9 +545,9 @@ AccelerantHWInterface::SetMode(const display_mode& mode) void AccelerantHWInterface::GetMode(display_mode *mode) { - if (mode && ReadLock()) { + if (mode && LockParallelAccess()) { *mode = fDisplayMode; - ReadUnlock(); + UnlockParallelAccess(); } } @@ -997,13 +997,13 @@ void AccelerantHWInterface::SetCursor(ServerCursor* cursor) { HWInterface::SetCursor(cursor); -// if (WriteLock()) { +// if (LockExclusiveAccess()) { // TODO: implement setting the hard ware cursor // NOTE: cursor should be always B_RGBA32 // NOTE: The HWInterface implementation should // still be called, since it takes ownership of // the cursor. -// WriteUnlock(); +// UnlockExclusiveAccess(); // } } @@ -1012,9 +1012,9 @@ void AccelerantHWInterface::SetCursorVisible(bool visible) { HWInterface::SetCursorVisible(visible); -// if (WriteLock()) { +// if (LockExclusiveAccess()) { // TODO: update graphics hardware -// WriteUnlock(); +// UnlockExclusiveAccess(); // } } @@ -1023,9 +1023,9 @@ void AccelerantHWInterface::MoveCursorTo(const float& x, const float& y) { HWInterface::MoveCursorTo(x, y); -// if (WriteLock()) { +// if (LockExclusiveAccess()) { // TODO: update graphics hardware -// WriteUnlock(); +// UnlockExclusiveAccess(); // } } diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index e6e17f124d..3734b1e579 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -23,7 +23,10 @@ #include "drawing_support.h" #define CRASH_IF_NOT_LOCKED -//#define CRASH_IF_NOT_LOCKED if (!IsLocked()) debugger("not locked!"); +//#define CRASH_IF_NOT_LOCKED if (!IsParallelAccessLocked()) debugger("not parallel locked!"); + +#define CRASH_IF_NOT_EXCLUSIVE_LOCKED +//#define CRASH_IF_NOT_EXCLUSIVE_LOCKED if (!IsExclusiveAccessLocked()) debugger("not exclusive locked!"); // make_rect_valid static inline void @@ -97,6 +100,38 @@ DrawingEngine::~DrawingEngine() } +// #pragma mark - locking + + +bool +DrawingEngine::LockParallelAccess() +{ + return fGraphicsCard->LockExclusiveAccess(); +} + + +void +DrawingEngine::UnlockParallelAccess() +{ + fGraphicsCard->UnlockExclusiveAccess(); +} + + +bool +DrawingEngine::LockExclusiveAccess() +{ + return fGraphicsCard->LockExclusiveAccess(); +} + + +void +DrawingEngine::UnlockExclusiveAccess() +{ + fGraphicsCard->UnlockExclusiveAccess(); +} + +// #pragma mark - + void DrawingEngine::FrameBufferChanged() { @@ -106,11 +141,13 @@ DrawingEngine::FrameBufferChanged() return; } - if (WriteLock()) { + // NOTE: locking is probably bogus, since we are called + // in the thread that changed the frame buffer... + if (LockExclusiveAccess()) { fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer()); // available HW acceleration might have changed fAvailableHWAccleration = fGraphicsCard->AvailableHWAcceleration(); - WriteUnlock(); + UnlockExclusiveAccess(); } } @@ -212,11 +249,11 @@ DrawingEngine::Sync() // Since A is to the left of C and B is to the top of C, The "node" // for C will point to the nodes of A and B as its "successors". Therefor, // A and B will have an "indegree" of 1 for C pointing to them. C will -// have and "indegree" of 0, because there was no rect to which C +// have an "indegree" of 0, because there was no rect to which C // was to the left or top of. When comparing A and B, neither is left // or top from the other and in the sense that the algorithm cares about. -// NOTE: comparisson of coordinates assumes that rects don't overlap +// NOTE: comparison of coordinates assumes that rects don't overlap // and don't share the actual edge either (as is the case in BRegions). struct node { @@ -263,12 +300,12 @@ struct node { int32 next_pointer; }; -bool +static bool is_left_of(const BRect& a, const BRect& b) { return (a.right < b.left); } -bool +static bool is_above(const BRect& a, const BRect& b) { return (a.bottom < b.top); @@ -279,150 +316,142 @@ void DrawingEngine::CopyRegion(/*const*/ BRegion* region, int32 xOffset, int32 yOffset) { - // NOTE: Write locking because we might use HW acceleration. - // This needs to be investigated, I'm doing this because of - // gut feeling. - if (WriteLock()) { - BRect frame = region->Frame(); - frame = frame | frame.OffsetByCopy(xOffset, yOffset); - fGraphicsCard->HideSoftwareCursor(frame); + CRASH_IF_NOT_EXCLUSIVE_LOCKED - int32 count = region->CountRects(); + BRect frame = region->Frame(); + frame = frame | frame.OffsetByCopy(xOffset, yOffset); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(frame); - // TODO: make this step unnecessary - // (by using different stack impl inside node) - node nodes[count]; - for (int32 i= 0; i < count; i++) { - nodes[i].init(region->RectAt(i), count); - } + int32 count = region->CountRects(); - for (int32 i = 0; i < count; i++) { - BRect a = region->RectAt(i); - for (int32 k = i + 1; k < count; k++) { - BRect b = region->RectAt(k); - int cmp = 0; - // compare horizontally - if (xOffset > 0) { - if (is_left_of(a, b)) { - cmp -= 1; - } else if (is_left_of(b, a)) { - cmp += 1; - } - } else if (xOffset < 0) { - if (is_left_of(a, b)) { - cmp += 1; - } else if (is_left_of(b, a)) { - cmp -= 1; - } - } - // compare vertically - if (yOffset > 0) { - if (is_above(a, b)) { - cmp -= 1; - } else if (is_above(b, a)) { - cmp += 1; - } - } else if (yOffset < 0) { - if (is_above(a, b)) { - cmp += 1; - } else if (is_above(b, a)) { - cmp -= 1; - } - } - // add appropriate node as successor - if (cmp > 0) { - nodes[i].push(&nodes[k]); - nodes[k].in_degree++; - } else if (cmp < 0) { - nodes[k].push(&nodes[i]); - nodes[i].in_degree++; - } - } - } - // put all nodes onto a stack that have an "indegree" count of zero - stack inDegreeZeroNodes; - for (int32 i = 0; i < count; i++) { - if (nodes[i].in_degree == 0) { - inDegreeZeroNodes.push(&nodes[i]); - } - } - // pop the rects from the stack, do the actual copy operation - // and decrease the "indegree" count of the other rects not - // currently on the stack and to which the current rect pointed - // to. If their "indegree" count reaches zero, put them onto the - // stack as well. - - clipping_rect* sortedRectList = NULL; - int32 nextSortedIndex = 0; - - if (fAvailableHWAccleration & HW_ACC_COPY_REGION) - sortedRectList = new clipping_rect[count]; - - while (!inDegreeZeroNodes.empty()) { - node* n = inDegreeZeroNodes.top(); - inDegreeZeroNodes.pop(); - - // do the software implementation or add to sorted - // rect list for using the HW accelerated version - // later - if (sortedRectList) { - sortedRectList[nextSortedIndex].left = (int32)n->rect.left; - sortedRectList[nextSortedIndex].top = (int32)n->rect.top; - sortedRectList[nextSortedIndex].right = (int32)n->rect.right; - sortedRectList[nextSortedIndex].bottom = (int32)n->rect.bottom; - nextSortedIndex++; - } else { - BRect touched = _CopyRect(n->rect, xOffset, yOffset); - fGraphicsCard->Invalidate(touched); - } - - for (int32 k = 0; k < n->next_pointer; k++) { - n->pointers[k]->in_degree--; - if (n->pointers[k]->in_degree == 0) - inDegreeZeroNodes.push(n->pointers[k]); - } - } - - // trigger the HW accelerated version if is was available - if (sortedRectList) - fGraphicsCard->CopyRegion(sortedRectList, count, xOffset, yOffset); - - delete[] sortedRectList; - - fGraphicsCard->ShowSoftwareCursor(); - - WriteUnlock(); + // TODO: make this step unnecessary + // (by using different stack impl inside node) + node nodes[count]; + for (int32 i= 0; i < count; i++) { + nodes[i].init(region->RectAt(i), count); } + + for (int32 i = 0; i < count; i++) { + BRect a = region->RectAt(i); + for (int32 k = i + 1; k < count; k++) { + BRect b = region->RectAt(k); + int cmp = 0; + // compare horizontally + if (xOffset > 0) { + if (is_left_of(a, b)) { + cmp -= 1; + } else if (is_left_of(b, a)) { + cmp += 1; + } + } else if (xOffset < 0) { + if (is_left_of(a, b)) { + cmp += 1; + } else if (is_left_of(b, a)) { + cmp -= 1; + } + } + // compare vertically + if (yOffset > 0) { + if (is_above(a, b)) { + cmp -= 1; + } else if (is_above(b, a)) { + cmp += 1; + } + } else if (yOffset < 0) { + if (is_above(a, b)) { + cmp += 1; + } else if (is_above(b, a)) { + cmp -= 1; + } + } + // add appropriate node as successor + if (cmp > 0) { + nodes[i].push(&nodes[k]); + nodes[k].in_degree++; + } else if (cmp < 0) { + nodes[k].push(&nodes[i]); + nodes[i].in_degree++; + } + } + } + // put all nodes onto a stack that have an "indegree" count of zero + stack inDegreeZeroNodes; + for (int32 i = 0; i < count; i++) { + if (nodes[i].in_degree == 0) { + inDegreeZeroNodes.push(&nodes[i]); + } + } + // pop the rects from the stack, do the actual copy operation + // and decrease the "indegree" count of the other rects not + // currently on the stack and to which the current rect pointed + // to. If their "indegree" count reaches zero, put them onto the + // stack as well. + + clipping_rect* sortedRectList = NULL; + int32 nextSortedIndex = 0; + + if (fAvailableHWAccleration & HW_ACC_COPY_REGION) + sortedRectList = new clipping_rect[count]; + + while (!inDegreeZeroNodes.empty()) { + node* n = inDegreeZeroNodes.top(); + inDegreeZeroNodes.pop(); + + // do the software implementation or add to sorted + // rect list for using the HW accelerated version + // later + if (sortedRectList) { + sortedRectList[nextSortedIndex].left = (int32)n->rect.left; + sortedRectList[nextSortedIndex].top = (int32)n->rect.top; + sortedRectList[nextSortedIndex].right = (int32)n->rect.right; + sortedRectList[nextSortedIndex].bottom = (int32)n->rect.bottom; + nextSortedIndex++; + } else { + BRect touched = _CopyRect(n->rect, xOffset, yOffset); + fGraphicsCard->Invalidate(touched); + } + + for (int32 k = 0; k < n->next_pointer; k++) { + n->pointers[k]->in_degree--; + if (n->pointers[k]->in_degree == 0) + inDegreeZeroNodes.push(n->pointers[k]); + } + } + + // trigger the HW accelerated version if is was available + if (sortedRectList) + fGraphicsCard->CopyRegion(sortedRectList, count, xOffset, yOffset); + + delete[] sortedRectList; + + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } // InvertRect void DrawingEngine::InvertRect(BRect r) { - // NOTE: Write locking because we might use HW acceleration. - // This needs to be investigated, I'm doing this because of - // gut feeling. - if (WriteLock()) { - make_rect_valid(r); - r = fPainter->ClipRect(r); - if (r.IsValid()) { - fGraphicsCard->HideSoftwareCursor(r); + CRASH_IF_NOT_LOCKED - // try hardware optimized version first - if (fAvailableHWAccleration & HW_ACC_INVERT_REGION) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->InvertRegion(region); - } else { - fPainter->InvertRect(r); + make_rect_valid(r); + r = fPainter->ClipRect(r); + if (r.IsValid()) { + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r); - fGraphicsCard->Invalidate(r); - } + // try hardware optimized version first + if (fAvailableHWAccleration & HW_ACC_INVERT_REGION) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->InvertRegion(region); + } else { + fPainter->InvertRect(r); - fGraphicsCard->ShowSoftwareCursor(); + fGraphicsCard->Invalidate(r); } - WriteUnlock(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -436,13 +465,14 @@ DrawingEngine::DrawBitmap(ServerBitmap *bitmap, BRect clipped = fPainter->ClipRect(dest); if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawState(d); fPainter->DrawBitmap(bitmap, source, dest); fGraphicsCard->Invalidate(clipped); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -460,7 +490,7 @@ DrawingEngine::DrawArc(BRect r, const float &angle, extend_by_stroke_width(clipped, d); clipped = fPainter->ClipRect(r); if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawState(d); @@ -475,7 +505,8 @@ DrawingEngine::DrawArc(BRect r, const float &angle, fPainter->StrokeArc(center, xRadius, yRadius, angle, span); fGraphicsCard->Invalidate(clipped); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -516,13 +547,14 @@ DrawingEngine::DrawEllipse(BRect r, const DrawState *d, bool filled) clipped = fPainter->ClipRect(clipped); if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawState(d); fPainter->DrawEllipse(r, filled); fGraphicsCard->Invalidate(clipped); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -539,13 +571,14 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, extend_by_stroke_width(bounds, d); bounds = fPainter->ClipRect(bounds); if (bounds.IsValid()) { - fGraphicsCard->HideSoftwareCursor(bounds); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(bounds); fPainter->SetDrawState(d); fPainter->DrawPolygon(ptlist, numpts, filled, closed); fGraphicsCard->Invalidate(bounds); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -562,27 +595,26 @@ DrawingEngine::StrokePoint(const BPoint& pt, const RGBColor &color) // * this function is only used by Decorators // * it assumes a one pixel wide line void -DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) +DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, + const RGBColor &color) { CRASH_IF_NOT_LOCKED - if (Lock()) { - BRect touched(start, end); - make_rect_valid(touched); - touched = fPainter->ClipRect(touched); - fGraphicsCard->HideSoftwareCursor(touched); + BRect touched(start, end); + make_rect_valid(touched); + touched = fPainter->ClipRect(touched); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched); - if (!fPainter->StraightLine(start, end, color.GetColor32())) { - DrawState context; - context.SetHighColor(color); - context.SetDrawingMode(B_OP_OVER); - StrokeLine(start, end, &context); - } else { - fGraphicsCard->Invalidate(touched); - } - fGraphicsCard->ShowSoftwareCursor(); - Unlock(); + if (!fPainter->StraightLine(start, end, color.GetColor32())) { + DrawState context; + context.SetHighColor(color); + context.SetDrawingMode(B_OP_OVER); + StrokeLine(start, end, &context); + } else { + fGraphicsCard->Invalidate(touched); } + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } // this function is used to draw a one pixel wide rect @@ -591,19 +623,16 @@ DrawingEngine::StrokeRect(BRect r, const RGBColor &color) { CRASH_IF_NOT_LOCKED - if (Lock()) { - make_rect_valid(r); - BRect clipped = fPainter->ClipRect(r); - if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); - - fPainter->StrokeRect(r, color.GetColor32()); - - fGraphicsCard->Invalidate(clipped); - fGraphicsCard->ShowSoftwareCursor(); - } + make_rect_valid(r); + BRect clipped = fPainter->ClipRect(r); + if (clipped.IsValid()) { + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - Unlock(); + fPainter->StrokeRect(r, color.GetColor32()); + + fGraphicsCard->Invalidate(clipped); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -616,30 +645,26 @@ DrawingEngine::FillRect(BRect r, const RGBColor& color) // NOTE: Write locking because we might use HW acceleration. // This needs to be investigated, I'm doing this because of // gut feeling. - if (WriteLock()) { - make_rect_valid(r); - r = fPainter->ClipRect(r); - if (r.IsValid()) { - bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r); - - // try hardware optimized version first - if (fAvailableHWAccleration & HW_ACC_FILL_REGION) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(region, color, - fSuspendSyncLevel == 0 - || cursorTouched); - } else { - fPainter->FillRect(r, color.GetColor32()); - - fGraphicsCard->Invalidate(r); - } + make_rect_valid(r); + r = fPainter->ClipRect(r); + if (r.IsValid()) { + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r); - if (cursorTouched) - fGraphicsCard->ShowSoftwareCursor(); + // try hardware optimized version first + if (fAvailableHWAccleration & HW_ACC_FILL_REGION) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(region, color, + fSuspendSyncLevel == 0 + || cursorTouched); + } else { + fPainter->FillRect(r, color.GetColor32()); + + fGraphicsCard->Invalidate(r); } - WriteUnlock(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -649,38 +674,31 @@ DrawingEngine::FillRegion(BRegion& r, const RGBColor& color) { CRASH_IF_NOT_LOCKED - // NOTE: Write locking because we might use HW acceleration. - // This needs to be investigated, I'm doing this because of - // gut feeling. // NOTE: region expected to be already clipped correctly!! - if (WriteLock()) { - BRect frame = r.Frame(); - bool cursorTouched = fGraphicsCard->HideSoftwareCursor(frame); + BRect frame = r.Frame(); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(frame); - bool doInSoftware = true; - // try hardware optimized version first - if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0 - && frame.Width() * frame.Height() > 100) { - fGraphicsCard->FillRegion(r, color, fSuspendSyncLevel == 0 - || cursorTouched); - doInSoftware = false; - } - - if (doInSoftware) { - - int32 count = r.CountRects(); - for (int32 i = 0; i < count; i++) { - fPainter->FillRectNoClipping(r.RectAt(i), color.GetColor32()); - } - - fGraphicsCard->Invalidate(frame); - } - - if (cursorTouched) - fGraphicsCard->ShowSoftwareCursor(); - - WriteUnlock(); + bool doInSoftware = true; + // try hardware optimized version first + if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0 + && frame.Width() * frame.Height() > 100) { + fGraphicsCard->FillRegion(r, color, fSuspendSyncLevel == 0 + || cursorTouched); + doInSoftware = false; } + + if (doInSoftware) { + + int32 count = r.CountRects(); + for (int32 i = 0; i < count; i++) { + fPainter->FillRectNoClipping(r.RectAt(i), color.GetColor32()); + } + + fGraphicsCard->Invalidate(frame); + } + + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } // #pragma mark - DrawState @@ -697,13 +715,14 @@ DrawingEngine::StrokeRect(BRect r, const DrawState *d) clipped = fPainter->ClipRect(clipped); if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawState(d); fPainter->StrokeRect(r); fGraphicsCard->Invalidate(clipped); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -713,52 +732,45 @@ DrawingEngine::FillRect(BRect r, const DrawState *d) { CRASH_IF_NOT_LOCKED - // NOTE: Write locking because we might use HW acceleration. - // This needs to be investigated, I'm doing this because of - // gut feeling. - if (WriteLock()) { - make_rect_valid(r); - r = fPainter->ClipRect(r); - if (r.IsValid()) { - bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r); + make_rect_valid(r); + r = fPainter->ClipRect(r); + if (r.IsValid()) { + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r); - bool doInSoftware = true; - if ((r.Width() + 1) * (r.Height() + 1) > 100.0) { - // try hardware optimized version first - // if the rect is large enough - if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { - if (d->GetPattern() == B_SOLID_HIGH - && (d->GetDrawingMode() == B_OP_COPY - || d->GetDrawingMode() == B_OP_OVER)) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(region, d->HighColor(), - fSuspendSyncLevel == 0 - || cursorTouched); - doInSoftware = false; - } else if (d->GetPattern() == B_SOLID_LOW - && d->GetDrawingMode() == B_OP_COPY) { - BRegion region(r); - region.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(region, d->LowColor(), - fSuspendSyncLevel == 0 - || cursorTouched); - doInSoftware = false; - } + bool doInSoftware = true; + if ((r.Width() + 1) * (r.Height() + 1) > 100.0) { + // try hardware optimized version first + // if the rect is large enough + if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { + if (d->GetPattern() == B_SOLID_HIGH + && (d->GetDrawingMode() == B_OP_COPY + || d->GetDrawingMode() == B_OP_OVER)) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(region, d->HighColor(), + fSuspendSyncLevel == 0 + || cursorTouched); + doInSoftware = false; + } else if (d->GetPattern() == B_SOLID_LOW + && d->GetDrawingMode() == B_OP_COPY) { + BRegion region(r); + region.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(region, d->LowColor(), + fSuspendSyncLevel == 0 + || cursorTouched); + doInSoftware = false; } } - if (doInSoftware) { - fPainter->SetDrawState(d); - fPainter->FillRect(r); + } + if (doInSoftware) { + fPainter->SetDrawState(d); + fPainter->FillRect(r); - fGraphicsCard->Invalidate(r); - } - - if (cursorTouched) - fGraphicsCard->ShowSoftwareCursor(); + fGraphicsCard->Invalidate(r); } - WriteUnlock(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -768,53 +780,46 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d) { CRASH_IF_NOT_LOCKED - // NOTE: Write locking because we might use HW acceleration. - // This needs to be investigated, I'm doing this because of - // gut feeling. - if (WriteLock()) { - BRect clipped = fPainter->ClipRect(r.Frame()); - if (clipped.IsValid()) { - bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); + BRect clipped = fPainter->ClipRect(r.Frame()); + if (clipped.IsValid()) { + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - bool doInSoftware = true; - // try hardware optimized version first - if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { - if (d->GetPattern() == B_SOLID_HIGH - && (d->GetDrawingMode() == B_OP_COPY - || d->GetDrawingMode() == B_OP_OVER)) { - r.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(r, d->HighColor(), - fSuspendSyncLevel == 0 - || cursorTouched); - doInSoftware = false; - } else if (d->GetPattern() == B_SOLID_LOW - && d->GetDrawingMode() == B_OP_COPY) { - r.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(r, d->LowColor(), - fSuspendSyncLevel == 0 - || cursorTouched); - doInSoftware = false; - } + bool doInSoftware = true; + // try hardware optimized version first + if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { + if (d->GetPattern() == B_SOLID_HIGH + && (d->GetDrawingMode() == B_OP_COPY + || d->GetDrawingMode() == B_OP_OVER)) { + r.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(r, d->HighColor(), + fSuspendSyncLevel == 0 + || cursorTouched); + doInSoftware = false; + } else if (d->GetPattern() == B_SOLID_LOW + && d->GetDrawingMode() == B_OP_COPY) { + r.IntersectWith(fPainter->ClippingRegion()); + fGraphicsCard->FillRegion(r, d->LowColor(), + fSuspendSyncLevel == 0 + || cursorTouched); + doInSoftware = false; } - - if (doInSoftware) { - fPainter->SetDrawState(d); - - BRect touched = fPainter->FillRect(r.RectAt(0)); - - int32 count = r.CountRects(); - for (int32 i = 1; i < count; i++) { - touched = touched | fPainter->FillRect(r.RectAt(i)); - } - - fGraphicsCard->Invalidate(touched); - } - - if (cursorTouched) - fGraphicsCard->ShowSoftwareCursor(); } - WriteUnlock(); + if (doInSoftware) { + fPainter->SetDrawState(d); + + BRect touched = fPainter->FillRect(r.RectAt(0)); + + int32 count = r.CountRects(); + for (int32 i = 1; i < count; i++) { + touched = touched | fPainter->FillRect(r.RectAt(i)); + } + + fGraphicsCard->Invalidate(touched); + } + + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -836,14 +841,15 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, clipped.bottom = ceilf(clipped.bottom); if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawState(d); BRect touched = filled ? fPainter->FillRoundRect(r, xrad, yrad) : fPainter->StrokeRoundRect(r, xrad, yrad); fGraphicsCard->Invalidate(touched); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -880,7 +886,7 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, extend_by_stroke_width(clipped, d); clipped = fPainter->ClipRect(clipped); if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawState(d); if (filled) @@ -889,7 +895,8 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, fPainter->StrokeTriangle(pts[0], pts[1], pts[2]); fGraphicsCard->Invalidate(clipped); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -904,13 +911,14 @@ DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, DrawState* con extend_by_stroke_width(touched, context); touched = fPainter->ClipRect(touched); if (touched.IsValid()) { - fGraphicsCard->HideSoftwareCursor(touched); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched); fPainter->SetDrawState(context); fPainter->StrokeLine(start, end); fGraphicsCard->Invalidate(touched); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -942,7 +950,7 @@ DrawingEngine::StrokeLineArray(int32 numLines, extend_by_stroke_width(touched, d); touched = fPainter->ClipRect(touched); if (touched.IsValid()) { - fGraphicsCard->HideSoftwareCursor(touched); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched); data = (const LineArrayData *)&(linedata[0]); @@ -964,7 +972,8 @@ DrawingEngine::StrokeLineArray(int32 numLines, } fGraphicsCard->Invalidate(touched); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } } @@ -996,14 +1005,15 @@ DrawingEngine::DrawString(const char* string, int32 length, b = fPainter->ClipRect(b); if (b.IsValid()) { //printf("bounding box '%s': %lld µs\n", string, system_time() - now); - fGraphicsCard->HideSoftwareCursor(b); + bool cursorTouched = fGraphicsCard->HideSoftwareCursor(b); //now = system_time(); BRect touched = fPainter->DrawString(string, length, pt, delta); //printf("drawing string: %lld µs\n", system_time() - now); fGraphicsCard->Invalidate(touched); - fGraphicsCard->ShowSoftwareCursor(); + if (cursorTouched) + fGraphicsCard->ShowSoftwareCursor(); } return penLocation; @@ -1018,16 +1028,13 @@ DrawingEngine::StringWidth(const char* string, int32 length, FontLocker locker(d); float width = 0.0; -// if (Lock()) { // NOTE: For now it is enough to block on the // font style lock, this already prevents multiple // threads from executing this code and avoids a // deadlock in case another thread holds the font // lock already and then tries to lock the drawing // engine after it is already locked here (race condition) - width = fPainter->StringWidth(string, length, d); -// Unlock(); -// } + width = fPainter->StringWidth(string, length, d); return width; } @@ -1049,77 +1056,37 @@ DrawingEngine::StringHeight(const char *string, int32 length, FontLocker locker(d); float height = 0.0; -// if (Lock()) { // NOTE: For now it is enough to block on the // font style lock, this already prevents multiple // threads from executing this code and avoids a // deadlock in case another thread holds the font // lock already and then tries to lock the drawing // engine after it is already locked here (race condition) - fPainter->SetDrawState(d, true); - BPoint dummy1(0.0, 0.0); - BPoint dummy2(0.0, 0.0); - height = fPainter->BoundingBox(string, length, dummy1, &dummy2).Height(); -// Unlock(); -// } + fPainter->SetDrawState(d, true); + BPoint dummy1(0.0, 0.0); + BPoint dummy2(0.0, 0.0); + height = fPainter->BoundingBox(string, length, dummy1, &dummy2).Height(); return height; } // #pragma mark - -// Lock -bool -DrawingEngine::Lock() -{ - return fGraphicsCard->WriteLock(); -} - -// Unlock -void -DrawingEngine::Unlock() -{ - fGraphicsCard->WriteUnlock(); -} - -// IsLocked -bool -DrawingEngine::IsLocked() -{ - return fGraphicsCard->IsWriteLocked(); -} - -// WriteLock -bool -DrawingEngine::WriteLock() -{ - return fGraphicsCard->WriteLock(); -} - -// WriteUnlock -void -DrawingEngine::WriteUnlock() -{ - fGraphicsCard->WriteUnlock(); -} - -// #pragma mark - - // DumpToFile bool DrawingEngine::DumpToFile(const char *path) { - if (Lock()) { - RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer(); - if (buffer) { - BRect bounds(0.0, 0.0, buffer->Width() - 1, buffer->Height() - 1); - SaveToPNG(path, bounds, buffer->ColorSpace(), - buffer->Bits(), - buffer->BitsLength(), - buffer->BytesPerRow()); - } - Unlock(); - } - return true; + CRASH_IF_NOT_EXCLUSIVE_LOCKED + + RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer(); + if (buffer) { + BRect bounds(0.0, 0.0, buffer->Width() - 1, buffer->Height() - 1); + SaveToPNG(path, bounds, buffer->ColorSpace(), + buffer->Bits(), + buffer->BitsLength(), + buffer->BytesPerRow()); + return true; + } + return false; } // DumpToBitmap @@ -1132,61 +1099,59 @@ DrawingEngine::DumpToBitmap() status_t DrawingEngine::ReadBitmap(ServerBitmap *bitmap, bool drawCursor, BRect bounds) { - if (Lock()) { - RenderingBuffer *buffer = fGraphicsCard->DrawingBuffer(); - if (!buffer) - return B_ERROR; + CRASH_IF_NOT_EXCLUSIVE_LOCKED - BRect clip(0, 0, buffer->Width() - 1, buffer->Height() - 1); - bounds = bounds & clip; - fGraphicsCard->HideSoftwareCursor(bounds); + RenderingBuffer *buffer = fGraphicsCard->DrawingBuffer(); + if (!buffer) + return B_ERROR; - status_t result = bitmap->ImportBits(buffer->Bits(), buffer->BitsLength(), - buffer->BytesPerRow(), buffer->ColorSpace(), - bounds.LeftTop(), BPoint(0, 0), - bounds.IntegerWidth() + 1, bounds.IntegerHeight() + 1); + BRect clip(0, 0, buffer->Width() - 1, buffer->Height() - 1); + bounds = bounds & clip; + fGraphicsCard->HideSoftwareCursor(bounds); - if (drawCursor) { - ServerCursor *cursor = fGraphicsCard->Cursor(); - int32 cursorWidth = cursor->Width(); - int32 cursorHeight = cursor->Height(); + status_t result = bitmap->ImportBits(buffer->Bits(), buffer->BitsLength(), + buffer->BytesPerRow(), buffer->ColorSpace(), + bounds.LeftTop(), BPoint(0, 0), + bounds.IntegerWidth() + 1, bounds.IntegerHeight() + 1); - BPoint cursorPosition = fGraphicsCard->CursorPosition(); - cursorPosition -= bounds.LeftTop() + cursor->GetHotSpot(); + if (drawCursor) { + ServerCursor *cursor = fGraphicsCard->Cursor(); + int32 cursorWidth = cursor->Width(); + int32 cursorHeight = cursor->Height(); - BBitmap cursorArea(BRect(0, 0, cursorWidth - 1, cursorHeight - 1), - B_BITMAP_NO_SERVER_LINK, B_RGBA32); - - cursorArea.ImportBits(bitmap->Bits(), bitmap->BitsLength(), - bitmap->BytesPerRow(), bitmap->ColorSpace(), - cursorPosition, BPoint(0, 0), - cursorWidth, cursorHeight); + BPoint cursorPosition = fGraphicsCard->CursorPosition(); + cursorPosition -= bounds.LeftTop() + cursor->GetHotSpot(); - uint8 *bits = (uint8 *)cursorArea.Bits(); - uint8 *cursorBits = (uint8 *)cursor->Bits(); - for (int32 i = 0; i < cursorHeight; i++) { - for (int32 j = 0; j < cursorWidth; j++) { - uint8 alpha = 255 - cursorBits[3]; - bits[0] = ((bits[0] * alpha) >> 8) + cursorBits[0]; - bits[1] = ((bits[1] * alpha) >> 8) + cursorBits[1]; - bits[2] = ((bits[2] * alpha) >> 8) + cursorBits[2]; - cursorBits += 4; - bits += 4; - } + BBitmap cursorArea(BRect(0, 0, cursorWidth - 1, cursorHeight - 1), + B_BITMAP_NO_SERVER_LINK, B_RGBA32); + + cursorArea.ImportBits(bitmap->Bits(), bitmap->BitsLength(), + bitmap->BytesPerRow(), bitmap->ColorSpace(), + cursorPosition, BPoint(0, 0), + cursorWidth, cursorHeight); + + uint8 *bits = (uint8 *)cursorArea.Bits(); + uint8 *cursorBits = (uint8 *)cursor->Bits(); + for (int32 i = 0; i < cursorHeight; i++) { + for (int32 j = 0; j < cursorWidth; j++) { + uint8 alpha = 255 - cursorBits[3]; + bits[0] = ((bits[0] * alpha) >> 8) + cursorBits[0]; + bits[1] = ((bits[1] * alpha) >> 8) + cursorBits[1]; + bits[2] = ((bits[2] * alpha) >> 8) + cursorBits[2]; + cursorBits += 4; + bits += 4; } - - bitmap->ImportBits(cursorArea.Bits(), cursorArea.BitsLength(), - cursorArea.BytesPerRow(), cursorArea.ColorSpace(), - BPoint(0, 0), cursorPosition, - cursorWidth, cursorHeight); } - fGraphicsCard->ShowSoftwareCursor(); - Unlock(); - return result; + bitmap->ImportBits(cursorArea.Bits(), cursorArea.BitsLength(), + cursorArea.BytesPerRow(), cursorArea.ColorSpace(), + BPoint(0, 0), cursorPosition, + cursorWidth, cursorHeight); } - return B_ERROR; + fGraphicsCard->ShowSoftwareCursor(); + + return result; } // #pragma mark - diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index ec5e7cf779..cbfe14a48a 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -44,17 +44,18 @@ public: // HWInterfaceListener interface virtual void FrameBufferChanged(); - // locking - bool Lock(); - void Unlock(); - bool IsLocked(); - - bool WriteLock(); - void WriteUnlock(); - // for "changing" hardware void SetHWInterface(HWInterface* interface); + // locking + bool LockParallelAccess(); + bool IsParallelAccessLocked(); + void UnlockParallelAccess(); + + bool LockExclusiveAccess(); + bool IsExclusiveAccessLocked(); + void UnlockExclusiveAccess(); + // for screen shots bool DumpToFile(const char *path); ServerBitmap* DumpToBitmap(); diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 18b10dccf7..4f0d73fb44 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -30,6 +30,7 @@ HWInterfaceListener::~HWInterfaceListener() {} HWInterface::HWInterface(bool doubleBuffered) : MultiLocker("hw interface lock"), fCursorAreaBackup(NULL), + fSoftwareCursorLock("software cursor lock"), fCursor(NULL), fDragBitmap(NULL), fDragBitmapOffset(0, 0), @@ -78,74 +79,78 @@ HWInterface::GetDriverPath(BString &path) } -// SetCursor +// #pragma mark - + + void HWInterface::SetCursor(ServerCursor* cursor) { - if (WriteLock()) { - // TODO: if a bitmap is being dragged, it could - // be considered iritating to the user to change - // cursor shapes while something is dragged. - // The disabled code below would do this (except - // for the minor annoyance that the cursor is not - // updated when the drag is over) -// if (fDragBitmap) { -// // TODO: like a "+" or "-" sign when dragging some files to indicate -// // the current drag mode? -// WriteUnlock(); -// return; -// } - if (fCursor != cursor) { - BRect oldFrame = _CursorFrame(); + if (!fSoftwareCursorLock.Lock()) + return; - if (fCursorAndDragBitmap == fCursor) { - // make sure _AdoptDragBitmap doesn't delete a real cursor - fCursorAndDragBitmap = NULL; - } + // TODO: if a bitmap is being dragged, it could + // be considered iritating to the user to change + // cursor shapes while something is dragged. + // The disabled code below would prevent this (except + // for the minor annoyance that the cursor is not + // updated when the drag is over) +// if (fDragBitmap) { +// // TODO: like a "+" or "-" sign when dragging some files to indicate +// // the current drag mode? +// UnlockExclusiveAccess(); +// return; +// } + if (fCursor != cursor) { + BRect oldFrame = _CursorFrame(); - if (fCursor) - fCursor->Release(); - - fCursor = cursor; - - if (fCursor) - fCursor->Acquire(); - - Invalidate(oldFrame); - - _AdoptDragBitmap(fDragBitmap, fDragBitmapOffset); - Invalidate(_CursorFrame()); + if (fCursorAndDragBitmap == fCursor) { + // make sure _AdoptDragBitmap doesn't delete a real cursor + fCursorAndDragBitmap = NULL; } - WriteUnlock(); + + if (fCursor) + fCursor->Release(); + + fCursor = cursor; + + if (fCursor) + fCursor->Acquire(); + + Invalidate(oldFrame); + + _AdoptDragBitmap(fDragBitmap, fDragBitmapOffset); + Invalidate(_CursorFrame()); } + fSoftwareCursorLock.Unlock(); } // SetCursorVisible void HWInterface::SetCursorVisible(bool visible) { - if (WriteLock()) { - if (fCursorVisible != visible) { - // NOTE: _CursorFrame() will - // return an invalid rect if - // fCursorVisible == false! - if (visible) { - fCursorVisible = visible; - fCursorObscured = false; - BRect r = _CursorFrame(); + if (!fSoftwareCursorLock.Lock()) + return; - _DrawCursor(r); - Invalidate(r); - } else { - BRect r = _CursorFrame(); - fCursorVisible = visible; + if (fCursorVisible != visible) { + // NOTE: _CursorFrame() will + // return an invalid rect if + // fCursorVisible == false! + if (visible) { + fCursorVisible = visible; + fCursorObscured = false; + BRect r = _CursorFrame(); - _RestoreCursorArea(); - Invalidate(r); - } + _DrawCursor(r); + Invalidate(r); + } else { + BRect r = _CursorFrame(); + fCursorVisible = visible; + + _RestoreCursorArea(); + Invalidate(r); } - WriteUnlock(); } + fSoftwareCursorLock.Unlock(); } // IsCursorVisible @@ -153,9 +158,9 @@ bool HWInterface::IsCursorVisible() { bool visible = true; - if (ReadLock()) { + if (fSoftwareCursorLock.Lock()) { visible = fCursorVisible; - ReadUnlock(); + fSoftwareCursorLock.Unlock(); } return visible; } @@ -164,46 +169,46 @@ HWInterface::IsCursorVisible() void HWInterface::ObscureCursor() { - if (WriteLock()) { - if (!fCursorObscured) { - SetCursorVisible(false); - fCursorObscured = true; - } - WriteUnlock(); + if (!fSoftwareCursorLock.Lock()) + return; + + if (!fCursorObscured) { + SetCursorVisible(false); + fCursorObscured = true; } + fSoftwareCursorLock.Unlock(); } // MoveCursorTo void HWInterface::MoveCursorTo(const float& x, const float& y) { - if (WriteLock()) { - BPoint p(x, y); - if (p != fCursorLocation) { - // unhide cursor if it is obscured only - if (fCursorObscured) { - // TODO: causes nested lock, which - // the MultiLocker doesn't actually support? - SetCursorVisible(true); - } - BRect oldFrame = _CursorFrame(); - fCursorLocation = p; - if (fCursorVisible) { - // Invalidate and _DrawCursor would not draw - // anything if the cursor is hidden - // (invalid cursor frame), but explicitly - // testing for it here saves us some cycles - if (fCursorAreaBackup) { - // means we have a software cursor which we need to draw - _RestoreCursorArea(); - _DrawCursor(_CursorFrame()); - } - Invalidate(oldFrame); - Invalidate(_CursorFrame()); - } + if (!fSoftwareCursorLock.Lock()) + return; + + BPoint p(x, y); + if (p != fCursorLocation) { + // unhide cursor if it is obscured only + if (fCursorObscured) { + SetCursorVisible(true); + } + BRect oldFrame = _CursorFrame(); + fCursorLocation = p; + if (fCursorVisible) { + // Invalidate and _DrawCursor would not draw + // anything if the cursor is hidden + // (invalid cursor frame), but explicitly + // testing for it here saves us some cycles + if (fCursorAreaBackup) { + // means we have a software cursor which we need to draw + _RestoreCursorArea(); + _DrawCursor(_CursorFrame()); + } + Invalidate(oldFrame); + Invalidate(_CursorFrame()); } - WriteUnlock(); } + fSoftwareCursorLock.Unlock(); } @@ -211,25 +216,28 @@ BPoint HWInterface::CursorPosition() { BPoint location; - if (ReadLock()) { + if (fSoftwareCursorLock.Lock()) { location = fCursorLocation; - ReadUnlock(); + fSoftwareCursorLock.Unlock(); } return location; } -// SetDragBitmap + void HWInterface::SetDragBitmap(const ServerBitmap* bitmap, const BPoint& offsetFromCursor) { - if (WriteLock()) { + if (fSoftwareCursorLock.Lock()) { _AdoptDragBitmap(bitmap, offsetFromCursor); - WriteUnlock(); + fSoftwareCursorLock.Unlock(); } } -// DrawingBuffer + +// #pragma mark - + + RenderingBuffer* HWInterface::DrawingBuffer() const { @@ -238,14 +246,14 @@ HWInterface::DrawingBuffer() const return FrontBuffer(); } -// IsDoubleBuffered + bool HWInterface::IsDoubleBuffered() const { return fDoubleBuffered; } -// Invalidate + // * the object needs to be already locked! status_t HWInterface::Invalidate(const BRect& frame) @@ -269,7 +277,7 @@ HWInterface::Invalidate(const BRect& frame) return B_OK; } -// CopyBackToFront + // * the object must already be locked! status_t HWInterface::CopyBackToFront(const BRect& frame) @@ -370,7 +378,9 @@ HWInterface::HideSoftwareCursor(const BRect& area) fCursorAreaBackup->right, fCursorAreaBackup->bottom); if (area.Intersects(backupArea)) { + fSoftwareCursorLock.Lock(); _RestoreCursorArea(); + // do not unlock the cursor lock return true; } } @@ -381,6 +391,7 @@ HWInterface::HideSoftwareCursor(const BRect& area) void HWInterface::HideSoftwareCursor() { + fSoftwareCursorLock.Lock(); _RestoreCursorArea(); } @@ -391,6 +402,7 @@ HWInterface::ShowSoftwareCursor() if (fCursorAreaBackup && fCursorAreaBackup->cursor_hidden) { _DrawCursor(_CursorFrame()); } + fSoftwareCursorLock.Unlock(); } @@ -415,7 +427,7 @@ HWInterface::RemoveListener(HWInterfaceListener* listener) // #pragma mark - -// _DrawCursor + // * default implementation, can be used as fallback or for // software cursor // * area is where we potentially draw the cursor, the cursor @@ -433,6 +445,7 @@ HWInterface::_DrawCursor(BRect area) const area = backBuffer->Bounds() & area; if (cf.IsValid() && area.Intersects(cf)) { + // clip to common area area = area & cf; @@ -465,7 +478,8 @@ HWInterface::_DrawCursor(BRect area) const uint8* dst = buffer; - if (fCursorAreaBackup && fCursorAreaBackup->buffer) { + if (fCursorAreaBackup && fCursorAreaBackup->buffer + && fSoftwareCursorLock.Lock()) { fCursorAreaBackup->cursor_hidden = false; // remember which area the backup contains fCursorAreaBackup->left = left; @@ -501,6 +515,7 @@ HWInterface::_DrawCursor(BRect area) const dst += width * 4; bup += bupBPR; } + fSoftwareCursorLock.Unlock(); } else { // blending for (int32 y = top; y <= bottom; y++) { @@ -531,8 +546,7 @@ HWInterface::_DrawCursor(BRect area) const } } -// _CopyToFront -// + // * source is assumed to be already at the right offset // * source is assumed to be in B_RGBA32 format // * location in front buffer is calculated @@ -563,8 +577,7 @@ HWInterface::_CopyToFront(uint8* src, uint32 srcBPR, dst += dstBPR; src += srcBPR; } - } else -printf("nothing to copy\n"); + } break; } // NOTE: on R5, B_RGB24 bitmaps are not supported by DrawBitmap() @@ -679,8 +692,6 @@ printf("nothing to copy\n"); } -// _CursorFrame -// // PRE: the object must be locked BRect HWInterface::_CursorFrame() const @@ -693,7 +704,7 @@ HWInterface::_CursorFrame() const return frame; } -// _RestoreCursorArea + void HWInterface::_RestoreCursorArea() const { diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index b0e16daa50..6a9c5d16a4 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -42,11 +43,20 @@ class HWInterfaceListener { virtual void FrameBufferChanged() = 0; }; -class HWInterface : public MultiLocker { +class HWInterface : protected MultiLocker { public: HWInterface(bool doubleBuffered = false); virtual ~HWInterface(); + // locking + bool LockParallelAccess() { return ReadLock(); } + bool IsParallelAccessLocked() { return IsReadLocked(); } + void UnlockParallelAccess() { ReadUnlock(); } + + bool LockExclusiveAccess() { return WriteLock(); } + bool IsExclusiveAccessLocked() { return IsWriteLocked(); } + void UnlockExclusiveAccess() { WriteUnlock(); } + // You need to WriteLock virtual status_t Initialize(); virtual status_t Shutdown() = 0; @@ -200,6 +210,7 @@ class HWInterface : public MultiLocker { }; buffer_clip* fCursorAreaBackup; + mutable BLocker fSoftwareCursorLock; ServerCursor* fCursor; const ServerBitmap* fDragBitmap; diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 0833ea5ef4..9990a6311e 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -84,7 +84,7 @@ Painter::Painter() fSubpixelPrecise(false), fPenSize(1.0), - fClippingRegion(new BRegion()), + fClippingRegion(NULL), fValidClipping(false), fDrawingMode(B_OP_COPY), fDrawingText(false), @@ -96,7 +96,7 @@ Painter::Painter() fMiterLimit(B_DEFAULT_MITER_LIMIT), fPatternHandler(new PatternHandler()), - fTextRenderer(new AGGTextRenderer()) + fTextRenderer(AGGTextRenderer::Default()) { // Usually, the drawing engine will lock the font for us when // needed - unfortunately, it can't know we need it here @@ -114,9 +114,7 @@ Painter::~Painter() { _MakeEmpty(); - delete fClippingRegion; delete fPatternHandler; - delete fTextRenderer; } // #pragma mark - @@ -141,8 +139,6 @@ Painter::AttachToBuffer(RenderingBuffer* buffer) fPixelFormat->SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false); fBaseRenderer = new renderer_base(*fPixelFormat); - // attach our clipping region to the renderer, it keeps a pointer - fBaseRenderer->set_clipping_region(fClippingRegion); // These are the AGG renderes and rasterizes which // will be used for stroking paths @@ -234,17 +230,14 @@ Painter::SetDrawState(const DrawState* data, bool updateFont) void Painter::ConstrainClipping(const BRegion* region) { - *fClippingRegion = *region; - fValidClipping = fClippingRegion->Frame().IsValid(); + fClippingRegion = region; + fBaseRenderer->set_clipping_region(const_cast(region)); + fValidClipping = region->Frame().IsValid(); if (fValidClipping) { clipping_rect cb = fClippingRegion->FrameInt(); fRasterizer->clip_box(cb.left, cb.top, cb.right + 1, cb.bottom + 1); } -// TODO: would be nice if we didn't need to copy a region -// for *each* drawing command... -//fBaseRenderer->set_clipping_region(const_cast(region)); -//fValidClipping = region->Frame().IsValid(); } // SetHighColor diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index d0af13424c..490e3365f0 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -273,7 +273,7 @@ mutable agg::conv_curve fCurve; bool fSubpixelPrecise; float fPenSize; - BRegion* fClippingRegion; + const BRegion* fClippingRegion; bool fValidClipping; drawing_mode fDrawingMode; bool fDrawingText; diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp index 8acafedabf..6cad2acb40 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp @@ -69,6 +69,10 @@ is_white_space(uint32 charCode) #define DEFAULT_UNI_CODE_BUFFER_SIZE 2048 +// init default instance +AGGTextRenderer +AGGTextRenderer::sDefaultInstance; + // constructor AGGTextRenderer::AGGTextRenderer() : fFontEngine(gFreeTypeLibrary), @@ -97,6 +101,13 @@ AGGTextRenderer::~AGGTextRenderer() free(fUnicodeBuffer); } +// Default +/*static*/ AGGTextRenderer* +AGGTextRenderer::Default() +{ + return &sDefaultInstance; +} + // SetFont bool AGGTextRenderer::SetFont(const ServerFont &font) diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h index 7e334471cb..e26ba8c522 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h @@ -21,6 +21,14 @@ class AGGTextRenderer { AGGTextRenderer(); virtual ~AGGTextRenderer(); + // NOTE: every Painter instance is using the same + // AGGTextRenderer instance, and the only thing that + // protects locking is the fact that every use of a + // ServerFont goes through a global lock... this will + // have to be changed. Maybe every ServerFont should + // have it's own AGGTextRenderer or something + static AGGTextRenderer* Default(); + bool SetFont(const ServerFont &font); void Unset(); @@ -76,6 +84,8 @@ class AGGTextRenderer { bool fAntialias; bool fKerning; Transformable fEmbeddedTransformation; // rotated or sheared font? + + static AGGTextRenderer sDefaultInstance; }; #endif // AGG_TEXT_RENDERER_H diff --git a/src/servers/app/PatternHandler.h b/src/servers/app/drawing/PatternHandler.h similarity index 100% rename from src/servers/app/PatternHandler.h rename to src/servers/app/drawing/PatternHandler.h diff --git a/src/servers/app/drawing/UpdateQueue.cpp b/src/servers/app/drawing/UpdateQueue.cpp index a9c0657e80..5ff5fc4934 100644 --- a/src/servers/app/drawing/UpdateQueue.cpp +++ b/src/servers/app/drawing/UpdateQueue.cpp @@ -85,7 +85,7 @@ UpdateQueue::_ExecuteUpdates() case B_OK: case B_TIMED_OUT: // execute updates - if (fInterface->ReadLock()) { + if (fInterface->LockParallelAccess()) { int32 count = fUpdateRegion.CountRects(); if (count > 0) { for (int32 i = 0; i < count; i++) { @@ -93,7 +93,7 @@ UpdateQueue::_ExecuteUpdates() } fUpdateRegion.MakeEmpty(); } - fInterface->ReadUnlock(); + fInterface->UnlockParallelAccess(); } break; case B_BAD_SEM_ID: