added 1 changeset to branch 'refs/remotes/looncraz-github/CAP-dirty' old head: c8b66e9c19935abbc477cfbec616f29824cc027a new head: 25b3a3b9460a9184c0db31854f7f96a55b26bcd4 overview: https://github.com/looncraz/haiku/compare/c8b66e9c1993...25b3a3b9460a ---------------------------------------------------------------------------- 25b3a3b9460a: Initial CompositeEngine (v2) Now overloading AccelerantHWInterface and giving each window its own CompositeWindowHWInterface which will need to interact with a dedicated type of accelerant for client-draw acceleration. Dozens of other small changes. This is the dirty branch, this stuff is full of errors ;-) [ looncraz <looncraz@xxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: 25b3a3b9460a9184c0db31854f7f96a55b26bcd4 Author: looncraz <looncraz@xxxxxxxxxxxx> Date: Sun Mar 22 22:33:02 2015 UTC ---------------------------------------------------------------------------- 16 files changed, 832 insertions(+), 185 deletions(-) src/servers/app/Desktop.cpp | 62 ++++- src/servers/app/Desktop.h | 8 +- src/servers/app/ServerWindow.cpp | 10 +- src/servers/app/Window.cpp | 31 ++- src/servers/app/Window.h | 5 +- .../drawing/interface/local/CompositeEngine.cpp | 255 +++++++++++++++++++ .../drawing/interface/local/CompositeEngine.h | 62 ++++- .../interface/local/CompositeHWInterface.cpp | 88 ++----- .../interface/local/CompositeHWInterface.h | 95 ++----- .../drawing/interface/local/CompositeWindow.cpp | 137 ++++++++-- .../drawing/interface/local/CompositeWindow.h | 29 ++- .../local/CompositeWindowHWInterface.cpp | 114 +++++++++ .../interface/local/CompositeWindowHWInterface.h | 100 ++++++++ src/servers/app/drawing/interface/local/Jamfile | 5 + .../drawing/interface/local/WeakLazyLocker.cpp | 8 + .../app/drawing/interface/local/WeakLazyLocker.h | 8 + ---------------------------------------------------------------------------- diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 26d1a78..79bafe5 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -39,6 +39,7 @@ #include "AppServer.h" #include "ClickTarget.h" +#include "CompositeEngine.h" #include "DecorManager.h" #include "DesktopSettingsPrivate.h" #include "DrawingEngine.h" @@ -438,7 +439,7 @@ Desktop::Desktop(uid_t userID, const char* targetScreen) fFocus(NULL), fFront(NULL), fBack(NULL), - fCompositingEnabled(false) + fCompositeEngine(NULL) { memset(fLastWorkspaceFocus, 0, sizeof(fLastWorkspaceFocus)); @@ -463,7 +464,11 @@ Desktop::Desktop(uid_t userID, const char* targetScreen) Desktop::~Desktop() { + if (fCompositeEngine != NULL) + fCompositeEngine->Destroy(); + delete fSettings; + delete fCompositeEngine; delete_area(fSharedReadOnlyArea); delete_port(fMessagePort); @@ -2702,6 +2707,57 @@ Desktop::WindowForClientLooperPort(port_id port) } +::CompositeEngine* +Desktop::CompositeEngine() +{ + /* + We must lock in case we are changing mode when we + are called. + */ + LockSingleWindow(); + ::CompositeEngine* engine = fCompositeEngine; + UnlockSingleWindow(); + + return engine; +} + + +bool +Desktop::IsCompositingEnabled() +{ + bool enabled = false; + LockSingleWindow(); + if (fCompositeEngine != NULL) + enabled = fCompositeEngine->IsEnabled(); + UnlockSingleWindow(); + + return enabled; +} + + +status_t +Desktop::SetCompositingEnabled(bool enable) +{ + if (enable == IsCompositingEnabled()) + return B_ALREADY_RUNNING; + + LockAllWindows(); + if (fCompositeEngine == NULL) { + fCompositeEngine = new (std::nothrow) ::CompositeEngine(this); + + if (fCompositeEngine == NULL) { + UnlockAllWindows(); + return B_NO_MEMORY; + } + } + + status_t error = fCompositeEngine->SetEnabled(true); + UnlockAllWindows(); + + return error; +} + + WindowList& Desktop::_Windows(int32 index) { @@ -3270,8 +3326,8 @@ Desktop::RebuildAndRedrawAfterWindowChange(Window* changedWindow, // remove clipping region from non-alpha window regions so windows // beneath this one do not draw needlessly - if (fCompositingEnabled && window->IsCompositeWindow()) - stillAvailableOnScreen.Exclude(&window->NonAlphaVisibleRegion()); + if (IsCompositingEnabled() && window->IsCompositeWindow()) + window->ExcludeNonAlphaVisibleRegion(&stillAvailableOnScreen); else stillAvailableOnScreen.Exclude(&window->VisibleRegion()); } diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 338f9f3..a5afcd5 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -40,6 +40,7 @@ class BMessage; +class CompositeEngine; class DecorAddOn; class DrawingEngine; class HWInterface; @@ -250,6 +251,11 @@ public: Window* WindowForClientLooperPort(port_id port); StackAndTile* GetStackAndTile() { return &fStackAndTile; } + + // Compositing + ::CompositeEngine* CompositeEngine(); + bool IsCompositingEnabled(); + status_t SetCompositingEnabled(bool); private: WindowList& _Windows(int32 index); @@ -356,7 +362,7 @@ private: Window* fFront; Window* fBack; - bool fCompositingEnabled; + ::CompositeEngine* fCompositeEngine; StackAndTile fStackAndTile; }; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index d6c6ba7..dd5a1c6 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -56,6 +56,8 @@ #include "AutoDeleter.h" #include "BBitmapBuffer.h" #include "BitmapManager.h" +#include "CompositeHWInterface.h" +#include "CompositeWindow.h" #include "Desktop.h" #include "DirectWindowInfo.h" #include "DrawingEngine.h" @@ -3627,9 +3629,13 @@ Window* ServerWindow::MakeWindow(BRect frame, const char* name, window_look look, window_feel feel, uint32 flags, uint32 workspace) { + //TODO: make this compile-time configurable - ::Window* window = new(std::nothrow) ::Window(frame, name, look, feel, flags, - workspace, this, fDesktop->HWInterface()->CreateDrawingEngine()); + CompositeHWInterface* windowHWInterface + = new (std::nothrow) CompositeHWInterface(fDesktop); + + ::CompositeWindow* window = new(std::nothrow) ::CompositeWindow(frame, + name, look, feel, flags, workspace, this, windowHWInterface); // TEMPORARY TEST - single window set WindowBuffer // TODO: change test to ensure B_NO_BUFFERED_DRAWING is NOT set in diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp index d247f65..a35a93e 100644 --- a/src/servers/app/Window.cpp +++ b/src/servers/app/Window.cpp @@ -225,16 +225,35 @@ Window::SetAlphaRegion(BRegion* alphaRegion) } -BRegion -Window::NonAlphaVisibleRegion() +void +Window::GetNonAlphaVisibleRegion(BRegion* nonAlphaVisibleRegion) { + // TODO: assert? + *nonAlphaVisibleRegion = fVisibleRegion; + // clipping must be read locked when this is called if (fAlphaRegion.CountRects() == 0) - return fVisibleRegion; + return; - BRegion nonAlphaVisibleRegion(fVisibleRegion); - nonAlphaVisibleRegion.Exclude(&fAlphaRegion); - return nonAlphaVisibleRegion; + nonAlphaVisibleRegion->Exclude(&fAlphaRegion); +} + + +void +Window::ExcludeNonAlphaVisibleRegion(BRegion* excludeNonAlphaRegion) +{ + BRegion nonAlphaVisibleRegion; + GetNonAlphaVisibleRegion(&nonAlphaVisibleRegion); + excludeNonAlphaRegion->Exclude(&nonAlphaVisibleRegion); +} + + +void +Window::IncludeNonAlphaVisibleRegion(BRegion* includeNonAlphaRegion) +{ + BRegion nonAlphaVisibleRegion; + GetNonAlphaVisibleRegion(&nonAlphaVisibleRegion); + includeNonAlphaRegion->Include(&nonAlphaVisibleRegion); } diff --git a/src/servers/app/Window.h b/src/servers/app/Window.h index 88d2326..0b54c51 100644 --- a/src/servers/app/Window.h +++ b/src/servers/app/Window.h @@ -121,10 +121,13 @@ public: void SetAlphaRegion(BRegion* alphaRegion); // you need to have ReadLock()ed the clipping! inline BRegion& VisibleRegion() { return fVisibleRegion; } - BRegion NonAlphaVisibleRegion(); inline BRegion& AlphaRegion() { return fAlphaRegion; } BRegion& VisibleContentRegion(); + void GetNonAlphaVisibleRegion(BRegion*); + void ExcludeNonAlphaVisibleRegion(BRegion*); + void IncludeNonAlphaVisibleRegion(BRegion*); + // 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); diff --git a/src/servers/app/drawing/interface/local/CompositeEngine.cpp b/src/servers/app/drawing/interface/local/CompositeEngine.cpp new file mode 100644 index 0000000..1d69166 --- /dev/null +++ b/src/servers/app/drawing/interface/local/CompositeEngine.cpp @@ -0,0 +1,255 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + +/*! Composes window draws per Desktop for local displays. */ + +/* + Technically this is version 2 of the CompositeEngine. + + The previous version was a proof-of-concept using an ugaly global accessor + and assumed there was only one output and Desktop and was rather ugly. + This is the lean and mean version ;-) +*/ + +//TODO: REMOVE BEFORE PATCH SUBMITTAL +#include "RapidDebug.h" + +#include "CompositeEngine.h" + +#include <Errors.h> +#include <PrivateScreen.h> + +#include "CompositeHWInterface.h" +#include "CompositeWindow.h" +#include "Desktop.h" +#include "ServerBitmap.h" +#include "ServerCursor.h" + +#if COMPOSITE_DEBUG +# define PREAMBLE _LOGF("engine(%p):desktop(%p): ", this, fDesktop); +# define STRACE(A) PREAMBLE _LOG(A) +# define STRACEF(A, X...) PREAMBLE _LOGF(A, X) +# define CAPDEBUG(X) X +#else +# define STRACE(A) +# define STRACEF(A, X...) +# define CAPDEBUG(X) +#endif + + +enum { + CAP_HZ_FULL = 0, + CAP_HZ_HALF, + CAP_HZ_SLOW +}; + + +CompositeEngine::CompositeEngine(Desktop* desktop) + : + fLock("CompositeEngine"), + fEnabled(false), + fClientsLocked(false), + fDesktop(desktop), + fFrameRateHint(CAP_HZ_FULL) + { + STRACE("created\n"); + } + + +CompositeEngine::~CompositeEngine() +{ + STRACE("destructed\n"); +} + + +bool +CompositeEngine::IsEnabled() const +{ + AutoReadLocker _(fLock); + return fEnabled; +} + + +status_t +CompositeEngine::SetEnabled(bool enable) +{ + STRACEF("SetEnabled: %s", enable ? "TRUE" : "FALSE"); + AutoWriteLocker writeLock(fLock); + + if (fEnabled) { + STRACE("already running!"); + return B_ALREADY_RUNNING; + } + + /* + TODO: + get timing info and performance info for control loop + */ + + /* + TODO: + Make client calls asynchronous, then have control loop wait so we + can return from this function more quickly. + + Enabling or disabling compositing should look like a quick flicker + on the screen, if anything at all. + */ + + fEnabled = enable; + fClientsLocked = true; + CompositeEngineClient* client = NULL; + for (int i = 0; i < fClients.CountItems(); ++i) { + client = fClients.ItemAt(i); + CAPDEBUG( + if (client == NULL) + STRACEF("NULL client in list! @ %i\n", i); + ); + + if (enable) + client->CompositingEnabling(); + else + client->CompositingDisabling(); + } + writeLock.Unlock(); + + /* + Now that all the prep work is done by our clients, we consider + ourselves to be fully enabled. However, since we have held onto + a write lock the entire time we prepared our client list, we need + to release that lock and then tell our clients that we are enabled + (or disabled). + + This happens before the control thread executes. + */ + + fLock.ReadLock(); + for (int i = 0; i < fClients.CountItems(); ++i) { + client = fClients.ItemAt(i); + CAPDEBUG( + if (client == NULL) + STRACEF("NULL client in list! @ %i\n", i); + ); + + client->CompositingEnabled(enable); + } + fClientsLocked = false; + + /* + TODO: execute control thread! + */ + + fLock.ReadUnlock(); + return B_OK; +} + + +void +CompositeEngine::Destroy() +{ + STRACE("Desktop destroyed!\n"); + SetEnabled(false); + fDesktop = NULL; + /* TODO: + When SetEnabled() becomes more asynchrnous we will need to wait like + the control thread would in this case! + Destroy() cannot return until we are confident all is well! + */ +} + + +status_t +CompositeEngine::SetDPMSMode(uint32 state, status_t hwError) +{ + AutoWriteLocker _(fLock); + + /* + The control thread will change its update interval based on our + suggestions here. + + If the DPMS mode is B_DPMS_ON, we want the control loop to run at + full steam. However, if the DPMS state is off/standby/suspend then + we should slow things down to save energy, but we need a good idea + as to whether or not the monitor actually suspended or not, so we + have the hwError call which we use to modify our hint. + + If the monitor is allegedly off/suspended, we move to the slowest + update interval, if we aren't so sure, we just move to "half." + */ + + if (state == B_DPMS_ON) { + fFrameRateHint = CAP_HZ_FULL; + return B_OK; + } + + if ( state == B_DPMS_OFF +// || state == B_DPMS_STANDBY + || state == B_DPMS_SUSPEND) { + + if (hwError == B_OK) + fFrameRateHint = CAP_HZ_SLOW; + else + fFrameRateHint = CAP_HZ_HALF; + + return B_OK; + } + + return B_UNSUPPORTED; +} + +bool +CompositeEngine::SetCursor(ServerCursor* cursor) +{ + /* + When we handle the cursor ourself (and hardware cursor isn't enabled) + we will re-render the cursor every frame when it sits over a direct + window just prior to the refresh in the hope that it will not be + blotted out. + + Otherwise we will simply redraw it when it moves or its area on the + screen is dirty. + */ + + return false; +} + + +void +CompositeEngine::SetCursorVisible(bool visible) +{ + +} + + +void +CompositeEngine::MoveCursorTo(float x, float y) +{ + +} + + +bool +CompositeEngine::SetDragBitmap(const ServerBitmap* bitmap, + const BPoint& offsetFromCursor) +{ + /* + When the CompositeOverlayBitmap is enabled we MAY set the + drag bitmap into it. + + Our real desire is to use a hardware accelerated function to + drag the bitmap (and moving windows) around without needing + to recompose anything beneath it, but we will need to take + care of the common case of no driver support. + */ + + return false; +} + + + + + diff --git a/src/servers/app/drawing/interface/local/CompositeEngine.h b/src/servers/app/drawing/interface/local/CompositeEngine.h index f63ad2d..c10e94a 100644 --- a/src/servers/app/drawing/interface/local/CompositeEngine.h +++ b/src/servers/app/drawing/interface/local/CompositeEngine.h @@ -1,33 +1,77 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + #ifndef CAP_COMPOSITE_ENGINE_H #define CAP_COMPOSITE_ENGINE_H +#include <ObjectList.h> +#include <OS.h> +#include <Point.h> + + +#include "MultiLocker.h" + + +class Desktop; +class CompositeWindow; +class HWInterface; +class ServerBitmap; +class ServerCursor; + /* For each Desktop (ScreenOwner) that has compositing enabled, it will create its own dedicated CompositeEngine. */ -class CompositeEngineClient{ +class CompositeEngineClient { public: + CompositeEngineClient(); + virtual ~CompositeEngineClient(); + virtual void CompositingEnabled(bool enabled) = 0; virtual void CompositingEnabling() = 0; virtual void CompositingDisabling() = 0; }; -class CompositeEngine{ +class CompositeEngine { public: - CompositeEngine (); + CompositeEngine(Desktop*); virtual ~CompositeEngine(); - virtual status_t SetDPMSMode(uint32 state); + bool IsEnabled() const; + status_t SetEnabled(bool); + + void Destroy(); + + virtual status_t SetDPMSMode(uint32 state, status_t hwError); + + virtual bool SetCursor(ServerCursor* cursor); + virtual void SetCursorVisible(bool); + virtual void MoveCursorTo(float, float); + + virtual bool SetDragBitmap(const ServerBitmap* bitmap, + const BPoint& offsetFromCursor); + +private: + friend class CompositeEngineClient; + void Attach(CompositeEngineClient*); + void Detach(CompositeEngineClient*); + + mutable MultiLocker fLock; + bool fEnabled; + bool fClientsLocked; - virtual void SetCursor(ServerCursor* cursor); - virtual void SetCursorVisible(bool); - virtual void MoveCursorTo(float, float); + Desktop* fDesktop; - virtual void SetDragBitmap(const ServerBitmap* bitmap, - const BPoint& offsetFromCursor); + uint32 fFrameRateHint; + BObjectList<CompositeEngineClient> fClients; }; diff --git a/src/servers/app/drawing/interface/local/CompositeHWInterface.cpp b/src/servers/app/drawing/interface/local/CompositeHWInterface.cpp index 0bc187b..a10dc68 100644 --- a/src/servers/app/drawing/interface/local/CompositeHWInterface.cpp +++ b/src/servers/app/drawing/interface/local/CompositeHWInterface.cpp @@ -1,4 +1,10 @@ -#include <Accelerant.h> +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ #include "CompositeEngine.h" #include "CompositeHWInterface.h" @@ -9,10 +15,9 @@ #include "RapidDebug.h" -CompositeHWInterface::CompositeHWInterface(Desktop* desktop) +CompositeHWInterface::CompositeHWInterface() : - AccelerantHWInterface(), - fDesktop(desktop) + AccelerantHWInterface() { } @@ -21,58 +26,16 @@ CompositeHWInterface::CompositeHWInterface(Desktop* desktop) CompositeHWInterface::~CompositeHWInterface() { -} - - - -DrawingEngine* -CompositeHWInterface::CreateDrawingEngine() -{ - return new (std::nothrow) DrawingEngine(this); -} - - -DrawingEngine* -CompositeHWInterface::CreateDrawingEngine(CompositeWindow* window) -{ - DrawingEngine* engine = new (std::nothrow) DrawingEngine(this); - engine->SetDrawingBuffer(window->DrawingBuffer()); -} - status_t -CompositeHWInterface::Initialize() -{ - - return AccelerantHWInterface::Initialize(); -} - - -status_t -CompositeHWInterface::Shutdown() -{ - return AccelerantHWInterface::Shutdown(); -} - - -// if screen is off, stop the compositing... -// if comes back on... bring it back -status_t CompositeHWInterface::SetDPMSMode(uint32 state) { - status_t error = AccelerantHWInterface::SetDPMSMode(state); - - if (fDesktop == NULL) - return B_ERROR; + status_t error = HWInterface::SetDPMSMode(state); - /* - The CompositeEngine doesn't always care if the accelerant failed - to set the DPMS mode for the display, it can possibly use the mode - set events themselves to change the target refresh rate (since a suspend - or standby event means the screen should be sleeping now). - */ + if (_CompositeEngine() != NULL) + return _CompositeEngine()->SetDPMSMode(state, error); - return fDesktop->CompositeEngine()->SetDPMSMode(state, error); + return error; } @@ -82,10 +45,14 @@ CompositeHWInterface::SetCursor(ServerCursor* cursor) /* When compositing a software cursor can be a very nasty thing, indeed! As such, the compositer must handle the timing (in the very least) of - the cursor draws and must be aware of any changes in the cursor. + the cursor draws and must be aware of any changes in the cursor unless + there is a hardware cursor... */ - if (fDesktop != NULL) - fDesktop->CompositeEngine()->SetCursor(cursor); + + if (!fHardwareCursor + && _CompositeEngine() != NULL + && _CompositeEngine()->SetCursor(cursor)) + return; AccelerantHWInterface::SetCursor(cursor); } @@ -94,8 +61,8 @@ CompositeHWInterface::SetCursor(ServerCursor* cursor) void CompositeHWInterface::SetCursorVisible(bool x) { - if (fDesktop != NULL) - fDesktop->CompositeEngine()->SetCursorVisible(x); + if (_CompositeEngine() != NULL) + _CompositeEngine()->SetCursorVisible(x); AccelerantHWInterface::SetCursorVisible(x); } @@ -104,7 +71,9 @@ CompositeHWInterface::SetCursorVisible(bool x) void CompositeHWInterface::MoveCursorTo(float x, float y) { - fDesktop->CompositeEngine()->MoveCursorTo(x,y); + if (_CompositeEngine() != NULL) + _CompositeEngine()->MoveCursorTo(x,y); + AccelerantHWInterface::MoveCursorTo(x,y); } @@ -116,17 +85,16 @@ CompositeHWInterface::SetDragBitmap(const ServerBitmap* bitmap, AccelerantHWInterface::SetDragBitmap(bitmap, offset); // TODO: create server-side exclusive CompositeOverlay // for dragging bitmaps - IF NEEDED... + // Our better option is to use hardware } void CompositeHWInterface::_DrawCursor(IntRect area) const { - if (fDesktop->CompositeEngine()->RedrawCursorOverlay(area) == false) - AccelerantHWInterface::_DrawCursor(area); + AccelerantHWInterface::_DrawCursor(area); - // if the CompositeEngine has a mouse handler (overlay), use it, - // otherwise revert to the AccelerantHWInterface's _DrawCursor() + //TODO! } diff --git a/src/servers/app/drawing/interface/local/CompositeHWInterface.h b/src/servers/app/drawing/interface/local/CompositeHWInterface.h index fe009db..17fbff4 100644 --- a/src/servers/app/drawing/interface/local/CompositeHWInterface.h +++ b/src/servers/app/drawing/interface/local/CompositeHWInterface.h @@ -1,92 +1,37 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + #ifndef COMPOSITE_HW_INTERFACE_H #define COMPOSITE_HW_INTERFACE_H #include <ObjectList.h> -#include "HWInterface.h" -#include "Desktop,h" - -class CompositeWindow; - -/* - CompositeHWInterface - One of these is created per compositing window. -*/ +#include "AccelerantHWInterface.h" class CompositeHWInterface : public HWInterface { public: - CompositeHWInterface (CompositeWindow*); + CompositeHWInterface (); virtual ~CompositeHWInterface (); - DrawingEngine* CreateDrawingEngine(); + void SetDesktop(Desktop*); - virtual status_t Initialize(); - virtual status_t Shutdown(); + virtual status_t SetDPMSMode(uint32 state); - virtual uint32 AvailableHWAcceleration() const; - - virtual RenderingBuffer* FrontBuffer() const; - virtual RenderingBuffer* BackBuffer() const; - - virtual void ResizeBy(int32 x, int32 y); - -protected: + virtual void SetCursor(ServerCursor* cursor); + virtual void SetCursorVisible(bool visible); + virtual void MoveCursorTo(float x, float y); + virtual void SetDragBitmap(const ServerBitmap* bitmap, + const BPoint& offsetFromCursor); private: - CompositeWindow* fWindow; - WindowBuffer* fFrontBuffer; - WindowBuffer* fBackBuffer; - -public: - /* - A lot of stuff we don't care about... - We must implement this for HWInterface, but CompositeHWInterface uses - the AccelerantHWInterface to interact with the standard 2D accelerant, - and will only directly interfaces with its own specialized accelerant - once such a thing exists... - */ - - virtual status_t SetMode(const display_mode& mode) - { return B_OK; } - virtual void GetMode(display_mode* mode) {} - - virtual status_t GetDeviceInfo(accelerant_device_info* info) - {return B_NOT_SUPPORTED;} - - virtual status_t GetFrameBufferConfig( - frame_buffer_config& config) - { return B_NOT_SUPPORTED; } - virtual status_t GetModeList(display_mode** _modeList, - uint32* _count) - { return B_NOT_SUPPORTED; } - virtual status_t GetPixelClockLimits(display_mode* mode, - uint32* _low, uint32* _high) - { return B_NOT_SUPPORTED; } - virtual status_t GetTimingConstraints(display_timing_constraints* - constraints) - { return B_NOT_SUPPORTED; } - virtual status_t ProposeMode(display_mode* candidate, - const display_mode* low, - const display_mode* high) - { return B_NOT_SUPPORTED; } - - virtual sem_id RetraceSemaphore() { return -1; } - virtual status_t WaitForRetrace( - bigtime_t timeout = B_INFINITE_TIMEOUT) - { return B_OK; } - - virtual status_t SetDPMSMode(uint32 state) - { return B_NOT_SUPPORTED; } - - virtual uint32 DPMSMode() - { return B_DPMS_ON; } - virtual uint32 DPMSCapabilities() - { return B_DPMS_ON; } - - virtual void Sync() {} - - + CompositeEngine* _CompositeEngine(); + Desktop* fDesktop; }; -#endif +#endif // COMPOSITE_HW_INTERFACE_H diff --git a/src/servers/app/drawing/interface/local/CompositeWindow.cpp b/src/servers/app/drawing/interface/local/CompositeWindow.cpp index f073515..a906057 100644 --- a/src/servers/app/drawing/interface/local/CompositeWindow.cpp +++ b/src/servers/app/drawing/interface/local/CompositeWindow.cpp @@ -3,31 +3,36 @@ * Distributed under the terms of the MIT license. * * Authors: - * looncraz <looncraz@xxxxxxxxxxxx> + * Joseph Groover <looncraz@xxxxxxxxxxxx> */ -#include "Window.h" #include "CompositeEngine.h" +#include "CompositeHWInterface.h" #include "CompositeWindow.h" +#include "Window.h" +#include "WindowBuffer.h" CompositeWindow::CompositeWindow(BRect frame, const char* name, window_look look, window_feel feel, uint32 flags, uint32 wspaces, - ::ServerWindow* window, CompositeHWInterface* hwInterface) + ::ServerWindow* window, HWInterface* hwInterface) :Window(frame, name, look, feel, flags, wspaces, window, - hwInterface->CreateDrawingEngine(this)), + hwInterface->CreateDrawingEngine()), fGraphicsCard(hwInterface), fIsCompositeWindow(_CompositeEngineValid() ? window->Desktop()->CompositeEngine()->IsEnabled() : false) { + if (_CompositeHWInterface() != NULL) + _CompositeHWInterface()->SetWindow(this); } CompositeWindow::~CompositeWindow() { - delete fGraphicsCard; + if (_CompositeHWInterface()) + delete _CompositeHWInterface(); } @@ -60,7 +65,7 @@ CompositeWindow::ReloadDecor() { // draw-lock window buffer // prepare for resize? - Window::ReloadDecor(); + return Window::ReloadDecor(); // draw-unlock window buffer } @@ -87,12 +92,22 @@ CompositeWindow::ProcessDirtyRegion(BRegion& regionOnScreen) return; } - fDirtyCopyRegion = NonAlphaVisibleRegion(); - fDirtyCopyRegion.IntersectWith(®ionOnScreen); - - fDirtyAlphaRegion = VisibleRegion(); - fDirtyAlphaRegion.IntersectWith(®ionOnScreen); - fDirtyAlphaRegion.Exclude(&visible); + // copy-mode work load + BRegion dirtyCopyRegion; + GetNonAlphaVisibleRegion(&dirtyCopyRegion); + dirtyCopyRegion.IntersectWith(®ionOnScreen); + + // alpha-mode work load + BRegion dirtyAlphaRegion = VisibleRegion(); + dirtyAlphaRegion.IntersectWith(®ionOnScreen); + dirtyAlphaRegion.Exclude(&dirtyCopyRegion); + + // We don't want to mess with these during the compositer lock + //... which only occurs in single-buffered mode + ClientLock(); + fDirtyCopyRegion.Include(&dirtyCopyRegion); + fDirtyAlphaRegion.Include(&dirtyAlphaRegion); + ClientUnlock(); } @@ -140,6 +155,9 @@ void CompositeWindow::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion, bool resizeStack) { + if (_CompositeHWInterface() != NULL) + _CompositeHWInterface()->ResizeBy(x, y); + Window::ResizeBy(x, y, dirtyRegion, resizeStack); } @@ -149,26 +167,94 @@ CompositeWindow::SetFlags(uint32 flags, BRegion* updateRegion) { Window::SetFlags(flags, updateRegion); /* - We will be adding some flags, perhaps. + We will be adding some flags. Some candidates: - B_NO_DOUBLE_BUFFER - B_NO_COMPOSITING - - This is to give the applications some control. + B_DOUBLE_BUFFER - full window + B_DIRECT_RENDER / B_DO_NOT_COMPOSITE / B_RENDER_TO_SCREEN + B_ALPHA_ENABLED - Top view's alpha values are not ignored, + required for window transparency */ } //#pragma mark - + +bool +CompositeWindow::LazyLock() +{ + if (IsCompositeWindow() + && !fGraphicsCard->IsDoubleBuffered()) + return fLazyLock.SetLazyServerLock(); + + //fGraphicsCard-> + return false; +} + + +bool +CompositeWindow::ServerLock() +{ + if (IsCompositeWindow()) + if (!fGraphicsCard->IsDoubleBuffered()) + return fLazyLock.ServerLock(); +// else +// fGraphicsCard->SetCopyToFrontEnabled(false); + + // TODO: see above... + + return true; +} + + +void +CompositeWindow::ServerUnlock() +{ + if (IsCompositeWindow()) + if (!fGraphicsCard->IsDoubleBuffered()) + fLazyLock.ServerUnlock(); +// else +// fGraphicsCard->SetCopyToFrontEnabled(true); + + // TODO: see above... + +} + + +bool +CompositeWindow::ClientLock() +{ + if (IsCompositeWindow() + && !fGraphicsCard->IsDoubleBuffered()) + return fLazyLock.ClientLock(); + + return true; +} + + +void +CompositeWindow::ClientUnlock() +{ + if (IsCompositeWindow() + && !fGraphicsCard->IsDoubleBuffered()) + return fLazyLock.ClientUnlock(); +} + + + +//#pragma mark - + + void -CompositeWindow::CompositingEnabled(bool) +CompositeWindow::CompositingEnabled(bool enabled) { // the whole Desktop window list is compositing (by default) // ... or not... // Before this is called, we can't assume that to be the case, so this is // our chance to cleanup from enabling or disabling compositing if that // matters to us. + // Further, the CompositeEngine cannot be accessed during the enabling/ + // disabling hooks, but we can talk to it now! // Note: it doesn't here, but other clients may need it... } @@ -204,6 +290,8 @@ CompositeWindow::CompositingDisabling() * that WindowBuffer is further modifying the coordinate space to accomodate * for a Decorator, shadows, resizing optimizations, or other reasons. */ + + void CompositeWindow::ConvertWindowToDrawing(BPoint* point) const { @@ -384,15 +472,18 @@ CompositeWindow::_CompositeEngineValid() const ::WindowBuffer* CompositeWindow::_WindowBuffer() { - /* - If fGraphicsCard is null, we should really just crash, because it - should never ever ever ever happen. + if (fIsBufferedWindow + && fSecondaryWindowBuffer != NULL) + return fSecondaryWindowBuffer; - Should probably consider an assert... - */ return fGraphicsCard->DrawingBuffer(); } +CompositeHWInterface* +CompositeWindow::_CompositeHWInterface() +{ + return dynamic_cast<CompositeHWInterface*>(fGraphicsCard); +} diff --git a/src/servers/app/drawing/interface/local/CompositeWindow.h b/src/servers/app/drawing/interface/local/CompositeWindow.h index 2b1c48b..778fd38 100644 --- a/src/servers/app/drawing/interface/local/CompositeWindow.h +++ b/src/servers/app/drawing/interface/local/CompositeWindow.h @@ -3,7 +3,7 @@ * Distributed under the terms of the MIT license. * * Authors: - * looncraz <looncraz@xxxxxxxxxxxx> + * Joseph Groover <looncraz@xxxxxxxxxxxx> */ #ifndef CAP_COMPOSITE_WINDOW_H @@ -11,7 +11,11 @@ #include <Region.h> -#include "CompositeEngineClient.h" +class CompositeHWInterface; +class WindowBuffer; + +#include "CompositeEngine.h" +#include "WeakLazyLocker.h" #include "Window.h" @@ -21,11 +25,14 @@ public: window_look, window_feel, uint32 flags, uint32 wspaces, ::ServerWindow* window, - CompositeHWInterface* hwInterface); + HWInterface* hwInterface); virtual ~CompositeWindow(); virtual bool IsCompositeWindow() const; - // we don't always return true! + + // Render to self-managed WindowBuffer + bool SetWindowBufferEnabled(bool); + bool IsWindowBufferEnabled() const; virtual void BeginUpdate(BPrivate::PortLink& link); virtual void EndUpdate(); @@ -47,6 +54,13 @@ public: virtual void SetFlags(uint32 flags, BRegion* updateRegion); + bool LazyServerLock(); + bool ServerLock(); + void ServerUnlock(); + + bool ClientLock(); + void ClientUnlock(); + protected: // CompositeEngineClient stuff virtual void CompositingEnabled(bool); @@ -71,14 +85,19 @@ protected: private: bool _CompositeEngineValid() const; + CompositeHWInterface* _CompositeHWInterface(); ::WindowBuffer* _WindowBuffer(); - CompositeHWInterface* fGraphicsCard; + HWInterface* fGraphicsCard; bool fIsCompositeWindow; + bool fIsBufferedWindow; + + ::WindowBuffer* fSecondaryWindowBuffer; BRegion fDirtyAlphaRegion; BRegion fDirtyCopyRegion; + WeakLazyLocker fLazyLock; }; #endif // CAP_COMPOSITE_WINDOW_H diff --git a/src/servers/app/drawing/interface/local/CompositeWindowHWInterface.cpp b/src/servers/app/drawing/interface/local/CompositeWindowHWInterface.cpp new file mode 100644 index 0000000..7d51417 --- /dev/null +++ b/src/servers/app/drawing/interface/local/CompositeWindowHWInterface.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + +#include "CompositeEngine.h" +#include "CompositeWindowHWInterface.h" +#include "CompositeWindow.h" +#include "DrawingEngine.h" + + +#include "RapidDebug.h" + + +CompositeWindowHWInterface::CompositeWindowHWInterface(Desktop* desktop) + : + HWInterface(), + fWindow(NULL), + fDesktop(desktop) + { + + } + + +CompositeWindowHWInterface::~CompositeWindowHWInterface() +{ + /**/ +} + + +void +CompositeWindowHWInterface::SetWindow(CompositeWindow* window) +{ +# if ENABLE_LOGGING + if (fWindow != NULL) { + _LOGF("CompositeWindowHWInterface::SetWindow(%p) - ALREADY SET TO: %p", + window, this); + } +# endif + fWindow = window; + +} + + +DrawingEngine* +CompositeWindowHWInterface::CreateDrawingEngine() +{ + return new (std::nothrow) DrawingEngine(this); +} + + +status_t +CompositeWindowHWInterface::Initialize() +{ // Will be called from Desktop + // TODO: + // Try and grab a compositing accelerant + // Spawn window buffer(s) for window + return HWInterface::Initialize(); +} + + +status_t +CompositeWindowHWInterface::Shutdown() +{ + // TODO: + // release our compositing accelerant + // destroy buffers + return HWInterface::Shutdown(); +} + + + +uint32 +CompositeWindowHWInterface::AvailableHWAcceleration() const +{ + return 0; +} + + +void +CompositeWindowHWInterface::ResizeBy(int32 x, int32 y) +{ + /* TODO! + if (_HasHardwareBuffers()) + fACCResizeBuffers(x, y); + else { + if (fBackBuffer != NULL) + fBackBuffer->ResizeBy(x, y); + + if (fFrontBuffer != NULL) + fFrontBuffer->ResizeBy(x, y); + } + */ +} + + +RenderingBuffer* +CompositeWindowHWInterface::FrontBuffer() const +{ + return fFrontBuffer; +} + + +RenderingBuffer* +CompositeWindowHWInterface::BackBuffer() const +{ + return fBackBuffer; +} + + + diff --git a/src/servers/app/drawing/interface/local/CompositeWindowHWInterface.h b/src/servers/app/drawing/interface/local/CompositeWindowHWInterface.h new file mode 100644 index 0000000..7a4ad9d --- /dev/null +++ b/src/servers/app/drawing/interface/local/CompositeWindowHWInterface.h @@ -0,0 +1,100 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + +#ifndef COMPOSITE_WINDOW_HW_INTERFACE_H +#define COMPOSITE_WINDOW_HW_INTERFACE_H + +#include <ObjectList.h> + +#include "HWInterface.h" +#include "Desktop.h" + +class CompositeWindow; + +/* + CompositeWindowHWInterface + One of these is created per compositing window. +*/ + + +class CompositeWindowHWInterface : public HWInterface { +public: + CompositeWindowHWInterface (Desktop* desktop); + virtual ~CompositeWindowHWInterface (); + + void SetWindow(CompositeWindow*); + + DrawingEngine* CreateDrawingEngine(); + + virtual status_t Initialize(); + virtual status_t Shutdown(); + + virtual uint32 AvailableHWAcceleration() const; + + virtual void ResizeBy(int32 x, int32 y); + +protected: + // Access the proper buffer via DrawingBuffer() + virtual RenderingBuffer* FrontBuffer() const; + virtual RenderingBuffer* BackBuffer() const; + +private: + CompositeWindow* fWindow; + Desktop* fDesktop; + WindowBuffer* fFrontBuffer; + WindowBuffer* fBackBuffer; + +public: + /* + A lot of stuff we don't care about... + */ + + virtual status_t SetMode(const display_mode& mode) + { return B_OK; } + virtual void GetMode(display_mode* mode) {} + + virtual status_t GetDeviceInfo(accelerant_device_info* info) + {return B_NOT_SUPPORTED;} + + virtual status_t GetFrameBufferConfig( + frame_buffer_config& config) + { return B_NOT_SUPPORTED; } + virtual status_t GetModeList(display_mode** _modeList, + uint32* _count) + { return B_NOT_SUPPORTED; } + virtual status_t GetPixelClockLimits(display_mode* mode, + uint32* _low, uint32* _high) + { return B_NOT_SUPPORTED; } + virtual status_t GetTimingConstraints(display_timing_constraints* + constraints) + { return B_NOT_SUPPORTED; } + virtual status_t ProposeMode(display_mode* candidate, + const display_mode* low, + const display_mode* high) + { return B_NOT_SUPPORTED; } + + virtual sem_id RetraceSemaphore() { return -1; } + virtual status_t WaitForRetrace( + bigtime_t timeout = B_INFINITE_TIMEOUT) + { return B_OK; } + + virtual status_t SetDPMSMode(uint32 state) + { return B_NOT_SUPPORTED; } + + virtual uint32 DPMSMode() + { return B_DPMS_ON; } + + virtual uint32 DPMSCapabilities() + { return 0; } + + virtual void Sync() {} + + +}; + +#endif // COMPOSITE_WINDOW_HW_INTERFACE_H diff --git a/src/servers/app/drawing/interface/local/Jamfile b/src/servers/app/drawing/interface/local/Jamfile index 4a6b2be..557ef6d 100644 --- a/src/servers/app/drawing/interface/local/Jamfile +++ b/src/servers/app/drawing/interface/local/Jamfile @@ -11,8 +11,13 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter font_support ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app stackandtile ] ; StaticLibrary libaslocal.a : AccelerantBuffer.cpp AccelerantHWInterface.cpp + CompositeEngine.cpp + CompositeHWInterface.cpp + CompositeWindow.cpp + WeakLazyLocker.cpp ; diff --git a/src/servers/app/drawing/interface/local/WeakLazyLocker.cpp b/src/servers/app/drawing/interface/local/WeakLazyLocker.cpp index 1fe8999..2ec7485 100644 --- a/src/servers/app/drawing/interface/local/WeakLazyLocker.cpp +++ b/src/servers/app/drawing/interface/local/WeakLazyLocker.cpp @@ -1,3 +1,11 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + #include <OS.h> #include <Locker.h> diff --git a/src/servers/app/drawing/interface/local/WeakLazyLocker.h b/src/servers/app/drawing/interface/local/WeakLazyLocker.h index 5fdb885..cb8db77 100644 --- a/src/servers/app/drawing/interface/local/WeakLazyLocker.h +++ b/src/servers/app/drawing/interface/local/WeakLazyLocker.h @@ -1,3 +1,11 @@ +/* + * Copyright 2001-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxxx> + */ + #ifndef CAP_WEAK_LAZY_LOCKER_H #define CAP_WEAK_LAZY_LOCKER_H