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 30UpdateQueue::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 46UpdateQueue::~UpdateQueue() 47{ 48 CALLED(); 49 50 Shutdown(); 51} 52 53// FrameBufferChanged 54void 55UpdateQueue::FrameBufferChanged() 56{ 57 CALLED(); 58 59 Init(); 60} 61 62// Init 63status_t 64UpdateQueue::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 86void 87UpdateQueue::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 100void 101UpdateQueue::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 115int32 116UpdateQueue::_ExecuteUpdatesEntry(void* cookie) 117{ 118 UpdateQueue *gc = (UpdateQueue*)cookie; 119 return gc->_ExecuteUpdates(); 120} 121 122// _ExecuteUpdates 123int32 124UpdateQueue::_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