📄 radeon_lighting.c
字号:
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.5 2002/09/16 18:05:20 eich Exp $ *//* * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. * * 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 * on 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 * VA LINUX SYSTEMS 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. * * Authors: * Gareth Hughes <gareth@valinux.com> * Keith Whitwell <keith@tungstengraphics.com> */#include "glheader.h"#include "imports.h"#include "api_arrayelt.h"/* #include "mmath.h" */#include "enums.h"#include "colormac.h"#include "radeon_context.h"#include "radeon_ioctl.h"#include "radeon_state.h"#include "radeon_tcl.h"#include "radeon_tex.h"#include "radeon_vtxfmt.h"/* ============================================================= * Materials *//* Update on colormaterial, material emmissive/ambient, * lightmodel.globalambient */void update_global_ambient( GLcontext *ctx ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); float *fcmd = (float *)RADEON_DB_STATE( glt ); /* Need to do more if both emmissive & ambient are PREMULT: */ if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] & ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) { COPY_3V( &fcmd[GLT_RED], ctx->Light.Material[0].Emission); ACC_SCALE_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient, ctx->Light.Material[0].Ambient); } else { COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); } RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);}/* Update on change to * - light[p].colors * - light[p].enabled * - material, * - colormaterial enabled * - colormaterial bitmask */void update_light_colors( GLcontext *ctx, GLuint p ){ struct gl_light *l = &ctx->Light.Light[p];/* fprintf(stderr, "%s\n", __FUNCTION__); */ if (l->Enabled) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); float *fcmd = (float *)RADEON_DB_STATE( lit[p] ); GLuint bitmask = ctx->Light.ColorMaterialBitmask; struct gl_material *mat = &ctx->Light.Material[0]; COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); if (!ctx->Light.ColorMaterialEnabled) bitmask = 0; if ((bitmask & FRONT_AMBIENT_BIT) == 0) SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient ); if ((bitmask & FRONT_DIFFUSE_BIT) == 0) SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse ); if ((bitmask & FRONT_SPECULAR_BIT) == 0) SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->Specular ); RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); }}/* Also fallback for asym colormaterial mode in twoside lighting... */void check_twoside_fallback( GLcontext *ctx ){ GLboolean fallback = GL_FALSE; if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { if (memcmp( &ctx->Light.Material[0], &ctx->Light.Material[1], sizeof(struct gl_material)) != 0) fallback = GL_TRUE; else if (ctx->Light.ColorMaterialEnabled && (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) != ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1)) fallback = GL_TRUE; } TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );}void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ){ if (ctx->Light.ColorMaterialEnabled) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLuint light_model_ctl = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; GLuint mask = ctx->Light.ColorMaterialBitmask; /* Default to PREMULT: */ light_model_ctl &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | (3 << RADEON_AMBIENT_SOURCE_SHIFT) | (3 << RADEON_DIFFUSE_SOURCE_SHIFT) | (3 << RADEON_SPECULAR_SOURCE_SHIFT)); if (mask & FRONT_EMISSION_BIT) { light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << RADEON_EMISSIVE_SOURCE_SHIFT); } if (mask & FRONT_AMBIENT_BIT) { light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << RADEON_AMBIENT_SOURCE_SHIFT); } if (mask & FRONT_DIFFUSE_BIT) { light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << RADEON_DIFFUSE_SOURCE_SHIFT); } if (mask & FRONT_SPECULAR_BIT) { light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << RADEON_SPECULAR_SOURCE_SHIFT); } if (light_model_ctl != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) { GLuint p; RADEON_STATECHANGE( rmesa, tcl ); rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl; for (p = 0 ; p < MAX_LIGHTS; p++) update_light_colors( ctx, p ); update_global_ambient( ctx ); } } check_twoside_fallback( ctx );}void radeonUpdateMaterial( GLcontext *ctx ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl ); GLuint p; GLuint mask = ~0; if (ctx->Light.ColorMaterialEnabled) mask &= ~ctx->Light.ColorMaterialBitmask; if (RADEON_DEBUG & DEBUG_STATE) fprintf(stderr, "%s\n", __FUNCTION__); if (mask & FRONT_EMISSION_BIT) { fcmd[MTL_EMMISSIVE_RED] = ctx->Light.Material[0].Emission[0]; fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1]; fcmd[MTL_EMMISSIVE_BLUE] = ctx->Light.Material[0].Emission[2]; fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3]; } if (mask & FRONT_AMBIENT_BIT) { fcmd[MTL_AMBIENT_RED] = ctx->Light.Material[0].Ambient[0]; fcmd[MTL_AMBIENT_GREEN] = ctx->Light.Material[0].Ambient[1]; fcmd[MTL_AMBIENT_BLUE] = ctx->Light.Material[0].Ambient[2]; fcmd[MTL_AMBIENT_ALPHA] = ctx->Light.Material[0].Ambient[3]; } if (mask & FRONT_DIFFUSE_BIT) { fcmd[MTL_DIFFUSE_RED] = ctx->Light.Material[0].Diffuse[0]; fcmd[MTL_DIFFUSE_GREEN] = ctx->Light.Material[0].Diffuse[1]; fcmd[MTL_DIFFUSE_BLUE] = ctx->Light.Material[0].Diffuse[2]; fcmd[MTL_DIFFUSE_ALPHA] = ctx->Light.Material[0].Diffuse[3]; } if (mask & FRONT_SPECULAR_BIT) { fcmd[MTL_SPECULAR_RED] = ctx->Light.Material[0].Specular[0]; fcmd[MTL_SPECULAR_GREEN] = ctx->Light.Material[0].Specular[1]; fcmd[MTL_SPECULAR_BLUE] = ctx->Light.Material[0].Specular[2]; fcmd[MTL_SPECULAR_ALPHA] = ctx->Light.Material[0].Specular[3]; } if (mask & FRONT_SHININESS_BIT) { fcmd[MTL_SHININESS] = ctx->Light.Material[0].Shininess; } if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) { for (p = 0 ; p < MAX_LIGHTS; p++) update_light_colors( ctx, p ); check_twoside_fallback( ctx ); update_global_ambient( ctx ); } else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE)) fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);}/* _NEW_LIGHT * _NEW_MODELVIEW * _MESA_NEW_NEED_EYE_COORDS * * Uses derived state from mesa: * _VP_inf_norm * _h_inf_norm * _Position * _NormDirection * _ModelViewInvScale * _NeedEyeCoords * _EyeZDir * * which are calculated in light.c and are correct for the current * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW * and _MESA_NEW_NEED_EYE_COORDS. */void radeonUpdateLighting( GLcontext *ctx ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); /* Have to check these, or have an automatic shortcircuit mechanism * to remove noop statechanges. (Or just do a better job on the * front end). */ { GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; if (ctx->_NeedEyeCoords) tmp &= ~RADEON_LIGHT_IN_MODELSPACE; else tmp |= RADEON_LIGHT_IN_MODELSPACE; /* Leave this test disabled: (unexplained q3 lockup) (even with new packets) */ if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) { RADEON_STATECHANGE( rmesa, tcl ); rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp; } } { GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye ); fcmd[EYE_X] = ctx->_EyeZDir[0]; fcmd[EYE_Y] = ctx->_EyeZDir[1]; fcmd[EYE_Z] = - ctx->_EyeZDir[2]; fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); }/* RADEON_STATECHANGE( rmesa, glt ); */ if (ctx->Light.Enabled) { GLint p; for (p = 0 ; p < MAX_LIGHTS; p++) { if (ctx->Light.Light[p].Enabled) { struct gl_light *l = &ctx->Light.Light[p]; GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] ); if (l->EyePosition[3] == 0.0) { COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); fcmd[LIT_POSITION_W] = 0; fcmd[LIT_DIRECTION_W] = 0; } else { COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0]; fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1]; fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2]; fcmd[LIT_DIRECTION_W] = 0; } RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); } } }}void radeonLightfv( GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLint p = light - GL_LIGHT0; struct gl_light *l = &ctx->Light.Light[p]; GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; switch (pname) { case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: update_light_colors( ctx, p ); break; case GL_SPOT_DIRECTION: /* picked up in update_light */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -