* 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.
*
* Authors:
@ -8,12 +8,17 @@
#ifndef _APPLICATION_PRIVATE_H
#define _APPLICATION_PRIVATE_H
#include <Application.h>
class BApplication::Private {
public:
static inline BPrivate::PortLink *ServerLink()
{ return be_app->fServerLink; }
public:
static inline BPrivate::PortLink *ServerLink()
{ return be_app->fServerLink; }
static inline BPrivate::ServerMemoryAllocator* ServerAllocator()
{ return be_app->fServerAllocator; }
};
#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
};
// bitmap allocation types
enum {
kAllocator,
kNewAllocatorArea,
kArea,
kHeap
};
#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.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
*/
#ifndef BITMAP_MANAGER_H_
#define BITMAP_MANAGER_H_
#ifndef BITMAP_MANAGER_H
#define BITMAP_MANAGER_H
#include <GraphicsDefs.h>
@ -15,28 +15,25 @@
#include <OS.h>
#include <Rect.h>
#include "BGet++.h"
class ClientMemoryAllocator;
class ServerBitmap;
class BitmapManager {
public:
BitmapManager();
virtual ~BitmapManager();
ServerBitmap* CreateBitmap(BRect bounds, color_space space,
int32 flags, int32 bytesPerRow = -1,
screen_id screen = B_MAIN_SCREEN_ID);
ServerBitmap* CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
color_space space, int32 flags, int32 bytesPerRow = -1,
screen_id screen = B_MAIN_SCREEN_ID,
int8* _allocationType = NULL);
void DeleteBitmap(ServerBitmap* bitmap);
protected:
BList fBitmapList;
int8* fBuffer;
BLocker fLock;
AreaPool fMemPool;
};
extern BitmapManager *gBitmapManager;
#endif /* BITMAP_MANAGER_H_ */
#endif /* BITMAP_MANAGER_H */

View File

