fix GL_BACK color material bug
[mesa.git] / src / mesa / drivers / glide / fxddspan.c
index b792caa0610da8f75e22970faf17aa862bf9e3ee..c620cc3c614e159f1752435069e9b19e0307d791 100644 (file)
@@ -2,9 +2,9 @@
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  3.3
  *
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 
 #if !defined(FXMESA_USE_ARGB) 
 
+
+#if defined(FX_GLIDE3) && defined(XF86DRI)
+
+static FxBool writeRegionClipped(fxMesaContext fxMesa, GrBuffer_t dst_buffer,
+                         FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format,
+                         FxU32 src_width, FxU32 src_height, FxI32 src_stride,
+                         void *src_data)
+{
+  int i, x, w, srcElt;
+  void *data;
+
+  if (src_width==1 && src_height==1) { /* Easy case writing a point */
+    for (i=0; i<fxMesa->numClipRects; i++) {
+      if ((dst_x>=fxMesa->pClipRects[i].x1) && 
+         (dst_x<fxMesa->pClipRects[i].x2) &&
+         (dst_y>=fxMesa->pClipRects[i].y1) && 
+         (dst_y<fxMesa->pClipRects[i].y2)) {
+       FX_grLfbWriteRegion(dst_buffer, dst_x, dst_y, src_format,
+                           1, 1, src_stride, src_data);
+       return GL_TRUE;
+      }
+    }
+  } else if (src_height==1) { /* Writing a span */
+    if (src_format==GR_LFB_SRC_FMT_8888) srcElt=4;
+    else if (src_format==GR_LFB_SRC_FMT_ZA16) srcElt=2;
+    else {
+      fprintf(stderr, "Unknown src_format passed to writeRegionClipped\n");
+      return GL_FALSE;
+    }
+    for (i=0; i<fxMesa->numClipRects; i++) {
+      if (dst_y>=fxMesa->pClipRects[i].y1 && dst_y<fxMesa->pClipRects[i].y2) {
+       if (dst_x<fxMesa->pClipRects[i].x1) {
+         x=fxMesa->pClipRects[i].x1;
+         data=((char*)src_data)+srcElt*(x - dst_x);
+         w=src_width-(x-dst_x);
+       } else {
+         x=dst_x;
+         data=src_data;
+         w=src_width;
+       }
+       if (x+w>fxMesa->pClipRects[i].x2) {
+         w=fxMesa->pClipRects[i].x2-x;
+       }
+       FX_grLfbWriteRegion(dst_buffer, x, dst_y, src_format, w, 1,
+                           src_stride, data);
+      }
+    }
+  } else { /* Punt on the case of arbitrary rectangles */
+    return GL_FALSE;
+  }
+  return GL_TRUE;
+}
+
+#else
+
+#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)             \
+  FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
+
+#endif
+
+
 /* KW: Rearranged the args in the call to grLfbWriteRegion().
  */
 #define LFB_WRITE_SPAN_MESA(dst_buffer,                \
                   src_data)                    \
 
 
-#else /* defined(FXMESA_USE_RGBA) */
+#else /* !defined(FXMESA_USE_RGBA) */
+
+#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)             \
+  FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
+
 
 #define MESACOLOR_TO_ARGB(c) (                         \
              ( ((unsigned int)(c[ACOMP]))<<24 ) |      \
              ( ((unsigned int)(c[GCOMP]))<<8 )  |      \
              (  (unsigned int)(c[BCOMP])) )
   
-void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer, 
+inline void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer, 
                         FxU32 dst_x, 
                         FxU32 dst_y, 
                         FxU32 src_width,
@@ -108,7 +173,7 @@ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
    {
       argb[i] = MESACOLOR_TO_ARGB(rgba[i]);
    }
-   writeRegionClipped(fxMesa, dst_buffer,
+   writeRegionClipped( /*fxMesa,*/ NULL, dst_buffer,
                       dst_x,
                       dst_y,
                       GR_LFB_SRC_FMT_8888,
@@ -117,61 +182,9 @@ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
                       src_stride,
                       (void*)argb);
 }
+#endif /* !defined(FXMESA_USE_RGBA) */
 
