* Implemented a new client allocation method: instead of having all bitmaps of

all teams in serveral server areas, and instead of having to eventually clone
  them all several times in BBitmap, we now have one or more areas per team,
  and BBitmap will only clone areas once if needed. As a side effect, this
  method should be magnitudes faster than the previous version.
* This method is also much more secure: instead of putting the allocation
  maintenance structures into those everyone-read-write areas, they are now
  separated, so that faulty applications cannot crash the app_server this
  way anymore. This should fix bug #172.
* Freeing memory is not yet implemented though! (although all memory will
  be freed upon app exit)
* There are now 3 different bitmap allocation strategies: per ClientMemoryAllocator
  (ie. via ServerApp), per area (for overlays, not yet implemented), and using
  malloc()/free() for server-only bitmaps.
* ServerBitmap now deletes its buffers itself.
* Cleaned up BBitmap and BApplication a bit.
* The test environment currently doesn't build anymore, will fix it next.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16826 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-03-18 13:43:26 +00:00
parent 66b7a0f477
commit 9a44fdc97c
21 changed files with 755 additions and 275 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2005, Haiku. * Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -8,12 +8,17 @@
#ifndef _APPLICATION_PRIVATE_H #ifndef _APPLICATION_PRIVATE_H
#define _APPLICATION_PRIVATE_H #define _APPLICATION_PRIVATE_H
#include <Application.h> #include <Application.h>
class BApplication::Private { class BApplication::Private {
public: public:
static inline BPrivate::PortLink *ServerLink() static inline BPrivate::PortLink *ServerLink()
{ return be_app->fServerLink; } { return be_app->fServerLink; }
static inline BPrivate::ServerMemoryAllocator* ServerAllocator()
{ return be_app->fServerAllocator; }
}; };
#endif // _APPLICATION_PRIVATE_H #endif // _APPLICATION_PRIVATE_H

View File

@ -0,0 +1,35 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef SERVER_MEMORY_ALLOCATOR_H
#define SERVER_MEMORY_ALLOCATOR_H
#include <OS.h>
#include <List.h>
namespace BPrivate {
class ServerMemoryAllocator {
public:
ServerMemoryAllocator();
~ServerMemoryAllocator();
status_t InitCheck();
status_t AddArea(area_id serverArea, area_id& _localArea, uint8*& _base);
void RemoveArea(area_id serverArea);
status_t AreaAndBaseFor(area_id serverArea, area_id& area, uint8*& base);
private:
BList fAreas;
};
} // namespace BPrivate
#endif /* SERVER_MEMORY_ALLOCATOR_H */

View File

@ -318,4 +318,12 @@ enum {
AS_LAST_CODE AS_LAST_CODE
}; };
// bitmap allocation types
enum {
kAllocator,
kNewAllocatorArea,
kArea,
kHeap
};
#endif // APP_SERVER_PROTOCOL_H #endif // APP_SERVER_PROTOCOL_H

View File

@ -1,12 +1,12 @@
/* /*
* Copyright 2001-2005, Haiku. * Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
*/ */
#ifndef BITMAP_MANAGER_H_ #ifndef BITMAP_MANAGER_H
#define BITMAP_MANAGER_H_ #define BITMAP_MANAGER_H
#include <GraphicsDefs.h> #include <GraphicsDefs.h>
@ -15,28 +15,25 @@
#include <OS.h> #include <OS.h>
#include <Rect.h> #include <Rect.h>
#include "BGet++.h" class ClientMemoryAllocator;
class ServerBitmap; class ServerBitmap;
class BitmapManager { class BitmapManager {
public: public:
BitmapManager(); BitmapManager();
virtual ~BitmapManager(); virtual ~BitmapManager();
ServerBitmap* CreateBitmap(BRect bounds, color_space space, ServerBitmap* CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
int32 flags, int32 bytesPerRow = -1, color_space space, int32 flags, int32 bytesPerRow = -1,
screen_id screen = B_MAIN_SCREEN_ID); screen_id screen = B_MAIN_SCREEN_ID,
int8* _allocationType = NULL);
void DeleteBitmap(ServerBitmap* bitmap); void DeleteBitmap(ServerBitmap* bitmap);
protected: protected:
BList fBitmapList; BList fBitmapList;
int8* fBuffer;
BLocker fLock; BLocker fLock;
AreaPool fMemPool;
}; };
extern BitmapManager *gBitmapManager; extern BitmapManager *gBitmapManager;
#endif /* BITMAP_MANAGER_H_ */ #endif /* BITMAP_MANAGER_H */

View File

