Attached are two patches whose objective is to improve DirectFB support 
on AMD (formerly National Semiconductor) Geode, especially the older 
GX1.

The first patch is a set of diffs for:

        nsc-kfb-driver-2.7.7/nsc/nsc_gx1_fb.c

The second patch is a cvs diff from the current DirectFB tree to patch:

        gfxdrivers/nsc/nsc.c

KERNEL PATCH

The kernel patch removes an ifdef that is forcing virtual Y resolution 
to always match Y resolution which prevents DirectFB from using double 
buffering.

1372,1381c1418,1419
< #ifdef CONFIG_FB_GEODE_TV
<    if ((par->flags & Display_TVO) && is_tv_supported()) {
<       var->xres_virtual = par->xres_virtual;
<       var->yres_virtual = par->yres_virtual;
<    } else
< #endif
<    {
<       var->xres_virtual = par->xres;
<       var->yres_virtual = par->yres;
<    }
---
>    var->xres_virtual = par->xres_virtual;
>    var->yres_virtual = par->yres_virtual;

There is a second ifdef that may or may not require the same change in 
gx1_Geode_set_par() though it hasn't tested well when I've made the 
same change there so Its not currently in this patch,

The second kernel driver change is to implement pan display which 
appears to be unimplemented at present in the NSC driver.  My patch 
doesn't implement YWRAP.  I've only extensively tested Y panning which 
is necessary for DirectFB double buffering

I don't have access to GX2 hardware so I've not implemented these 
changes in that driver since I'm not able to test them

DIRECTFB PATCH

The DirectFB patch implements hardware blitting on  GX1 graphics though 
it is constrained, by hardware, to only blit surfaces whose width 
matches the stride of the frame buffer.  In other cases it reverts to 
the generic software blit.  The current driver in CVS only implements 
hardware blit on GX2 graphics which doesn't  have this stride 
limitation.

The hardware accelerated functions for line, rectangle and fill have 
been modified to honor  dst_offset for Y so they work properly with 
double buffering.  In the current CVS version these don't honor 
dst_offset and are working on the wrong buffer in double buffered mode 
half the time.  X offset is not currently implemented in this patch 
which is focused on making double buffering work.

GEODE COMPRESSION BUFFER

The patch is disabling the Geode's compression buffer when the DirectFB 
nsc driver is initialized.  This may be a potential drag on performance 
since it increases memory traffic on the video memory during refresh.  
The compression buffer is very problematic for DirectFB since it is 
unaware of it location in video memory.  For example at 1024x768 the 
compression buffer is mapped right at the start of the second buffer.  
You will see display artifacts if its not disabled and you will usually 
crash the box as DirectFB overwrites the compression buffer with 
randomness. In the future the compression buffer could be moved to the 
end of video memory and video ram could be limited to prevent it from 
overwriting it. 

VIDEO HARDWARE INTERACTION

Moving the compression buffer to the end of video RAM can result in 
conflicts if you are using video hardware since the geode_v driver in 
geode_v4l2-2.3.2  also uses video memory.  In fact geode_v is currently 
putting its video buffers in video memory in an area that will also 
overlap the second buffer in double buffered mode at 1024x768.  This 
problem can be remedied by changing geodedrv.c memory buffer offset to:

#define MULTIBUFF_OFFSET          0x0

This puts the video buffer at the very end of video memory.  It is 
currently offset from the end of video memory by approximately 512K 
which causes it to interfere with DirectFB double buffering at 
1024x768.

If you set MULTIBUFF_OFFSET  to 0, shut off the compression buffer and 
limit DirectFB video ram to 3 MB you can run DirectFB double buffered 
at 1024x768 and play video at the same time.

