1a817d6adSAxel Dörfler /* 257a6c095SAxel Dörfler * Copyright 2002-2006, Haiku Inc. 3a817d6adSAxel Dörfler * Distributed under the terms of the MIT License. 4a817d6adSAxel Dörfler * 5a817d6adSAxel Dörfler * Authors: 6a817d6adSAxel Dörfler * Stefano Ceccherini (burton666@libero.it) 7a817d6adSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 8a817d6adSAxel Dörfler */ 9a817d6adSAxel Dörfler 1057a6c095SAxel Dörfler /*! 1157a6c095SAxel Dörfler BPrivateScreen is the class which does the real work for 1257a6c095SAxel Dörfler the proxy class BScreen (it interacts with the app_server). 13a817d6adSAxel Dörfler */ 14a817d6adSAxel Dörfler 15a817d6adSAxel Dörfler 16d9525baaSAxel Dörfler #include "AppMisc.h" 17466871ccSAxel Dörfler #include "AppServerLink.h" 18466871ccSAxel Dörfler #include "PrivateScreen.h" 19466871ccSAxel Dörfler #include "ServerProtocol.h" 20466871ccSAxel Dörfler 2157a6c095SAxel Dörfler #include <Application.h> 22a817d6adSAxel Dörfler #include <Autolock.h> 2316046321SStefano Ceccherini #include <Bitmap.h> 248eae8b05SStefano Ceccherini #include <Locker.h> 25b66d7537SAxel Dörfler #include <ObjectList.h> 26624df6c6SStefano Ceccherini #include <Window.h> 27314a1024SStefano Ceccherini 28466871ccSAxel Dörfler #include <new> 29624df6c6SStefano Ceccherini 30466871ccSAxel Dörfler #include <stdlib.h> 3139ffb980SStefano Ceccherini 32624df6c6SStefano Ceccherini 33b66d7537SAxel Dörfler static BObjectList<BPrivateScreen> sScreens(2, true); 348eae8b05SStefano Ceccherini 358eae8b05SStefano Ceccherini // used to synchronize creation/deletion of the sScreen object 368eae8b05SStefano Ceccherini static BLocker sScreenLock("screen lock"); 37624df6c6SStefano Ceccherini 38624df6c6SStefano Ceccherini 39ca8ed922SStefano Ceccherini using namespace BPrivate; 40ca8ed922SStefano Ceccherini 41624df6c6SStefano Ceccherini BPrivateScreen * 42b66d7537SAxel Dörfler BPrivateScreen::Get(BWindow *window) 43624df6c6SStefano Ceccherini { 44d9525baaSAxel Dörfler screen_id id = B_MAIN_SCREEN_ID; 45d9525baaSAxel Dörfler 46d9525baaSAxel Dörfler if (window != NULL) { 47d9525baaSAxel Dörfler BPrivate::AppServerLink link; 48d9525baaSAxel Dörfler link.StartMessage(AS_GET_SCREEN_ID_FROM_WINDOW); 49d9525baaSAxel Dörfler link.Attach<int32>(_get_object_token_(window)); 50d9525baaSAxel Dörfler 51d9525baaSAxel Dörfler status_t status; 52d9525baaSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) 53d9525baaSAxel Dörfler link.Read<screen_id>(&id); 54d9525baaSAxel Dörfler } 55d9525baaSAxel Dörfler 56b66d7537SAxel Dörfler return _Get(id, false); 57624df6c6SStefano Ceccherini } 58624df6c6SStefano Ceccherini 59624df6c6SStefano Ceccherini 60624df6c6SStefano Ceccherini BPrivateScreen * 61b66d7537SAxel Dörfler BPrivateScreen::Get(screen_id id) 62b66d7537SAxel Dörfler { 63b66d7537SAxel Dörfler return _Get(id, true); 64b66d7537SAxel Dörfler } 65b66d7537SAxel Dörfler 66b66d7537SAxel Dörfler 67b66d7537SAxel Dörfler BPrivateScreen * 68b66d7537SAxel Dörfler BPrivateScreen::_Get(screen_id id, bool check) 69624df6c6SStefano Ceccherini { 7057a6c095SAxel Dörfler // Nothing works without an app_server connection 7157a6c095SAxel Dörfler if (be_app == NULL) 7257a6c095SAxel Dörfler return NULL; 7357a6c095SAxel Dörfler 74a817d6adSAxel Dörfler BAutolock locker(sScreenLock); 758eae8b05SStefano Ceccherini 76b66d7537SAxel Dörfler // search for the screen ID 77b66d7537SAxel Dörfler 78b66d7537SAxel Dörfler for (int32 i = sScreens.CountItems(); i-- > 0;) { 79b66d7537SAxel Dörfler BPrivateScreen* screen = sScreens.ItemAt(i); 80b66d7537SAxel Dörfler 81b66d7537SAxel Dörfler if (screen->ID().id == id.id) { 82b66d7537SAxel Dörfler screen->_Acquire(); 83b66d7537SAxel Dörfler return screen; 84b66d7537SAxel Dörfler } 858eae8b05SStefano Ceccherini } 868eae8b05SStefano Ceccherini 87b66d7537SAxel Dörfler if (check) { 88b66d7537SAxel Dörfler // check if ID is valid 89b66d7537SAxel Dörfler if (!_IsValid(id)) 90b66d7537SAxel Dörfler return NULL; 91b66d7537SAxel Dörfler } 92b66d7537SAxel Dörfler 93b66d7537SAxel Dörfler // we need to allocate a new one 94b66d7537SAxel Dörfler 95b66d7537SAxel Dörfler BPrivateScreen* screen = new (std::nothrow) BPrivateScreen(id); 96b66d7537SAxel Dörfler if (screen == NULL) 97b66d7537SAxel Dörfler return NULL; 98b66d7537SAxel Dörfler 99b66d7537SAxel Dörfler sScreens.AddItem(screen); 100b66d7537SAxel Dörfler return screen; 101624df6c6SStefano Ceccherini } 102624df6c6SStefano Ceccherini 103624df6c6SStefano Ceccherini 104624df6c6SStefano Ceccherini void 105b66d7537SAxel Dörfler BPrivateScreen::Put(BPrivateScreen* screen) 106624df6c6SStefano Ceccherini { 107b66d7537SAxel Dörfler if (screen == NULL) 108b66d7537SAxel Dörfler return; 109b66d7537SAxel Dörfler 110b66d7537SAxel Dörfler BAutolock locker(sScreenLock); 111b66d7537SAxel Dörfler 112b66d7537SAxel Dörfler if (screen->_Release()) { 113b66d7537SAxel Dörfler if (screen->ID().id != B_MAIN_SCREEN_ID.id) { 114b66d7537SAxel Dörfler // we always keep the main screen object around - it will 115b66d7537SAxel Dörfler // never go away, even if you disconnect all monitors. 116b66d7537SAxel Dörfler sScreens.RemoveItem(screen); 117b66d7537SAxel Dörfler } 118b66d7537SAxel Dörfler } 119624df6c6SStefano Ceccherini } 120624df6c6SStefano Ceccherini 121624df6c6SStefano Ceccherini 122b66d7537SAxel Dörfler BPrivateScreen* 123b66d7537SAxel Dörfler BPrivateScreen::GetNext(BPrivateScreen* screen) 124624df6c6SStefano Ceccherini { 125b66d7537SAxel Dörfler BAutolock locker(sScreenLock); 126b66d7537SAxel Dörfler 127b66d7537SAxel Dörfler screen_id id; 128b66d7537SAxel Dörfler status_t status = screen->GetNextID(id); 129b66d7537SAxel Dörfler if (status < B_OK) 130b66d7537SAxel Dörfler return NULL; 131b66d7537SAxel Dörfler 132b66d7537SAxel Dörfler BPrivateScreen* nextScreen = Get(id); 133b66d7537SAxel Dörfler if (nextScreen == NULL) 134b66d7537SAxel Dörfler return NULL; 135b66d7537SAxel Dörfler 136b66d7537SAxel Dörfler Put(screen); 137b66d7537SAxel Dörfler return nextScreen; 138624df6c6SStefano Ceccherini } 139624df6c6SStefano Ceccherini 140624df6c6SStefano Ceccherini 141b66d7537SAxel Dörfler bool 142b66d7537SAxel Dörfler BPrivateScreen::_IsValid(screen_id id) 143b66d7537SAxel Dörfler { 144b66d7537SAxel Dörfler BPrivate::AppServerLink link; 145b66d7537SAxel Dörfler link.StartMessage(AS_VALID_SCREEN_ID); 146b66d7537SAxel Dörfler link.Attach<screen_id>(id); 147b66d7537SAxel Dörfler 148b66d7537SAxel Dörfler status_t status; 149b66d7537SAxel Dörfler if (link.FlushWithReply(status) != B_OK || status < B_OK) 150b66d7537SAxel Dörfler return false; 151b66d7537SAxel Dörfler 152b66d7537SAxel Dörfler return true; 153b66d7537SAxel Dörfler } 154b66d7537SAxel Dörfler 155b66d7537SAxel Dörfler 156b66d7537SAxel Dörfler // #pragma mark - 157b66d7537SAxel Dörfler 158b66d7537SAxel Dörfler 159624df6c6SStefano Ceccherini color_space 160624df6c6SStefano Ceccherini BPrivateScreen::ColorSpace() 161624df6c6SStefano Ceccherini { 162624df6c6SStefano Ceccherini display_mode mode; 1631f41d635SStefano Ceccherini if (GetMode(B_CURRENT_WORKSPACE, &mode) == B_OK) 164624df6c6SStefano Ceccherini return (color_space)mode.space; 165624df6c6SStefano Ceccherini 166624df6c6SStefano Ceccherini return B_NO_COLOR_SPACE; 167624df6c6SStefano Ceccherini } 168624df6c6SStefano Ceccherini 169624df6c6SStefano Ceccherini 170624df6c6SStefano Ceccherini BRect 171624df6c6SStefano Ceccherini BPrivateScreen::Frame() 172624df6c6SStefano Ceccherini { 17339ffb980SStefano Ceccherini // If something goes wrong, we just return this rectangle. 17439ffb980SStefano Ceccherini 175b66d7537SAxel Dörfler if (system_time() > fLastUpdate + 100000) { 176b66d7537SAxel Dörfler // invalidate the settings after 0.1 secs 177b66d7537SAxel Dörfler display_mode mode; 178b66d7537SAxel Dörfler if (GetMode(B_CURRENT_WORKSPACE, &mode) == B_OK) { 179b66d7537SAxel Dörfler fFrame.Set(0, 0, (float)mode.virtual_width - 1, 180b66d7537SAxel Dörfler (float)mode.virtual_height - 1); 181b66d7537SAxel Dörfler fLastUpdate = system_time(); 182b66d7537SAxel Dörfler } 183b66d7537SAxel Dörfler } 184b66d7537SAxel Dörfler 185b66d7537SAxel Dörfler return fFrame; 186624df6c6SStefano Ceccherini } 187624df6c6SStefano Ceccherini 188624df6c6SStefano Ceccherini 189b66d7537SAxel Dörfler bool 190b66d7537SAxel Dörfler BPrivateScreen::IsValid() const 191624df6c6SStefano Ceccherini { 192b66d7537SAxel Dörfler return BPrivateScreen::_IsValid(ID()); 193b66d7537SAxel Dörfler } 194b66d7537SAxel Dörfler 195b66d7537SAxel Dörfler 196b66d7537SAxel Dörfler status_t 197b66d7537SAxel Dörfler BPrivateScreen::GetNextID(screen_id& id) 198b66d7537SAxel Dörfler { 199b66d7537SAxel Dörfler BPrivate::AppServerLink link; 200b66d7537SAxel Dörfler link.StartMessage(AS_GET_NEXT_SCREEN_ID); 201b66d7537SAxel Dörfler link.Attach<screen_id>(ID()); 202b66d7537SAxel Dörfler 203b66d7537SAxel Dörfler status_t status; 204b66d7537SAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 205b66d7537SAxel Dörfler link.Read<screen_id>(&id); 206b66d7537SAxel Dörfler return B_OK; 207b66d7537SAxel Dörfler } 208b66d7537SAxel Dörfler 209b66d7537SAxel Dörfler return status; 210624df6c6SStefano Ceccherini } 211624df6c6SStefano Ceccherini 212624df6c6SStefano Ceccherini 213624df6c6SStefano Ceccherini status_t 214624df6c6SStefano Ceccherini BPrivateScreen::WaitForRetrace(bigtime_t timeout) 215624df6c6SStefano Ceccherini { 216*5ec797a7SStephan Aßmus // TODO: remove when interrupts are enabled again in the ATI driver 217*5ec797a7SStephan Aßmus return B_ERROR; 218624df6c6SStefano Ceccherini // Get the retrace semaphore if it's the first time 219624df6c6SStefano Ceccherini // we are called. Cache the value then. 220*5ec797a7SStephan Aßmus if (!fRetraceSemValid) 221a817d6adSAxel Dörfler fRetraceSem = _RetraceSemaphore(); 222624df6c6SStefano Ceccherini 223*5ec797a7SStephan Aßmus if (fRetraceSem < 0) { 224*5ec797a7SStephan Aßmus // syncing to retrace is not supported by the accelerant 225*5ec797a7SStephan Aßmus return fRetraceSem; 226*5ec797a7SStephan Aßmus } 227*5ec797a7SStephan Aßmus 228*5ec797a7SStephan Aßmus status_t status; 229624df6c6SStefano Ceccherini do { 230624df6c6SStefano Ceccherini status = acquire_sem_etc(fRetraceSem, 1, B_RELATIVE_TIMEOUT, timeout); 231624df6c6SStefano Ceccherini } while (status == B_INTERRUPTED); 232624df6c6SStefano Ceccherini 233624df6c6SStefano Ceccherini return status; 234624df6c6SStefano Ceccherini } 235624df6c6SStefano Ceccherini 236624df6c6SStefano Ceccherini 237624df6c6SStefano Ceccherini uint8 238624df6c6SStefano Ceccherini BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha) 239624df6c6SStefano Ceccherini { 240624df6c6SStefano Ceccherini // Looks like this check is necessary 241a817d6adSAxel Dörfler if (red == B_TRANSPARENT_COLOR.red 242a817d6adSAxel Dörfler && green == B_TRANSPARENT_COLOR.green 243a817d6adSAxel Dörfler && blue == B_TRANSPARENT_COLOR.blue 244a817d6adSAxel Dörfler && alpha == B_TRANSPARENT_COLOR.alpha) 245624df6c6SStefano Ceccherini return B_TRANSPARENT_8_BIT; 246624df6c6SStefano Ceccherini 2470ef40c5eSMichael Lotz uint16 index = ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | (blue >> 3); 248a817d6adSAxel Dörfler if (ColorMap()) 2492ed35bc8SStefano Ceccherini return fColorMap->index_map[index]; 250624df6c6SStefano Ceccherini 251624df6c6SStefano Ceccherini return 0; 252624df6c6SStefano Ceccherini } 253624df6c6SStefano Ceccherini 254624df6c6SStefano Ceccherini 255624df6c6SStefano Ceccherini rgb_color 256624df6c6SStefano Ceccherini BPrivateScreen::ColorForIndex(const uint8 index) 257624df6c6SStefano Ceccherini { 258a817d6adSAxel Dörfler if (ColorMap()) 259624df6c6SStefano Ceccherini return fColorMap->color_list[index]; 260624df6c6SStefano Ceccherini 261624df6c6SStefano Ceccherini return rgb_color(); 262624df6c6SStefano Ceccherini } 263624df6c6SStefano Ceccherini 264624df6c6SStefano Ceccherini 265624df6c6SStefano Ceccherini uint8 266624df6c6SStefano Ceccherini BPrivateScreen::InvertIndex(uint8 index) 267624df6c6SStefano Ceccherini { 268a817d6adSAxel Dörfler if (ColorMap()) 269624df6c6SStefano Ceccherini return fColorMap->inversion_map[index]; 270624df6c6SStefano Ceccherini 271624df6c6SStefano Ceccherini return 0; 272624df6c6SStefano Ceccherini } 273624df6c6SStefano Ceccherini 274624df6c6SStefano Ceccherini 275624df6c6SStefano Ceccherini const color_map * 276624df6c6SStefano Ceccherini BPrivateScreen::ColorMap() 277624df6c6SStefano Ceccherini { 278a817d6adSAxel Dörfler if (fColorMap == NULL) { 279a817d6adSAxel Dörfler BAutolock locker(sScreenLock); 280a817d6adSAxel Dörfler 281a817d6adSAxel Dörfler if (fColorMap != NULL) { 282a817d6adSAxel Dörfler // someone could have been faster than us 283a817d6adSAxel Dörfler return fColorMap; 284a817d6adSAxel Dörfler } 285a817d6adSAxel Dörfler 286a817d6adSAxel Dörfler // TODO: BeOS R5 here gets the colormap pointer 287a817d6adSAxel Dörfler // (with BApplication::ro_offset_to_ptr() ?) 288a817d6adSAxel Dörfler // which is contained in a shared area created by the server. 289a817d6adSAxel Dörfler BPrivate::AppServerLink link; 290a817d6adSAxel Dörfler link.StartMessage(AS_SCREEN_GET_COLORMAP); 291a817d6adSAxel Dörfler link.Attach<screen_id>(ID()); 292a817d6adSAxel Dörfler 293a817d6adSAxel Dörfler status_t status; 294a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 295a817d6adSAxel Dörfler fColorMap = (color_map *)malloc(sizeof(color_map)); 296a817d6adSAxel Dörfler fOwnsColorMap = true; 297a817d6adSAxel Dörfler link.Read<color_map>(fColorMap); 298a817d6adSAxel Dörfler } 299a817d6adSAxel Dörfler } 300a817d6adSAxel Dörfler 301624df6c6SStefano Ceccherini return fColorMap; 302624df6c6SStefano Ceccherini } 303624df6c6SStefano Ceccherini 304624df6c6SStefano Ceccherini 305624df6c6SStefano Ceccherini status_t 306466871ccSAxel Dörfler BPrivateScreen::GetBitmap(BBitmap **_bitmap, bool drawCursor, BRect *bounds) 307624df6c6SStefano Ceccherini { 308466871ccSAxel Dörfler if (_bitmap == NULL) 30916046321SStefano Ceccherini return B_BAD_VALUE; 31016046321SStefano Ceccherini 311a817d6adSAxel Dörfler BRect rect; 312a817d6adSAxel Dörfler if (bounds != NULL) 313a817d6adSAxel Dörfler rect = *bounds; 314a817d6adSAxel Dörfler else 315a817d6adSAxel Dörfler rect = Frame(); 316a817d6adSAxel Dörfler 317a817d6adSAxel Dörfler BBitmap* bitmap = new (std::nothrow) BBitmap(rect, ColorSpace()); 318466871ccSAxel Dörfler if (bitmap == NULL) 319466871ccSAxel Dörfler return B_NO_MEMORY; 320466871ccSAxel Dörfler 321466871ccSAxel Dörfler status_t status = bitmap->InitCheck(); 322466871ccSAxel Dörfler if (status == B_OK) 323a817d6adSAxel Dörfler status = ReadBitmap(bitmap, drawCursor, &rect); 324466871ccSAxel Dörfler if (status != B_OK) { 325466871ccSAxel Dörfler delete bitmap; 326466871ccSAxel Dörfler return status; 327466871ccSAxel Dörfler } 328466871ccSAxel Dörfler 329466871ccSAxel Dörfler *_bitmap = bitmap; 330466871ccSAxel Dörfler return B_OK; 331624df6c6SStefano Ceccherini } 332624df6c6SStefano Ceccherini 333624df6c6SStefano Ceccherini 334624df6c6SStefano Ceccherini status_t 335a817d6adSAxel Dörfler BPrivateScreen::ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bounds) 336624df6c6SStefano Ceccherini { 33716046321SStefano Ceccherini if (bitmap == NULL) 33816046321SStefano Ceccherini return B_BAD_VALUE; 33916046321SStefano Ceccherini 34016046321SStefano Ceccherini BRect rect; 341a817d6adSAxel Dörfler if (bounds != NULL) 342a817d6adSAxel Dörfler rect = *bounds; 34316046321SStefano Ceccherini else 34416046321SStefano Ceccherini rect = Frame(); 34516046321SStefano Ceccherini 34616046321SStefano Ceccherini BPrivate::AppServerLink link; 34716046321SStefano Ceccherini link.StartMessage(AS_READ_BITMAP); 3489a44fdc9SAxel Dörfler link.Attach<int32>(bitmap->_ServerToken()); 34916046321SStefano Ceccherini link.Attach<bool>(drawCursor); 35016046321SStefano Ceccherini link.Attach<BRect>(rect); 35116046321SStefano Ceccherini 352a817d6adSAxel Dörfler status_t status = B_ERROR; 353a817d6adSAxel Dörfler if (link.FlushWithReply(status) < B_OK || status != B_OK) 354a817d6adSAxel Dörfler return status; 35516046321SStefano Ceccherini 35616046321SStefano Ceccherini return B_OK; 357624df6c6SStefano Ceccherini } 358624df6c6SStefano Ceccherini 359624df6c6SStefano Ceccherini 360624df6c6SStefano Ceccherini rgb_color 36139ffb980SStefano Ceccherini BPrivateScreen::DesktopColor(uint32 workspace) 362624df6c6SStefano Ceccherini { 3633ba7d6f3SAxel Dörfler rgb_color color = { 51, 102, 152, 255 }; 364dd10337fSAxel Dörfler BPrivate::AppServerLink link; 3653ba7d6f3SAxel Dörfler 3663ba7d6f3SAxel Dörfler link.StartMessage(AS_GET_DESKTOP_COLOR); 3673f319b33SMichael Lotz link.Attach<uint32>(workspace); 3683ba7d6f3SAxel Dörfler 3693ba7d6f3SAxel Dörfler int32 code; 370dd10337fSAxel Dörfler if (link.FlushWithReply(code) == B_OK 371a817d6adSAxel Dörfler && code == B_OK) 3723ba7d6f3SAxel Dörfler link.Read<rgb_color>(&color); 3733ba7d6f3SAxel Dörfler 37439ffb980SStefano Ceccherini return color; 375624df6c6SStefano Ceccherini } 376624df6c6SStefano Ceccherini 377624df6c6SStefano Ceccherini 378624df6c6SStefano Ceccherini void 379a817d6adSAxel Dörfler BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace, 380a817d6adSAxel Dörfler bool makeDefault) 381624df6c6SStefano Ceccherini { 382dd10337fSAxel Dörfler BPrivate::AppServerLink link; 3833ba7d6f3SAxel Dörfler 3843ba7d6f3SAxel Dörfler link.StartMessage(AS_SET_DESKTOP_COLOR); 38539ffb980SStefano Ceccherini link.Attach<rgb_color>(color); 3868f9ab4d1SAxel Dörfler link.Attach<uint32>(workspace); 38739ffb980SStefano Ceccherini link.Attach<bool>(makeDefault); 38839ffb980SStefano Ceccherini link.Flush(); 389624df6c6SStefano Ceccherini } 390624df6c6SStefano Ceccherini 391624df6c6SStefano Ceccherini 392624df6c6SStefano Ceccherini status_t 393c6418981SStefano Ceccherini BPrivateScreen::ProposeMode(display_mode *target, 394c6418981SStefano Ceccherini const display_mode *low, const display_mode *high) 395624df6c6SStefano Ceccherini { 396c6418981SStefano Ceccherini // We can't return B_BAD_VALUE here, because it's used to indicate 397c6418981SStefano Ceccherini // that the mode returned is supported, but it doesn't fall 398c6418981SStefano Ceccherini // within the limit (see ProposeMode() documentation) 399c6418981SStefano Ceccherini if (target == NULL || low == NULL || high == NULL) 400624df6c6SStefano Ceccherini return B_ERROR; 401c6418981SStefano Ceccherini 402c6418981SStefano Ceccherini BPrivate::AppServerLink link; 403c6418981SStefano Ceccherini link.StartMessage(AS_PROPOSE_MODE); 404c6418981SStefano Ceccherini link.Attach<screen_id>(ID()); 405583f6c3eSStefano Ceccherini link.Attach<display_mode>(*target); 406583f6c3eSStefano Ceccherini link.Attach<display_mode>(*low); 407583f6c3eSStefano Ceccherini link.Attach<display_mode>(*high); 408583f6c3eSStefano Ceccherini 409c6418981SStefano Ceccherini status_t status = B_ERROR; 410a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 411c6418981SStefano Ceccherini link.Read<display_mode>(target); 412a817d6adSAxel Dörfler 413a817d6adSAxel Dörfler bool withinLimits; 414a817d6adSAxel Dörfler link.Read<bool>(&withinLimits); 415a817d6adSAxel Dörfler if (!withinLimits) 416a817d6adSAxel Dörfler status = B_BAD_VALUE; 417c6418981SStefano Ceccherini } 418c6418981SStefano Ceccherini 419c6418981SStefano Ceccherini return status; 420624df6c6SStefano Ceccherini } 421624df6c6SStefano Ceccherini 422624df6c6SStefano Ceccherini 423624df6c6SStefano Ceccherini status_t 424a817d6adSAxel Dörfler BPrivateScreen::GetModeList(display_mode **_modeList, uint32 *_count) 425624df6c6SStefano Ceccherini { 426a817d6adSAxel Dörfler if (_modeList == NULL || _count == NULL) 42710c5dab8SStefano Ceccherini return B_BAD_VALUE; 42810c5dab8SStefano Ceccherini 42910c5dab8SStefano Ceccherini BPrivate::AppServerLink link; 43010c5dab8SStefano Ceccherini link.StartMessage(AS_GET_MODE_LIST); 43110c5dab8SStefano Ceccherini link.Attach<screen_id>(ID()); 432a817d6adSAxel Dörfler 433a817d6adSAxel Dörfler status_t status = B_ERROR; 434a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 43506740743SAxel Dörfler uint32 count; 43606740743SAxel Dörfler if (link.Read<uint32>(&count) < B_OK) 43706740743SAxel Dörfler return B_ERROR; 43806740743SAxel Dörfler 439a817d6adSAxel Dörfler // TODO: this could get too big for the link 44006740743SAxel Dörfler int32 size = count * sizeof(display_mode); 44106740743SAxel Dörfler display_mode* modeList = (display_mode *)malloc(size); 44206740743SAxel Dörfler if (modeList == NULL) 443a817d6adSAxel Dörfler return B_NO_MEMORY; 444a817d6adSAxel Dörfler 44506740743SAxel Dörfler if (link.Read(modeList, size) < B_OK) { 44606740743SAxel Dörfler free(modeList); 44706740743SAxel Dörfler return B_ERROR; 44806740743SAxel Dörfler } 44906740743SAxel Dörfler 45006740743SAxel Dörfler *_modeList = modeList; 45106740743SAxel Dörfler *_count = count; 45210c5dab8SStefano Ceccherini } 45310c5dab8SStefano Ceccherini 45410c5dab8SStefano Ceccherini return status; 455624df6c6SStefano Ceccherini } 456624df6c6SStefano Ceccherini 457624df6c6SStefano Ceccherini 458624df6c6SStefano Ceccherini status_t 459624df6c6SStefano Ceccherini BPrivateScreen::GetMode(uint32 workspace, display_mode *mode) 460624df6c6SStefano Ceccherini { 461314a1024SStefano Ceccherini if (mode == NULL) 462314a1024SStefano Ceccherini return B_BAD_VALUE; 463314a1024SStefano Ceccherini 464dd10337fSAxel Dörfler BPrivate::AppServerLink link; 46534c39bf0SStefano Ceccherini link.StartMessage(AS_SCREEN_GET_MODE); 46634c39bf0SStefano Ceccherini link.Attach<screen_id>(ID()); 46739ffb980SStefano Ceccherini link.Attach<uint32>(workspace); 468fca6492fSStefano Ceccherini 46934c39bf0SStefano Ceccherini status_t status = B_ERROR; 470a817d6adSAxel Dörfler if (link.FlushWithReply(status) != B_OK 471a817d6adSAxel Dörfler || status != B_OK) 47239ffb980SStefano Ceccherini return status; 473a817d6adSAxel Dörfler 474a817d6adSAxel Dörfler link.Read<display_mode>(mode); 475a817d6adSAxel Dörfler return B_OK; 476624df6c6SStefano Ceccherini } 477624df6c6SStefano Ceccherini 478624df6c6SStefano Ceccherini 479624df6c6SStefano Ceccherini status_t 480624df6c6SStefano Ceccherini BPrivateScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault) 481624df6c6SStefano Ceccherini { 482314a1024SStefano Ceccherini if (mode == NULL) 483314a1024SStefano Ceccherini return B_BAD_VALUE; 484314a1024SStefano Ceccherini 485dd10337fSAxel Dörfler BPrivate::AppServerLink link; 486314a1024SStefano Ceccherini link.StartMessage(AS_SCREEN_SET_MODE); 487314a1024SStefano Ceccherini link.Attach<screen_id>(ID()); 48839ffb980SStefano Ceccherini link.Attach<uint32>(workspace); 48939ffb980SStefano Ceccherini link.Attach<display_mode>(*mode); 49039ffb980SStefano Ceccherini link.Attach<bool>(makeDefault); 491314a1024SStefano Ceccherini 492314a1024SStefano Ceccherini status_t status = B_ERROR; 493a817d6adSAxel Dörfler link.FlushWithReply(status); 494314a1024SStefano Ceccherini 49539ffb980SStefano Ceccherini return status; 496624df6c6SStefano Ceccherini } 497624df6c6SStefano Ceccherini 498624df6c6SStefano Ceccherini 499624df6c6SStefano Ceccherini status_t 500624df6c6SStefano Ceccherini BPrivateScreen::GetDeviceInfo(accelerant_device_info *info) 501624df6c6SStefano Ceccherini { 502c6418981SStefano Ceccherini if (info == NULL) 503c6418981SStefano Ceccherini return B_BAD_VALUE; 504c6418981SStefano Ceccherini 505c6418981SStefano Ceccherini BPrivate::AppServerLink link; 506c6418981SStefano Ceccherini link.StartMessage(AS_GET_ACCELERANT_INFO); 507c6418981SStefano Ceccherini link.Attach<screen_id>(ID()); 508a817d6adSAxel Dörfler 509a817d6adSAxel Dörfler status_t status = B_ERROR; 510a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 511c6418981SStefano Ceccherini link.Read<accelerant_device_info>(info); 512c6418981SStefano Ceccherini return B_OK; 513c6418981SStefano Ceccherini } 514c6418981SStefano Ceccherini 515a817d6adSAxel Dörfler return status; 516624df6c6SStefano Ceccherini } 517624df6c6SStefano Ceccherini 518624df6c6SStefano Ceccherini 519624df6c6SStefano Ceccherini status_t 520624df6c6SStefano Ceccherini BPrivateScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high) 521624df6c6SStefano Ceccherini { 52275de27f8SStefano Ceccherini if (mode == NULL || low == NULL || high == NULL) 52375de27f8SStefano Ceccherini return B_BAD_VALUE; 52475de27f8SStefano Ceccherini 52575de27f8SStefano Ceccherini BPrivate::AppServerLink link; 52675de27f8SStefano Ceccherini link.StartMessage(AS_GET_PIXEL_CLOCK_LIMITS); 52775de27f8SStefano Ceccherini link.Attach<screen_id>(ID()); 52875de27f8SStefano Ceccherini link.Attach<display_mode>(*mode); 52975de27f8SStefano Ceccherini 530a817d6adSAxel Dörfler status_t status; 531a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 53275de27f8SStefano Ceccherini link.Read<uint32>(low); 53375de27f8SStefano Ceccherini link.Read<uint32>(high); 53475de27f8SStefano Ceccherini return B_OK; 53575de27f8SStefano Ceccherini } 53675de27f8SStefano Ceccherini 537a817d6adSAxel Dörfler return status; 538624df6c6SStefano Ceccherini } 539624df6c6SStefano Ceccherini 540624df6c6SStefano Ceccherini 541624df6c6SStefano Ceccherini status_t 542a817d6adSAxel Dörfler BPrivateScreen::GetTimingConstraints(display_timing_constraints *constraints) 543624df6c6SStefano Ceccherini { 544a817d6adSAxel Dörfler if (constraints == NULL) 54555b222b0SStefano Ceccherini return B_BAD_VALUE; 54655b222b0SStefano Ceccherini 54775de27f8SStefano Ceccherini BPrivate::AppServerLink link; 54875de27f8SStefano Ceccherini link.StartMessage(AS_GET_TIMING_CONSTRAINTS); 54975de27f8SStefano Ceccherini link.Attach<screen_id>(ID()); 55075de27f8SStefano Ceccherini 551a817d6adSAxel Dörfler status_t status = B_ERROR; 552a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 553a817d6adSAxel Dörfler link.Read<display_timing_constraints>(constraints); 55475de27f8SStefano Ceccherini return B_OK; 55575de27f8SStefano Ceccherini } 55675de27f8SStefano Ceccherini 557a817d6adSAxel Dörfler return status; 558624df6c6SStefano Ceccherini } 559624df6c6SStefano Ceccherini 560624df6c6SStefano Ceccherini 561624df6c6SStefano Ceccherini status_t 562624df6c6SStefano Ceccherini BPrivateScreen::SetDPMS(uint32 dpmsState) 563624df6c6SStefano Ceccherini { 564dd10337fSAxel Dörfler BPrivate::AppServerLink link; 56555b222b0SStefano Ceccherini link.StartMessage(AS_SET_DPMS); 56639ffb980SStefano Ceccherini link.Attach<screen_id>(ID()); 56739ffb980SStefano Ceccherini link.Attach<uint32>(dpmsState); 56855b222b0SStefano Ceccherini 569a817d6adSAxel Dörfler status_t status = B_ERROR; 570a817d6adSAxel Dörfler link.FlushWithReply(status); 571a817d6adSAxel Dörfler 572a817d6adSAxel Dörfler return status; 573624df6c6SStefano Ceccherini } 574624df6c6SStefano Ceccherini 575624df6c6SStefano Ceccherini 576624df6c6SStefano Ceccherini uint32 577624df6c6SStefano Ceccherini BPrivateScreen::DPMSState() 578624df6c6SStefano Ceccherini { 57939ffb980SStefano Ceccherini uint32 state = 0; 58055b222b0SStefano Ceccherini 581dd10337fSAxel Dörfler BPrivate::AppServerLink link; 58255b222b0SStefano Ceccherini link.StartMessage(AS_GET_DPMS_STATE); 58339ffb980SStefano Ceccherini link.Attach<screen_id>(ID()); 584a817d6adSAxel Dörfler 585a817d6adSAxel Dörfler status_t status; 586a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) 58755b222b0SStefano Ceccherini link.Read<uint32>(&state); 58855b222b0SStefano Ceccherini 58939ffb980SStefano Ceccherini return state; 590624df6c6SStefano Ceccherini } 591624df6c6SStefano Ceccherini 592624df6c6SStefano Ceccherini 593624df6c6SStefano Ceccherini uint32 594624df6c6SStefano Ceccherini BPrivateScreen::DPMSCapabilites() 595624df6c6SStefano Ceccherini { 59639ffb980SStefano Ceccherini uint32 capabilities = 0; 59755b222b0SStefano Ceccherini 598dd10337fSAxel Dörfler BPrivate::AppServerLink link; 59955b222b0SStefano Ceccherini link.StartMessage(AS_GET_DPMS_CAPABILITIES); 60039ffb980SStefano Ceccherini link.Attach<screen_id>(ID()); 601a817d6adSAxel Dörfler 602a817d6adSAxel Dörfler status_t status; 603a817d6adSAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) 60455b222b0SStefano Ceccherini link.Read<uint32>(&capabilities); 60555b222b0SStefano Ceccherini 60639ffb980SStefano Ceccherini return capabilities; 607624df6c6SStefano Ceccherini } 608624df6c6SStefano Ceccherini 609624df6c6SStefano Ceccherini 610624df6c6SStefano Ceccherini void * 611624df6c6SStefano Ceccherini BPrivateScreen::BaseAddress() 612624df6c6SStefano Ceccherini { 613b66d7537SAxel Dörfler frame_buffer_config config; 614b66d7537SAxel Dörfler if (_GetFrameBufferConfig(config) != B_OK) 615624df6c6SStefano Ceccherini return NULL; 616b66d7537SAxel Dörfler 617b66d7537SAxel Dörfler return config.frame_buffer; 618624df6c6SStefano Ceccherini } 619624df6c6SStefano Ceccherini 620624df6c6SStefano Ceccherini 621624df6c6SStefano Ceccherini uint32 622624df6c6SStefano Ceccherini BPrivateScreen::BytesPerRow() 623624df6c6SStefano Ceccherini { 624b66d7537SAxel Dörfler frame_buffer_config config; 625b66d7537SAxel Dörfler if (_GetFrameBufferConfig(config) != B_OK) 626624df6c6SStefano Ceccherini return 0; 627624df6c6SStefano Ceccherini 628b66d7537SAxel Dörfler return config.bytes_per_row; 629624df6c6SStefano Ceccherini } 630624df6c6SStefano Ceccherini 631624df6c6SStefano Ceccherini 632a817d6adSAxel Dörfler // #pragma mark - private methods 63375de27f8SStefano Ceccherini 634a817d6adSAxel Dörfler 635a817d6adSAxel Dörfler sem_id 636a817d6adSAxel Dörfler BPrivateScreen::_RetraceSemaphore() 637a817d6adSAxel Dörfler { 63875de27f8SStefano Ceccherini BPrivate::AppServerLink link; 63975de27f8SStefano Ceccherini link.StartMessage(AS_GET_RETRACE_SEMAPHORE); 64075de27f8SStefano Ceccherini link.Attach<screen_id>(ID()); 641a817d6adSAxel Dörfler 642a817d6adSAxel Dörfler sem_id id = B_BAD_SEM_ID; 643*5ec797a7SStephan Aßmus status_t status = B_ERROR; 644*5ec797a7SStephan Aßmus if (link.FlushWithReply(status) == B_OK && status == B_OK) { 645*5ec797a7SStephan Aßmus link.Read<sem_id>(&id); 646*5ec797a7SStephan Aßmus fRetraceSemValid = true; 647*5ec797a7SStephan Aßmus } 64875de27f8SStefano Ceccherini 64975de27f8SStefano Ceccherini return id; 65075de27f8SStefano Ceccherini } 65175de27f8SStefano Ceccherini 65275de27f8SStefano Ceccherini 653b66d7537SAxel Dörfler status_t 654b66d7537SAxel Dörfler BPrivateScreen::_GetFrameBufferConfig(frame_buffer_config& config) 655b66d7537SAxel Dörfler { 656b66d7537SAxel Dörfler BPrivate::AppServerLink link; 657b66d7537SAxel Dörfler link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG); 658b66d7537SAxel Dörfler link.Attach<screen_id>(ID()); 659b66d7537SAxel Dörfler 660b66d7537SAxel Dörfler status_t status = B_ERROR; 661b66d7537SAxel Dörfler if (link.FlushWithReply(status) == B_OK && status == B_OK) { 662b66d7537SAxel Dörfler link.Read<frame_buffer_config>(&config); 663b66d7537SAxel Dörfler return B_OK; 664b66d7537SAxel Dörfler } 665b66d7537SAxel Dörfler 666b66d7537SAxel Dörfler return status; 667b66d7537SAxel Dörfler } 668b66d7537SAxel Dörfler 669b66d7537SAxel Dörfler 670b66d7537SAxel Dörfler BPrivateScreen::BPrivateScreen(screen_id id) 671624df6c6SStefano Ceccherini : 672b66d7537SAxel Dörfler fID(id), 673624df6c6SStefano Ceccherini fColorMap(NULL), 674624df6c6SStefano Ceccherini fRetraceSem(-1), 675*5ec797a7SStephan Aßmus fRetraceSemValid(false), 676b66d7537SAxel Dörfler fOwnsColorMap(false), 677b66d7537SAxel Dörfler fFrame(0, 0, 0, 0), 678b66d7537SAxel Dörfler fLastUpdate(0) 679624df6c6SStefano Ceccherini { 680624df6c6SStefano Ceccherini } 681624df6c6SStefano Ceccherini 682624df6c6SStefano Ceccherini 683624df6c6SStefano Ceccherini BPrivateScreen::~BPrivateScreen() 684624df6c6SStefano Ceccherini { 685624df6c6SStefano Ceccherini if (fOwnsColorMap) 686624df6c6SStefano Ceccherini free(fColorMap); 687624df6c6SStefano Ceccherini } 688