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