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