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