add FreeTexImageData hook to help single-copy texturing in drivers
[mesa.git] / src / mesa / main / buffers.c
1 /**
2 * \file buffers.c
3 * Frame buffer management.
4 */
5
6 /*
7 * Mesa 3-D graphics library
8 * Version: 6.3
9 *
10 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30
31 #include "glheader.h"
32 #include "imports.h"
33 #include "buffers.h"
34 #include "colormac.h"
35 #include "context.h"
36 #include "depth.h"
37 #include "enums.h"
38 #include "fbobject.h"
39 #include "stencil.h"
40 #include "state.h"
41 #include "mtypes.h"
42
43
44 #if _HAVE_FULL_GL
45 void GLAPIENTRY
46 _mesa_ClearIndex( GLfloat c )
47 {
48 GET_CURRENT_CONTEXT(ctx);
49 ASSERT_OUTSIDE_BEGIN_END(ctx);
50
51 if (ctx->Color.ClearIndex == (GLuint) c)
52 return;
53
54 FLUSH_VERTICES(ctx, _NEW_COLOR);
55 ctx->Color.ClearIndex = (GLuint) c;
56
57 if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) {
58 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
59 (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
60 }
61 }
62 #endif
63
64
65 /**
66 * Specify the clear values for the color buffers.
67 *
68 * \param red red color component.
69 * \param green green color component.
70 * \param blue blue color component.
71 * \param alpha alpha component.
72 *
73 * \sa glClearColor().
74 *
75 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a
76 * change, flushes the vertices and notifies the driver via the
77 * dd_function_table::ClearColor callback.
78 */
79 void GLAPIENTRY
80 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
81 {
82 GLfloat tmp[4];
83 GET_CURRENT_CONTEXT(ctx);
84 ASSERT_OUTSIDE_BEGIN_END(ctx);
85
86 tmp[0] = CLAMP(red, 0.0F, 1.0F);
87 tmp[1] = CLAMP(green, 0.0F, 1.0F);
88 tmp[2] = CLAMP(blue, 0.0F, 1.0F);
89 tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
90
91 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
92 return; /* no change */
93
94 FLUSH_VERTICES(ctx, _NEW_COLOR);
95 COPY_4V(ctx->Color.ClearColor, tmp);
96
97 if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) {
98 /* it's OK to call glClearColor in CI mode but it should be a NOP */
99 (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
100 }
101 }
102
103
104 /**
105 * Clear buffers.
106 *
107 * \param mask bit-mask indicating the buffers to be cleared.
108 *
109 * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState
110 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
111 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
112 * to clear the buffers, via the dd_function_table::Clear callback.
113 */
114 void GLAPIENTRY
115 _mesa_Clear( GLbitfield mask )
116 {
117 GET_CURRENT_CONTEXT(ctx);
118 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
119
120 if (MESA_VERBOSE & VERBOSE_API)
121 _mesa_debug(ctx, "glClear 0x%x\n", mask);
122
123 if (mask & ~(GL_COLOR_BUFFER_BIT |
124 GL_DEPTH_BUFFER_BIT |
125 GL_STENCIL_BUFFER_BIT |
126 GL_ACCUM_BUFFER_BIT)) {
127 /* invalid bit set */
128 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
129 return;
130 }
131
132 if (ctx->NewState) {
133 _mesa_update_state( ctx ); /* update _Xmin, etc */
134 }
135
136 if (ctx->RenderMode==GL_RENDER) {
137 const GLint x = ctx->DrawBuffer->_Xmin;
138 const GLint y = ctx->DrawBuffer->_Ymin;
139 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
140 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
141 GLbitfield ddMask;
142
143 /* don't clear depth buffer if depth writing disabled */
144 if (!ctx->Depth.Mask)
145 mask &= ~GL_DEPTH_BUFFER_BIT;
146
147 /* Build the bitmask to send to device driver's Clear function.
148 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
149 * of the FRONT/BACK_LEFT/RIGHT_BIT flags.
150 */
151 ddMask = 0;
152 if (mask & GL_COLOR_BUFFER_BIT)
153 ddMask |= ctx->Color._DrawDestMask[0];
154 if ((mask & GL_DEPTH_BUFFER_BIT) && ctx->Visual.depthBits > 0)
155 ddMask |= GL_DEPTH_BUFFER_BIT;
156 if ((mask & GL_STENCIL_BUFFER_BIT) && ctx->Visual.stencilBits > 0)
157 ddMask |= GL_STENCIL_BUFFER_BIT;
158 if ((mask & GL_ACCUM_BUFFER_BIT) && ctx->Visual.accumRedBits > 0)
159 ddMask |= GL_ACCUM_BUFFER_BIT;
160
161 ASSERT(ctx->Driver.Clear);
162 ctx->Driver.Clear( ctx, ddMask, (GLboolean) !ctx->Scissor.Enabled,
163 x, y, width, height );
164 }
165 }
166
167
168
169 /**
170 * Return bitmask of DD_* flags indicating which color buffers are
171 * available to the rendering context;
172 */
173 static GLuint
174 supported_buffer_bitmask(const GLcontext *ctx)
175 {
176 GLuint mask = DD_FRONT_LEFT_BIT; /* always have this */
177 GLint i;
178
179 if (ctx->Visual.stereoMode) {
180 mask |= DD_FRONT_RIGHT_BIT;
181 if (ctx->Visual.doubleBufferMode) {
182 mask |= DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT;
183 }
184 }
185 else if (ctx->Visual.doubleBufferMode) {
186 mask |= DD_BACK_LEFT_BIT;
187 }
188
189 for (i = 0; i < ctx->Visual.numAuxBuffers; i++) {
190 mask |= (DD_AUX0_BIT << i);
191 }
192
193 return mask;
194 }
195
196
197 /**
198 * Helper routine used by glDrawBuffer and glDrawBuffersARB.
199 * Given a GLenum naming (a) color buffer(s), return the corresponding
200 * bitmask of DD_* flags.
201 */
202 static GLuint
203 draw_buffer_enum_to_bitmask(GLenum buffer)
204 {
205 switch (buffer) {
206 case GL_FRONT:
207 return DD_FRONT_LEFT_BIT | DD_FRONT_RIGHT_BIT;
208 case GL_BACK:
209 return DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT;
210 case GL_NONE:
211 return 0;
212 case GL_RIGHT:
213 return DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT;
214 case GL_FRONT_RIGHT:
215 return DD_FRONT_RIGHT_BIT;
216 case GL_BACK_RIGHT:
217 return DD_BACK_RIGHT_BIT;
218 case GL_BACK_LEFT:
219 return DD_BACK_LEFT_BIT;
220 case GL_FRONT_AND_BACK:
221 return DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT
222 | DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT;
223 case GL_LEFT:
224 return DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT;
225 case GL_FRONT_LEFT:
226 return DD_FRONT_LEFT_BIT;
227 case GL_AUX0:
228 return DD_AUX0_BIT;
229 case GL_AUX1:
230 return DD_AUX1_BIT;
231 case GL_AUX2:
232 return DD_AUX2_BIT;
233 case GL_AUX3:
234 return DD_AUX3_BIT;
235 default:
236 /* error */
237 return ~0;
238 }
239 }
240
241
242 /**
243 * Helper routine used by glReadBuffer.
244 * Given a GLenum naming (a) color buffer(s), return the corresponding
245 * bitmask of DD_* flags.
246 */
247 static GLuint
248 read_buffer_enum_to_bitmask(GLenum buffer)
249 {
250 switch (buffer) {
251 case GL_FRONT:
252 return DD_FRONT_LEFT_BIT;
253 case GL_BACK:
254 return DD_BACK_LEFT_BIT;
255 case GL_RIGHT:
256 return DD_FRONT_RIGHT_BIT;
257 case GL_FRONT_RIGHT:
258 return DD_FRONT_RIGHT_BIT;
259 case GL_BACK_RIGHT:
260 return DD_BACK_RIGHT_BIT;
261 case GL_BACK_LEFT:
262 return DD_BACK_LEFT_BIT;
263 case GL_LEFT:
264 return DD_FRONT_LEFT_BIT;
265 case GL_FRONT_LEFT:
266 return DD_FRONT_LEFT_BIT;
267 case GL_AUX0:
268 return DD_AUX0_BIT;
269 case GL_AUX1:
270 return DD_AUX1_BIT;
271 case GL_AUX2:
272 return DD_AUX2_BIT;
273 case GL_AUX3:
274 return DD_AUX3_BIT;
275 default:
276 /* error */
277 return ~0;
278 }
279 }
280
281
282
283 /**
284 * Specify which color buffers to draw into.
285 *
286 * \param mode color buffer combination.
287 *
288 * \sa glDrawBuffer().
289 *
290 * Flushes the vertices and verifies the parameter and updates the
291 * gl_colorbuffer_attrib::_DrawDestMask bitfield. Marks new color state in
292 * __GLcontextRec::NewState and notifies the driver via the
293 * dd_function_table::DrawBuffer callback.
294 */
295 void GLAPIENTRY
296 _mesa_DrawBuffer( GLenum mode )
297 {
298 GET_CURRENT_CONTEXT(ctx);
299 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */
300
301 if (MESA_VERBOSE & VERBOSE_API)
302 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(mode));
303
304 if (ctx->Extensions.EXT_framebuffer_object && ctx->CurrentFramebuffer) {
305 /* Set drawbuffer for a framebuffer object */
306 if (mode == GL_NONE) {
307 ctx->CurrentFramebuffer->DrawBuffer[0] = mode;
308 }
309 else {
310 const GLint k = mode - GL_COLOR_ATTACHMENT0_EXT;
311 if (k >= 0 && k < ctx->Const.MaxColorAttachments) {
312 /* XXX check that the attachment point's Type != GL_NONE */
313 ctx->CurrentFramebuffer->DrawBuffer[0] = mode;
314 }
315 else {
316 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(mode)");
317 return;
318 }
319 }
320 }
321 else {
322 /* conventional behaviour */
323 /* Do error checking and compute the _DrawDestMask bitfield. */
324 GLenum destMask, supportedMask;
325
326 destMask = draw_buffer_enum_to_bitmask(mode);
327 if (destMask == ~0u) {
328 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(mode)");
329 return;
330 }
331
332 supportedMask = supported_buffer_bitmask(ctx);
333 destMask &= supportedMask;
334
335 if (destMask == 0) {
336 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(mode)");
337 return;
338 }
339
340 ctx->Color.DrawBuffer[0] = mode;
341 ctx->Color._DrawDestMask[0] = destMask;
342 ctx->NewState |= _NEW_COLOR;
343 }
344
345 /*
346 * Call device driver function.
347 */
348 if (ctx->Driver.DrawBuffer)
349 (*ctx->Driver.DrawBuffer)(ctx, mode);
350 }
351
352
353 /**
354 * Called by glDrawBuffersARB; specifies the destination color buffers
355 * for N fragment program color outputs.
356 */
357 void GLAPIENTRY
358 _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers)
359 {
360 GET_CURRENT_CONTEXT(ctx);
361 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
362
363 if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
364 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)" );
365 return;
366 }
367
368 if (ctx->Extensions.EXT_framebuffer_object && ctx->CurrentFramebuffer) {
369 /* Set drawbuffers for a framebuffer object */
370 GLint i;
371 GLuint usedAttachments = 0x0;
372 for (i = 0; i < n; i++) {
373 if (buffers[i] == GL_NONE) {
374 /* OK */
375 ctx->CurrentFramebuffer->DrawBuffer[i] = GL_NONE;
376 }
377 else {
378 const GLint k = buffers[i] - GL_COLOR_ATTACHMENT0_EXT;
379 if (k >= 0 && k < ctx->Const.MaxColorAttachments) {
380 /* XXX check that the attachment point's Type != GL_NONE */
381 if ((1 << k) & usedAttachments) {
382 _mesa_error(ctx, GL_INVALID_OPERATION,
383 "glDrawBuffersARB(duplicated attachment)");
384 return;
385 }
386 usedAttachments |= (1 << k);
387 ctx->CurrentFramebuffer->DrawBuffer[i] = buffers[i];
388 }
389 else {
390 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(mode)");
391 return;
392 }
393 }
394 }
395
396 /* set remaining color outputs to NONE */
397 for (i = n; i < ctx->Const.MaxDrawBuffers; i++) {
398 ctx->CurrentFramebuffer->DrawBuffer[i] = GL_NONE;
399 }
400 }
401 else {
402 /* Conventional operation */
403 GLint i;
404 GLuint usedBufferMask, supportedMask;
405
406 supportedMask = supported_buffer_bitmask(ctx);
407 usedBufferMask = 0;
408 for (i = 0; i < n; i++) {
409 GLuint destMask = draw_buffer_enum_to_bitmask(buffers[i]);
410 if (destMask == ~0u ) {
411 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
412 return;
413 }
414 destMask &= supportedMask;
415 if (destMask == 0) {
416 _mesa_error(ctx, GL_INVALID_OPERATION,
417 "glDrawBuffersARB(unsupported buffer)");
418 return;
419 }
420 if (destMask & usedBufferMask) {
421 /* can't specify a dest buffer more than once! */
422 _mesa_error(ctx, GL_INVALID_OPERATION,
423 "glDrawBuffersARB(duplicated buffer)");
424 return;
425 }
426 /* update bitmask */
427 usedBufferMask |= destMask;
428 /* save state */
429 ctx->Color.DrawBuffer[i] = buffers[i];
430 ctx->Color._DrawDestMask[i] = destMask;
431 }
432
433 /* set remaining color outputs to NONE */
434 for (i = n; i < ctx->Const.MaxDrawBuffers; i++) {
435 ctx->Color.DrawBuffer[i] = GL_NONE;
436 ctx->Color._DrawDestMask[i] = 0;
437 }
438
439 ctx->NewState |= _NEW_COLOR;
440 }
441
442 /*
443 * Call device driver function.
444 */
445 if (ctx->Driver.DrawBuffers)
446 (*ctx->Driver.DrawBuffers)(ctx, n, buffers);
447 }
448
449
450 /**
451 * Set the color buffer source for reading pixels.
452 *
453 * \param mode color buffer.
454 *
455 * \sa glReadBuffer().
456 *
457 * Verifies the parameter and updates gl_pixel_attrib::_ReadSrcMask. Marks
458 * new pixel state in __GLcontextRec::NewState and notifies the driver via
459 * dd_function_table::ReadBuffer.
460 */
461 void GLAPIENTRY
462 _mesa_ReadBuffer( GLenum mode )
463 {
464 GET_CURRENT_CONTEXT(ctx);
465 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
466
467 if (MESA_VERBOSE & VERBOSE_API)
468 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(mode));
469
470 if (ctx->Extensions.EXT_framebuffer_object && ctx->CurrentFramebuffer) {
471 /* Set readbuffer for a framebuffer object */
472 if (mode == GL_NONE) {
473 ctx->CurrentFramebuffer->ReadBuffer = mode;
474 }
475 else {
476 const GLint k = mode - GL_COLOR_ATTACHMENT0_EXT;
477 if (k >= 0 && k < ctx->Const.MaxColorAttachments) {
478 /* XXX check that the attachment point's Type != GL_NONE */
479 ctx->CurrentFramebuffer->ReadBuffer = mode;
480 }
481 else {
482 _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(mode)");
483 return;
484 }
485 }
486 }
487 else {
488 /* conventional operation */
489 GLuint srcMask, supportedMask;
490
491 srcMask = read_buffer_enum_to_bitmask(mode);
492 if (srcMask == ~0u) {
493 _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(mode)");
494 return;
495 }
496 supportedMask = supported_buffer_bitmask(ctx);
497 if ((srcMask & supportedMask) == 0) {
498 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(mode)");
499 return;
500 }
501 ctx->Pixel._ReadSrcMask = srcMask;
502 ctx->Pixel.ReadBuffer = mode;
503 ctx->NewState |= _NEW_PIXEL;
504 }
505
506 /*
507 * Call device driver function.
508 */
509 if (ctx->Driver.ReadBuffer)
510 (*ctx->Driver.ReadBuffer)(ctx, mode);
511 }
512
513
514 #if _HAVE_FULL_GL
515
516 /**
517 * GL_MESA_resize_buffers extension.
518 *
519 * When this function is called, we'll ask the window system how large
520 * the current window is. If it's a new size, we'll call the driver's
521 * ResizeBuffers function. The driver will then resize its color buffers
522 * as needed, and maybe call the swrast's routine for reallocating
523 * swrast-managed depth/stencil/accum/etc buffers.
524 * \note This function may be called from within Mesa or called by the
525 * user directly (see the GL_MESA_resize_buffers extension).
526 */
527 void GLAPIENTRY
528 _mesa_ResizeBuffersMESA( void )
529 {
530 GET_CURRENT_CONTEXT(ctx);
531
532 if (MESA_VERBOSE & VERBOSE_API)
533 _mesa_debug(ctx, "glResizeBuffersMESA\n");
534
535 if (ctx) {
536 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
537
538 if (ctx->DrawBuffer) {
539 GLuint buf_width, buf_height;
540 GLframebuffer *buffer = ctx->DrawBuffer;
541
542 /* ask device driver for size of output buffer */
543 (*ctx->Driver.GetBufferSize)( buffer, &buf_width, &buf_height );
544
545 /* see if size of device driver's color buffer (window) has changed */
546 if (buffer->Width == buf_width && buffer->Height == buf_height)
547 return; /* size is as expected */
548
549 buffer->Width = buf_width;
550 buffer->Height = buf_height;
551
552 ctx->Driver.ResizeBuffers( buffer );
553 }
554
555 if (ctx->ReadBuffer && ctx->ReadBuffer != ctx->DrawBuffer) {
556 GLuint buf_width, buf_height;
557 GLframebuffer *buffer = ctx->ReadBuffer;
558
559 /* ask device driver for size of read buffer */
560 (*ctx->Driver.GetBufferSize)( buffer, &buf_width, &buf_height );
561
562 /* see if size of device driver's color buffer (window) has changed */
563 if (buffer->Width == buf_width && buffer->Height == buf_height)
564 return; /* size is as expected */
565
566 buffer->Width = buf_width;
567 buffer->Height = buf_height;
568
569 ctx->Driver.ResizeBuffers( buffer );
570 }
571
572 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
573 }
574 }
575
576
577 /*
578 * XXX move somewhere else someday?
579 */
580 void GLAPIENTRY
581 _mesa_SampleCoverageARB(GLclampf value, GLboolean invert)
582 {
583 GET_CURRENT_CONTEXT(ctx);
584
585 if (!ctx->Extensions.ARB_multisample) {
586 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB");
587 return;
588 }
589
590 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
591 ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
592 ctx->Multisample.SampleCoverageInvert = invert;
593 ctx->NewState |= _NEW_MULTISAMPLE;
594 }
595
596 #endif
597
598
599 /**
600 * Define the scissor box.
601 *
602 * \param x, y coordinates of the scissor box lower-left corner.
603 * \param width width of the scissor box.
604 * \param height height of the scissor box.
605 *
606 * \sa glScissor().
607 *
608 * Verifies the parameters and updates __GLcontextRec::Scissor. On a
609 * change flushes the vertices and notifies the driver via
610 * the dd_function_table::Scissor callback.
611 */
612 void GLAPIENTRY
613 _mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
614 {
615 GET_CURRENT_CONTEXT(ctx);
616 ASSERT_OUTSIDE_BEGIN_END(ctx);
617
618 if (width < 0 || height < 0) {
619 _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
620 return;
621 }
622
623 if (MESA_VERBOSE & VERBOSE_API)
624 _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
625
626 if (x == ctx->Scissor.X &&
627 y == ctx->Scissor.Y &&
628 width == ctx->Scissor.Width &&
629 height == ctx->Scissor.Height)
630 return;
631
632 FLUSH_VERTICES(ctx, _NEW_SCISSOR);
633 ctx->Scissor.X = x;
634 ctx->Scissor.Y = y;
635 ctx->Scissor.Width = width;
636 ctx->Scissor.Height = height;
637
638 if (ctx->Driver.Scissor)
639 ctx->Driver.Scissor( ctx, x, y, width, height );
640 }
641
642
643
644 /**********************************************************************/
645 /** \name State management */
646 /*@{*/
647
648
649 /**
650 * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
651 * These values are computed from the buffer's width and height and
652 * the scissor box, if it's enabled.
653 * \param ctx the GL context.
654 */
655 void
656 _mesa_update_draw_buffer_bounds(GLcontext *ctx)
657 {
658 GLframebuffer *buffer = ctx->DrawBuffer;
659
660 buffer->_Xmin = 0;
661 buffer->_Ymin = 0;
662 buffer->_Xmax = buffer->Width;
663 buffer->_Ymax = buffer->Height;
664
665 if (ctx->Scissor.Enabled) {
666 if (ctx->Scissor.X > buffer->_Xmin) {
667 buffer->_Xmin = ctx->Scissor.X;
668 }
669 if (ctx->Scissor.Y > buffer->_Ymin) {
670 buffer->_Ymin = ctx->Scissor.Y;
671 }
672 if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {
673 buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;
674 }
675 if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {
676 buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;
677 }
678 /* finally, check for empty region */
679 if (buffer->_Xmin > buffer->_Xmax) {
680 buffer->_Xmin = buffer->_Xmax;
681 }
682 if (buffer->_Ymin > buffer->_Ymax) {
683 buffer->_Ymin = buffer->_Ymax;
684 }
685 }
686
687 ASSERT(buffer->_Xmin <= buffer->_Xmax);
688 ASSERT(buffer->_Ymin <= buffer->_Ymax);
689 }
690
691 /*@}*/
692
693
694 /**********************************************************************/
695 /** \name Initialization */
696 /*@{*/
697
698 /**
699 * Initialize the context's scissor state.
700 * \param ctx the GL context.
701 */
702 void
703 _mesa_init_scissor(GLcontext *ctx)
704 {
705 /* Scissor group */
706 ctx->Scissor.Enabled = GL_FALSE;
707 ctx->Scissor.X = 0;
708 ctx->Scissor.Y = 0;
709 ctx->Scissor.Width = 0;
710 ctx->Scissor.Height = 0;
711 }
712
713
714 /**
715 * Initialize the context's multisample state.
716 * \param ctx the GL context.
717 */
718 void
719 _mesa_init_multisample(GLcontext *ctx)
720 {
721 ctx->Multisample.Enabled = GL_FALSE;
722 ctx->Multisample.SampleAlphaToCoverage = GL_FALSE;
723 ctx->Multisample.SampleAlphaToOne = GL_FALSE;
724 ctx->Multisample.SampleCoverage = GL_FALSE;
725 ctx->Multisample.SampleCoverageValue = 1.0;
726 ctx->Multisample.SampleCoverageInvert = GL_FALSE;
727 }
728
729 /*@}*/