summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i965/brw_fallback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_fallback.c')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fallback.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fallback.c b/src/mesa/drivers/dri/i965/brw_fallback.c
new file mode 100644
index 0000000000..6bb3dd2217
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_fallback.c
@@ -0,0 +1,468 @@
+/**************************************************************************
+ *
+ * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN 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.
+ *
+ **************************************************************************/
+
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/swrast.h"
+#include "tnl/tnl.h"
+#include "context.h"
+#include "brw_context.h"
+#include "brw_exec.h"
+#include "brw_save.h"
+#include "brw_fallback.h"
+
+#include "glheader.h"
+#include "enums.h"
+#include "glapi.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "dispatch.h"
+
+
+typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
+
+
+/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */
+static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
+}
+
+static attr_func vert_attrfunc[4] = {
+ VertexAttrib1fvNV,
+ VertexAttrib2fvNV,
+ VertexAttrib3fvNV,
+ VertexAttrib4fvNV
+};
+
+#if 0
+static void VertexAttrib1fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib1fvARB(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib2fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib2fvARB(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib3fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib3fvARB(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib4fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib4fvARB(ctx->Exec, (target, v));
+}
+
+
+static attr_func vert_attrfunc_arb[4] = {
+ VertexAttrib1fvARB,
+ VertexAttrib2fvARB,
+ VertexAttrib3fvARB,
+ VertexAttrib4fvARB
+};
+#endif
+
+
+
+
+
+
+static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v )
+{
+ switch (target) {
+ case BRW_ATTRIB_MAT_FRONT_SHININESS:
+ CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SHININESS, v ));
+ break;
+ case BRW_ATTRIB_MAT_BACK_SHININESS:
+ CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SHININESS, v ));
+ break;
+ }
+}
+
+
+static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v )
+{
+ switch (target) {
+ case BRW_ATTRIB_MAT_FRONT_INDEXES:
+ CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_COLOR_INDEXES, v ));
+ break;
+ case BRW_ATTRIB_MAT_BACK_INDEXES:
+ CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_COLOR_INDEXES, v ));
+ break;
+ }
+}
+
+
+static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v )
+{
+ switch (target) {
+ case BRW_ATTRIB_MAT_FRONT_EMISSION:
+ CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_EMISSION, v ));
+ break;
+ case BRW_ATTRIB_MAT_BACK_EMISSION:
+ CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_EMISSION, v ));
+ break;
+ case BRW_ATTRIB_MAT_FRONT_AMBIENT:
+ CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_AMBIENT, v ));
+ break;
+ case BRW_ATTRIB_MAT_BACK_AMBIENT:
+ CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_AMBIENT, v ));
+ break;
+ case BRW_ATTRIB_MAT_FRONT_DIFFUSE:
+ CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_DIFFUSE, v ));
+ break;
+ case BRW_ATTRIB_MAT_BACK_DIFFUSE:
+ CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_DIFFUSE, v ));
+ break;
+ case BRW_ATTRIB_MAT_FRONT_SPECULAR:
+ CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SPECULAR, v ));
+ break;
+ case BRW_ATTRIB_MAT_BACK_SPECULAR:
+ CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SPECULAR, v ));
+ break;
+ }
+}
+
+
+static attr_func mat_attrfunc[4] = {
+ mat_attr1fv,
+ NULL,
+ mat_attr3fv,
+ mat_attr4fv
+};
+
+
+static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ (void) target;
+ CALL_Indexf(ctx->Exec, (v[0]));
+}
+
+static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ (void) target;
+ CALL_EdgeFlag(ctx->Exec, ((GLboolean)(v[0] == 1.0)));
+}
+
+struct loopback_attr {
+ GLint target;
+ GLint sz;
+ attr_func func;
+};
+
+/* Don't emit ends and begins on wrapped primitives. Don't replay
+ * wrapped vertices. If we get here, it's probably because the the
+ * precalculated wrapping is wrong.
+ */
+static void loopback_prim( GLcontext *ctx,
+ const GLfloat *buffer,
+ const struct brw_draw_prim *prim,
+ GLuint wrap_count,
+ GLuint vertex_size,
+ const struct loopback_attr *la, GLuint nr )
+{
+ GLint start = prim->start;
+ GLint end = start + prim->count;
+ const GLfloat *data;
+ GLint j;
+ GLuint k;
+
+ if (0)
+ _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
+ _mesa_lookup_enum_by_nr(prim->mode),
+ prim->begin ? "begin" : "..",
+ prim->end ? "end" : "..",
+ start,
+ end);
+
+ if (prim->begin) {
+ CALL_Begin(GET_DISPATCH(), ( prim->mode ));
+ }
+ else {
+ assert(start == 0);
+ start += wrap_count;
+ }
+
+ data = buffer + start * vertex_size;
+
+ for (j = start ; j < end ; j++) {
+ const GLfloat *tmp = data + la[0].sz;
+
+ for (k = 1 ; k < nr ; k++) {
+ la[k].func( ctx, la[k].target, tmp );
+ tmp += la[k].sz;
+ }
+
+ /* Fire the vertex
+ */
+ la[0].func( ctx, VERT_ATTRIB_POS, data );
+ data = tmp;
+ }
+
+ if (prim->end) {
+ CALL_End(GET_DISPATCH(), ());
+ }
+}
+
+/* Primitives generated by DrawArrays/DrawElements/Rectf may be
+ * caught here. If there is no primitive in progress, execute them
+ * normally, otherwise need to track and discard the generated
+ * primitives.
+ */
+static void loopback_weak_prim( GLcontext *ctx,
+ const struct brw_draw_prim *prim )
+{
+ /* Use the prim_weak flag to ensure that if this primitive
+ * wraps, we don't mistake future vertex_lists for part of the
+ * surrounding primitive.
+ *
+ * While this flag is set, we are simply disposing of data
+ * generated by an operation now known to be a noop.
+ */
+ if (prim->begin)
+ ctx->Driver.CurrentExecPrimitive |= BRW_SAVE_PRIM_WEAK;
+ if (prim->end)
+ ctx->Driver.CurrentExecPrimitive &= ~BRW_SAVE_PRIM_WEAK;
+}
+
+
+void brw_loopback_vertex_list( GLcontext *ctx,
+ const GLfloat *buffer,
+ const GLubyte *attrsz,
+ const struct brw_draw_prim *prim,
+ GLuint prim_count,
+ GLuint wrap_count,
+ GLuint vertex_size)
+{
+ struct loopback_attr la[BRW_ATTRIB_MAX];
+ GLuint i, nr = 0;
+
+ for (i = 0 ; i <= BRW_ATTRIB_TEX7 ; i++) {
+ if (attrsz[i]) {
+ la[nr].target = i;
+ la[nr].sz = attrsz[i];
+ la[nr].func = vert_attrfunc[attrsz[i]-1];
+ nr++;
+ }
+ }
+
+ for (i = BRW_ATTRIB_MAT_FRONT_AMBIENT ;
+ i <= BRW_ATTRIB_MAT_BACK_INDEXES ;
+ i++) {
+ if (attrsz[i]) {
+ la[nr].target = i;
+ la[nr].sz = attrsz[i];
+ la[nr].func = mat_attrfunc[attrsz[i]-1];
+ nr++;
+ }
+ }
+
+ if (attrsz[BRW_ATTRIB_EDGEFLAG]) {
+ la[nr].target = BRW_ATTRIB_EDGEFLAG;
+ la[nr].sz = attrsz[BRW_ATTRIB_EDGEFLAG];
+ la[nr].func = edgeflag_attr1fv;
+ nr++;
+ }
+
+ if (attrsz[BRW_ATTRIB_INDEX]) {
+ la[nr].target = BRW_ATTRIB_INDEX;
+ la[nr].sz = attrsz[BRW_ATTRIB_INDEX];
+ la[nr].func = index_attr1fv;
+ nr++;
+ }
+
+ /* XXX ARB vertex attribs */
+
+ for (i = 0 ; i < prim_count ; i++) {
+ if ((prim[i].mode & BRW_SAVE_PRIM_WEAK) &&
+ (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
+ {
+ loopback_weak_prim( ctx, &prim[i] );
+ }
+ else
+ {
+ loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
+ }
+ }
+}
+
+
+
+
+
+
+
+
+static GLboolean do_check_fallback(struct brw_context *brw)
+{
+ GLcontext *ctx = &brw->intel.ctx;
+ GLuint i;
+
+ /* BRW_NEW_METAOPS
+ */
+ if (brw->metaops.active)
+ return GL_FALSE;
+
+ if (brw->intel.no_rast)
+ return GL_TRUE;
+
+ /* _NEW_BUFFERS
+ */
+ if (ctx->DrawBuffer->_ColorDrawBufferMask[0] != BUFFER_BIT_FRONT_LEFT &&
+ ctx->DrawBuffer->_ColorDrawBufferMask[0] != BUFFER_BIT_BACK_LEFT)
+ return GL_TRUE;
+
+ /* _NEW_RENDERMODE
+ *
+ * XXX: need to save/restore RenderMode in metaops state, or
+ * somehow move to a new attribs pointer:
+ */
+ if (ctx->RenderMode != GL_RENDER)
+ return GL_TRUE;
+
+ /* _NEW_TEXTURE:
+ */
+ for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
+ struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
+ if (texUnit->_ReallyEnabled) {
+ struct intel_texture_object *intelObj = intel_texture_object(texUnit->_Current);
+ struct gl_texture_image *texImage = intelObj->base.Image[0][intelObj->firstLevel];
+ if (texImage->Border)
+ return GL_TRUE;
+ }
+ }
+
+ /* _NEW_STENCIL
+ */
+ if (brw->attribs.Stencil->Enabled &&
+ !brw->intel.hw_stencil) {
+ return GL_TRUE;
+ }
+
+
+ return GL_FALSE;
+}
+
+static void check_fallback(struct brw_context *brw)
+{
+ brw->intel.Fallback = do_check_fallback(brw);
+}
+
+const struct brw_tracked_state brw_check_fallback = {
+ .dirty = {
+ .mesa = _NEW_BUFFERS | _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL,
+ .brw = BRW_NEW_METAOPS,
+ .cache = 0
+ },
+ .update = check_fallback
+};
+
+
+
+
+/* If there is a fallback, fallback to software rasterization and
+ * transformation together. There is never a requirement to have
+ * software t&l but hardware rasterization.
+ *
+ * Further, all fallbacks are based on GL state, not on eg. primitive
+ * or vertex data.
+ */
+
+static void do_fallback( struct brw_context *brw,
+ GLboolean fallback )
+{
+ GLcontext *ctx = &brw->intel.ctx;
+
+ /* flush:
+ */
+ ctx->Driver.Flush( ctx );
+
+ if (fallback) {
+ _swsetup_Wakeup( ctx );
+ _tnl_wakeup_exec( ctx );
+
+ /* Need this because tnl_wakeup_exec does too much:
+ */
+ brw_save_wakeup(ctx);
+ brw_save_fallback(ctx, GL_TRUE);
+ }
+ else {
+ /* Flush vertices and copy-to-current:
+ */
+ FLUSH_CURRENT(ctx, 0);
+
+ _swrast_flush( ctx );
+
+ brw_exec_wakeup(ctx);
+
+ /* Need this because tnl_wakeup_exec does too much:
+ */
+ brw_save_wakeup(ctx);
+ brw_save_fallback(ctx, GL_FALSE);
+ }
+}
+
+
+void brw_fallback( GLcontext *ctx )
+{
+ struct brw_context *brw = brw_context(ctx);
+ do_fallback(brw, 1);
+}
+
+
+void brw_unfallback( GLcontext *ctx )
+{
+ struct brw_context *brw = brw_context(ctx);
+ do_fallback(brw, 0);
+}
+
+/* Not used:
+ */
+void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode )
+{
+}
+
+
+