* We now have working video overlay - even though the overlay_token handling

is currently broken, mode switches probably fail or result in sudden death
  (didn't try) it's good enough for Radeon cards and VLC (might work with
  others as well).
* Implemented follow modes for view bitmaps (wasn't taken into account at
  all before).
* Switched to a darker overlay color for now (dunno what exactly makes a
  good candidate there, but this one is good enough for now).
* Added TODO about a race condition in AS_LAYER_SET_VIEW_BITMAP.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17208 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-04-23 14:28:48 +00:00
parent ef9c8e384d
commit f7c7883b9f
10 changed files with 257 additions and 38 deletions

View File

@ -2564,7 +2564,7 @@ ServerApp::FindBitmap(int32 token) const
ServerBitmap* bitmap;
if (gTokenSpace.GetToken(token, kBitmapToken, (void**)&bitmap) == B_OK)
return bitmap;
return NULL;
}

View File

@ -375,8 +375,8 @@ OverlayCookie::OverlayCookie(HWInterface& interface)
fOverlayToken(NULL)
{
fSemaphore = create_sem(1, "overlay lock");
fColor.SetColor(255, 0, 255);
// that color is just for testing, of course!
fColor.SetColor(21, 16, 21, 16);
// TODO: whatever fine color we want to use here...
}
@ -409,6 +409,18 @@ OverlayCookie::SetOverlayData(const overlay_buffer* overlayBuffer,
}
void
OverlayCookie::TakeOverToken(OverlayCookie* other)
{
overlay_token token = other->OverlayToken();
if (token == NULL)
return;
fOverlayToken = token;
//other->fOverlayToken = NULL;
}
const overlay_buffer*
OverlayCookie::OverlayBuffer() const
{
@ -429,3 +441,44 @@ OverlayCookie::OverlayToken() const
return fOverlayToken;
}
void
OverlayCookie::Show()
{
// TODO: acquire token!
if (fOverlayToken == NULL) {
printf("%p: no overlay token\n", this);
return;
}
fHWInterface.ShowOverlay(this);
}
void
OverlayCookie::Hide()
{
// TODO: acquire token!
if (fOverlayToken == NULL) {
printf("%p: no overlay token\n", this);
return;
}
fHWInterface.HideOverlay(this);
}
void
OverlayCookie::SetView(const BRect& source, const BRect& destination)
{
fSource = source;
fDestination = destination;
if (fOverlayToken == NULL) {
printf("%p: no overlay token\n", this);
return;
}
fHWInterface.UpdateOverlay(this);
}

View File

