[haiku-commits] BRANCH looncraz-github.ScreenStream [b3f82077ee1d] in src: servers/app servers/app/drawing kits/interface

  • From: looncraz-github.ScreenStream <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 3 Apr 2015 06:16:47 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/looncraz-github/ScreenStream'
old head: 61a99d0fbfc74f53ae035740bafcc4382440abad
new head: b3f82077ee1d37d41363c08089a1a29be49324de
overview: https://github.com/looncraz/haiku/compare/61a99d0fbfc7...b3f82077ee1d

----------------------------------------------------------------------------

b3f82077ee1d: Experiment with Window Clipping Locking

No noticeable slowdown anywhere, but it will be necessary for
multiple threads to access the clipping in the future and gaining
a read lock on the Desktop will eventually cause a deadlock.

Could also permit reduced locking in Desktop since each Window
will be protecting its own clipping.

[ looncraz <looncraz@xxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit: b3f82077ee1d37d41363c08089a1a29be49324de
Author: looncraz <looncraz@xxxxxxxxxxxx>
Date: Fri Apr 3 04:03:22 2015 UTC

----------------------------------------------------------------------------

5 files changed, 47 insertions(+), 34 deletions(-)
src/kits/interface/ScreenStream.cpp | 2 +-
src/servers/app/MultiLocker.h | 14 +++++---
src/servers/app/Window.cpp | 54 ++++++++++++++++------------
src/servers/app/Window.h | 6 ++--
src/servers/app/drawing/UpdateStream.cpp | 5 ++-

----------------------------------------------------------------------------

diff --git a/src/kits/interface/ScreenStream.cpp
b/src/kits/interface/ScreenStream.cpp
index 3f7cecb..a598380 100644
--- a/src/kits/interface/ScreenStream.cpp
+++ b/src/kits/interface/ScreenStream.cpp
@@ -377,7 +377,7 @@ BScreenStream::_UpdateBitmap()
for (int32 y = (int32)rect.top; y < (int32)rect.bottom; ++y) {
bits = (uint8*)fBitmap->Bits();
bits += (int32)((y * bytesPerRow) + rect.left * 4);
- gfxset32(bits, color, rect.Width() * 4);
+ gfxset32(bits, color, (int32)rect.Width() * 4);
}
}

diff --git a/src/servers/app/MultiLocker.h b/src/servers/app/MultiLocker.h
index eac9ea5..7573e4e 100644
--- a/src/servers/app/MultiLocker.h
+++ b/src/servers/app/MultiLocker.h
@@ -173,20 +173,26 @@ public:

~AutoReadLocker()
{
- Unlock();
+ while (fLocked > 0)
+ Unlock();
}

void Unlock()
{
- if (fLocked) {
+ if (fLocked > 0) {
fLock.ReadUnlock();
- fLocked = false;
+ fLocked--;
}
}

+ void Lock()
+ {
+ fLocked += fLock.ReadLock();
+ }
+
private:
MultiLocker& fLock;
- bool fLocked;
+ int32 fLocked;
};