-#endif
-
-#if defined(FX_GLIDE3) && defined(XF86DRI)
-
-FxBool writeRegionClipped(fxMesaContext fxMesa, GrBuffer_t dst_buffer,
-                         FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format,
-                         FxU32 src_width, FxU32 src_height, FxI32 src_stride,
-                         void *src_data)
-{
-  int i, x, w;
-  void *data;
-
-  if (src_width==1 && src_height==1) { /* Easy case writing a point */
-    for (i=0; i<fxMesa->numClipRects; i++) {
-      if ((dst_x>=fxMesa->pClipRects[i].x1) && 
-         (dst_x<fxMesa->pClipRects[i].x2) &&
-         (dst_y>=fxMesa->pClipRects[i].y1) && 
-         (dst_y<fxMesa->pClipRects[i].y2)) {
-       FX_grLfbWriteRegion(dst_buffer, dst_x, dst_y, src_format,
-                           src_width, src_height, src_stride, src_data);
-       return GL_TRUE;
-      }
-    }
-  } else if (src_height==1) { /* Writing a span */
-    for (i=0; i<fxMesa->numClipRects; i++) {
-      if (dst_y>=fxMesa->pClipRects[i].y1 && dst_y<fxMesa->pClipRects[i].y2) {
-       if (dst_x<fxMesa->pClipRects[i].x1) {
-         x=fxMesa->pClipRects[i].x1;
-         data=((char*)src_data)+2*(dst_x-x);
-         w=src_width-(x-dst_x);
-       } else {
-         x=dst_x;
-         data=src_data;
-         w=src_width;
-       }
-       if (x+w>fxMesa->pClipRects[i].x2) {
-         w=fxMesa->pClipRects[i].x2-x;
-       }
-       FX_grLfbWriteRegion(dst_buffer, x, dst_y, src_format, w, src_height,
-                           src_stride, data);
-      }
-    }
-  } else { /* Punt on the case of arbitrary rectangles */
-    return GL_FALSE;
-  }
-  return GL_TRUE;
-}
-
-#else
-
-#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)             \
-  FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
-
-#endif
 
 /************************************************************************/
 /*****                    Span functions                            *****/
@@ -311,6 +324,7 @@ static void fxDDWriteMonoRGBASpan(const GLcontext *ctx,
 }
 
 
+#if 0
 static void fxDDReadRGBASpan(const GLcontext *ctx, 
                              GLuint n, GLint x, GLint y, GLubyte rgba[][4])
 {
@@ -319,6 +333,7 @@ static void fxDDReadRGBASpan(const GLcontext *ctx,
   GLuint i;
   GLint bottom=fxMesa->height+fxMesa->y_offset-1;
 
+  printf("read span %d, %d, %d\n", x,y,n);
   if (MESA_VERBOSE&VERBOSE_DRIVER) {
      fprintf(stderr,"fxmesa: fxDDReadRGBASpan(...)\n");
   }
@@ -336,6 +351,66 @@ static void fxDDReadRGBASpan(const GLcontext *ctx,
     rgba[i][ACOMP] = 255;
   }
 }
+#endif
+
+
+/*
+ * Read a span of 16-bit RGB pixels.  Note, we don't worry about cliprects
+ * since OpenGL says obscured pixels have undefined values.
+ */
+static void read_R5G6B5_span(const GLcontext *ctx, 
+                             GLuint n, GLint x, GLint y, GLubyte rgba[][4])
+{
+  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+  GrLfbInfo_t info;
+  BEGIN_BOARD_LOCK();
+  if (grLfbLock(GR_LFB_READ_ONLY,
+                fxMesa->currentFB,
+                GR_LFBWRITEMODE_ANY,
+                GR_ORIGIN_UPPER_LEFT,
+                FXFALSE,
+                &info)) {
+    const GLint winX = fxMesa->x_offset;
+    const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
+#ifdef XF86DRI
+    const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
+                          ? (fxMesa->screen_width) : (info.strideInBytes / 2);
+#else
+    const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
+#endif
+    const GLushort *data16 = (const GLushort *) info.lfbPtr
+                           + (winY - y) * srcStride
+                           + (winX + x);
+    const GLuint *data32 = (const GLuint *) data16;
+    GLuint i, j;
+    GLuint extraPixel = (n & 1);
+    n -= extraPixel;
+    for (i = j = 0; i < n; i += 2, j++) {
+      GLuint pixel = data32[j];
+      GLuint pixel0 = pixel & 0xffff;
+      GLuint pixel1 = pixel >> 16;
+      rgba[i][RCOMP] = FX_PixelToR[pixel0];
+      rgba[i][GCOMP] = FX_PixelToG[pixel0];
+      rgba[i][BCOMP] = FX_PixelToB[pixel0];
+      rgba[i][ACOMP] = 255;
+      rgba[i+1][RCOMP] = FX_PixelToR[pixel1];
+      rgba[i+1][GCOMP] = FX_PixelToG[pixel1];
+      rgba[i+1][BCOMP] = FX_PixelToB[pixel1];
+      rgba[i+1][ACOMP] = 255;
+    }
+    if (extraPixel) {
+      GLushort pixel = data16[n];
+      rgba[n][RCOMP] = FX_PixelToR[pixel];
+      rgba[n][GCOMP] = FX_PixelToG[pixel];
+      rgba[n][BCOMP] = FX_PixelToB[pixel];
+      rgba[n][ACOMP] = 255;
+    }
+
+    grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+  }
+  END_BOARD_LOCK();
+}
+
 
 /************************************************************************/
 /*****                    Pixel functions                           *****/
@@ -377,31 +452,48 @@ static void fxDDWriteMonoRGBAPixels(const GLcontext *ctx,
                        GR_LFB_SRC_FMT_8888,1,1,0,(void *) &fxMesa->color);
 }
 
