From c944fb5ffe7cf16154d6395001f43a6c965cab1f Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 18 Mar 2010 14:18:55 +0100 Subject: [PATCH] dri/nouveau: Implement texcoord generation. --- src/mesa/drivers/dri/nouveau/nouveau_gldefs.h | 19 ++++++++++ src/mesa/drivers/dri/nouveau/nouveau_state.c | 17 ++++++++- src/mesa/drivers/dri/nouveau/nouveau_util.h | 18 ++++++++++ src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c | 4 ++- src/mesa/drivers/dri/nouveau/nv10_context.c | 2 +- src/mesa/drivers/dri/nouveau/nv10_state_tex.c | 33 +++++++++++++++++ src/mesa/drivers/dri/nouveau/nv10_state_tnl.c | 6 ++-- src/mesa/drivers/dri/nouveau/nv20_context.c | 14 ++++---- src/mesa/drivers/dri/nouveau/nv20_driver.h | 3 ++ src/mesa/drivers/dri/nouveau/nv20_state_tex.c | 35 +++++++++++++++++++ src/mesa/drivers/dri/nouveau/nv20_state_tnl.c | 6 ++-- 11 files changed, 143 insertions(+), 14 deletions(-) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h b/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h index 00007a9a351..fbeed3baeab 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h @@ -260,4 +260,23 @@ nvgl_filter_mode(unsigned filter) } } +static inline unsigned +nvgl_texgen_mode(unsigned mode) +{ + switch (mode) { + case GL_EYE_LINEAR: + return 0x2400; + case GL_OBJECT_LINEAR: + return 0x2401; + case GL_SPHERE_MAP: + return 0x2402; + case GL_NORMAL_MAP: + return 0x8511; + case GL_REFLECTION_MAP: + return 0x8512; + default: + assert(0); + } +} + #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c index 603a46ed242..ef2cc787de7 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -234,6 +234,13 @@ nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state) context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); break; + case GL_TEXTURE_GEN_S: + case GL_TEXTURE_GEN_T: + case GL_TEXTURE_GEN_R: + case GL_TEXTURE_GEN_Q: + context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + context_dirty(ctx, MODELVIEW); + break; } } @@ -368,7 +375,15 @@ static void nouveau_tex_gen(GLcontext *ctx, GLenum coord, GLenum pname, const GLfloat *params) { - context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + switch (pname) { + case GL_TEXTURE_GEN_MODE: + context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + context_dirty(ctx, MODELVIEW); + break; + default: + context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + break; + } } static void diff --git a/src/mesa/drivers/dri/nouveau/nouveau_util.h b/src/mesa/drivers/dri/nouveau/nouveau_util.h index d6007aba2b9..584cb80ef62 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_util.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_util.h @@ -191,4 +191,22 @@ is_texture_source(int s) return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31); } +static inline struct gl_texgen * +get_texgen_coord(struct gl_texture_unit *u, int i) +{ + return ((struct gl_texgen *[]) + { &u->GenS, &u->GenT, &u->GenR, &u->GenQ }) [i]; +} + +static inline float * +get_texgen_coeff(struct gl_texgen *c) +{ + if (c->Mode == GL_OBJECT_LINEAR) + return c->ObjectPlane; + else if (c->Mode == GL_EYE_LINEAR) + return c->EyePlane; + else + return NULL; +} + #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c index f20a7df45ec..0c29eec8eec 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c @@ -224,9 +224,11 @@ vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays) if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD) vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG); - if (ctx->Light.Enabled) { + if (ctx->Light.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)) vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL); + if (ctx->Light.Enabled) { vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT)); vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE)); vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR)); diff --git a/src/mesa/drivers/dri/nouveau/nv10_context.c b/src/mesa/drivers/dri/nouveau/nv10_context.c index d008063d3c4..b6d10361de0 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_context.c +++ b/src/mesa/drivers/dri/nouveau/nv10_context.c @@ -212,7 +212,7 @@ nv10_hwctx_init(GLcontext *ctx) OUT_RING(chan, 0); BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1); OUT_RING(chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_S(0), 8); + BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_MODE_S(0), 8); for (i = 0; i < 8; i++) OUT_RING(chan, 0); diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c index 92148722af7..35f41d7295b 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c @@ -32,11 +32,44 @@ #include "nouveau_util.h" #include "nv10_driver.h" +#define TX_GEN_MODE(i, j) (NV10TCL_TX_GEN_MODE_S(i) + 4 * (j)) +#define TX_GEN_COEFF(i, j) (NV10TCL_TX_GEN_COEFF_S_A(i) + 16 * (j)) #define TX_MATRIX(i) (NV10TCL_TX0_MATRIX(0) + 64 * (i)) void nv10_emit_tex_gen(GLcontext *ctx, int emit) { + const int i = emit - NOUVEAU_STATE_TEX_GEN0; + struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *celsius = context_eng3d(ctx); + struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; + int j; + + for (j = 0; j < 4; j++) { + if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { + struct gl_texgen *coord = get_texgen_coord(unit, j); + float *k = get_texgen_coeff(coord); + + if (k) { + BEGIN_RING(chan, celsius, + TX_GEN_COEFF(i, j), 4); + OUT_RINGf(chan, k[0]); + OUT_RINGf(chan, k[1]); + OUT_RINGf(chan, k[2]); + OUT_RINGf(chan, k[3]); + } + + BEGIN_RING(chan, celsius, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, nvgl_texgen_mode(coord->Mode)); + + } else { + BEGIN_RING(chan, celsius, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, 0); + } + } + + context_dirty_i(ctx, TEX_MAT, i); } void diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c index 406e24c455d..2624c9bf305 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c @@ -474,12 +474,14 @@ nv10_emit_modelview(GLcontext *ctx, int emit) if (nctx->fallback != HWTNL) return; - if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) { + if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { BEGIN_RING(chan, celsius, NV10TCL_MODELVIEW0_MATRIX(0), 16); OUT_RINGm(chan, m->m); } - if (ctx->Light.Enabled) { + if (ctx->Light.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { int i, j; BEGIN_RING(chan, celsius, diff --git a/src/mesa/drivers/dri/nouveau/nv20_context.c b/src/mesa/drivers/dri/nouveau/nv20_context.c index 99df34716fc..789dcaa6b46 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_context.c +++ b/src/mesa/drivers/dri/nouveau/nv20_context.c @@ -297,9 +297,9 @@ nv20_hwctx_init(GLcontext *ctx) BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_ENABLE, 1); OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_S(0), - 4 * NV20TCL_TX_GEN_S__SIZE); - for (i=0; i < 4 * NV20TCL_TX_GEN_S__SIZE; i++) + BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_MODE_S(0), + 4 * NV20TCL_TX_GEN_MODE_S__SIZE); + for (i=0; i < 4 * NV20TCL_TX_GEN_MODE_S__SIZE; i++) OUT_RING(chan, 0); BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3); @@ -497,10 +497,10 @@ const struct nouveau_driver nv20_driver = { nv20_emit_tex_env, nv20_emit_tex_env, nv20_emit_tex_env, - nv10_emit_tex_gen, - nv10_emit_tex_gen, - nv10_emit_tex_gen, - nv10_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_gen, nv20_emit_tex_mat, nv20_emit_tex_mat, nv20_emit_tex_mat, diff --git a/src/mesa/drivers/dri/nouveau/nv20_driver.h b/src/mesa/drivers/dri/nouveau/nv20_driver.h index 05770b2d6cf..8adecef2c4e 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_driver.h +++ b/src/mesa/drivers/dri/nouveau/nv20_driver.h @@ -67,6 +67,9 @@ void nv20_emit_frag(GLcontext *ctx, int emit); /* nv20_state_tex.c */ +void +nv20_emit_tex_gen(GLcontext *ctx, int emit); + void nv20_emit_tex_mat(GLcontext *ctx, int emit); diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c index d7ac4c57bce..bb8a79c2c92 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c @@ -32,8 +32,43 @@ #include "nouveau_util.h" #include "nv20_driver.h" +#define TX_GEN_MODE(i, j) (NV20TCL_TX_GEN_MODE_S(i) + 4 * (j)) +#define TX_GEN_COEFF(i, j) (NV20TCL_TX_GEN_COEFF_S_A(i) + 16 * (j)) #define TX_MATRIX(i) (NV20TCL_TX0_MATRIX(0) + 64 * (i)) +void +nv20_emit_tex_gen(GLcontext *ctx, int emit) +{ + const int i = emit - NOUVEAU_STATE_TEX_GEN0; + struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *kelvin = context_eng3d(ctx); + struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; + int j; + + for (j = 0; j < 4; j++) { + if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { + struct gl_texgen *coord = get_texgen_coord(unit, j); + float *k = get_texgen_coeff(coord); + + if (k) { + BEGIN_RING(chan, kelvin, TX_GEN_COEFF(i, j), 4); + OUT_RINGf(chan, k[0]); + OUT_RINGf(chan, k[1]); + OUT_RINGf(chan, k[2]); + OUT_RINGf(chan, k[3]); + } + + BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, nvgl_texgen_mode(coord->Mode)); + + } else { + BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, 0); + } + } +} + void nv20_emit_tex_mat(GLcontext *ctx, int emit) { diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c index 43f8c723122..df22adf2729 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c @@ -359,12 +359,14 @@ nv20_emit_modelview(GLcontext *ctx, int emit) if (nctx->fallback != HWTNL) return; - if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) { + if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { BEGIN_RING(chan, kelvin, NV20TCL_MODELVIEW0_MATRIX(0), 16); OUT_RINGm(chan, m->m); } - if (ctx->Light.Enabled) { + if (ctx->Light.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { int i, j; BEGIN_RING(chan, kelvin, -- 2.30.2