* BView::FillRegion() sends the BRegion data instead of decomposing

it and rebuilding it on the server side (that causes a huge speed
  up for regions containing many rects)
* There is a method in ServerLink that could have been used, but I
  actually needed to add the direct BRegion support to LinkReceiver
* added LinkReceiver as a friend to BRegion class
* ServerApp and ServerWindow keep the CursorManager locked after they
  have retrieved a cursor until they have called Acquire() on the
  cursor. (Axel: what good is using atomic* stuff in Acquire() and
  Release() if we have to protect this by a lock anyways?)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16957 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-04-01 16:56:10 +00:00
parent b22badf221
commit 600fbd78e4
6 changed files with 54 additions and 38 deletions
+3 -2
View File
@@ -17,10 +17,10 @@
namespace BPrivate {
class ServerLink;
class LinkReceiver;
};
/* Integer rect used to define a cliping rectangle. All bounds are included */
/* Integer rect used to define a clipping rectangle. All bounds are inclusive. */
/* Moved from DirectWindow.h */
typedef struct {
int32 left;
@@ -71,6 +71,7 @@ private:
friend class BDirectWindow;
friend class Support;
friend class BPrivate::ServerLink;
friend class BPrivate::LinkReceiver;
void _AddRect(clipping_rect r);
void set_size(long new_size);
+6 -4
View File
@@ -14,6 +14,7 @@
#include <OS.h>
class BString;
class BRegion;
namespace BPrivate {
@@ -26,15 +27,16 @@ class LinkReceiver {
void SetPort(port_id port);
port_id Port(void) { return fReceivePort; }
status_t GetNextMessage(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
status_t GetNextMessage(int32& code, bigtime_t timeout = B_INFINITE_TIMEOUT);
bool HasMessages() const;
bool NeedsReply() const;
int32 Code() const;
virtual status_t Read(void *data, ssize_t size);
virtual status_t Read(void* data, ssize_t size);
status_t ReadString(char** _string, size_t* _length = NULL);
status_t ReadString(BString& string, size_t* _length = NULL);
status_t ReadString(char *buffer, size_t bufferSize);
status_t ReadString(char* buffer, size_t bufferSize);
status_t ReadRegion(BRegion* region);
template <class Type> status_t Read(Type *data)
{ return Read(data, sizeof(Type)); }
@@ -46,7 +48,7 @@ class LinkReceiver {
port_id fReceivePort;
char *fRecvBuffer;
char* fRecvBuffer;
int32 fRecvPosition; //current read position
int32 fRecvStart; //start of current message
int32 fRecvBufferSize;
+22 -1
View File
@@ -5,17 +5,20 @@
* Authors:
* Pahtz <[email protected]>
* Axel Dörfler
* Stephan Aßmus <[email protected]>
*/
/** Class for low-overhead port-based messaging */
#include <LinkReceiver.h>
#include <stdlib.h>
#include <string.h>
#include <new>
#include <ServerProtocol.h>
#include <LinkReceiver.h>
#include <String.h>
#include <Region.h>
#include "link_message.h"
@@ -396,4 +399,22 @@ err:
return status;
}
status_t
LinkReceiver::ReadRegion(BRegion* region)
{
status_t status = Read(&region->count, sizeof(int32));
if (status >= B_OK)
status = Read(&region->bound, sizeof(clipping_rect));
if (status >= B_OK) {
region->set_size(region->count);
status = Read(region->data, region->count * sizeof(clipping_rect));
if (status < B_OK)
region->MakeEmpty();
}
return status;
}
} // namespace BPrivate
+5 -12
View File
@@ -2714,19 +2714,12 @@ BView::FillRegion(BRegion *region, ::pattern pattern)
_UpdatePattern(pattern);
int32 count = region->CountRects();
fOwner->fLink->StartMessage(AS_FILL_REGION);
fOwner->fLink->AttachRegion(*region);
// TODO: make this automatically chose
// to send over area or handle failure here?
if (count * sizeof(BRect) < MAX_ATTACHMENT_SIZE) {
fOwner->fLink->StartMessage(AS_FILL_REGION);
fOwner->fLink->Attach<int32>(count);
for (int32 i = 0; i < count; i++)
fOwner->fLink->Attach<BRect>(region->RectAt(i));
_FlushIfNotInTransaction();
} else {
// TODO: send via area
}
_FlushIfNotInTransaction();
}
+10
View File
@@ -871,6 +871,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (link.Read<int32>(&token) != B_OK)
break;
if (!fDesktop->GetCursorManager().Lock())
break;
ServerCursor* oldCursor = fAppCursor;
fAppCursor = fDesktop->GetCursorManager().FindCursor(token);
if (fAppCursor != NULL)
@@ -882,6 +885,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (oldCursor != NULL)
oldCursor->Release();
fDesktop->GetCursorManager().Unlock();
if (sync) {
// The application is expecting a reply
fLink.StartMessage(B_OK);
@@ -944,6 +949,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (link.Read<bool>(&pendingViewCursor) != B_OK)
break;
if (!fDesktop->GetCursorManager().Lock())
break;
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
if (cursor) {
if (pendingViewCursor)
@@ -951,6 +959,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
cursor->Release();
}
fDesktop->GetCursorManager().Unlock();
break;
}
+8 -19
View File
@@ -1258,9 +1258,14 @@ ServerWindow::_DispatchViewMessage(int32 code,
if (link.Read<bool>(&sync) != B_OK)
break;
if (!fDesktop->GetCursorManager().Lock())
break;
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
fCurrentLayer->SetCursor(cursor);
fDesktop->GetCursorManager().Unlock();
if (fWindowLayer->IsFocus()) {
// The cursor might need to be updated now
if (fDesktop->ViewUnderMouse(fWindowLayer) == fCurrentLayer->Token())
@@ -1603,6 +1608,7 @@ ServerWindow::_DispatchViewMessage(int32 code,
status = link.Read<clipping_rect>(&r);
if (status < B_OK)
break;
// TODO: optimize (use AttachRegion()+ReadRegion())
region.Include(r);
}
} else
@@ -2096,30 +2102,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
{
DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title()));
int32 count;
link.Read<int32>(&count);
BRect* rects = new(nothrow) BRect[count];
if (link.Read(rects, sizeof(BRect) * count) < B_OK) {
delete[] rects;
break;
}
// Between the client-side conversion to BRects from clipping_rects to the overhead
// in repeatedly calling FillRect(), this is definitely in need of optimization. At
// least it works for now. :)
BRegion region;
for (int32 i = 0; i < count; i++) {
region.Include(rects[i]);
}
if (link.ReadRegion(&region) < B_OK)
break;
fCurrentLayer->ConvertToScreenForDrawing(&region);
drawingEngine->FillRegion(region, fCurrentLayer->CurrentState());
delete[] rects;
// TODO: create support for clipping_rect usage for faster BRegion display.
// Tweaks to DrawingEngine are necessary along with conversion routines in ViewLayer
break;
}
case AS_STROKE_LINEARRAY: