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:
parent
bd09e99dbd
commit
bff84e78b7
@ -430,18 +430,36 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
}
|
||||
|
||||
case AS_GET_WINDOW_LIST:
|
||||
{
|
||||
team_id team;
|
||||
link.Read<team_id>(&team);
|
||||
|
||||
fDesktop->WriteWindowList(team, fLink.Sender());
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_GET_WINDOW_INFO:
|
||||
{
|
||||
int32 serverToken;
|
||||
link.Read<int32>(&serverToken);
|
||||
|
||||
fDesktop->WriteWindowInfo(serverToken, fLink.Sender());
|
||||
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:
|
||||
{
|
||||
|
@ -83,43 +83,66 @@ using std::nothrow;
|
||||
static struct profile { int32 count; bigtime_t time; } sMessageProfile[AS_LAST_CODE];
|
||||
#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_info(NULL)
|
||||
{
|
||||
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) && (direct_info != NULL);
|
||||
}
|
||||
|
||||
struct direct_window_data {
|
||||
direct_window_data();
|
||||
~direct_window_data();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
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);
|
||||
|
||||
sem = create_sem(0, "direct sem");
|
||||
sem_ack = create_sem(0, "direct sem ack");
|
||||
}
|
||||
|
||||
|
||||
direct_window_data::~direct_window_data()
|
||||
{
|
||||
// this should make the client die in case it's still running
|
||||
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 -
|
||||
|
||||
|
||||
/*!
|
||||
Sets up the basic BWindow counterpart - you have to call Init() before
|
||||
you can actually use it, though.
|
||||
@ -884,6 +907,29 @@ fDesktop->ReadLockWindows();
|
||||
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:
|
||||
{
|
||||
int32 token;
|
||||
@ -1676,33 +1722,6 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
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:
|
||||
if (fDesktop->ReadLockWindows()) {
|
||||
_DispatchViewDrawingMessage(code, link);
|
||||
@ -2227,14 +2246,16 @@ ServerWindow::_EnableDirectWindowMode()
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fDirectWindowData = new (nothrow) dw_data;
|
||||
fDirectWindowData = new (nothrow) direct_window_data;
|
||||
if (fDirectWindowData == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (!fDirectWindowData->IsValid()) {
|
||||
status_t status = fDirectWindowData->InitCheck();
|
||||
if (status < B_OK) {
|
||||
delete fDirectWindowData;
|
||||
fDirectWindowData = NULL;
|
||||
return B_ERROR;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -2242,62 +2263,65 @@ ServerWindow::_EnableDirectWindowMode()
|
||||
|
||||
|
||||
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;
|
||||
|
||||
printf("bufferState = %ld\n", bufferState);
|
||||
fDirectWindowData->started = true;
|
||||
|
||||
if (bufferState != -1)
|
||||
fDirectWindowData->direct_info->buffer_state = (direct_buffer_state)bufferState;
|
||||
|
||||
fDirectWindowData->buffer_info->buffer_state = (direct_buffer_state)bufferState;
|
||||
|
||||
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) {
|
||||
// TODO: Locking ?
|
||||
RenderingBuffer *buffer = fDesktop->HWInterface()->FrontBuffer();
|
||||
fDirectWindowData->direct_info->bits = buffer->Bits();
|
||||
fDirectWindowData->direct_info->pci_bits = NULL; // TODO
|
||||
fDirectWindowData->direct_info->bytes_per_row = buffer->BytesPerRow();
|
||||
fDirectWindowData->direct_info->bits_per_pixel = buffer->BytesPerRow() / buffer->Width() * 8;
|
||||
fDirectWindowData->direct_info->pixel_format = buffer->ColorSpace();
|
||||
fDirectWindowData->direct_info->layout = B_BUFFER_NONINTERLEAVED;
|
||||
fDirectWindowData->direct_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO
|
||||
|
||||
fDirectWindowData->buffer_info->bits = buffer->Bits();
|
||||
fDirectWindowData->buffer_info->pci_bits = NULL; // TODO
|
||||
fDirectWindowData->buffer_info->bytes_per_row = buffer->BytesPerRow();
|
||||
fDirectWindowData->buffer_info->bits_per_pixel = buffer->BytesPerRow() / buffer->Width() * 8;
|
||||
fDirectWindowData->buffer_info->pixel_format = buffer->ColorSpace();
|
||||
fDirectWindowData->buffer_info->layout = B_BUFFER_NONINTERLEAVED;
|
||||
fDirectWindowData->buffer_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO
|
||||
|
||||
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
|
||||
const int32 kMaxClipRectsCount = (B_PAGE_SIZE - sizeof(direct_buffer_info))
|
||||
/ sizeof(clipping_rect);
|
||||
|
||||
// TODO: Is there a simpler way to obtain this result ?
|
||||
// We just want the region INSIDE the window, border excluded.
|
||||
BRegion clipRegion;
|
||||
// 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();
|
||||
// We just want the region inside the window, border excluded.
|
||||
BRegion clipRegion = fWindowLayer->VisibleContentRegion();
|
||||
clipRegion.PrintToStream();
|
||||
|
||||
for (uint32 i = 0; i < fDirectWindowData->direct_info->clip_list_count; i++)
|
||||
fDirectWindowData->direct_info->clip_list[i] = clipRegion.RectAtInt(i);
|
||||
fDirectWindowData->buffer_info->clip_list_count = min_c(clipRegion.CountRects(),
|
||||
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()
|
||||
release_sem(fDirectWindowData->direct_sem);
|
||||
release_sem(fDirectWindowData->sem);
|
||||
|
||||
// TODO: Waiting half a second in this thread is not a problem,
|
||||
// but since we are called from the RootLayer's thread too, very bad things could happen.
|
||||
// TODO: Waiting half a second in the ServerWindow thread is not a problem,
|
||||
// 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 ?)
|
||||
status_t status;
|
||||
do {
|
||||
// TODO: The timeout is 3000000 usecs (3 seconds) on beos.
|
||||
// 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);
|
||||
|
||||
if (status < B_OK) {
|
||||
|
@ -39,7 +39,7 @@ class WindowLayer;
|
||||
class Workspace;
|
||||
class ViewLayer;
|
||||
class ServerPicture;
|
||||
struct dw_data;
|
||||
struct direct_window_data;
|
||||
struct window_info;
|
||||
|
||||
#define AS_UPDATE_DECORATOR 'asud'
|
||||
@ -96,8 +96,8 @@ public:
|
||||
// related thread/team_id(s).
|
||||
inline team_id ClientTeam() const { return fClientTeam; }
|
||||
|
||||
void HandleDirectConnection(int bufferState = -1,
|
||||
int driverState = -1);
|
||||
void HandleDirectConnection(int32 bufferState = -1,
|
||||
int32 driverState = -1);
|
||||
|
||||
inline int32 ClientToken() const { return fClientToken; }
|
||||
inline int32 ServerToken() const { return fServerToken; }
|
||||
@ -158,7 +158,7 @@ private:
|
||||
BRegion fCurrentDrawingRegion;
|
||||
bool fCurrentDrawingRegionValid;
|
||||
|
||||
dw_data* fDirectWindowData;
|
||||
direct_window_data* fDirectWindowData;
|
||||
};
|
||||
|
||||
#endif // SERVER_WINDOW_H
|
||||
|
@ -187,7 +187,7 @@ WindowLayer::ReadUnlockWindows()
|
||||
}
|
||||
}
|
||||
|
||||
// SetClipping
|
||||
|
||||
void
|
||||
WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
||||
{
|
||||
@ -201,10 +201,11 @@ WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
||||
fVisibleContentRegionValid = 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
|
||||
WindowLayer::GetFullRegion(BRegion* region)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user