Hi,

attached are some more patches - can they be applied?

- a fix for dfb_gfxcard_drawstring_check_state()

- an implementation for IDirectFBSurface::BatchStretchBlit()
We have a use case where we have to do loads of stretched blits from src
to dst, and the number of stretched rectangles is high enough to cause
too high a CPU load using individual StretchBlit() calls.
I had sent this patch earlier, and I don't think anybody commented or
objected?


Cheers,
Andre'

>From 6116cc4d11d9791758998b1e300dddc1b184f01e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Draszik?= <andre.dras...@st.com>
Date: Mon, 30 Nov 2009 18:08:39 +0000
Subject: [PATCH 1/1] compile warning fix
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Signed-off-by: André Draszik <andre.dras...@st.com>
---
 src/core/gfxcard.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/core/gfxcard.c b/src/core/gfxcard.c
index fcd2cb4..830215c 100644
--- a/src/core/gfxcard.c
+++ b/src/core/gfxcard.c
@@ -2850,7 +2850,7 @@ bool dfb_gfxcard_drawstring_check_state( CoreFont *font, CardState *state )
      if (!data) {
           D_DEBUG_AT( Core_GfxState, "  -> No font data!\n" );
           dfb_font_unlock( font );
-          return;
+          return false;
      }
 
      orig_flags    = state->blittingflags;
-- 
1.6.3.3

>From 85b05cda66af62b9afa79bab61346be4940088ad Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Draszik?= <andre.dras...@st.com>
Date: Sat, 25 Jul 2009 13:41:03 +0100
Subject: [PATCH 1/2] (surface) add some source code level documentation
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Signed-off-by: André Draszik <andre.dras...@st.com>
---
 src/display/idirectfbsurface.h |   38 ++++++++++++++++++++++++++++++++++++--
 1 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/display/idirectfbsurface.h b/src/display/idirectfbsurface.h
index a350054..7c7a0c4 100644
--- a/src/display/idirectfbsurface.h
+++ b/src/display/idirectfbsurface.h
@@ -50,8 +50,42 @@ typedef struct {
      DFBSurfaceCapabilities caps;            /* capabilities */
 
      struct {
-         DFBRectangle       wanted;          /* passed to GetSubSurface */
-         DFBRectangle       granted;         /* clipped by parent on creation */
+         /* 'wanted' is passed to GetSubSurface(), it doesn't matter if it's
+            too large or has negative starting coordinates as long as it
+            intersects with the 'granted' rectangle of the parent.
+            'wanted' should be seen as the origin for operations on that
+            surface. Non sub surfaces have a 'wanted' rectangle
+            of '{ 0, 0, width, height }'. 'wanted' is calculated just once
+            during surface creation. */
+         DFBRectangle       wanted;
+         /* 'granted' is the intersection of the 'wanted' rectangle and the
+            'granted' one of the parent. If they do not intersect DFB_INVAREA
+            is returned. For non sub surfaces it's the same as the 'wanted'
+            rectangle, because it's the rectangle describing the whole
+            surface. 'granted' is calculated just once during surface
+            creation */
+         DFBRectangle       granted;
+         /* 'current' is the intersection of the 'granted' rectangle and the
+            surface extents. SetClip() and many other functions are limited
+            by this.
+            This way sub surface area information is preserved during surface
+            resizing, e.g. when resizing a window. Calling SetClip() with NULL
+            causes the clipping region to exactly cover the 'current'
+            rectangle, also the flag 'clip_set' is cleared causing the
+            clipping region to be set to the new 'current' after resizing. If
+            SetClip() is called with a clipping region specified, an
+            intersection is done with the 'wanted' rectangle that is then
+            stored in 'clip_wanted' and 'clip_set' is set. However, if there
+            is no intersection 'DFB_INVARG' is returned, otherwise another
+            intersection is made with the 'current' rectangle and gets applied
+            to the surface's state.
+            Each resize, after the 'current' rectangle is updated, the
+            clipping region is set to NULL or 'clip_wanted' depending on
+            'clip_set'. This way even clipping regions are restored or
+            extended automatically. It's now possible to create a fullscreen
+            primary and call SetVideoMode() with different resolutions or
+            pixelformats several times without the need for updating the
+            primary surface by recreating it */
          DFBRectangle       current;         /* currently available area */
          DFBInsets          insets;          /* actually set by the window manager */
      } area;
-- 
1.6.3.3

>From 7418faf296cb3c2a620e580dede2b91ce87cca49 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Draszik?= <andre.dras...@st.com>
Date: Tue, 4 Aug 2009 01:06:46 +0100
Subject: [PATCH 2/2] (surface) implement IDirectFBSurface::BatchStretchBlit()
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Signed-off-by: André Draszik <andre.dras...@st.com>
---
 include/directfb.h                             |   14 +++
 proxy/dispatcher/idirectfbsurface_dispatcher.c |   50 ++++++++++
 proxy/dispatcher/idirectfbsurface_dispatcher.h |    1 +
 proxy/requestor/idirectfbsurface_requestor.c   |   26 +++++
 src/core/gfxcard.c                             |   80 ++++++++++++++++
 src/core/gfxcard.h                             |    5 +
 src/display/idirectfbsurface.c                 |  122 +++++++++++++++++++++---
 7 files changed, 284 insertions(+), 14 deletions(-)

diff --git a/include/directfb.h b/include/directfb.h
index 12d38ef..0b6c0e1 100644
--- a/include/directfb.h
+++ b/include/directfb.h
@@ -4150,6 +4150,20 @@ DEFINE_INTERFACE(   IDirectFBSurface,
           const DFBPoint           *source2_points,
           int                       num
      );
+
+     /*
+      * Blit a bunch of areas scaled from the source to the destination
+      * rectangles.
+      *
+      * <b>source_rects</b> and <b>dest_rects</b> will be modified!
+      */
+     DFBResult (*BatchStretchBlit) (
+          IDirectFBSurface         *thiz,
+          IDirectFBSurface         *source,
+          DFBRectangle             *source_rects,
+          DFBRectangle             *dest_rects,
+          int                       num
+     );
 )
 
 
diff --git a/proxy/dispatcher/idirectfbsurface_dispatcher.c b/proxy/dispatcher/idirectfbsurface_dispatcher.c
index bd58500..b81b1c4 100644
--- a/proxy/dispatcher/idirectfbsurface_dispatcher.c
+++ b/proxy/dispatcher/idirectfbsurface_dispatcher.c
@@ -579,6 +579,21 @@ IDirectFBSurface_Dispatcher_StretchBlit( IDirectFBSurface   *thiz,
 }
 
 static DFBResult
