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 26const static bigtime_t kOverlayTimeout = 1000000LL; 27 // after 1 second, the team holding the lock will be killed 28 29class SemaphoreLocker { 30public: 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 52private: 53 sem_id fSemaphore; 54 status_t fStatus; 55}; 56 57 58// #pragma mark - 59 60 61Overlay::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){ 0, 80, 0, 0 }; 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 86Overlay::~Overlay() 87{ 88 fHWInterface.ReleaseOverlayChannel(fOverlayToken); 89 _FreeBuffer(); 90 91 delete_sem(fSemaphore); 92 TRACE("overlay: deleted %p\n", this); 93} 94 95 96status_t 97Overlay::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 109status_t 110Overlay::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 128status_t 129Overlay::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 145void 146Overlay::_FreeBuffer() 147{ 148 fHWInterface.FreeOverlayBuffer(fOverlayBuffer); 149 fOverlayBuffer = NULL; 150} 151 152 153status_t 154Overlay::_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 165void 166Overlay::SetClientData(overlay_client_data* clientData) 167{ 168 fClientData = clientData; 169 fClientData->lock = fSemaphore; 170 fClientData->buffer = (uint8*)fOverlayBuffer->buffer; 171} 172 173 174void 175Overlay::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 186void 187Overlay::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 198const overlay_buffer* 199Overlay::OverlayBuffer() const 200{ 201 return fOverlayBuffer; 202} 203 204 205overlay_client_data* 206Overlay::ClientData() const 207{ 208 return fClientData; 209} 210 211 212overlay_token 213Overlay::OverlayToken() const 214{ 215 return fOverlayToken; 216} 217 218 219void 220Overlay::Hide() 221{ 222 if (fOverlayToken == NULL) 223 return; 224 225 fHWInterface.HideOverlay(this); 226 TRACE("overlay: hide %p\n", this); 227} 228 229 230void 231Overlay::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_RGB15: 241 greenShift = colorShift = 3; 242 alphaShift = 7; 243 break; 244 case B_RGB16: 245 colorShift = 3; 246 greenShift = 2; 247 alphaShift = 8; 248 break; 249 } 250 251 fWindow.red.value = colorKey.red >> colorShift; 252 fWindow.green.value = colorKey.green >> greenShift; 253 fWindow.blue.value = colorKey.blue >> colorShift; 254 fWindow.alpha.value = colorKey.alpha >> alphaShift; 255 fWindow.red.mask = 0xff >> colorShift; 256 fWindow.green.mask = 0xff >> greenShift; 257 fWindow.blue.mask = 0xff >> colorShift; 258 fWindow.alpha.mask = 0xff >> alphaShift; 259} 260 261 262void 263Overlay::Configure(const BRect& source, const BRect& destination) 264{ 265 if (fOverlayToken == NULL) { 266 fOverlayToken = fHWInterface.AcquireOverlayChannel(); 267 if (fOverlayToken == NULL) 268 return; 269 } 270 271 TRACE("overlay: configure %p\n", this); 272 273 fView.h_start = (uint16)source.left; 274 fView.v_start = (uint16)source.top; 275 fView.width = (uint16)source.IntegerWidth() + 1; 276 fView.height = (uint16)source.IntegerHeight() + 1; 277 278 fWindow.h_start = (int16)destination.left; 279 fWindow.v_start = (int16)destination.top; 280 fWindow.width = (uint16)destination.IntegerWidth() + 1; 281 fWindow.height = (uint16)destination.IntegerHeight() + 1; 282 283 fHWInterface.ConfigureOverlay(this); 284} 285 286