From ded5874ea2183328e81015e199f54a3dd786fc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 20 Apr 2005 09:27:15 +0000 Subject: [PATCH] Implemented changes necessary for single buffered mode, it is turned off for now, because the soft cursor is currently not being taken care of. We will still use double buffering if the screen color space is not 32 bits, too. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12449 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/servers/app/RenderingBuffer.h | 9 +- .../app/drawing/AccelerantHWInterface.cpp | 93 ++++++++++++++----- .../app/drawing/AccelerantHWInterface.h | 6 ++ .../app/drawing/DisplayDriverPainter.cpp | 16 ++-- src/servers/app/drawing/HWInterface.cpp | 48 ++++++++-- src/servers/app/drawing/HWInterface.h | 11 ++- src/servers/app/drawing/ViewHWInterface.cpp | 63 +++++++++---- src/servers/app/drawing/ViewHWInterface.h | 3 +- 8 files changed, 185 insertions(+), 64 deletions(-) diff --git a/headers/private/servers/app/RenderingBuffer.h b/headers/private/servers/app/RenderingBuffer.h index c51c3ebbda..0ef31400b4 100644 --- a/headers/private/servers/app/RenderingBuffer.h +++ b/headers/private/servers/app/RenderingBuffer.h @@ -7,16 +7,21 @@ class RenderingBuffer { public: - RenderingBuffer() {}; - virtual ~RenderingBuffer() {}; + RenderingBuffer() {} + virtual ~RenderingBuffer() {} virtual status_t InitCheck() const = 0; virtual color_space ColorSpace() const = 0; virtual void* Bits() const = 0; virtual uint32 BytesPerRow() const = 0; + // the *count* of the pixels per line virtual uint32 Width() const = 0; + // the *count* of lines virtual uint32 Height() const = 0; + + inline uint32 BitsLength() const + { return Height() * BytesPerRow(); } }; #endif // RENDERING_BUFFER_H diff --git a/src/servers/app/drawing/AccelerantHWInterface.cpp b/src/servers/app/drawing/AccelerantHWInterface.cpp index 9c1647dc80..ff42cc776e 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.cpp +++ b/src/servers/app/drawing/AccelerantHWInterface.cpp @@ -329,23 +329,33 @@ AccelerantHWInterface::SetMode(const display_mode &mode) // NOTE: backbuffer is always B_RGBA32, this simplifies the // drawing backend implementation tremendously for the time // being. The color space conversion is handled in CopyBackToFront() - + delete fBackBuffer; - fBackBuffer = new MallocBuffer(fDisplayMode.virtual_width, - fDisplayMode.virtual_height); + + // TODO: Above not true anymore for single buffered mode!!! + // -> fall back to double buffer for fDisplayMode.space != B_RGB32 + // as intermediate solution... + bool doubleBuffered = HWInterface::IsDoubleBuffered(); + if ((color_space)fDisplayMode.space != B_RGB32 && + (color_space)fDisplayMode.space != B_RGBA32) + doubleBuffered = true; - status_t ret = fBackBuffer->InitCheck(); - if (ret < B_OK) { - delete fBackBuffer; - fBackBuffer = NULL; - return ret; + if (doubleBuffered) { + fBackBuffer = new MallocBuffer(fDisplayMode.virtual_width, + fDisplayMode.virtual_height); + + status_t ret = fBackBuffer->InitCheck(); + if (ret < B_OK) { + delete fBackBuffer; + fBackBuffer = NULL; + return ret; + } } // clear out backbuffer, alpha is 255 this way // TODO: maybe this should handle different color spaces in different // ways - memset(fBackBuffer->Bits(), 255, - fBackBuffer->BytesPerRow() * fBackBuffer->Height()); + memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength()); } return B_OK; @@ -454,6 +464,21 @@ AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode * return fAccProposeDisplayMode(candidate, &this_low, &this_high); } +// WaitForRetrace +status_t +AccelerantHWInterface::WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) +{ + accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL); + if (!AccelerantRetraceSemaphore) + return B_UNSUPPORTED; + + sem_id sem = AccelerantRetraceSemaphore(); + if (sem < 0) + return B_ERROR; + + return acquire_sem_etc(sem, 1, B_RELATIVE_TIMEOUT, timeout); +} + // SetDPMSMode status_t AccelerantHWInterface::SetDPMSMode(const uint32 &state) @@ -484,19 +509,41 @@ AccelerantHWInterface::DPMSCapabilities() const return fAccDPMSCapabilities(); } -// WaitForRetrace -status_t -AccelerantHWInterface::WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) +// SetCursor +void +AccelerantHWInterface::SetCursor(ServerCursor* cursor) { - accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL); - if (!AccelerantRetraceSemaphore) - return B_UNSUPPORTED; - - sem_id sem = AccelerantRetraceSemaphore(); - if (sem < 0) - return B_ERROR; - - return acquire_sem_etc(sem, 1, B_RELATIVE_TIMEOUT, timeout); + if (Lock()) { + HWInterface::SetCursor(cursor); + // TODO: implement setting the hard ware cursor + // NOTE: cursor should be always B_RGBA32 + // NOTE: The HWInterface implementation should + // still be called, since it takes ownership of + // the cursor. + Unlock(); + } +} + +// SetCursorVisible +void +AccelerantHWInterface::SetCursorVisible(bool visible) +{ + if (Lock()) { + HWInterface::SetCursorVisible(visible); + // TODO: update graphics hardware + Unlock(); + } +} + +// MoveCursorTo +void +AccelerantHWInterface::MoveCursorTo(const float& x, const float& y) +{ + if (Lock()) { + HWInterface::MoveCursorTo(x, y); + // TODO: update graphics hardware + Unlock(); + } } // FrontBuffer @@ -526,5 +573,7 @@ AccelerantHWInterface::_DrawCursor(BRect area) const // use the default implementation for now, // until we have a hardware cursor HWInterface::_DrawCursor(area); + // TODO: this would only be called, if we don't have + // a hardware cursor for some reason } diff --git a/src/servers/app/drawing/AccelerantHWInterface.h b/src/servers/app/drawing/AccelerantHWInterface.h index 018d010080..b46d1a472b 100644 --- a/src/servers/app/drawing/AccelerantHWInterface.h +++ b/src/servers/app/drawing/AccelerantHWInterface.h @@ -49,6 +49,12 @@ virtual status_t SetDPMSMode(const uint32 &state); virtual uint32 DPMSMode() const; virtual uint32 DPMSCapabilities() const; + // cursor handling +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; diff --git a/src/servers/app/drawing/DisplayDriverPainter.cpp b/src/servers/app/drawing/DisplayDriverPainter.cpp index 82db81c2db..1d736c7162 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.cpp +++ b/src/servers/app/drawing/DisplayDriverPainter.cpp @@ -96,7 +96,7 @@ DisplayDriverPainter::CopyBits(const BRect &src, const BRect &dst, if (Lock()) { // TODO: handle clipping to d->clipreg here? - RenderingBuffer* backBuffer = fGraphicsCard->BackBuffer(); + RenderingBuffer* backBuffer = fGraphicsCard->DrawingBuffer(); BRect valid(0, 0, backBuffer->Width() - 1, backBuffer->Height() - 1); if (valid.Intersects(src) && valid.Intersects(dst)) { @@ -288,7 +288,7 @@ DisplayDriverPainter::CopyRegionList(BList* list, BList* pList, BRect updateRect; - RenderingBuffer* backBuffer = fGraphicsCard->BackBuffer(); + RenderingBuffer* backBuffer = fGraphicsCard->DrawingBuffer(); uint8* bits = (uint8*)backBuffer->Bits(); uint32 bpr = backBuffer->BytesPerRow(); @@ -355,7 +355,7 @@ printf("region: %ld, rect: %ld, offset(%ld, %ld)\n", i, j, xOffset, yOffset); } */ - RenderingBuffer* bmp = fGraphicsCard->BackBuffer(); + RenderingBuffer* bmp = fGraphicsCard->DrawingBuffer(); uint32 bytesPerPixel = bmp->BytesPerRow() / bmp->Width(); BList rectList; @@ -1081,7 +1081,7 @@ DisplayDriverPainter::SetMode(const display_mode &mode) { if (Lock()) { if (fGraphicsCard->SetMode(mode) >= B_OK) { - fPainter->AttachToBuffer(fGraphicsCard->BackBuffer()); + fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer()); DisplayDriver::SetMode(mode); } else { fprintf(stderr, "DisplayDriverPainter::SetMode() - unsupported " @@ -1113,10 +1113,10 @@ DisplayDriverPainter::DumpToFile(const char *path) if (!output) return false; - RenderingBuffer *back_buffer = fGraphicsCard->BackBuffer(); - uint32 row = back_buffer->BytesPerRow() / 4; + RenderingBuffer *backBuffer = fGraphicsCard->DrawingBuffer(); + uint32 row = backBuffer->BytesPerRow() / 4; for (int i = 0; i < fDisplayMode.virtual_height; i++) { - fwrite((uint32 *)back_buffer->Bits() + i * row, 4, row, output); + fwrite((uint32 *)backBuffer->Bits() + i * row, 4, row, output); sync(); } fclose(output); @@ -1300,7 +1300,7 @@ void DisplayDriverPainter::ConstrainClippingRegion(BRegion *region) if (!region) { // BRegion empty; // fPainter->ConstrainClipping(empty); - if (RenderingBuffer* buffer = fGraphicsCard->BackBuffer()) { + if (RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer()) { BRegion all; all.Include(BRect(0, 0, buffer->Width() - 1, buffer->Height() - 1)); diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index f10be3de2b..48cf933ddc 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -14,11 +14,12 @@ #include "HWInterface.h" // constructor -HWInterface::HWInterface() +HWInterface::HWInterface(bool doubleBuffered) : BLocker("hw interface lock"), fCursor(NULL), fCursorVisible(true), fCursorLocation(0, 0), + fDoubleBuffered(doubleBuffered), // fUpdateExecutor(new UpdateQueue(this)) fUpdateExecutor(NULL) { @@ -100,23 +101,44 @@ HWInterface::GetCursorPosition() return location; } +// DrawingBuffer +RenderingBuffer* +HWInterface::DrawingBuffer() const +{ + if (IsDoubleBuffered()) + return BackBuffer(); + return FrontBuffer(); +} + +// IsDoubleBuffered +bool +HWInterface::IsDoubleBuffered() const +{ + return fDoubleBuffered; +} + // Invalidate // * the object needs to be already locked! status_t HWInterface::Invalidate(const BRect& frame) { - return CopyBackToFront(frame); + if (IsDoubleBuffered()) { + return CopyBackToFront(frame); // TODO: the remaining problem is the immediate wake up of the // thread carrying out the updates, when I enable it, there // seems to be a deadlock, but I didn't figure it out yet. // Maybe the same bug is there without the wakeup, only, triggered // less often.... scarry, huh? -/* if (frame.IsValid()) { - fUpdateExecutor->AddRect(frame); - return B_OK; +/* if (frame.IsValid()) { + fUpdateExecutor->AddRect(frame); + return B_OK; + } + return B_BAD_VALUE;*/ + } else { + _DrawCursor(frame); } - return B_BAD_VALUE;*/ + return B_OK; } // CopyBackToFront @@ -162,12 +184,22 @@ HWInterface::CopyBackToFront(const BRect& frame) // _DrawCursor // * default implementation, can be used as fallback or for // software cursor +// * area is where we potentially draw the cursor, the cursor +// might be somewhere else, in which case this function does nothing void HWInterface::_DrawCursor(BRect area) const { + RenderingBuffer* backBuffer = DrawingBuffer(); + if (!backBuffer) + return; + BRect cf = _CursorFrame(); - RenderingBuffer* backBuffer = BackBuffer(); - if (backBuffer && cf.IsValid() && area.Intersects(cf)) { + + // make sure we don't copy out of bounds + BRect bufferClip(0.0, 0.0, backBuffer->Width() - 1, backBuffer->Height() - 1); + area = bufferClip & area; + + if (cf.IsValid() && area.Intersects(cf)) { // clip to common area area = area & cf; diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index c70a58a46a..bcfb177af9 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -21,7 +21,7 @@ class UpdateQueue; class HWInterface : public BLocker { public: - HWInterface(); + HWInterface(bool doubleBuffered = true); virtual ~HWInterface(); virtual status_t Initialize() = 0; @@ -51,19 +51,21 @@ class HWInterface : public BLocker { // cursor handling virtual void SetCursor(ServerCursor* cursor); virtual void SetCursorVisible(bool visible); - virtual bool IsCursorVisible(); + bool IsCursorVisible(); virtual void MoveCursorTo(const float& x, const float& y); BPoint GetCursorPosition(); // frame buffer access + RenderingBuffer* DrawingBuffer() const; virtual RenderingBuffer* FrontBuffer() const = 0; virtual RenderingBuffer* BackBuffer() const = 0; + virtual bool IsDoubleBuffered() const; // Invalidate is planned to be used for scheduling an area for updating - status_t Invalidate(const BRect& frame); + virtual status_t Invalidate(const BRect& frame); // while as CopyBackToFront() actually performs the operation - virtual status_t CopyBackToFront(const BRect& frame); + status_t CopyBackToFront(const BRect& frame); protected: // implement this in derived classes @@ -79,6 +81,7 @@ class HWInterface : public BLocker { ServerCursor* fCursor; bool fCursorVisible; BPoint fCursorLocation; + bool fDoubleBuffered; private: UpdateQueue* fUpdateExecutor; diff --git a/src/servers/app/drawing/ViewHWInterface.cpp b/src/servers/app/drawing/ViewHWInterface.cpp index 8a95b5b2a6..efc5f98f53 100644 --- a/src/servers/app/drawing/ViewHWInterface.cpp +++ b/src/servers/app/drawing/ViewHWInterface.cpp @@ -403,31 +403,46 @@ ViewHWInterface::SetMode(const display_mode &mode) // NOTE: backbuffer is always B_RGBA32, this simplifies the // drawing backend implementation tremendously for the time // being. The color space conversion is handled in CopyBackToFront() - BBitmap* backBitmap = new BBitmap(frame, 0, B_RGBA32); - BBitmap* frontBitmap = new BBitmap(frame, 0, (color_space)fDisplayMode.space); - fBackBuffer = new BitmapBuffer(backBitmap); + // TODO: Above not true anymore for single buffered mode!!! + // -> fall back to double buffer for fDisplayMode.space != B_RGB32 + // as intermediate solution... + bool doubleBuffered = HWInterface::IsDoubleBuffered(); + if ((color_space)fDisplayMode.space != B_RGB32 && + (color_space)fDisplayMode.space != B_RGBA32) + doubleBuffered = true; + + BBitmap* frontBitmap = new BBitmap(frame, 0, (color_space)fDisplayMode.space); fFrontBuffer = new BitmapBuffer(frontBitmap); - status_t err = fBackBuffer->InitCheck(); - if (err < B_OK) { - delete fBackBuffer; - fBackBuffer = NULL; - ret = err; - } - - err = fFrontBuffer->InitCheck(); + status_t err = fFrontBuffer->InitCheck(); if (err < B_OK) { delete fFrontBuffer; fFrontBuffer = NULL; ret = err; } + if (err >= B_OK && doubleBuffered) { + // backbuffer is always B_RGBA32 + // since we override IsDoubleBuffered(), the drawing buffer + // is in effect also always B_RGBA32. + BBitmap* backBitmap = new BBitmap(frame, 0, B_RGBA32); + fBackBuffer = new BitmapBuffer(backBitmap); + + err = fBackBuffer->InitCheck(); + if (err < B_OK) { + delete fBackBuffer; + fBackBuffer = NULL; + ret = err; + } + } + if (ret >= B_OK) { // clear out buffers, alpha is 255 this way // TODO: maybe this should handle different color spaces in different ways - memset(backBitmap->Bits(), 255, backBitmap->BitsLength()); - memset(frontBitmap->Bits(), 255, frontBitmap->BitsLength()); + if (fBackBuffer) + memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength()); + memset(fFrontBuffer->Bits(), 255, fFrontBuffer->BitsLength()); // change the window size and update the bitmap used for drawing fWindow->ResizeTo(frame.Width(), frame.Height()); @@ -600,13 +615,23 @@ ViewHWInterface::BackBuffer() const return fBackBuffer; } -// CopyBackToFront -status_t -ViewHWInterface::CopyBackToFront(const BRect& frame) +// IsDoubleBuffered +bool +ViewHWInterface::IsDoubleBuffered() const { - status_t ret = HWInterface::CopyBackToFront(frame); -// TODO: investigate why this function is called before SetMode() was called! - if (fWindow) + if (fFrontBuffer) + return fBackBuffer != NULL; + + return HWInterface::IsDoubleBuffered(); +} + +// Invalidate +status_t +ViewHWInterface::Invalidate(const BRect& frame) +{ + status_t ret = HWInterface::Invalidate(frame); + + if (ret >= B_OK && fWindow) fWindow->Invalidate(frame); return ret; } diff --git a/src/servers/app/drawing/ViewHWInterface.h b/src/servers/app/drawing/ViewHWInterface.h index 15676410e8..509bd9ceb0 100644 --- a/src/servers/app/drawing/ViewHWInterface.h +++ b/src/servers/app/drawing/ViewHWInterface.h @@ -52,8 +52,9 @@ class ViewHWInterface : public HWInterface { // frame buffer access virtual RenderingBuffer* FrontBuffer() const; virtual RenderingBuffer* BackBuffer() const; + virtual bool IsDoubleBuffered() const; - virtual status_t CopyBackToFront(const BRect& frame); + virtual status_t Invalidate(const BRect& frame); private: BitmapBuffer* fBackBuffer;