Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  6.5.2
  4.  *
  5.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. #include "main/glheader.h"
  27. #include "main/context.h"
  28. #include "main/macros.h"
  29. #include "main/imports.h"
  30.  
  31. #include "s_accum.h"
  32. #include "s_context.h"
  33. #include "s_masking.h"
  34. #include "s_span.h"
  35.  
  36.  
  37. /* XXX this would have to change for accum buffers with more or less
  38.  * than 16 bits per color channel.
  39.  */
  40. #define ACCUM_SCALE16 32767.0F
  41.  
  42.  
  43. /*
  44.  * Accumulation buffer notes
  45.  *
  46.  * Normally, accumulation buffer values are GLshorts with values in
  47.  * [-32767, 32767] which represent floating point colors in [-1, 1],
  48.  * as defined by the OpenGL specification.
  49.  *
  50.  * We optimize for the common case used for full-scene antialiasing:
  51.  *    // start with accum buffer cleared to zero
  52.  *    glAccum(GL_LOAD, w);   // or GL_ACCUM the first image
  53.  *    glAccum(GL_ACCUM, w);
  54.  *    ...
  55.  *    glAccum(GL_ACCUM, w);
  56.  *    glAccum(GL_RETURN, 1.0);
  57.  * That is, we start with an empty accumulation buffer and accumulate
  58.  * n images, each with weight w = 1/n.
  59.  * In this scenario, we can simply store unscaled integer values in
  60.  * the accum buffer instead of scaled integers.  We'll also keep track
  61.  * of the w value so when we do GL_RETURN we simply divide the accumulated
  62.  * values by n (n=1/w).
  63.  * This lets us avoid _many_ int->float->int conversions.
  64.  */
  65.  
  66.  
  67. #if CHAN_BITS == 8
  68. /* enable the optimization */
  69. #define USE_OPTIMIZED_ACCUM  1
  70. #else
  71. #define USE_OPTIMIZED_ACCUM  0
  72. #endif
  73.  
  74.  
  75. /**
  76.  * This is called when we fall out of optimized/unscaled accum buffer mode.
  77.  * That is, we convert each unscaled accum buffer value into a scaled value
  78.  * representing the range[-1, 1].
  79.  */
  80. static void
  81. rescale_accum( struct gl_context *ctx )
  82. {
  83.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  84.    struct gl_renderbuffer *rb
  85.       = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
  86.    const GLfloat s = swrast->_IntegerAccumScaler * (32767.0F / CHAN_MAXF);
  87.  
  88.    assert(rb);
  89.    assert(rb->_BaseFormat == GL_RGBA);
  90.    /* add other types in future? */
  91.    assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT);
  92.    assert(swrast->_IntegerAccumMode);
  93.  
  94.    if (rb->GetPointer(ctx, rb, 0, 0)) {
  95.       /* directly-addressable memory */
  96.       GLuint y;
  97.       for (y = 0; y < rb->Height; y++) {
  98.          GLuint i;
  99.          GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, 0, y);
  100.          for (i = 0; i < 4 * rb->Width; i++) {
  101.             acc[i] = (GLshort) (acc[i] * s);
  102.          }
  103.       }
  104.    }
  105.    else {
  106.       /* use get/put row funcs */
  107.       GLuint y;
  108.       for (y = 0; y < rb->Height; y++) {
  109.          GLshort accRow[MAX_WIDTH * 4];
  110.          GLuint i;
  111.          rb->GetRow(ctx, rb, rb->Width, 0, y, accRow);
  112.          for (i = 0; i < 4 * rb->Width; i++) {
  113.             accRow[i] = (GLshort) (accRow[i] * s);
  114.          }
  115.          rb->PutRow(ctx, rb, rb->Width, 0, y, accRow, NULL);
  116.       }
  117.    }
  118.  
  119.    swrast->_IntegerAccumMode = GL_FALSE;
  120. }
  121.  
  122.  
  123.  
  124. /**
  125.  * Clear the accumulation Buffer.
  126.  */
  127. void
  128. _swrast_clear_accum_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb )
  129. {
  130.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  131.    GLuint x, y, width, height;
  132.  
  133.    /* No accumulation buffer! Not an error. */
  134.    if (!rb || !rb->Data)
  135.       return;
  136.  
  137.    assert(rb->_BaseFormat == GL_RGBA);
  138.    /* add other types in future? */
  139.    assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT);
  140.  
  141.    /* bounds, with scissor */
  142.    x = ctx->DrawBuffer->_Xmin;
  143.    y = ctx->DrawBuffer->_Ymin;
  144.    width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
  145.    height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
  146.  
  147.    if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
  148.       const GLfloat accScale = 32767.0;
  149.       GLshort clearVal[4];
  150.       GLuint i;
  151.  
  152.       clearVal[0] = (GLshort) (ctx->Accum.ClearColor[0] * accScale);
  153.       clearVal[1] = (GLshort) (ctx->Accum.ClearColor[1] * accScale);
  154.       clearVal[2] = (GLshort) (ctx->Accum.ClearColor[2] * accScale);
  155.       clearVal[3] = (GLshort) (ctx->Accum.ClearColor[3] * accScale);
  156.  
  157.       for (i = 0; i < height; i++) {
  158.          rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
  159.       }
  160.    }
  161.    else {
  162.       /* someday support other sizes */
  163.    }
  164.  
  165.    /* update optimized accum state vars */
  166.    if (ctx->Accum.ClearColor[0] == 0.0 && ctx->Accum.ClearColor[1] == 0.0 &&
  167.        ctx->Accum.ClearColor[2] == 0.0 && ctx->Accum.ClearColor[3] == 0.0) {
  168. #if USE_OPTIMIZED_ACCUM
  169.       swrast->_IntegerAccumMode = GL_TRUE;
  170. #else
  171.       swrast->_IntegerAccumMode = GL_FALSE;
  172. #endif
  173.       swrast->_IntegerAccumScaler = 0.0;  /* denotes empty accum buffer */
  174.    }
  175.    else {
  176.       swrast->_IntegerAccumMode = GL_FALSE;
  177.    }
  178. }
  179.  
  180.  
  181. static void
  182. accum_add(struct gl_context *ctx, GLfloat value,
  183.           GLint xpos, GLint ypos, GLint width, GLint height )
  184. {
  185.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  186.    struct gl_renderbuffer *rb
  187.       = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
  188.  
  189.    assert(rb);
  190.  
  191.    /* Leave optimized accum buffer mode */
  192.    if (swrast->_IntegerAccumMode)
  193.       rescale_accum(ctx);
  194.  
  195.    if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
  196.       const GLshort incr = (GLshort) (value * ACCUM_SCALE16);
  197.       if (rb->GetPointer(ctx, rb, 0, 0)) {
  198.          GLint i, j;
  199.          for (i = 0; i < height; i++) {
  200.             GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
  201.             for (j = 0; j < 4 * width; j++) {
  202.                acc[j] += incr;
  203.             }
  204.          }
  205.       }
  206.       else {
  207.          GLint i, j;
  208.          for (i = 0; i < height; i++) {
  209.             GLshort accRow[4 * MAX_WIDTH];
  210.             rb->GetRow(ctx, rb, width, xpos, ypos + i, accRow);
  211.             for (j = 0; j < 4 * width; j++) {
  212.                accRow[j] += incr;
  213.             }
  214.             rb->PutRow(ctx, rb, width, xpos, ypos + i, accRow, NULL);
  215.          }
  216.       }
  217.    }
  218.    else {
  219.       /* other types someday */
  220.    }
  221. }
  222.  
  223.  
  224. static void
  225. accum_mult(struct gl_context *ctx, GLfloat mult,
  226.            GLint xpos, GLint ypos, GLint width, GLint height )
  227. {
  228.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  229.    struct gl_renderbuffer *rb
  230.       = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
  231.  
  232.    assert(rb);
  233.  
  234.    /* Leave optimized accum buffer mode */
  235.    if (swrast->_IntegerAccumMode)
  236.       rescale_accum(ctx);
  237.  
  238.    if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
  239.       if (rb->GetPointer(ctx, rb, 0, 0)) {
  240.          GLint i, j;
  241.          for (i = 0; i < height; i++) {
  242.             GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
  243.             for (j = 0; j < 4 * width; j++) {
  244.                acc[j] = (GLshort) (acc[j] * mult);
  245.             }
  246.          }
  247.       }
  248.       else {
  249.          GLint i, j;
  250.          for (i = 0; i < height; i++) {
  251.             GLshort accRow[4 * MAX_WIDTH];
  252.             rb->GetRow(ctx, rb, width, xpos, ypos + i, accRow);
  253.             for (j = 0; j < 4 * width; j++) {
  254.                accRow[j] = (GLshort) (accRow[j] * mult);
  255.             }
  256.             rb->PutRow(ctx, rb, width, xpos, ypos + i, accRow, NULL);
  257.          }
  258.       }
  259.    }
  260.    else {
  261.       /* other types someday */
  262.    }
  263. }
  264.  
  265.  
  266.  
  267. static void
  268. accum_accum(struct gl_context *ctx, GLfloat value,
  269.             GLint xpos, GLint ypos, GLint width, GLint height )
  270. {
  271.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  272.    struct gl_renderbuffer *rb
  273.       = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
  274.    const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);
  275.  
  276.    assert(rb);
  277.  
  278.    if (!ctx->ReadBuffer->_ColorReadBuffer) {
  279.       /* no read buffer - OK */
  280.       return;
  281.    }
  282.  
  283.    /* May have to leave optimized accum buffer mode */
  284.    if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0)
  285.       swrast->_IntegerAccumScaler = value;
  286.    if (swrast->_IntegerAccumMode && value != swrast->_IntegerAccumScaler)
  287.       rescale_accum(ctx);
  288.  
  289.    if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
  290.       const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
  291.       GLshort accumRow[4 * MAX_WIDTH];
  292.       GLchan rgba[MAX_WIDTH][4];
  293.       GLint i;
  294.  
  295.       for (i = 0; i < height; i++) {
  296.          GLshort *acc;
  297.          if (directAccess) {
  298.             acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
  299.          }
  300.          else {
  301.             rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow);
  302.             acc = accumRow;
  303.          }
  304.  
  305.          /* read colors from color buffer */
  306.          _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
  307.                                 xpos, ypos + i, CHAN_TYPE, rgba);
  308.  
  309.          /* do accumulation */
  310.          if (swrast->_IntegerAccumMode) {
  311.             /* simply add integer color values into accum buffer */
  312.             GLint j;
  313.             for (j = 0; j < width; j++) {
  314.                acc[j * 4 + 0] += rgba[j][RCOMP];
  315.                acc[j * 4 + 1] += rgba[j][GCOMP];
  316.                acc[j * 4 + 2] += rgba[j][BCOMP];
  317.                acc[j * 4 + 3] += rgba[j][ACOMP];
  318.             }
  319.          }
  320.          else {
  321.             /* scaled integer (or float) accum buffer */
  322.             GLint j;
  323.             for (j = 0; j < width; j++) {
  324.                acc[j * 4 + 0] += (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
  325.                acc[j * 4 + 1] += (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
  326.                acc[j * 4 + 2] += (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
  327.                acc[j * 4 + 3] += (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
  328.             }
  329.          }
  330.  
  331.          if (!directAccess) {
  332.             rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
  333.          }
  334.       }
  335.    }
  336.    else {
  337.       /* other types someday */
  338.    }
  339. }
  340.  
  341.  
  342.  
  343. static void
  344. accum_load(struct gl_context *ctx, GLfloat value,
  345.            GLint xpos, GLint ypos, GLint width, GLint height )
  346. {
  347.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  348.    struct gl_renderbuffer *rb
  349.       = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
  350.    const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);
  351.  
  352.    assert(rb);
  353.  
  354.    if (!ctx->ReadBuffer->_ColorReadBuffer) {
  355.       /* no read buffer - OK */
  356.       return;
  357.    }
  358.  
  359.    /* This is a change to go into optimized accum buffer mode */
  360.    if (value > 0.0 && value <= 1.0) {
  361. #if USE_OPTIMIZED_ACCUM
  362.       swrast->_IntegerAccumMode = GL_TRUE;
  363. #else
  364.       swrast->_IntegerAccumMode = GL_FALSE;
  365. #endif
  366.       swrast->_IntegerAccumScaler = value;
  367.    }
  368.    else {
  369.       swrast->_IntegerAccumMode = GL_FALSE;
  370.       swrast->_IntegerAccumScaler = 0.0;
  371.    }
  372.  
  373.    if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
  374.       const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
  375.       GLshort accumRow[4 * MAX_WIDTH];
  376.       GLchan rgba[MAX_WIDTH][4];
  377.       GLint i;
  378.  
  379.       for (i = 0; i < height; i++) {
  380.          GLshort *acc;
  381.          if (directAccess) {
  382.             acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
  383.          }
  384.          else {
  385.             rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow);
  386.             acc = accumRow;
  387.          }
  388.  
  389.          /* read colors from color buffer */
  390.          _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
  391.                                 xpos, ypos + i, CHAN_TYPE, rgba);
  392.  
  393.          /* do load */
  394.          if (swrast->_IntegerAccumMode) {
  395.             /* just copy values in */
  396.             GLint j;
  397.             assert(swrast->_IntegerAccumScaler > 0.0);
  398.             assert(swrast->_IntegerAccumScaler <= 1.0);
  399.             for (j = 0; j < width; j++) {
  400.                acc[j * 4 + 0] = rgba[j][RCOMP];
  401.                acc[j * 4 + 1] = rgba[j][GCOMP];
  402.                acc[j * 4 + 2] = rgba[j][BCOMP];
  403.                acc[j * 4 + 3] = rgba[j][ACOMP];
  404.             }
  405.          }
  406.          else {
  407.             /* scaled integer (or float) accum buffer */
  408.             GLint j;
  409.             for (j = 0; j < width; j++) {
  410.                acc[j * 4 + 0] = (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
  411.                acc[j * 4 + 1] = (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
  412.                acc[j * 4 + 2] = (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
  413.                acc[j * 4 + 3] = (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
  414.             }
  415.          }
  416.  
  417.          if (!directAccess) {
  418.             rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
  419.          }
  420.       }
  421.    }
  422. }
  423.  
  424.  
  425. static void
  426. accum_return(struct gl_context *ctx, GLfloat value,
  427.              GLint xpos, GLint ypos, GLint width, GLint height )
  428. {
  429.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  430.    struct gl_framebuffer *fb = ctx->DrawBuffer;
  431.    struct gl_renderbuffer *accumRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer;
  432.    const GLboolean directAccess
  433.       = (accumRb->GetPointer(ctx, accumRb, 0, 0) != NULL);
  434.  
  435.    static GLchan multTable[32768];
  436.    static GLfloat prevMult = 0.0;
  437.    const GLfloat mult = swrast->_IntegerAccumScaler;
  438.    const GLint max = MIN2((GLint) (256 / mult), 32767);
  439.  
  440.    /* May have to leave optimized accum buffer mode */
  441.    if (swrast->_IntegerAccumMode && value != 1.0)
  442.       rescale_accum(ctx);
  443.  
  444.    if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) {
  445.       /* build lookup table to avoid many floating point multiplies */
  446.       GLint j;
  447.       assert(swrast->_IntegerAccumScaler <= 1.0);
  448.       if (mult != prevMult) {
  449.          for (j = 0; j < max; j++)
  450.             multTable[j] = IROUND((GLfloat) j * mult);
  451.          prevMult = mult;
  452.       }
  453.    }
  454.  
  455.    if (accumRb->DataType == GL_SHORT ||
  456.        accumRb->DataType == GL_UNSIGNED_SHORT) {
  457.       const GLfloat scale = value * CHAN_MAXF / ACCUM_SCALE16;
  458.       GLuint buffer;
  459.       GLint i;
  460.  
  461.       /* XXX maybe transpose the 'i' and 'buffer' loops??? */
  462.       for (i = 0; i < height; i++) {
  463.          GLshort accumRow[4 * MAX_WIDTH];
  464.          GLshort *acc;
  465.          SWspan span;
  466.  
  467.          /* init color span */
  468.          INIT_SPAN(span, GL_BITMAP);
  469.          span.end = width;
  470.          span.arrayMask = SPAN_RGBA;
  471.          span.x = xpos;
  472.          span.y = ypos + i;
  473.  
  474.          if (directAccess) {
  475.             acc = (GLshort *) accumRb->GetPointer(ctx, accumRb, xpos, ypos +i);
  476.          }
  477.          else {
  478.             accumRb->GetRow(ctx, accumRb, width, xpos, ypos + i, accumRow);
  479.             acc = accumRow;
  480.          }
  481.  
  482.          /* get the colors to return */
  483.          if (swrast->_IntegerAccumMode) {
  484.             GLint j;
  485.             for (j = 0; j < width; j++) {
  486.                ASSERT(acc[j * 4 + 0] < max);
  487.                ASSERT(acc[j * 4 + 1] < max);
  488.                ASSERT(acc[j * 4 + 2] < max);
  489.                ASSERT(acc[j * 4 + 3] < max);
  490.                span.array->rgba[j][RCOMP] = multTable[acc[j * 4 + 0]];
  491.                span.array->rgba[j][GCOMP] = multTable[acc[j * 4 + 1]];
  492.                span.array->rgba[j][BCOMP] = multTable[acc[j * 4 + 2]];
  493.                span.array->rgba[j][ACOMP] = multTable[acc[j * 4 + 3]];
  494.             }
  495.          }
  496.          else {
  497.             /* scaled integer (or float) accum buffer */
  498.             GLint j;
  499.             for (j = 0; j < width; j++) {
  500. #if CHAN_BITS==32
  501.                GLchan r = acc[j * 4 + 0] * scale;
  502.                GLchan g = acc[j * 4 + 1] * scale;
  503.                GLchan b = acc[j * 4 + 2] * scale;
  504.                GLchan a = acc[j * 4 + 3] * scale;
  505. #else
  506.                GLint r = IROUND( (GLfloat) (acc[j * 4 + 0]) * scale );
  507.                GLint g = IROUND( (GLfloat) (acc[j * 4 + 1]) * scale );
  508.                GLint b = IROUND( (GLfloat) (acc[j * 4 + 2]) * scale );
  509.                GLint a = IROUND( (GLfloat) (acc[j * 4 + 3]) * scale );
  510. #endif
  511.                span.array->rgba[j][RCOMP] = CLAMP( r, 0, CHAN_MAX );
  512.                span.array->rgba[j][GCOMP] = CLAMP( g, 0, CHAN_MAX );
  513.                span.array->rgba[j][BCOMP] = CLAMP( b, 0, CHAN_MAX );
  514.                span.array->rgba[j][ACOMP] = CLAMP( a, 0, CHAN_MAX );
  515.             }
  516.          }
  517.  
  518.          /* store colors */
  519.          for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) {
  520.             struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buffer];
  521.             const GLboolean masking = (!ctx->Color.ColorMask[buffer][RCOMP] ||
  522.                                        !ctx->Color.ColorMask[buffer][GCOMP] ||
  523.                                        !ctx->Color.ColorMask[buffer][BCOMP] ||
  524.                                        !ctx->Color.ColorMask[buffer][ACOMP]);
  525.             if (masking) {
  526.                _swrast_mask_rgba_span(ctx, rb, &span, buffer);
  527.             }
  528.             rb->PutRow(ctx, rb, width, xpos, ypos + i, span.array->rgba, NULL);
  529.          }
  530.       }
  531.    }
  532.    else {
  533.       /* other types someday */
  534.    }
  535. }
  536.  
  537.  
  538.  
  539. /**
  540.  * Software fallback for glAccum.
  541.  */
  542. void
  543. _swrast_Accum(struct gl_context *ctx, GLenum op, GLfloat value)
  544. {
  545.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  546.    GLint xpos, ypos, width, height;
  547.  
  548.    if (swrast->NewState)
  549.       _swrast_validate_derived( ctx );
  550.  
  551.    if (!ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer) {
  552.       _mesa_warning(ctx, "Calling glAccum() without an accumulation buffer");
  553.       return;
  554.    }
  555.  
  556.    swrast_render_start(ctx);
  557.  
  558.    /* Compute region after calling swrast_render_start() so that we know the
  559.     * drawbuffer's size/bounds are up to date.
  560.     */
  561.    xpos = ctx->DrawBuffer->_Xmin;
  562.    ypos = ctx->DrawBuffer->_Ymin;
  563.    width =  ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
  564.    height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
  565.  
  566.    switch (op) {
  567.       case GL_ADD:
  568.          if (value != 0.0F) {
  569.             accum_add(ctx, value, xpos, ypos, width, height);
  570.          }
  571.          break;
  572.       case GL_MULT:
  573.          if (value != 1.0F) {
  574.             accum_mult(ctx, value, xpos, ypos, width, height);
  575.          }
  576.          break;
  577.       case GL_ACCUM:
  578.          if (value != 0.0F) {
  579.             accum_accum(ctx, value, xpos, ypos, width, height);
  580.          }
  581.          break;
  582.       case GL_LOAD:
  583.          accum_load(ctx, value, xpos, ypos, width, height);
  584.          break;
  585.       case GL_RETURN:
  586.          accum_return(ctx, value, xpos, ypos, width, height);
  587.          break;
  588.       default:
  589.          _mesa_problem(ctx, "invalid mode in _swrast_Accum()");
  590.          break;
  591.    }
  592.  
  593.    swrast_render_finish(ctx);
  594. }
  595.