Until now falling back to software rasterizer worked only for TCL enabled cards.
For non TCL cards we used to plug our rendering functions in r300InitSwtcl, and we had never restored original functions for software rasterizer.
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");
options.stencil_two_side_disabled = driQueryOptionb(&r300->radeon.optionCache, "disable_stencil_two_side");
else
options.hw_tcl_enabled = 1;
+ options.conformance_mode = !driQueryOptionb(&r300->radeon.optionCache, "disable_lowimpact_fallback");
+
r300->options = options;
}
ctx = r300->radeon.glCtx;
+ r300->fallback = 0;
if (r300->options.hw_tcl_enabled)
ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
#define R300_MAX_AOS_ARRAYS 16
-#define R300_FALLBACK_NONE 0
-#define R300_FALLBACK_TCL 1
-#define R300_FALLBACK_RAST 2
-
/* r300_swtcl.c
*/
struct r300_swtcl_info {
GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
GLvector4f *temp_attrib[_TNL_ATTRIB_MAX];
- GLboolean disable_lowimpact_fallback;
-
struct r300_options {
uint32_t conformance_mode:1;
uint32_t hw_tcl_enabled:1;
struct r300_swtcl_info swtcl;
GLboolean vap_flush_needed;
+ uint32_t fallback;
+
DECLARE_RENDERINPUTS(render_inputs_bitset);
};
* no bugs...
*/
+#include "r300_render.h"
+
#include "main/glheader.h"
#include "main/state.h"
#include "main/imports.h"
#include "r300_tex.h"
#include "r300_emit.h"
#include "r300_fragprog_common.h"
+#include "r300_swtcl.h"
/**
* \brief Convert a OpenGL primitive type into a R300 primitive type.
COMMIT_BATCH();
}
-static GLboolean r300RunRender(GLcontext * ctx,
+static void r300RunRender(GLcontext * ctx,
struct tnl_pipeline_stage *stage)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
r300EmitCacheFlush(rmesa);
radeonReleaseArrays(ctx, ~0);
-
- return GL_FALSE;
}
-#define FALLBACK_IF(expr) \
- do { \
- if (expr) { \
- if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
- WARN_ONCE("Software fallback:%s\n", \
- #expr); \
- return R300_FALLBACK_RAST; \
- } \
- } while(0)
-
-static int r300Fallback(GLcontext * ctx)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- const unsigned back = ctx->Stencil._BackFace;
- FALLBACK_IF(r300->radeon.Fallback);
-
- struct r300_fragment_program *fp = (struct r300_fragment_program *) ctx->FragmentProgram._Current;
- if (fp && !fp->translated) {
- r300TranslateFragmentShader(ctx, ctx->FragmentProgram._Current);
- FALLBACK_IF(fp->error);
+static const char *getFallbackString(uint32_t bit)
+{
+ switch (bit) {
+ case R300_FALLBACK_VERTEX_PROGRAM :
+ return "vertex program";
+ case R300_FALLBACK_LINE_SMOOTH:
+ return "smooth lines";
+ case R300_FALLBACK_POINT_SMOOTH:
+ return "smooth points";
+ case R300_FALLBACK_POLYGON_SMOOTH:
+ return "smooth polygons";
+ case R300_FALLBACK_LINE_STIPPLE:
+ return "line stipple";
+ case R300_FALLBACK_POLYGON_STIPPLE:
+ return "polygon stipple";
+ case R300_FALLBACK_STENCIL_TWOSIDE:
+ return "two-sided stencil";
+ case R300_FALLBACK_RENDER_MODE:
+ return "render mode != GL_RENDER";
+ case R300_FALLBACK_FRAGMENT_PROGRAM:
+ return "fragment program";
+ case R300_FALLBACK_INVALID_BUFFERS:
+ return "invalid buffers";
+ default:
+ return "unknown";
}
+}
- FALLBACK_IF(ctx->RenderMode != GL_RENDER);
-
- FALLBACK_IF(ctx->Stencil.Enabled && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[back]
- || ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[back]
- || ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[back]));
-
- if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
- FALLBACK_IF(ctx->Point.PointSprite);
-
- if (!r300->disable_lowimpact_fallback) {
- FALLBACK_IF(ctx->Polygon.StippleFlag);
- FALLBACK_IF(ctx->Multisample._Enabled);
- FALLBACK_IF(ctx->Line.StippleFlag);
- FALLBACK_IF(ctx->Line.SmoothFlag);
- FALLBACK_IF(ctx->Point.SmoothFlag);
+void r300SwitchFallback(GLcontext *ctx, uint32_t bit, GLboolean mode)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ uint32_t old_fallback = rmesa->fallback;
+ static uint32_t fallback_warn = 0;
+
+ if (mode) {
+ if ((fallback_warn & bit) == 0) {
+ _mesa_fprintf(stderr, "WARNING! Falling back to software for %s\n", getFallbackString(bit));
+ fallback_warn |= bit;
+ }
+ rmesa->fallback |= bit;
+ /* update only if we change from no raster fallbacks to some raster fallbacks */
+ if (((old_fallback & R300_RASTER_FALLBACK_MASK) == 0) &&
+ ((bit & R300_RASTER_FALLBACK_MASK) > 0)) {
+
+ radeon_firevertices(&rmesa->radeon);
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ _swsetup_Wakeup( ctx );
+ }
+ } else {
+ rmesa->fallback &= ~bit;
+ /* update only if we have disabled all raster fallbacks */
+ if ((old_fallback & R300_RASTER_FALLBACK_MASK) == bit) {
+ _swrast_flush( ctx );
+
+ tnl->Driver.Render.Start = r300RenderStart;
+ tnl->Driver.Render.Finish = r300RenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = r300ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+ tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+ tnl->Driver.Render.Interp = _tnl_interp;
+
+ _tnl_invalidate_vertex_state( ctx, ~0 );
+ _tnl_invalidate_vertices( ctx, ~0 );
+ }
}
-
- return R300_FALLBACK_NONE;
+
}
static GLboolean r300RunNonTCLRender(GLcontext * ctx,
if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
- if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
+ if (rmesa->fallback & R300_RASTER_FALLBACK_MASK)
return GL_TRUE;
if (rmesa->options.hw_tcl_enabled == GL_FALSE)
return GL_TRUE;
- if (!r300ValidateBuffers(ctx))
- return GL_TRUE;
+ r300RunRender(ctx, stage);
- return r300RunRender(ctx, stage);
+ return GL_FALSE;
}
static GLboolean r300RunTCLRender(GLcontext * ctx,
struct tnl_pipeline_stage *stage)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct r300_vertex_program *vp;
if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
if (rmesa->options.hw_tcl_enabled == GL_FALSE)
return GL_TRUE;
- if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
- rmesa->options.hw_tcl_enabled = GL_FALSE;
- return GL_TRUE;
- }
-
- if (!r300ValidateBuffers(ctx))
- return GL_TRUE;
-
+ /* Call it here so we can fallback early */
r300UpdateShaders(rmesa);
- vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
- if (vp->native == GL_FALSE) {
- rmesa->options.hw_tcl_enabled = GL_FALSE;
+ r300SwitchFallback(ctx, R300_FALLBACK_INVALID_BUFFERS, !r300ValidateBuffers(ctx));
+
+ if (rmesa->fallback)
return GL_TRUE;
- }
- return r300RunRender(ctx, stage);
+ r300RunRender(ctx, stage);
+
+ return GL_FALSE;
}
const struct tnl_pipeline_stage _r300_render_stage = {
--- /dev/null
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * 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 THE COPYRIGHT OWNER(S) 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.
+ *
+ */
+
+#ifndef __R300_RENDER_H__
+#define __R300_RENDER_H__
+
+#include "main/mtypes.h"
+
+#define R300_FALLBACK_VERTEX_PROGRAM (1 << 0)
+#define R300_TCL_FALLBACK_MASK 0x0000ffff
+
+#define R300_FALLBACK_LINE_SMOOTH (1 << 16)
+#define R300_FALLBACK_POINT_SMOOTH (1 << 17)
+#define R300_FALLBACK_POLYGON_SMOOTH (1 << 18)
+#define R300_FALLBACK_LINE_STIPPLE (1 << 19)
+#define R300_FALLBACK_POLYGON_STIPPLE (1 << 20)
+#define R300_FALLBACK_STENCIL_TWOSIDE (1 << 21)
+#define R300_FALLBACK_RENDER_MODE (1 << 22)
+#define R300_FALLBACK_FRAGMENT_PROGRAM (1 << 23)
+#define R300_FALLBACK_INVALID_BUFFERS (1 << 31)
+#define R300_RASTER_FALLBACK_MASK 0xffff0000
+
+extern void r300SwitchFallback(GLcontext *ctx, uint32_t bit, GLboolean mode);
+
+#endif
#include "r300_fragprog_common.h"
#include "r300_fragprog.h"
#include "r500_fragprog.h"
+#include "r300_render.h"
#include "drirenderbuffer.h"
}
}
+static void r300CatchStencilFallback(GLcontext *ctx)
+{
+ const unsigned back = ctx->Stencil._BackFace;
+
+ if (ctx->Stencil._Enabled && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[back]
+ || ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[back]
+ || ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[back])) {
+ r300SwitchFallback(ctx, R300_FALLBACK_STENCIL_TWOSIDE, GL_TRUE);
+ } else {
+ r300SwitchFallback(ctx, R300_FALLBACK_STENCIL_TWOSIDE, GL_FALSE);
+ }
+}
+
static void r300SetStencilState(GLcontext * ctx, GLboolean state)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
GLboolean hw_stencil = GL_FALSE;
+
+ r300CatchStencilFallback(ctx);
+
if (ctx->DrawBuffer) {
struct radeon_renderbuffer *rrbStencil
= radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
r300->hw.zs.cmd[R300_ZS_CNTL_0] &=
~R300_STENCIL_ENABLE;
}
- } else {
-#if R200_MERGED
- FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state);
-#endif
}
}
GLenum func, GLint ref, GLuint mask)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- GLuint refmask =
- ((ctx->Stencil.Ref[0] & 0xff) << R300_STENCILREF_SHIFT)
- | ((ctx->Stencil.ValueMask[0] & 0xff) << R300_STENCILMASK_SHIFT);
- const unsigned back = ctx->Stencil._BackFace;
+ GLuint refmask;
GLuint flag;
+ const unsigned back = ctx->Stencil._BackFace;
+
+ r300CatchStencilFallback(ctx);
+
+ refmask = ((ctx->Stencil.Ref[0] & 0xff) << R300_STENCILREF_SHIFT)
+ | ((ctx->Stencil.ValueMask[0] & 0xff) << R300_STENCILMASK_SHIFT);
R300_STATECHANGE(rmesa, zs);
rmesa->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_STENCIL_FRONT_BACK;
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ r300CatchStencilFallback(ctx);
+
R300_STATECHANGE(rmesa, zs);
rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &=
~(R300_STENCILREF_MASK <<
r300ContextPtr rmesa = R300_CONTEXT(ctx);
const unsigned back = ctx->Stencil._BackFace;
+ r300CatchStencilFallback(ctx);
+
R300_STATECHANGE(rmesa, zs);
/* It is easier to mask what's left.. */
rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &=
case GL_CLIP_PLANE5:
r300SetClipPlaneState(ctx, cap, state);
break;
+ case GL_CULL_FACE:
+ r300UpdateCulling(ctx);
+ break;
case GL_DEPTH_TEST:
r300SetDepthState(ctx);
break;
- case GL_STENCIL_TEST:
- r300SetStencilState(ctx, state);
+ case GL_LINE_SMOOTH:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_LINE_SMOOTH, ctx->Line.SmoothFlag);
break;
- case GL_CULL_FACE:
- r300UpdateCulling(ctx);
+ case GL_LINE_STIPPLE:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_LINE_STIPPLE, ctx->Line.StippleFlag);
+ break;
+ case GL_POINT_SMOOTH:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_POINT_SMOOTH, ctx->Point.SmoothFlag);
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag);
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
break;
case GL_POLYGON_OFFSET_POINT:
case GL_POLYGON_OFFSET_LINE:
rmesa->radeon.state.scissor.enabled = state;
radeonUpdateScissor( ctx );
break;
+ case GL_STENCIL_TEST:
+ r300SetStencilState(ctx, state);
+ break;
default:
break;
}
{
GLcontext *ctx;
struct r300_vertex_program *vp;
+ struct r300_fragment_program *fp;
int i;
ctx = rmesa->radeon.glCtx;
+ fp = (struct r300_fragment_program *) ctx->FragmentProgram._Current;
if (rmesa->radeon.NewGLState && rmesa->options.hw_tcl_enabled) {
rmesa->radeon.NewGLState = 0;
}
r300SelectVertexShader(rmesa);
- vp = (struct r300_vertex_program *)
- CURRENT_VERTEX_SHADER(ctx);
- /*if (vp->translated == GL_FALSE)
- r300TranslateVertexShader(vp); */
- if (vp->translated == GL_FALSE) {
- fprintf(stderr, "Failing back to sw-tcl\n");
- rmesa->options.hw_tcl_enabled = 0;
- r300ResetHwState(rmesa);
-
- r300UpdateStateParameters(ctx, _NEW_PROGRAM |
- _NEW_PROGRAM_CONSTANTS);
- return;
- }
+ vp = (struct r300_vertex_program *) CURRENT_VERTEX_SHADER(ctx);
+ r300SwitchFallback(ctx, R300_FALLBACK_VERTEX_PROGRAM, !vp->native);
+ }
+
+ if (fp) {
+ if (!fp->translated)
+ r300TranslateFragmentShader(ctx, ctx->FragmentProgram._Current);
+
+ r300SwitchFallback(ctx, R300_FALLBACK_FRAGMENT_PROGRAM, fp->error);
}
+
r300UpdateStateParameters(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
}
static void r300RenderMode(GLcontext * ctx, GLenum mode)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- (void)rmesa;
- (void)mode;
+ r300SwitchFallback(ctx, R300_FALLBACK_RENDER_MODE, ctx->RenderMode != GL_RENDER);
}
/**
};
static void r300RasterPrimitive( GLcontext *ctx, GLuint prim );
-static void r300RenderPrimitive( GLcontext *ctx, GLenum prim );
/***********************************************************************
* Emit primitives as inline vertices *
}
-static void r300RenderStart(GLcontext *ctx)
+void r300RenderStart(GLcontext *ctx)
{
r300ContextPtr rmesa = R300_CONTEXT( ctx );
}
}
-static void r300RenderFinish(GLcontext *ctx)
+void r300RenderFinish(GLcontext *ctx)
{
}
}
}
-static void r300RenderPrimitive(GLcontext *ctx, GLenum prim)
+void r300RenderPrimitive(GLcontext *ctx, GLenum prim)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
r300RasterPrimitive( ctx, reduced_prim[prim] );
}
-static void r300ResetLineStipple(GLcontext *ctx)
+void r300ResetLineStipple(GLcontext *ctx)
{
}
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_need_projected_coords( ctx, GL_FALSE );
- r300ChooseRenderState(ctx);
}
void r300DestroySwtcl(GLcontext *ctx)
extern void r300InitSwtcl( GLcontext *ctx );
extern void r300DestroySwtcl( GLcontext *ctx );
+extern void r300RenderStart(GLcontext *ctx);
+extern void r300RenderFinish(GLcontext *ctx);
+extern void r300RenderPrimitive(GLcontext *ctx, GLenum prim);
+extern void r300ResetLineStipple(GLcontext *ctx);
+
extern void r300_swtcl_flush(GLcontext *ctx, uint32_t current_offset);
+
#endif