From 9c799cdc49e9200f5a1c7c7d9787d5729b5b0082 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 13 Nov 2002 16:57:44 +0000 Subject: [PATCH] Lots of clean-ups. Use new s_spantemp.h to generate all the span functions. Updated triangle functions (#define NAME, etc) --- src/mesa/drivers/osmesa/osmesa.c | 3069 ++++++++++++------------------ 1 file changed, 1200 insertions(+), 1869 deletions(-) diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index 35cf3c79e49..2699890186a 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -1,4 +1,4 @@ -/* $Id: osmesa.c,v 1.96 2002/10/30 19:49:30 brianp Exp $ */ +/* $Id: osmesa.c,v 1.97 2002/11/13 16:57:44 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -87,2094 +87,1425 @@ struct osmesa_context { }; - -/* A forward declaration: */ -static void osmesa_update_state( GLcontext *ctx, GLuint newstate ); -static void osmesa_register_swrast_functions( GLcontext *ctx ); - - - #define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx)) /**********************************************************************/ -/***** Public Functions *****/ +/*** Private Device Driver Functions ***/ /**********************************************************************/ -/* - * Create an Off-Screen Mesa rendering context. The only attribute needed is - * an RGBA vs Color-Index mode flag. - * - * Input: format - either GL_RGBA or GL_COLOR_INDEX - * sharelist - specifies another OSMesaContext with which to share - * display lists. NULL indicates no sharing. - * Return: an OSMesaContext or 0 if error - */ -GLAPI OSMesaContext GLAPIENTRY -OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) +static const GLubyte * +get_string( GLcontext *ctx, GLenum name ) { - return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, - 8, 16, sharelist); + (void) ctx; + switch (name) { + case GL_RENDERER: +#if CHAN_BITS == 32 + return (const GLubyte *) "Mesa OffScreen32"; +#elif CHAN_BITS == 16 + return (const GLubyte *) "Mesa OffScreen16"; +#else + return (const GLubyte *) "Mesa OffScreen"; +#endif + default: + return NULL; + } } +static void +osmesa_update_state( GLcontext *ctx, GLuint new_state ) +{ + /* easy - just propogate */ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); +} + -/* - * New in Mesa 3.5 - * - * Create context and specify size of ancillary buffers. - */ -GLAPI OSMesaContext GLAPIENTRY -OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, - GLint accumBits, OSMesaContext sharelist ) +static void +set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) { - OSMesaContext osmesa; - GLint rshift, gshift, bshift, ashift; - GLint rind, gind, bind, aind; - GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; - GLboolean rgbmode; - const GLuint i4 = 1; - const GLubyte *i1 = (GLubyte *) &i4; - const GLint little_endian = *i1; + /* separate read buffer not supported */ + ASSERT(buffer == ctx->DrawBuffer); + ASSERT(bufferBit == FRONT_LEFT_BIT); +} - rind = gind = bind = aind = 0; - if (format==OSMESA_COLOR_INDEX) { - indexBits = 8; - rshift = gshift = bshift = ashift = 0; - rgbmode = GL_FALSE; - } - else if (format==OSMESA_RGBA) { - indexBits = 0; - redBits = CHAN_BITS; - greenBits = CHAN_BITS; - blueBits = CHAN_BITS; - alphaBits = CHAN_BITS; - rind = 0; - gind = 1; - bind = 2; - aind = 3; - if (little_endian) { - rshift = 0; - gshift = 8; - bshift = 16; - ashift = 24; - } - else { - rshift = 24; - gshift = 16; - bshift = 8; - ashift = 0; - } - rgbmode = GL_TRUE; - } - else if (format==OSMESA_BGRA) { - indexBits = 0; - redBits = CHAN_BITS; - greenBits = CHAN_BITS; - blueBits = CHAN_BITS; - alphaBits = CHAN_BITS; - bind = 0; - gind = 1; - rind = 2; - aind = 3; - if (little_endian) { - bshift = 0; - gshift = 8; - rshift = 16; - ashift = 24; - } - else { - bshift = 24; - gshift = 16; - rshift = 8; - ashift = 0; - } - rgbmode = GL_TRUE; + +static void +get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) +{ + /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */ + GLcontext *ctx = (GLcontext *) _glapi_get_context(); + (void) buffer; + if (ctx) { + OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + *width = osmesa->width; + *height = osmesa->height; } - else if (format==OSMESA_ARGB) { - indexBits = 0; - redBits = CHAN_BITS; - greenBits = CHAN_BITS; - blueBits = CHAN_BITS; - alphaBits = CHAN_BITS; - aind = 0; - rind = 1; - gind = 2; - bind = 3; - if (little_endian) { - ashift = 0; - rshift = 8; - gshift = 16; - bshift = 24; +} + + +static void +clear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + /* sanity check - we only have a front-left buffer */ + ASSERT((mask & (DD_FRONT_RIGHT_BIT | + DD_BACK_LEFT_BIT | + DD_BACK_RIGHT_BIT)) == 0); + + /* use optimized clear for common cases (clear whole buffer to black) */ + if (mask & DD_FRONT_LEFT_BIT) { + if (osmesa->format == OSMESA_COLOR_INDEX) { + if (ctx->Color.ClearIndex == 0 && + ctx->Color.IndexMask == ~0 && + osmesa->rowlength == osmesa->width && + all) { + /* clear whole buffer to zeros */ + _mesa_bzero(osmesa->buffer, + osmesa->width * osmesa->height * sizeof(GLchan)); + mask &= ~DD_FRONT_LEFT_BIT; + } } else { - ashift = 24; - rshift = 16; - gshift = 8; - bshift = 0; + /* RGB[A] format */ + if (*colorMask == 0xffffffff && + ctx->Color.ClearColor[0] == 0.0F && + ctx->Color.ClearColor[1] == 0.0F && + ctx->Color.ClearColor[2] == 0.0F && + ctx->Color.ClearColor[3] == 0.0F && + osmesa->rowlength == osmesa->width && + all) { + GLint bytesPerPixel; + /* clear whole buffer to black */ + if (osmesa->format == OSMESA_RGBA || + osmesa->format == OSMESA_BGRA || + osmesa->format == OSMESA_ARGB) + bytesPerPixel = 4 * sizeof(GLchan); + else if (osmesa->format == OSMESA_RGB || + osmesa->format == OSMESA_BGR) + bytesPerPixel = 3 * sizeof(GLchan); + else if (osmesa->format == OSMESA_RGB_565) + bytesPerPixel = sizeof(GLushort); + else { + _mesa_problem(ctx, "bad pixel format in osmesa_clear()"); + return; + } + _mesa_bzero(osmesa->buffer, + bytesPerPixel * osmesa->width * osmesa->height); + mask &= ~DD_FRONT_LEFT_BIT; + } } - rgbmode = GL_TRUE; - } - else if (format==OSMESA_RGB) { - indexBits = 0; - redBits = CHAN_BITS; - greenBits = CHAN_BITS; - blueBits = CHAN_BITS; - alphaBits = 0; - bshift = 0; - gshift = 8; - rshift = 16; - ashift = 24; - rind = 0; - gind = 1; - bind = 2; - rgbmode = GL_TRUE; - } - else if (format==OSMESA_BGR) { - indexBits = 0; - redBits = CHAN_BITS; - greenBits = CHAN_BITS; - blueBits = CHAN_BITS; - alphaBits = 0; - bshift = 0; - gshift = 8; - rshift = 16; - ashift = 24; - rind = 2; - gind = 1; - bind = 0; - rgbmode = GL_TRUE; - } - else if (format==OSMESA_RGB_565) { - indexBits = 0; - redBits = 5; - greenBits = 6; - blueBits = 5; - alphaBits = 0; - rshift = 11; - gshift = 5; - bshift = 0; - ashift = 0; - rind = 0; /* not used */ - gind = 0; - bind = 0; - rgbmode = GL_TRUE; - } - else { - return NULL; } + if (mask) { + /* software fallback (spans) for everything else. */ + _swrast_Clear(ctx, mask, all, x, y, width, height); + } +} - osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); - if (osmesa) { - osmesa->gl_visual = _mesa_create_visual( rgbmode, - GL_FALSE, /* double buffer */ - GL_FALSE, /* stereo */ - redBits, - greenBits, - blueBits, - alphaBits, - indexBits, - depthBits, - stencilBits, - accumBits, - accumBits, - accumBits, - alphaBits ? accumBits : 0, - 1 /* num samples */ - ); - if (!osmesa->gl_visual) { - FREE(osmesa); - return NULL; - } - if (!_mesa_initialize_context(&osmesa->gl_ctx, - osmesa->gl_visual, - sharelist ? &sharelist->gl_ctx - : (GLcontext *) NULL, - (void *) osmesa, - GL_FALSE)) { - _mesa_destroy_visual( osmesa->gl_visual ); - FREE(osmesa); - return NULL; - } +/**********************************************************************/ +/***** Read/write spans/arrays of pixels *****/ +/**********************************************************************/ - _mesa_enable_sw_extensions(&(osmesa->gl_ctx)); - _mesa_enable_1_3_extensions(&(osmesa->gl_ctx)); - _mesa_enable_1_4_extensions(&(osmesa->gl_ctx)); - osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, - (GLboolean) ( osmesa->gl_visual->depthBits > 0 ), - (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ), - (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ), - GL_FALSE /* s/w alpha */ ); +/* RGBA */ +#define NAME(PREFIX) PREFIX##_RGBA +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLchan *P = osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#if CHAN_TYPE == GL_FLOAT +#define STORE_RGB_PIXEL(P, R, G, B) \ + P[0] = MAX2((R), 0.0F); + P[1] = MAX2((G), 0.0F); + P[2] = MAX2((B), 0.0F); + P[3] = CHAN_MAXF +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + P[0] = MAX2((R), 0.0F); + P[1] = MAX2((G), 0.0F); + P[2] = MAX2((B), 0.0F); + P[3] = CLAMP((A), 0.0F, CHAN_MAXF) +#else +#define STORE_RGB_PIXEL(P, R, G, B) \ + P[0] = R; P[1] = G; P[2] = B; P[3] = CHAN_MAX +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + P[0] = R; P[1] = G; P[2] = B; P[3] = A +#endif +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ + R = P[0]; G = P[1]; B = P[2]; A = P[3] +#include "swrast/s_spantemp.h" - if (!osmesa->gl_buffer) { - _mesa_destroy_visual( osmesa->gl_visual ); - _mesa_free_context_data( &osmesa->gl_ctx ); - FREE(osmesa); - return NULL; - } - osmesa->format = format; - osmesa->buffer = NULL; - osmesa->width = 0; - osmesa->height = 0; - osmesa->userRowLength = 0; - osmesa->rowlength = 0; - osmesa->yup = GL_TRUE; - osmesa->rshift = rshift; - osmesa->gshift = gshift; - osmesa->bshift = bshift; - osmesa->ashift = ashift; - osmesa->rInd = rind; - osmesa->gInd = gind; - osmesa->bInd = bind; - osmesa->aInd = aind; +/* BGRA */ +#define NAME(PREFIX) PREFIX##_BGRA +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLchan *P = osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_RGB_PIXEL(P, R, G, B) \ + P[2] = R; P[1] = G; P[0] = B; P[3] = CHAN_MAX +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + P[2] = R; P[1] = G; P[0] = B; P[3] = A +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ + R = P[2]; G = P[1]; B = P[0]; A = P[3] +#include "swrast/s_spantemp.h" + +/* ARGB */ +#define NAME(PREFIX) PREFIX##_ARGB +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLchan *P = osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_RGB_PIXEL(P, R, G, B) \ + P[1] = R; P[2] = G; P[3] = B; P[0] = CHAN_MAX +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + P[1] = R; P[2] = G; P[3] = B; P[0] = A +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ + R = P[1]; G = P[2]; B = P[3]; A = P[0] +#include "swrast/s_spantemp.h" + +/* RGB */ +#define NAME(PREFIX) PREFIX##_RGB +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLchan *P = osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_RGB_PIXEL(P, R, G, B) \ + P[0] = R; P[1] = G; P[2] = B +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + P[0] = R; P[1] = G; P[2] = B +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ + R = P[0]; G = P[1]; B = P[2]; A = CHAN_MAX +#include "swrast/s_spantemp.h" + +/* BGR */ +#define NAME(PREFIX) PREFIX##_BGR +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLchan *P = osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_RGB_PIXEL(P, R, G, B) \ + P[0] = B; P[1] = G; P[2] = R +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + P[0] = B; P[1] = G; P[2] = R +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ + B = P[0]; G = P[1]; R = P[2]; A = CHAN_MAX +#include "swrast/s_spantemp.h" + +/* 16-bit BGR */ +#define NAME(PREFIX) PREFIX##_RGB_565 +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_RGB_PIXEL(P, R, G, B) \ + *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) +#define STORE_RGBA_PIXEL(P, R, G, B, A) \ + *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ + R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \ + G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \ + B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \ + A = CHAN_MAX +#include "swrast/s_spantemp.h" + +/* color index */ +#define NAME(PREFIX) PREFIX##_CI +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLchan *P = osmesa->rowaddr[Y] + (X) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_CI_PIXEL(P, CI) \ + P[0] = CI +#define FETCH_CI_PIXEL(CI, P) \ + CI = P[0] +#include "swrast/s_spantemp.h" - /* Initialize the software rasterizer and helper modules. - */ - { - GLcontext *ctx = &osmesa->gl_ctx; +/**********************************************************************/ +/***** Optimized line rendering *****/ +/**********************************************************************/ - _swrast_CreateContext( ctx ); - _ac_CreateContext( ctx ); - _tnl_CreateContext( ctx ); - _swsetup_CreateContext( ctx ); - - _swsetup_Wakeup( ctx ); - osmesa_register_swrast_functions( ctx ); - } - } - return osmesa; -} +#if CHAN_TYPE == GL_FLOAT +#define PACK_RGBA(DST, R, G, B, A) \ +do { \ + (DST)[0] = MAX2( R, 0.0F ); \ + (DST)[1] = MAX2( G, 0.0F ); \ + (DST)[2] = MAX2( B, 0.0F ); \ + (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\ +} while (0) +#else +#define PACK_RGBA(DST, R, G, B, A) \ +do { \ + (DST)[osmesa->rInd] = R; \ + (DST)[osmesa->gInd] = G; \ + (DST)[osmesa->bInd] = B; \ + (DST)[osmesa->aInd] = A; \ +} while (0) +#endif + +#define PACK_RGB(DST, R, G, B) \ +do { \ + (DST)[0] = R; \ + (DST)[1] = G; \ + (DST)[2] = B; \ +} while (0) + +#define PACK_BGR(DST, R, G, B) \ +do { \ + (DST)[0] = B; \ + (DST)[1] = G; \ + (DST)[2] = R; \ +} while (0) + +#define PACK_RGB_565(DST, R, G, B) \ +do { \ + (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\ +} while (0) + +#define UNPACK_RED(P) ( (P)[osmesa->rInd] ) +#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] ) +#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] ) +#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] ) +#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X)) +#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X)) +#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X)) +#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X)) /* - * Destroy an Off-Screen Mesa rendering context. - * - * Input: ctx - the context to destroy + * Draw a flat-shaded, RGB line into an osmesa buffer. */ -GLAPI void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx ) +static void +flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - if (ctx) { - _swsetup_DestroyContext( &ctx->gl_ctx ); - _tnl_DestroyContext( &ctx->gl_ctx ); - _ac_DestroyContext( &ctx->gl_ctx ); - _swrast_DestroyContext( &ctx->gl_ctx ); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLchan *color = vert1->color; - _mesa_destroy_visual( ctx->gl_visual ); - _mesa_destroy_framebuffer( ctx->gl_buffer ); - _mesa_free_context_data( &ctx->gl_ctx ); - FREE( ctx ); - } -} +#define INTERP_XY 1 +#define CLIP_HACK 1 +#define PLOT(X, Y) \ +do { \ + GLchan *p = PIXELADDR4(X, Y); \ + PACK_RGBA(p, color[0], color[1], color[2], color[3]); \ +} while (0) +#ifdef WIN32 +#include "..\swrast\s_linetemp.h" +#else +#include "swrast/s_linetemp.h" +#endif +} /* - * Recompute the values of the context's rowaddr array. + * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. */ -static void compute_row_addresses( OSMesaContext ctx ) +static void +flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) { - GLint bytesPerPixel, bytesPerRow, i; - GLubyte *origin = (GLubyte *) ctx->buffer; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLchan *color = vert1->color; - if (ctx->format == OSMESA_COLOR_INDEX) { - /* CI mode */ - bytesPerPixel = 1 * sizeof(GLchan); - } - else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { - /* RGB mode */ - bytesPerPixel = 3 * sizeof(GLchan); - } - else if (ctx->format == OSMESA_RGB_565) { - /* 5/6/5 RGB pixel in 16 bits */ - bytesPerPixel = 2; - } - else { - /* RGBA mode */ - bytesPerPixel = 4 * sizeof(GLchan); - } +#define INTERP_XY 1 +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define CLIP_HACK 1 +#define PLOT(X, Y) \ +do { \ + if (Z < *zPtr) { \ + GLchan *p = PIXELADDR4(X, Y); \ + PACK_RGBA(p, color[RCOMP], color[GCOMP], \ + color[BCOMP], color[ACOMP]); \ + *zPtr = Z; \ + } \ +} while (0) - bytesPerRow = ctx->rowlength * bytesPerPixel; - if (ctx->yup) { - /* Y=0 is bottom line of window */ - for (i = 0; i < MAX_HEIGHT; i++) { - ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); - } - } - else { - /* Y=0 is top line of window */ - for (i = 0; i < MAX_HEIGHT; i++) { - GLint j = ctx->height - i - 1; - ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); - } - } +#ifdef WIN32 +#include "..\swrast\s_linetemp.h" +#else +#include "swrast/s_linetemp.h" +#endif } /* - * Bind an OSMesaContext to an image buffer. The image buffer is just a - * block of memory which the client provides. Its size must be at least - * as large as width*height*sizeof(type). Its address should be a multiple - * of 4 if using RGBA mode. - * - * Image data is stored in the order of glDrawPixels: row-major order - * with the lower-left image pixel stored in the first array position - * (ie. bottom-to-top). - * - * If the context's viewport hasn't been initialized yet, it will now be - * initialized to (0,0,width,height). - * - * Input: ctx - the rendering context - * buffer - the image buffer memory - * type - data type for pixel components - * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 - * are supported. But if Mesa's been compiled with CHAN_BITS==16 - * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build - * with CHAN_BITS==32 then type must be GL_FLOAT. - * width, height - size of image buffer in pixels, at least 1 - * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, - * invalid buffer address, invalid type, width<1, height<1, - * width>internal limit or height>internal limit. + * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer. + * XXX update for GLchan */ -GLAPI GLboolean GLAPIENTRY -OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, - GLsizei width, GLsizei height ) +static void +flat_blend_rgba_line( GLcontext *ctx, + const SWvertex *vert0, const SWvertex *vert1 ) { - if (!ctx || !buffer || - width < 1 || height < 1 || - width > MAX_WIDTH || height > MAX_HEIGHT) { - return GL_FALSE; - } + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLint rshift = osmesa->rshift; + const GLint gshift = osmesa->gshift; + const GLint bshift = osmesa->bshift; + const GLint avalue = vert0->color[3]; + const GLint msavalue = CHAN_MAX - avalue; + const GLint rvalue = vert1->color[0]*avalue; + const GLint gvalue = vert1->color[1]*avalue; + const GLint bvalue = vert1->color[2]*avalue; - if (ctx->format == OSMESA_RGB_565) { - if (type != GL_UNSIGNED_SHORT_5_6_5) - return GL_FALSE; +#define INTERP_XY 1 +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ + GLuint pixel = 0; \ + pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ + pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ + pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ + *ptr4 = pixel; \ } - else if (type != CHAN_TYPE) { - return GL_FALSE; + +#if 0 /* XXX use this in the future */ +#define PLOT(X,Y) \ + { \ + GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ + pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ + pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ + pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ + pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ } +#endif - osmesa_update_state( &ctx->gl_ctx, 0 ); - _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer ); +#ifdef WIN32 +#include "..\swrast\s_linetemp.h" +#else +#include "swrast/s_linetemp.h" +#endif +} - ctx->buffer = buffer; - ctx->width = width; - ctx->height = height; - if (ctx->userRowLength) - ctx->rowlength = ctx->userRowLength; - else - ctx->rowlength = width; - compute_row_addresses( ctx ); +/* + * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. + * But don't write to Z buffer. + * XXX update for GLchan + */ +static void +flat_blend_rgba_z_line( GLcontext *ctx, + const SWvertex *vert0, const SWvertex *vert1 ) +{ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLint rshift = osmesa->rshift; + const GLint gshift = osmesa->gshift; + const GLint bshift = osmesa->bshift; + const GLint avalue = vert0->color[3]; + const GLint msavalue = 256 - avalue; + const GLint rvalue = vert1->color[0]*avalue; + const GLint gvalue = vert1->color[1]*avalue; + const GLint bvalue = vert1->color[2]*avalue; - /* init viewport */ - if (ctx->gl_ctx.Viewport.Width == 0) { - /* initialize viewport and scissor box to buffer size */ - _mesa_Viewport( 0, 0, width, height ); - ctx->gl_ctx.Scissor.Width = width; - ctx->gl_ctx.Scissor.Height = height; - } - else { - /* this will make ensure we recognize the new buffer size */ - _mesa_ResizeBuffersMESA(); - } +#define INTERP_XY 1 +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ + GLuint pixel = 0; \ + pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ + pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ + pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ + *ptr4 = pixel; \ + } - /* Added by Gerk Huisma: */ - _tnl_MakeCurrent( &ctx->gl_ctx, ctx->gl_ctx.DrawBuffer, - ctx->gl_ctx.ReadBuffer ); +#if 0 /* XXX use this in the future */ +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ + pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ + pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ + pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ + pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ + } +#endif - return GL_TRUE; +#ifdef WIN32 +#include "..\swrast\s_linetemp.h" +#else +#include "swrast/s_linetemp.h" +#endif } - -GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) +/* + * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. + * XXX update for GLchan + */ +static void +flat_blend_rgba_z_line_write( GLcontext *ctx, + const SWvertex *vert0, const SWvertex *vert1 ) { - GLcontext *ctx = _mesa_get_current_context(); - if (ctx) - return (OSMesaContext) ctx; - else - return NULL; -} - - + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLint rshift = osmesa->rshift; + const GLint gshift = osmesa->gshift; + const GLint bshift = osmesa->bshift; + const GLint avalue = vert0->color[3]; + const GLint msavalue = 256 - avalue; + const GLint rvalue = vert1->color[0]*avalue; + const GLint gvalue = vert1->color[1]*avalue; + const GLint bvalue = vert1->color[2]*avalue; -GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) -{ - OSMesaContext ctx = OSMesaGetCurrentContext(); +#define INTERP_XY 1 +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ + GLuint pixel = 0; \ + pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ + pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ + pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ + *ptr4 = pixel; \ + *zPtr = Z; \ + } - switch (pname) { - case OSMESA_ROW_LENGTH: - if (value<0) { - _mesa_error( &ctx->gl_ctx, GL_INVALID_VALUE, - "OSMesaPixelStore(value)" ); - return; - } - ctx->userRowLength = value; - ctx->rowlength = value; - break; - case OSMESA_Y_UP: - ctx->yup = value ? GL_TRUE : GL_FALSE; - break; - default: - _mesa_error( &ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); - return; +#if 0 /* XXX use this in the future */ +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ + pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ + pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ + pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ + pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ + *zPtr = Z; \ } +#endif - compute_row_addresses( ctx ); +#ifdef WIN32 +#include "..\swrast\s_linetemp.h" +#else +#include "swrast/s_linetemp.h" +#endif } -GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) +/* + * Analyze context state to see if we can provide a fast line drawing + * function, like those in lines.c. Otherwise, return NULL. + */ +static swrast_line_func +osmesa_choose_line_function( GLcontext *ctx ) { - OSMesaContext ctx = OSMesaGetCurrentContext(); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const SWcontext *swrast = SWRAST_CONTEXT(ctx); - switch (pname) { - case OSMESA_WIDTH: - *value = ctx->width; - return; - case OSMESA_HEIGHT: - *value = ctx->height; - return; - case OSMESA_FORMAT: - *value = ctx->format; - return; - case OSMESA_TYPE: - *value = CHAN_TYPE; - return; - case OSMESA_ROW_LENGTH: - *value = ctx->rowlength; - return; - case OSMESA_Y_UP: - *value = ctx->yup; - return; - case OSMESA_MAX_WIDTH: - *value = MAX_WIDTH; - return; - case OSMESA_MAX_HEIGHT: - *value = MAX_HEIGHT; - return; - default: - _mesa_error(&ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); - return; + if (CHAN_BITS != 8) return NULL; + if (ctx->RenderMode != GL_RENDER) return NULL; + if (ctx->Line.SmoothFlag) return NULL; + if (ctx->Texture._EnabledUnits) return NULL; + if (ctx->Light.ShadeModel != GL_FLAT) return NULL; + if (ctx->Line.Width != 1.0F) return NULL; + if (ctx->Line.StippleFlag) return NULL; + if (ctx->Line.SmoothFlag) return NULL; + if (osmesa->format != OSMESA_RGBA && + osmesa->format != OSMESA_BGRA && + osmesa->format != OSMESA_ARGB) return NULL; + + if (swrast->_RasterMask==DEPTH_BIT + && ctx->Depth.Func==GL_LESS + && ctx->Depth.Mask==GL_TRUE + && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { + return (swrast_line_func) flat_rgba_z_line; } -} -/* - * Return the depth buffer associated with an OSMesa context. - * Input: c - the OSMesa context - * Output: width, height - size of buffer in pixels - * bytesPerValue - bytes per depth value (2 or 4) - * buffer - pointer to depth buffer values - * Return: GL_TRUE or GL_FALSE to indicate success or failure. - */ -GLAPI GLboolean GLAPIENTRY -OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, - GLint *bytesPerValue, void **buffer ) -{ - if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { - *width = 0; - *height = 0; - *bytesPerValue = 0; - *buffer = 0; - return GL_FALSE; + if (swrast->_RasterMask == 0) { + return (swrast_line_func) flat_rgba_line; } - else { - *width = c->gl_buffer->Width; - *height = c->gl_buffer->Height; - if (c->gl_visual->depthBits <= 16) - *bytesPerValue = sizeof(GLushort); - else - *bytesPerValue = sizeof(GLuint); - *buffer = c->gl_buffer->DepthBuffer; - return GL_TRUE; + + if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT) + && ctx->Depth.Func==GL_LESS + && ctx->Depth.Mask==GL_TRUE + && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS + && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA + && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA + && ctx->Color.BlendSrcA==GL_SRC_ALPHA + && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA + && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { + return (swrast_line_func) flat_blend_rgba_z_line_write; + } + + if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT) + && ctx->Depth.Func==GL_LESS + && ctx->Depth.Mask==GL_FALSE + && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS + && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA + && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA + && ctx->Color.BlendSrcA==GL_SRC_ALPHA + && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA + && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { + return (swrast_line_func) flat_blend_rgba_z_line; + } + + if (swrast->_RasterMask==BLEND_BIT + && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA + && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA + && ctx->Color.BlendSrcA==GL_SRC_ALPHA + && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA + && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { + return (swrast_line_func) flat_blend_rgba_line; } + + return (swrast_line_func) NULL; } + +/**********************************************************************/ +/***** Optimized triangle rendering *****/ +/**********************************************************************/ + + /* - * Return the color buffer associated with an OSMesa context. - * Input: c - the OSMesa context - * Output: width, height - size of buffer in pixels - * format - the pixel format (OSMESA_FORMAT) - * buffer - pointer to color buffer values - * Return: GL_TRUE or GL_FALSE to indicate success or failure. + * Smooth-shaded, z-less triangle, RGBA color. */ -GLAPI GLboolean GLAPIENTRY -OSMesaGetColorBuffer( OSMesaContext c, GLint *width, - GLint *height, GLint *format, void **buffer ) -{ - if (!c->buffer) { - *width = 0; - *height = 0; - *format = 0; - *buffer = 0; - return GL_FALSE; - } - else { - *width = c->width; - *height = c->height; - *format = c->format; - *buffer = c->buffer; - return GL_TRUE; - } -} - - - -struct name_address { - const char *Name; - GLvoid *Address; -}; - -static struct name_address functions[] = { - { "OSMesaCreateContext", (void *) OSMesaCreateContext }, - { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt }, - { "OSMesaDestroyContext", (void *) OSMesaDestroyContext }, - { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent }, - { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext }, - { "OSMesaPixelsStore", (void *) OSMesaPixelStore }, - { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv }, - { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer }, - { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer }, - { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress }, - { NULL, NULL } -}; - -GLAPI void * GLAPIENTRY -OSMesaGetProcAddress( const char *funcName ) -{ - int i; - for (i = 0; functions[i].Name; i++) { - if (_mesa_strcmp(functions[i].Name, funcName) == 0) - return (void *) functions[i].Address; +#define NAME smooth_rgba_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define SETUP_CODE \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLchan *img = PIXELADDR4(span.x, span.y); \ + for (i = 0; i < span.end; i++, img += 4) { \ + const GLdepth z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + PACK_RGBA(img, FixedToChan(span.red), \ + FixedToChan(span.green), FixedToChan(span.blue), \ + FixedToChan(span.alpha)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.alpha += span.alphaStep; \ + span.z += span.zStep; \ } - return (void *) _glapi_get_proc_address(funcName); -} - +#ifdef WIN32 +#include "..\swrast\s_tritemp.h" +#else +#include "swrast/s_tritemp.h" +#endif -/**********************************************************************/ -/*** Device Driver Functions ***/ -/**********************************************************************/ /* - * Useful macros: + * Flat-shaded, z-less triangle, RGBA color. */ +#define NAME flat_rgba_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define SETUP_CODE \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ + GLuint pixel; \ + PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ + v2->color[2], v2->color[3]); -#if CHAN_TYPE == GL_FLOAT -#define PACK_RGBA(DST, R, G, B, A) \ -do { \ - (DST)[0] = MAX2( R, 0.0F ); \ - (DST)[1] = MAX2( G, 0.0F ); \ - (DST)[2] = MAX2( B, 0.0F ); \ - (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\ -} while (0) +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ + for (i = 0; i < span.end; i++) { \ + const GLdepth z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + img[i] = pixel; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#ifdef WIN32 +#include "..\swrast\s_tritemp.h" #else -#define PACK_RGBA(DST, R, G, B, A) \ -do { \ - (DST)[osmesa->rInd] = R; \ - (DST)[osmesa->gInd] = G; \ - (DST)[osmesa->bInd] = B; \ - (DST)[osmesa->aInd] = A; \ -} while (0) +#include "swrast/s_tritemp.h" #endif -#define PACK_RGB(DST, R, G, B) \ -do { \ - (DST)[0] = R; \ - (DST)[1] = G; \ - (DST)[2] = B; \ -} while (0) - -#define PACK_BGR(DST, R, G, B) \ -do { \ - (DST)[0] = B; \ - (DST)[1] = G; \ - (DST)[2] = R; \ -} while (0) - -#define PACK_RGB_565(DST, R, G, B) \ -do { \ - (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\ -} while (0) - - -#define UNPACK_RED(P) ( (P)[osmesa->rInd] ) -#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] ) -#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] ) -#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] ) - - -#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X)) -#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X)) -#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X)) -#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X)) - -static void set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) -{ - /* separate read buffer not supported */ - ASSERT(buffer == ctx->DrawBuffer); - ASSERT(bufferBit == FRONT_LEFT_BIT); -} - - -static void clear( GLcontext *ctx, GLbitfield mask, GLboolean all, - GLint x, GLint y, GLint width, GLint height ) +/* + * Return pointer to an accelerated triangle function if possible. + */ +static swrast_tri_func +osmesa_choose_triangle_function( GLcontext *ctx ) { - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const SWcontext *swrast = SWRAST_CONTEXT(ctx); - /* sanity check - we only have a front-left buffer */ - ASSERT((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT)) == 0); - if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { - if (mask & DD_FRONT_LEFT_BIT) { - if (osmesa->format == OSMESA_COLOR_INDEX) { - if (all) { - /* Clear whole CI buffer */ -#if CHAN_TYPE == GL_UNSIGNED_BYTE - MEMSET(osmesa->buffer, ctx->Color.ClearIndex, - osmesa->rowlength * osmesa->height); -#else - const GLint n = osmesa->rowlength * osmesa->height; - GLchan *buffer = (GLchan *) osmesa->buffer; - GLint i; - for (i = 0; i < n; i ++) { - buffer[i] = ctx->Color.ClearIndex; - } -#endif - } - else { - /* Clear part of CI buffer */ - const GLchan clearIndex = (GLchan) ctx->Color.ClearIndex; - GLint i, j; - for (i = 0; i < height; i++) { - GLchan *ptr1 = PIXELADDR1(x, (y + i)); - for (j = 0; j < width; j++) { - *ptr1++ = clearIndex; - } - } - } - } - else if (osmesa->format == OSMESA_RGB) { - GLchan r, g, b; - CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]); - if (all) { - /* Clear whole RGB buffer */ - GLuint n = osmesa->rowlength * osmesa->height; - GLchan *ptr3 = (GLchan *) osmesa->buffer; - GLuint i; - for (i = 0; i < n; i++) { - PACK_RGB(ptr3, r, g, b); - ptr3 += 3; - } - } - else { - /* Clear part of RGB buffer */ - GLint i, j; - for (i = 0; i < height; i++) { - GLchan *ptr3 = PIXELADDR3(x, (y + i)); - for (j = 0; j < width; j++) { - PACK_RGB(ptr3, r, g, b); - ptr3 += 3; - } - } - } - } - else if (osmesa->format == OSMESA_BGR) { - GLchan r, g, b; - CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]); - if (all) { - /* Clear whole RGB buffer */ - const GLint n = osmesa->rowlength * osmesa->height; - GLchan *ptr3 = (GLchan *) osmesa->buffer; - GLint i; - for (i = 0; i < n; i++) { - PACK_BGR(ptr3, r, g, b); - ptr3 += 3; - } - } - else { - /* Clear part of RGB buffer */ - GLint i, j; - for (i = 0; i < height; i++) { - GLchan *ptr3 = PIXELADDR3(x, (y + i)); - for (j = 0; j < width; j++) { - PACK_BGR(ptr3, r, g, b); - ptr3 += 3; - } - } - } - } - else if (osmesa->format == OSMESA_RGB_565) { - GLushort clearPixel; - GLchan r, g, b; - CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]); - PACK_RGB_565(clearPixel, r, g, b); - if (all) { - /* Clear whole RGB buffer */ - const GLuint n = osmesa->rowlength * osmesa->height; - GLushort *ptr2 = (GLushort *) osmesa->buffer; - GLuint i; - for (i = 0; i < n; i++) { - *ptr2 = clearPixel; - ptr2++; - } - } - else { - /* clear scissored region */ - GLint i, j; - for (i = 0; i < height; i++) { - GLushort *ptr2 = (GLushort *) PIXELADDR2(x, (y + i)); - for (j = 0; j < width; j++) { - *ptr2 = clearPixel; - ptr2++; - } - } - } - } - else { -#if CHAN_TYPE == GL_UNSIGNED_BYTE - /* 4-byte pixel value */ - GLuint clearPixel; - GLchan *clr = (GLchan *) &clearPixel; - CLAMPED_FLOAT_TO_CHAN(clr[osmesa->rInd], ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(clr[osmesa->gInd], ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(clr[osmesa->bInd], ctx->Color.ClearColor[2]); - CLAMPED_FLOAT_TO_CHAN(clr[osmesa->aInd], ctx->Color.ClearColor[3]); - if (all) { - /* Clear whole RGBA buffer */ - const GLuint n = osmesa->rowlength * osmesa->height; - GLuint *ptr4 = (GLuint *) osmesa->buffer; - GLuint i; - if (clearPixel) { - for (i = 0; i < n; i++) { - *ptr4++ = clearPixel; - } - } - else { - _mesa_bzero(ptr4, n * sizeof(GLuint)); - } - } - else { - /* Clear part of RGBA buffer */ - GLint i, j; - for (i = 0; i < height; i++) { - GLuint *ptr4 = (GLuint *) PIXELADDR4(x, (y + i)); - for (j = 0; j < width; j++) { - *ptr4++ = clearPixel; - } - } - } -#else - GLchan r, g, b, a; - CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]); - CLAMPED_FLOAT_TO_CHAN(a, ctx->Color.ClearColor[3]); - if (all) { - /* Clear whole RGBA buffer */ - const GLuint n = osmesa->rowlength * osmesa->height; - GLchan *p = (GLchan *) osmesa->buffer; - GLuint i; - for (i = 0; i < n; i++) { - PACK_RGBA(p, r, g, b, a); - p += 4; - } - } - else { - /* Clear part of RGBA buffer */ - GLint i, j; - for (i = 0; i < height; i++) { - GLchan *p = PIXELADDR4(x, (y + i)); - for (j = 0; j < width; j++) { - PACK_RGBA(p, r, g, b, a); - p += 4; - } - } - } + if (CHAN_BITS != 8) return (swrast_tri_func) NULL; + if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; + if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; + if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; + if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; + if (osmesa->format != OSMESA_RGBA && + osmesa->format != OSMESA_BGRA && + osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL; + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) + return (swrast_tri_func) NULL; -#endif - } - mask &= ~DD_FRONT_LEFT_BIT; + if (swrast->_RasterMask == DEPTH_BIT && + ctx->Depth.Func == GL_LESS && + ctx->Depth.Mask == GL_TRUE && + ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { + if (ctx->Light.ShadeModel == GL_SMOOTH) { + return (swrast_tri_func) smooth_rgba_z_triangle; + } + else { + return (swrast_tri_func) flat_rgba_z_triangle; } } - - if (mask) - _swrast_Clear( ctx, mask, all, x, y, width, height ); + return (swrast_tri_func) NULL; } -static void buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) +/* Override for the swrast triangle-selection function. Try to use one + * of our internal triangle functions, otherwise fall back to the + * standard swrast functions. + */ +static void +osmesa_choose_triangle( GLcontext *ctx ) { - /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */ - GLcontext *ctx = (GLcontext *) _glapi_get_context(); - (void) buffer; - if (ctx) { - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - *width = osmesa->width; - *height = osmesa->height; - } -} - + SWcontext *swrast = SWRAST_CONTEXT(ctx); -/**********************************************************************/ -/***** Read/write spans/arrays of RGBA pixels *****/ -/**********************************************************************/ + swrast->Triangle = osmesa_choose_triangle_function( ctx ); + if (!swrast->Triangle) + _swrast_choose_triangle( ctx ); +} -/* Write RGBA pixels to an RGBA (or permuted) buffer. */ static void -write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgba[][4], const GLubyte mask[] ) +osmesa_choose_line( GLcontext *ctx ) { - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR4(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, p += 4) { - if (mask[i]) { - PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP], - rgba[i][BCOMP], rgba[i][ACOMP]); - } - } - } - else { - for (i = 0; i < n; i++, p += 4) { - PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP], - rgba[i][BCOMP], rgba[i][ACOMP]); - } - } + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + swrast->Line = osmesa_choose_line_function( ctx ); + if (!swrast->Line) + _swrast_choose_line( ctx ); } -/* Write RGBA pixels to an RGBA buffer. This is the fastest span-writer. */ +#define OSMESA_NEW_LINE (_NEW_LINE | \ + _NEW_TEXTURE | \ + _NEW_LIGHT | \ + _NEW_DEPTH | \ + _NEW_RENDERMODE | \ + _SWRAST_NEW_RASTERMASK) + +#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \ + _NEW_TEXTURE | \ + _NEW_LIGHT | \ + _NEW_DEPTH | \ + _NEW_RENDERMODE | \ + _SWRAST_NEW_RASTERMASK) + +/* one-time, per-context initialization */ static void -write_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgba[][4], const GLubyte mask[] ) +hook_in_driver_functions( GLcontext *ctx ) { OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y); - const GLuint *rgba4 = (const GLuint *) rgba; - GLuint i; - ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE); - if (mask) { - for (i = 0; i < n; i++) { - if (mask[i]) { - ptr4[i] = rgba4[i]; - } - } - } - else { - MEMCPY( ptr4, rgba4, n * 4 ); - } -} - - -/* Write RGB pixels to an RGBA (or permuted) buffer. */ -static void -write_rgb_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgb[][3], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR4(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, p+=4) { - if (mask[i]) { - PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], CHAN_MAX); - } - } - } - else { - for (i = 0; i < n; i++, p+=4) { - PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], CHAN_MAX); - } - } -} + SWcontext *swrast = SWRAST_CONTEXT( ctx ); + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + ASSERT((void *) osmesa == (void *) ctx->DriverCtx); + /* use default TCL pipeline */ + tnl->Driver.RunPipeline = _tnl_run_pipeline; -static void -write_monocolor_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLchan color[4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR4(x, y); - GLuint i; - for (i = 0; i < n; i++, p += 4) { - if (mask[i]) { - PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]); - } - } -} + ctx->Driver.GetString = get_string; + ctx->Driver.UpdateState = osmesa_update_state; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; + ctx->Driver.GetBufferSize = get_buffer_size; + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.Bitmap = _swrast_Bitmap; + ctx->Driver.Clear = clear; /* = _swrast_Clear */ + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + ctx->Driver.DrawBuffer = _swrast_DrawBuffer; + ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage2D = _mesa_store_teximage2d; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; -static void -write_rgba_pixels( const GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLchan *p = PIXELADDR4(x[i], y[i]); - PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP], - rgba[i][BCOMP], rgba[i][ACOMP]); - } - } -} + ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; + ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; + ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; + ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d; + ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; + ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + swdd->SetBuffer = set_buffer; -static void -write_monocolor_pixels( const GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - const GLchan color[4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLchan *p = PIXELADDR4(x[i], y[i]); - PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]); - } + /* RGB(A) span/pixel functions */ + if (osmesa->format == OSMESA_RGB) { + swdd->WriteRGBASpan = write_rgba_span_RGB; + swdd->WriteRGBSpan = write_rgb_span_RGB; + swdd->WriteMonoRGBASpan = write_monorgba_span_RGB; + swdd->WriteRGBAPixels = write_rgba_pixels_RGB; + swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB; + swdd->ReadRGBASpan = read_rgba_span_RGB; + swdd->ReadRGBAPixels = read_rgba_pixels_RGB; } -} - - -static void -read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, - GLchan rgba[][4] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - GLchan *p = PIXELADDR4(x, y); - for (i = 0; i < n; i++, p += 4) { - rgba[i][RCOMP] = UNPACK_RED(p); - rgba[i][GCOMP] = UNPACK_GREEN(p); - rgba[i][BCOMP] = UNPACK_BLUE(p); - rgba[i][ACOMP] = UNPACK_ALPHA(p); + else if (osmesa->format == OSMESA_BGR) { + swdd->WriteRGBASpan = write_rgba_span_BGR; + swdd->WriteRGBSpan = write_rgb_span_BGR; + swdd->WriteMonoRGBASpan = write_monorgba_span_BGR; + swdd->WriteRGBAPixels = write_rgba_pixels_BGR; + swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR; + swdd->ReadRGBASpan = read_rgba_span_BGR; + swdd->ReadRGBAPixels = read_rgba_pixels_BGR; + } + else if (osmesa->format == OSMESA_RGB_565) { + swdd->WriteRGBASpan = write_rgba_span_RGB_565; + swdd->WriteRGBSpan = write_rgb_span_RGB_565; + swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565; + swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565; + swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565; + swdd->ReadRGBASpan = read_rgba_span_RGB_565; + swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565; + } + else if (osmesa->format == OSMESA_RGBA) { + swdd->WriteRGBASpan = write_rgba_span_RGBA; + swdd->WriteRGBSpan = write_rgb_span_RGBA; + swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA; + swdd->WriteRGBAPixels = write_rgba_pixels_RGBA; + swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA; + swdd->ReadRGBASpan = read_rgba_span_RGBA; + swdd->ReadRGBAPixels = read_rgba_pixels_RGBA; + } + else if (osmesa->format == OSMESA_BGRA) { + swdd->WriteRGBASpan = write_rgba_span_BGRA; + swdd->WriteRGBSpan = write_rgb_span_BGRA; + swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA; + swdd->WriteRGBAPixels = write_rgba_pixels_BGRA; + swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA; + swdd->ReadRGBASpan = read_rgba_span_BGRA; + swdd->ReadRGBAPixels = read_rgba_pixels_BGRA; + } + else if (osmesa->format == OSMESA_ARGB) { + swdd->WriteRGBASpan = write_rgba_span_ARGB; + swdd->WriteRGBSpan = write_rgb_span_ARGB; + swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB; + swdd->WriteRGBAPixels = write_rgba_pixels_ARGB; + swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB; + swdd->ReadRGBASpan = read_rgba_span_ARGB; + swdd->ReadRGBAPixels = read_rgba_pixels_ARGB; + } + else if (osmesa->format == OSMESA_COLOR_INDEX) { + swdd->WriteCI32Span = write_index32_span_CI; + swdd->WriteCI8Span = write_index8_span_CI; + swdd->WriteMonoCISpan = write_monoindex_span_CI; + swdd->WriteCI32Pixels = write_index_pixels_CI; + swdd->WriteMonoCIPixels = write_monoindex_pixels_CI; + swdd->ReadCI32Span = read_index_span_CI; + swdd->ReadCI32Pixels = read_index_pixels_CI; + } + else { + _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n"); } -} - -/* Read RGBA pixels from an RGBA buffer */ -static void -read_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y, - GLchan rgba[][4] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y); - MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) ); + /* Extend the software rasterizer with our optimized line and triangle + * drawin functions. + */ + swrast->choose_line = osmesa_choose_line; + swrast->choose_triangle = osmesa_choose_triangle; + swrast->invalidate_line |= OSMESA_NEW_LINE; + swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE; } -static void -read_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - const GLchan *p = PIXELADDR4(x[i], y[i]); - rgba[i][RCOMP] = UNPACK_RED(p); - rgba[i][GCOMP] = UNPACK_GREEN(p); - rgba[i][BCOMP] = UNPACK_BLUE(p); - rgba[i][ACOMP] = UNPACK_ALPHA(p); - } - } -} + /**********************************************************************/ -/***** 3 byte RGB pixel support funcs *****/ +/***** Public Functions *****/ /**********************************************************************/ -/* Write RGBA pixels to an RGB buffer. */ -static void -write_rgba_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR3(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, p += 3) { - if (mask[i]) { - PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } - } - else { - for (i = 0; i < n; i++, p += 3) { - PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } -} - -/* Write RGBA pixels to an BGR buffer. */ -static void -write_rgba_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR3(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, p += 3) { - if (mask[i]) { - PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } - } - else { - for (i = 0; i < n; i++, p += 3) { - PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } -} - -/* Write RGB pixels to an RGB buffer. */ -static void -write_rgb_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgb[][3], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR3(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, p += 3) { - if (mask[i]) { - PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); - } - } - } - else { - for (i = 0; i < n; i++, p += 3) { - PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); - } - } -} -/* Write RGB pixels to an BGR buffer. */ -static void -write_rgb_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgb[][3], const GLubyte mask[] ) +/* + * Create an Off-Screen Mesa rendering context. The only attribute needed is + * an RGBA vs Color-Index mode flag. + * + * Input: format - either GL_RGBA or GL_COLOR_INDEX + * sharelist - specifies another OSMesaContext with which to share + * display lists. NULL indicates no sharing. + * Return: an OSMesaContext or 0 if error + */ +GLAPI OSMesaContext GLAPIENTRY +OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) { - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR3(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, p += 3) { - if (mask[i]) { - PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); - } - } - } - else { - for (i = 0; i < n; i++, p += 3) { - PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); - } - } + return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, + 8, 16, sharelist); } -static void -write_monocolor_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLchan color[4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR3(x, y); - GLuint i; - for (i = 0; i < n; i++, p += 3) { - if (mask[i]) { - PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]); - } - } -} -static void -write_monocolor_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLchan color[4], const GLubyte mask[] ) +/* + * New in Mesa 3.5 + * + * Create context and specify size of ancillary buffers. + */ +GLAPI OSMesaContext GLAPIENTRY +OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, + GLint accumBits, OSMesaContext sharelist ) { - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *p = PIXELADDR3(x, y); - GLuint i; - for (i = 0; i < n; i++, p += 3) { - if (mask[i]) { - PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]); - } - } -} + OSMesaContext osmesa; + GLint rshift, gshift, bshift, ashift; + GLint rind, gind, bind, aind; + GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; + GLboolean rgbmode; + const GLuint i4 = 1; + const GLubyte *i1 = (GLubyte *) &i4; + const GLint little_endian = *i1; -static void -write_rgba_pixels_RGB( const GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = (const OSMesaContext) ctx; - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLchan *p = PIXELADDR3(x[i], y[i]); - PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } + rind = gind = bind = aind = 0; + if (format==OSMESA_COLOR_INDEX) { + indexBits = 8; + rshift = gshift = bshift = ashift = 0; + rgbmode = GL_FALSE; } -} - -static void -write_rgba_pixels_BGR( const GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = (const OSMesaContext) ctx; - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLchan *p = PIXELADDR3(x[i], y[i]); - PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); + else if (format==OSMESA_RGBA) { + indexBits = 0; + redBits = CHAN_BITS; + greenBits = CHAN_BITS; + blueBits = CHAN_BITS; + alphaBits = CHAN_BITS; + rind = 0; + gind = 1; + bind = 2; + aind = 3; + if (little_endian) { + rshift = 0; + gshift = 8; + bshift = 16; + ashift = 24; } - } -} - -static void -write_monocolor_pixels_RGB( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLchan color[4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLchan *p = PIXELADDR3(x[i], y[i]); - PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]); + else { + rshift = 24; + gshift = 16; + bshift = 8; + ashift = 0; } + rgbmode = GL_TRUE; } -} - -static void -write_monocolor_pixels_BGR( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLchan color[4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLchan *p = PIXELADDR3(x[i], y[i]); - PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]); + else if (format==OSMESA_BGRA) { + indexBits = 0; + redBits = CHAN_BITS; + greenBits = CHAN_BITS; + blueBits = CHAN_BITS; + alphaBits = CHAN_BITS; + bind = 0; + gind = 1; + rind = 2; + aind = 3; + if (little_endian) { + bshift = 0; + gshift = 8; + rshift = 16; + ashift = 24; } - } -} - -static void -read_rgba_span3( const GLcontext *ctx, GLuint n, GLint x, GLint y, - GLchan rgba[][4] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - const GLchan *p = PIXELADDR3(x, y); - for (i = 0; i < n; i++, p += 3) { - rgba[i][RCOMP] = UNPACK_RED(p); - rgba[i][GCOMP] = UNPACK_GREEN(p); - rgba[i][BCOMP] = UNPACK_BLUE(p); - rgba[i][ACOMP] = CHAN_MAX; - } -} - -static void -read_rgba_pixels3( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - const GLchan *p = PIXELADDR3(x[i], y[i]); - rgba[i][RCOMP] = UNPACK_RED(p); - rgba[i][GCOMP] = UNPACK_GREEN(p); - rgba[i][BCOMP] = UNPACK_BLUE(p); - rgba[i][ACOMP] = CHAN_MAX; + else { + bshift = 24; + gshift = 16; + rshift = 8; + ashift = 0; } + rgbmode = GL_TRUE; } -} - - -/**********************************************************************/ -/***** 2 byte RGB pixel support funcs *****/ -/**********************************************************************/ - -/* Write RGBA pixels to an RGB_565 buffer. */ -static void -write_rgba_span2( const GLcontext *ctx, - GLuint n, GLint x, GLint y, - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLushort *ptr2 = (GLushort *) PIXELADDR2(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, ptr2++) { - if (mask[i]) { - PACK_RGB_565(*ptr2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } - } - else { - for (i = 0; i < n; i++, ptr2++) { - PACK_RGB_565(*ptr2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } -} - - -/* Write RGB pixels to an RGB_565 buffer. */ -static void -write_rgb_span2( const GLcontext *ctx, - GLuint n, GLint x, GLint y, - CONST GLchan rgb[][3], const GLubyte mask[] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLushort *ptr2 = (GLushort *) PIXELADDR2(x, y); - GLuint i; - if (mask) { - for (i = 0; i < n; i++, ptr2++) { - if (mask[i]) { - PACK_RGB_565(*ptr2, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); - } - } - } - else { - for (i = 0; i < n; i++, ptr2++) { - PACK_RGB_565(*ptr2, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); - } - } -} - - -static void -write_monocolor_span2( const GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLchan color[4], const GLubyte mask[] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLushort pixel; - GLushort *ptr2 = (GLushort *) PIXELADDR2(x, y); - GLuint i; - PACK_RGB_565(pixel, color[RCOMP], color[GCOMP], color[BCOMP]); - for (i = 0; i < n; i++, ptr2++) { - if (mask[i]) { - *ptr2 = pixel; - } - } -} - - -static void -write_rgba_pixels2( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - CONST GLchan rgba[][4], const GLubyte mask[] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - GLushort *ptr2 = (GLushort *) PIXELADDR2(x[i],y[i]); - PACK_RGB_565(*ptr2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); - } - } -} - -static void -write_monocolor_pixels2( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLchan color[4], const GLubyte mask[] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - GLushort pixel; - PACK_RGB_565(pixel, color[RCOMP], color[GCOMP], color[BCOMP]); - for (i = 0; i < n; i++) { - if (mask[i]) { - GLushort *ptr2 = (GLushort *) PIXELADDR2(x[i],y[i]); - *ptr2 = pixel; + else if (format==OSMESA_ARGB) { + indexBits = 0; + redBits = CHAN_BITS; + greenBits = CHAN_BITS; + blueBits = CHAN_BITS; + alphaBits = CHAN_BITS; + aind = 0; + rind = 1; + gind = 2; + bind = 3; + if (little_endian) { + ashift = 0; + rshift = 8; + gshift = 16; + bshift = 24; } - } -} - -static void -read_rgba_span2( const GLcontext *ctx, - GLuint n, GLint x, GLint y, - GLchan rgba[][4] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - const GLushort *ptr2 = (const GLushort *) PIXELADDR2(x, y); - for (i = 0; i < n; i++, ptr2++) { - /* This should be fixed to get the low bits right */ - rgba[i][RCOMP] = (*ptr2 >> 8) & 0xFe; - rgba[i][GCOMP] = (*ptr2 >> 3) & 0xFc; - rgba[i][BCOMP] = (*ptr2 << 3) & 0xFe; - rgba[i][ACOMP] = 0; - } -} - -static void -read_rgba_pixels2( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ) -{ - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - for (i = 0; i < n; i++) { - if (mask[i]) { - /* This should be fixed to get the low bits right */ - const GLushort *ptr2 = (const GLushort *) PIXELADDR2(x[i],y[i]); - rgba[i][RCOMP] = (*ptr2 >> 8) & 0xFE; - rgba[i][GCOMP] = (*ptr2 >> 3) & 0xFC; - rgba[i][BCOMP] = (*ptr2 << 3) & 0xFE; - rgba[i][ACOMP] = 0; + else { + ashift = 24; + rshift = 16; + gshift = 8; + bshift = 0; } + rgbmode = GL_TRUE; } -} - - - -/**********************************************************************/ -/***** Read/write spans/arrays of CI pixels *****/ -/**********************************************************************/ - -/* Write 32-bit color index to buffer */ -static void -write_index32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLuint index[], const GLubyte mask[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLchan *ptr1 = PIXELADDR1(x, y); - GLuint i; - if (mask) { - for (i=0;igl_visual = _mesa_create_visual( rgbmode, + GL_FALSE, /* double buffer */ + GL_FALSE, /* stereo */ + redBits, + greenBits, + blueBits, + alphaBits, + indexBits, + depthBits, + stencilBits, + accumBits, + accumBits, + accumBits, + alphaBits ? accumBits : 0, + 1 /* num samples */ + ); + if (!osmesa->gl_visual) { + FREE(osmesa); + return NULL; } - } -} - - -static void -read_index_span( const GLcontext *ctx, - GLuint n, GLint x, GLint y, GLuint index[] ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - GLuint i; - const GLchan *ptr1 = (const GLchan *) PIXELADDR1(x, y); - for (i=0;igl_ctx, + osmesa->gl_visual, + sharelist ? &sharelist->gl_ctx + : (GLcontext *) NULL, + (void *) osmesa, + GL_FALSE)) { + _mesa_destroy_visual( osmesa->gl_visual ); + FREE(osmesa); + return NULL; } - } -} - - - -/**********************************************************************/ -/***** Optimized line rendering *****/ -/**********************************************************************/ - - -/* - * Draw a flat-shaded, RGB line into an osmesa buffer. - */ -static void -flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const GLchan *color = vert1->color; - -#define INTERP_XY 1 -#define CLIP_HACK 1 -#define PLOT(X, Y) \ -do { \ - GLchan *p = PIXELADDR4(X, Y); \ - PACK_RGBA(p, color[0], color[1], color[2], color[3]); \ -} while (0) - -#ifdef WIN32 -#include "..\swrast\s_linetemp.h" -#else -#include "swrast/s_linetemp.h" -#endif -} - - -/* - * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. - */ -static void -flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const GLchan *color = vert1->color; - -#define INTERP_XY 1 -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define CLIP_HACK 1 -#define PLOT(X, Y) \ -do { \ - if (Z < *zPtr) { \ - GLchan *p = PIXELADDR4(X, Y); \ - PACK_RGBA(p, color[RCOMP], color[GCOMP], \ - color[BCOMP], color[ACOMP]); \ - *zPtr = Z; \ - } \ -} while (0) - - -#ifdef WIN32 -#include "..\swrast\s_linetemp.h" -#else -#include "swrast/s_linetemp.h" -#endif -} - - -/* - * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer. - * XXX update for GLchan - */ -static void -flat_blend_rgba_line( GLcontext *ctx, - const SWvertex *vert0, const SWvertex *vert1 ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const GLint rshift = osmesa->rshift; - const GLint gshift = osmesa->gshift; - const GLint bshift = osmesa->bshift; - const GLint avalue = vert0->color[3]; - const GLint msavalue = CHAN_MAX - avalue; - const GLint rvalue = vert1->color[0]*avalue; - const GLint gvalue = vert1->color[1]*avalue; - const GLint bvalue = vert1->color[2]*avalue; - -#define INTERP_XY 1 -#define CLIP_HACK 1 -#define PLOT(X,Y) \ - { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ - GLuint pixel = 0; \ - pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ - pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ - pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ - *ptr4 = pixel; \ - } - -#if 0 /* XXX use this in the future */ -#define PLOT(X,Y) \ - { \ - GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ - pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ - pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ - pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ - pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ - } -#endif - -#ifdef WIN32 -#include "..\swrast\s_linetemp.h" -#else -#include "swrast/s_linetemp.h" -#endif -} - - -/* - * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. - * But don't write to Z buffer. - * XXX update for GLchan - */ -static void -flat_blend_rgba_z_line( GLcontext *ctx, - const SWvertex *vert0, const SWvertex *vert1 ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const GLint rshift = osmesa->rshift; - const GLint gshift = osmesa->gshift; - const GLint bshift = osmesa->bshift; - const GLint avalue = vert0->color[3]; - const GLint msavalue = 256 - avalue; - const GLint rvalue = vert1->color[0]*avalue; - const GLint gvalue = vert1->color[1]*avalue; - const GLint bvalue = vert1->color[2]*avalue; - -#define INTERP_XY 1 -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define CLIP_HACK 1 -#define PLOT(X,Y) \ - if (Z < *zPtr) { \ - GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ - GLuint pixel = 0; \ - pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ - pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ - pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ - *ptr4 = pixel; \ - } - -#if 0 /* XXX use this in the future */ -#define PLOT(X,Y) \ - if (Z < *zPtr) { \ - GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ - pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ - pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ - pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ - pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ - } -#endif - -#ifdef WIN32 -#include "..\swrast\s_linetemp.h" -#else -#include "swrast/s_linetemp.h" -#endif -} - - -/* - * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. - * XXX update for GLchan - */ -static void -flat_blend_rgba_z_line_write( GLcontext *ctx, - const SWvertex *vert0, const SWvertex *vert1 ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const GLint rshift = osmesa->rshift; - const GLint gshift = osmesa->gshift; - const GLint bshift = osmesa->bshift; - const GLint avalue = vert0->color[3]; - const GLint msavalue = 256 - avalue; - const GLint rvalue = vert1->color[0]*avalue; - const GLint gvalue = vert1->color[1]*avalue; - const GLint bvalue = vert1->color[2]*avalue; - -#define INTERP_XY 1 -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define CLIP_HACK 1 -#define PLOT(X,Y) \ - if (Z < *zPtr) { \ - GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ - GLuint pixel = 0; \ - pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ - pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ - pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ - *ptr4 = pixel; \ - *zPtr = Z; \ - } - -#if 0 /* XXX use this in the future */ -#define PLOT(X,Y) \ - if (Z < *zPtr) { \ - GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ - pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ - pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ - pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ - pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ - *zPtr = Z; \ - } -#endif - -#ifdef WIN32 -#include "..\swrast\s_linetemp.h" -#else -#include "swrast/s_linetemp.h" -#endif -} - - -/* - * Analyze context state to see if we can provide a fast line drawing - * function, like those in lines.c. Otherwise, return NULL. - */ -static swrast_line_func -osmesa_choose_line_function( GLcontext *ctx ) -{ - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const SWcontext *swrast = SWRAST_CONTEXT(ctx); - - if (CHAN_BITS != 8) return NULL; - if (ctx->RenderMode != GL_RENDER) return NULL; - if (ctx->Line.SmoothFlag) return NULL; - if (ctx->Texture._EnabledUnits) return NULL; - if (ctx->Light.ShadeModel != GL_FLAT) return NULL; - if (ctx->Line.Width != 1.0F) return NULL; - if (ctx->Line.StippleFlag) return NULL; - if (ctx->Line.SmoothFlag) return NULL; - if (osmesa->format != OSMESA_RGBA && - osmesa->format != OSMESA_BGRA && - osmesa->format != OSMESA_ARGB) return NULL; - if (swrast->_RasterMask==DEPTH_BIT - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_TRUE - && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { - return (swrast_line_func) flat_rgba_z_line; - } + _mesa_enable_sw_extensions(&(osmesa->gl_ctx)); + _mesa_enable_1_3_extensions(&(osmesa->gl_ctx)); + /*_mesa_enable_1_4_extensions(&(osmesa->gl_ctx));*/ - if (swrast->_RasterMask == 0) { - return (swrast_line_func) flat_rgba_line; - } + osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, + (GLboolean) ( osmesa->gl_visual->depthBits > 0 ), + (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ), + (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ), + GL_FALSE /* s/w alpha */ ); - if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT) - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_TRUE - && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS - && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA - && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA - && ctx->Color.BlendSrcA==GL_SRC_ALPHA - && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA - && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { - return (swrast_line_func) flat_blend_rgba_z_line_write; - } + if (!osmesa->gl_buffer) { + _mesa_destroy_visual( osmesa->gl_visual ); + _mesa_free_context_data( &osmesa->gl_ctx ); + FREE(osmesa); + return NULL; + } + osmesa->format = format; + osmesa->buffer = NULL; + osmesa->width = 0; + osmesa->height = 0; + osmesa->userRowLength = 0; + osmesa->rowlength = 0; + osmesa->yup = GL_TRUE; + osmesa->rshift = rshift; + osmesa->gshift = gshift; + osmesa->bshift = bshift; + osmesa->ashift = ashift; + osmesa->rInd = rind; + osmesa->gInd = gind; + osmesa->bInd = bind; + osmesa->aInd = aind; - if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT) - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_FALSE - && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS - && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA - && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA - && ctx->Color.BlendSrcA==GL_SRC_ALPHA - && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA - && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { - return (swrast_line_func) flat_blend_rgba_z_line; - } + /* Initialize the software rasterizer and helper modules. */ + { + GLcontext *ctx = &osmesa->gl_ctx; - if (swrast->_RasterMask==BLEND_BIT - && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA - && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA - && ctx->Color.BlendSrcA==GL_SRC_ALPHA - && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA - && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { - return (swrast_line_func) flat_blend_rgba_line; + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + _swsetup_Wakeup( ctx ); + hook_in_driver_functions( ctx ); + } } - - return (swrast_line_func) NULL; + return osmesa; } -/**********************************************************************/ -/***** Optimized triangle rendering *****/ -/**********************************************************************/ - - /* - * Smooth-shaded, z-less triangle, RGBA color. + * Destroy an Off-Screen Mesa rendering context. + * + * Input: ctx - the context to destroy */ -static void smooth_rgba_z_triangle( GLcontext *ctx, - const SWvertex *v0, - const SWvertex *v1, - const SWvertex *v2 ) +GLAPI void GLAPIENTRY +OSMesaDestroyContext( OSMesaContext ctx ) { - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define INTERP_RGB 1 -#define INTERP_ALPHA 1 -#define RENDER_SPAN( span ) \ - GLuint i; \ - GLchan *img = PIXELADDR4(span.x, span.y); \ - for (i = 0; i < span.end; i++, img += 4) { \ - const GLdepth z = FixedToDepth(span.z); \ - if (z < zRow[i]) { \ - PACK_RGBA(img, FixedToChan(span.red), \ - FixedToChan(span.green), FixedToChan(span.blue), \ - FixedToChan(span.alpha)); \ - zRow[i] = z; \ - } \ - span.red += span.redStep; \ - span.green += span.greenStep; \ - span.blue += span.blueStep; \ - span.alpha += span.alphaStep; \ - span.z += span.zStep; \ - } + if (ctx) { + _swsetup_DestroyContext( &ctx->gl_ctx ); + _tnl_DestroyContext( &ctx->gl_ctx ); + _ac_DestroyContext( &ctx->gl_ctx ); + _swrast_DestroyContext( &ctx->gl_ctx ); -#ifdef WIN32 -#include "..\swrast\s_tritemp.h" -#else -#include "swrast/s_tritemp.h" -#endif + _mesa_destroy_visual( ctx->gl_visual ); + _mesa_destroy_framebuffer( ctx->gl_buffer ); + _mesa_free_context_data( &ctx->gl_ctx ); + FREE( ctx ); + } } - - /* - * Flat-shaded, z-less triangle, RGBA color. + * Recompute the values of the context's rowaddr array. */ -static void flat_rgba_z_triangle( GLcontext *ctx, - const SWvertex *v0, - const SWvertex *v1, - const SWvertex *v2 ) +static void +compute_row_addresses( OSMesaContext ctx ) { - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define SETUP_CODE \ - GLuint pixel; \ - PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ - v2->color[2], v2->color[3]); + GLint bytesPerPixel, bytesPerRow, i; + GLubyte *origin = (GLubyte *) ctx->buffer; -#define RENDER_SPAN( span ) \ - GLuint i; \ - GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ - for (i = 0; i < span.end; i++) { \ - const GLdepth z = FixedToDepth(span.z); \ - if (z < zRow[i]) { \ - img[i] = pixel; \ - zRow[i] = z; \ - } \ - span.z += span.zStep; \ + if (ctx->format == OSMESA_COLOR_INDEX) { + /* CI mode */ + bytesPerPixel = 1 * sizeof(GLchan); + } + else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { + /* RGB mode */ + bytesPerPixel = 3 * sizeof(GLchan); + } + else if (ctx->format == OSMESA_RGB_565) { + /* 5/6/5 RGB pixel in 16 bits */ + bytesPerPixel = 2; + } + else { + /* RGBA mode */ + bytesPerPixel = 4 * sizeof(GLchan); } -#ifdef WIN32 -#include "..\swrast\s_tritemp.h" -#else -#include "swrast/s_tritemp.h" -#endif -} + bytesPerRow = ctx->rowlength * bytesPerPixel; + if (ctx->yup) { + /* Y=0 is bottom line of window */ + for (i = 0; i < MAX_HEIGHT; i++) { + ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); + } + } + else { + /* Y=0 is top line of window */ + for (i = 0; i < MAX_HEIGHT; i++) { + GLint j = ctx->height - i - 1; + ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); + } + } +} /* - * Return pointer to an accelerated triangle function if possible. + * Bind an OSMesaContext to an image buffer. The image buffer is just a + * block of memory which the client provides. Its size must be at least + * as large as width*height*sizeof(type). Its address should be a multiple + * of 4 if using RGBA mode. + * + * Image data is stored in the order of glDrawPixels: row-major order + * with the lower-left image pixel stored in the first array position + * (ie. bottom-to-top). + * + * If the context's viewport hasn't been initialized yet, it will now be + * initialized to (0,0,width,height). + * + * Input: ctx - the rendering context + * buffer - the image buffer memory + * type - data type for pixel components + * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 + * are supported. But if Mesa's been compiled with CHAN_BITS==16 + * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build + * with CHAN_BITS==32 then type must be GL_FLOAT. + * width, height - size of image buffer in pixels, at least 1 + * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, + * invalid buffer address, invalid type, width<1, height<1, + * width>internal limit or height>internal limit. */ -static swrast_tri_func -osmesa_choose_triangle_function( GLcontext *ctx ) +GLAPI GLboolean GLAPIENTRY +OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, + GLsizei width, GLsizei height ) { - const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - const SWcontext *swrast = SWRAST_CONTEXT(ctx); - - if (CHAN_BITS != 8) return (swrast_tri_func) NULL; - if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; - if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; - if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; - if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; - if (osmesa->format != OSMESA_RGBA && - osmesa->format != OSMESA_BGRA && - osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL; - if (ctx->Polygon.CullFlag && - ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) - return (swrast_tri_func) NULL; + if (!ctx || !buffer || + width < 1 || height < 1 || + width > MAX_WIDTH || height > MAX_HEIGHT) { + return GL_FALSE; + } - if (swrast->_RasterMask == DEPTH_BIT && - ctx->Depth.Func == GL_LESS && - ctx->Depth.Mask == GL_TRUE && - ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { - if (ctx->Light.ShadeModel == GL_SMOOTH) { - return (swrast_tri_func) smooth_rgba_z_triangle; - } - else { - return (swrast_tri_func) flat_rgba_z_triangle; - } + if (ctx->format == OSMESA_RGB_565) { + if (type != GL_UNSIGNED_SHORT_5_6_5) + return GL_FALSE; } - return (swrast_tri_func) NULL; -} + else if (type != CHAN_TYPE) { + return GL_FALSE; + } + + osmesa_update_state( &ctx->gl_ctx, 0 ); + _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer ); + + ctx->buffer = buffer; + ctx->width = width; + ctx->height = height; + if (ctx->userRowLength) + ctx->rowlength = ctx->userRowLength; + else + ctx->rowlength = width; + compute_row_addresses( ctx ); + /* init viewport */ + if (ctx->gl_ctx.Viewport.Width == 0) { + /* initialize viewport and scissor box to buffer size */ + _mesa_Viewport( 0, 0, width, height ); + ctx->gl_ctx.Scissor.Width = width; + ctx->gl_ctx.Scissor.Height = height; + } + else { + /* this will make ensure we recognize the new buffer size */ + _mesa_ResizeBuffersMESA(); + } -/* Override for the swrast triangle-selection function. Try to use one - * of our internal triangle functions, otherwise fall back to the - * standard swrast functions. - */ -static void osmesa_choose_triangle( GLcontext *ctx ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); + /* Added by Gerk Huisma: */ + _tnl_MakeCurrent( &ctx->gl_ctx, ctx->gl_ctx.DrawBuffer, + ctx->gl_ctx.ReadBuffer ); - swrast->Triangle = osmesa_choose_triangle_function( ctx ); - if (!swrast->Triangle) - _swrast_choose_triangle( ctx ); + return GL_TRUE; } -static void osmesa_choose_line( GLcontext *ctx ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - - swrast->Line = osmesa_choose_line_function( ctx ); - if (!swrast->Line) - _swrast_choose_line( ctx ); -} -#define OSMESA_NEW_LINE (_NEW_LINE | \ - _NEW_TEXTURE | \ - _NEW_LIGHT | \ - _NEW_DEPTH | \ - _NEW_RENDERMODE | \ - _SWRAST_NEW_RASTERMASK) +GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) +{ + GLcontext *ctx = _mesa_get_current_context(); + if (ctx) + return (OSMesaContext) ctx; + else + return NULL; +} -#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \ - _NEW_TEXTURE | \ - _NEW_LIGHT | \ - _NEW_DEPTH | \ - _NEW_RENDERMODE | \ - _SWRAST_NEW_RASTERMASK) -/* Extend the software rasterizer with our line and triangle - * functions. - */ -static void osmesa_register_swrast_functions( GLcontext *ctx ) +GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) { - SWcontext *swrast = SWRAST_CONTEXT( ctx ); + OSMesaContext osmesa = OSMesaGetCurrentContext(); - swrast->choose_line = osmesa_choose_line; - swrast->choose_triangle = osmesa_choose_triangle; + switch (pname) { + case OSMESA_ROW_LENGTH: + if (value<0) { + _mesa_error( &osmesa->gl_ctx, GL_INVALID_VALUE, + "OSMesaPixelStore(value)" ); + return; + } + osmesa->userRowLength = value; + osmesa->rowlength = value ? value : osmesa->width; + break; + case OSMESA_Y_UP: + osmesa->yup = value ? GL_TRUE : GL_FALSE; + break; + default: + _mesa_error( &osmesa->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); + return; + } - swrast->invalidate_line |= OSMESA_NEW_LINE; - swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE; + compute_row_addresses( osmesa ); } -static const GLubyte *get_string( GLcontext *ctx, GLenum name ) +GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) { - (void) ctx; - switch (name) { - case GL_RENDERER: -#if CHAN_BITS == 32 - return (const GLubyte *) "Mesa OffScreen32"; -#elif CHAN_BITS == 16 - return (const GLubyte *) "Mesa OffScreen16"; -#else - return (const GLubyte *) "Mesa OffScreen"; -#endif + OSMesaContext osmesa = OSMesaGetCurrentContext(); + + switch (pname) { + case OSMESA_WIDTH: + *value = osmesa->width; + return; + case OSMESA_HEIGHT: + *value = osmesa->height; + return; + case OSMESA_FORMAT: + *value = osmesa->format; + return; + case OSMESA_TYPE: + *value = CHAN_TYPE; + return; + case OSMESA_ROW_LENGTH: + *value = osmesa->userRowLength; + return; + case OSMESA_Y_UP: + *value = osmesa->yup; + return; + case OSMESA_MAX_WIDTH: + *value = MAX_WIDTH; + return; + case OSMESA_MAX_HEIGHT: + *value = MAX_HEIGHT; + return; default: - return NULL; + _mesa_error(&osmesa->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); + return; } } - -static void osmesa_update_state( GLcontext *ctx, GLuint new_state ) +/* + * Return the depth buffer associated with an OSMesa context. + * Input: c - the OSMesa context + * Output: width, height - size of buffer in pixels + * bytesPerValue - bytes per depth value (2 or 4) + * buffer - pointer to depth buffer values + * Return: GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLAPI GLboolean GLAPIENTRY +OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, + GLint *bytesPerValue, void **buffer ) { - OSMesaContext osmesa = OSMESA_CONTEXT(ctx); - struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); - TNLcontext *tnl = TNL_CONTEXT(ctx); - - ASSERT((void *) osmesa == (void *) ctx->DriverCtx); - - /* - * XXX these function pointers could be initialized just once during - * context creation since they don't depend on any state changes. - */ - - ctx->Driver.GetString = get_string; - ctx->Driver.UpdateState = osmesa_update_state; - ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; - ctx->Driver.GetBufferSize = buffer_size; - - ctx->Driver.Accum = _swrast_Accum; - ctx->Driver.Bitmap = _swrast_Bitmap; - ctx->Driver.Clear = clear; - ctx->Driver.CopyPixels = _swrast_CopyPixels; - ctx->Driver.DrawPixels = _swrast_DrawPixels; - ctx->Driver.ReadPixels = _swrast_ReadPixels; - ctx->Driver.DrawBuffer = _swrast_DrawBuffer; - - ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; - ctx->Driver.TexImage1D = _mesa_store_teximage1d; - ctx->Driver.TexImage2D = _mesa_store_teximage2d; - ctx->Driver.TexImage3D = _mesa_store_teximage3d; - ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; - ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; - ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; - ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; - - ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; - ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; - ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; - ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d; - ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; - ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; - - ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; - ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; - ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; - ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; - ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; - ctx->Driver.CopyColorTable = _swrast_CopyColorTable; - ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; - ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; - ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; - - swdd->SetBuffer = set_buffer; - - /* RGB(A) span/pixel functions */ - if (osmesa->format == OSMESA_RGB) { - swdd->WriteRGBASpan = write_rgba_span_RGB; - swdd->WriteRGBSpan = write_rgb_span_RGB; - swdd->WriteMonoRGBASpan = write_monocolor_span_RGB; - swdd->WriteRGBAPixels = write_rgba_pixels_RGB; - swdd->WriteMonoRGBAPixels = write_monocolor_pixels_RGB; - swdd->ReadRGBASpan = read_rgba_span3; - swdd->ReadRGBAPixels = read_rgba_pixels3; + if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { + *width = 0; + *height = 0; + *bytesPerValue = 0; + *buffer = 0; + return GL_FALSE; } - else if (osmesa->format == OSMESA_BGR) { - swdd->WriteRGBASpan = write_rgba_span_BGR; - swdd->WriteRGBSpan = write_rgb_span_BGR; - swdd->WriteMonoRGBASpan = write_monocolor_span_BGR; - swdd->WriteRGBAPixels = write_rgba_pixels_BGR; - swdd->WriteMonoRGBAPixels = write_monocolor_pixels_BGR; - swdd->ReadRGBASpan = read_rgba_span3; - swdd->ReadRGBAPixels = read_rgba_pixels3; + else { + *width = c->gl_buffer->Width; + *height = c->gl_buffer->Height; + if (c->gl_visual->depthBits <= 16) + *bytesPerValue = sizeof(GLushort); + else + *bytesPerValue = sizeof(GLuint); + *buffer = c->gl_buffer->DepthBuffer; + return GL_TRUE; } - else if (osmesa->format == OSMESA_RGB_565) { - swdd->WriteRGBASpan = write_rgba_span2; - swdd->WriteRGBSpan = write_rgb_span2; - swdd->WriteMonoRGBASpan = write_monocolor_span2; - swdd->WriteRGBAPixels = write_rgba_pixels2; - swdd->WriteMonoRGBAPixels = write_monocolor_pixels2; - swdd->ReadRGBASpan = read_rgba_span2; - swdd->ReadRGBAPixels = read_rgba_pixels2; +} + +/* + * Return the color buffer associated with an OSMesa context. + * Input: c - the OSMesa context + * Output: width, height - size of buffer in pixels + * format - the pixel format (OSMESA_FORMAT) + * buffer - pointer to color buffer values + * Return: GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLAPI GLboolean GLAPIENTRY +OSMesaGetColorBuffer( OSMesaContext c, GLint *width, + GLint *height, GLint *format, void **buffer ) +{ + if (!c->buffer) { + *width = 0; + *height = 0; + *format = 0; + *buffer = 0; + return GL_FALSE; } else { - /* 4 GLchan / pixel in frame buffer */ - swdd->WriteRGBSpan = write_rgb_span; - swdd->WriteRGBAPixels = write_rgba_pixels; - swdd->WriteMonoRGBASpan = write_monocolor_span; - swdd->WriteMonoRGBAPixels = write_monocolor_pixels; - if (osmesa->format == OSMESA_RGBA && - CHAN_TYPE == GL_UNSIGNED_BYTE && - RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) { - /* special, fast case */ - swdd->WriteRGBASpan = write_rgba_span_rgba; - swdd->ReadRGBASpan = read_rgba_span_rgba; - } - else { - swdd->WriteRGBASpan = write_rgba_span; - swdd->ReadRGBASpan = read_rgba_span; - } - swdd->ReadRGBAPixels = read_rgba_pixels; + *width = c->width; + *height = c->height; + *format = c->format; + *buffer = c->buffer; + return GL_TRUE; } +} - /* CI span/pixel functions */ - swdd->WriteCI32Span = write_index32_span; - swdd->WriteCI8Span = write_index8_span; - swdd->WriteMonoCISpan = write_monoindex_span; - swdd->WriteCI32Pixels = write_index_pixels; - swdd->WriteMonoCIPixels = write_monoindex_pixels; - swdd->ReadCI32Span = read_index_span; - swdd->ReadCI32Pixels = read_index_pixels; - tnl->Driver.RunPipeline = _tnl_run_pipeline; - _swrast_InvalidateState( ctx, new_state ); - _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); - _tnl_InvalidateState( ctx, new_state ); +struct name_address { + const char *Name; + GLvoid *Address; +}; + +static struct name_address functions[] = { + { "OSMesaCreateContext", (void *) OSMesaCreateContext }, + { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt }, + { "OSMesaDestroyContext", (void *) OSMesaDestroyContext }, + { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent }, + { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext }, + { "OSMesaPixelsStore", (void *) OSMesaPixelStore }, + { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv }, + { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer }, + { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer }, + { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress }, + { NULL, NULL } +}; + +GLAPI void * GLAPIENTRY +OSMesaGetProcAddress( const char *funcName ) +{ + int i; + for (i = 0; functions[i].Name; i++) { + if (_mesa_strcmp(functions[i].Name, funcName) == 0) + return (void *) functions[i].Address; + } + return (void *) _glapi_get_proc_address(funcName); } -- 2.30.2