s/BlendEquatioRGB/BlendEquationRGB/
[mesa.git] / src / mesa / swrast / s_buffers.c
index 46ffe8cc90c4e0ac8d3dec13affe0a9820b627d4..22aee6c91d25734b78149051f7583cd2ccae6761 100644 (file)
@@ -1,21 +1,20 @@
-/* $Id: s_buffers.c,v 1.3 2001/01/23 23:39:37 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
- * 
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
- * 
+ * Version:  5.1
+ *
+ * Copyright (C) 1999-2002  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"),
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
 
 #include "glheader.h"
+#include "colormac.h"
 #include "macros.h"
-#include "mem.h"
+#include "imports.h"
 
 #include "s_accum.h"
 #include "s_alphabuf.h"
+#include "s_context.h"
 #include "s_depth.h"
 #include "s_masking.h"
 #include "s_stencil.h"
@@ -44,6 +45,7 @@
 static void
 clear_color_buffer_with_masking( GLcontext *ctx )
 {
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLint x = ctx->DrawBuffer->_Xmin;
    const GLint y = ctx->DrawBuffer->_Ymin;
    const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
@@ -51,23 +53,21 @@ clear_color_buffer_with_masking( GLcontext *ctx )
 
    if (ctx->Visual.rgbMode) {
       /* RGBA mode */
-      const GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF);
-      const GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF);
-      const GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF);
-      const GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF);
+      GLchan clearColor[4];
       GLint i;
+      CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
+      CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
+      CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
+      CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
       for (i = 0; i < height; i++) {
          GLchan rgba[MAX_WIDTH][4];
          GLint j;
-         for (j=0; j<width; j++) {
-            rgba[j][RCOMP] = r;
-            rgba[j][GCOMP] = g;
-            rgba[j][BCOMP] = b;
-            rgba[j][ACOMP] = a;
+         for (j = 0; j < width; j++) {
+            COPY_CHAN4(rgba[j], clearColor);
          }
-         _mesa_mask_rgba_span( ctx, width, x, y + i, rgba );
-         (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y + i,
-                                      (CONST GLchan (*)[4]) rgba, NULL );
+         _swrast_mask_rgba_array( ctx, width, x, y + i, rgba );
+         (*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i,
+                                          (CONST GLchan (*)[4]) rgba, NULL );
       }
    }
    else {
@@ -80,8 +80,8 @@ clear_color_buffer_with_masking( GLcontext *ctx )
          for (j=0;j<width;j++) {
             span[j] = ctx->Color.ClearIndex;
          }
-         _mesa_mask_index_span( ctx, width, x, y + i, span );
-         (*ctx->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
+         _swrast_mask_index_array( ctx, width, x, y + i, span );
+         (*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
       }
    }
 }
@@ -94,6 +94,7 @@ clear_color_buffer_with_masking( GLcontext *ctx )
 static void
 clear_color_buffer(GLcontext *ctx)
 {
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLint x = ctx->DrawBuffer->_Xmin;
    const GLint y = ctx->DrawBuffer->_Ymin;
    const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
@@ -101,48 +102,31 @@ clear_color_buffer(GLcontext *ctx)
 
    if (ctx->Visual.rgbMode) {
       /* RGBA mode */
-      const GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF);
-      const GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF);
-      const GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF);
-      const GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF);
-      GLchan span[MAX_WIDTH][4];
+      GLchan clearColor[4];
       GLint i;
 
+      CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
+      CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
+      CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
+      CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
+
       ASSERT(*((GLuint *) &ctx->Color.ColorMask) == 0xffffffff);
+      ASSERT(swrast->Driver.WriteRGBASpan);
 
-      for (i = 0; i < width; i++) {
-         span[i][RCOMP] = r;
-         span[i][GCOMP] = g;
-         span[i][BCOMP] = b;
-         span[i][ACOMP] = a;
-      }
       for (i = 0; i < height; i++) {
-         (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y + i,
-                                       (CONST GLchan (*)[4]) span, NULL );
+         (*swrast->Driver.WriteMonoRGBASpan)( ctx, width, x, y + i,
+                                              clearColor, NULL );
       }
    }
    else {
       /* Color index mode */
-      ASSERT(ctx->Color.IndexMask == ~0);
-      if (ctx->Visual.indexBits == 8) {
-         /* 8-bit clear */
-         GLubyte span[MAX_WIDTH];
-         GLint i;
-         MEMSET(span, ctx->Color.ClearIndex, width);
-         for (i = 0; i < height; i++) {
-            (*ctx->Driver.WriteCI8Span)( ctx, width, x, y + i, span, NULL );
-         }
-      }
-      else {
-         /* non 8-bit clear */
-         GLuint span[MAX_WIDTH];
-         GLint i;
-         for (i = 0; i < width; i++) {
-            span[i] = ctx->Color.ClearIndex;
-         }
-         for (i = 0; i < height; i++) {
-            (*ctx->Driver.WriteCI32Span)( ctx, width, x, y + i, span, NULL );
-         }
+      GLint i;
+      ASSERT((ctx->Color.IndexMask & ((1 << ctx->Visual.indexBits) - 1))
+             == (GLuint) ((1 << ctx->Visual.indexBits) - 1));
+      ASSERT(swrast->Driver.WriteMonoCISpan);
+      for (i = 0; i < height; i++) {
+         (*swrast->Driver.WriteMonoCISpan)( ctx, width, x, y + i,
+                                            ctx->Color.ClearIndex, NULL);
       }
    }
 }