-static void fxDDReadRGBAPixels(const GLcontext *ctx,
+
+static void read_R5G6B5_pixels(const GLcontext *ctx,
                                GLuint n, const GLint x[], const GLint y[],
                                GLubyte rgba[][4], const GLubyte mask[])
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLuint i;
-  GLint bottom=fxMesa->y_delta-1;
-
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-     fprintf(stderr,"fxmesa: fxDDReadRGBAPixels(...)\n");
-  }
-
-  for(i=0;i<n;i++) {
-    if(mask[i]) {
-      GLushort pixel;
-      FX_grLfbReadRegion(fxMesa->currentFB,x[i],bottom-y[i],1,1,0,&pixel);
-      rgba[i][RCOMP] = FX_PixelToR[pixel];
-      rgba[i][GCOMP] = FX_PixelToG[pixel];
-      rgba[i][BCOMP] = FX_PixelToB[pixel];
-      rgba[i][ACOMP] = 255;
+  fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
+  GrLfbInfo_t info;
+  BEGIN_BOARD_LOCK();
+  if (grLfbLock(GR_LFB_READ_ONLY,
+                fxMesa->currentFB,
+                GR_LFBWRITEMODE_ANY,
+                GR_ORIGIN_UPPER_LEFT,
+                FXFALSE,
+                &info)) {
+#ifdef XF86DRI
+    const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
+                          ? (fxMesa->screen_width) : (info.strideInBytes / 2);
+#else
+    const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
+#endif
+    const GLint winX = fxMesa->x_offset;
+    const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
+    GLuint i;
+    for(i=0;i<n;i++) {
+      if(mask[i]) {
+        const GLushort *data16 = (const GLushort *) info.lfbPtr
+                               + (winY - y[i]) * srcStride
+                               + (winX + x[i]);
+        const GLushort pixel = *data16;
+        rgba[i][RCOMP] = FX_PixelToR[pixel];
+        rgba[i][GCOMP] = FX_PixelToG[pixel];
+        rgba[i][BCOMP] = FX_PixelToB[pixel];
+        rgba[i][ACOMP] = 255;
+      }
     }
+    grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
   }
+  END_BOARD_LOCK();
 }
 
 
+
 /************************************************************************/
 /*****                    Depth functions                           *****/
 /************************************************************************/
@@ -410,11 +502,11 @@ void fxDDWriteDepthSpan(GLcontext *ctx,
                         GLuint n, GLint x, GLint y, const GLdepth depth[],
                         const GLubyte mask[])
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLint bottom=fxMesa->height+fxMesa->y_offset-1;
+  fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
+  GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-     fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n");
+  if (MESA_VERBOSE & VERBOSE_DRIVER) {
+     fprintf(stderr, "fxmesa: fxDDWriteDepthSpan(...)\n");
   }
 
   x += fxMesa->x_offset;
@@ -423,14 +515,20 @@ void fxDDWriteDepthSpan(GLcontext *ctx,
     GLint i;
     for (i = 0; i < n; i++) {
       if (mask[i]) {
-        writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x + i, bottom-y,
-                           GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &depth[i]);
+        GLshort d = depth[i];
+        writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x + i, bottom - y,
+                           GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d);
       }
     }
   }
   else {
-    writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x, bottom-y,
-                       GR_LFB_SRC_FMT_ZA16, n, 1, 0, (void *) depth);
+    GLushort depth16[MAX_WIDTH];
+    GLint i;
+    for (i = 0; i < n; i++) {
+      depth16[i] = depth[i];
+    }
+    writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x, bottom - y,
+                       GR_LFB_SRC_FMT_ZA16, n, 1, 0, (void *) depth16);
   }
 }
 
