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