xref: /haiku/src/servers/app/drawing/UpdateQueue.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
1 /*
2  * Copyright 2005-2008 Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #include "UpdateQueue.h"
6 
7 #include <new>
8 #include <stdio.h>
9 #include <string.h>
10 
11 
12 //#define TRACE_UPDATE_QUEUE
13 #ifdef TRACE_UPDATE_QUEUE
14 #	include <FunctionTracer.h>
15 #	include <String.h>
16 
17 	static int32 sFunctionDepth = -1;
18 #	define CALLED(x...)	FunctionTracer _ft("UpdateQueue", __FUNCTION__, \
19 							sFunctionDepth)
20 #	define TRACE(x...)	{ BString _to; \
21 							_to.Append(' ', (sFunctionDepth + 1) * 2); \
22 							printf("%s", _to.String()); printf(x); }
23 #else
24 #	define CALLED(x...)
25 #	define TRACE(x...)
26 #endif
27 
28 
29 // constructor
30 UpdateQueue::UpdateQueue(HWInterface* interface)
31 	:
32 	BLocker("AppServer_UpdateQueue"),
33 	fQuitting(false),
34  	fInterface(interface),
35 	fUpdateRegion(),
36 	fUpdateExecutor(B_BAD_THREAD_ID),
37 	fRetraceSem(B_BAD_SEM_ID),
38 	fRefreshDuration(1000000 / 60)
39 {
40 	CALLED();
41 	TRACE("this: %p\n", this);
42 	TRACE("fInterface: %p\n", fInterface);
43 }
44 
45 // destructor
46 UpdateQueue::~UpdateQueue()
47 {
48 	CALLED();
49 
50 	Shutdown();
51 }
52 
53 // FrameBufferChanged
54 void
55 UpdateQueue::FrameBufferChanged()
56 {
57 	CALLED();
58 
59 	Init();
60 }
61 
62 // Init
63 status_t
64 UpdateQueue::Init()
65 {
66 	CALLED();
67 
68 	Shutdown();
69 
70 	fRetraceSem = fInterface->RetraceSemaphore();
71 //	fRefreshDuration = fInterface->...
72 
73 	TRACE("fRetraceSem: %ld, fRefreshDuration: %lld\n",
74 		fRetraceSem, fRefreshDuration);
75 
76 	fQuitting = false;
77 	fUpdateExecutor = spawn_thread(_ExecuteUpdatesEntry, "update queue runner",
78 		B_REAL_TIME_PRIORITY, this);
79 	if (fUpdateExecutor < B_OK)
80 		return fUpdateExecutor;
81 
82 	return resume_thread(fUpdateExecutor);
83 }
84 
85 // Shutdown
86 void
87 UpdateQueue::Shutdown()
88 {
89 	CALLED();
90 
91 	if (fUpdateExecutor < B_OK)
92 		return;
93 	fQuitting = true;
94 	status_t exitValue;
95 	wait_for_thread(fUpdateExecutor, &exitValue);
96 	fUpdateExecutor = B_BAD_THREAD_ID;
97 }
98 
99 // AddRect
100 void
101 UpdateQueue::AddRect(const BRect& rect)
102 {
103 	if (!rect.IsValid())
104 		return;
105 
106 	CALLED();
107 
108 	if (Lock()) {
109 		fUpdateRegion.Include(rect);
110 		Unlock();
111 	}
112 }
113 
114 // _ExecuteUpdatesEntry
115 int32
116 UpdateQueue::_ExecuteUpdatesEntry(void* cookie)
117 {
118 	UpdateQueue *gc = (UpdateQueue*)cookie;
119 	return gc->_ExecuteUpdates();
120 }
121 
122 // _ExecuteUpdates
123 int32
124 UpdateQueue::_ExecuteUpdates()
125 {
126 	while (!fQuitting) {
127 		status_t err;
128 		if (fRetraceSem >= 0) {
129 			bigtime_t timeout = system_time() + fRefreshDuration * 2;
130 //			TRACE("acquire_sem_etc(%lld)\n", timeout);
131 			do {
132 				err = acquire_sem_etc(fRetraceSem, 1,
133 					B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout);
134 			} while (err == B_INTERRUPTED && !fQuitting);
135 		} else {
136 			bigtime_t timeout = system_time() + fRefreshDuration;
137 //			TRACE("snooze_until(%lld)\n", timeout);
138 			do {
139 				err = snooze_until(timeout, B_SYSTEM_TIMEBASE);
140 			} while (err == B_INTERRUPTED && !fQuitting);
141 		}
142 		if (fQuitting)
143 			return B_OK;
144 		switch (err) {
145 			case B_OK:
146 			case B_TIMED_OUT:
147 				// execute updates
148 				if (fInterface->LockParallelAccess()) {
149 					if (Lock()) {
150 						int32 count = fUpdateRegion.CountRects();
151 						if (count > 0) {
152 							TRACE("CopyBackToFront() - rects: %ld\n", count);
153 							// NOTE: not using the BRegion version, since that
154 							// doesn't take care of leaving out and compositing
155 							// the cursor.
156 							for (int32 i = 0; i < count; i++)
157 								fInterface->CopyBackToFront(
158 									fUpdateRegion.RectAt(i));
159 							fUpdateRegion.MakeEmpty();
160 						}
161 						Unlock();
162 					}
163 					fInterface->UnlockParallelAccess();
164 				}
165 				break;
166 			default:
167 				return err;
168 		}
169 	}
170 	return B_OK;
171 }
172 
173