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
This commit is contained in:
Stephan Aßmus
2005-04-20 09:27:15 +00:00
parent 807ba996da
commit ded5874ea2
8 changed files with 185 additions and 64 deletions
@@ -7,16 +7,21 @@
class RenderingBuffer { class RenderingBuffer {
public: public:
RenderingBuffer() {}; RenderingBuffer() {}
virtual ~RenderingBuffer() {}; virtual ~RenderingBuffer() {}
virtual status_t InitCheck() const = 0; virtual status_t InitCheck() const = 0;
virtual color_space ColorSpace() const = 0; virtual color_space ColorSpace() const = 0;
virtual void* Bits() const = 0; virtual void* Bits() const = 0;
virtual uint32 BytesPerRow() const = 0; virtual uint32 BytesPerRow() const = 0;
// the *count* of the pixels per line
virtual uint32 Width() const = 0; virtual uint32 Width() const = 0;
// the *count* of lines
virtual uint32 Height() const = 0; virtual uint32 Height() const = 0;
inline uint32 BitsLength() const
{ return Height() * BytesPerRow(); }
}; };
#endif // RENDERING_BUFFER_H #endif // RENDERING_BUFFER_H
@@ -331,21 +331,31 @@ AccelerantHWInterface::SetMode(const display_mode &mode)
// being. The color space conversion is handled in CopyBackToFront() // being. The color space conversion is handled in CopyBackToFront()
delete fBackBuffer; delete fBackBuffer;
fBackBuffer = new MallocBuffer(fDisplayMode.virtual_width,
fDisplayMode.virtual_height);
status_t ret = fBackBuffer->InitCheck(); // TODO: Above not true anymore for single buffered mode!!!
if (ret < B_OK) { // -> fall back to double buffer for fDisplayMode.space != B_RGB32
delete fBackBuffer; // as intermediate solution...
fBackBuffer = NULL; bool doubleBuffered = HWInterface::IsDoubleBuffered();
return ret; if ((color_space)fDisplayMode.space != B_RGB32 &&
(color_space)fDisplayMode.space != B_RGBA32)
doubleBuffered = true;
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 // clear out backbuffer, alpha is 255 this way
// TODO: maybe this should handle different color spaces in different // TODO: maybe this should handle different color spaces in different
// ways // ways
memset(fBackBuffer->Bits(), 255, memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength());
fBackBuffer->BytesPerRow() * fBackBuffer->Height());
} }
return B_OK; return B_OK;
@@ -454,6 +464,21 @@ AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode *
return fAccProposeDisplayMode(candidate, &this_low, &this_high); 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 // SetDPMSMode
status_t status_t
AccelerantHWInterface::SetDPMSMode(const uint32 &state) AccelerantHWInterface::SetDPMSMode(const uint32 &state)
@@ -484,19 +509,41 @@ AccelerantHWInterface::DPMSCapabilities() const
return fAccDPMSCapabilities(); return fAccDPMSCapabilities();
} }
// WaitForRetrace // SetCursor
status_t void
AccelerantHWInterface::WaitForRetrace(bigtime_t timeout = B_INFINITE_TIMEOUT) AccelerantHWInterface::SetCursor(ServerCursor* cursor)
{ {
accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL); if (Lock()) {
if (!AccelerantRetraceSemaphore) HWInterface::SetCursor(cursor);
return B_UNSUPPORTED; // 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();
}
}
sem_id sem = AccelerantRetraceSemaphore(); // SetCursorVisible
if (sem < 0) void
return B_ERROR; AccelerantHWInterface::SetCursorVisible(bool visible)
{
if (Lock()) {
HWInterface::SetCursorVisible(visible);
// TODO: update graphics hardware
Unlock();
}
}
return acquire_sem_etc(sem, 1, B_RELATIVE_TIMEOUT, timeout); // MoveCursorTo
void
AccelerantHWInterface::MoveCursorTo(const float& x, const float& y)
{
if (Lock()) {
HWInterface::MoveCursorTo(x, y);
// TODO: update graphics hardware
Unlock();
}
} }
// FrontBuffer // FrontBuffer
@@ -526,5 +573,7 @@ AccelerantHWInterface::_DrawCursor(BRect area) const
// use the default implementation for now, // use the default implementation for now,
// until we have a hardware cursor // until we have a hardware cursor
HWInterface::_DrawCursor(area); HWInterface::_DrawCursor(area);
// TODO: this would only be called, if we don't have
// a hardware cursor for some reason
} }
@@ -49,6 +49,12 @@ virtual status_t SetDPMSMode(const uint32 &state);
virtual uint32 DPMSMode() const; virtual uint32 DPMSMode() const;
virtual uint32 DPMSCapabilities() 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 // frame buffer access
virtual RenderingBuffer *FrontBuffer() const; virtual RenderingBuffer *FrontBuffer() const;
virtual RenderingBuffer *BackBuffer() const; virtual RenderingBuffer *BackBuffer() const;
@@ -96,7 +96,7 @@ DisplayDriverPainter::CopyBits(const BRect &src, const BRect &dst,
if (Lock()) { if (Lock()) {
// TODO: handle clipping to d->clipreg here? // 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); BRect valid(0, 0, backBuffer->Width() - 1, backBuffer->Height() - 1);
if (valid.Intersects(src) && valid.Intersects(dst)) { if (valid.Intersects(src) && valid.Intersects(dst)) {
@@ -288,7 +288,7 @@ DisplayDriverPainter::CopyRegionList(BList* list, BList* pList,
BRect updateRect; BRect updateRect;
RenderingBuffer* backBuffer = fGraphicsCard->BackBuffer(); RenderingBuffer* backBuffer = fGraphicsCard->DrawingBuffer();
uint8* bits = (uint8*)backBuffer->Bits(); uint8* bits = (uint8*)backBuffer->Bits();
uint32 bpr = backBuffer->BytesPerRow(); 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(); uint32 bytesPerPixel = bmp->BytesPerRow() / bmp->Width();
BList rectList; BList rectList;
@@ -1081,7 +1081,7 @@ DisplayDriverPainter::SetMode(const display_mode &mode)
{ {
if (Lock()) { if (Lock()) {
if (fGraphicsCard->SetMode(mode) >= B_OK) { if (fGraphicsCard->SetMode(mode) >= B_OK) {
fPainter->AttachToBuffer(fGraphicsCard->BackBuffer()); fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer());
DisplayDriver::SetMode(mode); DisplayDriver::SetMode(mode);
} else { } else {
fprintf(stderr, "DisplayDriverPainter::SetMode() - unsupported " fprintf(stderr, "DisplayDriverPainter::SetMode() - unsupported "
@@ -1113,10 +1113,10 @@ DisplayDriverPainter::DumpToFile(const char *path)
if (!output) if (!output)
return false; return false;
RenderingBuffer *back_buffer = fGraphicsCard->BackBuffer(); RenderingBuffer *backBuffer = fGraphicsCard->DrawingBuffer();
uint32 row = back_buffer->BytesPerRow() / 4; uint32 row = backBuffer->BytesPerRow() / 4;
for (int i = 0; i < fDisplayMode.virtual_height; i++) { 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(); sync();
} }
fclose(output); fclose(output);
@@ -1300,7 +1300,7 @@ void DisplayDriverPainter::ConstrainClippingRegion(BRegion *region)
if (!region) { if (!region) {
// BRegion empty; // BRegion empty;
// fPainter->ConstrainClipping(empty); // fPainter->ConstrainClipping(empty);
if (RenderingBuffer* buffer = fGraphicsCard->BackBuffer()) { if (RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer()) {
BRegion all; BRegion all;
all.Include(BRect(0, 0, buffer->Width() - 1, all.Include(BRect(0, 0, buffer->Width() - 1,
buffer->Height() - 1)); buffer->Height() - 1));
+40 -8
View File
@@ -14,11 +14,12 @@
#include "HWInterface.h" #include "HWInterface.h"
// constructor // constructor
HWInterface::HWInterface() HWInterface::HWInterface(bool doubleBuffered)
: BLocker("hw interface lock"), : BLocker("hw interface lock"),
fCursor(NULL), fCursor(NULL),
fCursorVisible(true), fCursorVisible(true),
fCursorLocation(0, 0), fCursorLocation(0, 0),
fDoubleBuffered(doubleBuffered),
// fUpdateExecutor(new UpdateQueue(this)) // fUpdateExecutor(new UpdateQueue(this))
fUpdateExecutor(NULL) fUpdateExecutor(NULL)
{ {
@@ -100,23 +101,44 @@ HWInterface::GetCursorPosition()
return location; return location;
} }
// DrawingBuffer
RenderingBuffer*
HWInterface::DrawingBuffer() const
{
if (IsDoubleBuffered())
return BackBuffer();
return FrontBuffer();
}
// IsDoubleBuffered
bool
HWInterface::IsDoubleBuffered() const
{
return fDoubleBuffered;
}
// Invalidate // Invalidate
// * the object needs to be already locked! // * the object needs to be already locked!
status_t status_t
HWInterface::Invalidate(const BRect& frame) HWInterface::Invalidate(const BRect& frame)
{ {
return CopyBackToFront(frame); if (IsDoubleBuffered()) {
return CopyBackToFront(frame);
// TODO: the remaining problem is the immediate wake up of the // TODO: the remaining problem is the immediate wake up of the
// thread carrying out the updates, when I enable it, there // thread carrying out the updates, when I enable it, there
// seems to be a deadlock, but I didn't figure it out yet. // seems to be a deadlock, but I didn't figure it out yet.
// Maybe the same bug is there without the wakeup, only, triggered // Maybe the same bug is there without the wakeup, only, triggered
// less often.... scarry, huh? // less often.... scarry, huh?
/* if (frame.IsValid()) { /* if (frame.IsValid()) {
fUpdateExecutor->AddRect(frame); fUpdateExecutor->AddRect(frame);
return B_OK; return B_OK;
}
return B_BAD_VALUE;*/
} else {
_DrawCursor(frame);
} }
return B_BAD_VALUE;*/ return B_OK;
} }
// CopyBackToFront // CopyBackToFront
@@ -162,12 +184,22 @@ HWInterface::CopyBackToFront(const BRect& frame)
// _DrawCursor // _DrawCursor
// * default implementation, can be used as fallback or for // * default implementation, can be used as fallback or for
// software cursor // software cursor
// * area is where we potentially draw the cursor, the cursor
// might be somewhere else, in which case this function does nothing
void void
HWInterface::_DrawCursor(BRect area) const HWInterface::_DrawCursor(BRect area) const
{ {
RenderingBuffer* backBuffer = DrawingBuffer();
if (!backBuffer)
return;
BRect cf = _CursorFrame(); 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 // clip to common area
area = area & cf; area = area & cf;
+7 -4
View File
@@ -21,7 +21,7 @@ class UpdateQueue;
class HWInterface : public BLocker { class HWInterface : public BLocker {
public: public:
HWInterface(); HWInterface(bool doubleBuffered = true);
virtual ~HWInterface(); virtual ~HWInterface();
virtual status_t Initialize() = 0; virtual status_t Initialize() = 0;
@@ -51,19 +51,21 @@ class HWInterface : public BLocker {
// cursor handling // cursor handling
virtual void SetCursor(ServerCursor* cursor); virtual void SetCursor(ServerCursor* cursor);
virtual void SetCursorVisible(bool visible); virtual void SetCursorVisible(bool visible);
virtual bool IsCursorVisible(); bool IsCursorVisible();
virtual void MoveCursorTo(const float& x, virtual void MoveCursorTo(const float& x,
const float& y); const float& y);
BPoint GetCursorPosition(); BPoint GetCursorPosition();
// frame buffer access // frame buffer access
RenderingBuffer* DrawingBuffer() const;
virtual RenderingBuffer* FrontBuffer() const = 0; virtual RenderingBuffer* FrontBuffer() const = 0;
virtual RenderingBuffer* BackBuffer() const = 0; virtual RenderingBuffer* BackBuffer() const = 0;
virtual bool IsDoubleBuffered() const;
// Invalidate is planned to be used for scheduling an area for updating // 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 // while as CopyBackToFront() actually performs the operation
virtual status_t CopyBackToFront(const BRect& frame); status_t CopyBackToFront(const BRect& frame);
protected: protected:
// implement this in derived classes // implement this in derived classes
@@ -79,6 +81,7 @@ class HWInterface : public BLocker {
ServerCursor* fCursor; ServerCursor* fCursor;
bool fCursorVisible; bool fCursorVisible;
BPoint fCursorLocation; BPoint fCursorLocation;
bool fDoubleBuffered;
private: private:
UpdateQueue* fUpdateExecutor; UpdateQueue* fUpdateExecutor;
+44 -19
View File
@@ -403,31 +403,46 @@ ViewHWInterface::SetMode(const display_mode &mode)
// NOTE: backbuffer is always B_RGBA32, this simplifies the // NOTE: backbuffer is always B_RGBA32, this simplifies the
// drawing backend implementation tremendously for the time // drawing backend implementation tremendously for the time
// being. The color space conversion is handled in CopyBackToFront() // 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); fFrontBuffer = new BitmapBuffer(frontBitmap);
status_t err = fBackBuffer->InitCheck(); status_t err = fFrontBuffer->InitCheck();
if (err < B_OK) {
delete fBackBuffer;
fBackBuffer = NULL;
ret = err;
}
err = fFrontBuffer->InitCheck();
if (err < B_OK) { if (err < B_OK) {
delete fFrontBuffer; delete fFrontBuffer;
fFrontBuffer = NULL; fFrontBuffer = NULL;
ret = err; 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) { if (ret >= B_OK) {
// clear out buffers, alpha is 255 this way // clear out buffers, alpha is 255 this way
// TODO: maybe this should handle different color spaces in different ways // TODO: maybe this should handle different color spaces in different ways
memset(backBitmap->Bits(), 255, backBitmap->BitsLength()); if (fBackBuffer)
memset(frontBitmap->Bits(), 255, frontBitmap->BitsLength()); memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength());
memset(fFrontBuffer->Bits(), 255, fFrontBuffer->BitsLength());
// change the window size and update the bitmap used for drawing // change the window size and update the bitmap used for drawing
fWindow->ResizeTo(frame.Width(), frame.Height()); fWindow->ResizeTo(frame.Width(), frame.Height());
@@ -600,13 +615,23 @@ ViewHWInterface::BackBuffer() const
return fBackBuffer; return fBackBuffer;
} }
// CopyBackToFront // IsDoubleBuffered
status_t bool
ViewHWInterface::CopyBackToFront(const BRect& frame) ViewHWInterface::IsDoubleBuffered() const
{ {
status_t ret = HWInterface::CopyBackToFront(frame); if (fFrontBuffer)
// TODO: investigate why this function is called before SetMode() was called! return fBackBuffer != NULL;
if (fWindow)
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); fWindow->Invalidate(frame);
return ret; return ret;
} }
+2 -1
View File
@@ -52,8 +52,9 @@ class ViewHWInterface : public HWInterface {
// frame buffer access // frame buffer access
virtual RenderingBuffer* FrontBuffer() const; virtual RenderingBuffer* FrontBuffer() const;
virtual RenderingBuffer* BackBuffer() const; virtual RenderingBuffer* BackBuffer() const;
virtual bool IsDoubleBuffered() const;
virtual status_t CopyBackToFront(const BRect& frame); virtual status_t Invalidate(const BRect& frame);
private: private:
BitmapBuffer* fBackBuffer; BitmapBuffer* fBackBuffer;