diff options
Diffstat (limited to 'src/mesa/drivers/dri/unichrome/via_context.c')
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_context.c | 946 |
1 files changed, 946 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c new file mode 100644 index 0000000000..49c2465655 --- /dev/null +++ b/src/mesa/drivers/dri/unichrome/via_context.c @@ -0,0 +1,946 @@ +/* + * 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. + */ + +/** + * \file via_context.c + * + * \author John Sheng (presumably of either VIA Technologies or S3 Graphics) + * \author Others at VIA Technologies? + * \author Others at S3 Graphics? + */ + +#include "glheader.h" +#include "context.h" +#include "matrix.h" +#include "state.h" +#include "simple_list.h" +#include "extensions.h" +#include "framebuffer.h" +#include "renderbuffer.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "array_cache/acache.h" + +#include "tnl/t_pipeline.h" + +#include "drivers/common/driverfuncs.h" + +#include "via_screen.h" +#include "via_dri.h" + +#include "via_state.h" +#include "via_tex.h" +#include "via_span.h" +#include "via_tris.h" +#include "via_ioctl.h" +#include "via_fb.h" + +#include <stdio.h> +#include "macros.h" +#include "drirenderbuffer.h" + +#define need_GL_ARB_multisample +#define need_GL_ARB_point_parameters +#define need_GL_EXT_fog_coord +#define need_GL_EXT_secondary_color +#include "extension_helper.h" + +#define DRIVER_DATE "20060710" + +#include "vblank.h" +#include "utils.h" + +GLuint VIA_DEBUG = 0; + +/** + * Return various strings for \c glGetString. + * + * \sa glGetString + */ +static const GLubyte *viaGetString(GLcontext *ctx, GLenum name) +{ + static char buffer[128]; + unsigned offset; + + + switch (name) { + case GL_VENDOR: + return (GLubyte *)"VIA Technology"; + + case GL_RENDERER: { + static const char * const chipset_names[] = { + "UniChrome", + "CastleRock (CLE266)", + "UniChrome (KM400)", + "UniChrome (K8M800)", + "UniChrome (PM8x0/CN400)", + }; + struct via_context *vmesa = VIA_CONTEXT(ctx); + unsigned id = vmesa->viaScreen->deviceID; + + offset = driGetRendererString( buffer, + chipset_names[(id > VIA_PM800) ? 0 : id], + DRIVER_DATE, 0 ); + return (GLubyte *)buffer; + } + + default: + return NULL; + } +} + + +/** + * Calculate a width that satisfies the hardware's alignment requirements. + * On the Unichrome hardware, each scanline must be aligned to a multiple of + * 16 pixels. + * + * \param width Minimum buffer width, in pixels. + * + * \returns A pixel width that meets the alignment requirements. + */ +static __inline__ unsigned +buffer_align( unsigned width ) +{ + return (width + 0x0f) & ~0x0f; +} + + +static void +viaDeleteRenderbuffer(struct gl_renderbuffer *rb) +{ + /* Don't free() since we're contained in via_context struct. */ +} + +static GLboolean +viaRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + rb->Width = width; + rb->Height = height; + rb->InternalFormat = internalFormat; + return GL_TRUE; +} + + +static void +viaInitRenderbuffer(struct via_renderbuffer *vrb, GLenum format, + __DRIdrawablePrivate *dPriv) +{ + const GLuint name = 0; + struct gl_renderbuffer *rb = & vrb->Base; + + vrb->dPriv = dPriv; + _mesa_init_renderbuffer(rb, name); + + /* Make sure we're using a null-valued GetPointer routine */ + assert(rb->GetPointer(NULL, rb, 0, 0) == NULL); + + rb->InternalFormat = format; + + if (format == GL_RGBA) { + /* Color */ + rb->_BaseFormat = GL_RGBA; + rb->DataType = GL_UNSIGNED_BYTE; + } + else if (format == GL_DEPTH_COMPONENT16) { + /* Depth */ + rb->_BaseFormat = GL_DEPTH_COMPONENT; + /* we always Get/Put 32-bit Z values */ + rb->DataType = GL_UNSIGNED_INT; + } + else if (format == GL_DEPTH_COMPONENT24) { + /* Depth */ + rb->_BaseFormat = GL_DEPTH_COMPONENT; + /* we always Get/Put 32-bit Z values */ + rb->DataType = GL_UNSIGNED_INT; + } + else { + /* Stencil */ + ASSERT(format == GL_STENCIL_INDEX8_EXT); + rb->_BaseFormat = GL_STENCIL_INDEX; + rb->DataType = GL_UNSIGNED_BYTE; + } + + rb->Delete = viaDeleteRenderbuffer; + rb->AllocStorage = viaRenderbufferStorage; +} + + +/** + * Calculate the framebuffer parameters for all buffers (front, back, depth, + * and stencil) associated with the specified context. + * + * \warning + * This function also calls \c AllocateBuffer to actually allocate the + * buffers. + * + * \sa AllocateBuffer + */ +static GLboolean +calculate_buffer_parameters(struct via_context *vmesa, + struct gl_framebuffer *fb, + __DRIdrawablePrivate *dPriv) +{ + const unsigned shift = vmesa->viaScreen->bitsPerPixel / 16; + const unsigned extra = 32; + unsigned w; + unsigned h; + + /* Normally, the renderbuffer would be added to the framebuffer just once + * when the framebuffer was created. The VIA driver is a bit funny + * though in that the front/back/depth renderbuffers are in the per-context + * state! + * That should be fixed someday. + */ + + if (!vmesa->front.Base.InternalFormat) { + /* do one-time init for the renderbuffers */ + viaInitRenderbuffer(&vmesa->front, GL_RGBA, dPriv); + viaSetSpanFunctions(&vmesa->front, &fb->Visual); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &vmesa->front.Base); + + if (fb->Visual.doubleBufferMode) { + viaInitRenderbuffer(&vmesa->back, GL_RGBA, dPriv); + viaSetSpanFunctions(&vmesa->back, &fb->Visual); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &vmesa->back.Base); + } + + if (vmesa->glCtx->Visual.depthBits > 0) { + viaInitRenderbuffer(&vmesa->depth, + (vmesa->glCtx->Visual.depthBits == 16 + ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24), + dPriv); + viaSetSpanFunctions(&vmesa->depth, &fb->Visual); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &vmesa->depth.Base); + } + + if (vmesa->glCtx->Visual.stencilBits > 0) { + viaInitRenderbuffer(&vmesa->stencil, GL_STENCIL_INDEX8_EXT, + dPriv); + viaSetSpanFunctions(&vmesa->stencil, &fb->Visual); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &vmesa->stencil.Base); + } + } + + assert(vmesa->front.Base.InternalFormat); + assert(vmesa->front.Base.AllocStorage); + if (fb->Visual.doubleBufferMode) { + assert(vmesa->back.Base.AllocStorage); + } + if (fb->Visual.depthBits) { + assert(vmesa->depth.Base.AllocStorage); + } + + + /* Allocate front-buffer */ + if (vmesa->drawType == GLX_PBUFFER_BIT) { + w = vmesa->driDrawable->w; + h = vmesa->driDrawable->h; + + vmesa->front.bpp = vmesa->viaScreen->bitsPerPixel; + vmesa->front.pitch = buffer_align( w ) << shift; /* bytes, not pixels */ + vmesa->front.size = vmesa->front.pitch * h; + + if (vmesa->front.map) + via_free_draw_buffer(vmesa, &vmesa->front); + if (!via_alloc_draw_buffer(vmesa, &vmesa->front)) + return GL_FALSE; + + } else { + w = vmesa->viaScreen->width; + h = vmesa->viaScreen->height; + + vmesa->front.bpp = vmesa->viaScreen->bitsPerPixel; + vmesa->front.pitch = buffer_align( w ) << shift; /* bytes, not pixels */ + vmesa->front.size = vmesa->front.pitch * h; + if (getenv("ALTERNATE_SCREEN")) + vmesa->front.offset = vmesa->front.size; + else + vmesa->front.offset = 0; + vmesa->front.map = (char *) vmesa->driScreen->pFB; + } + + + /* Allocate back-buffer */ + if (vmesa->hasBack) { + vmesa->back.bpp = vmesa->viaScreen->bitsPerPixel; + vmesa->back.pitch = (buffer_align( vmesa->driDrawable->w ) << shift); + vmesa->back.pitch += extra; + vmesa->back.pitch = MIN2(vmesa->back.pitch, vmesa->front.pitch); + vmesa->back.size = vmesa->back.pitch * vmesa->driDrawable->h; + if (vmesa->back.map) + via_free_draw_buffer(vmesa, &vmesa->back); + if (!via_alloc_draw_buffer(vmesa, &vmesa->back)) + return GL_FALSE; + } + else { + if (vmesa->back.map) + via_free_draw_buffer(vmesa, &vmesa->back); + (void) memset( &vmesa->back, 0, sizeof( vmesa->back ) ); + } + + + /* Allocate depth-buffer */ + if ( vmesa->hasStencil || vmesa->hasDepth ) { + vmesa->depth.bpp = vmesa->depthBits; + if (vmesa->depth.bpp == 24) + vmesa->depth.bpp = 32; + + vmesa->depth.pitch = (buffer_align( vmesa->driDrawable->w ) * + (vmesa->depth.bpp/8)) + extra; + vmesa->depth.size = vmesa->depth.pitch * vmesa->driDrawable->h; + + if (vmesa->depth.map) + via_free_draw_buffer(vmesa, &vmesa->depth); + if (!via_alloc_draw_buffer(vmesa, &vmesa->depth)) { + return GL_FALSE; + } + } + else { + if (vmesa->depth.map) + via_free_draw_buffer(vmesa, &vmesa->depth); + (void) memset( & vmesa->depth, 0, sizeof( vmesa->depth ) ); + } + + /* stencil buffer is same as depth buffer */ + vmesa->stencil.handle = vmesa->depth.handle; + vmesa->stencil.size = vmesa->depth.size; + vmesa->stencil.offset = vmesa->depth.offset; + vmesa->stencil.index = vmesa->depth.index; + vmesa->stencil.pitch = vmesa->depth.pitch; + vmesa->stencil.bpp = vmesa->depth.bpp; + vmesa->stencil.map = vmesa->depth.map; + vmesa->stencil.orig = vmesa->depth.orig; + vmesa->stencil.origMap = vmesa->depth.origMap; + + if( vmesa->viaScreen->width == vmesa->driDrawable->w && + vmesa->viaScreen->height == vmesa->driDrawable->h ) { + vmesa->doPageFlip = vmesa->allowPageFlip; + if (vmesa->hasBack) { + assert(vmesa->back.pitch == vmesa->front.pitch); + } + } + else + vmesa->doPageFlip = GL_FALSE; + + return GL_TRUE; +} + + +void viaReAllocateBuffers(GLcontext *ctx, GLframebuffer *drawbuffer, + GLuint width, GLuint height) +{ + struct via_context *vmesa = VIA_CONTEXT(ctx); + + calculate_buffer_parameters(vmesa, drawbuffer, vmesa->driDrawable); + + _mesa_resize_framebuffer(ctx, drawbuffer, width, height); +} + +/* Extension strings exported by the Unichrome driver. + */ +const struct dri_extension card_extensions[] = +{ + { "GL_ARB_multisample", GL_ARB_multisample_functions }, + { "GL_ARB_multitexture", NULL }, + { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, + { "GL_ARB_texture_env_add", NULL }, + { "GL_ARB_texture_env_combine", NULL }, +/* { "GL_ARB_texture_env_dot3", NULL }, */ + { "GL_ARB_texture_mirrored_repeat", NULL }, + { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_EXT_texture_env_combine", NULL }, +/* { "GL_EXT_texture_env_dot3", NULL }, */ + { "GL_EXT_texture_lod_bias", NULL }, + { "GL_NV_blend_square", NULL }, + { NULL, NULL } +}; + +extern const struct tnl_pipeline_stage _via_fastrender_stage; +extern const struct tnl_pipeline_stage _via_render_stage; + +static const struct tnl_pipeline_stage *via_pipeline[] = { + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + /* REMOVE: point attenuation stage */ +#if 1 + &_via_fastrender_stage, /* ADD: unclipped rastersetup-to-dma */ +#endif + &_tnl_render_stage, + 0, +}; + + +static const struct dri_debug_control debug_control[] = +{ + { "fall", DEBUG_FALLBACKS }, + { "tex", DEBUG_TEXTURE }, + { "ioctl", DEBUG_IOCTL }, + { "prim", DEBUG_PRIMS }, + { "vert", DEBUG_VERTS }, + { "state", DEBUG_STATE }, + { "verb", DEBUG_VERBOSE }, + { "dri", DEBUG_DRI }, + { "dma", DEBUG_DMA }, + { "san", DEBUG_SANITY }, + { "sync", DEBUG_SYNC }, + { "sleep", DEBUG_SLEEP }, + { "pix", DEBUG_PIXEL }, + { "2d", DEBUG_2D }, + { NULL, 0 } +}; + + +static GLboolean +AllocateDmaBuffer(struct via_context *vmesa) +{ + if (vmesa->dma) + via_free_dma_buffer(vmesa); + + if (!via_alloc_dma_buffer(vmesa)) + return GL_FALSE; + + vmesa->dmaLow = 0; + vmesa->dmaCliprectAddr = ~0; + return GL_TRUE; +} + +static void +FreeBuffer(struct via_context *vmesa) +{ + if (vmesa->front.map && vmesa->drawType == GLX_PBUFFER_BIT) + via_free_draw_buffer(vmesa, &vmesa->front); + + if (vmesa->back.map) + via_free_draw_buffer(vmesa, &vmesa->back); + + if (vmesa->depth.map) + via_free_draw_buffer(vmesa, &vmesa->depth); + + if (vmesa->breadcrumb.map) + via_free_draw_buffer(vmesa, &vmesa->breadcrumb); + + if (vmesa->dma) + via_free_dma_buffer(vmesa); +} + + +GLboolean +viaCreateContext(const __GLcontextModes *visual, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + GLcontext *ctx, *shareCtx; + struct via_context *vmesa; + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + viaScreenPrivate *viaScreen = (viaScreenPrivate *)sPriv->private; + drm_via_sarea_t *saPriv = (drm_via_sarea_t *) + (((GLubyte *)sPriv->pSAREA) + viaScreen->sareaPrivOffset); + struct dd_function_table functions; + + /* Allocate via context */ + vmesa = (struct via_context *) CALLOC_STRUCT(via_context); + if (!vmesa) { + return GL_FALSE; + } + + /* Parse configuration files. + */ + driParseConfigFiles (&vmesa->optionCache, &viaScreen->optionCache, + sPriv->myNum, "unichrome"); + + /* pick back buffer */ + vmesa->hasBack = visual->doubleBufferMode; + + switch(visual->depthBits) { + case 0: + vmesa->hasDepth = GL_FALSE; + vmesa->depthBits = 0; + vmesa->depth_max = 1.0; + break; + case 16: + vmesa->hasDepth = GL_TRUE; + vmesa->depthBits = visual->depthBits; + vmesa->have_hw_stencil = GL_FALSE; + vmesa->depth_max = (GLfloat)0xffff; + vmesa->depth_clear_mask = 0xf << 28; + vmesa->ClearDepth = 0xffff; + vmesa->polygon_offset_scale = 1.0 / vmesa->depth_max; + break; + case 24: + vmesa->hasDepth = GL_TRUE; + vmesa->depthBits = visual->depthBits; + vmesa->depth_max = (GLfloat) 0xffffff; + vmesa->depth_clear_mask = 0xe << 28; + vmesa->ClearDepth = 0xffffff00; + + assert(visual->haveStencilBuffer); + assert(visual->stencilBits == 8); + + vmesa->have_hw_stencil = GL_TRUE; + vmesa->stencilBits = visual->stencilBits; + vmesa->stencil_clear_mask = 0x1 << 28; + vmesa->polygon_offset_scale = 2.0 / vmesa->depth_max; + break; + case 32: + vmesa->hasDepth = GL_TRUE; + vmesa->depthBits = visual->depthBits; + assert(!visual->haveStencilBuffer); + vmesa->have_hw_stencil = GL_FALSE; + vmesa->depth_max = (GLfloat)0xffffffff; + vmesa->depth_clear_mask = 0xf << 28; + vmesa->ClearDepth = 0xffffffff; + vmesa->polygon_offset_scale = 2.0 / vmesa->depth_max; + break; + default: + assert(0); + break; + } + + make_empty_list(&vmesa->freed_tex_buffers); + make_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO]); + make_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP]); + make_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM]); + + _mesa_init_driver_functions(&functions); + viaInitTextureFuncs(&functions); + + /* Allocate the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((struct via_context *) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + + vmesa->glCtx = _mesa_create_context(visual, shareCtx, &functions, + (void*) vmesa); + + vmesa->shareCtx = shareCtx; + + if (!vmesa->glCtx) { + FREE(vmesa); + return GL_FALSE; + } + driContextPriv->driverPrivate = vmesa; + + ctx = vmesa->glCtx; + + if (driQueryOptionb(&vmesa->optionCache, "excess_mipmap")) + ctx->Const.MaxTextureLevels = 11; + else + ctx->Const.MaxTextureLevels = 10; + + ctx->Const.MaxTextureUnits = 2; + ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; + ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; + + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = 1.0; + ctx->Const.MaxLineWidthAA = 1.0; + ctx->Const.LineWidthGranularity = 1.0; + + ctx->Const.MinPointSize = 1.0; + ctx->Const.MinPointSizeAA = 1.0; + ctx->Const.MaxPointSize = 1.0; + ctx->Const.MaxPointSizeAA = 1.0; + ctx->Const.PointSizeGranularity = 1.0; + + ctx->Driver.GetString = viaGetString; + + ctx->DriverCtx = (void *)vmesa; + vmesa->glCtx = ctx; + + /* Initialize the software rasterizer and helper modules. + */ + _swrast_CreateContext(ctx); + _ac_CreateContext(ctx); + _tnl_CreateContext(ctx); + _swsetup_CreateContext(ctx); + + /* Install the customized pipeline: + */ + _tnl_destroy_pipeline(ctx); + _tnl_install_pipeline(ctx, via_pipeline); + + /* Configure swrast and T&L to match hardware characteristics: + */ + _swrast_allow_pixel_fog(ctx, GL_FALSE); + _swrast_allow_vertex_fog(ctx, GL_TRUE); + _tnl_allow_pixel_fog(ctx, GL_FALSE); + _tnl_allow_vertex_fog(ctx, GL_TRUE); + +/* vmesa->display = dpy; */ + vmesa->display = sPriv->display; + + vmesa->hHWContext = driContextPriv->hHWContext; + vmesa->driFd = sPriv->fd; + vmesa->driHwLock = &sPriv->pSAREA->lock; + + vmesa->viaScreen = viaScreen; + vmesa->driScreen = sPriv; + vmesa->sarea = saPriv; + + vmesa->renderIndex = ~0; + vmesa->setupIndex = ~0; + vmesa->hwPrimitive = GL_POLYGON+1; + + /* KW: Hardwire this. Was previously set bogusly in + * viaCreateBuffer. Needs work before PBUFFER can be used: + */ + vmesa->drawType = GLX_WINDOW_BIT; + + + _math_matrix_ctr(&vmesa->ViewportMatrix); + + /* Do this early, before VIA_FLUSH_DMA can be called: + */ + if (!AllocateDmaBuffer(vmesa)) { + fprintf(stderr ,"AllocateDmaBuffer fail\n"); + FreeBuffer(vmesa); + FREE(vmesa); + return GL_FALSE; + } + + /* Allocate a small piece of fb memory for synchronization: + */ + vmesa->breadcrumb.bpp = 32; + vmesa->breadcrumb.pitch = buffer_align( 64 ) << 2; + vmesa->breadcrumb.size = vmesa->breadcrumb.pitch; + + if (!via_alloc_draw_buffer(vmesa, &vmesa->breadcrumb)) { + fprintf(stderr ,"AllocateDmaBuffer fail\n"); + FreeBuffer(vmesa); + FREE(vmesa); + return GL_FALSE; + } + + driInitExtensions( ctx, card_extensions, GL_TRUE ); + viaInitStateFuncs(ctx); + viaInitTriFuncs(ctx); + viaInitSpanFuncs(ctx); + viaInitIoctlFuncs(ctx); + viaInitState(ctx); + + if (getenv("VIA_DEBUG")) + VIA_DEBUG = driParseDebugString( getenv( "VIA_DEBUG" ), + debug_control ); + + if (getenv("VIA_NO_RAST") || + driQueryOptionb(&vmesa->optionCache, "no_rast")) + FALLBACK(vmesa, VIA_FALLBACK_USER_DISABLE, 1); + + vmesa->vblank_flags = + vmesa->viaScreen->irqEnabled ? + driGetDefaultVBlankFlags(&vmesa->optionCache) : VBLANK_FLAG_NO_IRQ; + + if (getenv("VIA_PAGEFLIP")) + vmesa->allowPageFlip = 1; + + (*dri_interface->getUST)( &vmesa->swap_ust ); + + + vmesa->regMMIOBase = (GLuint *)((unsigned long)viaScreen->reg); + vmesa->pnGEMode = (GLuint *)((unsigned long)viaScreen->reg + 0x4); + vmesa->regEngineStatus = (GLuint *)((unsigned long)viaScreen->reg + 0x400); + vmesa->regTranSet = (GLuint *)((unsigned long)viaScreen->reg + 0x43C); + vmesa->regTranSpace = (GLuint *)((unsigned long)viaScreen->reg + 0x440); + vmesa->agpBase = viaScreen->agpBase; + + + return GL_TRUE; +} + +void +viaDestroyContext(__DRIcontextPrivate *driContextPriv) +{ + GET_CURRENT_CONTEXT(ctx); + struct via_context *vmesa = + (struct via_context *)driContextPriv->driverPrivate; + struct via_context *current = ctx ? VIA_CONTEXT(ctx) : NULL; + assert(vmesa); /* should never be null */ + + /* check if we're deleting the currently bound context */ + if (vmesa == current) { + VIA_FLUSH_DMA(vmesa); + _mesa_make_current(NULL, NULL, NULL); + } + + if (vmesa) { + viaWaitIdle(vmesa, GL_FALSE); + if (vmesa->doPageFlip) { + LOCK_HARDWARE(vmesa); + if (vmesa->pfCurrentOffset != 0) { + fprintf(stderr, "%s - reset pf\n", __FUNCTION__); + viaResetPageFlippingLocked(vmesa); + } + UNLOCK_HARDWARE(vmesa); + } + + _swsetup_DestroyContext(vmesa->glCtx); + _tnl_DestroyContext(vmesa->glCtx); + _ac_DestroyContext(vmesa->glCtx); + _swrast_DestroyContext(vmesa->glCtx); + /* free the Mesa context */ + _mesa_destroy_context(vmesa->glCtx); + /* release our data */ + FreeBuffer(vmesa); + + assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP])); + assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO])); + assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM])); + assert (is_empty_list(&vmesa->freed_tex_buffers)); + + driDestroyOptionCache(&vmesa->optionCache); + + FREE(vmesa); + } +} + + +void viaXMesaWindowMoved(struct via_context *vmesa) +{ + __DRIdrawablePrivate *const drawable = vmesa->driDrawable; + __DRIdrawablePrivate *const readable = vmesa->driReadable; + struct via_renderbuffer *const draw_buffer = + (struct via_renderbuffer *) drawable->driverPrivate; + struct via_renderbuffer *const read_buffer = + (struct via_renderbuffer *) readable->driverPrivate; + GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3; + + if (!drawable) + return; + + switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) { + case BUFFER_BIT_BACK_LEFT: + if (drawable->numBackClipRects == 0) { + vmesa->numClipRects = drawable->numClipRects; + vmesa->pClipRects = drawable->pClipRects; + } + else { + vmesa->numClipRects = drawable->numBackClipRects; + vmesa->pClipRects = drawable->pBackClipRects; + } + break; + case BUFFER_BIT_FRONT_LEFT: + vmesa->numClipRects = drawable->numClipRects; + vmesa->pClipRects = drawable->pClipRects; + break; + default: + vmesa->numClipRects = 0; + break; + } + + if ((draw_buffer->drawW != drawable->w) + || (draw_buffer->drawH != drawable->h)) { + calculate_buffer_parameters(vmesa, vmesa->glCtx->DrawBuffer, + drawable); + } + + draw_buffer->drawXoff = (GLuint)(((drawable->x * bytePerPixel) & 0x1f) / + bytePerPixel); + draw_buffer->drawX = drawable->x - draw_buffer->drawXoff; + draw_buffer->drawY = drawable->y; + draw_buffer->drawW = drawable->w; + draw_buffer->drawH = drawable->h; + + if (drawable != readable) { + if ((read_buffer->drawW != readable->w) + || (read_buffer->drawH != readable->h)) { + calculate_buffer_parameters(vmesa, vmesa->glCtx->ReadBuffer, + readable); + } + + read_buffer->drawXoff = (GLuint)(((readable->x * bytePerPixel) & 0x1f) / + bytePerPixel); + read_buffer->drawX = readable->x - read_buffer->drawXoff; + read_buffer->drawY = readable->y; + read_buffer->drawW = readable->w; + read_buffer->drawH = readable->h; + } + + vmesa->front.orig = (vmesa->front.offset + + draw_buffer->drawY * vmesa->front.pitch + + draw_buffer->drawX * bytePerPixel); + + vmesa->front.origMap = (vmesa->front.map + + draw_buffer->drawY * vmesa->front.pitch + + draw_buffer->drawX * bytePerPixel); + + vmesa->back.orig = vmesa->back.offset; + vmesa->depth.orig = vmesa->depth.offset; + vmesa->back.origMap = vmesa->back.map; + vmesa->depth.origMap = vmesa->depth.map; + + viaCalcViewport(vmesa->glCtx); +} + +GLboolean +viaUnbindContext(__DRIcontextPrivate *driContextPriv) +{ + return GL_TRUE; +} + +GLboolean +viaMakeCurrent(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + if (VIA_DEBUG & DEBUG_DRI) { + fprintf(stderr, "driContextPriv = %016lx\n", (unsigned long)driContextPriv); + fprintf(stderr, "driDrawPriv = %016lx\n", (unsigned long)driDrawPriv); + fprintf(stderr, "driReadPriv = %016lx\n", (unsigned long)driReadPriv); + } + + if (driContextPriv) { + struct via_context *vmesa = + (struct via_context *)driContextPriv->driverPrivate; + GLcontext *ctx = vmesa->glCtx; + struct gl_framebuffer *drawBuffer, *readBuffer; + + drawBuffer = (GLframebuffer *)driDrawPriv->driverPrivate; + readBuffer = (GLframebuffer *)driReadPriv->driverPrivate; + + if (vmesa->driDrawable != driDrawPriv) { + driDrawableInitVBlank(driDrawPriv, vmesa->vblank_flags, + &vmesa->vbl_seq); + } + + if ((vmesa->driDrawable != driDrawPriv) + || (vmesa->driReadable != driReadPriv)) { + vmesa->driDrawable = driDrawPriv; + vmesa->driReadable = driReadPriv; + + if ((drawBuffer->Width != driDrawPriv->w) + || (drawBuffer->Height != driDrawPriv->h)) { + _mesa_resize_framebuffer(ctx, drawBuffer, + driDrawPriv->w, driDrawPriv->h); + drawBuffer->Initialized = GL_TRUE; + } + + if (!calculate_buffer_parameters(vmesa, drawBuffer, driDrawPriv)) { + return GL_FALSE; + } + + if (driDrawPriv != driReadPriv) { + if ((readBuffer->Width != driReadPriv->w) + || (readBuffer->Height != driReadPriv->h)) { + _mesa_resize_framebuffer(ctx, readBuffer, + driReadPriv->w, driReadPriv->h); + readBuffer->Initialized = GL_TRUE; + } + + if (!calculate_buffer_parameters(vmesa, readBuffer, driReadPriv)) { + return GL_FALSE; + } + } + } + + _mesa_make_current(vmesa->glCtx, drawBuffer, readBuffer); + + ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); + + viaXMesaWindowMoved(vmesa); + ctx->Driver.Scissor(vmesa->glCtx, + vmesa->glCtx->Scissor.X, + vmesa->glCtx->Scissor.Y, + vmesa->glCtx->Scissor.Width, + vmesa->glCtx->Scissor.Height); + } + else { + _mesa_make_current(NULL, NULL, NULL); + } + + return GL_TRUE; +} + +void viaGetLock(struct via_context *vmesa, GLuint flags) +{ + __DRIdrawablePrivate *dPriv = vmesa->driDrawable; + __DRIscreenPrivate *sPriv = vmesa->driScreen; + + drmGetLock(vmesa->driFd, vmesa->hHWContext, flags); + + DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); + if (dPriv != vmesa->driReadable) { + DRI_VALIDATE_DRAWABLE_INFO(sPriv, vmesa->driReadable); + } + + if (vmesa->sarea->ctxOwner != vmesa->hHWContext) { + vmesa->sarea->ctxOwner = vmesa->hHWContext; + vmesa->newEmitState = ~0; + } + + if (vmesa->lastStamp != dPriv->lastStamp) { + viaXMesaWindowMoved(vmesa); + driUpdateFramebufferSize(vmesa->glCtx, dPriv); + vmesa->newEmitState = ~0; + vmesa->lastStamp = dPriv->lastStamp; + } + + if (vmesa->doPageFlip && + vmesa->pfCurrentOffset != vmesa->sarea->pfCurrentOffset) { + fprintf(stderr, "%s - reset pf\n", __FUNCTION__); + viaResetPageFlippingLocked(vmesa); + } +} + + +void +viaSwapBuffers(__DRIdrawablePrivate *drawablePrivate) +{ + __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *)drawablePrivate; + + if (dPriv && + dPriv->driContextPriv && + dPriv->driContextPriv->driverPrivate) { + struct via_context *vmesa = + (struct via_context *)dPriv->driContextPriv->driverPrivate; + GLcontext *ctx = vmesa->glCtx; + + _mesa_notifySwapBuffers(ctx); + + if (ctx->Visual.doubleBufferMode) { + if (vmesa->doPageFlip) { + viaPageFlip(dPriv); + } + else { + viaCopyBuffer(dPriv); + } + } + else + VIA_FLUSH_DMA(vmesa); + } + else { + _mesa_problem(NULL, "viaSwapBuffers: drawable has no context!\n"); + } +} |