@@ -157,29 +141,15 @@ clear_color_buffer(GLcontext *ctx)
 static void
 clear_color_buffers(GLcontext *ctx)
 {
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
    GLuint bufferBit;
 
    /* loop over four possible dest color buffers */
    for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
-      if (bufferBit & ctx->Color.DrawDestMask) {
-         if (bufferBit == FRONT_LEFT_BIT) {
-            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
-            (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_FRONT_LEFT);
-         }
-         else if (bufferBit == FRONT_RIGHT_BIT) {
-            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
-            (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_FRONT_RIGHT);
-         }
-         else if (bufferBit == BACK_LEFT_BIT) {
-            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
-            (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_BACK_LEFT);
-         }
-         else {
-            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
-            (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_BACK_RIGHT);
-         }
-         
+      if (bufferBit & ctx->Color._DrawDestMask) {
+         (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
+
          if (colorMask != 0xffffffff) {
             clear_color_buffer_with_masking(ctx);
          }
@@ -189,19 +159,18 @@ clear_color_buffers(GLcontext *ctx)
       }
    }
 
-   /* restore default read/draw buffers */
-   (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
-   (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer );
+   /* restore default read/draw buffer */
+   _swrast_use_draw_buffer(ctx);
 }
 
 
 
-void 
+void
 _swrast_Clear( GLcontext *ctx, GLbitfield mask,
-              GLboolean all, 
+              GLboolean all,
               GLint x, GLint y, GLint width, GLint height )
 {
-
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 #ifdef DEBUG
    {
       GLbitfield legalBits = DD_FRONT_LEFT_BIT |
@@ -215,43 +184,104 @@ _swrast_Clear( GLcontext *ctx, GLbitfield mask,
    }
 #endif
 
-   RENDER_START(ctx);
+   RENDER_START(swrast,ctx);
 
    /* do software clearing here */
    if (mask) {
-      if (mask & ctx->Color.DrawDestMask)   clear_color_buffers(ctx);
-      if (mask & GL_DEPTH_BUFFER_BIT)    _mesa_clear_depth_buffer(ctx);
-      if (mask & GL_ACCUM_BUFFER_BIT)    _mesa_clear_accum_buffer(ctx);
-      if (mask & GL_STENCIL_BUFFER_BIT)  _mesa_clear_stencil_buffer(ctx);
+      if (mask & ctx->Color._DrawDestMask)   clear_color_buffers(ctx);
+      if (mask & GL_DEPTH_BUFFER_BIT)    _swrast_clear_depth_buffer(ctx);
+      if (mask & GL_ACCUM_BUFFER_BIT)    _swarst_clear_accum_buffer(ctx);
+      if (mask & GL_STENCIL_BUFFER_BIT)  _swrast_clear_stencil_buffer(ctx);
    }
 
    /* clear software-based alpha buffer(s) */
    if ( (mask & GL_COLOR_BUFFER_BIT)
        && ctx->DrawBuffer->UseSoftwareAlphaBuffers
        && ctx->Color.ColorMask[ACOMP]) {
-      _mesa_clear_alpha_buffers( ctx );
+      _swrast_clear_alpha_buffers( ctx );
    }
 
-   RENDER_FINISH(ctx);
+   RENDER_FINISH(swrast,ctx);
 }
 
 
 void
-_swrast_alloc_buffers( GLcontext *ctx )
+_swrast_alloc_buffers( GLframebuffer *buffer )
 {
    /* Reallocate other buffers if needed. */
-   if (ctx->DrawBuffer->UseSoftwareDepthBuffer) {
-      _mesa_alloc_depth_buffer( ctx );
+   if (buffer->UseSoftwareDepthBuffer) {
+      _swrast_alloc_depth_buffer( buffer );
    }
-   if (ctx->DrawBuffer->UseSoftwareStencilBuffer) {
-      _mesa_alloc_stencil_buffer( ctx );
+   if (buffer->UseSoftwareStencilBuffer) {
+      _swrast_alloc_stencil_buffer( buffer );
    }
-   if (ctx->DrawBuffer->UseSoftwareAccumBuffer) {
-      _mesa_alloc_accum_buffer( ctx );
+   if (buffer->UseSoftwareAccumBuffer) {
+      _swrast_alloc_accum_buffer( buffer );
    }
-   if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
-      _mesa_alloc_alpha_buffers( ctx );
+   if (buffer->UseSoftwareAlphaBuffers) {
+      _swrast_alloc_alpha_buffers( buffer );
    }
 }
 
 
+/*
+ * Fallback for ctx->Driver.DrawBuffer()
+ */
+void
+_swrast_DrawBuffer( GLcontext *ctx, GLenum mode )
+{
+   _swrast_use_draw_buffer(ctx);
+}
+
+
+/*
+ * Setup things so that we read/write spans from the user-designated
+ * read buffer (set via glReadPixels).  We usually just have to call
+ * this for glReadPixels, glCopyPixels, etc.
+ */
+void
+_swrast_use_read_buffer( GLcontext *ctx )
+{
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+   /* Do this so the software-emulated alpha plane span functions work! */
+   swrast->CurrentBuffer = ctx->Pixel._ReadSrcMask;
+   /* Tell the device driver where to read/write spans */
+   (*swrast->Driver.SetBuffer)( ctx, ctx->ReadBuffer, swrast->CurrentBuffer );
+}
+
+
+/*
+ * Setup things so that we read/write spans from the default draw buffer.
+ * This is the usual mode that Mesa's software rasterizer operates in.
+ */
+void
+_swrast_use_draw_buffer( GLcontext *ctx )
+{
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+   /* The user can specify rendering to zero, one, two, or four color
+    * buffers simultaneously with glDrawBuffer()!
+    * We don't expect the span/point/line/triangle functions to deal with
+    * that mess so we'll iterate over the multiple buffers as needed.
+    * But usually we only render to one color buffer at a time.
+    * We set ctx->Color._DriverDrawBuffer to that buffer and tell the
+    * device driver to use that buffer.
+    * Look in s_span.c's multi_write_rgba_span() function to see how
+    * we loop over multiple color buffers when needed.
+    */
+
+   if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT)
+      swrast->CurrentBuffer = FRONT_LEFT_BIT;
+   else if (ctx->Color._DrawDestMask & BACK_LEFT_BIT)
+      swrast->CurrentBuffer = BACK_LEFT_BIT;
+   else if (ctx->Color._DrawDestMask & FRONT_RIGHT_BIT)
+      swrast->CurrentBuffer = FRONT_RIGHT_BIT;
+   else if (ctx->Color._DrawDestMask & BACK_RIGHT_BIT)
+      swrast->CurrentBuffer = BACK_RIGHT_BIT;
+   else
+      /* glDrawBuffer(GL_NONE) */
+      swrast->CurrentBuffer = FRONT_LEFT_BIT; /* we always have this buffer */
+
+   (*swrast->Driver.SetBuffer)( ctx, ctx->DrawBuffer, swrast->CurrentBuffer );
+}