* Copyright 2001-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
*/
created or destroyed, the BitmapManager needs to handle it. It takes care of
all memory management related to them.
*/
#include "BitmapManager.h"
#include "ClientMemoryAllocator.h"
#include "HWInterface.h"
#include "Overlay.h"
#include "ServerApp.h"
#include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerTokenSpace.h"
#include <BitmapPrivate.h>
#include <ObjectList.h>
#include <video_overlay.h>
#include <AppDefs.h>
#include <Autolock.h>
#include <Bitmap.h>
#include <Message.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using std::nothrow;
BitmapManager *gBitmapManager = NULL;
int
compare_app_pointer(const ServerApp* a, const ServerApp* b)
{
return (addr_t)a - (addr_t)b;
}
BitmapManager::BitmapManager()
:
fBitmapList(1024),
fLock("BitmapManager Lock")
{
}
BitmapManager::~BitmapManager()
{
int32 count = fBitmapList.CountItems();
for (int32 i = 0; i < count; i++)
delete (ServerBitmap*)fBitmapList.ItemAt(i);
}
\param bounds Size of the bitmap
\param space Color space of the bitmap
\param flags Bitmap flags as defined in Bitmap.h
\param bytesPerRow Number of bytes per row.
\param screen Screen id of the screen associated with it. Unused.
\return A new ServerBitmap or NULL if unable to allocate one.
*/
ServerBitmap*
BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator,
HWInterface& hwInterface, BRect bounds, color_space space, uint32 flags,
int32 bytesPerRow, int32 screen, uint8* _allocationFlags)
{
BAutolock locker(fLock);
if (!locker.IsLocked())
return NULL;
overlay_token overlayToken = NULL;
if (flags & B_BITMAP_WILL_OVERLAY) {
if (!hwInterface.CheckOverlayRestrictions(bounds.IntegerWidth() + 1,
bounds.IntegerHeight() + 1, space))
return NULL;
if (flags & B_BITMAP_RESERVE_OVERLAY_CHANNEL) {
overlayToken = hwInterface.AcquireOverlayChannel();
if (overlayToken == NULL)
return NULL;
}
}
ServerBitmap* bitmap = new(std::nothrow) ServerBitmap(bounds, space, flags,
bytesPerRow);
if (bitmap == NULL) {
if (overlayToken != NULL)
hwInterface.ReleaseOverlayChannel(overlayToken);
return NULL;
}
uint8* buffer = NULL;
if (flags & B_BITMAP_WILL_OVERLAY) {
Overlay* overlay = new(std::nothrow) Overlay(hwInterface, bitmap,
overlayToken);
overlay_client_data* clientData = NULL;
if (overlay != NULL && overlay->InitCheck() == B_OK) {
clientData = (overlay_client_data*)bitmap->fClientMemory.Allocate(
allocator, sizeof(overlay_client_data));
}
if (clientData != NULL) {
overlay->SetClientData(clientData);
bitmap->fMemory = &bitmap->fClientMemory;
bitmap->SetOverlay(overlay);
bitmap->fBytesPerRow = overlay->OverlayBuffer()->bytes_per_row;
buffer = (uint8*)overlay->OverlayBuffer()->buffer;
if (_allocationFlags)
*_allocationFlags = kFramebuffer;
} else
delete overlay;
} else if (allocator != NULL) {
buffer = (uint8*)bitmap->fClientMemory.Allocate(allocator,
bitmap->BitsLength());
if (buffer != NULL) {
bitmap->fMemory = &bitmap->fClientMemory;
if (_allocationFlags)
*_allocationFlags = kAllocator;
}
} else {
buffer = (uint8*)malloc(bitmap->BitsLength());
if (buffer != NULL) {
bitmap->fMemory = NULL;
if (_allocationFlags)
*_allocationFlags = kHeap;
}
}
bool success = false;
if (buffer != NULL) {
success = fBitmapList.AddItem(bitmap);
if (success && bitmap->Overlay() != NULL) {
success = fOverlays.AddItem(bitmap);
if (!success)
fBitmapList.RemoveItem(bitmap);
}
}
if (success) {
bitmap->fBuffer = buffer;
bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap);
} else {
free(buffer);
delete bitmap;
bitmap = NULL;
}
return bitmap;
}
ServerBitmap*
BitmapManager::CloneFromClient(area_id clientArea, int32 areaOffset,
BRect bounds, color_space space, uint32 flags, int32 bytesPerRow)
{
BAutolock locker(fLock);
if (!locker.IsLocked())
return NULL;
BReference<ServerBitmap> bitmap(new(std::nothrow) ServerBitmap(bounds, space, flags,
bytesPerRow), true);
if (bitmap == NULL)
return NULL;
ClonedAreaMemory* memory = new(std::nothrow) ClonedAreaMemory;
if (memory == NULL) {
return NULL;
}
int8* buffer = (int8*)memory->Clone(clientArea, areaOffset);
if (buffer == NULL) {
delete memory;
return NULL;
}
bitmap->fMemory = memory;
bitmap->fBuffer = memory->Address();
bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap);
return bitmap.Detach();
}
*/
void
BitmapManager::BitmapRemoved(ServerBitmap* bitmap)
{
BAutolock locker(fLock);
if (!locker.IsLocked())
return;
gTokenSpace.RemoveToken(bitmap->Token());
if (bitmap->Overlay() != NULL)
fOverlays.RemoveItem(bitmap);
fBitmapList.RemoveItem(bitmap);
}
void
BitmapManager::SuspendOverlays()
{
BAutolock locker(fLock);
if (!locker.IsLocked())
return;
BObjectList<ServerApp> apps;
for (int32 i = 0; i < fOverlays.CountItems(); i++) {
ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer);
}
for (int32 i = 0; i < apps.CountItems(); i++) {
BMessage notify(B_RELEASE_OVERLAY_LOCK);
apps.ItemAt(i)->SendMessageToClient(¬ify);
}
for (int32 i = 0; i < fOverlays.CountItems(); i++) {
ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
bitmap->Overlay()->Suspend(bitmap, false);
}
}
void
BitmapManager::ResumeOverlays()
{
BAutolock locker(fLock);
if (!locker.IsLocked())
return;
BObjectList<ServerApp> apps;
for (int32 i = 0; i < fOverlays.CountItems(); i++) {
ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer);
}
for (int32 i = 0; i < apps.CountItems(); i++) {
BMessage notify(B_RELEASE_OVERLAY_LOCK);
apps.ItemAt(i)->SendMessageToClient(¬ify);
}
for (int32 i = 0; i < fOverlays.CountItems(); i++) {
ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
bitmap->Overlay()->Resume(bitmap);
}
}