blob: ed7001d48dfb3c97cef878273e813746074fb59a [file] [log] [blame]
/*
* 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 "vbo/vbo.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_ARB_vertex_buffer_object
#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_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "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);
_vbo_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->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);
if (getenv("VIA_PAGEFLIP"))
vmesa->allowPageFlip = 1;
(*sPriv->systemTime->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 */
if (vmesa->driDrawable) {
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);
}
}
/* check if we're deleting the currently bound context */
if (vmesa == current) {
VIA_FLUSH_DMA(vmesa);
_mesa_make_current(NULL, NULL, NULL);
}
_swsetup_DestroyContext(vmesa->glCtx);
_tnl_DestroyContext(vmesa->glCtx);
_vbo_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 * draw_buffer;
struct via_renderbuffer * read_buffer;
GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
if (!drawable)
return;
draw_buffer = (struct via_renderbuffer *) drawable->driverPrivate;
read_buffer = (struct via_renderbuffer *) readable->driverPrivate;
switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0]) {
case BUFFER_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_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->drawX = drawable->x;
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->drawX = readable->x;
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 +
draw_buffer->drawY * vmesa->back.pitch +
draw_buffer->drawX * bytePerPixel);
vmesa->back.origMap = (vmesa->back.map +
draw_buffer->drawY * vmesa->back.pitch +
draw_buffer->drawX * bytePerPixel);
vmesa->depth.orig = (vmesa->depth.offset +
draw_buffer->drawY * vmesa->depth.pitch +
draw_buffer->drawX * bytePerPixel);
vmesa->depth.origMap = (vmesa->depth.map +
draw_buffer->drawY * vmesa->depth.pitch +
draw_buffer->drawX * bytePerPixel);
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)
|| (vmesa->driReadable != driReadPriv)) {
if (driDrawPriv->swap_interval == (unsigned)-1) {
driDrawPriv->vblFlags =
vmesa->viaScreen->irqEnabled ?
driGetDefaultVBlankFlags(&vmesa->optionCache) :
VBLANK_FLAG_NO_IRQ;
driDrawableInitVBlank(driDrawPriv);
}
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");
}
}