#endif // MULTI_LOCKER_H
diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp
index c485891..f8bb0d0 100644
--- a/src/servers/app/Window.cpp
+++ b/src/servers/app/Window.cpp
@@ -95,6 +95,8 @@ Window::Window(const BRect& frame, const char *name,
fWindow(window),
fDrawingEngine(drawingEngine),
fDesktop(window->Desktop()),
+ fClippingLock(name),
+

fCurrentUpdateSession(&fUpdateSessions[0]),
fPendingUpdateSession(&fUpdateSessions[1]),
@@ -198,7 +200,8 @@ void
Window::SetClipping(BRegion* stillAvailableOnScreen)
{
// this function is only called from the Desktop thread
-
+ // but we grab the window's clipping lock anyway
+ AutoWriteLocker lock(&fClippingLock);
// start from full region (as if the window was fully visible)
GetFullRegion(&fVisibleRegion);
// clip to region still available on screen
@@ -216,6 +219,7 @@ Window::GetFullRegion(BRegion* region)
// the outside, the clipping needs to be readlocked!

// start from the decorator border, extend to use the frame
+ AutoReadLocker lock(&fClippingLock);
GetBorderRegion(region);
region->Include(fFrame);
}
@@ -226,7 +230,7 @@ Window::GetBorderRegion(BRegion* region)
{
// TODO: if someone needs to call this from
// the outside, the clipping needs to be readlocked!
-
+ AutoReadLocker lock(&fClippingLock);
::Decorator* decorator = Decorator();
if (decorator)
*region = decorator->GetFootprint();
@@ -240,9 +244,15 @@ Window::GetContentRegion(BRegion* region)
{
// TODO: if someone needs to call this from
// the outside, the clipping needs to be readlocked!
+ AutoReadLocker lock(&fClippingLock);

if (!fContentRegionValid) {
- _UpdateContentRegion();
+ lock.Unlock();
+ if (fClippingLock.WriteLock()) {
+ _UpdateContentRegion();
+ fClippingLock.WriteUnlock();
+ }
+ lock.Lock();
}

*region = fContentRegion;
@@ -256,29 +266,23 @@ Window::VisibleContentRegion()
// the outside, the clipping needs to be readlocked!

// regions expected to be locked
- if (!fVisibleContentRegionValid) {
- GetContentRegion(&fVisibleContentRegion);
- fVisibleContentRegion.IntersectWith(&fVisibleRegion);
- }
- return fVisibleContentRegion;
-}

+ AutoReadLocker lock(&fClippingLock);

-void
-Window::ReadLock()
-{
- fDesktop->LockSingleWindow();
-}
-
-
-void
-Window::ReadUnlock()
-{
- fDesktop->UnlockSingleWindow();
-}
+ if (!fVisibleContentRegionValid) {
+ lock.Unlock();

+ if (fClippingLock.WriteLock()) {
+ GetContentRegion(&fVisibleContentRegion);
+ fVisibleContentRegion.IntersectWith(&fVisibleRegion);
+ fClippingLock.WriteUnlock();
+ }

+ lock.Lock();
+ }

+ return fVisibleContentRegion;
+}


// #pragma mark -
@@ -311,8 +315,12 @@ Window::MoveBy(int32 x, int32 y, bool moveStack)
// processed yet
fDirtyRegion.OffsetBy(x, y);

- if (fContentRegionValid)
- fContentRegion.OffsetBy(x, y);
+ if (fContentRegionValid) {
+ if (fClippingLock.WriteLock()) {
+ fContentRegion.OffsetBy(x, y);
+ fClippingLock.WriteUnlock();
+ }
+ }

if (fCurrentUpdateSession->IsUsed())
fCurrentUpdateSession->MoveBy(x, y);
diff --git a/src/servers/app/Window.h b/src/servers/app/Window.h
index 2f4b54d..dbfce88 100644
--- a/src/servers/app/Window.h
+++ b/src/servers/app/Window.h
@@ -14,6 +14,7 @@
#define WINDOW_H


+#include "MultiLocker.h"
#include "RegionPool.h"
#include "ServerWindow.h"
#include "View.h"
@@ -119,9 +120,6 @@ public:
inline BRegion& VisibleRegion() { return
fVisibleRegion; }
BRegion& VisibleContentRegion();

- void ReadLock();
- void ReadUnlock();
-
// TODO: not protected by a lock, but noone should need
this anyways
// make private? when used inside Window, it has the
ReadLock()
void GetFullRegion(BRegion*
region);
@@ -370,6 +368,8 @@ protected:
DrawingEngine* fDrawingEngine;
::Desktop* fDesktop;

+ MultiLocker fClippingLock;
+
// The synchronization, which client drawing commands
// belong to the redraw of which dirty region is handled
// through an UpdateSession. When the client has
diff --git a/src/servers/app/drawing/UpdateStream.cpp
b/src/servers/app/drawing/UpdateStream.cpp
index ec4dd07..230cdcc 100644
--- a/src/servers/app/drawing/UpdateStream.cpp
+++ b/src/servers/app/drawing/UpdateStream.cpp
@@ -103,9 +103,7 @@ UpdateStream::GetRegion() const
if(fClientMaskRegion != NULL)
fRegion->Exclude(fClientMaskRegion);
if (fClientMaskWindow != NULL) {
-// fClientMaskWindow->ReadLock();

fRegion->Exclude(&(fClientMaskWindow->VisibleContentRegion()));
-// fClientMaskWindow->ReadUnlock();
}
fDirty = false;
}
@@ -129,8 +127,9 @@ UpdateStream::GetMaskRegion() const

BRegion mask;

- if (fClientMaskWindow != NULL)
+ if (fClientMaskWindow != NULL) {
mask.Include(&(fClientMaskWindow->VisibleContentRegion()));
+ }

if (fClientMaskRegion != NULL)
mask.Include(fClientMaskRegion);


Other related posts: