summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/unichrome/via_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/unichrome/via_context.c')
-rw-r--r--src/mesa/drivers/dri/unichrome/via_context.c946
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");
+ }
+}