[haiku-commits] BRANCH looncraz-github.CAP-volatile - in src/servers/app/drawing: . Painter

  • From: looncraz-github.CAP-volatile <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 7 Nov 2012 00:48:41 +0100 (CET)

added 1 changeset to branch 'refs/remotes/looncraz-github/CAP-volatile'
old head: 9a6145e94f3f2ede998299f7635db0b75d8fcaa2
new head: 19a4ceb1deac3b5fdf5de1f6cb76b1c5a11be4ba

----------------------------------------------------------------------------

19a4ceb: Window-level draw buffering.
  
  Introduce resizable WindowBuffer, give DrawingEngine ability to change 
buffers at run-time, give Painter ability to paint a RenderBuffer directly,
  add user API flag to selectively override window buffering.
  
  Compiles.  No further testing performed.  Window currently does not attempt 
to use WindowBuffer.

                                         [ Yourself <user@shredder.(none)> ]

----------------------------------------------------------------------------

Commit:      19a4ceb1deac3b5fdf5de1f6cb76b1c5a11be4ba

Author:      Yourself <user@shredder.(none)>
Date:        Tue Nov  6 22:41:16 2012 UTC

----------------------------------------------------------------------------

10 files changed, 619 insertions(+), 6 deletions(-)
headers/os/interface/Window.h               |   3 +-
src/servers/app/Window.cpp                  |   3 +-
src/servers/app/Window.h                    |  10 +
src/servers/app/drawing/DrawingEngine.cpp   |  52 ++-
src/servers/app/drawing/DrawingEngine.h     |   9 +-
src/servers/app/drawing/Jamfile             |   2 +
src/servers/app/drawing/Painter/Painter.cpp |  37 ++-
src/servers/app/drawing/Painter/Painter.h   |   3 +
src/servers/app/drawing/WindowBuffer.cpp    | 419 ++++++++++++++++++++++++
src/servers/app/drawing/WindowBuffer.h      |  87 +++++

----------------------------------------------------------------------------

diff --git a/headers/os/interface/Window.h b/headers/os/interface/Window.h
index f1c406f..2acf631 100644
--- a/headers/os/interface/Window.h
+++ b/headers/os/interface/Window.h
@@ -77,7 +77,8 @@ enum {
        B_SAME_POSITION_IN_ALL_WORKSPACES       = 0x00200000,
        B_AUTO_UPDATE_SIZE_LIMITS                       = 0x00400000,
        B_CLOSE_ON_ESCAPE                                       = 0x00800000,
-       B_NO_SERVER_SIDE_WINDOW_MODIFIERS       = 0x00000200
+       B_NO_SERVER_SIDE_WINDOW_MODIFIERS       = 0x00000200,
+       B_NO_BUFFERED_DRAWING                           = 0x01000000
 };
 
 #define B_CURRENT_WORKSPACE                            0
diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp
index 117e67a..26d2a65 100644
--- a/src/servers/app/Window.cpp
+++ b/src/servers/app/Window.cpp
@@ -119,7 +119,8 @@ Window::Window(const BRect& frame, const char *name,
        fMinHeight(1),
        fMaxHeight(32768),
 
-       fWorkspacesViewCount(0)
+       fWorkspacesViewCount(0),
+       fWindowBuffer(NULL)
 {
        _InitWindowStack();
 
diff --git a/src/servers/app/Window.h b/src/servers/app/Window.h
index 6817df2..73a365a 100644
--- a/src/servers/app/Window.h
+++ b/src/servers/app/Window.h
@@ -72,6 +72,7 @@ class DrawingEngine;
 class EventDispatcher;
 class Screen;
 class WindowBehaviour;
+class WindowBuffer;
 class WorkspacesView;
 
 // TODO: move this into a proper place
@@ -106,6 +107,13 @@ public:
                        ::ServerWindow*         ServerWindow() const { return 
fWindow; }
                        ::EventTarget&          EventTarget() const
                                                                        { 
return fWindow->EventTarget(); }
+                       ::WindowBuffer*         WindowBuffer() const
+                                                                       { 
return fWindowBuffer; }
+
+                       bool                            SetBufferEnabled(bool 
bufferEnabled);
+                       
+                       bool                            IsBufferEnabled() const
+                                                                       {       
return WindowBuffer() != NULL;  }
 
                        bool                            ReloadDecor();
 
@@ -431,6 +439,8 @@ protected:
 
                        int32                           fWorkspacesViewCount;
 
+                       ::WindowBuffer*         fWindowBuffer;
+               
                friend class DecorManager;
 
 private:
diff --git a/src/servers/app/drawing/DrawingEngine.cpp 
b/src/servers/app/drawing/DrawingEngine.cpp
index 4e3a836..223800d 100644
--- a/src/servers/app/drawing/DrawingEngine.cpp
+++ b/src/servers/app/drawing/DrawingEngine.cpp
@@ -20,6 +20,8 @@
 #include "ServerBitmap.h"
 #include "ServerCursor.h"
 #include "RenderingBuffer.h"
+#include "Window.h"
+#include "WindowBuffer.h"
 
 #include "drawing_support.h"
 
@@ -101,6 +103,7 @@ DrawingEngine::DrawingEngine(HWInterface* interface)
        :
        fPainter(new Painter()),
        fGraphicsCard(NULL),
+       fDrawingBuffer(NULL),
        fAvailableHWAccleration(0),
        fSuspendSyncLevel(0),
        fCopyToFront(true)
@@ -178,7 +181,15 @@ DrawingEngine::FrameBufferChanged()
        // NOTE: locking is probably bogus, since we are called
        // in the thread that changed the frame buffer...
        if (LockExclusiveAccess()) {
-               fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer());
+               fPainter->DetachFromBuffer();
+
+               if (fDrawingBuffer != NULL){
+                       fPainter->AttachToBuffer(fDrawingBuffer);
+               }
+               else{
+                       
fPainter->AttachToBuffer(fGraphicsCard->DrawingBuffer());
+               }
+
                // available HW acceleration might have changed
                fAvailableHWAccleration = 
fGraphicsCard->AvailableHWAcceleration();
                UnlockExclusiveAccess();
@@ -205,6 +216,18 @@ DrawingEngine::SetHWInterface(HWInterface* interface)
 
 
 void
+DrawingEngine::SetDrawingBuffer(RenderingBuffer* buffer)
+{
+       if (LockExclusiveAccess()){
+               fDrawingBuffer = buffer;
+
+               FrameBufferChanged();
+               UnlockExclusiveAccess();
+       }
+}
+
+
+void
 DrawingEngine::SetCopyToFrontEnabled(bool enable)
 {
        fCopyToFront = enable;
@@ -605,6 +628,7 @@ DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const 
BRect& bitmapRect,
 {
        ASSERT_PARALLEL_LOCKED();
 
+
        BRect clipped = fPainter->ClipRect(viewRect);
        if (clipped.IsValid()) {
                AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -617,6 +641,24 @@ DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const 
BRect& bitmapRect,
 
 
 void
+DrawingEngine::DrawBuffer(RenderingBuffer* buffer, const BRect& bufferRect,
+       const BRect& viewRect, uint32 options)
+{
+       ASSERT_PARALLEL_LOCKED();
+
+
+       BRect clipped = fPainter->ClipRect(viewRect);
+       if (clipped.IsValid()) {
+               AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
+
+               fPainter->DrawBuffer(buffer, bufferRect, viewRect, options);
+
+               _CopyToFront(clipped);
+       }
+}
+
+
+void
 DrawingEngine::DrawArc(BRect r, const float& angle, const float& span,
        bool filled)
 {
@@ -889,6 +931,7 @@ DrawingEngine::FillRegion(BRegion& r, const rgb_color& 
color)
 {
        ASSERT_PARALLEL_LOCKED();
 
+
        // NOTE: region expected to be already clipped correctly!!
        BRect frame = r.Frame();
        if (!fPainter->Bounds().Contains(frame)) {
@@ -1004,6 +1047,7 @@ DrawingEngine::FillRect(BRect r, const BGradient& 
gradient)
        ASSERT_PARALLEL_LOCKED();
 
        make_rect_valid(r);
+
        r = fPainter->AlignAndClipRect(r);
        if (!r.IsValid())
                return;
@@ -1373,7 +1417,6 @@ DrawingEngine::DrawString(const char* string, int32 
length,
        const BPoint* offsets)
 {
        ASSERT_PARALLEL_LOCKED();
-
        // use a FontCacheRefernece to speed up the second pass of
        // drawing the string
        FontCacheReference cacheReference;
@@ -1492,6 +1535,7 @@ BRect
 DrawingEngine::CopyRect(BRect src, int32 xOffset, int32 yOffset) const
 {
        // TODO: assumes drawing buffer is 32 bits (which it currently always 
is)
+
        BRect dst;
        RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer();
        if (buffer) {
@@ -1533,6 +1577,7 @@ DrawingEngine::_CopyRect(uint8* src, uint32 width, uint32 
height,
        uint32 bytesPerRow, int32 xOffset, int32 yOffset) const
 {
        // TODO: assumes drawing buffer is 32 bits (which it currently always 
is)
+
        int32 xIncrement;
        int32 yIncrement;
 
@@ -1597,3 +1642,6 @@ DrawingEngine::_CopyToFront(const BRect& frame)
        if (fCopyToFront)
                fGraphicsCard->Invalidate(frame);
 }
+
+
+
diff --git a/src/servers/app/drawing/DrawingEngine.h 
b/src/servers/app/drawing/DrawingEngine.h
index ce89487..804cc50 100644
--- a/src/servers/app/drawing/DrawingEngine.h
+++ b/src/servers/app/drawing/DrawingEngine.h
@@ -20,13 +20,13 @@
 
 #include "HWInterface.h"
 
-
 class BPoint;
 class BRect;
 class BRegion;
 
 class DrawState;
 class Painter;
+class RenderingBuffer;
 class ServerBitmap;
 class ServerCursor;
 class ServerFont;
@@ -42,6 +42,8 @@ public:
 
        // for "changing" hardware
                        void                    SetHWInterface(HWInterface* 
interface);
+                       
+                       void                    
SetDrawingBuffer(RenderingBuffer*);
 
        virtual void                    SetCopyToFrontEnabled(bool enable);
                        bool                    CopyToFrontEnabled() const
@@ -97,6 +99,10 @@ public:
        virtual void                    DrawBitmap(ServerBitmap* bitmap,
                                                                const BRect& 
bitmapRect, const BRect& viewRect,
                                                                uint32 options 
= 0);
+       
+       virtual void                    DrawBuffer(RenderingBuffer* buffer,
+                                                               const BRect& 
bufferRect, const BRect& viewRect,
+                                                               uint32 options 
= 0);
        // drawing primitives
        virtual void                    DrawArc(BRect r, const float& angle,
                                                                const float& 
span, bool filled);
@@ -195,6 +201,7 @@ private:
 
                        Painter*                fPainter;
                        HWInterface*    fGraphicsCard;
+                       RenderingBuffer*fDrawingBuffer;
                        uint32                  fAvailableHWAccleration;
                        int32                   fSuspendSyncLevel;
                        bool                    fCopyToFront;
diff --git a/src/servers/app/drawing/Jamfile b/src/servers/app/drawing/Jamfile
index ff28d23..5c75fc1 100644
--- a/src/servers/app/drawing/Jamfile
+++ b/src/servers/app/drawing/Jamfile
@@ -29,6 +29,8 @@ StaticLibrary libasdrawing.a :
        BitmapHWInterface.cpp
        BBitmapBuffer.cpp
        HWInterface.cpp
+       
+       WindowBuffer.cpp
 ;
 
 SubInclude HAIKU_TOP src servers app drawing Painter ;
diff --git a/src/servers/app/drawing/Painter/Painter.cpp 
b/src/servers/app/drawing/Painter/Painter.cpp
index 2dc6bb8..ff7b59b 100644
--- a/src/servers/app/drawing/Painter/Painter.cpp
+++ b/src/servers/app/drawing/Painter/Painter.cpp
@@ -1629,6 +1629,41 @@ Painter::DrawBitmap(const ServerBitmap* bitmap, BRect 
bitmapRect,
 }
 
 
+
+BRect 
+Painter::DrawBuffer(const RenderingBuffer* buffer, BRect srcRect, BRect 
destRect,
+               uint32 options) const
+{
+       CHECK_CLIPPING
+
+       BRect touched = _Clipped(destRect);
+
+       if (buffer && buffer->InitCheck() == B_OK && touched.IsValid()) {
+               // the native buffer coordinate system
+               BRect actualSourceRect(0, 0, buffer->Width()-1, 
buffer->Height()-1);
+
+               TRACE("Painter::DrawBuffer()\n");
+               TRACE("   actualSourceRect = (%.1f, %.1f) - (%.1f, %.1f)\n",
+                       actualSourceRect.left, actualSourceRect.top,
+                       actualSourceRect.right, actualSourceRect.bottom);
+               TRACE("   srcRect = (%.1f, %.1f) - (%.1f, %.1f)\n",
+                       srcRect.left, srcRect.top, srcRect.right,
+                       srcRect.bottom);
+               TRACE("   destRect = (%.1f, %.1f) - (%.1f, %.1f)\n",
+                       destRect.left, destRect.top, destRect.right, 
destRect.bottom);
+
+               agg::rendering_buffer srcBuffer;
+               srcBuffer.attach((uint8*)buffer->Bits(), buffer->Width(), 
buffer->Height(),
+                       buffer->BytesPerRow());
+
+               _DrawBitmap(srcBuffer, buffer->ColorSpace(), actualSourceRect,
+                       srcRect, destRect, options);
+       }
+
+       return touched;
+}
+
+
 // #pragma mark -
 
 
@@ -1719,7 +1754,7 @@ Painter::_Transform(const BPoint& point, bool 
centerOffset) const
 BRect
 Painter::_Clipped(const BRect& rect) const
 {
-       if (rect.IsValid())
+       if (rect.IsValid() && fClippingRegion != NULL)
                return BRect(rect & fClippingRegion->Frame());
 
        return BRect(rect);
diff --git a/src/servers/app/drawing/Painter/Painter.h 
b/src/servers/app/drawing/Painter/Painter.h
index 645c95b..9b39684 100644
--- a/src/servers/app/drawing/Painter/Painter.h
+++ b/src/servers/app/drawing/Painter/Painter.h
@@ -220,6 +220,9 @@ public:
                        BRect                           DrawBitmap(const 
ServerBitmap* bitmap,
                                                                        BRect 
bitmapRect, BRect viewRect,
                                                                        uint32 
options) const;
+                       
+                       BRect                           DrawBuffer(const 
RenderingBuffer* buffer,
+                                                                       BRect 
src, BRect dest, uint32 options) const;
 
                                                                // some 
convenience stuff
                        BRect                           FillRegion(const 
BRegion* region) const;
diff --git a/src/servers/app/drawing/WindowBuffer.cpp 
b/src/servers/app/drawing/WindowBuffer.cpp
new file mode 100644
index 0000000..f5adf3a
--- /dev/null
+++ b/src/servers/app/drawing/WindowBuffer.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2001-2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Joseph Groover <looncraz@xxxxxxxxxxx>
+ */
+
+
+#include <Autolock.h>
+#include <malloc.h>
+#include <InterfacePrivate.h>
+#include <Screen.h>
+#include <syslog.h>
+
+#include <Window.h>
+
+#include "Window.h"
+
+#include "DrawingEngine.h"
+#include "drawing_support.h"
+#include "WindowBuffer.h"
+
+//#include "RapidDebug.h"
+
+#define _LOGF(...)
+
+WindowBuffer::WindowBuffer(Window* window)
+       :
+       RenderingBuffer(),
+       fWidth((int32)window->Frame().Width()),
+       fHeight((int32)window->Frame().Height()),
+       fBufferFillPattern(4294967295LL),
+       fBufferFillSrc(NULL),
+       fOverProvision(30),
+       fBounds(window->Frame()),
+       fWindow(window),
+       fBuffer(NULL)
+{
+       fBounds.OffsetBy(-fBounds.left, -fBounds.top);
+
+#      if ENABLE_LOGGING
+       BRect rect = window->Frame();
+
+       _LOGF("WindowBuffer(%s)( %i, %i, %i, %i )\n",
+               window->Title(),
+               (int)rect.left, (int)rect.top, (int)rect.right, (int)rect.bottom
+       );
+
+#      endif
+
+       _NewWindowSize(&fWidth, &fHeight);
+
+
+       SetBufferFillPattern(0);
+       FillBuffer();
+       _LOGF("\tBuffer created: %li x %li\n", fWidth, fHeight);
+}
+
+// destructor
+WindowBuffer::~WindowBuffer()
+{
+       fLock.Lock();
+
+       if (fBufferFillSrc != NULL)
+               free(fBufferFillSrc);
+       if (fBuffer != NULL)
+               free(fBuffer);
+}
+
+
+// #pragma mark resizing
+
+
+void   // see _ResizeTo() && _NewWindowSize()
+WindowBuffer::ResizeTo(int32 width, int32 height)
+{
+       BAutolock _(fLock);
+       int32   newW = width,   newH = height;
+
+       if (_NewWindowSize(&newW, &newH))
+               _ResizeTo(newW, newH);
+
+}
+
+
+void
+WindowBuffer::ResizeBy(int32 horizontal, int32 vertical)
+{
+       ResizeTo(fBounds.Width() + horizontal,
+               fBounds.Height() + vertical);
+}
+
+// #prgma mark -
+
+bool
+WindowBuffer::Lock()
+{
+       return fLock.Lock();
+}
+
+void
+WindowBuffer::Unlock()
+{
+       fLock.Unlock();
+}
+
+
+Window*
+WindowBuffer::GetWindow()
+{
+       return fWindow;
+}
+
+
+// #pragma mark Mandatory
+
+status_t
+WindowBuffer::InitCheck() const
+{
+       BAutolock _(fLock);
+
+       if (fWidth > 0 && fHeight > 0)
+       return B_OK;
+
+       return B_BAD_VALUE;
+}
+
+
+color_space
+WindowBuffer::ColorSpace() const
+{
+       return B_RGBA32;
+}
+
+
+void*
+WindowBuffer::Bits()   const
+{      BAutolock __(fLock);
+
+       if (fBuffer != NULL){
+       // if (!fIsCompressed)
+                       return fBuffer;
+               //else{
+                       //_DecompressBuffer();
+               //}
+       }else
+               fBuffer = malloc(BytesPerRow() * fHeight);
+
+
+       if (fWindow != NULL)
+               _LOGF("Bits() called: %s\n", fWindow->Title());
+
+
+       return fBuffer;
+}
+
+
+uint32
+WindowBuffer::BytesPerRow() const
+{      BAutolock _(fLock);
+
+       // I am assuming this is equal to frame_buffer_config's bytes_per_row
+       // this is vital, I believe, for acceleration to work correctly.
+
+       return BPrivate::get_bytes_per_row(B_RGBA32, fWidth);
+}
+
+
+uint32
+WindowBuffer::Width() const
+{      BAutolock _(fLock);
+       if (fWidth < 0 )
+               return 0;
+       return fWidth;
+}
+
+
+uint32
+WindowBuffer::Height() const
+{      BAutolock _(fLock);
+       if (fHeight <0)
+               return 0;
+       return fHeight;
+}
+
+
+// #pragma mark -
+
+
+void
+WindowBuffer::FillBuffer()
+{
+       BAutolock _(fLock);
+
+       uint32 * dest = (uint32*)Bits();
+
+       if (dest == NULL
+               || Width() == 0
+               || Height() == 0)
+               return;
+
+       uint32 bpr = BytesPerRow();     // cache it because it is "heavy"
+
+       if (fBufferFillSrc == NULL){
+               fBufferFillSrc = (uint32*)malloc(bpr);
+               for (uint32 i = 0; i < bpr/4; ++i)
+                       fBufferFillSrc[i] = fBufferFillPattern;
+       }
+
+       for (uint32 i = 0; i < Height(); ++i)   {
+               gfxcpy32((uint8*)dest, (const uint8*)fBufferFillSrc, bpr);
+               dest += Width();
+       }
+
+}
+
+
+void
+WindowBuffer::SetBufferFillColor(rgb_color color)
+{
+       SetBufferFillPattern(_ColorPattern(color));
+}
+
+
+void
+WindowBuffer::SetBufferFillPattern(uint32 pattern)
+{      BAutolock _(fLock);
+
+       fBufferFillPattern = pattern;
+
+       if (fBufferFillSrc)
+               free(fBufferFillSrc);
+
+       fBufferFillSrc = (uint32*)malloc(BytesPerRow());
+
+       if (fBufferFillSrc != NULL)
+               for (uint32 i = 0; i < BytesPerRow()/4; ++i)
+                       fBufferFillSrc[i] = fBufferFillPattern;
+       // we DO NOT draw just because the color changed...
+}
+
+
+bool
+WindowBuffer::LockForUpdate(bigtime_t scheduledUpdate)
+{
+//     if (fLastUpdate + fUpdateInterval < scheduledUpdate){
+               fClientDrawLock.Lock();
+               return Lock();
+//     }
+
+//     return false;
+}
+
+
+void
+WindowBuffer::UnlockFromUpdate()
+{
+//     fLastUpdate = system_time();
+       fClientDrawLock.Unlock();
+       Unlock();
+}
+
+
+// #pragma mark private
+
+uint32
+WindowBuffer::_ColorPattern(const rgb_color &color)
+{      // NativeColor() may use the accelerant's features
+
+       return (uint32)(color.alpha << 24) | (color.red << 16) | (color.green 
<< 8)
+               |(color.blue);
+//     return gCompositeEngine->NativeColor(color);
+}
+
+
+/*
+
+       This resize function refers to the resizing of the buffer
+       itself.
+*/
+
+void
+WindowBuffer::_ResizeTo(int32 width, int32 height)
+{
+/*
+       calls to here come exclusively from the Desktop thread, so
+       we should already be locked and drawing should be suspended.
+*/
+       _LOGF(
+               "_ResizeTo from (%lu, %lu) to (%lu, %lu)\n",
+               fWidth, fHeight, width, height
+       );
+
+       BAutolock _(fLock);
+
+       if (width == fWidth && height == fHeight)
+               return;
+
+       // todo: should we LockExclusiveAccess() to the drawing engine?
+       // it may be superfluous.. but maybe not...
+
+       if (fBuffer != NULL){
+
+               uint32  bpp = 4,
+                               bpr = bpp*width;
+               uint32* destBuffer = (uint32*)malloc(bpr*height),
+                               *newBuffer = destBuffer;
+               uint32* srcBuffer = (uint32*)fBuffer;
+
+               if (destBuffer == NULL){
+                       debugger("WindowBuffer::_ResizeTo():\n\t"
+                                       "Unable to allocate destination 
buffer\n");
+                       return;
+               }
+
+               // all of these need to be created here, dont't fuss...
+               int32   srcWidth        = fWidth,
+                               srcLen          = srcWidth*bpp,
+                               destWidth       = width,
+                               destLen         = destWidth*bpp,
+                               srcHeight       = fHeight,
+                               xDelta          = width - fWidth,
+                               xDeltaLen       = xDelta * bpp,
+                               yDelta          = height - fHeight,
+                               xShrinkDelta= 0;
+
+               // shrinking...
+               if (srcWidth > width){
+                       xShrinkDelta = srcWidth - width;
+                       srcWidth = width;
+                       srcLen = srcWidth * bpp;
+                       xDelta = 0;
+                       xDeltaLen = 0;
+               }
+
+               if (srcHeight > height){
+                       srcHeight = height;
+                       yDelta = 0;
+               }
+
+               // copy the old data row-by-row to the new buffer
+               for (int32 y = 0; y < srcHeight; ++y){
+                       gfxcpy32((uint8*)destBuffer, (const uint8*)srcBuffer, 
srcLen);
+                       destBuffer += srcWidth;
+                       srcBuffer += srcWidth + xShrinkDelta;
+                       if (xDelta){    // zero-fill extra width for drawing...
+                               gfxset32((uint8*)destBuffer, 0, xDeltaLen);
+                               destBuffer += xDelta;
+                       }
+               }
+
+               // zero-fill extra height for drawing
+               for (int32 y = 0; y < yDelta; ++y){
+                       gfxset32((uint8*)destBuffer, 0, destLen);
+                       destBuffer += destWidth;
+               }
+
+               fWidth = width;
+               fHeight = height;
+
+               free(fBuffer);
+               fBuffer = newBuffer;
+       }       // end buffer NULL-check
+
+       fWidth = width;
+       fHeight = height;
+
+       // as our pointer changed, the drawing engine needs to be updated:
+       fWindow->GetDrawingEngine()->SetDrawingBuffer(this);
+}
+
+
+// determine proper buffer size for a given window width & height
+// we also determine the new windowFrame for convenience
+
+bool
+WindowBuffer::_NewWindowSize(int32* width, int32* height)
+{
+       // sanity checks
+       if (*width < 0)         *width = 0;
+       if (*height < 0)        *height = 0;
+
+       int32   newW = *width,
+                       newH = *height;
+
+       fBounds.left = 0;
+       fBounds.top = 0;
+       
+       fBounds.right = newW - 1;
+       fBounds.bottom = newH - 1;
+
+       bool resizeBuffer = false;
+
+       if (newW > fWidth){
+               if ((fWindow->Flags() & B_NOT_RESIZABLE) == false
+                       && (fWindow->Flags() & B_NOT_H_RESIZABLE) == false)
+                               newW += fOverProvision;
+
+               *width = newW;
+               resizeBuffer = true;
+       }
+       else
+               *width = fWidth;
+
+       if (newH > fHeight){
+               if ((fWindow->Flags() & B_NOT_RESIZABLE) == false
+                       && (fWindow->Flags() & B_NOT_V_RESIZABLE) == false)
+                               newH += fOverProvision;
+
+               *height = newH;
+               resizeBuffer = true;
+       }
+       else
+               *height = fHeight;
+
+       return resizeBuffer;
+}
+
diff --git a/src/servers/app/drawing/WindowBuffer.h 
b/src/servers/app/drawing/WindowBuffer.h
new file mode 100644
index 0000000..7e178a0
--- /dev/null
+++ b/src/servers/app/drawing/WindowBuffer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2001-2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Joseph Groover <looncraz@xxxxxxxxxxx>
+ */
+
+#ifndef WINDOW_BUFFER_H
+#define WINDOW_BUFFER_H
+
+#include <Locker.h>
+#include <GraphicsDefs.h>
+#include <Region.h>
+
+#include "RenderingBuffer.h"
+
+class Window;
+
+class WindowBuffer : public RenderingBuffer{
+ public:
+                                                               
WindowBuffer(Window* window);
+       virtual                                         ~WindowBuffer();
+
+                       size_t                          MemoryUsage();
+
+                       // resizes the WINDOW
+                       void                            ResizeTo(int32 width, 
int32 height);
+                       void                            ResizeBy(int32 horiz, 
int32 vert);
+
+                       // this locks the buffer during drawing or during
+                       // screen refresh
+
+                       bool                            Lock();
+                       void                            Unlock();
+                       bool                            IsLocked();
+
+                       Window*                         GetWindow();
+
+                       // standard stuff for RenderingBuffer
+       virtual status_t                        InitCheck() const;
+       virtual color_space                     ColorSpace() const;
+       virtual void*                           Bits() const;
+       virtual uint32                          BytesPerRow() const;
+       // the Width() and Height() are for the buffer, not the window!
+       virtual uint32                          Width() const;
+       virtual uint32                          Height() const;
+
+                       void                            FillBuffer();
+
+                       void                            
SetBufferFillColor(rgb_color);
+                       void                            
SetBufferFillPattern(uint32);
+
+                       size_t                          
ReduceMemoryFootprint(bool max = false);
+                               // shrinks window buffer to fit contents, if 
max is true
+                               // we will also eleminate over-provisioning
+                               // Returns memory saved by operation.
+
+                       // the update session, when client draws, we need to be 
locked.
+                       // if we don't, we will get flickering/tearing.
+                       bool                            LockForUpdate(bigtime_t 
= system_time());
+                       void                            UnlockFromUpdate();
+
+ private:
+                       uint32                          _ColorPattern(const 
rgb_color&);
+                       void                            _ResizeTo(int32 width, 
int32 height);
+                       bool                            _NewWindowSize(int32* 
width, int32* height);
+
+       mutable BLocker                         fLock,
+                                                               fClientDrawLock;
+
+                       int32                           fWidth,
+                                                               fHeight;
+                               
+                       uint32                          fBufferFillPattern,
+                                                       *       fBufferFillSrc;
+
+                       uint8                           fOverProvision;
+
+                       IntRect                         fBounds;
+
+                       Window*                         fWindow;
+
+       mutable void*                           fBuffer;
+};
+
+#endif // WINDOW_BUFFER_H


Other related posts: