| /* |
| * Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. |
| * |
| * Permission to use, copy, modify, distribute, and sell this software and its |
| * documentation for any purpose is hereby granted without fee, provided that |
| * the above copyright notice appear in all copies and that both that |
| * copyright notice and this permission notice appear in supporting |
| * documentation, and that the name of Alan Hourihane not be used in |
| * advertising or publicity pertaining to distribution of the software without |
| * specific, written prior permission. Alan Hourihane makes no representations |
| * about the suitability of this software for any purpose. It is provided |
| * "as is" without express or implied warranty. |
| * |
| * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
| * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
| * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| * |
| * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> |
| * |
| * Trident CyberBladeXP driver. |
| * |
| */ |
| #include "trident_dri.h" |
| #include "trident_context.h" |
| #include "trident_lock.h" |
| |
| #include "swrast/swrast.h" |
| #include "swrast_setup/swrast_setup.h" |
| #include "vbo/vbo.h" |
| |
| #include "tnl/tnl.h" |
| #include "tnl/t_pipeline.h" |
| |
| #include "context.h" |
| #include "simple_list.h" |
| #include "matrix.h" |
| #include "extensions.h" |
| #include "framebuffer.h" |
| #include "renderbuffer.h" |
| #if defined(USE_X86_ASM) |
| #include "x86/common_x86_asm.h" |
| #endif |
| #include "simple_list.h" |
| #include "mm.h" |
| #include "drirenderbuffer.h" |
| |
| #include "drivers/common/driverfuncs.h" |
| #include "dri_util.h" |
| #include "utils.h" |
| |
| static const struct tnl_pipeline_stage *trident_pipeline[] = { |
| &_tnl_vertex_transform_stage, |
| &_tnl_normal_transform_stage, |
| &_tnl_lighting_stage, |
| &_tnl_texgen_stage, |
| &_tnl_texture_transform_stage, |
| &_tnl_render_stage, |
| 0, |
| }; |
| |
| |
| static GLboolean |
| tridentCreateContext( const __GLcontextModes *glVisual, |
| __DRIcontextPrivate *driContextPriv, |
| void *sharedContextPrivate) |
| { |
| GLcontext *ctx, *shareCtx; |
| __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; |
| tridentContextPtr tmesa; |
| tridentScreenPtr tridentscrn; |
| struct dd_function_table functions; |
| #if 0 |
| drm_trident_sarea_t *saPriv=(drm_trident_sarea_t *)(((char*)sPriv->pSAREA)+ |
| sizeof(XF86DRISAREARec)); |
| #endif |
| |
| tmesa = (tridentContextPtr) CALLOC( sizeof(*tmesa) ); |
| if ( !tmesa ) return GL_FALSE; |
| |
| /* Allocate the Mesa context */ |
| if (sharedContextPrivate) |
| shareCtx = ((tridentContextPtr) sharedContextPrivate)->glCtx; |
| else |
| shareCtx = NULL; |
| |
| _mesa_init_driver_functions(&functions); |
| |
| tmesa->glCtx = |
| _mesa_create_context(glVisual, shareCtx, &functions, (void *)tmesa); |
| |
| if (!tmesa->glCtx) { |
| FREE(tmesa); |
| return GL_FALSE; |
| } |
| |
| tmesa->driContext = driContextPriv; |
| tmesa->driScreen = sPriv; |
| tmesa->driDrawable = NULL; /* Set by XMesaMakeCurrent */ |
| |
| tmesa->hHWContext = driContextPriv->hHWContext; |
| tmesa->driHwLock = (drmLock *)&sPriv->pSAREA->lock; |
| tmesa->driFd = sPriv->fd; |
| #if 0 |
| tmesa->sarea = saPriv; |
| #endif |
| |
| tridentscrn = tmesa->tridentScreen = (tridentScreenPtr)(sPriv->private); |
| |
| ctx = tmesa->glCtx; |
| |
| ctx->Const.MaxTextureLevels = 13; /* 4K by 4K? Is that right? */ |
| ctx->Const.MaxTextureUnits = 1; /* Permedia 3 */ |
| |
| ctx->Const.MinLineWidth = 0.0; |
| ctx->Const.MaxLineWidth = 255.0; |
| |
| ctx->Const.MinLineWidthAA = 0.0; |
| ctx->Const.MaxLineWidthAA = 65536.0; |
| |
| ctx->Const.MinPointSize = 0.0; |
| ctx->Const.MaxPointSize = 255.0; |
| |
| ctx->Const.MinPointSizeAA = 0.5; /* 4x4 quality mode */ |
| ctx->Const.MaxPointSizeAA = 16.0; |
| ctx->Const.PointSizeGranularity = 0.25; |
| |
| #if 0 |
| tmesa->texHeap = mmInit( 0, tmesa->tridentScreen->textureSize ); |
| |
| make_empty_list(&tmesa->TexObjList); |
| make_empty_list(&tmesa->SwappedOut); |
| |
| tmesa->CurrentTexObj[0] = 0; |
| tmesa->CurrentTexObj[1] = 0; /* Permedia 3, second texture */ |
| |
| tmesa->RenderIndex = ~0; |
| #endif |
| |
| /* 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, trident_pipeline ); |
| |
| /* Configure swrast to match hardware characteristics: |
| */ |
| _swrast_allow_pixel_fog( ctx, GL_FALSE ); |
| _swrast_allow_vertex_fog( ctx, GL_TRUE ); |
| |
| tridentInitVB( ctx ); |
| tridentDDInitExtensions( ctx ); |
| tridentDDInitDriverFuncs( ctx ); |
| tridentDDInitStateFuncs( ctx ); |
| #if 0 |
| tridentDDInitSpanFuncs( ctx ); |
| tridentDDInitTextureFuncs( ctx ); |
| #endif |
| tridentDDInitTriFuncs( ctx ); |
| tridentDDInitState( tmesa ); |
| |
| driContextPriv->driverPrivate = (void *)tmesa; |
| |
| UNLOCK_HARDWARE(tmesa); |
| |
| return GL_TRUE; |
| } |
| |
| static void |
| tridentDestroyContext(__DRIcontextPrivate *driContextPriv) |
| { |
| tridentContextPtr tmesa = (tridentContextPtr)driContextPriv->driverPrivate; |
| |
| if (tmesa) { |
| _swsetup_DestroyContext( tmesa->glCtx ); |
| _tnl_DestroyContext( tmesa->glCtx ); |
| _vbo_DestroyContext( tmesa->glCtx ); |
| _swrast_DestroyContext( tmesa->glCtx ); |
| |
| /* free the Mesa context */ |
| tmesa->glCtx->DriverCtx = NULL; |
| _mesa_destroy_context(tmesa->glCtx); |
| |
| _mesa_free(tmesa); |
| driContextPriv->driverPrivate = NULL; |
| } |
| } |
| |
| |
| static GLboolean |
| tridentCreateBuffer( __DRIscreenPrivate *driScrnPriv, |
| __DRIdrawablePrivate *driDrawPriv, |
| const __GLcontextModes *mesaVis, |
| GLboolean isPixmap ) |
| { |
| tridentScreenPtr screen = (tridentScreenPtr) driScrnPriv->private; |
| |
| if (isPixmap) { |
| return GL_FALSE; /* not implemented */ |
| } |
| else { |
| struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); |
| |
| { |
| driRenderbuffer *frontRb |
| = driNewRenderbuffer(GL_RGBA, NULL, screen->cpp, |
| screen->frontOffset, screen->frontPitch, |
| driDrawPriv); |
| /* |
| tridentSetSpanFunctions(frontRb, mesaVis); |
| */ |
| _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); |
| } |
| |
| if (mesaVis->doubleBufferMode) { |
| driRenderbuffer *backRb |
| = driNewRenderbuffer(GL_RGBA, NULL, screen->cpp, |
| screen->backOffset, screen->backPitch, |
| driDrawPriv); |
| /* |
| tridentSetSpanFunctions(backRb, mesaVis); |
| */ |
| _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); |
| } |
| |
| if (mesaVis->depthBits == 16) { |
| driRenderbuffer *depthRb |
| = driNewRenderbuffer(GL_DEPTH_COMPONENT16, NULL, screen->cpp, |
| screen->depthOffset, screen->depthPitch, |
| driDrawPriv); |
| /* |
| tridentSetSpanFunctions(depthRb, mesaVis); |
| */ |
| _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); |
| } |
| else if (mesaVis->depthBits == 24) { |
| driRenderbuffer *depthRb |
| = driNewRenderbuffer(GL_DEPTH_COMPONENT24, NULL, screen->cpp, |
| screen->depthOffset, screen->depthPitch, |
| driDrawPriv); |
| /* |
| tridentSetSpanFunctions(depthRb, mesaVis); |
| */ |
| _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); |
| } |
| |
| /* no h/w stencil? |
| if (mesaVis->stencilBits > 0 && !swStencil) { |
| driRenderbuffer *stencilRb |
| = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT); |
| tridentSetSpanFunctions(stencilRb, mesaVis); |
| _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); |
| } |
| */ |
| |
| _mesa_add_soft_renderbuffers(fb, |
| GL_FALSE, /* color */ |
| GL_FALSE, /* depth */ |
| mesaVis->stencilBits > 0, |
| mesaVis->accumRedBits > 0, |
| GL_FALSE, /* alpha */ |
| GL_FALSE /* aux */); |
| driDrawPriv->driverPrivate = (void *) fb; |
| |
| return (driDrawPriv->driverPrivate != NULL); |
| } |
| } |
| |
| |
| static void |
| tridentDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) |
| { |
| _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); |
| } |
| |
| static void |
| tridentSwapBuffers(__DRIdrawablePrivate *drawablePrivate) |
| { |
| __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; |
| |
| if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { |
| tridentContextPtr tmesa; |
| GLcontext *ctx; |
| tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate; |
| ctx = tmesa->glCtx; |
| if (ctx->Visual.doubleBufferMode) { |
| _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ |
| tridentCopyBuffer( dPriv ); |
| } |
| } |
| else { |
| /* XXX this shouldn't be an error but we can't handle it for now */ |
| _mesa_problem(NULL, "tridentSwapBuffers: drawable has no context!\n"); |
| } |
| } |
| |
| static GLboolean |
| tridentMakeCurrent(__DRIcontextPrivate *driContextPriv, |
| __DRIdrawablePrivate *driDrawPriv, |
| __DRIdrawablePrivate *driReadPriv) |
| { |
| if (driContextPriv) { |
| GET_CURRENT_CONTEXT(ctx); |
| tridentContextPtr oldCtx = ctx ? TRIDENT_CONTEXT(ctx) : NULL; |
| tridentContextPtr newCtx = (tridentContextPtr) driContextPriv->driverPrivate; |
| |
| if ( newCtx != oldCtx ) { |
| newCtx->dirty = ~0; |
| } |
| |
| if (newCtx->driDrawable != driDrawPriv) { |
| newCtx->driDrawable = driDrawPriv; |
| #if 0 |
| tridentUpdateWindow ( newCtx->glCtx ); |
| tridentUpdateViewportOffset( newCtx->glCtx ); |
| #endif |
| } |
| |
| newCtx->drawOffset = newCtx->tridentScreen->backOffset; |
| newCtx->drawPitch = newCtx->tridentScreen->backPitch; |
| |
| _mesa_make_current( newCtx->glCtx, |
| (GLframebuffer *) driDrawPriv->driverPrivate, |
| (GLframebuffer *) driReadPriv->driverPrivate ); |
| |
| if (!newCtx->glCtx->Viewport.Width) { |
| _mesa_set_viewport(newCtx->glCtx, 0, 0, |
| driDrawPriv->w, driDrawPriv->h); |
| } |
| } else { |
| _mesa_make_current( NULL, NULL, NULL ); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| tridentUnbindContext( __DRIcontextPrivate *driContextPriv ) |
| { |
| return GL_TRUE; |
| } |
| |
| |
| static tridentScreenPtr |
| tridentCreateScreen( __DRIscreenPrivate *sPriv ) |
| { |
| TRIDENTDRIPtr tDRIPriv = (TRIDENTDRIPtr)sPriv->pDevPriv; |
| tridentScreenPtr tridentScreen; |
| |
| if (sPriv->devPrivSize != sizeof(TRIDENTDRIRec)) { |
| fprintf(stderr,"\nERROR! sizeof(TRIDENTDRIRec) does not match passed size from device driver\n"); |
| return GL_FALSE; |
| } |
| |
| /* Allocate the private area */ |
| tridentScreen = (tridentScreenPtr) CALLOC( sizeof(*tridentScreen) ); |
| if ( !tridentScreen ) return NULL; |
| |
| tridentScreen->driScreen = sPriv; |
| |
| tridentScreen->frontOffset = tDRIPriv->frontOffset; |
| tridentScreen->backOffset = tDRIPriv->backOffset; |
| tridentScreen->depthOffset = tDRIPriv->depthOffset; |
| tridentScreen->frontPitch = tDRIPriv->frontPitch; |
| tridentScreen->backPitch = tDRIPriv->backPitch; |
| tridentScreen->depthPitch = tDRIPriv->depthPitch; |
| tridentScreen->width = tDRIPriv->width; |
| tridentScreen->height = tDRIPriv->height; |
| |
| printf("%d %d\n",tridentScreen->width,tridentScreen->height); |
| printf("%d %d\n",tridentScreen->frontPitch,tridentScreen->backPitch); |
| printf("offset 0x%x 0x%x\n",tridentScreen->backOffset,tridentScreen->depthOffset); |
| |
| tridentScreen->mmio.handle = tDRIPriv->regs; |
| tridentScreen->mmio.size = 0x20000; |
| |
| if (drmMap(sPriv->fd, |
| tridentScreen->mmio.handle, tridentScreen->mmio.size, |
| (drmAddressPtr)&tridentScreen->mmio.map)) { |
| FREE(tridentScreen); |
| return GL_FALSE; |
| } |
| printf("MAPPED at %p\n", tridentScreen->mmio.map); |
| |
| return tridentScreen; |
| } |
| |
| /* Destroy the device specific screen private data struct. |
| */ |
| static void |
| tridentDestroyScreen( __DRIscreenPrivate *sPriv ) |
| { |
| tridentScreenPtr tridentScreen = (tridentScreenPtr)sPriv->private; |
| |
| FREE(tridentScreen); |
| } |
| |
| static GLboolean |
| tridentInitDriver(__DRIscreenPrivate *sPriv) |
| { |
| sPriv->private = (void *) tridentCreateScreen( sPriv ); |
| |
| if (!sPriv->private) { |
| tridentDestroyScreen( sPriv ); |
| return GL_FALSE; |
| } |
| |
| return GL_TRUE; |
| } |
| |
| /** |
| * This is the driver specific part of the createNewScreen entry point. |
| * |
| * \todo maybe fold this into intelInitDriver |
| * |
| * \return the __GLcontextModes supported by this driver |
| */ |
| const __DRIconfig **tridentInitScreen(__DRIscreenPrivate *psp) |
| { |
| static const __DRIversion ddx_expected = { 4, 0, 0 }; |
| static const __DRIversion dri_expected = { 3, 1, 0 }; |
| static const __DRIversion drm_expected = { 1, 0, 0 }; |
| |
| if ( ! driCheckDriDdxDrmVersions2( "Trident", |
| &psp->dri_version, & dri_expected, |
| &psp->ddx_version, & ddx_expected, |
| &psp->drm_version, & drm_expected ) ) |
| return NULL; |
| |
| if (!tridentInitDriver(psp)) |
| return NULL; |
| |
| /* Wait... what? This driver doesn't report any modes... */ |
| #if 0 |
| TRIDENTDRIPtr dri_priv = (TRIDENTDRIPtr) psp->pDevPriv; |
| *driver_modes = tridentFillInModes( dri_priv->bytesPerPixel * 8, |
| GL_TRUE ); |
| #endif |
| |
| return NULL; |
| } |
| |
| const struct __DriverAPIRec driDriverAPI = { |
| tridentInitScreen, |
| tridentDestroyScreen, |
| tridentCreateContext, |
| tridentDestroyContext, |
| tridentCreateBuffer, |
| tridentDestroyBuffer, |
| tridentSwapBuffers, |
| tridentMakeCurrent, |
| tridentUnbindContext, |
| }; |