xref: /haiku/src/servers/app/drawing/UpdateQueue.cpp (revision 2469a6f4272b43fb04e11290808216f6a7610599)
1*2469a6f4SStephan Aßmus /*
2*2469a6f4SStephan Aßmus  * Copyright 2005-2008 Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
3*2469a6f4SStephan Aßmus  * Distributed under the terms of the MIT License.
4*2469a6f4SStephan Aßmus  */
5*2469a6f4SStephan Aßmus #include "UpdateQueue.h"
63294d07bSStephan Aßmus 
73294d07bSStephan Aßmus #include <new>
83294d07bSStephan Aßmus #include <stdio.h>
9f6939eb1SStephan Aßmus #include <string.h>
103294d07bSStephan Aßmus 
113294d07bSStephan Aßmus 
12*2469a6f4SStephan Aßmus //#define TRACE_UPDATE_QUEUE
13*2469a6f4SStephan Aßmus #ifdef TRACE_UPDATE_QUEUE
14*2469a6f4SStephan Aßmus #	include <FunctionTracer.h>
15*2469a6f4SStephan Aßmus #	include <String.h>
16*2469a6f4SStephan Aßmus 
17*2469a6f4SStephan Aßmus 	static int32 sFunctionDepth = -1;
18*2469a6f4SStephan Aßmus #	define CALLED(x...)	FunctionTracer _ft("UpdateQueue", __FUNCTION__, \
19*2469a6f4SStephan Aßmus 							sFunctionDepth)
20*2469a6f4SStephan Aßmus #	define TRACE(x...)	{ BString _to; \
21*2469a6f4SStephan Aßmus 							_to.Append(' ', (sFunctionDepth + 1) * 2); \
22*2469a6f4SStephan Aßmus 							printf("%s", _to.String()); printf(x); }
23*2469a6f4SStephan Aßmus #else
24*2469a6f4SStephan Aßmus #	define CALLED(x...)
25*2469a6f4SStephan Aßmus #	define TRACE(x...)
26*2469a6f4SStephan Aßmus #endif
27*2469a6f4SStephan Aßmus 
283294d07bSStephan Aßmus 
293294d07bSStephan Aßmus // constructor
UpdateQueue(HWInterface * interface)303294d07bSStephan Aßmus UpdateQueue::UpdateQueue(HWInterface* interface)
31*2469a6f4SStephan Aßmus 	:
32*2469a6f4SStephan Aßmus 	BLocker("AppServer_UpdateQueue"),
33*2469a6f4SStephan Aßmus 	fQuitting(false),
34f38c001eSMarcus Overhagen  	fInterface(interface),
353294d07bSStephan Aßmus 	fUpdateRegion(),
36*2469a6f4SStephan Aßmus 	fUpdateExecutor(B_BAD_THREAD_ID),
37*2469a6f4SStephan Aßmus 	fRetraceSem(B_BAD_SEM_ID),
38*2469a6f4SStephan Aßmus 	fRefreshDuration(1000000 / 60)
393294d07bSStephan Aßmus {
40*2469a6f4SStephan Aßmus 	CALLED();
41*2469a6f4SStephan Aßmus 	TRACE("this: %p\n", this);
42*2469a6f4SStephan Aßmus 	TRACE("fInterface: %p\n", fInterface);
433294d07bSStephan Aßmus }
443294d07bSStephan Aßmus 
453294d07bSStephan Aßmus // destructor
~UpdateQueue()463294d07bSStephan Aßmus UpdateQueue::~UpdateQueue()
473294d07bSStephan Aßmus {
48*2469a6f4SStephan Aßmus 	CALLED();
49*2469a6f4SStephan Aßmus 
50*2469a6f4SStephan Aßmus 	Shutdown();
513294d07bSStephan Aßmus }
523294d07bSStephan Aßmus 
53*2469a6f4SStephan Aßmus // FrameBufferChanged
54*2469a6f4SStephan Aßmus void
FrameBufferChanged()55*2469a6f4SStephan Aßmus UpdateQueue::FrameBufferChanged()
563294d07bSStephan Aßmus {
57*2469a6f4SStephan Aßmus 	CALLED();
58*2469a6f4SStephan Aßmus 
59*2469a6f4SStephan Aßmus 	Init();
60*2469a6f4SStephan Aßmus }
61*2469a6f4SStephan Aßmus 
62*2469a6f4SStephan Aßmus // Init
63*2469a6f4SStephan Aßmus status_t
Init()64*2469a6f4SStephan Aßmus UpdateQueue::Init()
65*2469a6f4SStephan Aßmus {
66*2469a6f4SStephan Aßmus 	CALLED();
67*2469a6f4SStephan Aßmus 
68*2469a6f4SStephan Aßmus 	Shutdown();
69*2469a6f4SStephan Aßmus 
70*2469a6f4SStephan Aßmus 	fRetraceSem = fInterface->RetraceSemaphore();
71*2469a6f4SStephan Aßmus //	fRefreshDuration = fInterface->...
72*2469a6f4SStephan Aßmus 
73*2469a6f4SStephan Aßmus 	TRACE("fRetraceSem: %ld, fRefreshDuration: %lld\n",
74*2469a6f4SStephan Aßmus 		fRetraceSem, fRefreshDuration);
75*2469a6f4SStephan Aßmus 
76*2469a6f4SStephan Aßmus 	fQuitting = false;
77*2469a6f4SStephan Aßmus 	fUpdateExecutor = spawn_thread(_ExecuteUpdatesEntry, "update queue runner",
78*2469a6f4SStephan Aßmus 		B_REAL_TIME_PRIORITY, this);
79*2469a6f4SStephan Aßmus 	if (fUpdateExecutor < B_OK)
80*2469a6f4SStephan Aßmus 		return fUpdateExecutor;
81*2469a6f4SStephan Aßmus 
82*2469a6f4SStephan Aßmus 	return resume_thread(fUpdateExecutor);
83*2469a6f4SStephan Aßmus }
84*2469a6f4SStephan Aßmus 
85*2469a6f4SStephan Aßmus // Shutdown
86*2469a6f4SStephan Aßmus void
Shutdown()87*2469a6f4SStephan Aßmus UpdateQueue::Shutdown()
88*2469a6f4SStephan Aßmus {
89*2469a6f4SStephan Aßmus 	CALLED();
90*2469a6f4SStephan Aßmus 
91*2469a6f4SStephan Aßmus 	if (fUpdateExecutor < B_OK)
92*2469a6f4SStephan Aßmus 		return;
93*2469a6f4SStephan Aßmus 	fQuitting = true;
94*2469a6f4SStephan Aßmus 	status_t exitValue;
95*2469a6f4SStephan Aßmus 	wait_for_thread(fUpdateExecutor, &exitValue);
96*2469a6f4SStephan Aßmus 	fUpdateExecutor = B_BAD_THREAD_ID;
973294d07bSStephan Aßmus }
983294d07bSStephan Aßmus 
993294d07bSStephan Aßmus // AddRect
1003294d07bSStephan Aßmus void
AddRect(const BRect & rect)1013294d07bSStephan Aßmus UpdateQueue::AddRect(const BRect& rect)
1023294d07bSStephan Aßmus {
103*2469a6f4SStephan Aßmus 	if (!rect.IsValid())
104*2469a6f4SStephan Aßmus 		return;
105*2469a6f4SStephan Aßmus 
106*2469a6f4SStephan Aßmus 	CALLED();
107*2469a6f4SStephan Aßmus 
108*2469a6f4SStephan Aßmus 	if (Lock()) {
1093294d07bSStephan Aßmus 		fUpdateRegion.Include(rect);
110*2469a6f4SStephan Aßmus 		Unlock();
111*2469a6f4SStephan Aßmus 	}
1123294d07bSStephan Aßmus }
1133294d07bSStephan Aßmus 
114*2469a6f4SStephan Aßmus // _ExecuteUpdatesEntry
1153294d07bSStephan Aßmus int32
_ExecuteUpdatesEntry(void * cookie)116*2469a6f4SStephan Aßmus UpdateQueue::_ExecuteUpdatesEntry(void* cookie)
1173294d07bSStephan Aßmus {
1183294d07bSStephan Aßmus 	UpdateQueue *gc = (UpdateQueue*)cookie;
1193294d07bSStephan Aßmus 	return gc->_ExecuteUpdates();
1203294d07bSStephan Aßmus }
1213294d07bSStephan Aßmus 
1223294d07bSStephan Aßmus // _ExecuteUpdates
1233294d07bSStephan Aßmus int32
_ExecuteUpdates()1243294d07bSStephan Aßmus UpdateQueue::_ExecuteUpdates()
1253294d07bSStephan Aßmus {
126*2469a6f4SStephan Aßmus 	while (!fQuitting) {
127*2469a6f4SStephan Aßmus 		status_t err;
128*2469a6f4SStephan Aßmus 		if (fRetraceSem >= 0) {
129*2469a6f4SStephan Aßmus 			bigtime_t timeout = system_time() + fRefreshDuration * 2;
130*2469a6f4SStephan Aßmus //			TRACE("acquire_sem_etc(%lld)\n", timeout);
131*2469a6f4SStephan Aßmus 			do {
132*2469a6f4SStephan Aßmus 				err = acquire_sem_etc(fRetraceSem, 1,
133*2469a6f4SStephan Aßmus 					B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout);
134*2469a6f4SStephan Aßmus 			} while (err == B_INTERRUPTED && !fQuitting);
135*2469a6f4SStephan Aßmus 		} else {
136*2469a6f4SStephan Aßmus 			bigtime_t timeout = system_time() + fRefreshDuration;
137*2469a6f4SStephan Aßmus //			TRACE("snooze_until(%lld)\n", timeout);
138*2469a6f4SStephan Aßmus 			do {
139*2469a6f4SStephan Aßmus 				err = snooze_until(timeout, B_SYSTEM_TIMEBASE);
140*2469a6f4SStephan Aßmus 			} while (err == B_INTERRUPTED && !fQuitting);
141*2469a6f4SStephan Aßmus 		}
142*2469a6f4SStephan Aßmus 		if (fQuitting)
143*2469a6f4SStephan Aßmus 			return B_OK;
1443294d07bSStephan Aßmus 		switch (err) {
1453294d07bSStephan Aßmus 			case B_OK:
1463294d07bSStephan Aßmus 			case B_TIMED_OUT:
1473294d07bSStephan Aßmus 				// execute updates
1482cfe93e7SStephan Aßmus 				if (fInterface->LockParallelAccess()) {
149*2469a6f4SStephan Aßmus 					if (Lock()) {
1503294d07bSStephan Aßmus 						int32 count = fUpdateRegion.CountRects();
151f6939eb1SStephan Aßmus 						if (count > 0) {
152*2469a6f4SStephan Aßmus 							TRACE("CopyBackToFront() - rects: %ld\n", count);
153*2469a6f4SStephan Aßmus 							// NOTE: not using the BRegion version, since that
154*2469a6f4SStephan Aßmus 							// doesn't take care of leaving out and compositing
155*2469a6f4SStephan Aßmus 							// the cursor.
156*2469a6f4SStephan Aßmus 							for (int32 i = 0; i < count; i++)
157*2469a6f4SStephan Aßmus 								fInterface->CopyBackToFront(
158*2469a6f4SStephan Aßmus 									fUpdateRegion.RectAt(i));
1593294d07bSStephan Aßmus 							fUpdateRegion.MakeEmpty();
160f6939eb1SStephan Aßmus 						}
161*2469a6f4SStephan Aßmus 						Unlock();
162*2469a6f4SStephan Aßmus 					}
1632cfe93e7SStephan Aßmus 					fInterface->UnlockParallelAccess();
1643294d07bSStephan Aßmus 				}
1653294d07bSStephan Aßmus 				break;
1663294d07bSStephan Aßmus 			default:
167*2469a6f4SStephan Aßmus 				return err;
1683294d07bSStephan Aßmus 		}
1693294d07bSStephan Aßmus 	}
170*2469a6f4SStephan Aßmus 	return B_OK;
1713294d07bSStephan Aßmus }
1723294d07bSStephan Aßmus 
173