* Reenabled direct window mode, ie. reverted r32693.

* Fixed warnings with DEBUG enabled.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32740 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-08-27 08:39:48 +00:00
parent 050ad934be
commit 2c704682c4
+104 -91
View File
@@ -1,13 +1,18 @@
/* /*
* Copyright 2003-2008, Haiku Inc. * Copyright 2003-2009, Haiku Inc.
* Authors: * Authors:
* Stefano Ceccherini <[email protected]> * Stefano Ceccherini <[email protected]>
* Carwyn Jones <[email protected]> * Carwyn Jones <[email protected]>
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <DirectWindow.h> #include <DirectWindow.h>
#include <stdio.h>
#include <string.h>
#include <Screen.h> #include <Screen.h>
#include <clipping.h> #include <clipping.h>
@@ -15,13 +20,13 @@
#include <DirectWindowPrivate.h> #include <DirectWindowPrivate.h>
#include <ServerProtocol.h> #include <ServerProtocol.h>
#include <stdio.h>
#include <string.h>
//#define DEBUG 1 //#define DEBUG 1
#define OUTPUT printf
//#define OUTPUT debug_printf
// We don't need this kind of locking, since the directDaemonFunc // We don't need this kind of locking, since the directDaemonFunc
// doesn't access critical shared data. // doesn't access critical shared data.
#define DW_NEEDS_LOCKING 0 #define DW_NEEDS_LOCKING 0
@@ -33,6 +38,8 @@ enum dw_status_bits {
#if DEBUG #if DEBUG
static void static void
print_direct_buffer_state(const direct_buffer_state &state) print_direct_buffer_state(const direct_buffer_state &state)
{ {
@@ -41,7 +48,7 @@ print_direct_buffer_state(const direct_buffer_state &state)
if (modeState == B_DIRECT_START) if (modeState == B_DIRECT_START)
strcpy(string, "B_DIRECT_START"); strcpy(string, "B_DIRECT_START");
else if (modeState == B_DIRECT_MODIFY) else if (modeState == B_DIRECT_MODIFY)
strcpy(string, "B_DIRECT_MODIFY"); strcpy(string, "B_DIRECT_MODIFY");
else if (modeState == B_DIRECT_STOP) else if (modeState == B_DIRECT_STOP)
strcpy(string, "B_DIRECT_STOP"); strcpy(string, "B_DIRECT_STOP");
@@ -53,8 +60,8 @@ print_direct_buffer_state(const direct_buffer_state &state)
strcat(string, " | B_BUFFER_MOVED"); strcat(string, " | B_BUFFER_MOVED");
if (state & B_BUFFER_RESET) if (state & B_BUFFER_RESET)
strcat(string, " | B_BUFFER_RESET"); strcat(string, " | B_BUFFER_RESET");
printf("direct_buffer_state: %s\n", string); OUTPUT("direct_buffer_state: %s\n", string);
} }
@@ -66,30 +73,33 @@ print_direct_driver_state(const direct_driver_state &state)
char string[64]; char string[64];
if (state == B_DRIVER_CHANGED) if (state == B_DRIVER_CHANGED)
strcpy(string, "B_DRIVER_CHANGED"); strcpy(string, "B_DRIVER_CHANGED");
else if (state == B_MODE_CHANGED) else if (state == B_MODE_CHANGED)
strcpy(string, "B_MODE_CHANGED"); strcpy(string, "B_MODE_CHANGED");
printf("direct_driver_state: %s\n", string); OUTPUT("direct_driver_state: %s\n", string);
} }
#if DEBUG > 1
static void static void
print_direct_buffer_layout(const buffer_layout &layout) print_direct_buffer_layout(const buffer_layout &layout)
{ {
char string[64]; char string[64];
if (layout == B_BUFFER_NONINTERLEAVED) if (layout == B_BUFFER_NONINTERLEAVED)
strcpy(string, "B_BUFFER_NONINTERLEAVED"); strcpy(string, "B_BUFFER_NONINTERLEAVED");
else else
strcpy(string, "unknown"); strcpy(string, "unknown");
printf("layout: %s\n", string); OUTPUT("layout: %s\n", string);
} }
static void static void
print_direct_buffer_orientation(const buffer_orientation &orientation) print_direct_buffer_orientation(const buffer_orientation &orientation)
{ {
char string[64]; char string[64];
switch (orientation) { switch (orientation) {
case B_BUFFER_TOP_TO_BOTTOM: case B_BUFFER_TOP_TO_BOTTOM:
@@ -102,61 +112,71 @@ print_direct_buffer_orientation(const buffer_orientation &orientation)
strcpy(string, "unknown"); strcpy(string, "unknown");
break; break;
} }
printf("orientation: %s\n", string); OUTPUT("orientation: %s\n", string);
} }
#endif // DEBUG > 2
static void static void
print_direct_buffer_info(const direct_buffer_info &info) print_direct_buffer_info(const direct_buffer_info &info)
{ {
print_direct_buffer_state(info.buffer_state); print_direct_buffer_state(info.buffer_state);
print_direct_driver_state(info.driver_state); print_direct_driver_state(info.driver_state);
#if DEBUG > 1 # if DEBUG > 1
printf("bits: %p\n", info.bits); OUTPUT("bits: %p\n", info.bits);
printf("pci_bits: %p\n", info.pci_bits); OUTPUT("pci_bits: %p\n", info.pci_bits);
printf("bytes_per_row: %ld\n", info.bytes_per_row); OUTPUT("bytes_per_row: %ld\n", info.bytes_per_row);
printf("bits_per_pixel: %lu\n", info.bits_per_pixel); OUTPUT("bits_per_pixel: %lu\n", info.bits_per_pixel);
printf("pixel_format: %d\n", info.pixel_format); OUTPUT("pixel_format: %d\n", info.pixel_format);
print_direct_buffer_layout(info.layout); print_direct_buffer_layout(info.layout);
print_direct_buffer_orientation(info.orientation); print_direct_buffer_orientation(info.orientation);
#if DEBUG > 2 # if DEBUG > 2
// TODO: this won't work correctly with debug_printf()
printf("CLIPPING INFO:\n"); printf("CLIPPING INFO:\n");
printf("clipping_rects count: %ld\n", info.clip_list_count); printf("clipping_rects count: %ld\n", info.clip_list_count);
printf("- window_bounds:\n"); printf("- window_bounds:\n");
BRegion region; BRegion region;
region.Set(info.window_bounds); region.Set(info.window_bounds);
region.PrintToStream(); region.PrintToStream();
region.MakeEmpty(); region.MakeEmpty();
for (uint32 i = 0; i < info.clip_list_count; i++) for (uint32 i = 0; i < info.clip_list_count; i++)
region.Include(info.clip_list[i]); region.Include(info.clip_list[i]);
printf("- clip_list:\n"); printf("- clip_list:\n");
region.PrintToStream(); region.PrintToStream();
#endif # endif
#endif # endif
printf("\n\n"); OUTPUT("\n");
} }
#endif
#endif // DEBUG
// #pragma mark -
BDirectWindow::BDirectWindow(BRect frame, const char *title, window_type type, BDirectWindow::BDirectWindow(BRect frame, const char *title, window_type type,
uint32 flags, uint32 workspace) uint32 flags, uint32 workspace)
: BWindow(frame, title, type, flags, workspace) :
BWindow(frame, title, type, flags, workspace)
{ {
_InitData(); _InitData();
} }
BDirectWindow::BDirectWindow(BRect frame, const char *title, window_look look, BDirectWindow::BDirectWindow(BRect frame, const char *title, window_look look,
window_feel feel, uint32 flags, uint32 workspace) window_feel feel, uint32 flags, uint32 workspace)
: BWindow(frame, title, look, feel, flags, workspace) :
BWindow(frame, title, look, feel, flags, workspace)
{ {
_InitData(); _InitData();
} }
@@ -168,7 +188,9 @@ BDirectWindow::~BDirectWindow()
} }
// start of regular BWindow API // #pragma mark - BWindow API implementation
BArchivable * BArchivable *
BDirectWindow::Instantiate(BMessage *data) BDirectWindow::Instantiate(BMessage *data)
{ {
@@ -270,7 +292,7 @@ BDirectWindow::MenusEnded()
void void
BDirectWindow::WindowActivated(bool state) BDirectWindow::WindowActivated(bool state)
{ {
inherited::WindowActivated(state); inherited::WindowActivated(state);
} }
@@ -330,7 +352,6 @@ BDirectWindow::ConvertToMessage(void *raw, int32 code)
void void
BDirectWindow::DirectConnected(direct_buffer_info *info) BDirectWindow::DirectConnected(direct_buffer_info *info)
{ {
fprintf(stderr, "BDirectWindow::DirectConnected(): should not be ever called!!!!\n");
// implemented in subclasses // implemented in subclasses
} }
@@ -343,12 +364,12 @@ BDirectWindow::GetClippingRegion(BRegion *region, BPoint *origin) const
if (IsLocked() || !_LockDirect()) if (IsLocked() || !_LockDirect())
return B_ERROR; return B_ERROR;
if (fInDirectConnect) { if (fInDirectConnect) {
_UnlockDirect(); _UnlockDirect();
return B_ERROR; return B_ERROR;
} }
// BPoint's coordinates are floats. We can only work // BPoint's coordinates are floats. We can only work
// with integers._DaemonStarter // with integers._DaemonStarter
int32 originX, originY; int32 originX, originY;
@@ -376,8 +397,8 @@ BDirectWindow::GetClippingRegion(BRegion *region, BPoint *origin) const
fBufferDesc->clip_list[c]); fBufferDesc->clip_list[c]);
} }
// adjust bounds by the given origin point // adjust bounds by the given origin point
region->OffsetBy(-originX, -originY); region->OffsetBy(-originX, -originY);
#endif #endif
_UnlockDirect(); _UnlockDirect();
@@ -415,30 +436,22 @@ BDirectWindow::IsFullScreen() const
} }
/*static*/ /*static*/ bool
bool
BDirectWindow::SupportsWindowMode(screen_id id) BDirectWindow::SupportsWindowMode(screen_id id)
{ {
/* display_mode mode; display_mode mode;
status_t status = BScreen(id).GetMode(&mode); status_t status = BScreen(id).GetMode(&mode);
if (status == B_OK) if (status == B_OK)
return mode.flags & B_PARALLEL_ACCESS; return (mode.flags & B_PARALLEL_ACCESS) != 0;
return false;*/
// TODO: Apparently, the above is false for the vesa driver,
// but enabling it doesn't do any harm... maybe we should just return always true.
// At least, I can't see why window mode shouldn't be supported.
// additional NOTE: it probably depends on wether hardware cursor is supported or
// not
return false; return false;
// TODO: For now
} }
// #pragma mark - Private methods // #pragma mark - Private methods
/* static */
int32 /*static*/ int32
BDirectWindow::_daemon_thread(void *arg) BDirectWindow::_daemon_thread(void *arg)
{ {
return static_cast<BDirectWindow *>(arg)->_DirectDaemon(); return static_cast<BDirectWindow *>(arg)->_DirectDaemon();
@@ -457,9 +470,8 @@ BDirectWindow::_DirectDaemon()
status = acquire_sem(fDisableSem); status = acquire_sem(fDisableSem);
} while (status == B_INTERRUPTED); } while (status == B_INTERRUPTED);
if (status < B_OK) { if (status != B_OK) {
fprintf(stderr, fprintf(stderr, "DirectDaemon: failed to acquire direct sem: %s\n",
"DirectDaemon: failed to acquire direct sem\n",
strerror(status)); strerror(status));
return -1; return -1;
} }
@@ -469,14 +481,16 @@ BDirectWindow::_DirectDaemon()
#endif #endif
if (_LockDirect()) { if (_LockDirect()) {
if ((fBufferDesc->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_START) if ((fBufferDesc->buffer_state & B_DIRECT_MODE_MASK)
== B_DIRECT_START)
fConnectionEnable = true; fConnectionEnable = true;
fInDirectConnect = true; fInDirectConnect = true;
DirectConnected(fBufferDesc); DirectConnected(fBufferDesc);
fInDirectConnect = false; fInDirectConnect = false;
if ((fBufferDesc->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP) if ((fBufferDesc->buffer_state & B_DIRECT_MODE_MASK)
== B_DIRECT_STOP)
fConnectionEnable = false; fConnectionEnable = false;
_UnlockDirect(); _UnlockDirect();
@@ -486,8 +500,7 @@ BDirectWindow::_DirectDaemon()
// If we aren't quick enough to release this sem, our app // If we aren't quick enough to release this sem, our app
// will be terminated by the app_server // will be terminated by the app_server
if ((status = release_sem(fDisableSemAck)) != B_OK) { if ((status = release_sem(fDisableSemAck)) != B_OK) {
fprintf(stderr, fprintf(stderr, "DirectDaemon: failed to release sem: %s\n",
"DirectDaemon: failed to release sem: (%s)\n",
strerror(status)); strerror(status));
return -1; return -1;
} }
@@ -497,24 +510,25 @@ BDirectWindow::_DirectDaemon()
} }
// LockDirect() and UnlockDirect() are no-op on R5. I tried to call (R5's) LockDirect()
// repeatedly, from the same thread and from different threads, nothing happened.
// They're not needed though, as the direct_daemon_thread doesn't change
// any shared data. They are probably here for future enhancements
bool bool
BDirectWindow::_LockDirect() const BDirectWindow::_LockDirect() const
{ {
// LockDirect() and UnlockDirect() are no-op on BeOS. I tried to call BeOS's
// version repeatedly, from the same thread and from different threads,
// nothing happened.
// They're not needed though, as the direct_daemon_thread doesn't change
// any shared data. They are probably here for future enhancements.
status_t status = B_OK; status_t status = B_OK;
#if DW_NEEDS_LOCKING #if DW_NEEDS_LOCKING
BDirectWindow *casted = const_cast<BDirectWindow *>(this); BDirectWindow *casted = const_cast<BDirectWindow *>(this);
if (atomic_add(&casted->fDirectLock, 1) > 0) { if (atomic_add(&casted->fDirectLock, 1) > 0) {
do { do {
status = acquire_sem(casted->fDirectSem); status = acquire_sem(casted->fDirectSem);
} while (status == B_INTERRUPTED); } while (status == B_INTERRUPTED);
} }
if (status == B_OK) { if (status == B_OK) {
casted->fDirectLockOwner = find_thread(NULL); casted->fDirectLockOwner = find_thread(NULL);
casted->fDirectLockCount++; casted->fDirectLockCount++;
@@ -530,10 +544,10 @@ BDirectWindow::_UnlockDirect() const
{ {
#if DW_NEEDS_LOCKING #if DW_NEEDS_LOCKING
BDirectWindow *casted = const_cast<BDirectWindow *>(this); BDirectWindow *casted = const_cast<BDirectWindow *>(this);
if (atomic_add(&casted->fDirectLock, -1) > 1) if (atomic_add(&casted->fDirectLock, -1) > 1)
release_sem(casted->fDirectSem); release_sem(casted->fDirectSem);
casted->fDirectLockCount--; casted->fDirectLockCount--;
#endif #endif
} }
@@ -545,23 +559,22 @@ BDirectWindow::_InitData()
fConnectionEnable = false; fConnectionEnable = false;
fIsFullScreen = false; fIsFullScreen = false;
fInDirectConnect = false; fInDirectConnect = false;
fInitStatus = 0; fInitStatus = 0;
status_t status = B_ERROR; status_t status = B_ERROR;
struct direct_window_sync_data syncData; struct direct_window_sync_data syncData;
if (Lock()) { if (Lock()) {
fLink->StartMessage(AS_DIRECT_WINDOW_GET_SYNC_DATA); fLink->StartMessage(AS_DIRECT_WINDOW_GET_SYNC_DATA);
if (fLink->FlushWithReply(status) == B_OK if (fLink->FlushWithReply(status) == B_OK && status == B_OK)
&& status == B_OK) {
fLink->Read<direct_window_sync_data>(&syncData); fLink->Read<direct_window_sync_data>(&syncData);
}
Unlock(); Unlock();
} }
if (status < B_OK) if (status < B_OK)
return; return;
#if DW_NEEDS_LOCKING #if DW_NEEDS_LOCKING
fDirectLock = 0; fDirectLock = 0;
fDirectLockCount = 0; fDirectLockCount = 0;
fDirectLockOwner = -1; fDirectLockOwner = -1;
@@ -569,20 +582,20 @@ BDirectWindow::_InitData()
fDirectSem = create_sem(0, "direct sem"); fDirectSem = create_sem(0, "direct sem");
if (fDirectSem > 0) if (fDirectSem > 0)
fInitStatus |= DW_STATUS_SEM_CREATED; fInitStatus |= DW_STATUS_SEM_CREATED;
#endif #endif
fSourceClippingArea = syncData.area; fSourceClippingArea = syncData.area;
fDisableSem = syncData.disable_sem; fDisableSem = syncData.disable_sem;
fDisableSemAck = syncData.disable_sem_ack; fDisableSemAck = syncData.disable_sem_ack;
fClonedClippingArea = clone_area("cloned direct area", (void**)&fBufferDesc, fClonedClippingArea = clone_area("cloned direct area", (void**)&fBufferDesc,
B_ANY_ADDRESS, B_READ_AREA, fSourceClippingArea); B_ANY_ADDRESS, B_READ_AREA, fSourceClippingArea);
if (fClonedClippingArea > 0) { if (fClonedClippingArea > 0) {
fInitStatus |= DW_STATUS_AREA_CLONED; fInitStatus |= DW_STATUS_AREA_CLONED;
fDirectDaemonId = spawn_thread(_daemon_thread, "direct daemon", fDirectDaemonId = spawn_thread(_daemon_thread, "direct daemon",
B_DISPLAY_PRIORITY, this); B_DISPLAY_PRIORITY, this);
if (fDirectDaemonId > 0) { if (fDirectDaemonId > 0) {
fDaemonKiller = false; fDaemonKiller = false;
@@ -603,9 +616,9 @@ BDirectWindow::_DisposeData()
// notification, or bad things will happen // notification, or bad things will happen
while (fConnectionEnable) while (fConnectionEnable)
snooze(50000); snooze(50000);
_LockDirect(); _LockDirect();
if (fInitStatus & DW_STATUS_THREAD_STARTED) { if (fInitStatus & DW_STATUS_THREAD_STARTED) {
fDaemonKiller = true; fDaemonKiller = true;
// delete this sem, otherwise the Direct daemon thread // delete this sem, otherwise the Direct daemon thread
@@ -614,11 +627,11 @@ BDirectWindow::_DisposeData()
status_t retVal; status_t retVal;
wait_for_thread(fDirectDaemonId, &retVal); wait_for_thread(fDirectDaemonId, &retVal);
} }
#if DW_NEEDS_LOCKING #if DW_NEEDS_LOCKING
if (fInitStatus & DW_STATUS_SEM_CREATED) if (fInitStatus & DW_STATUS_SEM_CREATED)
delete_sem(fDirectSem); delete_sem(fDirectSem);
#endif #endif
if (fInitStatus & DW_STATUS_AREA_CLONED) if (fInitStatus & DW_STATUS_AREA_CLONED)
delete_area(fClonedClippingArea); delete_area(fClonedClippingArea);