Merge branch 'gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / r300 / r300_context.c
index 3e18725f04a1df08400c7c6c06a699fc0ca3ba1d..fcf571d20603aa856628241680a5c203ef576585 100644 (file)
@@ -27,11 +27,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
-/*
- * Authors:
- *   Keith Whitwell <keith@tungstengraphics.com>
- *   Nicolai Haehnle <prefect_@gmx.net>
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * \author Nicolai Haehnle <prefect_@gmx.net>
  */
+
 #include "glheader.h"
 #include "api_arrayelt.h"
 #include "context.h"
@@ -44,10 +47,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
+#include "tnl/t_vp_build.h"
 
 #include "drivers/common/driverfuncs.h"
 
@@ -58,9 +62,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_state.h"
 #include "r300_ioctl.h"
 #include "r300_tex.h"
+#include "r300_emit.h"
+#include "r300_swtcl.h"
 
 #ifdef USER_BUFFERS
-#include "radeon_mm.h"
+#include "r300_mem.h"
 #endif
 
 #include "vblank.h"
@@ -68,23 +74,34 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xmlpool.h"           /* for symbolic values of enum-type options */
 
 /* hw_tcl_on derives from future_hw_tcl_on when its safe to change it. */
-int future_hw_tcl_on=0;
-int hw_tcl_on=0;
+int future_hw_tcl_on = 1;
+int hw_tcl_on = 1;
 
+#define need_GL_EXT_stencil_two_side
 #define need_GL_ARB_multisample
+#define need_GL_ARB_point_parameters
 #define need_GL_ARB_texture_compression
 #define need_GL_ARB_vertex_buffer_object
 #define need_GL_ARB_vertex_program
 #define need_GL_EXT_blend_minmax