@ -150,6 +150,7 @@ class OverlayCookie {
void SetOverlayData(const overlay_buffer* overlayBuffer,
overlay_token token, overlay_client_data* clientData);
void TakeOverToken(OverlayCookie* other);
const overlay_buffer* OverlayBuffer() const;
overlay_client_data* ClientData() const;
@ -161,6 +162,20 @@ class OverlayCookie {
const RGBColor& Color() const
{ return fColor; }
void SetVisible(bool visible)
{ fVisible = visible; }
bool IsVisible() const
{ return fVisible; }
void SetView(const BRect& source, const BRect& destination);
const BRect& Source() const
{ return fSource; }
const BRect& Destination() const
{ return fDestination; }
void Show();
void Hide();
private:
HWInterface& fHWInterface;
const overlay_buffer* fOverlayBuffer;
@ -168,6 +183,9 @@ class OverlayCookie {
overlay_token fOverlayToken;
sem_id fSemaphore;
RGBColor fColor;
BRect fSource;
BRect fDestination;
bool fVisible;
};
// ShallowCopy (only for server bitmaps)

View File

@ -1501,14 +1501,21 @@ ServerWindow::_DispatchViewMessage(int32 code,
link.Read<int32>(&resizingMode);
status_t status = link.Read<int32>(&options);
rgb_color colorKey = {0};
if (status == B_OK) {
ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken);
if (bitmapToken == -1 || bitmap != NULL) {
// TODO: this is a race condition: the bitmap could have been
// deleted in the mean time!!
fCurrentLayer->SetViewBitmap(bitmap, srcRect, dstRect,
resizingMode, options);
BRegion dirty(fCurrentLayer->Bounds());
fWindowLayer->InvalidateView(fCurrentLayer, dirty);
if (bitmap != NULL && bitmap->OverlayCookie() != NULL)
colorKey = bitmap->OverlayCookie()->Color().GetColor32();
} else
status = B_BAD_VALUE;
}
@ -1516,8 +1523,6 @@ ServerWindow::_DispatchViewMessage(int32 code,
fLink.StartMessage(status);
if (status == B_OK && (options & AS_REQUEST_COLOR_KEY) != 0) {
// Attach color key for the overlay bitmap
// TODO: get color key from the accelerant
rgb_color colorKey = {40, 40, 40, 255};
fLink.Attach<rgb_color>(colorKey);
}

View File

@ -37,6 +37,38 @@
using std::nothrow;
void
resize_frame(BRect& frame, uint32 resizingMode, int32 x, int32 y)
{
// follow with left side
if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
frame.left += x;
else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
frame.left += x / 2;
// follow with right side
if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
frame.right += x;
else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
frame.right += x / 2;
// follow with top side
if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
frame.top += y;
else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
frame.top += y / 2;
// follow with bottom side
if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
frame.bottom += y;
else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
frame.bottom += y / 2;
}
// #pragma mark -
ViewLayer::ViewLayer(BRect frame, BPoint scrollingOffset, const char* name,
int32 token, uint32 resizeMode, uint32 flags)
:
@ -417,8 +449,18 @@ void
ViewLayer::SetViewBitmap(ServerBitmap* bitmap, BRect sourceRect,
BRect destRect, int32 resizingMode, int32 options)
{
if (fViewBitmap != NULL)
if (fViewBitmap != NULL) {
if (bitmap != NULL) {
// take over overlay token from current overlay (if it has any)
OverlayCookie* oldOverlay = _Overlay();
OverlayCookie* newOverlay = bitmap->OverlayCookie();
if (oldOverlay != NULL && newOverlay != NULL)
newOverlay->TakeOverToken(oldOverlay);
}
gBitmapManager->DeleteBitmap(fViewBitmap);
}
// the caller is allowed to delete the bitmap after setting the background
if (bitmap != NULL)
@ -436,6 +478,32 @@ ViewLayer::SetViewBitmap(ServerBitmap* bitmap, BRect sourceRect,
roundf(fBitmapDestination.top));
fBitmapDestination.right = roundf(fBitmapDestination.right);
fBitmapDestination.bottom = roundf(fBitmapDestination.bottom);
_UpdateOverlayView();
}
OverlayCookie*
ViewLayer::_Overlay() const
{
if (fViewBitmap == NULL)
return NULL;
return fViewBitmap->OverlayCookie();
}
void
ViewLayer::_UpdateOverlayView() const
{
OverlayCookie* overlay = _Overlay();
if (overlay == NULL)
return;
BRect destination = fBitmapDestination;
ConvertToScreen(&destination);
overlay->SetView(fBitmapSource, destination);
}
@ -680,6 +748,9 @@ ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
// the screen clipping
InvalidateScreenClipping(true);
}
// overlay handling
_UpdateOverlayView();
}
// ResizeBy
@ -734,43 +805,26 @@ ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
child->ParentResized(x, y, dirtyRegion);
// view bitmap
resize_frame(fBitmapDestination, fBitmapResizingMode, x, y);
// at this point, children are at their new locations,
// so we can rebuild the clipping
// TODO: when the implementation of Hide() and Show() is
// complete, see if this should be avoided
RebuildClipping(false);
// overlay handling
_UpdateOverlayView();
}
// ParentResized
void
ViewLayer::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
{
uint16 rm = fResizeMode & 0x0000FFFF;
BRect newFrame = fFrame;
// follow with left side
if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
newFrame.left += x;
else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
newFrame.left += x / 2;
// follow with right side
if ((rm & 0x000FU) == _VIEW_RIGHT_)
newFrame.right += x;
else if ((rm & 0x000FU) == _VIEW_CENTER_)
newFrame.right += x / 2;
// follow with top side
if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
newFrame.top += y;
else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
newFrame.top += y / 2;
// follow with bottom side
if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
newFrame.bottom += y;
else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
newFrame.bottom += y / 2;
resize_frame(newFrame, fResizeMode & 0x0000ffff, x, y);
if (newFrame != fFrame) {
// careful, MoveBy will change fFrame
@ -978,9 +1032,7 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
// add the current clipping
redraw->IntersectWith(effectiveClipping);
OverlayCookie* overlayCookie = NULL;
if (fViewBitmap != NULL)
overlayCookie = fViewBitmap->OverlayCookie();
OverlayCookie* overlayCookie = _Overlay();
if (fViewBitmap != NULL && overlayCookie == NULL) {
// draw view bitmap
@ -1064,14 +1116,13 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
}
if (overlayCookie != NULL) {
drawingEngine->FillRegion(*redraw, overlayCookie->Color());
} else if (!fViewColor.IsTransparentMagic()) {
if (!fViewColor.IsTransparentMagic()) {
// fill visible region with view color,
// this version of FillRegion ignores any
// clipping, that's why "redraw" needs to
// be correct
drawingEngine->FillRegion(*redraw, fViewColor);
drawingEngine->FillRegion(*redraw, overlayCookie != NULL
? overlayCookie->Color() : fViewColor);
}
fWindow->RecycleRegion(redraw);
@ -1160,6 +1211,17 @@ ViewLayer::UpdateVisibleDeep(bool parentVisible)
fVisible = parentVisible && !fHidden;
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
child->UpdateVisibleDeep(fVisible);
// overlay handling
OverlayCookie* overlay = _Overlay();
if (overlay == NULL)
return;
if (fVisible && !overlay->IsVisible())
overlay->Show();
else if (!fVisible && overlay->IsVisible())
overlay->Hide();
}
// MarkBackgroundDirty

View File

@ -26,6 +26,7 @@ namespace BPrivate {
class DrawState;
class DrawingEngine;
class OverlayCookie;
class WindowLayer;
class ServerBitmap;
class ServerCursor;
@ -208,6 +209,8 @@ class ViewLayer {
protected:
void _MoveScreenClipping(int32 x, int32 y,
bool deep);
OverlayCookie* _Overlay() const;
void _UpdateOverlayView() const;
BString fName;
int32 fToken;

View File

@ -761,6 +761,57 @@ AccelerantHWInterface::FreeOverlayBuffer(const overlay_buffer* buffer)
}
void
AccelerantHWInterface::ShowOverlay(OverlayCookie* overlay)
{
UpdateOverlay(overlay);
}
void
AccelerantHWInterface::HideOverlay(OverlayCookie* overlay)
{
fAccConfigureOverlay(overlay->OverlayToken(), overlay->OverlayBuffer(), NULL, NULL);
}
void
AccelerantHWInterface::UpdateOverlay(OverlayCookie* overlay)
{
const overlay_buffer* buffer = overlay->OverlayBuffer();
overlay_view view;
view.h_start = (uint16)overlay->Source().left;
view.v_start = (uint16)overlay->Source().top;
view.width = (uint16)overlay->Source().IntegerWidth() + 1;
view.height = (uint16)overlay->Source().IntegerHeight() + 1;
overlay_window window;
window.h_start = (int16)overlay->Destination().left;
window.v_start = (int16)overlay->Destination().top;
window.width = (uint16)overlay->Destination().IntegerWidth() + 1;
window.height = (uint16)overlay->Destination().IntegerHeight() + 1;
window.offset_top = 0;
window.offset_left = 0;
window.offset_right = 0;
window.offset_bottom = 0;
// TODO: for now, this should be done somewhere else, ideally
rgb_color colorKey = overlay->Color().GetColor32();
window.red.value = colorKey.red;
window.green.value = colorKey.green;
window.blue.value = colorKey.blue;
window.alpha.value = colorKey.alpha;
window.red.mask = 0xff;
window.green.mask = 0xff;
window.blue.mask = 0xff;
window.alpha.mask = 0xff;
fAccConfigureOverlay(overlay->OverlayToken(), buffer, &window, &view);
}
// CopyRegion
void
AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList,

View File

@ -65,6 +65,10 @@ public:
color_space space);
virtual void FreeOverlayBuffer(const overlay_buffer* buffer);
virtual void ShowOverlay(OverlayCookie* overlay);
virtual void HideOverlay(OverlayCookie* overlay);
virtual void UpdateOverlay(OverlayCookie* overlay);
// accelerated drawing
virtual void CopyRegion(const clipping_rect* sortedRectList,
uint32 count,

View File

@ -335,6 +335,24 @@ HWInterface::FreeOverlayBuffer(const overlay_buffer* buffer)
}
void
HWInterface::ShowOverlay(OverlayCookie* overlay)
{
}
void
HWInterface::HideOverlay(OverlayCookie* overlay)
{
}
void
HWInterface::UpdateOverlay(OverlayCookie* overlay)
{
}
// HideSoftwareCursor
bool
HWInterface::HideSoftwareCursor(const BRect& area)

View File

@ -19,6 +19,7 @@
#include <Region.h>
class OverlayCookie;
class RenderingBuffer;
class RGBColor;
class ServerBitmap;
@ -106,6 +107,10 @@ class HWInterface : public MultiLocker {
color_space space);
virtual void FreeOverlayBuffer(const overlay_buffer* buffer);
virtual void ShowOverlay(OverlayCookie* overlay);
virtual void HideOverlay(OverlayCookie* overlay);
virtual void UpdateOverlay(OverlayCookie* overlay);
// frame buffer access (you need to ReadLock!)
RenderingBuffer* DrawingBuffer() const;
virtual RenderingBuffer* FrontBuffer() const = 0;