BDirectWindow: Clone the framebuffer from app_server, if necessary.

This paves the way for accelerants to map the framebuffer in
user memory, not kernel memory. It uses the ServerMemoryAllocator
in order to avoid mapping the framebuffer multiple times in
client applications.

While at it, clean up some names.

Tested with DirectWindowStars and GLTeapot, both work.

Change-Id: I4e0c003fae99891044af0a5e6e1d6a4506da6430
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10571
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Augustin Cavalier
2026-03-24 14:01:11 +00:00
committed by waddlesplash
parent ede14380e5
commit f6be811473
5 changed files with 66 additions and 24 deletions
+7 -8
View File
@@ -35,15 +35,14 @@ typedef struct {
direct_buffer_state buffer_state;
direct_driver_state driver_state;
void *bits;
void *pci_bits;
addr_t _reserved; // was pci_bits
int32 bytes_per_row;
uint32 bits_per_pixel;
color_space pixel_format;
buffer_layout layout;
buffer_orientation orientation;
uint32 _reserved[9];
uint32 _dd_type_;
uint32 _dd_token_;
area_id bits_area;
uint32 _reserved1[10];
uint32 clip_list_count;
clipping_rect window_bounds;
clipping_rect clip_bounds;
@@ -141,7 +140,7 @@ private:
bool fConnectionEnable;
bool fIsFullScreen;
bool _unused;
bool fInDirectConnect;
bool fInDirectConnected;
int32 fDirectLock;
sem_id fDirectSem;
uint32 fDirectLockCount;
@@ -151,12 +150,12 @@ private:
sem_id fDisableSemAck;
uint32 fInitStatus;
uint32 fInfoAreaSize;
uint32 _reserved[2];
area_id fClonedClippingArea;
area_id fSourceClippingArea;
area_id fSourceDirectArea;
area_id fClonedDirectArea;
area_id fSourceBitsArea;
thread_id fDirectDaemonId;
direct_buffer_info* fBufferDesc;
+33 -10
View File
@@ -17,8 +17,10 @@
#include <clipping.h>
#include <AppServerLink.h>
#include <ApplicationPrivate.h>
#include <DirectWindowPrivate.h>
#include <ServerProtocol.h>
#include <ServerMemoryAllocator.h>
//#define DEBUG 1
@@ -128,7 +130,6 @@ print_direct_buffer_info(const direct_buffer_info &info)
# if DEBUG > 1
OUTPUT("bits: %p\n", info.bits);
OUTPUT("pci_bits: %p\n", info.pci_bits);
OUTPUT("bytes_per_row: %ld\n", info.bytes_per_row);
OUTPUT("bits_per_pixel: %lu\n", info.bits_per_pixel);
OUTPUT("pixel_format: %d\n", info.pixel_format);
@@ -366,7 +367,7 @@ BDirectWindow::GetClippingRegion(BRegion* region, BPoint* origin) const
if (IsLocked() || !_LockDirect())
return B_ERROR;
if (!fInDirectConnect) {
if (!fInDirectConnected) {
_UnlockDirect();
return B_ERROR;
}
@@ -486,9 +487,29 @@ BDirectWindow::_DirectDaemon()
== B_DIRECT_START)
fConnectionEnable = true;
fInDirectConnect = true;
if (fBufferDesc->bits == NULL) {
// (re-)clone the bits area
BPrivate::AppServerLink linkLocker;
// protects ServerAllocator
BPrivate::ServerMemoryAllocator* allocator
= BApplication::Private::ServerAllocator();
allocator->RemoveArea(fSourceBitsArea);
area_id localArea;
uint8* bits;
status_t status = allocator->AddArea(fBufferDesc->bits_area,
localArea, bits, (size_t)-1);
if (status != B_OK) {
_UnlockDirect();
return -1;
}
fBufferDesc->bits = (void*)bits;
fSourceBitsArea = fBufferDesc->bits_area;
}
fInDirectConnected = true;
DirectConnected(fBufferDesc);
fInDirectConnect = false;
fInDirectConnected = false;
if ((fBufferDesc->buffer_state & B_DIRECT_MODE_MASK)
== B_DIRECT_STOP)
@@ -559,7 +580,7 @@ BDirectWindow::_InitData()
{
fConnectionEnable = false;
fIsFullScreen = false;
fInDirectConnect = false;
fInDirectConnected = false;
fInitStatus = 0;
@@ -583,14 +604,16 @@ BDirectWindow::_InitData()
fInitStatus |= DW_STATUS_SEM_CREATED;
#endif
fSourceClippingArea = syncData.area;
fSourceDirectArea = syncData.area;
fDisableSem = syncData.disable_sem;
fDisableSemAck = syncData.disable_sem_ack;
fClonedClippingArea = clone_area("cloned direct area", (void**)&fBufferDesc,
B_ANY_ADDRESS, B_READ_AREA, fSourceClippingArea);
fClonedDirectArea = clone_area("cloned direct area", (void**)&fBufferDesc,
B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, fSourceDirectArea);
if (fClonedClippingArea > 0) {
fSourceBitsArea = -1;
if (fClonedDirectArea > 0) {
fInitStatus |= DW_STATUS_AREA_CLONED;
fDirectDaemonId = spawn_thread(_daemon_thread, "direct daemon",
@@ -633,7 +656,7 @@ BDirectWindow::_DisposeData()
#endif
if (fInitStatus & DW_STATUS_AREA_CLONED)
delete_area(fClonedClippingArea);
delete_area(fClonedDirectArea);
}
+22 -5
View File
@@ -15,6 +15,7 @@
#include <syslog.h>
#include <Autolock.h>
#include <kernel.h>
#include "RenderingBuffer.h"
#include "clipping.h"
@@ -35,6 +36,7 @@ DirectWindowInfo::DirectWindowInfo()
memset(fBufferInfo, 0, DIRECT_BUFFER_INFO_AREA_SIZE);
fBufferInfo->buffer_state = B_DIRECT_STOP;
fBufferInfo->bits_area = -1;
fSem = create_sem(0, "direct sem");
fAcknowledgeSem = create_sem(0, "direct sem ack");
@@ -92,9 +94,21 @@ DirectWindowInfo::SetState(direct_buffer_state bufferState,
if ((int)driverState != -1)
fBufferInfo->driver_state = driverState;
if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
fBufferInfo->bits = buffer->Bits();
fBufferInfo->pci_bits = NULL; // TODO
if ((bufferState & B_BUFFER_RESET) != 0 || fBufferInfo->bits_area < 0) {
void* bits = buffer->Bits();
if (IS_USER_ADDRESS(bits)) {
fBufferInfo->bits = NULL;
area_id area = area_for(bits);
fBufferInfo->bits_area = area;
// make sure the area is cloneable
set_area_protection(area, B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA);
} else {
// framebuffer is in kernel address space
// TODO: update all drivers and then drop this case!
fBufferInfo->bits = bits;
}
fBufferInfo->bytes_per_row = buffer->BytesPerRow();
switch (buffer->ColorSpace()) {
@@ -137,6 +151,9 @@ DirectWindowInfo::SetState(direct_buffer_state bufferState,
fBufferInfo->layout = B_BUFFER_NONINTERLEAVED;
fBufferInfo->orientation = B_BUFFER_TOP_TO_BOTTOM;
// TODO
}
if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
fBufferInfo->window_bounds = to_clipping_rect(windowFrame);
const int32 kMaxClipRectsCount = (DIRECT_BUFFER_INFO_AREA_SIZE
@@ -150,7 +167,7 @@ DirectWindowInfo::SetState(direct_buffer_state bufferState,
fBufferInfo->clip_list[i] = clipRegion.RectAtInt(i);
}
return _SyncronizeWithClient();
return _SynchronizeWithClient();
}
@@ -171,7 +188,7 @@ DirectWindowInfo::DisableFullScreen()
status_t
DirectWindowInfo::_SyncronizeWithClient()
DirectWindowInfo::_SynchronizeWithClient()
{
// Releasing this semaphore causes the client to call
// BDirectWindow::DirectConnected()
+1 -1
View File
@@ -40,7 +40,7 @@ public:
window_feel OriginalFeel() const { return fOriginalFeel; }
private:
status_t _SyncronizeWithClient();
status_t _SynchronizeWithClient();
direct_buffer_info* fBufferInfo;
sem_id fSem;
+3
View File
@@ -3,6 +3,9 @@ SubDir HAIKU_TOP src servers app ;
UseLibraryHeaders agg ;
UsePrivateHeaders app graphics input interface shared storage support ;
UsePrivateKernelHeaders ;
# TODO: Remove! (only needed by DirectWindowInfo.cpp)
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;