+//#define need_GL_EXT_fog_coord
+#define need_GL_EXT_multi_draw_arrays
 #define need_GL_EXT_secondary_color
 #define need_GL_EXT_blend_equation_separate
 #define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_gpu_program_parameters
 #define need_GL_NV_vertex_program
 #include "extension_helper.h"
 
 const struct dri_extension card_extensions[] = {
+  /* *INDENT-OFF* */
+  {"GL_ARB_depth_texture",             NULL},
+  {"GL_ARB_fragment_program",          NULL},
   {"GL_ARB_multisample",               GL_ARB_multisample_functions},
   {"GL_ARB_multitexture",              NULL},
+  {"GL_ARB_point_parameters",          GL_ARB_point_parameters_functions},
+  {"GL_ARB_shadow",                    NULL},
+  {"GL_ARB_shadow_ambient",            NULL},
   {"GL_ARB_texture_border_clamp",      NULL},
   {"GL_ARB_texture_compression",       GL_ARB_texture_compression_functions},
   {"GL_ARB_texture_cube_map",          NULL},
@@ -95,14 +112,16 @@ const struct dri_extension card_extensions[] = {
   {"GL_ARB_texture_mirrored_repeat",   NULL},
   {"GL_ARB_vertex_buffer_object",      GL_ARB_vertex_buffer_object_functions},
   {"GL_ARB_vertex_program",            GL_ARB_vertex_program_functions},
-#if USE_ARB_F_P == 1
-  {"GL_ARB_fragment_program",          NULL},
-#endif
   {"GL_EXT_blend_equation_separate",   GL_EXT_blend_equation_separate_functions},
   {"GL_EXT_blend_func_separate",       GL_EXT_blend_func_separate_functions},
   {"GL_EXT_blend_minmax",              GL_EXT_blend_minmax_functions},
   {"GL_EXT_blend_subtract",            NULL},
+//  {"GL_EXT_fog_coord",                       GL_EXT_fog_coord_functions },
+  {"GL_EXT_multi_draw_arrays",         GL_EXT_multi_draw_arrays_functions},
+  {"GL_EXT_gpu_program_parameters",     GL_EXT_gpu_program_parameters_functions},
   {"GL_EXT_secondary_color",           GL_EXT_secondary_color_functions},
+  {"GL_EXT_shadow_funcs",              NULL},
+  {"GL_EXT_stencil_two_side",          GL_EXT_stencil_two_side_functions},
   {"GL_EXT_stencil_wrap",              NULL},
   {"GL_EXT_texture_edge_clamp",                NULL},
   {"GL_EXT_texture_env_combine",       NULL},
@@ -115,15 +134,17 @@ const struct dri_extension card_extensions[] = {
   {"GL_ATI_texture_mirror_once",       NULL},
   {"GL_MESA_pack_invert",              NULL},
   {"GL_MESA_ycbcr_texture",            NULL},
+  {"GL_MESAX_texture_float",           NULL},
   {"GL_NV_blend_square",               NULL},
   {"GL_NV_vertex_program",             GL_NV_vertex_program_functions},
   {"GL_SGIS_generate_mipmap",          NULL},
+  {"GL_SGIX_depth_texture",            NULL},
   {NULL,                               NULL}
+  /* *INDENT-ON* */
 };
 
 extern struct tnl_pipeline_stage _r300_render_stage;
 extern const struct tnl_pipeline_stage _r300_tcl_stage;
-extern const struct tnl_pipeline_stage _r300_texrect_stage;
 
 static const struct tnl_pipeline_stage *r300_pipeline[] = {
 
@@ -139,7 +160,6 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
        &_tnl_fog_coordinate_stage,
        &_tnl_texgen_stage,
        &_tnl_texture_transform_stage,
-       &_tnl_arb_vertex_program_stage,
        &_tnl_vertex_program_stage,
 
        /* Try again to go to tcl?
@@ -154,14 +174,11 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
 
        /* Else do them here.
         */
-       /* scale texture rectangle to 0..1. */
-       &_r300_texrect_stage,
        &_r300_render_stage,
        &_tnl_render_stage,     /* FALLBACK  */
        0,
 };
 
-
 /* Create the device specific rendering context.
  */
 GLboolean r300CreateContext(const __GLcontextModes * glVisual,
@@ -180,16 +197,21 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        assert(screen);
 
        /* Allocate the R300 context */
-       r300 = (r300ContextPtr)CALLOC(sizeof(*r300));
+       r300 = (r300ContextPtr) CALLOC(sizeof(*r300));
        if (!r300)
                return GL_FALSE;
 
+       if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
+               hw_tcl_on = future_hw_tcl_on = 0;
+
        /* Parse configuration files.
         * Do this here so that initialMaxAnisotropy is set before we create
         * the default textures.
         */
        driParseConfigFiles(&r300->radeon.optionCache, &screen->optionCache,
                            screen->driScreen->myNum, "r300");
+       r300->initialMaxAnisotropy = driQueryOptionf(&r300->radeon.optionCache,
+                                                    "def_max_anisotropy");
 
        /* Init default driver functions then plug in our R300-specific functions
         * (the texture functions are especially important)
@@ -199,23 +221,21 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        r300InitStateFuncs(&functions);
        r300InitTextureFuncs(&functions);
        r300InitShaderFuncs(&functions);
-       
+
 #ifdef USER_BUFFERS
-       radeon_mm_init(r300);
+       r300_mem_init(r300);
 #endif
-#ifdef HW_VBOS
-       if (hw_tcl_on) {
-               r300_init_vbo_funcs(&functions);
-       }
-#endif 
+
        if (!radeonInitContext(&r300->radeon, &functions,
-                              glVisual, driContextPriv, sharedContextPrivate)) {
+                              glVisual, driContextPriv,
+                              sharedContextPrivate)) {
                FREE(r300);
                return GL_FALSE;
        }
 
        /* Init r300 context data */
-       r300->dma.buf0_address = r300->radeon.radeonScreen->buffers->list[0].address;
+       r300->dma.buf0_address =
+           r300->radeon.radeonScreen->buffers->list[0].address;
 
        (void)memset(r300->texture_heaps, 0, sizeof(r300->texture_heaps));
        make_empty_list(&r300->swapped);
@@ -223,6 +243,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        r300->nr_heaps = 1 /* screen->numTexHeaps */ ;
        assert(r300->nr_heaps < RADEON_NR_TEX_HEAPS);
        for (i = 0; i < r300->nr_heaps; i++) {
+               /* *INDENT-OFF* */
                r300->texture_heaps[i] = driCreateTextureHeap(i, r300,
                                                               screen->
                                                               texSize[i], 12,
@@ -238,9 +259,10 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
                                                               (destroy_texture_object_t
                                                                *)
                                                               r300DestroyTexObj);
+               /* *INDENT-ON* */
        }
        r300->texture_depth = driQueryOptioni(&r300->radeon.optionCache,
-                                              "texture_depth");
+                                             "texture_depth");
        if (r300->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
                r300->texture_depth = (screen->cpp == 4) ?
                    DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
@@ -250,15 +272,22 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
         * texturable memory at once.
         */
 
-       ctx = r300->radeon.glCtx; 
-       
-       ctx->Const.MaxTextureImageUnits = driQueryOptioni(&r300->radeon.optionCache,
-                                                    "texture_image_units");
-       ctx->Const.MaxTextureCoordUnits = driQueryOptioni(&r300->radeon.optionCache,
-                                                    "texture_coord_units");
-       ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureImageUnits,
-                                         ctx->Const.MaxTextureCoordUnits);
+       ctx = r300->radeon.glCtx;
+
+       ctx->Const.MaxTextureImageUnits =
+           driQueryOptioni(&r300->radeon.optionCache, "texture_image_units");
+       ctx->Const.MaxTextureCoordUnits =
+           driQueryOptioni(&r300->radeon.optionCache, "texture_coord_units");
+       ctx->Const.MaxTextureUnits =
+           MIN2(ctx->Const.MaxTextureImageUnits,
+                ctx->Const.MaxTextureCoordUnits);
        ctx->Const.MaxTextureMaxAnisotropy = 16.0;
+       ctx->Const.MaxTextureLodBias = 16.0;
+
+       if (screen->chip_family >= CHIP_FAMILY_RV515) {
+           ctx->Const.MaxTextureLevels = 13;
+           ctx->Const.MaxTextureRectSize = 4096;
+       }
 
        ctx->Const.MinPointSize = 1.0;
        ctx->Const.MinPointSizeAA = 1.0;
@@ -269,21 +298,19 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        ctx->Const.MinLineWidthAA = 1.0;
        ctx->Const.MaxLineWidth = R300_LINESIZE_MAX;
        ctx->Const.MaxLineWidthAA = R300_LINESIZE_MAX;
-       
-       if (hw_tcl_on)
-               ctx->_MaintainTnlProgram = GL_TRUE;
-       
+
 #ifdef USER_BUFFERS
        /* Needs further modifications */
 #if 0
-       ctx->Const.MaxArrayLockSize = (/*512*/RADEON_BUFFER_SIZE*16*1024) / (4*4);
+       ctx->Const.MaxArrayLockSize =
+           ( /*512 */ RADEON_BUFFER_SIZE * 16 * 1024) / (4 * 4);
 #endif
 #endif
 
        /* Initialize the software rasterizer and helper modules.
         */
        _swrast_CreateContext(ctx);
-       _ac_CreateContext(ctx);
+       _vbo_CreateContext(ctx);
        _tnl_CreateContext(ctx);
        _swsetup_CreateContext(ctx);
        _swsetup_Wakeup(ctx);
@@ -296,7 +323,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
 
        /* Try and keep materials and vertices separate:
         */
-       _tnl_isolate_materials(ctx, GL_TRUE);
+/*     _tnl_isolate_materials(ctx, GL_TRUE); */
 
        /* Configure swrast and TNL to match hardware characteristics:
         */
@@ -306,49 +333,57 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        _tnl_allow_vertex_fog(ctx, GL_TRUE);
 
        /* currently bogus data */
-       ctx->Const.VertexProgram.MaxNativeInstructions=VSF_MAX_FRAGMENT_LENGTH;
-       ctx->Const.VertexProgram.MaxNativeAttribs=16; /* r420 */
-       ctx->Const.VertexProgram.MaxTemps=32;
-       ctx->Const.VertexProgram.MaxNativeTemps=/*VSF_MAX_FRAGMENT_TEMPS*/32;
-       ctx->Const.VertexProgram.MaxNativeParameters=256; /* r420 */
-       ctx->Const.VertexProgram.MaxNativeAddressRegs=1;
-
-#if USE_ARB_F_P
+       if (screen->chip_flags & RADEON_CHIPSET_TCL) {
+               ctx->Const.VertexProgram.MaxInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
+               ctx->Const.VertexProgram.MaxNativeInstructions =
+                 VSF_MAX_FRAGMENT_LENGTH / 4;
+               ctx->Const.VertexProgram.MaxNativeAttribs = 16; /* r420 */
+               ctx->Const.VertexProgram.MaxTemps = 32;
+               ctx->Const.VertexProgram.MaxNativeTemps =
+                 /*VSF_MAX_FRAGMENT_TEMPS */ 32;
+               ctx->Const.VertexProgram.MaxNativeParameters = 256;     /* r420 */
+               ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
+       }
+
        ctx->Const.FragmentProgram.MaxNativeTemps = PFS_NUM_TEMP_REGS;
-       ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* copy i915... */
+       ctx->Const.FragmentProgram.MaxNativeAttribs = 11;       /* copy i915... */
        ctx->Const.FragmentProgram.MaxNativeParameters = PFS_NUM_CONST_REGS;
        ctx->Const.FragmentProgram.MaxNativeAluInstructions = PFS_MAX_ALU_INST;
        ctx->Const.FragmentProgram.MaxNativeTexInstructions = PFS_MAX_TEX_INST;
-       ctx->Const.FragmentProgram.MaxNativeInstructions = PFS_MAX_ALU_INST+PFS_MAX_TEX_INST;
-       ctx->Const.FragmentProgram.MaxNativeTexIndirections = PFS_MAX_TEX_INDIRECT;
-       ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* and these are?? */
-       ctx->_MaintainTexEnvProgram = GL_TRUE;
-#endif
+       ctx->Const.FragmentProgram.MaxNativeInstructions =
+           PFS_MAX_ALU_INST + PFS_MAX_TEX_INST;
+       ctx->Const.FragmentProgram.MaxNativeTexIndirections =
+           PFS_MAX_TEX_INDIRECT;
+       ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;    /* and these are?? */
+       _tnl_ProgramCacheInit(ctx);
+       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
 
        driInitExtensions(ctx, card_extensions, GL_TRUE);
-       
-       if (r300->radeon.glCtx->Mesa_DXTn) {
-         _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
-         _mesa_enable_extension( ctx, "GL_S3_s3tc" );
-       }
-       else if (driQueryOptionb (&r300->radeon.optionCache, "force_s3tc_enable")) {
-         _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+
+       if (driQueryOptionb
+           (&r300->radeon.optionCache, "disable_stencil_two_side"))
+               _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
+
+       if (r300->radeon.glCtx->Mesa_DXTn
+           && !driQueryOptionb(&r300->radeon.optionCache, "disable_s3tc")) {
+               _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+               _mesa_enable_extension(ctx, "GL_S3_s3tc");
+       } else
+           if (driQueryOptionb(&r300->radeon.optionCache, "force_s3tc_enable"))
+       {
+               _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
        }
 
+       r300->disable_lowimpact_fallback =
+           driQueryOptionb(&r300->radeon.optionCache,
+                           "disable_lowimpact_fallback");
+
        radeonInitSpanFuncs(ctx);
        r300InitCmdBuf(r300);
        r300InitState(r300);
-       
-#ifdef RADEON_VTXFMT_A
-       radeon_init_vtxfmt_a(r300);
-#endif
+       if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
+               r300InitSwtcl(ctx);
 
-#if 0
-       /* plug in a few more device driver functions */
-       /* XXX these should really go right after _mesa_init_driver_functions() */
-       r300InitPixelFuncs(ctx);
-       r300InitSwtcl(ctx);
-#endif
        TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
 
        tcl_mode = driQueryOptioni(&r300->radeon.optionCache, "tcl_mode");
@@ -361,15 +396,83 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        if (tcl_mode == DRI_CONF_TCL_SW ||
            !(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
                if (r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
-                       r300->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
+                       r300->radeon.radeonScreen->chip_flags &=
+                           ~RADEON_CHIPSET_TCL;
                        fprintf(stderr, "Disabling HW TCL support\n");
                }
-               TCL_FALLBACK(r300->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
+               TCL_FALLBACK(r300->radeon.glCtx,
+                            RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
        }
 
        return GL_TRUE;
 }
 
+static void r300FreeGartAllocations(r300ContextPtr r300)
+{
+       int i, ret, tries = 0, done_age, in_use = 0;
+       drm_radeon_mem_free_t memfree;
+
+       memfree.region = RADEON_MEM_REGION_GART;
+
+#ifdef USER_BUFFERS
+       for (i = r300->rmm->u_last; i > 0; i--) {
+               if (r300->rmm->u_list[i].ptr == NULL) {
+                       continue;
+               }
+
+               /* check whether this buffer is still in use */
+               if (r300->rmm->u_list[i].pending) {
+                       in_use++;
+               }
+       }
+       /* Cannot flush/lock if no context exists. */
+       if (in_use)
+               r300FlushCmdBuf(r300, __FUNCTION__);
+
+       done_age = radeonGetAge((radeonContextPtr) r300);
+
+       for (i = r300->rmm->u_last; i > 0; i--) {
+               if (r300->rmm->u_list[i].ptr == NULL) {
+                       continue;
+               }
+
+               /* check whether this buffer is still in use */
+               if (!r300->rmm->u_list[i].pending) {
+                       continue;
+               }
+
+               assert(r300->rmm->u_list[i].h_pending == 0);
+
+               tries = 0;
+               while (r300->rmm->u_list[i].age > done_age && tries++ < 1000) {
+                       usleep(10);
+                       done_age = radeonGetAge((radeonContextPtr) r300);
+               }
+               if (tries >= 1000) {
+                       WARN_ONCE("Failed to idle region!");
+               }
+
+               memfree.region_offset = (char *)r300->rmm->u_list[i].ptr -
+                   (char *)r300->radeon.radeonScreen->gartTextures.map;
+
+               ret = drmCommandWrite(r300->radeon.radeonScreen->driScreen->fd,
+                                     DRM_RADEON_FREE, &memfree,
+                                     sizeof(memfree));
+               if (ret) {
+                       fprintf(stderr, "Failed to free at %p\nret = %s\n",
+                               r300->rmm->u_list[i].ptr, strerror(-ret));
+               } else {
+                       if (i == r300->rmm->u_last)
+                               r300->rmm->u_last--;
+
+                       r300->rmm->u_list[i].pending = 0;
+                       r300->rmm->u_list[i].ptr = NULL;
+               }
+       }
+       r300->rmm->u_head = i;
+#endif                         /* USER_BUFFERS */
+}
+
 /* Destroy the device specific context.
  */
 void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
@@ -395,18 +498,22 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
        if (r300) {
                GLboolean release_texture_heaps;
 
-               release_texture_heaps = (r300->radeon.glCtx->Shared->RefCount == 1);
+               release_texture_heaps =
+                   (r300->radeon.glCtx->Shared->RefCount == 1);
                _swsetup_DestroyContext(r300->radeon.glCtx);
+               _tnl_ProgramCacheDestroy(r300->radeon.glCtx);
                _tnl_DestroyContext(r300->radeon.glCtx);
-               _ac_DestroyContext(r300->radeon.glCtx);
+               _vbo_DestroyContext(r300->radeon.glCtx);
                _swrast_DestroyContext(r300->radeon.glCtx);
-               
-               r300ReleaseArrays(r300->radeon.glCtx);
+
                if (r300->dma.current.buf) {
-                       r300ReleaseDmaRegion(r300, &r300->dma.current, __FUNCTION__ );
-                       r300FlushCmdBuf(r300, __FUNCTION__ );
+                       r300ReleaseDmaRegion(r300, &r300->dma.current,
+                                            __FUNCTION__);
+#ifndef USER_BUFFERS
+                       r300FlushCmdBuf(r300, __FUNCTION__);
+#endif
                }
-                               
+               r300FreeGartAllocations(r300);
                r300DestroyCmdBuf(r300);
 
                if (radeon->state.scissor.pClipRects) {
@@ -430,6 +537,13 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
 
                radeonCleanupContext(&r300->radeon);
 
+#ifdef USER_BUFFERS
+               /* the memory manager might be accessed when Mesa frees the shared
+                * state, so don't destroy it earlier
+                */
+               r300_mem_destroy(r300);
+#endif
+
                /* free the option cache */
                driDestroyOptionCache(&r300->radeon.optionCache);