Added some root layer locking in ServerWindow.cpp when accessing the layer tree. Moved HWInterface management out of DisplayDriverPainter and into Desktop. Removed all the directly hardware related functions from DisplayDriver API. They just called the same HWInterface functions. Now DisplayDriver is much cleaner and ready for being attached to a yet to be written BitmapHWInterface. Clean up of the display mode stuff in Screen and the View-/AccelerantHWInterface. Frequency is now regarded on Haiku. AccelerantHWInterface::GetModeList now works before SetMode has been called. Added MultiLocker from the sample code. HWInterface uses it now in preparation to being used from multiple instances of DisplayDriver.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13252 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-06-23 23:46:17 +00:00
parent 1b53e8af26
commit 3dcb3b079a
23 changed files with 1289 additions and 1049 deletions

View File

@ -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 <bpmagic@columbus.rr.com>
@ -34,6 +17,7 @@
#include <Accelerant.h>
#include <Font.h>
#include <Locker.h>
#include <Point.h>
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

View File

@ -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));
}

View File

@ -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 <adioanca@cotty.iren.ro>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Class used to encapsulate desktop management
//
//------------------------------------------------------------------------------
#include <stdio.h>
#include <Region.h>
#include <Message.h>
#include <Region.h>
#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.

View File

@ -1,77 +1,68 @@
//------------------------------------------------------------------------------
// 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 <adioanca@cotty.iren.ro>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Class used to encapsulate desktop management
//
//------------------------------------------------------------------------------
#ifndef _DESKTOP_H_
#define _DESKTOP_H_
#include <Locker.h>
#include <List.h>
#include <Menu.h>
#include <InterfaceDefs.h>
#include <List.h>
#include <Locker.h>
#include <Menu.h>
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 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
{
@ -81,37 +72,40 @@ public:
}
// 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;
scroll_bar_info ScrollBarInfo() const;
void SetMenuInfo(const menu_info &info);
menu_info MenuInfo(void) const;
menu_info MenuInfo() const;
void UseFFMouse(const bool &useffm);
bool FFMouseInUse(void) const;
bool FFMouseInUse() const;
void SetFFMouseMode(const mode_mouse &value);
mode_mouse FFMouseMode(void) const;
mode_mouse FFMouseMode() const;
// Debugging methods
void PrintToStream(void);
void PrintToStream();
void PrintVisibleInRootLayerNo(int32 no);
private:
void AddDriver(DisplayDriver *driver);
private:
void _AddGraphicsCard(HWInterface* interface);
BList fWinBorderList;
BLocker fWinLock;
BList fRootLayerList;
RootLayer *fActiveRootLayer;
RootLayer* fActiveRootLayer;
BList fScreenList;
Screen *fActiveScreen;
Screen* fActiveScreen;
scroll_bar_info fScrollBarInfo;
menu_info fMenuInfo;

View File

@ -72,6 +72,7 @@ Server app_server :
# Misc. Sources
DebugInfoManager.cpp
SubWindowList.cpp
MultiLocker.cpp
PicturePlayer.cpp
PNGDump.cpp
RAMLinkMsgReader.cpp

View File

@ -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 <Debug.h>
#include <Errors.h>
#include <OS.h>
//#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
}

View File

@ -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 <OS.h>
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

View File

@ -37,9 +37,9 @@
#include <PortLink.h>
#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<Screen *>(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<Screen *>(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<float>(&evt.where.y);
msg.Read<int32>(&evt.buttons);
GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y);
GetHWInterface()->MoveCursorTo(evt.where.x, evt.where.y);
fLastMousePosition = evt.where;

View File

@ -33,15 +33,16 @@
#include <Locker.h>
#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;

View File

@ -10,42 +10,43 @@
* Axel Dörfler, axeld@pinc-software.de
*/
#include <AppDefs.h>
#include <List.h>
#include <String.h>
#include <Autolock.h>
#include <SysCursor.h>
#include <ColorSet.h>
#include <RGBColor.h>
#include <ScrollBar.h>
#include <Shape.h>
#include <ServerProtocol.h>
#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 <stdio.h>
#include <string.h>
#include <AppDefs.h>
#include <Autolock.h>
#include <ColorSet.h>
#include <List.h>
#include <ScrollBar.h>
#include <ServerProtocol.h>
#include <Shape.h>
#include <String.h>
#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 <syslog.h>
//#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<bool>(&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<status_t>(B_OK);
fLink.Attach<status_t>(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<uint32>(count);
fLink.Attach(modeList, sizeof(display_mode) * count);

View File

@ -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 <adioanca@myrealbox.com>
// Axel Dörfler, axeld@pinc-software.de
// Stephan Aßmus, <superstippi@gmx.de>
// Description: Handles individual screens
//
//------------------------------------------------------------------------------
#include <Accelerant.h>
#include <Point.h>
#include <GraphicsDefs.h>
@ -34,79 +17,121 @@
#include <stdlib.h>
#include <stdio.h>
#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 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));
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;
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;
}

