diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 14cf2646b8..21a8cc8452 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -430,18 +430,36 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) } case AS_GET_WINDOW_LIST: + { team_id team; link.Read(&team); fDesktop->WriteWindowList(team, fLink.Sender()); break; + } case AS_GET_WINDOW_INFO: + { int32 serverToken; link.Read(&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(&id) == B_OK) { + fLink.StartMessage(B_OK); + fLink.Attach(true); + } else + fLink.StartMessage(B_BAD_VALUE); + + fLink.Flush(); + break; + } case AS_UPDATE_COLORS: { diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index fbe3d18804..8d530b0dd6 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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(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(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(layer->FullVisible()); - BRegion exclude = const_cast(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) { diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index e75a247331..11e868ecea 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -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 diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index a83edd94b3..5ade42170c 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -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) {