This enables BDirectWindow support again.
It also fixed a bug in the old code - the handshake semaphores were created acquirable, causing the BDirectWindow::DirectDaemonFunc() to call DirectConnected() with an uninitialized buffer and way too early - this probably didn't show up before since it called it before the BDirectWindow constructor ran through, so that DirectConnected() would still point to the BDirectWindow version, and not to the implemented one of its subclass... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15505 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -430,18 +430,36 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case AS_GET_WINDOW_LIST:
|
case AS_GET_WINDOW_LIST:
|
||||||
|
{
|
||||||
team_id team;
|
team_id team;
|
||||||
link.Read<team_id>(&team);
|
link.Read<team_id>(&team);
|
||||||
|
|
||||||
fDesktop->WriteWindowList(team, fLink.Sender());
|
fDesktop->WriteWindowList(team, fLink.Sender());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AS_GET_WINDOW_INFO:
|
case AS_GET_WINDOW_INFO:
|
||||||
|
{
|
||||||
int32 serverToken;
|
int32 serverToken;
|
||||||
link.Read<int32>(&serverToken);
|
link.Read<int32>(&serverToken);
|
||||||
|
|
||||||
fDesktop->WriteWindowInfo(serverToken, fLink.Sender());
|
fDesktop->WriteWindowInfo(serverToken, fLink.Sender());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case AS_DIRECT_WINDOW_SUPPORTS_WINDOW_MODE:
|
||||||
|
{
|
||||||
|
// TODO: How to determine this?
|
||||||
|
screen_id id;
|
||||||
|
if (link.Read<screen_id>(&id) == B_OK) {
|
||||||
|
fLink.StartMessage(B_OK);
|
||||||
|
fLink.Attach<bool>(true);
|
||||||
|
} else
|
||||||
|
fLink.StartMessage(B_BAD_VALUE);
|
||||||
|
|
||||||
|
fLink.Flush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AS_UPDATE_COLORS:
|
case AS_UPDATE_COLORS:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -83,41 +83,64 @@ using std::nothrow;
|
|||||||
static struct profile { int32 count; bigtime_t time; } sMessageProfile[AS_LAST_CODE];
|
static struct profile { int32 count; bigtime_t time; } sMessageProfile[AS_LAST_CODE];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct dw_data {
|
|
||||||
sem_id direct_sem;
|
|
||||||
sem_id direct_sem_ack;
|
|
||||||
area_id direct_area;
|
|
||||||
direct_buffer_info *direct_info;
|
|
||||||
|
|
||||||
dw_data() :
|
struct direct_window_data {
|
||||||
direct_sem(-1),
|
direct_window_data();
|
||||||
direct_sem_ack(-1),
|
~direct_window_data();
|
||||||
direct_area(-1),
|
|
||||||
direct_info(NULL)
|
status_t InitCheck() const;
|
||||||
{
|
|
||||||
direct_area = create_area("direct area", (void **)&direct_info,
|
sem_id sem;
|
||||||
|
sem_id sem_ack;
|
||||||
|
area_id area;
|
||||||
|
bool started;
|
||||||
|
direct_buffer_info *buffer_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
direct_window_data::direct_window_data()
|
||||||
|
:
|
||||||
|
sem(-1),
|
||||||
|
sem_ack(-1),
|
||||||
|
area(-1),
|
||||||
|
started(false),
|
||||||
|
buffer_info(NULL)
|
||||||
|
{
|
||||||
|
area = create_area("direct area", (void **)&buffer_info,
|
||||||
B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE);
|
B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE);
|
||||||
|
|
||||||
direct_sem = create_sem(1, "direct sem");
|
sem = create_sem(0, "direct sem");
|
||||||
direct_sem_ack = create_sem(1, "direct sem ack");
|
sem_ack = create_sem(0, "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
|
direct_window_data::~direct_window_data()
|
||||||
{
|
{
|
||||||
return (direct_area >= 0) && (direct_sem >= 0)
|
// this should make the client die in case it's still running
|
||||||
&& (direct_sem_ack >= 0) && (direct_info != NULL);
|
buffer_info->bits = NULL;
|
||||||
}
|
buffer_info->bytes_per_row = 0;
|
||||||
};
|
|
||||||
|
delete_area(area);
|
||||||
|
delete_sem(sem);
|
||||||
|
delete_sem(sem_ack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
direct_window_data::InitCheck() const
|
||||||
|
{
|
||||||
|
if (area < B_OK)
|
||||||
|
return area;
|
||||||
|
if (sem < B_OK)
|
||||||
|
return sem;
|
||||||
|
if (sem_ack < B_OK)
|
||||||
|
return sem_ack;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -884,6 +907,29 @@ fDesktop->ReadLockWindows();
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BDirectWindow communication
|
||||||
|
|
||||||
|
case AS_DIRECT_WINDOW_GET_SYNC_DATA:
|
||||||
|
{
|
||||||
|
status_t status = _EnableDirectWindowMode();
|
||||||
|
if (status == B_OK) {
|
||||||
|
fLink.StartMessage(B_OK);
|
||||||
|
struct direct_window_sync_data syncData = {
|
||||||
|
fDirectWindowData->area,
|
||||||
|
fDirectWindowData->sem,
|
||||||
|
fDirectWindowData->sem_ack
|
||||||
|
};
|
||||||
|
|
||||||
|
fLink.Attach(&syncData, sizeof(syncData));
|
||||||
|
} else
|
||||||
|
fLink.StartMessage(status);
|
||||||
|
|
||||||
|
fLink.Flush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// View creation and destruction (don't need a valid fCurrentLayer)
|
||||||
|
|
||||||
case AS_SET_CURRENT_LAYER:
|
case AS_SET_CURRENT_LAYER:
|
||||||
{
|
{
|
||||||
int32 token;
|
int32 token;
|
||||||
@@ -1676,33 +1722,6 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BDirectWindow communication
|
|
||||||
|
|
||||||
case AS_DIRECT_WINDOW_SUPPORTS_WINDOW_MODE:
|
|
||||||
// TODO: How to determine this?
|
|
||||||
fLink.StartMessage(B_OK);
|
|
||||||
fLink.Attach<bool>(true);
|
|
||||||
fLink.Flush();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AS_DIRECT_WINDOW_GET_SYNC_DATA:
|
|
||||||
{
|
|
||||||
if (_EnableDirectWindowMode() == B_OK) {
|
|
||||||
fLink.StartMessage(B_OK);
|
|
||||||
struct direct_window_sync_data syncData = {
|
|
||||||
fDirectWindowData->direct_area,
|
|
||||||
fDirectWindowData->direct_sem,
|
|
||||||
fDirectWindowData->direct_sem_ack
|
|
||||||
};
|
|
||||||
|
|
||||||
fLink.Attach(&syncData, sizeof(syncData));
|
|
||||||
} else
|
|
||||||
fLink.StartMessage(B_ERROR);
|
|
||||||
|
|
||||||
fLink.Flush();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (fDesktop->ReadLockWindows()) {
|
if (fDesktop->ReadLockWindows()) {
|
||||||
_DispatchViewDrawingMessage(code, link);
|
_DispatchViewDrawingMessage(code, link);
|
||||||
@@ -2227,14 +2246,16 @@ ServerWindow::_EnableDirectWindowMode()
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
fDirectWindowData = new (nothrow) dw_data;
|
fDirectWindowData = new (nothrow) direct_window_data;
|
||||||
if (fDirectWindowData == NULL)
|
if (fDirectWindowData == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if (!fDirectWindowData->IsValid()) {
|
status_t status = fDirectWindowData->InitCheck();
|
||||||
|
if (status < B_OK) {
|
||||||
delete fDirectWindowData;
|
delete fDirectWindowData;
|
||||||
fDirectWindowData = NULL;
|
fDirectWindowData = NULL;
|
||||||
return B_ERROR;
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -2242,62 +2263,65 @@ ServerWindow::_EnableDirectWindowMode()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerWindow::HandleDirectConnection(int bufferState, int driverState)
|
ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState)
|
||||||
{
|
{
|
||||||
if (fDirectWindowData == NULL)
|
STRACE(("HandleDirectConnection(bufferState = %ld, driverState = %ld)\n",
|
||||||
|
bufferState, driverState));
|
||||||
|
|
||||||
|
if (fDirectWindowData == NULL
|
||||||
|
|| (!fDirectWindowData->started
|
||||||
|
&& (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START))
|
||||||
return;
|
return;
|
||||||
|
printf("bufferState = %ld\n", bufferState);
|
||||||
|
fDirectWindowData->started = true;
|
||||||
|
|
||||||
if (bufferState != -1)
|
if (bufferState != -1)
|
||||||
fDirectWindowData->direct_info->buffer_state = (direct_buffer_state)bufferState;
|
fDirectWindowData->buffer_info->buffer_state = (direct_buffer_state)bufferState;
|
||||||
|
|
||||||
if (driverState != -1)
|
if (driverState != -1)
|
||||||
fDirectWindowData->direct_info->driver_state = (direct_driver_state)driverState;
|
fDirectWindowData->buffer_info->driver_state = (direct_driver_state)driverState;
|
||||||
|
|
||||||
if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
|
if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
|
||||||
// TODO: Locking ?
|
// TODO: Locking ?
|
||||||
RenderingBuffer *buffer = fDesktop->HWInterface()->FrontBuffer();
|
RenderingBuffer *buffer = fDesktop->HWInterface()->FrontBuffer();
|
||||||
fDirectWindowData->direct_info->bits = buffer->Bits();
|
fDirectWindowData->buffer_info->bits = buffer->Bits();
|
||||||
fDirectWindowData->direct_info->pci_bits = NULL; // TODO
|
fDirectWindowData->buffer_info->pci_bits = NULL; // TODO
|
||||||
fDirectWindowData->direct_info->bytes_per_row = buffer->BytesPerRow();
|
fDirectWindowData->buffer_info->bytes_per_row = buffer->BytesPerRow();
|
||||||
fDirectWindowData->direct_info->bits_per_pixel = buffer->BytesPerRow() / buffer->Width() * 8;
|
fDirectWindowData->buffer_info->bits_per_pixel = buffer->BytesPerRow() / buffer->Width() * 8;
|
||||||
fDirectWindowData->direct_info->pixel_format = buffer->ColorSpace();
|
fDirectWindowData->buffer_info->pixel_format = buffer->ColorSpace();
|
||||||
fDirectWindowData->direct_info->layout = B_BUFFER_NONINTERLEAVED;
|
fDirectWindowData->buffer_info->layout = B_BUFFER_NONINTERLEAVED;
|
||||||
fDirectWindowData->direct_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO
|
fDirectWindowData->buffer_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO
|
||||||
|
|
||||||
WindowLayer *layer = const_cast<WindowLayer *>(GetWindowLayer());
|
WindowLayer *layer = const_cast<WindowLayer *>(GetWindowLayer());
|
||||||
fDirectWindowData->direct_info->window_bounds = to_clipping_rect(layer->Frame());
|
fDirectWindowData->buffer_info->window_bounds = to_clipping_rect(layer->Frame());
|
||||||
|
|
||||||
// TODO: Review this
|
// TODO: Review this
|
||||||
const int32 kMaxClipRectsCount = (B_PAGE_SIZE - sizeof(direct_buffer_info))
|
const int32 kMaxClipRectsCount = (B_PAGE_SIZE - sizeof(direct_buffer_info))
|
||||||
/ sizeof(clipping_rect);
|
/ sizeof(clipping_rect);
|
||||||
|
|
||||||
// TODO: Is there a simpler way to obtain this result ?
|
// We just want the region inside the window, border excluded.
|
||||||
// We just want the region INSIDE the window, border excluded.
|
BRegion clipRegion = fWindowLayer->VisibleContentRegion();
|
||||||
BRegion clipRegion;
|
clipRegion.PrintToStream();
|
||||||
// TODO: fix HandleDirectConnection()
|
|
||||||
/* = const_cast<BRegion &>(layer->FullVisible());
|
|
||||||
BRegion exclude = const_cast<BRegion &>(layer->VisibleRegion());
|
|
||||||
clipRegion.Exclude(&exclude);
|
|
||||||
*/
|
|
||||||
fDirectWindowData->direct_info->clip_list_count = min_c(clipRegion.CountRects(),
|
|
||||||
kMaxClipRectsCount);
|
|
||||||
fDirectWindowData->direct_info->clip_bounds = clipRegion.FrameInt();
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < fDirectWindowData->direct_info->clip_list_count; i++)
|
fDirectWindowData->buffer_info->clip_list_count = min_c(clipRegion.CountRects(),
|
||||||
fDirectWindowData->direct_info->clip_list[i] = clipRegion.RectAtInt(i);
|
kMaxClipRectsCount);
|
||||||
|
fDirectWindowData->buffer_info->clip_bounds = clipRegion.FrameInt();
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < fDirectWindowData->buffer_info->clip_list_count; i++)
|
||||||
|
fDirectWindowData->buffer_info->clip_list[i] = clipRegion.RectAtInt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Releasing this sem causes the client to call BDirectWindow::DirectConnected()
|
// Releasing this sem causes the client to call BDirectWindow::DirectConnected()
|
||||||
release_sem(fDirectWindowData->direct_sem);
|
release_sem(fDirectWindowData->sem);
|
||||||
|
|
||||||
// TODO: Waiting half a second in this thread is not a problem,
|
// TODO: Waiting half a second in the ServerWindow thread is not a problem,
|
||||||
// but since we are called from the RootLayer's thread too, very bad things could happen.
|
// but since we are called from the Desktop's thread too, very bad things could happen.
|
||||||
// Find some way to call this method only within ServerWindow's thread (messaging ?)
|
// Find some way to call this method only within ServerWindow's thread (messaging ?)
|
||||||
status_t status;
|
status_t status;
|
||||||
do {
|
do {
|
||||||
// TODO: The timeout is 3000000 usecs (3 seconds) on beos.
|
// TODO: The timeout is 3000000 usecs (3 seconds) on beos.
|
||||||
// Test, but I think half a second is enough.
|
// Test, but I think half a second is enough.
|
||||||
status = acquire_sem_etc(fDirectWindowData->direct_sem_ack, 1, B_TIMEOUT, 500000);
|
status = acquire_sem_etc(fDirectWindowData->sem_ack, 1, B_TIMEOUT, 500000);
|
||||||
} while (status == B_INTERRUPTED);
|
} while (status == B_INTERRUPTED);
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class WindowLayer;
|
|||||||
class Workspace;
|
class Workspace;
|
||||||
class ViewLayer;
|
class ViewLayer;
|
||||||
class ServerPicture;
|
class ServerPicture;
|
||||||
struct dw_data;
|
struct direct_window_data;
|
||||||
struct window_info;
|
struct window_info;
|
||||||
|
|
||||||
#define AS_UPDATE_DECORATOR 'asud'
|
#define AS_UPDATE_DECORATOR 'asud'
|
||||||
@@ -96,8 +96,8 @@ public:
|
|||||||
// related thread/team_id(s).
|
// related thread/team_id(s).
|
||||||
inline team_id ClientTeam() const { return fClientTeam; }
|
inline team_id ClientTeam() const { return fClientTeam; }
|
||||||
|
|
||||||
void HandleDirectConnection(int bufferState = -1,
|
void HandleDirectConnection(int32 bufferState = -1,
|
||||||
int driverState = -1);
|
int32 driverState = -1);
|
||||||
|
|
||||||
inline int32 ClientToken() const { return fClientToken; }
|
inline int32 ClientToken() const { return fClientToken; }
|
||||||
inline int32 ServerToken() const { return fServerToken; }
|
inline int32 ServerToken() const { return fServerToken; }
|
||||||
@@ -158,7 +158,7 @@ private:
|
|||||||
BRegion fCurrentDrawingRegion;
|
BRegion fCurrentDrawingRegion;
|
||||||
bool fCurrentDrawingRegionValid;
|
bool fCurrentDrawingRegionValid;
|
||||||
|
|
||||||
dw_data* fDirectWindowData;
|
direct_window_data* fDirectWindowData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SERVER_WINDOW_H
|
#endif // SERVER_WINDOW_H
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ WindowLayer::ReadUnlockWindows()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClipping
|
|
||||||
void
|
void
|
||||||
WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
||||||
{
|
{
|
||||||
@@ -201,10 +201,11 @@ WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
|||||||
fVisibleContentRegionValid = false;
|
fVisibleContentRegionValid = false;
|
||||||
fEffectiveDrawingRegionValid = false;
|
fEffectiveDrawingRegionValid = false;
|
||||||
|
|
||||||
// TODO: Window()->HandleDirectConnection(B_DIRECT_MODIFY | B_CLIPPING_MODIFIED);
|
// TODO: review this!
|
||||||
|
fWindow->HandleDirectConnection(B_DIRECT_MODIFY | B_CLIPPING_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFullRegion
|
|
||||||
void
|
void
|
||||||
WindowLayer::GetFullRegion(BRegion* region)
|
WindowLayer::GetFullRegion(BRegion* region)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user