added 33 changesets to branch 'refs/remotes/looncraz-github/compositing' old head: 0000000000000000000000000000000000000000 new head: fe7207954e1107589c440b9181a85a2a4fcc352f ---------------------------------------------------------------------------- 8bcdc04: Doing thing right - I hope Brought CompositeEngine.h more inline with app_server and fixed numerous little errors (I hate USB keyboards...). Changed UpdateQueue into HWUpdateQueue and created a new UpdateQueue as, basically, an interface class. Created CompositeUpdateQueue to act as a final-gathering place for areas in the back-buffer which need to be copied to the front buffer. Begin fleshing out CompositingPerfmon. Verified clean build status, have not verified run-time sanity, though there should be no effects at this point other than a slightly larger binary. 58fcae3: Finally a working man's commit... Much future planning (immediate future...), app_server communication protocol setup started, fixed a few things, changed some more, yadda yadda. All compiles, but will not link. That is intentional (lets me know where I am going next in case I forget to add a note to my TODO). ca74099: Major commit Re-oriented ComositeEngine scrap pieces from CAFE::RenderEngine, namely removing performance modes - as these aren't likely needed int the limited role in the app_server. If anything, the app_server will only need three modes: slow(5hz), 60hz, @refresh, which is better handled with SetSlowMode() and SetUpdateEveryRefresh(). Moved special accessors to CompositingPrivate. Prepared app_server port communication, implemented some BWindow changes (SetDrawingMode()), prepare for special full-screen modes to prevent unneeded updates from the back coming forward. Created WindowBuffer, which will be atttached to a Painter with a new method to render the buffer directly, which is attached to a standard RenderEngine, which will be generated by the CompsiteHWInterface. WindowBuffer will collect updated rects and the CompositeEngine will prioritize updates front-to-back, ceasing updates when a new frame is to be renderred - but not before completing updates for any active WindowBuffer. While WindowBuffer is active with the CompositeEngine, the client will be unable to make drawing changes, so we will push as many threads to each WindowBuffer as possible, with each dirty rect possibly being handled by a separate thread/core and unlock that WindowBuffer as quickly as possible. 5df5c10: Adding needed funcitonality to Window: Ability to use WindowBuffer (for compositing OR caching). Bring numerous other objects in line with changes. Take into account requirements for hardware acceleration. CompositeHWInterface is now an AccelerantHWInterface. Trying to limit requirements in the future for acceleration. NOTE: the build will not link at this point, still on purpose... 55b3b78: Implement some missing functions. Found some lacking areas, and implemented missing WindowBuffer functions. CompositeEngine is only hold-up until link success. 9cd2054: Various tidbits. d6c9717: Message Handling Setup message handling for compositing. The CompositeEngine will handle all of its own requests. This is merely a prelude before setting up a route around ServerApp to expediate communications. Purpose being that some messages will undoubtedly be very time sensitive... and having all handling code in one place is quite nice. Began changes and made first runs of modified app_server (without incident, but no regression testing-yet). app_server now builds. Modified binaries thus far: libbe.so, app_server 86d79d7: Bug fixes Test run with compositing enabled to trace down bugs. Found several - as expected. 79c4de7: Adapt view to local buffer coordinates for drawing. Hoping this way works - it did eliminate all segment violations up to the Desktop bitmap draw, so we are no longer overunning the buffers it would seem... This is being kept as its own commit so it can be easily undone later, or referenced. 3823042: Working out the kinks... As we are now much more sensitive to writing outside of a View's bounds, we have to make adjustments... I believe I will be making Painter more aware of it's buffer's limitations, and to act accordingly to prevent segment violations. At this point, app_server can run in compositing mode, though nothing is painted on the screen. However, with very little effort (just clicking around) we find ourselves with a segment violation in Window SeetDrawingBuffer(), IIRC... next commit ;-) a649fe9: Re-orienting to mixed-compositing (temporarily) Removed Window::SetDrawingMode in preference to the original B_RENDER_COMPOSITE window flag. The app_server internals make so many assumptions that drawing is occuring directly in the screen coordinate space that I am having surprising difficulty getting even a single Window to draw into its own WindowBuffer without some code blasting past the boundaries (and thus crashing). Decorators now draw directly into the screen buffer, but will soon be rewritten to draw into the over-provisioned WindowBuffers of their 'owning' windows. Currently, using the app_server without compositing enabled is going to be fruitless, and compositing still defaults to disabled, so don't expect to build a usable app_server - though it does build without issue. Modified View to use ConvertForDrawing instead of ConvertToScreenForDrawing. The functions are still very rudimentary, will be cloned in WindowBuffer, and the View functions will call into WindowBuffer to ascertain the proper drawing area. Further, the disconnect of DrawingEngine and its owner must be dissolved. And Painter with its buffer... Both must be made aware of their drawing space so they do no attempt to write outside of it, but intelligently clip their drawing. Each with their own degree of agressiveness and reaction. 7104d4b: Assorted tidbits Found chicken/egg problem in Window constructor which was causing problems. Things are much better now. Decided against using UpdateQueue in preference to dual BRegion for the WindowBuffer. Window's UpdateSession may be used instead when I get further along. Decorators are very confused as to dirty regions, but I am preparing to over-provision WindowBuffer to optimize resize performance and to permit room to draw the decorator directly into the WindowBuffer. Clipping will prevent window content spill-over, but decorators will be able to draw over the window (but should avoid it, naturally). Decorator changes are coming soon - the order of initialization may change radically - but it may not... d4f54d1: Re-orientation to new model... -Decided to change the methodology for View's ConvertForDrawing() to convert up through the parents all of the way to the window. The window then does the final conversion based upon its type: Window: converts drawing to screen coordinate space OffscreenWindow: does no further conversion CompositeWindow: converts to WindowBuffer coordinate space (Others will inherit the behavior from Window, but I will investigate the need to override such behavior.) -Virtualized many functions in Window to facilitate a functional CompositeWindow typee so as to keep the code paths separate. -Making first steps to have WindowBuffer stay alive even after a Window's Quit() or destruction until all referencing objects have adapted or been destroyed. WindowBuffer is now a BReferenceable & only BReference<WindowBuffer> will be passed around. TODO: DrawingEngine will manually call AcquireReference() and ReleaseReference() if casting to WindowBuffer succeeds. Why: this greatly simplifies locking, and also permits lazy-recycling of allocated buffer spaces in the future. I believe all other changes are in-ine with the abovee. This will not build. Will probably spout out many many errors. Will certainly not link ;-) 7117024: Moving Along Further implementing CompositeWindow. Re-wrote WindowBuffer's _ResizeTo() function with tested & working code. Compiles, will not link. Much work to go. b59f6ce: Bug fix, misc... e8b91bd: Fixes Non-compositing mode now mostly works properly again. There are probably a few bugs here and there, but they should be minor(or obvious). Ran into an interesting situation where View::ConvertToWindow() somehow converts all of the way to the screen, which makes no sense... somewhere the drawing instructions are being converted from window coordinates to screen coordinates - and I can't find it... I checked in both View.cpp files (src/kits, and src/servers/app), ServerWindow (which receives the drawing messages from BView), and the ConvertToParent() code to try and solve this dilemma. I even had ever single view spout out its frame to make sure the view attached to the window had an origin of (0,0) - and they all did... Next commit will hopefully solve this... 443ba22: Bug fix Figured out the problem with View::ConvertForDrawing(*) - ConvertToParent when there is no parent results in an undesired result (though it seems like it shouldn't do anything.. the frame should be (0,0,rt, bt). c52e7f2: Continuing progress. CompositeHWInterface taking over for AccelratedHWInterface. CompositeWindow taking over for Window (for non-offscren windows only). Temporary B_RENDER_COMPOSITE flag being utilized to force a single window into compositing for testing. Logging levels reduced to eliminate tested code-paths. Further reductions forth-coming. DrawingEngine now capable of having a RenderingBuffer manually set via its public API. RenderingBuffer now capable of being aware of such changes to augment lazy-allocation techniques - or other uses (such as knowing when we are no longer being modified...). Builds. Runs. Works. Drawing doesn't seem to be re-routed to set RenderingBuffer, so there is some logging in place to trace that issue... eb34894: Bug fixes & more prep-work WindowBuffer: fWindowFrame was not being updated. Over-provisioning was being added at the wrong time - thereby not bein applied at all. Cleaned up the code and removed interim window frame as the window frame must change for each and every resize event. CompositeWindow Setup to use a new method to temporarily mark a test window as compositing. Decorator: Preparing to drastically change how drawing is handled in Decorator. Will implement BView-style drawing interfaces, and hide much of the tedium. This is important as a Decorator may draw in foreign coordinate systems - such as WindowBuffer's. All frames and drawing will be relative to the window frame. Move events will need to be blocked entirely from a custom decorator's awareness. app_server builds & runs. An odd memory leak is still occuring in relation, I believe, to WindowBuffer... which is an odd situation... after WindowBuffer is destroyed, some RAM seems to not be returned to the system. Will need to chase this down. 1e36fee: Correct oversight. WindowBuffer was meant to hold its largest size in both dimensions, but any time a new max was achieved in either dimension it'd lose the other dimension's previous setting. This commit resolves this. On a side note: verified performance increase of other commits in non-compositing mode. Slightly faster than anticipated. bd713a3: Test drawing WindowBuffer to frame buffer CompositeEngine::Draw() working better - also not locking exclusively & for a much shorter duration. There seems to be some issues with DrawBuffer(), it draws very quickly, but there are large black regions seemingly even outside the drawing region... very strange. Created AlphaRegion to hold and compute the WindowBuffer region's alpha areas as well as the screen's for fast reference. The theory is that the screen's alpha region will be updated for every window movement (focus changes, moving windows, minmizations, blocking, etc...) and each WindowBuffer's region will be largely stagnant, or will change relatively slowly. It is one consideration into the forthcoming Compositing Optimization Guide for Haiku application developers. 537a2ca: Cleaned up CompositingPrivate Haven't even tried compiling these changes. RenderSession may or may not persist, just exploring matters... Having hard drive difficulties so I thought it best to push these changes up ASAP. 388e1af: Coding with headache == hard Correcting mistakes and completing initial CompositingPrivate changes. Removed RenderSession, may have windows maintain visible regions. Compiles - haven't tested running yet, but there should be no new issues. 6fe0747: More client-server comms Flesh out more of the CompositeEngine communication protocol. There is currently a stalling issue with getCompositingConfig() in CompositingProvate. Began to flesh out the fundamental server-side requirements for BCompositeOverlay, which is a BBitmap which accepts views and will provide numerous special-purpose features (such as locking to mouse movement and likely other conditions). Decided to make over-provisioning configurable. Also re-worked BWindow::_RequestEffect() to not use a BMessage by internally converting an uint32 to BPrivate::effect_type. Builds & runs. Have observed a performance increase in non-composited mode. I believe this is due to the optimizations in the code-paths for ConvertForDrawing vs ConvertToScreenForDrawing. The latter, IIRC, used a side-effect to work up view hierarchy which resulted in numerous vtable lookups. Don't quote me on that though... long time since I looked at the original code ;-) My guess of +0.5fps in CompositePerfTest3 was about spot-on, seeing about +0.75fps in VMWare. 67b90e3: CompositeOverlay More CompositeOverlay work. I believe this should remain public API, but perhaps not until compositing is more stabilized. 6ad2af3: BCompositeOverlay Public API should now be final. Client code should be functional. Server-side code still just a place-holder. Compiles & links once again. TODO: need to convert rgb_color to a fill pattern based upon BBitmap's color space rather than using the accelerant's conversion in case the video driver uses a different pattern and will convert the bitmap before displaying on-screen. I doubt this is a problem on x86 these days, but other platforms will likely also desire the compositing features. 090b450: Server-side CompositeOverlay Setting up the server-side of things for BCompositeOverlay. Also touched a couple of other areas as I ran into things that need to be implemented now or in the future. Compiles - will not link (missing CompositeEngine::Hide(CompositeOverlay*) and Show(...)). 4687592: Adjust to requirements. Found most of the reason why the drawing was all weird... mostly due to clipping - which I anticipated... Further investigated the conversion requirements, and stripped out unneeded virtual overrides. Making some attempts to improve performance, I have investigated the need for alpha regions - determined they are more vital than ever if we hope to have CPU-based compositing with an acceptable performance level... Preparing for cursor overlays, and a few other tidbits. 1489f21: Coordinate conversion & optimization Added ability to convert back from the window's coordinate space to a view for various current and future uses. "Profiled" code paths to determine usage and performance, decided optimization was called for - and was surprised by the end result. CompositePerfTest3 went from 24FPS to 27FPS - with just 12bytes or so of RAM per view extra... Also cleans up the code nicely ;-) Wish I had more time... and that I weren't sick :-( 76dfc16: ScreenStateGrid & more ScreenStateGrid represents the visible screen as a grid of cells. It is just an unfinished header at this point. Made changes to some comments to better suit the understandability to the uninitiated (i.e.... everyone else but me...). Also preparing CompositeEngine to use ScreenStateGrid, and to re-purpose Desktop's window listing rather than having its own. Z-order will be handled by sorting the Desktop's window list. The desktop window will be window 0, and the top-most window will be at the highest index. Also a bit of extra loop unrolling to help speed up the final render task - more unrolling may be worthwhile, but it could be counter-productive at the same time... e12c27c: Poor scaling, so re-designed Quick-n-dirty performance test of a faux-ScreenStateGrid determined that the grid method would have poor scalability at higher resolutions. It was faster at 1024x768 and below, but from there became slower. Mutated ScreenStateGrid into CompositeScreenStates, which holds numerous regions an interplexes them to gain the necessary output regions. 57a09ef: Re-orient towards CompositeScreenStates Haven't test CompositeScreenStates yet, so that is next on my todo list (off git). CompositeEngine's crude test-mode Draw() function has been gutted as it was no longer usable. Once CompositeScreenStates is verified, I will be moving to direct full-mode compositing of all windows, working out the kinks as they come along. fe72079: CScreenStates verified (well enough for now, anyway) No changes needed to CScreenStates - seems to work like a charm. Re-oriented towards using it, will be working window events back up the (logical) object stack to assure all is well. Next temporary draw routine will cycle through every window, in order, in the dirty region and draw them. It will then perform the alpha-mode render. Performance will be sad, but it will be required to make further progress. [ looncraz <looncraz@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 64 files changed, 6316 insertions(+), 176 deletions(-) headers/os/interface/Bitmap.h | 1 + headers/os/interface/CompositeOverlay.h | 158 ++++ headers/os/interface/Window.h | 11 +- headers/private/app/CompositingPrivate.h | 190 ++++ headers/private/app/ServerProtocol.h | 31 + src/kits/app/CompositingPrivate.cpp | 395 ++++++++ src/kits/app/Jamfile | 1 + src/kits/interface/CompositeOverlay.cpp | 575 ++++++++++++ src/kits/interface/Jamfile | 1 + src/kits/interface/Window.cpp | 77 ++- src/servers/app/AppServer.cpp | 3 + src/servers/app/BitmapManager.cpp | 21 +- src/servers/app/Jamfile | 1 + src/servers/app/OffscreenServerWindow.cpp | 8 +- src/servers/app/OffscreenWindow.cpp | 32 +- src/servers/app/OffscreenWindow.h | 6 + src/servers/app/ProfileMessageSupport.cpp | 18 +- src/servers/app/RapidDebug.h | 36 + src/servers/app/RenderingBuffer.h | 5 + src/servers/app/Screen.cpp | 2 +- src/servers/app/ScreenManager.cpp | 4 +- src/servers/app/ServerApp.cpp | 21 +- src/servers/app/ServerPicture.cpp | 40 +- src/servers/app/ServerWindow.cpp | 157 +++- src/servers/app/View.cpp | 206 ++++- src/servers/app/View.h | 61 +- src/servers/app/Window.cpp | 220 +++++- src/servers/app/Window.h | 49 +- src/servers/app/decorator/Decorator.h | 1 + src/servers/app/drawing/AccelerantHWInterface.h | 3 +- src/servers/app/drawing/BitmapBuffer.cpp | 1 + src/servers/app/drawing/BitmapBuffer.h | 2 +- src/servers/app/drawing/DrawingEngine.cpp | 68 ++- src/servers/app/drawing/DrawingEngine.h | 9 +- src/servers/app/drawing/HWInterface.cpp | 4 +- src/servers/app/drawing/HWInterface.h | 5 +- src/servers/app/drawing/Jamfile | 2 + src/servers/app/drawing/Painter/Painter.cpp | 38 +- src/servers/app/drawing/Painter/Painter.h | 3 + src/servers/app/drawing/UpdateQueue.cpp | 14 +- src/servers/app/drawing/UpdateQueue.h | 9 +- .../app/drawing/compositing/AlphaRegion.cpp | 113 +++ src/servers/app/drawing/compositing/AlphaRegion.h | 78 ++ .../app/drawing/compositing/CompositeEffect.h | 36 + .../app/drawing/compositing/CompositeEngine.cpp | 773 ++++++++++++++++ .../app/drawing/compositing/CompositeEngine.h | 175 ++++ .../drawing/compositing/CompositeEngineClient.cpp | 28 + .../drawing/compositing/CompositeEngineClient.h | 26 + .../drawing/compositing/CompositeHWInterface.cpp | 128 +++ .../app/drawing/compositing/CompositeHWInterface.h | 47 + .../app/drawing/compositing/CompositeOverlay.cpp | 235 +++++ .../app/drawing/compositing/CompositeOverlay.h | 102 ++ .../drawing/compositing/CompositeScreenStates.cpp | 165 ++++ .../drawing/compositing/CompositeScreenStates.h | 108 +++ .../app/drawing/compositing/CompositeWindow.cpp | 416 +++++++++ .../app/drawing/compositing/CompositeWindow.h | 108 +++ .../app/drawing/compositing/CompositingPerfmon.cpp | 312 +++++++ .../app/drawing/compositing/CompositingPerfmon.h | 115 +++ src/servers/app/drawing/compositing/Jamfile | 28 + .../app/drawing/compositing/WindowBuffer.cpp | 739 +++++++++++++++ src/servers/app/drawing/compositing/WindowBuffer.h | 233 +++++ src/servers/app/drawing/drawing_support.h | 34 +- .../app/drawing/remote/RemoteHWInterface.cpp | 2 +- src/servers/app/drawing/remote/RemoteHWInterface.h | 2 +- ############################################################################ Commit: 8bcdc04f4d70593563c525f07d5dea55133a13f2 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Mar 23 02:10:44 2012 UTC Doing thing right - I hope Brought CompositeEngine.h more inline with app_server and fixed numerous little errors (I hate USB keyboards...). Changed UpdateQueue into HWUpdateQueue and created a new UpdateQueue as, basically, an interface class. Created CompositeUpdateQueue to act as a final-gathering place for areas in the back-buffer which need to be copied to the front buffer. Begin fleshing out CompositingPerfmon. Verified clean build status, have not verified run-time sanity, though there should be no effects at this point other than a slightly larger binary. ---------------------------------------------------------------------------- diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 8e448eb..4c8dd5c 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -21,7 +21,7 @@ #include "DrawingEngine.h" #include "RenderingBuffer.h" #include "SystemPalette.h" -#include "UpdateQueue.h" +#include "HWUpdateQueue.h" using std::nothrow; @@ -313,7 +313,7 @@ HWInterface::SetAsyncDoubleBuffered(bool doubleBuffered) if (doubleBuffered) { if (fUpdateExecutor != NULL) return; - fUpdateExecutor = new (nothrow) UpdateQueue(this); + fUpdateExecutor = new (nothrow) HWUpdateQueue(this); AddListener(fUpdateExecutor); } else { if (fUpdateExecutor == NULL) @@ -355,12 +355,12 @@ HWInterface::Invalidate(const BRect& frame) { if (IsDoubleBuffered()) { #if 0 -// NOTE: The UpdateQueue works perfectly fine, but it screws the +// NOTE: The HWUpdateQueue works perfectly fine, but it screws the // flicker-free-ness of the double buffered rendering. The problem being the -// asynchronous nature. The UpdateQueue will transfer regions of the screen +// asynchronous nature. The HWUpdateQueue will transfer regions of the screen // which have been clean at the time we are in this function, but which have // been damaged meanwhile by drawing into them again. All in all, the -// UpdateQueue is good for reducing the number of times that the transfer +// HWUpdateQueue is good for reducing the number of times that the transfer // is performed, and makes it happen during refresh only, but until there // is a smarter way to synchronize this all better, I've disabled it. if (fUpdateExecutor != NULL) { diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index ab0f7bb..630302d 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -29,7 +29,7 @@ class EventStream; class Overlay; class RenderingBuffer; class ServerBitmap; -class UpdateQueue; +class HWUpdateQueue; enum { @@ -161,7 +161,7 @@ public: virtual status_t InvalidateRegion(BRegion& region); virtual status_t Invalidate(const BRect& frame); // while as CopyBackToFront() actually performs the operation - // either directly or asynchronously by the UpdateQueue thread + // either directly or asynchronously by the HWUpdateQueue thread virtual status_t CopyBackToFront(const BRect& frame); protected: @@ -257,7 +257,7 @@ protected: int fVGADevice; private: - UpdateQueue* fUpdateExecutor; + HWUpdateQueue* fUpdateExecutor; BList fListeners; }; diff --git a/src/servers/app/drawing/HWUpdateQueue.cpp b/src/servers/app/drawing/HWUpdateQueue.cpp new file mode 100644 index 0000000..b6d5bb1 --- /dev/null +++ b/src/servers/app/drawing/HWUpdateQueue.cpp @@ -0,0 +1,157 @@ +/* + * Copyright 2005-2008 Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include "HWUpdateQueue.h" + +#include <new> +#include <stdio.h> +#include <string.h> + + +//#define TRACE_UPDATE_QUEUE +#ifdef TRACE_UPDATE_QUEUE +# include <FunctionTracer.h> +# include <String.h> + + static int32 sFunctionDepth = -1; +# define CALLED(x...) FunctionTracer _ft("HWUpdateQueue", __FUNCTION__, \ + sFunctionDepth) +# define TRACE(x...) { BString _to; \ + _to.Append(' ', (sFunctionDepth + 1) * 2); \ + printf("%s", _to.String()); printf(x); } +#else +# define CALLED(x...) +# define TRACE(x...) +#endif + + +// constructor +HWUpdateQueue::HWUpdateQueue(HWInterface* interface) + : + UpdateQueue("AppServer_HWUpdateQueue"), + fQuitting(false), + fInterface(interface), + fUpdateExecutor(B_BAD_THREAD_ID), + fRetraceSem(B_BAD_SEM_ID), + fRefreshDuration(1000000 / 60) +{ + CALLED(); + TRACE("this: %p\n", this); + TRACE("fInterface: %p\n", fInterface); +} + +// destructor +HWUpdateQueue::~HWUpdateQueue() +{ + CALLED(); + + Shutdown(); +} + +// FrameBufferChanged +void +HWUpdateQueue::FrameBufferChanged() +{ + CALLED(); + + Init(); +} + +// Init +status_t +HWUpdateQueue::Init() +{ + CALLED(); + + Shutdown(); + + fRetraceSem = fInterface->RetraceSemaphore(); +// fRefreshDuration = fInterface->... + + TRACE("fRetraceSem: %ld, fRefreshDuration: %lld\n", + fRetraceSem, fRefreshDuration); + + fQuitting = false; + fUpdateExecutor = spawn_thread(_ExecuteUpdatesEntry, "update queue runner", + B_REAL_TIME_PRIORITY, this); + if (fUpdateExecutor < B_OK) + return fUpdateExecutor; + + return resume_thread(fUpdateExecutor); +} + +// Shutdown +void +HWUpdateQueue::Shutdown() +{ + CALLED(); + + if (fUpdateExecutor < B_OK) + return; + fQuitting = true; + status_t exitValue; + wait_for_thread(fUpdateExecutor, &exitValue); + fUpdateExecutor = B_BAD_THREAD_ID; +} + + +// _ExecuteUpdatesEntry +int32 +HWUpdateQueue::_ExecuteUpdatesEntry(void* cookie) +{ + HWUpdateQueue *gc = (HWUpdateQueue*)cookie; + return gc->_ExecuteUpdates(); +} + +// _ExecuteUpdates +int32 +HWUpdateQueue::_ExecuteUpdates() +{ + while (!fQuitting) { + status_t err; + if (fRetraceSem >= 0) { + bigtime_t timeout = system_time() + fRefreshDuration * 2; +// TRACE("acquire_sem_etc(%lld)\n", timeout); + do { + err = acquire_sem_etc(fRetraceSem, 1, + B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout); + } while (err == B_INTERRUPTED && !fQuitting); + } else { + bigtime_t timeout = system_time() + fRefreshDuration; +// TRACE("snooze_until(%lld)\n", timeout); + do { + err = snooze_until(timeout, B_SYSTEM_TIMEBASE); + } while (err == B_INTERRUPTED && !fQuitting); + } + if (fQuitting) + return B_OK; + switch (err) { + case B_OK: + case B_TIMED_OUT: + // execute updates + if (fInterface->LockParallelAccess()) { + if (Lock()) { + int32 count = fUpdateRegion.CountRects(); + if (count > 0) { + TRACE("CopyBackToFront() - rects: %ld\n", count); + // NOTE: not using the BRegion version, since that + // doesn't take care of leaving out and compositing + // the cursor. + for (int32 i = 0; i < count; i++) + fInterface->CopyBackToFront( + fUpdateRegion.RectAt(i)); + fUpdateRegion.MakeEmpty(); + } + Unlock(); + } + fInterface->UnlockParallelAccess(); + } + break; + default: + return err; + } + } + return B_OK; +} + diff --git a/src/servers/app/drawing/HWUpdateQueue.h b/src/servers/app/drawing/HWUpdateQueue.h new file mode 100644 index 0000000..5834276 --- /dev/null +++ b/src/servers/app/drawing/HWUpdateQueue.h @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2008 Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef UPDATE_QUEUE_H +#define UPDATE_QUEUE_H + +#include <List.h> +#include <Locker.h> +#include <OS.h> +#include <Region.h> + +#include "HWInterface.h" +#include "UpdateQueue.h" + +/* + For future reference, this is used in HWInterface and is called the + fUpdateExecutor. It is meant to be used for double-buffering. +*/ + +class HWUpdateQueue : public UpdateQueue, public HWInterfaceListener { + public: + HWUpdateQueue(HWInterface* interface); + virtual ~HWUpdateQueue(); + + virtual void FrameBufferChanged(); + + status_t Init(); + void Shutdown(); + + private: + static int32 _ExecuteUpdatesEntry(void *cookie); + int32 _ExecuteUpdates(); + + volatile bool fQuitting; + HWInterface* fInterface; + + thread_id fUpdateExecutor; + sem_id fRetraceSem; + bigtime_t fRefreshDuration; +}; + +#endif // UPDATE_QUEUE_H diff --git a/src/servers/app/drawing/Jamfile b/src/servers/app/drawing/Jamfile index ee5c465..b81efa3 100644 --- a/src/servers/app/drawing/Jamfile +++ b/src/servers/app/drawing/Jamfile @@ -7,6 +7,7 @@ UsePrivateSystemHeaders ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app font ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing compositing ] ; 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 ] ; @@ -18,6 +19,7 @@ StaticLibrary libasdrawing.a : BitmapBuffer.cpp drawing_support.cpp DrawingEngine.cpp + HWUpdateQueue.cpp MallocBuffer.cpp UpdateQueue.cpp PatternHandler.cpp @@ -28,5 +30,6 @@ StaticLibrary libasdrawing.a : HWInterface.cpp ; +SubInclude HAIKU_TOP src servers app drawing compositing ; SubInclude HAIKU_TOP src servers app drawing Painter ; SubInclude HAIKU_TOP src servers app drawing remote ; diff --git a/src/servers/app/drawing/UpdateQueue.cpp b/src/servers/app/drawing/UpdateQueue.cpp index d16a3e3..dd4394b 100644 --- a/src/servers/app/drawing/UpdateQueue.cpp +++ b/src/servers/app/drawing/UpdateQueue.cpp @@ -1,172 +1,40 @@ -/* - * Copyright 2005-2008 Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. - */ -#include "UpdateQueue.h" - -#include <new> -#include <stdio.h> -#include <string.h> +#include <Rect.h> +#include <Region.h> -//#define TRACE_UPDATE_QUEUE -#ifdef TRACE_UPDATE_QUEUE -# include <FunctionTracer.h> -# include <String.h> - static int32 sFunctionDepth = -1; -# define CALLED(x...) FunctionTracer _ft("UpdateQueue", __FUNCTION__, \ - sFunctionDepth) -# define TRACE(x...) { BString _to; \ - _to.Append(' ', (sFunctionDepth + 1) * 2); \ - printf("%s", _to.String()); printf(x); } -#else -# define CALLED(x...) -# define TRACE(x...) -#endif +#include "UpdateQueue.h" -// constructor -UpdateQueue::UpdateQueue(HWInterface* interface) +UpdateQueue::UpdateQueue(const BString & name) : - BLocker("AppServer_UpdateQueue"), - fQuitting(false), - fInterface(interface), - fUpdateRegion(), - fUpdateExecutor(B_BAD_THREAD_ID), - fRetraceSem(B_BAD_SEM_ID), - fRefreshDuration(1000000 / 60) -{ - CALLED(); - TRACE("this: %p\n", this); - TRACE("fInterface: %p\n", fInterface); -} - -// destructor -UpdateQueue::~UpdateQueue() -{ - CALLED(); - - Shutdown(); -} - -// FrameBufferChanged -void -UpdateQueue::FrameBufferChanged() -{ - CALLED(); - - Init(); -} - -// Init -status_t -UpdateQueue::Init() -{ - CALLED(); - - Shutdown(); - - fRetraceSem = fInterface->RetraceSemaphore(); -// fRefreshDuration = fInterface->... + BLocker(name.String()), + fName(name) + { + } - TRACE("fRetraceSem: %ld, fRefreshDuration: %lld\n", - fRetraceSem, fRefreshDuration); +// copy constructor +UpdateQueue::UpdateQueue(const UpdateQueue& clone) + : + BLocker(clone.fName.String()), + fUpdateRegion(clone.fUpdateRegion), + fName(clone.fName) + { + } - fQuitting = false; - fUpdateExecutor = spawn_thread(_ExecuteUpdatesEntry, "update queue runner", - B_REAL_TIME_PRIORITY, this); - if (fUpdateExecutor < B_OK) - return fUpdateExecutor; - - return resume_thread(fUpdateExecutor); -} -// Shutdown -void -UpdateQueue::Shutdown() -{ - CALLED(); +UpdateQueue::~UpdateQueue() +{ /*lock or test for lock?*/ } - if (fUpdateExecutor < B_OK) - return; - fQuitting = true; - status_t exitValue; - wait_for_thread(fUpdateExecutor, &exitValue); - fUpdateExecutor = B_BAD_THREAD_ID; -} // AddRect -void -UpdateQueue::AddRect(const BRect& rect) +void UpdateQueue::AddRect(const BRect& rect) { if (!rect.IsValid()) return; - CALLED(); - if (Lock()) { fUpdateRegion.Include(rect); Unlock(); - } + } // what about when we fail to obtain the lock!?! } - -// _ExecuteUpdatesEntry -int32 -UpdateQueue::_ExecuteUpdatesEntry(void* cookie) -{ - UpdateQueue *gc = (UpdateQueue*)cookie; - return gc->_ExecuteUpdates(); -} - -// _ExecuteUpdates -int32 -UpdateQueue::_ExecuteUpdates() -{ - while (!fQuitting) { - status_t err; - if (fRetraceSem >= 0) { - bigtime_t timeout = system_time() + fRefreshDuration * 2; -// TRACE("acquire_sem_etc(%lld)\n", timeout); - do { - err = acquire_sem_etc(fRetraceSem, 1, - B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout); - } while (err == B_INTERRUPTED && !fQuitting); - } else { - bigtime_t timeout = system_time() + fRefreshDuration; -// TRACE("snooze_until(%lld)\n", timeout); - do { - err = snooze_until(timeout, B_SYSTEM_TIMEBASE); - } while (err == B_INTERRUPTED && !fQuitting); - } - if (fQuitting) - return B_OK; - switch (err) { - case B_OK: - case B_TIMED_OUT: - // execute updates - if (fInterface->LockParallelAccess()) { - if (Lock()) { - int32 count = fUpdateRegion.CountRects(); - if (count > 0) { - TRACE("CopyBackToFront() - rects: %ld\n", count); - // NOTE: not using the BRegion version, since that - // doesn't take care of leaving out and compositing - // the cursor. - for (int32 i = 0; i < count; i++) - fInterface->CopyBackToFront( - fUpdateRegion.RectAt(i)); - fUpdateRegion.MakeEmpty(); - } - Unlock(); - } - fInterface->UnlockParallelAccess(); - } - break; - default: - return err; - } - } - return B_OK; -} - diff --git a/src/servers/app/drawing/UpdateQueue.h b/src/servers/app/drawing/UpdateQueue.h index f8c5614..de5155f 100644 --- a/src/servers/app/drawing/UpdateQueue.h +++ b/src/servers/app/drawing/UpdateQueue.h @@ -1,41 +1,37 @@ +#ifndef UPDATE_QUEUE_INTERFACE_H +#define UPDATE_QUEUE_INTERFACE_H + /* - * Copyright 2005-2008 Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef UPDATE_QUEUE_H -#define UPDATE_QUEUE_H + With the advent of the CompositeEngine it is better + to abstract the interface to minimize other code + changes and to make mode changes painless and fast. + + As such we have a copy constructor and handle the common + tasks here. + + It is VERY simple... + + This stores the areas which needs to be copied from the + back buffer to the front buffer (video card - normally). +*/ -#include <List.h> #include <Locker.h> -#include <OS.h> #include <Region.h> +#include <Rect.h> +#include <String.h> -#include "HWInterface.h" - - -class UpdateQueue : public BLocker, public HWInterfaceListener { +class UpdateQueue: public BLocker{ public: - UpdateQueue(HWInterface* interface); - virtual ~UpdateQueue(); - - virtual void FrameBufferChanged(); - - status_t Init(); - void Shutdown(); - - void AddRect(const BRect& rect); - - private: - static int32 _ExecuteUpdatesEntry(void *cookie); - int32 _ExecuteUpdates(); + UpdateQueue(const BString& name); + UpdateQueue(const UpdateQueue&); + virtual ~UpdateQueue(); + + void AddRect(const BRect&); + protected: + BRegion fUpdateRegion; + BString fName; +}; - volatile bool fQuitting; - HWInterface* fInterface; - BRegion fUpdateRegion; - thread_id fUpdateExecutor; - sem_id fRetraceSem; - bigtime_t fRefreshDuration; -}; +#endif -#endif // UPDATE_QUEUE_H diff --git a/src/servers/app/drawing/compositing/CompositeEngine.h b/src/servers/app/drawing/compositing/CompositeEngine.h new file mode 100644 index 0000000..eb34d55 --- /dev/null +++ b/src/servers/app/drawing/compositing/CompositeEngine.h @@ -0,0 +1,247 @@ +/* + * Copyright 2012, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Joseph Groover <looncraz@xxxxxxxxxxx> + */ +#ifndef COMPOSITING_ENGINE_H +#define COMPOSITING_ENGINE_H + + +#include <ObjectList.h> +#include <OS.h> +#include <String.h> + +#include "HWInterface.h" +#include "RenderingBuffer.h" +#include "ServerBitmap.h" +#include "UpdateQueue.h" + +/* + performance_mode determines the rate at which we will update changes + in the back-buffer into the front-buffer. + We batch updates together and change the performance mode based on the + amount of changes made, the area covered - along with app-requested + performance modes (new API) or ServerWindow requests based on user + action (window resize/move, typing, etc...) + Just becauuse we are in, say, FULL_PERFORMANCE_MODE does not mean we + will actually be operating at a full 60 fps, that is just the reference + update interval (1/60th of a second [minus some time for overhead]) +*/ +enum performance_mode{ + STOP_PERFORMANCE_MODE = 0, // 0 fps (screen off) + SLOW_PERFORMANCE_MODE = 5, // <= 5 fps (sitting at the desktop) + MILD_PERFORMANCE_MODE = 15, // < 15 fps (normal GUIs, low motion) + HIGH_PERFORMANCE_MODE = 30, // < 30 fps (videos, moderate motion) + FULL_PERFORMANCE_MODE = 60, // ~ 60 fps (animations, moving video) + SYNC_PERFORMANCE_MODE = 120,// @ refresh rate - up to 120hz + WILD_PERFORMANCE_MODE = 1000// max power! - up to 1000fps... +}; + +enum composite_mode{ + NORMAL_COMPOSITE = 0//, // CPU[s] do[es] the work + // ACCEL_COMPOSITE, // GPU accelerated + // MIXED_COMPOSITE, // CPU does some, GPU does some + // XGPUS_COMPOSITE, // multiple GPUs for compositing + // XHEAD_COMPOSITE // treat monitors separately - + // one workspace per monitor ;-) +}; + +/* + composite_client_type + + It is often useful for the CompositeEngine to know what type of client + is denying or making a request so as to react properly. + + Basically, if a Desktop requests STOP_PERFORMANCE_MODE, that means the + monitor has gone to black (or is going to sleep). If a Window asks, we + will outright deny it. If a workspace asks, and we are in XHEAD_COMPOSITE, + then we stop updates for the screen for that workspace, only increasing + when the workspace permits us. + + This allows us to not touch the code too much in the future. + + A CompositeEngineClient can identify itself as being of one of types + as follows: +*/ +enum composite_client_type{ + ANONYMOUS_COMPOSITE_CLIENT = 0, + DESKTOP_COMPOSITE_CLIENT, + DESKTOPWINDOW_COMPOSITE_CLIENT, + WORKSPACE_COMPOSITE_CLIENT, + WINDOW_COMPOSITE_CLIENT, + SERVERWINDOW_COMPOSITE_CLIENT, + DIRECTWINDOW_COMPOSITE_CLIENT, + UPDATEQUEUE_COMPOSITE_CLIENT +}; + +class Window; + +class CompositeEngineClient{ +public: + CompositeEngineClient( const BString & name, + composite_client_type = + ANONYMOUS_COMPOSITE_CLIENT); + virtual ~CompositeEngineClient(); + + virtual void CompositingEnabled(bool enabled) = 0; + + + // optional: + + // if you need to do something BEFORE compositing takes over + // or before it ceases to render you need to override one of the following: + virtual void CompositingEnabling(); + virtual void CompositingDisabling(); + + virtual void CompositingChanged(performance_mode, + composite_mode); + virtual void CompositingPerformance(bool isLow = true); + + // affect operations + + // When a mode change is to be made we ask our clients if it is acceptable. + // Your opinion is just that - an opinion ;-) Unless you are a Desktop... + virtual bool CompositingModesRequested(performance_mode, + composite_mode); + + + void MarkScreenRegionDirty(BRegion&); + + // tell the composite engine that you need to be treated better + // or that you are being treated too well. + // There are five (unnamed) priority levels (0-4) + // everyone starts at zero (lowest priority). + void IncreaseCompositeClientPriority(); + void DecreaseCompositeClientPriority(); + void SetCompositeClientPriority(uint8); + + uint8 CompositeClientPriorityLevel() const; + + // If requested mode (or higher) is achieved, true is returned. + // there are few scenarios in which these will fail... + bool SuggestCompositingMode(performance_mode, + composite_mode = NORMAL_COMPOSITE); + + bool RequireCompositingMode(performance_mode, + composite_mode = NORMAL_COMPOSITE); + +}; + + +class CompositeEngine : public HWInterfaceListener{ +public: + explicit CompositeEngine(); + ~CompositeEngine(); // no use for a vtable... + + // without a HWInterface we can't push out to the hardware + bool SetHWInterface(HWInterface* interface); + HWInterface* GetHWInterface() const; + + bool IsCompositingEnabled() const; + status_t SetCompositingEnabled(bool enable); + // synchronous + + size_t TotalMemoryUsage(); + size_t LimitMemoryUsage(size_t); + // returns actual limit approved + + size_t MemoryLimit() const; + + // Clients + status_t AttachClient(CompositeEngineClient* + listener); + status_t DetachClient(CompositeEngineClient* + listener); + + uint8 CurrentFPS() const; + uint8 MaxFPS() const; + + performance_mode PerformanceMode() const; + bool RequirePerformanceMode(performance_mode mode); + // if we can't get the mode (or higher) we don't try to elevate + // we simply return false and remain in whatever mode we were + // already in. + + bool SuggestPerformanceMode(performance_mode mode); + // SuggestPerformanceMode() will do its best to elevate to as + // close to the requested mode as possible. The reasons for + // the mode to not elevate are as follows: + // Low memory, slow front buffer access, system limits, + // power saving mode, etc... + + + // back-buffer operations + void Copy(BRect src, BRect dest); + void Move(BRect src, BRect dest); + // updates dirty areas as well + + void Invalidate(BRect rect); + void Fill(BRect rect, rgb_color); + + UpdateQueue* GetUpdateQueue() const; + // if compositing is enabled we return CompositeUpdateQueue, + // otherwise we will return HWUpdateQueue + + void SetDirty(BRegion& region); + void SetDirty(Window* window, BRegion& region); + + ServerBitmap* GetBitmap(BRect rect); + + // color_space must equal B_RGBA32 + bool DrawBitmap(BRect, ServerBitmap*); + bool DrawBitmap(BPoint, ServerBitmap*); + + void DrawWindow(Window*); + + void SetFullScreenWindow(Window*); + // disables background updates... + + // full-screen fading (synchronous) + void FadeOut(); + void FadeIn(); + + void SetGreyscale(bool); + bool IsGreyscale() const; + + + +private: + static int32 _MasterControlThread(void*); + static int32 _SlaveRenderThread(void*); + static int32 _BackToFrontThread(void*); + + BRect _NextUpdateRect(bool&); + uint8 _NextUpdateBatchWeight(); + void _PushToFront(); + void _SetPerformanceMode(performance_mode); + + BLocker fClientsLock, + fModeSwitchLock, + fMasterLock; + + BObjectList<CompositeEngineClient> + fClients; + + uint8 fFrames_Max, + fFrames_Average, + fFrames_Target, + fUpdates_PendingPriority; + + bigtime_t fUpdate_DesiredInterval, + fUpdate_NextTime, + fEngine_InstantiatedTime, + fEngine_EnabledTime; + + performance_mode fPerformanceMode, + fPerformanceMode_Last; + + bool fCompositingEnabled : 1; + +}; + +extern "C" CompositeEngine* gCompositeEngine; + +#endif // COMPOSITING_ENGINE_H + diff --git a/src/servers/app/drawing/compositing/CompositeUpdateQueue.cpp b/src/servers/app/drawing/compositing/CompositeUpdateQueue.cpp new file mode 100644 index 0000000..cabc9ea --- /dev/null +++ b/src/servers/app/drawing/compositing/CompositeUpdateQueue.cpp @@ -0,0 +1,4 @@ +#include "CompositeUpdateQueue.h" + + + diff --git a/src/servers/app/drawing/compositing/CompositeUpdateQueue.h b/src/servers/app/drawing/compositing/CompositeUpdateQueue.h new file mode 100644 index 0000000..155e271 --- /dev/null +++ b/src/servers/app/drawing/compositing/CompositeUpdateQueue.h @@ -0,0 +1,47 @@ +#ifndef COMPOSITE_UPDATE_QUEUE_H +#define COMPOSITE_UPDATE_QUEUE_H + +/* + CompositeUpdateQueue + Accumulates all dirty areas of the back-buffer for they + can be copied to the front buffer on demand. + + Unlike HWUpdateQueue, the code for the copy is not here - + it is in the CompositeEngine. +*/ + +#include "CompositeEngine.h" +#include "UpdateQueue.h" + +class CompositeUpdateQueue : public UpdateQueue, public CompositeEngineClient{ + public: + explicit CompositeUpdateQueue(); + virtual ~CompositeUpdateQueue(); + + void CompositingEnabling(); + void CompositingDisabling(); + + void CompositingEnabled(bool); + void CompositingChanged(performance_mode, + composite_mode); + + // ALL functions lock, unless stated... + + // number of rects in the region... + int32 CountPendingUpdates(); + + /* + PendingUpdateArea() calculates the pixel area which the + pending updates cover. By area, I mean width * height... + + The stopMath parameter tells us to stop accumulating once + we hit that particular area of coveragee. If we hit that + area, we return stopMath (even if we calculated to higher). + */ + int32 PendingUpdateArea(int32 stopMath = 10000); + + BRegion* UpdateRegion(); +}; + + +#endif // COMPOSITE_UPDATE_QUEUE_H diff --git a/src/servers/app/drawing/compositing/CompositingPerfmon.h b/src/servers/app/drawing/compositing/CompositingPerfmon.h new file mode 100644 index 0000000..7056283 --- /dev/null +++ b/src/servers/app/drawing/compositing/CompositingPerfmon.h @@ -0,0 +1,47 @@ +#ifndef COMPOSITING_PERFORMANCE_MONITOR_H +#define COMPOSITING_PERFORMANCE_MONITOR_H + + +/* + CompositingPerfmon is informed of every performance-related bit of + information the CompositeEngine generates. + + Very simple at this point. +*/ + +class CompositingPerfmon{ + public: + CompositingPerfmon(bool enable = false); + ~CompositingPerfmon(); + + bool MonitoringEnabled() const; + + // determines frame rate & avg cost. + void BackToFrontBegins (); + void BackToFrontEnds (); + + // triple buffering + void BackBufferSwapBegins(); + void BackBufferSwapEnds (); + + // only on full-window re-compositing + void RenderWindowBegins (Window*); + void RenderWindowEnds (Window*); + + + // enabling / disabling compositing... + void DisableBegins (); + void DisableEnds (); + + void EnableBegins (); + void EnableEnds (); + + + + + +}; + + +#endif + diff --git a/src/servers/app/drawing/compositing/Jamfile b/src/servers/app/drawing/compositing/Jamfile new file mode 100644 index 0000000..8751fc3 --- /dev/null +++ b/src/servers/app/drawing/compositing/Jamfile @@ -0,0 +1,18 @@ +SubDir HAIKU_TOP src servers app drawing compositing ; + +UseLibraryHeaders agg ; +UsePrivateHeaders app graphics interface kernel shared ; +UsePrivateHeaders [ FDirName graphics common ] ; +UsePrivateSystemHeaders ; + +UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app font ] ; +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 $(HAIKU_FREETYPE_HEADERS) : true ; + +StaticLibrary libasdrawing.a : + CompositeUpdateQueue.cpp +; ############################################################################ Commit: 58fcae348665fa57b49ba0f675d857218ed7382d Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sat Mar 24 00:15:18 2012 UTC Finally a working man's commit... Much future planning (immediate future...), app_server communication protocol setup started, fixed a few things, changed some more, yadda yadda. All compiles, but will not link. That is intentional (lets me know where I am going next in case I forget to add a note to my TODO). ---------------------------------------------------------------------------- diff --git a/headers/os/interface/Window.h b/headers/os/interface/Window.h index 03a63e1..ae3f6d0 100644 --- a/headers/os/interface/Window.h +++ b/headers/os/interface/Window.h @@ -240,6 +240,11 @@ public: bool IsModal() const; bool IsFloating() const; + virtual void SetDrawingMode(drawing_mode mode); + drawing_mode DrawingMode() const; + + bool IsCompositingEnabled() const; + status_t SetWindowAlignment(window_alignment mode, int32 h, int32 hOffset = 0, int32 width = 0, int32 widthOffset = 0, @@ -352,7 +357,10 @@ private: void _GetDecoratorSize(float* _borderWidth, float* _tabHeight) const; - +protected: + bool _SetFullscreenCompositeModeEnabled(bool); + bigtime_t _DimEffect_ByHalf(); + bigtime_t _DimEffect_ToNormal(); private: char* fTitle; int32 _unused0; diff --git a/headers/private/app/CompositingPrivate.h b/headers/private/app/CompositingPrivate.h new file mode 100644 index 0000000..ff196e4 --- /dev/null +++ b/headers/private/app/CompositingPrivate.h @@ -0,0 +1,160 @@ +#ifndef COMPOSITING_PRIVATE_H +#define COMPOSITING_PRIVATE_H + +#include <OS.h> +#include <String.h> + +class BWindow; + +namespace BPrivate{ + +/* + performance_mode determines the rate at which we will update changes + in the back-buffer into the front-buffer. + We batch updates together and change the performance mode based on the + amount of changes made, the area covered - along with app-requested + performance modes (new API) or ServerWindow requests based on user + action (window resize/move, typing, etc...) + Just becauuse we are in, say, FULL_PERFORMANCE_MODE does not mean we + will actually be operating at a full 60 fps, that is just the reference + update interval (1/60th of a second [minus some time for overhead]) +*/ +enum performance_mode{ + STOP_PERFORMANCE_MODE = 0, // 0 fps (screen off) + SLOW_PERFORMANCE_MODE = 5, // <= 5 fps (sitting at the desktop) + MILD_PERFORMANCE_MODE = 15, // < 15 fps (normal GUIs, low motion) + HIGH_PERFORMANCE_MODE = 30, // < 30 fps (videos, moderate motion) + FULL_PERFORMANCE_MODE = 60, // ~ 60 fps (animations, moving video) + SYNC_PERFORMANCE_MODE = 120,// @ refresh rate - up to 120hz + WILD_PERFORMANCE_MODE = 1000// max power! - up to 1000fps... +}; + +enum composite_mode{ + NORMAL_COMPOSITE = 0//, // CPU[s] do[es] the work + // ACCEL_COMPOSITE, // GPU accelerated + // MIXED_COMPOSITE, // CPU does some, GPU does some + // XGPUS_COMPOSITE, // multiple GPUs for compositing + // XHEAD_COMPOSITE // treat monitors separately - + // one workspace per monitor ;-) +}; + +/* + composite_client_type + + It is often useful for the CompositeEngine to know what type of client + is denying or making a request so as to react properly. + + Basically, if a Desktop requests STOP_PERFORMANCE_MODE, that means the + monitor has gone to black (or is going to sleep). If a Window asks, we + will outright deny it. If a workspace asks, and we are in XHEAD_COMPOSITE, + then we stop updates for the screen for that workspace, only increasing + when the workspace permits us. + + This allows us to not touch the code too much in the future. + + A CompositeEngineClient can identify itself as being of one of types + as follows: +*/ +enum composite_client_type{ + ANONYMOUS_COMPOSITE_CLIENT = 0, + DESKTOP_COMPOSITE_CLIENT, + DESKTOPWINDOW_COMPOSITE_CLIENT, + WORKSPACE_COMPOSITE_CLIENT, + WINDOW_COMPOSITE_CLIENT, + SERVERWINDOW_COMPOSITE_CLIENT, + DIRECTWINDOW_COMPOSITE_CLIENT, + UPDATEQUEUE_COMPOSITE_CLIENT, + FULLSCREEN_COMPOSITE_CLIENT // screensaver, game, etc... +}; + + +/* +typedef struct CompositingStatus{ + bool enabled; + bigtime_t timeEnabled; + performance_mode performanceMode; + composite_mode compositingMode; + int32 frameRate, + averagesUpdates; // per refresh + + size_t memoryLimit, + memoryUsageEstimate; + + bool mouseIsOverlay, + shadowsEnabled, + dimmingEnabled, + fullscreenActive; + + BString mouseOverlay; // by name +}; +*/ + +uint8 compositingPerfLevelForPerfMode(performance_mode); +performance_mode compositingPerfModeForPerfLevel(uint8); +int32 compositingRateForPerfMode(performance_mode); + +// user-side onlly - don't use from within app_server +bool getCompositingEnabled(); +bool setCompositingEnabled(bool); + +bool setCompositingMode(composite_mode); +composite_mode getCompositingMode(); + +performance_mode getCompositingPerformance(); +status_t setCompositingPerformance(performance_mode); + +int32 getCompositingFPS(); + +size_t getCompositingMemoryLimit(); +size_t setCompositingMemoryLimit(size_t); + // returns new limit - you may never get an exact + // match... minimum is about 1.5*frame buffer size + +size_t getCompositingMemoryUsageEstimate(); +size_t getCompositingMemoryUsage(); + // avoid calling this, it forcefully calculates the + // actual usage. + +//CompositingStatus getCompositingStatus(); + // this (will be) a heavy call, use only when you need + // all the information at once + +BString getCompositingMouseOverlay(); +bool setCompositingMouseOverlay(const BString&); + // by name, not path + +bool getCompositingFullscreenMode(); +status_t setCompositingFullscreenMode(BWindow*, bool); + // set a window to be treated as full-screen + // ALL other updates cease until the window is destroyed + // or this is called again, with false to disable the mode. + + +// TODO: consider moving built-in effects to its own place... + +bool getShadowEffectsEnabled(); +bool setShadowEffectsEnabled(bool); +/* +BMessage* getShadowEffectsConfig(); +bool setShadowEffectsConfig(); +*/ +// returns time until effect should be complete +bigtime_t dimEffect_ScreenByHalf(); +bigtime_t dimEffect_ScreenToBlack(); +bigtime_t dimEffect_ScreenToNormal(); + +// BWindow has its own internal method we access +bigtime_t dimEffect_WindowByHalf(BWindow*); +bigtime_t dimEffect_WindowToNormal(BWindow*); +/* +bool setEffect_Addon(BString); +BString getEffect_Addon(); +*/ + +}; + + + + +#endif + diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index ef7c439..946d457 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -112,6 +112,41 @@ enum { AS_SET_SIZE_LIMITS, AS_ACTIVATE_WINDOW, AS_IS_FRONT_WINDOW, + AS_SET_DRAWING_MODE, + AS_GET_DRAWING_MODE, + + // Compositing definitions + AS_SET_COMPOSITING_ENABLED, + AS_GET_COMPOSITING_ENABLED, + AS_SET_COMPOSITING_MODE, + AS_GET_COMPOSITING_MODE, + AS_SET_COMPOSITING_PERFORMANCE, + AS_GET_COMPOSITING_PERFORMANCE, + AS_GET_COMPOSITING_FPS, + AS_SET_COMPOSITING_MEMLIMT, + AS_GET_COMPOSITING_MEMLIMT, + AS_GET_COMPOSITING_MEMUSAGE_ESTIMATE, + AS_GET_COMPOSITING_MEMUSAGE, + AS_GET_COMPOSITING_STATUS, + AS_SET_COMPOSITING_MOUSE_OVERLAY, + AS_GET_COMPOSITING_MOUSE_OVERLAY, + AS_GET_COMPOSITING_DIMMING_ENABLED, + AS_SET_COMPOSITING_DIMMING_ENABLED, + AS_GET_COMPOSITING_FULLSCREEN_MODE, + AS_SET_COMPOSITING_FULLSCREEN_MODE, + + // built-in effects + AS_SET_EFFECT_SHADOWS_ENABLED, + AS_GET_EFFECT_SHADOWS_ENABLED, + AS_SET_EFFECT_SHADOWS_CONFIG, + AS_GET_EFFECT_SHADOWS_CONFIG, + AS_DIM_EFFECT_SCREEN_BY_HALF, + AS_DIM_EFFECT_SCREEN_TO_BLACK, + AS_DIM_EFFECT_SCREEN_TO_NORMAL, + AS_DIM_EFFECT_WINDOW_BY_HALF, + AS_DIM_EFFECT_WINDOW_TO_NORMAL, + AS_SET_EFFECT_ADD_ON, + AS_GET_EFFECT_ADD_ON, // BPicture definitions AS_CREATE_PICTURE, diff --git a/src/kits/app/CompositingPrivate.cpp b/src/kits/app/CompositingPrivate.cpp new file mode 100644 index 0000000..627d1b4 --- /dev/null +++ b/src/kits/app/CompositingPrivate.cpp @@ -0,0 +1,283 @@ +#include <AppServerLink.h> +#include <ServerProtocol.h> +#include <String.h> +#include <OS.h> + +// not really fond of this... but need it... for now +#define protected public +# include <Window.h> +#undef protected + +#include "CompositingPrivate.h" + + +namespace BPrivate{ + + +int32 compositingRateForPerfMode(performance_mode mode) +{ + return (int32)mode; +} + +uint8 compositingPerfLevelForPerfMode(performance_mode mode) +{ + switch(mode){ + case STOP_PERFORMANCE_MODE: + return 0; + case SLOW_PERFORMANCE_MODE: + return 1; + case MILD_PERFORMANCE_MODE: + return 2; + case HIGH_PERFORMANCE_MODE: + return 3; + case FULL_PERFORMANCE_MODE: + return 4; + case SYNC_PERFORMANCE_MODE: + return 5; + case WILD_PERFORMANCE_MODE: + return 6; + }; + + return 3; +} + +performance_mode compositingPerfModeForPerfLevel(uint8 level) +{ + switch(level){ + case 0: return STOP_PERFORMANCE_MODE; + case 1: return SLOW_PERFORMANCE_MODE; + case 2: return MILD_PERFORMANCE_MODE; + case 3: return HIGH_PERFORMANCE_MODE; + case 4: return FULL_PERFORMANCE_MODE; + case 5: return SYNC_PERFORMANCE_MODE; + case 6: return WILD_PERFORMANCE_MODE; + }; + // never will get here... + return HIGH_PERFORMANCE_MODE; +} + + +performance_mode getCompositingPerformance() +{ + int32 perfLevel; + AppServerLink link; + link.StartMessage(AS_GET_COMPOSITING_PERFORMANCE); + + int32 code; + if (link.FlushWithReply(code) == B_OK) { + link.Read<int32>(&perfLevel); + } + + return compositingPerfModeForPerfLevel(perfLevel); +} + + + +bool getCompositingEnabled() +{ + bool enabled = false; + BPrivate::AppServerLink link; + link.StartMessage(AS_GET_COMPOSITING_ENABLED); + + int32 code; + if (link.FlushWithReply(code) == B_OK) { + link.Read<bool>(&enabled); + } + + return enabled; +} + +bool setCompositingEnabled(bool enable) +{ + BPrivate::AppServerLink link; + link.StartMessage(AS_SET_COMPOSITING_ENABLED); + link.Attach<bool>(enable); + link.Flush(); + return getCompositingEnabled(); +} + + + +bool setCompositingMode(composite_mode mode) +{ // noop + return true; +} + +composite_mode getCompositingMode() +{ + return NORMAL_COMPOSITE; +} + + +status_t setCompositingPerformance(performance_mode mode) +{ + BPrivate::AppServerLink link; + link.StartMessage(AS_SET_COMPOSITING_PERFORMANCE); + link.Attach<uint8>(compositingPerfLevelForPerfMode(mode)); + link.Flush(); + return B_OK; // no error support yet... +} + + + +int32 getCompositingFPS() +{ + BPrivate::AppServerLink link; + + int32 fps; + link.StartMessage(AS_GET_COMPOSITING_FPS); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status != B_OK) + return -1; + link.Read<int32>(&fps); + return fps; +} + + + +size_t getCompositingMemoryLimit() +{ + BPrivate::AppServerLink link; + + size_t limit; + link.StartMessage(AS_GET_COMPOSITING_MEMLIMT); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status != B_OK) + return 0; // just say no limit... + link.Read<size_t>(&limit); + return limit; +} + + +size_t setCompositingMemoryLimit(size_t limit) +{ + BPrivate::AppServerLink link; + link.StartMessage(AS_SET_COMPOSITING_MEMLIMT); + link.Attach<size_t>(limit); + link.Flush(); + + return getCompositingMemoryLimit(); +} + + + +size_t getCompositingMemoryUsageEstimate() +{ + BPrivate::AppServerLink link; + + size_t usage; + link.StartMessage(AS_GET_COMPOSITING_MEMUSAGE_ESTIMATE); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status != B_OK) + return 0; // just say no usage... + link.Read<size_t>(&usage); + return usage; +} + +size_t getCompositingMemoryUsage() +{ // may look almost identical... but MUCH more work is done when called... + BPrivate::AppServerLink link; + + size_t usage; + link.StartMessage(AS_GET_COMPOSITING_MEMUSAGE); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status != B_OK) + return 0; // just say no usage... + link.Read<size_t>(&usage); + return usage; +} + + + +BString getCompositingMouseOverlay() +{ + return ""; +} + +bool setCompositingMouseOverlay(const BString& overlay) +{ + return false; +} + + +// #pragma mark Builtin Effects + + +bool getShadowEffectsEnabled() +{ + bool enabled = false; + BPrivate::AppServerLink link; + link.StartMessage(AS_GET_EFFECT_SHADOWS_ENABLED); + + int32 code; + if (link.FlushWithReply(code) == B_OK) { + link.Read<bool>(&enabled); + } + + return enabled; + +} + +bool setShadowEffectsEnabled(bool enable) +{ + BPrivate::AppServerLink link; + link.StartMessage(AS_SET_EFFECT_SHADOWS_ENABLED); + link.Attach<bool>(enable); + link.Flush(); + + return getShadowEffectsEnabled(); +} + + + +bigtime_t dimEffect_ScreenByHalf() +{ + BPrivate::AppServerLink link; + bigtime_t time = 0; + link.StartMessage(AS_DIM_EFFECT_SCREEN_BY_HALF); + int32 code; + + if (link.FlushWithReply(code) == B_OK) + link.Read<bigtime_t>(&time); + + return time; +} + +bigtime_t dimEffect_ScreenToBlack() +{ + BPrivate::AppServerLink link; + bigtime_t time = 0; + link.StartMessage(AS_DIM_EFFECT_SCREEN_TO_BLACK); + int32 code; + + if (link.FlushWithReply(code) == B_OK) + link.Read<bigtime_t>(&time); + + return time; +} + +bigtime_t dimEffect_ScreenToNormal() +{ + BPrivate::AppServerLink link; + bigtime_t time = 0; + link.StartMessage(AS_DIM_EFFECT_SCREEN_TO_NORMAL); + int32 code; + + if (link.FlushWithReply(code) == B_OK) + link.Read<bigtime_t>(&time); + + return time; +} + +bigtime_t dimEffect_WindowByHalf(BWindow* window) +{ + return window->_DimEffect_ByHalf(); +} + +bigtime_t dimEffect_WindowToNormal(BWindow* window) +{ + return window->_DimEffect_ToNormal(); +} + + +}; // end namespace BPrivate diff --git a/src/kits/app/Jamfile b/src/kits/app/Jamfile index 1f01a00..dd03249 100644 --- a/src/kits/app/Jamfile +++ b/src/kits/app/Jamfile @@ -28,6 +28,7 @@ MergeObject <libbe>app_kit.o : Application.cpp AppMisc.cpp AppServerLink.cpp + CompositingPrivate.cpp Cursor.cpp Clipboard.cpp DesktopLink.cpp diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 80729cd..43a3ea6 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -2117,6 +2117,50 @@ BWindow::Frame() const } +void +BWindow::SetDrawingMode(drawing_mode mode) +{ // if compositing is enabled this has an effect + // otherwise it really has no effect (at this point) + + if (Lock()) { + fLink->StartMessage(AS_SET_DRAWING_MODE); + fLink->Attach<int8>((int8)mode); + fLink->Flush(); + Unlock(); + } + +} + + +drawing_mode +BWindow::DrawingMode() const +{ + int8 drawingMode = (int8) B_OP_OVER; + + fLink->StartMessage(AS_GET_DRAWING_MODE); + + int32 code; + if (fLink->FlushWithReply(code) == B_OK && code == B_OK) { + fLink->Read<int8>(&drawingMode); + } + return (drawing_mode)drawingMode; +} + + +bool +BWindow::IsCompositingEnabled() const +{ // we have a link, no need to use utilty functions... + bool enabled = false; + fLink->StartMessage(AS_GET_COMPOSITING_ENABLED); + + int32 code; + if (fLink->FlushWithReply(code) == B_OK && code == B_OK) { + fLink->Read<bool>(&enabled); + } + return enabled; +} + + BRect BWindow::DecoratorFrame() const { @@ -4059,6 +4103,73 @@ BWindow::_GetDecoratorSize(float* _borderWidth, float* _tabHeight) const } +/* + _SetFullscreenCompositeModeEnabled: + Tells CompositeEngine to treat this window as if it + were the only thing visible on screen. + + All other updates cease. If we are in B_OP_ALPHA mode the + current screen buffer is cached (with this window 'hidden') + and is used as the backdrop. + + Further, in the future, updates application's make to their + windows will be discarded while this mode is held and when + the mode is released, each visible window will be asked to + redraw their contents. + + Screensavers, full-screen games, and full-screen video should + all invoke this for maximum performance, and disable this once + done. + + This is why it is a protected member, rather than private. + + TODO: consider a new name and improve visibility??? +*/ +bool +BWindow::_SetFullscreenCompositeModeEnabled(bool enable) +{ + fLink->StartMessage(AS_SET_COMPOSITING_FULLSCREEN_MODE); + fLink->Attach<bool>(enable); + fLink->Flush(); + + bool value = false; + // TODO: work out two-way communication details... sure + // it already works... just don't know how - yet ;-) + return value; +} + + +// These functions will normally be called externally. +bigtime_t // window will be dimmed with an overlay +BWindow::_DimEffect_ByHalf() +{ // please note: dimmed windows do not have control input locked! + // it is a visual indicator only (unlike screen dimming) + fLink->StartMessage(AS_DIM_EFFECT_WINDOW_BY_HALF); + bigtime_t time = 0; + + int32 code; + if (fLink->FlushWithReply(code) == B_OK) + fLink->Read<bigtime_t>(&time); + + return time; +} + + +bigtime_t // dimming level will fade away +BWindow::_DimEffect_ToNormal() +{ // if not dimmed, this is all for not ;-) + fLink->StartMessage(AS_DIM_EFFECT_WINDOW_TO_NORMAL); + bigtime_t time = 0; + + int32 code; + if (fLink->FlushWithReply(code) == B_OK) + fLink->Read<bigtime_t>(&time); + + return time; +} + + + // #pragma mark - C++ binary compatibility kludge diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index f31ebbb..0494ac0 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -4,6 +4,7 @@ UseLibraryHeaders agg ; UsePrivateHeaders app graphics input interface kernel shared storage support ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing compositing ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app stackandtile ] ; diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 5472f04..7ef75bd 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -91,6 +91,42 @@ string_for_message_code(uint32 code, BString& string) CODE(AS_SET_SIZE_LIMITS); CODE(AS_ACTIVATE_WINDOW); CODE(AS_IS_FRONT_WINDOW); + CODE(AS_SET_DRAWING_MODE); + CODE(AS_GET_DRAWING_MODE); + + // Compositing definitions + CODE(AS_SET_COMPOSITING_ENABLED); + CODE(AS_GET_COMPOSITING_ENABLED); + CODE(AS_SET_COMPOSITING_MODE); + CODE(AS_GET_COMPOSITING_MODE); + CODE(AS_SET_COMPOSITING_PERFORMANCE); + CODE(AS_GET_COMPOSITING_PERFORMANCE); + CODE(AS_GET_COMPOSITING_FPS); + CODE(AS_SET_COMPOSITING_MEMLIMT); + CODE(AS_GET_COMPOSITING_MEMLIMT); + CODE(AS_GET_COMPOSITING_MEMUSAGE_ESTIMATE); + CODE(AS_GET_COMPOSITING_MEMUSAGE); + CODE(AS_GET_COMPOSITING_STATUS); + CODE(AS_SET_COMPOSITING_MOUSE_OVERLAY); + CODE(AS_GET_COMPOSITING_MOUSE_OVERLAY); + CODE(AS_GET_COMPOSITING_DIMMING_ENABLED); + CODE(AS_SET_COMPOSITING_DIMMING_ENABLED); + CODE(AS_GET_COMPOSITING_FULLSCREEN_MODE); + CODE(AS_SET_COMPOSITING_FULLSCREEN_MODE); + + // built-in effects + CODE(AS_SET_EFFECT_SHADOWS_ENABLED); + CODE(AS_GET_EFFECT_SHADOWS_ENABLED); + CODE(AS_SET_EFFECT_SHADOWS_CONFIG); + CODE(AS_GET_EFFECT_SHADOWS_CONFIG); + CODE(AS_DIM_EFFECT_SCREEN_BY_HALF); + CODE(AS_DIM_EFFECT_SCREEN_TO_BLACK); + CODE(AS_DIM_EFFECT_SCREEN_TO_NORMAL); + CODE(AS_DIM_EFFECT_WINDOW_BY_HALF); + CODE(AS_DIM_EFFECT_WINDOW_TO_NORMAL); + CODE(AS_SET_EFFECT_ADD_ON); + CODE(AS_GET_EFFECT_ADD_ON); + // BPicture definitions CODE(AS_CREATE_PICTURE); diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 8ffea24..34d0c3e 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -53,6 +53,7 @@ #include "AppServer.h" #include "AutoDeleter.h" +#include "CompositeEngine.h" #include "Desktop.h" #include "DirectWindowInfo.h" #include "DrawingEngine.h" @@ -844,7 +845,55 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) fLink.Flush(); break; } - + case AS_SET_DRAWING_MODE: + { DTRACE(("ServerWindow %s: Message AS_SET_DRAWING_MODE\n", Title())); + int8 newMode = (int8)fWindow->DrawingMode(); + + if (link.Read<int8>(&newMode) == B_OK) + fWindow->SetDrawingMode((drawing_mode)newMode); + + break; + } + case AS_GET_DRAWING_MODE: + { + DTRACE(("ServerWindow %s: Message AS_GET_DRAWING_MODE\n", Title())); + fLink.StartMessage(B_OK); + fLink.Attach<int8>((int8)fWindow->DrawingMode()); + fLink.Flush(); + break; + } + case AS_SET_COMPOSITING_FULLSCREEN_MODE: + { + DTRACE(( + "ServerWindow %s: Message AS_SET_COMPOSITING_FULLSCREEN_MODE\n", + Title())); + bool enable; + link.Read<bool>(&enable); + fLink.StartMessage(B_OK); + fLink.Attach<bool>( + gCompositeEngine->SetToFullscreenMode(fWindow, enable)); + + fLink.Flush(); + break; + } + case AS_DIM_EFFECT_WINDOW_BY_HALF: + { + DTRACE(("ServerWindow %s: Message AS_DIM_EFFECT_WINDOW_BY_HALF\n", + Title())); + fLink.StartMessage(B_OK); + fLink.Attach<bigtime_t>(fWindow->DimEffect_ByHalf()); + fLink.Flush(); + break; + } + case AS_DIM_EFFECT_WINDOW_TO_NORMAL: + { + DTRACE(("ServerWindow %s: Message AS_DIM_EFFECT_WINDOW_TO_NORMAL\n", + Title())); + fLink.StartMessage(B_OK); + fLink.Attach<bigtime_t>(fWindow->DimEffect_ToNormal()); + fLink.Flush(); + break; + } case AS_GET_WORKSPACES: { DTRACE(("ServerWindow %s: Message AS_GET_WORKSPACES\n", Title())); diff --git a/src/servers/app/Window.h b/src/servers/app/Window.h index 887f2d8..328141f 100644 --- a/src/servers/app/Window.h +++ b/src/servers/app/Window.h @@ -306,6 +306,14 @@ public: bool MoveToTopStackLayer(); bool MoveToStackPosition(int32 index, bool isMoving); + + // Window Compositing methods. + drawing_mode DrawingMode() const; + void SetDrawingMode(drawing_mode); + + bigtime_t DimEffect_ByHalf(); + bigtime_t DimEffect_ToNormal(); + protected: void _ShiftPartOfRegion(BRegion* region, BRegion* regionToShift, int32 xOffset, diff --git a/src/servers/app/drawing/compositing/CompositeEngine.cpp b/src/servers/app/drawing/compositing/CompositeEngine.cpp new file mode 100644 index 0000000..43c5a75 --- /dev/null +++ b/src/servers/app/drawing/compositing/CompositeEngine.cpp @@ -0,0 +1,333 @@ +#include <Autolock.h> +#include <CompositingPrivate.h> + +#include "CompositeEngine.h" + +// auto-instantiate +CompositeEngine * gCompositeEngine = new CompositeEngine(); + + +/* + Be forewarned: we have five separate locks which interact + with each other. And that doesn't count the objects we + have which have their own locks... + + Use BAutolock whenever possible!! And make sure you are + choosing the right lock(s)! +*/ + +CompositeEngine::CompositeEngine() + : + fClientsLock("AppServer::CompositeEngine_Clients"), + fModeSwitchLock("AppServer::CompositeEngine_ModeSwitch"), + fMasterLock("AppServer::CompositeEngine_MasterControl"), + fBackToFrontLock("AppServer::CompositeEngine_BackToFront"), + fHardwareLock("AppServer::CompositeEngine_HardwareInterface"), + fFrames_Max(0), + fFrames_Target(60), + fUpdates_PendingPriority(255), + fUpdate_DesiredInterval(1000000/60), + fUpdate_NextTime(system_time() + 10000), + fEngine_InstantiatedTime(system_time()), + fEngine_EnabledTime(0), + fPerformanceMode(FULL_PERFORMANCE_MODE), + fPerformanceMode_Last(STOP_PERFORMANCE_MODE), + fCompositeMode(NORMAL_COMPOSITE), + fCompositingEnabled(false), // ALWAYS default to off + fHardware(NULL) + { + // when we come to be very little is alive, + // don't expect any other part of app_server to + // be ready or instantiated - they may not be. + } + + +CompositeEngine::~CompositeEngine() +{ // we are NEVER to be destructed. + debugger("AppServer Horror\n" + "CompositeEngine destroyed!\n" + "But this should not be!"); // 8-) +} + + +// #pragma mark - + +bool +CompositeEngine::SetHWInterface(HWInterface* interface) +{ // we do not assum ownership of the HWInterface + BAutolock _(fHardwareLock); + if (interface != NULL) + fHardware = interface; + else + return false; + + return true; +} + + +HWInterface* +CompositeEngine::GetHWInterface() const +{ BAutolock _(fHardwareLock); + return fHardware; +} + + +bool +CompositeEngine::IsCompositingEnabled() const +{ // we need the lock because we want to return true + // if we are almost enabled... + BAutolock _(fModeSwitchLock); + return fCompositingEnabled; +} + + +status_t +CompositeEngine::SetCompositingEnabled(bool enable) +{ + BAutolock _(fModeSwitchLock); + + status_t error = B_UNSUPPORTED; + + return error; +} + + +// #pragma mark MemLimits + +size_t +CompositeEngine::CalculateMemoryUsage() +{ // must traverse window list and sum up buffer sizes + // as well as the back buffer + BAutolock _(fModeSwitchLock); + + size_t total = 0; + + return total == 0 ? fEstimatedMemoryUsage : total; +} + + +size_t +CompositeEngine::EstimateMemoryUsage() const +{ // accuracy is not guaranteed - no need to lock + return fEstimatedMemoryUsage; +} + + +size_t +CompositeEngine::FrameBufferSize() const +{ BAutolock _(fModeSwitchLock); + return fFrameBufferSize; +} + + +size_t +CompositeEngine::LimitMemoryUsage(size_t limit) +{ + if (limit < FrameBufferSize()){ + limit = (size_t)(((float)FrameBufferSize()) * 1.5); + } // room for frame buffer and a little more... + // this SHOULD cause windows to render directly to the + // back-buffer, in turn, at the expense of performance... + // basically we swap WindowBuffer for BackBuffer + // those aren't the names (yet)... + + + fMemoryLimit = limit; + + if (fEstimatedMemoryUsage < fMemoryLimit){ + BAutolock _(fModeSwitchLock); + _EnforceMemoryLimit(); + } + + return fMemoryLimit; +} + + +size_t +CompositeEngine::MemoryLimit() const +{ BAutolock _(fModeSwitchLock); + return fMemoryLimit; +} + + +// #pragma mark Clients + + +status_t +CompositeEngine::AttachClient(CompositeEngineClient* client) +{ if (client == NULL) + return B_BAD_VALUE; + + BAutolock _(fClientsLock); + + // are we already in the list? + + if (fClients.IndexOf(client) >= 0) + return B_BAD_INDEX; + + return fClients.AddItem(client) ? B_OK : B_ERROR; +} + + +status_t +CompositeEngine::DetachClient(CompositeEngineClient* client) +{ if (client == NULL) + return B_BAD_VALUE; + + BAutolock _(fClientsLock); + if (fClients.IndexOf(client) < 0) + return B_BAD_INDEX; + + return (fClients.RemoveItem(client, false)) ? B_OK : B_ERROR; +} + + +// #pragma mark Performance + +uint8 +CompositeEngine::CurrentFPS() const +{ + //return fPerfmon->FrontBuffer()->CompletionRate(1000000); + return 0; +} + + +performance_mode +CompositeEngine::PerformanceMode() const +{ BAutolock _(fModeSwitchLock); + return fPerformanceMode; +} + + + +bool +CompositeEngine::RequirePerformanceMode(performance_mode mode, + CompositeEngineClient* client) +{ + return _SetPerformanceMode(mode, client, true, true); +} + + + +bool +CompositeEngine::SuggestPerformanceMode(performance_mode mode, + CompositeEngineClient* client) +{ + return _SetPerformanceMode(mode, client, false, true); +} + + +#define PerfModeLevel(x) compositingPerfLevelForPerfMode(x) +#define PerfModeByLevel(x) compositingPerfModeForPerfLevel(x) + +bool +CompositeEngine::_SetPerformanceMode(performance_mode mode, + CompositeEngineClient* client, bool force, bool lock) +{ + if (lock) BAutolock _(fClientsLock); + // verify client is attached: + if (fClients.IndexOf(client) < 0) // not a client + return false; + + if (lock) BAutolock _(fModeSwitchLock); + + // weed out unacceptable requests: + + if (mode == STOP_PERFORMANCE_MODE + && client->CompositeClientType() != DESKTOP_COMPOSITE_CLIENT) + return false; + + if (mode == WILD_PERFORMANCE_MODE + && client->CompositeClientType() != DESKTOP_COMPOSITE_CLIENT) + return false; + + bool faster = PerfModeLevel(mode) > PerfModeLevel(fPerformanceMode); + + // ask clients if the new mode is acceptable, weigh opinions + + int32 blockWeight = 0, clientWeight = 0; + + CompositeEngineClient * blockingClient = NULL; + + for (int32 i = 0; i < fClients.CountItems(); ++i){ + if (fClients.ItemAt(i)-> + CompositingModeRequested(mode, fCompositeMode) == false){ + + blockingClient = fClients.ItemAt(i); + clientWeight = blockingClient->CompositeClientPriority() + 1; + + switch(blockingClient->CompositeClientType()){ + case ANONYMOUS_COMPOSITE_CLIENT: + break; + case DESKTOP_COMPOSITE_CLIENT: + case FULLSCREEN_COMPOSITE_CLIENT: + clientWeight *= faster ? 256 : 128; + break; // we like to get our way... + case DESKTOPWINDOW_COMPOSITE_CLIENT: + clientWeight *= faster ? 64 : 48; + break; // shouldn't be time-critical + case WORKSPACE_COMPOSITE_CLIENT: + break;// special mode not yet supported + case WINDOW_COMPOSITE_CLIENT: + clientWeight = faster ? 32 : 64; + break; // prevent slow-downs, not speed-ups... + case SERVERWINDOW_COMPOSITE_CLIENT: + case DIRECTWINDOW_COMPOSITE_CLIENT: + case UPDATEQUEUE_COMPOSITE_CLIENT: + break; // not sure if relevant - yet + default: + break; + } + blockWeight += clientWeight; + } + } // end client opinion requests + + // now how the "opinions" work: + + uint8 delta = 0, newLevel = PerfModeLevel(mode); + + if (blockWeight != 0){ + if (faster){ + delta = PerfModeLevel(mode) - PerfModeLevel(fPerformanceMode); + + if (blockWeight <= 64 && delta > 2) + newLevel -= 1; + + if (blockWeight <= 128 && delta > 1) + newLevel -= 1; + + if (blockWeight <= 256 && delta > 1) + newLevel -= 2; // possibly denying change + + if (blockWeight > 256) // deny change + newLevel = PerfModeLevel(fPerformanceMode); + + }else{ // want to go slower... + delta = PerfModeLevel(fPerformanceMode) - PerfModeLevel(mode); + + if (blockWeight <= 64 && delta > 2) + newLevel += 1; + + if (blockWeight <= 128 && delta > 1) + newLevel += 1; + + if (blockWeight <= 256 && delta > 1) + newLevel += 2; // possibly denying change + + if (blockWeight > 256) // deny change + newLevel = PerfModeLevel(fPerformanceMode); + + }// end slower + } // end has some blockWeight + + if (force && PerfModeLevel(mode) != newLevel) + return false; // no changes for all that work... + + fPerformanceMode = PerfModeByLevel(newLevel); + return PerfModeLevel(mode) <= PerfModeLevel(fPerformanceMode); + +} + + + + diff --git a/src/servers/app/drawing/compositing/CompositeEngine.h b/src/servers/app/drawing/compositing/CompositeEngine.h index eb34d55..e612bfd 100644 --- a/src/servers/app/drawing/compositing/CompositeEngine.h +++ b/src/servers/app/drawing/compositing/CompositeEngine.h @@ -13,69 +13,13 @@ #include <OS.h> #include <String.h> +#include "CompositingPrivate.h" #include "HWInterface.h" #include "RenderingBuffer.h" #include "ServerBitmap.h" #include "UpdateQueue.h" -/* - performance_mode determines the rate at which we will update changes - in the back-buffer into the front-buffer. - We batch updates together and change the performance mode based on the - amount of changes made, the area covered - along with app-requested - performance modes (new API) or ServerWindow requests based on user - action (window resize/move, typing, etc...) - Just becauuse we are in, say, FULL_PERFORMANCE_MODE does not mean we - will actually be operating at a full 60 fps, that is just the reference - update interval (1/60th of a second [minus some time for overhead]) -*/ -enum performance_mode{ - STOP_PERFORMANCE_MODE = 0, // 0 fps (screen off) - SLOW_PERFORMANCE_MODE = 5, // <= 5 fps (sitting at the desktop) - MILD_PERFORMANCE_MODE = 15, // < 15 fps (normal GUIs, low motion) - HIGH_PERFORMANCE_MODE = 30, // < 30 fps (videos, moderate motion) - FULL_PERFORMANCE_MODE = 60, // ~ 60 fps (animations, moving video) - SYNC_PERFORMANCE_MODE = 120,// @ refresh rate - up to 120hz - WILD_PERFORMANCE_MODE = 1000// max power! - up to 1000fps... -}; - -enum composite_mode{ - NORMAL_COMPOSITE = 0//, // CPU[s] do[es] the work - // ACCEL_COMPOSITE, // GPU accelerated - // MIXED_COMPOSITE, // CPU does some, GPU does some - // XGPUS_COMPOSITE, // multiple GPUs for compositing - // XHEAD_COMPOSITE // treat monitors separately - - // one workspace per monitor ;-) -}; - -/* - composite_client_type - - It is often useful for the CompositeEngine to know what type of client - is denying or making a request so as to react properly. - - Basically, if a Desktop requests STOP_PERFORMANCE_MODE, that means the - monitor has gone to black (or is going to sleep). If a Window asks, we - will outright deny it. If a workspace asks, and we are in XHEAD_COMPOSITE, - then we stop updates for the screen for that workspace, only increasing - when the workspace permits us. - - This allows us to not touch the code too much in the future. - - A CompositeEngineClient can identify itself as being of one of types - as follows: -*/ -enum composite_client_type{ - ANONYMOUS_COMPOSITE_CLIENT = 0, - DESKTOP_COMPOSITE_CLIENT, - DESKTOPWINDOW_COMPOSITE_CLIENT, - WORKSPACE_COMPOSITE_CLIENT, - WINDOW_COMPOSITE_CLIENT, - SERVERWINDOW_COMPOSITE_CLIENT, - DIRECTWINDOW_COMPOSITE_CLIENT, - UPDATEQUEUE_COMPOSITE_CLIENT -}; - +using namespace BPrivate; class Window; class CompositeEngineClient{ @@ -88,7 +32,7 @@ public: virtual void CompositingEnabled(bool enabled) = 0; - // optional: + // optional override: // if you need to do something BEFORE compositing takes over // or before it ceases to render you need to override one of the following: @@ -97,28 +41,44 @@ public: virtual void CompositingChanged(performance_mode, composite_mode); - virtual void CompositingPerformance(bool isLow = true); + + virtual void CompositingPerformanceSlow(bool isSlow); + // this is triggered to inform a client that they will be getting + // less attention for one of the reasons as follows: + /* + 1. Screen-saver is active + 2. Entered into SLOW or STOP performance mode + 3. System is bogged down + + When isSlow is true, you should consider limiting updates + and redraws until isSlow comes back as false. + */ // affect operations // When a mode change is to be made we ask our clients if it is acceptable. - // Your opinion is just that - an opinion ;-) Unless you are a Desktop... - virtual bool CompositingModesRequested(performance_mode, + // Your opinion is just that - an opinion ;-) + virtual bool CompositingModeRequested(performance_mode, composite_mode); - - + // your opinion about composite_mode doesn't matter... it is there + // just so you can take it into account if you need to... + void MarkScreenRegionDirty(BRegion&); + // this may seem like an odd place for this, but it is not... // tell the composite engine that you need to be treated better // or that you are being treated too well. // There are five (unnamed) priority levels (0-4) // everyone starts at zero (lowest priority). - void IncreaseCompositeClientPriority(); - void DecreaseCompositeClientPriority(); - void SetCompositeClientPriority(uint8); + // Increasing priority gives your update entries added strength and + // increases the strength of your opinions + // It is best to stay at zero, only increasing as it becomes more + // important for you to get your way. + // Even Desktop has a priority of zero & only escalates as needed. + uint8 IncreaseCompositeClientPriority(); + uint8 DecreaseCompositeClientPriority(); + uint8 SetCompositeClientPriority(uint8); - uint8 CompositeClientPriorityLevel() const; - // If requested mode (or higher) is achieved, true is returned. // there are few scenarios in which these will fail... bool SuggestCompositingMode(performance_mode, @@ -126,11 +86,29 @@ public: bool RequireCompositingMode(performance_mode, composite_mode = NORMAL_COMPOSITE); - + + composite_client_type CompositeClientType() const; + + bool SetCompositeClientFullscreen(bool); + uint8 CompositeClientPriority() const; + + bool SetToFullscreenMode(Window*, bool enable) + { + return false; + } + + private: + composite_client_type fClientType; + + bool fFullscreen; + + uint8 fPriority; + + BString fName; }; -class CompositeEngine : public HWInterfaceListener{ +class CompositeEngine{ public: explicit CompositeEngine(); ~CompositeEngine(); // no use for a vtable... @@ -143,7 +121,9 @@ public: status_t SetCompositingEnabled(bool enable); // synchronous - size_t TotalMemoryUsage(); + size_t CalculateMemoryUsage(); + size_t EstimateMemoryUsage() const; + size_t FrameBufferSize() const; size_t LimitMemoryUsage(size_t); // returns actual limit approved @@ -156,15 +136,16 @@ public: listener); uint8 CurrentFPS() const; - uint8 MaxFPS() const; performance_mode PerformanceMode() const; - bool RequirePerformanceMode(performance_mode mode); + bool RequirePerformanceMode(performance_mode mode, + CompositeEngineClient* client); // if we can't get the mode (or higher) we don't try to elevate // we simply return false and remain in whatever mode we were // already in. - bool SuggestPerformanceMode(performance_mode mode); + bool SuggestPerformanceMode(performance_mode mode, + CompositeEngineClient* client); // SuggestPerformanceMode() will do its best to elevate to as // close to the requested mode as possible. The reasons for // the mode to not elevate are as follows: @@ -195,7 +176,7 @@ public: void DrawWindow(Window*); - void SetFullScreenWindow(Window*); + bool SetToFullscreenMode(Window*, bool); // disables background updates... // full-screen fading (synchronous) @@ -212,20 +193,24 @@ private: static int32 _SlaveRenderThread(void*); static int32 _BackToFrontThread(void*); + void _EnforceMemoryLimit(); BRect _NextUpdateRect(bool&); uint8 _NextUpdateBatchWeight(); void _PushToFront(); - void _SetPerformanceMode(performance_mode); + bool _SetPerformanceMode(performance_mode, + CompositeEngineClient* client, + bool force, bool lock = false); - BLocker fClientsLock, + mutable BLocker fClientsLock, fModeSwitchLock, - fMasterLock; + fMasterLock, + fBackToFrontLock, + fHardwareLock; BObjectList<CompositeEngineClient> fClients; uint8 fFrames_Max, - fFrames_Average, fFrames_Target, fUpdates_PendingPriority; @@ -237,7 +222,15 @@ private: performance_mode fPerformanceMode, fPerformanceMode_Last; + composite_mode fCompositeMode; + bool fCompositingEnabled : 1; + + HWInterface* fHardware; + + size_t fMemoryLimit, + fFrameBufferSize, + fEstimatedMemoryUsage; }; diff --git a/src/servers/app/drawing/compositing/Jamfile b/src/servers/app/drawing/compositing/Jamfile index 8751fc3..5b3f3cc 100644 --- a/src/servers/app/drawing/compositing/Jamfile +++ b/src/servers/app/drawing/compositing/Jamfile @@ -14,5 +14,6 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter font_support UseHeaders $(HAIKU_FREETYPE_HEADERS) : true ; StaticLibrary libasdrawing.a : + CompositeEngine.cpp CompositeUpdateQueue.cpp ; ############################################################################ Commit: ca740996653746647b85e29f05a33620a23cab20 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Tue Mar 27 23:53:12 2012 UTC Major commit Re-oriented ComositeEngine scrap pieces from CAFE::RenderEngine, namely removing performance modes - as these aren't likely needed int the limited role in the app_server. If anything, the app_server will only need three modes: slow(5hz), 60hz, @refresh, which is better handled with SetSlowMode() and SetUpdateEveryRefresh(). Moved special accessors to CompositingPrivate. Prepared app_server port communication, implemented some BWindow changes (SetDrawingMode()), prepare for special full-screen modes to prevent unneeded updates from the back coming forward. Created WindowBuffer, which will be atttached to a Painter with a new method to render the buffer directly, which is attached to a standard RenderEngine, which will be generated by the CompsiteHWInterface. WindowBuffer will collect updated rects and the CompositeEngine will prioritize updates front-to-back, ceasing updates when a new frame is to be renderred - but not before completing updates for any active WindowBuffer. While WindowBuffer is active with the CompositeEngine, the client will be unable to make drawing changes, so we will push as many threads to each WindowBuffer as possible, with each dirty rect possibly being handled by a separate thread/core and unlock that WindowBuffer as quickly as possible. ---------------------------------------------------------------------------- diff --git a/headers/private/app/CompositingPrivate.h b/headers/private/app/CompositingPrivate.h index ff196e4..f37a28d 100644 --- a/headers/private/app/CompositingPrivate.h +++ b/headers/private/app/CompositingPrivate.h @@ -1,3 +1,7 @@ +/* + The function names are quite long...sorry! +*/ + #ifndef COMPOSITING_PRIVATE_H #define COMPOSITING_PRIVATE_H @@ -8,136 +12,60 @@ class BWindow; namespace BPrivate{ -/* - performance_mode determines the rate at which we will update changes - in the back-buffer into the front-buffer. - We batch updates together and change the performance mode based on the - amount of changes made, the area covered - along with app-requested - performance modes (new API) or ServerWindow requests based on user - action (window resize/move, typing, etc...) - Just becauuse we are in, say, FULL_PERFORMANCE_MODE does not mean we - will actually be operating at a full 60 fps, that is just the reference - update interval (1/60th of a second [minus some time for overhead]) -*/ -enum performance_mode{ - STOP_PERFORMANCE_MODE = 0, // 0 fps (screen off) - SLOW_PERFORMANCE_MODE = 5, // <= 5 fps (sitting at the desktop) - MILD_PERFORMANCE_MODE = 15, // < 15 fps (normal GUIs, low motion) - HIGH_PERFORMANCE_MODE = 30, // < 30 fps (videos, moderate motion) - FULL_PERFORMANCE_MODE = 60, // ~ 60 fps (animations, moving video) - SYNC_PERFORMANCE_MODE = 120,// @ refresh rate - up to 120hz - WILD_PERFORMANCE_MODE = 1000// max power! - up to 1000fps... -}; - -enum composite_mode{ - NORMAL_COMPOSITE = 0//, // CPU[s] do[es] the work - // ACCEL_COMPOSITE, // GPU accelerated - // MIXED_COMPOSITE, // CPU does some, GPU does some - // XGPUS_COMPOSITE, // multiple GPUs for compositing - // XHEAD_COMPOSITE // treat monitors separately - - // one workspace per monitor ;-) -}; -/* - composite_client_type - - It is often useful for the CompositeEngine to know what type of client - is denying or making a request so as to react properly. - - Basically, if a Desktop requests STOP_PERFORMANCE_MODE, that means the - monitor has gone to black (or is going to sleep). If a Window asks, we - will outright deny it. If a workspace asks, and we are in XHEAD_COMPOSITE, - then we stop updates for the screen for that workspace, only increasing - when the workspace permits us. +typedef struct shadow_config{ + uint8 alpha, red, green, blue, // color + width, // shadow width from decorator + depth, // how many windows get shadows... + blend_rate; // how quickly to blend + + BString* addonName; // NULL if not one!! - This allows us to not touch the code too much in the future. - - A CompositeEngineClient can identify itself as being of one of types - as follows: -*/ -enum composite_client_type{ - ANONYMOUS_COMPOSITE_CLIENT = 0, - DESKTOP_COMPOSITE_CLIENT, - DESKTOPWINDOW_COMPOSITE_CLIENT, - WORKSPACE_COMPOSITE_CLIENT, - WINDOW_COMPOSITE_CLIENT, - SERVERWINDOW_COMPOSITE_CLIENT, - DIRECTWINDOW_COMPOSITE_CLIENT, - UPDATEQUEUE_COMPOSITE_CLIENT, - FULLSCREEN_COMPOSITE_CLIENT // screensaver, game, etc... + shadow_config(): alpha(50), red(0), green(0), blue(0), + width(5), depth(1), blend_rate(128), + addonName(NULL){} + ~shadow_config(){delete addonName;} }; - -/* -typedef struct CompositingStatus{ - bool enabled; - bigtime_t timeEnabled; - performance_mode performanceMode; - composite_mode compositingMode; - int32 frameRate, - averagesUpdates; // per refresh - - size_t memoryLimit, - memoryUsageEstimate; - - bool mouseIsOverlay, - shadowsEnabled, - dimmingEnabled, - fullscreenActive; - [ *** diff truncated: 1837 lines dropped *** ] ############################################################################ Commit: 5df5c102c2fc75818f339719402d11ae8751511f Author: looncraz <looncraz@xxxxxxxxxxx> Date: Wed Mar 28 22:55:44 2012 UTC Adding needed funcitonality to Window: Ability to use WindowBuffer (for compositing OR caching). Bring numerous other objects in line with changes. Take into account requirements for hardware acceleration. CompositeHWInterface is now an AccelerantHWInterface. Trying to limit requirements in the future for acceleration. NOTE: the build will not link at this point, still on purpose... ---------------------------------------------------------------------------- ############################################################################ Commit: 55b3b782cc5fa0172e026c2ed02d8cfd2ce78214 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Wed Mar 28 23:52:11 2012 UTC Implement some missing functions. Found some lacking areas, and implemented missing WindowBuffer functions. CompositeEngine is only hold-up until link success. ---------------------------------------------------------------------------- ############################################################################ Commit: 9cd2054810a019964e29eac906c744b75b18b93a Author: looncraz <looncraz@xxxxxxxxxxx> Date: Thu Mar 29 01:56:42 2012 UTC Various tidbits. ---------------------------------------------------------------------------- ############################################################################ Commit: d6c9717f1e2ba3574e4fa8f85129089aa4092d94 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Thu Mar 29 21:49:23 2012 UTC Message Handling Setup message handling for compositing. The CompositeEngine will handle all of its own requests. This is merely a prelude before setting up a route around ServerApp to expediate communications. Purpose being that some messages will undoubtedly be very time sensitive... and having all handling code in one place is quite nice. Began changes and made first runs of modified app_server (without incident, but no regression testing-yet). app_server now builds. Modified binaries thus far: libbe.so, app_server ---------------------------------------------------------------------------- ############################################################################ Commit: 86d79d7db4618cf741cb7256c1c69328ed40eb00 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Mar 30 00:31:29 2012 UTC Bug fixes Test run with compositing enabled to trace down bugs. Found several - as expected. ---------------------------------------------------------------------------- ############################################################################ Commit: 79c4de7d12c73d8cddd5844b7db38c54bd1ab3a4 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Mar 30 01:04:47 2012 UTC Adapt view to local buffer coordinates for drawing. Hoping this way works - it did eliminate all segment violations up to the Desktop bitmap draw, so we are no longer overunning the buffers it would seem... This is being kept as its own commit so it can be easily undone later, or referenced. ---------------------------------------------------------------------------- ############################################################################ Commit: 3823042ff2d6502ca7b3d2528d7d4a21e88bf8ca Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Mar 30 23:06:59 2012 UTC Working out the kinks... As we are now much more sensitive to writing outside of a View's bounds, we have to make adjustments... I believe I will be making Painter more aware of it's buffer's limitations, and to act accordingly to prevent segment violations. At this point, app_server can run in compositing mode, though nothing is painted on the screen. However, with very little effort (just clicking around) we find ourselves with a segment violation in Window SeetDrawingBuffer(), IIRC... next commit ;-) ---------------------------------------------------------------------------- ############################################################################ Commit: a649fe99b33faf3b6e1c544194debadeaf479d35 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sun Apr 1 14:46:33 2012 UTC Re-orienting to mixed-compositing (temporarily) Removed Window::SetDrawingMode in preference to the original B_RENDER_COMPOSITE window flag. The app_server internals make so many assumptions that drawing is occuring directly in the screen coordinate space that I am having surprising difficulty getting even a single Window to draw into its own WindowBuffer without some code blasting past the boundaries (and thus crashing). Decorators now draw directly into the screen buffer, but will soon be rewritten to draw into the over-provisioned WindowBuffers of their 'owning' windows. Currently, using the app_server without compositing enabled is going to be fruitless, and compositing still defaults to disabled, so don't expect to build a usable app_server - though it does build without issue. Modified View to use ConvertForDrawing instead of ConvertToScreenForDrawing. The functions are still very rudimentary, will be cloned in WindowBuffer, and the View functions will call into WindowBuffer to ascertain the proper drawing area. Further, the disconnect of DrawingEngine and its owner must be dissolved. And Painter with its buffer... Both must be made aware of their drawing space so they do no attempt to write outside of it, but intelligently clip their drawing. Each with their own degree of agressiveness and reaction. ---------------------------------------------------------------------------- ############################################################################ Commit: 7104d4bcc1e3dd4fea5898b1c7fc9df609d634c1 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sun Apr 1 22:31:45 2012 UTC Assorted tidbits Found chicken/egg problem in Window constructor which was causing problems. Things are much better now. Decided against using UpdateQueue in preference to dual BRegion for the WindowBuffer. Window's UpdateSession may be used instead when I get further along. Decorators are very confused as to dirty regions, but I am preparing to over-provision WindowBuffer to optimize resize performance and to permit room to draw the decorator directly into the WindowBuffer. Clipping will prevent window content spill-over, but decorators will be able to draw over the window (but should avoid it, naturally). Decorator changes are coming soon - the order of initialization may change radically - but it may not... ---------------------------------------------------------------------------- ############################################################################ Commit: d4f54d1dde0c860a823e3743a28c521c74c57902 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Tue Apr 3 23:20:13 2012 UTC Re-orientation to new model... -Decided to change the methodology for View's ConvertForDrawing() to convert up through the parents all of the way to the window. The window then does the final conversion based upon its type: Window: converts drawing to screen coordinate space OffscreenWindow: does no further conversion CompositeWindow: converts to WindowBuffer coordinate space (Others will inherit the behavior from Window, but I will investigate the need to override such behavior.) -Virtualized many functions in Window to facilitate a functional CompositeWindow typee so as to keep the code paths separate. -Making first steps to have WindowBuffer stay alive even after a Window's Quit() or destruction until all referencing objects have adapted or been destroyed. WindowBuffer is now a BReferenceable & only BReference<WindowBuffer> will be passed around. TODO: DrawingEngine will manually call AcquireReference() and ReleaseReference() if casting to WindowBuffer succeeds. Why: this greatly simplifies locking, and also permits lazy-recycling of allocated buffer spaces in the future. I believe all other changes are in-ine with the abovee. This will not build. Will probably spout out many many errors. Will certainly not link ;-) ---------------------------------------------------------------------------- ############################################################################ Commit: 7117024f8d2f8226724266e7df97da5e4cdf3d59 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Wed Apr 4 16:24:22 2012 UTC Moving Along Further implementing CompositeWindow. Re-wrote WindowBuffer's _ResizeTo() function with tested & working code. Compiles, will not link. Much work to go. ---------------------------------------------------------------------------- ############################################################################ Commit: b59f6ceaa131c5dac8981740ad5c577e7c140c19 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Wed Apr 4 21:24:38 2012 UTC Bug fix, misc... ---------------------------------------------------------------------------- ############################################################################ Commit: e8b91bdb2f392cd530bf28726b29eb3be42ca4af Author: looncraz <looncraz@xxxxxxxxxxx> Date: Thu Apr 5 00:38:40 2012 UTC Fixes Non-compositing mode now mostly works properly again. There are probably a few bugs here and there, but they should be minor(or obvious). Ran into an interesting situation where View::ConvertToWindow() somehow converts all of the way to the screen, which makes no sense... somewhere the drawing instructions are being converted from window coordinates to screen coordinates - and I can't find it... I checked in both View.cpp files (src/kits, and src/servers/app), ServerWindow (which receives the drawing messages from BView), and the ConvertToParent() code to try and solve this dilemma. I even had ever single view spout out its frame to make sure the view attached to the window had an origin of (0,0) - and they all did... Next commit will hopefully solve this... ---------------------------------------------------------------------------- ############################################################################ Commit: 443ba22c684cc41b18117cf05e76ecd0f2dcae21 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Thu Apr 5 22:11:02 2012 UTC Bug fix Figured out the problem with View::ConvertForDrawing(*) - ConvertToParent when there is no parent results in an undesired result (though it seems like it shouldn't do anything.. the frame should be (0,0,rt, bt). ---------------------------------------------------------------------------- ############################################################################ Commit: c52e7f21c19a2a4a1f4dfd737bf86beda04d64ef Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Apr 6 00:32:40 2012 UTC Continuing progress. CompositeHWInterface taking over for AccelratedHWInterface. CompositeWindow taking over for Window (for non-offscren windows only). Temporary B_RENDER_COMPOSITE flag being utilized to force a single window into compositing for testing. Logging levels reduced to eliminate tested code-paths. Further reductions forth-coming. DrawingEngine now capable of having a RenderingBuffer manually set via its public API. RenderingBuffer now capable of being aware of such changes to augment lazy-allocation techniques - or other uses (such as knowing when we are no longer being modified...). Builds. Runs. Works. Drawing doesn't seem to be re-routed to set RenderingBuffer, so there is some logging in place to trace that issue... ---------------------------------------------------------------------------- ############################################################################ Commit: eb34894293ebf80d5645ff540eac4cf3b05a1eb3 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sat Apr 7 23:21:12 2012 UTC Bug fixes & more prep-work WindowBuffer: fWindowFrame was not being updated. Over-provisioning was being added at the wrong time - thereby not bein applied at all. Cleaned up the code and removed interim window frame as the window frame must change for each and every resize event. CompositeWindow Setup to use a new method to temporarily mark a test window as compositing. Decorator: Preparing to drastically change how drawing is handled in Decorator. Will implement BView-style drawing interfaces, and hide much of the tedium. This is important as a Decorator may draw in foreign coordinate systems - such as WindowBuffer's. All frames and drawing will be relative to the window frame. Move events will need to be blocked entirely from a custom decorator's awareness. app_server builds & runs. An odd memory leak is still occuring in relation, I believe, to WindowBuffer... which is an odd situation... after WindowBuffer is destroyed, some RAM seems to not be returned to the system. Will need to chase this down. ---------------------------------------------------------------------------- ############################################################################ Commit: 1e36feeee65807731468f65e7dcbf8525cfdab8a Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sun Apr 8 11:04:58 2012 UTC Correct oversight. WindowBuffer was meant to hold its largest size in both dimensions, but any time a new max was achieved in either dimension it'd lose the other dimension's previous setting. This commit resolves this. On a side note: verified performance increase of other commits in non-compositing mode. Slightly faster than anticipated. ---------------------------------------------------------------------------- ############################################################################ Commit: bd713a3d3c513f1362cccf25ae353f8cacddddd0 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Tue Apr 10 21:37:03 2012 UTC Test drawing WindowBuffer to frame buffer CompositeEngine::Draw() working better - also not locking exclusively & for a much shorter duration. There seems to be some issues with DrawBuffer(), it draws very quickly, but there are large black regions seemingly even outside the drawing region... very strange. Created AlphaRegion to hold and compute the WindowBuffer region's alpha areas as well as the screen's for fast reference. The theory is that the screen's alpha region will be updated for every window movement (focus changes, moving windows, minmizations, blocking, etc...) and each WindowBuffer's region will be largely stagnant, or will change relatively slowly. It is one consideration into the forthcoming Compositing Optimization Guide for Haiku application developers. ---------------------------------------------------------------------------- ############################################################################ Commit: 537a2cabe7d841c0dd1daf5c9c814b232a1750f4 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Thu Apr 12 01:11:14 2012 UTC Cleaned up CompositingPrivate Haven't even tried compiling these changes. RenderSession may or may not persist, just exploring matters... Having hard drive difficulties so I thought it best to push these changes up ASAP. ---------------------------------------------------------------------------- ############################################################################ Commit: 388e1affb237f576dce3265c23c61517c60ed723 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Apr 13 00:33:58 2012 UTC Coding with headache == hard Correcting mistakes and completing initial CompositingPrivate changes. Removed RenderSession, may have windows maintain visible regions. Compiles - haven't tested running yet, but there should be no new issues. ---------------------------------------------------------------------------- ############################################################################ Commit: 6fe07471eb0087168b29d1729f82472ec6ba103a Author: looncraz <looncraz@xxxxxxxxxxx> Date: Fri Apr 13 22:49:49 2012 UTC More client-server comms Flesh out more of the CompositeEngine communication protocol. There is currently a stalling issue with getCompositingConfig() in CompositingProvate. Began to flesh out the fundamental server-side requirements for BCompositeOverlay, which is a BBitmap which accepts views and will provide numerous special-purpose features (such as locking to mouse movement and likely other conditions). Decided to make over-provisioning configurable. Also re-worked BWindow::_RequestEffect() to not use a BMessage by internally converting an uint32 to BPrivate::effect_type. Builds & runs. Have observed a performance increase in non-composited mode. I believe this is due to the optimizations in the code-paths for ConvertForDrawing vs ConvertToScreenForDrawing. The latter, IIRC, used a side-effect to work up view hierarchy which resulted in numerous vtable lookups. Don't quote me on that though... long time since I looked at the original code ;-) My guess of +0.5fps in CompositePerfTest3 was about spot-on, seeing about +0.75fps in VMWare. ---------------------------------------------------------------------------- ############################################################################ Commit: 67b90e34a3c9737c1b8e4bdcf14809898638c386 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sat Apr 14 23:56:43 2012 UTC CompositeOverlay More CompositeOverlay work. I believe this should remain public API, but perhaps not until compositing is more stabilized. ---------------------------------------------------------------------------- ############################################################################ Commit: 6ad2af33ca7243630c3a2b6373f6635bd8068680 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sun Apr 15 14:20:31 2012 UTC BCompositeOverlay Public API should now be final. Client code should be functional. Server-side code still just a place-holder. Compiles & links once again. TODO: need to convert rgb_color to a fill pattern based upon BBitmap's color space rather than using the accelerant's conversion in case the video driver uses a different pattern and will convert the bitmap before displaying on-screen. I doubt this is a problem on x86 these days, but other platforms will likely also desire the compositing features. ---------------------------------------------------------------------------- ############################################################################ Commit: 090b4504b48ec428a4204f393f0e864314777cbd Author: looncraz <looncraz@xxxxxxxxxxx> Date: Mon Apr 16 01:36:31 2012 UTC Server-side CompositeOverlay Setting up the server-side of things for BCompositeOverlay. Also touched a couple of other areas as I ran into things that need to be implemented now or in the future. Compiles - will not link (missing CompositeEngine::Hide(CompositeOverlay*) and Show(...)). ---------------------------------------------------------------------------- ############################################################################ Commit: 4687592535a3a7cdf3529a3e1ef2a6d46fbc948a Author: looncraz <looncraz@xxxxxxxxxxx> Date: Wed Apr 18 23:17:17 2012 UTC Adjust to requirements. Found most of the reason why the drawing was all weird... mostly due to clipping - which I anticipated... Further investigated the conversion requirements, and stripped out unneeded virtual overrides. Making some attempts to improve performance, I have investigated the need for alpha regions - determined they are more vital than ever if we hope to have CPU-based compositing with an acceptable performance level... Preparing for cursor overlays, and a few other tidbits. ---------------------------------------------------------------------------- ############################################################################ Commit: 1489f21a65cc70da3b2380c9e331306dd05dd182 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Sat Apr 21 01:18:29 2012 UTC Coordinate conversion & optimization Added ability to convert back from the window's coordinate space to a view for various current and future uses. "Profiled" code paths to determine usage and performance, decided optimization was called for - and was surprised by the end result. CompositePerfTest3 went from 24FPS to 27FPS - with just 12bytes or so of RAM per view extra... Also cleans up the code nicely ;-) Wish I had more time... and that I weren't sick :-( ---------------------------------------------------------------------------- ############################################################################ Commit: 76dfc16cc25448807d2ed6e28a45de749c95554e Author: looncraz <looncraz@xxxxxxxxxxx> Date: Mon Apr 23 20:27:27 2012 UTC ScreenStateGrid & more ScreenStateGrid represents the visible screen as a grid of cells. It is just an unfinished header at this point. Made changes to some comments to better suit the understandability to the uninitiated (i.e.... everyone else but me...). Also preparing CompositeEngine to use ScreenStateGrid, and to re-purpose Desktop's window listing rather than having its own. Z-order will be handled by sorting the Desktop's window list. The desktop window will be window 0, and the top-most window will be at the highest index. Also a bit of extra loop unrolling to help speed up the final render task - more unrolling may be worthwhile, but it could be counter-productive at the same time... ---------------------------------------------------------------------------- ############################################################################ Commit: e12c27cf6c418b7467a7a10c288229963cea9e71 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Mon Apr 23 22:27:40 2012 UTC Poor scaling, so re-designed Quick-n-dirty performance test of a faux-ScreenStateGrid determined that the grid method would have poor scalability at higher resolutions. It was faster at 1024x768 and below, but from there became slower. Mutated ScreenStateGrid into CompositeScreenStates, which holds numerous regions an interplexes them to gain the necessary output regions. ---------------------------------------------------------------------------- ############################################################################ Commit: 57a09efe27371b022b4807139f4e74ac6e2c3259 Author: looncraz <looncraz@xxxxxxxxxxx> Date: Mon Apr 23 23:40:29 2012 UTC Re-orient towards CompositeScreenStates Haven't test CompositeScreenStates yet, so that is next on my todo list (off git). CompositeEngine's crude test-mode Draw() function has been gutted as it was no longer usable. Once CompositeScreenStates is verified, I will be moving to direct full-mode compositing of all windows, working out the kinks as they come along. ---------------------------------------------------------------------------- ############################################################################ Commit: fe7207954e1107589c440b9181a85a2a4fcc352f Author: looncraz <looncraz@xxxxxxxxxxx> Date: Tue Apr 24 02:03:44 2012 UTC CScreenStates verified (well enough for now, anyway) No changes needed to CScreenStates - seems to work like a charm. Re-oriented towards using it, will be working window events back up the (logical) object stack to assure all is well. Next temporary draw routine will cycle through every window, in order, in the dirty region and draw them. It will then perform the alpha-mode render. Performance will be sad, but it will be required to make further progress. ----------------------------------------------------------------------------