buffers.c revision cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290
1/* $Id: buffers.c,v 1.21 2000/12/26 05:09:27 keithw Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 6 * 7 * Copyright (C) 1999-2000 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 "glheader.h" 32#include "accum.h" 33#include "buffers.h" 34#include "context.h" 35#include "depth.h" 36#include "enums.h" 37#include "macros.h" 38#include "masking.h" 39#include "mem.h" 40#include "stencil.h" 41#include "state.h" 42#include "mtypes.h" 43#include "swrast/swrast.h" 44#endif 45 46 47 48void 49_mesa_ClearIndex( GLfloat c ) 50{ 51 GET_CURRENT_CONTEXT(ctx); 52 ASSERT_OUTSIDE_BEGIN_END(ctx); 53 54 if (ctx->Color.ClearIndex == (GLuint)c) 55 return; 56 57 58 FLUSH_VERTICES(ctx, _NEW_COLOR); 59 ctx->Color.ClearIndex = (GLuint) c; 60 61 if (!ctx->Visual.RGBAflag) { 62 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */ 63 (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex ); 64 } 65} 66 67 68 69void 70_mesa_ClearColor( GLclampf red, GLclampf green, 71 GLclampf blue, GLclampf alpha ) 72{ 73 GLfloat tmp[4]; 74 GET_CURRENT_CONTEXT(ctx); 75 ASSERT_OUTSIDE_BEGIN_END(ctx); 76 77 tmp[0] = CLAMP( red, 0.0, 1.0 ); 78 tmp[1] = CLAMP( green, 0.0, 1.0 ); 79 tmp[2] = CLAMP( blue, 0.0, 1.0 ); 80 tmp[3] = CLAMP( alpha, 0.0, 1.0 ); 81 82 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) 83 return; 84 85 FLUSH_VERTICES(ctx, _NEW_COLOR); 86 COPY_4FV( ctx->Color.ClearColor, tmp ); 87 88 if (ctx->Visual.RGBAflag) { 89 GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF); 90 GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF); 91 GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF); 92 GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF); 93 (*ctx->Driver.ClearColor)( ctx, r, g, b, a ); 94 } 95} 96 97 98 99 100 101 102void 103_mesa_Clear( GLbitfield mask ) 104{ 105 GET_CURRENT_CONTEXT(ctx); 106 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 107 108 if (MESA_VERBOSE & VERBOSE_API) 109 fprintf(stderr, "glClear 0x%x\n", mask); 110 111 if (ctx->NewState) { 112 gl_update_state( ctx ); /* update _Xmin, etc */ 113 } 114 115 if (ctx->RenderMode==GL_RENDER) { 116 const GLint x = ctx->DrawBuffer->_Xmin; 117 const GLint y = ctx->DrawBuffer->_Ymin; 118 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 119 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 120 GLbitfield ddMask; 121 GLbitfield newMask; 122 123 /* don't clear depth buffer if depth writing disabled */ 124 if (!ctx->Depth.Mask) 125 CLEAR_BITS(mask, GL_DEPTH_BUFFER_BIT); 126 127 /* Build bitmask to send to driver Clear function */ 128 ddMask = mask & (GL_DEPTH_BUFFER_BIT | 129 GL_STENCIL_BUFFER_BIT | 130 GL_ACCUM_BUFFER_BIT); 131 if (mask & GL_COLOR_BUFFER_BIT) { 132 ddMask |= ctx->Color.DrawDestMask; 133 } 134 135 ASSERT(ctx->Driver.Clear); 136 newMask = (*ctx->Driver.Clear)( ctx, ddMask, !ctx->Scissor.Enabled, 137 x, y, width, height ); 138 139#ifdef DEBUG 140 { 141 GLbitfield legalBits = DD_FRONT_LEFT_BIT | 142 DD_FRONT_RIGHT_BIT | 143 DD_BACK_LEFT_BIT | 144 DD_BACK_RIGHT_BIT | 145 DD_DEPTH_BIT | 146 DD_STENCIL_BIT | 147 DD_ACCUM_BIT; 148 assert((newMask & (~legalBits)) == 0); 149 } 150#endif 151 152 if (newMask) 153 _swrast_Clear( ctx, newMask, !ctx->Scissor.Enabled, 154 x, y, width, height ); 155 } 156} 157 158 159void 160_mesa_DrawBuffer( GLenum mode ) 161{ 162 GET_CURRENT_CONTEXT(ctx); 163 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ 164 165 166 if (MESA_VERBOSE & VERBOSE_API) 167 fprintf(stderr, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode)); 168 169 switch (mode) { 170 case GL_AUX0: 171 case GL_AUX1: 172 case GL_AUX2: 173 case GL_AUX3: 174 /* AUX buffers not implemented in Mesa at this time */ 175 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 176 return; 177 case GL_RIGHT: 178 if (!ctx->Visual.StereoFlag) { 179 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 180 return;} 181 if (ctx->Visual.DBflag) 182 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT; 183 else 184 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT; 185 break; 186 case GL_FRONT_RIGHT: 187 if (!ctx->Visual.StereoFlag) { 188 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 189 return; 190 } 191 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT; 192 break; 193 case GL_BACK_RIGHT: 194 if (!ctx->Visual.StereoFlag) { 195 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 196 return; 197 } 198 if (!ctx->Visual.DBflag) { 199 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 200 return; 201 } 202 ctx->Color.DrawDestMask = BACK_RIGHT_BIT; 203 break; 204 case GL_BACK_LEFT: 205 if (!ctx->Visual.DBflag) { 206 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 207 return; 208 } 209 ctx->Color.DrawDestMask = BACK_LEFT_BIT; 210 break; 211 case GL_FRONT_AND_BACK: 212 if (!ctx->Visual.DBflag) { 213 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 214 return; 215 } 216 if (ctx->Visual.StereoFlag) 217 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT 218 | FRONT_RIGHT_BIT | BACK_RIGHT_BIT; 219 else 220 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT; 221 break; 222 case GL_BACK: 223 if (!ctx->Visual.DBflag) { 224 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 225 return; 226 } 227 if (ctx->Visual.StereoFlag) 228 ctx->Color.DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT; 229 else 230 ctx->Color.DrawDestMask = BACK_LEFT_BIT; 231 break; 232 case GL_LEFT: 233 /* never an error */ 234 if (ctx->Visual.DBflag) 235 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT; 236 else 237 ctx->Color.DrawDestMask = FRONT_LEFT_BIT; 238 break; 239 case GL_FRONT_LEFT: 240 /* never an error */ 241 ctx->Color.DrawDestMask = FRONT_LEFT_BIT; 242 break; 243 case GL_FRONT: 244 /* never an error */ 245 if (ctx->Visual.StereoFlag) 246 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT; 247 else 248 ctx->Color.DrawDestMask = FRONT_LEFT_BIT; 249 break; 250 case GL_NONE: 251 /* never an error */ 252 ctx->Color.DrawDestMask = 0; 253 break; 254 default: 255 gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" ); 256 return; 257 } 258 259 /* 260 * Make the dest buffer mode more precise if possible 261 */ 262 if (mode == GL_LEFT && !ctx->Visual.DBflag) 263 ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT; 264 else if (mode == GL_RIGHT && !ctx->Visual.DBflag) 265 ctx->Color.DriverDrawBuffer = GL_FRONT_RIGHT; 266 else if (mode == GL_FRONT && !ctx->Visual.StereoFlag) 267 ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT; 268 else if (mode == GL_BACK && !ctx->Visual.StereoFlag) 269 ctx->Color.DriverDrawBuffer = GL_BACK_LEFT; 270 else 271 ctx->Color.DriverDrawBuffer = mode; 272 273 /* 274 * Set current alpha buffer pointer 275 */ 276 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) { 277 if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT) 278 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha; 279 else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT) 280 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha; 281 else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT) 282 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha; 283 else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT) 284 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha; 285 } 286 287 /* 288 * If we get here there can't have been an error. 289 * Now see if device driver can implement the drawing to the target 290 * buffer(s). The driver may not be able to do GL_FRONT_AND_BACK mode 291 * for example. We'll take care of that in the core code by looping 292 * over the individual buffers. 293 */ 294 ASSERT(ctx->Driver.SetDrawBuffer); 295 if ( (*ctx->Driver.SetDrawBuffer)(ctx, ctx->Color.DriverDrawBuffer) ) { 296 /* All OK, the driver will do all buffer writes */ 297 ctx->Color.MultiDrawBuffer = GL_FALSE; 298 } 299 else { 300 /* We'll have to loop over the multiple draw buffer targets */ 301 ctx->Color.MultiDrawBuffer = GL_TRUE; 302 /* Set drawing buffer to front for now */ 303 (void) (*ctx->Driver.SetDrawBuffer)(ctx, GL_FRONT_LEFT); 304 } 305 306 ctx->Color.DrawBuffer = mode; 307 ctx->NewState |= _NEW_COLOR; 308} 309 310 311 312void 313_mesa_ReadBuffer( GLenum mode ) 314{ 315 GET_CURRENT_CONTEXT(ctx); 316 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 317 318 if (MESA_VERBOSE & VERBOSE_API) 319 fprintf(stderr, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode)); 320 321 switch (mode) { 322 case GL_AUX0: 323 case GL_AUX1: 324 case GL_AUX2: 325 case GL_AUX3: 326 /* AUX buffers not implemented in Mesa at this time */ 327 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" ); 328 return; 329 case GL_LEFT: 330 case GL_FRONT: 331 case GL_FRONT_LEFT: 332 /* Front-Left buffer, always exists */ 333 ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT; 334 break; 335 case GL_BACK: 336 case GL_BACK_LEFT: 337 /* Back-Left buffer, requires double buffering */ 338 if (!ctx->Visual.DBflag) { 339 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" ); 340 return; 341 } 342 ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT; 343 break; 344 case GL_FRONT_RIGHT: 345 case GL_RIGHT: 346 if (!ctx->Visual.StereoFlag) { 347 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" ); 348 return; 349 } 350 ctx->Pixel.DriverReadBuffer = GL_FRONT_RIGHT; 351 break; 352 case GL_BACK_RIGHT: 353 if (!ctx->Visual.StereoFlag || !ctx->Visual.DBflag) { 354 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" ); 355 return; 356 } 357 ctx->Pixel.DriverReadBuffer = GL_BACK_RIGHT; 358 break; 359 default: 360 gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" ); 361 return; 362 } 363 364 ctx->Pixel.ReadBuffer = mode; 365 ctx->NewState |= _NEW_PIXEL; 366} 367 368 369/* 370 * GL_MESA_resize_buffers extension 371 */ 372void 373_mesa_ResizeBuffersMESA( void ) 374{ 375 GLcontext *ctx = _mesa_get_current_context(); 376 377 GLuint buf_width, buf_height; 378 379 if (MESA_VERBOSE & VERBOSE_API) 380 fprintf(stderr, "glResizeBuffersMESA\n"); 381 382 /* ask device driver for size of output buffer */ 383 (*ctx->Driver.GetBufferSize)( ctx, &buf_width, &buf_height ); 384 385 /* see if size of device driver's color buffer (window) has changed */ 386 if (ctx->DrawBuffer->Width == (GLint) buf_width && 387 ctx->DrawBuffer->Height == (GLint) buf_height) 388 return; 389 390 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 391 392 /* save buffer size */ 393 ctx->DrawBuffer->Width = buf_width; 394 ctx->DrawBuffer->Height = buf_height; 395 396 _swrast_alloc_buffers( ctx ); 397} 398