* 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:
parent
66b7a0f477
commit
9a44fdc97c
@ -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
|
||||
|
35
headers/private/app/ServerMemoryAllocator.h
Normal file
35
headers/private/app/ServerMemoryAllocator.h
Normal 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 */
|
@ -318,4 +318,12 @@ enum {
|
||||
AS_LAST_CODE
|
||||
};
|
||||
|
||||
// bitmap allocation types
|
||||
enum {
|
||||
kAllocator,
|
||||
kNewAllocatorArea,
|
||||
kArea,
|
||||
kHeap
|
||||
};
|
||||
|
||||
#endif // APP_SERVER_PROTOCOL_H
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
;
|
||||
|
@ -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>
|
||||
|
123
src/kits/app/ServerMemoryAllocator.cpp
Normal file
123
src/kits/app/ServerMemoryAllocator.cpp
Normal 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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
234
src/servers/app/ClientMemoryAllocator.cpp
Normal file
234
src/servers/app/ClientMemoryAllocator.cpp
Normal 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;
|
||||
}
|
||||
|
62
src/servers/app/ClientMemoryAllocator.h
Normal file
62
src/servers/app/ClientMemoryAllocator.h
Normal 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 */
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -181,7 +181,6 @@ ServerCursor::ServerCursor(const ServerCursor* cursor)
|
||||
//! Frees the heap space allocated for the cursor's image data
|
||||
ServerCursor::~ServerCursor()
|
||||
{
|
||||
_FreeBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user