blob: f730c831e4d11c1b6358d8cc356002af90badc6a [file] [log] [blame]
/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
/*
* Copyright 2000 Gareth Hughes
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* GARETH HUGHES 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.
*/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Leif Delgass <ldelgass@retinalburn.net>
* Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
*/
#include "glheader.h"
#include "context.h"
#include "simple_list.h"
#include "imports.h"
#include "matrix.h"
#include "extensions.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 "drivers/common/driverfuncs.h"
#include "mach64_context.h"
#include "mach64_ioctl.h"
#include "mach64_dd.h"
#include "mach64_span.h"
#include "mach64_state.h"
#include "mach64_tex.h"
#include "mach64_tris.h"
#include "mach64_vb.h"
#include "utils.h"
#include "vblank.h"
#define need_GL_ARB_multisample
#define need_GL_ARB_vertex_buffer_object
#include "extension_helper.h"
#ifndef MACH64_DEBUG
int MACH64_DEBUG = (0);
#endif
static const struct dri_debug_control debug_control[] =
{
{ "sync", DEBUG_ALWAYS_SYNC },
{ "api", DEBUG_VERBOSE_API },
{ "msg", DEBUG_VERBOSE_MSG },
{ "lru", DEBUG_VERBOSE_LRU },
{ "dri", DEBUG_VERBOSE_DRI },
{ "ioctl", DEBUG_VERBOSE_IOCTL },
{ "prims", DEBUG_VERBOSE_PRIMS },
{ "count", DEBUG_VERBOSE_COUNT },
{ "nowait", DEBUG_NOWAIT },
{ "fall", DEBUG_VERBOSE_FALLBACK },
{ NULL, 0 }
};
const struct dri_extension card_extensions[] =
{
{ "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
{ "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_texture_edge_clamp", NULL },
{ "GL_MESA_ycbcr_texture", NULL },
{ "GL_SGIS_generate_mipmap", NULL },
{ NULL, NULL }
};
/* Create the device specific context.
*/
GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate )
{
GLcontext *ctx, *shareCtx;
__DRIscreenPrivate *driScreen = driContextPriv->driScreenPriv;
struct dd_function_table functions;
mach64ContextPtr mmesa;
mach64ScreenPtr mach64Screen;
int i, heap;
GLuint *c_textureSwapsPtr = NULL;
#if DO_DEBUG
MACH64_DEBUG = driParseDebugString(getenv("MACH64_DEBUG"), debug_control);
#endif
/* Allocate the mach64 context */
mmesa = (mach64ContextPtr) CALLOC( sizeof(*mmesa) );
if ( !mmesa )
return GL_FALSE;
/* Init default driver functions then plug in our Mach64-specific functions
* (the texture functions are especially important)
*/
_mesa_init_driver_functions( &functions );
mach64InitDriverFuncs( &functions );
mach64InitIoctlFuncs( &functions );
mach64InitTextureFuncs( &functions );
/* Allocate the Mesa context */
if (sharedContextPrivate)
shareCtx = ((mach64ContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
mmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
&functions, (void *)mmesa);
if (!mmesa->glCtx) {
FREE(mmesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = mmesa;
ctx = mmesa->glCtx;
mmesa->driContext = driContextPriv;
mmesa->driScreen = driScreen;
mmesa->driDrawable = NULL;
mmesa->hHWContext = driContextPriv->hHWContext;
mmesa->driHwLock = &driScreen->pSAREA->lock;
mmesa->driFd = driScreen->fd;
mach64Screen = mmesa->mach64Screen = (mach64ScreenPtr)driScreen->private;
/* Parse configuration files */
driParseConfigFiles (&mmesa->optionCache, &mach64Screen->optionCache,
mach64Screen->driScreen->myNum, "mach64");
mmesa->sarea = (drm_mach64_sarea_t *)((char *)driScreen->pSAREA +
sizeof(drm_sarea_t));
mmesa->CurrentTexObj[0] = NULL;
mmesa->CurrentTexObj[1] = NULL;
(void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
make_empty_list( &mmesa->swapped );
mmesa->firstTexHeap = mach64Screen->firstTexHeap;
mmesa->lastTexHeap = mach64Screen->firstTexHeap + mach64Screen->numTexHeaps;
for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
mach64Screen->texSize[i],
6, /* align to 64-byte boundary, use 12 for page-size boundary */
MACH64_NR_TEX_REGIONS,
(drmTextureRegionPtr)mmesa->sarea->tex_list[i],
&mmesa->sarea->tex_age[i],
&mmesa->swapped,
sizeof( mach64TexObj ),
(destroy_texture_object_t *) mach64DestroyTexObj );
#if ENABLE_PERF_BOXES
c_textureSwapsPtr = & mmesa->c_textureSwaps;
#endif
driSetTextureSwapCounterLocation( mmesa->texture_heaps[i],
c_textureSwapsPtr );
}
mmesa->RenderIndex = -1; /* Impossible value */
mmesa->vert_buf = NULL;
mmesa->num_verts = 0;
mmesa->new_state = MACH64_NEW_ALL;
mmesa->dirty = MACH64_UPLOAD_ALL;
/* Set the maximum texture size small enough that we can
* guarentee that both texture units can bind a maximal texture
* and have them both in memory (on-card or AGP) at once.
* Test for 2 textures * bytes/texel * size * size. There's no
* need to account for mipmaps since we only upload one level.
*/
ctx->Const.MaxTextureUnits = 2;
ctx->Const.MaxTextureImageUnits = 2;
ctx->Const.MaxTextureCoordUnits = 2;
heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP;
driCalculateMaxTextureLevels( & mmesa->texture_heaps[heap],
1,
& ctx->Const,
mach64Screen->cpp,
10, /* max 2D texture size is 1024x1024 */
0, /* 3D textures unsupported. */
0, /* cube textures unsupported. */
0, /* texture rectangles unsupported. */
1, /* mipmapping unsupported. */
GL_TRUE, /* need to have both textures in
either local or AGP memory */
0 );
#if ENABLE_PERF_BOXES
mmesa->boxes = ( getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL );
#endif
/* Allocate the vertex buffer
*/
mmesa->vert_buf = ALIGN_MALLOC(MACH64_BUFFER_SIZE, 32);
if ( !mmesa->vert_buf )
return GL_FALSE;
mmesa->vert_used = 0;
mmesa->vert_total = MACH64_BUFFER_SIZE;
/* 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, mach64_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 );
driInitExtensions( ctx, card_extensions, GL_TRUE );
mach64InitVB( ctx );
mach64InitTriFuncs( ctx );
mach64DDInitStateFuncs( ctx );
mach64DDInitSpanFuncs( ctx );
mach64DDInitState( mmesa );
mmesa->do_irqs = (mmesa->mach64Screen->irq && !getenv("MACH64_NO_IRQS"));
driContextPriv->driverPrivate = (void *)mmesa;
if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
fprintf(stderr, "disabling 3D acceleration\n");
FALLBACK(mmesa, MACH64_FALLBACK_DISABLE, 1);
}
return GL_TRUE;
}
/* Destroy the device specific context.
*/
void mach64DestroyContext( __DRIcontextPrivate *driContextPriv )
{
mach64ContextPtr mmesa = (mach64ContextPtr) driContextPriv->driverPrivate;
assert(mmesa); /* should never be null */
if ( mmesa ) {
GLboolean release_texture_heaps;
release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
_swsetup_DestroyContext( mmesa->glCtx );
_tnl_DestroyContext( mmesa->glCtx );
_vbo_DestroyContext( mmesa->glCtx );
_swrast_DestroyContext( mmesa->glCtx );
if (release_texture_heaps) {
/* This share group is about to go away, free our private
* texture object data.
*/
int i;
for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
driDestroyTextureHeap( mmesa->texture_heaps[i] );
mmesa->texture_heaps[i] = NULL;
}
assert( is_empty_list( & mmesa->swapped ) );
}
mach64FreeVB( mmesa->glCtx );
/* Free the vertex buffer */
if ( mmesa->vert_buf )
ALIGN_FREE( mmesa->vert_buf );
/* free the Mesa context */
mmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(mmesa->glCtx);
FREE( mmesa );
}
}
/* Force the context `c' to be the current context and associate with it
* buffer `b'.
*/
GLboolean
mach64MakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv )
{
if ( driContextPriv ) {
GET_CURRENT_CONTEXT(ctx);
mach64ContextPtr oldMach64Ctx = ctx ? MACH64_CONTEXT(ctx) : NULL;
mach64ContextPtr newMach64Ctx = (mach64ContextPtr) driContextPriv->driverPrivate;
if ( newMach64Ctx != oldMach64Ctx ) {
newMach64Ctx->new_state |= MACH64_NEW_CONTEXT;
newMach64Ctx->dirty = MACH64_UPLOAD_ALL;
}
if ( newMach64Ctx->driDrawable != driDrawPriv ) {
if (driDrawPriv->swap_interval == (unsigned)-1) {
driDrawPriv->vblFlags = (newMach64Ctx->do_irqs)
? driGetDefaultVBlankFlags(&newMach64Ctx->optionCache)
: VBLANK_FLAG_NO_IRQ;
driDrawableInitVBlank( driDrawPriv );
}
newMach64Ctx->driDrawable = driDrawPriv;
mach64CalcViewport( newMach64Ctx->glCtx );
}
_mesa_make_current( newMach64Ctx->glCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate );
newMach64Ctx->new_state |= MACH64_NEW_CLIP;
} else {
_mesa_make_current( NULL, NULL, NULL );
}
return GL_TRUE;
}
/* Force the context `c' to be unbound from its buffer.
*/
GLboolean
mach64UnbindContext( __DRIcontextPrivate *driContextPriv )
{
return GL_TRUE;
}