Implemented basic server side support for BDirectWindow. It doesn't fill the direct_buffer_info struct correctly, it just sends B_DIRECT_START/STOP messages on show/hide for now. Tested with dw_info

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14347 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini 2005-10-11 05:25:52 +00:00
parent a88fdc5722
commit ef06444893
2 changed files with 133 additions and 2 deletions

View File

@ -23,6 +23,7 @@
#include <new>
#include <AppDefs.h>
#include <DirectWindow.h>
#include <GraphicsDefs.h>
#include <Message.h>
#include <PortLink.h>
@ -74,6 +75,47 @@
# define DTRACE(x) ;
#endif
struct dw_data {
sem_id direct_sem;
sem_id direct_sem_ack;
area_id direct_area;
direct_buffer_info *direct_info;
dw_data() :
direct_sem(-1),
direct_sem_ack(-1),
direct_area(-1)
{
direct_area = create_area("direct area", (void **)&direct_info,
B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE);
direct_sem = create_sem(1, "direct sem");
direct_sem_ack = create_sem(1, "direct sem ack");
}
~dw_data()
{
if (direct_area >= 0)
delete_area(direct_area);
if (direct_sem >= 0)
delete_sem(direct_sem);
if (direct_sem_ack >= 0)
delete_sem(direct_sem_ack);
}
bool IsValid() const
{
return (direct_area >= 0) && (direct_sem >= 0) && (direct_sem_ack >= 0);
}
};
// TODO: Copied from DirectWindow.cpp: Move to a common header
struct dw_sync_data {
area_id area;
sem_id disableSem;
sem_id disableSemAck;
};
/*!
\brief Constructor
@ -93,7 +135,8 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
fClientLooperPort(looperPort),
fClientViewsWithInvalidCoords(B_VIEW_RESIZED),
fHandlerToken(handlerID),
fCurrentLayer(NULL)
fCurrentLayer(NULL),
fDirectWindowData(NULL)
{
STRACE(("ServerWindow(%s)::ServerWindow()\n", title));
@ -116,6 +159,7 @@ ServerWindow::~ServerWindow()
BPrivate::gDefaultTokens.RemoveToken(fServerToken);
delete fDirectWindowData;
STRACE(("#ServerWindow(%p) will exit NOW\n", this));
}
@ -220,6 +264,9 @@ ServerWindow::Show()
rootLayer->ShowWinBorder(fWinBorder);
rootLayer->Unlock();
}
if (fDirectWindowData != NULL)
_HandleDirectConnection(B_DIRECT_START);
}
//! Hides the window's WinBorder
@ -237,6 +284,9 @@ ServerWindow::Hide()
rootLayer->HideWinBorder(fWinBorder);
rootLayer->Unlock();
}
if (fDirectWindowData != NULL)
_HandleDirectConnection(B_DIRECT_STOP);
}
@ -1568,7 +1618,31 @@ myRootLayer->Unlock();
fLink.Flush();
break;
}
case AS_DW_GET_SYNC_DATA:
{
// TODO: Use token or get rid of it.
int32 serverToken;
link.Read<int32>(&serverToken);
if (_EnableDirectWindowMode() == B_OK) {
fLink.StartMessage(SERVER_TRUE);
struct dw_sync_data syncData = {
fDirectWindowData->direct_area,
fDirectWindowData->direct_sem,
fDirectWindowData->direct_sem_ack
};
fLink.Attach(&syncData, sizeof(syncData));
} else
fLink.StartMessage(SERVER_FALSE);
fLink.Flush();
break;
}
default:
_DispatchGraphicsMessage(code, link);
break;
@ -2281,6 +2355,56 @@ ServerWindow::MakeWinBorder(BRect frame, const char* name,
workspace, this, gDesktop->GetDisplayDriver());
}
status_t
ServerWindow::_EnableDirectWindowMode()
{
if (fDirectWindowData != NULL)
return B_ERROR; // already in direct window mode
fDirectWindowData = new (nothrow) dw_data;
if (fDirectWindowData == NULL)
return B_NO_MEMORY;
if (!fDirectWindowData->IsValid()) {
delete fDirectWindowData;
fDirectWindowData = NULL;
return B_ERROR;
}
return B_OK;
}
void
ServerWindow::_HandleDirectConnection(direct_buffer_state state)
{
if (fDirectWindowData == NULL)
return;
fDirectWindowData->direct_info->buffer_state = state;
if ((state & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
// TODO: Fill these correctly
fDirectWindowData->direct_info->bits = NULL;
fDirectWindowData->direct_info->pci_bits = NULL;
fDirectWindowData->direct_info->clip_list_count = 0;
}
// Releasing this sem causes the client to call BDirectWindow::DirectConnected()
release_sem(fDirectWindowData->direct_sem);
// TODO: Waiting 3 seconds in this thread could cause weird things: test
status_t status = acquire_sem_etc(fDirectWindowData->direct_sem_ack, 1, B_TIMEOUT, 3000000);
if (status == B_TIMED_OUT) {
// The client application didn't release the semaphore
// within the given timeout. Deleting this member should make it crash.
delete fDirectWindowData;
fDirectWindowData = NULL;
}
}
status_t
ServerWindow::PictureToRegion(ServerPicture *picture, BRegion &region,
bool inverse, BPoint where)

View File

@ -13,6 +13,7 @@
#define _SERVERWIN_H_
#include <DirectWindow.h> // for direct_buffer_state
#include <GraphicsDefs.h>
#include <PortLink.h>
#include <Locker.h>
@ -38,6 +39,7 @@ class Workspace;
class RootLayer;
class Layer;
class ServerPicture;
struct dw_data;
struct window_info;
#define AS_UPDATE_DECORATOR 'asud'
@ -115,6 +117,9 @@ private:
virtual void _PrepareQuit();
virtual void _GetLooperName(char* name, size_t size);
status_t _EnableDirectWindowMode();
void _HandleDirectConnection(direct_buffer_state state);
// TODO: Move me elsewhere
status_t PictureToRegion(ServerPicture *picture,
BRegion &,
@ -139,6 +144,8 @@ private:
int32 fHandlerToken;
Layer* fCurrentLayer;
dw_data* fDirectWindowData;
};
#endif // _SERVERWIN_H_