implemented invalidation triggered from the client side. 20 clients each displaying an animation in one view at 25 fps leaves the new clipping unimpressed, everything is fluent, also during moving and resizing windows
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15275 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
755ae3a961
commit
727653f7ab
@ -1,8 +1,13 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Message.h>
|
||||
#include <MessageQueue.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <Messenger.h>
|
||||
#include <Rect.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "WindowLayer.h"
|
||||
@ -11,6 +16,71 @@
|
||||
|
||||
#define SLOW_DRAWING 0
|
||||
|
||||
#define SPEED 2.0
|
||||
|
||||
// random_number_between
|
||||
static float
|
||||
random_number_between(float v1, float v2)
|
||||
{
|
||||
if (v1 < v2)
|
||||
return v1 + fmod(rand() / 1000.0, (v2 - v1));
|
||||
else if (v2 < v1)
|
||||
return v2 + fmod(rand() / 1000.0, (v1 - v2));
|
||||
return v1;
|
||||
}
|
||||
|
||||
// init_polygon
|
||||
static void
|
||||
init_polygon(const BRect& b, point* polygon)
|
||||
{
|
||||
polygon[0].x = b.left;
|
||||
polygon[0].y = b.top;
|
||||
polygon[0].direction_x = random_number_between(-SPEED, SPEED);
|
||||
polygon[0].direction_y = random_number_between(-SPEED, SPEED);
|
||||
polygon[1].x = b.right;
|
||||
polygon[1].y = b.top;
|
||||
polygon[1].direction_x = random_number_between(-SPEED, SPEED);
|
||||
polygon[1].direction_y = random_number_between(-SPEED, SPEED);
|
||||
polygon[2].x = b.right;
|
||||
polygon[2].y = b.bottom;
|
||||
polygon[2].direction_x = random_number_between(-SPEED, SPEED);
|
||||
polygon[2].direction_y = random_number_between(-SPEED, SPEED);
|
||||
polygon[3].x = b.left;
|
||||
polygon[3].y = b.bottom;
|
||||
polygon[3].direction_x = random_number_between(-SPEED, SPEED);
|
||||
polygon[3].direction_y = random_number_between(-SPEED, SPEED);
|
||||
}
|
||||
|
||||
// morph
|
||||
static inline void
|
||||
morph(double* value, double* direction, double min, double max)
|
||||
{
|
||||
*value += *direction;
|
||||
if (*value < min) {
|
||||
*value = min;
|
||||
*direction = -*direction;
|
||||
} else if (*value > max) {
|
||||
*value = max;
|
||||
*direction = -*direction;
|
||||
}
|
||||
}
|
||||
|
||||
// morph_polygon
|
||||
static inline void
|
||||
morph_polygon(const BRect& b, point* polygon)
|
||||
{
|
||||
morph(&polygon[0].x, &polygon[0].direction_x, b.left, b.right);
|
||||
morph(&polygon[1].x, &polygon[1].direction_x, b.left, b.right);
|
||||
morph(&polygon[2].x, &polygon[2].direction_x, b.left, b.right);
|
||||
morph(&polygon[3].x, &polygon[3].direction_x, b.left, b.right);
|
||||
morph(&polygon[0].y, &polygon[0].direction_y, b.top, b.bottom);
|
||||
morph(&polygon[1].y, &polygon[1].direction_y, b.top, b.bottom);
|
||||
morph(&polygon[2].y, &polygon[2].direction_y, b.top, b.bottom);
|
||||
morph(&polygon[3].y, &polygon[3].direction_y, b.top, b.bottom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// constructor
|
||||
ClientLooper::ClientLooper(const char* name, WindowLayer* serverWindow)
|
||||
: BLooper("", B_DISPLAY_PRIORITY),
|
||||
@ -20,11 +90,17 @@ ClientLooper::ClientLooper(const char* name, WindowLayer* serverWindow)
|
||||
BString clientName(name);
|
||||
clientName << " client";
|
||||
SetName(clientName.String());
|
||||
|
||||
BMessenger messenger(this);
|
||||
fTicker = new BMessageRunner(messenger, new BMessage(MSG_TICK), 40000);
|
||||
|
||||
init_polygon(BRect(0, 0, 100, 100), fPolygon);
|
||||
}
|
||||
|
||||
// destructor
|
||||
ClientLooper::~ClientLooper()
|
||||
{
|
||||
delete fTicker;
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
@ -40,9 +116,13 @@ ClientLooper::MessageReceived(BMessage* message)
|
||||
// the client is slow
|
||||
// snooze(40000L);
|
||||
// send the command to redraw a view
|
||||
BMessage command(MSG_DRAWING_COMMAND);
|
||||
command.AddInt32("token", i);
|
||||
fServerWindow->PostMessage(&command);
|
||||
if (i == 5) {
|
||||
_DrawAnimatedLayer(i);
|
||||
} else {
|
||||
BMessage command(MSG_DRAWING_COMMAND);
|
||||
command.AddInt32("token", i);
|
||||
fServerWindow->PostMessage(&command);
|
||||
}
|
||||
}
|
||||
|
||||
fServerWindow->PostMessage(MSG_END_UPDATE);
|
||||
@ -69,8 +149,33 @@ ClientLooper::MessageReceived(BMessage* message)
|
||||
fServerWindow->PostMessage(MSG_SHOW);
|
||||
break;
|
||||
|
||||
case MSG_TICK: {
|
||||
BMessage invalidate(MSG_INVALIDATE_VIEW);
|
||||
invalidate.AddInt32("token", 5);
|
||||
fServerWindow->PostMessage(&invalidate);
|
||||
|
||||
morph_polygon(BRect(0, 0, 100, 100), fPolygon);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// _DrawAnimatedLayer
|
||||
void
|
||||
ClientLooper::_DrawAnimatedLayer(int32 token)
|
||||
{
|
||||
BMessage message(MSG_DRAW_POLYGON);
|
||||
message.AddInt32("token", token);
|
||||
|
||||
message.AddPoint("point", BPoint(fPolygon[0].x, fPolygon[0].y));
|
||||
message.AddPoint("point", BPoint(fPolygon[1].x, fPolygon[1].y));
|
||||
message.AddPoint("point", BPoint(fPolygon[2].x, fPolygon[2].y));
|
||||
message.AddPoint("point", BPoint(fPolygon[3].x, fPolygon[3].y));
|
||||
|
||||
fServerWindow->PostMessage(&message);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,15 @@ enum {
|
||||
MSG_VIEWS_REMOVED = 'vwrm',
|
||||
|
||||
MSG_WINDOW_HIDDEN = 'whdn',
|
||||
|
||||
MSG_TICK = 'tick',
|
||||
};
|
||||
|
||||
struct point {
|
||||
double x;
|
||||
double y;
|
||||
double direction_x;
|
||||
double direction_y;
|
||||
};
|
||||
|
||||
class ClientLooper : public BLooper {
|
||||
@ -25,6 +34,13 @@ class ClientLooper : public BLooper {
|
||||
private:
|
||||
WindowLayer* fServerWindow;
|
||||
int32 fViewCount;
|
||||
|
||||
BMessageRunner* fTicker;
|
||||
|
||||
|
||||
void _DrawAnimatedLayer(int32 token);
|
||||
|
||||
point fPolygon[4];
|
||||
};
|
||||
|
||||
#endif // CLIENT_LOOPER_H
|
||||
|
@ -22,6 +22,9 @@
|
||||
// the update session, which tells us the cause of the update
|
||||
#define DELAYED_BACKGROUND_CLEARING 1
|
||||
|
||||
// IMPORTANT: nested ReadLockClipping()s are not supported (by MultiLocker)
|
||||
|
||||
|
||||
// constructor
|
||||
WindowLayer::WindowLayer(BRect frame, const char* name,
|
||||
DrawingEngine* drawingEngine, Desktop* desktop)
|
||||
@ -75,6 +78,9 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
|
||||
// destructor
|
||||
WindowLayer::~WindowLayer()
|
||||
{
|
||||
fClient->Lock();
|
||||
fClient->Quit();
|
||||
|
||||
delete fTopLayer;
|
||||
}
|
||||
|
||||
@ -117,6 +123,27 @@ WindowLayer::MessageReceived(BMessage* message)
|
||||
_DrawClient(token);
|
||||
break;
|
||||
}
|
||||
case MSG_DRAW_POLYGON: {
|
||||
int32 token;
|
||||
BPoint polygon[4];
|
||||
if (message->FindInt32("token", &token) >= B_OK &&
|
||||
message->FindPoint("point", 0, &polygon[0]) >= B_OK &&
|
||||
message->FindPoint("point", 1, &polygon[1]) >= B_OK &&
|
||||
message->FindPoint("point", 2, &polygon[2]) >= B_OK &&
|
||||
message->FindPoint("point", 3, &polygon[3]) >= B_OK) {
|
||||
|
||||
_DrawClientPolygon(token, polygon);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case MSG_INVALIDATE_VIEW: {
|
||||
int32 token;
|
||||
if (message->FindInt32("token", &token) >= B_OK)
|
||||
InvalidateView(token);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_SHOW:
|
||||
if (IsHidden()) {
|
||||
@ -386,6 +413,26 @@ WindowLayer::MarkContentDirty(BRegion* regionOnScreen)
|
||||
}
|
||||
}
|
||||
|
||||
// InvalidateView
|
||||
void
|
||||
WindowLayer::InvalidateView(int32 token)
|
||||
{
|
||||
if (fDesktop && fDesktop->ReadLockClipping()) {
|
||||
|
||||
ViewLayer* layer = (ViewLayer*)fTokenViewMap.ItemAt(token);
|
||||
if (!layer || !layer->IsVisible()) {
|
||||
fDesktop->ReadUnlockClipping();
|
||||
return;
|
||||
}
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
|
||||
_MarkContentDirty(&layer->ScreenClipping(&fContentRegion));
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
//# pragma mark -
|
||||
|
||||
// CopyContents
|
||||
@ -507,12 +554,14 @@ WindowLayer::_DrawClient(int32 token)
|
||||
// We have to be sure that the clipping is up to date.
|
||||
// If true readlocking would work correctly, this would
|
||||
// not be an issue
|
||||
ViewLayer* layer = (ViewLayer*)fTokenViewMap.ItemAt(token);
|
||||
if (!layer || !layer->IsVisible())
|
||||
return;
|
||||
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
ViewLayer* layer = (ViewLayer*)fTokenViewMap.ItemAt(token);
|
||||
if (!layer || !layer->IsVisible()) {
|
||||
fDesktop->ReadUnlockClipping();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fEffectiveDrawingRegionValid) {
|
||||
fEffectiveDrawingRegion = VisibleContentRegion();
|
||||
if (fInUpdate) {
|
||||
@ -551,6 +600,68 @@ WindowLayer::_DrawClient(int32 token)
|
||||
}
|
||||
}
|
||||
|
||||
// _DrawClientPolygon
|
||||
void
|
||||
WindowLayer::_DrawClientPolygon(int32 token, BPoint polygon[4])
|
||||
{
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
ViewLayer* layer = (ViewLayer*)fTokenViewMap.ItemAt(token);
|
||||
if (!layer || !layer->IsVisible()) {
|
||||
fDesktop->ReadUnlockClipping();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fEffectiveDrawingRegionValid) {
|
||||
fEffectiveDrawingRegion = VisibleContentRegion();
|
||||
if (fInUpdate) {
|
||||
// enforce the dirty region of the update session
|
||||
fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession.DirtyRegion());
|
||||
} else {
|
||||
printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token);
|
||||
}
|
||||
fEffectiveDrawingRegionValid = true;
|
||||
}
|
||||
|
||||
BRegion effectiveClipping(fEffectiveDrawingRegion);
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
effectiveClipping.IntersectWith(&layer->ScreenClipping(&fContentRegion));
|
||||
|
||||
if (effectiveClipping.CountRects() > 0) {
|
||||
#if DELAYED_BACKGROUND_CLEARING
|
||||
layer->Draw(fDrawingEngine, &effectiveClipping,
|
||||
&fContentRegion, false);
|
||||
#endif
|
||||
|
||||
if (fDrawingEngine->Lock()) {
|
||||
|
||||
fDrawingEngine->PushState();
|
||||
fDrawingEngine->ConstrainClippingRegion(&effectiveClipping);
|
||||
fDrawingEngine->SetPenSize(3);
|
||||
// fDrawingEngine->SetDrawingMode(B_OP_BLEND);
|
||||
layer->ConvertToTop(&polygon[0]);
|
||||
layer->ConvertToTop(&polygon[1]);
|
||||
layer->ConvertToTop(&polygon[2]);
|
||||
layer->ConvertToTop(&polygon[3]);
|
||||
fDrawingEngine->BeginLineArray(4);
|
||||
fDrawingEngine->AddLine(polygon[0], polygon[1], layer->ViewColor());
|
||||
fDrawingEngine->AddLine(polygon[1], polygon[2], layer->ViewColor());
|
||||
fDrawingEngine->AddLine(polygon[2], polygon[3], layer->ViewColor());
|
||||
fDrawingEngine->AddLine(polygon[3], polygon[0], layer->ViewColor());
|
||||
fDrawingEngine->EndLineArray();
|
||||
|
||||
fDrawingEngine->PopState();
|
||||
fDrawingEngine->MarkDirty(&effectiveClipping);
|
||||
fDrawingEngine->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// _DrawBorder
|
||||
void
|
||||
WindowLayer::_DrawBorder()
|
||||
|
@ -14,14 +14,17 @@ class Desktop;
|
||||
class DrawingEngine;
|
||||
|
||||
enum {
|
||||
MSG_REDRAW = 'rdrw',
|
||||
MSG_REDRAW = 'rdrw',
|
||||
|
||||
// client messages
|
||||
MSG_BEGIN_UPDATE = 'bgud',
|
||||
MSG_END_UPDATE = 'edud',
|
||||
MSG_DRAWING_COMMAND = 'draw',
|
||||
MSG_BEGIN_UPDATE = 'bgud',
|
||||
MSG_END_UPDATE = 'edud',
|
||||
MSG_DRAWING_COMMAND = 'draw',
|
||||
|
||||
MSG_SHOW = 'show',
|
||||
MSG_SHOW = 'show',
|
||||
|
||||
MSG_INVALIDATE_VIEW = 'invl',
|
||||
MSG_DRAW_POLYGON = 'drwp',
|
||||
};
|
||||
|
||||
class UpdateSession {
|
||||
@ -82,6 +85,7 @@ class WindowLayer : public BLooper {
|
||||
|
||||
void MarkDirty(BRegion* regionOnScreen);
|
||||
void MarkContentDirty(BRegion* regionOnScreen);
|
||||
void InvalidateView(int32 token);
|
||||
|
||||
void ProcessDirtyRegion(BRegion* region);
|
||||
|
||||
@ -98,6 +102,7 @@ class WindowLayer : public BLooper {
|
||||
// different types of drawing
|
||||
void _TriggerContentRedraw();
|
||||
void _DrawClient(int32 token);
|
||||
void _DrawClientPolygon(int32 token, BPoint polygon[4]);
|
||||
void _DrawBorder();
|
||||
|
||||
// handling update sessions
|
||||
|
@ -220,6 +220,8 @@ Window::Test()
|
||||
int
|
||||
main(int argc, const char* argv[])
|
||||
{
|
||||
srand((long int)system_time());
|
||||
|
||||
App app;
|
||||
app.Run();
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user