From 879c2f7039d48709dd6ac582e58a88eb552c4c5a Mon Sep 17 00:00:00 2001
From: Timothy Strelchun <Timothy.Strelchun@Intel.Com>
Date: Mon, 30 May 2011 22:24:47 -0700
Subject: [PATCH] GPU system memory support mods for aligned buffer directfbrc commands.
 Added the directfbrc commands system-surface-base-alignment and
 system-surface-pitch-alignment. If the graphics driver supports system memory, these commands
 are used to sets the byte alignment for the system memory based surface's base address and
 pitch, or zero for no alignment (which is the default). Aligning these allows pixel data to
 travel more efficiently through the CPU and across the memory bus to increase performance,
 and meet GPU requirements (if any).

Updated the system memory surface pools to use these values for creating surface buffers when
they are non-zero. The local surface pool will use the posix_memalign function and the shared
surface pool will bloat the size to allow for base address to be aligned.
---
 src/core/local_surface_pool.c  |   36 ++++++++++++++++++---
 src/core/shared_surface_pool.c |   47 ++++++++++++++++++++++++---
 src/misc/conf.c                |   67 +++++++++++++++++++++++++++++++++++++++-
 src/misc/conf.h                |    9 +++++-
 4 files changed, 146 insertions(+), 13 deletions(-)

diff --git a/src/core/local_surface_pool.c b/src/core/local_surface_pool.c
index 5e5ab52..c1c88b3 100644
--- a/src/core/local_surface_pool.c
+++ b/src/core/local_surface_pool.c
@@ -1,5 +1,5 @@
 /*
-   (c) Copyright 2001-2009  The world wide DirectFB Open Source Community (directfb.org)
+   (c) Copyright 2001-2011  The world wide DirectFB Open Source Community (directfb.org)
    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
 
    All rights reserved.
@@ -36,6 +36,7 @@
 #include <core/core.h>
 #include <core/surface_pool.h>
 #include <core/system.h>
+#include <misc/conf.h>
 
 
 /**********************************************************************************************************************/
@@ -213,11 +214,36 @@ localAllocateBuffer( CoreSurfacePool       *pool,
      surface = buffer->surface;
      D_MAGIC_ASSERT( surface, CoreSurface );
 
-     dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );
+     /* Create aligned local system surface buffer if both base address and pitch are non-zero. */
+     if (dfb_config->system_surface_align_base && dfb_config->system_surface_align_pitch) {
+          /* Make sure base address and pitch are a positive power of two. */
+          D_ASSERT( dfb_config->system_surface_align_base >= 4 );
+          D_ASSERT( !(dfb_config->system_surface_align_base & (dfb_config->system_surface_align_base-1)) );
+          D_ASSERT( dfb_config->system_surface_align_pitch >= 2 );
+          D_ASSERT( !(dfb_config->system_surface_align_pitch & (dfb_config->system_surface_align_pitch-1)) );
+
+          dfb_surface_calc_buffer_size( surface, dfb_config->system_surface_align_pitch, 0,
+                                        &alloc->pitch, &alloc->size );
+
+          /* Note: The posix_memalign function requires base alignment to actually be at least four. */
+          int tempRet = posix_memalign( &alloc->addr, dfb_config->system_surface_align_base, alloc->size );
+          if ( tempRet != 0 ) {
+              D_ERROR( "Local surface pool: Error from posix_memalign:%d with base alignment value:%d. "
+                       "%s()-%s:%d\n",
+                       tempRet, dfb_config->system_surface_align_base,
+                       __FUNCTION__, __FILE__, __LINE__ );
+              return DFB_FAILURE;
+          }
+     }
+     else {
+          /* Create un-aligned local system surface buffer. */
+
+          dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );
 
-     alloc->addr = D_MALLOC( alloc->size );
-     if (!alloc->addr)
-          return D_OOM();
+          alloc->addr = D_MALLOC( alloc->size );
+          if (!alloc->addr)
+               return D_OOM();
+     }
 
      alloc->call = local->call;
      alloc->fid  = fusion_id( dfb_core_world(NULL) );
