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