diff --git a/src/servers/app/drawing/DisplayDriver.cpp b/src/servers/app/drawing/DisplayDriver.cpp index 7f3c317a8a..b15c7babd3 100644 --- a/src/servers/app/drawing/DisplayDriver.cpp +++ b/src/servers/app/drawing/DisplayDriver.cpp @@ -38,8 +38,7 @@ \brief Sets up internal variables needed by all DisplayDriver subclasses */ DisplayDriver::DisplayDriver() - : fCursorHandler(this), - fDPMSState(B_DPMS_ON), + : fDPMSState(B_DPMS_ON), fDPMSCaps(B_DPMS_ON) { fDisplayMode.virtual_width = 640; @@ -68,7 +67,7 @@ DisplayDriver::~DisplayDriver() bool DisplayDriver::Initialize() { - fCursorHandler.SetCursor(new ServerCursor(default_cursor_data)); + SetCursor(new ServerCursor(default_cursor_data)); return true; } @@ -83,127 +82,6 @@ DisplayDriver::Shutdown() { } -/*! - \brief Hides the cursor. - - Hide calls are not nestable, unlike that of the BApplication class. Subclasses should - call _SetCursorHidden(true) somewhere within this function to ensure that data is - maintained accurately. Subclasses must include a call to DisplayDriver::HideCursor - for proper state tracking. -*/ -void -DisplayDriver::HideCursor() -{ - Lock(); - fCursorHandler.Hide(); - Unlock(); -} - -/*! - \brief Returns whether the cursor is visible or not. - \return true if hidden or obscured, false if not. - -*/ -bool -DisplayDriver::IsCursorHidden() -{ - Lock(); - bool value = fCursorHandler.IsHidden(); - Unlock(); - - return value; -} - -/*! - \brief Moves the cursor to the given point. - - The coordinates passed to MoveCursorTo are guaranteed to be within the frame buffer's - range, but the cursor data itself will need to be clipped. A check to see if the - cursor is obscured should be made and if so, a call to _SetCursorObscured(false) - should be made the cursor in addition to displaying at the passed coordinates. -*/ -void -DisplayDriver::MoveCursorTo(const float &x, const float &y) -{ - Lock(); - fCursorHandler.MoveTo(BPoint(x, y)); - Unlock(); -} - -/*! - \brief Shows the cursor. - - Show calls are not nestable, unlike that of the BApplication class. Subclasses should - call _SetCursorHidden(false) somewhere within this function to ensure that data is - maintained accurately. Subclasses must call DisplayDriver::ShowCursor at some point - to ensure proper state tracking. -*/ -void -DisplayDriver::ShowCursor() -{ - Lock(); - fCursorHandler.Show(); - Unlock(); -} - -/*! - \brief Obscures the cursor. - - Obscure calls are not nestable. Subclasses should call DisplayDriver::ObscureCursor - somewhere within this function to ensure that data is maintained accurately. A check - will be made by the system before the next MoveCursorTo call to show the cursor if - it is obscured. -*/ -void -DisplayDriver::ObscureCursor() -{ - Lock(); - fCursorHandler.Obscure(); - Unlock(); - -} - -/*! - \brief Changes the cursor. - \param cursor The new cursor. Guaranteed to be non-NULL. - - The driver does not take ownership of the given cursor. Subclasses should make - a copy of the cursor passed to it. The default version of this function hides the - cursory, replaces it, and shows the cursor if previously visible. -*/ -void -DisplayDriver::SetCursor(ServerCursor *cursor) -{ - Lock(); - fCursorHandler.SetCursor(cursor); - Unlock(); -} - -//! Returns the cursor's current position -BPoint -DisplayDriver::GetCursorPosition() -{ - Lock(); - BPoint pos = fCursorHandler.GetPosition(); - Unlock(); - - return pos; -} - -/*! - \brief Returns whether or not the cursor is currently obscured - \return True if obscured, false if not. -*/ -bool -DisplayDriver::IsCursorObscured(bool state) -{ - Lock(); - bool obscured = fCursorHandler.IsObscured(); - Unlock(); - - return obscured; -} - // Protected Internal Functions /* \brief Sets the screen mode to specified resolution and color depth. diff --git a/src/servers/app/drawing/DisplayDriverImpl.cpp b/src/servers/app/drawing/DisplayDriverImpl.cpp index 6e36b9ec40..d8f7a7588e 100644 --- a/src/servers/app/drawing/DisplayDriverImpl.cpp +++ b/src/servers/app/drawing/DisplayDriverImpl.cpp @@ -51,7 +51,8 @@ static Blitter blitter; */ DisplayDriverImpl::DisplayDriverImpl() : DisplayDriver(), - fLocker("DisplayDriver lock") + fLocker("DisplayDriver lock"), + fCursorHandler(this) { } @@ -2272,6 +2273,127 @@ void DisplayDriverImpl::GetTruncatedStrings(const char **instrings,const int32 & // TODO: Implement DisplayDriverImpl::GetTruncatedStrings } +/*! + \brief Hides the cursor. + + Hide calls are not nestable, unlike that of the BApplication class. Subclasses should + call _SetCursorHidden(true) somewhere within this function to ensure that data is + maintained accurately. Subclasses must include a call to DisplayDriver::HideCursor + for proper state tracking. +*/ +void +DisplayDriverImpl::HideCursor() +{ + Lock(); + fCursorHandler.Hide(); + Unlock(); +} + +/*! + \brief Returns whether the cursor is visible or not. + \return true if hidden or obscured, false if not. + +*/ +bool +DisplayDriverImpl::IsCursorHidden() +{ + Lock(); + bool value = fCursorHandler.IsHidden(); + Unlock(); + + return value; +} + +/*! + \brief Moves the cursor to the given point. + + The coordinates passed to MoveCursorTo are guaranteed to be within the frame buffer's + range, but the cursor data itself will need to be clipped. A check to see if the + cursor is obscured should be made and if so, a call to _SetCursorObscured(false) + should be made the cursor in addition to displaying at the passed coordinates. +*/ +void +DisplayDriverImpl::MoveCursorTo(const float &x, const float &y) +{ + Lock(); + fCursorHandler.MoveTo(BPoint(x, y)); + Unlock(); +} + +/*! + \brief Shows the cursor. + + Show calls are not nestable, unlike that of the BApplication class. Subclasses should + call _SetCursorHidden(false) somewhere within this function to ensure that data is + maintained accurately. Subclasses must call DisplayDriver::ShowCursor at some point + to ensure proper state tracking. +*/ +void +DisplayDriverImpl::ShowCursor() +{ + Lock(); + fCursorHandler.Show(); + Unlock(); +} + +/*! + \brief Obscures the cursor. + + Obscure calls are not nestable. Subclasses should call DisplayDriver::ObscureCursor + somewhere within this function to ensure that data is maintained accurately. A check + will be made by the system before the next MoveCursorTo call to show the cursor if + it is obscured. +*/ +void +DisplayDriverImpl::ObscureCursor() +{ + Lock(); + fCursorHandler.Obscure(); + Unlock(); + +} + +/*! + \brief Changes the cursor. + \param cursor The new cursor. Guaranteed to be non-NULL. + + The driver does not take ownership of the given cursor. Subclasses should make + a copy of the cursor passed to it. The default version of this function hides the + cursory, replaces it, and shows the cursor if previously visible. +*/ +void +DisplayDriverImpl::SetCursor(ServerCursor *cursor) +{ + Lock(); + fCursorHandler.SetCursor(cursor); + Unlock(); +} + +//! Returns the cursor's current position +BPoint +DisplayDriverImpl::GetCursorPosition() +{ + Lock(); + BPoint pos = fCursorHandler.GetPosition(); + Unlock(); + + return pos; +} + +/*! + \brief Returns whether or not the cursor is currently obscured + \return True if obscured, false if not. +*/ +bool +DisplayDriverImpl::IsCursorObscured(bool state) +{ + Lock(); + bool obscured = fCursorHandler.IsObscured(); + Unlock(); + + return obscured; +} + /*! \brief Locks the driver \param timeout Optional timeout specifier diff --git a/src/servers/app/drawing/DisplayDriverPainter.cpp b/src/servers/app/drawing/DisplayDriverPainter.cpp index 8e0222df83..cd8549a445 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.cpp +++ b/src/servers/app/drawing/DisplayDriverPainter.cpp @@ -128,7 +128,7 @@ DisplayDriverPainter::CopyRegionList(BList* list, BList* pList, if (!clipReg || !Lock()) return; -// This is the same implementation as in DisplayDriverImpl for now +// This is the same implementation as in DisplayDriverPainter for now // since we're not using painter.... this won't do much good, will it? // fPainter->ConstrainClipping(*clipReg); @@ -755,6 +755,65 @@ DisplayDriverPainter::GetTruncatedStrings(const char **instrings, printf("DisplayDriverPainter::GetTruncatedStrings()\n"); } +// HideCursor +void +DisplayDriverPainter::HideCursor() +{ + fGraphicsCard->SetCursorVisible(false); +} + +// IsCursorHidden +bool +DisplayDriverPainter::IsCursorHidden() +{ + return !fGraphicsCard->IsCursorVisible(); +} + +// MoveCursorTo +void +DisplayDriverPainter::MoveCursorTo(const float &x, const float &y) +{ + fGraphicsCard->MoveCursorTo(x, y); +} + +// ShowCursor +void +DisplayDriverPainter::ShowCursor() +{ + fGraphicsCard->SetCursorVisible(true); +} + +// ObscureCursor +void +DisplayDriverPainter::ObscureCursor() +{ + // TODO: I don't think this has anything to do with the DisplayDriver + // implement elsewhere!! +} + +// SetCursor +void +DisplayDriverPainter::SetCursor(ServerCursor *cursor) +{ + fGraphicsCard->SetCursor(cursor); +} + +// GetCursorPosition +BPoint +DisplayDriverPainter::GetCursorPosition() +{ + return fGraphicsCard->GetCursorPosition(); +} + +// IsCursorObscured +bool +DisplayDriverPainter::IsCursorObscured(bool state) +{ + // TODO: I don't think this has anything to do with the DisplayDriver + // implement elsewhere!! + return false; +} + // Lock bool DisplayDriverPainter::Lock(bigtime_t timeout) diff --git a/src/servers/app/drawing/DisplayDriverPainter.h b/src/servers/app/drawing/DisplayDriverPainter.h index 6f519666d1..7a23271450 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.h +++ b/src/servers/app/drawing/DisplayDriverPainter.h @@ -217,10 +217,8 @@ class DisplayDriverPainter : public DisplayDriver { const float &maxwidth, char **outstrings); - virtual bool Lock(bigtime_t timeout = B_INFINITE_TIMEOUT); - virtual void Unlock(); - -/* virtual void HideCursor(); + // cursor handling + virtual void HideCursor(); virtual bool IsCursorHidden(); virtual void MoveCursorTo( const float &x, const float &y); @@ -228,9 +226,12 @@ class DisplayDriverPainter : public DisplayDriver { virtual void ObscureCursor(); virtual void SetCursor(ServerCursor *cursor); BPoint GetCursorPosition(); - virtual bool IsCursorObscured(bool state);*/ - + virtual bool IsCursorObscured(bool state); + + virtual bool Lock(bigtime_t timeout = B_INFINITE_TIMEOUT); + virtual void Unlock(); + // display mode access virtual void SetMode(const display_mode &mode); diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 2cbffb09e3..0e9480522e 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -1,14 +1,106 @@ // HWInterface.cpp +#include "ServerCursor.h" + #include "HWInterface.h" // constructor HWInterface::HWInterface() - : BLocker("hw interface lock") + : BLocker("hw interface lock"), + fCursor(NULL), + fCursorVisible(true), + fCursorLocation(0.5, 0.5) { } // destructor HWInterface::~HWInterface() { + delete fCursor; } + +// SetCursor +void +HWInterface::SetCursor(ServerCursor* cursor) +{ + if (Lock()) { + if (fCursor != cursor) { + BRect oldFrame = _CursorFrame(); + delete fCursor; + fCursor = cursor; + Invalidate(oldFrame); + Invalidate(_CursorFrame()); + } + Unlock(); + } +} + +// SetCursorVisible +void +HWInterface::SetCursorVisible(bool visible) +{ + if (Lock()) { + if (fCursorVisible != visible) { + fCursorVisible = visible; + Invalidate(_CursorFrame()); + } + Unlock(); + } +} + +// IsCursorVisible +bool +HWInterface::IsCursorVisible() +{ + bool visible = true; + if (Lock()) { + visible = fCursorVisible; + Unlock(); + } + return visible; +} + +// MoveCursorTo +void +HWInterface::MoveCursorTo(const float& x, const float& y) +{ + if (Lock()) { + BPoint p(x, y); + if (p != fCursorLocation) { + BRect oldFrame = _CursorFrame(); + fCursorLocation = p; + Invalidate(oldFrame); + Invalidate(_CursorFrame()); + } + Unlock(); + } +} + +// GetCursorPosition +BPoint +HWInterface::GetCursorPosition() +{ + BPoint location; + if (Lock()) { + location = fCursorLocation; + Unlock(); + } + return location; +} + +// _CursorFrame +// +// PRE: the object must be locked +BRect +HWInterface::_CursorFrame() const +{ + BRect frame(0.0, 0.0, -1.0, -1.0); + if (fCursor && fCursorVisible) { + frame = fCursor->Bounds(); + frame.OffsetTo(fCursorLocation - fCursor->GetHotSpot()); + } + return frame; +} + + + diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index ddf13f2794..1caf3a178a 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -13,9 +13,10 @@ #include #include #include +#include class RenderingBuffer; -class BRect; +class ServerCursor; class HWInterface : public BLocker { public: @@ -25,10 +26,10 @@ class HWInterface : public BLocker { virtual status_t Initialize() = 0; virtual status_t Shutdown() = 0; + // screen mode stuff virtual status_t SetMode(const display_mode &mode) = 0; // virtual void GetMode(display_mode *mode) = 0; - virtual status_t GetDeviceInfo(accelerant_device_info *info) = 0; virtual status_t GetModeList(display_mode **mode_list, uint32 *count) = 0; @@ -46,6 +47,14 @@ class HWInterface : public BLocker { virtual uint32 DPMSMode() const = 0; virtual uint32 DPMSCapabilities() const = 0; + // cursor handling + virtual void SetCursor(ServerCursor* cursor); + virtual void SetCursorVisible(bool visible); + virtual bool IsCursorVisible(); + virtual void MoveCursorTo(const float& x, + const float& y); + BPoint GetCursorPosition(); + // frame buffer access virtual RenderingBuffer* FrontBuffer() const = 0; virtual RenderingBuffer* BackBuffer() const = 0; @@ -54,6 +63,13 @@ class HWInterface : public BLocker { virtual status_t Invalidate(const BRect& frame) = 0; // while as CopyBackToFront() actually performs the operation virtual status_t CopyBackToFront(const BRect& frame) = 0; + + protected: + BRect _CursorFrame() const; + + ServerCursor* fCursor; + bool fCursorVisible; + BPoint fCursorLocation; }; #endif // HW_INTERFACE_H diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 31f4137775..897119eda4 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -150,7 +150,7 @@ Painter::SetDrawData(const DrawData* data) SetLowColor(data->lowcolor.GetColor32()); SetScale(data->scale); SetPenSize(data->pensize); -// SetOrigin(); +// fOrigin = data->coordOrigin; SetDrawingMode(data->draw_mode); SetBlendingMode(data->alphaSrcMode, data->alphaFncMode); SetPenLocation(data->penlocation); diff --git a/src/servers/app/drawing/ViewHWInterface.cpp b/src/servers/app/drawing/ViewHWInterface.cpp index be06625462..0e5e2168a7 100644 --- a/src/servers/app/drawing/ViewHWInterface.cpp +++ b/src/servers/app/drawing/ViewHWInterface.cpp @@ -29,6 +29,7 @@ #include "BitmapBuffer.h" #include "PortLink.h" #include "ServerConfig.h" +#include "ServerCursor.h" #include "ServerProtocol.h" #include "UpdateQueue.h" @@ -112,12 +113,6 @@ class CardView : public BView { private: BPortLink* fServerLink; const BBitmap* fBitmap; - -/* int hide_cursor; - BBitmap *cursor; - - BRect cursorframe, oldcursorframe; - bool obscure_cursor;*/ }; class CardWindow : public BWindow { @@ -157,31 +152,11 @@ CardView::CardView(BRect bounds) return; } fServerLink = new BPortLink(serverInputPort); - - // Create a cursor which isn't just a box -/* cursor=new BBitmap(BRect(0,0,20,20),B_RGBA32,true); - BView *v=new BView(cursor->Bounds(),"v", B_FOLLOW_NONE, B_WILL_DRAW); - hide_cursor=0; - - cursor->Lock(); - cursor->AddChild(v); - - v->SetHighColor(255,255,255,0); - v->FillRect(cursor->Bounds()); - v->SetHighColor(255,0,0,255); - v->FillTriangle(cursor->Bounds().LeftTop(),cursor->Bounds().RightTop(),cursor->Bounds().LeftBottom()); - - cursor->RemoveChild(v); - cursor->Unlock(); - - cursorframe=cursor->Bounds(); - oldcursorframe=cursor->Bounds();*/ } CardView::~CardView() { delete fServerLink; -/* delete cursor;*/ } // AttachedToWindow @@ -197,16 +172,6 @@ CardView::Draw(BRect updateRect) if (fBitmap) { DrawBitmapAsync(fBitmap, updateRect, updateRect); } -/* if (viewbmp) { - DrawBitmapAsync(viewbmp,oldcursorframe,oldcursorframe); - DrawBitmapAsync(viewbmp,rect,rect); - - if (hide_cursor == 0 && obscure_cursor == false) { - SetDrawingMode(B_OP_ALPHA); - DrawBitmapAsync(cursor,cursor->Bounds(), cursorframe); - SetDrawingMode(B_OP_COPY); - } - }*/ } // These functions emulate the Input Server by sending the *exact* same kind of messages @@ -228,12 +193,11 @@ CardView::MouseMoved(BPoint pt, uint32 transit, const BMessage* dragMessage) { if (!Bounds().Contains(pt)) return; -// TODO: no cursor support yet // A bug in R5 prevents this call from having an effect if // called elsewhere, and calling it here works, if we're lucky :-) -// BCursor cursor(kEmptyCursor); -// SetViewCursor(&cursor, true); + BCursor cursor(kEmptyCursor); + SetViewCursor(&cursor, true); #ifdef ENABLE_INPUT_SERVER_EMULATION send_mouse_moved(fServerLink, pt, Window()->CurrentMessage()); @@ -420,9 +384,6 @@ ViewHWInterface::SetMode(const display_mode &mode) printf("ViewHWInterface::SetMode(%s)\n", string_for_color_space((color_space)fDisplayMode.space)); -// left over code -// hide_cursor=0; - BRect frame(0.0, 0.0, fDisplayMode.virtual_width - 1, fDisplayMode.virtual_height - 1); @@ -494,9 +455,6 @@ printf("ViewHWInterface::SetMode(%s)\n", string_for_color_space((color_space)fDi status_t ViewHWInterface::GetDeviceInfo(accelerant_device_info *info) { -// if(!info || !is_initialized) -// return B_ERROR; - // We really don't have to provide anything here because this is strictly // a software-only driver, but we'll have some fun, anyway. @@ -514,11 +472,6 @@ ViewHWInterface::GetDeviceInfo(accelerant_device_info *info) status_t ViewHWInterface::GetModeList(display_mode **modes, uint32 *count) { -// if(!count || !is_initialized) -// return B_ERROR; - -// screenwin->Lock(); - // DEPRECATED: // NOTE: Originally, I was going to figure out good timing values to be // returned in each of the modes supported, but I won't bother, being this @@ -576,7 +529,6 @@ ViewHWInterface::GetModeList(display_mode **modes, uint32 *count) modes[i]->v_display_start=0; modes[i]->flags=B_PARALLEL_ACCESS; } -// screenwin->Unlock(); return B_OK; } @@ -675,16 +627,14 @@ ViewHWInterface::CopyBackToFront(const BRect& frame) // && area.Intersects(fBackBuffer->Bitmap()->Bounds())) { const BBitmap* from = fBackBuffer->Bitmap(); - const BBitmap* into = fFrontBuffer->Bitmap(); +// const BBitmap* into = fFrontBuffer->Bitmap(); // make sure we don't copy out of bounds area = from->Bounds() & area; // area = into->Bounds() & area; - uint32 srcBPR = from->BytesPerRow(); - uint32 dstBPR = into->BytesPerRow(); - uint8* dst = (uint8*)into->Bits(); - uint8* src = (uint8*)from->Bits(); + uint32 srcBPR = fBackBuffer->BytesPerRow(); + uint8* src = (uint8*)fBackBuffer->Bits(); // convert to integer coordinates int32 x = (int32)floorf(area.left); @@ -695,141 +645,9 @@ ViewHWInterface::CopyBackToFront(const BRect& frame) // offset to left top pixel in source buffer (always B_RGBA32) src += y * srcBPR + x * 4; - // transfer, handle colorspace conversion - switch (into->ColorSpace()) { - case B_RGB32: - case B_RGBA32: { - int32 bytes = (right - x + 1) * 4; - - if (bytes > 0) { - // offset to left top pixel in dest buffer - dst += y * dstBPR + x * 4; - // copy - for (; y <= bottom; y++) { - memcpy(dst, src, bytes); - dst += dstBPR; - src += srcBPR; - } - } - break; - } - // NOTE: on R5, B_RGB24 bitmaps are not supported by DrawBitmap() - case B_RGB24: { - // offset to left top pixel in dest buffer - dst += y * dstBPR + x * 3; - int32 left = x; - // copy - for (; y <= bottom; y++) { - uint8* srcHandle = src; - uint8* dstHandle = dst; - x = left; - for (; x <= right; x++) { - dstHandle[0] = srcHandle[0]; - dstHandle[1] = srcHandle[1]; - dstHandle[2] = srcHandle[2]; - dstHandle += 3; - srcHandle += 4; - } - dst += dstBPR; - src += srcBPR; - } - break; - } - case B_RGB16: { - // offset to left top pixel in dest buffer - dst += y * dstBPR + x * 2; - int32 left = x; - // copy - // TODO: assumes BGR order, does this work on big endian as well? - for (; y <= bottom; y++) { - uint8* srcHandle = src; - uint16* dstHandle = (uint16*)dst; - x = left; - for (; x <= right; x++) { - *dstHandle = (uint16)(((srcHandle[2] & 0xf8) << 8) | - ((srcHandle[1] & 0xfc) << 3) | - (srcHandle[0] >> 3)); - dstHandle ++; - srcHandle += 4; - } - dst += dstBPR; - src += srcBPR; - } - break; - } - case B_RGB15: { - // offset to left top pixel in dest buffer - dst += y * dstBPR + x * 2; - int32 left = x; - // copy - // TODO: assumes BGR order, does this work on big endian as well? - for (; y <= bottom; y++) { - uint8* srcHandle = src; - uint16* dstHandle = (uint16*)dst; - x = left; - for (; x <= right; x++) { - *dstHandle = (uint16)(((srcHandle[2] & 0xf8) << 7) | - ((srcHandle[1] & 0xf8) << 2) | - (srcHandle[0] >> 3)); - dstHandle ++; - srcHandle += 4; - } - dst += dstBPR; - src += srcBPR; - } - break; - } - case B_CMAP8: { - // offset to left top pixel in dest buffer - dst += y * dstBPR + x; - int32 left = x; - // copy - // TODO: using BScreen will not be an option in the - // final implementation, will it? The BBitmap implementation - // has a class that handles this, something so useful - // should be moved to a more public place. - // TODO: assumes BGR order again - BScreen screen; - for (; y <= bottom; y++) { - uint8* srcHandle = src; - uint8* dstHandle = dst; - x = left; - for (; x <= right; x++) { - *dstHandle = screen.IndexForColor(srcHandle[2], - srcHandle[1], - srcHandle[0]); - dstHandle ++; - srcHandle += 4; - } - dst += dstBPR; - src += srcBPR; - } - break; - } - case B_GRAY8: { - // offset to left top pixel in dest buffer - dst += y * dstBPR + x; - int32 left = x; - // copy - // TODO: assumes BGR order, does this work on big endian as well? - for (; y <= bottom; y++) { - uint8* srcHandle = src; - uint8* dstHandle = dst; - x = left; - for (; x <= right; x++) { - *dstHandle = (308 * srcHandle[2] + 600 * srcHandle[1] + 116 * srcHandle[0]) / 1024; - dstHandle ++; - srcHandle += 4; - } - dst += dstBPR; - src += srcBPR; - } - break; - } - default: - fprintf(stderr, "ViewHWInterface::CopyBackToFront() - unsupported front buffer format!\n"); - break; - } + _CopyToFront(src, srcBPR, x, y, right, bottom); + + _DrawCursor(area); // update the region on screen fWindow->Invalidate(area); @@ -838,6 +656,225 @@ ViewHWInterface::CopyBackToFront(const BRect& frame) return B_OK; } +// _DrawCursor +void +ViewHWInterface::_DrawCursor(BRect area) const +{ + BRect cf = _CursorFrame(); + if (cf.IsValid() && area.Intersects(cf)) { + // clip to common area + area = area & cf; + + int32 left = (int32)floorf(area.left); + int32 top = (int32)floorf(area.top); + int32 right = (int32)ceilf(area.right); + int32 bottom = (int32)ceilf(area.bottom); + int32 width = right - left + 1; + int32 height = bottom - top + 1; + + // make a bitmap from the backbuffer + // that has the cursor blended on top of it + + // blending buffer + uint8* buffer = new uint8[width * height * 4]; + + // offset into back buffer + uint8* src = (uint8*)fBackBuffer->Bits(); + uint32 srcBPR = fBackBuffer->BytesPerRow(); + src += top * srcBPR + left * 4; + + // offset into cursor bitmap + uint8* crs = (uint8*)fCursor->Bits(); + uint32 crsBPR = fCursor->BytesPerRow(); + // since area is clipped to cf, + // the diff between top and cf.top is always positive, + // same for diff between left and cf.left + crs += (top - (int32)floorf(cf.top)) * crsBPR + + (left - (int32)floorf(cf.left)) * 4; + + uint8* dst = buffer; + + // blending + for (int32 y = top; y <= bottom; y++) { + uint8* s = src; + uint8* c = crs; + uint8* d = dst; + for (int32 x = left; x <= right; x++) { + // assume backbuffer alpha = 255 + // TODO: it appears alpha in cursor us upside down + uint8 a = 255 - c[3]; + d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8; + d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8; + d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8; + d[3] = 255; + s += 4; + c += 4; + d += 4; + } + crs += crsBPR; + src += srcBPR; + dst += width * 4; + } + + // copy result to front buffer + _CopyToFront(buffer, width * 4, left, top, right, bottom); + + delete[] buffer; + } +} + +// _CopyToFront +// +// * source is assumed to be already at the right offset +// * source is assumed to be in B_RGBA32 format +// * location in front buffer is calculated +// * conversion from B_RGBA32 to format of front buffer is taken care of +void +ViewHWInterface::_CopyToFront(uint8* src, uint32 srcBPR, + int32 x, int32 y, + int32 right, int32 bottom) const +{ + uint8* dst = (uint8*)fFrontBuffer->Bits(); + uint32 dstBPR = fFrontBuffer->BytesPerRow(); + + // transfer, handle colorspace conversion + switch (fFrontBuffer->ColorSpace()) { + case B_RGB32: + case B_RGBA32: { + int32 bytes = (right - x + 1) * 4; + + if (bytes > 0) { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 4; + // copy + for (; y <= bottom; y++) { + memcpy(dst, src, bytes); + dst += dstBPR; + src += srcBPR; + } + } + break; + } + // NOTE: on R5, B_RGB24 bitmaps are not supported by DrawBitmap() + case B_RGB24: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 3; + int32 left = x; + // copy + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint8* dstHandle = dst; + x = left; + for (; x <= right; x++) { + dstHandle[0] = srcHandle[0]; + dstHandle[1] = srcHandle[1]; + dstHandle[2] = srcHandle[2]; + dstHandle += 3; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_RGB16: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 2; + int32 left = x; + // copy + // TODO: assumes BGR order, does this work on big endian as well? + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint16* dstHandle = (uint16*)dst; + x = left; + for (; x <= right; x++) { + *dstHandle = (uint16)(((srcHandle[2] & 0xf8) << 8) | + ((srcHandle[1] & 0xfc) << 3) | + (srcHandle[0] >> 3)); + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_RGB15: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 2; + int32 left = x; + // copy + // TODO: assumes BGR order, does this work on big endian as well? + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint16* dstHandle = (uint16*)dst; + x = left; + for (; x <= right; x++) { + *dstHandle = (uint16)(((srcHandle[2] & 0xf8) << 7) | + ((srcHandle[1] & 0xf8) << 2) | + (srcHandle[0] >> 3)); + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_CMAP8: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x; + int32 left = x; + // copy + // TODO: using BScreen will not be an option in the + // final implementation, will it? The BBitmap implementation + // has a class that handles this, something so useful + // should be moved to a more public place. + // TODO: assumes BGR order again + BScreen screen; + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint8* dstHandle = dst; + x = left; + for (; x <= right; x++) { + *dstHandle = screen.IndexForColor(srcHandle[2], + srcHandle[1], + srcHandle[0]); + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_GRAY8: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x; + int32 left = x; + // copy + // TODO: assumes BGR order, does this work on big endian as well? + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint8* dstHandle = dst; + x = left; + for (; x <= right; x++) { + *dstHandle = (308 * srcHandle[2] + 600 * srcHandle[1] + 116 * srcHandle[0]) / 1024; + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + default: + fprintf(stderr, "ViewHWInterface::CopyBackToFront() - unsupported front buffer format!\n"); + break; + } + +} + /*void ViewHWInterface::CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d) { diff --git a/src/servers/app/drawing/ViewHWInterface.h b/src/servers/app/drawing/ViewHWInterface.h index 5375f2e277..728e238e81 100644 --- a/src/servers/app/drawing/ViewHWInterface.h +++ b/src/servers/app/drawing/ViewHWInterface.h @@ -57,6 +57,11 @@ class ViewHWInterface : public HWInterface { virtual status_t CopyBackToFront(const BRect& area); private: + void _DrawCursor(BRect area) const; + void _CopyToFront(uint8* src, uint32 srcBPR, + int32 x, int32 y, + int32 right, int32 bottom) const; + BitmapBuffer* fBackBuffer; BitmapBuffer* fFrontBuffer;