diff --git a/headers/private/servers/app/DisplayDriver.h b/headers/private/servers/app/DisplayDriver.h index 711f3d4455..9e29d90eb3 100644 --- a/headers/private/servers/app/DisplayDriver.h +++ b/headers/private/servers/app/DisplayDriver.h @@ -1,23 +1,6 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2005, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved +// Distributed under the terms of the MIT license. // // File Name: DisplayDriver.h // Authors: DarkWyrm @@ -34,6 +17,7 @@ #include #include #include +#include class BPoint; class BRect; @@ -64,57 +48,18 @@ typedef struct } LineArrayData; -/* -#ifndef HOOK_DEFINE_CURSOR - -#define HOOK_DEFINE_CURSOR 0 -#define HOOK_MOVE_CURSOR 1 -#define HOOK_SHOW_CURSOR 2 -#define HOOK_DRAW_LINE_8BIT 3 -#define HOOK_DRAW_LINE_16BIT 12 -#define HOOK_DRAW_LINE_32BIT 4 -#define HOOK_DRAW_RECT_8BIT 5 -#define HOOK_DRAW_RECT_16BIT 13 -#define HOOK_DRAW_RECT_32BIT 6 -#define HOOK_BLIT 7 -#define HOOK_DRAW_ARRAY_8BIT 8 -#define HOOK_DRAW_ARRAY_16BIT 14 // Not implemented in current R5 drivers -#define HOOK_DRAW_ARRAY_32BIT 9 -#define HOOK_SYNC 10 -#define HOOK_INVERT_RECT 11 - -#endif - -class DisplayDriver; - -typedef void (DisplayDriver::* SetPixelFuncType)(int x, int y); -typedef void (DisplayDriver::* SetHorizontalLineFuncType)(int xstart, int xend, int y); -typedef void (DisplayDriver::* SetVerticalLineFuncType)(int x, int ystart, int yend); -typedef void (DisplayDriver::* SetRectangleFuncType)(int left, int top, int right, int bottom); -*/ - -/*! - \class DisplayDriver DisplayDriver.h - \brief Mostly abstract class which handles all graphics output for the server. - - The DisplayDriver is called in order to handle all messiness associated with - a particular rendering context, such as the screen, and the methods to - handle organizing information related to it along with writing to the context - itself. - - While all virtual functions are technically optional, the default versions - do very little, so implementing them all more or less required. -*/ - class DisplayDriver { public: DisplayDriver(); virtual ~DisplayDriver(); // when implementing, be sure to call the inherited version - virtual bool Initialize(); + virtual status_t Initialize(); virtual void Shutdown(); + // call this on mode changes! + virtual void Update() = 0; + // clipping for all drawing functions virtual void ConstrainClippingRegion(BRegion* region) = 0; @@ -265,81 +210,12 @@ public: int32 length, const DrawData *d) = 0; - virtual void GetBoundingBoxes(const char *string, - int32 count, - font_metric_mode mode, - escapement_delta *delta, - BRect *rectarray, - const DrawData *d) = 0; - - virtual void GetEscapements( const char *string, - int32 charcount, - escapement_delta *delta, - escapement_delta *escapements, - escapement_delta *offsets, - const DrawData *d) = 0; - - virtual void GetEdges( const char *string, - int32 charcount, - edge_info *edgearray, - const DrawData *d) = 0; - - virtual void GetHasGlyphs( const char *string, - int32 charcount, - bool *hasarray) = 0; - - virtual void GetTruncatedStrings(const char **instrings, - const int32 &stringcount, - const uint32 &mode, - const float &maxwidth, - char **outstrings) = 0; - - virtual void HideCursor() = 0; - virtual bool IsCursorHidden() = 0; - virtual void MoveCursorTo( const float &x, - const float &y) = 0; - virtual void ShowCursor() = 0; - virtual void ObscureCursor() = 0; - virtual void SetCursor(ServerCursor *cursor) = 0; - virtual BPoint GetCursorPosition() = 0; - virtual bool IsCursorObscured(bool state) = 0; - - - // Virtual methods which need to be implemented by each subclass - - // These two will rarely be implemented by subclasses, - // but it still needs to be possible - virtual bool Lock(bigtime_t timeout = B_INFINITE_TIMEOUT) = 0; + virtual bool Lock() = 0; virtual void Unlock() = 0; - // display mode access - virtual status_t SetMode(const display_mode &mode); - virtual void GetMode(display_mode &mode); - virtual bool DumpToFile(const char *path) = 0; virtual ServerBitmap* DumpToBitmap() = 0; - virtual status_t SetDPMSMode(const uint32 &state) = 0; - virtual uint32 DPMSMode() = 0; - virtual uint32 DPMSCapabilities() = 0; - virtual status_t GetDeviceInfo(accelerant_device_info *info) = 0; - - virtual status_t GetModeList(display_mode **mode_list, - uint32 *count) = 0; - - virtual status_t GetPixelClockLimits(display_mode *mode, - uint32 *low, - uint32 *high) = 0; - - virtual status_t GetTimingConstraints(display_timing_constraints *dtc) = 0; - virtual status_t ProposeMode(display_mode *candidate, - const display_mode *low, - const display_mode *high) = 0; - - virtual status_t WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) = 0; - - protected: - display_mode fDisplayMode; }; #endif diff --git a/src/servers/app/AppServer.cpp b/src/servers/app/AppServer.cpp index 6440d8242d..a24450989f 100644 --- a/src/servers/app/AppServer.cpp +++ b/src/servers/app/AppServer.cpp @@ -25,8 +25,8 @@ #include "DecorManager.h" #include "DefaultDecorator.h" #include "Desktop.h" -#include "DisplayDriver.h" #include "FontServer.h" +#include "HWInterface.h" #include "RegistrarDefs.h" #include "RGBColor.h" #include "RootLayer.h" @@ -346,7 +346,7 @@ AppServer::CursorThread(void* data) p.y = *server->fCursorAddr & 0x7fff; p.x = *server->fCursorAddr >> 15 & 0x7fff; - gDesktop->GetDisplayDriver()->MoveCursorTo(p.x, p.y); + gDesktop->GetHWInterface()->MoveCursorTo(p.x, p.y); STRACE(("CursorThread : %f, %f\n", p.x, p.y)); } diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 029c90a13f..2ac3cb429b 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -1,36 +1,19 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2005, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved. +// Distributed under the terms of the MIT license. // // File Name: Desktop.cpp // Author: Adi Oanca +// Stephan Aßmus // Description: Class used to encapsulate desktop management // //------------------------------------------------------------------------------ #include -#include + #include +#include #include "AppServer.h" -#include "Desktop.h" -#include "DisplayDriver.h" #include "DisplayDriverPainter.h" #include "Globals.h" #include "Layer.h" @@ -42,6 +25,20 @@ #include "WinBorder.h" #include "Workspace.h" +#ifdef __HAIKU__ +#define USE_ACCELERANT 1 +#else +#define USE_ACCELERANT 0 +#endif + +#if USE_ACCELERANT + #include "AccelerantHWInterface.h" +#else + #include "ViewHWInterface.h" +#endif + +#include "Desktop.h" + //#define DEBUG_DESKTOP #ifdef DEBUG_DESKTOP @@ -51,14 +48,14 @@ #endif -Desktop::Desktop(void) +Desktop::Desktop() { fActiveRootLayer = NULL; fActiveScreen = NULL; } -Desktop::~Desktop(void) +Desktop::~Desktop() { for (int32 i = 0; WinBorder *border = (WinBorder *)fWinBorderList.ItemAt(i); i++) delete border; @@ -72,9 +69,9 @@ Desktop::~Desktop(void) void -Desktop::Init(void) +Desktop::Init() { - DisplayDriver *driver = NULL; + HWInterface *interface = NULL; // Eventually we will loop through drivers until // one can't initialize in order to support multiple monitors. @@ -82,8 +79,14 @@ Desktop::Init(void) bool initDrivers = true; while (initDrivers) { - driver = new DisplayDriverPainter(); - AddDriver(driver); + +#if USE_ACCELERANT + interface = new AccelerantHWInterface(); +#else + interface = new ViewHWInterface(); +#endif + + _AddGraphicsCard(interface); initDrivers = false; } @@ -99,25 +102,24 @@ Desktop::Init(void) void -Desktop::AddDriver(DisplayDriver *driver) +Desktop::_AddGraphicsCard(HWInterface* interface) { - if (driver->Initialize()) { - Screen *screen = new Screen(driver, fScreenList.CountItems() + 1); - // The driver is now owned by the screen + Screen *screen = new Screen(interface, fScreenList.CountItems() + 1); + // The interface is now owned by the screen + + if (screen->Initialize() >= B_OK && fScreenList.AddItem((void*)screen)) { // TODO: be careful of screen initialization - monitor may not support 640x480 screen->SetMode(800, 600, B_RGB32, 60.f); - fScreenList.AddItem(screen); } else { - driver->Shutdown(); - delete driver; + delete screen; } } void -Desktop::InitMode(void) +Desktop::InitMode() { // this is init mode for n-SS. fActiveScreen = (Screen *)fScreenList.ItemAt(0); @@ -223,6 +225,12 @@ Desktop::GetDisplayDriver() const return ScreenAt(0)->GetDisplayDriver(); } +inline HWInterface * +Desktop::GetHWInterface() const +{ + return ScreenAt(0)->GetHWInterface(); +} + //--------------------------------------------------------------------------- // Methods for layer(WinBorder) manipulation. diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index bb0496c60d..3fd18f37b1 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -1,122 +1,116 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2002, Haiku, Inc. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved. +// Distributed under the terms of the MIT license. // -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// File Name: Desktop.cpp +// File Name: Desktop.h // Author: Adi Oanca +// Stephan Aßmus // Description: Class used to encapsulate desktop management // //------------------------------------------------------------------------------ #ifndef _DESKTOP_H_ #define _DESKTOP_H_ -#include -#include -#include #include +#include +#include +#include +class BMessage; +class BPortLink; +class DisplayDriver; +class HWInterface; +class Layer; class RootLayer; class Screen; -class Layer; -class BMessage; class WinBorder; -class DisplayDriver; -class BPortLink; -class Desktop -{ -public: +class Desktop { + public: // startup methods - Desktop(void); - virtual ~Desktop(void); - void Init(void); + Desktop(); + virtual ~Desktop(); + + void Init(); // 1-BigScreen or n-SmallScreens - void InitMode(void); + void InitMode(); // Methods for multiple monitors. - Screen *ScreenAt(int32 index) const; - int32 ScreenCount(void) const; - Screen *ActiveScreen(void) const; + Screen* ScreenAt(int32 index) const; + int32 ScreenCount() const; + Screen* ActiveScreen() const; - void SetActiveRootLayerByIndex(int32 listIndex); - void SetActiveRootLayer(RootLayer *rl); - RootLayer *RootLayerAt(int32 index); - RootLayer *ActiveRootLayer(void) const; - int32 ActiveRootLayerIndex(void) const; - int32 CountRootLayers(void) const; - DisplayDriver *GetDisplayDriver(void) const; + void SetActiveRootLayerByIndex(int32 index); + void SetActiveRootLayer(RootLayer* layer); + RootLayer* RootLayerAt(int32 index); + RootLayer* ActiveRootLayer() const; + int32 ActiveRootLayerIndex() const; + int32 CountRootLayers() const; + + DisplayDriver* GetDisplayDriver() const; + HWInterface* GetHWInterface() const; // Methods for layer(WinBorder) manipulation. - void AddWinBorder(WinBorder *winBorder); - void RemoveWinBorder(WinBorder *winBorder); - void SetWinBorderFeel(WinBorder *winBorder, uint32 feel); - void AddWinBorderToSubset(WinBorder *winBorder, WinBorder *toWinBorder); - void RemoveWinBorderFromSubset(WinBorder *winBorder, WinBorder *fromWinBorder); + void AddWinBorder(WinBorder *winBorder); + void RemoveWinBorder(WinBorder *winBorder); + void SetWinBorderFeel(WinBorder *winBorder, + uint32 feel); + void AddWinBorderToSubset(WinBorder *winBorder, + WinBorder *toWinBorder); + void RemoveWinBorderFromSubset(WinBorder *winBorder, + WinBorder *fromWinBorder); - WinBorder* FindWinBorderByServerWindowTokenAndTeamID(int32 token, team_id teamID); + WinBorder* FindWinBorderByServerWindowTokenAndTeamID(int32 token, + team_id teamID); // get list of registed windows - const BList& WindowList() const - { - if (!IsLocked()) - debugger("You must lock before getting registered windows list\n"); - return fWinBorderList; - } + const BList& WindowList() const + { + if (!IsLocked()) + debugger("You must lock before getting registered windows list\n"); + return fWinBorderList; + } // locking with regards to registered windows list - bool Lock() { return fWinLock.Lock(); } - void Unlock() { return fWinLock.Unlock(); } - bool IsLocked() const { return fWinLock.IsLocked(); } + bool Lock() + { return fWinLock.Lock(); } + void Unlock() + { return fWinLock.Unlock(); } + bool IsLocked() const + { return fWinLock.IsLocked(); } // Methods for various desktop stuff handled by the server - void SetScrollBarInfo(const scroll_bar_info &info); - scroll_bar_info ScrollBarInfo(void) const; + void SetScrollBarInfo(const scroll_bar_info &info); + scroll_bar_info ScrollBarInfo() const; - void SetMenuInfo(const menu_info &info); - menu_info MenuInfo(void) const; + void SetMenuInfo(const menu_info &info); + menu_info MenuInfo() const; - void UseFFMouse(const bool &useffm); - bool FFMouseInUse(void) const; - void SetFFMouseMode(const mode_mouse &value); - mode_mouse FFMouseMode(void) const; + void UseFFMouse(const bool &useffm); + bool FFMouseInUse() const; + void SetFFMouseMode(const mode_mouse &value); + mode_mouse FFMouseMode() const; // Debugging methods - void PrintToStream(void); - void PrintVisibleInRootLayerNo(int32 no); + void PrintToStream(); + void PrintVisibleInRootLayerNo(int32 no); -private: - void AddDriver(DisplayDriver *driver); + private: + void _AddGraphicsCard(HWInterface* interface); - BList fWinBorderList; - BLocker fWinLock; - - BList fRootLayerList; - RootLayer *fActiveRootLayer; - - BList fScreenList; - Screen *fActiveScreen; - - scroll_bar_info fScrollBarInfo; - menu_info fMenuInfo; - mode_mouse fMouseMode; - bool fFFMouseMode; + BList fWinBorderList; + BLocker fWinLock; + + BList fRootLayerList; + RootLayer* fActiveRootLayer; + + BList fScreenList; + Screen* fActiveScreen; + + scroll_bar_info fScrollBarInfo; + menu_info fMenuInfo; + mode_mouse fMouseMode; + bool fFFMouseMode; }; extern Desktop *gDesktop; diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index f4b037f25e..d38c33bede 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -72,6 +72,7 @@ Server app_server : # Misc. Sources DebugInfoManager.cpp SubWindowList.cpp + MultiLocker.cpp PicturePlayer.cpp PNGDump.cpp RAMLinkMsgReader.cpp diff --git a/src/servers/app/MultiLocker.cpp b/src/servers/app/MultiLocker.cpp new file mode 100644 index 0000000000..4028fb1a51 --- /dev/null +++ b/src/servers/app/MultiLocker.cpp @@ -0,0 +1,465 @@ +/* MultiLocker.cpp */ +/* + Copyright 1999, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ + +#include "MultiLocker.h" + +#include +#include +#include + +//#define TIMING 1 +#define DEBUG 1 + + +MultiLocker::MultiLocker(const char* semaphoreBaseName) + : fInit(B_NO_INIT), + fReadCount(0), + fReadSem(-1), + fWriteCount(0), + fWriteSem(-1), + fLockCount(0), + fWriterLock(-1), + fWriterNest(0), + fWriterThread(-1), + fWriterStackBase(0), + fDebugArray(NULL), + fMaxThreads(0) +{ + //build the semaphores + if (semaphoreBaseName) { + char name[128]; + sprintf(name, "%s-%s", semaphoreBaseName, "ReadSem"); + fReadSem = create_sem(0, name); + sprintf(name, "%s-%s", semaphoreBaseName, "WriteSem"); + fWriteSem = create_sem(0, name); + sprintf(name, "%s-%s", semaphoreBaseName, "WriterLock"); + fWriterLock = create_sem(0, name); + } else { + fReadSem = create_sem(0, "ReadSem"); + fWriteSem = create_sem(0, "WriteSem"); + fWriterLock = create_sem(0, "WriterLock"); + } + + if (fReadSem >= 0 && fWriteSem >=0 && fWriterLock >= 0) + fInit = B_OK; + + #if DEBUG + //we are in debug mode! + //create the reader tracking list + //the array needs to be large enough to hold all possible threads + system_info sys; + get_system_info(&sys); + fMaxThreads = sys.max_threads; + printf("max_threads: %ld used_threads: %ld\n", sys.max_threads, sys.used_threads); + fDebugArray = (int32 *) malloc(fMaxThreads * sizeof(int32)); + for (int32 i = 0; i < fMaxThreads; i++) { + fDebugArray[i] = 0; + } + + #endif + #if TIMING + //initialize the counter variables + rl_count = ru_count = wl_count = wu_count = islock_count = 0; + rl_time = ru_time = wl_time = wu_time = islock_time = 0; + #if DEBUG + reg_count = unreg_count = 0; + reg_time = unreg_time = 0; + #endif + #endif +} + + +MultiLocker::~MultiLocker() +{ + //become the writer + if (!IsWriteLocked()) WriteLock(); + + //set locker to be uninitialized + fInit = B_NO_INIT; + + //delete the semaphores + delete_sem(fReadSem); + delete_sem(fWriteSem); + delete_sem(fWriterLock); + + #if DEBUG + //we are in debug mode! + //clear and delete the reader tracking list + free(fDebugArray); + #endif + #if TIMING + //let's produce some performance numbers + printf("MultiLocker Statistics:\n" + "Avg ReadLock: %lld\n" + "Avg ReadUnlock: %lld\n" + "Avg WriteLock: %lld\n" + "Avg WriteUnlock: %lld\n" + "Avg IsWriteLocked: %lld\n", + rl_count > 0 ? rl_time / rl_count : 0, + ru_count > 0 ? ru_time / ru_count : 0, + wl_count > 0 ? wl_time / wl_count : 0, + wu_count > 0 ? wu_time / wu_count : 0, + islock_count > 0 ? islock_time / islock_count : 0 + ); + #if DEBUG + printf( "Avg register_thread: %lld\n" + "Avg unregister_thread: %lld\n", + reg_count > 0 ? reg_time / reg_count : 0, + unreg_count > 0 ? unreg_time / unreg_count : 0 + ); + #endif + #endif +} + +status_t +MultiLocker::InitCheck() +{ + return fInit; +} + +bool +MultiLocker::ReadLock() +{ + #if TIMING + bigtime_t start = system_time(); + #endif + + bool locked = false; + + //the lock must be initialized + if (fInit == B_OK) { + if (IsWriteLocked()) { + //the writer simply increments the nesting + fWriterNest++; + locked = true; + } else { + //increment and retrieve the current count of readers + int32 current_count = atomic_add(&fReadCount, 1); + if (current_count < 0) { + //a writer holds the lock so wait for fReadSem to be released + locked = (acquire_sem_etc(fReadSem, 1, B_DO_NOT_RESCHEDULE, + B_INFINITE_TIMEOUT) == B_OK); + } else locked = true; + #if DEBUG + //register if we acquired the lock + if (locked) register_thread(); + #endif + } + + } + + #if TIMING + bigtime_t end = system_time(); + rl_time += (end - start); + rl_count++; + #endif + + return locked; +} + +bool +MultiLocker::WriteLock() +{ + #if TIMING + bigtime_t start = system_time(); + #endif + + bool locked = false; + + if (fInit == B_OK) { + uint32 stack_base = 0; + thread_id thread = -1; + + if (IsWriteLocked(&stack_base, &thread)) { + //already the writer - increment the nesting count + fWriterNest++; + locked = true; + } else { + //new writer acquiring the lock + if (atomic_add(&fLockCount, 1) >= 1) { + //another writer in the lock - acquire the semaphore + locked = (acquire_sem_etc(fWriterLock, 1, B_DO_NOT_RESCHEDULE, + B_INFINITE_TIMEOUT) == B_OK); + } else locked = true; + + if (locked) { + //new holder of the lock + + //decrement fReadCount by a very large number + //this will cause new readers to block on fReadSem + int32 readers = atomic_add(&fReadCount, -LARGE_NUMBER); + + if (readers > 0) { + //readers hold the lock - acquire fWriteSem + locked = (acquire_sem_etc(fWriteSem, readers, B_DO_NOT_RESCHEDULE, + B_INFINITE_TIMEOUT) == B_OK); + } + if (locked) { + ASSERT(fWriterThread == -1); + //record thread information + fWriterThread = thread; + fWriterStackBase = stack_base; + } + } + } + } + + #if TIMING + bigtime_t end = system_time(); + wl_time += (end - start); + wl_count++; + #endif + + return locked; +} + +bool +MultiLocker::ReadUnlock() +{ + #if TIMING + bigtime_t start = system_time(); + #endif + + bool unlocked = false; + + if (IsWriteLocked()) { + //writers simply decrement the nesting count + fWriterNest--; + unlocked = true; + } else { + //decrement and retrieve the read counter + int32 current_count = atomic_add(&fReadCount, -1); + if (current_count < 0) { + //a writer is waiting for the lock so release fWriteSem + unlocked = (release_sem_etc(fWriteSem, 1, + B_DO_NOT_RESCHEDULE) == B_OK); + } else unlocked = true; + + #ifdef DEBUG + //unregister if we released the lock + if (unlocked) unregister_thread(); + #endif + } + + #if TIMING + bigtime_t end = system_time(); + ru_time += (end - start); + ru_count++; + #endif + + return unlocked; +} + +bool +MultiLocker::WriteUnlock() +{ + #if TIMING + bigtime_t start = system_time(); + #endif + + bool unlocked = false; + + if (IsWriteLocked()) { + //if this is a nested lock simply decrement the nest count + if (fWriterNest > 0) { + fWriterNest--; + unlocked = true; + } else { + //writer finally unlocking + + //increment fReadCount by a large number + //this will let new readers acquire the read lock + //retrieve the number of current waiters + int32 readersWaiting = atomic_add(&fReadCount, LARGE_NUMBER) + LARGE_NUMBER; + + if (readersWaiting > 0) { + //readers are waiting to acquire the lock + unlocked = (release_sem_etc(fReadSem, readersWaiting, + B_DO_NOT_RESCHEDULE) == B_OK); + } else unlocked = true; + + if (unlocked) { + //clear the information + fWriterThread = -1; + fWriterStackBase = 0; + + //decrement and retrieve the lock count + if (atomic_add(&fLockCount, -1) > 1) { + //other writers are waiting so release fWriterLock + unlocked = (release_sem_etc(fWriterLock, 1, + B_DO_NOT_RESCHEDULE) == B_OK); + } + } + } + + } else debugger("Non-writer attempting to WriteUnlock()\n"); + + #if TIMING + bigtime_t end = system_time(); + wu_time += (end - start); + wu_count++; + #endif + + return unlocked; +} + +/* this function demonstrates a nice method of determining if the current thread */ +/* is the writer or not. The method involves caching the index of the page in memory */ +/* where the thread's stack is located. Each time a new writer acquires the lock, */ +/* its thread_id and stack_page are recorded. IsWriteLocked gets the stack_page of the */ +/* current thread and sees if it is a match. If the stack_page matches you are guaranteed */ +/* to have the matching thread. If the stack page doesn't match the more traditional */ +/* find_thread(NULL) method of matching the thread_ids is used. */ + +/* This technique is very useful when dealing with a lock that is acquired in a nested fashion. */ +/* It could be expanded to cache the information of the last thread in the lock, and then if */ +/* the same thread returns while there is no one in the lock, it could save some time, if the */ +/* same thread is likely to acquire the lock again and again. */ +/* I should note another shortcut that could be implemented here */ +/* If fWriterThread is set to -1 then there is no writer in the lock, and we could */ +/* return from this function much faster. However the function is currently set up */ +/* so all of the stack_base and thread_id info is determined here. WriteLock passes */ +/* in some variables so that if the lock is not held it does not have to get the thread_id */ +/* and stack base again. Instead this function returns that information. So this shortcut */ +/* would only move this information gathering outside of this function, and I like it all */ +/* contained. */ + +bool +MultiLocker::IsWriteLocked(uint32 *the_stack_base, thread_id *the_thread) +{ + #if TIMING + bigtime_t start = system_time(); + #endif + + //get a variable on the stack + bool write_lock_holder = false; + + if (fInit == B_OK) { + uint32 stack_base; + thread_id thread = 0; + + //determine which page in memory this stack represents + //this is managed by taking the address of the item on the + //stack and dividing it by the size of the memory pages + //if it is the same as the cached stack_page, there is a match + stack_base = (uint32) &write_lock_holder/B_PAGE_SIZE; + if (fWriterStackBase == stack_base) { + write_lock_holder = true; + } else { + //as there was no stack_page match we resort to the + //tried and true methods + thread = find_thread(NULL); + if (fWriterThread == thread) { + write_lock_holder = true; + } + } + + //if someone wants this information, give it to them + if (the_stack_base != NULL) { + *the_stack_base = stack_base; + } + if (the_thread != NULL) { + *the_thread = thread; + } + } + + #if TIMING + bigtime_t end = system_time(); + islock_time += (end - start); + islock_count++; + #endif + + return write_lock_holder; +} + +bool +MultiLocker::IsReadLocked() +{ + //a properly initialized MultiLocker in non-debug always returns true + bool locked = true; + if (fInit == B_NO_INIT) locked = false; + + #if DEBUG + //determine if the lock is actually held + thread_id thread = find_thread(NULL); + if (fDebugArray[thread % fMaxThreads] > 0) locked = true; + else locked = false; + #endif + + return locked; +} + + +/* these two functions manage the debug array for readers */ +/* an array is created in the constructor large enough to hold */ +/* an int32 for each of the maximum number of threads the system */ +/* can have at one time. */ +/* this array does not need to be locked because each running thread */ +/* can be uniquely mapped to a slot in the array by performing: */ +/* thread_id % max_threads */ +/* each time ReadLock is called while in debug mode the thread_id */ +/* is retrived in register_thread() and the count is adjusted in the */ +/* array. If register thread is ever called and the count is not 0 then */ +/* an illegal, potentially deadlocking nested ReadLock occured */ +/* unregister_thread clears the appropriate slot in the array */ + +/* this system could be expanded or retracted to include multiple arrays of information */ +/* in all fairness for it's current use, fDebugArray could be an array of bools */ + +/* The disadvantage of this system for maintaining state is that it sucks up a ton of */ +/* memory. The other method (which would be slower), would involve an additional lock and */ +/* traversing a list of cached information. As this is only for a debug mode, the extra memory */ +/* was not deemed to be a problem */ + +void +MultiLocker::register_thread() +{ + #ifdef DEBUG + #if TIMING + bigtime_t start = system_time(); + #endif + + thread_id thread = find_thread(NULL); + + ASSERT_WITH_MESSAGE(fDebugArray[thread%fMaxThreads] == 0,"Nested ReadLock!\n"); + fDebugArray[thread%fMaxThreads]++; + + #if TIMING + bigtime_t end = system_time(); + reg_time += (end - start); + reg_count++; + #endif + #else + debugger("register_thread should never be called unless in DEBUG mode!\n"); + #endif +} + +void +MultiLocker::unregister_thread() +{ + #ifdef DEBUG + #if TIMING + bigtime_t start = system_time(); + #endif + + thread_id thread = find_thread(NULL); + + ASSERT(fDebugArray[thread%fMaxThreads] == 1); + fDebugArray[thread%fMaxThreads]--; + + #if TIMING + bigtime_t end = system_time(); + unreg_time += (end - start); + unreg_count++; + #endif + #else + debugger("unregister_thread should never be called unless in DEBUG mode!\n"); + #endif + +} + + + diff --git a/src/servers/app/MultiLocker.h b/src/servers/app/MultiLocker.h new file mode 100644 index 0000000000..22406dfc32 --- /dev/null +++ b/src/servers/app/MultiLocker.h @@ -0,0 +1,114 @@ +/* MultiLocker.h */ +/* + Copyright 1999, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ + +/* multiple-reader single-writer locking class */ + +#ifndef MULTI_LOCKER_H +#define MULTI_LOCKER_H + +//#define TIMING 1 + +#include + +const int32 LARGE_NUMBER = 100000; + +class MultiLocker { + public: + MultiLocker(const char* semaphoreBaseName); + virtual ~MultiLocker(); + + status_t InitCheck(); + + //locking for reading or writing + bool ReadLock(); + bool WriteLock(); + + //unlocking after reading or writing + bool ReadUnlock(); + bool WriteUnlock(); + + //does the current thread hold a write lock ? + bool IsWriteLocked(uint32 *stack_base = NULL, thread_id *thread = NULL); + //in DEBUG mode returns whether the lock is held + //in non-debug mode returns true + bool IsReadLocked(); + + private: + //functions for managing the DEBUG reader array + void register_thread(); + void unregister_thread(); + + status_t fInit; + //readers adjust count and block on fReadSem when a writer + //hold the lock + int32 fReadCount; + sem_id fReadSem; + //writers adjust the count and block on fWriteSem + //when readers hold the lock + int32 fWriteCount; + sem_id fWriteSem; + //writers must acquire fWriterLock when acquiring a write lock + int32 fLockCount; + sem_id fWriterLock; + int32 fWriterNest; + + thread_id fWriterThread; + uint32 fWriterStackBase; + + int32 * fDebugArray; + int32 fMaxThreads; + +#if TIMING + uint32 rl_count; + bigtime_t rl_time; + uint32 ru_count; + bigtime_t ru_time; + uint32 wl_count; + bigtime_t wl_time; + uint32 wu_count; + bigtime_t wu_time; + uint32 islock_count; + bigtime_t islock_time; + uint32 reg_count; + bigtime_t reg_time; + uint32 unreg_count; + bigtime_t unreg_time; +#endif +}; + +class AutoWriteLocker { + public: + AutoWriteLocker(MultiLocker* lock) + : fLock(lock) + { + fLock->WriteLock(); + } + ~AutoWriteLocker() + { + fLock->WriteUnlock(); + } + private: + MultiLocker* fLock; +}; + +class AutoReadLocker { + public: + AutoReadLocker(MultiLocker* lock) + : fLock(lock) + { + fLock->ReadLock(); + } + ~AutoReadLocker() + { + fLock->ReadUnlock(); + } + private: + MultiLocker* fLock; +}; + + + +#endif diff --git a/src/servers/app/RootLayer.cpp b/src/servers/app/RootLayer.cpp index 66e7b207c5..251abc9d7e 100644 --- a/src/servers/app/RootLayer.cpp +++ b/src/servers/app/RootLayer.cpp @@ -37,9 +37,9 @@ #include #include "Decorator.h" -#include "Desktop.h" #include "DisplayDriver.h" #include "Globals.h" +#include "HWInterface.h" #include "Layer.h" #include "ServerApp.h" #include "ServerConfig.h" @@ -994,7 +994,19 @@ void RootLayer::SetScreens(Screen *screens[], int32 rows, int32 columns) { // NOTE: All screens *must* have the same resolution - fScreenPtrList.MakeEmpty(); + + // TODO: This function is badly named. Appearently, it + // adjusts the root layers frame rectangle, taking the information + // from the first screen in its list. However, a Screen object + // has actually now a different meaning. It manages access to + // the hardware and *owns* the HWInterface instance. + // This means there is going to be one Screen object per physical + // screen attached (unless I misunderstood how it was intended). + // A workspace needs to be attached to a screen + // and then on workspace activation, the appropriate updating + // needs to occur. The workspace tells its screen to configure + // to the workspaces mode, and then someone takes care of + // telling RootLayer to adjust itself and all other layers regions. uint16 width, height; uint32 colorSpace; @@ -1021,29 +1033,28 @@ RootLayer::SetScreenMode(int32 width, int32 height, uint32 colorSpace, float fre { if (fScreenWidth == width && fScreenHeight == height && fColorSpace == colorSpace && frequency == fFrequency) - return false; + return true; - bool accepted = true; + // NOTE: Currently, we have only one screen in that list. + // Before I changed it, this function would only accept modes + // that each of the (potentially multiple) screens can accept. + // However, I didn't really know what this gives in practice. + // We should re-think this when we really do support multiple monitors. + // For now, this function could potentially set the first couple of + // screens to the new mode, and fail to do so for the rest of them. + status_t ret = B_ERROR; for (int i = 0; i < fScreenPtrList.CountItems(); i++) { Screen *screen = static_cast(fScreenPtrList.ItemAt(i)); - if (!(screen->SupportsMode(width, height, colorSpace, frequency))) - accepted = false; - } - - if (!accepted) - return false; - - for (int i = 0; i < fScreenPtrList.CountItems(); i++) { - Screen *screen = static_cast(fScreenPtrList.ItemAt(i)); - - screen->SetMode(width, height, colorSpace, frequency); + ret = screen->SetMode(width, height, colorSpace, frequency); + if (ret < B_OK) + break; } SetScreens(Screens(), fRows, fColumns); - return true; + return ret >= B_OK; } //--------------------------------------------------------------------------- @@ -1083,7 +1094,7 @@ RootLayer::MouseEventHandler(int32 code, BPrivate::PortLink& msg) // mouse driver (which is ok, but we need to catch it here). // CRITICAL("mouse position changed in B_MOUSE_DOWN from last B_MOUSE_MOVED\n"); // update on screen mouse pos - GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y); + GetHWInterface()->MoveCursorTo(evt.where.x, evt.where.y); fLastMousePosition = evt.where; } @@ -1194,7 +1205,7 @@ RootLayer::MouseEventHandler(int32 code, BPrivate::PortLink& msg) fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_MOUSE_MOVED (%.1f, %.1f)!\n", evt.where.x, evt.where.y, fLastMousePosition.x, fLastMousePosition.y); // update on screen mouse pos - GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y); + GetHWInterface()->MoveCursorTo(evt.where.x, evt.where.y); fLastMousePosition = evt.where; } @@ -1262,7 +1273,7 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M msg.Read(&evt.where.y); msg.Read(&evt.buttons); - GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y); + GetHWInterface()->MoveCursorTo(evt.where.x, evt.where.y); fLastMousePosition = evt.where; diff --git a/src/servers/app/RootLayer.h b/src/servers/app/RootLayer.h index 7e911b3127..86893f13eb 100644 --- a/src/servers/app/RootLayer.h +++ b/src/servers/app/RootLayer.h @@ -33,15 +33,16 @@ #include #include "DebugInfoManager.h" +#include "Desktop.h" #include "Layer.h" #include "CursorManager.h" #include "Workspace.h" +class DisplayDriver; +class HWInterface; class RGBColor; class Screen; class WinBorder; -class Desktop; -class DisplayDriver; namespace BPrivate { class PortLink; @@ -173,6 +174,9 @@ friend class Desktop; void MouseEventHandler(int32 code, BPrivate::PortLink& link); void KeyboardEventHandler(int32 code, BPrivate::PortLink& link); + inline HWInterface* GetHWInterface() const + { return fDesktop->GetHWInterface(); } + Desktop* fDesktop; BMessage* fDragMessage; Layer* fLastMouseMoved; diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 97ca04f29e..801061f305 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -10,42 +10,43 @@ * Axel Dörfler, axeld@pinc-software.de */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AppServer.h" -#include "BitmapManager.h" -#include "BGet++.h" -#include "CursorManager.h" -#include "DecorManager.h" -#include "Desktop.h" -#include "DisplayDriver.h" -#include "FontServer.h" -#include "RAMLinkMsgReader.h" -#include "RootLayer.h" -#include "ServerApp.h" -#include "ServerScreen.h" -#include "ServerWindow.h" -#include "ServerCursor.h" -#include "ServerBitmap.h" -#include "ServerPicture.h" -#include "ServerConfig.h" -#include "SystemPalette.h" -#include "WinBorder.h" -#include "LayerData.h" -#include "Utils.h" - #include #include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AppServer.h" +#include "BGet++.h" +#include "BitmapManager.h" +#include "CursorManager.h" +#include "Desktop.h" +#include "DecorManager.h" +#include "DisplayDriver.h" +#include "FontServer.h" +#include "HWInterface.h" +#include "LayerData.h" +#include "RAMLinkMsgReader.h" +//#include "RGBColor.h" +#include "RootLayer.h" +#include "ServerBitmap.h" +#include "ServerConfig.h" +#include "ServerCursor.h" +#include "ServerPicture.h" +#include "ServerScreen.h" +#include "ServerWindow.h" +#include "SysCursor.h" +#include "SystemPalette.h" +#include "Utils.h" +#include "WinBorder.h" + +#include "ServerApp.h" #include //#define DEBUG_SERVERAPP @@ -359,7 +360,7 @@ ServerApp::SetAppCursor(void) // there should be a way that this ServerApp be attached to a particular // RootLayer to know which RootLayer's cursor to modify. if (fAppCursor) - gDesktop->ActiveRootLayer()->GetDisplayDriver()->SetCursor(fAppCursor); + gDesktop->GetHWInterface()->SetCursor(fAppCursor); } @@ -886,7 +887,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // although this isn't pretty, ATM we have only one RootLayer. // there should be a way that this ServerApp be attached to a particular // RootLayer to know which RootLayer's cursor to modify. - gDesktop->ActiveRootLayer()->GetDisplayDriver()->ShowCursor(); +// TODO: support nested showing/hiding + gDesktop->GetHWInterface()->SetCursorVisible(true); fCursorHidden = false; break; } @@ -896,7 +898,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // although this isn't pretty, ATM we have only one RootLayer. // there should be a way that this ServerApp be attached to a particular // RootLayer to know which RootLayer's cursor to modify. - gDesktop->ActiveRootLayer()->GetDisplayDriver()->HideCursor(); +// TODO: support nested showing/hiding + gDesktop->GetHWInterface()->SetCursorVisible(false); fCursorHidden = true; break; } @@ -906,7 +909,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // although this isn't pretty, ATM we have only one RootLayer. // there should be a way that this ServerApp be attached to a particular // RootLayer to know which RootLayer's cursor to modify. - gDesktop->ActiveRootLayer()->GetDisplayDriver()->ObscureCursor(); +// gDesktop->GetHWInterface()->ObscureCursor(); break; } case AS_QUERY_CURSOR_HIDDEN: @@ -940,7 +943,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // although this isn't pretty, ATM we have only one RootLayer. // there should be a way that this ServerApp be attached to a particular // RootLayer to know which RootLayer's cursor to modify. - gDesktop->ActiveRootLayer()->GetDisplayDriver()->SetCursor(fAppCursor); + gDesktop->GetHWInterface()->SetCursor(fAppCursor); break; } case AS_SET_CURSOR_BCURSOR: @@ -961,7 +964,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // RootLayer to know which RootLayer's cursor to modify. ServerCursor *cursor; if ((cursor = gDesktop->ActiveRootLayer()->GetCursorManager().FindCursor(ctoken))) - gDesktop->ActiveRootLayer()->GetDisplayDriver()->SetCursor(cursor); + gDesktop->GetHWInterface()->SetCursor(cursor); if (sync) { // the application is expecting a reply, but plans to do literally nothing @@ -1847,7 +1850,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // We have the screen_id and the workspace number, with these // we need to find the corresponding "driver", and call getmode on it display_mode mode; - gDesktop->GetDisplayDriver()->GetMode(mode); + gDesktop->ScreenAt(0)->GetMode(&mode); // actually this isn't still enough as different workspaces can // have different display_modes @@ -1880,15 +1883,12 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) bool makedefault = false; link.Read(&makedefault); - // TODO: Adi doesn't like this: see if - // messaging is better. - gDesktop->ActiveRootLayer()->Lock(); - // TODO: This should return something - gDesktop->GetDisplayDriver()->SetMode(mode); - gDesktop->ActiveRootLayer()->Unlock(); +// TODO: lock RootLayer, set mode and tell it to update it's frame and all clipping +// optionally put this into a message and let the root layer thread handle it. +// status_t ret = gDesktop->ScreenAt(0)->SetMode(mode); fLink.StartMessage(SERVER_TRUE); - fLink.Attach(B_OK); + fLink.Attach(ret); fLink.Flush(); break; } @@ -1897,7 +1897,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) { display_mode* modeList; uint32 count; - if (gDesktop->GetDisplayDriver()->GetModeList(&modeList, &count) == B_OK) { + if (gDesktop->GetHWInterface()->GetModeList(&modeList, &count) == B_OK) { fLink.StartMessage(SERVER_TRUE); fLink.Attach(count); fLink.Attach(modeList, sizeof(display_mode) * count); diff --git a/src/servers/app/ServerScreen.cpp b/src/servers/app/ServerScreen.cpp index 032eb0877a..735ce727e1 100644 --- a/src/servers/app/ServerScreen.cpp +++ b/src/servers/app/ServerScreen.cpp @@ -1,32 +1,15 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2005, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved. +// Distributed under the terms of the MIT license. // // File Name: ServerScreen.cpp // Author: Adi Oanca // Axel Dörfler, axeld@pinc-software.de +// Stephan Aßmus, // Description: Handles individual screens // //------------------------------------------------------------------------------ - #include #include #include @@ -34,79 +17,121 @@ #include #include +#include "CursorData.h" +#include "DisplayDriverPainter.h" +#include "HaikuSystemCursor.h" +#include "HWInterface.h" +#include "ServerCursor.h" + #include "ServerScreen.h" -#include "DisplayDriver.h" -Screen::Screen(DisplayDriver *driver, int32 id) - : - fID(id), - fDriver(driver) +Screen::Screen(HWInterface *interface, int32 id) + : fID(id), + fDriver(interface ? new DisplayDriverPainter(interface) : NULL), + fHWInterface(interface) +{ +} + +Screen::Screen() + : fID(-1), + fDriver(NULL), + fHWInterface(NULL) { } -Screen::~Screen(void) +Screen::~Screen() { + Shutdown(); delete fDriver; + delete fHWInterface; } -bool -Screen::SupportsMode(uint16 width, uint16 height, uint32 colorspace, float frequency) +status_t +Screen::Initialize() { - // TODO: remove/improve - return true; - display_mode *dm = NULL; - uint32 count; - - status_t err = fDriver->GetModeList(&dm, &count); - if (err < B_OK) { - // We've run into quite a problem here! This is a function which is a requirement - // for a graphics module. The best thing that we can hope for is 640x480x8 without - // knowing anything else. While even this seems like insanity to assume that we - // can support this, the only lower mode supported is 640x400, but we shouldn't even - // bother with such a pathetic possibility. - if (width == 640 && height == 480 && colorspace == B_CMAP8) - return true; - - return false; + status_t ret = B_NO_INIT; + if (fDriver) { + // this will also init the graphics hardware the driver is attached to + ret = fDriver->Initialize(); + if (ret >= B_OK) { + // take care of setting the cursor on this screen +// SetCursor(new ServerCursor(default_cursor_data)); + // TODO: some temporary goofing arround + ServerCursor* cursor = new ServerCursor(kHaikuCursorBits, + kHaikuCursorWidth, + kHaikuCursorHeight, + kHaikuCursorFormat); + // we just happen to know where the hotspot is + cursor->SetHotSpot(BPoint(1, 0)); + + fHWInterface->SetCursor(cursor); + } } - - for (uint32 i = 0; i < count; i++) { - if (dm[i].virtual_width == width - && dm[i].virtual_height == height - && dm[i].space == colorspace) - return true; - } - - free(dm); - return false; -} - - -bool -Screen::SetMode(uint16 width, uint16 height, uint32 colorspace, float frequency) -{ - if (!SupportsMode(width, height, colorspace, frequency)) - return false; - - display_mode mode; - mode.virtual_width = width; - mode.virtual_height = height; - mode.space = colorspace; - // ToDo: frequency! - // (we need to search the mode list for this) - - return fDriver->SetMode(mode) >= B_OK; + return ret; } void -Screen::GetMode(uint16 &width, uint16 &height, uint32 &colorspace, float &frequency) const +Screen::Shutdown() +{ + if (fDriver) + fDriver->Shutdown(); +} + + +status_t +Screen::SetMode(display_mode mode) +{ + status_t ret = fHWInterface->SetMode(mode); + + // the DisplayDriverPainter needs to adjust itself + if (ret >= B_OK) + fDriver->Update(); + + return ret; +} + + +status_t +Screen::SetMode(uint16 width, uint16 height, uint32 colorspace, + float frequency) +{ + status_t ret = B_ERROR; + + // search for a matching mode + display_mode mode; + ret = _FindMode(width, height, colorspace, frequency, &mode); + + if (ret < B_OK) { + // Ups. Not good. Ignore the requested mode and use fallback params. + mode.virtual_width = 640; + mode.virtual_height = 480; + mode.space = B_CMAP8; + } + + ret = SetMode(mode); + + return ret; +} + + +void +Screen::GetMode(display_mode* mode) const +{ + fHWInterface->GetMode(mode); +} + + +void +Screen::GetMode(uint16 &width, uint16 &height, uint32 &colorspace, + float &frequency) const { display_mode mode; - fDriver->GetMode(mode); + + fHWInterface->GetMode(&mode); width = mode.virtual_width; height = mode.virtual_height; @@ -116,9 +141,58 @@ Screen::GetMode(uint16 &width, uint16 &height, uint32 &colorspace, float &freque } -int32 -Screen::ScreenNumber(void) const +status_t +Screen::_FindMode(uint16 width, uint16 height, uint32 colorspace, + float frequency, display_mode* mode) const { - return fID; + display_mode* dm = NULL; + uint32 count; + + status_t err = fHWInterface->GetModeList(&dm, &count); + if (err < B_OK) { + // We've run into quite a problem here! This is a function which is a requirement + // for a graphics module. The best thing that we can hope for is 640x480x8 without + // knowing anything else. While even this seems like insanity to assume that we + // can support this, the only lower mode supported is 640x400, but we shouldn't even + // bother with such a pathetic possibility. + if (width == 640 && height == 480 && colorspace == B_CMAP8) + return B_OK; + + return err; + } + + bool found = false; + for (uint32 i = 0; i < count; i++) { + if (dm[i].virtual_width == width + && dm[i].virtual_height == height + && dm[i].space == colorspace) { +#if __HAIKU__ + // we have found a mode with the correct width, height and format + // now see if the frequency matches (don't be too picky) + float modeFrequency = 0.0; + float t = dm[i].timing.h_total * dm[i].timing.v_total; + if (t != 0.0) + modeFrequency = dm[i].timing.pixel_clock * 1000.f / t; + + if (int(modeFrequency/* * 10.0*/ + 0.5) == int(frequency/* * 10.0*/ + 0.5)) { + *mode = dm[i]; + found = true; + break; + } +#else + // Ignore frequency in test mode + *mode = dm[i]; + found = true; + break; +#endif // __HAIKU__ + } + } + + delete[] dm; + + if (!found) { + fprintf(stderr, "mode not found (%d, %d, %f)!\n", width, height, frequency); + } + return found ? B_OK : B_ERROR; } diff --git a/src/servers/app/ServerScreen.h b/src/servers/app/ServerScreen.h index 8a917efa9f..c07f85b976 100644 --- a/src/servers/app/ServerScreen.h +++ b/src/servers/app/ServerScreen.h @@ -1,55 +1,64 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2005, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved. +// Distributed under the terms of the MIT license. // // File Name: ServerScreen.h // Author: Adi Oanca // Axel Dörfler, axeld@pinc-software.de +// Stephan Aßmus, // Description: Handles individual screens // //------------------------------------------------------------------------------ #ifndef _SCREEN_H_ #define _SCREEN_H_ - +#include #include class DisplayDriver; +class HWInterface; class Screen { -public: - Screen(DisplayDriver *driver, int32 id); - Screen() {} - ~Screen(void); + public: + Screen(HWInterface *interface, int32 id); + Screen(); + virtual ~Screen(); - void SetID(int32 ID) { fID = ID; } - bool SupportsMode(uint16 width, uint16 height, uint32 colorspace, float frequency); - bool SetMode(uint16 width, uint16 height, uint32 colorspace, float frequency); - void GetMode(uint16 &width, uint16 &height, uint32 &colorspace, float &frequency) const; + status_t Initialize(); + void Shutdown(); - int32 ScreenNumber(void) const; - DisplayDriver *GetDisplayDriver() const { return fDriver; } + void SetID(int32 ID) + { fID = ID; } -private: - int32 fID; - DisplayDriver *fDriver; + status_t SetMode(display_mode mode); + status_t SetMode(uint16 width, + uint16 height, + uint32 colorspace, + float frequency); + void GetMode(display_mode* mode) const; + void GetMode(uint16 &width, + uint16 &height, + uint32 &colorspace, + float &frequency) const; + + inline int32 ScreenNumber() const + { return fID; } + + inline DisplayDriver* GetDisplayDriver() const + { return fDriver; } + inline HWInterface* GetHWInterface() const + { return fHWInterface; } + + private: + status_t _FindMode(uint16 width, + uint16 height, + uint32 colorspace, + float frequency, + display_mode* mode) const; + + int32 fID; + DisplayDriver* fDriver; + HWInterface* fHWInterface; }; #endif /* _SCREEN_H_ */ diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index fc6bb8256c..e35015cfcd 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -10,36 +10,34 @@ * Axel Dörfler, axeld@pinc-software.de */ - #include -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#include #include + #include "AppServer.h" #include "BGet++.h" #include "DebugInfoManager.h" #include "Desktop.h" +#include "DisplayDriver.h" +#include "HWInterface.h" #include "Layer.h" +#include "MessagePrivate.h" #include "RAMLinkMsgReader.h" #include "RootLayer.h" -#include "ServerWindow.h" #include "ServerApp.h" -#include "ServerProtocol.h" -#include "ServerPicture.h" -#include "WinBorder.h" -#include "TokenHandler.h" -#include "Utils.h" -#include "DisplayDriver.h" #include "ServerBitmap.h" #include "ServerPicture.h" +#include "ServerProtocol.h" +#include "TokenHandler.h" +#include "Utils.h" +#include "WinBorder.h" #include "Workspace.h" -#include "MessagePrivate.h" + +#include "ServerWindow.h" //#define DEBUG_SERVERWINDOW //#define DEBUG_SERVERWINDOW_GRAPHICS @@ -420,9 +418,10 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // -> it will invalidate areas previously out of screen dst = dst | src; + fCurrentLayer->fLayerData->OffsetOrigin(BPoint(dh, dv)); + _CopyBits(myRootLayer, fCurrentLayer, src, dst, xOffset, yOffset); - fCurrentLayer->fLayerData->OffsetOrigin(BPoint(dh, dv)); break; } @@ -451,7 +450,9 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) link.Read(&token); +myRootLayer->Lock(); Layer *current = fWinBorder->FindLayer(token); +myRootLayer->Unlock(); if (current) { DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token)); } else { @@ -475,12 +476,14 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) if (fCurrentLayer != NULL) break; +myRootLayer->Lock(); fWinBorder->fTopLayer = CreateLayerTree(link, NULL); fWinBorder->fTopLayer->SetAsTopLayer(true); fCurrentLayer = fWinBorder->fTopLayer; // connect decorator and top layer. fWinBorder->AddChild(fWinBorder->fTopLayer, NULL); +myRootLayer->Unlock(); break; } @@ -490,6 +493,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) Layer* parent = NULL; Layer* newLayer = CreateLayerTree(link, &parent); +myRootLayer->Lock(); if (parent != NULL) parent->AddChild(newLayer, this); @@ -500,6 +504,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) myRootLayer->GoInvalidate(newLayer, newLayer->Frame()); #endif +myRootLayer->Unlock(); break; } case AS_LAYER_DELETE: @@ -514,12 +519,14 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) parent = fCurrentLayer->fParent; // here we remove current layer from list. +myRootLayer->Lock(); fCurrentLayer->RemoveSelf(); fCurrentLayer->PruneTree(); if (parent) myRootLayer->GoInvalidate(parent, BRegion(fCurrentLayer->Frame())); - +myRootLayer->Unlock(); + #ifdef DEBUG_SERVERWINDOW parent->PrintTree(); #endif @@ -1429,7 +1436,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) // 1) BPoint mouse location // 2) int32 button state - fLink.Attach(gDesktop->GetDisplayDriver()->GetCursorPosition()); + fLink.Attach(gDesktop->GetHWInterface()->GetCursorPosition()); fLink.Attach(gDesktop->ActiveRootLayer()->Buttons()); fLink.Flush(); diff --git a/src/servers/app/drawing/AccelerantHWInterface.cpp b/src/servers/app/drawing/AccelerantHWInterface.cpp index 28798a784c..2c4b64d6f7 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.cpp +++ b/src/servers/app/drawing/AccelerantHWInterface.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// Copyright 2002-2005, Haiku, Inc. +// Copyright 2002-2005, Haiku, Inc. All rights reserved. // Distributed under the terms of the MIT License. // // @@ -12,7 +12,9 @@ // //------------------------------------------------------------------------------ +#include #include +#include #include @@ -24,7 +26,6 @@ #include #include -//#include "PortLink.h" #include "RGBColor.h" #include "ServerConfig.h" #include "ServerCursor.h" @@ -51,6 +52,12 @@ extern "C" status_t _kern_frame_buffer_update(void *baseAddress, #endif +bool +operator==(const display_mode& a, const display_mode& b) +{ + return memcmp(&a, &b, sizeof(display_mode)) == 0; +} + // constructor AccelerantHWInterface::AccelerantHWInterface() : HWInterface(), @@ -90,7 +97,7 @@ AccelerantHWInterface::AccelerantHWInterface() fModeList(NULL), fBackBuffer(NULL), - fFrontBuffer(new AccelerantBuffer()) + fFrontBuffer(new(nothrow) AccelerantBuffer()) { fDisplayMode.virtual_width = 640; fDisplayMode.virtual_height = 480; @@ -107,7 +114,7 @@ AccelerantHWInterface::~AccelerantHWInterface() { delete fBackBuffer; delete fFrontBuffer; - delete fModeList; + delete[] fModeList; } @@ -118,21 +125,25 @@ AccelerantHWInterface::~AccelerantHWInterface() status_t AccelerantHWInterface::Initialize() { - for (int32 i = 1; fCardFD != B_ENTRY_NOT_FOUND; i++) { - fCardFD = OpenGraphicsDevice(i); - if (fCardFD < 0) { - ATRACE(("Failed to open graphics device\n")); - continue; + status_t ret = HWInterface::Initialize(); + if (ret >= B_OK) { + for (int32 i = 1; fCardFD != B_ENTRY_NOT_FOUND; i++) { + fCardFD = _OpenGraphicsDevice(i); + if (fCardFD < 0) { + ATRACE(("Failed to open graphics device\n")); + continue; + } + + if (_OpenAccelerant(fCardFD) == B_OK) + break; + + close(fCardFD); + // _OpenAccelerant() failed, try to open next graphics card } - - if (OpenAccelerant(fCardFD) == B_OK) - break; - - close(fCardFD); - // OpenAccelerant() failed, try to open next graphics card + + return fCardFD >= 0 ? B_OK : fCardFD; } - - return fCardFD >= 0 ? B_OK : fCardFD; + return ret; } @@ -148,7 +159,7 @@ AccelerantHWInterface::Initialize() the first working entry. */ int -AccelerantHWInterface::OpenGraphicsDevice(int deviceNumber) +AccelerantHWInterface::_OpenGraphicsDevice(int deviceNumber) { DIR *directory = opendir("/dev/graphics"); if (!directory) @@ -194,7 +205,7 @@ AccelerantHWInterface::OpenGraphicsDevice(int deviceNumber) status_t -AccelerantHWInterface::OpenAccelerant(int device) +AccelerantHWInterface::_OpenAccelerant(int device) { char signature[1024]; if (ioctl(device, B_GET_ACCELERANT_SIGNATURE, @@ -248,7 +259,7 @@ AccelerantHWInterface::OpenAccelerant(int device) if (fAccelerantImage < B_OK) return B_ERROR; - if (SetupDefaultHooks() != B_OK) { + if (_SetupDefaultHooks() != B_OK) { ATRACE(("cannot setup default hooks\n")); uninit_accelerant uninitAccelerant = (uninit_accelerant) @@ -265,7 +276,7 @@ AccelerantHWInterface::OpenAccelerant(int device) status_t -AccelerantHWInterface::SetupDefaultHooks() +AccelerantHWInterface::_SetupDefaultHooks() { // required fAccAcquireEngine = (acquire_engine)fAccelerantHook(B_ACQUIRE_ENGINE, NULL); @@ -324,37 +335,36 @@ AccelerantHWInterface::Shutdown() status_t AccelerantHWInterface::SetMode(const display_mode &mode) { + AutoWriteLocker _(this); // TODO: There are places this function can fail, // maybe it needs to roll back changes in case of an // error. // prevent from doing the unnecessary if (fModeCount > 0 && fBackBuffer && fFrontBuffer - && fDisplayMode.virtual_width == mode.virtual_width - && fDisplayMode.virtual_height == mode.virtual_height - && fDisplayMode.space == mode.space) { + && fDisplayMode == mode) { return B_OK; } - // TODO: check if the mode is valid even (ie complies to the modes we said we would support) - // or else ret = B_BAD_VALUE - if (fModeCount <= 0 || !fModeList) { - if (UpdateModeList() != B_OK || fModeCount <= 0) { + if (_UpdateModeList() != B_OK || fModeCount <= 0) { ATRACE(("unable to update mode list\n")); return B_ERROR; } } + // check if the mode is in our list + bool found = false; for (int32 i = 0; i < fModeCount; i++) { - if (fModeList[i].virtual_width == mode.virtual_width - && fModeList[i].virtual_height == mode.virtual_height - && fModeList[i].space == mode.space) { - - fDisplayMode = fModeList[i]; + if (fModeList[i] == mode) { + found = true; break; } } + if (!found) + return B_BAD_VALUE; + + fDisplayMode = mode; if (fAccSetDisplayMode(&fDisplayMode) != B_OK) { ATRACE(("setting display mode failed\n")); @@ -366,7 +376,7 @@ AccelerantHWInterface::SetMode(const display_mode &mode) // update frontbuffer fFrontBuffer->SetDisplayMode(fDisplayMode); - if (UpdateFrameBufferConfig() != B_OK) + if (_UpdateFrameBufferConfig() != B_OK) return B_ERROR; // Update the frame buffer used by the on-screen KDL @@ -399,10 +409,10 @@ AccelerantHWInterface::SetMode(const display_mode &mode) doubleBuffered = true; if (doubleBuffered) { - fBackBuffer = new MallocBuffer(fDisplayMode.virtual_width, - fDisplayMode.virtual_height); + fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width, + fDisplayMode.virtual_height); - status_t ret = fBackBuffer->InitCheck(); + status_t ret = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY; if (ret < B_OK) { delete fBackBuffer; fBackBuffer = NULL; @@ -427,19 +437,22 @@ AccelerantHWInterface::SetMode(const display_mode &mode) void AccelerantHWInterface::GetMode(display_mode *mode) { - if (mode) + if (mode && ReadLock()) { *mode = fDisplayMode; + ReadUnlock(); + } } status_t -AccelerantHWInterface::UpdateModeList() +AccelerantHWInterface::_UpdateModeList() { fModeCount = fAccGetModeCount(); if (fModeCount <= 0) return B_ERROR; - fModeList = new display_mode[fModeCount]; + delete[] fModeList; + fModeList = new(nothrow) display_mode[fModeCount]; if (!fModeList) return B_NO_MEMORY; @@ -453,7 +466,7 @@ AccelerantHWInterface::UpdateModeList() status_t -AccelerantHWInterface::UpdateFrameBufferConfig() +AccelerantHWInterface::_UpdateFrameBufferConfig() { if (fAccGetFrameBufferConfig(&fFrameBufferConfig) != B_OK) { ATRACE(("unable to get frame buffer config\n")); @@ -479,21 +492,33 @@ AccelerantHWInterface::GetDeviceInfo(accelerant_device_info *info) // GetModeList status_t -AccelerantHWInterface::GetModeList(display_mode **modes, uint32 *count) +AccelerantHWInterface::GetModeList(display_mode** modes, uint32 *count) { + AutoReadLocker _(this); + if (!count || !modes) return B_BAD_VALUE; - - *modes = new display_mode[fModeCount]; - *count = fModeCount; - - memcpy(*modes, fModeList, sizeof(display_mode) * fModeCount); - return B_OK; + + status_t ret = fModeList ? B_OK : _UpdateModeList(); + + if (ret >= B_OK) { + *modes = new(nothrow) display_mode[fModeCount]; + if (*modes) { + *count = fModeCount; + memcpy(*modes, fModeList, sizeof(display_mode) * fModeCount); + } else { + *count = 0; + ret = B_NO_MEMORY; + } + } + return ret; } status_t AccelerantHWInterface::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high) { + AutoReadLocker _(this); + if (!mode || !low || !high) return B_BAD_VALUE; @@ -503,6 +528,8 @@ AccelerantHWInterface::GetPixelClockLimits(display_mode *mode, uint32 *low, uint status_t AccelerantHWInterface::GetTimingConstraints(display_timing_constraints *dtc) { + AutoReadLocker _(this); + if (!dtc) return B_BAD_VALUE; @@ -515,6 +542,8 @@ AccelerantHWInterface::GetTimingConstraints(display_timing_constraints *dtc) status_t AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode *low, const display_mode *high) { + AutoReadLocker _(this); + if (!candidate || !low || !high) return B_BAD_VALUE; @@ -533,6 +562,8 @@ AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode * status_t AccelerantHWInterface::WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) { + AutoReadLocker _(this); + accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL); if (!AccelerantRetraceSemaphore) return B_UNSUPPORTED; @@ -548,6 +579,8 @@ AccelerantHWInterface::WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) status_t AccelerantHWInterface::SetDPMSMode(const uint32 &state) { + AutoWriteLocker _(this); + if (!fAccSetDPMSMode) return B_UNSUPPORTED; @@ -556,8 +589,10 @@ AccelerantHWInterface::SetDPMSMode(const uint32 &state) // DPMSMode uint32 -AccelerantHWInterface::DPMSMode() const +AccelerantHWInterface::DPMSMode() { + AutoReadLocker _(this); + if (!fAccDPMSMode) return B_UNSUPPORTED; @@ -566,8 +601,10 @@ AccelerantHWInterface::DPMSMode() const // DPMSCapabilities uint32 -AccelerantHWInterface::DPMSCapabilities() const +AccelerantHWInterface::DPMSCapabilities() { + AutoReadLocker _(this); + if (!fAccDPMSCapabilities) return B_UNSUPPORTED; @@ -690,37 +727,37 @@ AccelerantHWInterface::InvertRegion(/*const*/ BRegion& region) void AccelerantHWInterface::SetCursor(ServerCursor* cursor) { - if (Lock()) { - HWInterface::SetCursor(cursor); + HWInterface::SetCursor(cursor); +// if (WriteLock()) { // TODO: implement setting the hard ware cursor // NOTE: cursor should be always B_RGBA32 // NOTE: The HWInterface implementation should // still be called, since it takes ownership of // the cursor. - Unlock(); - } +// WriteUnlock(); +// } } // SetCursorVisible void AccelerantHWInterface::SetCursorVisible(bool visible) { - if (Lock()) { - HWInterface::SetCursorVisible(visible); + HWInterface::SetCursorVisible(visible); +// if (WriteLock()) { // TODO: update graphics hardware - Unlock(); - } +// WriteUnlock(); +// } } // MoveCursorTo void AccelerantHWInterface::MoveCursorTo(const float& x, const float& y) { - if (Lock()) { - HWInterface::MoveCursorTo(x, y); + HWInterface::MoveCursorTo(x, y); +// if (WriteLock()) { // TODO: update graphics hardware - Unlock(); - } +// WriteUnlock(); +// } } // FrontBuffer diff --git a/src/servers/app/drawing/AccelerantHWInterface.h b/src/servers/app/drawing/AccelerantHWInterface.h index 06b722b423..e3e6479bc6 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.h +++ b/src/servers/app/drawing/AccelerantHWInterface.h @@ -45,8 +45,8 @@ virtual status_t ProposeMode(display_mode *candidate, virtual status_t WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT); virtual status_t SetDPMSMode(const uint32 &state); -virtual uint32 DPMSMode() const; -virtual uint32 DPMSCapabilities() const; +virtual uint32 DPMSMode(); +virtual uint32 DPMSCapabilities(); // query for available hardware accleration and perform it virtual uint32 AvailableHWAcceleration() const; @@ -72,11 +72,11 @@ protected: virtual void _DrawCursor(BRect area) const; private: - int OpenGraphicsDevice(int deviceNumber); - status_t OpenAccelerant(int device); - status_t SetupDefaultHooks(); - status_t UpdateModeList(); - status_t UpdateFrameBufferConfig(); + int _OpenGraphicsDevice(int deviceNumber); + status_t _OpenAccelerant(int device); + status_t _SetupDefaultHooks(); + status_t _UpdateModeList(); + status_t _UpdateFrameBufferConfig(); void _RegionToRectParams(/*const*/ BRegion* region, fill_rect_params** params, uint32* count) const; diff --git a/src/servers/app/drawing/DisplayDriver.cpp b/src/servers/app/drawing/DisplayDriver.cpp index 3a13a62f31..dbf45ec5d3 100644 --- a/src/servers/app/drawing/DisplayDriver.cpp +++ b/src/servers/app/drawing/DisplayDriver.cpp @@ -1,53 +1,26 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2002, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved +// Distributed under the terms of the MIT license. // // File Name: DisplayDriver.cpp -// Author: DarkWyrm +// Authors: DarkWyrm // Gabe Yoder -// Description: Mostly abstract class which handles all graphics output +// Stephan Aßmus +// +// Description: Abstract class which handles all graphics output // for the server // //------------------------------------------------------------------------------ #include #include -#include "CursorData.h" -#include "HaikuSystemCursor.h" -#include "ServerCursor.h" #include "DisplayDriver.h" -/*! - \brief Sets up internal variables needed by all DisplayDriver subclasses -*/ DisplayDriver::DisplayDriver() { - fDisplayMode.virtual_width = 640; - fDisplayMode.virtual_height = 480; - fDisplayMode.space = B_RGBA32; } -/*! - \brief Does nothing -*/ DisplayDriver::~DisplayDriver() { } @@ -56,25 +29,14 @@ DisplayDriver::~DisplayDriver() \brief Initializes the driver object. \return true if successful, false if not - Initializes the CursorHandler with the default system cursor. - Derived versions should set up the driver for display, including the initial clearing of the screen. If things do not go as they should, false should be returned. */ -bool +status_t DisplayDriver::Initialize() { -// SetCursor(new ServerCursor(default_cursor_data)); - // TODO: some temporary goofing arround - ServerCursor* cursor = new ServerCursor(kHaikuCursorBits, - kHaikuCursorWidth, - kHaikuCursorHeight, - kHaikuCursorFormat); - // we just happen to know - cursor->SetHotSpot(BPoint(1, 0)); - SetCursor(cursor); - return true; + return B_OK; } /*! @@ -88,32 +50,3 @@ DisplayDriver::Shutdown() { } -/* - \brief Sets the screen mode to specified resolution and color depth. - \param mode Data structure as defined in Screen.h - - Subclasses must include calls to _SetDepth, _SetHeight, _SetWidth, and _SetMode - to update the state variables kept internally by the DisplayDriver class. -*/ -status_t -DisplayDriver::SetMode(const display_mode &mode) -{ - if (Lock()) { - fDisplayMode = mode; - Unlock(); - return B_OK; - } - - return B_ERROR; -} - -// GetMode -void -DisplayDriver::GetMode(display_mode &mode) -{ - if (Lock()) { - mode = fDisplayMode; - Unlock(); - } -} - diff --git a/src/servers/app/drawing/DisplayDriverPainter.cpp b/src/servers/app/drawing/DisplayDriverPainter.cpp index 7e49207407..2170c13b5b 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.cpp +++ b/src/servers/app/drawing/DisplayDriverPainter.cpp @@ -1,23 +1,6 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2005, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved. +// Distributed under the terms of the MIT license. // // File Name: DisplayDriverPainter.cpp // Author: Stephan Aßmus @@ -28,35 +11,19 @@ #include #include +#include "HWInterface.h" #include "LayerData.h" #include "Painter.h" #include "PNGDump.h" #include "RenderingBuffer.h" -#ifdef __HAIKU__ -#define USE_ACCELERANT 1 -#else -#define USE_ACCELERANT 0 -#endif - - -#if USE_ACCELERANT - #include "AccelerantHWInterface.h" -#else - #include "ViewHWInterface.h" -#endif - #include "DisplayDriverPainter.h" // constructor -DisplayDriverPainter::DisplayDriverPainter() +DisplayDriverPainter::DisplayDriverPainter(HWInterface* hwInterface) : DisplayDriver(), fPainter(new Painter()), -#if USE_ACCELERANT - fGraphicsCard(new AccelerantHWInterface()), -#else - fGraphicsCard(new ViewHWInterface()), -#endif + fGraphicsCard(hwInterface), fAvailableHWAccleration(0) { } @@ -64,22 +31,24 @@ DisplayDriverPainter::DisplayDriverPainter() // destructor DisplayDriverPainter::~DisplayDriverPainter() { - delete fGraphicsCard; + delete fPainter; } // Initialize -bool +status_t DisplayDriverPainter::Initialize() { - status_t err = fGraphicsCard->Initialize(); - if (err < B_OK) - fprintf(stderr, "HWInterface::Initialize() failed: %s\n", strerror(err)); - if (err >= B_OK) { - fAvailableHWAccleration = fGraphicsCard->AvailableHWAcceleration(); - return DisplayDriver::Initialize(); + status_t err = B_ERROR; + if (WriteLock()) { + err = fGraphicsCard->Initialize(); + if (err < B_OK) + fprintf(stderr, "HWInterface::Initialize() failed: %s\n", strerror(err)); + if (err >= B_OK) { + err = DisplayDriver::Initialize(); + } + WriteUnlock(); } - - return false; + return err; } // Shutdown @@ -89,6 +58,18 @@ DisplayDriverPainter::Shutdown() DisplayDriver::Shutdown(); } +// Update +void +DisplayDriverPainter::Update() +{ + if (Lock()) { + fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer()); + // available HW acceleration might have changed + fAvailableHWAccleration = fGraphicsCard->AvailableHWAcceleration(); + Unlock(); + } +} + // ConstrainClippingRegion void DisplayDriverPainter::ConstrainClippingRegion(BRegion *region) { @@ -222,7 +203,10 @@ void DisplayDriverPainter::CopyRegion(/*const*/ BRegion* region, int32 xOffset, int32 yOffset) { - if (Lock()) { + // NOTE: Write locking because we might use HW acceleration. + // This needs to be investigated, I'm doing this because of + // gut feeling. + if (WriteLock()) { fGraphicsCard->HideSoftwareCursor(region->Frame()); int32 count = region->CountRects(); @@ -329,7 +313,7 @@ DisplayDriverPainter::CopyRegion(/*const*/ BRegion* region, fGraphicsCard->ShowSoftwareCursor(); - Unlock(); + WriteUnlock(); } } @@ -349,7 +333,10 @@ void DisplayDriverPainter::CopyRegionList(BList* list, BList* pList, int32 rCount, BRegion* clipReg) { - if (Lock()) { + // NOTE: Write locking because we might use HW acceleration. + // This needs to be investigated, I'm doing this because of + // gut feeling. + if (WriteLock()) { for (int32 i = 0; i < rCount; i++) { BRegion* region = (BRegion*)list->ItemAt(i); @@ -357,7 +344,7 @@ DisplayDriverPainter::CopyRegionList(BList* list, BList* pList, CopyRegion(region, (int32)offset->x, (int32)offset->y); } - Unlock(); + WriteUnlock(); } } @@ -365,7 +352,10 @@ DisplayDriverPainter::CopyRegionList(BList* list, BList* pList, void DisplayDriverPainter::InvertRect(const BRect &r) { - if (Lock()) { + // NOTE: Write locking because we might use HW acceleration. + // This needs to be investigated, I'm doing this because of + // gut feeling. + if (WriteLock()) { BRect vr(min_c(r.left, r.right), min_c(r.top, r.bottom), max_c(r.left, r.right), @@ -388,7 +378,7 @@ DisplayDriverPainter::InvertRect(const BRect &r) fGraphicsCard->ShowSoftwareCursor(); } - Unlock(); + WriteUnlock(); } } @@ -499,7 +489,10 @@ DisplayDriverPainter::FillPolygon(BPoint *ptlist, int32 numpts, void DisplayDriverPainter::FillRect(const BRect& r, const RGBColor& color) { - if (Lock()) { + // NOTE: Write locking because we might use HW acceleration. + // This needs to be investigated, I'm doing this because of + // gut feeling. + if (WriteLock()) { BRect vr(min_c(r.left, r.right), min_c(r.top, r.bottom), max_c(r.left, r.right), @@ -522,7 +515,7 @@ DisplayDriverPainter::FillRect(const BRect& r, const RGBColor& color) fGraphicsCard->ShowSoftwareCursor(); } - Unlock(); + WriteUnlock(); } } @@ -530,7 +523,10 @@ DisplayDriverPainter::FillRect(const BRect& r, const RGBColor& color) void DisplayDriverPainter::FillRect(const BRect &r, const DrawData *d) { - if (Lock()) { + // NOTE: Write locking because we might use HW acceleration. + // This needs to be investigated, I'm doing this because of + // gut feeling. + if (WriteLock()) { BRect vr(min_c(r.left, r.right), min_c(r.top, r.bottom), max_c(r.left, r.right), @@ -568,7 +564,7 @@ DisplayDriverPainter::FillRect(const BRect &r, const DrawData *d) fGraphicsCard->ShowSoftwareCursor(); } - Unlock(); + WriteUnlock(); } } @@ -576,7 +572,10 @@ DisplayDriverPainter::FillRect(const BRect &r, const DrawData *d) void DisplayDriverPainter::FillRegion(BRegion& r, const DrawData *d) { - if (Lock()) { + // NOTE: Write locking because we might use HW acceleration. + // This needs to be investigated, I'm doing this because of + // gut feeling. + if (WriteLock()) { fGraphicsCard->HideSoftwareCursor(fPainter->ClipRect(r.Frame())); @@ -610,7 +609,7 @@ DisplayDriverPainter::FillRegion(BRegion& r, const DrawData *d) fGraphicsCard->ShowSoftwareCursor(); - Unlock(); + WriteUnlock(); } } @@ -1062,161 +1061,32 @@ DisplayDriverPainter::StringHeight(const char *string, int32 length, return height; } -// GetBoundingBoxes -void -DisplayDriverPainter::GetBoundingBoxes(const char *string, int32 count, - font_metric_mode mode, - escapement_delta *delta, - BRect *rectarray, const DrawData *d) -{ - // ?!? each glyph or what? - printf("DisplayDriverPainter::GetBoundingBoxes()\n"); -} - -// GetEscapements -void -DisplayDriverPainter::GetEscapements(const char *string, int32 charcount, - escapement_delta *delta, - escapement_delta *escapements, - escapement_delta *offsets, - const DrawData *d) -{ - printf("DisplayDriverPainter::GetEscapements()\n"); -} - -// GetEdges -void -DisplayDriverPainter::GetEdges(const char *string, int32 charcount, - edge_info *edgearray, const DrawData *d) -{ - printf("DisplayDriverPainter::GetEdges()\n"); -} - -// GetHasGlyphs -void DisplayDriverPainter::GetHasGlyphs(const char *string, int32 charcount, - bool *hasarray) -{ - printf("DisplayDriverPainter::GetHasGlyphs()\n"); -} - -// GetTruncatedStrings -void -DisplayDriverPainter::GetTruncatedStrings(const char **instrings, - const int32 &stringcount, - const uint32 &mode, - const float &maxwidth, - char **outstrings) -{ - printf("DisplayDriverPainter::GetTruncatedStrings()\n"); -} - -// HideCursor -void -DisplayDriverPainter::HideCursor() -{ - fGraphicsCard->SetCursorVisible(false); -} - -// IsCursorHidden -bool -DisplayDriverPainter::IsCursorHidden() -{ - return !fGraphicsCard->IsCursorVisible(); -} - -// MoveCursorTo -void -DisplayDriverPainter::MoveCursorTo(const float &x, const float &y) -{ - fGraphicsCard->MoveCursorTo(x, y); -} - -// ShowCursor -void -DisplayDriverPainter::ShowCursor() -{ - fGraphicsCard->SetCursorVisible(true); -} - -// ObscureCursor -void -DisplayDriverPainter::ObscureCursor() -{ - // TODO: I don't think this has anything to do with the DisplayDriver - // implement elsewhere!! -} - -// SetCursor -void -DisplayDriverPainter::SetCursor(ServerCursor *cursor) -{ - fGraphicsCard->SetCursor(cursor); -} - -// GetCursorPosition -BPoint -DisplayDriverPainter::GetCursorPosition() -{ - return fGraphicsCard->GetCursorPosition(); -} - -// IsCursorObscured -bool -DisplayDriverPainter::IsCursorObscured(bool state) -{ - // TODO: I don't think this has anything to do with the DisplayDriver - // implement elsewhere!! - return false; -} - // Lock bool -DisplayDriverPainter::Lock(bigtime_t timeout) -{ - bool success = false; - // NOTE: I'm hoping I don't change the semantics and implications of - // the original implementation, but I need the locker to be somewhere - // else in order to serialize only the access to the back buffer - if (timeout == B_INFINITE_TIMEOUT) { - success = fGraphicsCard->Lock(); -//printf("DisplayDriverPainter::Lock()\n"); - } else { - success = (fGraphicsCard->LockWithTimeout(timeout) >= B_OK) ? true : false; -//printf("DisplayDriverPainter::LockWithTimeout(): %d\n", success); - } - - return success; +DisplayDriverPainter::Lock() +{ + return fGraphicsCard->ReadLock(); } // Unlock void DisplayDriverPainter::Unlock() { -//printf("DisplayDriverPainter::Unlock()\n"); - fGraphicsCard->Unlock(); + fGraphicsCard->ReadUnlock(); } -// SetMode -status_t -DisplayDriverPainter::SetMode(const display_mode &mode) +// WriteLock +bool +DisplayDriverPainter::WriteLock() +{ + return fGraphicsCard->WriteLock(); +} + +// WriteUnlock +void +DisplayDriverPainter::WriteUnlock() { - status_t status = B_ERROR; - - if (Lock()) { - status = fGraphicsCard->SetMode(mode); - if (status >= B_OK) { - fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer()); - // available HW acceleration might have changed - fAvailableHWAccleration = fGraphicsCard->AvailableHWAcceleration(); - status = DisplayDriver::SetMode(mode); - } else { - fprintf(stderr, "DisplayDriverPainter::SetMode() - unsupported " - "mode!\n"); - } - Unlock(); - } - - return status; + fGraphicsCard->WriteUnlock(); } // DumpToFile @@ -1245,127 +1115,6 @@ DisplayDriverPainter::DumpToBitmap() return NULL; } -// SetDPMSMode -status_t -DisplayDriverPainter::SetDPMSMode(const uint32 &state) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->SetDPMSMode(state); - Unlock(); - } - return ret; -} - -// DPMSMode -uint32 -DisplayDriverPainter::DPMSMode() -{ - uint32 mode = 0; - if (Lock()) { - mode = fGraphicsCard->DPMSMode(); - Unlock(); - } - return mode; -} - -// DPMSCapabilities -uint32 -DisplayDriverPainter::DPMSCapabilities() -{ - uint32 caps = 0; - if (Lock()) { - caps = fGraphicsCard->DPMSMode(); - Unlock(); - } - return caps; -} - -// GetDeviceInfo -status_t -DisplayDriverPainter::GetDeviceInfo(accelerant_device_info *info) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->GetDeviceInfo(info); - Unlock(); - } - return ret; -} - -// GetModeList -status_t -DisplayDriverPainter::GetModeList(display_mode **mode_list, uint32 *count) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->GetModeList(mode_list, count); - Unlock(); - } - return ret; -} - -// GetMode -void -DisplayDriverPainter::GetMode(display_mode &mode) -{ - if (Lock()) { - fGraphicsCard->GetMode(&mode); - Unlock(); - } -} - -// GetPixelClockLimits -status_t DisplayDriverPainter::GetPixelClockLimits(display_mode *mode, - uint32 *low, - uint32 *high) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->GetPixelClockLimits(mode, low, high); - Unlock(); - } - return ret; -} - -// GetTimingConstraints -status_t -DisplayDriverPainter::GetTimingConstraints(display_timing_constraints *dtc) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->GetTimingConstraints(dtc); - Unlock(); - } - return ret; -} - -// ProposeMode -status_t -DisplayDriverPainter::ProposeMode(display_mode *candidate, - const display_mode *low, - const display_mode *high) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->ProposeMode(candidate, low, high); - Unlock(); - } - return ret; -} - -// WaitForRetrace -status_t -DisplayDriverPainter::WaitForRetrace(bigtime_t timeout) -{ - status_t ret = B_ERROR; - if (Lock()) { - ret = fGraphicsCard->WaitForRetrace(timeout); - Unlock(); - } - return ret; -} - // _CopyRect BRect DisplayDriverPainter::_CopyRect(BRect src, int32 xOffset, int32 yOffset) const diff --git a/src/servers/app/drawing/DisplayDriverPainter.h b/src/servers/app/drawing/DisplayDriverPainter.h index 5e1f5206a0..e544b57496 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.h +++ b/src/servers/app/drawing/DisplayDriverPainter.h @@ -1,25 +1,8 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2002, Haiku, Inc. +// Copyright (c) 2001-2005, Haiku, Inc. All rights reserved. +// Distributed under the terms of the MIT license. // -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// File Name: DisplayDriver.h +// File Name: DisplayDriverPainter.h // Authors: DarkWyrm // Gabe Yoder // Stephan Aßmus @@ -38,13 +21,15 @@ class Painter; class DisplayDriverPainter : public DisplayDriver { public: - DisplayDriverPainter(); + DisplayDriverPainter(HWInterface* hwInterface); virtual ~DisplayDriverPainter(); // when implementing, be sure to call the inherited version - virtual bool Initialize(); + virtual status_t Initialize(); virtual void Shutdown(); + virtual void Update(); + // clipping for all drawing functions, passing a NULL region // will remove any clipping (drawing allowed everywhere) virtual void ConstrainClippingRegion(BRegion* region); @@ -196,82 +181,26 @@ public: int32 length, const DrawData *d); - virtual void GetBoundingBoxes(const char *string, - int32 count, - font_metric_mode mode, - escapement_delta *delta, - BRect *rectarray, - const DrawData *d); - - virtual void GetEscapements( const char *string, - int32 charcount, - escapement_delta *delta, - escapement_delta *escapements, - escapement_delta *offsets, - const DrawData *d); - - virtual void GetEdges( const char *string, - int32 charcount, - edge_info *edgearray, - const DrawData *d); - - virtual void GetHasGlyphs( const char *string, - int32 charcount, - bool *hasarray); - - virtual void GetTruncatedStrings(const char **instrings, - const int32 &stringcount, - const uint32 &mode, - const float &maxwidth, - char **outstrings); - - // cursor handling - virtual void HideCursor(); - virtual bool IsCursorHidden(); - virtual void MoveCursorTo( const float &x, - const float &y); - virtual void ShowCursor(); - virtual void ObscureCursor(); - virtual void SetCursor(ServerCursor *cursor); - BPoint GetCursorPosition(); - virtual bool IsCursorObscured(bool state); - - - virtual bool Lock(bigtime_t timeout = B_INFINITE_TIMEOUT); + virtual bool Lock(); virtual void Unlock(); - // display mode access - virtual status_t SetMode(const display_mode &mode); - virtual void GetMode(display_mode &mode); + bool WriteLock(); + void WriteUnlock(); - virtual bool DumpToFile(const char *path); + virtual bool DumpToFile( const char *path); virtual ServerBitmap* DumpToBitmap(); - virtual status_t SetDPMSMode(const uint32 &state); - virtual uint32 DPMSMode(); - virtual uint32 DPMSCapabilities(); - virtual status_t GetDeviceInfo(accelerant_device_info *info); - - virtual status_t GetModeList(display_mode **mode_list, - uint32 *count); - - virtual status_t GetPixelClockLimits(display_mode *mode, - uint32 *low, - uint32 *high); - - virtual status_t GetTimingConstraints(display_timing_constraints *dtc); - virtual status_t ProposeMode(display_mode *candidate, - const display_mode *low, - const display_mode *high); - - virtual status_t WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT); - private: - BRect _CopyRect(BRect r, int32 xOffset, int32 yOffset) const; + BRect _CopyRect( BRect r, + int32 xOffset, + int32 yOffset) const; - void _CopyRect(uint8* bits, - uint32 width, uint32 height, uint32 bpr, - int32 xOffset, int32 yOffset) const; + void _CopyRect( uint8* bits, + uint32 width, + uint32 height, + uint32 bpr, + int32 xOffset, + int32 yOffset) const; Painter* fPainter; HWInterface* fGraphicsCard; diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 10ae6a20e7..1ace4b713c 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -15,7 +15,7 @@ // constructor HWInterface::HWInterface(bool doubleBuffered) - : BLocker("hw interface lock"), + : MultiLocker("hw interface lock"), fCursorAreaBackup(NULL), fSoftwareCursorHidden(false), fCursor(NULL), @@ -35,11 +35,18 @@ HWInterface::~HWInterface() delete fUpdateExecutor; } +// Initialize +status_t +HWInterface::Initialize() +{ + return MultiLocker::InitCheck(); +} + // SetCursor void HWInterface::SetCursor(ServerCursor* cursor) { - if (Lock()) { + if (WriteLock()) { if (fCursor != cursor) { BRect oldFrame = _CursorFrame(); delete fCursor; @@ -55,7 +62,7 @@ HWInterface::SetCursor(ServerCursor* cursor) fCursorAreaBackup = NULL; Invalidate(r); } - Unlock(); + WriteUnlock(); } } @@ -63,12 +70,12 @@ HWInterface::SetCursor(ServerCursor* cursor) void HWInterface::SetCursorVisible(bool visible) { - if (Lock()) { + if (WriteLock()) { if (fCursorVisible != visible) { fCursorVisible = visible; Invalidate(_CursorFrame()); } - Unlock(); + WriteUnlock(); } } @@ -77,9 +84,9 @@ bool HWInterface::IsCursorVisible() { bool visible = true; - if (Lock()) { + if (WriteLock()) { visible = fCursorVisible; - Unlock(); + WriteUnlock(); } return visible; } @@ -88,7 +95,7 @@ HWInterface::IsCursorVisible() void HWInterface::MoveCursorTo(const float& x, const float& y) { - if (Lock()) { + if (WriteLock()) { BPoint p(x, y); if (p != fCursorLocation) { BRect oldFrame = _CursorFrame(); @@ -100,7 +107,7 @@ HWInterface::MoveCursorTo(const float& x, const float& y) Invalidate(oldFrame); Invalidate(_CursorFrame()); } - Unlock(); + WriteUnlock(); } } @@ -109,9 +116,9 @@ BPoint HWInterface::GetCursorPosition() { BPoint location; - if (Lock()) { + if (ReadLock()) { location = fCursorLocation; - Unlock(); + ReadUnlock(); } return location; } diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index 92740504d4..a7805e61d5 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -11,10 +11,11 @@ #include #include -#include #include #include +#include "MultiLocker.h" + class RenderingBuffer; class RGBColor; class ServerCursor; @@ -26,12 +27,13 @@ enum { HW_ACC_INVERT_REGION = 0x00000004, }; -class HWInterface : public BLocker { +class HWInterface : public MultiLocker { public: HWInterface(bool doubleBuffered = false); virtual ~HWInterface(); - virtual status_t Initialize() = 0; + // You need to WriteLock + virtual status_t Initialize(); virtual status_t Shutdown() = 0; // screen mode stuff @@ -52,8 +54,8 @@ class HWInterface : public BLocker { virtual status_t WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) = 0; virtual status_t SetDPMSMode(const uint32 &state) = 0; - virtual uint32 DPMSMode() const = 0; - virtual uint32 DPMSCapabilities() const = 0; + virtual uint32 DPMSMode() = 0; + virtual uint32 DPMSCapabilities() = 0; // query for available hardware accleration and perform it // (Initialize() must have been called already) @@ -67,7 +69,7 @@ class HWInterface : public BLocker { const RGBColor& color) {} virtual void InvertRegion(/*const*/ BRegion& region) {} - // cursor handling + // cursor handling (these do their own Read/Write locking) virtual void SetCursor(ServerCursor* cursor); virtual void SetCursorVisible(bool visible); bool IsCursorVisible(); @@ -75,13 +77,14 @@ class HWInterface : public BLocker { const float& y); BPoint GetCursorPosition(); - // frame buffer access + // frame buffer access (you need to ReadLock!) RenderingBuffer* DrawingBuffer() const; virtual RenderingBuffer* FrontBuffer() const = 0; virtual RenderingBuffer* BackBuffer() const = 0; virtual bool IsDoubleBuffered() const; // Invalidate is planned to be used for scheduling an area for updating + // you need to WriteLock! virtual status_t Invalidate(const BRect& frame); // while as CopyBackToFront() actually performs the operation status_t CopyBackToFront(const BRect& frame); @@ -94,6 +97,12 @@ class HWInterface : public BLocker { // then, after all drawing commands that triggered have been caried out, // it shows the cursor again. This approach would have the adventage of // the code not cluttering/slowing down DisplayDriverPainter. + // For now, we hide the cursor for any drawing operation that has + // a bounding box containing the cursor (in DisplayDriverPainter) so + // the cursor hiding is completely transparent from code using DisplayDriverPainter. + // --- + // NOTE: Investigate locking for these! The client code should already hold a + // ReadLock, but maybe these functions should acquire a WriteLock! void HideSoftwareCursor(const BRect& area); void HideSoftwareCursor(); void ShowSoftwareCursor(); diff --git a/src/servers/app/drawing/UpdateQueue.cpp b/src/servers/app/drawing/UpdateQueue.cpp index 639e67bf7d..fdf576f95f 100644 --- a/src/servers/app/drawing/UpdateQueue.cpp +++ b/src/servers/app/drawing/UpdateQueue.cpp @@ -85,7 +85,7 @@ UpdateQueue::_ExecuteUpdates() case B_OK: case B_TIMED_OUT: // execute updates - if (fInterface->LockWithTimeout(5000) >= B_OK) { + if (fInterface->ReadLock()) { int32 count = fUpdateRegion.CountRects(); if (count > 0) { for (int32 i = 0; i < count; i++) { @@ -93,7 +93,7 @@ UpdateQueue::_ExecuteUpdates() } fUpdateRegion.MakeEmpty(); } - fInterface->Unlock(); + fInterface->ReadUnlock(); } break; case B_BAD_SEM_ID: diff --git a/src/servers/app/drawing/ViewHWInterface.cpp b/src/servers/app/drawing/ViewHWInterface.cpp index 8f7efac4ee..7308512992 100644 --- a/src/servers/app/drawing/ViewHWInterface.cpp +++ b/src/servers/app/drawing/ViewHWInterface.cpp @@ -376,8 +376,10 @@ ViewHWInterface::ViewHWInterface() // destructor ViewHWInterface::~ViewHWInterface() { - fWindow->Lock(); - fWindow->Quit(); + if (fWindow) { + fWindow->Lock(); + fWindow->Quit(); + } delete fBackBuffer; delete fFrontBuffer; @@ -401,6 +403,8 @@ ViewHWInterface::Shutdown() status_t ViewHWInterface::SetMode(const display_mode &mode) { + AutoWriteLocker _(this); + status_t ret = B_OK; // prevent from doing the unnecessary if (fBackBuffer && fFrontBuffer @@ -519,8 +523,10 @@ ViewHWInterface::SetMode(const display_mode &mode) void ViewHWInterface::GetMode(display_mode* mode) { - if (mode) + if (mode && ReadLock()) { *mode = fDisplayMode; + ReadUnlock(); + } } // GetDeviceInfo @@ -529,13 +535,17 @@ ViewHWInterface::GetDeviceInfo(accelerant_device_info *info) { // We really don't have to provide anything here because this is strictly // a software-only driver, but we'll have some fun, anyway. - - info->version=100; - sprintf(info->name,"Haiku, Inc. ViewHWInterface"); - sprintf(info->chipset,"Haiku, Inc. Chipset"); - sprintf(info->serial_no,"3.14159265358979323846"); - info->memory=134217728; // 128 MB, not that we really have that much. :) - info->dac_speed=0xFFFFFFFF; // *heh* + if (ReadLock()) { + + info->version=100; + sprintf(info->name,"Haiku, Inc. ViewHWInterface"); + sprintf(info->chipset,"Haiku, Inc. Chipset"); + sprintf(info->serial_no,"3.14159265358979323846"); + info->memory=134217728; // 128 MB, not that we really have that much. :) + info->dac_speed=0xFFFFFFFF; // *heh* + + ReadUnlock(); + } return B_OK; } @@ -544,10 +554,7 @@ ViewHWInterface::GetDeviceInfo(accelerant_device_info *info) status_t ViewHWInterface::GetModeList(display_mode **_modes, uint32 *_count) { - // DEPRECATED: - // NOTE: Originally, I was going to figure out good timing values to be - // returned in each of the modes supported, but I won't bother, being this - // won't be used much longer anyway. + AutoReadLocker _(this); const struct resolution { int32 width, height; } resolutions[] = { {640, 480}, {800, 600}, {1024, 768}, {1152, 864}, {1280, 960}, @@ -613,20 +620,26 @@ ViewHWInterface::ProposeMode(display_mode *candidate, const display_mode *low, c status_t ViewHWInterface::SetDPMSMode(const uint32 &state) { + AutoWriteLocker _(this); + return BScreen().SetDPMS(state); } // DPMSMode uint32 -ViewHWInterface::DPMSMode() const +ViewHWInterface::DPMSMode() { + AutoReadLocker _(this); + return BScreen().DPMSState(); } // DPMSCapabilities uint32 -ViewHWInterface::DPMSCapabilities() const +ViewHWInterface::DPMSCapabilities() { + AutoReadLocker _(this); + return BScreen().DPMSCapabilites(); } diff --git a/src/servers/app/drawing/ViewHWInterface.h b/src/servers/app/drawing/ViewHWInterface.h index 0a162d63f0..32261b5901 100644 --- a/src/servers/app/drawing/ViewHWInterface.h +++ b/src/servers/app/drawing/ViewHWInterface.h @@ -45,8 +45,8 @@ class ViewHWInterface : public HWInterface { virtual status_t WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT); virtual status_t SetDPMSMode(const uint32 &state); - virtual uint32 DPMSMode() const; - virtual uint32 DPMSCapabilities() const; + virtual uint32 DPMSMode(); + virtual uint32 DPMSCapabilities(); // frame buffer access virtual RenderingBuffer* FrontBuffer() const;