-- Ed Millard
1330a1331,1376
>  * gx1_geodefb_pan_display
>  *
>  * Description: This function Pan or Wrap the Display
>  *                              and it looks only at xoffset, yoffset and
>  *                              the FB_VMODE_YWRAP flag.
>  *      parameters:
>  *                 var: Pointer to fb_var_screeninfo which has the parameters
>  *                              to set the hardware. 
>  *        con:  The console which has to be updated with parameters 
>  *                              in 'var' structure.
>  *       info:  This is a pointer to the frame buffer information 
>  *                              structure.  
>  *     return:  error value 
>  *----------------------------------------------------------------*/
> static int
> gx1_geodefb_pan_display(struct fb_var_screeninfo *var,
>                     int con, struct fb_info *info)
> {
>    int status = 0;
>    unsigned short pitch;
>    unsigned short xoffset = 0;
> 
>    assert(var != NULL);
> 
>    if(var) {
>       if (var->xoffset > (var->xres_virtual - var->xres)
>       ||  var->yoffset > (var->yres_virtual - var->yres))
>          return -EINVAL;
> 
>       pitch = gfx_get_display_pitch();
> 
>       xoffset = var->xoffset * (var->bits_per_pixel >> 3);
> 
>       gfx_set_display_offset(var->yoffset * pitch + xoffset);
> 
>       fb_display[con].var.xoffset = var->xoffset;
>       fb_display[con].var.yoffset = var->yoffset;
> 
>    }else{
>       status = -EINVAL;
>    }
> 
>    return status;
> }
> 
> /*-----------------------------------------------------------------
1372,1381c1418,1419
< #ifdef CONFIG_FB_GEODE_TV
<    if ((par->flags & Display_TVO) && is_tv_supported()) {
<       var->xres_virtual = par->xres_virtual;
<       var->yres_virtual = par->yres_virtual;
<    } else
< #endif
<    {
<       var->xres_virtual = par->xres;
<       var->yres_virtual = par->yres;
<    }
---
>    var->xres_virtual = par->xres_virtual;
>    var->yres_virtual = par->yres_virtual;
2089a2128
>    fb_pan_display:gx1_geodefb_pan_display,
? gfxdrivers/nsc/nsc.c.new
Index: gfxdrivers/nsc/nsc.c
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/nsc/nsc.c,v
retrieving revision 1.9
diff -u -3 -p -r1.9 nsc.c
--- gfxdrivers/nsc/nsc.c	30 Mar 2004 23:42:37 -0000	1.9
+++ gfxdrivers/nsc/nsc.c	13 Jul 2004 22:59:12 -0000
@@ -205,6 +205,7 @@ static bool nscDrawLine(void *drv, void 
 static bool nscFillRectangle(void *drv, void *dev, DFBRectangle *rect);
 static bool nscDrawRectangle(void *drv, void *dev, DFBRectangle *rect);
 static bool nscBlit(void *drv, void *dev, DFBRectangle *rect, int dx, int dy);
+static bool nscBlitGu1(void *drv, void *dev, DFBRectangle *rect, int dx, int dy);
 
 static void gxEngineSync(void *drv, void *dev)
 {
@@ -227,6 +228,7 @@ gxCheckState(void *drv,
 {
 #if NSC_ACCEL
    NSCDriverData *gxdrv = (NSCDriverData *) drv;
+   NSCDeviceData *gxdev = (NSCDeviceData *) dev;
 
    if(state->destination->format != DSPF_RGB16)
       return;
@@ -235,15 +237,38 @@ gxCheckState(void *drv,
 
 	   if(state->source->format != DSPF_RGB16)
 		  return;
-      /* if there are no other blitting flags than the supported
-       * and the source and destination formats are the same
-       */
       if (gxdrv->cpu) {
+         /* GU2 - if there are no other blitting flags than the supported
+          * and the source and destination formats are the same 
+          */
          if (!(state->blittingflags & ~GX_SUPPORTED_BLITTINGFLAGS) &&
              state->source && state->source->format != DSPF_RGB24) {
             state->accel |= GX_SUPPORTED_BLITTINGFUNCTIONS;
          }
-     }
+      } else{
+         /* GU1 - source width must match frame buffer strid
+          */
+         if(state->source) {
+            int src_pitch = 0;
+            int dst_pitch = 0;
+
+            if(state->source) {
+               src_pitch = state->source->width * DFB_BYTES_PER_PIXEL(state->source->format);
+            }
+
+            if (state->modified & SMF_DESTINATION) {
+               if(state->destination && state->destination->front_buffer)
+                  dst_pitch = state->destination->back_buffer->video.pitch;
+            }
+            if(dst_pitch == 0) {
+               dst_pitch = gxdev->dst_pitch;
+            }
+       
+            if(src_pitch == dst_pitch && state->source) {
+               state->accel |= GX_SUPPORTED_BLITTINGFUNCTIONS;
+            }
+         }
+      }
    } else {
       /* if there are no other drawing flags than the supported */
       if (!(state->drawingflags & ~GX_SUPPORTED_DRAWINGFLAGS)) {
@@ -327,15 +352,17 @@ nscDrawLine(void *drv, void *dev, DFBReg
    short majorErr;
    unsigned short destData;
    NSCDeviceData *gxdev = (NSCDeviceData *) dev;
+   int yoffset;
 
    destData = 0;                        /*  Value will be 0x8 (or) 0 */
    dx = line->x2 - line->x1;            /*  delta values */
    dy = line->y2 - line->y1;
    adx = ABS(dx);
    ady = ABS(dy);
+   yoffset = gxdev->dst_offset / gxdev->dst_pitch;
 
    /* Canonical Bresenham stepper.
-    * * We use hardware to draw the pixels to take care of alu modes
+    * * We use hardware to draw the pixels to take care of alu modes 
     * * and whatnot.
     */
    Gal_set_raster_operation(0xF0);
@@ -351,7 +378,7 @@ nscDrawLine(void *drv, void *dev, DFBReg
       majorErr = (short)(ady << 1);
 
       Gal_bresenham_line((short)line->x1,
-                         (short)line->y1,
+                         (short)line->y1 + yoffset,
                          (short)adx,
                          (short)(majorErr - adx),
                          (short)majorErr,
@@ -367,7 +394,7 @@ nscDrawLine(void *drv, void *dev, DFBReg
          vectorMode |= GP_VECTOR_MAJOR_AXIS_POS;
       majorErr = (short)(adx << 1);
       Gal_bresenham_line((short)line->x1,
-                         (short)line->y1,
+                         (short)line->y1 + yoffset,
                          (short)ady,
                          (short)(majorErr - ady),
                          (short)majorErr,
@@ -381,10 +408,13 @@ static bool
 nscFillRectangle(void *drv, void *dev, DFBRectangle *rect)
 {
    NSCDeviceData *gxdev = (NSCDeviceData *) dev;
+   int yoffset;
 
    Gal_set_raster_operation(0xF0);
    Gal_set_solid_pattern(gxdev->Color);
-   Gal_pattern_fill(rect->x, rect->y, rect->w, rect->h);
+
+   yoffset = gxdev->dst_offset / gxdev->dst_pitch;
+   Gal_pattern_fill(rect->x, rect->y + yoffset, rect->w, rect->h);
 
    return true;
 }
@@ -393,14 +423,18 @@ static bool
 nscDrawRectangle(void *drv, void *dev, DFBRectangle *rect)
 {
    NSCDeviceData *gxdev = (NSCDeviceData *) dev;
+   int yoffset;
 
    Gal_set_raster_operation(0xF0);
    Gal_set_solid_pattern(gxdev->Color);
-   Gal_pattern_fill(rect->x, rect->y, rect->w, 1);
-   Gal_pattern_fill(rect->x, ((rect->y + rect->h) - 1), rect->w, 1);
-   Gal_pattern_fill(rect->x, (rect->y + 1), 1, (rect->h - 2));
+
+   yoffset = gxdev->dst_offset / gxdev->dst_pitch;
+
+   Gal_pattern_fill(rect->x, rect->y + yoffset, rect->w, 1);
+   Gal_pattern_fill(rect->x, ((rect->y + yoffset + rect->h) - 1), rect->w, 1);
+   Gal_pattern_fill(rect->x, (rect->y + yoffset + 1), 1, (rect->h - 2));
    Gal_pattern_fill(((rect->x + rect->w) - 1),
-                    (rect->y + 1), 1, (rect->h - 2));
+                    (rect->y + yoffset + 1), 1, (rect->h - 2));
 
    return true;
 }
@@ -427,6 +461,34 @@ nscBlit(void *drv, void *dev, DFBRectang
    return true;
 }
 
+static bool
+nscBlitGu1(void *drv, void *dev, DFBRectangle * rect, int dx, int dy)
+{ 
+   int result, yoff;
+
+   NSCDeviceData *nscdev = (NSCDeviceData *) dev;
+
+   Gal_set_solid_pattern(nscdev->Color);
+   if (nscdev->v_srcColorkey) {
+      Gal_set_source_transparency(nscdev->src_colorkey, 0xFFFF);
+   }
+#if 0
+   printf("rect x %d y %d w %d h %d dx %d dy %d src_off %x dst_off %x src pitch %x dst pitch %x\n",
+		rect->x, rect->y, rect->w, rect->h, dx, dy,
+		nscdev->src_offset, nscdev->dst_offset,
+		nscdev->src_pitch, nscdev->dst_pitch);
+#endif
+
+   Gal_set_raster_operation(0xCC);
+   
+   yoff = nscdev->src_offset / nscdev->src_pitch;
+   result = Gal_screen_to_screen_blt(rect->x, rect->y + yoff, dx, dy,
+                             (unsigned short)rect->w,
+                             (unsigned short)rect->h);
+
+   return true;
+}
+
 /* exported symbols */
 
 static int
@@ -460,6 +522,8 @@ driver_init_driver(GraphicsDevice      *
 {
    NSCDriverData *gxdrv = (NSCDriverData *) driver_data;
 
+   Gal_set_compression_enable(0);
+
    gxdrv->cpu_version = sAdapterInfo.dwCPUVersion;
    gxdrv->cpu = 0;
    if ((gxdrv->cpu_version & 0xFF) == GFX_CPU_REDCLOUD) {
@@ -477,8 +541,13 @@ driver_init_driver(GraphicsDevice      *
    funcs->DrawLine = nscDrawLine;
    if (gxdrv->cpu) {
       funcs->Blit = nscBlit;
+   } else {
+      funcs->Blit = nscBlitGu1;
    }
 #endif /* NSC_ACCEL */
+
+    /*dfb_config->pollvsync_after = 1;*/
+
    return DFB_OK;
 }
 
@@ -487,8 +556,6 @@ driver_init_device(GraphicsDevice *devic
                    GraphicsDeviceInfo *device_info,
                    void *driver_data, void *device_data)
 {
-   NSCDriverData *gxdrv = (NSCDriverData *) driver_data;
-
    snprintf(device_info->name,
             DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "NSC GX1/GX2 driver version");
    snprintf(device_info->vendor,
@@ -497,10 +564,8 @@ driver_init_device(GraphicsDevice *devic
    device_info->caps.flags = CCF_NOTRIEMU;
    device_info->caps.accel = GX_SUPPORTED_DRAWINGFUNCTIONS;
    device_info->caps.drawing = GX_SUPPORTED_DRAWINGFLAGS;
-   if (gxdrv->cpu) {
-      device_info->caps.accel |= GX_SUPPORTED_BLITTINGFUNCTIONS;
-      device_info->caps.blitting = GX_SUPPORTED_BLITTINGFLAGS;
-   }
+   device_info->caps.accel |= GX_SUPPORTED_BLITTINGFUNCTIONS;
+   device_info->caps.blitting = GX_SUPPORTED_BLITTINGFLAGS;
    return DFB_OK;
 }
 

Reply via email to