source: trunk/src/opengl/mesa/osmesa.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

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