home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / misc.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  18KB  |  593 lines

  1. /* $Id: misc.c,v 1.3 1999/10/08 09:27:11 keithw dead $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
  8.  * 
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  * 
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #ifdef PC_HEADER
  29. #include "all.h"
  30. #else
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34. #include "accum.h"
  35. #include "alphabuf.h"
  36. #include "context.h"
  37. #include "depth.h"
  38. #include "enums.h"
  39. #include "macros.h"
  40. #include "masking.h"
  41. //#include "misc.h"
  42. #include "stencil.h"
  43. #include "types.h"
  44. #ifdef XFree86Server
  45. #undef MISC_H
  46. #include "GL/xf86glx.h"
  47. #endif
  48. #endif
  49.  
  50.  
  51.  
  52. void gl_ClearIndex( GLcontext *ctx, GLfloat c )
  53. {
  54.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearIndex");
  55.    ctx->Color.ClearIndex = (GLuint) c;
  56.    if (!ctx->Visual->RGBAflag) {
  57.       /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
  58.       (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
  59.    }
  60. }
  61.  
  62.  
  63.  
  64. void gl_ClearColor( GLcontext *ctx, GLclampf red, GLclampf green,
  65.                     GLclampf blue, GLclampf alpha )
  66. {
  67.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearColor");
  68.  
  69.    ctx->Color.ClearColor[0] = CLAMP( red,   0.0F, 1.0F );
  70.    ctx->Color.ClearColor[1] = CLAMP( green, 0.0F, 1.0F );
  71.    ctx->Color.ClearColor[2] = CLAMP( blue,  0.0F, 1.0F );
  72.    ctx->Color.ClearColor[3] = CLAMP( alpha, 0.0F, 1.0F );
  73.  
  74.    if (ctx->Visual->RGBAflag) {
  75.       GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
  76.       GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
  77.       GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
  78.       GLubyte a = (GLint) (ctx->Color.ClearColor[3] * 255.0F);
  79.       (*ctx->Driver.ClearColor)( ctx, r, g, b, a );
  80.    }
  81. }
  82.  
  83.  
  84.  
  85.  
  86. /*
  87.  * Clear the color buffer when glColorMask or glIndexMask is in effect.
  88.  */
  89. static void clear_color_buffer_with_masking( GLcontext *ctx )
  90. {
  91.    GLint x, y, height, width;
  92.  
  93.    /* Compute region to clear */
  94.    if (ctx->Scissor.Enabled) {
  95.       x = ctx->Buffer->Xmin;
  96.       y = ctx->Buffer->Ymin;
  97.       height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  98.       width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  99.    }
  100.    else {
  101.       x = 0;
  102.       y = 0;
  103.       height = ctx->Buffer->Height;
  104.       width  = ctx->Buffer->Width;
  105.    }
  106.  
  107.    if (ctx->Visual->RGBAflag) {
  108.       /* RGBA mode */
  109.       GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
  110.       GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
  111.       GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
  112.       GLubyte a = (GLint) (ctx->Color.ClearColor[3] * 255.0F);
  113.       GLint i;
  114.       for (i=0;i<height;i++,y++) {
  115.          GLubyte rgba[MAX_WIDTH][4];
  116.          GLint j;
  117.          for (j=0; j<width; j++) {
  118.             rgba[j][RCOMP] = r;
  119.             rgba[j][GCOMP] = g;
  120.             rgba[j][BCOMP] = b;
  121.             rgba[j][ACOMP] = a;
  122.          }
  123.          gl_mask_rgba_span( ctx, width, x, y, rgba );
  124.          (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 
  125.                        (const GLubyte (*)[4])rgba, NULL );
  126.       }
  127.    }
  128.    else {
  129.       /* Color index mode */
  130.       GLuint indx[MAX_WIDTH];
  131.       GLubyte mask[MAX_WIDTH];
  132.       GLint i, j;
  133.       MEMSET( mask, 1, width );
  134.       for (i=0;i<height;i++,y++) {
  135.          for (j=0;j<width;j++) {
  136.             indx[j] = ctx->Color.ClearIndex;
  137.          }
  138.          gl_mask_index_span( ctx, width, x, y, indx );
  139.          (*ctx->Driver.WriteCI32Span)( ctx, width, x, y, indx, mask );
  140.       }
  141.    }
  142. }
  143.  
  144.  
  145.  
  146. /*
  147.  * Clear the front and/or back color buffers.  Also clear the alpha
  148.  * buffer(s) if present.
  149.  */
  150. static void clear_color_buffers( GLcontext *ctx )
  151. {
  152.  
  153.    if (ctx->RasterMask & MULTI_DRAW_BIT) {
  154.       GLuint bufferBit;
  155.  
  156.       if (ctx->Color.DrawBuffer == GL_NONE)
  157.          return;
  158.  
  159.       /* loop over four possible dest color buffers */
  160.       for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
  161.          if (bufferBit & ctx->Color.DrawDestMask) {
  162.             if (bufferBit == FRONT_LEFT_BIT) {
  163.                (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
  164.                ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
  165.             }
  166.             else if (bufferBit == FRONT_RIGHT_BIT) {
  167.                (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
  168.                ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
  169.             }
  170.             else if (bufferBit == BACK_LEFT_BIT) {
  171.                (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
  172.                ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
  173.             }
  174.             else {
  175.                (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
  176.                ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
  177.             }
  178.  
  179.             if (ctx->Color.SWmasking) {
  180.                clear_color_buffer_with_masking( ctx );
  181.             }
  182.             else {
  183.                GLint x = ctx->Buffer->Xmin;
  184.                GLint y = ctx->Buffer->Ymin;
  185.                GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  186.                GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  187.                (void) (*ctx->Driver.Clear)( ctx, GL_COLOR_BUFFER_BIT,
  188.                                             !ctx->Scissor.Enabled,
  189.                                             x, y, width, height );
  190.             }
  191.          }
  192.       }
  193.  
  194.       /* restore default dest buffer */
  195.       (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
  196.    }
  197.    else {
  198.       /* normal case:  clear exactly one color buffer */
  199.  
  200.       if (ctx->Color.SWmasking) {
  201.          clear_color_buffer_with_masking( ctx );
  202.       }
  203.       else {
  204.          GLint x = ctx->Buffer->Xmin;
  205.          GLint y = ctx->Buffer->Ymin;
  206.          GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  207.          GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  208.          (void) (*ctx->Driver.Clear)( ctx, GL_COLOR_BUFFER_BIT,
  209.                                       !ctx->Scissor.Enabled,
  210.                                       x, y, width, height );
  211.       }
  212.    }
  213. }
  214.  
  215.  
  216.  
  217. void gl_Clear( GLcontext *ctx, GLbitfield mask )
  218. {
  219. #ifdef PROFILE
  220.    GLdouble t0 = gl_time();
  221. #endif
  222.  
  223.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClear");
  224.  
  225.    if (MESA_VERBOSE & VERBOSE_API)
  226.       fprintf(stderr, "glClear 0x%x\n", mask);
  227.  
  228.    if (ctx->RenderMode==GL_RENDER) {
  229.       GLint x, y, width, height;
  230.       GLbitfield newMask;
  231.  
  232.       if (ctx->NewState) {
  233.          gl_update_state( ctx );
  234.       }
  235.  
  236.       x = ctx->Buffer->Xmin;
  237.       y = ctx->Buffer->Ymin;
  238.       height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  239.       width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  240.  
  241.       /* clear software alpha buffer(s) */
  242.       if ( (mask & GL_COLOR_BUFFER_BIT) && (ctx->RasterMask & ALPHABUF_BIT) ) {
  243.          gl_clear_alpha_buffers( ctx );
  244.       }
  245.  
  246.       /* let device driver try to clear the buffers */
  247.       if ((mask & GL_COLOR_BUFFER_BIT) != 0
  248.           && (ctx->Color.SWmasking || (ctx->RasterMask & MULTI_DRAW_BIT))) {
  249.          /* Driver can't clear color buffer for some reason, let it try
  250.           * to clear the other ancillary buffers.
  251.           */
  252.          GLbitfield mask2 = mask & (~GL_COLOR_BUFFER_BIT);
  253.          newMask = (*ctx->Driver.Clear)( ctx, mask2, !ctx->Scissor.Enabled,
  254.                                          x, y, width, height );
  255.          newMask |= GL_COLOR_BUFFER_BIT;
  256.       }
  257.       else {
  258.          newMask = (*ctx->Driver.Clear)( ctx, mask, !ctx->Scissor.Enabled,
  259.                                          x, y, width, height );
  260.       }
  261.  
  262.       if (newMask & GL_COLOR_BUFFER_BIT)    clear_color_buffers( ctx );
  263.       if (newMask & GL_DEPTH_BUFFER_BIT)    gl_clear_depth_buffer( ctx );
  264.       if (newMask & GL_ACCUM_BUFFER_BIT)    gl_clear_accum_buffer( ctx );
  265.       if (newMask & GL_STENCIL_BUFFER_BIT)  gl_clear_stencil_buffer( ctx );
  266.  
  267. #ifdef PROFILE
  268.       ctx->ClearTime += gl_time() - t0;
  269.       ctx->ClearCount++;
  270. #endif
  271.    }
  272. }
  273.  
  274.  
  275.  
  276. void gl_Finish( GLcontext *ctx )
  277. {
  278.    /* Don't compile into display list */
  279.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glFinish");
  280.    if (ctx->Driver.Finish) {
  281.       (*ctx->Driver.Finish)( ctx );
  282.    }
  283. }
  284.  
  285.  
  286.  
  287. void gl_Flush( GLcontext *ctx )
  288. {
  289.    /* Don't compile into display list */
  290.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glFlush");
  291.    if (ctx->Driver.Flush) {
  292.       (*ctx->Driver.Flush)( ctx );
  293.    }
  294. }
  295.  
  296.  
  297.  
  298. GLboolean gl_Hint( GLcontext *ctx, GLenum target, GLenum mode )
  299. {
  300.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glHint", GL_FALSE);
  301.  
  302.    if (MESA_VERBOSE & VERBOSE_API)
  303.       fprintf(stderr, "glHint %s %d\n", gl_lookup_enum_by_nr(target), mode);
  304.  
  305.    switch (target) {
  306.    case GL_FOG_HINT:
  307.       ctx->Hint.Fog = mode;
  308.       break;
  309.    case GL_LINE_SMOOTH_HINT:
  310.       ctx->Hint.LineSmooth = mode;
  311.       break;
  312.    case GL_PERSPECTIVE_CORRECTION_HINT:
  313.       ctx->Hint.PerspectiveCorrection = mode;
  314.       break;
  315.    case GL_POINT_SMOOTH_HINT:
  316.       ctx->Hint.PointSmooth = mode;
  317.       break;
  318.    case GL_POLYGON_SMOOTH_HINT:
  319.       ctx->Hint.PolygonSmooth = mode;
  320.       break;
  321.    case GL_PREFER_DOUBLEBUFFER_HINT_PGI:
  322.    case GL_STRICT_DEPTHFUNC_HINT_PGI:
  323.       break;
  324.    case GL_STRICT_LIGHTING_HINT_PGI:
  325.       ctx->Hint.StrictLighting = mode;
  326.       break;
  327.    case GL_STRICT_SCISSOR_HINT_PGI:
  328.    case GL_FULL_STIPPLE_HINT_PGI:
  329.    case GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI:
  330.    case GL_NATIVE_GRAPHICS_END_HINT_PGI:
  331.    case GL_CONSERVE_MEMORY_HINT_PGI:
  332.    case GL_RECLAIM_MEMORY_HINT_PGI:
  333.       break;
  334.    case GL_ALWAYS_FAST_HINT_PGI:
  335.       if (mode) {
  336.      ctx->Hint.AllowDrawWin = GL_TRUE;
  337.      ctx->Hint.AllowDrawSpn = GL_FALSE;
  338.      ctx->Hint.AllowDrawMem = GL_FALSE;
  339.       } else {
  340.      ctx->Hint.AllowDrawWin = GL_TRUE;
  341.      ctx->Hint.AllowDrawSpn = GL_TRUE;
  342.      ctx->Hint.AllowDrawMem = GL_TRUE;
  343.       } 
  344.       break;
  345.    case GL_ALWAYS_SOFT_HINT_PGI:
  346.       ctx->Hint.AllowDrawWin = GL_TRUE;
  347.       ctx->Hint.AllowDrawSpn = GL_TRUE;
  348.       ctx->Hint.AllowDrawMem = GL_TRUE;
  349.       break;
  350.    case GL_ALLOW_DRAW_OBJ_HINT_PGI:
  351.       break;
  352.    case GL_ALLOW_DRAW_WIN_HINT_PGI:
  353.       ctx->Hint.AllowDrawWin = mode;
  354.       break;
  355.    case GL_ALLOW_DRAW_SPN_HINT_PGI:
  356.       ctx->Hint.AllowDrawSpn = mode;
  357.       break;
  358.    case GL_ALLOW_DRAW_MEM_HINT_PGI:
  359.       ctx->Hint.AllowDrawMem = mode;
  360.       break;
  361.    case GL_CLIP_NEAR_HINT_PGI:
  362.    case GL_CLIP_FAR_HINT_PGI:
  363.    case GL_WIDE_LINE_HINT_PGI:
  364.    case GL_BACK_NORMALS_HINT_PGI:
  365.    case GL_NATIVE_GRAPHICS_HANDLE_PGI:
  366.       break;
  367.  
  368.       /* GL_EXT_clip_volume_hint */
  369.    case GL_CLIP_VOLUME_CLIPPING_HINT_EXT:
  370.       ctx->Hint.ClipVolumeClipping = mode;
  371.       break;
  372.  
  373.    default:
  374.       gl_error( ctx, GL_INVALID_ENUM, "glHint(target)" );
  375.       return GL_FALSE;
  376.    }
  377.    ctx->NewState |= NEW_ALL;   /* just to be safe */
  378.  
  379.    if (ctx->Driver.Hint) {
  380.       (*ctx->Driver.Hint)( ctx, target, mode );
  381.    }
  382.    
  383.    return GL_TRUE;
  384. }
  385.  
  386.    
  387.  
  388.  
  389. void gl_DrawBuffer( GLcontext *ctx, GLenum mode )
  390. {
  391.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawBuffer");
  392.  
  393.    if (MESA_VERBOSE & VERBOSE_API)
  394.       fprintf(stderr, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode));
  395.  
  396.    switch (mode) {
  397.       case GL_AUX0:
  398.       case GL_AUX1:
  399.       case GL_AUX2:
  400.       case GL_AUX3:
  401.          /* AUX buffers not implemented in Mesa at this time */
  402.          gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  403.          return;
  404.       case GL_RIGHT:
  405.          if (!ctx->Visual->StereoFlag) {
  406.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  407.             return;
  408.          }
  409.          if (ctx->Visual->DBflag)
  410.             ctx->Color.DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
  411.          else
  412.             ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
  413.          break;
  414.       case GL_FRONT_RIGHT:
  415.          if (!ctx->Visual->StereoFlag) {
  416.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  417.             return;
  418.          }
  419.          ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
  420.          break;
  421.       case GL_BACK_RIGHT:
  422.          if (!ctx->Visual->StereoFlag) {
  423.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  424.             return;
  425.          }
  426.          if (!ctx->Visual->DBflag) {
  427.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  428.             return;
  429.          }
  430.          ctx->Color.DrawDestMask = BACK_RIGHT_BIT;
  431.          break;
  432.       case GL_BACK_LEFT:
  433.          if (!ctx->Visual->DBflag) {
  434.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  435.             return;
  436.          }
  437.          ctx->Color.DrawDestMask = BACK_LEFT_BIT;
  438.          break;
  439.       case GL_FRONT_AND_BACK:
  440.          if (!ctx->Visual->DBflag) {
  441.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  442.             return;
  443.          }
  444.          if (ctx->Visual->StereoFlag)
  445.             ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT
  446.                                     | FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
  447.          else
  448.             ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
  449.          break;
  450.       case GL_BACK:
  451.          if (!ctx->Visual->DBflag) {
  452.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  453.             return;
  454.          }
  455.          if (ctx->Visual->StereoFlag)
  456.             ctx->Color.DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT;
  457.          else
  458.             ctx->Color.DrawDestMask = BACK_LEFT_BIT;
  459.          break;
  460.       case GL_LEFT:
  461.          /* never an error */
  462.          if (ctx->Visual->DBflag)
  463.             ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
  464.          else
  465.             ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
  466.          break;
  467.       case GL_FRONT_LEFT:
  468.          /* never an error */
  469.          ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
  470.          break;
  471.       case GL_FRONT:
  472.          /* never an error */
  473.          if (ctx->Visual->StereoFlag)
  474.             ctx->Color.DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT;
  475.          else
  476.             ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
  477.          break;
  478.       case GL_NONE:
  479.          /* never an error */
  480.          ctx->Color.DrawDestMask = 0;
  481.          break;
  482.       default:
  483.          gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
  484.          return;
  485.    }
  486.  
  487.    /*
  488.     * Make the dest buffer mode more precise if possible
  489.     */
  490.    if (mode == GL_LEFT && !ctx->Visual->DBflag)
  491.       ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
  492.    else if (mode == GL_RIGHT && !ctx->Visual->DBflag)
  493.       ctx->Color.DriverDrawBuffer = GL_FRONT_RIGHT;
  494.    else if (mode == GL_FRONT && !ctx->Visual->StereoFlag)
  495.       ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
  496.    else if (mode == GL_BACK && !ctx->Visual->StereoFlag)
  497.       ctx->Color.DriverDrawBuffer = GL_BACK_LEFT;
  498.    else
  499.       ctx->Color.DriverDrawBuffer = mode;
  500.  
  501.    /*
  502.     * Set current alpha buffer pointer
  503.     */
  504.    if (ctx->Visual->SoftwareAlpha) {
  505.       if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT)
  506.          ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
  507.       else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT)
  508.          ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
  509.       else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT)
  510.          ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
  511.       else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT)
  512.          ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
  513.    }
  514.  
  515.    /*
  516.     * If we get here there can't have been an error.
  517.     * Now see if device driver can implement the drawing to the target
  518.     * buffer(s).  The driver may not be able to do GL_FRONT_AND_BACK mode
  519.     * for example.  We'll take care of that in the core code by looping
  520.     * over the individual buffers.
  521.     */
  522.    ASSERT(ctx->Driver.SetBuffer);
  523.    if ( (*ctx->Driver.SetBuffer)(ctx, ctx->Color.DriverDrawBuffer) ) {
  524.       /* All OK, the driver will do all buffer writes */
  525.       ctx->Color.MultiDrawBuffer = GL_FALSE;
  526.    }
  527.    else {
  528.       /* We'll have to loop over the multiple draw buffer targets */
  529.       ctx->Color.MultiDrawBuffer = GL_TRUE;
  530.       /* Set drawing buffer to front for now */
  531.       (*ctx->Driver.SetBuffer)(ctx, GL_FRONT_LEFT);
  532.    }
  533.  
  534.    ctx->Color.DrawBuffer = mode;
  535.    ctx->NewState |= NEW_RASTER_OPS;
  536. }
  537.  
  538.  
  539.  
  540. void gl_ReadBuffer( GLcontext *ctx, GLenum mode )
  541. {
  542.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glReadBuffer");
  543.  
  544.    if (MESA_VERBOSE & VERBOSE_API)
  545.       fprintf(stderr, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode));
  546.  
  547.    switch (mode) {
  548.       case GL_AUX0:
  549.       case GL_AUX1:
  550.       case GL_AUX2:
  551.       case GL_AUX3:
  552.          /* AUX buffers not implemented in Mesa at this time */
  553.          gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  554.          return;
  555.       case GL_LEFT:
  556.       case GL_FRONT:
  557.       case GL_FRONT_LEFT:
  558.          /* Front-Left buffer, always exists */
  559.          ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
  560.          break;
  561.       case GL_BACK:
  562.       case GL_BACK_LEFT:
  563.          /* Back-Left buffer, requires double buffering */
  564.          if (!ctx->Visual->DBflag) {
  565.             gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  566.             return;
  567.          }
  568.          ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT;
  569.          break;
  570.       case GL_FRONT_RIGHT:
  571.       case GL_RIGHT:
  572.          if (!ctx->Visual->StereoFlag) {
  573.             gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  574.             return;
  575.          }
  576.          ctx->Pixel.DriverReadBuffer = GL_FRONT_RIGHT;
  577.          break;
  578.       case GL_BACK_RIGHT:
  579.          if (!ctx->Visual->StereoFlag || !ctx->Visual->DBflag) {
  580.             gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  581.             return;
  582.          }
  583.          ctx->Pixel.DriverReadBuffer = GL_BACK_RIGHT;
  584.          break;
  585.       default:
  586.          gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
  587.          return;
  588.    }
  589.  
  590.    ctx->Pixel.ReadBuffer = mode;
  591.    ctx->NewState |= NEW_RASTER_OPS;
  592. }
  593.