@@ -438,15 +536,20 @@ void fxDDWriteDepthSpan(GLcontext *ctx,
 void fxDDReadDepthSpan(GLcontext *ctx,
                        GLuint n, GLint x, GLint y, GLdepth depth[])
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLint bottom=fxMesa->height+fxMesa->y_offset-1;
+  fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
+  GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
+  GLushort depth16[MAX_WIDTH];
+  GLuint i;
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-     fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n");
+  if (MESA_VERBOSE & VERBOSE_DRIVER) {
+     fprintf(stderr, "fxmesa: fxDDReadDepthSpan(...)\n");
   }
 
-  x+=fxMesa->x_offset;
-  FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depth);
+  x += fxMesa->x_offset;
+  FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, depth16);
+  for (i = 0; i < n; i++) {
+    depth[i] = depth16[i];
+  }
 }
 
 
@@ -455,20 +558,21 @@ void fxDDWriteDepthPixels(GLcontext *ctx,
                           GLuint n, const GLint x[], const GLint y[],
                           const GLdepth depth[], const GLubyte mask[])
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLint bottom=fxMesa->height+fxMesa->y_offset-1;
+  fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
+  GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
   GLuint i;
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-     fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n");
+  if (MESA_VERBOSE & VERBOSE_DRIVER) {
+    fprintf(stderr, "fxmesa: fxDDWriteDepthPixels(...)\n");
   }
 
   for (i = 0; i < n; i++) {
     if (mask[i]) {
       int xpos = x[i] + fxMesa->x_offset;
       int ypos = bottom - y[i];
+      GLushort d = depth[i];
       writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, xpos, ypos,
-                         GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &depth[i]);
+                         GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d);
     }
   }
 }
@@ -477,19 +581,20 @@ void fxDDWriteDepthPixels(GLcontext *ctx,
 void fxDDReadDepthPixels(GLcontext *ctx, GLuint n,
                          const GLint x[], const GLint y[], GLdepth depth[])
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLint bottom=fxMesa->height+fxMesa->y_offset-1;
+  fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
+  GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
   GLuint i;
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-     fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n");
+  if (MESA_VERBOSE & VERBOSE_DRIVER) {
+    fprintf(stderr, "fxmesa: fxDDReadDepthPixels(...)\n");
   }
 
-
   for (i = 0; i < n; i++) {
     int xpos = x[i] + fxMesa->x_offset;
     int ypos = bottom - y[i];
-    FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER,xpos,ypos,1,1,0,&depth[i]);
+    GLushort d;
+    FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, xpos, ypos, 1, 1, 0, &d);
+    depth[i] = d;
   }
 }
 
@@ -513,8 +618,9 @@ void fxSetupDDSpanPointers(GLcontext *ctx)
   ctx->Driver.WriteCI32Pixels     =NULL;
   ctx->Driver.WriteMonoCIPixels   =NULL;
 
-  ctx->Driver.ReadRGBASpan        =fxDDReadRGBASpan;
-  ctx->Driver.ReadRGBAPixels      =fxDDReadRGBAPixels;
+  /*  ctx->Driver.ReadRGBASpan        =fxDDReadRGBASpan;*/
+  ctx->Driver.ReadRGBASpan = read_R5G6B5_span;
+  ctx->Driver.ReadRGBAPixels      = read_R5G6B5_pixels;
 
   ctx->Driver.ReadCI32Span        =NULL;
   ctx->Driver.ReadCI32Pixels      =NULL;