diff --git a/src/core/shared_surface_pool.c b/src/core/shared_surface_pool.c
index 55cbc2b..9c27a00 100644
--- a/src/core/shared_surface_pool.c
+++ b/src/core/shared_surface_pool.c
@@ -1,5 +1,5 @@
 /*
-   (c) Copyright 2001-2009  The world wide DirectFB Open Source Community (directfb.org)
+   (c) Copyright 2001-2011  The world wide DirectFB Open Source Community (directfb.org)
    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
 
    All rights reserved.
@@ -53,6 +53,7 @@ typedef struct {
 
 typedef struct {
      void *addr;
+     void *aligned_addr;
      int   pitch;
      int   size;
 } SharedAllocationData;
@@ -144,11 +145,40 @@ sharedAllocateBuffer( CoreSurfacePool       *pool,
 
      D_MAGIC_ASSERT( surface, CoreSurface );
 
-     dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );
+     /* Create aligned shared system surface buffer if both base address and pitch are non-zero. */
+     if (dfb_config->system_surface_align_base && dfb_config->system_surface_align_pitch) {
+          /* Make sure base address and pitch are a positive power of two. */
+          D_ASSERT( dfb_config->system_surface_align_base >= 2 );
+          D_ASSERT( !(dfb_config->system_surface_align_base & (dfb_config->system_surface_align_base-1)) );
+          D_ASSERT( dfb_config->system_surface_align_pitch >= 2 );
+          D_ASSERT( !(dfb_config->system_surface_align_pitch & (dfb_config->system_surface_align_pitch-1)) );
 
-     alloc->addr = SHMALLOC( data->shmpool, alloc->size );
-     if (!alloc->addr)
-          return D_OOSHM();
+          dfb_surface_calc_buffer_size( surface, dfb_config->system_surface_align_pitch, 0,
+                                        &alloc->pitch, &alloc->size );
+
+          alloc->addr = SHMALLOC( data->shmpool, alloc->size + dfb_config->system_surface_align_base );
+          if ( !alloc->addr )
+               return D_OOSHM();
+
+          /* Calculate the aligned address. */
+
+          unsigned int addr = (unsigned int) alloc->addr;
+          unsigned int aligned_offset = dfb_config->system_surface_align_base -
+                                        (addr % dfb_config->system_surface_align_base );
+
+          alloc->aligned_addr = (void*) (addr + aligned_offset);
+     }
+     else {
+          /* Create un-aligned shared system surface buffer. */
+
+          dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );
+
+          alloc->addr = SHMALLOC( data->shmpool, alloc->size );
+          if (!alloc->addr)
+               return D_OOSHM();
+
+          alloc->aligned_addr = NULL;
+     }
 
      allocation->flags = CSALF_VOLATILE;
      allocation->size  = alloc->size;
