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