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