diff --git a/src/tests/servers/app/newerClipping/Desktop.cpp b/src/tests/servers/app/newerClipping/Desktop.cpp index 9349bac016..76d39225e4 100644 --- a/src/tests/servers/app/newerClipping/Desktop.cpp +++ b/src/tests/servers/app/newerClipping/Desktop.cpp @@ -8,12 +8,13 @@ #include #include "DrawingEngine.h" +#include "DrawView.h" #include "WindowLayer.h" #include "Desktop.h" // constructor -Desktop::Desktop(DrawView* drawView) +Desktop::Desktop(DrawView* drawView, DrawingEngine* engine) : BLooper("desktop", B_URGENT_DISPLAY_PRIORITY), fTracking(false), fLastMousePos(-1.0, -1.0), @@ -25,8 +26,12 @@ Desktop::Desktop(DrawView* drawView) fClippingLock("clipping lock"), fBackgroundRegion(), + fMasterClipping(), + fXOffset(0), + fYOffset(0), + fDrawView(drawView), - fDrawingEngine(fDrawView->GetDrawingEngine()), + fDrawingEngine(engine), fWindows(64), @@ -45,36 +50,6 @@ Desktop::~Desktop() { } -// Draw -void -Desktop::Draw(BRect updateRect) -{ -#if !RUN_WITH_FRAME_BUFFER - // since parts of the view might have been exposed, - // we need a clipping rebuild - if (LockClipping()) { - BRegion background; - _RebuildClippingForAllWindows(&background); - _SetBackground(&background); - - UnlockClipping(); - } -#endif - - if (fDrawingEngine->Lock()) { - fDrawingEngine->SetHighColor(51, 102, 152); - fDrawingEngine->FillRegion(&fBackgroundRegion); - fDrawingEngine->Unlock(); - } - -#if !RUN_WITH_FRAME_BUFFER - // trigger redrawing windows - BRegion update(updateRect); - update.Exclude(&fBackgroundRegion); - MarkDirty(&update); -#endif -} - // MouseDown void Desktop::MouseDown(BPoint where, uint32 buttons, int32 clicks) @@ -103,19 +78,7 @@ Desktop::MouseDown(BPoint where, uint32 buttons, int32 clicks) fIs2ndButton = true; } else if (buttons == B_TERTIARY_MOUSE_BUTTON) { -#if RUN_WITH_FRAME_BUFFER - if (fDrawingEngine->Lock()) { - BRegion region(fDrawingEngine->Bounds()); - fDrawingEngine->Unlock(); - - MarkDirty(®ion); - region = fBackgroundRegion; - fBackgroundRegion.MakeEmpty(); - _SetBackground(®ion); - } -#else - fDrawingEngine->MarkDirty(); -#endif + fDrawView->Invalidate(); } } @@ -163,23 +126,7 @@ Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) } } } else if (fIs2ndButton) { - if (fDrawingEngine->Lock()) { - fDrawingEngine->SetHighColor(0, 0, 0); - fDrawingEngine->StrokeLine(fLastMousePos, where); - - BRect dirty(fLastMousePos, where); - if (dirty.left > dirty.right) { - dirty.left = where.x; - dirty.right = fLastMousePos.x; - } - if (dirty.top > dirty.bottom) { - dirty.top = where.y; - dirty.bottom = fLastMousePos.y; - } - fDrawingEngine->MarkDirty(dirty); - - fDrawingEngine->Unlock(); - } + fDrawingEngine->StrokeLine(fLastMousePos, where, (rgb_color){ 0, 0, 0, 255 }); fLastMousePos = where; } } @@ -197,6 +144,9 @@ Desktop::MessageReceived(BMessage* message) message->FindInt32("buttons", (int32*)&buttons) >= B_OK && message->FindInt32("clicks", &clicks) >= B_OK) { + where.x += fXOffset; + where.y += fYOffset; + MouseDown(where, buttons, clicks); } break; @@ -205,6 +155,9 @@ Desktop::MessageReceived(BMessage* message) BPoint where; if (message->FindPoint("where", &where) >= B_OK) { + where.x += fXOffset; + where.y += fYOffset; + MouseUp(where); } break; @@ -215,18 +168,15 @@ Desktop::MessageReceived(BMessage* message) uint32 transit; if (message->FindPoint("where", &where) >= B_OK && message->FindInt32("be:transit", (int32*)&transit) >= B_OK) { + + where.x += fXOffset; + where.y += fYOffset; MouseMoved(where, transit, NULL); } } break; } - case MSG_DRAW: { - BRect area; - if (message->FindRect("area", &area) >= B_OK) - Draw(area); - } - case MSG_ADD_WINDOW: { WindowLayer* window; @@ -251,6 +201,37 @@ Desktop::MessageReceived(BMessage* message) // #pragma mark - +// SetMasterClipping +void +Desktop::SetMasterClipping(BRegion* clipping) +{ + BRegion update = *clipping; + update.Exclude(&fMasterClipping); + + fMasterClipping = *clipping; + // since parts of the view might have been exposed, + // we need a clipping rebuild + BRegion background; + _RebuildClippingForAllWindows(&background); + _SetBackground(&background); + + fDrawingEngine->FillRegion(&fBackgroundRegion, (rgb_color){ 51, 102, 152, 255 }); + + // trigger redrawing windows + update.Exclude(&fBackgroundRegion); + MarkDirty(&update); +} + +// SetOffset +void +Desktop::SetOffset(int32 x, int32 y) +{ + fXOffset = x; + fYOffset = y; +} + +// #pragma mark - + // AddWindow bool Desktop::AddWindow(WindowLayer* window) @@ -387,17 +368,10 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y) // moved into the dirty region (for now) newDirtyRegion.Include(&window->VisibleRegion()); - if (fDrawingEngine->Lock()) { - fDrawingEngine->CopyRegion(©Region, x, y); - - // in the dirty region, exclude the parts that we - // could move by blitting - copyRegion.OffsetBy(x, y); - newDirtyRegion.Exclude(©Region); - fDrawingEngine->MarkDirty(©Region); - - fDrawingEngine->Unlock(); - } + fDrawingEngine->CopyRegion(©Region, x, y); + + copyRegion.OffsetBy(x, y); + newDirtyRegion.Exclude(©Region); MarkDirty(&newDirtyRegion); _SetBackground(&background); @@ -456,6 +430,8 @@ Desktop::HideWindow(WindowLayer* window) void Desktop::SetWindowHidden(WindowLayer* window, bool hidden) { + // TODO: if in ffm mode, make sure to switch focus + // if appropriate if (LockClipping()) { if (window->IsHidden() != hidden) { @@ -627,14 +603,7 @@ Desktop::_RebuildClippingForAllWindows(BRegion* stillAvailableOnScreen) // each window on the screen will take a portion from that area // figure out what the entire screen area is - if (!fDrawView->Window()) - stillAvailableOnScreen->Set(fDrawView->Bounds()); - else { - if (fDrawView->Window()->Lock()) { - fDrawView->GetClippingRegion(stillAvailableOnScreen); - fDrawView->Window()->Unlock(); - } - } + *stillAvailableOnScreen = fMasterClipping; // set clipping of each window int32 count = CountWindows(); @@ -677,12 +646,6 @@ Desktop::_SetBackground(BRegion* background) dirtyBackground.IntersectWith(background); fBackgroundRegion = *background; if (dirtyBackground.Frame().IsValid()) { - if (fDrawingEngine->Lock()) { - fDrawingEngine->SetHighColor(51, 102, 152); - fDrawingEngine->FillRegion(&dirtyBackground); - fDrawingEngine->MarkDirty(&dirtyBackground); - - fDrawingEngine->Unlock(); - } + fDrawingEngine->FillRegion(&dirtyBackground, (rgb_color){ 51, 102, 152, 255 }); } } diff --git a/src/tests/servers/app/newerClipping/Desktop.h b/src/tests/servers/app/newerClipping/Desktop.h index b59b16dcde..67a8347557 100644 --- a/src/tests/servers/app/newerClipping/Desktop.h +++ b/src/tests/servers/app/newerClipping/Desktop.h @@ -7,8 +7,6 @@ #include #include -#include "DrawingEngine.h" - #define SHOW_GLOBAL_DIRTY_REGION 0 #define SHOW_WINDOW_CONTENT_DIRTY_REGION 0 @@ -20,6 +18,8 @@ # include #endif +class DrawingEngine; +class DrawView; class WindowLayer; class ViewLayer; @@ -34,12 +34,11 @@ enum { class Desktop : public BLooper { public: - Desktop(DrawView* drawView); + Desktop(DrawView* drawView, + DrawingEngine* engine); virtual ~Desktop(); // functions for the DrawView - void Draw(BRect updateRect); - void MouseDown(BPoint where, uint32 buttons, int32 clicks); void MouseUp(BPoint where); @@ -48,6 +47,9 @@ class Desktop : public BLooper { virtual void MessageReceived(BMessage* message); + void SetMasterClipping(BRegion* clipping); + void SetOffset(int32 x, int32 y); + bool AddWindow(WindowLayer* window); bool RemoveWindow(WindowLayer* window); int32 IndexOf(WindowLayer* window) const; @@ -117,6 +119,10 @@ private: #endif BRegion fBackgroundRegion; + BRegion fMasterClipping; + int32 fXOffset; + int32 fYOffset; + DrawView* fDrawView; DrawingEngine* fDrawingEngine; diff --git a/src/tests/servers/app/newerClipping/DrawingEngine.cpp b/src/tests/servers/app/newerClipping/DrawingEngine.cpp deleted file mode 100644 index c4e095d586..0000000000 --- a/src/tests/servers/app/newerClipping/DrawingEngine.cpp +++ /dev/null @@ -1,315 +0,0 @@ - -#include -#include - -#include -#include -#include -#include - -#include "Desktop.h" - -#include "DrawingEngine.h" - -// constructor -DrawingEngine::DrawingEngine(BRect frame, DrawView* drawView) - : BView(frame, "drawing engine", B_FOLLOW_ALL, B_WILL_DRAW), - fDrawView(drawView) -{ -} - -// destructor -DrawingEngine::~DrawingEngine() -{ -} - -// Lock -bool -DrawingEngine::Lock() -{ - return Window()->Lock(); -} - -// Unlock -void -DrawingEngine::Unlock() -{ -#if RUN_WITH_FRAME_BUFFER - Sync(); -#else -// Flush() takes some time, but we -// need to do that, since we draw -// at any time, outside actual updates - Flush(); -#endif - Window()->Unlock(); -} - -// MarkDirty -void -DrawingEngine::MarkDirty(BRegion* region) -{ -#if RUN_WITH_FRAME_BUFFER - BRect frame = region->Frame(); - if (frame.IsValid()) { - BMessage message(MSG_INVALIDATE); - message.AddRect("area", frame); - fDrawView->Looper()->PostMessage(&message, fDrawView); - } -#endif -} - -// MarkDirty -void -DrawingEngine::MarkDirty(BRect rect) -{ -#if RUN_WITH_FRAME_BUFFER - if (rect.IsValid()) { - BMessage message(MSG_INVALIDATE); - message.AddRect("area", rect); - fDrawView->Looper()->PostMessage(&message, fDrawView); - } -#endif -} - -// MarkDirty -void -DrawingEngine::MarkDirty() -{ - if (Lock()) { - Invalidate(); - Unlock(); - } -} - -struct node { - node() - { - pointers = NULL; - } - node(const BRect& r, int32 maxPointers) - { - init(r, maxPointers); - } - ~node() - { - delete [] pointers; - } - - void init(const BRect& r, int32 maxPointers) - { - rect = r; - pointers = new node*[maxPointers]; - in_degree = 0; - next_pointer = 0; - } - - void push(node* node) - { - pointers[next_pointer] = node; - next_pointer++; - } - node* top() - { - return pointers[next_pointer]; - } - node* pop() - { - node* ret = top(); - next_pointer--; - return ret; - } - - BRect rect; - int32 in_degree; - node** pointers; - int32 next_pointer; -}; - -bool -is_left_of(const BRect& a, const BRect& b) -{ - return (a.right < b.left); -} -bool -is_above(const BRect& a, const BRect& b) -{ - return (a.bottom < b.top); -} - -void -DrawingEngine::CopyRegion(BRegion* region, int32 xOffset, int32 yOffset) -{ - int32 count = region->CountRects(); - - // 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. - - while (!inDegreeZeroNodes.empty()) { - node* n = inDegreeZeroNodes.top(); - inDegreeZeroNodes.pop(); - - CopyBits(n->rect, BRect(n->rect).OffsetByCopy(xOffset, yOffset)); - - 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]); - } - } -} - -// constructor -DrawView::DrawView(BRect frame) -#if RUN_WITH_FRAME_BUFFER - : BView(frame, "desktop", B_FOLLOW_ALL, B_WILL_DRAW), -#else - : DrawingEngine(frame, NULL), -#endif - fDesktop(NULL), - -#if RUN_WITH_FRAME_BUFFER - fFrameBuffer(new BBitmap(Bounds(), B_RGB32, true)), - fDrawingEngine(new DrawingEngine(Bounds(), this)) -#else - fDrawingEngine(this) -#endif -{ - SetViewColor(B_TRANSPARENT_COLOR); -#if RUN_WITH_FRAME_BUFFER - if (fFrameBuffer->Lock()) { - fFrameBuffer->AddChild(fDrawingEngine); - fFrameBuffer->Unlock(); - } -#endif -} - -// destructor -DrawView::~DrawView() -{ -#if RUN_WITH_FRAME_BUFFER - delete fFrameBuffer; -#endif -} - -// MessageReceived -void -DrawView::MessageReceived(BMessage* message) -{ - switch (message->what) { - case MSG_INVALIDATE: { - BRect area; - if (message->FindRect("area", &area) == B_OK) { - Invalidate(area); - } - break; - } - default: - BView::MessageReceived(message); - } -} - -// Draw -void -DrawView::Draw(BRect updateRect) -{ -#if RUN_WITH_FRAME_BUFFER - DrawBitmap(fFrameBuffer, updateRect, updateRect); -#else - BMessage message(MSG_DRAW); - message.AddRect("area", updateRect); - fDesktop->PostMessage(&message); -#endif -} - -// MouseDown -void -DrawView::MouseDown(BPoint where) -{ - SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); - - fDesktop->PostMessage(Window()->CurrentMessage()); -} - -// MouseUp -void -DrawView::MouseUp(BPoint where) -{ - fDesktop->PostMessage(Window()->CurrentMessage()); -} - -// MouseMoved -void -DrawView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) -{ - fDesktop->PostMessage(Window()->CurrentMessage()); -} - -// SetDesktop -void -DrawView::SetDesktop(Desktop* desktop) -{ - fDesktop = desktop; -} - - diff --git a/src/tests/servers/app/newerClipping/DrawingEngine.h b/src/tests/servers/app/newerClipping/DrawingEngine.h deleted file mode 100644 index f8cbc3cd5c..0000000000 --- a/src/tests/servers/app/newerClipping/DrawingEngine.h +++ /dev/null @@ -1,68 +0,0 @@ - -#ifndef DRAWING_ENGINE_H -#define DRAWING_ENGINE_H - -#include - -class Desktop; -class DrawView; - -enum { - MSG_INVALIDATE = 'invl', -}; - -class DrawingEngine : public BView { - public: - DrawingEngine(BRect frame, DrawView* drawView); - virtual ~DrawingEngine(); - - bool Lock(); - void Unlock(); - - void CopyRegion(BRegion *region, int32 xOffset, int32 yOffset); - - void MarkDirty(BRegion* region); - void MarkDirty(BRect rect); - void MarkDirty(); - - private: - DrawView* fDrawView; -}; - -#define RUN_WITH_FRAME_BUFFER 0 - - -#if RUN_WITH_FRAME_BUFFER -class DrawView : public BView { -#else -class DrawView : public DrawingEngine { -#endif - - public: - DrawView(BRect frame); - virtual ~DrawView(); - - virtual void MessageReceived(BMessage* message); - - virtual void Draw(BRect updateRect); - - virtual void MouseDown(BPoint where); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 code, - const BMessage* dragMessage); - - void SetDesktop(Desktop* desktop); - DrawingEngine* GetDrawingEngine() const - { return fDrawingEngine; } - - private: - Desktop* fDesktop; - -#if RUN_WITH_FRAME_BUFFER - BBitmap* fFrameBuffer; -#endif - DrawingEngine* fDrawingEngine; -}; - -#endif // DRAWING_ENGINE_H - diff --git a/src/tests/servers/app/newerClipping/ViewLayer.cpp b/src/tests/servers/app/newerClipping/ViewLayer.cpp index e8ba10935e..7aa9087963 100644 --- a/src/tests/servers/app/newerClipping/ViewLayer.cpp +++ b/src/tests/servers/app/newerClipping/ViewLayer.cpp @@ -618,14 +618,8 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, // add the current clipping redraw.IntersectWith(effectiveClipping); - if (drawingEngine->Lock()) { - // fill visible region with white - drawingEngine->SetHighColor(255, 255, 255); - drawingEngine->FillRegion(&redraw); - - drawingEngine->MarkDirty(&redraw); - drawingEngine->Unlock(); - } + // fill visible region with white + drawingEngine->FillRegion(&redraw, (rgb_color){ 255, 255, 255, 255 }); // let children draw if (deep) { @@ -644,28 +638,22 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, void ViewLayer::ClientDraw(DrawingEngine* drawingEngine, BRegion* effectiveClipping) { + BRect b(Bounds()); + b.OffsetTo(0.0, 0.0); + ConvertToTop(&b); + if (drawingEngine->Lock()) { + drawingEngine->ConstrainClipping(effectiveClipping); // draw a frame with the view color - BRect b(Bounds()); - b.OffsetTo(0.0, 0.0); - ConvertToTop(&b); - drawingEngine->PushState(); - drawingEngine->ConstrainClippingRegion(effectiveClipping); - - drawingEngine->SetHighColor(fViewColor); -// drawingEngine->SetDrawingMode(B_OP_BLEND); - drawingEngine->StrokeRect(b); + drawingEngine->StrokeRect(b, fViewColor); b.InsetBy(1, 1); - drawingEngine->StrokeRect(b); + drawingEngine->StrokeRect(b, fViewColor); b.InsetBy(1, 1); - drawingEngine->StrokeRect(b); + drawingEngine->StrokeRect(b, fViewColor); b.InsetBy(1, 1); - drawingEngine->StrokeLine(b.LeftTop(), b.RightBottom()); + drawingEngine->StrokeLine(b.LeftTop(), b.RightBottom(), fViewColor); - drawingEngine->PopState(); - - drawingEngine->MarkDirty(effectiveClipping); drawingEngine->Unlock(); } } diff --git a/src/tests/servers/app/newerClipping/WindowLayer.cpp b/src/tests/servers/app/newerClipping/WindowLayer.cpp index 9089987cd1..fecd493754 100644 --- a/src/tests/servers/app/newerClipping/WindowLayer.cpp +++ b/src/tests/servers/app/newerClipping/WindowLayer.cpp @@ -192,7 +192,7 @@ WindowLayer::GetFullRegion(BRegion* region) const fFrame.right + 4, fFrame.bottom + 4)); // add the title tab region->Include(BRect(fFrame.left - 4, fFrame.top - 20, - (fFrame.left + fFrame.right) / 2, fFrame.top - 5)); + ceilf((fFrame.left + fFrame.right) / 2), fFrame.top - 5)); } // GetBorderRegion @@ -201,7 +201,7 @@ WindowLayer::GetBorderRegion(BRegion* region) { if (!fBorderRegionValid) { fBorderRegion.Set(BRect(fFrame.left - 4, fFrame.top - 20, - (fFrame.left + fFrame.right) / 2, fFrame.top - 5)); + ceilf((fFrame.left + fFrame.right) / 2), fFrame.top - 5)); fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.top - 4, fFrame.right + 4, fFrame.top - 1)); fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.top, @@ -212,21 +212,6 @@ WindowLayer::GetBorderRegion(BRegion* region) fFrame.right - 11, fFrame.bottom + 4)); fBorderRegion.Include(BRect(fFrame.right - 10, fFrame.bottom - 10, fFrame.right + 4, fFrame.bottom + 4)); -/* // TODO: speed up by avoiding "Exclude()" - // start from the frame, extend to include decorator border - fBorderRegion.Set(BRect(fFrame.left - 4, fFrame.top - 4, - fFrame.right + 4, fFrame.bottom + 4)); - - fBorderRegion.Exclude(fFrame); - - // add the title tab - fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.top - 20, - (fFrame.left + fFrame.right) / 2, fFrame.top - 5)); - - // resize handle - // if (B_DOCUMENT_WINDOW_LOOK) - fBorderRegion.Include(BRect(fFrame.right - 10, fFrame.bottom - 10, - fFrame.right, fFrame.bottom));*/ fBorderRegionValid = true; } @@ -680,25 +665,22 @@ WindowLayer::_DrawClientPolygon(int32 token, BPoint polygon[4]) &fContentRegion, false); #endif + layer->ConvertToTop(&polygon[0]); + layer->ConvertToTop(&polygon[1]); + layer->ConvertToTop(&polygon[2]); + layer->ConvertToTop(&polygon[3]); + 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->ConstrainClipping(&effectiveClipping); + +// fDrawingEngine->SetPenSize(3); +// fDrawingEngine->SetDrawingMode(B_OP_BLEND); + fDrawingEngine->StrokeLine(polygon[0], polygon[1], layer->ViewColor()); + fDrawingEngine->StrokeLine(polygon[1], polygon[2], layer->ViewColor()); + fDrawingEngine->StrokeLine(polygon[2], polygon[3], layer->ViewColor()); + fDrawingEngine->StrokeLine(polygon[3], polygon[0], layer->ViewColor()); - fDrawingEngine->PopState(); - fDrawingEngine->MarkDirty(&effectiveClipping); fDrawingEngine->Unlock(); } } @@ -728,57 +710,59 @@ WindowLayer::_DrawBorder() dirtyBorderRegion.IntersectWith(&fDirtyRegion); if (dirtyBorderRegion.CountRects() > 0) { + + rgb_color lowColor; + rgb_color highColor; + if (fFocus) { + lowColor = (rgb_color){ 255, 203, 0, 255 }; + highColor = (rgb_color){ 0, 0, 0, 255 }; + } else { + lowColor = (rgb_color){ 216, 216, 216, 0 }; + highColor = (rgb_color){ 30, 30, 30, 255 }; + } + + fDrawingEngine->FillRegion(&dirtyBorderRegion, lowColor); + + rgb_color light = tint_color(lowColor, B_LIGHTEN_2_TINT); + rgb_color shadow = tint_color(lowColor, B_DARKEN_2_TINT); + if (fDrawingEngine->Lock()) { - fDrawingEngine->ConstrainClippingRegion(&dirtyBorderRegion); + fDrawingEngine->ConstrainClipping(&dirtyBorderRegion); - if (fFocus) { - fDrawingEngine->SetLowColor(255, 203, 0, 255); - fDrawingEngine->SetHighColor(0, 0, 0, 255); - } else { - fDrawingEngine->SetLowColor(216, 216, 216, 0); - fDrawingEngine->SetHighColor(30, 30, 30, 255); - } - rgb_color light = tint_color(fDrawingEngine->LowColor(), B_LIGHTEN_2_TINT); - rgb_color shadow = tint_color(fDrawingEngine->LowColor(), B_DARKEN_2_TINT); - - fDrawingEngine->FillRect(dirtyBorderRegion.Frame(), B_SOLID_LOW); - - fDrawingEngine->DrawString(Name(), BPoint(fFrame.left, fFrame.top - 5)); + fDrawingEngine->DrawString(Name(), BPoint(fFrame.left, fFrame.top - 5), highColor); BRect frame(fFrame); - fDrawingEngine->BeginLineArray(12); frame.InsetBy(-1, -1); - fDrawingEngine->AddLine(BPoint(frame.left, frame.bottom), - BPoint(frame.left, frame.top), shadow); - fDrawingEngine->AddLine(BPoint(frame.left + 1, frame.top), - BPoint(frame.right, frame.top), shadow); - fDrawingEngine->AddLine(BPoint(frame.right, frame.top + 1), - BPoint(frame.right, frame.bottom - 11), light); - fDrawingEngine->AddLine(BPoint(frame.right - 1, frame.bottom - 11), - BPoint(frame.right - 11, frame.bottom - 11), light); - fDrawingEngine->AddLine(BPoint(frame.right - 11, frame.bottom - 10), - BPoint(frame.right - 11, frame.bottom), light); - fDrawingEngine->AddLine(BPoint(frame.right - 12, frame.bottom), - BPoint(frame.left + 1, frame.bottom), light); + fDrawingEngine->StrokeLine(BPoint(frame.left, frame.bottom), + BPoint(frame.left, frame.top), shadow); + fDrawingEngine->StrokeLine(BPoint(frame.left + 1, frame.top), + BPoint(frame.right, frame.top), shadow); + fDrawingEngine->StrokeLine(BPoint(frame.right, frame.top + 1), + BPoint(frame.right, frame.bottom - 11), light); + fDrawingEngine->StrokeLine(BPoint(frame.right - 1, frame.bottom - 11), + BPoint(frame.right - 11, frame.bottom - 11), light); + fDrawingEngine->StrokeLine(BPoint(frame.right - 11, frame.bottom - 10), + BPoint(frame.right - 11, frame.bottom), light); + fDrawingEngine->StrokeLine(BPoint(frame.right - 12, frame.bottom), + BPoint(frame.left + 1, frame.bottom), light); frame.InsetBy(-3, -3); - fDrawingEngine->AddLine(BPoint(frame.left, frame.bottom), - BPoint(frame.left, frame.top - 16), light); - fDrawingEngine->AddLine(BPoint(frame.left + 1, frame.top - 16), - BPoint((frame.left + frame.right) / 2, frame.top - 16), light); - fDrawingEngine->AddLine(BPoint((frame.left + frame.right) / 2, frame.top - 15), - BPoint((frame.left + frame.right) / 2, frame.top), shadow); - fDrawingEngine->AddLine(BPoint((frame.left + frame.right) / 2 + 1, frame.top), - BPoint(frame.left + frame.right, frame.top), light); - fDrawingEngine->AddLine(BPoint(frame.right, frame.top + 1), - BPoint(frame.right, frame.bottom), shadow); - fDrawingEngine->AddLine(BPoint(frame.right, frame.bottom), - BPoint(frame.left + 1, frame.bottom), shadow); - fDrawingEngine->EndLineArray(); + int32 tabRight = ceilf((fFrame.left + fFrame.right) / 2); + fDrawingEngine->StrokeLine(BPoint(frame.left, frame.bottom), + BPoint(frame.left, frame.top - 16), light); + fDrawingEngine->StrokeLine(BPoint(frame.left + 1, frame.top - 16), + BPoint(tabRight, frame.top - 16), light); + fDrawingEngine->StrokeLine(BPoint(tabRight, frame.top - 15), + BPoint(tabRight, frame.top), shadow); + fDrawingEngine->StrokeLine(BPoint(tabRight + 1, frame.top), + BPoint(frame.right, frame.top), light); + fDrawingEngine->StrokeLine(BPoint(frame.right, frame.top + 1), + BPoint(frame.right, frame.bottom), shadow); + fDrawingEngine->StrokeLine(BPoint(frame.right, frame.bottom), + BPoint(frame.left + 1, frame.bottom), shadow); - fDrawingEngine->ConstrainClippingRegion(NULL); - fDrawingEngine->MarkDirty(&dirtyBorderRegion); + fDrawingEngine->ConstrainClipping(NULL); fDrawingEngine->Unlock(); } } diff --git a/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.cpp b/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.cpp new file mode 100644 index 0000000000..4425179977 --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.cpp @@ -0,0 +1,890 @@ +/* + * Copyright 2001-2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + * DarkWyrm + * Stephan Aßmus + */ + +/** Accelerant based HWInterface implementation */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "AccelerantHWInterface.h" +//#include "AccelerantBuffer.h" +//#include "MallocBuffer.h" + +using std::nothrow; + +#define DEBUG_DRIVER_MODULE + +#ifdef DEBUG_DRIVER_MODULE +# include +# define ATRACE(x) printf x +#else +# define ATRACE(x) ; +#endif + +// constructor +AccelerantHWInterface::AccelerantHWInterface() + : //HWInterface(), + fCardFD(-1), + fAccelerantImage(-1), + fAccelerantHook(NULL), + fEngineToken(NULL), + fSyncToken(), + + // required hooks + fAccAcquireEngine(NULL), + fAccReleaseEngine(NULL), + fAccSyncToToken(NULL), + fAccGetModeCount(NULL), + fAccGetModeList(NULL), + fAccGetFrameBufferConfig(NULL), + fAccSetDisplayMode(NULL), + fAccGetDisplayMode(NULL), + fAccGetPixelClockLimits(NULL), + + // optional accelerant hooks + fAccGetTimingConstraints(NULL), + fAccProposeDisplayMode(NULL), + fAccFillRect(NULL), + fAccInvertRect(NULL), + fAccScreenBlit(NULL), + fAccSetCursorShape(NULL), + fAccMoveCursor(NULL), + fAccShowCursor(NULL)//, + + // dpms hooks +/* fAccDPMSCapabilities(NULL), + fAccDPMSMode(NULL), + fAccSetDPMSMode(NULL), + + fModeCount(0), + fModeList(NULL),*/ + +// fBackBuffer(NULL), +// fFrontBuffer(new(nothrow) AccelerantBuffer()) +{ +/* fDisplayMode.virtual_width = 640; + fDisplayMode.virtual_height = 480; + fDisplayMode.space = B_RGB32;*/ + + // NOTE: I have no clue what I'm doing here. +// fSyncToken.counter = 0; +// fSyncToken.engine_id = 0; + memset(&fSyncToken, 0, sizeof(sync_token)); +} + +// destructor +AccelerantHWInterface::~AccelerantHWInterface() +{ +// delete fBackBuffer; +// delete fFrontBuffer; +// delete[] fModeList; +} + + +/*! + \brief Opens the first available graphics device and initializes it + \return B_OK on success or an appropriate error message on failure. +*/ +status_t +AccelerantHWInterface::Initialize() +{ + status_t ret = B_OK;//HWInterface::Initialize(); + if (ret >= B_OK) { + for (int32 i = 1; fCardFD != B_ENTRY_NOT_FOUND; i++) { + fCardFD = _OpenGraphicsDevice(i); + if (fCardFD < 0) { + ATRACE(("Failed to open graphics device\n")); + continue; + } + + if (_OpenAccelerant(fCardFD) == B_OK) + break; + + close(fCardFD); + // _OpenAccelerant() failed, try to open next graphics card + } + + return fCardFD >= 0 ? B_OK : fCardFD; + } + return ret; +} + + +/*! + \brief Opens a graphics device for read-write access + \param deviceNumber Number identifying which graphics card to open (1 for first card) + \return The file descriptor for the opened graphics device + + The deviceNumber is relative to the number of graphics devices that can be successfully + opened. One represents the first card that can be successfully opened (not necessarily + the first one listed in the directory). + Graphics drivers must be able to be opened more than once, so we really get + the first working entry. +*/ +int +AccelerantHWInterface::_OpenGraphicsDevice(int deviceNumber) +{ + DIR *directory = opendir("/dev/graphics"); + if (!directory) + return -1; + + // ToDo: the former R5 "stub" driver is called "vesa" under Haiku; however, + // we do not need to avoid this driver this way when is has been ported + // to the new driver architecture - the special case here can then be + // removed. + int count = 0; + struct dirent *entry; + int current_card_fd = -1; + char path[PATH_MAX]; + while (count < deviceNumber && (entry = readdir(directory)) != NULL) { + if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") || + !strcmp(entry->d_name, "stub") || !strcmp(entry->d_name, "vesa")) + continue; + + if (current_card_fd >= 0) { + close(current_card_fd); + current_card_fd = -1; + } + + sprintf(path, "/dev/graphics/%s", entry->d_name); + current_card_fd = open(path, B_READ_WRITE); + if (current_card_fd >= 0) + count++; + } + + // Open VESA driver if we were not able to get a better one + if (count < deviceNumber) { + if (deviceNumber == 1) { + sprintf(path, "/dev/graphics/vesa"); + current_card_fd = open(path, B_READ_WRITE); + } else { + close(current_card_fd); + current_card_fd = B_ENTRY_NOT_FOUND; + } + } + + fCardNameInDevFS = entry->d_name; + + return current_card_fd; +} + + +status_t +AccelerantHWInterface::_OpenAccelerant(int device) +{ + char signature[1024]; + if (ioctl(device, B_GET_ACCELERANT_SIGNATURE, + &signature, sizeof(signature)) != B_OK) + return B_ERROR; + + ATRACE(("accelerant signature is: %s\n", signature)); + + struct stat accelerant_stat; + const static directory_which dirs[] = { + B_USER_ADDONS_DIRECTORY, + B_COMMON_ADDONS_DIRECTORY, + B_BEOS_ADDONS_DIRECTORY + }; + + fAccelerantImage = -1; + + for (int32 i = 0; i < 3; i++) { + char path[PATH_MAX]; + if (find_directory(dirs[i], -1, false, path, PATH_MAX) != B_OK) + continue; + + strcat(path, "/accelerants/"); + strcat(path, signature); + if (stat(path, &accelerant_stat) != 0) + continue; + + fAccelerantImage = load_add_on(path); + if (fAccelerantImage >= 0) { + if (get_image_symbol(fAccelerantImage, B_ACCELERANT_ENTRY_POINT, + B_SYMBOL_TYPE_ANY, (void**)(&fAccelerantHook)) != B_OK ) { + ATRACE(("unable to get B_ACCELERANT_ENTRY_POINT\n")); + unload_add_on(fAccelerantImage); + fAccelerantImage = -1; + return B_ERROR; + } + + + accelerant_clone_info_size cloneInfoSize; + cloneInfoSize = (accelerant_clone_info_size)fAccelerantHook(B_ACCELERANT_CLONE_INFO_SIZE, NULL); + if (!cloneInfoSize) { + ATRACE(("unable to get B_ACCELERANT_CLONE_INFO_SIZE (%s)\n", path)); + unload_add_on(fAccelerantImage); + fAccelerantImage = -1; + return B_ERROR; + } + + ssize_t cloneSize = cloneInfoSize(); + void* cloneInfoData = malloc(cloneSize); + +// get_accelerant_clone_info getCloneInfo; +// getCloneInfo = (get_accelerant_clone_info)fAccelerantHook(B_GET_ACCELERANT_CLONE_INFO, NULL); +// if (!getCloneInfo) { +// ATRACE(("unable to get B_GET_ACCELERANT_CLONE_INFO (%s)\n", path)); +// unload_add_on(fAccelerantImage); +// fAccelerantImage = -1; +// return B_ERROR; +// } +// printf("getCloneInfo: %p\n", getCloneInfo); +// +// getCloneInfo(cloneInfoData); +// TODO: this is what works for the ATI Radeon driver... +sprintf((char*)cloneInfoData, "graphics/%s", fCardNameInDevFS.String()); + + clone_accelerant cloneAccelerant; + cloneAccelerant = (clone_accelerant)fAccelerantHook(B_CLONE_ACCELERANT, NULL); + if (!cloneAccelerant) { + ATRACE(("unable to get B_CLONE_ACCELERANT\n")); + unload_add_on(fAccelerantImage); + fAccelerantImage = -1; + return B_ERROR; + } + status_t ret = cloneAccelerant(cloneInfoData); + if (ret != B_OK) { + ATRACE(("Cloning accelerant unsuccessful: %s\n", strerror(ret))); + unload_add_on(fAccelerantImage); + fAccelerantImage = -1; + return B_ERROR; + } + + break; + } + } + + if (fAccelerantImage < B_OK) + return B_ERROR; + + if (_SetupDefaultHooks() != B_OK) { + ATRACE(("cannot setup default hooks\n")); + + uninit_accelerant uninitAccelerant = (uninit_accelerant) + fAccelerantHook(B_UNINIT_ACCELERANT, NULL); + if (uninitAccelerant != NULL) + uninitAccelerant(); + + unload_add_on(fAccelerantImage); + return B_ERROR; + } + + return B_OK; +} + + +status_t +AccelerantHWInterface::_SetupDefaultHooks() +{ + // required + fAccAcquireEngine = (acquire_engine)fAccelerantHook(B_ACQUIRE_ENGINE, NULL); + fAccReleaseEngine = (release_engine)fAccelerantHook(B_RELEASE_ENGINE, NULL); + fAccSyncToToken = (sync_to_token)fAccelerantHook(B_SYNC_TO_TOKEN, NULL); + fAccGetModeCount = (accelerant_mode_count)fAccelerantHook(B_ACCELERANT_MODE_COUNT, NULL); + fAccGetModeList = (get_mode_list)fAccelerantHook(B_GET_MODE_LIST, NULL); + fAccGetFrameBufferConfig = (get_frame_buffer_config)fAccelerantHook(B_GET_FRAME_BUFFER_CONFIG, NULL); + fAccSetDisplayMode = (set_display_mode)fAccelerantHook(B_SET_DISPLAY_MODE, NULL); + fAccGetDisplayMode = (get_display_mode)fAccelerantHook(B_GET_DISPLAY_MODE, NULL); + fAccGetPixelClockLimits = (get_pixel_clock_limits)fAccelerantHook(B_GET_PIXEL_CLOCK_LIMITS, NULL); + + if (!fAccAcquireEngine || !fAccReleaseEngine || !fAccGetFrameBufferConfig + || !fAccGetModeCount || !fAccGetModeList || !fAccSetDisplayMode + || !fAccGetDisplayMode || !fAccGetPixelClockLimits) { + return B_ERROR; + } + + // optional + fAccGetTimingConstraints = (get_timing_constraints)fAccelerantHook(B_GET_TIMING_CONSTRAINTS, NULL); + fAccProposeDisplayMode = (propose_display_mode)fAccelerantHook(B_PROPOSE_DISPLAY_MODE, NULL); + + // cursor + fAccSetCursorShape = (set_cursor_shape)fAccelerantHook(B_SET_CURSOR_SHAPE, NULL); + fAccMoveCursor = (move_cursor)fAccelerantHook(B_MOVE_CURSOR, NULL); + fAccShowCursor = (show_cursor)fAccelerantHook(B_SHOW_CURSOR, NULL); + + // dpms +// fAccDPMSCapabilities = (dpms_capabilities)fAccelerantHook(B_DPMS_CAPABILITIES, NULL); +// fAccDPMSMode = (dpms_mode)fAccelerantHook(B_DPMS_MODE, NULL); +// fAccSetDPMSMode = (set_dpms_mode)fAccelerantHook(B_SET_DPMS_MODE, NULL); + + // update acceleration hooks + // TODO: would actually have to pass a valid display_mode! + fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, NULL); + fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE, NULL); + fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, NULL); + + return B_OK; +} + +// Shutdown +status_t +AccelerantHWInterface::Shutdown() +{ + if (fAccelerantHook) { + uninit_accelerant UninitAccelerant = (uninit_accelerant)fAccelerantHook(B_UNINIT_ACCELERANT, NULL); + if (UninitAccelerant) + UninitAccelerant(); + } + + if (fAccelerantImage >= 0) + unload_add_on(fAccelerantImage); + + if (fCardFD >= 0) + close(fCardFD); + + return B_OK; +} +/* +// SetMode +status_t +AccelerantHWInterface::SetMode(const display_mode &mode) +{ + AutoWriteLocker _(this); + // TODO: There are places this function can fail, + // maybe it needs to roll back changes in case of an + // error. + + // prevent from doing the unnecessary + if (fModeCount > 0 && fBackBuffer && fFrontBuffer + && fDisplayMode == mode) { + // TODO: better comparison of display modes + return B_OK; + } + + // just try to set the mode - we let the graphics driver + // approve or deny the request, as it should know best + + fDisplayMode = mode; + + if (fAccSetDisplayMode(&fDisplayMode) != B_OK) { + ATRACE(("setting display mode failed\n")); + fAccGetDisplayMode(&fDisplayMode); + // We just keep the current mode and continue. + // Note, on startup, this may be different from + // what we think is the current display mode + } + + // update frontbuffer + fFrontBuffer->SetDisplayMode(fDisplayMode); + if (_UpdateFrameBufferConfig() != B_OK) + return B_ERROR; + + // Update the frame buffer used by the on-screen KDL +#ifdef __HAIKU__ + uint32 depth = (fFrameBufferConfig.bytes_per_row / fDisplayMode.virtual_width) << 3; + if (fDisplayMode.space == B_RGB15) + depth = 15; + + _kern_frame_buffer_update(fFrameBufferConfig.frame_buffer, + fDisplayMode.virtual_width, fDisplayMode.virtual_height, + depth, fFrameBufferConfig.bytes_per_row); +#endif + + // update backbuffer if neccessary + if (!fBackBuffer || fBackBuffer->Width() != fDisplayMode.virtual_width + || fBackBuffer->Height() != fDisplayMode.virtual_height) { + // NOTE: backbuffer is always B_RGBA32, this simplifies the + // drawing backend implementation tremendously for the time + // being. The color space conversion is handled in CopyBackToFront() + + delete fBackBuffer; + fBackBuffer = NULL; + + // TODO: Above not true anymore for single buffered mode!!! + // -> fall back to double buffer for fDisplayMode.space != B_RGB32 + // as intermediate solution... + bool doubleBuffered = HWInterface::IsDoubleBuffered(); + if ((color_space)fDisplayMode.space != B_RGB32 && + (color_space)fDisplayMode.space != B_RGBA32) + doubleBuffered = true; + + if (doubleBuffered) { + fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width, + fDisplayMode.virtual_height); + + status_t ret = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY; + if (ret < B_OK) { + delete fBackBuffer; + fBackBuffer = NULL; + return ret; + } + // clear out backbuffer, alpha is 255 this way + memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength()); + } + } + + // update acceleration hooks + fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, (void *)&fDisplayMode); + fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE, + (void *)&fDisplayMode); + fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, + (void *)&fDisplayMode); + + return B_OK; +} + + +void +AccelerantHWInterface::GetMode(display_mode *mode) +{ + if (mode && ReadLock()) { + *mode = fDisplayMode; + ReadUnlock(); + } +} + + +status_t +AccelerantHWInterface::_UpdateModeList() +{ + fModeCount = fAccGetModeCount(); + if (fModeCount <= 0) + return B_ERROR; + + delete[] fModeList; + fModeList = new(nothrow) display_mode[fModeCount]; + if (!fModeList) + return B_NO_MEMORY; + + if (fAccGetModeList(fModeList) != B_OK) { + ATRACE(("unable to get mode list\n")); + return B_ERROR; + } + + return B_OK; +} + + +status_t +AccelerantHWInterface::_UpdateFrameBufferConfig() +{ + if (fAccGetFrameBufferConfig(&fFrameBufferConfig) != B_OK) { + ATRACE(("unable to get frame buffer config\n")); + return B_ERROR; + } + + fFrontBuffer->SetFrameBufferConfig(fFrameBufferConfig); + return B_OK; +} + + +status_t +AccelerantHWInterface::GetDeviceInfo(accelerant_device_info *info) +{ + get_accelerant_device_info GetAccelerantDeviceInfo = (get_accelerant_device_info)fAccelerantHook(B_GET_ACCELERANT_DEVICE_INFO, NULL); + if (!GetAccelerantDeviceInfo) { + ATRACE(("No B_GET_ACCELERANT_DEVICE_INFO hook found\n")); + return B_UNSUPPORTED; + } + + return GetAccelerantDeviceInfo(info); +} + + +status_t +AccelerantHWInterface::GetFrameBufferConfig(frame_buffer_config& config) +{ + config = fFrameBufferConfig; + return B_OK; +} + + +status_t +AccelerantHWInterface::GetModeList(display_mode** modes, uint32 *count) +{ + AutoReadLocker _(this); + + if (!count || !modes) + return B_BAD_VALUE; + + status_t ret = fModeList ? B_OK : _UpdateModeList(); + + if (ret >= B_OK) { + *modes = new(nothrow) display_mode[fModeCount]; + if (*modes) { + *count = fModeCount; + memcpy(*modes, fModeList, sizeof(display_mode) * fModeCount); + } else { + *count = 0; + ret = B_NO_MEMORY; + } + } + return ret; +} + +status_t +AccelerantHWInterface::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high) +{ + AutoReadLocker _(this); + + if (!mode || !low || !high) + return B_BAD_VALUE; + + return fAccGetPixelClockLimits(mode, low, high); +} + +status_t +AccelerantHWInterface::GetTimingConstraints(display_timing_constraints *dtc) +{ + AutoReadLocker _(this); + + if (!dtc) + return B_BAD_VALUE; + + if (fAccGetTimingConstraints) + return fAccGetTimingConstraints(dtc); + + return B_UNSUPPORTED; +} + +status_t +AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode *low, const display_mode *high) +{ + AutoReadLocker _(this); + + if (!candidate || !low || !high) + return B_BAD_VALUE; + + if (!fAccProposeDisplayMode) + return B_UNSUPPORTED; + + // avoid const issues + display_mode this_high, this_low; + this_high = *high; + this_low = *low; + + return fAccProposeDisplayMode(candidate, &this_low, &this_high); +} + +// RetraceSemaphore +sem_id +AccelerantHWInterface::RetraceSemaphore() +{ + accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL); + if (!AccelerantRetraceSemaphore) + return B_UNSUPPORTED; + + return AccelerantRetraceSemaphore(); +} + +// WaitForRetrace +status_t +AccelerantHWInterface::WaitForRetrace(bigtime_t timeout) +{ + AutoReadLocker _(this); + + accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL); + if (!AccelerantRetraceSemaphore) + return B_UNSUPPORTED; + + sem_id sem = AccelerantRetraceSemaphore(); + if (sem < 0) + return B_ERROR; + + return acquire_sem_etc(sem, 1, B_RELATIVE_TIMEOUT, timeout); +} + +// SetDPMSMode +status_t +AccelerantHWInterface::SetDPMSMode(const uint32 &state) +{ + AutoWriteLocker _(this); + + if (!fAccSetDPMSMode) + return B_UNSUPPORTED; + + return fAccSetDPMSMode(state); +} + +// DPMSMode +uint32 +AccelerantHWInterface::DPMSMode() +{ + AutoReadLocker _(this); + + if (!fAccDPMSMode) + return B_UNSUPPORTED; + + return fAccDPMSMode(); +} + +// DPMSCapabilities +uint32 +AccelerantHWInterface::DPMSCapabilities() +{ + AutoReadLocker _(this); + + if (!fAccDPMSCapabilities) + return B_UNSUPPORTED; + + return fAccDPMSCapabilities(); +} +*/ +// AvailableHardwareAcceleration +uint32 +AccelerantHWInterface::AvailableHWAcceleration() const +{ + uint32 flags = 0; + +/* if (!IsDoubleBuffered()) { + if (fAccScreenBlit) + flags |= HW_ACC_COPY_REGION; + if (fAccFillRect) + flags |= HW_ACC_FILL_REGION; + if (fAccInvertRect) + flags |= HW_ACC_INVERT_REGION; + }*/ + + return flags; +} + +// CopyRegion +void +AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList, + uint32 count, int32 xOffset, int32 yOffset) +{ + if (fAccScreenBlit && fAccAcquireEngine) { + if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) { + + // convert the rects + blit_params* params = new blit_params[count]; + for (uint32 i = 0; i < count; i++) { + params[i].src_left = (uint16)sortedRectList[i].left; + params[i].src_top = (uint16)sortedRectList[i].top; + + params[i].dest_left = (uint16)sortedRectList[i].left + xOffset; + params[i].dest_top = (uint16)sortedRectList[i].top + yOffset; + + // NOTE: width and height are expressed as distance, not pixel count! + params[i].width = (uint16)(sortedRectList[i].right - sortedRectList[i].left); + params[i].height = (uint16)(sortedRectList[i].bottom - sortedRectList[i].top); + } + + // go + fAccScreenBlit(fEngineToken, params, count); + + // done + if (fAccReleaseEngine) + fAccReleaseEngine(fEngineToken, &fSyncToken); + + // sync + if (fAccSyncToToken) + fAccSyncToToken(&fSyncToken); + + delete[] params; + } + } +} + +// FillRegion +void +AccelerantHWInterface::FillRegion(/*const*/ BRegion& region, const rgb_color& color) +{ + if (fAccFillRect && fAccAcquireEngine) { + if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) { + + // convert the region + uint32 count; + fill_rect_params* fillParams; + _RegionToRectParams(®ion, &fillParams, &count); + + // go + fAccFillRect(fEngineToken, _NativeColor(color), fillParams, count); + + // done + if (fAccReleaseEngine) + fAccReleaseEngine(fEngineToken, &fSyncToken); + + // sync + if (fAccSyncToToken) + fAccSyncToToken(&fSyncToken); + + delete[] fillParams; + } + } +} + +// InvertRegion +void +AccelerantHWInterface::InvertRegion(/*const*/ BRegion& region) +{ + if (fAccInvertRect && fAccAcquireEngine) { + if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) { + + // convert the region + uint32 count; + fill_rect_params* fillParams; + _RegionToRectParams(®ion, &fillParams, &count); + + // go + fAccInvertRect(fEngineToken, fillParams, count); + + // done + if (fAccReleaseEngine) + fAccReleaseEngine(fEngineToken, &fSyncToken); + + // sync + if (fAccSyncToToken) + fAccSyncToToken(&fSyncToken); + + delete[] fillParams; + } else { + fprintf(stderr, "AcquireEngine failed!\n"); + } + } else { + fprintf(stderr, "AccelerantHWInterface::InvertRegion() called, but hook not available!\n"); + } +} +/* +// SetCursor +void +AccelerantHWInterface::SetCursor(ServerCursor* cursor) +{ + HWInterface::SetCursor(cursor); +// if (WriteLock()) { + // 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(); +// } +} + +// SetCursorVisible +void +AccelerantHWInterface::SetCursorVisible(bool visible) +{ + HWInterface::SetCursorVisible(visible); +// if (WriteLock()) { + // TODO: update graphics hardware +// WriteUnlock(); +// } +} + +// MoveCursorTo +void +AccelerantHWInterface::MoveCursorTo(const float& x, const float& y) +{ + HWInterface::MoveCursorTo(x, y); +// if (WriteLock()) { + // TODO: update graphics hardware +// WriteUnlock(); +// } +} + +// FrontBuffer +RenderingBuffer * +AccelerantHWInterface::FrontBuffer() const +{ + if (!fModeList) + return NULL; + + return fFrontBuffer; +} + +// BackBuffer +RenderingBuffer * +AccelerantHWInterface::BackBuffer() const +{ + if (!fModeList) + return NULL; + + return fBackBuffer; +} + +// IsDoubleBuffered +bool +AccelerantHWInterface::IsDoubleBuffered() const +{ + if (fModeList) + return fBackBuffer != NULL; + + return HWInterface::IsDoubleBuffered(); +} + +// _DrawCursor +void +AccelerantHWInterface::_DrawCursor(BRect area) const +{ + // use the default implementation for now, + // until we have a hardware cursor + HWInterface::_DrawCursor(area); + // TODO: this would only be called, if we don't have + // a hardware cursor for some reason +} +*/ +// _RegionToRectParams +void +AccelerantHWInterface::_RegionToRectParams(/*const*/ BRegion* region, + fill_rect_params** params, + uint32* count) const +{ + *count = region->CountRects(); + *params = new fill_rect_params[*count]; + + for (uint32 i = 0; i < *count; i++) { + clipping_rect r = region->RectAtInt(i); + (*params)[i].left = (uint16)r.left; + (*params)[i].top = (uint16)r.top; + (*params)[i].right = (uint16)r.right; + (*params)[i].bottom = (uint16)r.bottom; + } +} + +// _NativeColor +uint32 +AccelerantHWInterface::_NativeColor(const rgb_color& c) const +{ + // NOTE: This functions looks somehow suspicios to me. + // It assumes that all graphics cards have the same native endianess, no? +/* switch (fDisplayMode.space) { + case B_CMAP8: + case B_GRAY8: + return color.GetColor8(); + + case B_RGB15_BIG: + case B_RGBA15_BIG: + case B_RGB15_LITTLE: + case B_RGBA15_LITTLE: + return color.GetColor15(); + + case B_RGB16_BIG: + case B_RGB16_LITTLE: + return color.GetColor16(); + + case B_RGB32_BIG: + case B_RGBA32_BIG: + case B_RGB32_LITTLE: + case B_RGBA32_LITTLE: { + rgb_color c = color.GetColor32(); + uint32 native = (c.alpha << 24) | + (c.red << 16) | + (c.green << 8) | + (c.blue); + return native; + } + } + return 0;*/ + uint32 native = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue); + return native; +} diff --git a/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.h b/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.h new file mode 100644 index 0000000000..5ae442475d --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.h @@ -0,0 +1,134 @@ +/* + * Copyright 2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + * Stephan Aßmus + */ +#ifndef ACCELERANT_HW_INTERFACE_H +#define ACCELERANT_HW_INTERFACE_H + + +#include + +#include +#include +#include +#include + +//class MallocBuffer; +//class AccelerantBuffer; + + +class AccelerantHWInterface : public BLocker/* : public HWInterface*/ { +public: + AccelerantHWInterface(); + virtual ~AccelerantHWInterface(); + + virtual status_t Initialize(); + virtual status_t Shutdown(); + +/* virtual status_t SetMode(const display_mode &mode); + virtual void GetMode(display_mode *mode); + + virtual status_t GetDeviceInfo(accelerant_device_info *info); + virtual status_t GetFrameBufferConfig(frame_buffer_config& config); + + virtual status_t GetModeList(display_mode **mode_list, + uint32 *count); + virtual status_t GetPixelClockLimits(display_mode *mode, + uint32 *low, uint32 *high); + virtual status_t GetTimingConstraints(display_timing_constraints *dtc); + virtual status_t ProposeMode(display_mode *candidate, + const display_mode *low, + const display_mode *high); + + virtual sem_id RetraceSemaphore(); + virtual status_t WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT); + + virtual status_t SetDPMSMode(const uint32 &state); + virtual uint32 DPMSMode(); + virtual uint32 DPMSCapabilities();*/ + + // query for available hardware accleration and perform it + virtual uint32 AvailableHWAcceleration() const; + + virtual void CopyRegion(const clipping_rect* sortedRectList, + uint32 count, + int32 xOffset, int32 yOffset); + virtual void FillRegion(/*const*/ BRegion& region, + const rgb_color& color); + virtual void InvertRegion(/*const*/ BRegion& region); + + // cursor handling +/*virtual void SetCursor(ServerCursor* cursor); +virtual void SetCursorVisible(bool visible); +virtual void MoveCursorTo(const float& x, + const float& y);*/ + + // frame buffer access +//virtual RenderingBuffer* FrontBuffer() const; +//virtual RenderingBuffer* BackBuffer() const; +//virtual bool IsDoubleBuffered() const; + +protected: +//virtual void _DrawCursor(BRect area) const; + +private: + int _OpenGraphicsDevice(int deviceNumber); + status_t _OpenAccelerant(int device); + status_t _SetupDefaultHooks(); + status_t _UpdateModeList(); + status_t _UpdateFrameBufferConfig(); + void _RegionToRectParams(/*const*/ BRegion* region, + fill_rect_params** params, + uint32* count) const; + uint32 _NativeColor(const rgb_color& color) const; + + int fCardFD; + image_id fAccelerantImage; + GetAccelerantHook fAccelerantHook; + engine_token *fEngineToken; + sync_token fSyncToken; + + // required hooks - guaranteed to be valid + acquire_engine fAccAcquireEngine; + release_engine fAccReleaseEngine; + sync_to_token fAccSyncToToken; + accelerant_mode_count fAccGetModeCount; + get_mode_list fAccGetModeList; + get_frame_buffer_config fAccGetFrameBufferConfig; + set_display_mode fAccSetDisplayMode; + get_display_mode fAccGetDisplayMode; + get_pixel_clock_limits fAccGetPixelClockLimits; + + // optional accelerant hooks + get_timing_constraints fAccGetTimingConstraints; + propose_display_mode fAccProposeDisplayMode; + fill_rectangle fAccFillRect; + invert_rectangle fAccInvertRect; + screen_to_screen_blit fAccScreenBlit; + set_cursor_shape fAccSetCursorShape; + move_cursor fAccMoveCursor; + show_cursor fAccShowCursor; + + BString fCardNameInDevFS; + // dpms hooks +/* dpms_capabilities fAccDPMSCapabilities; + dpms_mode fAccDPMSMode; + set_dpms_mode fAccSetDPMSMode; + + frame_buffer_config fFrameBufferConfig; + int fModeCount; + display_mode *fModeList;*/ + + +// MallocBuffer *fBackBuffer; +// AccelerantBuffer *fFrontBuffer; + + +// display_mode fDisplayMode; +}; + +#endif // ACCELERANT_HW_INTERFACE_H diff --git a/src/tests/servers/app/newerClipping/drawing/DirectWindowBuffer.cpp b/src/tests/servers/app/newerClipping/drawing/DirectWindowBuffer.cpp new file mode 100644 index 0000000000..7e31e80ced --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/DirectWindowBuffer.cpp @@ -0,0 +1,94 @@ +#include + +#include "DirectWindowBuffer.h" + +// constructor +DirectWindowBuffer::DirectWindowBuffer() + : fBits(NULL), + fWidth(0), + fHeight(0), + fBytesPerRow(0), + fFormat(B_NO_COLOR_SPACE), + fWindowClipping() +{ +} + +// destructor +DirectWindowBuffer::~DirectWindowBuffer() +{ +} + +// InitCheck +status_t +DirectWindowBuffer::InitCheck() const +{ + if (fBits) + return B_OK; + + return B_NO_INIT; +} + +// ColorSpace +color_space +DirectWindowBuffer::ColorSpace() const +{ + return fFormat; +} + +// Bits +void* +DirectWindowBuffer::Bits() const +{ + return fBits; +} + +// BytesPerRow +uint32 +DirectWindowBuffer::BytesPerRow() const +{ + return fBytesPerRow; +} + +// Width +uint32 +DirectWindowBuffer::Width() const +{ + return fWidth; +} + +// Height +uint32 +DirectWindowBuffer::Height() const +{ + return fHeight; +} + +// Set +void +DirectWindowBuffer::SetTo(direct_buffer_info* info) +{ + fWindowClipping.MakeEmpty(); + + if (info) { + int32 xOffset = info->window_bounds.left; + int32 yOffset = info->window_bounds.top; + // Get clipping information + for (int32 i = 0; i < info->clip_list_count; i++) { + fWindowClipping.Include(info->clip_list[i]); + } + fBytesPerRow = info->bytes_per_row; + fBits = (void*)info->bits; + fFormat = info->pixel_format; + // fBounds = info->window_bounds; + // fDirty = true; + fWidth = info->window_bounds.right - info->window_bounds.left + 1; + fHeight = info->window_bounds.bottom - info->window_bounds.top + 1; + } else { + fBits = NULL; + fWidth = 0; + fHeight = 0; + fBytesPerRow = 0; + fFormat = B_NO_COLOR_SPACE; + } +} + diff --git a/src/tests/servers/app/newerClipping/drawing/DirectWindowBuffer.h b/src/tests/servers/app/newerClipping/drawing/DirectWindowBuffer.h new file mode 100644 index 0000000000..e7b8a1882c --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/DirectWindowBuffer.h @@ -0,0 +1,35 @@ +#ifndef DIRECT_WINDOW_BUFFER_H +#define DIRECT_WINDOW_BUFFER_H + +#include "RenderingBuffer.h" + +struct direct_buffer_info; + +class DirectWindowBuffer : public RenderingBuffer { + public: + DirectWindowBuffer(); + virtual ~DirectWindowBuffer(); + + virtual status_t InitCheck() const; + + virtual color_space ColorSpace() const; + virtual void* Bits() const; + virtual uint32 BytesPerRow() const; + virtual uint32 Width() const; + virtual uint32 Height() const; + + void SetTo(direct_buffer_info* info); + + BRegion& WindowClipping() + { return fWindowClipping; } + private: + void* fBits; + uint32 fWidth; + uint32 fHeight; + uint32 fBytesPerRow; + color_space fFormat; + + BRegion fWindowClipping; +}; + +#endif // DIRECT_WINDOW_BUFFER_H diff --git a/src/tests/servers/app/newerClipping/drawing/DrawView.cpp b/src/tests/servers/app/newerClipping/drawing/DrawView.cpp new file mode 100644 index 0000000000..8263feb2fa --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/DrawView.cpp @@ -0,0 +1,53 @@ + +#include + +#include + +#include "Desktop.h" + +#include "DrawView.h" + +// constructor +DrawView::DrawView(BRect frame) + : BView(frame, "desktop", B_FOLLOW_ALL, 0), + fDesktop(NULL) +{ + SetViewColor(B_TRANSPARENT_COLOR); +} + +// destructor +DrawView::~DrawView() +{ +} + +// MouseDown +void +DrawView::MouseDown(BPoint where) +{ + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + + fDesktop->PostMessage(Window()->CurrentMessage()); +} + +// MouseUp +void +DrawView::MouseUp(BPoint where) +{ + fDesktop->PostMessage(Window()->CurrentMessage()); +} + +// MouseMoved +void +DrawView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) +{ + fDesktop->PostMessage(Window()->CurrentMessage()); +} + +// SetDesktop +void +DrawView::SetDesktop(Desktop* desktop) +{ + fDesktop = desktop; +} + + diff --git a/src/tests/servers/app/newerClipping/drawing/DrawView.h b/src/tests/servers/app/newerClipping/drawing/DrawView.h new file mode 100644 index 0000000000..0099d9cddf --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/DrawView.h @@ -0,0 +1,26 @@ + +#ifndef DRAW_VIEW_H +#define DRAW_VIEW_H + +#include + +class Desktop; + +class DrawView : public BView { + public: + DrawView(BRect frame); + virtual ~DrawView(); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 code, + const BMessage* dragMessage); + + void SetDesktop(Desktop* desktop); + + private: + Desktop* fDesktop; +}; + +#endif // DRAW_VIEW_H + diff --git a/src/tests/servers/app/newerClipping/drawing/DrawingEngine.cpp b/src/tests/servers/app/newerClipping/drawing/DrawingEngine.cpp new file mode 100644 index 0000000000..a346ade9b2 --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/DrawingEngine.cpp @@ -0,0 +1,308 @@ + +#include +#include + +#include + +#include "AccelerantHWInterface.h" +#include "DirectWindowBuffer.h" + +#include "DrawingEngine.h" + +// constructor +DrawingEngine::DrawingEngine(AccelerantHWInterface* interface, + DirectWindowBuffer* buffer) + : fHWInterface(interface), + fBuffer(buffer), + fCurrentClipping() +{ +} + +// destructor +DrawingEngine::~DrawingEngine() +{ +} + +// Lock +bool +DrawingEngine::Lock() +{ + return fHWInterface->Lock(); +} + +// Unlock +void +DrawingEngine::Unlock() +{ + fHWInterface->Unlock(); +} + +// ConstrainClipping +void +DrawingEngine::ConstrainClipping(BRegion* region) +{ + if (region) + fCurrentClipping = *region; + else + fCurrentClipping.MakeEmpty(); +} + +// StraightLine +bool +DrawingEngine::StraightLine(BPoint a, BPoint b, const rgb_color& c) +{ + uint8* dst = (uint8*)fBuffer->Bits(); + uint32 bpr = fBuffer->BytesPerRow(); + + if (dst && fCurrentClipping.Frame().IsValid()) { + + int32 clipBoxCount = fCurrentClipping.CountRects(); + + uint32 color; + color = (255 << 24) | (c.red << 16) | (c.green << 8) | (c.blue); + + if (a.x == b.x) { + // vertical + int32 x = (int32)a.x; + dst += x * 4; + int32 y1 = (int32)min_c(a.y, b.y); + int32 y2 = (int32)max_c(a.y, b.y); + // draw a line, iterate over clipping boxes + for (int32 i = 0; i < clipBoxCount; i++) { + clipping_rect rect = fCurrentClipping.RectAtInt(i); + + if (rect.left <= x && + rect.right >= x) { + int32 i = max_c(rect.top, y1); + int32 end = min_c(rect.bottom, y2); + uint8* handle = dst + i * bpr; + for (; i <= end; i++) { + *(uint32*)handle = color; + handle += bpr; + } + } + } + + return true; + + } else if (a.y == b.y) { + // horizontal + int32 y = (int32)a.y; + dst += y * bpr; + int32 x1 = (int32)min_c(a.x, b.x); + int32 x2 = (int32)max_c(a.x, b.x); + // draw a line, iterate over clipping boxes + for (int32 i = 0; i < clipBoxCount; i++) { + clipping_rect rect = fCurrentClipping.RectAtInt(i); + + if (rect.top <= y && + rect.bottom >= y) { + int32 i = max_c(rect.left, x1); + int32 end = min_c(rect.right, x2); + uint32* handle = (uint32*)(dst + i * 4); + for (; i <= end; i++) { + *handle++ = color; + } + } + } + + return true; + } + } + return false; +} + +// StrokeLine +void +DrawingEngine::StrokeLine(BPoint a, BPoint b, const rgb_color& color) +{ + if (!StraightLine(a, b, color)) { + // ... + } +} + +// StrokeRect +void +DrawingEngine::StrokeRect(BRect r, const rgb_color& color) +{ + StrokeLine(r.LeftTop(), r.RightTop(), color); + StrokeLine(r.RightTop(), r.RightBottom(), color); + StrokeLine(r.RightBottom(), r.LeftBottom(), color); + StrokeLine(r.LeftBottom(), r.LeftTop(), color); +} + +// FillRegion +void +DrawingEngine::FillRegion(BRegion *region, const rgb_color& color) +{ + if (Lock()) { + // for speed reasons, expected to be already clipped + fHWInterface->FillRegion(*region, color); + + Unlock(); + } +} + +// DrawString +void +DrawingEngine::DrawString(const char* string, BPoint baseLine, + const rgb_color& color) +{ +} + + + + +struct node { + node() + { + pointers = NULL; + } + node(const BRect& r, int32 maxPointers) + { + init(r, maxPointers); + } + ~node() + { + delete [] pointers; + } + + void init(const BRect& r, int32 maxPointers) + { + rect = r; + pointers = new node*[maxPointers]; + in_degree = 0; + next_pointer = 0; + } + + void push(node* node) + { + pointers[next_pointer] = node; + next_pointer++; + } + node* top() + { + return pointers[next_pointer]; + } + node* pop() + { + node* ret = top(); + next_pointer--; + return ret; + } + + BRect rect; + int32 in_degree; + node** pointers; + int32 next_pointer; +}; + +bool +is_left_of(const BRect& a, const BRect& b) +{ + return (a.right < b.left); +} +bool +is_above(const BRect& a, const BRect& b) +{ + return (a.bottom < b.top); +} + +void +DrawingEngine::CopyRegion(BRegion* region, int32 xOffset, int32 yOffset) +{ + if (Lock()) { + + int32 count = region->CountRects(); + + // 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 = new clipping_rect[count]; + int32 nextSortedIndex = 0; + + while (!inDegreeZeroNodes.empty()) { + node* n = inDegreeZeroNodes.top(); + inDegreeZeroNodes.pop(); + + 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++; + + 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 blit + fHWInterface->CopyRegion(sortedRectList, count, xOffset, yOffset); + + delete[] sortedRectList; + + Unlock(); + } +} diff --git a/src/tests/servers/app/newerClipping/drawing/DrawingEngine.h b/src/tests/servers/app/newerClipping/drawing/DrawingEngine.h new file mode 100644 index 0000000000..e6dc0478e7 --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/DrawingEngine.h @@ -0,0 +1,41 @@ + +#ifndef DRAWING_ENGINE_H +#define DRAWING_ENGINE_H + +#include +#include + +class AccelerantHWInterface; +class DirectWindowBuffer; + +class DrawingEngine { + public: + DrawingEngine(AccelerantHWInterface* interface, + DirectWindowBuffer* buffer); + virtual ~DrawingEngine(); + + bool Lock(); + void Unlock(); + + void ConstrainClipping(BRegion* region); + + bool StraightLine(BPoint a, BPoint b, const rgb_color& c); + void StrokeLine(BPoint a, BPoint b, const rgb_color& color); + void StrokeRect(BRect r, const rgb_color& color); + + void FillRegion(BRegion *region, const rgb_color& color); + + void DrawString(const char* string, BPoint baseLine, + const rgb_color& color); + + void CopyRegion(BRegion *region, int32 xOffset, int32 yOffset); + + private: + AccelerantHWInterface* fHWInterface; + DirectWindowBuffer* fBuffer; + BRegion fCurrentClipping; +}; + + +#endif // DRAWING_ENGINE_H + diff --git a/src/tests/servers/app/newerClipping/drawing/RenderingBuffer.h b/src/tests/servers/app/newerClipping/drawing/RenderingBuffer.h new file mode 100644 index 0000000000..c1c706fe4f --- /dev/null +++ b/src/tests/servers/app/newerClipping/drawing/RenderingBuffer.h @@ -0,0 +1,33 @@ +// RenderingBuffer.h + +#ifndef RENDERING_BUFFER_H +#define RENDERING_BUFFER_H + +#include +#include + +class RenderingBuffer { + public: + RenderingBuffer() {} + virtual ~RenderingBuffer() {} + + virtual status_t InitCheck() const = 0; + + virtual color_space ColorSpace() const = 0; + virtual void* Bits() const = 0; + virtual uint32 BytesPerRow() const = 0; + // the *count* of the pixels per line + virtual uint32 Width() const = 0; + // the *count* of lines + virtual uint32 Height() const = 0; + + inline uint32 BitsLength() const + { return Height() * BytesPerRow(); } + + inline BRect Bounds() const + { return BRect(0.0, 0.0, + Width() - 1, + Height() - 1); } +}; + +#endif // RENDERING_BUFFER_H diff --git a/src/tests/servers/app/newerClipping/main.cpp b/src/tests/servers/app/newerClipping/main.cpp index ee1a7628fb..4ca97487eb 100644 --- a/src/tests/servers/app/newerClipping/main.cpp +++ b/src/tests/servers/app/newerClipping/main.cpp @@ -1,13 +1,16 @@ #include -#include +#include #include #include #include +#include "AccelerantHWInterface.h" #include "Desktop.h" +#include "DirectWindowBuffer.h" #include "DrawingEngine.h" +#include "DrawView.h" #include "ViewLayer.h" #include "WindowLayer.h" @@ -18,19 +21,25 @@ class App : public BApplication { virtual void ReadyToRun(); }; -class Window : public BWindow { +class Window : public BDirectWindow { public: - Window(const char* title); - virtual ~Window(); + Window(const char* title); + virtual ~Window(); - virtual bool QuitRequested(); + virtual bool QuitRequested(); - void AddWindow(BRect frame, const char* name); - void Test(); + virtual void DirectConnected(direct_buffer_info* info); + + void AddWindow(BRect frame, const char* name); + void Test(); private: - DrawView* fView; - Desktop* fDesktop; - bool fQuit; + DrawView* fView; + Desktop* fDesktop; + bool fQuit; + DirectWindowBuffer fBuffer; + AccelerantHWInterface fInterface; + DrawingEngine fEngine; + }; // constructor @@ -52,15 +61,20 @@ App::ReadyToRun() // constructor Window::Window(const char* title) - : BWindow(BRect(50, 50, 800, 650), title, - B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS) + : BDirectWindow(BRect(50, 50, 800, 650), title, + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS), + fQuit(false), + fBuffer(), + fInterface(), + fEngine(&fInterface, &fBuffer) { + fInterface.Initialize(); fView = new DrawView(Bounds()); - fDesktop = new Desktop(fView); - fDesktop->Run(); AddChild(fView); fView->MakeFocus(true); - fQuit = false; + + fDesktop = new Desktop(fView, &fEngine); + fDesktop->Run(); } // destructor @@ -82,6 +96,34 @@ Window::QuitRequested() return true; } +// DirectConnected +void +Window::DirectConnected(direct_buffer_info* info) +{ + // TODO: for some reason, this deadlocks + // on B_DIRECT_STOP... be aware + fDesktop->LockClipping(); + + fEngine.Lock(); + + switch(info->buffer_state & B_DIRECT_MODE_MASK) { + case B_DIRECT_START: + case B_DIRECT_MODIFY: + fBuffer.SetTo(info); + fDesktop->SetOffset(info->window_bounds.left, info->window_bounds.top); + break; + case B_DIRECT_STOP: + fBuffer.SetTo(NULL); + break; + } + + fDesktop->SetMasterClipping(&fBuffer.WindowClipping()); + + fEngine.Unlock(); + + fDesktop->UnlockClipping(); +} + // AddWindow void Window::AddWindow(BRect frame, const char* name) diff --git a/src/tests/servers/app/newerClipping/makefile b/src/tests/servers/app/newerClipping/makefile index 6f2f1b8bf4..b7c291d8f2 100644 --- a/src/tests/servers/app/newerClipping/makefile +++ b/src/tests/servers/app/newerClipping/makefile @@ -32,11 +32,14 @@ TYPE= APP # in folder names do not work well with this makefile. SRCS= ClientLooper.cpp \ Desktop.cpp \ - DrawingEngine.cpp \ main.cpp \ MultiLocker.cpp \ ViewLayer.cpp \ WindowLayer.cpp \ + drawing/AccelerantHWInterface.cpp \ + drawing/DirectWindowBuffer.cpp \ + drawing/DrawingEngine.cpp \ + drawing/DrawView.cpp \ # trace.c # specify the resource files to use @@ -58,7 +61,7 @@ RSRCS= # naming scheme you need to specify the path to the library # and it's name # library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS= be +LIBS= be game # specify additional paths to directories following the standard # libXXX.so or libXXX.a naming scheme. You can specify full paths