From f7c7883b9f7be15d6ffcc066e0f75e3d878c7923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 23 Apr 2006 14:28:48 +0000 Subject: [PATCH] * 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 --- src/servers/app/ServerApp.cpp | 2 +- src/servers/app/ServerBitmap.cpp | 57 +++++++- src/servers/app/ServerBitmap.h | 18 +++ src/servers/app/ServerWindow.cpp | 9 +- src/servers/app/ViewLayer.cpp | 128 +++++++++++++----- src/servers/app/ViewLayer.h | 3 + .../app/drawing/AccelerantHWInterface.cpp | 51 +++++++ .../app/drawing/AccelerantHWInterface.h | 4 + src/servers/app/drawing/HWInterface.cpp | 18 +++ src/servers/app/drawing/HWInterface.h | 5 + 10 files changed, 257 insertions(+), 38 deletions(-) diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index f618313e09..6f9b7626d1 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -2564,7 +2564,7 @@ ServerApp::FindBitmap(int32 token) const ServerBitmap* bitmap; if (gTokenSpace.GetToken(token, kBitmapToken, (void**)&bitmap) == B_OK) return bitmap; - + return NULL; } diff --git a/src/servers/app/ServerBitmap.cpp b/src/servers/app/ServerBitmap.cpp index 15576d0678..13d154a0d1 100644 --- a/src/servers/app/ServerBitmap.cpp +++ b/src/servers/app/ServerBitmap.cpp @@ -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); +} + diff --git a/src/servers/app/ServerBitmap.h b/src/servers/app/ServerBitmap.h index 7182718ee3..25ba165923 100644 --- a/src/servers/app/ServerBitmap.h +++ b/src/servers/app/ServerBitmap.h @@ -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) diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index b778814029..768070d4cb 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1501,14 +1501,21 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&resizingMode); status_t status = link.Read(&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(colorKey); } diff --git a/src/servers/app/ViewLayer.cpp b/src/servers/app/ViewLayer.cpp index cac4ce53a5..a6d73717ca 100644 --- a/src/servers/app/ViewLayer.cpp +++ b/src/servers/app/ViewLayer.cpp @@ -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 diff --git a/src/servers/app/ViewLayer.h b/src/servers/app/ViewLayer.h index d327dec8ba..2daf63812c 100644 --- a/src/servers/app/ViewLayer.h +++ b/src/servers/app/ViewLayer.h @@ -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; diff --git a/src/servers/app/drawing/AccelerantHWInterface.cpp b/src/servers/app/drawing/AccelerantHWInterface.cpp index be86130e5a..9adcf9b1d7 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.cpp +++ b/src/servers/app/drawing/AccelerantHWInterface.cpp @@ -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, diff --git a/src/servers/app/drawing/AccelerantHWInterface.h b/src/servers/app/drawing/AccelerantHWInterface.h index 84ad77f278..315e6d287a 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.h +++ b/src/servers/app/drawing/AccelerantHWInterface.h @@ -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, diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 46a2c3c49b..1dd4593078 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -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) diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index 5c53e65a09..9dfce95328 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -19,6 +19,7 @@ #include +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;