@@ -189,7 +219,12 @@ sharedLock( CoreSurfacePool       *pool,
      D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
      D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
 
-     lock->addr  = alloc->addr;
+     /* Provide aligned address if one's available, otherwise the un-aligned one. */
+     if (alloc->aligned_addr)
+          lock->addr = alloc->aligned_addr;
+     else
+          lock->addr = alloc->addr;
+
      lock->pitch = alloc->pitch;
 
      return DFB_OK;
diff --git a/src/misc/conf.c b/src/misc/conf.c
index 13b153d..9a15004 100644
--- a/src/misc/conf.c
+++ b/src/misc/conf.c
@@ -1,5 +1,5 @@
 /*
-   (c) Copyright 2001-2009  The world wide DirectFB Open Source Community (directfb.org)
+   (c) Copyright 2001-2011  The world wide DirectFB Open Source Community (directfb.org)
    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
 
    All rights reserved.
@@ -76,6 +76,18 @@ static const char *config_usage =
      "  pixelformat=<pixelformat>      Set the default pixel format\n"
      "  surface-shmpool-size=<kb>      Set the size of the shared memory pool used\n"
      "                                 for shared system memory surfaces.\n"
+     "  system-surface-base-alignment=<byte alignment>\n"
+     "                                 If GPU supports system memory, sets the byte alignment for\n"
+     "                                 system memory based surface's base address (value must be a\n"
+     "                                 positive power of two that is four or greater), or zero for\n"
+     "                                 no alignment. Aligning the base address (along with the\n"
+     "                                 pitch) allows the data to travel more efficiently through\n"
+     "                                 the CPU and memory bus to increase performance, and meet GPU\n"
+     "                                 requirements (if any). Default is 0 (no alignment).\n"
+     "  system-surface-pitch-alignment=<byte alignment>\n"
+     "                                 If GPU supports system memory, sets the pitch alignment for\n"
+     "                                 system memory based surface's pitch (value must be a positive\n"
+     "                                 power of two), or zero for no alignment. Default is 0.\n"
      "  session=<num>                  Select multi app world (zero based, -1 = new)\n"
      "  remote=<host>[:<port>]         Set remote host and port to connect to\n"
      "  primary-layer=<id>             Select an alternative primary layer\n"
@@ -428,6 +440,8 @@ static void config_allocate( void )
      dfb_config->matrox_tv_std            = DSETV_PAL;
      dfb_config->i8xx_overlay_pipe_b      = false;
      dfb_config->surface_shmpool_size     = 64 * 1024 * 1024;
+     dfb_config->system_surface_align_base  = 0;
+     dfb_config->system_surface_align_pitch = 0;
      dfb_config->keep_accumulators        = 1024;
      dfb_config->font_format              = DSPF_A8;
      dfb_config->cursor_automation        = true;
@@ -605,6 +619,57 @@ DFBResult dfb_config_set( const char *name, const char *value )
                return DFB_INVARG;
           }
      } else
+     if (strcmp( name, "system-surface-base-alignment" ) == 0) {
+          if (value) {
+               char *error;
+               ulong base_align;
+
+               base_align = strtoul( value, &error, 10 );
+
+               if (*error) {
+                    D_ERROR( "DirectFB/Config '%s': Error in decimal value '%s'!\n", name, error );
+                    return DFB_INVARG;
+               }
+
+               /* If non-zero, value must be a positive power of two that is four or greater. */
+               if (base_align && (base_align < 4 || (base_align & (base_align-1)) != 0)) {
+                   D_ERROR( "DirectFB/Config '%s': If non-zero, value must be a positive power-of-two "
+                            "that is four or greater!\n", name );
+                   return DFB_INVARG;
+               }
+
+               dfb_config->system_surface_align_base = base_align;
+          }
+          else {
+               D_ERROR( "DirectFB/Config '%s': No value specified!\n", name );
+               return DFB_INVARG;
+          }
+     } else
+     if (strcmp( name, "system-surface-pitch-alignment" ) == 0) {
+          if (value) {
+               char *error;
+               ulong pitch_align;
+
+               pitch_align = strtoul( value, &error, 10 );
+
+               if (*error) {
+                    D_ERROR( "DirectFB/Config '%s': Error in decimal value '%s'!\n", name, error );
+                    return DFB_INVARG;
+               }
+
+               /* If non-zero, value must be a positive power of two. */
+               if (pitch_align && (pitch_align == 1 || (pitch_align & (pitch_align-1)) != 0)) {
+                   D_ERROR( "DirectFB/Config '%s': If non-zero, value must be a positive power-of-two!\n", name );
+                   return DFB_INVARG;
+               }
+
+               dfb_config->system_surface_align_pitch = pitch_align;
+          }
+          else {
+               D_ERROR( "DirectFB/Config '%s': No value specified!\n", name );
+               return DFB_INVARG;
+          }
+     } else
      if (strcmp (name, "session" ) == 0) {
           if (value) {
                int session;
diff --git a/src/misc/conf.h b/src/misc/conf.h
index 626b3b2..9889dbf 100644
--- a/src/misc/conf.h
+++ b/src/misc/conf.h
@@ -1,5 +1,5 @@
 /*
-   (c) Copyright 2001-2009  The world wide DirectFB Open Source Community (directfb.org)
+   (c) Copyright 2001-2011  The world wide DirectFB Open Source Community (directfb.org)
    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
 
    All rights reserved.
@@ -226,6 +226,13 @@ typedef struct
      int           surface_shmpool_size;          /* Set the size of the shared memory pool used for
                                                      shared system memory surfaces. */
 
+     unsigned int  system_surface_align_base;     /* If GPU supports system memory, byte alignment for system
+                                                     surface's base address (must be a positive power of two
+                                                     that is four or greater), or zero for no alignment. */
+     unsigned int  system_surface_align_pitch;    /* If GPU supports system memory, byte alignment for system
+                                                     surface's pitch (must be a positive power of two), or
+                                                     zero for no alignment. */
+
      bool          no_cursor_updates;             /* Never show the cursor etc. */
 
      struct {
-- 
1.6.0.6

