/* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, * 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 (including the * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include "main/context.h" #include "main/context.h" #include "main/matrix.h" #include "main/framebuffer.h" #include "main/renderbuffer.h" #include "main/simple_list.h" #include "utils.h" #include "main/extensions.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" #include "vbo/vbo.h" #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" #include "savagedd.h" #include "savagestate.h" #include "savagetex.h" #include "savagespan.h" #include "savagetris.h" #include "savageioctl.h" #include "savage_bci.h" #include "savage_dri.h" #include "drirenderbuffer.h" #include "texmem.h" #define need_GL_EXT_secondary_color #include "main/remap_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; #endif /*For time caculating test*/ #if defined(DEBUG_TIME) && DEBUG_TIME struct timeval tv_s,tv_f; unsigned long time_sum=0; struct timeval tv_s1,tv_f1; #endif static const struct dri_extension card_extensions[] = { { "GL_ARB_multitexture", NULL }, { "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, }; PUBLIC const __DRIextension *savageScreenExtensions[] = { &driCoreExtension.base, &driLegacyExtension.base, &driReadDrawableExtension, }; static GLboolean savageInitDriver(__DRIscreenPrivate *sPriv) { savageScreenPrivate *savageScreen; SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv; if (sPriv->devPrivSize != sizeof(SAVAGEDRIRec)) { fprintf(stderr,"\nERROR! sizeof(SAVAGEDRIRec) does not match passed size from device driver\n"); return GL_FALSE; } /* Allocate the private area */ savageScreen = (savageScreenPrivate *)_mesa_malloc(sizeof(savageScreenPrivate)); if (!savageScreen) return GL_FALSE; savageScreen->driScrnPriv = sPriv; sPriv->private = (void *)savageScreen; savageScreen->chipset=gDRIPriv->chipset; savageScreen->width=gDRIPriv->width; savageScreen->height=gDRIPriv->height; savageScreen->mem=gDRIPriv->mem; savageScreen->cpp=gDRIPriv->cpp; savageScreen->zpp=gDRIPriv->zpp; 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->depthOffset=gDRIPriv->depthOffset; savageScreen->textureOffset[SAVAGE_CARD_HEAP] = gDRIPriv->textureOffset; savageScreen->textureSize[SAVAGE_CARD_HEAP] = gDRIPriv->textureSize; savageScreen->logTextureGranularity[SAVAGE_CARD_HEAP] = gDRIPriv->logTextureGranularity; savageScreen->textureOffset[SAVAGE_AGP_HEAP] = gDRIPriv->agpTextureHandle; savageScreen->textureSize[SAVAGE_AGP_HEAP] = gDRIPriv->agpTextureSize; savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] = gDRIPriv->logAgpTextureGranularity; 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) { _mesa_free(savageScreen); sPriv->private = NULL; return GL_FALSE; } } else savageScreen->agpTextures.map = NULL; savageScreen->texVirtual[SAVAGE_CARD_HEAP] = (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) { _mesa_free(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); sPriv->extensions = savageScreenExtensions; #if 0 savageDDFastPathInit(); savageDDTrifuncInit(); savageDDSetupInit(); #endif return GL_TRUE; } /* Accessed by dlsym from dri_mesa_init.c */ static void savageDestroyScreen(__DRIscreenPrivate *sPriv) { savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private; if (savageScreen->bufs) drmUnmapBufs(savageScreen->bufs); /* free all option information */ driDestroyOptionInfo (&savageScreen->optionCache); _mesa_free(savageScreen); sPriv->private = NULL; } static GLboolean savageCreateContext( const __GLcontextModes *mesaVis, __DRIcontextPrivate *driContextPriv, void *sharedContextPrivate ) { GLcontext *ctx, *shareCtx; savageContextPtr imesa; __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; struct dd_function_table functions; 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)_mesa_calloc(sizeof(savageContext)); if (!imesa) { return GL_FALSE; } /* Init default driver functions then plug in savage-specific texture * functions that are needed as early as during context creation. */ _mesa_init_driver_functions( &functions ); savageDDInitTextureFuncs( &functions ); /* Allocate the Mesa context */ if (sharedContextPrivate) shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa); if (!ctx) { _mesa_free(imesa); return GL_FALSE; } driContextPriv->driverPrivate = imesa; 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; ctx->Const.MinLineWidthAA = 1.0; ctx->Const.MaxLineWidth = 3.0; ctx->Const.MaxLineWidthAA = 3.0; ctx->Const.LineWidthGranularity = 1.0; #endif ctx->Const.MaxDrawBuffers = 1; /* Dri stuff */ imesa->hHWContext = driContextPriv->hHWContext; imesa->driFd = sPriv->fd; imesa->driHwLock = &sPriv->pSAREA->lock; imesa->savageScreen = savageScreen; imesa->driScreen = sPriv; imesa->sarea = saPriv; imesa->glBuffer = NULL; /* DMA buffer */ for(i=0;i<5;i++) { imesa->apertureBase[i] = (GLubyte *)savageScreen->aperture.map + 0x01000000 * i; } imesa->aperturePitch = savageScreen->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. */ } 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 = mesaVis->stencilBits && mesaVis->depthBits == 24; imesa->depth_scale = (imesa->savageScreen->zpp == 2) ? (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 = (uint32_t *)malloc(imesa->bufferSize); imesa->vtxBuf = &imesa->clientVtxBuf; imesa->firstElt = -1; /* Uninitialized vertex format. Force setting the vertex state in * savageRenderStart. */ imesa->vertex_size = 0; /* Utah stuff */ imesa->new_state = ~0; imesa->new_gl_state = ~0; imesa->RenderIndex = ~0; imesa->dirty = ~0; imesa->lostContext = GL_TRUE; imesa->CurrentTexObj[0] = 0; imesa->CurrentTexObj[1] = 0; /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); _vbo_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); /* Install the customized pipeline: */ _tnl_destroy_pipeline( ctx ); _tnl_install_pipeline( ctx, savage_pipeline ); 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->drm_version.minor < 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: */ _tnl_allow_pixel_fog( ctx, GL_FALSE ); _tnl_allow_vertex_fog( ctx, GL_TRUE ); _swrast_allow_pixel_fog( ctx, GL_FALSE ); _swrast_allow_vertex_fog( ctx, GL_TRUE ); ctx->DriverCtx = (void *) imesa; imesa->glCtx = 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 ); savageDDInitDriverFuncs( ctx ); savageDDInitIoctlFuncs( ctx ); savageInitTriFuncs( ctx ); savageDDInitState( imesa ); driContextPriv->driverPrivate = (void *) imesa; return GL_TRUE; } static void savageDestroyContext(__DRIcontextPrivate *driContextPriv) { savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate; GLuint i; assert (imesa); /* should never be NULL */ if (imesa) { 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); _swsetup_DestroyContext(imesa->glCtx ); _tnl_DestroyContext( imesa->glCtx ); _vbo_DestroyContext( imesa->glCtx ); _swrast_DestroyContext( imesa->glCtx ); /* free the Mesa context */ imesa->glCtx->DriverCtx = NULL; _mesa_destroy_context(imesa->glCtx); /* no longer use vertex_dma_buf*/ Xfree(imesa); } } 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 { 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); } } static void savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) { _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL); } #if 0 void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv) { /* XXX should do swap according to the buffer, not the context! */ savageContextPtr imesa = savageCtx; FLUSH_VB( imesa->glCtx, "swap buffers" ); savageSwapBuffers(imesa); } #endif void savageXMesaSetClipRects(savageContextPtr imesa) { __DRIdrawablePrivate *dPriv = imesa->driDrawable; if ((dPriv->numBackClipRects == 0) || (imesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_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; } 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"); savageXMesaSetClipRects(imesa); driUpdateFramebufferSize(imesa->glCtx, drawable); if (drawable != readable) { driUpdateFramebufferSize(imesa->glCtx, readable); } } static GLboolean savageUnbindContext(__DRIcontextPrivate *driContextPriv) { savageContextPtr savage = (savageContextPtr) driContextPriv->driverPrivate; if (savage) savage->dirty = ~0; return GL_TRUE; } #if 0 static GLboolean savageOpenFullScreen(__DRIcontextPrivate *driContextPriv) { if (driContextPriv) { savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate; imesa->IsFullScreen = GL_TRUE; imesa->backup_frontOffset = imesa->savageScreen->frontOffset; imesa->backup_backOffset = imesa->savageScreen->backOffset; imesa->backup_frontBitmapDesc = imesa->savageScreen->frontBitmapDesc; imesa->savageScreen->frontBitmapDesc = imesa->savageScreen->backBitmapDesc; imesa->toggle = TARGET_BACK; } return GL_TRUE; } static GLboolean savageCloseFullScreen(__DRIcontextPrivate *driContextPriv) { if (driContextPriv) { savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate; WAIT_IDLE_EMPTY(imesa); imesa->IsFullScreen = GL_FALSE; imesa->savageScreen->frontOffset = imesa->backup_frontOffset; imesa->savageScreen->backOffset = imesa->backup_backOffset; imesa->savageScreen->frontBitmapDesc = imesa->backup_frontBitmapDesc; } return GL_TRUE; } #endif static GLboolean savageMakeCurrent(__DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv) { if (driContextPriv) { 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->dirty = ~0; _mesa_make_current(imesa->glCtx, drawBuffer, readBuffer); savageXMesaWindowMoved( imesa ); } else { _mesa_make_current(NULL, NULL, NULL); } return GL_TRUE; } void savageGetLock( savageContextPtr imesa, GLuint flags ) { __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 = drawable->lastStamp; int heap; unsigned int timestamp = 0; /* We know there has been contention. */ drmGetLock(imesa->driFd, imesa->hHWContext, flags); /* Note contention for throttling hint */ imesa->any_contend = 1; /* If the window moved, may need to set a new cliprect now. * * NOTE: This releases and regains the hw lock, so all state * checking must be done *after* this call: */ 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 * accelerated commands, so the DRI locking in the X server is even * more broken than usual. */ if (sarea->ctxOwner != me) { imesa->dirty |= (SAVAGE_UPLOAD_LOCAL | SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_FOGTBL | SAVAGE_UPLOAD_TEX0 | SAVAGE_UPLOAD_TEX1 | SAVAGE_UPLOAD_TEXGLOBAL); imesa->lostContext = GL_TRUE; sarea->ctxOwner = me; } 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] ); } if (drawable->lastStamp != stamp) { driUpdateFramebufferSize(imesa->glCtx, drawable); savageXMesaWindowMoved( imesa ); } } static const __DRIconfig ** savageFillInModes( __DRIscreenPrivate *psp, unsigned pixel_bits, unsigned depth_bits, unsigned stencil_bits, GLboolean have_back_buffer ) { __DRIconfig **configs; __GLcontextModes * m; unsigned depth_buffer_factor; unsigned back_buffer_factor; GLenum fb_format; GLenum fb_type; int i; /* 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 */ }; uint8_t depth_bits_array[2]; uint8_t stencil_bits_array[2]; uint8_t msaa_samples_array[1]; 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; msaa_samples_array[0] = 0; depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1; back_buffer_factor = (have_back_buffer) ? 2 : 1; 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; } configs = driCreateConfigs(fb_format, fb_type, depth_bits_array, stencil_bits_array, depth_buffer_factor, back_buffer_modes, back_buffer_factor, msaa_samples_array, 1); if (configs == NULL) { fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", __func__, __LINE__ ); return NULL; } /* Mark the visual as slow if there are "fake" stencil bits. */ for (i = 0; configs[i]; i++) { m = &configs[i]->modes; if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { m->visualRating = GLX_SLOW_CONFIG; } } return (const __DRIconfig **) configs; } /** * This is the driver specific part of the createNewScreen entry point. * * \todo maybe fold this into intelInitDriver * * \return the __GLcontextModes supported by this driver */ static const __DRIconfig ** savageInitScreen(__DRIscreenPrivate *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 }; SAVAGEDRIPtr dri_priv = (SAVAGEDRIPtr)psp->pDevPriv; if ( ! driCheckDriDdxDrmVersions2( "Savage", &psp->dri_version, & dri_expected, &psp->ddx_version, & ddx_expected, &psp->drm_version, & drm_expected ) ) return NULL; if (!savageInitDriver(psp)) return NULL; return savageFillInModes( psp, dri_priv->cpp*8, (dri_priv->cpp == 2) ? 16 : 24, (dri_priv->cpp == 2) ? 0 : 8, (dri_priv->backOffset != dri_priv->depthOffset) ); } const struct __DriverAPIRec driDriverAPI = { savageInitScreen, savageDestroyScreen, savageCreateContext, savageDestroyContext, savageCreateBuffer, savageDestroyBuffer, savageSwapBuffers, savageMakeCurrent, savageUnbindContext };