1 /* 2 * Copyright 2006-2009, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "Overlay.h" 11 12 #include <BitmapPrivate.h> 13 14 #include "HWInterface.h" 15 #include "ServerBitmap.h" 16 17 18 //#define TRACE_OVERLAY 19 #ifdef TRACE_OVERLAY 20 # define TRACE(x...) ktrace_printf(x); 21 #else 22 # define TRACE(x...) ; 23 #endif 24 25 26 const static bigtime_t kOverlayTimeout = 1000000LL; 27 // after 1 second, the team holding the lock will be killed 28 29 class SemaphoreLocker { 30 public: 31 SemaphoreLocker(sem_id semaphore, bigtime_t timeout = B_INFINITE_TIMEOUT) 32 : 33 fSemaphore(semaphore) 34 { 35 do { 36 fStatus = acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, 37 timeout); 38 } while (fStatus == B_INTERRUPTED); 39 } 40 41 ~SemaphoreLocker() 42 { 43 if (fStatus == B_OK) 44 release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE); 45 } 46 47 status_t LockStatus() 48 { 49 return fStatus; 50 } 51 52 private: 53 sem_id fSemaphore; 54 status_t fStatus; 55 }; 56 57 58 // #pragma mark - 59 60 61 Overlay::Overlay(HWInterface& interface, ServerBitmap* bitmap, 62 overlay_token token) 63 : 64 fHWInterface(interface), 65 fOverlayBuffer(NULL), 66 fClientData(NULL), 67 fOverlayToken(token) 68 { 69 fSemaphore = create_sem(1, "overlay lock"); 70 fColor = (rgb_color){ 21, 16, 21, 16 }; 71 // TODO: whatever fine color we want to use here... 72 73 fWindow.offset_top = 0; 74 fWindow.offset_left = 0; 75 fWindow.offset_right = 0; 76 fWindow.offset_bottom = 0; 77 78 fWindow.flags = B_OVERLAY_COLOR_KEY; 79 80 _AllocateBuffer(bitmap); 81 82 TRACE("overlay: created %p, bitmap %p\n", this, bitmap); 83 } 84 85 86 Overlay::~Overlay() 87 { 88 fHWInterface.ReleaseOverlayChannel(fOverlayToken); 89 _FreeBuffer(); 90 91 delete_sem(fSemaphore); 92 TRACE("overlay: deleted %p\n", this); 93 } 94 95 96 status_t 97 Overlay::InitCheck() const 98 { 99 if (fSemaphore < B_OK) 100 return fSemaphore; 101 102 if (fOverlayBuffer == NULL) 103 return B_NO_MEMORY; 104 105 return B_OK; 106 } 107 108 109 status_t 110 Overlay::Resume(ServerBitmap* bitmap) 111 { 112 SemaphoreLocker locker(fSemaphore, kOverlayTimeout); 113 if (locker.LockStatus() == B_TIMED_OUT) { 114 // TODO: kill app! 115 } 116 117 TRACE("overlay: resume %p (lock status %ld)\n", this, locker.LockStatus()); 118 119 status_t status = _AllocateBuffer(bitmap); 120 if (status < B_OK) 121 return status; 122 123 fClientData->buffer = (uint8*)fOverlayBuffer->buffer; 124 return B_OK; 125 } 126 127 128 status_t 129 Overlay::Suspend(ServerBitmap* bitmap, bool needTemporary) 130 { 131 SemaphoreLocker locker(fSemaphore, kOverlayTimeout); 132 if (locker.LockStatus() == B_TIMED_OUT) { 133 // TODO: kill app! 134 } 135 136 TRACE("overlay: suspend %p (lock status %ld)\n", this, locker.LockStatus()); 137 138 _FreeBuffer(); 139 fClientData->buffer = NULL; 140 141 return B_OK; 142 } 143 144 145 void 146 Overlay::_FreeBuffer() 147 { 148 fHWInterface.FreeOverlayBuffer(fOverlayBuffer); 149 fOverlayBuffer = NULL; 150 } 151 152 153 status_t 154 Overlay::_AllocateBuffer(ServerBitmap* bitmap) 155 { 156 fOverlayBuffer = fHWInterface.AllocateOverlayBuffer(bitmap->Width(), 157 bitmap->Height(), bitmap->ColorSpace()); 158 if (fOverlayBuffer == NULL) 159 return B_NO_MEMORY; 160 161 return B_OK; 162 } 163 164 165 void 166 Overlay::SetClientData(overlay_client_data* clientData) 167 { 168 fClientData = clientData; 169 fClientData->lock = fSemaphore; 170 fClientData->buffer = (uint8*)fOverlayBuffer->buffer; 171 } 172 173 174 void 175 Overlay::SetFlags(uint32 flags) 176 { 177 if (flags & B_OVERLAY_FILTER_HORIZONTAL) 178 fWindow.flags |= B_OVERLAY_HORIZONTAL_FILTERING; 179 if (flags & B_OVERLAY_FILTER_VERTICAL) 180 fWindow.flags |= B_OVERLAY_VERTICAL_FILTERING; 181 if (flags & B_OVERLAY_MIRROR) 182 fWindow.flags |= B_OVERLAY_HORIZONTAL_MIRRORING; 183 } 184 185 186 void 187 Overlay::TakeOverToken(Overlay* other) 188 { 189 overlay_token token = other->OverlayToken(); 190 if (token == NULL) 191 return; 192 193 fOverlayToken = token; 194 //other->fOverlayToken = NULL; 195 } 196 197 198 const overlay_buffer* 199 Overlay::OverlayBuffer() const 200 { 201 return fOverlayBuffer; 202 } 203 204 205 overlay_client_data* 206 Overlay::ClientData() const 207 { 208 return fClientData; 209 } 210 211 212 overlay_token 213 Overlay::OverlayToken() const 214 { 215 return fOverlayToken; 216 } 217 218 219 void 220 Overlay::Hide() 221 { 222 if (fOverlayToken == NULL) 223 return; 224 225 fHWInterface.HideOverlay(this); 226 TRACE("overlay: hide %p\n", this); 227 } 228 229 230 void 231 Overlay::SetColorSpace(uint32 colorSpace) 232 { 233 if ((fWindow.flags & B_OVERLAY_COLOR_KEY) == 0) 234 return; 235 236 uint8 colorShift = 0, greenShift = 0, alphaShift = 0; 237 rgb_color colorKey = fColor; 238 239 switch (colorSpace) { 240 case B_CMAP8: 241 colorKey.red = 0xff; 242 colorKey.green = 0xff; 243 colorKey.blue = 0xff; 244 colorKey.alpha = 0xff; 245 break; 246 case B_RGB15: 247 greenShift = colorShift = 3; 248 alphaShift = 7; 249 break; 250 case B_RGB16: 251 colorShift = 3; 252 greenShift = 2; 253 alphaShift = 8; 254 break; 255 } 256 257 fWindow.red.value = colorKey.red >> colorShift; 258 fWindow.green.value = colorKey.green >> greenShift; 259 fWindow.blue.value = colorKey.blue >> colorShift; 260 fWindow.alpha.value = colorKey.alpha >> alphaShift; 261 fWindow.red.mask = 0xff >> colorShift; 262 fWindow.green.mask = 0xff >> greenShift; 263 fWindow.blue.mask = 0xff >> colorShift; 264 fWindow.alpha.mask = 0xff >> alphaShift; 265 } 266 267 268 void 269 Overlay::Configure(const BRect& source, const BRect& destination) 270 { 271 if (fOverlayToken == NULL) { 272 fOverlayToken = fHWInterface.AcquireOverlayChannel(); 273 if (fOverlayToken == NULL) 274 return; 275 } 276 277 TRACE("overlay: configure %p\n", this); 278 279 fView.h_start = (uint16)source.left; 280 fView.v_start = (uint16)source.top; 281 fView.width = (uint16)source.IntegerWidth() + 1; 282 fView.height = (uint16)source.IntegerHeight() + 1; 283 284 fWindow.h_start = (int16)destination.left; 285 fWindow.v_start = (int16)destination.top; 286 fWindow.width = (uint16)destination.IntegerWidth() + 1; 287 fWindow.height = (uint16)destination.IntegerHeight() + 1; 288 289 fHWInterface.ConfigureOverlay(this); 290 } 291 292