X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fsavage%2Fsavage_xmesa.c;h=9678c526aa01721503b8f8fd9dd03fefa0f258e4;hb=aac367f48afc62176faf67aa6f329fbeae2004b4;hp=c7b31df2c68fc518a72dbc5350cd955bb6002fc0;hpb=2cd815b66009eea8e06dc4b6dfd32cb7898ff416;p=mesa.git diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c index c7b31df2c68..9678c526aa0 100644 --- a/src/mesa/drivers/dri/savage/savage_xmesa.c +++ b/src/mesa/drivers/dri/savage/savage_xmesa.c @@ -23,21 +23,24 @@ */ -#ifdef GLX_DIRECT_RENDERING - #include #include #include "savagecontext.h" #include "context.h" #include "matrix.h" - +#include "framebuffer.h" +#include "renderbuffer.h" #include "simple_list.h" +#include "utils.h" + +#include "extensions.h" + #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" #include "tnl/t_pipeline.h" @@ -53,22 +56,71 @@ #include "savage_dri.h" -#include "savagedma.h" +#include "drirenderbuffer.h" +#include "texmem.h" +#define need_GL_ARB_multisample +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_buffer_object +#define need_GL_EXT_secondary_color +#include "extension_helper.h" + +#include "xmlpool.h" + +/* Driver-specific options + */ +#define SAVAGE_ENABLE_VDMA(def) \ +DRI_CONF_OPT_BEGIN(enable_vdma,bool,def) \ + DRI_CONF_DESC(en,"Use DMA for vertex transfers") \ + DRI_CONF_DESC(de,"Benutze DMA für Vertextransfers") \ +DRI_CONF_OPT_END +#define SAVAGE_ENABLE_FASTPATH(def) \ +DRI_CONF_OPT_BEGIN(enable_fastpath,bool,def) \ + DRI_CONF_DESC(en,"Use fast path for unclipped primitives") \ + DRI_CONF_DESC(de,"Schneller Codepfad für ungeschnittene Polygone") \ +DRI_CONF_OPT_END +#define SAVAGE_SYNC_FRAMES(def) \ +DRI_CONF_OPT_BEGIN(sync_frames,bool,def) \ + DRI_CONF_DESC(en,"Synchronize with graphics hardware after each frame") \ + DRI_CONF_DESC(de,"Synchronisiere nach jedem Frame mit Grafikhardware") \ +DRI_CONF_OPT_END + +/* Configuration + */ +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_QUALITY + DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB) + DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER) + DRI_CONF_FLOAT_DEPTH(false) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_PERFORMANCE + SAVAGE_ENABLE_VDMA(true) + SAVAGE_ENABLE_FASTPATH(true) + SAVAGE_SYNC_FRAMES(false) + DRI_CONF_MAX_TEXTURE_UNITS(2,1,2) + DRI_CONF_TEXTURE_HEAPS(DRI_CONF_TEXTURE_HEAPS_ALL) + DRI_CONF_FORCE_S3TC_ENABLE(false) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_DEBUG + DRI_CONF_NO_RAST(false) + DRI_CONF_SECTION_END +DRI_CONF_END; +static const GLuint __driNConfigOptions = 10; + + +static const struct dri_debug_control debug_control[] = +{ + { "fall", DEBUG_FALLBACKS }, + { "api", DEBUG_VERBOSE_API }, + { "tex", DEBUG_VERBOSE_TEX }, + { "verb", DEBUG_VERBOSE_MSG }, + { "dma", DEBUG_DMA }, + { "state", DEBUG_STATE }, + { NULL, 0 } +}; #ifndef SAVAGE_DEBUG -int SAVAGE_DEBUG = (0 -/* | DEBUG_ALWAYS_SYNC */ -/* | DEBUG_VERBOSE_RING */ -/* | DEBUG_VERBOSE_OUTREG */ -/* | DEBUG_VERBOSE_MSG */ -/* | DEBUG_NO_OUTRING */ -/* | DEBUG_NO_OUTREG */ -/* | DEBUG_VERBOSE_API */ -/* | DEBUG_VERBOSE_2D */ -/* | DEBUG_VERBOSE_DRI */ -/* | DEBUG_VALIDATE_RING */ -/* | DEBUG_VERBOSE_IOCTL */ - ); +int SAVAGE_DEBUG = 0; #endif @@ -79,6 +131,43 @@ unsigned long time_sum=0; struct timeval tv_s1,tv_f1; #endif +static const struct dri_extension card_extensions[] = +{ + { "GL_ARB_multisample", GL_ARB_multisample_functions }, + { "GL_ARB_multitexture", NULL }, + { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, + { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_EXT_texture_lod_bias", NULL }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { NULL, NULL } +}; + +static const struct dri_extension s4_extensions[] = +{ + { "GL_ARB_texture_env_add", NULL }, + { "GL_ARB_texture_mirrored_repeat", NULL }, + { NULL, NULL } +}; + +extern struct tnl_pipeline_stage _savage_texnorm_stage; +extern struct tnl_pipeline_stage _savage_render_stage; + +static const struct tnl_pipeline_stage *savage_pipeline[] = { + + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_savage_texnorm_stage, + &_savage_render_stage, + &_tnl_render_stage, + 0, +}; + + /* this is first function called in dirver*/ static GLboolean @@ -86,33 +175,15 @@ savageInitDriver(__DRIscreenPrivate *sPriv) { savageScreenPrivate *savageScreen; SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv; + PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = + (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension")); - /* Check the DRI version */ - { - int major, minor, patch; - if (XF86DRIQueryVersion(sPriv->display, &major, &minor, &patch)) { - if (major != 4 || minor < 0) { - __driUtilMessage("savage DRI driver expected DRI version 4.0.x but got version %d.%d.%d", major, minor, patch); - return GL_FALSE; - } - } - } - - /* Check that the DDX driver version is compatible */ - if (sPriv->ddxMajor != 1 || - sPriv->ddxMinor < 0) { - __driUtilMessage("savage DRI driver expected DDX driver version 1.0.x but got version %d.%d.%d", sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch); + if (sPriv->devPrivSize != sizeof(SAVAGEDRIRec)) { + fprintf(stderr,"\nERROR! sizeof(SAVAGEDRIRec) does not match passed size from device driver\n"); return GL_FALSE; } - /* Check that the DRM driver version is compatible */ - if (sPriv->drmMajor != 1 || - sPriv->drmMinor < 0) { - __driUtilMessage("savage DRI driver expected DRM driver version 1.1.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch); - return GL_FALSE; - } - /* Allocate the private area */ savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate)); if (!savageScreen) @@ -127,23 +198,19 @@ savageInitDriver(__DRIscreenPrivate *sPriv) savageScreen->mem=gDRIPriv->mem; savageScreen->cpp=gDRIPriv->cpp; savageScreen->zpp=gDRIPriv->zpp; - savageScreen->frontPitch=gDRIPriv->frontPitch; - savageScreen->frontOffset=gDRIPriv->frontOffset; - savageScreen->frontBitmapDesc = gDRIPriv->frontBitmapDesc; - + + savageScreen->agpMode=gDRIPriv->agpMode; + + savageScreen->bufferSize=gDRIPriv->bufferSize; + if (gDRIPriv->cpp == 4) savageScreen->frontFormat = DV_PF_8888; else savageScreen->frontFormat = DV_PF_565; - + savageScreen->frontOffset=gDRIPriv->frontOffset; savageScreen->backOffset = gDRIPriv->backOffset; - savageScreen->backBitmapDesc = gDRIPriv->backBitmapDesc; savageScreen->depthOffset=gDRIPriv->depthOffset; - savageScreen->depthBitmapDesc = gDRIPriv->depthBitmapDesc; -#if 0 - savageScreen->backPitch = gDRIPriv->auxPitch; - savageScreen->backPitchBits = gDRIPriv->auxPitchBits; -#endif + savageScreen->textureOffset[SAVAGE_CARD_HEAP] = gDRIPriv->textureOffset; savageScreen->textureSize[SAVAGE_CARD_HEAP] = @@ -152,27 +219,56 @@ savageInitDriver(__DRIscreenPrivate *sPriv) gDRIPriv->logTextureGranularity; savageScreen->textureOffset[SAVAGE_AGP_HEAP] = - gDRIPriv->agpTextures.handle; + gDRIPriv->agpTextureHandle; savageScreen->textureSize[SAVAGE_AGP_HEAP] = - gDRIPriv->agpTextures.size; + gDRIPriv->agpTextureSize; savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] = gDRIPriv->logAgpTextureGranularity; - - savageScreen->back.handle = gDRIPriv->backbuffer; - savageScreen->back.size = gDRIPriv->backbufferSize; - savageScreen->back.map = - (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->backOffset); - - savageScreen->depth.handle = gDRIPriv->depthbuffer; - savageScreen->depth.size = gDRIPriv->depthbufferSize; - savageScreen->depth.map = - (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->depthOffset); - - savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; + savageScreen->agpTextures.handle = gDRIPriv->agpTextureHandle; + savageScreen->agpTextures.size = gDRIPriv->agpTextureSize; + if (gDRIPriv->agpTextureSize) { + if (drmMap(sPriv->fd, + savageScreen->agpTextures.handle, + savageScreen->agpTextures.size, + (drmAddress *)&(savageScreen->agpTextures.map)) != 0) { + Xfree(savageScreen); + sPriv->private = NULL; + return GL_FALSE; + } + } else + savageScreen->agpTextures.map = NULL; savageScreen->texVirtual[SAVAGE_CARD_HEAP] = - (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->textureOffset); + (drmAddress)(((GLubyte *)sPriv->pFB)+gDRIPriv->textureOffset); + savageScreen->texVirtual[SAVAGE_AGP_HEAP] = + (drmAddress)(savageScreen->agpTextures.map); + + savageScreen->aperture.handle = gDRIPriv->apertureHandle; + savageScreen->aperture.size = gDRIPriv->apertureSize; + savageScreen->aperturePitch = gDRIPriv->aperturePitch; + if (drmMap(sPriv->fd, + savageScreen->aperture.handle, + savageScreen->aperture.size, + (drmAddress *)&savageScreen->aperture.map) != 0) + { + Xfree(savageScreen); + sPriv->private = NULL; + return GL_FALSE; + } + + savageScreen->bufs = drmMapBufs(sPriv->fd); + + savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; + + /* parse information in __driConfigOptions */ + driParseOptionInfo (&savageScreen->optionCache, + __driConfigOptions, __driNConfigOptions); + + if (glx_enable_extension != NULL) { + (*glx_enable_extension)(sPriv->psc, "GLX_SGI_make_current_read"); + } + #if 0 savageDDFastPathInit(); savageDDTrifuncInit(); @@ -188,7 +284,12 @@ savageDestroyScreen(__DRIscreenPrivate *sPriv) { savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private; - + if (savageScreen->bufs) + drmUnmapBufs(savageScreen->bufs); + + /* free all option information */ + driDestroyOptionInfo (&savageScreen->optionCache); + Xfree(savageScreen); sPriv->private = NULL; } @@ -230,10 +331,10 @@ savageCreateContext( const __GLcontextModes *mesaVis, savageContextPtr imesa; __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; struct dd_function_table functions; - SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv; savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private; drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+ savageScreen->sarea_priv_offset); + int textureSize[SAVAGE_NR_TEX_HEAPS]; int i; imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1); if (!imesa) { @@ -257,24 +358,19 @@ savageCreateContext( const __GLcontextModes *mesaVis, } driContextPriv->driverPrivate = imesa; - /* BEGIN;*/ - /* Set the maximum texture size small enough that we can guarentee - * that both texture units can bind a maximal texture and have them - * in memory at once. - */ - if (savageScreen->textureSize[SAVAGE_CARD_HEAP] < 2*1024*1024) { - ctx->Const.MaxTextureLevels = 9; - } else if (savageScreen->textureSize[SAVAGE_CARD_HEAP] < 8*1024*1024) { - ctx->Const.MaxTextureLevels = 10; - } else { - ctx->Const.MaxTextureLevels = 11; - } - if (savageScreen->chipset >= S3_SAVAGE4) - ctx->Const.MaxTextureUnits = 2; - else - ctx->Const.MaxTextureUnits = 1; - ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; - ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; + imesa->cmdBuf.size = SAVAGE_CMDBUF_SIZE; + imesa->cmdBuf.base = imesa->cmdBuf.write = + malloc(SAVAGE_CMDBUF_SIZE * sizeof(drm_savage_cmd_header_t)); + if (!imesa->cmdBuf.base) + return GL_FALSE; + + /* Parse configuration files */ + driParseConfigFiles (&imesa->optionCache, &savageScreen->optionCache, + sPriv->myNum, "savage"); + + imesa->float_depth = driQueryOptionb(&imesa->optionCache, "float_depth") && + savageScreen->chipset >= S3_SAVAGE4; + imesa->no_rast = driQueryOptionb(&imesa->optionCache, "no_rast"); #if 0 ctx->Const.MinLineWidth = 1.0; @@ -297,116 +393,104 @@ savageCreateContext( const __GLcontextModes *mesaVis, /* DMA buffer */ - /*The shadow pointer*/ - imesa->shadowPointer = - (volatile GLuint *)((((GLuint)(&saPriv->shadow_status)) + 31) & 0xffffffe0L) ; - /* here we use eventTag1 because eventTag0 is used by HWXvMC*/ - imesa->eventTag1 = (volatile GLuint *)(imesa->shadowPointer + 6); - /* imesa->eventTag1=(volatile GLuint *)(imesa->MMIO_BASE+0x48c04);*/ - imesa->shadowCounter = MAX_SHADOWCOUNTER; - imesa->shadowStatus = GL_TRUE;/*Will judge by 2d message */ - - if (drmMap(sPriv->fd, - gDRIPriv->registers.handle, - gDRIPriv->registers.size, - (drmAddress *)&(gDRIPriv->registers.map)) != 0) - { - Xfree(savageScreen); - sPriv->private = NULL; - return GL_FALSE; - } - - if (drmMap(sPriv->fd, - gDRIPriv->agpTextures.handle, - gDRIPriv->agpTextures.size, - (drmAddress *)&(gDRIPriv->agpTextures.map)) != 0) - { - Xfree(savageScreen); - sPriv->private = NULL; - return GL_FALSE; - } - -/* agp texture*/ - savageScreen->texVirtual[SAVAGE_AGP_HEAP] = - (drmAddress)(gDRIPriv->agpTextures.map); - - - - gDRIPriv->BCIcmdBuf.map = (drmAddress *) - ((unsigned int)gDRIPriv->registers.map+0x00010000); - - imesa->MMIO_BASE = (GLuint)gDRIPriv->registers.map; - imesa->BCIBase= (GLuint)gDRIPriv->BCIcmdBuf.map; - - savageScreen->aperture.handle = gDRIPriv->aperture.handle; - savageScreen->aperture.size = gDRIPriv->aperture.size; - if (drmMap(sPriv->fd, - savageScreen->aperture.handle, - savageScreen->aperture.size, - (drmAddress *)&savageScreen->aperture.map) != 0) - { - Xfree(savageScreen); - sPriv->private = NULL; - return GL_FALSE; - } - - - - - for(i=0;i<5;i++) { - imesa->apertureBase[i] = ((GLuint)savageScreen->aperture.map + - 0x01000000 * i ); - - + imesa->apertureBase[i] = (GLubyte *)savageScreen->aperture.map + + 0x01000000 * i; } - { - volatile unsigned int * tmp; - - tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x850C); - - - tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x48C40); - - - tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x48C44); - - - tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x48C48); + imesa->aperturePitch = savageScreen->aperturePitch; - - - } - - imesa->aperturePitch = gDRIPriv->aperturePitch; - - /* change texHeap initialize to support two kind of texture heap*/ /* here is some parts of initialization, others in InitDriver() */ + (void) memset( imesa->textureHeaps, 0, sizeof( imesa->textureHeaps ) ); + make_empty_list( & imesa->swapped ); + + textureSize[SAVAGE_CARD_HEAP] = savageScreen->textureSize[SAVAGE_CARD_HEAP]; + textureSize[SAVAGE_AGP_HEAP] = savageScreen->textureSize[SAVAGE_AGP_HEAP]; imesa->lastTexHeap = savageScreen->texVirtual[SAVAGE_AGP_HEAP] ? 2 : 1; + switch(driQueryOptioni (&imesa->optionCache, "texture_heaps")) { + case DRI_CONF_TEXTURE_HEAPS_CARD: /* only use card memory, if available */ + if (textureSize[SAVAGE_CARD_HEAP]) + imesa->lastTexHeap = 1; + break; + case DRI_CONF_TEXTURE_HEAPS_GART: /* only use gart memory, if available */ + if (imesa->lastTexHeap == 2 && textureSize[SAVAGE_AGP_HEAP]) + textureSize[SAVAGE_CARD_HEAP] = 0; + break; + /*default: Nothing to do, use all available memory. */ + } - /*allocate texHeap for multi-tex*/ - { - int i; - - for(i=0;itexHeap[i] = mmInit( 0, savageScreen->textureSize[i] ); - make_empty_list(&imesa->TexObjList[i]); - } - - make_empty_list(&imesa->SwappedOut); + for (i = 0; i < imesa->lastTexHeap; i++) { + imesa->textureHeaps[i] = driCreateTextureHeap( + i, imesa, + textureSize[i], + 11, /* 2^11 = 2k alignment */ + SAVAGE_NR_TEX_REGIONS, + (drmTextureRegionPtr)imesa->sarea->texList[i], + &imesa->sarea->texAge[i], + &imesa->swapped, + sizeof( savageTexObj ), + (destroy_texture_object_t *) savageDestroyTexObj ); + /* If textureSize[i] == 0 textureHeaps[i] is NULL. This can happen + * if there is not enough card memory for a card texture heap. */ + if (imesa->textureHeaps[i]) + driSetTextureSwapCounterLocation( imesa->textureHeaps[i], + & imesa->c_textureSwaps ); + } + imesa->texture_depth = driQueryOptioni (&imesa->optionCache, + "texture_depth"); + if (imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB) + imesa->texture_depth = ( savageScreen->cpp == 4 ) ? + DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16; + + if (savageScreen->chipset >= S3_SAVAGE4) + ctx->Const.MaxTextureUnits = 2; + else + ctx->Const.MaxTextureUnits = 1; + if (driQueryOptioni(&imesa->optionCache, "texture_units") < + ctx->Const.MaxTextureUnits) + ctx->Const.MaxTextureUnits = + driQueryOptioni(&imesa->optionCache, "texture_units"); + ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; + ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; + + driCalculateMaxTextureLevels( imesa->textureHeaps, + imesa->lastTexHeap, + & ctx->Const, + 4, + 11, /* max 2D texture size is 2048x2048 */ + 0, /* 3D textures unsupported. */ + 0, /* cube textures unsupported. */ + 0, /* texture rectangles unsupported. */ + 12, + GL_FALSE, + 0 ); + if (ctx->Const.MaxTextureLevels <= 6) { /*spec requires at least 64x64*/ + __driUtilMessage("Not enough texture memory. " + "Falling back to indirect rendering."); + Xfree(imesa); + return GL_FALSE; } - imesa->hw_stencil = GL_FALSE; -#if HW_STENCIL imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; -#endif imesa->depth_scale = (imesa->savageScreen->zpp == 2) ? - (1.0F/0x10000):(1.0F/0x1000000); + (1.0F/0xffff):(1.0F/0xffffff); + + imesa->bufferSize = savageScreen->bufferSize; + imesa->dmaVtxBuf.total = 0; + imesa->dmaVtxBuf.used = 0; + imesa->dmaVtxBuf.flushed = 0; + + imesa->clientVtxBuf.total = imesa->bufferSize / 4; + imesa->clientVtxBuf.used = 0; + imesa->clientVtxBuf.flushed = 0; + imesa->clientVtxBuf.buf = (u_int32_t *)malloc(imesa->bufferSize); + + imesa->vtxBuf = &imesa->clientVtxBuf; + + imesa->firstElt = -1; /* Uninitialized vertex format. Force setting the vertex state in * savageRenderStart. @@ -416,29 +500,44 @@ savageCreateContext( const __GLcontextModes *mesaVis, /* Utah stuff */ imesa->new_state = ~0; + imesa->new_gl_state = ~0; imesa->RenderIndex = ~0; imesa->dirty = ~0; imesa->lostContext = GL_TRUE; - imesa->TextureMode = ctx->Texture.Unit[0].EnvMode; imesa->CurrentTexObj[0] = 0; imesa->CurrentTexObj[1] = 0; - imesa->texAge[SAVAGE_CARD_HEAP]=0; - imesa->texAge[SAVAGE_AGP_HEAP]=0; /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); - _ac_CreateContext( ctx ); + _vbo_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); /* Install the customized pipeline: */ -#if 0 _tnl_destroy_pipeline( ctx ); _tnl_install_pipeline( ctx, savage_pipeline ); -#endif + + imesa->enable_fastpath = driQueryOptionb(&imesa->optionCache, + "enable_fastpath"); + /* DRM versions before 2.1.3 would only render triangle lists. ELTS + * support was added in 2.2.0. */ + if (imesa->enable_fastpath && sPriv->drmMinor < 2) { + fprintf (stderr, + "*** Disabling fast path because your DRM version is buggy " + "or doesn't\n*** support ELTS. You need at least Savage DRM " + "version 2.2.\n"); + imesa->enable_fastpath = GL_FALSE; + } + + if (!savageScreen->bufs || savageScreen->chipset == S3_SUPERSAVAGE) + imesa->enable_vdma = GL_FALSE; + else + imesa->enable_vdma = driQueryOptionb(&imesa->optionCache, "enable_vdma"); + + imesa->sync_frames = driQueryOptionb(&imesa->optionCache, "sync_frames"); /* Configure swrast to match hardware characteristics: */ @@ -449,10 +548,23 @@ savageCreateContext( const __GLcontextModes *mesaVis, ctx->DriverCtx = (void *) imesa; imesa->glCtx = ctx; - if (savageDMAInit(imesa) == GL_FALSE) - return GL_FALSE; - - savageDDExtensionsInit( ctx ); + +#ifndef SAVAGE_DEBUG + SAVAGE_DEBUG = driParseDebugString( getenv( "SAVAGE_DEBUG" ), + debug_control ); +#endif + + driInitExtensions( ctx, card_extensions, GL_TRUE ); + if (savageScreen->chipset >= S3_SAVAGE4) + driInitExtensions( ctx, s4_extensions, GL_FALSE ); + if (ctx->Mesa_DXTn || + driQueryOptionb (&imesa->optionCache, "force_s3tc_enable")) { + _mesa_enable_extension( ctx, "GL_S3_s3tc" ); + if (savageScreen->chipset >= S3_SAVAGE4) + /* This extension needs DXT3 and DTX5 support in hardware. + * Not available on Savage3D/MX/IX. */ + _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); + } savageDDInitStateFuncs( ctx ); savageDDInitSpanFuncs( ctx ); @@ -471,25 +583,24 @@ static void savageDestroyContext(__DRIcontextPrivate *driContextPriv) { savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate; + GLuint i; assert (imesa); /* should never be NULL */ if (imesa) { - savageTextureObjectPtr next_t, t; + savageFlushVertices(imesa); + savageReleaseIndexedVerts(imesa); + savageFlushCmdBuf(imesa, GL_TRUE); /* release DMA buffer */ + WAIT_IDLE_EMPTY(imesa); + + for (i = 0; i < imesa->lastTexHeap; i++) + driDestroyTextureHeap(imesa->textureHeaps[i]); + + free(imesa->cmdBuf.base); + free(imesa->clientVtxBuf.buf); - /* update for multi-tex*/ - { - int i; - for(i=0;iTexObjList[i])) - savageDestroyTexObj(imesa, t); - } - foreach_s (t, next_t, &(imesa->SwappedOut)) - savageDestroyTexObj(imesa, t); - /*free the dma buffer*/ - savageDMAClose(imesa); _swsetup_DestroyContext(imesa->glCtx ); _tnl_DestroyContext( imesa->glCtx ); - _ac_DestroyContext( imesa->glCtx ); + _vbo_DestroyContext( imesa->glCtx ); _swrast_DestroyContext( imesa->glCtx ); /* free the Mesa context */ @@ -501,27 +612,97 @@ savageDestroyContext(__DRIcontextPrivate *driContextPriv) } } + static GLboolean savageCreateBuffer( __DRIscreenPrivate *driScrnPriv, __DRIdrawablePrivate *driDrawPriv, const __GLcontextModes *mesaVis, GLboolean isPixmap) { + savageScreenPrivate *screen = (savageScreenPrivate *) driScrnPriv->private; + if (isPixmap) { return GL_FALSE; /* not implemented */ } else { -#if HW_STENCIL - GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; -#else - GLboolean swStencil = mesaVis->stencilBits > 0; -#endif - driDrawPriv->driverPrivate = (void *) - _mesa_create_framebuffer(mesaVis, - GL_FALSE, /* software depth buffer? */ - swStencil, - mesaVis->accumRedBits > 0, - mesaVis->alphaBits > 0 ); + GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; + struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + /* + * XXX: this value needs to be set according to the config file + * setting. But we don't get that until we create a rendering + * context!!!! + */ + GLboolean float_depth = GL_FALSE; + + { + driRenderbuffer *frontRb + = driNewRenderbuffer(GL_RGBA, + (GLubyte *) screen->aperture.map + + 0x01000000 * TARGET_FRONT, + screen->cpp, + screen->frontOffset, screen->aperturePitch, + driDrawPriv); + savageSetSpanFunctions(frontRb, mesaVis, float_depth); + assert(frontRb->Base.Data); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + } + + if (mesaVis->doubleBufferMode) { + driRenderbuffer *backRb + = driNewRenderbuffer(GL_RGBA, + (GLubyte *) screen->aperture.map + + 0x01000000 * TARGET_BACK, + screen->cpp, + screen->backOffset, screen->aperturePitch, + driDrawPriv); + savageSetSpanFunctions(backRb, mesaVis, float_depth); + assert(backRb->Base.Data); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + } + + if (mesaVis->depthBits == 16) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT16, + (GLubyte *) screen->aperture.map + + 0x01000000 * TARGET_DEPTH, + screen->zpp, + screen->depthOffset, screen->aperturePitch, + driDrawPriv); + savageSetSpanFunctions(depthRb, mesaVis, float_depth); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + else if (mesaVis->depthBits == 24) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT24, + (GLubyte *) screen->aperture.map + + 0x01000000 * TARGET_DEPTH, + screen->zpp, + screen->depthOffset, screen->aperturePitch, + driDrawPriv); + savageSetSpanFunctions(depthRb, mesaVis, float_depth); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + + if (mesaVis->stencilBits > 0 && !swStencil) { + driRenderbuffer *stencilRb + = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, + (GLubyte *) screen->aperture.map + + 0x01000000 * TARGET_DEPTH, + screen->zpp, + screen->depthOffset, screen->aperturePitch, + driDrawPriv); + savageSetSpanFunctions(stencilRb, mesaVis, float_depth); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + GL_FALSE, /* depth */ + swStencil, + mesaVis->accumRedBits > 0, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + driDrawPriv->driverPrivate = (void *) fb; return (driDrawPriv->driverPrivate != NULL); } @@ -530,7 +711,7 @@ savageCreateBuffer( __DRIscreenPrivate *driScrnPriv, static void savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) { - _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); } #if 0 @@ -544,62 +725,41 @@ void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv) } #endif -void savageXMesaSetFrontClipRects( savageContextPtr imesa ) -{ - __DRIdrawablePrivate *dPriv = imesa->driDrawable; - - imesa->numClipRects = dPriv->numClipRects; - imesa->pClipRects = dPriv->pClipRects; - imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS; - imesa->drawX = dPriv->x; - imesa->drawY = dPriv->y; - - savageEmitDrawingRectangle( imesa ); -} - -void savageXMesaSetBackClipRects( savageContextPtr imesa ) +void savageXMesaSetClipRects(savageContextPtr imesa) { __DRIdrawablePrivate *dPriv = imesa->driDrawable; - if (dPriv->numBackClipRects == 0) - { - - + if ((dPriv->numBackClipRects == 0) + || (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT)) { imesa->numClipRects = dPriv->numClipRects; imesa->pClipRects = dPriv->pClipRects; imesa->drawX = dPriv->x; imesa->drawY = dPriv->y; } else { - - imesa->numClipRects = dPriv->numBackClipRects; imesa->pClipRects = dPriv->pBackClipRects; imesa->drawX = dPriv->backX; imesa->drawY = dPriv->backY; } - savageEmitDrawingRectangle( imesa ); - imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS; - - + savageCalcViewport( imesa->glCtx ); } static void savageXMesaWindowMoved( savageContextPtr imesa ) { + __DRIdrawablePrivate *const drawable = imesa->driDrawable; + __DRIdrawablePrivate *const readable = imesa->driReadable; + if (0) fprintf(stderr, "savageXMesaWindowMoved\n\n"); - switch (imesa->glCtx->Color._DrawDestMask) { - case FRONT_LEFT_BIT: - savageXMesaSetFrontClipRects( imesa ); - break; - case BACK_LEFT_BIT: - savageXMesaSetBackClipRects( imesa ); - break; - default: - break; + savageXMesaSetClipRects(imesa); + + driUpdateFramebufferSize(imesa->glCtx, drawable); + if (drawable != readable) { + driUpdateFramebufferSize(imesa->glCtx, readable); } } @@ -614,6 +774,7 @@ savageUnbindContext(__DRIcontextPrivate *driContextPriv) return GL_TRUE; } +#if 0 static GLboolean savageOpenFullScreen(__DRIcontextPrivate *driContextPriv) { @@ -639,7 +800,7 @@ savageCloseFullScreen(__DRIcontextPrivate *driContextPriv) if (driContextPriv) { savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate; - WAIT_IDLE_EMPTY; + WAIT_IDLE_EMPTY(imesa); imesa->IsFullScreen = GL_FALSE; imesa->savageScreen->frontOffset = imesa->backup_frontOffset; imesa->savageScreen->backOffset = imesa->backup_backOffset; @@ -647,7 +808,7 @@ savageCloseFullScreen(__DRIcontextPrivate *driContextPriv) } return GL_TRUE; } - +#endif static GLboolean savageMakeCurrent(__DRIcontextPrivate *driContextPriv, @@ -655,26 +816,33 @@ savageMakeCurrent(__DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driReadPriv) { if (driContextPriv) { - savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate; - + savageContextPtr imesa + = (savageContextPtr) driContextPriv->driverPrivate; + struct gl_framebuffer *drawBuffer + = (GLframebuffer *) driDrawPriv->driverPrivate; + struct gl_framebuffer *readBuffer + = (GLframebuffer *) driReadPriv->driverPrivate; + driRenderbuffer *frontRb = (driRenderbuffer *) + drawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + driRenderbuffer *backRb = (driRenderbuffer *) + drawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer; + + assert(frontRb->Base.Data); + if (imesa->glCtx->Visual.doubleBufferMode) { + assert(backRb->Base.Data); + } + imesa->driReadable = driReadPriv; imesa->driDrawable = driDrawPriv; - imesa->mesa_drawable = driDrawPriv; imesa->dirty = ~0; - _mesa_make_current2(imesa->glCtx, - (GLframebuffer *) driDrawPriv->driverPrivate, - (GLframebuffer *) driReadPriv->driverPrivate); + _mesa_make_current(imesa->glCtx, drawBuffer, readBuffer); savageXMesaWindowMoved( imesa ); - - if (!imesa->glCtx->Viewport.Width) - _mesa_set_viewport(imesa->glCtx, 0, 0, - driDrawPriv->w, driDrawPriv->h); } else { - _mesa_make_current(NULL, NULL); + _mesa_make_current(NULL, NULL, NULL); } return GL_TRUE; } @@ -682,12 +850,14 @@ savageMakeCurrent(__DRIcontextPrivate *driContextPriv, void savageGetLock( savageContextPtr imesa, GLuint flags ) { - __DRIdrawablePrivate *dPriv = imesa->driDrawable; + __DRIdrawablePrivate *const drawable = imesa->driDrawable; + __DRIdrawablePrivate *const readable = imesa->driReadable; __DRIscreenPrivate *sPriv = imesa->driScreen; drm_savage_sarea_t *sarea = imesa->sarea; int me = imesa->hHWContext; - int stamp = dPriv->lastStamp; + int stamp = drawable->lastStamp; int heap; + unsigned int timestamp = 0; @@ -705,10 +875,11 @@ void savageGetLock( savageContextPtr imesa, GLuint flags ) * NOTE: This releases and regains the hw lock, so all state * checking must be done *after* this call: */ - DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); - + DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable); + if (drawable != readable) { + DRI_VALIDATE_DRAWABLE_INFO(sPriv, readable); + } - /* If we lost context, need to dump all registers to hardware. * Note that we don't care about 2d contexts, even if they perform @@ -716,58 +887,33 @@ void savageGetLock( savageContextPtr imesa, GLuint flags ) * more broken than usual. */ if (sarea->ctxOwner != me) { - imesa->dirty |= (SAVAGE_UPLOAD_CTX | - SAVAGE_UPLOAD_CLIPRECTS | + imesa->dirty |= (SAVAGE_UPLOAD_LOCAL | + SAVAGE_UPLOAD_GLOBAL | + SAVAGE_UPLOAD_FOGTBL | SAVAGE_UPLOAD_TEX0 | - SAVAGE_UPLOAD_TEX1); + SAVAGE_UPLOAD_TEX1 | + SAVAGE_UPLOAD_TEXGLOBAL); imesa->lostContext = GL_TRUE; sarea->ctxOwner = me; } - /* Shared texture managment - if another client has played with - * texture space, figure out which if any of our textures have been - * ejected, and update our global LRU. - */ - /*frank just for compiling,texAge,texList,AGP*/ - - for(heap= 0 ;heap < imesa->lastTexHeap ; heap++) - { - if (sarea->texAge[heap] != imesa->texAge[heap]) { - int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]); - int idx, nr = 0; + for (heap = 0; heap < imesa->lastTexHeap; ++heap) { + /* If a heap was changed, update its timestamp. Do this before + * DRI_AGE_TEXTURES updates the local_age. */ + if (imesa->textureHeaps[heap] && + imesa->textureHeaps[heap]->global_age[0] > + imesa->textureHeaps[heap]->local_age) { + if (timestamp == 0) + timestamp = savageEmitEventLocked(imesa, 0); + imesa->textureHeaps[heap]->timestamp = timestamp; + } + DRI_AGE_TEXTURES( imesa->textureHeaps[heap] ); + } - /* Have to go right round from the back to ensure stuff ends up - * LRU in our local list... - */ - for (idx = sarea->texList[heap][SAVAGE_NR_TEX_REGIONS].prev ; - idx != SAVAGE_NR_TEX_REGIONS && nr < SAVAGE_NR_TEX_REGIONS ; - idx = sarea->texList[heap][idx].prev, nr++) - { - if (sarea->texList[heap][idx].age > imesa->texAge[heap]) - { - savageTexturesGone(imesa, heap ,idx * sz, sz, - sarea->texList[heap][idx].in_use); - } - } - - if (nr == SAVAGE_NR_TEX_REGIONS) - { - savageTexturesGone(imesa, heap, 0, - imesa->savageScreen->textureSize[heap], 0); - savageResetGlobalLRU( imesa , heap ); - } - - imesa->dirty |= SAVAGE_UPLOAD_TEX0IMAGE; - imesa->dirty |= SAVAGE_UPLOAD_TEX1IMAGE; - imesa->texAge[heap] = sarea->texAge[heap]; - } - } /* end of for loop */ - - if (dPriv->lastStamp != stamp) + if (drawable->lastStamp != stamp) { + driUpdateFramebufferSize(imesa->glCtx, drawable); savageXMesaWindowMoved( imesa ); - - - + } } @@ -781,25 +927,152 @@ static const struct __DriverAPIRec savageAPI = { savageDestroyBuffer, savageSwapBuffers, savageMakeCurrent, - savageUnbindContext, - savageOpenFullScreen, - savageCloseFullScreen + savageUnbindContext }; +static __GLcontextModes * +savageFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy + * enough to add support. Basically, if a context is created with an + * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping + * will never be used. + * + * FK: What about drivers that don't use page flipping? Could they + * just expose GLX_SWAP_COPY_OML? + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */ + }; + + u_int8_t depth_bits_array[2]; + u_int8_t stencil_bits_array[2]; + + + depth_bits_array[0] = depth_bits; + depth_bits_array[1] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; + + depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1; + back_buffer_factor = (have_back_buffer) ? 2 : 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if ( pixel_bits == 16 ) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGR; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); + m = modes; + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_TRUE_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_DIRECT_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for ( m = modes ; m != NULL ; m = m->next ) { + if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) { + m->visualRating = GLX_SLOW_CONFIG; + } + } + + return modes; +} + -/* - * This is the bootstrap function for the driver. - * The __driCreateScreen name is the symbol that libGL.so fetches. - * Return: pointer to a __DRIscreenPrivate. +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. */ -void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, - int numConfigs, __GLXvisualConfig *config) +PUBLIC +void * __DRI_CREATE_NEW_SCREEN(int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes ) + { __DRIscreenPrivate *psp; - psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &savageAPI); - return (void *) psp; -} + static const __DRIversion ddx_expected = { 2, 0, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 2, 1, 0 }; + dri_interface = interface; -#endif + if ( ! driCheckDriDdxDrmVersions2( "Savage", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected ) ) { + return NULL; + } + + psp = __driUtilCreateNewScreen(scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &savageAPI); + if ( psp != NULL ) { + SAVAGEDRIPtr dri_priv = (SAVAGEDRIPtr)psp->pDevPriv; + *driver_modes = savageFillInModes( dri_priv->cpp*8, + (dri_priv->cpp == 2) ? 16 : 24, + (dri_priv->cpp == 2) ? 0 : 8, + (dri_priv->backOffset != dri_priv->depthOffset) ); + + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + driInitExtensions( NULL, card_extensions, GL_FALSE ); + } + + return (void *) psp; +}