New triangle rasterization code. Store per-span initial/step values in the
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
1 /* $Id: osmesa.c,v 1.55 2001/05/14 16:23:04 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 /*
29 * Off-Screen Mesa rendering / Rendering into client memory space
30 *
31 * Note on thread safety: this driver is thread safe. All
32 * functions are reentrant. The notion of current context is
33 * managed by the core _mesa_make_current() and _mesa_get_current_context()
34 * functions. Those functions are thread-safe.
35 */
36
37
38 #include "glheader.h"
39 #include "GL/osmesa.h"
40 #include "context.h"
41 #include "colormac.h"
42 #include "depth.h"
43 #include "extensions.h"
44 #include "macros.h"
45 #include "matrix.h"
46 #include "mem.h"
47 #include "mmath.h"
48 #include "mtypes.h"
49 #include "texformat.h"
50 #include "texstore.h"
51 #include "array_cache/acache.h"
52 #include "swrast/swrast.h"
53 #include "swrast_setup/swrast_setup.h"
54 #include "swrast/s_context.h"
55 #include "swrast/s_depth.h"
56 #include "swrast/s_lines.h"
57 #include "swrast/s_triangle.h"
58 #include "swrast/s_trispan.h"
59 #include "tnl/tnl.h"
60 #include "tnl/t_context.h"
61 #include "tnl/t_pipeline.h"
62
63
64
65 /*
66 * This is the OS/Mesa context struct.
67 * Notice how it includes a GLcontext. By doing this we're mimicking
68 * C++ inheritance/derivation.
69 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
70 * or vice versa.
71 */
72 struct osmesa_context {
73 GLcontext gl_ctx; /* The core GL/Mesa context */
74 GLvisual *gl_visual; /* Describes the buffers */
75 GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
76 GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */
77 void *buffer; /* the image buffer */
78 GLint width, height; /* size of image buffer */
79 GLint rowlength; /* number of pixels per row */
80 GLint userRowLength; /* user-specified number of pixels per row */
81 GLint rshift, gshift; /* bit shifts for RGBA formats */
82 GLint bshift, ashift;
83 GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
84 GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */
85 GLboolean yup; /* TRUE -> Y increases upward */
86 /* FALSE -> Y increases downward */
87 };
88
89
90
91 /* A forward declaration: */
92 static void osmesa_update_state( GLcontext *ctx, GLuint newstate );
93 static void osmesa_register_swrast_functions( GLcontext *ctx );
94
95
96
97 #define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx))
98
99
100
101 /**********************************************************************/
102 /***** Public Functions *****/
103 /**********************************************************************/
104
105
106 /*
107 * Create an Off-Screen Mesa rendering context. The only attribute needed is
108 * an RGBA vs Color-Index mode flag.
109 *
110 * Input: format - either GL_RGBA or GL_COLOR_INDEX
111 * sharelist - specifies another OSMesaContext with which to share
112 * display lists. NULL indicates no sharing.
113 * Return: an OSMesaContext or 0 if error
114 */
115 OSMesaContext GLAPIENTRY
116 OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
117 {
118 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
119 8, 16, sharelist);
120 }
121
122
123
124 /*
125 * New in Mesa 3.5
126 *
127 * Create context and specify size of ancillary buffers.
128 */
129 OSMesaContext GLAPIENTRY
130 OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
131 GLint accumBits, OSMesaContext sharelist )
132 {
133 OSMesaContext osmesa;
134 GLint rshift, gshift, bshift, ashift;
135 GLint rind, gind, bind, aind;
136 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
137 GLboolean rgbmode;
138 GLboolean swalpha;
139 const GLuint i4 = 1;
140 const GLubyte *i1 = (GLubyte *) &i4;
141 const GLint little_endian = *i1;
142
143 swalpha = GL_FALSE;
144 rind = gind = bind = aind = 0;
145 if (format==OSMESA_COLOR_INDEX) {
146 indexBits = 8;
147 rshift = gshift = bshift = ashift = 0;
148 rgbmode = GL_FALSE;
149 }
150 else if (format==OSMESA_RGBA) {
151 indexBits = 0;
152 redBits = CHAN_BITS;
153 greenBits = CHAN_BITS;
154 blueBits = CHAN_BITS;
155 alphaBits = CHAN_BITS;
156 rind = 0;
157 gind = 1;
158 bind = 2;
159 aind = 3;
160 if (little_endian) {
161 rshift = 0;
162 gshift = 8;
163 bshift = 16;
164 ashift = 24;
165 }
166 else {
167 rshift = 24;
168 gshift = 16;
169 bshift = 8;
170 ashift = 0;
171 }
172 rgbmode = GL_TRUE;
173 }
174 else if (format==OSMESA_BGRA) {
175 indexBits = 0;
176 redBits = CHAN_BITS;
177 greenBits = CHAN_BITS;
178 blueBits = CHAN_BITS;
179 alphaBits = CHAN_BITS;
180 rind = 2;
181 gind = 1;
182 bind = 0;
183 aind = 3;
184 if (little_endian) {
185 ashift = 0;
186 rshift = 8;
187 gshift = 16;
188 bshift = 24;
189 }
190 else {
191 bshift = 24;
192 gshift = 16;
193 rshift = 8;
194 ashift = 0;
195 }
196 rgbmode = GL_TRUE;
197 }
198 else if (format==OSMESA_ARGB) {
199 indexBits = 0;
200 redBits = CHAN_BITS;
201 greenBits = CHAN_BITS;
202 blueBits = CHAN_BITS;
203 alphaBits = CHAN_BITS;
204 rind = 1;
205 gind = 2;
206 bind = 3;
207 aind = 0;
208 if (little_endian) {
209 bshift = 0;
210 gshift = 8;
211 rshift = 16;
212 ashift = 24;
213 }
214 else {
215 ashift = 24;
216 rshift = 16;
217 gshift = 8;
218 bshift = 0;
219 }
220 rgbmode = GL_TRUE;
221 }
222 else if (format==OSMESA_RGB) {
223 indexBits = 0;
224 redBits = CHAN_BITS;
225 greenBits = CHAN_BITS;
226 blueBits = CHAN_BITS;
227 alphaBits = 0;
228 bshift = 0;
229 gshift = 8;
230 rshift = 16;
231 ashift = 24;
232 rind = 0;
233 gind = 1;
234 bind = 2;
235 rgbmode = GL_TRUE;
236 swalpha = GL_TRUE;
237 }
238 else if (format==OSMESA_BGR) {
239 indexBits = 0;
240 redBits = CHAN_BITS;
241 greenBits = CHAN_BITS;
242 blueBits = CHAN_BITS;
243 alphaBits = 0;
244 bshift = 0;
245 gshift = 8;
246 rshift = 16;
247 ashift = 24;
248 rind = 2;
249 gind = 1;
250 bind = 0;
251 rgbmode = GL_TRUE;
252 swalpha = GL_TRUE;
253 }
254 else {
255 return NULL;
256 }
257
258
259 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
260 if (osmesa) {
261 osmesa->gl_visual = _mesa_create_visual( rgbmode,
262 GL_FALSE, /* double buffer */
263 GL_FALSE, /* stereo */
264 redBits,
265 greenBits,
266 blueBits,
267 alphaBits,
268 indexBits,
269 depthBits,
270 stencilBits,
271 accumBits,
272 accumBits,
273 accumBits,
274 alphaBits ? accumBits : 0,
275 1 /* num samples */
276 );
277 if (!osmesa->gl_visual) {
278 FREE(osmesa);
279 return NULL;
280 }
281
282 if (!_mesa_initialize_context(&osmesa->gl_ctx,
283 osmesa->gl_visual,
284 sharelist ? &sharelist->gl_ctx
285 : (GLcontext *) NULL,
286 (void *) osmesa, GL_TRUE )) {
287 _mesa_destroy_visual( osmesa->gl_visual );
288 FREE(osmesa);
289 return NULL;
290 }
291
292 _mesa_enable_sw_extensions(&(osmesa->gl_ctx));
293
294 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
295 osmesa->gl_visual->depthBits > 0,
296 osmesa->gl_visual->stencilBits > 0,
297 osmesa->gl_visual->accumRedBits > 0,
298 osmesa->gl_visual->alphaBits > 0 );
299
300 if (!osmesa->gl_buffer) {
301 _mesa_destroy_visual( osmesa->gl_visual );
302 _mesa_free_context_data( &osmesa->gl_ctx );
303 FREE(osmesa);
304 return NULL;
305 }
306 osmesa->format = format;
307 osmesa->buffer = NULL;
308 osmesa->width = 0;
309 osmesa->height = 0;
310 osmesa->userRowLength = 0;
311 osmesa->rowlength = 0;
312 osmesa->yup = GL_TRUE;
313 osmesa->rshift = rshift;
314 osmesa->gshift = gshift;
315 osmesa->bshift = bshift;
316 osmesa->ashift = ashift;
317 osmesa->rInd = rind;
318 osmesa->gInd = gind;
319 osmesa->bInd = bind;
320 osmesa->aInd = aind;
321
322
323 /* Initialize the software rasterizer and helper modules.
324 */
325 {
326 GLcontext *ctx = &osmesa->gl_ctx;
327
328 _swrast_CreateContext( ctx );
329 _ac_CreateContext( ctx );
330 _tnl_CreateContext( ctx );
331 _swsetup_CreateContext( ctx );
332
333 osmesa_register_swrast_functions( ctx );
334 }
335 }
336 return osmesa;
337 }
338
339
340
341
342 /*
343 * Destroy an Off-Screen Mesa rendering context.
344 *
345 * Input: ctx - the context to destroy
346 */
347 void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx )
348 {
349 if (ctx) {
350 _swsetup_DestroyContext( &ctx->gl_ctx );
351 _tnl_DestroyContext( &ctx->gl_ctx );
352 _ac_DestroyContext( &ctx->gl_ctx );
353 _swrast_DestroyContext( &ctx->gl_ctx );
354
355 _mesa_destroy_visual( ctx->gl_visual );
356 _mesa_destroy_framebuffer( ctx->gl_buffer );
357 _mesa_free_context_data( &ctx->gl_ctx );
358 FREE( ctx );
359 }
360 }
361
362
363
364 /*
365 * Recompute the values of the context's rowaddr array.
366 */
367 static void compute_row_addresses( OSMesaContext ctx )
368 {
369 GLint bytesPerPixel, bytesPerRow, i;
370 GLubyte *origin = (GLubyte *) ctx->buffer;
371
372 if (ctx->format == OSMESA_COLOR_INDEX) {
373 /* CI mode */
374 bytesPerPixel = 1 * sizeof(GLchan);
375 }
376 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
377 /* RGB mode */
378 bytesPerPixel = 3 * sizeof(GLchan);
379 }
380 else {
381 /* RGBA mode */
382 bytesPerPixel = 4 * sizeof(GLchan);
383 }
384
385 bytesPerRow = ctx->rowlength * bytesPerPixel;
386
387 if (ctx->yup) {
388 /* Y=0 is bottom line of window */
389 for (i = 0; i < MAX_HEIGHT; i++) {
390 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
391 }
392 }
393 else {
394 /* Y=0 is top line of window */
395 for (i = 0; i < MAX_HEIGHT; i++) {
396 GLint j = ctx->height - i - 1;
397 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
398 }
399 }
400 }
401
402
403 /*
404 * Bind an OSMesaContext to an image buffer. The image buffer is just a
405 * block of memory which the client provides. Its size must be at least
406 * as large as width*height*sizeof(type). Its address should be a multiple
407 * of 4 if using RGBA mode.
408 *
409 * Image data is stored in the order of glDrawPixels: row-major order
410 * with the lower-left image pixel stored in the first array position
411 * (ie. bottom-to-top).
412 *
413 * Since the only type initially supported is GL_UNSIGNED_BYTE, if the
414 * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA
415 * value. If the context is in color indexed mode, each pixel will be
416 * stored as a 1-byte value.
417 *
418 * If the context's viewport hasn't been initialized yet, it will now be
419 * initialized to (0,0,width,height).
420 *
421 * Input: ctx - the rendering context
422 * buffer - the image buffer memory
423 * type - data type for pixel components, only GL_UNSIGNED_BYTE
424 * supported now
425 * width, height - size of image buffer in pixels, at least 1
426 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
427 * invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1,
428 * width>internal limit or height>internal limit.
429 */
430 GLboolean GLAPIENTRY
431 OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
432 GLsizei width, GLsizei height )
433 {
434 if (!ctx || !buffer || type != CHAN_TYPE ||
435 width < 1 || height < 1 ||
436 width > MAX_WIDTH || height > MAX_HEIGHT) {
437 return GL_FALSE;
438 }
439
440 osmesa_update_state( &ctx->gl_ctx, 0 );
441 _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer );
442
443 ctx->buffer = buffer;
444 ctx->width = width;
445 ctx->height = height;
446 if (ctx->userRowLength)
447 ctx->rowlength = ctx->userRowLength;
448 else
449 ctx->rowlength = width;
450
451 compute_row_addresses( ctx );
452
453 /* init viewport */
454 if (ctx->gl_ctx.Viewport.Width==0) {
455 /* initialize viewport and scissor box to buffer size */
456 _mesa_Viewport( 0, 0, width, height );
457 ctx->gl_ctx.Scissor.Width = width;
458 ctx->gl_ctx.Scissor.Height = height;
459 }
460
461 return GL_TRUE;
462 }
463
464
465
466 OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
467 {
468 GLcontext *ctx = _mesa_get_current_context();
469 if (ctx)
470 return (OSMesaContext) ctx;
471 else
472 return NULL;
473 }
474
475
476
477 void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
478 {
479 OSMesaContext ctx = OSMesaGetCurrentContext();
480
481 switch (pname) {
482 case OSMESA_ROW_LENGTH:
483 if (value<0) {
484 _mesa_error( &ctx->gl_ctx, GL_INVALID_VALUE,
485 "OSMesaPixelStore(value)" );
486 return;
487 }
488 ctx->userRowLength = value;
489 ctx->rowlength = value;
490 break;
491 case OSMESA_Y_UP:
492 ctx->yup = value ? GL_TRUE : GL_FALSE;
493 break;
494 default:
495 _mesa_error( &ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
496 return;
497 }
498
499 compute_row_addresses( ctx );
500 }
501
502
503 void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
504 {
505 OSMesaContext ctx = OSMesaGetCurrentContext();
506
507 switch (pname) {
508 case OSMESA_WIDTH:
509 *value = ctx->width;
510 return;
511 case OSMESA_HEIGHT:
512 *value = ctx->height;
513 return;
514 case OSMESA_FORMAT:
515 *value = ctx->format;
516 return;
517 case OSMESA_TYPE:
518 *value = CHAN_TYPE;
519 return;
520 case OSMESA_ROW_LENGTH:
521 *value = ctx->rowlength;
522 return;
523 case OSMESA_Y_UP:
524 *value = ctx->yup;
525 return;
526 default:
527 _mesa_error(&ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
528 return;
529 }
530 }
531
532 /*
533 * Return the depth buffer associated with an OSMesa context.
534 * Input: c - the OSMesa context
535 * Output: width, height - size of buffer in pixels
536 * bytesPerValue - bytes per depth value (2 or 4)
537 * buffer - pointer to depth buffer values
538 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
539 */
540 GLboolean GLAPIENTRY
541 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
542 GLint *bytesPerValue, void **buffer )
543 {
544 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
545 *width = 0;
546 *height = 0;
547 *bytesPerValue = 0;
548 *buffer = 0;
549 return GL_FALSE;
550 }
551 else {
552 *width = c->gl_buffer->Width;
553 *height = c->gl_buffer->Height;
554 if (c->gl_visual->depthBits <= 16)
555 *bytesPerValue = sizeof(GLushort);
556 else
557 *bytesPerValue = sizeof(GLuint);
558 *buffer = c->gl_buffer->DepthBuffer;
559 return GL_TRUE;
560 }
561 }
562
563 /*
564 * Return the color buffer associated with an OSMesa context.
565 * Input: c - the OSMesa context
566 * Output: width, height - size of buffer in pixels
567 * format - the pixel format (OSMESA_FORMAT)
568 * buffer - pointer to color buffer values
569 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
570 */
571 GLboolean GLAPIENTRY
572 OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
573 GLint *height, GLint *format, void **buffer )
574 {
575 if (!c->buffer) {
576 *width = 0;
577 *height = 0;
578 *format = 0;
579 *buffer = 0;
580 return GL_FALSE;
581 }
582 else {
583 *width = c->width;
584 *height = c->height;
585 *format = c->format;
586 *buffer = c->buffer;
587 return GL_TRUE;
588 }
589 }
590
591 /**********************************************************************/
592 /*** Device Driver Functions ***/
593 /**********************************************************************/
594
595
596 /*
597 * Useful macros:
598 */
599
600 #define PACK_RGBA(DST, R, G, B, A) \
601 do { \
602 (DST)[osmesa->rInd] = R; \
603 (DST)[osmesa->gInd] = G; \
604 (DST)[osmesa->bInd] = B; \
605 (DST)[osmesa->aInd] = A; \
606 } while (0)
607
608 #define PACK_RGB(DST, R, G, B) \
609 do { \
610 (DST)[0] = R; \
611 (DST)[1] = G; \
612 (DST)[2] = B; \
613 } while (0)
614
615 #define PACK_BGR(DST, R, G, B) \
616 do { \
617 (DST)[0] = B; \
618 (DST)[1] = G; \
619 (DST)[2] = R; \
620 } while (0)
621
622
623 #define UNPACK_RED(P) ( (P)[osmesa->rInd] )
624 #define UNPACK_GREEN(P) ( (P)[osmesa->gInd] )
625 #define UNPACK_BLUE(P) ( (P)[osmesa->bInd] )
626 #define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] )
627
628
629 #define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X))
630 #define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X))
631 #define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X))
632
633
634
635 static GLboolean set_draw_buffer( GLcontext *ctx, GLenum mode )
636 {
637 (void) ctx;
638 if (mode==GL_FRONT_LEFT) {
639 return GL_TRUE;
640 }
641 else {
642 return GL_FALSE;
643 }
644 }
645
646
647 static void set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
648 {
649 /* separate read buffer not supported */
650 ASSERT(buffer == ctx->DrawBuffer);
651 ASSERT(mode == GL_FRONT_LEFT);
652 }
653
654
655 static void clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
656 GLint x, GLint y, GLint width, GLint height )
657 {
658 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
659 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
660
661 /* sanity check - we only have a front-left buffer */
662 ASSERT((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT)) == 0);
663 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
664 if (mask & DD_FRONT_LEFT_BIT) {
665 if (osmesa->format == OSMESA_COLOR_INDEX) {
666 if (all) {
667 /* Clear whole CI buffer */
668 #if CHAN_TYPE == GL_UNSIGNED_BYTE
669 MEMSET(osmesa->buffer, ctx->Color.ClearIndex,
670 osmesa->rowlength * osmesa->height);
671 #else
672 const GLint n = osmesa->rowlength * osmesa->height;
673 GLchan *buffer = (GLchan *) osmesa->buffer;
674 GLint i;
675 for (i = 0; i < n; i ++) {
676 buffer[i] = ctx->Color.ClearIndex;
677 }
678 #endif
679 }
680 else {
681 /* Clear part of CI buffer */
682 const GLchan clearIndex = (GLchan) ctx->Color.ClearIndex;
683 GLint i, j;
684 for (i = 0; i < height; i++) {
685 GLchan *ptr1 = PIXELADDR1(x, (y + i));
686 for (j = 0; j < width; j++) {
687 *ptr1++ = clearIndex;
688 }
689 }
690 }
691 }
692 else if (osmesa->format == OSMESA_RGB) {
693 const GLchan r = ctx->Color.ClearColor[0];
694 const GLchan g = ctx->Color.ClearColor[1];
695 const GLchan b = ctx->Color.ClearColor[2];
696 if (all) {
697 /* Clear whole RGB buffer */
698 GLuint n = osmesa->rowlength * osmesa->height;
699 GLchan *ptr3 = (GLchan *) osmesa->buffer;
700 GLuint i;
701 for (i = 0; i < n; i++) {
702 PACK_RGB(ptr3, r, g, b);
703 ptr3 += 3;
704 }
705 }
706 else {
707 /* Clear part of RGB buffer */
708 GLint i, j;
709 for (i = 0; i < height; i++) {
710 GLchan *ptr3 = PIXELADDR3(x, (y + i));
711 for (j = 0; j < width; j++) {
712 PACK_RGB(ptr3, r, g, b);
713 ptr3 += 3;
714 }
715 }
716 }
717 }
718 else if (osmesa->format == OSMESA_BGR) {
719 const GLchan r = ctx->Color.ClearColor[0];
720 const GLchan g = ctx->Color.ClearColor[1];
721 const GLchan b = ctx->Color.ClearColor[2];
722 if (all) {
723 /* Clear whole RGB buffer */
724 const GLint n = osmesa->rowlength * osmesa->height;
725 GLchan *ptr3 = (GLchan *) osmesa->buffer;
726 GLint i;
727 for (i = 0; i < n; i++) {
728 PACK_BGR(ptr3, r, g, b);
729 ptr3 += 3;
730 }
731 }
732 else {
733 /* Clear part of RGB buffer */
734 GLint i, j;
735 for (i = 0; i < height; i++) {
736 GLchan *ptr3 = PIXELADDR3(x, (y + i));
737 for (j = 0; j < width; j++) {
738 PACK_BGR(ptr3, r, g, b);
739 ptr3 += 3;
740 }
741 }
742 }
743 }
744 else {
745 #if CHAN_TYPE == GL_UNSIGNED_BYTE
746 /* 4-byte pixel value */
747 GLuint clearPixel;
748 GLchan *clr = (GLchan *) &clearPixel;
749 clr[osmesa->rInd] = ctx->Color.ClearColor[0];
750 clr[osmesa->gInd] = ctx->Color.ClearColor[1];
751 clr[osmesa->bInd] = ctx->Color.ClearColor[2];
752 clr[osmesa->aInd] = ctx->Color.ClearColor[3];
753 if (all) {
754 /* Clear whole RGBA buffer */
755 const GLuint n = osmesa->rowlength * osmesa->height;
756 GLuint *ptr4 = (GLuint *) osmesa->buffer;
757 GLuint i;
758 if (clearPixel) {
759 for (i = 0; i < n; i++) {
760 *ptr4++ = clearPixel;
761 }
762 }
763 else {
764 BZERO(ptr4, n * sizeof(GLuint));
765 }
766 }
767 else {
768 /* Clear part of RGBA buffer */
769 GLint i, j;
770 for (i = 0; i < height; i++) {
771 GLuint *ptr4 = (GLuint *) PIXELADDR4(x, (y + i));
772 for (j = 0; j < width; j++) {
773 *ptr4++ = clearPixel;
774 }
775 }
776 }
777 #else
778 const GLchan r = ctx->Color.ClearColor[0];
779 const GLchan g = ctx->Color.ClearColor[1];
780 const GLchan b = ctx->Color.ClearColor[2];
781 const GLchan a = ctx->Color.ClearColor[3];
782 if (all) {
783 /* Clear whole RGBA buffer */
784 const GLuint n = osmesa->rowlength * osmesa->height;
785 GLchan *p = (GLchan *) osmesa->buffer;
786 GLuint i;
787 for (i = 0; i < n; i++) {
788 PACK_RGBA(p, r, g, b, a);
789 p += 4;
790 }
791 }
792 else {
793 /* Clear part of RGBA buffer */
794 GLint i, j;
795 for (i = 0; i < height; i++) {
796 GLchan *p = PIXELADDR4(x, (y + i));
797 for (j = 0; j < width; j++) {
798 PACK_RGBA(p, r, g, b, a);
799 p += 4;
800 }
801 }
802 }
803
804 #endif
805 }
806 mask &= ~DD_FRONT_LEFT_BIT;
807 }
808 }
809
810 if (mask)
811 _swrast_Clear( ctx, mask, all, x, y, width, height );
812 }
813
814
815
816 static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
817 {
818 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
819 *width = osmesa->width;
820 *height = osmesa->height;
821 }
822
823
824 /**********************************************************************/
825 /***** Read/write spans/arrays of RGBA pixels *****/
826 /**********************************************************************/
827
828 /* Write RGBA pixels to an RGBA (or permuted) buffer. */
829 static void
830 write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
831 CONST GLchan rgba[][4], const GLubyte mask[] )
832 {
833 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
834 GLchan *p = PIXELADDR4(x, y);
835 GLuint i;
836 if (mask) {
837 for (i = 0; i < n; i++, p += 4) {
838 if (mask[i]) {
839 PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
840 rgba[i][BCOMP], rgba[i][ACOMP]);
841 }
842 }
843 }
844 else {
845 for (i = 0; i < n; i++, p += 4) {
846 PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
847 rgba[i][BCOMP], rgba[i][ACOMP]);
848 }
849 }
850 }
851
852
853 /* Write RGBA pixels to an RGBA buffer. This is the fastest span-writer. */
854 static void
855 write_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
856 CONST GLchan rgba[][4], const GLubyte mask[] )
857 {
858 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
859 GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
860 const GLuint *rgba4 = (const GLuint *) rgba;
861 GLuint i;
862 ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);
863 if (mask) {
864 for (i = 0; i < n; i++) {
865 if (mask[i]) {
866 ptr4[i] = rgba4[i];
867 }
868 }
869 }
870 else {
871 MEMCPY( ptr4, rgba4, n * 4 );
872 }
873 }
874
875
876 /* Write RGB pixels to an RGBA (or permuted) buffer. */
877 static void
878 write_rgb_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
879 CONST GLchan rgb[][3], const GLubyte mask[] )
880 {
881 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
882 GLchan *p = PIXELADDR4(x, y);
883 GLuint i;
884 if (mask) {
885 for (i = 0; i < n; i++, p+=4) {
886 if (mask[i]) {
887 PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
888 }
889 }
890 }
891 else {
892 for (i = 0; i < n; i++, p+=4) {
893 PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
894 }
895 }
896 }
897
898
899
900 static void
901 write_monocolor_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
902 const GLchan color[4], const GLubyte mask[] )
903 {
904 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
905 GLchan *p = PIXELADDR4(x, y);
906 GLuint i;
907 for (i = 0; i < n; i++, p += 4) {
908 if (mask[i]) {
909 PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
910 }
911 }
912 }
913
914
915
916 static void
917 write_rgba_pixels( const GLcontext *ctx, GLuint n,
918 const GLint x[], const GLint y[],
919 CONST GLchan rgba[][4], const GLubyte mask[] )
920 {
921 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
922 GLuint i;
923 for (i = 0; i < n; i++) {
924 if (mask[i]) {
925 GLchan *p = PIXELADDR4(x[i], y[i]);
926 PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
927 rgba[i][BCOMP], rgba[i][ACOMP]);
928 }
929 }
930 }
931
932
933
934 static void
935 write_monocolor_pixels( const GLcontext *ctx, GLuint n,
936 const GLint x[], const GLint y[],
937 const GLchan color[4], const GLubyte mask[] )
938 {
939 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
940 GLuint i;
941 for (i = 0; i < n; i++) {
942 if (mask[i]) {
943 GLchan *p = PIXELADDR4(x[i], y[i]);
944 PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
945 }
946 }
947 }
948
949
950 static void
951 read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
952 GLchan rgba[][4] )
953 {
954 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
955 GLuint i;
956 GLchan *p = PIXELADDR4(x, y);
957 for (i = 0; i < n; i++, p += 4) {
958 rgba[i][RCOMP] = UNPACK_RED(p);
959 rgba[i][GCOMP] = UNPACK_GREEN(p);
960 rgba[i][BCOMP] = UNPACK_BLUE(p);
961 rgba[i][ACOMP] = UNPACK_ALPHA(p);
962 }
963 }
964
965
966 /* Read RGBA pixels from an RGBA buffer */
967 static void
968 read_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
969 GLchan rgba[][4] )
970 {
971 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
972 GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
973 MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) );
974 }
975
976
977 static void
978 read_rgba_pixels( const GLcontext *ctx,
979 GLuint n, const GLint x[], const GLint y[],
980 GLchan rgba[][4], const GLubyte mask[] )
981 {
982 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
983 GLuint i;
984 for (i = 0; i < n; i++) {
985 if (mask[i]) {
986 const GLchan *p = PIXELADDR4(x[i], y[i]);
987 rgba[i][RCOMP] = UNPACK_RED(p);
988 rgba[i][GCOMP] = UNPACK_GREEN(p);
989 rgba[i][BCOMP] = UNPACK_BLUE(p);
990 rgba[i][ACOMP] = UNPACK_ALPHA(p);
991 }
992 }
993 }
994
995 /**********************************************************************/
996 /***** 3 byte RGB pixel support funcs *****/
997 /**********************************************************************/
998
999 /* Write RGBA pixels to an RGB buffer. */
1000 static void
1001 write_rgba_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1002 CONST GLchan rgba[][4], const GLubyte mask[] )
1003 {
1004 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1005 GLchan *p = PIXELADDR3(x, y);
1006 GLuint i;
1007 if (mask) {
1008 for (i = 0; i < n; i++, p += 3) {
1009 if (mask[i]) {
1010 PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1011 }
1012 }
1013 }
1014 else {
1015 for (i = 0; i < n; i++, p += 3) {
1016 PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1017 }
1018 }
1019 }
1020
1021 /* Write RGBA pixels to an BGR buffer. */
1022 static void
1023 write_rgba_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1024 CONST GLchan rgba[][4], const GLubyte mask[] )
1025 {
1026 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1027 GLchan *p = PIXELADDR3(x, y);
1028 GLuint i;
1029 if (mask) {
1030 for (i = 0; i < n; i++, p += 3) {
1031 if (mask[i]) {
1032 PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1033 }
1034 }
1035 }
1036 else {
1037 for (i = 0; i < n; i++, p += 3) {
1038 PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1039 }
1040 }
1041 }
1042
1043 /* Write RGB pixels to an RGB buffer. */
1044 static void
1045 write_rgb_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1046 CONST GLchan rgb[][3], const GLubyte mask[] )
1047 {
1048 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1049 GLchan *p = PIXELADDR3(x, y);
1050 GLuint i;
1051 if (mask) {
1052 for (i = 0; i < n; i++, p += 3) {
1053 if (mask[i]) {
1054 PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1055 }
1056 }
1057 }
1058 else {
1059 for (i = 0; i < n; i++, p += 3) {
1060 PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1061 }
1062 }
1063 }
1064
1065 /* Write RGB pixels to an BGR buffer. */
1066 static void
1067 write_rgb_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1068 CONST GLchan rgb[][3], const GLubyte mask[] )
1069 {
1070 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1071 GLchan *p = PIXELADDR3(x, y);
1072 GLuint i;
1073 if (mask) {
1074 for (i = 0; i < n; i++, p += 3) {
1075 if (mask[i]) {
1076 PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1077 }
1078 }
1079 }
1080 else {
1081 for (i = 0; i < n; i++, p += 3) {
1082 PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1083 }
1084 }
1085 }
1086
1087
1088 static void
1089 write_monocolor_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1090 const GLchan color[4], const GLubyte mask[] )
1091 {
1092 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1093 GLchan *p = PIXELADDR3(x, y);
1094 GLuint i;
1095 for (i = 0; i < n; i++, p += 3) {
1096 if (mask[i]) {
1097 PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1098 }
1099 }
1100 }
1101
1102 static void
1103 write_monocolor_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1104 const GLchan color[4], const GLubyte mask[] )
1105 {
1106 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1107 GLchan *p = PIXELADDR3(x, y);
1108 GLuint i;
1109 for (i = 0; i < n; i++, p += 3) {
1110 if (mask[i]) {
1111 PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1112 }
1113 }
1114 }
1115
1116 static void
1117 write_rgba_pixels_RGB( const GLcontext *ctx, GLuint n,
1118 const GLint x[], const GLint y[],
1119 CONST GLchan rgba[][4], const GLubyte mask[] )
1120 {
1121 const OSMesaContext osmesa = (const OSMesaContext) ctx;
1122 GLuint i;
1123 for (i = 0; i < n; i++) {
1124 if (mask[i]) {
1125 GLchan *p = PIXELADDR3(x[i], y[i]);
1126 PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1127 }
1128 }
1129 }
1130
1131 static void
1132 write_rgba_pixels_BGR( const GLcontext *ctx, GLuint n,
1133 const GLint x[], const GLint y[],
1134 CONST GLchan rgba[][4], const GLubyte mask[] )
1135 {
1136 const OSMesaContext osmesa = (const OSMesaContext) ctx;
1137 GLuint i;
1138 for (i = 0; i < n; i++) {
1139 if (mask[i]) {
1140 GLchan *p = PIXELADDR3(x[i], y[i]);
1141 PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1142 }
1143 }
1144 }
1145
1146 static void
1147 write_monocolor_pixels_RGB( const GLcontext *ctx,
1148 GLuint n, const GLint x[], const GLint y[],
1149 const GLchan color[4], const GLubyte mask[] )
1150 {
1151 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1152 GLuint i;
1153 for (i = 0; i < n; i++) {
1154 if (mask[i]) {
1155 GLchan *p = PIXELADDR3(x[i], y[i]);
1156 PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1157 }
1158 }
1159 }
1160
1161 static void
1162 write_monocolor_pixels_BGR( const GLcontext *ctx,
1163 GLuint n, const GLint x[], const GLint y[],
1164 const GLchan color[4], const GLubyte mask[] )
1165 {
1166 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1167 GLuint i;
1168 for (i = 0; i < n; i++) {
1169 if (mask[i]) {
1170 GLchan *p = PIXELADDR3(x[i], y[i]);
1171 PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1172 }
1173 }
1174 }
1175
1176 static void
1177 read_rgba_span3( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1178 GLchan rgba[][4] )
1179 {
1180 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1181 GLuint i;
1182 const GLchan *p = PIXELADDR3(x, y);
1183 for (i = 0; i < n; i++, p += 3) {
1184 rgba[i][RCOMP] = UNPACK_RED(p);
1185 rgba[i][GCOMP] = UNPACK_GREEN(p);
1186 rgba[i][BCOMP] = UNPACK_BLUE(p);
1187 rgba[i][ACOMP] = 255;
1188 }
1189 }
1190
1191 static void
1192 read_rgba_pixels3( const GLcontext *ctx,
1193 GLuint n, const GLint x[], const GLint y[],
1194 GLchan rgba[][4], const GLubyte mask[] )
1195 {
1196 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1197 GLuint i;
1198 for (i = 0; i < n; i++) {
1199 if (mask[i]) {
1200 const GLchan *p = PIXELADDR3(x[i], y[i]);
1201 rgba[i][RCOMP] = UNPACK_RED(p);
1202 rgba[i][GCOMP] = UNPACK_GREEN(p);
1203 rgba[i][BCOMP] = UNPACK_BLUE(p);
1204 rgba[i][ACOMP] = 255;
1205 }
1206 }
1207 }
1208
1209
1210 /**********************************************************************/
1211 /***** Read/write spans/arrays of CI pixels *****/
1212 /**********************************************************************/
1213
1214 /* Write 32-bit color index to buffer */
1215 static void
1216 write_index32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1217 const GLuint index[], const GLubyte mask[] )
1218 {
1219 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1220 GLchan *ptr1 = PIXELADDR1(x, y);
1221 GLuint i;
1222 if (mask) {
1223 for (i=0;i<n;i++,ptr1++) {
1224 if (mask[i]) {
1225 *ptr1 = (GLchan) index[i];
1226 }
1227 }
1228 }
1229 else {
1230 for (i=0;i<n;i++,ptr1++) {
1231 *ptr1 = (GLchan) index[i];
1232 }
1233 }
1234 }
1235
1236
1237 /* Write 8-bit color index to buffer */
1238 static void
1239 write_index8_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1240 const GLubyte index[], const GLubyte mask[] )
1241 {
1242 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1243 GLchan *ptr1 = PIXELADDR1(x, y);
1244 GLuint i;
1245 if (mask) {
1246 for (i=0;i<n;i++,ptr1++) {
1247 if (mask[i]) {
1248 *ptr1 = (GLchan) index[i];
1249 }
1250 }
1251 }
1252 else {
1253 MEMCPY(ptr1, index, n * sizeof(GLchan));
1254 }
1255 }
1256
1257
1258 static void
1259 write_monoindex_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1260 GLuint colorIndex, const GLubyte mask[] )
1261 {
1262 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1263 GLchan *ptr1 = PIXELADDR1(x, y);
1264 GLuint i;
1265 for (i=0;i<n;i++,ptr1++) {
1266 if (mask[i]) {
1267 *ptr1 = (GLchan) colorIndex;
1268 }
1269 }
1270 }
1271
1272
1273 static void
1274 write_index_pixels( const GLcontext *ctx,
1275 GLuint n, const GLint x[], const GLint y[],
1276 const GLuint index[], const GLubyte mask[] )
1277 {
1278 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1279 GLuint i;
1280 for (i=0;i<n;i++) {
1281 if (mask[i]) {
1282 GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1283 *ptr1 = (GLchan) index[i];
1284 }
1285 }
1286 }
1287
1288
1289 static void
1290 write_monoindex_pixels( const GLcontext *ctx,
1291 GLuint n, const GLint x[], const GLint y[],
1292 GLuint colorIndex, const GLubyte mask[] )
1293 {
1294 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1295 GLuint i;
1296 for (i=0;i<n;i++) {
1297 if (mask[i]) {
1298 GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1299 *ptr1 = (GLchan) colorIndex;
1300 }
1301 }
1302 }
1303
1304
1305 static void
1306 read_index_span( const GLcontext *ctx,
1307 GLuint n, GLint x, GLint y, GLuint index[] )
1308 {
1309 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1310 GLuint i;
1311 const GLchan *ptr1 = (const GLchan *) PIXELADDR1(x, y);
1312 for (i=0;i<n;i++,ptr1++) {
1313 index[i] = (GLuint) *ptr1;
1314 }
1315 }
1316
1317
1318 static void
1319 read_index_pixels( const GLcontext *ctx,
1320 GLuint n, const GLint x[], const GLint y[],
1321 GLuint index[], const GLubyte mask[] )
1322 {
1323 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1324 GLuint i;
1325 for (i=0;i<n;i++) {
1326 if (mask[i] ) {
1327 const GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1328 index[i] = (GLuint) *ptr1;
1329 }
1330 }
1331 }
1332
1333
1334
1335 /**********************************************************************/
1336 /***** Optimized line rendering *****/
1337 /**********************************************************************/
1338
1339
1340 /*
1341 * Draw a flat-shaded, RGB line into an osmesa buffer.
1342 */
1343 static void
1344 flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
1345 {
1346 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1347 const GLchan *color = vert0->color;
1348
1349 #define INTERP_XY 1
1350 #define CLIP_HACK 1
1351 #define PLOT(X, Y) \
1352 do { \
1353 GLchan *p = PIXELADDR4(X, Y); \
1354 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \
1355 } while (0)
1356
1357 #ifdef WIN32
1358 #include "..\swrast\s_linetemp.h"
1359 #else
1360 #include "swrast/s_linetemp.h"
1361 #endif
1362 }
1363
1364
1365 /*
1366 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
1367 */
1368 static void
1369 flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
1370 {
1371 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1372 const GLchan *color = vert0->color;
1373
1374 #define INTERP_XY 1
1375 #define INTERP_Z 1
1376 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1377 #define CLIP_HACK 1
1378 #define PLOT(X, Y) \
1379 do { \
1380 if (Z < *zPtr) { \
1381 GLchan *p = PIXELADDR4(X, Y); \
1382 PACK_RGBA(p, color[RCOMP], color[GCOMP], \
1383 color[BCOMP], color[ACOMP]); \
1384 *zPtr = Z; \
1385 } \
1386 } while (0)
1387
1388
1389 #ifdef WIN32
1390 #include "..\swrast\s_linetemp.h"
1391 #else
1392 #include "swrast/s_linetemp.h"
1393 #endif
1394 }
1395
1396
1397 /*
1398 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
1399 * XXX update for GLchan
1400 */
1401 static void
1402 flat_blend_rgba_line( GLcontext *ctx,
1403 const SWvertex *vert0, const SWvertex *vert1 )
1404 {
1405 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1406 const GLint rshift = osmesa->rshift;
1407 const GLint gshift = osmesa->gshift;
1408 const GLint bshift = osmesa->bshift;
1409 const GLint avalue = vert0->color[3];
1410 const GLint msavalue = 255 - avalue;
1411 const GLint rvalue = vert0->color[0]*avalue;
1412 const GLint gvalue = vert0->color[1]*avalue;
1413 const GLint bvalue = vert0->color[2]*avalue;
1414
1415 #define INTERP_XY 1
1416 #define CLIP_HACK 1
1417 #define PLOT(X,Y) \
1418 { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \
1419 GLuint pixel = 0; \
1420 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
1421 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
1422 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
1423 *ptr4 = pixel; \
1424 }
1425
1426 #ifdef WIN32
1427 #include "..\swrast\s_linetemp.h"
1428 #else
1429 #include "swrast/s_linetemp.h"
1430 #endif
1431 }
1432
1433
1434 /*
1435 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1436 * XXX update for GLchan
1437 */
1438 static void
1439 flat_blend_rgba_z_line( GLcontext *ctx,
1440 const SWvertex *vert0, const SWvertex *vert1 )
1441 {
1442 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1443 const GLint rshift = osmesa->rshift;
1444 const GLint gshift = osmesa->gshift;
1445 const GLint bshift = osmesa->bshift;
1446 const GLint avalue = vert0->color[3];
1447 const GLint msavalue = 256 - avalue;
1448 const GLint rvalue = vert0->color[0]*avalue;
1449 const GLint gvalue = vert0->color[1]*avalue;
1450 const GLint bvalue = vert0->color[2]*avalue;
1451
1452 #define INTERP_XY 1
1453 #define INTERP_Z 1
1454 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1455 #define CLIP_HACK 1
1456 #define PLOT(X,Y) \
1457 if (Z < *zPtr) { \
1458 GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \
1459 GLuint pixel = 0; \
1460 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \
1461 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \
1462 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \
1463 *ptr4 = pixel; \
1464 }
1465
1466 #ifdef WIN32
1467 #include "..\swrast\s_linetemp.h"
1468 #else
1469 #include "swrast/s_linetemp.h"
1470 #endif
1471 }
1472
1473
1474 /*
1475 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1476 * XXX update for GLchan
1477 */
1478 static void
1479 flat_blend_rgba_z_line_write( GLcontext *ctx,
1480 const SWvertex *vert0, const SWvertex *vert1 )
1481 {
1482 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1483 const GLint rshift = osmesa->rshift;
1484 const GLint gshift = osmesa->gshift;
1485 const GLint bshift = osmesa->bshift;
1486 const GLint avalue = vert0->color[3];
1487 const GLint msavalue = 256 - avalue;
1488 const GLint rvalue = vert0->color[0]*avalue;
1489 const GLint gvalue = vert0->color[1]*avalue;
1490 const GLint bvalue = vert0->color[2]*avalue;
1491
1492 #define INTERP_XY 1
1493 #define INTERP_Z 1
1494 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1495 #define CLIP_HACK 1
1496 #define PLOT(X,Y) \
1497 if (Z < *zPtr) { \
1498 GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \
1499 GLuint pixel = 0; \
1500 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \
1501 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \
1502 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \
1503 *ptr4 = pixel; \
1504 *zPtr = Z; \
1505 }
1506
1507 #ifdef WIN32
1508 #include "..\swrast\s_linetemp.h"
1509 #else
1510 #include "swrast/s_linetemp.h"
1511 #endif
1512 }
1513
1514
1515 /*
1516 * Analyze context state to see if we can provide a fast line drawing
1517 * function, like those in lines.c. Otherwise, return NULL.
1518 */
1519 static swrast_line_func
1520 osmesa_choose_line_function( GLcontext *ctx )
1521 {
1522 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1523 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1524
1525 if (CHAN_BITS != 8) return NULL;
1526 if (ctx->RenderMode != GL_RENDER) return NULL;
1527 if (ctx->Line.SmoothFlag) return NULL;
1528 if (ctx->Texture._ReallyEnabled) return NULL;
1529 if (ctx->Light.ShadeModel != GL_FLAT) return NULL;
1530 if (ctx->Line.Width != 1.0F) return NULL;
1531 if (ctx->Line.StippleFlag) return NULL;
1532 if (ctx->Line.SmoothFlag) return NULL;
1533 if (osmesa->format != OSMESA_RGBA &&
1534 osmesa->format != OSMESA_BGRA &&
1535 osmesa->format != OSMESA_ARGB) return NULL;
1536
1537 if (swrast->_RasterMask==DEPTH_BIT
1538 && ctx->Depth.Func==GL_LESS
1539 && ctx->Depth.Mask==GL_TRUE
1540 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1541 return flat_rgba_z_line;
1542 }
1543
1544 if (swrast->_RasterMask == 0) {
1545 return flat_rgba_line;
1546 }
1547
1548 if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1549 && ctx->Depth.Func==GL_LESS
1550 && ctx->Depth.Mask==GL_TRUE
1551 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1552 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1553 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1554 && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1555 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1556 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1557 return flat_blend_rgba_z_line_write;
1558 }
1559
1560 if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1561 && ctx->Depth.Func==GL_LESS
1562 && ctx->Depth.Mask==GL_FALSE
1563 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1564 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1565 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1566 && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1567 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1568 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1569 return flat_blend_rgba_z_line;
1570 }
1571
1572 if (swrast->_RasterMask==BLEND_BIT
1573 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1574 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1575 && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1576 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1577 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1578 return flat_blend_rgba_line;
1579 }
1580
1581 return NULL;
1582 }
1583
1584
1585 /**********************************************************************/
1586 /***** Optimized triangle rendering *****/
1587 /**********************************************************************/
1588
1589
1590 /*
1591 * Smooth-shaded, z-less triangle, RGBA color.
1592 */
1593 static void smooth_rgba_z_triangle( GLcontext *ctx,
1594 const SWvertex *v0,
1595 const SWvertex *v1,
1596 const SWvertex *v2 )
1597 {
1598 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1599
1600 #define INTERP_Z 1
1601 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1602 #define INTERP_RGB 1
1603 #define INTERP_ALPHA 1
1604 #define RENDER_SPAN( span ) \
1605 GLuint i; \
1606 GLchan *img = PIXELADDR4(span.x, span.y); \
1607 for (i = 0; i < span.count; i++, img += 4) { \
1608 const GLdepth z = FixedToDepth(span.z); \
1609 if (z < zRow[i]) { \
1610 PACK_RGBA(img, FixedToInt(span.red), \
1611 FixedToInt(span.green), FixedToInt(span.blue), \
1612 FixedToInt(span.alpha)); \
1613 zRow[i] = z; \
1614 } \
1615 span.red += span.redStep; \
1616 span.green += span.greenStep; \
1617 span.blue += span.blueStep; \
1618 span.alpha += span.alphaStep; \
1619 span.z += span.zStep; \
1620 }
1621
1622 #ifdef WIN32
1623 #include "..\swrast\s_tritemp.h"
1624 #else
1625 #include "swrast/s_tritemp.h"
1626 #endif
1627 }
1628
1629
1630
1631
1632 /*
1633 * Flat-shaded, z-less triangle, RGBA color.
1634 */
1635 static void flat_rgba_z_triangle( GLcontext *ctx,
1636 const SWvertex *v0,
1637 const SWvertex *v1,
1638 const SWvertex *v2 )
1639 {
1640 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1641 #define INTERP_Z 1
1642 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1643 #define SETUP_CODE \
1644 GLuint pixel; \
1645 PACK_RGBA((GLchan *) &pixel, v0->color[0], v0->color[1], \
1646 v0->color[2], v0->color[3]);
1647
1648 #define RENDER_SPAN( span ) \
1649 GLuint i; \
1650 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \
1651 for (i = 0; i < span.count; i++) { \
1652 const GLdepth z = FixedToDepth(span.z); \
1653 if (z < zRow[i]) { \
1654 img[i] = pixel; \
1655 zRow[i] = z; \
1656 } \
1657 span.z += span.zStep; \
1658 }
1659
1660 #ifdef WIN32
1661 #include "..\swrast\s_tritemp.h"
1662 #else
1663 #include "swrast/s_tritemp.h"
1664 #endif
1665 }
1666
1667
1668
1669 /*
1670 * Return pointer to an accelerated triangle function if possible.
1671 */
1672 static swrast_tri_func
1673 osmesa_choose_triangle_function( GLcontext *ctx )
1674 {
1675 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1676 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1677
1678 if (CHAN_BITS != 8) return (swrast_tri_func) NULL;
1679 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
1680 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
1681 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL;
1682 if (ctx->Texture._ReallyEnabled) return (swrast_tri_func) NULL;
1683 if (osmesa->format != OSMESA_RGBA &&
1684 osmesa->format != OSMESA_BGRA &&
1685 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL;
1686
1687 if (swrast->_RasterMask == DEPTH_BIT &&
1688 ctx->Depth.Func == GL_LESS &&
1689 ctx->Depth.Mask == GL_TRUE &&
1690 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1691 if (ctx->Light.ShadeModel == GL_SMOOTH) {
1692 return smooth_rgba_z_triangle;
1693 }
1694 else {
1695 return flat_rgba_z_triangle;
1696 }
1697 }
1698 return (swrast_tri_func) NULL;
1699 }
1700
1701
1702
1703 /* Override for the swrast triangle-selection function. Try to use one
1704 * of our internal triangle functions, otherwise fall back to the
1705 * standard swrast functions.
1706 */
1707 static void osmesa_choose_triangle( GLcontext *ctx )
1708 {
1709 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1710
1711 swrast->Triangle = osmesa_choose_triangle_function( ctx );
1712 if (!swrast->Triangle)
1713 _swrast_choose_triangle( ctx );
1714 }
1715
1716 static void osmesa_choose_line( GLcontext *ctx )
1717 {
1718 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1719
1720 swrast->Line = osmesa_choose_line_function( ctx );
1721 if (!swrast->Line)
1722 _swrast_choose_line( ctx );
1723 }
1724
1725
1726 #define OSMESA_NEW_LINE (_NEW_LINE | \
1727 _NEW_TEXTURE | \
1728 _NEW_LIGHT | \
1729 _NEW_DEPTH | \
1730 _NEW_RENDERMODE | \
1731 _SWRAST_NEW_RASTERMASK)
1732
1733 #define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1734 _NEW_TEXTURE | \
1735 _NEW_LIGHT | \
1736 _NEW_DEPTH | \
1737 _NEW_RENDERMODE | \
1738 _SWRAST_NEW_RASTERMASK)
1739
1740
1741 /* Extend the software rasterizer with our line and triangle
1742 * functions.
1743 */
1744 static void osmesa_register_swrast_functions( GLcontext *ctx )
1745 {
1746 SWcontext *swrast = SWRAST_CONTEXT( ctx );
1747
1748 swrast->choose_line = osmesa_choose_line;
1749 swrast->choose_triangle = osmesa_choose_triangle;
1750
1751 swrast->invalidate_line |= OSMESA_NEW_LINE;
1752 swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
1753 }
1754
1755
1756 static const GLubyte *get_string( GLcontext *ctx, GLenum name )
1757 {
1758 (void) ctx;
1759 switch (name) {
1760 case GL_RENDERER:
1761 return (const GLubyte *) "Mesa OffScreen";
1762 default:
1763 return NULL;
1764 }
1765 }
1766
1767
1768 static void osmesa_update_state( GLcontext *ctx, GLuint new_state )
1769 {
1770 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1771 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
1772 TNLcontext *tnl = TNL_CONTEXT(ctx);
1773
1774 ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
1775
1776 /*
1777 * XXX these function pointers could be initialized just once during
1778 * context creation since they don't depend on any state changes.
1779 */
1780
1781 ctx->Driver.GetString = get_string;
1782 ctx->Driver.UpdateState = osmesa_update_state;
1783 ctx->Driver.SetDrawBuffer = set_draw_buffer;
1784 ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers;
1785 ctx->Driver.GetBufferSize = buffer_size;
1786
1787 ctx->Driver.Accum = _swrast_Accum;
1788 ctx->Driver.Bitmap = _swrast_Bitmap;
1789 ctx->Driver.Clear = clear;
1790 ctx->Driver.CopyPixels = _swrast_CopyPixels;
1791 ctx->Driver.DrawPixels = _swrast_DrawPixels;
1792 ctx->Driver.ReadPixels = _swrast_ReadPixels;
1793
1794 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
1795 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
1796 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
1797 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
1798 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
1799 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
1800 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
1801 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
1802
1803 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
1804 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
1805 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
1806 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
1807 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
1808 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1809 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1810 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1811 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1812
1813
1814 /* RGB(A) span/pixel functions */
1815 if (osmesa->format == OSMESA_RGB) {
1816 swdd->WriteRGBASpan = write_rgba_span_RGB;
1817 swdd->WriteRGBSpan = write_rgb_span_RGB;
1818 swdd->WriteMonoRGBASpan = write_monocolor_span_RGB;
1819 swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
1820 swdd->WriteMonoRGBAPixels = write_monocolor_pixels_RGB;
1821 swdd->ReadRGBASpan = read_rgba_span3;
1822 swdd->ReadRGBAPixels = read_rgba_pixels3;
1823 }
1824 else if (osmesa->format == OSMESA_BGR) {
1825 swdd->WriteRGBASpan = write_rgba_span_BGR;
1826 swdd->WriteRGBSpan = write_rgb_span_BGR;
1827 swdd->WriteMonoRGBASpan = write_monocolor_span_BGR;
1828 swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
1829 swdd->WriteMonoRGBAPixels = write_monocolor_pixels_BGR;
1830 swdd->ReadRGBASpan = read_rgba_span3;
1831 swdd->ReadRGBAPixels = read_rgba_pixels3;
1832 }
1833 else {
1834 /* 4 bytes / pixel in frame buffer */
1835 swdd->WriteRGBSpan = write_rgb_span;
1836 swdd->WriteRGBAPixels = write_rgba_pixels;
1837 swdd->WriteMonoRGBASpan = write_monocolor_span;
1838 swdd->WriteMonoRGBAPixels = write_monocolor_pixels;
1839 if (osmesa->format == OSMESA_RGBA &&
1840 CHAN_TYPE == GL_UNSIGNED_BYTE &&
1841 RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) {
1842 /* special, fast case */
1843 swdd->WriteRGBASpan = write_rgba_span_rgba;
1844 swdd->ReadRGBASpan = read_rgba_span_rgba;
1845 }
1846 else {
1847 swdd->WriteRGBASpan = write_rgba_span;
1848 swdd->ReadRGBASpan = read_rgba_span;
1849 }
1850 swdd->ReadRGBAPixels = read_rgba_pixels;
1851 }
1852
1853 /* CI span/pixel functions */
1854 swdd->WriteCI32Span = write_index32_span;
1855 swdd->WriteCI8Span = write_index8_span;
1856 swdd->WriteMonoCISpan = write_monoindex_span;
1857 swdd->WriteCI32Pixels = write_index_pixels;
1858 swdd->WriteMonoCIPixels = write_monoindex_pixels;
1859 swdd->ReadCI32Span = read_index_span;
1860 swdd->ReadCI32Pixels = read_index_pixels;
1861
1862 swdd->SetReadBuffer = set_read_buffer;
1863
1864 tnl->Driver.RunPipeline = _tnl_run_pipeline;
1865 tnl->Driver.RenderStart = _swsetup_RenderStart;
1866 tnl->Driver.RenderFinish = _swsetup_RenderFinish;
1867 tnl->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices;
1868 tnl->Driver.RenderPrimitive = _swsetup_RenderPrimitive;
1869 tnl->Driver.PointsFunc = _swsetup_Points;
1870 tnl->Driver.LineFunc = _swsetup_Line;
1871 tnl->Driver.TriangleFunc = _swsetup_Triangle;
1872 tnl->Driver.QuadFunc = _swsetup_Quad;
1873 tnl->Driver.ResetLineStipple = _swrast_ResetLineStipple;
1874 tnl->Driver.RenderInterp = _swsetup_RenderInterp;
1875 tnl->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
1876 tnl->Driver.RenderClippedLine = _swsetup_RenderClippedLine;
1877 tnl->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon;
1878
1879
1880 _swrast_InvalidateState( ctx, new_state );
1881 _swsetup_InvalidateState( ctx, new_state );
1882 _ac_InvalidateState( ctx, new_state );
1883 _tnl_InvalidateState( ctx, new_state );
1884 }