X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fosmesa%2Fosmesa.c;h=cc2081129df9181b6e958e33f5ceaef154eee7b0;hb=10d343f407bddf011be3d2b79a6541815759785a;hp=a0bb746d007435b8ca4b302793316e97f273a10c;hpb=cb5ecb883eb3be842ef44c61df8d4b527877c858;p=mesa.git diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index a0bb746d007..cc2081129df 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -1,21 +1,21 @@ -/* $Id: osmesa.c,v 1.3 1999/11/11 01:28:41 brianp Exp $ */ +/* $Id: osmesa.c,v 1.92 2002/10/17 15:26:38 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.3 - * - * Copyright (C) 1999 Brian Paul All Rights Reserved. - * + * Version: 4.1 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -27,73 +27,75 @@ /* * Off-Screen Mesa rendering / Rendering into client memory space + * + * Note on thread safety: this driver is thread safe. All + * functions are reentrant. The notion of current context is + * managed by the core _mesa_make_current() and _mesa_get_current_context() + * functions. Those functions are thread-safe. */ -#ifdef PC_HEADER -#include "all.h" -#else -#include -#include +#include "glheader.h" #include "GL/osmesa.h" +#include "buffers.h" #include "context.h" +#include "colormac.h" #include "depth.h" -#include "mem.h" +#include "extensions.h" +#include "imports.h" +#include "macros.h" #include "matrix.h" -#include "types.h" -#include "vb.h" -#endif +#include "mem.h" +#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_lines.h" +#include "swrast/s_triangle.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +/* + * This is the OS/Mesa context struct. + * Notice how it includes a GLcontext. By doing this we're mimicking + * C++ inheritance/derivation. + * Later, we can cast a GLcontext pointer into an OSMesaContext pointer + * or vice versa. + */ struct osmesa_context { - GLcontext *gl_ctx; /* The core GL/Mesa context */ + GLcontext gl_ctx; /* The core GL/Mesa context */ GLvisual *gl_visual; /* Describes the buffers */ GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */ GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */ void *buffer; /* the image buffer */ GLint width, height; /* size of image buffer */ - GLuint pixel; /* current color index or RGBA pixel value */ - GLuint clearpixel; /* pixel for clearing the color buffer */ GLint rowlength; /* number of pixels per row */ GLint userRowLength; /* user-specified number of pixels per row */ GLint rshift, gshift; /* bit shifts for RGBA formats */ GLint bshift, ashift; - GLint rind, gind, bind; /* index offsets for RGBA formats */ - void *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ + GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */ + GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ GLboolean yup; /* TRUE -> Y increases upward */ /* FALSE -> Y increases downward */ }; -#ifdef THREADS - -#include "mthreads.h" /* Mesa platform independent threads interface */ - -static MesaTSD osmesa_ctx_tsd; - -static void osmesa_ctx_thread_init() { - MesaInitTSD(&osmesa_ctx_tsd); -} - -static OSMesaContext osmesa_get_thread_context( void ) { - return (OSMesaContext) MesaGetTSD(&osmesa_ctx_tsd); -} - -static void osmesa_set_thread_context( OSMesaContext ctx ) { - MesaSetTSD(&osmesa_ctx_tsd, ctx, osmesa_ctx_thread_init); -} - - -#else - /* One current context for address space, all threads */ - static OSMesaContext Current = NULL; -#endif +/* A forward declaration: */ +static void osmesa_update_state( GLcontext *ctx, GLuint newstate ); +static void osmesa_register_swrast_functions( GLcontext *ctx ); -/* A forward declaration: */ -static void osmesa_update_state( GLcontext *ctx ); +#define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx)) @@ -111,20 +113,35 @@ static void osmesa_update_state( GLcontext *ctx ); * display lists. NULL indicates no sharing. * Return: an OSMesaContext or 0 if error */ -OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) +GLAPI OSMesaContext GLAPIENTRY +OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) +{ + return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, + 8, 16, sharelist); +} + + + +/* + * 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 ) { OSMesaContext osmesa; GLint rshift, gshift, bshift, ashift; - GLint rind, gind, bind; - GLint indexBits, alphaBits; + GLint rind, gind, bind, aind; + GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; GLboolean rgbmode; - GLboolean swalpha; - GLuint i4 = 1; - GLubyte *i1 = (GLubyte *) &i4; - GLint little_endian = *i1; + const GLuint i4 = 1; + const GLubyte *i1 = (GLubyte *) &i4; + const GLint little_endian = *i1; + __GLimports imports; - swalpha = GL_FALSE; - rind = gind = bind = 0; + rind = gind = bind = aind = 0; if (format==OSMESA_COLOR_INDEX) { indexBits = 8; rshift = gshift = bshift = ashift = 0; @@ -132,7 +149,14 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share } else if (format==OSMESA_RGBA) { indexBits = 0; - alphaBits = 8; + 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; @@ -149,12 +173,19 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share } else if (format==OSMESA_BGRA) { indexBits = 0; - alphaBits = 8; + redBits = CHAN_BITS; + greenBits = CHAN_BITS; + blueBits = CHAN_BITS; + alphaBits = CHAN_BITS; + bind = 0; + gind = 1; + rind = 2; + aind = 3; if (little_endian) { - ashift = 0; - rshift = 8; - gshift = 16; - bshift = 24; + bshift = 0; + gshift = 8; + rshift = 16; + ashift = 24; } else { bshift = 24; @@ -166,12 +197,19 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share } else if (format==OSMESA_ARGB) { indexBits = 0; - alphaBits = 8; + redBits = CHAN_BITS; + greenBits = CHAN_BITS; + blueBits = CHAN_BITS; + alphaBits = CHAN_BITS; + aind = 0; + rind = 1; + gind = 2; + bind = 3; if (little_endian) { - bshift = 0; - gshift = 8; - rshift = 16; - ashift = 24; + ashift = 0; + rshift = 8; + gshift = 16; + bshift = 24; } else { ashift = 24; @@ -183,29 +221,48 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share } 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; - bind = 2; - gind = 1; rind = 0; + gind = 1; + bind = 2; rgbmode = GL_TRUE; - swalpha = 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; - bind = 0; - gind = 1; 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; - swalpha = GL_TRUE; } else { return NULL; @@ -214,31 +271,51 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); if (osmesa) { - osmesa->gl_visual = gl_create_visual( rgbmode, - swalpha, /* software alpha */ - GL_FALSE, /* double buffer */ - GL_FALSE, /* stereo */ - DEPTH_BITS, - STENCIL_BITS, - ACCUM_BITS, - indexBits, - 8, 8, 8, alphaBits ); + 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; } - osmesa->gl_ctx = gl_create_context( osmesa->gl_visual, - sharelist ? sharelist->gl_ctx : (GLcontext *) NULL, - (void *) osmesa, GL_TRUE ); - if (!osmesa->gl_ctx) { - gl_destroy_visual( osmesa->gl_visual ); + _mesa_init_default_imports( &imports, (void *) osmesa ); + if (!_mesa_initialize_context(&osmesa->gl_ctx, + osmesa->gl_visual, + sharelist ? &sharelist->gl_ctx + : (GLcontext *) NULL, + &imports)) { + _mesa_destroy_visual( osmesa->gl_visual ); FREE(osmesa); return NULL; } - osmesa->gl_buffer = gl_create_framebuffer( osmesa->gl_visual ); + + _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 */ ); + if (!osmesa->gl_buffer) { - gl_destroy_visual( osmesa->gl_visual ); - gl_destroy_context( osmesa->gl_ctx ); + _mesa_destroy_visual( osmesa->gl_visual ); + _mesa_free_context_data( &osmesa->gl_ctx ); FREE(osmesa); return NULL; } @@ -246,8 +323,6 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share osmesa->buffer = NULL; osmesa->width = 0; osmesa->height = 0; - osmesa->pixel = 0; - osmesa->clearpixel = 0; osmesa->userRowLength = 0; osmesa->rowlength = 0; osmesa->yup = GL_TRUE; @@ -255,26 +330,48 @@ OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext share osmesa->gshift = gshift; osmesa->bshift = bshift; osmesa->ashift = ashift; - osmesa->rind = rind; - osmesa->gind = gind; - osmesa->bind = bind; + osmesa->rInd = rind; + osmesa->gInd = gind; + osmesa->bInd = bind; + osmesa->aInd = aind; + + + /* Initialize the software rasterizer and helper modules. + */ + { + GLcontext *ctx = &osmesa->gl_ctx; + + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + _swsetup_Wakeup( ctx ); + osmesa_register_swrast_functions( ctx ); + } } return osmesa; } + /* * Destroy an Off-Screen Mesa rendering context. * * Input: ctx - the context to destroy */ -void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx ) +GLAPI void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx ) { if (ctx) { - gl_destroy_visual( ctx->gl_visual ); - gl_destroy_framebuffer( ctx->gl_buffer ); - gl_destroy_context( ctx->gl_ctx ); + _swsetup_DestroyContext( &ctx->gl_ctx ); + _tnl_DestroyContext( &ctx->gl_ctx ); + _ac_DestroyContext( &ctx->gl_ctx ); + _swrast_DestroyContext( &ctx->gl_ctx ); + + _mesa_destroy_visual( ctx->gl_visual ); + _mesa_destroy_framebuffer( ctx->gl_buffer ); + _mesa_free_context_data( &ctx->gl_ctx ); FREE( ctx ); } } @@ -286,56 +383,39 @@ void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx ) */ static void compute_row_addresses( OSMesaContext ctx ) { - GLint i; + GLint bytesPerPixel, bytesPerRow, i; + GLubyte *origin = (GLubyte *) ctx->buffer; + + 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); + } + + bytesPerRow = ctx->rowlength * bytesPerPixel; if (ctx->yup) { /* Y=0 is bottom line of window */ - if (ctx->format==OSMESA_COLOR_INDEX) { - /* 1-byte CI mode */ - GLubyte *origin = (GLubyte *) ctx->buffer; - for (i=0;irowaddr[i] = origin + i * ctx->rowlength; - } - } - else { - if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) { - /* 3-byte RGB mode */ - GLubyte *origin = (GLubyte *) ctx->buffer; - for (i=0;irowaddr[i] = origin + (i * (ctx->rowlength*3)); - } - } else { - /* 4-byte RGBA mode */ - GLuint *origin = (GLuint *) ctx->buffer; - for (i=0;irowaddr[i] = origin + i * ctx->rowlength; - } - } + for (i = 0; i < MAX_HEIGHT; i++) { + ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); } } else { /* Y=0 is top line of window */ - if (ctx->format==OSMESA_COLOR_INDEX) { - /* 1-byte CI mode */ - GLubyte *origin = (GLubyte *) ctx->buffer; - for (i=0;irowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength; - } - } - else { - if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) { - /* 3-byte RGB mode */ - GLubyte *origin = (GLubyte *) ctx->buffer; - for (i=0;irowaddr[i] = origin + ((ctx->height-i-1) * (ctx->rowlength*3)); - } - } else { - /* 4-byte RGBA mode */ - GLuint *origin = (GLuint *) ctx->buffer; - for (i=0;irowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength; - } - } + for (i = 0; i < MAX_HEIGHT; i++) { + GLint j = ctx->height - i - 1; + ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); } } } @@ -351,33 +431,41 @@ static void compute_row_addresses( OSMesaContext ctx ) * with the lower-left image pixel stored in the first array position * (ie. bottom-to-top). * - * Since the only type initially supported is GL_UNSIGNED_BYTE, if the - * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA - * value. If the context is in color indexed mode, each pixel will be - * stored as a 1-byte value. - * * 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, only GL_UNSIGNED_BYTE - * supported now + * 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, type!=GL_UNSIGNED_BYTE, width<1, height<1, + * invalid buffer address, invalid type, width<1, height<1, * width>internal limit or height>internal limit. */ -GLboolean GLAPIENTRY OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, - GLsizei width, GLsizei height ) +GLAPI GLboolean GLAPIENTRY +OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, + GLsizei width, GLsizei height ) { - if (!ctx || !buffer || type!=GL_UNSIGNED_BYTE - || width<1 || height<1 || width>MAX_WIDTH || height>MAX_HEIGHT) { + if (!ctx || !buffer || + width < 1 || height < 1 || + width > MAX_WIDTH || height > MAX_HEIGHT) { + return GL_FALSE; + } + + if (ctx->format == OSMESA_RGB_565) { + if (type != GL_UNSIGNED_SHORT_5_6_5) + return GL_FALSE; + } + else if (type != CHAN_TYPE) { return GL_FALSE; } - osmesa_update_state( ctx->gl_ctx ); - gl_make_current( ctx->gl_ctx, ctx->gl_buffer ); + osmesa_update_state( &ctx->gl_ctx, 0 ); + _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer ); ctx->buffer = buffer; ctx->width = width; @@ -387,51 +475,48 @@ GLboolean GLAPIENTRY OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum else ctx->rowlength = width; -#ifdef THREADS - /* Set current context for the calling thread */ - osmesa_set_thread_context(ctx); -#else - /* Set current context for the address space, all threads */ - Current = ctx; -#endif - compute_row_addresses( ctx ); /* init viewport */ - if (ctx->gl_ctx->Viewport.Width==0) { + 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; + 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(); } + /* Added by Gerk Huisma: */ + _tnl_MakeCurrent( &ctx->gl_ctx, ctx->gl_ctx.DrawBuffer, + ctx->gl_ctx.ReadBuffer ); + return GL_TRUE; } - -OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) +GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) { -#ifdef THREADS - /* Return current handle for the calling thread */ - return osmesa_get_thread_context(); -#else - /* Return current handle for the address space, all threads */ - return Current; -#endif + GLcontext *ctx = _mesa_get_current_context(); + if (ctx) + return (OSMesaContext) ctx; + else + return NULL; } -void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) +GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) { OSMesaContext ctx = OSMesaGetCurrentContext(); switch (pname) { case OSMESA_ROW_LENGTH: if (value<0) { - gl_error( ctx->gl_ctx, GL_INVALID_VALUE, + _mesa_error( &ctx->gl_ctx, GL_INVALID_VALUE, "OSMesaPixelStore(value)" ); return; } @@ -442,7 +527,7 @@ void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) ctx->yup = value ? GL_TRUE : GL_FALSE; break; default: - gl_error( ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); + _mesa_error( &ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); return; } @@ -450,7 +535,7 @@ void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) } -void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) +GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) { OSMesaContext ctx = OSMesaGetCurrentContext(); @@ -465,7 +550,7 @@ void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) *value = ctx->format; return; case OSMESA_TYPE: - *value = GL_UNSIGNED_BYTE; + *value = CHAN_TYPE; return; case OSMESA_ROW_LENGTH: *value = ctx->rowlength; @@ -473,14 +558,18 @@ void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) 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: - gl_error( ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)" ); + _mesa_error(&ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); return; } } - - /* * Return the depth buffer associated with an OSMesa context. * Input: c - the OSMesa context @@ -489,10 +578,11 @@ void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) * buffer - pointer to depth buffer values * Return: GL_TRUE or GL_FALSE to indicate success or failure. */ -GLboolean GLAPIENTRY OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, - GLint *bytesPerValue, void **buffer ) +GLAPI GLboolean GLAPIENTRY +OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, + GLint *bytesPerValue, void **buffer ) { - if ((!c->gl_buffer) || (!c->gl_buffer->Depth)) { + if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { *width = 0; *height = 0; *bytesPerValue = 0; @@ -502,14 +592,75 @@ GLboolean GLAPIENTRY OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint else { *width = c->gl_buffer->Width; *height = c->gl_buffer->Height; - *bytesPerValue = sizeof(GLdepth); - *buffer = c->gl_buffer->Depth; + if (c->gl_visual->depthBits <= 16) + *bytesPerValue = sizeof(GLushort); + else + *bytesPerValue = sizeof(GLuint); + *buffer = c->gl_buffer->DepthBuffer; + return GL_TRUE; + } +} + +/* + * 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 { + *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 (strcmp(functions[i].Name, funcName) == 0) + return (void *) functions[i].Address; + } + return (void *) _glapi_get_proc_address(funcName); +} + /**********************************************************************/ /*** Device Driver Functions ***/ @@ -519,161 +670,269 @@ GLboolean GLAPIENTRY OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint /* * Useful macros: */ -#define PACK_RGBA(R,G,B,A) ( ((R) << osmesa->rshift) \ - | ((G) << osmesa->gshift) \ - | ((B) << osmesa->bshift) \ - | ((A) << osmesa->ashift) ) -#define PACK_RGBA2(R,G,B,A) ( ((R) << rshift) \ - | ((G) << gshift) \ - | ((B) << bshift) \ - | ((A) << ashift) ) +#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 UNPACK_RED(P) (((P) >> osmesa->rshift) & 0xff) -#define UNPACK_GREEN(P) (((P) >> osmesa->gshift) & 0xff) -#define UNPACK_BLUE(P) (((P) >> osmesa->bshift) & 0xff) -#define UNPACK_ALPHA(P) (((P) >> osmesa->ashift) & 0xff) +#define PACK_RGB(DST, R, G, B) \ +do { \ + (DST)[0] = R; \ + (DST)[1] = G; \ + (DST)[2] = B; \ +} while (0) -#define PIXELADDR1(X,Y) ((GLubyte *) osmesa->rowaddr[Y] + (X)) -#define PIXELADDR3(X,Y) ((GLubyte *) osmesa->rowaddr[Y] + ((X)*3)) -#define PIXELADDR4(X,Y) ((GLuint *) osmesa->rowaddr[Y] + (X)) +#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) - -static GLboolean set_buffer( GLcontext *ctx, GLenum mode ) -{ - (void) ctx; - if (mode==GL_FRONT_LEFT) { - return GL_TRUE; - } - else { - return GL_FALSE; - } -} +#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] ) -static void clear_index( GLcontext *ctx, GLuint index ) -{ - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - osmesa->clearpixel = index; -} +#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 clear_color( GLcontext *ctx, - GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +static void set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - osmesa->clearpixel = PACK_RGBA( r, g, b, a ); + /* separate read buffer not supported */ + ASSERT(buffer == ctx->DrawBuffer); + ASSERT(bufferBit == FRONT_LEFT_BIT); } - -static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all, - GLint x, GLint y, GLint width, GLint height ) +static void clear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - if (mask & GL_COLOR_BUFFER_BIT) { - if (osmesa->format==OSMESA_COLOR_INDEX) { - if (all) { - /* Clear whole CI buffer */ - MEMSET(osmesa->buffer, osmesa->clearpixel, - osmesa->rowlength * osmesa->height); - } - else { - /* Clear part of CI buffer */ - GLint i, j; - for (i=0;iclearpixel; + 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); + 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 if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) { - GLubyte rval = UNPACK_RED(osmesa->clearpixel); - GLubyte gval = UNPACK_GREEN(osmesa->clearpixel); - GLubyte bval = UNPACK_BLUE(osmesa->clearpixel); - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; - if (all) { - GLuint i, n; - GLubyte *ptr3 = (GLubyte *) osmesa->buffer; - /* Clear whole RGB buffer */ - n = osmesa->rowlength * osmesa->height; - for (i=0;irowlength * osmesa->height; - ptr4 = (GLuint *) osmesa->buffer; - for (i=0;iclearpixel; - } - } - else { - /* Clear part of RGBA buffer */ - GLint i, j; - for (i=0;iclearpixel; + 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 { + 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; + } + } + } + +#endif + } + mask &= ~DD_FRONT_LEFT_BIT; } } - return mask & (~GL_COLOR_BUFFER_BIT); -} - - - -static void set_index( GLcontext *ctx, GLuint index ) -{ - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - osmesa->pixel = index; + + if (mask) + _swrast_Clear( ctx, mask, all, x, y, width, height ); } -static void set_color( GLcontext *ctx, - GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +static void buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - osmesa->pixel = PACK_RGBA( r, g, b, a ); -} - - - -static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) -{ - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - *width = osmesa->width; - *height = osmesa->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; + } } @@ -682,44 +941,42 @@ static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) /**********************************************************************/ /* Write RGBA pixels to an RGBA (or permuted) buffer. */ -static void write_rgba_span( const GLcontext *ctx, - GLuint n, GLint x, GLint y, - CONST GLubyte rgba[][4], const GLubyte mask[] ) +static void +write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, + CONST GLchan rgba[][4], const GLubyte mask[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - GLuint *ptr4 = PIXELADDR4( x, y ); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *p = PIXELADDR4(x, y); GLuint i; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint ashift = osmesa->ashift; if (mask) { - for (i=0;iDriverCtx; - GLuint *ptr4 = PIXELADDR4( x, y ); + 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;iDriverCtx; - GLuint *ptr4 = PIXELADDR4( x, y ); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *p = PIXELADDR4(x, y); GLuint i; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint ashift = osmesa->ashift; if (mask) { - for (i=0;iDriverCtx; - GLuint *ptr4 = PIXELADDR4(x,y); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *p = PIXELADDR4(x, y); GLuint i; - for (i=0;ipixel; + PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]); } } } -static void write_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - CONST GLubyte rgba[][4], const GLubyte mask[] ) +static void +write_rgba_pixels( const GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], + CONST GLchan rgba[][4], const GLubyte mask[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint ashift = osmesa->ashift; - for (i=0;iDriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - for (i=0;ipixel; + GLchan *p = PIXELADDR4(x[i], y[i]); + PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]); } } } -static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, - GLubyte rgba[][4] ) +static void +read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, + GLchan rgba[][4] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - GLuint *ptr4 = PIXELADDR4(x,y); - for (i=0;iDriverCtx; - GLuint *ptr4 = PIXELADDR4(x,y); - MEMCPY( rgba, ptr4, n * 4 * sizeof(GLubyte) ); + OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y); + MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) ); } -static void read_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLubyte rgba[][4], const GLubyte mask[] ) +static void +read_rgba_pixels( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLchan rgba[][4], const GLubyte mask[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - for (i=0;iDriverCtx; - GLubyte *ptr3 = PIXELADDR3( x, y); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *p = PIXELADDR3(x, y); GLuint i; - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; if (mask) { - for (i=0;iDriverCtx; - GLubyte *ptr3 = PIXELADDR3( x, y); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *p = PIXELADDR3(x, y); GLuint i; - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; if (mask) { - for (i=0;iDriverCtx; + 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]); + } + } +} - GLubyte rval = UNPACK_RED(osmesa->pixel); - GLubyte gval = UNPACK_GREEN(osmesa->pixel); - GLubyte bval = UNPACK_BLUE(osmesa->pixel); - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; +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[] ) +{ + 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]); + } + } +} - GLubyte *ptr3 = PIXELADDR3( x, y); +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;iDriverCtx; + const OSMesaContext osmesa = (const OSMesaContext) ctx; GLuint i; - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; + 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]); + } + } +} - for (i=0;iDriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; - GLubyte rval = UNPACK_RED(osmesa->pixel); - GLubyte gval = UNPACK_GREEN(osmesa->pixel); - GLubyte bval = UNPACK_BLUE(osmesa->pixel); - for (i=0;iDriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; - GLubyte *ptr3 = PIXELADDR3( x, y); - for (i=0;i> 8) & 0xFe; + rgba[i][GCOMP] = (*ptr2 >> 3) & 0xFc; + rgba[i][BCOMP] = (*ptr2 << 3) & 0xFe; rgba[i][ACOMP] = 0; } } -static void read_rgba_pixels3( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLubyte rgba[][4], const GLubyte mask[] ) +static void +read_rgba_pixels2( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLchan rgba[][4], const GLubyte mask[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - GLint rind = osmesa->rind; - GLint gind = osmesa->gind; - GLint bind = osmesa->bind; - for (i=0;i> 8) & 0xFE; + rgba[i][GCOMP] = (*ptr2 >> 3) & 0xFC; + rgba[i][BCOMP] = (*ptr2 << 3) & 0xFE; rgba[i][ACOMP] = 0; } } } + /**********************************************************************/ /***** 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[] ) +static void +write_index32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLuint index[], const GLubyte mask[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - GLubyte *ptr1 = PIXELADDR1(x,y); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *ptr1 = PIXELADDR1(x, y); GLuint i; if (mask) { for (i=0;iDriverCtx; - GLubyte *ptr1 = PIXELADDR1(x,y); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *ptr1 = PIXELADDR1(x, y); GLuint i; if (mask) { for (i=0;iDriverCtx; - GLubyte *ptr1 = PIXELADDR1(x,y); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLchan *ptr1 = PIXELADDR1(x, y); GLuint i; for (i=0;ipixel; + *ptr1 = (GLchan) colorIndex; } } } -static void write_index_pixels( const GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLuint index[], const GLubyte mask[] ) +static void +write_index_pixels( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLuint index[], const GLubyte mask[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; for (i=0;iDriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; for (i=0;ipixel; + GLchan *ptr1 = PIXELADDR1(x[i], y[i]); + *ptr1 = (GLchan) colorIndex; } } } -static void read_index_span( const GLcontext *ctx, - GLuint n, GLint x, GLint y, GLuint index[] ) +static void +read_index_span( const GLcontext *ctx, + GLuint n, GLint x, GLint y, GLuint index[] ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; - GLubyte *ptr1 = PIXELADDR1(x,y); + const GLchan *ptr1 = (const GLchan *) PIXELADDR1(x, y); for (i=0;iDriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); GLuint i; for (i=0;iDriverCtx; - GLubyte *color = ctx->VB->ColorPtr->data[pvert]; - unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] ); + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + const GLchan *color = vert1->color; #define INTERP_XY 1 #define CLIP_HACK 1 -#define PLOT(X,Y) { GLuint *ptr4 = PIXELADDR4(X,Y); *ptr4 = pixel; } +#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 "..\linetemp.h" +#include "..\swrast\s_linetemp.h" #else -#include "linetemp.h" +#include "swrast/s_linetemp.h" #endif } @@ -1175,140 +1619,184 @@ static void flat_rgba_line( GLcontext *ctx, /* * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. */ -static void flat_rgba_z_line( GLcontext *ctx, - GLuint vert0, GLuint vert1, GLuint pvert ) +static void +flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - GLubyte *color = ctx->VB->ColorPtr->data[pvert]; - unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] ); + 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) \ - if (Z < *zPtr) { \ - GLuint *ptr4 = PIXELADDR4(X,Y); \ - *ptr4 = pixel; \ - *zPtr = Z; \ - } +#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 "..\linetemp.h" +#include "..\swrast\s_linetemp.h" #else -#include "linetemp.h" +#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, - GLuint vert0, GLuint vert1, GLuint pvert ) +static void +flat_blend_rgba_line( GLcontext *ctx, + const SWvertex *vert0, const SWvertex *vert1 ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - struct vertex_buffer *VB = ctx->VB; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint avalue = VB->ColorPtr->data[pvert][3]; - GLint msavalue = 255 - avalue; - GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; - GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; - GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; + 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 = PIXELADDR4(X,Y); \ - GLuint pixel = 0; \ + { 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; \ + *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 "..\linetemp.h" +#include "..\swrast\s_linetemp.h" #else -#include "linetemp.h" +#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, - GLuint vert0, GLuint vert1, GLuint pvert ) +static void +flat_blend_rgba_z_line( GLcontext *ctx, + const SWvertex *vert0, const SWvertex *vert1 ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - struct vertex_buffer *VB = ctx->VB; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint avalue = VB->ColorPtr->data[pvert][3]; - GLint msavalue = 256 - avalue; - GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; - GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; - GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; + 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 = 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; \ - } \ +#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 "..\linetemp.h" +#include "..\swrast\s_linetemp.h" #else -#include "linetemp.h" +#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, - GLuint vert0, GLuint vert1, GLuint pvert ) +static void +flat_blend_rgba_z_line_write( GLcontext *ctx, + const SWvertex *vert0, const SWvertex *vert1 ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - struct vertex_buffer *VB = ctx->VB; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint avalue = VB->ColorPtr->data[pvert][3]; - GLint msavalue = 256 - avalue; - GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; - GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; - GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; + 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 = 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; \ +#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 "..\linetemp.h" +#include "..\swrast\s_linetemp.h" #else -#include "linetemp.h" +#include "swrast/s_linetemp.h" #endif } @@ -1317,95 +1805,69 @@ static void flat_blend_rgba_z_line_write( GLcontext *ctx, * Analyze context state to see if we can provide a fast line drawing * function, like those in lines.c. Otherwise, return NULL. */ -static line_func choose_line_function( GLcontext *ctx ) +static swrast_line_func +osmesa_choose_line_function( GLcontext *ctx ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + 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.Enabled) return NULL; - if (ctx->Light.ShadeModel!=GL_FLAT) return NULL; - - if (ctx->Line.Width==1.0F - && ctx->Line.StippleFlag==GL_FALSE) { - - if (ctx->RasterMask==DEPTH_BIT - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_TRUE) { - switch(osmesa->format) { - case OSMESA_RGBA: - case OSMESA_BGRA: - case OSMESA_ARGB: - return flat_rgba_z_line; - default: - return NULL; - } - } - - if (ctx->RasterMask==0) { - switch(osmesa->format) { - case OSMESA_RGBA: - case OSMESA_BGRA: - case OSMESA_ARGB: - return flat_rgba_line; - default: - return NULL; - } - } - - if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT) - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_TRUE - && 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) { - switch(osmesa->format) { - case OSMESA_RGBA: - case OSMESA_BGRA: - case OSMESA_ARGB: - return flat_blend_rgba_z_line_write; - default: - return NULL; - } - } - - if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT) - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_FALSE - && 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) { - switch(osmesa->format) { - case OSMESA_RGBA: - case OSMESA_BGRA: - case OSMESA_ARGB: - return flat_blend_rgba_z_line; - default: - return NULL; - } - } - - if (ctx->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) { - switch(osmesa->format) { - case OSMESA_RGBA: - case OSMESA_BGRA: - case OSMESA_ARGB: - return flat_blend_rgba_line; - default: - return NULL; - } - } - - } - 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; + } + + if (swrast->_RasterMask == 0) { + return (swrast_line_func) flat_rgba_line; + } + + 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; } @@ -1417,37 +1879,38 @@ static line_func choose_line_function( GLcontext *ctx ) /* * Smooth-shaded, z-less triangle, RGBA color. */ -static void smooth_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, - GLuint v2, GLuint pv ) +static void smooth_rgba_z_triangle( GLcontext *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - GLint rshift = osmesa->rshift; - GLint gshift = osmesa->gshift; - GLint bshift = osmesa->bshift; - GLint ashift = osmesa->ashift; - (void) pv; + 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 INNER_LOOP( LEFT, RIGHT, Y ) \ -{ \ - GLint i, len = RIGHT-LEFT; \ - GLuint *img = PIXELADDR4(LEFT,Y); \ - for (i=0;iDriverCtx; + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INTERP_Z 1 -#define SETUP_CODE \ - GLubyte r = VB->ColorPtr->data[pv][0]; \ - GLubyte g = VB->ColorPtr->data[pv][1]; \ - GLubyte b = VB->ColorPtr->data[pv][2]; \ - GLubyte a = VB->ColorPtr->data[pv][3]; \ - GLuint pixel = PACK_RGBA(r,g,b,a); - -#define INNER_LOOP( LEFT, RIGHT, Y ) \ -{ \ - GLint i, len = RIGHT-LEFT; \ - GLuint *img = PIXELADDR4(LEFT,Y); \ - for (i=0;icolor[0], v2->color[1], \ + v2->color[2], v2->color[3]); + +#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 "..\tritemp.h" +#include "..\swrast\s_tritemp.h" #else -#include "tritemp.h" +#include "swrast/s_tritemp.h" #endif } @@ -1494,30 +1957,91 @@ static void flat_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, /* * Return pointer to an accelerated triangle function if possible. */ -static triangle_func choose_triangle_function( GLcontext *ctx ) +static swrast_tri_func +osmesa_choose_triangle_function( GLcontext *ctx ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; - - if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) return NULL; - - if (ctx->Polygon.SmoothFlag) return NULL; - if (ctx->Polygon.StippleFlag) return NULL; - if (ctx->Texture.Enabled) return NULL; - - if (ctx->RasterMask==DEPTH_BIT - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_TRUE - && osmesa->format!=OSMESA_COLOR_INDEX) { - if (ctx->Light.ShadeModel==GL_SMOOTH) { - return smooth_rgba_z_triangle; + 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 (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 flat_rgba_z_triangle; + return (swrast_tri_func) flat_rgba_z_triangle; } } - return NULL; + return (swrast_tri_func) NULL; +} + + + +/* 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); + + swrast->Triangle = osmesa_choose_triangle_function( ctx ); + if (!swrast->Triangle) + _swrast_choose_triangle( ctx ); } +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) + +#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 ) +{ + SWcontext *swrast = SWRAST_CONTEXT( ctx ); + + 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 const GLubyte *get_string( GLcontext *ctx, GLenum name ) @@ -1525,70 +2049,134 @@ static const GLubyte *get_string( GLcontext *ctx, GLenum name ) (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 ) +static void osmesa_update_state( GLcontext *ctx, GLuint new_state ) { - OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); - ctx->Driver.GetString = get_string; - ctx->Driver.UpdateState = osmesa_update_state; + ASSERT((void *) osmesa == (void *) ctx->DriverCtx); - ctx->Driver.SetBuffer = set_buffer; - ctx->Driver.Color = set_color; - ctx->Driver.Index = set_index; - ctx->Driver.ClearIndex = clear_index; - ctx->Driver.ClearColor = clear_color; - ctx->Driver.Clear = clear; + /* + * 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.PointsFunc = NULL; - ctx->Driver.LineFunc = choose_line_function( ctx ); - ctx->Driver.TriangleFunc = choose_triangle_function( ctx ); - + 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) || (osmesa->format==OSMESA_BGR)) { - /* 3 bytes / pixel in frame buffer */ - ctx->Driver.WriteRGBASpan = write_rgba_span3; - ctx->Driver.WriteRGBSpan = write_rgb_span3; - ctx->Driver.WriteRGBAPixels = write_rgba_pixels3; - ctx->Driver.WriteMonoRGBASpan = write_monocolor_span3; - ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels3; - ctx->Driver.ReadRGBASpan = read_rgba_span3; - ctx->Driver.ReadRGBAPixels = read_rgba_pixels3; + 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; + } + 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 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; } else { - /* 4 bytes / pixel in frame buffer */ - if (osmesa->format==OSMESA_RGBA - && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) - ctx->Driver.WriteRGBASpan = write_rgba_span_rgba; - else - ctx->Driver.WriteRGBASpan = write_rgba_span; - ctx->Driver.WriteRGBSpan = write_rgb_span; - ctx->Driver.WriteRGBAPixels = write_rgba_pixels; - ctx->Driver.WriteMonoRGBASpan = write_monocolor_span; - ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels; - if (osmesa->format==OSMESA_RGBA - && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) - ctx->Driver.ReadRGBASpan = read_rgba_span_rgba; - else - ctx->Driver.ReadRGBASpan = read_rgba_span; - ctx->Driver.ReadRGBAPixels = read_rgba_pixels; + /* 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; } /* CI span/pixel functions */ - ctx->Driver.WriteCI32Span = write_index32_span; - ctx->Driver.WriteCI8Span = write_index8_span; - ctx->Driver.WriteMonoCISpan = write_monoindex_span; - ctx->Driver.WriteCI32Pixels = write_index_pixels; - ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels; - ctx->Driver.ReadCI32Span = read_index_span; - ctx->Driver.ReadCI32Pixels = read_index_pixels; + 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 ); }