+IDirectFBSurface_Dispatcher_BatchStretchBlit( IDirectFBSurface   *thiz,
+                                              IDirectFBSurface   *source,
+                                              DFBRectangle       *source_rects,
+                                              DFBRectangle       *destination_rects,
+                                              int                 num )
+{
+     DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Dispatcher)
+
+     if (!source)
+          return DFB_INVARG;
+
+     return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
 IDirectFBSurface_Dispatcher_TextureTriangles( IDirectFBSurface     *thiz,
                                               IDirectFBSurface     *source,
                                               const DFBVertex      *vertices,
@@ -1140,6 +1155,37 @@ Dispatch_StretchBlit( IDirectFBSurface *thiz, IDirectFBSurface *real,
 }
 
 static DirectResult
+Dispatch_BatchStretchBlit( IDirectFBSurface *thiz, IDirectFBSurface *real,
+                           VoodooManager *manager, VoodooRequestMessage *msg )
+{
+     DirectResult         ret;
+     VoodooMessageParser  parser;
+     VoodooInstanceID     instance;
+     unsigned int         num;
+     const DFBRectangle  *source_rects;
+     const DFBRectangle  *dest_rects;
+     void                *surface;
+
+     DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Dispatcher)
+
+     VOODOO_PARSER_BEGIN( parser, msg );
+     VOODOO_PARSER_GET_ID( parser, instance );
+     VOODOO_PARSER_GET_UINT( parser, num );
+     VOODOO_PARSER_GET_DATA( parser, source_rects );
+     VOODOO_PARSER_GET_DATA( parser, dest_rects );
+     VOODOO_PARSER_END( parser );
+
+     ret = voodoo_manager_lookup_local( manager, instance, NULL, &surface );
+     if (ret)
+          return ret;
+
+     real->BatchStretchBlit( real, surface, (DFBRectangle *) source_rects,
+                             (DFBRectangle *) dest_rects, num );
+
+     return DFB_OK;
+}
+
+static DirectResult
 Dispatch_TextureTriangles( IDirectFBSurface *thiz, IDirectFBSurface *real,
                            VoodooManager *manager, VoodooRequestMessage *msg )
 {
@@ -1603,6 +1649,9 @@ Dispatch( void *dispatcher, void *real, VoodooManager *manager, VoodooRequestMes
           case IDIRECTFBSURFACE_METHOD_ID_StretchBlit:
                return Dispatch_StretchBlit( dispatcher, real, manager, msg );
 
+          case IDIRECTFBSURFACE_METHOD_ID_BatchStretchBlit:
+               return Dispatch_BatchStretchBlit( dispatcher, real, manager, msg );
+
           case IDIRECTFBSURFACE_METHOD_ID_TextureTriangles:
                return Dispatch_TextureTriangles( dispatcher, real, manager, msg );
 
@@ -1733,6 +1782,7 @@ Construct( IDirectFBSurface *thiz,
      thiz->TileBlit = IDirectFBSurface_Dispatcher_TileBlit;
      thiz->BatchBlit = IDirectFBSurface_Dispatcher_BatchBlit;
      thiz->StretchBlit = IDirectFBSurface_Dispatcher_StretchBlit;
+     thiz->BatchStretchBlit = IDirectFBSurface_Dispatcher_BatchStretchBlit;
      thiz->TextureTriangles = IDirectFBSurface_Dispatcher_TextureTriangles;
 
      thiz->SetDrawingFlags = IDirectFBSurface_Dispatcher_SetDrawingFlags;
diff --git a/proxy/dispatcher/idirectfbsurface_dispatcher.h b/proxy/dispatcher/idirectfbsurface_dispatcher.h
index a04b9d8..dcc6eaf 100644
--- a/proxy/dispatcher/idirectfbsurface_dispatcher.h
+++ b/proxy/dispatcher/idirectfbsurface_dispatcher.h
@@ -87,5 +87,6 @@
 #define IDIRECTFBSURFACE_METHOD_ID_Read                      56
 #define IDIRECTFBSURFACE_METHOD_ID_SetColors                 57
 #define IDIRECTFBSURFACE_METHOD_ID_BatchBlit2                58
+#define IDIRECTFBSURFACE_METHOD_ID_BatchStretchBlit          59
 
 #endif
diff --git a/proxy/requestor/idirectfbsurface_requestor.c b/proxy/requestor/idirectfbsurface_requestor.c
index 105f542..a3b5b46 100644
--- a/proxy/requestor/idirectfbsurface_requestor.c
+++ b/proxy/requestor/idirectfbsurface_requestor.c
@@ -901,6 +901,31 @@ IDirectFBSurface_Requestor_StretchBlit( IDirectFBSurface   *thiz,
 }
 
 static DFBResult
+IDirectFBSurface_Requestor_BatchStretchBlit( IDirectFBSurface   *thiz,
+                                             IDirectFBSurface   *source,
+                                             DFBRectangle       *source_rects,
+                                             DFBRectangle       *dest_rects,
+                                             int                 num )
+{
+     IDirectFBSurface_Requestor_data *source_data;
+
+     DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+     if (!source)
+          return DFB_INVARG;
+
+     DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+     return voodoo_manager_request( data->manager, data->instance,
+                                    IDIRECTFBSURFACE_METHOD_ID_BatchStretchBlit, VREQ_QUEUE, NULL,
+                                    VMBT_ID, source_data->instance,
+                                    VMBT_UINT, num,
+                                    VMBT_DATA, num * sizeof(DFBRectangle), source_rects,
+                                    VMBT_DATA, num * sizeof(DFBRectangle), dest_rects,
+                                    VMBT_NONE );
+}
+
+static DFBResult
 IDirectFBSurface_Requestor_TextureTriangles( IDirectFBSurface     *thiz,
                                              IDirectFBSurface     *source,
                                              const DFBVertex      *vertices,
@@ -1220,6 +1245,7 @@ Construct( IDirectFBSurface *thiz,
      thiz->TileBlit = IDirectFBSurface_Requestor_TileBlit;
      thiz->BatchBlit = IDirectFBSurface_Requestor_BatchBlit;
      thiz->StretchBlit = IDirectFBSurface_Requestor_StretchBlit;
+     thiz->BatchStretchBlit = IDirectFBSurface_Requestor_BatchStretchBlit;
      thiz->TextureTriangles = IDirectFBSurface_Requestor_TextureTriangles;
 
      thiz->SetDrawingFlags = IDirectFBSurface_Requestor_SetDrawingFlags;
diff --git a/src/core/gfxcard.c b/src/core/gfxcard.c
index 71f40ce..8ce3996 100644
--- a/src/core/gfxcard.c
+++ b/src/core/gfxcard.c
@@ -2240,6 +2240,86 @@ void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect,
      dfb_state_unlock( state );
 }
 
+void dfb_gfxcard_batchstretchblit( DFBRectangle *srects,
+                                   DFBRectangle *drects,
+                                   int num, CardState *state )
+{
+     int i = 0;
+
+     D_DEBUG_AT( Core_GraphicsOps, "%s( %p, %p [%d], %p )\n", __FUNCTION__, srects, drects, num, state );
+
+     D_ASSERT( card != NULL );
+     D_ASSERT( card->shared != NULL );
+     D_MAGIC_ASSERT( state, CardState );
+     D_ASSERT( srects != NULL );
+     D_ASSERT( drects != NULL );
+     D_ASSERT( num > 0 );
+
+     /* The state is locked during graphics operations. */
+     dfb_state_lock( state );
+
+     /* Signal beginning of sequence of operations if not already done. */
+     dfb_state_start_drawing( state, card );
+
+     if (dfb_gfxcard_state_check( state, DFXL_STRETCHBLIT ) &&
+         dfb_gfxcard_state_acquire( state, DFXL_STRETCHBLIT ))
+     {
+          bool need_clip = (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING )
+                            && !D_FLAGS_IS_SET( card->caps.clip, DFXL_STRETCHBLIT ));
+
+          for (; i<num; i++) {
+               DFBRectangle * __restrict srect = &srects[i];
+               DFBRectangle * __restrict drect = &drects[i];
+
+               if (need_clip)
+                    dfb_clip_stretchblit( &state->clip, srect, drect );
+
+               if (!card->funcs.StretchBlit( card->driver_data, card->device_data,
+                                             srect, drect ))
+                    break;
+          }
+
+          dfb_gfxcard_state_release( state );
+     }
+
+     if (i < num) {
+          if (gAcquire( state, DFXL_STRETCHBLIT )) {
+               for (; i<num; i++) {
+                    DFBRectangle * __restrict srect = &srects[i];
+                    DFBRectangle * __restrict drect = &drects[i];
+
+                    if (state->render_options & DSRO_MATRIX) {
+                         int x1, y1, x2, y2;
+
+                         if (state->matrix[0] < 0  || state->matrix[1] != 0 ||
+                             state->matrix[3] != 0 || state->matrix[4] < 0  ||
+                             state->matrix[6] != 0 || state->matrix[7] != 0) {
+                              D_WARN( "rotation not yet implemented" );
+                              continue;
+                         }
+
+                         x1 = drect->x;    y1 = drect->y;
+                         x2 = x1+drect->w; y2 = y1+drect->h;
+                         DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
+                         DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
+                         drect->x = x1;    drect->y = y1;
+                         drect->w = x2-x1; drect->h = y2-y1;
+
+                         if (!dfb_clip_blit_precheck( &state->clip,
+                                                      drect->w, drect->h, drect->x, drect->y ))
+                           continue;
+                    }
+
+                    gStretchBlit( state, srect, drect );
+               }
+
+               gRelease( state );
+          }
+     }
+
+     dfb_state_unlock( state );
+}
+
 void dfb_gfxcard_texture_triangles( DFBVertex *vertices, int num,
                                     DFBTriangleFormation formation,
                                     CardState *state )
diff --git a/src/core/gfxcard.h b/src/core/gfxcard.h
index 535b9b7..3307f07 100644
--- a/src/core/gfxcard.h
+++ b/src/core/gfxcard.h
@@ -374,6 +374,11 @@ void dfb_gfxcard_stretchblit            ( DFBRectangle         *srect,
                                           DFBRectangle         *drect,
                                           CardState            *state );
 
+void dfb_gfxcard_batchstretchblit       ( DFBRectangle         *srects,
+                                          DFBRectangle         *drects,
+                                          int                   num,
+                                          CardState            *state );
+
 void dfb_gfxcard_texture_triangles      ( DFBVertex            *vertices,
                                           int                   num,
                                           DFBTriangleFormation  formation,
diff --git a/src/display/idirectfbsurface.c b/src/display/idirectfbsurface.c
index c532849..498d322 100644
--- a/src/display/idirectfbsurface.c
+++ b/src/display/idirectfbsurface.c
@@ -1881,6 +1881,42 @@ IDirectFBSurface_BatchBlit( IDirectFBSurface   *thiz,
      return DFB_OK;
 }
 
+static bool
+clip_StretchBlit( DFBRectangle       * __restrict src,
+                  const DFBRectangle * __restrict current_area_src,
+                  DFBRectangle       * __restrict dst )
+{
+     DFBRectangle orig_src = *src;
+
+     if (!dfb_rectangle_intersect( src, current_area_src )) {
+          src->w = src->h = 0;
+          dst->w = dst->h = 0;
+          return false;
+     }
+
+     /* clipping of the source rectangle must be applied to the destination */
+
+     if (src->x != orig_src.x)
+          dst->x += (int)( (src->x - orig_src.x) *
+                           (dst->w / (float)orig_src.w) + 0.5f);
+
+     if (src->y != orig_src.y)
+          dst->y += (int)( (src->y - orig_src.y) *
+                           (dst->h / (float)orig_src.h) + 0.5f);
+
+     if (src->w != orig_src.w)
+          dst->w = D_ICEIL(dst->w * (src->w / (float)orig_src.w));
+
+     if (src->h != orig_src.h)
+          dst->h = D_ICEIL(dst->h * (src->h / (float)orig_src.h));
+
+     D_DEBUG_AT( Surface, "  -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\n",
+                 0, dst->x, dst->y, dst->w, dst->h,
+                 src->x, src->y, src->w, src->h );
+
+     return true;
+}
+
 static DFBResult
 IDirectFBSurface_BatchBlit2( IDirectFBSurface   *thiz,
                              IDirectFBSurface   *source,
@@ -2055,23 +2091,79 @@ IDirectFBSurface_StretchBlit( IDirectFBSurface   *thiz,
 
      /* clipping of the source rectangle must be applied to the destination */
      {
-          DFBRectangle orig_src = srect;
-
-          if (!dfb_rectangle_intersect( &srect, &src_data->area.current ))
+          if (!clip_StretchBlit( &srect, &src_data->area.current, &drect ))
                return DFB_INVAREA;
+     }
+
+     dfb_state_set_source( &data->state, src_data->surface );
+
+     /* fetch the source color key from the source if necessary */
+     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)
+          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );
+
+     dfb_gfxcard_stretchblit( &srect, &drect, &data->state );
+
+     return DFB_OK;
+}
+
+static DFBResult
+IDirectFBSurface_BatchStretchBlit( IDirectFBSurface *thiz,
+                                   IDirectFBSurface *source,
+                                   DFBRectangle     *source_rects,
+                                   DFBRectangle     *dest_rects,
+                                   int               num )
+{
+     IDirectFBSurface_data *src_data;
+     const DFBRectangle    *scaled_current_src;
+     DFBRectangle           temp;
+     int                    scaled_one;
+     int                    i, sx, sy, dx, dy;
+     bool                   fixed_point;
+
+     DIRECT_INTERFACE_GET_DATA(IDirectFBSurface)
+
+     D_DEBUG_AT( Surface, "%s( %p, %d )\n", __FUNCTION__, thiz, num );
+
+     if (!data->surface)
+          return DFB_DESTROYED;
+
+
+     if (!source || !source_rects || !dest_rects || num < 1)
+          return DFB_INVARG;
+
+     if (!data->area.current.w || !data->area.current.h)
+          return DFB_INVAREA;
+
+     if (data->locked)
+          return DFB_LOCKED;
+
+
+     src_data = (IDirectFBSurface_data*)source->priv;
 
-          if (srect.x != orig_src.x)
-               drect.x += (int)( (srect.x - orig_src.x) *
-                                 (drect.w / (float)orig_src.w) + 0.5f);
+     if (!src_data->area.current.w || !src_data->area.current.h)
+          return DFB_INVAREA;
 
-          if (srect.y != orig_src.y)
-               drect.y += (int)( (srect.y - orig_src.y) *
-                                 (drect.h / (float)orig_src.h) + 0.5f);
 
-          if (srect.w != orig_src.w)
-               drect.w = D_ICEIL(drect.w * (srect.w / (float)orig_src.w));
-          if (srect.h != orig_src.h)
-               drect.h = D_ICEIL(drect.h * (srect.h / (float)orig_src.h));
+     for (i=0; i<num; i++) {
+          DFBRectangle * __restrict src = &source_rects[i];
+          DFBRectangle * __restrict dst = &dest_rects[i];
+
+          if (dst->w < 1 || dst->h < 1) {
+               dst->w = 0;
+               dst->h = 0;
+               continue;
+          }
+
+          if (src->w < 1 || src->h < 1)
+               return DFB_INVARG;
+
+          src->x += src_data->area.wanted.x;
+          src->y += src_data->area.wanted.y;
+
+          dst->x += data->area.wanted.x;
+          dst->y += data->area.wanted.y;
+
+          clip_StretchBlit( src, &src_data->area.current, dst );
      }
 
      dfb_state_set_source( &data->state, src_data->surface );
@@ -2080,7 +2172,8 @@ IDirectFBSurface_StretchBlit( IDirectFBSurface   *thiz,
      if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)
           dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );
 
-     dfb_gfxcard_stretchblit( &srect, &drect, &data->state );
+     dfb_gfxcard_batchstretchblit( source_rects, dest_rects, num,
+                                   &data->state );
 
      return DFB_OK;
 }
@@ -2834,6 +2927,7 @@ DFBResult IDirectFBSurface_Construct( IDirectFBSurface       *thiz,
      thiz->BatchBlit = IDirectFBSurface_BatchBlit;
      thiz->BatchBlit2 = IDirectFBSurface_BatchBlit2;
      thiz->StretchBlit = IDirectFBSurface_StretchBlit;
+     thiz->BatchStretchBlit = IDirectFBSurface_BatchStretchBlit;
      thiz->TextureTriangles = IDirectFBSurface_TextureTriangles;
 
      thiz->SetDrawingFlags = IDirectFBSurface_SetDrawingFlags;
-- 
1.6.3.3

_______________________________________________
directfb-dev mailing list
directfb-dev@directfb.org
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev

Reply via email to