Overhaul of texture image handling.
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
1 /* $Id: osmesa.c,v 1.44 2001/02/06 21:42:49 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 *bytesPerValue = sizeof(GLdepth);
546 *buffer = c->gl_buffer->DepthBuffer;
547 return GL_TRUE;
548 }
549 }
550
551 /*
552 * Return the color buffer associated with an OSMesa context.
553 * Input: c - the OSMesa context
554 * Output: width, height - size of buffer in pixels
555 * format - the pixel format (OSMESA_FORMAT)
556 * buffer - pointer to color buffer values
557 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
558 */
559 GLboolean GLAPIENTRY
560 OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
561 GLint *height, GLint *format, void **buffer )
562 {
563 if (!c->buffer) {
564 *width = 0;
565 *height = 0;
566 *format = 0;
567 *buffer = 0;
568 return GL_FALSE;
569 }
570 else {
571 *width = c->width;
572 *height = c->height;
573 *format = c->format;
574 *buffer = c->buffer;
575 return GL_TRUE;
576 }
577 }
578
579 /**********************************************************************/
580 /*** Device Driver Functions ***/
581 /**********************************************************************/
582
583
584 /*
585 * Useful macros:
586 */
587
588 #define PACK_RGBA(DST, R, G, B, A) \
589 do { \
590 (DST)[osmesa->rInd] = R; \
591 (DST)[osmesa->gInd] = G; \
592 (DST)[osmesa->bInd] = B; \
593 (DST)[osmesa->aInd] = A; \
594 } while (0)
595
596 #define PACK_RGB(DST, R, G, B) \
597 do { \
598 (DST)[0] = R; \
599 (DST)[1] = G; \
600 (DST)[2] = B; \
601 } while (0)
602
603 #define PACK_BGR(DST, R, G, B) \
604 do { \
605 (DST)[0] = B; \
606 (DST)[1] = G; \
607 (DST)[2] = R; \
608 } while (0)
609
610
611 #define UNPACK_RED(P) ( ((GLchan *) &(P))[osmesa->rInd] )
612 #define UNPACK_GREEN(P) ( ((GLchan *) &(P))[osmesa->gInd] )
613 #define UNPACK_BLUE(P) ( ((GLchan *) &(P))[osmesa->bInd] )
614 #define UNPACK_ALPHA(P) ( ((GLchan *) &(P))[osmesa->aInd] )
615
616
617 #define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X))
618 #define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X))
619 #define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X))
620
621
622
623 static GLboolean set_draw_buffer( GLcontext *ctx, GLenum mode )
624 {
625 (void) ctx;
626 if (mode==GL_FRONT_LEFT) {
627 return GL_TRUE;
628 }
629 else {
630 return GL_FALSE;
631 }
632 }
633
634
635 static void set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
636 {
637 /* separate read buffer not supported */
638 ASSERT(buffer == ctx->DrawBuffer);
639 ASSERT(mode == GL_FRONT_LEFT);
640 }
641
642
643 static void clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
644 GLint x, GLint y, GLint width, GLint height )
645 {
646 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
647 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
648
649 /* sanity check - we only have a front-left buffer */
650 ASSERT((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT)) == 0);
651 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
652 if (mask & DD_FRONT_LEFT_BIT) {
653 if (osmesa->format == OSMESA_COLOR_INDEX) {
654 if (all) {
655 /* Clear whole CI buffer */
656 #if CHAN_TYPE == GL_UNSIGNED_BYTE
657 MEMSET(osmesa->buffer, ctx->Color.ClearIndex,
658 osmesa->rowlength * osmesa->height);
659 #else
660 const GLint n = osmesa->rowlength * osmesa->height;
661 GLchan *buffer = (GLchan *) osmesa->buffer;
662 GLint i;
663 for (i = 0; i < n; i ++) {
664 buffer[i] = ctx->Color.ClearIndex;
665 }
666 #endif
667 }
668 else {
669 /* Clear part of CI buffer */
670 const GLchan clearIndex = (GLchan) ctx->Color.ClearIndex;
671 GLint i, j;
672 for (i = 0; i < height; i++) {
673 GLchan *ptr1 = PIXELADDR1(x, (y + i));
674 for (j = 0; j < width; j++) {
675 *ptr1++ = clearIndex;
676 }
677 }
678 }
679 }
680 else if (osmesa->format == OSMESA_RGB) {
681 const GLchan r = ctx->Color.ClearColor[0];
682 const GLchan g = ctx->Color.ClearColor[1];
683 const GLchan b = ctx->Color.ClearColor[2];
684 if (all) {
685 /* Clear whole RGB buffer */
686 GLuint n = osmesa->rowlength * osmesa->height;
687 GLchan *ptr3 = (GLchan *) osmesa->buffer;
688 GLuint i;
689 for (i = 0; i < n; i++) {
690 PACK_RGB(ptr3, r, g, b);
691 ptr3 += 3;
692 }
693 }
694 else {
695 /* Clear part of RGB buffer */
696 GLint i, j;
697 for (i = 0; i < height; i++) {
698 GLchan *ptr3 = PIXELADDR3(x, (y + i));
699 for (j = 0; j < width; j++) {
700 PACK_RGB(ptr3, r, g, b);
701 ptr3 += 3;
702 }
703 }
704 }
705 }
706 else if (osmesa->format == OSMESA_BGR) {
707 const GLchan r = ctx->Color.ClearColor[0];
708 const GLchan g = ctx->Color.ClearColor[1];
709 const GLchan b = ctx->Color.ClearColor[2];
710 if (all) {
711 /* Clear whole RGB buffer */
712 const GLint n = osmesa->rowlength * osmesa->height;
713 GLchan *ptr3 = (GLchan *) osmesa->buffer;
714 GLint i;
715 for (i = 0; i < n; i++) {
716 PACK_BGR(ptr3, r, g, b);
717 ptr3 += 3;
718 }
719 }
720 else {
721 /* Clear part of RGB buffer */
722 GLint i, j;
723 for (i = 0; i < height; i++) {
724 GLchan *ptr3 = PIXELADDR3(x, (y + i));
725 for (j = 0; j < width; j++) {
726 PACK_BGR(ptr3, r, g, b);
727 ptr3 += 3;
728 }
729 }
730 }
731 }
732 else {
733 #if CHAN_TYPE == GL_UNSIGNED_BYTE
734 /* 4-byte pixel value */
735 GLuint clearPixel;
736 GLchan *clr = (GLchan *) &clearPixel;
737 clr[osmesa->rInd] = ctx->Color.ClearColor[0];
738 clr[osmesa->gInd] = ctx->Color.ClearColor[1];
739 clr[osmesa->bInd] = ctx->Color.ClearColor[2];
740 clr[osmesa->aInd] = ctx->Color.ClearColor[3];
741 if (all) {
742 /* Clear whole RGBA buffer */
743 const GLuint n = osmesa->rowlength * osmesa->height;
744 GLuint *ptr4 = (GLuint *) osmesa->buffer;
745 GLuint i;
746 if (clearPixel) {
747 for (i = 0; i < n; i++) {
748 *ptr4++ = clearPixel;
749 }
750 }
751 else {
752 BZERO(ptr4, n * sizeof(GLuint));
753 }
754 }
755 else {
756 /* Clear part of RGBA buffer */
757 GLint i, j;
758 for (i = 0; i < height; i++) {
759 GLuint *ptr4 = (GLuint *) PIXELADDR4(x, (y + i));
760 for (j = 0; j < width; j++) {
761 *ptr4++ = clearPixel;
762 }
763 }
764 }
765 #else
766 const GLchan r = ctx->Color.ClearColor[0];
767 const GLchan g = ctx->Color.ClearColor[1];
768 const GLchan b = ctx->Color.ClearColor[2];
769 const GLchan a = ctx->Color.ClearColor[3];
770 if (all) {
771 /* Clear whole RGBA buffer */
772 const GLuint n = osmesa->rowlength * osmesa->height;
773 GLchan *p = (GLchan *) osmesa->buffer;
774 GLuint i;
775 for (i = 0; i < n; i++) {
776 PACK_RGBA(p, r, g, b, a);
777 p += 4;
778 }
779 }
780 else {
781 /* Clear part of RGBA buffer */
782 GLint i, j;
783 for (i = 0; i < height; i++) {
784 GLchan *p = PIXELADDR4(x, (y + i));
785 for (j = 0; j < width; j++) {
786 PACK_RGBA(p, r, g, b, a);
787 p += 4;
788 }
789 }
790 }
791
792 #endif
793 }
794 mask &= ~DD_FRONT_LEFT_BIT;
795 }
796 }
797
798 if (mask)
799 _swrast_Clear( ctx, mask, all, x, y, width, height );
800 }
801
802
803
804 static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
805 {
806 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
807 *width = osmesa->width;
808 *height = osmesa->height;
809 }
810
811
812 /**********************************************************************/
813 /***** Read/write spans/arrays of RGBA pixels *****/
814 /**********************************************************************/
815
816 /* Write RGBA pixels to an RGBA (or permuted) buffer. */
817 static void
818 write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
819 CONST GLchan rgba[][4], const GLubyte mask[] )
820 {
821 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
822 GLchan *p = PIXELADDR4(x, y);
823 GLuint i;
824 if (mask) {
825 for (i = 0; i < n; i++, p += 4) {
826 if (mask[i]) {
827 PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
828 rgba[i][BCOMP], rgba[i][ACOMP]);
829 }
830 }
831 }
832 else {
833 for (i = 0; i < n; i++, p += 4) {
834 PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
835 rgba[i][BCOMP], rgba[i][ACOMP]);
836 }
837 }
838 }
839
840
841 /* Write RGBA pixels to an RGBA buffer. This is the fastest span-writer. */
842 static void
843 write_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
844 CONST GLchan rgba[][4], const GLubyte mask[] )
845 {
846 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
847 GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
848 const GLuint *rgba4 = (const GLuint *) rgba;
849 GLuint i;
850 ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);
851 if (mask) {
852 for (i = 0; i < n; i++) {
853 if (mask[i]) {
854 ptr4[i] = rgba4[i];
855 }
856 }
857 }
858 else {
859 MEMCPY( ptr4, rgba4, n * 4 );
860 }
861 }
862
863
864 /* Write RGB pixels to an RGBA (or permuted) buffer. */
865 static void
866 write_rgb_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
867 CONST GLchan rgb[][3], const GLubyte mask[] )
868 {
869 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
870 GLchan *p = PIXELADDR4(x, y);
871 GLuint i;
872 if (mask) {
873 for (i = 0; i < n; i++, p+=4) {
874 if (mask[i]) {
875 PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
876 }
877 }
878 }
879 else {
880 for (i = 0; i < n; i++, p+=4) {
881 PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
882 }
883 }
884 }
885
886
887
888 static void
889 write_monocolor_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
890 const GLchan color[4], const GLubyte mask[] )
891 {
892 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
893 GLchan *p = PIXELADDR4(x, y);
894 GLuint i;
895 for (i = 0; i < n; i++, p += 4) {
896 if (mask[i]) {
897 PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
898 }
899 }
900 }
901
902
903
904 static void
905 write_rgba_pixels( const GLcontext *ctx, GLuint n,
906 const GLint x[], const GLint y[],
907 CONST GLchan rgba[][4], const GLubyte mask[] )
908 {
909 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
910 GLuint i;
911 for (i = 0; i < n; i++) {
912 if (mask[i]) {
913 GLchan *p = PIXELADDR4(x[i], y[i]);
914 PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
915 rgba[i][BCOMP], rgba[i][ACOMP]);
916 }
917 }
918 }
919
920
921
922 static void
923 write_monocolor_pixels( const GLcontext *ctx, GLuint n,
924 const GLint x[], const GLint y[],
925 const GLchan color[4], const GLubyte mask[] )
926 {
927 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
928 GLuint i;
929 for (i = 0; i < n; i++) {
930 if (mask[i]) {
931 GLchan *p = PIXELADDR4(x[i], y[i]);
932 PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
933 }
934 }
935 }
936
937
938 static void
939 read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
940 GLchan rgba[][4] )
941 {
942 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
943 GLuint i;
944 GLchan *p = PIXELADDR4(x, y);
945 for (i = 0; i < n; i++, p += 4) {
946 rgba[i][RCOMP] = UNPACK_RED(p);
947 rgba[i][GCOMP] = UNPACK_GREEN(p);
948 rgba[i][BCOMP] = UNPACK_BLUE(p);
949 rgba[i][ACOMP] = UNPACK_ALPHA(p);
950 }
951 }
952
953
954 /* Read RGBA pixels from an RGBA buffer */
955 static void
956 read_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
957 GLchan rgba[][4] )
958 {
959 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
960 GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
961 MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) );
962 }
963
964
965 static void
966 read_rgba_pixels( const GLcontext *ctx,
967 GLuint n, const GLint x[], const GLint y[],
968 GLchan rgba[][4], const GLubyte mask[] )
969 {
970 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
971 GLuint i;
972 for (i = 0; i < n; i++) {
973 if (mask[i]) {
974 const GLchan *p = PIXELADDR4(x[i], y[i]);
975 rgba[i][RCOMP] = UNPACK_RED(p);
976 rgba[i][GCOMP] = UNPACK_GREEN(p);
977 rgba[i][BCOMP] = UNPACK_BLUE(p);
978 rgba[i][ACOMP] = UNPACK_ALPHA(p);
979 }
980 }
981 }
982
983 /**********************************************************************/
984 /***** 3 byte RGB pixel support funcs *****/
985 /**********************************************************************/
986
987 /* Write RGBA pixels to an RGB buffer. */
988 static void
989 write_rgba_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
990 CONST GLchan rgba[][4], const GLubyte mask[] )
991 {
992 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
993 GLchan *p = PIXELADDR3(x, y);
994 GLuint i;
995 if (mask) {
996 for (i = 0; i < n; i++, p += 3) {
997 if (mask[i]) {
998 PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
999 }
1000 }
1001 }
1002 else {
1003 for (i = 0; i < n; i++, p += 3) {
1004 PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1005 }
1006 }
1007 }
1008
1009 /* Write RGBA pixels to an BGR buffer. */
1010 static void
1011 write_rgba_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1012 CONST GLchan rgba[][4], const GLubyte mask[] )
1013 {
1014 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1015 GLchan *p = PIXELADDR3(x, y);
1016 GLuint i;
1017 if (mask) {
1018 for (i = 0; i < n; i++, p += 3) {
1019 if (mask[i]) {
1020 PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1021 }
1022 }
1023 }
1024 else {
1025 for (i = 0; i < n; i++, p += 3) {
1026 PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1027 }
1028 }
1029 }
1030
1031 /* Write RGB pixels to an RGB buffer. */
1032 static void
1033 write_rgb_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1034 CONST GLchan rgb[][3], const GLubyte mask[] )
1035 {
1036 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1037 GLchan *p = PIXELADDR3(x, y);
1038 GLuint i;
1039 if (mask) {
1040 for (i = 0; i < n; i++, p += 3) {
1041 if (mask[i]) {
1042 PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1043 }
1044 }
1045 }
1046 else {
1047 for (i = 0; i < n; i++, p += 3) {
1048 PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1049 }
1050 }
1051 }
1052
1053 /* Write RGB pixels to an BGR buffer. */
1054 static void
1055 write_rgb_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1056 CONST GLchan rgb[][3], const GLubyte mask[] )
1057 {
1058 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1059 GLchan *p = PIXELADDR3(x, y);
1060 GLuint i;
1061 if (mask) {
1062 for (i = 0; i < n; i++, p += 3) {
1063 if (mask[i]) {
1064 PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1065 }
1066 }
1067 }
1068 else {
1069 for (i = 0; i < n; i++, p += 3) {
1070 PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1071 }
1072 }
1073 }
1074
1075
1076 static void
1077 write_monocolor_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1078 const GLchan color[4], const GLubyte mask[] )
1079 {
1080 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1081 GLchan *p = PIXELADDR3(x, y);
1082 GLuint i;
1083 for (i = 0; i < n; i++, p += 3) {
1084 if (mask[i]) {
1085 PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1086 }
1087 }
1088 }
1089
1090 static void
1091 write_monocolor_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1092 const GLchan color[4], const GLubyte mask[] )
1093 {
1094 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1095 GLchan *p = PIXELADDR3(x, y);
1096 GLuint i;
1097 for (i = 0; i < n; i++, p += 3) {
1098 if (mask[i]) {
1099 PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1100 }
1101 }
1102 }
1103
1104 static void
1105 write_rgba_pixels_RGB( const GLcontext *ctx, GLuint n,
1106 const GLint x[], const GLint y[],
1107 CONST GLchan rgba[][4], const GLubyte mask[] )
1108 {
1109 const OSMesaContext osmesa = (const OSMesaContext) ctx;
1110 GLuint i;
1111 for (i = 0; i < n; i++) {
1112 if (mask[i]) {
1113 GLchan *p = PIXELADDR3(x[i], y[i]);
1114 PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1115 }
1116 }
1117 }
1118
1119 static void
1120 write_rgba_pixels_BGR( const GLcontext *ctx, GLuint n,
1121 const GLint x[], const GLint y[],
1122 CONST GLchan rgba[][4], const GLubyte mask[] )
1123 {
1124 const OSMesaContext osmesa = (const OSMesaContext) ctx;
1125 GLuint i;
1126 for (i = 0; i < n; i++) {
1127 if (mask[i]) {
1128 GLchan *p = PIXELADDR3(x[i], y[i]);
1129 PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1130 }
1131 }
1132 }
1133
1134 static void
1135 write_monocolor_pixels_RGB( const GLcontext *ctx,
1136 GLuint n, const GLint x[], const GLint y[],
1137 const GLchan color[4], const GLubyte mask[] )
1138 {
1139 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1140 GLuint i;
1141 for (i = 0; i < n; i++) {
1142 if (mask[i]) {
1143 GLchan *p = PIXELADDR3(x[i], y[i]);
1144 PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1145 }
1146 }
1147 }
1148
1149 static void
1150 write_monocolor_pixels_BGR( const GLcontext *ctx,
1151 GLuint n, const GLint x[], const GLint y[],
1152 const GLchan color[4], const GLubyte mask[] )
1153 {
1154 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1155 GLuint i;
1156 for (i = 0; i < n; i++) {
1157 if (mask[i]) {
1158 GLchan *p = PIXELADDR3(x[i], y[i]);
1159 PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1160 }
1161 }
1162 }
1163
1164 static void
1165 read_rgba_span3( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1166 GLchan rgba[][4] )
1167 {
1168 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1169 GLuint i;
1170 const GLchan *p = PIXELADDR3(x, y);
1171 for (i = 0; i < n; i++, p += 3) {
1172 rgba[i][RCOMP] = UNPACK_RED(p);
1173 rgba[i][GCOMP] = UNPACK_GREEN(p);
1174 rgba[i][BCOMP] = UNPACK_BLUE(p);
1175 rgba[i][ACOMP] = 255;
1176 }
1177 }
1178
1179 static void
1180 read_rgba_pixels3( const GLcontext *ctx,
1181 GLuint n, const GLint x[], const GLint y[],
1182 GLchan rgba[][4], const GLubyte mask[] )
1183 {
1184 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1185 GLuint i;
1186 for (i = 0; i < n; i++) {
1187 if (mask[i]) {
1188 const GLchan *p = PIXELADDR3(x[i], y[i]);
1189 rgba[i][RCOMP] = UNPACK_RED(p);
1190 rgba[i][GCOMP] = UNPACK_GREEN(p);
1191 rgba[i][BCOMP] = UNPACK_BLUE(p);
1192 rgba[i][ACOMP] = 255;
1193 }
1194 }
1195 }
1196
1197
1198 /**********************************************************************/
1199 /***** Read/write spans/arrays of CI pixels *****/
1200 /**********************************************************************/
1201
1202 /* Write 32-bit color index to buffer */
1203 static void
1204 write_index32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1205 const GLuint index[], const GLubyte mask[] )
1206 {
1207 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1208 GLchan *ptr1 = PIXELADDR1(x, y);
1209 GLuint i;
1210 if (mask) {
1211 for (i=0;i<n;i++,ptr1++) {
1212 if (mask[i]) {
1213 *ptr1 = (GLchan) index[i];
1214 }
1215 }
1216 }
1217 else {
1218 for (i=0;i<n;i++,ptr1++) {
1219 *ptr1 = (GLchan) index[i];
1220 }
1221 }
1222 }
1223
1224
1225 /* Write 8-bit color index to buffer */
1226 static void
1227 write_index8_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1228 const GLubyte index[], const GLubyte mask[] )
1229 {
1230 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1231 GLchan *ptr1 = PIXELADDR1(x, y);
1232 GLuint i;
1233 if (mask) {
1234 for (i=0;i<n;i++,ptr1++) {
1235 if (mask[i]) {
1236 *ptr1 = (GLchan) index[i];
1237 }
1238 }
1239 }
1240 else {
1241 MEMCPY(ptr1, index, n * sizeof(GLchan));
1242 }
1243 }
1244
1245
1246 static void
1247 write_monoindex_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1248 GLuint colorIndex, const GLubyte mask[] )
1249 {
1250 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1251 GLchan *ptr1 = PIXELADDR1(x, y);
1252 GLuint i;
1253 for (i=0;i<n;i++,ptr1++) {
1254 if (mask[i]) {
1255 *ptr1 = (GLchan) colorIndex;
1256 }
1257 }
1258 }
1259
1260
1261 static void
1262 write_index_pixels( const GLcontext *ctx,
1263 GLuint n, const GLint x[], const GLint y[],
1264 const GLuint index[], const GLubyte mask[] )
1265 {
1266 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1267 GLuint i;
1268 for (i=0;i<n;i++) {
1269 if (mask[i]) {
1270 GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1271 *ptr1 = (GLchan) index[i];
1272 }
1273 }
1274 }
1275
1276
1277 static void
1278 write_monoindex_pixels( const GLcontext *ctx,
1279 GLuint n, const GLint x[], const GLint y[],
1280 GLuint colorIndex, const GLubyte mask[] )
1281 {
1282 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1283 GLuint i;
1284 for (i=0;i<n;i++) {
1285 if (mask[i]) {
1286 GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1287 *ptr1 = (GLchan) colorIndex;
1288 }
1289 }
1290 }
1291
1292
1293 static void
1294 read_index_span( const GLcontext *ctx,
1295 GLuint n, GLint x, GLint y, GLuint index[] )
1296 {
1297 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1298 GLuint i;
1299 const GLchan *ptr1 = (const GLchan *) PIXELADDR1(x, y);
1300 for (i=0;i<n;i++,ptr1++) {
1301 index[i] = (GLuint) *ptr1;
1302 }
1303 }
1304
1305
1306 static void
1307 read_index_pixels( const GLcontext *ctx,
1308 GLuint n, const GLint x[], const GLint y[],
1309 GLuint index[], const GLubyte mask[] )
1310 {
1311 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1312 GLuint i;
1313 for (i=0;i<n;i++) {
1314 if (mask[i] ) {
1315 const GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1316 index[i] = (GLuint) *ptr1;
1317 }
1318 }
1319 }
1320
1321
1322
1323 /**********************************************************************/
1324 /***** Optimized line rendering *****/
1325 /**********************************************************************/
1326
1327
1328 /*
1329 * Draw a flat-shaded, RGB line into an osmesa buffer.
1330 */
1331 static void
1332 flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
1333 {
1334 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1335 const GLchan *color = vert0->color;
1336
1337 #define INTERP_XY 1
1338 #define CLIP_HACK 1
1339 #define PLOT(X, Y) \
1340 do { \
1341 GLchan *p = PIXELADDR4(X, Y); \
1342 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \
1343 } while (0)
1344
1345 #ifdef WIN32
1346 #include "..\swrast\s_linetemp.h"
1347 #else
1348 #include "swrast/s_linetemp.h"
1349 #endif
1350 }
1351
1352
1353 /*
1354 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
1355 */
1356 static void
1357 flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
1358 {
1359 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1360 const GLchan *color = vert0->color;
1361
1362 #define INTERP_XY 1
1363 #define INTERP_Z 1
1364 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1365 #define CLIP_HACK 1
1366 #define PLOT(X, Y) \
1367 do { \
1368 if (Z < *zPtr) { \
1369 GLchan *p = PIXELADDR4(X, Y); \
1370 PACK_RGBA(p, color[RCOMP], color[GCOMP], \
1371 color[BCOMP], color[ACOMP]); \
1372 *zPtr = Z; \
1373 } \
1374 } while (0)
1375
1376
1377 #ifdef WIN32
1378 #include "..\swrast\s_linetemp.h"
1379 #else
1380 #include "swrast/s_linetemp.h"
1381 #endif
1382 }
1383
1384
1385 /*
1386 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
1387 * XXX update for GLchan
1388 */
1389 static void
1390 flat_blend_rgba_line( GLcontext *ctx,
1391 const SWvertex *vert0, const SWvertex *vert1 )
1392 {
1393 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1394 const GLint rshift = osmesa->rshift;
1395 const GLint gshift = osmesa->gshift;
1396 const GLint bshift = osmesa->bshift;
1397 const GLint avalue = vert0->color[3];
1398 const GLint msavalue = 255 - avalue;
1399 const GLint rvalue = vert0->color[0]*avalue;
1400 const GLint gvalue = vert0->color[1]*avalue;
1401 const GLint bvalue = vert0->color[2]*avalue;
1402
1403 #define INTERP_XY 1
1404 #define CLIP_HACK 1
1405 #define PLOT(X,Y) \
1406 { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \
1407 GLuint pixel = 0; \
1408 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
1409 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
1410 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
1411 *ptr4 = pixel; \
1412 }
1413
1414 #ifdef WIN32
1415 #include "..\swrast\s_linetemp.h"
1416 #else
1417 #include "swrast/s_linetemp.h"
1418 #endif
1419 }
1420
1421
1422 /*
1423 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1424 * XXX update for GLchan
1425 */
1426 static void
1427 flat_blend_rgba_z_line( GLcontext *ctx,
1428 const SWvertex *vert0, const SWvertex *vert1 )
1429 {
1430 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1431 const GLint rshift = osmesa->rshift;
1432 const GLint gshift = osmesa->gshift;
1433 const GLint bshift = osmesa->bshift;
1434 const GLint avalue = vert0->color[3];
1435 const GLint msavalue = 256 - avalue;
1436 const GLint rvalue = vert0->color[0]*avalue;
1437 const GLint gvalue = vert0->color[1]*avalue;
1438 const GLint bvalue = vert0->color[2]*avalue;
1439
1440 #define INTERP_XY 1
1441 #define INTERP_Z 1
1442 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1443 #define CLIP_HACK 1
1444 #define PLOT(X,Y) \
1445 if (Z < *zPtr) { \
1446 GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \
1447 GLuint pixel = 0; \
1448 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \
1449 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \
1450 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \
1451 *ptr4 = pixel; \
1452 }
1453
1454 #ifdef WIN32
1455 #include "..\swrast\s_linetemp.h"
1456 #else
1457 #include "swrast/s_linetemp.h"
1458 #endif
1459 }
1460
1461
1462 /*
1463 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1464 * XXX update for GLchan
1465 */
1466 static void
1467 flat_blend_rgba_z_line_write( GLcontext *ctx,
1468 const SWvertex *vert0, const SWvertex *vert1 )
1469 {
1470 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1471 const GLint rshift = osmesa->rshift;
1472 const GLint gshift = osmesa->gshift;
1473 const GLint bshift = osmesa->bshift;
1474 const GLint avalue = vert0->color[3];
1475 const GLint msavalue = 256 - avalue;
1476 const GLint rvalue = vert0->color[0]*avalue;
1477 const GLint gvalue = vert0->color[1]*avalue;
1478 const GLint bvalue = vert0->color[2]*avalue;
1479
1480 #define INTERP_XY 1
1481 #define INTERP_Z 1
1482 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1483 #define CLIP_HACK 1
1484 #define PLOT(X,Y) \
1485 if (Z < *zPtr) { \
1486 GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \
1487 GLuint pixel = 0; \
1488 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \
1489 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \
1490 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \
1491 *ptr4 = pixel; \
1492 *zPtr = Z; \
1493 }
1494
1495 #ifdef WIN32
1496 #include "..\swrast\s_linetemp.h"
1497 #else
1498 #include "swrast/s_linetemp.h"
1499 #endif
1500 }
1501
1502
1503 /*
1504 * Analyze context state to see if we can provide a fast line drawing
1505 * function, like those in lines.c. Otherwise, return NULL.
1506 */
1507 static swrast_line_func
1508 osmesa_choose_line_function( GLcontext *ctx )
1509 {
1510 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1511 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1512
1513 if (CHAN_BITS != 8) return NULL;
1514 if (ctx->RenderMode != GL_RENDER) return NULL;
1515 if (ctx->Line.SmoothFlag) return NULL;
1516 if (ctx->Texture._ReallyEnabled) return NULL;
1517 if (ctx->Light.ShadeModel != GL_FLAT) return NULL;
1518 if (ctx->Line.Width != 1.0F) return NULL;
1519 if (ctx->Line.StippleFlag) return NULL;
1520 if (ctx->Line.SmoothFlag) return NULL;
1521 if (osmesa->format != OSMESA_RGBA &&
1522 osmesa->format != OSMESA_BGRA &&
1523 osmesa->format != OSMESA_ARGB) return NULL;
1524
1525 if (swrast->_RasterMask==DEPTH_BIT
1526 && ctx->Depth.Func==GL_LESS
1527 && ctx->Depth.Mask==GL_TRUE
1528 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1529 return flat_rgba_z_line;
1530 }
1531
1532 if (swrast->_RasterMask == 0) {
1533 return flat_rgba_line;
1534 }
1535
1536 if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1537 && ctx->Depth.Func==GL_LESS
1538 && ctx->Depth.Mask==GL_TRUE
1539 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1540 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1541 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1542 && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1543 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1544 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1545 return flat_blend_rgba_z_line_write;
1546 }
1547
1548 if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1549 && ctx->Depth.Func==GL_LESS
1550 && ctx->Depth.Mask==GL_FALSE
1551 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1552 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1553 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1554 && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1555 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1556 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1557 return flat_blend_rgba_z_line;
1558 }
1559
1560 if (swrast->_RasterMask==BLEND_BIT
1561 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1562 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1563 && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1564 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1565 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1566 return flat_blend_rgba_line;
1567 }
1568
1569 return NULL;
1570 }
1571
1572
1573 /**********************************************************************/
1574 /***** Optimized triangle rendering *****/
1575 /**********************************************************************/
1576
1577
1578 /*
1579 * Smooth-shaded, z-less triangle, RGBA color.
1580 */
1581 static void smooth_rgba_z_triangle( GLcontext *ctx,
1582 const SWvertex *v0,
1583 const SWvertex *v1,
1584 const SWvertex *v2 )
1585 {
1586 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1587
1588 #define INTERP_Z 1
1589 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1590 #define INTERP_RGB 1
1591 #define INTERP_ALPHA 1
1592 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1593 { \
1594 GLint i, len = RIGHT-LEFT; \
1595 GLchan *img = PIXELADDR4(LEFT, Y); \
1596 (void) fffog; \
1597 for (i = 0; i < len; i++, img += 4) { \
1598 GLdepth z = FixedToDepth(ffz); \
1599 if (z < zRow[i]) { \
1600 PACK_RGBA(img, FixedToInt(ffr), FixedToInt(ffg), \
1601 FixedToInt(ffb), FixedToInt(ffa)); \
1602 zRow[i] = z; \
1603 } \
1604 ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; ffa += fdadx;\
1605 ffz += fdzdx; \
1606 } \
1607 }
1608 #ifdef WIN32
1609 #include "..\swrast\s_tritemp.h"
1610 #else
1611 #include "swrast/s_tritemp.h"
1612 #endif
1613 }
1614
1615
1616
1617
1618 /*
1619 * Flat-shaded, z-less triangle, RGBA color.
1620 */
1621 static void flat_rgba_z_triangle( GLcontext *ctx,
1622 const SWvertex *v0,
1623 const SWvertex *v1,
1624 const SWvertex *v2 )
1625 {
1626 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1627 #define INTERP_Z 1
1628 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1629 #define SETUP_CODE \
1630 GLuint pixel; \
1631 PACK_RGBA((GLchan *) &pixel, v0->color[0], v0->color[1], \
1632 v0->color[2], v0->color[3]);
1633
1634 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1635 { \
1636 GLint i, len = RIGHT-LEFT; \
1637 GLuint *img = (GLuint *) PIXELADDR4(LEFT, Y); \
1638 (void) fffog; \
1639 for (i=0;i<len;i++) { \
1640 GLdepth z = FixedToDepth(ffz); \
1641 if (z < zRow[i]) { \
1642 img[i] = pixel; \
1643 zRow[i] = z; \
1644 } \
1645 ffz += fdzdx; \
1646 } \
1647 }
1648 #ifdef WIN32
1649 #include "..\swrast\s_tritemp.h"
1650 #else
1651 #include "swrast/s_tritemp.h"
1652 #endif
1653 }
1654
1655
1656
1657 /*
1658 * Return pointer to an accelerated triangle function if possible.
1659 */
1660 static swrast_tri_func
1661 osmesa_choose_triangle_function( GLcontext *ctx )
1662 {
1663 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1664 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1665
1666 if (CHAN_BITS != 8) return (swrast_tri_func) NULL;
1667 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
1668 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
1669 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL;
1670 if (ctx->Texture._ReallyEnabled) return (swrast_tri_func) NULL;
1671 if (osmesa->format != OSMESA_RGBA &&
1672 osmesa->format != OSMESA_BGRA &&
1673 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL;
1674
1675 if (swrast->_RasterMask == DEPTH_BIT &&
1676 ctx->Depth.Func == GL_LESS &&
1677 ctx->Depth.Mask == GL_TRUE &&
1678 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1679 if (ctx->Light.ShadeModel == GL_SMOOTH) {
1680 return smooth_rgba_z_triangle;
1681 }
1682 else {
1683 return flat_rgba_z_triangle;
1684 }
1685 }
1686 return (swrast_tri_func) NULL;
1687 }
1688
1689
1690
1691 /* Override for the swrast triangle-selection function. Try to use one
1692 * of our internal triangle functions, otherwise fall back to the
1693 * standard swrast functions.
1694 */
1695 static void osmesa_choose_triangle( GLcontext *ctx )
1696 {
1697 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1698
1699 swrast->Triangle = osmesa_choose_triangle_function( ctx );
1700 if (!swrast->Triangle)
1701 _swrast_choose_triangle( ctx );
1702 }
1703
1704 static void osmesa_choose_line( GLcontext *ctx )
1705 {
1706 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1707
1708 swrast->Line = osmesa_choose_line_function( ctx );
1709 if (!swrast->Line)
1710 _swrast_choose_line( ctx );
1711 }
1712
1713
1714 #define OSMESA_NEW_LINE (_NEW_LINE | \
1715 _NEW_TEXTURE | \
1716 _NEW_LIGHT | \
1717 _NEW_DEPTH | \
1718 _NEW_RENDERMODE | \
1719 _SWRAST_NEW_RASTERMASK)
1720
1721 #define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1722 _NEW_TEXTURE | \
1723 _NEW_LIGHT | \
1724 _NEW_DEPTH | \
1725 _NEW_RENDERMODE | \
1726 _SWRAST_NEW_RASTERMASK)
1727
1728
1729 /* Extend the software rasterizer with our line and triangle
1730 * functions.
1731 */
1732 static void osmesa_register_swrast_functions( GLcontext *ctx )
1733 {
1734 SWcontext *swrast = SWRAST_CONTEXT( ctx );
1735
1736 swrast->choose_line = osmesa_choose_line;
1737 swrast->choose_triangle = osmesa_choose_triangle;
1738
1739 swrast->invalidate_line |= OSMESA_NEW_LINE;
1740 swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
1741 }
1742
1743
1744 static const GLubyte *get_string( GLcontext *ctx, GLenum name )
1745 {
1746 (void) ctx;
1747 switch (name) {
1748 case GL_RENDERER:
1749 return (const GLubyte *) "Mesa OffScreen";
1750 default:
1751 return NULL;
1752 }
1753 }
1754
1755
1756 static void osmesa_update_state( GLcontext *ctx, GLuint new_state )
1757 {
1758 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1759
1760 ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
1761
1762 /*
1763 * XXX these function pointers could be initialized just once during
1764 * context creation since they don't depend on any state changes.
1765 */
1766
1767 ctx->Driver.GetString = get_string;
1768 ctx->Driver.UpdateState = osmesa_update_state;
1769
1770 ctx->Driver.SetDrawBuffer = set_draw_buffer;
1771 ctx->Driver.SetReadBuffer = set_read_buffer;
1772
1773 ctx->Driver.Accum = _swrast_Accum;
1774 ctx->Driver.Bitmap = _swrast_Bitmap;
1775 ctx->Driver.Clear = clear;
1776 ctx->Driver.CopyPixels = _swrast_CopyPixels;
1777 ctx->Driver.DrawPixels = _swrast_DrawPixels;
1778 ctx->Driver.ReadPixels = _swrast_ReadPixels;
1779 ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers;
1780
1781 ctx->Driver.GetBufferSize = buffer_size;
1782
1783 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
1784 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
1785 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
1786 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
1787 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
1788 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
1789 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
1790
1791 ctx->Driver.PointsFunc = _swsetup_Points;
1792 ctx->Driver.LineFunc = _swsetup_Line;
1793 ctx->Driver.TriangleFunc = _swsetup_Triangle;
1794 ctx->Driver.QuadFunc = _swsetup_Quad;
1795 ctx->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices;
1796 ctx->Driver.RenderPrimitive = _swsetup_RenderPrimitive;
1797 ctx->Driver.RenderStart = _swsetup_RenderStart;
1798 ctx->Driver.RenderFinish = _swsetup_RenderFinish;
1799 ctx->Driver.RenderInterp = _swsetup_RenderInterp;
1800 ctx->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
1801 ctx->Driver.RenderClippedLine = _swsetup_RenderClippedLine;
1802 ctx->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon;
1803
1804 /* RGB(A) span/pixel functions */
1805 if (osmesa->format == OSMESA_RGB) {
1806 ctx->Driver.WriteRGBASpan = write_rgba_span_RGB;
1807 ctx->Driver.WriteRGBSpan = write_rgb_span_RGB;
1808 ctx->Driver.WriteMonoRGBASpan = write_monocolor_span_RGB;
1809 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_RGB;
1810 ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels_RGB;
1811 ctx->Driver.ReadRGBASpan = read_rgba_span3;
1812 ctx->Driver.ReadRGBAPixels = read_rgba_pixels3;
1813 }
1814 else if (osmesa->format == OSMESA_BGR) {
1815 ctx->Driver.WriteRGBASpan = write_rgba_span_BGR;
1816 ctx->Driver.WriteRGBSpan = write_rgb_span_BGR;
1817 ctx->Driver.WriteMonoRGBASpan = write_monocolor_span_BGR;
1818 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_BGR;
1819 ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels_BGR;
1820 ctx->Driver.ReadRGBASpan = read_rgba_span3;
1821 ctx->Driver.ReadRGBAPixels = read_rgba_pixels3;
1822 }
1823 else {
1824 /* 4 bytes / pixel in frame buffer */
1825 ctx->Driver.WriteRGBSpan = write_rgb_span;
1826 ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
1827 ctx->Driver.WriteMonoRGBASpan = write_monocolor_span;
1828 ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels;
1829 if (osmesa->format == OSMESA_RGBA &&
1830 CHAN_TYPE == GL_UNSIGNED_BYTE &&
1831 RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) {
1832 /* special, fast case */
1833 ctx->Driver.WriteRGBASpan = write_rgba_span_rgba;
1834 ctx->Driver.ReadRGBASpan = read_rgba_span_rgba;
1835 }
1836 else {
1837 ctx->Driver.WriteRGBASpan = write_rgba_span;
1838 ctx->Driver.ReadRGBASpan = read_rgba_span;
1839 }
1840 ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
1841 }
1842
1843 /* CI span/pixel functions */
1844 ctx->Driver.WriteCI32Span = write_index32_span;
1845 ctx->Driver.WriteCI8Span = write_index8_span;
1846 ctx->Driver.WriteMonoCISpan = write_monoindex_span;
1847 ctx->Driver.WriteCI32Pixels = write_index_pixels;
1848 ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels;
1849 ctx->Driver.ReadCI32Span = read_index_span;
1850 ctx->Driver.ReadCI32Pixels = read_index_pixels;
1851
1852 _swrast_InvalidateState( ctx, new_state );
1853 _swsetup_InvalidateState( ctx, new_state );
1854 _ac_InvalidateState( ctx, new_state );
1855 _tnl_InvalidateState( ctx, new_state );
1856 }