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

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