[Libreoffice-commits] .: Branch 'feature/gtk3' - vcl/inc vcl/unx
Michael Meeks
michael at kemper.freedesktop.org
Mon Jul 4 07:39:02 PDT 2011
vcl/inc/unx/gtk/gtkframe.hxx | 7 -
vcl/inc/unx/gtk/gtkgdi.hxx | 5
vcl/unx/gtk/window/gtkframe.cxx | 244 ++++++++++++++++++++++++----------------
3 files changed, 159 insertions(+), 97 deletions(-)
New commits:
commit 13984398b244db5a645c8f89ec1dfde975439fa5
Author: Michael Meeks <michael.meeks at novell.com>
Date: Mon Jul 4 15:13:54 2011 +0100
initial copyArea support for optimised scrolling, and improved rendering
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index ec895d8..71dfc04 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -181,8 +181,8 @@ class GtkSalFrame : public SalFrame, public basebmp::BitmapDeviceDamageTracker
GtkWidget* m_pWindow;
#if GTK_CHECK_VERSION(3,0,0) && !defined GTK3_X11_RENDER
basebmp::BitmapDeviceSharedPtr m_aFrame;
- int m_nDuringRender;
#endif
+ int m_nDuringRender;
GdkWindow* m_pForeignParent;
GdkNativeWindow m_aForeignParentWindow;
GdkWindow* m_pForeignTopLevel;
@@ -326,6 +326,11 @@ public:
int getScreenNumber() const { return m_nScreen; }
void updateScreenNumber();
+ // only for gtk3 ...
+ void pushIgnoreDamage();
+ void popIgnoreDamage();
+ void renderArea( cairo_t *cr, cairo_rectangle_t *src );
+
void moveToScreen( int nScreen );
virtual ~GtkSalFrame();
diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
index a89a40b..4b46814 100644
--- a/vcl/inc/unx/gtk/gtkgdi.hxx
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -53,8 +53,13 @@ public:
};
#else
class GtkSalGraphics : public SvpSalGraphics {
+ GtkSalFrame *mpFrame;
public:
GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow );
+ virtual void copyArea( long nDestX, long nDestY,
+ long nSrcX, long nSrcY,
+ long nSrcWidth, long nSrcHeight,
+ sal_uInt16 /*nFlags*/ );
};
#endif // GTK3_X11_RENDER
diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx
index c6f9e37..b32ecba 100644
--- a/vcl/unx/gtk/window/gtkframe.cxx
+++ b/vcl/unx/gtk/window/gtkframe.cxx
@@ -340,7 +340,7 @@ GetAlternateKeyCode( const sal_uInt16 nKeyCode )
return aAlternate;
}
-static int queuePureRedraw = 0;
+static int debugQueuePureRedraw = 0;
void GtkSalFrame::doKeyCallback( guint state,
guint keyval,
@@ -364,8 +364,8 @@ void GtkSalFrame::doKeyCallback( guint state,
// shift-zero forces a re-draw and event is swallowed
if (keyval == GDK_0) // && (state & GDK_SHIFT_MASK))
{
- queuePureRedraw += 2;
- fprintf( stderr, "force re-draw %d\n", queuePureRedraw );
+ debugQueuePureRedraw += 2;
+ fprintf( stderr, "force re-draw %d\n", debugQueuePureRedraw );
gtk_widget_queue_draw (m_pWindow);
return;
}
@@ -433,9 +433,7 @@ GtkSalFrame::GtkSalFrame( SalFrame* pParent, sal_uLong nStyle )
{
m_nScreen = getDisplay()->GetDefaultScreenNumber();
getDisplay()->registerFrame( this );
-#if GTK_CHECK_VERSION(3,0,0) && !defined GTK3_X11_RENDER
- m_nDuringRender = 0;
-#endif
+ m_nDuringRender = 0;
m_bDefaultPos = true;
m_bDefaultSize = ( (nStyle & SAL_FRAME_STYLE_SIZEABLE) && ! pParent );
m_bWindowIsGtkPlug = false;
@@ -624,7 +622,7 @@ void GtkSalFrame::InitCommon()
m_pRegion = NULL;
m_ePointerStyle = 0xffff;
m_bSetFocusOnMap = false;
-
+
#if GTK_CHECK_VERSION(3,0,0) && !defined GTK3_X11_RENDER
gtk_widget_set_app_paintable( m_pWindow, sal_True );
gtk_widget_set_double_buffered( m_pWindow, FALSE );
@@ -640,7 +638,7 @@ void GtkSalFrame::InitCommon()
// fixed is needed since we have to position plugin windows
m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL ));
gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pFixedContainer) );
-
+
// show the widgets
gtk_widget_show( GTK_WIDGET(m_pFixedContainer) );
@@ -1106,7 +1104,6 @@ void GtkSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
sal_Bool GtkSalFrame::PostEvent( void* pData )
{
- g_warning ("post event");
getDisplay()->SendInternalEvent( this, pData );
return sal_True;
}
@@ -3026,16 +3023,33 @@ gboolean GtkSalFrame::signalCrossing( GtkWidget*, GdkEventCrossing* pEvent, gpoi
return sal_True;
}
+void GtkSalFrame::pushIgnoreDamage()
+{
+#if GTK_CHECK_VERSION(3,0,0)
+ m_nDuringRender++;
+#endif
+}
+
+void GtkSalFrame::popIgnoreDamage()
+{
+#if GTK_CHECK_VERSION(3,0,0)
+ m_nDuringRender--;
+#endif
+}
+
void GtkSalFrame::damaged (const basegfx::B2IRange& rDamageRect)
{
#if GTK_CHECK_VERSION(3,0,0)
if (m_nDuringRender)
return;
- /* fprintf (stderr, "bitmap damaged %d %d (%dx%d)\n",
- (int) rDamageRect.getMinX(),
- (int) rDamageRect.getMinY(),
- (int) rDamageRect.getWidth(),
- (int) rDamageRect.getHeight() ); */
+ long long area = rDamageRect.getWidth() * rDamageRect.getHeight();
+ if( area > 32 * 1024 )
+ fprintf( stderr, "bitmap damaged %d %d (%dx%d) area %lld\n",
+ (int) rDamageRect.getMinX(),
+ (int) rDamageRect.getMinY(),
+ (int) rDamageRect.getWidth(),
+ (int) rDamageRect.getHeight(),
+ area );
gtk_widget_queue_draw_area( m_pWindow,
rDamageRect.getMinX(),
rDamageRect.getMinY(),
@@ -3045,67 +3059,35 @@ void GtkSalFrame::damaged (const basegfx::B2IRange& rDamageRect)
}
#if GTK_CHECK_VERSION(3,0,0)
-// This is unpleasant: we assume that a draw event was an expose earlier in life ...
-// We also hope & pray (for gtk 3.0.0) that the window was realised/mapped before draw
-// was called or we will badmatch
-gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
+// FIXME: This is incredibly lame ... but so is cairo's insistance on -exactly-
+// its own stride - neither more nor less - particularly not more aligned
+// we like 8byte aligned, it likes 4 - most odd.
+void GtkSalFrame::renderArea( cairo_t *cr, cairo_rectangle_t *area )
{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
- cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
+ if( !m_aFrame.get() )
+ return;
- struct SalPaintEvent aEvent( x1, y1, x2 - x1, y2 - y1 );
- aEvent.mbImmediateUpdate = true;
+ basebmp::RawMemorySharedArray data = m_aFrame->getBuffer();
+ basegfx::B2IVector size = m_aFrame->getSize();
+ sal_Int32 nStride = m_aFrame->getScanlineStride();
- GTK_YIELD_GRAB();
- // FIXME: we quite probably want to stop re-rendering of pieces
- // that we know are just damaged and hence rendered already ...
- if (queuePureRedraw <= 0) {
- pThis->m_nDuringRender++;
- fprintf (stderr, "paint %d\n", queuePureRedraw);
- pThis->CallCallback( SALEVENT_PAINT, &aEvent );
- pThis->m_nDuringRender--;
- } else {
- queuePureRedraw--;
- fprintf (stderr, "signalDraw %d\n", queuePureRedraw);
+ if (area->y + area->height > size.getY() ||
+ area->x + area->width > size.getX()) {
+ g_warning ("Error: renderArea: invalid geometry of sub area !");
+ return;
}
-#if GTK_CHECK_VERSION(3,0,0) && !defined GTK3_X11_RENDER
- if( !pThis->m_aFrame.get() )
- return sal_False;
-
- basebmp::RawMemorySharedArray data = pThis->m_aFrame->getBuffer();
- basegfx::B2IVector size = pThis->m_aFrame->getSize();
- sal_Int32 nStride = pThis->m_aFrame->getScanlineStride();
-
- // FIXME: this is horribly inefficient ...
-
- // ARGB == ARGB32 ... map straight across from bmpdev (?) ...
-
-#if 0
- // Draw flat white rectangle first:
cairo_save( cr );
- cairo_set_line_width( cr, 1.0 );
- cairo_set_source_rgba( cr, 1.0, 1.0, 1.0, 1.0 );
- cairo_rectangle( cr, 0, 0, size.getX(), size.getY() );
- cairo_fill( cr );
- cairo_stroke( cr );
- cairo_restore( cr );
-#endif
-#if 1
- cairo_save( cr );
+ int cairo_stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, area->width);
+ unsigned char *p, *src, *mem = (unsigned char *)malloc (32 * cairo_stride * area->height);
+ p = mem;
+ src = data.get();
+ src += (int)area->y * nStride + (int)area->x * 3;
- int cairo_stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, size.getX());
- // FIXME: This is incredibly lame ... but so is cairo's insistance on -exactly-
- // its own stride - neither more nor less - particularly not more aligned
- // we like 8byte aligned, it likes 4 - most odd.
- unsigned char *p, *src, *mem = (unsigned char *)malloc (32 * cairo_stride * size.getY());
- p = mem; src = data.get();
- for (int y = 0; y < size.getY(); ++y)
+ for (int y = 0; y < area->height; ++y)
{
- for (int x = 0; x < size.getX(); ++x)
+ for (int x = 0; x < area->width; ++x)
{
p[x*4 + 0] = src[x*3 + 0]; // B
p[x*4 + 1] = src[x*3 + 1]; // G
@@ -3118,7 +3100,7 @@ gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
cairo_surface_t *pSurface =
cairo_image_surface_create_for_data( mem,
CAIRO_FORMAT_ARGB32,
- size.getX(), size.getY(),
+ area->width, area->height,
cairo_stride );
/* g_warning( "Fixed cairo status %d %d strides: %d vs %d, mask %d\n",
(int) cairo_status( cr ),
@@ -3126,52 +3108,77 @@ gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
(int) nStride,
(int) cairo_stride,
(int) (cairo_stride & (sizeof (uint32_t)-1)) ); */
-#endif
+
cairo_set_operator( cr, CAIRO_OPERATOR_OVER );
- cairo_set_source_surface( cr, pSurface, 0, 0 );
+ cairo_set_source_surface( cr, pSurface, area->x, area->y );
cairo_paint( cr );
cairo_surface_destroy( pSurface );
free (mem);
cairo_restore( cr );
+ // Render red rectangles to show what was re-rendered ...
#if 1
cairo_save( cr );
cairo_set_line_width( cr, 1.0 );
cairo_set_source_rgb( cr, 1.0, 0, 0 );
- cairo_rectangle( cr, x1 + 1, y1 + 1, x2 - x1 - 2, y2 - y1 - 2 );
+ cairo_rectangle( cr, area->x + 1.0, area->y + 1.0, area->width - 2.0, area->height - 2.0 );
cairo_stroke( cr );
cairo_restore( cr );
#endif
+}
+#endif
-/*
- basebmp::Format::TWENTYFOUR_BIT_TC_MASK );
- * cairo_format_t:
- * @CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with
- * alpha in the upper 8 bits, then red, then green, then blue.
- * The 32-bit quantities are stored native-endian. Pre-multiplied
- * alpha is used. (That is, 50% transparent red is 0x80800000,
- * not 0x80ff0000.)
- * @CAIRO_FORMAT_RGB24: each pixel is a 32-bit quantity, with
- * the upper 8 bits unused. Red, Green, and Blue are stored
- * in the remaining 24 bits in that order.
- * @CAIRO_FORMAT_A8: each pixel is a 8-bit quantity holding
- * an alpha value.
- * @CAIRO_FORMAT_A1: each pixel is a 1-bit quantity holding
- * an alpha value. Pixels are packed together into 32-bit
- * quantities. The ordering of the bits matches the
- * endianess of the platform. On a big-endian machine, the
- * first pixel is in the uppermost bit, on a little-endian
- * machine the first pixel is in the least-significant bit.
- * @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity
- * with red in the upper 5 bits, then green in the middle
- * 6 bits, and blue in the lower 5 bits.
- */
+// This is unpleasant: we assume that a draw event was an expose earlier in life ...
+// We also hope & pray (for gtk 3.0.0) that the window was realised/mapped before draw
+// was called or we will badmatch
+gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
+{
+ GtkSalFrame* pThis = (GtkSalFrame*)frame;
+
+ double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
+ cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
+
+ GTK_YIELD_GRAB();
+
+ if (debugQueuePureRedraw > 0)
+ {
+ debugQueuePureRedraw--;
+#if GTK_CHECK_VERSION(3,0,0) && !defined GTK3_X11_RENDER
+ fprintf (stderr, "skip signalDraw for debug %d\n", debugQueuePureRedraw);
+ cairo_rectangle_t rect = { x1, y1, x2 - x1, y2 - y1 };
+ pThis->renderArea( cr, &rect );
#endif
+ return FALSE;
+ }
- return sal_False;
-}
+ // FIXME: we quite probably want to stop re-rendering of pieces
+ // that we know are just damaged by us and hence already re-rendered
+ pThis->m_nDuringRender++;
+
+ // FIXME: we need to profile whether re-rendering the entire
+ // clip region, and just pushing (with renderArea) smaller pieces
+ // is faster ...
+ cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list (cr);
+ fprintf( stderr, "paint %d regions\n", rects->num_rectangles);
+ for (int i = 0; i < rects->num_rectangles; i++) {
+ cairo_rectangle_t rect = rects->rectangles[i];
+ fprintf( stderr, "\t%d -> %g,%g %gx%g\n", i,
+ rect.x, rect.y, rect.width, rect.height );
+
+ struct SalPaintEvent aEvent( rect.x, rect.y, rect.width, rect.height );
+ aEvent.mbImmediateUpdate = true;
+ pThis->CallCallback( SALEVENT_PAINT, &aEvent );
+
+#if GTK_CHECK_VERSION(3,0,0) && !defined GTK3_X11_RENDER
+ pThis->renderArea( cr, &rect );
#endif
+ }
+
+ pThis->m_nDuringRender--;
+
+ return FALSE;
+}
gboolean GtkSalFrame::signalExpose( GtkWidget*, GdkEventExpose* pEvent, gpointer frame )
{
@@ -4203,10 +4210,55 @@ GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
#else
GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
- : SvpSalGraphics()
+ : SvpSalGraphics(),
+ mpFrame( pFrame )
{
}
+static void print_update_area (GdkWindow *window, const char *msg)
+{
+ cairo_region_t *region = gdk_window_get_update_area (window);
+ if (!region) {
+ fprintf (stderr, "%s - NULL\n", msg);
+ return;
+ }
+ int numrect = cairo_region_num_rectangles (region);
+ fprintf (stderr, "%s - %d rects\n", msg, numrect);
+ for (int i = 0; i < numrect; i++) {
+ cairo_rectangle_int_t rect;
+ cairo_region_get_rectangle (region, i, &rect);
+ fprintf( stderr, "\t%d -> %d,%d %dx%d\n", i,
+ rect.x, rect.y, rect.width, rect.height );
+ }
+}
+
+void GtkSalGraphics::copyArea( long nDestX, long nDestY,
+ long nSrcX, long nSrcY,
+ long nSrcWidth, long nSrcHeight,
+ sal_uInt16 nFlags )
+{
+ mpFrame->pushIgnoreDamage();
+ SvpSalGraphics::copyArea( nDestY, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, nFlags );
+ mpFrame->popIgnoreDamage();
+
+ cairo_rectangle_int_t rect = { (int)nSrcX, (int)nSrcY, (int)nSrcWidth, (int)nSrcHeight };
+ cairo_region_t *region = cairo_region_create_rectangle( &rect );
+
+ print_update_area( gtk_widget_get_window( mpFrame->getWindow() ), "before copy area" );
+
+ g_warning ("FIXME: copy area delta: %d %d needs clip intersect\n",
+ nDestX - nSrcX, nDestY - nSrcY );
+ // cairo_region_intersect (copy_area, window->clip_region_with_children);
+
+ // FIXME: this will queue (duplicate) gtk+ re-rendering for the exposed area, c'est la vie
+ // FIXME: if 'implicit_paint' is set - we will queue a complete re-draw ...
+ gdk_window_move_region( gtk_widget_get_window( mpFrame->getWindow() ),
+ region, nDestX - nSrcX, nDestY - nSrcY );
+
+ print_update_area( gtk_widget_get_window( mpFrame->getWindow() ), "after copy area" );
+ cairo_region_destroy( region );
+}
+
#endif // GTK3_X11_RENDER
#endif
More information about the Libreoffice-commits
mailing list