@ -5,8 +5,8 @@
* Authors: * Authors:
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
*/ */
#ifndef _SERVER_BITMAP_H_ #ifndef SERVER_BITMAP_H
#define _SERVER_BITMAP_H_ #define SERVER_BITMAP_H
#include <GraphicsDefs.h> #include <GraphicsDefs.h>
@ -15,6 +15,7 @@
class BitmapManager; class BitmapManager;
class ClientMemoryAllocator;
/*! /*!
\class ServerBitmap ServerBitmap.h \class ServerBitmap ServerBitmap.h
@ -31,11 +32,6 @@ class ServerBitmap {
void Acquire(); void Acquire();
inline area_id Area() const
{ return fArea; }
inline int32 AreaOffset() const
{ return fOffset; }
inline uint8* Bits() const inline uint8* Bits() const
{ return fBuffer; } { return fBuffer; }
inline uint32 BitsLength() const inline uint32 BitsLength() const
@ -59,6 +55,12 @@ class ServerBitmap {
inline int32 Token() const inline int32 Token() const
{ return fToken; } { return fToken; }
inline void* AllocationCookie() const
{ return fAllocationCookie; }
area_id Area() const;
uint32 AreaOffset() const;
//! Does a shallow copy of the bitmap passed to it //! Does a shallow copy of the bitmap passed to it
inline void ShallowCopy(const ServerBitmap *from); inline void ShallowCopy(const ServerBitmap *from);
@ -84,23 +86,19 @@ protected:
virtual ~ServerBitmap(); virtual ~ServerBitmap();
//! used by the BitmapManager //! used by the BitmapManager
inline void _SetArea(area_id ID) // inline void _SetBuffer(void *ptr)
{ fArea = ID; } // { fBuffer = (uint8*)ptr; }
//! used by the BitmapManager
inline void _SetBuffer(void *ptr)
{ fBuffer = (uint8*)ptr; }
bool _Release(); bool _Release();
void _AllocateBuffer(); void _AllocateBuffer();
void _FreeBuffer();
void _HandleSpace(color_space space, void _HandleSpace(color_space space,
int32 bytesperline = -1); int32 bytesperline = -1);
bool fInitialized; bool fInitialized;
area_id fArea; ClientMemoryAllocator* fAllocator;
void* fAllocationCookie;
uint8* fBuffer; uint8* fBuffer;
int32 fReferenceCount; int32 fReferenceCount;
@ -111,7 +109,6 @@ protected:
int32 fFlags; int32 fFlags;
int fBitsPerPixel; int fBitsPerPixel;
int32 fToken; int32 fToken;
int32 fOffset;
}; };
class UtilityBitmap : public ServerBitmap { class UtilityBitmap : public ServerBitmap {
@ -140,7 +137,6 @@ ServerBitmap::ShallowCopy(const ServerBitmap* from)
return; return;
fInitialized = from->fInitialized; fInitialized = from->fInitialized;
fArea = from->fArea;
fBuffer = from->fBuffer; fBuffer = from->fBuffer;
fWidth = from->fWidth; fWidth = from->fWidth;
fHeight = from->fHeight; fHeight = from->fHeight;
@ -149,8 +145,6 @@ ServerBitmap::ShallowCopy(const ServerBitmap* from)
fFlags = from->fFlags; fFlags = from->fFlags;
fBitsPerPixel = from->fBitsPerPixel; fBitsPerPixel = from->fBitsPerPixel;
fToken = from->fToken; fToken = from->fToken;
fOffset = from->fOffset;
} }
#endif // SERVER_BITMAP_H
#endif // _SERVER_BITMAP_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2005, Haiku. * Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -36,6 +36,7 @@
#include <MenuWindow.h> #include <MenuWindow.h>
#include <ObjectLocker.h> #include <ObjectLocker.h>
#include <PortLink.h> #include <PortLink.h>
#include <ServerMemoryAllocator.h>
#include <ServerProtocol.h> #include <ServerProtocol.h>
using namespace BPrivate; using namespace BPrivate;
@ -162,14 +163,14 @@ static void fill_argv_message(BMessage &message);
BApplication::BApplication(const char *signature) BApplication::BApplication(const char *signature)
: BLooper(looper_name_for(signature)) : BLooper(looper_name_for(signature))
{ {
InitData(signature, true, NULL); _InitData(signature, true, NULL);
} }
BApplication::BApplication(const char *signature, status_t *_error) BApplication::BApplication(const char *signature, status_t *_error)
: BLooper(looper_name_for(signature)) : BLooper(looper_name_for(signature))
{ {
InitData(signature, true, _error); _InitData(signature, true, _error);
} }
@ -177,7 +178,7 @@ BApplication::BApplication(const char *signature, bool initGUI,
status_t *_error) status_t *_error)
: BLooper(looper_name_for(signature)) : BLooper(looper_name_for(signature))
{ {
InitData(signature, initGUI, _error); _InitData(signature, initGUI, _error);
} }
@ -189,7 +190,7 @@ BApplication::BApplication(BMessage *data)
const char *signature = NULL; const char *signature = NULL;
data->FindString("mime_sig", &signature); data->FindString("mime_sig", &signature);
InitData(signature, true, NULL); _InitData(signature, true, NULL);
bigtime_t pulseRate; bigtime_t pulseRate;
if (data->FindInt64("_pulse", &pulseRate) == B_OK) if (data->FindInt64("_pulse", &pulseRate) == B_OK)
@ -213,7 +214,7 @@ BApplication::~BApplication()
Lock(); Lock();
// tell all loopers(usually windows) to quit. Also, wait for them. // tell all loopers(usually windows) to quit. Also, wait for them.
quit_all_windows(true); _QuitAllWindows(true);
// unregister from the roster // unregister from the roster
BRoster::Private().RemoveApp(Team()); BRoster::Private().RemoveApp(Team());
@ -242,7 +243,7 @@ BApplication::operator=(const BApplication &rhs)
void void
BApplication::InitData(const char *signature, bool initGUI, status_t *_error) BApplication::_InitData(const char *signature, bool initGUI, status_t *_error)
{ {
DBG(OUT("BApplication::InitData(`%s', %p)\n", signature, _error)); DBG(OUT("BApplication::InitData(`%s', %p)\n", signature, _error));
// check whether there exists already an application // check whether there exists already an application
@ -250,9 +251,9 @@ BApplication::InitData(const char *signature, bool initGUI, status_t *_error)
debugger("2 BApplication objects were created. Only one is allowed."); debugger("2 BApplication objects were created. Only one is allowed.");
fServerLink = new BPrivate::PortLink(-1, -1); fServerLink = new BPrivate::PortLink(-1, -1);
fServerHeap = NULL; fServerAllocator = NULL;
fInitialWorkspace = 0; fInitialWorkspace = 0;
fDraggedMessage = NULL; //fDraggedMessage = NULL;
fReadyToRunCalled = false; fReadyToRunCalled = false;
// initially, there is no pulse // initially, there is no pulse
@ -536,7 +537,7 @@ BApplication::Quit()
bool bool
BApplication::QuitRequested() BApplication::QuitRequested()
{ {
return quit_all_windows(false); return _QuitAllWindows(false);
} }
@ -693,7 +694,7 @@ BApplication::SetCursor(const BCursor *cursor, bool sync)
int32 int32
BApplication::CountWindows() const BApplication::CountWindows() const
{ {
return count_windows(false); return _CountWindows(false);
// we're ignoring menu windows // we're ignoring menu windows
} }
@ -701,7 +702,7 @@ BApplication::CountWindows() const
BWindow * BWindow *
BApplication::WindowAt(int32 index) const BApplication::WindowAt(int32 index) const
{ {
return window_at(index, false); return _WindowAt(index, false);
// we're ignoring menu windows // we're ignoring menu windows
} }
@ -794,7 +795,7 @@ BApplication::DispatchMessage(BMessage *message, BHandler *handler)
switch (message->what) { switch (message->what) {
case B_ARGV_RECEIVED: case B_ARGV_RECEIVED:
do_argv(message); _ArgvReceived(message);
break; break;
case B_REFS_RECEIVED: case B_REFS_RECEIVED:
@ -974,37 +975,13 @@ BApplication::EndRectTracking()
status_t status_t
BApplication::setup_server_heaps() BApplication::_SetupServerAllocator()
{ {
// TODO: implement? fServerAllocator = new (std::nothrow) BPrivate::ServerMemoryAllocator();
if (fServerAllocator == NULL)
return B_NO_MEMORY;
// We may not need to implement this function or the XX_offs_to_ptr functions. return fServerAllocator->InitCheck();
// R5 sets up a couple of areas for various tasks having to do with the
// app_server. Currently (7/29/04), the R1 app_server does not do this and
// may never do this unless a significant need is found for it. --DW
return B_OK;
}
void *
BApplication::rw_offs_to_ptr(uint32 offset)
{
return NULL; // TODO: implement
}
void *
BApplication::ro_offs_to_ptr(uint32 offset)
{
return NULL; // TODO: implement
}
void *
BApplication::global_ro_offs_to_ptr(uint32 offset)
{
return NULL; // TODO: implement
} }
@ -1012,11 +989,11 @@ status_t
BApplication::_InitGUIContext() BApplication::_InitGUIContext()
{ {
// An app_server connection is necessary for a lot of stuff, so get that first. // An app_server connection is necessary for a lot of stuff, so get that first.
status_t error = connect_to_app_server(); status_t error = _ConnectToServer();
if (error != B_OK) if (error != B_OK)
return error; return error;
error = setup_server_heaps(); error = _SetupServerAllocator();
if (error != B_OK) if (error != B_OK)
return error; return error;
@ -1030,6 +1007,7 @@ BApplication::_InitGUIContext()
B_CURSOR_SYSTEM_DEFAULT = new BCursor(B_HAND_CURSOR); B_CURSOR_SYSTEM_DEFAULT = new BCursor(B_HAND_CURSOR);
B_CURSOR_I_BEAM = new BCursor(B_I_BEAM_CURSOR); B_CURSOR_I_BEAM = new BCursor(B_I_BEAM_CURSOR);
// TODO: would be nice to get the workspace at launch time from the registrar
fInitialWorkspace = current_workspace(); fInitialWorkspace = current_workspace();
return B_OK; return B_OK;
@ -1037,7 +1015,7 @@ BApplication::_InitGUIContext()
status_t status_t
BApplication::connect_to_app_server() BApplication::_ConnectToServer()
{ {
port_id serverPort = find_port(SERVER_PORT_NAME); port_id serverPort = find_port(SERVER_PORT_NAME);
if (serverPort < B_OK) if (serverPort < B_OK)
@ -1096,7 +1074,7 @@ BApplication::connect_to_app_server()
return B_OK; return B_OK;
} }
#if 0
void void
BApplication::send_drag(BMessage *message, int32 vs_token, BPoint offset, BApplication::send_drag(BMessage *message, int32 vs_token, BPoint offset,
BRect dragRect, BHandler *replyTo) BRect dragRect, BHandler *replyTo)
@ -1118,10 +1096,10 @@ BApplication::write_drag(_BSession_ *session, BMessage *message)
{ {
// TODO: implement // TODO: implement
} }
#endif
bool bool
BApplication::window_quit_loop(bool quitFilePanels, bool force) BApplication::_WindowQuitLoop(bool quitFilePanels, bool force)
{ {
BList looperList; BList looperList;
{ {
@ -1173,7 +1151,7 @@ BApplication::window_quit_loop(bool quitFilePanels, bool force)
bool bool
BApplication::quit_all_windows(bool force) BApplication::_QuitAllWindows(bool force)
{ {
AssertLocked(); AssertLocked();
@ -1181,9 +1159,9 @@ BApplication::quit_all_windows(bool force)
// allowed to lock the application - which would cause a deadlock // allowed to lock the application - which would cause a deadlock
Unlock(); Unlock();
bool quit = window_quit_loop(false, force); bool quit = _WindowQuitLoop(false, force);
if (!quit) if (!quit)
quit = window_quit_loop(true, force); quit = _WindowQuitLoop(true, force);
Lock(); Lock();
@ -1192,12 +1170,8 @@ BApplication::quit_all_windows(bool force)
void void
BApplication::do_argv(BMessage *message) BApplication::_ArgvReceived(BMessage *message)
{ {
// TODO: Consider renaming this function to something
// a bit more descriptive, like "handle_argv_message()",
// or "HandleArgvMessage()"
ASSERT(message != NULL); ASSERT(message != NULL);
// build the argv vector // build the argv vector
@ -1242,11 +1216,11 @@ BApplication::InitialWorkspace()
int32 int32
BApplication::count_windows(bool includeMenus) const BApplication::_CountWindows(bool includeMenus) const
{ {
int32 count = 0; int32 count = 0;
BList windowList; BList windowList;
if (get_window_list(&windowList, includeMenus) == B_OK) if (_GetWindowList(&windowList, includeMenus) == B_OK)
count = windowList.CountItems(); count = windowList.CountItems();
return count; return count;
@ -1254,11 +1228,11 @@ BApplication::count_windows(bool includeMenus) const
BWindow * BWindow *
BApplication::window_at(uint32 index, bool includeMenus) const BApplication::_WindowAt(uint32 index, bool includeMenus) const
{ {
BList windowList; BList windowList;
BWindow *window = NULL; BWindow *window = NULL;
if (get_window_list(&windowList, includeMenus) == B_OK) { if (_GetWindowList(&windowList, includeMenus) == B_OK) {
if ((int32)index < windowList.CountItems()) if ((int32)index < windowList.CountItems())
window = static_cast<BWindow *>(windowList.ItemAt(index)); window = static_cast<BWindow *>(windowList.ItemAt(index));
} }
@ -1268,7 +1242,7 @@ BApplication::window_at(uint32 index, bool includeMenus) const
status_t status_t
BApplication::get_window_list(BList *list, bool includeMenus) const BApplication::_GetWindowList(BList *list, bool includeMenus) const
{ {
ASSERT(list); ASSERT(list);
@ -1291,15 +1265,11 @@ BApplication::get_window_list(BList *list, bool includeMenus) const
} }
int32 // #pragma mark -
BApplication::async_quit_entry(void *data)
{
return 0; // TODO: implement? not implemented?
}
// check_app_signature /*!
/*! \brief Checks whether the supplied string is a valid application signature. \brief Checks whether the supplied string is a valid application signature.
An error message is printed, if the string is no valid app signature. An error message is printed, if the string is no valid app signature.
@ -1308,9 +1278,7 @@ BApplication::async_quit_entry(void *data)
- \c B_OK: \a signature is a valid app signature. - \c B_OK: \a signature is a valid app signature.
- \c B_BAD_VALUE: \a signature is \c NULL or no valid app signature. - \c B_BAD_VALUE: \a signature is \c NULL or no valid app signature.
*/ */
static status_t
static
status_t
check_app_signature(const char *signature) check_app_signature(const char *signature)
{ {
bool isValid = false; bool isValid = false;
@ -1328,17 +1296,15 @@ check_app_signature(const char *signature)
} }
// looper_name_for /*!
/*! \brief Returns the looper name for a given signature. \brief Returns the looper name for a given signature.
Normally this is "AppLooperPort", but in case of the registrar a Normally this is "AppLooperPort", but in case of the registrar a
special name. special name.
\return The looper name. \return The looper name.
*/ */
static const char *
static
const char *
looper_name_for(const char *signature) looper_name_for(const char *signature)
{ {
if (signature && !strcasecmp(signature, kRegistrarSignature)) if (signature && !strcasecmp(signature, kRegistrarSignature))
@ -1347,12 +1313,10 @@ looper_name_for(const char *signature)
} }
// fill_argv_message /*!
/*! \brief Fills the passed BMessage with B_ARGV_RECEIVED infos. \brief Fills the passed BMessage with B_ARGV_RECEIVED infos.
*/ */
static void
static
void
fill_argv_message(BMessage &message) fill_argv_message(BMessage &message)
{ {
message.what = B_ARGV_RECEIVED; message.what = B_ARGV_RECEIVED;

View File

@ -18,8 +18,8 @@ if $(RUN_WITHOUT_APP_SERVER) != 0 {
} }
UsePrivateHeaders shared app interface ; UsePrivateHeaders shared app interface ;
UsePrivateHeaders [ FDirName kernel util ] ; # For KMessage.h
UsePrivateHeaders [ FDirName servers app ] ; UsePrivateHeaders [ FDirName servers app ] ;
UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
SetSubDirSupportedPlatforms haiku libbe_test ; SetSubDirSupportedPlatforms haiku libbe_test ;
@ -56,6 +56,7 @@ MergeObject <libbe>app_kit.o :
Server.cpp Server.cpp
ServerLink.cpp ServerLink.cpp
ServerMemIO.cpp ServerMemIO.cpp
ServerMemoryAllocator.cpp
TokenSpace.cpp TokenSpace.cpp
TypeConstants.cpp TypeConstants.cpp
; ;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2005, Haiku Inc. All rights reserved. * Copyright 2005-2006, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -18,7 +18,6 @@
#include <AppMisc.h> #include <AppMisc.h>
#include <BlockCache.h> #include <BlockCache.h>
#include <Entry.h> #include <Entry.h>
#include <KMessage.h>
#include <Messenger.h> #include <Messenger.h>
#include <MessengerPrivate.h> #include <MessengerPrivate.h>
#include <Path.h> #include <Path.h>
@ -26,6 +25,7 @@
#include <Rect.h> #include <Rect.h>
#include <String.h> #include <String.h>
#include <TokenSpace.h> #include <TokenSpace.h>
#include <util/KMessage.h>
#include <ctype.h> #include <ctype.h>
#include <malloc.h> #include <malloc.h>

View File

@ -0,0 +1,123 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
/*!
Note, this class don't provide any locking whatsoever - you are
supposed to have a BPrivate::AppServerLink object around which
does the necessary locking.
However, this is not enforced in the methods here, you have to
take care for yourself!
*/
#include "ServerMemoryAllocator.h"
#include <syscalls.h>
#include <new>
namespace BPrivate {
struct area_mapping {
area_id server_area;
area_id local_area;
uint8* local_base;
};
ServerMemoryAllocator::ServerMemoryAllocator()
:
fAreas(4)
{
}
ServerMemoryAllocator::~ServerMemoryAllocator()
{
for (int32 i = fAreas.CountItems(); i-- > 0;) {
area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
delete_area(mapping->local_area);
delete mapping;
}
}
status_t
ServerMemoryAllocator::InitCheck()
{
return B_OK;
}
status_t
ServerMemoryAllocator::AddArea(area_id serverArea, area_id& _area, uint8*& _base)
{
area_mapping* mapping = new (std::nothrow) area_mapping;
if (mapping == NULL || !fAreas.AddItem(mapping)) {
delete mapping;
return B_NO_MEMORY;
}
// reserve 128 MB of space for the area
void* base = (void*)0x60000000;
status_t status = _kern_reserve_heap_address_range((addr_t*)&base,
B_BASE_ADDRESS, 128 * 1024 * 1024);
mapping->local_area = clone_area("server_memory", &base,
status == B_OK ? B_EXACT_ADDRESS : B_BASE_ADDRESS,
B_READ_AREA | B_WRITE_AREA, serverArea);
if (mapping->local_area < B_OK) {
status = mapping->local_area;
delete mapping;
return status;
}
mapping->server_area = serverArea;
mapping->local_base = (uint8*)base;
_area = mapping->local_area;
_base = mapping->local_base;
return B_OK;
}
void
ServerMemoryAllocator::RemoveArea(area_id serverArea)
{
for (int32 i = fAreas.CountItems(); i-- > 0;) {
area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
if (mapping->server_area == serverArea) {
// we found the area we should remove
delete_area(mapping->local_area);
delete mapping;
break;
}
}
}
status_t
ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area, uint8*& _base)
{
for (int32 i = fAreas.CountItems(); i-- > 0;) {
area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
if (mapping->server_area == serverArea) {
_area = mapping->local_area;
_base = mapping->local_base;
return B_OK;
}
}
return B_ERROR;
}
} // namespace BPrivate

View File

@ -1,22 +1,20 @@
/* /*
* Copyright 2001-2005, Haiku Inc. * Copyright 2001-2006, Haiku Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Ingo Weinhold (bonefish@users.sf.net) * Ingo Weinhold (bonefish@users.sf.net)
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de
*/ */
/** BBitmap objects represent off-screen windows that /*!
* contain bitmap data. BBitmap objects represent off-screen windows that
*/ contain bitmap data.
*/
#include <algorithm> #include "ColorConversion.h"
#include <limits.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <Application.h> #include <Application.h>
#include <Bitmap.h> #include <Bitmap.h>
@ -25,11 +23,16 @@
#include <View.h> #include <View.h>
#include <Window.h> #include <Window.h>
#include "ColorConversion.h" #include <ApplicationPrivate.h>
// Includes to be able to talk to the app_server
#include <ServerProtocol.h>
#include <AppServerLink.h> #include <AppServerLink.h>
#include <ServerMemoryAllocator.h>
#include <ServerProtocol.h>
#include <algorithm>
#include <limits.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
// get_raw_bytes_per_row // get_raw_bytes_per_row
@ -112,7 +115,9 @@ get_bytes_per_row(color_space colorSpace, int32 width)
} }
// constructor // #pragma mark -
/*! \brief Creates and initializes a BBitmap. /*! \brief Creates and initializes a BBitmap.
\param bounds The bitmap dimensions. \param bounds The bitmap dimensions.
\param flags Creation flags. \param flags Creation flags.
@ -124,7 +129,7 @@ get_bytes_per_row(color_space colorSpace, int32 width)
*/ */
BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace, BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
int32 bytesPerRow, screen_id screenID) int32 bytesPerRow, screen_id screenID)
: fBasePtr(NULL), : fBasePointer(NULL),
fSize(0), fSize(0),
fColorSpace(B_NO_COLOR_SPACE), fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1), fBounds(0, 0, -1, -1),
@ -133,11 +138,11 @@ BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
fServerToken(-1), fServerToken(-1),
fAreaOffset(-1), fAreaOffset(-1),
fArea(-1), fArea(-1),
fOrigArea(-1), fServerArea(-1),
fFlags(0), fFlags(0),
fInitError(B_NO_INIT) fInitError(B_NO_INIT)
{ {
InitObject(bounds, colorSpace, flags, bytesPerRow, screenID); _InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
} }
// constructor // constructor
@ -152,7 +157,7 @@ BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
*/ */
BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews, BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
bool needsContiguous) bool needsContiguous)
: fBasePtr(NULL), : fBasePointer(NULL),
fSize(0), fSize(0),
fColorSpace(B_NO_COLOR_SPACE), fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1), fBounds(0, 0, -1, -1),
@ -161,13 +166,13 @@ BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
fServerToken(-1), fServerToken(-1),
fAreaOffset(-1), fAreaOffset(-1),
fArea(-1), fArea(-1),
fOrigArea(-1), fServerArea(-1),
fFlags(0), fFlags(0),
fInitError(B_NO_INIT) fInitError(B_NO_INIT)
{ {
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0) int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0); | (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW, _InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW,
B_MAIN_SCREEN_ID); B_MAIN_SCREEN_ID);
} }
@ -183,7 +188,7 @@ BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
*/ */
BBitmap::BBitmap(const BBitmap *source, bool acceptsViews, BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
bool needsContiguous) bool needsContiguous)
: fBasePtr(NULL), : fBasePointer(NULL),
fSize(0), fSize(0),
fColorSpace(B_NO_COLOR_SPACE), fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1), fBounds(0, 0, -1, -1),
@ -192,14 +197,14 @@ BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
fServerToken(-1), fServerToken(-1),
fAreaOffset(-1), fAreaOffset(-1),
fArea(-1), fArea(-1),
fOrigArea(-1), fServerArea(-1),
fFlags(0), fFlags(0),
fInitError(B_NO_INIT) fInitError(B_NO_INIT)
{ {
if (source && source->IsValid()) { if (source && source->IsValid()) {
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0) int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0); | (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
InitObject(source->Bounds(), source->ColorSpace(), flags, _InitObject(source->Bounds(), source->ColorSpace(), flags,
source->BytesPerRow(), B_MAIN_SCREEN_ID); source->BytesPerRow(), B_MAIN_SCREEN_ID);
if (InitCheck() == B_OK) if (InitCheck() == B_OK)
memcpy(Bits(), source->Bits(), BytesPerRow()); memcpy(Bits(), source->Bits(), BytesPerRow());
@ -212,7 +217,7 @@ BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
BBitmap::~BBitmap() BBitmap::~BBitmap()
{ {
delete fWindow; delete fWindow;
CleanUp(); _CleanUp();
} }
// unarchiving constructor // unarchiving constructor
@ -221,7 +226,7 @@ BBitmap::~BBitmap()
*/ */
BBitmap::BBitmap(BMessage *data) BBitmap::BBitmap(BMessage *data)
: BArchivable(data), : BArchivable(data),
fBasePtr(NULL), fBasePointer(NULL),
fSize(0), fSize(0),
fColorSpace(B_NO_COLOR_SPACE), fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1), fBounds(0, 0, -1, -1),
@ -230,7 +235,7 @@ BBitmap::BBitmap(BMessage *data)
fServerToken(-1), fServerToken(-1),
fAreaOffset(-1), fAreaOffset(-1),
fArea(-1), fArea(-1),
fOrigArea(-1), fServerArea(-1),
fFlags(0), fFlags(0),
fInitError(B_NO_INIT) fInitError(B_NO_INIT)
{ {
@ -246,14 +251,14 @@ BBitmap::BBitmap(BMessage *data)
int32 rowBytes = 0; int32 rowBytes = 0;
data->FindInt32("_rowbytes", &rowBytes); data->FindInt32("_rowbytes", &rowBytes);
InitObject(bounds, cspace, flags, rowBytes, B_MAIN_SCREEN_ID); _InitObject(bounds, cspace, flags, rowBytes, B_MAIN_SCREEN_ID);
if (data->HasData("_data", B_RAW_TYPE) && InitCheck() == B_OK) { if (data->HasData("_data", B_RAW_TYPE) && InitCheck() == B_OK) {
AssertPtr(); _AssertPointer();
ssize_t size = 0; ssize_t size = 0;
const void *buffer; const void *buffer;
if (data->FindData("_data", B_RAW_TYPE, &buffer, &size) == B_OK) if (data->FindData("_data", B_RAW_TYPE, &buffer, &size) == B_OK)
memcpy(fBasePtr, buffer, size); memcpy(fBasePointer, buffer, size);
} }
if (fFlags & B_BITMAP_ACCEPTS_VIEWS) { if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
@ -311,8 +316,8 @@ BBitmap::Archive(BMessage *data, bool deep) const
// true and it does save all formats as B_RAW_TYPE and it does save // true and it does save all formats as B_RAW_TYPE and it does save
// the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to
// the BeBook) // the BeBook)
const_cast<BBitmap *>(this)->AssertPtr(); const_cast<BBitmap *>(this)->_AssertPointer();
data->AddData("_data", B_RAW_TYPE, fBasePtr, fSize); data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize);
} }
return B_OK; return B_OK;
@ -363,7 +368,7 @@ BBitmap::UnlockBits()
area_id area_id
BBitmap::Area() const BBitmap::Area() const
{ {
const_cast<BBitmap *>(this)->AssertPtr(); const_cast<BBitmap *>(this)->_AssertPointer();
return fArea; return fArea;
} }
@ -374,8 +379,8 @@ BBitmap::Area() const
void * void *
BBitmap::Bits() const BBitmap::Bits() const
{ {
const_cast<BBitmap *>(this)->AssertPtr(); const_cast<BBitmap *>(this)->_AssertPointer();
return fBasePtr; return (void*)fBasePointer;
} }
// BitsLength // BitsLength
@ -501,7 +506,7 @@ status_t
BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset, BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
color_space colorSpace) color_space colorSpace)
{ {
AssertPtr(); _AssertPointer();
if (InitCheck() != B_OK) if (InitCheck() != B_OK)
return B_NO_INIT; return B_NO_INIT;
@ -513,7 +518,7 @@ BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
if (bpr < 0) if (bpr < 0)
bpr = get_bytes_per_row(colorSpace, width); bpr = get_bytes_per_row(colorSpace, width);
return BPrivate::ConvertBits(data, (uint8*)fBasePtr + offset, length, return BPrivate::ConvertBits(data, (uint8*)fBasePointer + offset, length,
fSize - offset, bpr, fBytesPerRow, colorSpace, fColorSpace, width, fSize - offset, bpr, fBytesPerRow, colorSpace, fColorSpace, width,
fBounds.IntegerHeight() + 1); fBounds.IntegerHeight() + 1);
} }
@ -545,7 +550,7 @@ status_t
BBitmap::ImportBits(const void *data, int32 length, int32 bpr, BBitmap::ImportBits(const void *data, int32 length, int32 bpr,
color_space colorSpace, BPoint from, BPoint to, int32 width, int32 height) color_space colorSpace, BPoint from, BPoint to, int32 width, int32 height)
{ {
AssertPtr(); _AssertPointer();
if (InitCheck() != B_OK) if (InitCheck() != B_OK)
return B_NO_INIT; return B_NO_INIT;
@ -556,7 +561,7 @@ BBitmap::ImportBits(const void *data, int32 length, int32 bpr,
if (bpr < 0) if (bpr < 0)
bpr = get_bytes_per_row(colorSpace, fBounds.IntegerWidth() + 1); bpr = get_bytes_per_row(colorSpace, fBounds.IntegerWidth() + 1);
return BPrivate::ConvertBits(data, fBasePtr, length, fSize, bpr, return BPrivate::ConvertBits(data, fBasePointer, length, fSize, bpr,
fBytesPerRow, colorSpace, fColorSpace, from, to, width, height); fBytesPerRow, colorSpace, fColorSpace, from, to, width, height);
} }
@ -783,6 +788,7 @@ BBitmap::operator=(const BBitmap &)
return *this; return *this;
} }
#if 0
// get_shared_pointer // get_shared_pointer
/*! \brief ??? /*! \brief ???
*/ */
@ -791,17 +797,15 @@ BBitmap::get_shared_pointer() const
{ {
return NULL; // not implemented return NULL; // not implemented
} }
#endif
// get_server_token
/*! \brief ???
*/
int32 int32
BBitmap::get_server_token() const BBitmap::_ServerToken() const
{ {
return fServerToken; return fServerToken;
} }
// InitObject
/*! \brief Initializes the bitmap. /*! \brief Initializes the bitmap.
\param bounds The bitmap dimensions. \param bounds The bitmap dimensions.
\param colorSpace The bitmap's color space. \param colorSpace The bitmap's color space.
@ -812,7 +816,7 @@ BBitmap::get_server_token() const
\param screenID ??? \param screenID ???
*/ */
void void
BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags, BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int32 bytesPerRow, screen_id screenID) int32 bytesPerRow, screen_id screenID)
{ {
//printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n", //printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n",
@ -826,7 +830,7 @@ BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
flags |= B_BITMAP_NO_SERVER_LINK; flags |= B_BITMAP_NO_SERVER_LINK;
#endif // RUN_WITHOUT_APP_SERVER #endif // RUN_WITHOUT_APP_SERVER
CleanUp(); _CleanUp();
// check params // check params
if (!bounds.IsValid() || !bitmaps_support_space(colorSpace, NULL)) { if (!bounds.IsValid() || !bitmaps_support_space(colorSpace, NULL)) {
@ -857,8 +861,8 @@ BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int32 size = bytesPerRow * (bounds.IntegerHeight() + 1); int32 size = bytesPerRow * (bounds.IntegerHeight() + 1);
if (flags & B_BITMAP_NO_SERVER_LINK) { if (flags & B_BITMAP_NO_SERVER_LINK) {
fBasePtr = malloc(size); fBasePointer = (uint8*)malloc(size);
if (fBasePtr) { if (fBasePointer) {
fSize = size; fSize = size;
fColorSpace = colorSpace; fColorSpace = colorSpace;
fBounds = bounds; fBounds = bounds;
@ -883,34 +887,51 @@ BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
link.Attach<int32>(bytesPerRow); link.Attach<int32>(bytesPerRow);
link.Attach<int32>(screenID.id); link.Attach<int32>(screenID.id);
// Reply Data:
// 1) int32 server token
// 2) area_id id of the area in which the bitmap data resides
// 3) int32 area pointer offset used to calculate fBasePtr
error = B_ERROR;
if (link.FlushWithReply(error) == B_OK && error == B_OK) { if (link.FlushWithReply(error) == B_OK && error == B_OK) {
// server side success // server side success
// Get token // Get token
link.Read<int32>(&fServerToken); link.Read<int32>(&fServerToken);
link.Read<area_id>(&fOrigArea);
link.Read<int32>(&fAreaOffset); int8 allocationType;
link.Read<int8>(&allocationType);
if (fOrigArea >= B_OK) {
if (allocationType == kArea) {
// TODO: implement me (server-side as well), needed for overlays
fServerArea = B_ERROR;
fAreaOffset = -1;
// that signals the cleanup code to delete our area
fBasePointer = NULL;
} else {
link.Read<area_id>(&fServerArea);
link.Read<int32>(&fAreaOffset);
BPrivate::ServerMemoryAllocator* allocator
= BApplication::Private::ServerAllocator();
if (allocationType == kNewAllocatorArea)
error = allocator->AddArea(fServerArea, fArea, fBasePointer);
else {
error = allocator->AreaAndBaseFor(fServerArea, fArea, fBasePointer);
if (error == B_OK)
fBasePointer += fAreaOffset;
}
}
if (fServerArea >= B_OK) {
fSize = size; fSize = size;
fColorSpace = colorSpace; fColorSpace = colorSpace;
fBounds = bounds; fBounds = bounds;
fBytesPerRow = bytesPerRow; fBytesPerRow = bytesPerRow;
fFlags = flags; fFlags = flags;
} else } else
error = fOrigArea; error = fServerArea;
} }
if (error < B_OK) { if (error < B_OK) {
fBasePtr = NULL; fBasePointer = NULL;
fServerToken = -1; fServerToken = -1;
fArea = -1; fArea = -1;
fOrigArea = -1; fServerArea = -1;
fAreaOffset = -1; fAreaOffset = -1;
// NOTE: why not "0" in case of error? // NOTE: why not "0" in case of error?
fFlags = flags; fFlags = flags;
@ -940,13 +961,13 @@ BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
informs the server to do so as well (if needed). informs the server to do so as well (if needed).
*/ */
void void
BBitmap::CleanUp() BBitmap::_CleanUp()
{ {
if (fBasePtr == NULL) if (fBasePointer == NULL)
return; return;
if (fFlags & B_BITMAP_NO_SERVER_LINK) { if (fFlags & B_BITMAP_NO_SERVER_LINK) {
free(fBasePtr); free(fBasePointer);
} else { } else {
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
// AS_DELETE_BITMAP: // AS_DELETE_BITMAP:
@ -955,32 +976,31 @@ BBitmap::CleanUp()
link.StartMessage(AS_DELETE_BITMAP); link.StartMessage(AS_DELETE_BITMAP);
link.Attach<int32>(fServerToken); link.Attach<int32>(fServerToken);
link.Flush(); link.Flush();
if (fArea >= 0) // TODO: we may want to delete parts of the server memory areas here!
if (fAreaOffset == -1) {
// we own that area, so we have to delete it
delete_area(fArea); delete_area(fArea);
}
fArea = -1; fArea = -1;
fServerToken = -1; fServerToken = -1;
fAreaOffset = -1; fAreaOffset = -1;
} }
fBasePtr = NULL; fBasePointer = NULL;
} }
void void
BBitmap::AssertPtr() BBitmap::_AssertPointer()
{ {
if (fBasePtr == NULL && fAreaOffset != -1 && InitCheck() == B_OK) { if (fBasePointer == NULL && fServerArea >= B_OK && fAreaOffset == -1) {
// Offset was saved into "fArea" as we can't add // We lazily clone our own areas - if the bitmap is part of the usual
// any member variable due to Binary compatibility // server memory area, or is a B_BITMAP_NO_SERVER_LINK bitmap, it already
// Get the area in which the data resides // has its data.
fArea = clone_area("shared bitmap area", (void **)&fBasePtr, B_ANY_ADDRESS, fArea = clone_area("shared bitmap area", (void **)&fBasePointer, B_ANY_ADDRESS,
B_READ_AREA | B_WRITE_AREA, fOrigArea); B_READ_AREA | B_WRITE_AREA, fServerArea);
if (fArea >= B_OK) {
// Jump to the location in the area
fBasePtr = (int8 *)fBasePtr + fAreaOffset;
} else
fBasePtr = NULL;
} }
} }

View File

@ -338,7 +338,7 @@ BPrivateScreen::ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bounds)
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
link.StartMessage(AS_READ_BITMAP); link.StartMessage(AS_READ_BITMAP);
link.Attach<int32>(bitmap->get_server_token()); link.Attach<int32>(bitmap->_ServerToken());
link.Attach<bool>(drawCursor); link.Attach<bool>(drawCursor);
link.Attach<BRect>(rect); link.Attach<BRect>(rect);

View File

@ -1331,7 +1331,7 @@ BView::DragMessage(BMessage *message, BBitmap *image,
message->Flatten(buffer, bufferSize); message->Flatten(buffer, bufferSize);
fOwner->fLink->StartMessage(AS_LAYER_DRAG_IMAGE); fOwner->fLink->StartMessage(AS_LAYER_DRAG_IMAGE);
fOwner->fLink->Attach<int32>(image->get_server_token()); fOwner->fLink->Attach<int32>(image->_ServerToken());
fOwner->fLink->Attach<int32>((int32)dragMode); fOwner->fLink->Attach<int32>((int32)dragMode);
fOwner->fLink->Attach<BPoint>(offset); fOwner->fLink->Attach<BPoint>(offset);
fOwner->fLink->Attach<int32>(bufferSize); fOwner->fLink->Attach<int32>(bufferSize);
@ -2235,7 +2235,7 @@ BView::DrawBitmapAsync(const BBitmap *bitmap, BRect srcRect, BRect dstRect)
check_lock(); check_lock();
fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP); fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP);
fOwner->fLink->Attach<int32>(bitmap->get_server_token()); fOwner->fLink->Attach<int32>(bitmap->_ServerToken());
fOwner->fLink->Attach<BRect>(dstRect); fOwner->fLink->Attach<BRect>(dstRect);
fOwner->fLink->Attach<BRect>(srcRect); fOwner->fLink->Attach<BRect>(srcRect);
@ -2268,7 +2268,7 @@ BView::DrawBitmapAsync(const BBitmap *bitmap, BPoint where)
check_lock(); check_lock();
fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP); fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP);
fOwner->fLink->Attach<int32>(bitmap->get_server_token()); fOwner->fLink->Attach<int32>(bitmap->_ServerToken());
BRect src = bitmap->Bounds(); BRect src = bitmap->Bounds();
BRect dst = src.OffsetToCopy(where); BRect dst = src.OffsetToCopy(where);
fOwner->fLink->Attach<BRect>(dst); fOwner->fLink->Attach<BRect>(dst);
@ -4320,7 +4320,7 @@ BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect,
if (!do_owner_check()) if (!do_owner_check())
return B_ERROR; return B_ERROR;
int32 serverToken = bitmap ? bitmap->get_server_token() : -1; int32 serverToken = bitmap ? bitmap->_ServerToken() : -1;
fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_BITMAP); fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_BITMAP);
fOwner->fLink->Attach<int32>(serverToken); fOwner->fLink->Attach<int32>(serverToken);

View File

@ -1,18 +1,19 @@
/* /*
* Copyright 2001-2005, Haiku. * Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
*/ */
/** Handler for allocating and freeing area memory for BBitmaps /*!
* on the server side. Utilizes the BGET pool allocator. Handler for allocating and freeing area memory for BBitmaps
* on the server side. Utilizes the BGET pool allocator.
* Whenever a ServerBitmap associated with a client-side BBitmap needs to be
* created or destroyed, the BitmapManager needs to handle it. It takes care of Whenever a ServerBitmap associated with a client-side BBitmap needs to be
* all memory management related to them. created or destroyed, the BitmapManager needs to handle it. It takes care of
*/ all memory management related to them.
*/
#include <new> #include <new>
@ -23,7 +24,9 @@
#include <Bitmap.h> #include <Bitmap.h>
#include "BitmapManager.h" #include "BitmapManager.h"
#include "ClientMemoryAllocator.h"
#include "ServerBitmap.h" #include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerTokenSpace.h" #include "ServerTokenSpace.h"
using std::nothrow; using std::nothrow;
@ -40,9 +43,7 @@ BitmapManager *gBitmapManager = NULL;
BitmapManager::BitmapManager() BitmapManager::BitmapManager()
: :
fBitmapList(1024), fBitmapList(1024),
fBuffer(NULL), fLock("BitmapManager Lock")
fLock("BitmapManager Lock"),
fMemPool("bitmap pool", BITMAP_AREA_SIZE)
{ {
} }
@ -53,7 +54,9 @@ BitmapManager::~BitmapManager()
int32 count = fBitmapList.CountItems(); int32 count = fBitmapList.CountItems();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
if (ServerBitmap* bitmap = (ServerBitmap*)fBitmapList.ItemAt(i)) { if (ServerBitmap* bitmap = (ServerBitmap*)fBitmapList.ItemAt(i)) {
fMemPool.ReleaseBuffer(bitmap->fBuffer); if (bitmap->AllocationCookie() != NULL)
debugger("We're not supposed to keep our cookies...");
delete bitmap; delete bitmap;
} }
} }
@ -70,8 +73,9 @@ BitmapManager::~BitmapManager()
\return A new ServerBitmap or NULL if unable to allocate one. \return A new ServerBitmap or NULL if unable to allocate one.
*/ */
ServerBitmap* ServerBitmap*
BitmapManager::CreateBitmap(BRect bounds, color_space space, int32 flags, BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
int32 bytesPerRow, screen_id screen) color_space space, int32 flags, int32 bytesPerRow, screen_id screen,
int8* _allocationType)
{ {
BAutolock locker(fLock); BAutolock locker(fLock);
@ -86,26 +90,41 @@ if (flags & B_BITMAP_WILL_OVERLAY)
if (bitmap == NULL) if (bitmap == NULL)
return NULL; return NULL;
uint8* buffer = (uint8*)fMemPool.GetBuffer(bitmap->BitsLength()); void* cookie = NULL;
uint8* buffer = NULL;
if (allocator != NULL) {
bool newArea;
cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea);
if (cookie != NULL) {
bitmap->fAllocator = allocator;
bitmap->fAllocationCookie = cookie;
if (_allocationType)
*_allocationType = newArea ? kNewAllocatorArea : kAllocator;
}
} else {
buffer = (uint8*)malloc(bitmap->BitsLength());
if (buffer != NULL) {
bitmap->fAllocator = NULL;
bitmap->fAllocationCookie = NULL;
if (_allocationType)
*_allocationType = kHeap;
}
}
if (buffer && fBitmapList.AddItem(bitmap)) { if (buffer && fBitmapList.AddItem(bitmap)) {
bitmap->fArea = area_for(buffer);
bitmap->fBuffer = buffer; bitmap->fBuffer = buffer;
bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap); bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap);
bitmap->fInitialized = true; bitmap->fInitialized = true;
// calculate area offset
area_info info;
get_area_info(bitmap->fArea, &info);
bitmap->fOffset = buffer - (uint8*)info.address;
if (flags & B_BITMAP_CLEAR_TO_WHITE) { if (flags & B_BITMAP_CLEAR_TO_WHITE) {
// should work for most colorspaces // should work for most colorspaces
memset(bitmap->Bits(), 255, bitmap->BitsLength()); memset(bitmap->Bits(), 255, bitmap->BitsLength());
} }
} else { } else {
// Allocation failed for buffer or bitmap list // Allocation failed for buffer or bitmap list
fMemPool.ReleaseBuffer(buffer);
delete bitmap; delete bitmap;
bitmap = NULL; bitmap = NULL;
} }
@ -119,7 +138,7 @@ if (flags & B_BITMAP_WILL_OVERLAY)
\param bitmap The bitmap to delete \param bitmap The bitmap to delete
*/ */
void void
BitmapManager::DeleteBitmap(ServerBitmap *bitmap) BitmapManager::DeleteBitmap(ServerBitmap* bitmap)
{ {
if (bitmap == NULL || !bitmap->_Release()) { if (bitmap == NULL || !bitmap->_Release()) {
// there are other references to this bitmap, we don't have to delete it yet // there are other references to this bitmap, we don't have to delete it yet
@ -130,9 +149,6 @@ BitmapManager::DeleteBitmap(ServerBitmap *bitmap)
if (!locker.IsLocked()) if (!locker.IsLocked())
return; return;
if (fBitmapList.RemoveItem(bitmap)) { if (fBitmapList.RemoveItem(bitmap))
// Server code will require a check to ensure bitmap doesn't have its own area
fMemPool.ReleaseBuffer(bitmap->fBuffer);
delete bitmap; delete bitmap;
}
} }

View File

@ -0,0 +1,234 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
/*!
This class manages a pool of areas for one client. The client is supposed
to clone these areas into its own address space to access the data.
This mechanism is only used for bitmaps for far.
Note, this class doesn't provide any real locking - you need to have the
ServerApp locked when interacting with any method of this class.
The Lock()/Unlock() methods are needed whenever you access a pointer that
lies within an area allocated using this class. This is needed because an
area might be temporarily unavailable or might be relocated at any time.
*/
// TODO: right now, areas will always stay static until they are deleted;
// locking is not yet done or enforced!
#include "ClientMemoryAllocator.h"
#include "ServerApp.h"
#include <stdlib.h>
typedef block_list::Iterator block_iterator;
typedef chunk_list::Iterator chunk_iterator;
ClientMemoryAllocator::ClientMemoryAllocator(ServerApp* application)
:
fApplication(application),
fLock("client memory lock")
{
}
ClientMemoryAllocator::~ClientMemoryAllocator()
{
}
status_t
ClientMemoryAllocator::InitCheck()
{
return fLock.InitCheck() < B_OK ? fLock.InitCheck() : B_OK;
}
void *
ClientMemoryAllocator::Allocate(size_t size, void** _address, bool& newArea)
{
// Search best matching free block from the list
block_iterator iterator = fFreeBlocks.GetIterator();
struct block* block;
struct block* best = NULL;
while ((block = iterator.Next()) != NULL) {
if (block->size >= size && (best == NULL || block->size < best->size))
best = block;
}
if (best == NULL) {
// We didn't find a free block - we need to allocate
// another chunk, or resize an existing chunk
best = _AllocateChunk(size, newArea);
if (best == NULL)
return NULL;
} else
newArea = false;
// We need to split the chunk into two parts: the one to keep
// and the one to give away
if (best->size == size) {
// The simple case: the free block has exactly the size we wanted to have
fFreeBlocks.Remove(best);
*_address = best->base;
return best;
}
// TODO: maybe we should have the user reserve memory in its object
// for us, so we don't have to do this here...
struct block* usedBlock = (struct block*)malloc(sizeof(struct block));
if (usedBlock == NULL)
return NULL;
usedBlock->base = best->base;
usedBlock->size = size;
usedBlock->chunk = best->chunk;
best->base += size;
best->size -= size;
*_address = usedBlock->base;
return usedBlock;
}
void
ClientMemoryAllocator::Free(void *cookie)
{
if (cookie == NULL)
return;
// TODO: implement me!!!
}
area_id
ClientMemoryAllocator::Area(void* cookie)
{
struct block* block = (struct block*)cookie;
if (block != NULL)
return block->chunk->area;
return B_ERROR;
}
uint32
ClientMemoryAllocator::AreaOffset(void* cookie)
{
struct block* block = (struct block*)cookie;
if (block != NULL)
return block->base - block->chunk->base;
return 0;
}
bool
ClientMemoryAllocator::Lock()
{
return fLock.ReadLock();
}
void
ClientMemoryAllocator::Unlock()
{
fLock.ReadUnlock();
}
struct block *
ClientMemoryAllocator::_AllocateChunk(size_t size, bool& newArea)
{
// round up to multiple of page size
size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
// At first, try to resize our existing areas
chunk_iterator iterator = fChunks.GetIterator();
struct chunk* chunk;
while ((chunk = iterator.Next()) != NULL) {
status_t status = resize_area(chunk->area, chunk->size + size);
if (status == B_OK) {
newArea = false;
break;
}
}
// TODO: resize and relocate while holding the write lock
struct block* block;
uint8* address;
if (chunk == NULL) {
// TODO: temporary measurement as long as resizing areas doesn't
// work the way we need (with relocating the area, if needed)
if (size < B_PAGE_SIZE * 32)
size = B_PAGE_SIZE * 32;
// create new area for this allocation
chunk = (struct chunk*)malloc(sizeof(struct chunk));
if (chunk == NULL)
return NULL;
block = (struct block*)malloc(sizeof(struct block));
if (block == NULL) {
free(chunk);
return NULL;
}
char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "heap:%ld:%s", fApplication->ClientTeam(),
fApplication->SignatureLeaf());
area_id area = create_area(name, (void**)&address, B_ANY_ADDRESS, size,
B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (area < B_OK) {
free(block);
free(chunk);
return NULL;
}
// add chunk to list
chunk->area = area;
chunk->base = address;
chunk->size = size;
fChunks.Add(chunk);
newArea = true;
} else {
// create new free block for this chunk
block = (struct block *)malloc(sizeof(struct block));
if (block == NULL)
return NULL;
address = chunk->base + chunk->size;
chunk->size += size;
}
// add block to free list
block->chunk = chunk;
block->base = address;
block->size = size;
fFreeBlocks.Add(block);
return block;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef CLIENT_MEMORY_ALLOCATOR_H
#define CLIENT_MEMORY_ALLOCATOR_H
#include "MultiLocker.h"
#include <util/DoublyLinkedList.h>
class ServerApp;
struct chunk;
struct block;
struct chunk : DoublyLinkedListLinkImpl<struct chunk> {
area_id area;
uint8* base;
size_t size;
};
struct block : DoublyLinkedListLinkImpl<struct block> {
struct chunk* chunk;
uint8* base;
size_t size;
};
typedef DoublyLinkedList<block> block_list;
typedef DoublyLinkedList<chunk> chunk_list;
class ClientMemoryAllocator {
public:
ClientMemoryAllocator(ServerApp* application);
~ClientMemoryAllocator();
status_t InitCheck();
void *Allocate(size_t size, void** _address, bool& newArea);
void Free(void* cookie);
area_id Area(void* cookie);
uint32 AreaOffset(void* cookie);
bool Lock();
void Unlock();
private:
struct block *_AllocateChunk(size_t size, bool& newArea);
ServerApp* fApplication;
MultiLocker fLock;
chunk_list fChunks;
block_list fFreeBlocks;
};
#endif /* CLIENT_MEMORY_ALLOCATOR_H */

View File

@ -3,7 +3,7 @@ SubDir HAIKU_TOP src servers app ;
AddResources app_server : app_server.rdef ; AddResources app_server : app_server.rdef ;
UseLibraryHeaders png zlib ; UseLibraryHeaders png zlib ;
UsePrivateHeaders app graphics input interface shared [ FDirName servers app ] ; UsePrivateHeaders app graphics input interface kernel shared [ FDirName servers app ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseFreeTypeHeaders ; UseFreeTypeHeaders ;
@ -14,6 +14,7 @@ Server app_server :
AppServer.cpp AppServer.cpp
BGet++.cpp BGet++.cpp
BitmapManager.cpp BitmapManager.cpp
ClientMemoryAllocator.cpp
ColorSet.cpp ColorSet.cpp
CursorData.cpp CursorData.cpp
CursorManager.cpp CursorManager.cpp

View File

@ -94,13 +94,14 @@ ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
fViewCursor(NULL), fViewCursor(NULL),
fCursorHideLevel(0), fCursorHideLevel(0),
fIsActive(false), fIsActive(false),
fSharedMem("shared memory", 32768) fSharedMem("shared memory", 32768),
fMemoryAllocator(this)
{ {
if (fSignature == "") if (fSignature == "")
fSignature = "application/no-signature"; fSignature = "application/no-signature";
char name[B_OS_NAME_LENGTH]; char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "a<%s", Signature()); snprintf(name, sizeof(name), "a<%ld:%s", clientTeam, SignatureLeaf());
fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name); fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
if (fMessagePort < B_OK) if (fMessagePort < B_OK)
@ -329,12 +330,7 @@ ServerApp::CurrentCursor() const
void void
ServerApp::_GetLooperName(char* name, size_t length) ServerApp::_GetLooperName(char* name, size_t length)
{ {
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST snprintf(name, length, "a:%ld:%s", ClientTeam(), SignatureLeaf());
strlcpy(name, Signature(), length);
#else
strncpy(name, Signature(), length);
name[length - 1] = '\0';
#endif
} }
@ -729,6 +725,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// First, let's attempt to allocate the bitmap // First, let's attempt to allocate the bitmap
ServerBitmap *bitmap = NULL; ServerBitmap *bitmap = NULL;
int8 allocationType = kAllocator;
BRect frame; BRect frame;
color_space colorSpace; color_space colorSpace;
int32 flags, bytesPerRow; int32 flags, bytesPerRow;
@ -739,8 +737,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read<int32>(&flags); link.Read<int32>(&flags);
link.Read<int32>(&bytesPerRow); link.Read<int32>(&bytesPerRow);
if (link.Read<screen_id>(&screenID) == B_OK) { if (link.Read<screen_id>(&screenID) == B_OK) {
bitmap = gBitmapManager->CreateBitmap(frame, colorSpace, flags, bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator, frame,
bytesPerRow, screenID); colorSpace, flags, bytesPerRow, screenID, &allocationType);
} }
STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n", STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n",
@ -749,8 +747,14 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (bitmap != NULL && fBitmapList.AddItem(bitmap)) { if (bitmap != NULL && fBitmapList.AddItem(bitmap)) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<int32>(bitmap->Token()); fLink.Attach<int32>(bitmap->Token());
fLink.Attach<area_id>(bitmap->Area()); fLink.Attach<int8>(allocationType);
fLink.Attach<int32>(bitmap->AreaOffset());
if (allocationType == kArea) {
// TODO: implement me!
} else {
fLink.Attach<area_id>(fMemoryAllocator.Area(bitmap->AllocationCookie()));
fLink.Attach<int32>(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie()));
}
} else } else
fLink.StartMessage(B_NO_MEMORY); fLink.StartMessage(B_NO_MEMORY);

View File

@ -13,14 +13,16 @@
#define SERVER_APP_H #define SERVER_APP_H
#include "ClientMemoryAllocator.h"
#include "MessageLooper.h" #include "MessageLooper.h"
#include "BGet++.h" #include "BGet++.h"
#include <String.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <TokenSpace.h> #include <TokenSpace.h>
#include <Messenger.h>
#include <String.h>
class AreaPool; class AreaPool;
class BMessage; class BMessage;
@ -66,6 +68,7 @@ class ServerApp : public MessageLooper {
team_id ClientTeam() const; team_id ClientTeam() const;
const char* Signature() const { return fSignature.String(); } const char* Signature() const { return fSignature.String(); }
const char* SignatureLeaf() const { return fSignature.String() + 12; }
void RemoveWindow(ServerWindow* window); void RemoveWindow(ServerWindow* window);
bool InWorkspace(int32 index) const; bool InWorkspace(int32 index) const;
@ -132,6 +135,7 @@ class ServerApp : public MessageLooper {
bool fIsActive; bool fIsActive;
AreaPool fSharedMem; AreaPool fSharedMem;
ClientMemoryAllocator fMemoryAllocator;
}; };
#endif // SERVER_APP_H #endif // SERVER_APP_H

View File

@ -8,6 +8,7 @@
#include "ServerBitmap.h" #include "ServerBitmap.h"
#include "ClientMemoryAllocator.h"
#include "ColorConversion.h" #include "ColorConversion.h"
#include <new> #include <new>
@ -31,7 +32,8 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space,
int32 flags, int32 bytesPerRow, int32 flags, int32 bytesPerRow,
screen_id screen) screen_id screen)
: fInitialized(false), : fInitialized(false),
fArea(B_ERROR), fAllocator(NULL),
fAllocationCookie(NULL),
fBuffer(NULL), fBuffer(NULL),
fReferenceCount(1), fReferenceCount(1),
// WARNING: '1' is added to the width and height. // WARNING: '1' is added to the width and height.
@ -53,10 +55,10 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space,
//! Copy constructor does not copy the buffer. //! Copy constructor does not copy the buffer.
ServerBitmap::ServerBitmap(const ServerBitmap* bmp) ServerBitmap::ServerBitmap(const ServerBitmap* bmp)
: fInitialized(false), : fInitialized(false),
fArea(B_ERROR), fAllocator(NULL),
fAllocationCookie(NULL),
fBuffer(NULL), fBuffer(NULL),
fReferenceCount(1) fReferenceCount(1)
// TODO: what about fToken and fOffset ?!?
{ {
if (bmp) { if (bmp) {
fInitialized = bmp->fInitialized; fInitialized = bmp->fInitialized;
@ -77,13 +79,14 @@ ServerBitmap::ServerBitmap(const ServerBitmap* bmp)
} }
/*!
\brief Empty. Defined for subclasses.
*/
ServerBitmap::~ServerBitmap() ServerBitmap::~ServerBitmap()
{ {
// TODO: Maybe it would be wiser to free the buffer here, if (fAllocator != NULL)
// instead of do that in every subclass ? fAllocator->Free(AllocationCookie());
else if (fAllocationCookie != NULL)
delete_area((area_id)fAllocationCookie);
else
free(fBuffer);
} }
@ -122,20 +125,6 @@ ServerBitmap::_AllocateBuffer(void)
} }
/*!
\brief Internal function used by subclasses
Subclasses should call this to free the internal buffer.
*/
void
ServerBitmap::_FreeBuffer()
{
delete[] fBuffer;
fBuffer = NULL;
fInitialized = false;
}
/*! /*!
\brief Internal function used to translate color space values to appropriate internal \brief Internal function used to translate color space values to appropriate internal
values. values.
@ -271,6 +260,29 @@ ServerBitmap::ImportBits(const void *bits, int32 bitsLength, int32 bytesPerRow,
} }
area_id
ServerBitmap::Area() const
{
if (fAllocator != NULL)
return fAllocator->Area(AllocationCookie());
if (fAllocationCookie != NULL)
return (area_id)fAllocationCookie;
return B_ERROR;
}
uint32
ServerBitmap::AreaOffset() const
{
if (fAllocator != NULL)
return fAllocator->AreaOffset(AllocationCookie());
return 0;
}
void void
ServerBitmap::PrintToStream() ServerBitmap::PrintToStream()
{ {
@ -291,12 +303,13 @@ UtilityBitmap::UtilityBitmap(BRect rect, color_space space,
} }
UtilityBitmap::UtilityBitmap(const ServerBitmap* bmp) UtilityBitmap::UtilityBitmap(const ServerBitmap* bitmap)
: ServerBitmap(bmp) : ServerBitmap(bitmap)
{ {
_AllocateBuffer(); _AllocateBuffer();
if (bmp->Bits())
memcpy(Bits(), bmp->Bits(), bmp->BitsLength()); if (bitmap->Bits())
memcpy(Bits(), bitmap->Bits(), bitmap->BitsLength());
} }
@ -313,5 +326,4 @@ UtilityBitmap::UtilityBitmap(const uint8* alreadyPaddedData,
UtilityBitmap::~UtilityBitmap() UtilityBitmap::~UtilityBitmap()
{ {
_FreeBuffer();
} }

View File

@ -181,7 +181,6 @@ ServerCursor::ServerCursor(const ServerCursor* cursor)
//! Frees the heap space allocated for the cursor's image data //! Frees the heap space allocated for the cursor's image data
ServerCursor::~ServerCursor() ServerCursor::~ServerCursor()
{ {
_FreeBuffer();
} }

View File

@ -6,7 +6,7 @@ SetSubDirSupportedPlatforms libbe_test ;
if $(TARGET_PLATFORM) = libbe_test { if $(TARGET_PLATFORM) = libbe_test {
UseLibraryHeaders agg png zlib ; UseLibraryHeaders agg png zlib ;
UsePrivateHeaders app graphics input interface shared [ FDirName servers app ] ; UsePrivateHeaders app graphics input interface kernel shared [ FDirName servers app ] ;
local appServerDir = [ FDirName $(HAIKU_TOP) src servers app ] ; local appServerDir = [ FDirName $(HAIKU_TOP) src servers app ] ;
@ -52,6 +52,7 @@ SharedLibrary libhwinterfaceimpl.so :
SharedLibrary libhaikuappserver.so : SharedLibrary libhaikuappserver.so :
Angle.cpp Angle.cpp
BGet++.cpp BGet++.cpp
ClientMemoryAllocator.cpp
ColorSet.cpp ColorSet.cpp
CursorData.cpp CursorData.cpp
CursorManager.cpp CursorManager.cpp