Implemented some more overlay support - the overlay bitmap is now allocated

via the graphics driver (but not yet shown on screen).
I probably got the meaning of the "overlay count" wrong - I guess that you
can allocate any number of overlay bitmaps, but can only see "overlay count"
on screen at a time (right now, I only allow to create "overlay count" bitmaps).
Stephan?


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17193 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-04-21 20:14:41 +00:00
parent 2e16ba2acc
commit 37b502f28b
13 changed files with 288 additions and 56 deletions
+1 -1
View File
@@ -336,7 +336,7 @@ enum cursor_which {
enum { enum {
kAllocator, kAllocator,
kNewAllocatorArea, kNewAllocatorArea,
kArea, kFramebuffer,
kHeap kHeap
}; };
+5 -10
View File
@@ -928,12 +928,12 @@ BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int8 allocationType; int8 allocationType;
link.Read<int8>(&allocationType); link.Read<int8>(&allocationType);
if (allocationType == kArea) { if (allocationType == kFramebuffer) {
// TODO: implement me (server-side as well), needed for overlays link.Read<addr_t>((addr_t*)&fBasePointer);
link.Read<int32>(&fBytesPerRow);
fServerArea = B_ERROR; fServerArea = B_ERROR;
fAreaOffset = -1; fAreaOffset = 0;
// that signals the cleanup code to delete our area
fBasePointer = NULL;
} else { } else {
link.Read<area_id>(&fServerArea); link.Read<area_id>(&fServerArea);
link.Read<int32>(&fAreaOffset); link.Read<int32>(&fAreaOffset);
@@ -1012,11 +1012,6 @@ BBitmap::_CleanUp()
// TODO: we may want to delete parts of the server memory areas here! // TODO: we may want to delete parts of the server memory areas here!
if (fAreaOffset == -1) {
// we own that area, so we have to delete it
delete_area(fArea);
}
fArea = -1; fArea = -1;
fServerToken = -1; fServerToken = -1;
fAreaOffset = -1; fAreaOffset = -1;
+52 -13
View File
@@ -16,18 +16,22 @@
*/ */
#include <new> #include "BitmapManager.h"
#include <stdio.h>
#include <string.h> #include "ClientMemoryAllocator.h"
#include "HWInterface.h"
#include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerTokenSpace.h"
#include <video_overlay.h>
#include <Autolock.h> #include <Autolock.h>
#include <Bitmap.h> #include <Bitmap.h>
#include "BitmapManager.h" #include <new>
#include "ClientMemoryAllocator.h" #include <stdio.h>
#include "ServerBitmap.h" #include <string.h>
#include "ServerProtocol.h"
#include "ServerTokenSpace.h"
using std::nothrow; using std::nothrow;
@@ -73,8 +77,8 @@ BitmapManager::~BitmapManager()
\return A new ServerBitmap or NULL if unable to allocate one. \return A new ServerBitmap or NULL if unable to allocate one.
*/ */
ServerBitmap* ServerBitmap*
BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds, BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, HWInterface& hwInterface,
color_space space, int32 flags, int32 bytesPerRow, screen_id screen, BRect bounds, color_space space, int32 flags, int32 bytesPerRow, screen_id screen,
int8* _allocationType) int8* _allocationType)
{ {
BAutolock locker(fLock); BAutolock locker(fLock);
@@ -83,17 +87,52 @@ BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
return NULL; return NULL;
// TODO: create an overlay bitmap if graphics card supports it // TODO: create an overlay bitmap if graphics card supports it
if (flags & B_BITMAP_WILL_OVERLAY) if (flags & B_BITMAP_WILL_OVERLAY) {
if (!hwInterface.WriteLock()
|| !hwInterface.CheckOverlayRestrictions(bounds.IntegerWidth() + 1,
bounds.IntegerHeight() + 1, space)) {
hwInterface.WriteUnlock();
return NULL; return NULL;
}
// We now hold the HWInterface write lock!
// Keeping the interface locked makes sure the overlay is still
// available when we allocate the buffer
}
ServerBitmap* bitmap = new(nothrow) ServerBitmap(bounds, space, flags, bytesPerRow); ServerBitmap* bitmap = new(nothrow) ServerBitmap(bounds, space, flags, bytesPerRow);
if (bitmap == NULL) if (bitmap == NULL) {
if (flags & B_BITMAP_WILL_OVERLAY)
hwInterface.WriteUnlock();
return NULL; return NULL;
}
void* cookie = NULL; void* cookie = NULL;
uint8* buffer = NULL; uint8* buffer = NULL;
if (allocator != NULL) { if (flags & B_BITMAP_WILL_OVERLAY) {
OverlayCookie* overlayCookie = new (std::nothrow) OverlayCookie(hwInterface);
const overlay_buffer* overlayBuffer = NULL;
if (overlayCookie != NULL) {
overlayBuffer = hwInterface.AllocateOverlayBuffer(bitmap->Width(),
bitmap->Height(), space);
}
hwInterface.WriteUnlock();
if (overlayBuffer != NULL) {
overlayCookie->SetOverlayBuffer(overlayBuffer);
bitmap->fAllocationCookie = overlayCookie;
bitmap->fBytesPerRow = overlayBuffer->bytes_per_row;
buffer = (uint8*)overlayBuffer->buffer;
if (_allocationType)
*_allocationType = kFramebuffer;
} else
delete overlayCookie;
} else if (allocator != NULL) {
bool newArea; bool newArea;
cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea); cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea);
if (cookie != NULL) { if (cookie != NULL) {
+3 -1
View File
@@ -16,6 +16,7 @@
#include <Rect.h> #include <Rect.h>
class ClientMemoryAllocator; class ClientMemoryAllocator;
class HWInterface;
class ServerBitmap; class ServerBitmap;
class BitmapManager { class BitmapManager {
@@ -23,7 +24,8 @@ class BitmapManager {
BitmapManager(); BitmapManager();
virtual ~BitmapManager(); virtual ~BitmapManager();
ServerBitmap* CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds, ServerBitmap* CreateBitmap(ClientMemoryAllocator* allocator,
HWInterface& hwInterface, BRect bounds,
color_space space, int32 flags, int32 bytesPerRow = -1, color_space space, int32 flags, int32 bytesPerRow = -1,
screen_id screen = B_MAIN_SCREEN_ID, screen_id screen = B_MAIN_SCREEN_ID,
int8* _allocationType = NULL); int8* _allocationType = NULL);
+7 -4
View File
@@ -589,8 +589,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read<int32>(&flags); link.Read<int32>(&flags);
link.Read<int32>(&bytesPerRow); link.Read<int32>(&bytesPerRow);
if (link.Read<screen_id>(&screenID) == B_OK) { if (link.Read<screen_id>(&screenID) == B_OK) {
bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator, frame, // TODO: choose the right HWInterface with regards to the screenID
colorSpace, flags, bytesPerRow, screenID, &allocationType); bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator,
*fDesktop->HWInterface(), frame, colorSpace, flags, bytesPerRow,
screenID, &allocationType);
} }
STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n", STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n",
@@ -601,8 +603,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
fLink.Attach<int32>(bitmap->Token()); fLink.Attach<int32>(bitmap->Token());
fLink.Attach<int8>(allocationType); fLink.Attach<int8>(allocationType);
if (allocationType == kArea) { if (allocationType == kFramebuffer) {
// TODO: implement me! fLink.Attach<addr_t>((addr_t)bitmap->Bits());
fLink.Attach<int32>(bitmap->BytesPerRow());
} else { } else {
fLink.Attach<area_id>(fMemoryAllocator.Area(bitmap->AllocationCookie())); fLink.Attach<area_id>(fMemoryAllocator.Area(bitmap->AllocationCookie()));
fLink.Attach<int32>(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie())); fLink.Attach<int32>(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie()));
+66 -7
View File
@@ -10,6 +10,7 @@
#include "ServerBitmap.h" #include "ServerBitmap.h"
#include "ClientMemoryAllocator.h" #include "ClientMemoryAllocator.h"
#include "ColorConversion.h" #include "ColorConversion.h"
#include "HWInterface.h"
#include <new> #include <new>
#include <stdio.h> #include <stdio.h>
@@ -17,6 +18,24 @@
using std::nothrow; using std::nothrow;
/*!
A word about memory housekeeping and why it's implemented this way:
The reason why this looks so complicated is to optimize the most common
path (bitmap creation from the application), and don't cause any further
memory allocations for maintaining memory in that case.
If a bitmap was allocated this way, both, the fAllocator and fAllocationCookie
members are used.
For overlays, the creation speed is not crucial, that's why we can easily live
with the overhead of some heap allocations. The fAllocationCookie will point
to an OverlayCookie object that will also free the buffer upon destruction.
If the memory was allocated on the app_server heap, neither fAllocator, nor
fAllocationCookie are used, and the buffer is just freed in that case when
the bitmap is destructed. This method is mainly used for cursors.
*/
/*! /*!
\brief Constructor called by the BitmapManager (only). \brief Constructor called by the BitmapManager (only).
@@ -46,7 +65,7 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space,
fSpace(space), fSpace(space),
fFlags(flags), fFlags(flags),
fBitsPerPixel(0) fBitsPerPixel(0)
// TODO: what about fToken and fOffset ?!? // fToken is initialized (if used) by the BitmapManager
{ {
_HandleSpace(space, bytesPerRow); _HandleSpace(space, bytesPerRow);
} }
@@ -83,9 +102,10 @@ ServerBitmap::~ServerBitmap()
{ {
if (fAllocator != NULL) if (fAllocator != NULL)
fAllocator->Free(AllocationCookie()); fAllocator->Free(AllocationCookie());
else if (fAllocationCookie != NULL) else if (fAllocationCookie != NULL) {
delete_area((area_id)fAllocationCookie); delete (OverlayCookie *)fAllocationCookie;
else // deleting the cookie will also free the buffer
} else
free(fBuffer); free(fBuffer);
} }
@@ -267,9 +287,6 @@ ServerBitmap::Area() const
if (fAllocator != NULL) if (fAllocator != NULL)
return fAllocator->Area(AllocationCookie()); return fAllocator->Area(AllocationCookie());
if (fAllocationCookie != NULL)
return (area_id)fAllocationCookie;
return B_ERROR; return B_ERROR;
} }
@@ -284,6 +301,16 @@ ServerBitmap::AreaOffset() const
} }
const overlay_buffer*
ServerBitmap::OverlayBuffer() const
{
if (fAllocator != NULL || fAllocationCookie == NULL)
return NULL;
return ((OverlayCookie*)fAllocationCookie)->OverlayBuffer();
}
void void
ServerBitmap::PrintToStream() ServerBitmap::PrintToStream()
{ {
@@ -328,3 +355,35 @@ UtilityBitmap::UtilityBitmap(const uint8* alreadyPaddedData,
UtilityBitmap::~UtilityBitmap() UtilityBitmap::~UtilityBitmap()
{ {
} }
// #pragma mark -
OverlayCookie::OverlayCookie(HWInterface& interface)
:
fHWInterface(interface),
fOverlayBuffer(NULL)
{
}
OverlayCookie::~OverlayCookie()
{
fHWInterface.FreeOverlayBuffer(fOverlayBuffer);
}
void
OverlayCookie::SetOverlayBuffer(const overlay_buffer* overlayBuffer)
{
fOverlayBuffer = overlayBuffer;
}
const overlay_buffer*
OverlayCookie::OverlayBuffer()
{
return fOverlayBuffer;
}
+19
View File
@@ -13,9 +13,12 @@
#include <Rect.h> #include <Rect.h>
#include <OS.h> #include <OS.h>
#include <video_overlay.h>
class BitmapManager; class BitmapManager;
class ClientMemoryAllocator; class ClientMemoryAllocator;
class HWInterface;
/*! /*!
\class ServerBitmap ServerBitmap.h \class ServerBitmap ServerBitmap.h
@@ -61,6 +64,8 @@ class ServerBitmap {
area_id Area() const; area_id Area() const;
uint32 AreaOffset() const; uint32 AreaOffset() const;
const overlay_buffer* OverlayBuffer() const;
//! Does a shallow copy of the bitmap passed to it //! Does a shallow copy of the bitmap passed to it
inline void ShallowCopy(const ServerBitmap *from); inline void ShallowCopy(const ServerBitmap *from);
@@ -129,6 +134,20 @@ class UtilityBitmap : public ServerBitmap {
virtual ~UtilityBitmap(); virtual ~UtilityBitmap();
}; };
//! An allocation cookie for overlays
class OverlayCookie {
public:
OverlayCookie(HWInterface& interface);
~OverlayCookie();
void SetOverlayBuffer(const overlay_buffer* overlayBuffer);
const overlay_buffer* OverlayBuffer();
private:
HWInterface& fHWInterface;
const overlay_buffer* fOverlayBuffer;
};
// ShallowCopy // ShallowCopy
void void
ServerBitmap::ShallowCopy(const ServerBitmap* from) ServerBitmap::ShallowCopy(const ServerBitmap* from)
+9 -4
View File
@@ -192,17 +192,22 @@ WorkspacesLayer::_DrawWindow(DrawingEngine* drawingEngine, const BRect& workspac
tabFrame.top = frame.top - 1; tabFrame.top = frame.top - 1;
tabFrame.bottom = frame.top - 1; tabFrame.bottom = frame.top - 1;
tabFrame = tabFrame & workspaceFrame;
backgroundRegion.Exclude(tabFrame); if (decorator != NULL && tabFrame.IsValid()) {
backgroundRegion.Exclude(frame);
if (decorator != NULL)
drawingEngine->StrokeLine(tabFrame.LeftTop(), tabFrame.RightBottom(), yellow); drawingEngine->StrokeLine(tabFrame.LeftTop(), tabFrame.RightBottom(), yellow);
backgroundRegion.Exclude(tabFrame);
}
drawingEngine->StrokeRect(frame, frameColor); drawingEngine->StrokeRect(frame, frameColor);
frame = frame & workspaceFrame;
if (frame.IsValid()) {
backgroundRegion.Exclude(frame);
frame.InsetBy(1, 1); frame.InsetBy(1, 1);
drawingEngine->FillRect(frame, white); drawingEngine->FillRect(frame, white);
}
// draw title // draw title
@@ -101,6 +101,8 @@ AccelerantHWInterface::AccelerantHWInterface()
fBackBuffer(NULL), fBackBuffer(NULL),
fFrontBuffer(new (nothrow) AccelerantBuffer()), fFrontBuffer(new (nothrow) AccelerantBuffer()),
fUsedOverlays(0),
fRectParams(new (nothrow) fill_rect_params[kDefaultParamsCount]), fRectParams(new (nothrow) fill_rect_params[kDefaultParamsCount]),
fRectParamsCount(kDefaultParamsCount), fRectParamsCount(kDefaultParamsCount),
fBlitParams(new (nothrow) blit_params[kDefaultParamsCount]), fBlitParams(new (nothrow) blit_params[kDefaultParamsCount]),
@@ -684,6 +686,72 @@ AccelerantHWInterface::AvailableHWAcceleration() const
return flags; return flags;
} }
bool
AccelerantHWInterface::CheckOverlayRestrictions(int32 width, int32 height,
color_space colorSpace)
{
// check if the current display mode supports overlay
if (fAccOverlayCount == NULL
|| fAccOverlaySupportedSpaces == NULL
|| fAccGetOverlayConstraints == NULL
|| fAccAllocateOverlayBuffer == NULL
|| fAccReleaseOverlayBuffer == NULL
|| (fDisplayMode.flags & B_SUPPORTS_OVERLAYS) == 0)
return false;
// check if there is an overlay buffer available
uint32 available = fAccOverlayCount(&fDisplayMode);
if ((int32)available <= fUsedOverlays)
return false;
// Note: we can't really check the size of the overlay upfront - we
// must assume fAccAllocateOverlayBuffer() will fail in that case.
if (width < 0 || width > 65535 || height < 0 || height > 65535)
return false;
// check color space
const uint32* spaces = fAccOverlaySupportedSpaces(&fDisplayMode);
if (spaces == NULL)
return false;
for (int32 i = 0; spaces[i] != 0; i++) {
if (spaces[i] == (uint32)colorSpace)
return true;
}
return false;
}
const overlay_buffer*
AccelerantHWInterface::AllocateOverlayBuffer(int32 width, int32 height, color_space space)
{
if (fAccAllocateOverlayBuffer == NULL)
return NULL;
const overlay_buffer* buffer = fAccAllocateOverlayBuffer(space, width, height);
if (buffer != NULL)
atomic_add(&fUsedOverlays, 1);
return buffer;
}
void
AccelerantHWInterface::FreeOverlayBuffer(const overlay_buffer* buffer)
{
if (buffer == NULL || fAccReleaseOverlayBuffer == NULL)
return;
atomic_add(&fUsedOverlays, -1);
fAccReleaseOverlayBuffer(buffer);
}
// CopyRegion // CopyRegion
void void
AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList, AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList,
@@ -1,5 +1,5 @@
/* /*
* Copyright 2005, Haiku. * Copyright 2005-2006, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -55,6 +55,14 @@ public:
// query for available hardware accleration and perform it // query for available hardware accleration and perform it
virtual uint32 AvailableHWAcceleration() const; virtual uint32 AvailableHWAcceleration() const;
// overlay support
virtual bool CheckOverlayRestrictions(int32 width, int32 height,
color_space colorSpace);
virtual const overlay_buffer* AllocateOverlayBuffer(int32 width, int32 height,
color_space space);
virtual void FreeOverlayBuffer(const overlay_buffer* buffer);
// accelerated drawing
virtual void CopyRegion(const clipping_rect* sortedRectList, virtual void CopyRegion(const clipping_rect* sortedRectList,
uint32 count, uint32 count,
int32 xOffset, int32 yOffset); int32 xOffset, int32 yOffset);
@@ -141,6 +149,8 @@ private:
display_mode fDisplayMode; display_mode fDisplayMode;
vint32 fUsedOverlays;
mutable fill_rect_params* fRectParams; mutable fill_rect_params* fRectParams;
mutable uint32 fRectParamsCount; mutable uint32 fRectParamsCount;
mutable blit_params* fBlitParams; mutable blit_params* fBlitParams;
+21
View File
@@ -301,6 +301,27 @@ HWInterface::CopyBackToFront(const BRect& frame)
return B_BAD_VALUE; return B_BAD_VALUE;
} }
bool
HWInterface::CheckOverlayRestrictions(int32 width, int32 height, color_space colorSpace)
{
return false;
}
const overlay_buffer*
HWInterface::AllocateOverlayBuffer(int32 width, int32 height, color_space space)
{
return NULL;
}
void
HWInterface::FreeOverlayBuffer(const overlay_buffer* buffer)
{
}
// HideSoftwareCursor // HideSoftwareCursor
bool bool
HWInterface::HideSoftwareCursor(const BRect& area) HWInterface::HideSoftwareCursor(const BRect& area)
+12 -1
View File
@@ -9,12 +9,15 @@
#define HW_INTERFACE_H #define HW_INTERFACE_H
#include "MultiLocker.h"
#include <video_overlay.h>
#include <Accelerant.h> #include <Accelerant.h>
#include <GraphicsCard.h> #include <GraphicsCard.h>
#include <OS.h> #include <OS.h>
#include <Region.h> #include <Region.h>
#include "MultiLocker.h"
class RenderingBuffer; class RenderingBuffer;
class RGBColor; class RGBColor;
@@ -22,6 +25,7 @@ class ServerBitmap;
class ServerCursor; class ServerCursor;
class UpdateQueue; class UpdateQueue;
class BString; class BString;
struct overlay_buffer;
enum { enum {
HW_ACC_COPY_REGION = 0x00000001, HW_ACC_COPY_REGION = 0x00000001,
@@ -92,6 +96,13 @@ class HWInterface : public MultiLocker {
void SetDragBitmap(const ServerBitmap* bitmap, void SetDragBitmap(const ServerBitmap* bitmap,
const BPoint& offsetFromCursor); const BPoint& offsetFromCursor);
// overlay support
virtual bool CheckOverlayRestrictions(int32 width, int32 height,
color_space colorSpace);
virtual const overlay_buffer* AllocateOverlayBuffer(int32 width, int32 height,
color_space space);
virtual void FreeOverlayBuffer(const overlay_buffer* buffer);
// frame buffer access (you need to ReadLock!) // frame buffer access (you need to ReadLock!)
RenderingBuffer* DrawingBuffer() const; RenderingBuffer* DrawingBuffer() const;
virtual RenderingBuffer* FrontBuffer() const = 0; virtual RenderingBuffer* FrontBuffer() const = 0;
+1 -1
View File
@@ -4,7 +4,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
AddSubDirSupportedPlatforms libbe_test ; AddSubDirSupportedPlatforms libbe_test ;
UseLibraryHeaders agg ; UseLibraryHeaders agg ;
UsePrivateHeaders app interface shared ; UsePrivateHeaders app graphics interface shared ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;