View File

@ -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 <adioanca@myrealbox.com>
// Axel Dörfler, axeld@pinc-software.de
// Stephan Aßmus, <superstippi@gmx.de>
// Description: Handles individual screens
//
//------------------------------------------------------------------------------
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <Accelerant.h>
#include <Point.h>
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; }
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;
private:
int32 fID;
DisplayDriver *fDriver;
DisplayDriver* fDriver;
HWInterface* fHWInterface;
};
#endif /* _SCREEN_H_ */

View File

@ -10,36 +10,34 @@
* Axel Dörfler, axeld@pinc-software.de
*/
#include <AppDefs.h>
#include <Rect.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <View.h>
#include <Message.h>
#include <GraphicsDefs.h>
#include <Message.h>
#include <PortLink.h>
#include <Rect.h>
#include <View.h>
#include <ViewAux.h>
#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<int32>(&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,11 +519,13 @@ 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();
@ -1429,7 +1436,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
// 1) BPoint mouse location
// 2) int32 button state
fLink.Attach<BPoint>(gDesktop->GetDisplayDriver()->GetCursorPosition());
fLink.Attach<BPoint>(gDesktop->GetHWInterface()->GetCursorPosition());
fLink.Attach<int32>(gDesktop->ActiveRootLayer()->Buttons());
fLink.Flush();

View File

@ -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 <new>
#include <stdio.h>
#include <string.h>
#include <Cursor.h>
@ -24,7 +26,6 @@
#include <sys/ioctl.h>
#include <unistd.h>
//#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()
{
status_t ret = HWInterface::Initialize();
if (ret >= B_OK) {
for (int32 i = 1; fCardFD != B_ENTRY_NOT_FOUND; i++) {
fCardFD = OpenGraphicsDevice(i);
fCardFD = _OpenGraphicsDevice(i);
if (fCardFD < 0) {
ATRACE(("Failed to open graphics device\n"));
continue;
}
if (OpenAccelerant(fCardFD) == B_OK)
if (_OpenAccelerant(fCardFD) == B_OK)
break;
close(fCardFD);
// OpenAccelerant() failed, try to open next graphics card
// _OpenAccelerant() failed, try to open next graphics card
}
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,
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;
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);
return B_OK;
} 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);
// 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);
// if (WriteLock()) {
// TODO: update graphics hardware
Unlock();
}
// WriteUnlock();
// }
}
// MoveCursorTo
void
AccelerantHWInterface::MoveCursorTo(const float& x, const float& y)
{
if (Lock()) {
HWInterface::MoveCursorTo(x, y);
// if (WriteLock()) {
// TODO: update graphics hardware
Unlock();
}
// WriteUnlock();
// }
}
// FrontBuffer

View File

@ -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;

View File

@ -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 <bpmagic@columbus.rr.com>
// Authors: DarkWyrm <bpmagic@columbus.rr.com>
// Gabe Yoder <gyoder@stny.rr.com>
// Description: Mostly abstract class which handles all graphics output
// Stephan Aßmus <superstippi@gmx.de>
//
// Description: Abstract class which handles all graphics output
// for the server
//
//------------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#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();
}
}

View File

@ -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 <superstippi@gmx.de>
@ -28,35 +11,19 @@
#include <algo.h>
#include <stack.h>
#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();
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) {
fAvailableHWAccleration = fGraphicsCard->AvailableHWAcceleration();
return DisplayDriver::Initialize();
err = DisplayDriver::Initialize();
}
return false;
WriteUnlock();
}
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)
DisplayDriverPainter::Lock()
{
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;
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()
{
status_t status = B_ERROR;
return fGraphicsCard->WriteLock();
}
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;
// WriteUnlock
void
DisplayDriverPainter::WriteUnlock()
{
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

View File

@ -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 <bpmagic@columbus.rr.com>
// Gabe Yoder <gyoder@stny.rr.com>
// Stephan Aßmus <superstippi@gmx.de>
@ -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;

View File

@ -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;
}

View File

@ -11,10 +11,11 @@
#include <Accelerant.h>
#include <GraphicsCard.h>
#include <Locker.h>
#include <OS.h>
#include <Region.h>
#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();

View File

@ -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:

View File

@ -376,8 +376,10 @@ ViewHWInterface::ViewHWInterface()
// destructor
ViewHWInterface::~ViewHWInterface()
{
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,6 +535,7 @@ 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.
if (ReadLock()) {
info->version=100;
sprintf(info->name,"Haiku, Inc. ViewHWInterface");
@ -537,6 +544,9 @@ ViewHWInterface::GetDeviceInfo(accelerant_device_info *info)
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();
}

View File

@ -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;