@ -5,8 +5,8 @@
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
*/
#ifndef _SERVER_BITMAP_H_
#define _SERVER_BITMAP_H_
#ifndef SERVER_BITMAP_H
#define SERVER_BITMAP_H
#include <GraphicsDefs.h>
@ -15,6 +15,7 @@
class BitmapManager;
class ClientMemoryAllocator;
/*!
\class ServerBitmap ServerBitmap.h
@ -31,11 +32,6 @@ class ServerBitmap {
void Acquire();
inline area_id Area() const
{ return fArea; }
inline int32 AreaOffset() const
{ return fOffset; }
inline uint8* Bits() const
{ return fBuffer; }
inline uint32 BitsLength() const
@ -59,6 +55,12 @@ class ServerBitmap {
inline int32 Token() const
{ 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
inline void ShallowCopy(const ServerBitmap *from);
@ -84,23 +86,19 @@ protected:
virtual ~ServerBitmap();
//! used by the BitmapManager
inline void _SetArea(area_id ID)
{ fArea = ID; }
//! used by the BitmapManager
inline void _SetBuffer(void *ptr)
{ fBuffer = (uint8*)ptr; }
// inline void _SetBuffer(void *ptr)
// { fBuffer = (uint8*)ptr; }
bool _Release();
void _AllocateBuffer();
void _FreeBuffer();
void _HandleSpace(color_space space,
int32 bytesperline = -1);
bool fInitialized;
area_id fArea;
ClientMemoryAllocator* fAllocator;
void* fAllocationCookie;
uint8* fBuffer;
int32 fReferenceCount;
@ -111,7 +109,6 @@ protected:
int32 fFlags;
int fBitsPerPixel;
int32 fToken;
int32 fOffset;
};
class UtilityBitmap : public ServerBitmap {
@ -140,7 +137,6 @@ ServerBitmap::ShallowCopy(const ServerBitmap* from)
return;
fInitialized = from->fInitialized;
fArea = from->fArea;
fBuffer = from->fBuffer;
fWidth = from->fWidth;
fHeight = from->fHeight;
@ -149,8 +145,6 @@ ServerBitmap::ShallowCopy(const ServerBitmap* from)
fFlags = from->fFlags;
fBitsPerPixel = from->fBitsPerPixel;
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.
*
* Authors:
@ -36,6 +36,7 @@
#include <MenuWindow.h>
#include <ObjectLocker.h>
#include <PortLink.h>
#include <ServerMemoryAllocator.h>
#include <ServerProtocol.h>
using namespace BPrivate;
@ -162,14 +163,14 @@ static void fill_argv_message(BMessage &message);
BApplication::BApplication(const char *signature)
: BLooper(looper_name_for(signature))
{
InitData(signature, true, NULL);
_InitData(signature, true, NULL);
}
BApplication::BApplication(const char *signature, status_t *_error)
: 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)
: 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;
data->FindString("mime_sig", &signature);
InitData(signature, true, NULL);
_InitData(signature, true, NULL);
bigtime_t pulseRate;
if (data->FindInt64("_pulse", &pulseRate) == B_OK)
@ -213,7 +214,7 @@ BApplication::~BApplication()
Lock();
// tell all loopers(usually windows) to quit. Also, wait for them.
quit_all_windows(true);
_QuitAllWindows(true);
// unregister from the roster
BRoster::Private().RemoveApp(Team());
@ -242,7 +243,7 @@ BApplication::operator=(const BApplication &rhs)
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));
// 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.");
fServerLink = new BPrivate::PortLink(-1, -1);
fServerHeap = NULL;
fServerAllocator = NULL;
fInitialWorkspace = 0;
fDraggedMessage = NULL;
//fDraggedMessage = NULL;
fReadyToRunCalled = false;
// initially, there is no pulse
@ -536,7 +537,7 @@ BApplication::Quit()
bool
BApplication::QuitRequested()
{
return quit_all_windows(false);
return _QuitAllWindows(false);
}
@ -693,7 +694,7 @@ BApplication::SetCursor(const BCursor *cursor, bool sync)
int32
BApplication::CountWindows() const
{
return count_windows(false);
return _CountWindows(false);
// we're ignoring menu windows
}
@ -701,7 +702,7 @@ BApplication::CountWindows() const
BWindow *
BApplication::WindowAt(int32 index) const
{
return window_at(index, false);
return _WindowAt(index, false);
// we're ignoring menu windows
}
@ -794,7 +795,7 @@ BApplication::DispatchMessage(BMessage *message, BHandler *handler)
switch (message->what) {
case B_ARGV_RECEIVED:
do_argv(message);
_ArgvReceived(message);
break;
case B_REFS_RECEIVED:
@ -974,37 +975,13 @@ BApplication::EndRectTracking()
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.
// 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
return fServerAllocator->InitCheck();
}
@ -1012,11 +989,11 @@ status_t
BApplication::_InitGUIContext()
{
// 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)
return error;
error = setup_server_heaps();
error = _SetupServerAllocator();
if (error != B_OK)
return error;
@ -1030,6 +1007,7 @@ BApplication::_InitGUIContext()
B_CURSOR_SYSTEM_DEFAULT = new BCursor(B_HAND_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();
return B_OK;
@ -1037,7 +1015,7 @@ BApplication::_InitGUIContext()
status_t
BApplication::connect_to_app_server()
BApplication::_ConnectToServer()
{
port_id serverPort = find_port(SERVER_PORT_NAME);
if (serverPort < B_OK)
@ -1096,7 +1074,7 @@ BApplication::connect_to_app_server()
return B_OK;
}
#if 0
void
BApplication::send_drag(BMessage *message, int32 vs_token, BPoint offset,
BRect dragRect, BHandler *replyTo)
@ -1118,10 +1096,10 @@ BApplication::write_drag(_BSession_ *session, BMessage *message)
{
// TODO: implement
}
#endif
bool
BApplication::window_quit_loop(bool quitFilePanels, bool force)
BApplication::_WindowQuitLoop(bool quitFilePanels, bool force)
{
BList looperList;
{
@ -1173,7 +1151,7 @@ BApplication::window_quit_loop(bool quitFilePanels, bool force)
bool
BApplication::quit_all_windows(bool force)
BApplication::_QuitAllWindows(bool force)
{
AssertLocked();
@ -1181,9 +1159,9 @@ BApplication::quit_all_windows(bool force)
// allowed to lock the application - which would cause a deadlock
Unlock();
bool quit = window_quit_loop(false, force);
bool quit = _WindowQuitLoop(false, force);
if (!quit)
quit = window_quit_loop(true, force);
quit = _WindowQuitLoop(true, force);
Lock();
@ -1192,12 +1170,8 @@ BApplication::quit_all_windows(bool force)
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);
// build the argv vector
@ -1242,11 +1216,11 @@ BApplication::InitialWorkspace()
int32
BApplication::count_windows(bool includeMenus) const
BApplication::_CountWindows(bool includeMenus) const
{
int32 count = 0;
BList windowList;
if (get_window_list(&windowList, includeMenus) == B_OK)
if (_GetWindowList(&windowList, includeMenus) == B_OK)
count = windowList.CountItems();
return count;
@ -1254,11 +1228,11 @@ BApplication::count_windows(bool includeMenus) const
BWindow *
BApplication::window_at(uint32 index, bool includeMenus) const
BApplication::_WindowAt(uint32 index, bool includeMenus) const
{
BList windowList;
BWindow *window = NULL;
if (get_window_list(&windowList, includeMenus) == B_OK) {
if (_GetWindowList(&windowList, includeMenus) == B_OK) {
if ((int32)index < windowList.CountItems())
window = static_cast<BWindow *>(windowList.ItemAt(index));
}
@ -1268,7 +1242,7 @@ BApplication::window_at(uint32 index, bool includeMenus) const
status_t
BApplication::get_window_list(BList *list, bool includeMenus) const
BApplication::_GetWindowList(BList *list, bool includeMenus) const
{
ASSERT(list);
@ -1291,15 +1265,11 @@ BApplication::get_window_list(BList *list, bool includeMenus) const
}
int32
BApplication::async_quit_entry(void *data)
{
return 0; // TODO: implement? not implemented?
}
// #pragma mark -
// 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.
@ -1308,9 +1278,7 @@ BApplication::async_quit_entry(void *data)
- \c B_OK: \a signature is a 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)
{
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
special name.
\return The looper name.
*/
static
const char *
static const char *
looper_name_for(const char *signature)
{
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)
{
message.what = B_ARGV_RECEIVED;

View File

@ -18,8 +18,8 @@ if $(RUN_WITHOUT_APP_SERVER) != 0 {
}
UsePrivateHeaders shared app interface ;
UsePrivateHeaders [ FDirName kernel util ] ; # For KMessage.h
UsePrivateHeaders [ FDirName servers app ] ;
UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
SetSubDirSupportedPlatforms haiku libbe_test ;
@ -56,6 +56,7 @@ MergeObject <libbe>app_kit.o :
Server.cpp
ServerLink.cpp
ServerMemIO.cpp
ServerMemoryAllocator.cpp
TokenSpace.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.
*
* Authors:
@ -18,7 +18,6 @@
#include <AppMisc.h>
#include <BlockCache.h>
#include <Entry.h>
#include <KMessage.h>
#include <Messenger.h>
#include <MessengerPrivate.h>
#include <Path.h>
@ -26,6 +25,7 @@
#include <Rect.h>
#include <String.h>
#include <TokenSpace.h>
#include <util/KMessage.h>
#include <ctype.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.
*
* Authors:
* Ingo Weinhold (bonefish@users.sf.net)
* DarkWyrm <bpmagic@columbus.rr.com>
* 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 <limits.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include "ColorConversion.h"
#include <Application.h>
#include <Bitmap.h>
@ -25,11 +23,16 @@
#include <View.h>
#include <Window.h>
#include "ColorConversion.h"
// Includes to be able to talk to the app_server
#include <ServerProtocol.h>
#include <ApplicationPrivate.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
@ -112,7 +115,9 @@ get_bytes_per_row(color_space colorSpace, int32 width)
}
// constructor
// #pragma mark -
/*! \brief Creates and initializes a BBitmap.
\param bounds The bitmap dimensions.
\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,
int32 bytesPerRow, screen_id screenID)
: fBasePtr(NULL),
: fBasePointer(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
@ -133,11 +138,11 @@ BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fServerArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
_InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
}
// constructor
@ -152,7 +157,7 @@ BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
*/
BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
bool needsContiguous)
: fBasePtr(NULL),
: fBasePointer(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
@ -161,13 +166,13 @@ BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fServerArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 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);
}
@ -183,7 +188,7 @@ BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
*/
BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
bool needsContiguous)
: fBasePtr(NULL),
: fBasePointer(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
@ -192,14 +197,14 @@ BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fServerArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
if (source && source->IsValid()) {
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 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);
if (InitCheck() == B_OK)
memcpy(Bits(), source->Bits(), BytesPerRow());
@ -212,7 +217,7 @@ BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
BBitmap::~BBitmap()
{
delete fWindow;
CleanUp();
_CleanUp();
}
// unarchiving constructor
@ -221,7 +226,7 @@ BBitmap::~BBitmap()
*/
BBitmap::BBitmap(BMessage *data)
: BArchivable(data),
fBasePtr(NULL),
fBasePointer(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
@ -230,7 +235,7 @@ BBitmap::BBitmap(BMessage *data)
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fServerArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
@ -246,14 +251,14 @@ BBitmap::BBitmap(BMessage *data)
int32 rowBytes = 0;
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) {
AssertPtr();
_AssertPointer();
ssize_t size = 0;
const void *buffer;
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) {
@ -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
// the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to
// the BeBook)
const_cast<BBitmap *>(this)->AssertPtr();
data->AddData("_data", B_RAW_TYPE, fBasePtr, fSize);
const_cast<BBitmap *>(this)->_AssertPointer();
data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize);
}
return B_OK;
@ -363,7 +368,7 @@ BBitmap::UnlockBits()
area_id
BBitmap::Area() const
{
const_cast<BBitmap *>(this)->AssertPtr();
const_cast<BBitmap *>(this)->_AssertPointer();
return fArea;
}
@ -374,8 +379,8 @@ BBitmap::Area() const
void *
BBitmap::Bits() const
{
const_cast<BBitmap *>(this)->AssertPtr();
return fBasePtr;
const_cast<BBitmap *>(this)->_AssertPointer();
return (void*)fBasePointer;
}
// BitsLength
@ -501,7 +506,7 @@ status_t
BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
color_space colorSpace)
{
AssertPtr();
_AssertPointer();
if (InitCheck() != B_OK)
return B_NO_INIT;
@ -513,7 +518,7 @@ BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
if (bpr < 0)
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,
fBounds.IntegerHeight() + 1);
}
@ -545,7 +550,7 @@ status_t
BBitmap::ImportBits(const void *data, int32 length, int32 bpr,
color_space colorSpace, BPoint from, BPoint to, int32 width, int32 height)
{
AssertPtr();
_AssertPointer();
if (InitCheck() != B_OK)
return B_NO_INIT;
@ -556,7 +561,7 @@ BBitmap::ImportBits(const void *data, int32 length, int32 bpr,
if (bpr < 0)
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);
}
@ -783,6 +788,7 @@ BBitmap::operator=(const BBitmap &)
return *this;
}
#if 0
// get_shared_pointer
/*! \brief ???
*/
@ -791,17 +797,15 @@ BBitmap::get_shared_pointer() const
{
return NULL; // not implemented
}
#endif
// get_server_token
/*! \brief ???
*/
int32
BBitmap::get_server_token() const
BBitmap::_ServerToken() const
{
return fServerToken;
}
// InitObject
/*! \brief Initializes the bitmap.
\param bounds The bitmap dimensions.
\param colorSpace The bitmap's color space.
@ -812,7 +816,7 @@ BBitmap::get_server_token() const
\param screenID ???
*/
void
BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int32 bytesPerRow, screen_id screenID)
{
//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;
#endif // RUN_WITHOUT_APP_SERVER
CleanUp();
_CleanUp();
// check params
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);
if (flags & B_BITMAP_NO_SERVER_LINK) {
fBasePtr = malloc(size);
if (fBasePtr) {
fBasePointer = (uint8*)malloc(size);
if (fBasePointer) {
fSize = size;
fColorSpace = colorSpace;
fBounds = bounds;
@ -883,34 +887,51 @@ BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
link.Attach<int32>(bytesPerRow);
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) {
// server side success
// Get token
link.Read<int32>(&fServerToken);
link.Read<area_id>(&fOrigArea);
link.Read<int32>(&fAreaOffset);
if (fOrigArea >= B_OK) {
int8 allocationType;
link.Read<int8>(&allocationType);
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;
fColorSpace = colorSpace;
fBounds = bounds;
fBytesPerRow = bytesPerRow;
fFlags = flags;
} else
error = fOrigArea;
error = fServerArea;
}
if (error < B_OK) {
fBasePtr = NULL;
fBasePointer = NULL;
fServerToken = -1;
fArea = -1;
fOrigArea = -1;
fServerArea = -1;
fAreaOffset = -1;
// NOTE: why not "0" in case of error?
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).
*/
void
BBitmap::CleanUp()
BBitmap::_CleanUp()
{
if (fBasePtr == NULL)
if (fBasePointer == NULL)
return;
if (fFlags & B_BITMAP_NO_SERVER_LINK) {
free(fBasePtr);
free(fBasePointer);
} else {
BPrivate::AppServerLink link;
// AS_DELETE_BITMAP:
@ -955,32 +976,31 @@ BBitmap::CleanUp()
link.StartMessage(AS_DELETE_BITMAP);
link.Attach<int32>(fServerToken);
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);
}
fArea = -1;
fServerToken = -1;
fAreaOffset = -1;
}
fBasePtr = NULL;
fBasePointer = NULL;
}
void
BBitmap::AssertPtr()
BBitmap::_AssertPointer()
{
if (fBasePtr == NULL && fAreaOffset != -1 && InitCheck() == B_OK) {
// Offset was saved into "fArea" as we can't add
// any member variable due to Binary compatibility
// Get the area in which the data resides
fArea = clone_area("shared bitmap area", (void **)&fBasePtr, B_ANY_ADDRESS,
B_READ_AREA | B_WRITE_AREA, fOrigArea);
if (fArea >= B_OK) {
// Jump to the location in the area
fBasePtr = (int8 *)fBasePtr + fAreaOffset;
} else
fBasePtr = NULL;
if (fBasePointer == NULL && fServerArea >= B_OK && fAreaOffset == -1) {
// We lazily clone our own areas - if the bitmap is part of the usual
// server memory area, or is a B_BITMAP_NO_SERVER_LINK bitmap, it already
// has its data.
fArea = clone_area("shared bitmap area", (void **)&fBasePointer, B_ANY_ADDRESS,
B_READ_AREA | B_WRITE_AREA, fServerArea);
}
}

View File

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

View File

@ -1331,7 +1331,7 @@ BView::DragMessage(BMessage *message, BBitmap *image,
message->Flatten(buffer, bufferSize);
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<BPoint>(offset);
fOwner->fLink->Attach<int32>(bufferSize);
@ -2235,7 +2235,7 @@ BView::DrawBitmapAsync(const BBitmap *bitmap, BRect srcRect, BRect dstRect)
check_lock();
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>(srcRect);
@ -2268,7 +2268,7 @@ BView::DrawBitmapAsync(const BBitmap *bitmap, BPoint where)
check_lock();
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 dst = src.OffsetToCopy(where);
fOwner->fLink->Attach<BRect>(dst);
@ -4320,7 +4320,7 @@ BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect,
if (!do_owner_check())
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->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.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
*/
/** 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
* all memory management related to them.
*/
/*!
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
all memory management related to them.
*/
#include <new>
@ -23,7 +24,9 @@
#include <Bitmap.h>
#include "BitmapManager.h"
#include "ClientMemoryAllocator.h"
#include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerTokenSpace.h"
using std::nothrow;
@ -40,9 +43,7 @@ BitmapManager *gBitmapManager = NULL;
BitmapManager::BitmapManager()
:
fBitmapList(1024),
fBuffer(NULL),
fLock("BitmapManager Lock"),
fMemPool("bitmap pool", BITMAP_AREA_SIZE)
fLock("BitmapManager Lock")
{
}
@ -53,7 +54,9 @@ BitmapManager::~BitmapManager()
int32 count = fBitmapList.CountItems();
for (int32 i = 0; i < count; 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;
}
}
@ -70,8 +73,9 @@ BitmapManager::~BitmapManager()
\return A new ServerBitmap or NULL if unable to allocate one.
*/
ServerBitmap*
BitmapManager::CreateBitmap(BRect bounds, color_space space, int32 flags,
int32 bytesPerRow, screen_id screen)
BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
color_space space, int32 flags, int32 bytesPerRow, screen_id screen,
int8* _allocationType)
{
BAutolock locker(fLock);
@ -86,26 +90,41 @@ if (flags & B_BITMAP_WILL_OVERLAY)
if (bitmap == 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)) {
bitmap->fArea = area_for(buffer);
bitmap->fBuffer = buffer;
bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap);
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) {
// should work for most colorspaces
memset(bitmap->Bits(), 255, bitmap->BitsLength());
}
} else {
// Allocation failed for buffer or bitmap list
fMemPool.ReleaseBuffer(buffer);
delete bitmap;
bitmap = NULL;
}
@ -119,7 +138,7 @@ if (flags & B_BITMAP_WILL_OVERLAY)
\param bitmap The bitmap to delete
*/
void
BitmapManager::DeleteBitmap(ServerBitmap *bitmap)
BitmapManager::DeleteBitmap(ServerBitmap* bitmap)
{
if (bitmap == NULL || !bitmap->_Release()) {
// 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())
return;
if (fBitmapList.RemoveItem(bitmap)) {
// Server code will require a check to ensure bitmap doesn't have its own area
fMemPool.ReleaseBuffer(bitmap->fBuffer);
if (fBitmapList.RemoveItem(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 ;
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 ] ;
UseFreeTypeHeaders ;
@ -14,6 +14,7 @@ Server app_server :
AppServer.cpp
BGet++.cpp
BitmapManager.cpp
ClientMemoryAllocator.cpp
ColorSet.cpp
CursorData.cpp
CursorManager.cpp

View File

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

View File

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

View File

@ -8,6 +8,7 @@
#include "ServerBitmap.h"
#include "ClientMemoryAllocator.h"
#include "ColorConversion.h"
#include <new>
@ -31,7 +32,8 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space,
int32 flags, int32 bytesPerRow,
screen_id screen)
: fInitialized(false),
fArea(B_ERROR),
fAllocator(NULL),
fAllocationCookie(NULL),
fBuffer(NULL),
fReferenceCount(1),
// 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.
ServerBitmap::ServerBitmap(const ServerBitmap* bmp)
: fInitialized(false),
fArea(B_ERROR),
fAllocator(NULL),
fAllocationCookie(NULL),
fBuffer(NULL),
fReferenceCount(1)
// TODO: what about fToken and fOffset ?!?
{
if (bmp) {
fInitialized = bmp->fInitialized;
@ -77,13 +79,14 @@ ServerBitmap::ServerBitmap(const ServerBitmap* bmp)
}
/*!
\brief Empty. Defined for subclasses.
*/
ServerBitmap::~ServerBitmap()
{
// TODO: Maybe it would be wiser to free the buffer here,
// instead of do that in every subclass ?
if (fAllocator != NULL)
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
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
ServerBitmap::PrintToStream()
{
@ -291,12 +303,13 @@ UtilityBitmap::UtilityBitmap(BRect rect, color_space space,
}
UtilityBitmap::UtilityBitmap(const ServerBitmap* bmp)
: ServerBitmap(bmp)
UtilityBitmap::UtilityBitmap(const ServerBitmap* bitmap)
: ServerBitmap(bitmap)
{
_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()
{
_FreeBuffer();
}

View File

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

View File

@ -6,7 +6,7 @@ SetSubDirSupportedPlatforms libbe_test ;
if $(TARGET_PLATFORM) = libbe_test {
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 ] ;
@ -52,6 +52,7 @@ SharedLibrary libhwinterfaceimpl.so :
SharedLibrary libhaikuappserver.so :
Angle.cpp
BGet++.cpp
ClientMemoryAllocator.cpp
ColorSet.cpp
CursorData.cpp
CursorManager.cpp