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 {
kAllocator,
kNewAllocatorArea,
kArea,
kFramebuffer,
kHeap
};
+5 -10
View File
@@ -928,12 +928,12 @@ BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int8 allocationType;
link.Read<int8>(&allocationType);
if (allocationType == kArea) {
// TODO: implement me (server-side as well), needed for overlays
if (allocationType == kFramebuffer) {
link.Read<addr_t>((addr_t*)&fBasePointer);
link.Read<int32>(&fBytesPerRow);
fServerArea = B_ERROR;
fAreaOffset = -1;
// that signals the cleanup code to delete our area
fBasePointer = NULL;
fAreaOffset = 0;
} else {
link.Read<area_id>(&fServerArea);
link.Read<int32>(&fAreaOffset);
@@ -1012,11 +1012,6 @@ BBitmap::_CleanUp()
// 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;
fServerToken = -1;
fAreaOffset = -1;
+53 -14
View File
@@ -16,18 +16,22 @@
*/
#include <new>
#include <stdio.h>
#include <string.h>
#include "BitmapManager.h"
#include "ClientMemoryAllocator.h"
#include "HWInterface.h"
#include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerTokenSpace.h"
#include <video_overlay.h>
#include <Autolock.h>
#include <Bitmap.h>
#include "BitmapManager.h"
#include "ClientMemoryAllocator.h"
#include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerTokenSpace.h"
#include <new>
#include <stdio.h>
#include <string.h>
using std::nothrow;
@@ -73,8 +77,8 @@ BitmapManager::~BitmapManager()
\return A new ServerBitmap or NULL if unable to allocate one.
*/
ServerBitmap*
BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
color_space space, int32 flags, int32 bytesPerRow, screen_id screen,
BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, HWInterface& hwInterface,
BRect bounds, color_space space, int32 flags, int32 bytesPerRow, screen_id screen,
int8* _allocationType)
{
BAutolock locker(fLock);
@@ -83,17 +87,52 @@ BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, BRect bounds,
return NULL;
// TODO: create an overlay bitmap if graphics card supports it
if (flags & B_BITMAP_WILL_OVERLAY)
return NULL;
if (flags & B_BITMAP_WILL_OVERLAY) {
if (!hwInterface.WriteLock()
|| !hwInterface.CheckOverlayRestrictions(bounds.IntegerWidth() + 1,
bounds.IntegerHeight() + 1, space)) {
hwInterface.WriteUnlock();
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);
if (bitmap == NULL)
if (bitmap == NULL) {
if (flags & B_BITMAP_WILL_OVERLAY)
hwInterface.WriteUnlock();
return NULL;
}
void* cookie = 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;
cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea);
if (cookie != NULL) {
+3 -1
View File
@@ -16,6 +16,7 @@
#include <Rect.h>
class ClientMemoryAllocator;
class HWInterface;
class ServerBitmap;
class BitmapManager {
@@ -23,7 +24,8 @@ class BitmapManager {
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,
screen_id screen = B_MAIN_SCREEN_ID,
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>(&bytesPerRow);
if (link.Read<screen_id>(&screenID) == B_OK) {
bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator, frame,
colorSpace, flags, bytesPerRow, screenID, &allocationType);
// TODO: choose the right HWInterface with regards to the screenID
bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator,
*fDesktop->HWInterface(), frame, colorSpace, flags, bytesPerRow,
screenID, &allocationType);
}
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<int8>(allocationType);
if (allocationType == kArea) {
// TODO: implement me!
if (allocationType == kFramebuffer) {
fLink.Attach<addr_t>((addr_t)bitmap->Bits());
fLink.Attach<int32>(bitmap->BytesPerRow());
} else {
fLink.Attach<area_id>(fMemoryAllocator.Area(bitmap->AllocationCookie()));
fLink.Attach<int32>(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie()));
+66 -7
View File
@@ -10,6 +10,7 @@
#include "ServerBitmap.h"
#include "ClientMemoryAllocator.h"
#include "ColorConversion.h"
#include "HWInterface.h"
#include <new>
#include <stdio.h>
@@ -17,6 +18,24 @@
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).
@@ -46,7 +65,7 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space,
fSpace(space),
fFlags(flags),
fBitsPerPixel(0)
// TODO: what about fToken and fOffset ?!?
// fToken is initialized (if used) by the BitmapManager
{
_HandleSpace(space, bytesPerRow);
}
@@ -83,9 +102,10 @@ ServerBitmap::~ServerBitmap()
{
if (fAllocator != NULL)
fAllocator->Free(AllocationCookie());
else if (fAllocationCookie != NULL)
delete_area((area_id)fAllocationCookie);
else
else if (fAllocationCookie != NULL) {
delete (OverlayCookie *)fAllocationCookie;
// deleting the cookie will also free the buffer
} else
free(fBuffer);
}
@@ -267,9 +287,6 @@ ServerBitmap::Area() const
if (fAllocator != NULL)
return fAllocator->Area(AllocationCookie());
if (fAllocationCookie != NULL)
return (area_id)fAllocationCookie;
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
ServerBitmap::PrintToStream()
{
@@ -328,3 +355,35 @@ UtilityBitmap::UtilityBitmap(const uint8* alreadyPaddedData,
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 <OS.h>
#include <video_overlay.h>
class BitmapManager;
class ClientMemoryAllocator;
class HWInterface;
/*!
\class ServerBitmap ServerBitmap.h
@@ -61,6 +64,8 @@ class ServerBitmap {
area_id Area() const;
uint32 AreaOffset() const;
const overlay_buffer* OverlayBuffer() const;
//! Does a shallow copy of the bitmap passed to it
inline void ShallowCopy(const ServerBitmap *from);
@@ -129,6 +134,20 @@ class UtilityBitmap : public ServerBitmap {
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
void
ServerBitmap::ShallowCopy(const ServerBitmap* from)
+11 -6
View File
@@ -192,17 +192,22 @@ WorkspacesLayer::_DrawWindow(DrawingEngine* drawingEngine, const BRect& workspac
tabFrame.top = frame.top - 1;
tabFrame.bottom = frame.top - 1;
tabFrame = tabFrame & workspaceFrame;
backgroundRegion.Exclude(tabFrame);
backgroundRegion.Exclude(frame);
if (decorator != NULL)
if (decorator != NULL && tabFrame.IsValid()) {
drawingEngine->StrokeLine(tabFrame.LeftTop(), tabFrame.RightBottom(), yellow);
backgroundRegion.Exclude(tabFrame);
}
drawingEngine->StrokeRect(frame, frameColor);
frame.InsetBy(1, 1);
drawingEngine->FillRect(frame, white);
frame = frame & workspaceFrame;
if (frame.IsValid()) {
backgroundRegion.Exclude(frame);
frame.InsetBy(1, 1);
drawingEngine->FillRect(frame, white);
}
// draw title
@@ -101,6 +101,8 @@ AccelerantHWInterface::AccelerantHWInterface()
fBackBuffer(NULL),
fFrontBuffer(new (nothrow) AccelerantBuffer()),
fUsedOverlays(0),
fRectParams(new (nothrow) fill_rect_params[kDefaultParamsCount]),
fRectParamsCount(kDefaultParamsCount),
fBlitParams(new (nothrow) blit_params[kDefaultParamsCount]),
@@ -684,6 +686,72 @@ AccelerantHWInterface::AvailableHWAcceleration() const
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
void
AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList,
+21 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005, Haiku.
* Copyright 2005-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -55,6 +55,14 @@ public:
// query for available hardware accleration and perform it
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,
uint32 count,
int32 xOffset, int32 yOffset);
@@ -66,18 +74,18 @@ public:
virtual void Sync();
// cursor handling
virtual void SetCursor(ServerCursor* cursor);
virtual void SetCursorVisible(bool visible);
virtual void MoveCursorTo(const float& x,
virtual void SetCursor(ServerCursor* cursor);
virtual void SetCursorVisible(bool visible);
virtual void MoveCursorTo(const float& x,
const float& y);
// frame buffer access
virtual RenderingBuffer* FrontBuffer() const;
virtual RenderingBuffer* BackBuffer() const;
virtual bool IsDoubleBuffered() const;
virtual RenderingBuffer* FrontBuffer() const;
virtual RenderingBuffer* BackBuffer() const;
virtual bool IsDoubleBuffered() const;
protected:
virtual void _DrawCursor(BRect area) const;
virtual void _DrawCursor(BRect area) const;
private:
int _OpenGraphicsDevice(int deviceNumber);
@@ -134,13 +142,15 @@ private:
frame_buffer_config fFrameBufferConfig;
int fModeCount;
display_mode *fModeList;
display_mode* fModeList;
MallocBuffer *fBackBuffer;
AccelerantBuffer *fFrontBuffer;
MallocBuffer* fBackBuffer;
AccelerantBuffer* fFrontBuffer;
display_mode fDisplayMode;
vint32 fUsedOverlays;
mutable fill_rect_params* fRectParams;
mutable uint32 fRectParamsCount;
mutable blit_params* fBlitParams;
+21
View File
@@ -301,6 +301,27 @@ HWInterface::CopyBackToFront(const BRect& frame)
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
bool
HWInterface::HideSoftwareCursor(const BRect& area)
+12 -1
View File
@@ -9,12 +9,15 @@
#define HW_INTERFACE_H
#include "MultiLocker.h"
#include <video_overlay.h>
#include <Accelerant.h>
#include <GraphicsCard.h>
#include <OS.h>
#include <Region.h>
#include "MultiLocker.h"
class RenderingBuffer;
class RGBColor;
@@ -22,6 +25,7 @@ class ServerBitmap;
class ServerCursor;
class UpdateQueue;
class BString;
struct overlay_buffer;
enum {
HW_ACC_COPY_REGION = 0x00000001,
@@ -92,6 +96,13 @@ class HWInterface : public MultiLocker {
void SetDragBitmap(const ServerBitmap* bitmap,
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!)
RenderingBuffer* DrawingBuffer() const;
virtual RenderingBuffer* FrontBuffer() const = 0;
+1 -1
View File
@@ -4,7 +4,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
AddSubDirSupportedPlatforms libbe_test ;
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 drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;