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