Merge branch 'mesa_7_6_branch'
[mesa.git] / src / mesa / drivers / dri / r300 / r300_context.c
index 8f0effd83e2726ca2383f8f359ee15941f22462e..2c2b16aa98dc60d0e25df6516d4be5b5af3657c5 100644 (file)
@@ -43,8 +43,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/matrix.h"
 #include "main/extensions.h"
 #include "main/state.h"
-#include "main/texobj.h"
 #include "main/bufferobj.h"
+#include "main/texobj.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
@@ -56,46 +56,48 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "drivers/common/driverfuncs.h"
 
-#include "radeon_ioctl.h"
-#include "radeon_span.h"
 #include "r300_context.h"
+#include "radeon_context.h"
+#include "radeon_span.h"
 #include "r300_cmdbuf.h"
 #include "r300_state.h"
 #include "r300_ioctl.h"
 #include "r300_tex.h"
 #include "r300_emit.h"
 #include "r300_swtcl.h"
-
-#ifdef USER_BUFFERS
-#include "r300_mem.h"
-#endif
+#include "radeon_bocs_wrapper.h"
+#include "radeon_buffer_objects.h"
+#include "radeon_queryobj.h"
 
 #include "vblank.h"
 #include "utils.h"
 #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 = 1;
-int hw_tcl_on = 1;
-
 #define need_GL_VERSION_2_0
+#define need_GL_ARB_occlusion_query
 #define need_GL_ARB_point_parameters
 #define need_GL_ARB_vertex_program
 #define need_GL_EXT_blend_equation_separate
 #define need_GL_EXT_blend_func_separate
 #define need_GL_EXT_blend_minmax
+#define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_framebuffer_object
 #define need_GL_EXT_fog_coord
 #define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_provoking_vertex
 #define need_GL_EXT_secondary_color
 #define need_GL_EXT_stencil_two_side
 #define need_GL_ATI_separate_stencil
 #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_occlusion_query",           GL_ARB_occlusion_query_functions},
   {"GL_ARB_multitexture",              NULL},
   {"GL_ARB_point_parameters",          GL_ARB_point_parameters_functions},
   {"GL_ARB_shadow",                    NULL},
@@ -112,8 +114,10 @@ const struct dri_extension card_extensions[] = {
   {"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_packed_depth_stencil",      NULL},
   {"GL_EXT_fog_coord",                 GL_EXT_fog_coord_functions },
   {"GL_EXT_gpu_program_parameters",     GL_EXT_gpu_program_parameters_functions},
+  {"GL_EXT_provoking_vertex",           GL_EXT_provoking_vertex_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},
@@ -125,6 +129,8 @@ const struct dri_extension card_extensions[] = {
   {"GL_EXT_texture_lod_bias",          NULL},
   {"GL_EXT_texture_mirror_clamp",      NULL},
   {"GL_EXT_texture_rectangle",         NULL},
+  {"GL_EXT_texture_sRGB",              NULL},
+  {"GL_EXT_vertex_array_bgra",         NULL},
   {"GL_ATI_separate_stencil",          GL_ATI_separate_stencil_functions},
   {"GL_ATI_texture_env_combine3",      NULL},
   {"GL_ATI_texture_mirror_once",       NULL},
@@ -139,6 +145,12 @@ const struct dri_extension card_extensions[] = {
 };
 
 
+const struct dri_extension mm_extensions[] = {
+  { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
+  { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+  { NULL, NULL }
+};
+
 /**
  * The GL 2.0 functions are needed to make display lists work with
  * functions added by GL_ATI_separate_stencil.
@@ -147,16 +159,7 @@ const struct dri_extension gl_20_extension[] = {
   {"GL_VERSION_2_0",                   GL_VERSION_2_0_functions },
 };
 
-
-extern struct tnl_pipeline_stage _r300_render_stage;
-extern const struct tnl_pipeline_stage _r300_tcl_stage;
-
 static const struct tnl_pipeline_stage *r300_pipeline[] = {
-
-       /* Try and go straight to t&l
-        */
-       &_r300_tcl_stage,
-
        /* Catch any t&l fallbacks
         */
        &_tnl_vertex_transform_stage,
@@ -165,147 +168,188 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
        &_tnl_fog_coordinate_stage,
        &_tnl_texgen_stage,
        &_tnl_texture_transform_stage,
+       &_tnl_point_attenuation_stage,
        &_tnl_vertex_program_stage,
-
-       /* Try again to go to tcl?
-        *     - no good for asymmetric-twoside (do with multipass)
-        *     - no good for asymmetric-unfilled (do with multipass)
-        *     - good for material
-        *     - good for texgen
-        *     - need to manipulate a bit of state
-        *
-        * - worth it/not worth it?
-        */
-
-       /* Else do them here.
-        */
-       &_r300_render_stage,
-       &_tnl_render_stage,     /* FALLBACK  */
+       &_tnl_render_stage,
        0,
 };
 
-/* Create the device specific rendering context.
- */
-GLboolean r300CreateContext(const __GLcontextModes * glVisual,
-                           __DRIcontextPrivate * driContextPriv,
-                           void *sharedContextPrivate)
+static void r300_get_lock(radeonContextPtr rmesa)
 {
-       __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
-       radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
-       struct dd_function_table functions;
-       r300ContextPtr r300;
-       GLcontext *ctx;
-       int tcl_mode, i;
-
-       assert(glVisual);
-       assert(driContextPriv);
-       assert(screen);
+       drm_radeon_sarea_t *sarea = rmesa->sarea;
 
-       /* Allocate the R300 context */
-       r300 = (r300ContextPtr) CALLOC(sizeof(*r300));
-       if (!r300)
-               return GL_FALSE;
+       if (sarea->ctx_owner != rmesa->dri.hwContext) {
+               sarea->ctx_owner = rmesa->dri.hwContext;
+               if (!rmesa->radeonScreen->kernel_mm)
+                       radeon_bo_legacy_texture_age(rmesa->radeonScreen->bom);
+       }
+}
 
-       if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
-               hw_tcl_on = future_hw_tcl_on = 0;
+static void r300_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
+{
+    /* please flush pipe do all pending work */
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_SC_SCREENDOOR, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_SC_SCREENDOOR, 1));
+    radeon_cs_write_dword(cs, 0x00FFFFFF);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_SC_HYPERZ, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_US_CONFIG, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_ZB_CNTL, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdwait(rmesa->radeonScreen, R300_WAIT_3D));
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_RB3D_DSTCACHE_CTLSTAT, 1));
+    radeon_cs_write_dword(cs, R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_ZB_ZCACHE_CTLSTAT, 1));
+    radeon_cs_write_dword(cs, R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE);
+    radeon_cs_write_dword(cs, cmdwait(rmesa->radeonScreen,
+                               R300_WAIT_3D | R300_WAIT_3D_CLEAN));
+}
 
-       /* 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");
+static void r300_vtbl_pre_emit_atoms(radeonContextPtr radeon)
+{
+       BATCH_LOCALS(radeon);
 
-       /* Init default driver functions then plug in our R300-specific functions
-        * (the texture functions are especially important)
-        */
-       _mesa_init_driver_functions(&functions);
-       r300InitIoctlFuncs(&functions);
-       r300InitStateFuncs(&functions);
-       r300InitTextureFuncs(&functions);
-       r300InitShaderFuncs(&functions);
+       cp_wait(radeon, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+       BEGIN_BATCH_NO_AUTOSTATE(2);
+       OUT_BATCH_REGVAL(R300_TX_INVALTAGS, R300_TX_FLUSH);
+       END_BATCH();
+       end_3d(radeon);
+}
 
-#ifdef USER_BUFFERS
-       r300_mem_init(r300);
-#endif
+static void r300_fallback(GLcontext *ctx, GLuint bit, GLboolean mode)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       if (mode)
+               r300->radeon.Fallback |= bit;
+       else
+               r300->radeon.Fallback &= ~bit;
+}
 
-       if (!radeonInitContext(&r300->radeon, &functions,
-                              glVisual, driContextPriv,
-                              sharedContextPrivate)) {
-               FREE(r300);
-               return GL_FALSE;
+static void r300_emit_query_finish(radeonContextPtr radeon)
+{
+       r300ContextPtr r300 = (r300ContextPtr)radeon;
+       struct radeon_query_object *query = radeon->query.current;
+       BATCH_LOCALS(radeon);
+
+       BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->radeon.radeonScreen->num_gb_pipes + 2);
+       switch (r300->radeon.radeonScreen->num_gb_pipes) {
+       case 4:
+               OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+               OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+               OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+       case 3:
+               OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2);
+               OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+               OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+       case 2:
+               if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) {
+                       OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+               } else {
+                       OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1);
+               }
+               OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+               OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+       case 1:
+       default:
+               OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0);
+               OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+               OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+               break;
        }
+       OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
+       END_BATCH();
+       query->curr_offset += r300->radeon.radeonScreen->num_gb_pipes * sizeof(uint32_t);
+       assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+       query->emitted_begin = GL_FALSE;
+}
 
-       /* Init r300 context data */
-       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);
-
-       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,
-                                                              RADEON_NR_TEX_REGIONS,
-                                                              (drmTextureRegionPtr)
-                                                              r300->radeon.sarea->
-                                                              tex_list[i],
-                                                              &r300->radeon.sarea->
-                                                              tex_age[i],
-                                                              &r300->swapped,
-                                                              sizeof
-                                                              (r300TexObj),
-                                                              (destroy_texture_object_t
-                                                               *)
-                                                              r300DestroyTexObj);
-               /* *INDENT-ON* */
-       }
-       r300->texture_depth = driQueryOptioni(&r300->radeon.optionCache,
-                                             "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;
-
-       /* Set the maximum texture size small enough that we can guarentee that
-        * all texture units can bind a maximal texture and have them both in
-        * texturable memory at once.
-        */
+static void rv530_emit_query_finish_single_z(radeonContextPtr radeon)
+{
+       BATCH_LOCALS(radeon);
+       struct radeon_query_object *query = radeon->query.current;
+
+       BEGIN_BATCH_NO_AUTOSTATE(8);
+       OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+       OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+       OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+       OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+       END_BATCH();
+
+       query->curr_offset += sizeof(uint32_t);
+       assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+       query->emitted_begin = GL_FALSE;
+}
 
-       ctx = r300->radeon.glCtx;
+static void rv530_emit_query_finish_double_z(radeonContextPtr radeon)
+{
+       BATCH_LOCALS(radeon);
+       struct radeon_query_object *query = radeon->query.current;
+
+       BEGIN_BATCH_NO_AUTOSTATE(14);
+       OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+       OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+       OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+       OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
+       OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+       OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+       OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+       END_BATCH();
+
+       query->curr_offset += 2 * sizeof(uint32_t);
+       assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+       query->emitted_begin = GL_FALSE;
+}
+
+static void r300_init_vtbl(radeonContextPtr radeon)
+{
+       radeon->vtbl.get_lock = r300_get_lock;
+       radeon->vtbl.update_viewport_offset = r300UpdateViewportOffset;
+       radeon->vtbl.emit_cs_header = r300_vtbl_emit_cs_header;
+       radeon->vtbl.swtcl_flush = r300_swtcl_flush;
+       radeon->vtbl.pre_emit_atoms = r300_vtbl_pre_emit_atoms;
+       radeon->vtbl.fallback = r300_fallback;
+       if (radeon->radeonScreen->chip_family == CHIP_FAMILY_RV530) {
+               if (radeon->radeonScreen->num_z_pipes == 2)
+                       radeon->vtbl.emit_query_finish = rv530_emit_query_finish_double_z;
+               else
+                       radeon->vtbl.emit_query_finish = rv530_emit_query_finish_single_z;
+       } else
+               radeon->vtbl.emit_query_finish = r300_emit_query_finish;
+}
+
+static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
 
        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.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;
-       else
-           ctx->Const.MaxTextureLevels = 12;
-
-        driCalculateMaxTextureLevels( r300->texture_heaps,
-                                      r300->nr_heaps,
-                                      & ctx->Const,
-                                      4,
-                                      ctx->Const.MaxTextureLevels - 1,
-                                      MIN2(ctx->Const.MaxTextureLevels,
-                                           MAX_3D_TEXTURE_LEVELS) - 1,
-                                      ctx->Const.MaxTextureLevels - 1,
-                                      ctx->Const.MaxTextureLevels - 1,
-                                      ctx->Const.MaxTextureLevels - 1,
-                                      GL_FALSE,
-                                      2 );
+       if (screen->chip_family >= CHIP_FAMILY_RV515) {
+               ctx->Const.MaxTextureLevels = 13;
+               ctx->Const.MaxCubeTextureLevels = 13;
+               ctx->Const.MaxTextureRectSize = 4096;
+       }
+       else {
+               ctx->Const.MaxTextureLevels = 12;
+               ctx->Const.MaxCubeTextureLevels = 12;
+               ctx->Const.MaxTextureRectSize = 2048;
+       }
 
        ctx->Const.MinPointSize = 1.0;
        ctx->Const.MinPointSizeAA = 1.0;
@@ -317,261 +361,183 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        ctx->Const.MaxLineWidth = R300_LINESIZE_MAX;
        ctx->Const.MaxLineWidthAA = R300_LINESIZE_MAX;
 
-#ifdef USER_BUFFERS
-       /* Needs further modifications */
-#if 0
-       ctx->Const.MaxArrayLockSize =
-           ( /*512 */ RADEON_BUFFER_SIZE * 16 * 1024) / (4 * 4);
-#endif
-#endif
-
        ctx->Const.MaxDrawBuffers = 1;
 
-       /* Initialize the software rasterizer and helper modules.
-        */
-       _swrast_CreateContext(ctx);
-       _vbo_CreateContext(ctx);
-       _tnl_CreateContext(ctx);
-       _swsetup_CreateContext(ctx);
-       _swsetup_Wakeup(ctx);
-       _ae_create_context(ctx);
-
-       /* Install the customized pipeline:
-        */
-       _tnl_destroy_pipeline(ctx);
-       _tnl_install_pipeline(ctx, r300_pipeline);
-
-       /* Try and keep materials and vertices separate:
-        */
-/*     _tnl_isolate_materials(ctx, GL_TRUE); */
-
-       /* Configure swrast and TNL 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);
-
        /* currently bogus data */
-       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;
+       if (r300->options.hw_tcl_enabled) {
+               ctx->Const.VertexProgram.MaxNativeInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
+               ctx->Const.VertexProgram.MaxNativeAluInstructions = 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.MaxNativeTemps = 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.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->VertexProgram._MaintainTnlProgram = GL_TRUE;
-       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+       if (screen->chip_family >= CHIP_FAMILY_RV515) {
+               ctx->Const.FragmentProgram.MaxNativeTemps = R500_PFS_NUM_TEMP_REGS;
+               ctx->Const.FragmentProgram.MaxNativeAttribs = 11;       /* copy i915... */
+
+               /* The hardware limits are higher than this,
+                * but the non-KMS DRM interface artificially limits us
+                * to this many instructions.
+                *
+                * We could of course work around it in the KMS path,
+                * but it would be a mess, so it seems wiser
+                * to leave it as is. Going forward, the Gallium driver
+                * will not be subject to these limitations.
+                */
+               ctx->Const.FragmentProgram.MaxNativeParameters = 255;
+               ctx->Const.FragmentProgram.MaxNativeAluInstructions = 255;
+               ctx->Const.FragmentProgram.MaxNativeTexInstructions = 255;
+               ctx->Const.FragmentProgram.MaxNativeInstructions = 255;
+               ctx->Const.FragmentProgram.MaxNativeTexIndirections = 255;
+               ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
+       } else {
+               ctx->Const.FragmentProgram.MaxNativeTemps = R300_PFS_NUM_TEMP_REGS;
+               ctx->Const.FragmentProgram.MaxNativeAttribs = 11;       /* copy i915... */
+               ctx->Const.FragmentProgram.MaxNativeParameters = R300_PFS_NUM_CONST_REGS;
+               ctx->Const.FragmentProgram.MaxNativeAluInstructions = R300_PFS_MAX_ALU_INST;
+               ctx->Const.FragmentProgram.MaxNativeTexInstructions = R300_PFS_MAX_TEX_INST;
+               ctx->Const.FragmentProgram.MaxNativeInstructions = R300_PFS_MAX_ALU_INST + R300_PFS_MAX_TEX_INST;
+               ctx->Const.FragmentProgram.MaxNativeTexIndirections = R300_PFS_MAX_TEX_INDIRECT;
+               ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
+       }
 
-       driInitExtensions(ctx, card_extensions, GL_TRUE);
+}
 
-       if (driQueryOptionb
-           (&r300->radeon.optionCache, "disable_stencil_two_side"))
-               _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
+static void r300ParseOptions(r300ContextPtr r300, radeonScreenPtr screen)
+{
+       struct r300_options options = { 0 };
 
-       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");
-       }
+       driParseConfigFiles(&r300->radeon.optionCache, &screen->optionCache,
+                           screen->driScreen->myNum, "r300");
 
-       r300->disable_lowimpact_fallback =
-           driQueryOptionb(&r300->radeon.optionCache,
-                           "disable_lowimpact_fallback");
+       r300->radeon.initialMaxAnisotropy = driQueryOptionf(&r300->radeon.optionCache, "def_max_anisotropy");
 
-       radeonInitSpanFuncs(ctx);
-       r300InitCmdBuf(r300);
-       r300InitState(r300);
-       if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
-               r300InitSwtcl(ctx);
+       options.stencil_two_side_disabled = driQueryOptionb(&r300->radeon.optionCache, "disable_stencil_two_side");
+       options.s3tc_force_enabled = driQueryOptionb(&r300->radeon.optionCache, "force_s3tc_enable");
+       options.s3tc_force_disabled = driQueryOptionb(&r300->radeon.optionCache, "disable_s3tc");
 
-       TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+       if (!(screen->chip_flags & RADEON_CHIPSET_TCL) || driQueryOptioni(&r300->radeon.optionCache, "tcl_mode") == DRI_CONF_TCL_SW)
+               options.hw_tcl_enabled = 0;
+       else
+               options.hw_tcl_enabled = 1;
 
-       tcl_mode = driQueryOptioni(&r300->radeon.optionCache, "tcl_mode");
-       if (driQueryOptionb(&r300->radeon.optionCache, "no_rast")) {
-               fprintf(stderr, "disabling 3D acceleration\n");
-#if R200_MERGED
-               FALLBACK(&r300->radeon, RADEON_FALLBACK_DISABLE, 1);
-#endif
-       }
-       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;
-                       fprintf(stderr, "Disabling HW TCL support\n");
-               }
-               TCL_FALLBACK(r300->radeon.glCtx,
-                            RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
-       }
+       options.conformance_mode = !driQueryOptionb(&r300->radeon.optionCache, "disable_lowimpact_fallback");
 
-       return GL_TRUE;
+       r300->options = options;
 }
 
-static void r300FreeGartAllocations(r300ContextPtr r300)
+static void r300InitGLExtensions(GLcontext *ctx)
 {
-       int i, ret, tries = 0, done_age, in_use = 0;
-       drm_radeon_mem_free_t memfree;
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
 
-       memfree.region = RADEON_MEM_REGION_GART;
+       driInitExtensions(ctx, card_extensions, GL_TRUE);
+       if (r300->radeon.radeonScreen->kernel_mm)
+               driInitExtensions(ctx, mm_extensions, GL_FALSE);
 
-#ifdef USER_BUFFERS
-       for (i = r300->rmm->u_last; i > 0; i--) {
-               if (r300->rmm->u_list[i].ptr == NULL) {
-                       continue;
-               }
+       if (r300->options.stencil_two_side_disabled)
+               _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
 
-               /* check whether this buffer is still in use */
-               if (r300->rmm->u_list[i].pending) {
-                       in_use++;
-               }
+       if (r300->options.s3tc_force_enabled) {
+               _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+               _mesa_enable_extension(ctx, "GL_S3_s3tc");
+       } else if (r300->options.s3tc_force_disabled) {
+               _mesa_disable_extension(ctx, "GL_EXT_texture_compression_s3tc");
        }
-       /* Cannot flush/lock if no context exists. */
-       if (in_use)
-               r300FlushCmdBuf(r300, __FUNCTION__);
 
-       done_age = radeonGetAge((radeonContextPtr) r300);
+       if (!r300->radeon.radeonScreen->drmSupportsOcclusionQueries) {
+               _mesa_disable_extension(ctx, "GL_ARB_occlusion_query");
+       }
+}
 
-       for (i = r300->rmm->u_last; i > 0; i--) {
-               if (r300->rmm->u_list[i].ptr == NULL) {
-                       continue;
-               }
+/* Create the device specific rendering context.
+ */
+GLboolean r300CreateContext(const __GLcontextModes * glVisual,
+                           __DRIcontextPrivate * driContextPriv,
+                           void *sharedContextPrivate)
+{
+       __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+       radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
+       struct dd_function_table functions;
+       r300ContextPtr r300;
+       GLcontext *ctx;
 
-               /* check whether this buffer is still in use */
-               if (!r300->rmm->u_list[i].pending) {
-                       continue;
-               }
+       assert(glVisual);
+       assert(driContextPriv);
+       assert(screen);
 
-               assert(r300->rmm->u_list[i].h_pending == 0);
+       r300 = (r300ContextPtr) CALLOC(sizeof(*r300));
+       if (!r300)
+               return GL_FALSE;
 
-               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!");
-               }
+       r300ParseOptions(r300, screen);
 
-               memfree.region_offset = (char *)r300->rmm->u_list[i].ptr -
-                   (char *)r300->radeon.radeonScreen->gartTextures.map;
+       r300->radeon.radeonScreen = screen;
+       r300_init_vtbl(&r300->radeon);
 
-               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--;
+       _mesa_init_driver_functions(&functions);
+       r300InitIoctlFuncs(&functions);
+       r300InitStateFuncs(&functions);
+       r300InitTextureFuncs(&functions);
+       r300InitShaderFuncs(&functions);
+       radeonInitQueryObjFunctions(&functions);
+       radeonInitBufferObjectFuncs(&functions);
 
-                       r300->rmm->u_list[i].pending = 0;
-                       r300->rmm->u_list[i].ptr = NULL;
-               }
+       if (!radeonInitContext(&r300->radeon, &functions,
+                              glVisual, driContextPriv,
+                              sharedContextPrivate)) {
+               FREE(r300);
+               return GL_FALSE;
        }
-       r300->rmm->u_head = i;
-#endif                         /* USER_BUFFERS */
-}
 
