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