-/* Destroy the device specific context.
- */
-void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
-{
-       GET_CURRENT_CONTEXT(ctx);
-       r300ContextPtr r300 = (r300ContextPtr) driContextPriv->driverPrivate;
-       radeonContextPtr radeon = (radeonContextPtr) r300;
-       radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
-       int i;
-
-       if (RADEON_DEBUG & DEBUG_DRI) {
-               fprintf(stderr, "Destroying context !\n");
-       }
+       ctx = r300->radeon.glCtx;
 
-       /* check if we're deleting the currently bound context */
-       if (&r300->radeon == current) {
-               radeonFlush(r300->radeon.glCtx);
-               _mesa_make_current(NULL, NULL, NULL);
-       }
+       r300->fallback = 0;
+       if (r300->options.hw_tcl_enabled)
+               ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
 
-       /* Free r300 context resources */
-       assert(r300);           /* should never be null */
-
-       if (r300) {
-               GLboolean release_texture_heaps;
-
-               release_texture_heaps =
-                   (r300->radeon.glCtx->Shared->RefCount == 1);
-               _swsetup_DestroyContext(r300->radeon.glCtx);
-               _tnl_DestroyContext(r300->radeon.glCtx);
-               _vbo_DestroyContext(r300->radeon.glCtx);
-               _swrast_DestroyContext(r300->radeon.glCtx);
-
-               if (r300->dma.current.buf) {
-                       r300ReleaseDmaRegion(r300, &r300->dma.current,
-                                            __FUNCTION__);
-#ifndef USER_BUFFERS
-                       r300FlushCmdBuf(r300, __FUNCTION__);
-#endif
-               }
-               r300FreeGartAllocations(r300);
-               r300DestroyCmdBuf(r300);
+       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
 
-               if (radeon->state.scissor.pClipRects) {
-                       FREE(radeon->state.scissor.pClipRects);
-                       radeon->state.scissor.pClipRects = NULL;
-               }
+       r300InitConstValues(ctx, screen);
 
-               if (release_texture_heaps) {
-                       /* This share group is about to go away, free our private
-                        * texture object data.
-                        */
-                       int i;
+       _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
 
-                       for (i = 0; i < r300->nr_heaps; i++) {
-                               driDestroyTextureHeap(r300->texture_heaps[i]);
-                               r300->texture_heaps[i] = NULL;
-                       }
+       /* Initialize the software rasterizer and helper modules.
+        */
+       _swrast_CreateContext(ctx);
+       _vbo_CreateContext(ctx);
+       _tnl_CreateContext(ctx);
+       _swsetup_CreateContext(ctx);
+       _swsetup_Wakeup(ctx);
 
-                       assert(is_empty_list(&r300->swapped));
-               }
+       /* Install the customized pipeline:
+        */
+       _tnl_destroy_pipeline(ctx);
+       _tnl_install_pipeline(ctx, r300_pipeline);
+       TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
 
-                /* Drop texture object references from current hardware state */
-               for (i = 0; i < 8; i++) {
-                       _mesa_reference_texobj(&r300->state.texture.unit[i].texobj, NULL);
-               }
+       /* Configure swrast and TNL 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);
 
-               radeonCleanupContext(&r300->radeon);
+       if (r300->options.hw_tcl_enabled) {
+               r300InitDraw(ctx);
+       } else {
+               r300InitSwtcl(ctx);
+       }
 
-#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
+       radeon_fbo_init(&r300->radeon);
+       radeonInitSpanFuncs( ctx );
+       r300InitCmdBuf(r300);
+       r300InitState(r300);
+       r300InitShaderFunctions(r300);
 
-               /* free the option cache */
-               driDestroyOptionCache(&r300->radeon.optionCache);
+       r300InitGLExtensions(ctx);
 
-               FREE(r300);
-       }
+       return GL_TRUE;
 }
+