diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/Mesa/src/mesa/drivers/dri/r300 | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/r300')
48 files changed, 21536 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/Makefile b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/Makefile new file mode 100644 index 000000000..57c7fc7aa --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/Makefile @@ -0,0 +1,83 @@ +# src/mesa/drivers/dri/r300/Makefile + + +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = r300_dri.so +DEFINES += -DCOMPILE_R300 -DGLX_DIRECT_RENDERING -DR200_MERGED=0 + +MINIGLX_SOURCES = server/radeon_dri.c + +COMMON_SOURCES = \ + ../../common/driverfuncs.c \ + ../common/mm.c \ + ../common/utils.c \ + ../common/texmem.c \ + ../common/vblank.c \ + ../common/xmlconfig.c \ + ../common/dri_util.c + +DRIVER_SOURCES = \ + radeon_screen.c \ + radeon_context.c \ + radeon_ioctl.c \ + radeon_lock.c \ + radeon_span.c \ + radeon_state.c \ + \ + r300_context.c \ + r300_ioctl.c \ + r300_cmdbuf.c \ + r300_state.c \ + r300_render.c \ + r300_texmem.c \ + r300_tex.c \ + r300_texstate.c \ + r300_texprog.c \ + r300_vertexprog.c \ + r300_fragprog.c \ + r300_shader.c \ + r300_maos.c +# \ +# r200_context.c \ +# r200_ioctl.c \ +# r200_state.c \ +# r200_state_init.c \ +# r200_cmdbuf.c \ +# r200_pixel.c \ +# r200_tex.c \ +# r200_texmem.c \ +# r200_texstate.c \ +# r200_swtcl.c \ +# r200_maos.c \ +# r200_sanity.c \ +# r200_vtxfmt.c \ +# r200_vtxfmt_c.c \ +# r200_vtxfmt_sse.c \ +# r200_vtxfmt_x86.c + + +C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES) + +X86_SOURCES = +#r200_vtxtmp_x86.S + +SYMLINKS = \ + server/radeon_dri.c \ + server/radeon_dri.h \ + server/radeon.h \ + server/radeon_macros.h \ + server/radeon_reg.h + +##### TARGETS ##### + + +include ../Makefile.template + +$(SYMLINKS): + mkdir -p server + for i in $(SYMLINKS) ; do rm -f $$i && test -f ../radeon/$$i && ln -s ../../radeon/$$i $$i ; done + +symlinks: $(SYMLINKS) + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/pixel_shader.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/pixel_shader.h new file mode 100644 index 000000000..0d04859f9 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/pixel_shader.h @@ -0,0 +1,103 @@ +#ifndef __PIXEL_SHADER_H__ +#define __PIXEL_SHADER_H__ + +#include "r300_reg.h" + + +/* INSTR 0 */ + +#define PFS_OP_MAD 0 +#define PFS_OP_DP3 1 +#define PFS_OP_DP4 2 +#define PFS_OP_MIN 4 +#define PFS_OP_MAX 5 +#define PFS_OP_CMP 8 +#define PFS_OP_FRC 9 +#define PFS_OP_OUTC_REPL_ALPHA 10 + +/* "or" these with arg0 value to negate or take absolute value of an argument */ +#define PFS_ARG_NEG (1<<5) +#define PFS_ARG_ABS (1<<6) + +#define MAKE_PFS_INSTR0(op, arg0, arg1, arg2, flags) \ + ( ((op)<<23) \ + | ((arg0)<<R300_FPI0_ARG0C_SHIFT) \ + | ((arg1)<<R300_FPI0_ARG1C_SHIFT) \ + | ((arg2)<<R300_FPI0_ARG2C_SHIFT) \ + | (flags) \ + ) + +#define PFS_FLAG_X 1 +#define PFS_FLAG_Y 2 +#define PFS_FLAG_XY 3 +#define PFS_FLAG_Z 4 +#define PFS_FLAG_XZ 5 +#define PFS_FLAG_YZ 6 +#define PFS_FLAG_ALL 7 +#define PFS_FLAG_NONE 0 + +#define EASY_PFS_INSTR0(op, arg0, arg1, arg2) \ + MAKE_PFS_INSTR0(PFS_OP_##op, \ + R300_FPI0_ARGC_##arg0, \ + R300_FPI0_ARGC_##arg1, \ + R300_FPI0_ARGC_##arg2, \ + 0) + +/* INSTR 1 */ + +#define PFS_FLAG_CONST (1<<5) + +#define MAKE_PFS_INSTR1(dstc, src0, src1, src2, reg, output) \ + ((src0) | ((src1) << R300_FPI1_SRC1C_SHIFT) \ + | ((src2)<<R300_FPI1_SRC2C_SHIFT) \ + | ((dstc) << R300_FPI1_DSTC_SHIFT) \ + | ((reg) << 23) | ((output)<<26)) + +#define EASY_PFS_INSTR1(dstc, src0, src1, src2, reg, output) \ + MAKE_PFS_INSTR1(dstc, src0, src1, src2, PFS_FLAG_##reg, PFS_FLAG_##output) + +/* INSTR 2 */ + +/* you can "or" PFS_ARG_NEG with these values to negate them */ + +#define MAKE_PFS_INSTR2(op, arg0, arg1, arg2, flags) \ + (((op) << 23) | \ + ((arg0)<<R300_FPI2_ARG0A_SHIFT) | \ + ((arg1)<<R300_FPI2_ARG1A_SHIFT) | \ + ((arg2)<<R300_FPI2_ARG2A_SHIFT) | \ + (flags)) + +#define EASY_PFS_INSTR2(op, arg0, arg1, arg2) \ + MAKE_PFS_INSTR2(R300_FPI2_OUTA_##op, \ + R300_FPI2_ARGA_##arg0, \ + R300_FPI2_ARGA_##arg1, \ + R300_FPI2_ARGA_##arg2, \ + 0) + + +/* INSTR 3 */ + +#define PFS_FLAG_NONE 0 +#define PFS_FLAG_REG 1 +#define PFS_FLAG_OUTPUT 2 +#define PFS_FLAG_BOTH 3 + +#define MAKE_PFS_INSTR3(dstc, src0, src1, src2, flags) \ + ((src0) | ((src1) << R300_FPI1_SRC1C_SHIFT) \ + | ((src2)<<R300_FPI1_SRC2C_SHIFT) \ + | ((dstc) << R300_FPI1_DSTC_SHIFT) \ + | ((flags) << 23)) + +#define EASY_PFS_INSTR3(dstc, src0, src1, src2, flag) \ + MAKE_PFS_INSTR3(dstc, src0, src1, src2, PFS_FLAG_##flag) + + /* What are 0's ORed with flags ? They are register numbers that + just happen to be 0 */ +#define PFS_NOP { \ + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO), \ + EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL), \ + EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO), \ + EASY_PFS_INSTR3(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT) \ + } + +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_context.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_context.h new file mode 100644 index 000000000..2c1eda33f --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_context.h @@ -0,0 +1,822 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_context.h,v 1.2 2002/12/16 16:18:54 dawes Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __R200_CONTEXT_H__ +#define __R200_CONTEXT_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "tnl/t_vertex.h" +#include "drm.h" +#include "radeon_drm.h" +#include "dri_util.h" +#include "texmem.h" + +#include "macros.h" +#include "mtypes.h" +#include "colormac.h" +#include "r200_reg.h" +#include "radeon_context.h" + +#define ENABLE_HW_3D_TEXTURE 1 /* XXX this is temporary! */ + +struct r200_context; +typedef struct r200_context r200ContextRec; +typedef struct r200_context *r200ContextPtr; + +#include "mm.h" + +/* The blit width for texture uploads + */ +#define BLIT_WIDTH_BYTES 1024 + +/* Use the templated vertex format: + */ +#define COLOR_IS_RGBA +#define TAG(x) r200##x +#include "tnl_dd/t_dd_vertex.h" +#undef TAG + +typedef void (*r200_tri_func) (r200ContextPtr, + r200Vertex *, r200Vertex *, r200Vertex *); + +typedef void (*r200_line_func) (r200ContextPtr, r200Vertex *, r200Vertex *); + +typedef void (*r200_point_func) (r200ContextPtr, r200Vertex *); + +struct r200_depthbuffer_state { + GLfloat scale; +}; + +struct r200_stencilbuffer_state { + GLboolean hwBuffer; + GLuint clear; /* rb3d_stencilrefmask value */ +}; + +struct r200_stipple_state { + GLuint mask[32]; +}; + +typedef struct r200_tex_obj r200TexObj, *r200TexObjPtr; + +/* Texture object in locally shared texture space. + */ +struct r200_tex_obj { + driTextureObject base; + + GLuint bufAddr; /* Offset to start of locally + shared texture block */ + + GLuint dirty_state; /* Flags (1 per texunit) for + whether or not this texobj + has dirty hardware state + (pp_*) that needs to be + brought into the + texunit. */ + + drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS]; + /* Six, for the cube faces */ + + GLuint pp_txfilter; /* hardware register values */ + GLuint pp_txformat; + GLuint pp_txformat_x; + GLuint pp_txoffset; /* Image location in texmem. + All cube faces follow. */ + GLuint pp_txsize; /* npot only */ + GLuint pp_txpitch; /* npot only */ + GLuint pp_border_color; + GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */ + + GLboolean border_fallback; +}; + +struct r200_texture_env_state { + r200TexObjPtr texobj; + GLenum format; + GLenum envMode; +}; + +#define R200_MAX_TEXTURE_UNITS 6 + +struct r200_texture_state { + struct r200_texture_env_state unit[R200_MAX_TEXTURE_UNITS]; +}; + +struct r200_state_atom { + struct r200_state_atom *next, *prev; + const char *name; /* for debug */ + int cmd_size; /* size in bytes */ + GLuint idx; + int *cmd; /* one or more cmd's */ + int *lastcmd; /* one or more cmd's */ + int *savedcmd; /* one or more cmd's */ + GLboolean dirty; + GLboolean(*check) (GLcontext *, int); /* is this state active? */ +}; + +/* Trying to keep these relatively short as the variables are becoming + * extravagently long. Drop the driver name prefix off the front of + * everything - I think we know which driver we're in by now, and keep the + * prefix to 3 letters unless absolutely impossible. + */ + +#define CTX_CMD_0 0 +#define CTX_PP_MISC 1 +#define CTX_PP_FOG_COLOR 2 +#define CTX_RE_SOLID_COLOR 3 +#define CTX_RB3D_BLENDCNTL 4 +#define CTX_RB3D_DEPTHOFFSET 5 +#define CTX_RB3D_DEPTHPITCH 6 +#define CTX_RB3D_ZSTENCILCNTL 7 +#define CTX_CMD_1 8 +#define CTX_PP_CNTL 9 +#define CTX_RB3D_CNTL 10 +#define CTX_RB3D_COLOROFFSET 11 +#define CTX_CMD_2 12 /* why */ +#define CTX_RB3D_COLORPITCH 13 /* why */ +#define CTX_STATE_SIZE_OLDDRM 14 +#define CTX_CMD_3 14 +#define CTX_RB3D_BLENDCOLOR 15 +#define CTX_RB3D_ABLENDCNTL 16 +#define CTX_RB3D_CBLENDCNTL 17 +#define CTX_STATE_SIZE_NEWDRM 18 + +#define SET_CMD_0 0 +#define SET_SE_CNTL 1 +#define SET_RE_CNTL 2 /* replace se_coord_fmt */ +#define SET_STATE_SIZE 3 + +#define VTE_CMD_0 0 +#define VTE_SE_VTE_CNTL 1 +#define VTE_STATE_SIZE 2 + +#define LIN_CMD_0 0 +#define LIN_RE_LINE_PATTERN 1 +#define LIN_RE_LINE_STATE 2 +#define LIN_CMD_1 3 +#define LIN_SE_LINE_WIDTH 4 +#define LIN_STATE_SIZE 5 + +#define MSK_CMD_0 0 +#define MSK_RB3D_STENCILREFMASK 1 +#define MSK_RB3D_ROPCNTL 2 +#define MSK_RB3D_PLANEMASK 3 +#define MSK_STATE_SIZE 4 + +#define VPT_CMD_0 0 +#define VPT_SE_VPORT_XSCALE 1 +#define VPT_SE_VPORT_XOFFSET 2 +#define VPT_SE_VPORT_YSCALE 3 +#define VPT_SE_VPORT_YOFFSET 4 +#define VPT_SE_VPORT_ZSCALE 5 +#define VPT_SE_VPORT_ZOFFSET 6 +#define VPT_STATE_SIZE 7 + +#define ZBS_CMD_0 0 +#define ZBS_SE_ZBIAS_FACTOR 1 +#define ZBS_SE_ZBIAS_CONSTANT 2 +#define ZBS_STATE_SIZE 3 + +#define MSC_CMD_0 0 +#define MSC_RE_MISC 1 +#define MSC_STATE_SIZE 2 + +#define TAM_CMD_0 0 +#define TAM_DEBUG3 1 +#define TAM_STATE_SIZE 2 + +#define TEX_CMD_0 0 +#define TEX_PP_TXFILTER 1 /*2c00 */ +#define TEX_PP_TXFORMAT 2 /*2c04 */ +#define TEX_PP_TXFORMAT_X 3 /*2c08 */ +#define TEX_PP_TXSIZE 4 /*2c0c */ +#define TEX_PP_TXPITCH 5 /*2c10 */ +#define TEX_PP_BORDER_COLOR 6 /*2c14 */ +#define TEX_CMD_1 7 +#define TEX_PP_TXOFFSET 8 /*2d00 */ +#define TEX_STATE_SIZE 9 + +#define CUBE_CMD_0 0 /* 1 register follows */ +#define CUBE_PP_CUBIC_FACES 1 /* 0x2c18 */ +#define CUBE_CMD_1 2 /* 5 registers follow */ +#define CUBE_PP_CUBIC_OFFSET_F1 3 /* 0x2d04 */ +#define CUBE_PP_CUBIC_OFFSET_F2 4 /* 0x2d08 */ +#define CUBE_PP_CUBIC_OFFSET_F3 5 /* 0x2d0c */ +#define CUBE_PP_CUBIC_OFFSET_F4 6 /* 0x2d10 */ +#define CUBE_PP_CUBIC_OFFSET_F5 7 /* 0x2d14 */ +#define CUBE_STATE_SIZE 8 + +#define PIX_CMD_0 0 +#define PIX_PP_TXCBLEND 1 +#define PIX_PP_TXCBLEND2 2 +#define PIX_PP_TXABLEND 3 +#define PIX_PP_TXABLEND2 4 +#define PIX_STATE_SIZE 5 + +#define TF_CMD_0 0 +#define TF_TFACTOR_0 1 +#define TF_TFACTOR_1 2 +#define TF_TFACTOR_2 3 +#define TF_TFACTOR_3 4 +#define TF_TFACTOR_4 5 +#define TF_TFACTOR_5 6 +#define TF_STATE_SIZE 7 + +#define TCL_CMD_0 0 +#define TCL_LIGHT_MODEL_CTL_0 1 +#define TCL_LIGHT_MODEL_CTL_1 2 +#define TCL_PER_LIGHT_CTL_0 3 +#define TCL_PER_LIGHT_CTL_1 4 +#define TCL_PER_LIGHT_CTL_2 5 +#define TCL_PER_LIGHT_CTL_3 6 +#define TCL_CMD_1 7 +#define TCL_UCP_VERT_BLEND_CTL 8 +#define TCL_STATE_SIZE 9 + +#define MSL_CMD_0 0 +#define MSL_MATRIX_SELECT_0 1 +#define MSL_MATRIX_SELECT_1 2 +#define MSL_MATRIX_SELECT_2 3 +#define MSL_MATRIX_SELECT_3 4 +#define MSL_MATRIX_SELECT_4 5 +#define MSL_STATE_SIZE 6 + +#define TCG_CMD_0 0 +#define TCG_TEX_PROC_CTL_2 1 +#define TCG_TEX_PROC_CTL_3 2 +#define TCG_TEX_PROC_CTL_0 3 +#define TCG_TEX_PROC_CTL_1 4 +#define TCG_TEX_CYL_WRAP_CTL 5 +#define TCG_STATE_SIZE 6 + +#define MTL_CMD_0 0 +#define MTL_EMMISSIVE_RED 1 +#define MTL_EMMISSIVE_GREEN 2 +#define MTL_EMMISSIVE_BLUE 3 +#define MTL_EMMISSIVE_ALPHA 4 +#define MTL_AMBIENT_RED 5 +#define MTL_AMBIENT_GREEN 6 +#define MTL_AMBIENT_BLUE 7 +#define MTL_AMBIENT_ALPHA 8 +#define MTL_DIFFUSE_RED 9 +#define MTL_DIFFUSE_GREEN 10 +#define MTL_DIFFUSE_BLUE 11 +#define MTL_DIFFUSE_ALPHA 12 +#define MTL_SPECULAR_RED 13 +#define MTL_SPECULAR_GREEN 14 +#define MTL_SPECULAR_BLUE 15 +#define MTL_SPECULAR_ALPHA 16 +#define MTL_CMD_1 17 +#define MTL_SHININESS 18 +#define MTL_STATE_SIZE 19 + +#define VAP_CMD_0 0 +#define VAP_SE_VAP_CNTL 1 +#define VAP_STATE_SIZE 2 + +/* Replaces a lot of packet info from radeon + */ +#define VTX_CMD_0 0 +#define VTX_VTXFMT_0 1 +#define VTX_VTXFMT_1 2 +#define VTX_TCL_OUTPUT_VTXFMT_0 3 +#define VTX_TCL_OUTPUT_VTXFMT_1 4 +#define VTX_CMD_1 5 +#define VTX_TCL_OUTPUT_COMPSEL 6 +#define VTX_CMD_2 7 +#define VTX_STATE_CNTL 8 +#define VTX_STATE_SIZE 9 + +#define VTX_COLOR(v,n) (((v)>>(R200_VTX_COLOR_0_SHIFT+(n)*2))&\ + R200_VTX_COLOR_MASK) + +/** + * Given the \c R200_SE_VTX_FMT_1 for the current vertex state, determine + * how many components are in texture coordinate \c n. + */ +#define VTX_TEXn_COUNT(v,n) (((v) >> (3 * n)) & 0x07) + +#define MAT_CMD_0 0 +#define MAT_ELT_0 1 +#define MAT_STATE_SIZE 17 + +#define GRD_CMD_0 0 +#define GRD_VERT_GUARD_CLIP_ADJ 1 +#define GRD_VERT_GUARD_DISCARD_ADJ 2 +#define GRD_HORZ_GUARD_CLIP_ADJ 3 +#define GRD_HORZ_GUARD_DISCARD_ADJ 4 +#define GRD_STATE_SIZE 5 + +/* position changes frequently when lighting in modelpos - separate + * out to new state item? + */ +#define LIT_CMD_0 0 +#define LIT_AMBIENT_RED 1 +#define LIT_AMBIENT_GREEN 2 +#define LIT_AMBIENT_BLUE 3 +#define LIT_AMBIENT_ALPHA 4 +#define LIT_DIFFUSE_RED 5 +#define LIT_DIFFUSE_GREEN 6 +#define LIT_DIFFUSE_BLUE 7 +#define LIT_DIFFUSE_ALPHA 8 +#define LIT_SPECULAR_RED 9 +#define LIT_SPECULAR_GREEN 10 +#define LIT_SPECULAR_BLUE 11 +#define LIT_SPECULAR_ALPHA 12 +#define LIT_POSITION_X 13 +#define LIT_POSITION_Y 14 +#define LIT_POSITION_Z 15 +#define LIT_POSITION_W 16 +#define LIT_DIRECTION_X 17 +#define LIT_DIRECTION_Y 18 +#define LIT_DIRECTION_Z 19 +#define LIT_DIRECTION_W 20 +#define LIT_ATTEN_QUADRATIC 21 +#define LIT_ATTEN_LINEAR 22 +#define LIT_ATTEN_CONST 23 +#define LIT_ATTEN_XXX 24 +#define LIT_CMD_1 25 +#define LIT_SPOT_DCD 26 +#define LIT_SPOT_DCM 27 +#define LIT_SPOT_EXPONENT 28 +#define LIT_SPOT_CUTOFF 29 +#define LIT_SPECULAR_THRESH 30 +#define LIT_RANGE_CUTOFF 31 /* ? */ +#define LIT_ATTEN_CONST_INV 32 +#define LIT_STATE_SIZE 33 + +/* Fog + */ +#define FOG_CMD_0 0 +#define FOG_R 1 +#define FOG_C 2 +#define FOG_D 3 +#define FOG_PAD 4 +#define FOG_STATE_SIZE 5 + +/* UCP + */ +#define UCP_CMD_0 0 +#define UCP_X 1 +#define UCP_Y 2 +#define UCP_Z 3 +#define UCP_W 4 +#define UCP_STATE_SIZE 5 + +/* GLT - Global ambient + */ +#define GLT_CMD_0 0 +#define GLT_RED 1 +#define GLT_GREEN 2 +#define GLT_BLUE 3 +#define GLT_ALPHA 4 +#define GLT_STATE_SIZE 5 + +/* EYE + */ +#define EYE_CMD_0 0 +#define EYE_X 1 +#define EYE_Y 2 +#define EYE_Z 3 +#define EYE_RESCALE_FACTOR 4 +#define EYE_STATE_SIZE 5 + +/* CST - constant state + */ +#define CST_CMD_0 0 +#define CST_PP_CNTL_X 1 +#define CST_CMD_1 2 +#define CST_RB3D_DEPTHXY_OFFSET 3 +#define CST_CMD_2 4 +#define CST_RE_AUX_SCISSOR_CNTL 5 +#define CST_CMD_3 6 +#define CST_RE_SCISSOR_TL_0 7 +#define CST_RE_SCISSOR_BR_0 8 +#define CST_CMD_4 9 +#define CST_SE_VAP_CNTL_STATUS 10 +#define CST_CMD_5 11 +#define CST_RE_POINTSIZE 12 +#define CST_CMD_6 13 +#define CST_SE_TCL_INPUT_VTX_0 14 +#define CST_SE_TCL_INPUT_VTX_1 15 +#define CST_SE_TCL_INPUT_VTX_2 16 +#define CST_SE_TCL_INPUT_VTX_3 17 +#define CST_STATE_SIZE 18 + +struct r200_hw_state { + /* Head of the linked list of state atoms. */ + struct r200_state_atom atomlist; + + /* Hardware state, stored as cmdbuf commands: + * -- Need to doublebuffer for + * - reviving state after loss of context + * - eliding noop statechange loops? (except line stipple count) + */ + struct r200_state_atom ctx; + struct r200_state_atom set; + struct r200_state_atom vte; + struct r200_state_atom lin; + struct r200_state_atom msk; + struct r200_state_atom vpt; + struct r200_state_atom vap; + struct r200_state_atom vtx; + struct r200_state_atom tcl; + struct r200_state_atom msl; + struct r200_state_atom tcg; + struct r200_state_atom msc; + struct r200_state_atom cst; + struct r200_state_atom tam; + struct r200_state_atom tf; + struct r200_state_atom tex[6]; + struct r200_state_atom cube[6]; + struct r200_state_atom zbs; + struct r200_state_atom mtl[2]; + struct r200_state_atom mat[9]; + struct r200_state_atom lit[8]; /* includes vec, scl commands */ + struct r200_state_atom ucp[6]; + struct r200_state_atom pix[6]; /* pixshader stages */ + struct r200_state_atom eye; /* eye pos */ + struct r200_state_atom grd; /* guard band clipping */ + struct r200_state_atom fog; + struct r200_state_atom glt; + + int max_state_size; /* Number of bytes necessary for a full state emit. */ + GLboolean is_dirty, all_dirty; +}; + +struct r200_colorbuffer_state { + int roundEnable; +}; + +struct r200_state { + /* Derived state for internal purposes: + */ + struct r200_colorbuffer_state color; + struct r200_depthbuffer_state depth; + struct r200_stencilbuffer_state stencil; + struct r200_stipple_state stipple; + struct r200_texture_state texture; +}; + +/* Need refcounting on dma buffers: + */ +struct r200_dma_buffer { + int refcount; /* the number of retained regions in buf */ + drmBufPtr buf; +}; + +#define GET_START(rvb) (rmesa->radeon.radeonScreen->gart_buffer_offset + \ + (rvb)->address - rmesa->dma.buf0_address + \ + (rvb)->start) + +/* A retained region, eg vertices for indexed vertices. + */ +struct r200_dma_region { + struct r200_dma_buffer *buf; + char *address; /* == buf->address */ + int start, end, ptr; /* offsets from start of buf */ + int aos_start; + int aos_stride; + int aos_size; +}; + +struct r200_dma { + /* Active dma region. Allocations for vertices and retained + * regions come from here. Also used for emitting random vertices, + * these may be flushed by calling flush_current(); + */ + struct r200_dma_region current; + + void (*flush) (r200ContextPtr); + + char *buf0_address; /* start of buf[0], for index calcs */ + GLuint nr_released_bufs; /* flush after so many buffers released */ +}; + +#define R200_CMD_BUF_SZ (8*1024) + +struct r200_store { + GLuint statenr; + GLuint primnr; + char cmd_buf[R200_CMD_BUF_SZ]; + int cmd_used; + int elts_start; +}; + +/* r200_tcl.c + */ +struct r200_tcl_info { + GLuint vertex_format; + GLint last_offset; + GLuint hw_primitive; + + struct r200_dma_region *aos_components[8]; + GLuint nr_aos_components; + + GLuint *Elts; + + struct r200_dma_region indexed_verts; + struct r200_dma_region obj; + struct r200_dma_region rgba; + struct r200_dma_region spec; + struct r200_dma_region fog; + struct r200_dma_region tex[R200_MAX_TEXTURE_UNITS]; + struct r200_dma_region norm; +}; + +/* r200_swtcl.c + */ +struct r200_swtcl_info { + GLuint RenderIndex; + + /** + * Size of a hardware vertex. This is calculated when \c ::vertex_attrs is + * installed in the Mesa state vector. + */ + GLuint vertex_size; + + /** + * Attributes instructing the Mesa TCL pipeline where / how to put vertex + * data in the hardware buffer. + */ + struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; + + /** + * Number of elements of \c ::vertex_attrs that are actually used. + */ + GLuint vertex_attr_count; + + /** + * Cached pointer to the buffer where Mesa will store vertex data. + */ + GLubyte *verts; + + /* Fallback rasterization functions + */ + r200_point_func draw_point; + r200_line_func draw_line; + r200_tri_func draw_tri; + + GLuint hw_primitive; + GLenum render_primitive; + GLuint numverts; + + /** + * Offset of the 4UB color data within a hardware (swtcl) vertex. + */ + GLuint coloroffset; + + /** + * Offset of the 3UB specular color data within a hardware (swtcl) vertex. + */ + GLuint specoffset; + + /** + * Should Mesa project vertex data or will the hardware do it? + */ + GLboolean needproj; + + struct r200_dma_region indexed_verts; +}; + +struct r200_ioctl { + GLuint vertex_offset; + GLuint vertex_size; +}; + +#define R200_MAX_PRIMS 64 + +/* Want to keep a cache of these around. Each is parameterized by + * only a single value which has only a small range. Only expect a + * few, so just rescan the list each time? + */ +struct dynfn { + struct dynfn *next, *prev; + int key[2]; + char *code; +}; + +struct dfn_lists { + struct dynfn Vertex2f; + struct dynfn Vertex2fv; + struct dynfn Vertex3f; + struct dynfn Vertex3fv; + struct dynfn Color4ub; + struct dynfn Color4ubv; + struct dynfn Color3ub; + struct dynfn Color3ubv; + struct dynfn Color4f; + struct dynfn Color4fv; + struct dynfn Color3f; + struct dynfn Color3fv; + struct dynfn SecondaryColor3ubEXT; + struct dynfn SecondaryColor3ubvEXT; + struct dynfn SecondaryColor3fEXT; + struct dynfn SecondaryColor3fvEXT; + struct dynfn Normal3f; + struct dynfn Normal3fv; + struct dynfn TexCoord3f; + struct dynfn TexCoord3fv; + struct dynfn TexCoord2f; + struct dynfn TexCoord2fv; + struct dynfn TexCoord1f; + struct dynfn TexCoord1fv; + struct dynfn MultiTexCoord3fARB; + struct dynfn MultiTexCoord3fvARB; + struct dynfn MultiTexCoord2fARB; + struct dynfn MultiTexCoord2fvARB; + struct dynfn MultiTexCoord1fARB; + struct dynfn MultiTexCoord1fvARB; +}; + +struct dfn_generators { + struct dynfn *(*Vertex2f) (GLcontext *, const int *); + struct dynfn *(*Vertex2fv) (GLcontext *, const int *); + struct dynfn *(*Vertex3f) (GLcontext *, const int *); + struct dynfn *(*Vertex3fv) (GLcontext *, const int *); + struct dynfn *(*Color4ub) (GLcontext *, const int *); + struct dynfn *(*Color4ubv) (GLcontext *, const int *); + struct dynfn *(*Color3ub) (GLcontext *, const int *); + struct dynfn *(*Color3ubv) (GLcontext *, const int *); + struct dynfn *(*Color4f) (GLcontext *, const int *); + struct dynfn *(*Color4fv) (GLcontext *, const int *); + struct dynfn *(*Color3f) (GLcontext *, const int *); + struct dynfn *(*Color3fv) (GLcontext *, const int *); + struct dynfn *(*SecondaryColor3ubEXT) (GLcontext *, const int *); + struct dynfn *(*SecondaryColor3ubvEXT) (GLcontext *, const int *); + struct dynfn *(*SecondaryColor3fEXT) (GLcontext *, const int *); + struct dynfn *(*SecondaryColor3fvEXT) (GLcontext *, const int *); + struct dynfn *(*Normal3f) (GLcontext *, const int *); + struct dynfn *(*Normal3fv) (GLcontext *, const int *); + struct dynfn *(*TexCoord3f) (GLcontext *, const int *); + struct dynfn *(*TexCoord3fv) (GLcontext *, const int *); + struct dynfn *(*TexCoord2f) (GLcontext *, const int *); + struct dynfn *(*TexCoord2fv) (GLcontext *, const int *); + struct dynfn *(*TexCoord1f) (GLcontext *, const int *); + struct dynfn *(*TexCoord1fv) (GLcontext *, const int *); + struct dynfn *(*MultiTexCoord3fARB) (GLcontext *, const int *); + struct dynfn *(*MultiTexCoord3fvARB) (GLcontext *, const int *); + struct dynfn *(*MultiTexCoord2fARB) (GLcontext *, const int *); + struct dynfn *(*MultiTexCoord2fvARB) (GLcontext *, const int *); + struct dynfn *(*MultiTexCoord1fARB) (GLcontext *, const int *); + struct dynfn *(*MultiTexCoord1fvARB) (GLcontext *, const int *); +}; + +struct r200_prim { + GLuint start; + GLuint end; + GLuint prim; +}; + + /* A maximum total of 29 elements per vertex: 3 floats for position, 3 + * floats for normal, 4 floats for color, 4 bytes for secondary color, + * 3 floats for each texture unit (18 floats total). + * + * we maybe need add. 4 to prevent segfault if someone specifies + * GL_TEXTURE6/GL_TEXTURE7 (esp. for the codegen-path) (FIXME: ) + * + * The position data is never actually stored here, so 3 elements could be + * trimmed out of the buffer. + */ + +#define R200_MAX_VERTEX_SIZE ((3*6)+11) + +struct r200_vbinfo { + GLint counter, initial_counter; + GLint *dmaptr; + void (*notify) (void); + GLint vertex_size; + + union { + float f; + int i; + r200_color_t color; + } vertex[R200_MAX_VERTEX_SIZE]; + + GLfloat *normalptr; + GLfloat *floatcolorptr; + r200_color_t *colorptr; + GLfloat *floatspecptr; + r200_color_t *specptr; + GLfloat *texcoordptr[8]; /* 6 (TMU) + 2 for r200_vtxfmt_c.c when GL_TEXTURE6/7 */ + + GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */ + GLuint primflags; + GLboolean enabled; /* *_NO_VTXFMT / *_NO_TCL env vars */ + GLboolean installed; + GLboolean fell_back; + GLboolean recheck; + GLint nrverts; + GLuint vtxfmt_0, vtxfmt_1; + + GLuint installed_vertex_format; + GLuint installed_color_3f_sz; + + struct r200_prim primlist[R200_MAX_PRIMS]; + int nrprims; + + struct dfn_lists dfn_cache; + struct dfn_generators codegen; + GLvertexformat vtxfmt; +}; + +/** + * R200 context structure. + */ +struct r200_context { + struct radeon_context radeon; /* parent class, must be first */ + + /* Driver and hardware state management + */ + struct r200_hw_state hw; + struct r200_state state; + + /* Texture object bookkeeping + */ + unsigned nr_heaps; + driTexHeap *texture_heaps[R200_NR_TEX_HEAPS]; + driTextureObject swapped; + int texture_depth; + float initialMaxAnisotropy; + + /* Rasterization and vertex state: + */ + GLuint NewGLState; + + /* Vertex buffers + */ + struct r200_ioctl ioctl; + struct r200_dma dma; + struct r200_store store; + GLboolean save_on_next_unlock; + + /* Clientdata textures; + */ + GLuint prefer_gart_client_texturing; + + /* TCL stuff + */ + GLmatrix TexGenMatrix[R200_MAX_TEXTURE_UNITS]; + GLboolean recheck_texgen[R200_MAX_TEXTURE_UNITS]; + GLboolean TexGenNeedNormals[R200_MAX_TEXTURE_UNITS]; + GLuint TexMatEnabled; + GLuint TexMatCompSel; + GLuint TexGenEnabled; + GLuint TexGenInputs; + GLuint TexGenCompSel; + GLmatrix tmpmat; + + /* r200_tcl.c + */ + struct r200_tcl_info tcl; + + /* r200_swtcl.c + */ + struct r200_swtcl_info swtcl; + + /* r200_vtxfmt.c + */ + struct r200_vbinfo vb; +}; + +#define R200_CONTEXT(ctx) ((r200ContextPtr)(ctx->DriverCtx)) + +extern void r200DestroyContext(__DRIcontextPrivate * driContextPriv); +extern GLboolean r200CreateContext(const __GLcontextModes * glVisual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate); + +#endif +#endif /* __R200_CONTEXT_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_ioctl.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_ioctl.h new file mode 100644 index 000000000..db7bd7697 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_ioctl.h @@ -0,0 +1,204 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __R200_IOCTL_H__ +#define __R200_IOCTL_H__ + +#include "simple_list.h" +#include "radeon_dri.h" +#include "radeon_lock.h" + +#include "xf86drm.h" +#include "drm.h" +#include "r200_context.h" +#include "radeon_drm.h" + +extern void r200EmitState(r200ContextPtr rmesa); +extern void r200EmitVertexAOS(r200ContextPtr rmesa, + GLuint vertex_size, GLuint offset); + +extern void r200EmitVbufPrim(r200ContextPtr rmesa, + GLuint primitive, GLuint vertex_nr); + +extern void r200FlushElts(r200ContextPtr rmesa); + +extern GLushort *r200AllocEltsOpenEnded(r200ContextPtr rmesa, + GLuint primitive, GLuint min_nr); + +extern void r200EmitAOS(r200ContextPtr rmesa, + struct r200_dma_region **regions, + GLuint n, GLuint offset); + +extern void r200EmitBlit(r200ContextPtr rmesa, + GLuint color_fmt, + GLuint src_pitch, + GLuint src_offset, + GLuint dst_pitch, + GLuint dst_offset, + GLint srcx, GLint srcy, + GLint dstx, GLint dsty, GLuint w, GLuint h); + +extern void r200EmitWait(r200ContextPtr rmesa, GLuint flags); + +extern void r200FlushCmdBuf(r200ContextPtr rmesa, const char *); +extern int r200FlushCmdBufLocked(r200ContextPtr rmesa, const char *caller); +extern void r200Flush(GLcontext * ctx); + +extern void r200RefillCurrentDmaRegion(r200ContextPtr rmesa); + +extern void r200AllocDmaRegion(r200ContextPtr rmesa, + struct r200_dma_region *region, + int bytes, int alignment); + +extern void r200AllocDmaRegionVerts(r200ContextPtr rmesa, + struct r200_dma_region *region, + int numverts, int vertsize, int alignment); + +extern void r200ReleaseDmaRegion(r200ContextPtr rmesa, + struct r200_dma_region *region, + const char *caller); + +extern void r200WaitForVBlank(r200ContextPtr rmesa); +extern void r200InitIoctlFuncs(struct dd_function_table *functions); + +extern void *r200AllocateMemoryMESA(__DRInativeDisplay * dpy, int scrn, + GLsizei size, GLfloat readfreq, + GLfloat writefreq, GLfloat priority); +extern void r200FreeMemoryMESA(__DRInativeDisplay * dpy, int scrn, + GLvoid * pointer); +extern GLuint r200GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn, + const GLvoid * pointer); + +extern GLboolean r200IsGartMemory(r200ContextPtr rmesa, const GLvoid * pointer, + GLint size); + +extern GLuint r200GartOffsetFromVirtual(r200ContextPtr rmesa, + const GLvoid * pointer); + +void r200SaveHwState(r200ContextPtr radeon); +void r200SetUpAtomList(r200ContextPtr rmesa); + +/* ================================================================ + * Helper macros: + */ + +/* Close off the last primitive, if it exists. + */ +#define R200_NEWPRIM( rmesa ) \ +do { \ + if ( rmesa->dma.flush ) \ + rmesa->dma.flush( rmesa ); \ +} while (0) + +/* Can accomodate several state changes and primitive changes without + * actually firing the buffer. + */ +#define R200_STATECHANGE( rmesa, ATOM ) \ +do { \ + R200_NEWPRIM( rmesa ); \ + rmesa->hw.ATOM.dirty = GL_TRUE; \ + rmesa->hw.is_dirty = GL_TRUE; \ +} while (0) + +#define R200_DB_STATE( ATOM ) \ + memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \ + rmesa->hw.ATOM.cmd_size * 4) + +static __inline int R200_DB_STATECHANGE(r200ContextPtr rmesa, + struct r200_state_atom *atom) +{ + if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size * 4)) { + int *tmp; + R200_NEWPRIM(rmesa); + atom->dirty = GL_TRUE; + rmesa->hw.is_dirty = GL_TRUE; + tmp = atom->cmd; + atom->cmd = atom->lastcmd; + atom->lastcmd = tmp; + return 1; + } else + return 0; +} + +/* Fire the buffered vertices no matter what. + */ +#define R200_FIREVERTICES( r200 ) \ +do { \ + if ( (r200)->store.cmd_used || (r200)->dma.flush ) { \ + radeonFlush( (r200)->radeon.glCtx ); \ + } \ +} while (0) + +/* Command lengths. Note that any time you ensure ELTS_BUFSZ or VBUF_BUFSZ + * are available, you will also be adding an rmesa->state.max_state_size because + * r200EmitState is called from within r200EmitVbufPrim and r200FlushElts. + */ +#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2)) * sizeof(int)) +#define VERT_AOS_BUFSZ (5 * sizeof(int)) +#define ELTS_BUFSZ(nr) (12 + nr * 2) +#define VBUF_BUFSZ (3 * sizeof(int)) + +/* Ensure that a minimum amount of space is available in the command buffer. + * This is used to ensure atomicity of state updates with the rendering requests + * that rely on them. + * + * An alternative would be to implement a "soft lock" such that when the buffer + * wraps at an inopportune time, we grab the lock, flush the current buffer, + * and hang on to the lock until the critical section is finished and we flush + * the buffer again and unlock. + */ +static __inline void r200EnsureCmdBufSpace(r200ContextPtr rmesa, int bytes) +{ + if (rmesa->store.cmd_used + bytes > R200_CMD_BUF_SZ) + r200FlushCmdBuf(rmesa, __FUNCTION__); + assert(bytes <= R200_CMD_BUF_SZ); +} + +/* Alloc space in the command buffer + */ +static __inline char *r200AllocCmdBuf(r200ContextPtr rmesa, + int bytes, const char *where) +{ + char *head; + + if (rmesa->store.cmd_used + bytes > R200_CMD_BUF_SZ) + r200FlushCmdBuf(rmesa, where); + + head = rmesa->store.cmd_buf + rmesa->store.cmd_used; + rmesa->store.cmd_used += bytes; + assert(rmesa->store.cmd_used <= R200_CMD_BUF_SZ); + return head; +} + +#endif /* __R200_IOCTL_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_reg.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_reg.h new file mode 100644 index 000000000..1336e961a --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_reg.h @@ -0,0 +1,1423 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_reg.h,v 1.2 2002/12/16 16:18:54 dawes Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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 _R200_REG_H_ +#define _R200_REG_H_ + +#define R200_PP_MISC 0x1c14 +#define R200_REF_ALPHA_MASK 0x000000ff +#define R200_ALPHA_TEST_FAIL (0 << 8) +#define R200_ALPHA_TEST_LESS (1 << 8) +#define R200_ALPHA_TEST_LEQUAL (2 << 8) +#define R200_ALPHA_TEST_EQUAL (3 << 8) +#define R200_ALPHA_TEST_GEQUAL (4 << 8) +#define R200_ALPHA_TEST_GREATER (5 << 8) +#define R200_ALPHA_TEST_NEQUAL (6 << 8) +#define R200_ALPHA_TEST_PASS (7 << 8) +#define R200_ALPHA_TEST_OP_MASK (7 << 8) +#define R200_CHROMA_FUNC_FAIL (0 << 16) +#define R200_CHROMA_FUNC_PASS (1 << 16) +#define R200_CHROMA_FUNC_NEQUAL (2 << 16) +#define R200_CHROMA_FUNC_EQUAL (3 << 16) +#define R200_CHROMA_KEY_NEAREST (0 << 18) +#define R200_CHROMA_KEY_ZERO (1 << 18) +#define R200_RIGHT_HAND_CUBE_D3D (0 << 24) +#define R200_RIGHT_HAND_CUBE_OGL (1 << 24) +#define R200_PP_FOG_COLOR 0x1c18 +#define R200_FOG_COLOR_MASK 0x00ffffff +#define R200_FOG_VERTEX (0 << 24) +#define R200_FOG_TABLE (1 << 24) +#define R200_FOG_USE_DEPTH (0 << 25) +#define R200_FOG_USE_W (1 << 25) +#define R200_FOG_USE_DIFFUSE_ALPHA (2 << 25) +#define R200_FOG_USE_SPEC_ALPHA (3 << 25) +#define R200_FOG_USE_VTX_FOG (4 << 25) +#define R200_FOG_USE_MASK (7 << 25) +#define R200_RE_SOLID_COLOR 0x1c1c +#define R200_RB3D_BLENDCNTL 0x1c20 +#define R200_COMB_FCN_MASK (7 << 12) +#define R200_COMB_FCN_ADD_CLAMP (0 << 12) +#define R200_COMB_FCN_ADD_NOCLAMP (1 << 12) +#define R200_COMB_FCN_SUB_CLAMP (2 << 12) +#define R200_COMB_FCN_SUB_NOCLAMP (3 << 12) +#define R200_COMB_FCN_MIN (4 << 12) +#define R200_COMB_FCN_MAX (5 << 12) +#define R200_COMB_FCN_RSUB_CLAMP (6 << 12) +#define R200_COMB_FCN_RSUB_NOCLAMP (7 << 12) +#define R200_BLEND_GL_ZERO (32) +#define R200_BLEND_GL_ONE (33) +#define R200_BLEND_GL_SRC_COLOR (34) +#define R200_BLEND_GL_ONE_MINUS_SRC_COLOR (35) +#define R200_BLEND_GL_DST_COLOR (36) +#define R200_BLEND_GL_ONE_MINUS_DST_COLOR (37) +#define R200_BLEND_GL_SRC_ALPHA (38) +#define R200_BLEND_GL_ONE_MINUS_SRC_ALPHA (39) +#define R200_BLEND_GL_DST_ALPHA (40) +#define R200_BLEND_GL_ONE_MINUS_DST_ALPHA (41) +#define R200_BLEND_GL_SRC_ALPHA_SATURATE (42) /* src factor only */ +#define R200_BLEND_GL_CONST_COLOR (43) +#define R200_BLEND_GL_ONE_MINUS_CONST_COLOR (44) +#define R200_BLEND_GL_CONST_ALPHA (45) +#define R200_BLEND_GL_ONE_MINUS_CONST_ALPHA (46) +#define R200_BLEND_MASK (63) +#define R200_SRC_BLEND_SHIFT (16) +#define R200_DST_BLEND_SHIFT (24) +#define R200_RB3D_DEPTHOFFSET 0x1c24 +#define R200_RB3D_DEPTHPITCH 0x1c28 +#define R200_DEPTHPITCH_MASK 0x00001ff8 +#define R200_DEPTH_ENDIAN_NO_SWAP (0 << 18) +#define R200_DEPTH_ENDIAN_WORD_SWAP (1 << 18) +#define R200_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) +#define R200_RB3D_ZSTENCILCNTL 0x1c2c +#define R200_DEPTH_FORMAT_MASK (0xf << 0) +#define R200_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) +#define R200_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) +#define R200_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0) +#define R200_DEPTH_FORMAT_32BIT_INT_Z (4 << 0) +#define R200_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0) +#define R200_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0) +#define R200_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0) +#define R200_Z_TEST_NEVER (0 << 4) +#define R200_Z_TEST_LESS (1 << 4) +#define R200_Z_TEST_LEQUAL (2 << 4) +#define R200_Z_TEST_EQUAL (3 << 4) +#define R200_Z_TEST_GEQUAL (4 << 4) +#define R200_Z_TEST_GREATER (5 << 4) +#define R200_Z_TEST_NEQUAL (6 << 4) +#define R200_Z_TEST_ALWAYS (7 << 4) +#define R200_Z_TEST_MASK (7 << 4) +#define R200_STENCIL_TEST_NEVER (0 << 12) +#define R200_STENCIL_TEST_LESS (1 << 12) +#define R200_STENCIL_TEST_LEQUAL (2 << 12) +#define R200_STENCIL_TEST_EQUAL (3 << 12) +#define R200_STENCIL_TEST_GEQUAL (4 << 12) +#define R200_STENCIL_TEST_GREATER (5 << 12) +#define R200_STENCIL_TEST_NEQUAL (6 << 12) +#define R200_STENCIL_TEST_ALWAYS (7 << 12) +#define R200_STENCIL_TEST_MASK (0x7 << 12) +#define R200_STENCIL_FAIL_KEEP (0 << 16) +#define R200_STENCIL_FAIL_ZERO (1 << 16) +#define R200_STENCIL_FAIL_REPLACE (2 << 16) +#define R200_STENCIL_FAIL_INC (3 << 16) +#define R200_STENCIL_FAIL_DEC (4 << 16) +#define R200_STENCIL_FAIL_INVERT (5 << 16) +#define R200_STENCIL_FAIL_INC_WRAP (6 << 16) +#define R200_STENCIL_FAIL_DEC_WRAP (7 << 16) +#define R200_STENCIL_FAIL_MASK (0x7 << 16) +#define R200_STENCIL_ZPASS_KEEP (0 << 20) +#define R200_STENCIL_ZPASS_ZERO (1 << 20) +#define R200_STENCIL_ZPASS_REPLACE (2 << 20) +#define R200_STENCIL_ZPASS_INC (3 << 20) +#define R200_STENCIL_ZPASS_DEC (4 << 20) +#define R200_STENCIL_ZPASS_INVERT (5 << 20) +#define R200_STENCIL_ZPASS_INC_WRAP (6 << 20) +#define R200_STENCIL_ZPASS_DEC_WRAP (7 << 20) +#define R200_STENCIL_ZPASS_MASK (0x7 << 20) +#define R200_STENCIL_ZFAIL_KEEP (0 << 24) +#define R200_STENCIL_ZFAIL_ZERO (1 << 24) +#define R200_STENCIL_ZFAIL_REPLACE (2 << 24) +#define R200_STENCIL_ZFAIL_INC (3 << 24) +#define R200_STENCIL_ZFAIL_DEC (4 << 24) +#define R200_STENCIL_ZFAIL_INVERT (5 << 24) +#define R200_STENCIL_ZFAIL_INC_WRAP (6 << 24) +#define R200_STENCIL_ZFAIL_DEC_WRAP (7 << 24) +#define R200_STENCIL_ZFAIL_MASK (0x7 << 24) +#define R200_Z_WRITE_ENABLE (1 << 30) +/*gap*/ +#define R200_PP_CNTL 0x1c38 +#define R200_TEX_0_ENABLE 0x00000010 +#define R200_TEX_1_ENABLE 0x00000020 +#define R200_TEX_2_ENABLE 0x00000040 +#define R200_TEX_3_ENABLE 0x00000080 +#define R200_TEX_4_ENABLE 0x00000100 +#define R200_TEX_5_ENABLE 0x00000200 +#define R200_TEX_ENABLE_MASK 0x000003f0 +#define R200_FILTER_ROUND_MODE_MASK 0x00000400 +#define R200_TEX_BLEND_7_ENABLE 0x00000800 +#define R200_TEX_BLEND_0_ENABLE 0x00001000 +#define R200_TEX_BLEND_1_ENABLE 0x00002000 +#define R200_TEX_BLEND_2_ENABLE 0x00004000 +#define R200_TEX_BLEND_3_ENABLE 0x00008000 +#define R200_TEX_BLEND_4_ENABLE 0x00010000 +#define R200_TEX_BLEND_5_ENABLE 0x00020000 +#define R200_TEX_BLEND_6_ENABLE 0x00040000 +#define R200_MULTI_PASS_ENABLE 0x00080000 +#define R200_SPECULAR_ENABLE 0x00200000 +#define R200_FOG_ENABLE 0x00400000 +#define R200_ALPHA_TEST_ENABLE 0x00800000 +#define R200_ANTI_ALIAS_NONE 0x00000000 +#define R200_ANTI_ALIAS_LINE 0x01000000 +#define R200_ANTI_ALIAS_POLY 0x02000000 +#define R200_ANTI_ALIAS_MASK 0x03000000 +#define R200_RB3D_CNTL 0x1c3c +#define R200_ALPHA_BLEND_ENABLE (1 << 0) +#define R200_PLANE_MASK_ENABLE (1 << 1) +#define R200_DITHER_ENABLE (1 << 2) +#define R200_ROUND_ENABLE (1 << 3) +#define R200_SCALE_DITHER_ENABLE (1 << 4) +#define R200_DITHER_INIT (1 << 5) +#define R200_ROP_ENABLE (1 << 6) +#define R200_STENCIL_ENABLE (1 << 7) +#define R200_Z_ENABLE (1 << 8) +#define R200_DEPTH_XZ_OFFEST_ENABLE (1 << 9) +#define R200_COLOR_FORMAT_ARGB1555 (3 << 10) +#define R200_COLOR_FORMAT_RGB565 (4 << 10) +#define R200_COLOR_FORMAT_ARGB8888 (6 << 10) +#define R200_COLOR_FORMAT_RGB332 (7 << 10) +#define R200_COLOR_FORMAT_Y8 (8 << 10) +#define R200_COLOR_FORMAT_RGB8 (9 << 10) +#define R200_COLOR_FORMAT_YUV422_VYUY (11 << 10) +#define R200_COLOR_FORMAT_YUV422_YVYU (12 << 10) +#define R200_COLOR_FORMAT_aYUV444 (14 << 10) +#define R200_COLOR_FORMAT_ARGB4444 (15 << 10) +#define R200_CLRCMP_FLIP_ENABLE (1 << 14) +#define R200_SEPARATE_ALPHA_ENABLE (1 << 16) +#define R200_RB3D_COLOROFFSET 0x1c40 +#define R200_COLOROFFSET_MASK 0xfffffff0 +#define R200_RE_WIDTH_HEIGHT 0x1c44 +#define R200_RE_WIDTH_SHIFT 0 +#define R200_RE_HEIGHT_SHIFT 16 +#define R200_RB3D_COLORPITCH 0x1c48 +#define R200_COLORPITCH_MASK 0x000001ff8 +#define R200_COLOR_ENDIAN_NO_SWAP (0 << 18) +#define R200_COLOR_ENDIAN_WORD_SWAP (1 << 18) +#define R200_COLOR_ENDIAN_DWORD_SWAP (2 << 18) +#define R200_SE_CNTL 0x1c4c +#define R200_FFACE_CULL_CW (0 << 0) +#define R200_FFACE_CULL_CCW (1 << 0) +#define R200_FFACE_CULL_DIR_MASK (1 << 0) +#define R200_BFACE_CULL (0 << 1) +#define R200_BFACE_SOLID (3 << 1) +#define R200_FFACE_CULL (0 << 3) +#define R200_FFACE_SOLID (3 << 3) +#define R200_FFACE_CULL_MASK (3 << 3) +#define R200_FLAT_SHADE_VTX_0 (0 << 6) +#define R200_FLAT_SHADE_VTX_1 (1 << 6) +#define R200_FLAT_SHADE_VTX_2 (2 << 6) +#define R200_FLAT_SHADE_VTX_LAST (3 << 6) +#define R200_DIFFUSE_SHADE_SOLID (0 << 8) +#define R200_DIFFUSE_SHADE_FLAT (1 << 8) +#define R200_DIFFUSE_SHADE_GOURAUD (2 << 8) +#define R200_DIFFUSE_SHADE_MASK (3 << 8) +#define R200_ALPHA_SHADE_SOLID (0 << 10) +#define R200_ALPHA_SHADE_FLAT (1 << 10) +#define R200_ALPHA_SHADE_GOURAUD (2 << 10) +#define R200_ALPHA_SHADE_MASK (3 << 10) +#define R200_SPECULAR_SHADE_SOLID (0 << 12) +#define R200_SPECULAR_SHADE_FLAT (1 << 12) +#define R200_SPECULAR_SHADE_GOURAUD (2 << 12) +#define R200_SPECULAR_SHADE_MASK (3 << 12) +#define R200_FOG_SHADE_SOLID (0 << 14) +#define R200_FOG_SHADE_FLAT (1 << 14) +#define R200_FOG_SHADE_GOURAUD (2 << 14) +#define R200_FOG_SHADE_MASK (3 << 14) +#define R200_ZBIAS_ENABLE_POINT (1 << 16) +#define R200_ZBIAS_ENABLE_LINE (1 << 17) +#define R200_ZBIAS_ENABLE_TRI (1 << 18) +#define R200_WIDELINE_ENABLE (1 << 20) +#define R200_VTX_PIX_CENTER_D3D (0 << 27) +#define R200_VTX_PIX_CENTER_OGL (1 << 27) +#define R200_ROUND_MODE_TRUNC (0 << 28) +#define R200_ROUND_MODE_ROUND (1 << 28) +#define R200_ROUND_MODE_ROUND_EVEN (2 << 28) +#define R200_ROUND_MODE_ROUND_ODD (3 << 28) +#define R200_ROUND_PREC_16TH_PIX (0 << 30) +#define R200_ROUND_PREC_8TH_PIX (1 << 30) +#define R200_ROUND_PREC_4TH_PIX (2 << 30) +#define R200_ROUND_PREC_HALF_PIX (3 << 30) +#define R200_RE_CNTL 0x1c50 +#define R200_STIPPLE_ENABLE 0x1 +#define R200_SCISSOR_ENABLE 0x2 +#define R200_PATTERN_ENABLE 0x4 +#define R200_PERSPECTIVE_ENABLE 0x8 +#define R200_POINT_SMOOTH 0x20 +#define R200_VTX_STQ0_D3D 0x00010000 +#define R200_VTX_STQ1_D3D 0x00040000 +#define R200_VTX_STQ2_D3D 0x00100000 +#define R200_VTX_STQ3_D3D 0x00400000 +#define R200_VTX_STQ4_D3D 0x01000000 +#define R200_VTX_STQ5_D3D 0x04000000 +/* gap */ +#define R200_RE_STIPPLE_ADDR 0x1cc8 +#define R200_RE_STIPPLE_DATA 0x1ccc +#define R200_RE_LINE_PATTERN 0x1cd0 +#define R200_LINE_PATTERN_MASK 0x0000ffff +#define R200_LINE_REPEAT_COUNT_SHIFT 16 +#define R200_LINE_PATTERN_START_SHIFT 24 +#define R200_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28) +#define R200_LINE_PATTERN_BIG_BIT_ORDER (1 << 28) +#define R200_LINE_PATTERN_AUTO_RESET (1 << 29) +#define R200_RE_LINE_STATE 0x1cd4 +#define R200_LINE_CURRENT_PTR_SHIFT 0 +#define R200_LINE_CURRENT_COUNT_SHIFT 8 +#define R200_RE_SCISSOR_TL_0 0x1cd8 +#define R200_RE_SCISSOR_BR_0 0x1cdc +#define R200_RE_SCISSOR_TL_1 0x1ce0 +#define R200_RE_SCISSOR_BR_1 0x1ce4 +#define R200_RE_SCISSOR_TL_2 0x1ce8 +#define R200_RE_SCISSOR_BR_2 0x1cec +/* gap */ +#define R200_RB3D_DEPTHXY_OFFSET 0x1d60 +#define R200_DEPTHX_SHIFT 0 +#define R200_DEPTHY_SHIFT 16 +/* gap */ +#define R200_RB3D_STENCILREFMASK 0x1d7c +#define R200_STENCIL_REF_SHIFT 0 +#define R200_STENCIL_REF_MASK (0xff << 0) +#define R200_STENCIL_MASK_SHIFT 16 +#define R200_STENCIL_VALUE_MASK (0xff << 16) +#define R200_STENCIL_WRITEMASK_SHIFT 24 +#define R200_STENCIL_WRITE_MASK (0xff << 24) +#define R200_RB3D_ROPCNTL 0x1d80 +#define R200_ROP_MASK (15 << 8) +#define R200_ROP_CLEAR (0 << 8) +#define R200_ROP_NOR (1 << 8) +#define R200_ROP_AND_INVERTED (2 << 8) +#define R200_ROP_COPY_INVERTED (3 << 8) +#define R200_ROP_AND_REVERSE (4 << 8) +#define R200_ROP_INVERT (5 << 8) +#define R200_ROP_XOR (6 << 8) +#define R200_ROP_NAND (7 << 8) +#define R200_ROP_AND (8 << 8) +#define R200_ROP_EQUIV (9 << 8) +#define R200_ROP_NOOP (10 << 8) +#define R200_ROP_OR_INVERTED (11 << 8) +#define R200_ROP_COPY (12 << 8) +#define R200_ROP_OR_REVERSE (13 << 8) +#define R200_ROP_OR (14 << 8) +#define R200_ROP_SET (15 << 8) +#define R200_RB3D_PLANEMASK 0x1d84 +/* gap */ +#define R200_SE_VPORT_XSCALE 0x1d98 +#define R200_SE_VPORT_XOFFSET 0x1d9c +#define R200_SE_VPORT_YSCALE 0x1da0 +#define R200_SE_VPORT_YOFFSET 0x1da4 +#define R200_SE_VPORT_ZSCALE 0x1da8 +#define R200_SE_VPORT_ZOFFSET 0x1dac +#define R200_SE_ZBIAS_FACTOR 0x1db0 +#define R200_SE_ZBIAS_CONSTANT 0x1db4 +#define R200_SE_LINE_WIDTH 0x1db8 +#define R200_LINE_WIDTH_SHIFT 0x00000000 +#define R200_MINPOINTSIZE_SHIFT 0x00000010 +/* gap */ +#define R200_SE_VAP_CNTL 0x2080 +#define R200_VAP_TCL_ENABLE 0x00000001 +#define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 +#define R200_VAP_FORCE_W_TO_ONE 0x00010000 +#define R200_VAP_D3D_TEX_DEFAULT 0x00020000 +#define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 +#define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 +#define R200_SE_VF_CNTL 0x2084 +#define R200_VF_PRIM_NONE 0x00000000 +#define R200_VF_PRIM_POINTS 0x00000001 +#define R200_VF_PRIM_LINES 0x00000002 +#define R200_VF_PRIM_LINE_STRIP 0x00000003 +#define R200_VF_PRIM_TRIANGLES 0x00000004 +#define R200_VF_PRIM_TRIANGLE_FAN 0x00000005 +#define R200_VF_PRIM_TRIANGLE_STRIP 0x00000006 +#define R200_VF_PRIM_RECT_LIST 0x00000008 +#define R200_VF_PRIM_3VRT_POINTS 0x00000009 +#define R200_VF_PRIM_3VRT_LINES 0x0000000a +#define R200_VF_PRIM_POINT_SPRITES 0x0000000b +#define R200_VF_PRIM_LINE_LOOP 0x0000000c +#define R200_VF_PRIM_QUADS 0x0000000d +#define R200_VF_PRIM_QUAD_STRIP 0x0000000e +#define R200_VF_PRIM_POLYGON 0x0000000f +#define R200_VF_PRIM_MASK 0x0000000f +#define R200_VF_PRIM_WALK_IND 0x00000010 +#define R200_VF_PRIM_WALK_LIST 0x00000020 +#define R200_VF_PRIM_WALK_RING 0x00000030 +#define R200_VF_PRIM_WALK_MASK 0x00000030 +#define R200_VF_COLOR_ORDER_RGBA 0x00000040 +#define R200_VF_TCL_OUTPUT_VTX_ENABLE 0x00000200 +#define R200_VF_INDEX_SZ_4 0x00000800 +#define R200_VF_VERTEX_NUMBER_MASK 0xffff0000 +#define R200_VF_VERTEX_NUMBER_SHIFT 16 +#define R200_SE_VTX_FMT_0 0x2088 +#define R200_VTX_XY 0 /* always have xy */ +#define R200_VTX_Z0 (1<<0) +#define R200_VTX_W0 (1<<1) +#define R200_VTX_WEIGHT_COUNT_SHIFT (2) +#define R200_VTX_PV_MATRIX_SEL (1<<5) +#define R200_VTX_N0 (1<<6) +#define R200_VTX_POINT_SIZE (1<<7) +#define R200_VTX_DISCRETE_FOG (1<<8) +#define R200_VTX_SHININESS_0 (1<<9) +#define R200_VTX_SHININESS_1 (1<<10) +#define R200_VTX_COLOR_NOT_PRESENT 0 +#define R200_VTX_PK_RGBA 1 +#define R200_VTX_FP_RGB 2 +#define R200_VTX_FP_RGBA 3 +#define R200_VTX_COLOR_MASK 3 +#define R200_VTX_COLOR_0_SHIFT 11 +#define R200_VTX_COLOR_1_SHIFT 13 +#define R200_VTX_COLOR_2_SHIFT 15 +#define R200_VTX_COLOR_3_SHIFT 17 +#define R200_VTX_COLOR_4_SHIFT 19 +#define R200_VTX_COLOR_5_SHIFT 21 +#define R200_VTX_COLOR_6_SHIFT 23 +#define R200_VTX_COLOR_7_SHIFT 25 +#define R200_VTX_XY1 (1<<28) +#define R200_VTX_Z1 (1<<29) +#define R200_VTX_W1 (1<<30) +#define R200_VTX_N1 (1<<31) +#define R200_SE_VTX_FMT_1 0x208c +#define R200_VTX_TEX0_COMP_CNT_SHIFT 0 +#define R200_VTX_TEX1_COMP_CNT_SHIFT 3 +#define R200_VTX_TEX2_COMP_CNT_SHIFT 6 +#define R200_VTX_TEX3_COMP_CNT_SHIFT 9 +#define R200_VTX_TEX4_COMP_CNT_SHIFT 12 +#define R200_VTX_TEX5_COMP_CNT_SHIFT 15 +#define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090 +#define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094 +/* gap */ +#define R200_SE_VTE_CNTL 0x20b0 +#define R200_VPORT_X_SCALE_ENA 0x00000001 +#define R200_VPORT_X_OFFSET_ENA 0x00000002 +#define R200_VPORT_Y_SCALE_ENA 0x00000004 +#define R200_VPORT_Y_OFFSET_ENA 0x00000008 +#define R200_VPORT_Z_SCALE_ENA 0x00000010 +#define R200_VPORT_Z_OFFSET_ENA 0x00000020 +#define R200_VTX_XY_FMT 0x00000100 +#define R200_VTX_Z_FMT 0x00000200 +#define R200_VTX_W0_FMT 0x00000400 +#define R200_VTX_W0_NORMALIZE 0x00000800 +#define R200_VTX_ST_DENORMALIZED 0x00001000 +/* gap */ +#define R200_SE_VTX_NUM_ARRAYS 0x20c0 +#define R200_SE_VTX_AOS_ATTR01 0x20c4 +#define R200_SE_VTX_AOS_ADDR0 0x20c8 +#define R200_SE_VTX_AOS_ADDR1 0x20cc +#define R200_SE_VTX_AOS_ATTR23 0x20d0 +#define R200_SE_VTX_AOS_ADDR2 0x20d4 +#define R200_SE_VTX_AOS_ADDR3 0x20d8 +#define R200_SE_VTX_AOS_ATTR45 0x20dc +#define R200_SE_VTX_AOS_ADDR4 0x20e0 +#define R200_SE_VTX_AOS_ADDR5 0x20e4 +#define R200_SE_VTX_AOS_ATTR67 0x20e8 +#define R200_SE_VTX_AOS_ADDR6 0x20ec +#define R200_SE_VTX_AOS_ADDR7 0x20f0 +#define R200_SE_VTX_AOS_ATTR89 0x20f4 +#define R200_SE_VTX_AOS_ADDR8 0x20f8 +#define R200_SE_VTX_AOS_ADDR9 0x20fc +#define R200_SE_VTX_AOS_ATTR1011 0x2100 +#define R200_SE_VTX_AOS_ADDR10 0x2104 +#define R200_SE_VTX_AOS_ADDR11 0x2108 +#define R200_SE_VF_MAX_VTX_INDX 0x210c +#define R200_SE_VF_MIN_VTX_INDX 0x2110 +/* gap */ +#define R200_SE_VAP_CNTL_STATUS 0x2140 +#define R200_VC_NO_SWAP (0 << 0) +#define R200_VC_16BIT_SWAP (1 << 0) +#define R200_VC_32BIT_SWAP (2 << 0) +/* gap */ +#define R200_SE_VTX_STATE_CNTL 0x2180 +#define R200_VSC_COLOR_0_ASSEMBLY_CNTL_SHIFT 0x00000000 +#define R200_VSC_COLOR_1_ASSEMBLY_CNTL_SHIFT 0x00000002 +#define R200_VSC_COLOR_2_ASSEMBLY_CNTL_SHIFT 0x00000004 +#define R200_VSC_COLOR_3_ASSEMBLY_CNTL_SHIFT 0x00000006 +#define R200_VSC_COLOR_4_ASSEMBLY_CNTL_SHIFT 0x00000008 +#define R200_VSC_COLOR_5_ASSEMBLY_CNTL_SHIFT 0x0000000a +#define R200_VSC_COLOR_6_ASSEMBLY_CNTL_SHIFT 0x0000000c +#define R200_VSC_COLOR_7_ASSEMBLY_CNTL_SHIFT 0x0000000e +#define R200_VSC_UPDATE_USER_COLOR_0_ENABLE 0x00010000 +#define R200_VSC_UPDATE_USER_COLOR_1_ENABLE 0x00020000 +/* gap */ +#define R200_SE_TCL_VECTOR_INDX_REG 0x2200 +#define R200_SE_TCL_VECTOR_DATA_REG 0x2204 +#define R200_SE_TCL_SCALAR_INDX_REG 0x2208 +#define R200_SE_TCL_SCALAR_DATA_REG 0x220c +/* gap */ +#define R200_SE_TCL_MATRIX_SEL_0 0x2230 +#define R200_MODELVIEW_0_SHIFT (0) +#define R200_MODELVIEW_1_SHIFT (8) +#define R200_MODELVIEW_2_SHIFT (16) +#define R200_MODELVIEW_3_SHIFT (24) +#define R200_SE_TCL_MATRIX_SEL_1 0x2234 +#define R200_IT_MODELVIEW_0_SHIFT (0) +#define R200_IT_MODELVIEW_1_SHIFT (8) +#define R200_IT_MODELVIEW_2_SHIFT (16) +#define R200_IT_MODELVIEW_3_SHIFT (24) +#define R200_SE_TCL_MATRIX_SEL_2 0x2238 +#define R200_MODELPROJECT_0_SHIFT (0) +#define R200_MODELPROJECT_1_SHIFT (8) +#define R200_MODELPROJECT_2_SHIFT (16) +#define R200_MODELPROJECT_3_SHIFT (24) +#define R200_SE_TCL_MATRIX_SEL_3 0x223c +#define R200_TEXMAT_0_SHIFT 0 +#define R200_TEXMAT_1_SHIFT 8 +#define R200_TEXMAT_2_SHIFT 16 +#define R200_TEXMAT_3_SHIFT 24 +#define R200_SE_TCL_MATRIX_SEL_4 0x2240 +#define R200_TEXMAT_4_SHIFT 0 +#define R200_TEXMAT_5_SHIFT 8 +/* gap */ +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +#define R200_OUTPUT_XYZW (1<<0) +#define R200_OUTPUT_COLOR_0 (1<<8) +#define R200_OUTPUT_COLOR_1 (1<<9) +#define R200_OUTPUT_TEX_0 (1<<16) +#define R200_OUTPUT_TEX_1 (1<<17) +#define R200_OUTPUT_TEX_2 (1<<18) +#define R200_OUTPUT_TEX_3 (1<<19) +#define R200_OUTPUT_TEX_4 (1<<20) +#define R200_OUTPUT_TEX_5 (1<<21) +#define R200_OUTPUT_TEX_MASK (0x3f<<16) +#define R200_OUTPUT_DISCRETE_FOG (1<<24) +#define R200_OUTPUT_PT_SIZE (1<<25) +#define R200_FORCE_INORDER_PROC (1<<31) +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 +#define R200_VERTEX_POSITION_ADDR__SHIFT 0x00000000 +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_1 0x2258 +#define R200_VTX_COLOR_0_ADDR__SHIFT 0x00000000 +#define R200_VTX_COLOR_1_ADDR__SHIFT 0x00000008 +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_2 0x225c +#define R200_VTX_TEX_0_ADDR__SHIFT 0x00000000 +#define R200_VTX_TEX_1_ADDR__SHIFT 0x00000008 +#define R200_VTX_TEX_2_ADDR__SHIFT 0x00000010 +#define R200_VTX_TEX_3_ADDR__SHIFT 0x00000018 +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_3 0x2260 +#define R200_VTX_TEX_4_ADDR__SHIFT 0x00000000 +#define R200_VTX_TEX_5_ADDR__SHIFT 0x00000008 + +/* gap */ +#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 +#define R200_LIGHTING_ENABLE (1<<0) +#define R200_LIGHT_IN_MODELSPACE (1<<1) +#define R200_LOCAL_VIEWER (1<<2) +#define R200_NORMALIZE_NORMALS (1<<3) +#define R200_RESCALE_NORMALS (1<<4) +#define R200_SPECULAR_LIGHTS (1<<5) +#define R200_DIFFUSE_SPECULAR_COMBINE (1<<6) +#define R200_LIGHT_ALPHA (1<<7) +#define R200_LOCAL_LIGHT_VEC_GL (1<<8) +#define R200_LIGHT_NO_NORMAL_AMBIENT_ONLY (1<<9) +#define R200_LIGHT_TWOSIDE (1<<10) +#define R200_FRONT_SHININESS_SOURCE_SHIFT (0xb) +#define R200_BACK_SHININESS_SOURCE_SHIFT (0xd) +#define R200_LM0_SOURCE_MATERIAL_0 (0) +#define R200_LM0_SOURCE_MATERIAL_1 (1) +#define R200_LM0_SOURCE_VERTEX_SHININESS_0 (2) +#define R200_LM0_SOURCE_VERTEX_SHININESS_1 (3) +#define R200_SE_TCL_LIGHT_MODEL_CTL_1 0x226c +#define R200_LM1_SOURCE_LIGHT_PREMULT (0) +#define R200_LM1_SOURCE_MATERIAL_0 (1) +#define R200_LM1_SOURCE_VERTEX_COLOR_0 (2) +#define R200_LM1_SOURCE_VERTEX_COLOR_1 (3) +#define R200_LM1_SOURCE_VERTEX_COLOR_2 (4) +#define R200_LM1_SOURCE_VERTEX_COLOR_3 (5) +#define R200_LM1_SOURCE_VERTEX_COLOR_4 (6) +#define R200_LM1_SOURCE_VERTEX_COLOR_5 (7) +#define R200_LM1_SOURCE_VERTEX_COLOR_6 (8) +#define R200_LM1_SOURCE_VERTEX_COLOR_7 (9) +#define R200_LM1_SOURCE_MATERIAL_1 (0xf) +#define R200_FRONT_EMISSIVE_SOURCE_SHIFT (0) +#define R200_FRONT_AMBIENT_SOURCE_SHIFT (4) +#define R200_FRONT_DIFFUSE_SOURCE_SHIFT (8) +#define R200_FRONT_SPECULAR_SOURCE_SHIFT (12) +#define R200_BACK_EMISSIVE_SOURCE_SHIFT (16) +#define R200_BACK_AMBIENT_SOURCE_SHIFT (20) +#define R200_BACK_DIFFUSE_SOURCE_SHIFT (24) +#define R200_BACK_SPECULAR_SOURCE_SHIFT (28) +#define R200_SE_TCL_PER_LIGHT_CTL_0 0x2270 +#define R200_LIGHT_0_ENABLE (1<<0) +#define R200_LIGHT_0_ENABLE_AMBIENT (1<<1) +#define R200_LIGHT_0_ENABLE_SPECULAR (1<<2) +#define R200_LIGHT_0_IS_LOCAL (1<<3) +#define R200_LIGHT_0_IS_SPOT (1<<4) +#define R200_LIGHT_0_DUAL_CONE (1<<5) +#define R200_LIGHT_0_ENABLE_RANGE_ATTEN (1<<6) +#define R200_LIGHT_0_CONSTANT_RANGE_ATTEN (1<<7) +#define R200_LIGHT_1_ENABLE (1<<16) +#define R200_LIGHT_1_ENABLE_AMBIENT (1<<17) +#define R200_LIGHT_1_ENABLE_SPECULAR (1<<18) +#define R200_LIGHT_1_IS_LOCAL (1<<19) +#define R200_LIGHT_1_IS_SPOT (1<<20) +#define R200_LIGHT_1_DUAL_CONE (1<<21) +#define R200_LIGHT_1_ENABLE_RANGE_ATTEN (1<<22) +#define R200_LIGHT_1_CONSTANT_RANGE_ATTEN (1<<23) +#define R200_LIGHT_0_SHIFT (0) +#define R200_LIGHT_1_SHIFT (16) +#define R200_SE_TCL_PER_LIGHT_CTL_1 0x2274 +#define R200_LIGHT_2_SHIFT (0) +#define R200_LIGHT_3_SHIFT (16) +#define R200_SE_TCL_PER_LIGHT_CTL_2 0x2278 +#define R200_LIGHT_4_SHIFT (0) +#define R200_LIGHT_5_SHIFT (16) +#define R200_SE_TCL_PER_LIGHT_CTL_3 0x227c +#define R200_LIGHT_6_SHIFT (0) +#define R200_LIGHT_7_SHIFT (16) +/* gap */ +#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 +#define R200_TEXGEN_0_COMP_MASK_SHIFT (0) +#define R200_TEXGEN_1_COMP_MASK_SHIFT (4) +#define R200_TEXGEN_2_COMP_MASK_SHIFT (8) +#define R200_TEXGEN_3_COMP_MASK_SHIFT (12) +#define R200_TEXGEN_4_COMP_MASK_SHIFT (16) +#define R200_TEXGEN_5_COMP_MASK_SHIFT (20) +#define R200_SE_TCL_TEX_PROC_CTL_3 0x22ac +#define R200_TEXGEN_0_INPUT_TEX_SHIFT (0) +#define R200_TEXGEN_1_INPUT_TEX_SHIFT (4) +#define R200_TEXGEN_2_INPUT_TEX_SHIFT (8) +#define R200_TEXGEN_3_INPUT_TEX_SHIFT (12) +#define R200_TEXGEN_4_INPUT_TEX_SHIFT (16) +#define R200_TEXGEN_5_INPUT_TEX_SHIFT (20) +#define R200_SE_TCL_TEX_PROC_CTL_0 0x22b0 +#define R200_TEXGEN_TEXMAT_0_ENABLE (1<<0) +#define R200_TEXGEN_TEXMAT_1_ENABLE (1<<1) +#define R200_TEXGEN_TEXMAT_2_ENABLE (1<<2) +#define R200_TEXGEN_TEXMAT_3_ENABLE (1<<3) +#define R200_TEXGEN_TEXMAT_4_ENABLE (1<<4) +#define R200_TEXGEN_TEXMAT_5_ENABLE (1<<5) +#define R200_TEXMAT_0_ENABLE (1<<8) +#define R200_TEXMAT_1_ENABLE (1<<9) +#define R200_TEXMAT_2_ENABLE (1<<10) +#define R200_TEXMAT_3_ENABLE (1<<11) +#define R200_TEXMAT_4_ENABLE (1<<12) +#define R200_TEXMAT_5_ENABLE (1<<13) +#define R200_TEXGEN_FORCE_W_TO_ONE (1<<16) +#define R200_SE_TCL_TEX_PROC_CTL_1 0x22b4 +#define R200_TEXGEN_INPUT_MASK (0xf) +#define R200_TEXGEN_INPUT_TEXCOORD_0 (0) +#define R200_TEXGEN_INPUT_TEXCOORD_1 (1) +#define R200_TEXGEN_INPUT_TEXCOORD_2 (2) +#define R200_TEXGEN_INPUT_TEXCOORD_3 (3) +#define R200_TEXGEN_INPUT_TEXCOORD_4 (4) +#define R200_TEXGEN_INPUT_TEXCOORD_5 (5) +#define R200_TEXGEN_INPUT_OBJ (8) +#define R200_TEXGEN_INPUT_EYE (9) +#define R200_TEXGEN_INPUT_EYE_NORMAL (0xa) +#define R200_TEXGEN_INPUT_EYE_REFLECT (0xb) +#define R200_TEXGEN_INPUT_SPHERE (0xd) +#define R200_TEXGEN_0_INPUT_SHIFT (0) +#define R200_TEXGEN_1_INPUT_SHIFT (4) +#define R200_TEXGEN_2_INPUT_SHIFT (8) +#define R200_TEXGEN_3_INPUT_SHIFT (12) +#define R200_TEXGEN_4_INPUT_SHIFT (16) +#define R200_TEXGEN_5_INPUT_SHIFT (20) +#define R200_SE_TC_TEX_CYL_WRAP_CTL 0x22b8 +/* gap */ +#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 +#define R200_UCP_IN_CLIP_SPACE (1<<0) +#define R200_UCP_IN_MODEL_SPACE (1<<1) +#define R200_UCP_ENABLE_0 (1<<2) +#define R200_UCP_ENABLE_1 (1<<3) +#define R200_UCP_ENABLE_2 (1<<4) +#define R200_UCP_ENABLE_3 (1<<5) +#define R200_UCP_ENABLE_4 (1<<6) +#define R200_UCP_ENABLE_5 (1<<7) +#define R200_TCL_FOG_MASK (3<<8) +#define R200_TCL_FOG_DISABLE (0<<8) +#define R200_TCL_FOG_EXP (1<<8) +#define R200_TCL_FOG_EXP2 (2<<8) +#define R200_TCL_FOG_LINEAR (3<<8) +#define R200_RNG_BASED_FOG (1<<10) +#define R200_CLIP_DISABLE (1<<11) +#define R200_CULL_FRONT_IS_CW (0<<28) +#define R200_CULL_FRONT_IS_CCW (1<<28) +#define R200_CULL_FRONT (1<<29) +#define R200_CULL_BACK (1<<30) +#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4 +/* gap */ +#define R200_SE_VTX_ST_POS_0_X_4 0x2300 +#define R200_SE_VTX_ST_POS_0_Y_4 0x2304 +#define R200_SE_VTX_ST_POS_0_Z_4 0x2308 +#define R200_SE_VTX_ST_POS_0_W_4 0x230c +#define R200_SE_VTX_ST_NORM_0_X 0x2310 +#define R200_SE_VTX_ST_NORM_0_Y 0x2314 +#define R200_SE_VTX_ST_NORM_0_Z 0x2318 +#define R200_SE_VTX_ST_PVMS 0x231c +#define R200_SE_VTX_ST_CLR_0_R 0x2320 +#define R200_SE_VTX_ST_CLR_0_G 0x2324 +#define R200_SE_VTX_ST_CLR_0_B 0x2328 +#define R200_SE_VTX_ST_CLR_0_A 0x232c +#define R200_SE_VTX_ST_CLR_1_R 0x2330 +#define R200_SE_VTX_ST_CLR_1_G 0x2334 +#define R200_SE_VTX_ST_CLR_1_B 0x2338 +#define R200_SE_VTX_ST_CLR_1_A 0x233c +#define R200_SE_VTX_ST_CLR_2_R 0x2340 +#define R200_SE_VTX_ST_CLR_2_G 0x2344 +#define R200_SE_VTX_ST_CLR_2_B 0x2348 +#define R200_SE_VTX_ST_CLR_2_A 0x234c +#define R200_SE_VTX_ST_CLR_3_R 0x2350 +#define R200_SE_VTX_ST_CLR_3_G 0x2354 +#define R200_SE_VTX_ST_CLR_3_B 0x2358 +#define R200_SE_VTX_ST_CLR_3_A 0x235c +#define R200_SE_VTX_ST_CLR_4_R 0x2360 +#define R200_SE_VTX_ST_CLR_4_G 0x2364 +#define R200_SE_VTX_ST_CLR_4_B 0x2368 +#define R200_SE_VTX_ST_CLR_4_A 0x236c +#define R200_SE_VTX_ST_CLR_5_R 0x2370 +#define R200_SE_VTX_ST_CLR_5_G 0x2374 +#define R200_SE_VTX_ST_CLR_5_B 0x2378 +#define R200_SE_VTX_ST_CLR_5_A 0x237c +#define R200_SE_VTX_ST_CLR_6_R 0x2380 +#define R200_SE_VTX_ST_CLR_6_G 0x2384 +#define R200_SE_VTX_ST_CLR_6_B 0x2388 +#define R200_SE_VTX_ST_CLR_6_A 0x238c +#define R200_SE_VTX_ST_CLR_7_R 0x2390 +#define R200_SE_VTX_ST_CLR_7_G 0x2394 +#define R200_SE_VTX_ST_CLR_7_B 0x2398 +#define R200_SE_VTX_ST_CLR_7_A 0x239c +#define R200_SE_VTX_ST_TEX_0_S 0x23a0 +#define R200_SE_VTX_ST_TEX_0_T 0x23a4 +#define R200_SE_VTX_ST_TEX_0_R 0x23a8 +#define R200_SE_VTX_ST_TEX_0_Q 0x23ac +#define R200_SE_VTX_ST_TEX_1_S 0x23b0 +#define R200_SE_VTX_ST_TEX_1_T 0x23b4 +#define R200_SE_VTX_ST_TEX_1_R 0x23b8 +#define R200_SE_VTX_ST_TEX_1_Q 0x23bc +#define R200_SE_VTX_ST_TEX_2_S 0x23c0 +#define R200_SE_VTX_ST_TEX_2_T 0x23c4 +#define R200_SE_VTX_ST_TEX_2_R 0x23c8 +#define R200_SE_VTX_ST_TEX_2_Q 0x23cc +#define R200_SE_VTX_ST_TEX_3_S 0x23d0 +#define R200_SE_VTX_ST_TEX_3_T 0x23d4 +#define R200_SE_VTX_ST_TEX_3_R 0x23d8 +#define R200_SE_VTX_ST_TEX_3_Q 0x23dc +#define R200_SE_VTX_ST_TEX_4_S 0x23e0 +#define R200_SE_VTX_ST_TEX_4_T 0x23e4 +#define R200_SE_VTX_ST_TEX_4_R 0x23e8 +#define R200_SE_VTX_ST_TEX_4_Q 0x23ec +#define R200_SE_VTX_ST_TEX_5_S 0x23f0 +#define R200_SE_VTX_ST_TEX_5_T 0x23f4 +#define R200_SE_VTX_ST_TEX_5_R 0x23f8 +#define R200_SE_VTX_ST_TEX_5_Q 0x23fc +#define R200_SE_VTX_ST_PNT_SPRT_SZ 0x2400 +#define R200_SE_VTX_ST_DISC_FOG 0x2404 +#define R200_SE_VTX_ST_SHININESS_0 0x2408 +#define R200_SE_VTX_ST_SHININESS_1 0x240c +#define R200_SE_VTX_ST_BLND_WT_0 0x2410 +#define R200_SE_VTX_ST_BLND_WT_1 0x2414 +#define R200_SE_VTX_ST_BLND_WT_2 0x2418 +#define R200_SE_VTX_ST_BLND_WT_3 0x241c +#define R200_SE_VTX_ST_POS_1_X 0x2420 +#define R200_SE_VTX_ST_POS_1_Y 0x2424 +#define R200_SE_VTX_ST_POS_1_Z 0x2428 +#define R200_SE_VTX_ST_POS_1_W 0x242c +#define R200_SE_VTX_ST_NORM_1_X 0x2430 +#define R200_SE_VTX_ST_NORM_1_Y 0x2434 +#define R200_SE_VTX_ST_NORM_1_Z 0x2438 +#define R200_SE_VTX_ST_USR_CLR_0_R 0x2440 +#define R200_SE_VTX_ST_USR_CLR_0_G 0x2444 +#define R200_SE_VTX_ST_USR_CLR_0_B 0x2448 +#define R200_SE_VTX_ST_USR_CLR_0_A 0x244c +#define R200_SE_VTX_ST_USR_CLR_1_R 0x2450 +#define R200_SE_VTX_ST_USR_CLR_1_G 0x2454 +#define R200_SE_VTX_ST_USR_CLR_1_B 0x2458 +#define R200_SE_VTX_ST_USR_CLR_1_A 0x245c +#define R200_SE_VTX_ST_CLR_0_PKD 0x2460 +#define R200_SE_VTX_ST_CLR_1_PKD 0x2464 +#define R200_SE_VTX_ST_CLR_2_PKD 0x2468 +#define R200_SE_VTX_ST_CLR_3_PKD 0x246c +#define R200_SE_VTX_ST_CLR_4_PKD 0x2470 +#define R200_SE_VTX_ST_CLR_5_PKD 0x2474 +#define R200_SE_VTX_ST_CLR_6_PKD 0x2478 +#define R200_SE_VTX_ST_CLR_7_PKD 0x247c +#define R200_SE_VTX_ST_POS_0_X_2 0x2480 +#define R200_SE_VTX_ST_POS_0_Y_2 0x2484 +#define R200_SE_VTX_ST_PAR_CLR_LD 0x2488 +#define R200_SE_VTX_ST_USR_CLR_PKD 0x248c +#define R200_SE_VTX_ST_POS_0_X_3 0x2490 +#define R200_SE_VTX_ST_POS_0_Y_3 0x2494 +#define R200_SE_VTX_ST_POS_0_Z_3 0x2498 +#define R200_SE_VTX_ST_END_OF_PKT 0x249c +/* gap */ +#define R200_RE_POINTSIZE 0x2648 +#define R200_POINTSIZE_SHIFT 0 +#define R200_MAXPOINTSIZE_SHIFT 16 +/* gap */ +#define R200_RE_TOP_LEFT 0x26c0 +#define R200_RE_LEFT_SHIFT 0 +#define R200_RE_TOP_SHIFT 16 +#define R200_RE_MISC 0x26c4 +#define R200_STIPPLE_COORD_MASK 0x1f +#define R200_STIPPLE_X_OFFSET_SHIFT 0 +#define R200_STIPPLE_X_OFFSET_MASK (0x1f << 0) +#define R200_STIPPLE_Y_OFFSET_SHIFT 8 +#define R200_STIPPLE_Y_OFFSET_MASK (0x1f << 8) +#define R200_STIPPLE_LITTLE_BIT_ORDER (0 << 16) +#define R200_STIPPLE_BIG_BIT_ORDER (1 << 16) +/* gap */ +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_EXCLUSIVE_SCISSOR_0 0x01000000 +#define R200_EXCLUSIVE_SCISSOR_1 0x02000000 +#define R200_EXCLUSIVE_SCISSOR_2 0x04000000 +#define R200_SCISSOR_ENABLE_0 0x10000000 +#define R200_SCISSOR_ENABLE_1 0x20000000 +#define R200_SCISSOR_ENABLE_2 0x40000000 +/* gap */ +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_MAG_FILTER_NEAREST (0 << 0) +#define R200_MAG_FILTER_LINEAR (1 << 0) +#define R200_MAG_FILTER_MASK (1 << 0) +#define R200_MIN_FILTER_NEAREST (0 << 1) +#define R200_MIN_FILTER_LINEAR (1 << 1) +#define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +#define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +#define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +#define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +#define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) +#define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) +#define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +#define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +#define R200_MIN_FILTER_MASK (15 << 1) +#define R200_MAX_ANISO_1_TO_1 (0 << 5) +#define R200_MAX_ANISO_2_TO_1 (1 << 5) +#define R200_MAX_ANISO_4_TO_1 (2 << 5) +#define R200_MAX_ANISO_8_TO_1 (3 << 5) +#define R200_MAX_ANISO_16_TO_1 (4 << 5) +#define R200_MAX_ANISO_MASK (7 << 5) +#define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) +#define R200_MAX_MIP_LEVEL_SHIFT 16 +#define R200_YUV_TO_RGB (1 << 20) +#define R200_YUV_TEMPERATURE_COOL (0 << 21) +#define R200_YUV_TEMPERATURE_HOT (1 << 21) +#define R200_YUV_TEMPERATURE_MASK (1 << 21) +#define R200_WRAPEN_S (1 << 22) +#define R200_CLAMP_S_WRAP (0 << 23) +#define R200_CLAMP_S_MIRROR (1 << 23) +#define R200_CLAMP_S_CLAMP_LAST (2 << 23) +#define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +#define R200_CLAMP_S_CLAMP_BORDER (4 << 23) +#define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +#define R200_CLAMP_S_CLAMP_GL (6 << 23) +#define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +#define R200_CLAMP_S_MASK (7 << 23) +#define R200_WRAPEN_T (1 << 26) +#define R200_CLAMP_T_WRAP (0 << 27) +#define R200_CLAMP_T_MIRROR (1 << 27) +#define R200_CLAMP_T_CLAMP_LAST (2 << 27) +#define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +#define R200_CLAMP_T_CLAMP_BORDER (4 << 27) +#define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +#define R200_CLAMP_T_CLAMP_GL (6 << 27) +#define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +#define R200_CLAMP_T_MASK (7 << 27) +#define R200_KILL_LT_ZERO (1 << 30) +#define R200_BORDER_MODE_OGL (0 << 31) +#define R200_BORDER_MODE_D3D (1 << 31) +#define R200_PP_TXFORMAT_0 0x2c04 +#define R200_TXFORMAT_I8 (0 << 0) +#define R200_TXFORMAT_AI88 (1 << 0) +#define R200_TXFORMAT_RGB332 (2 << 0) +#define R200_TXFORMAT_ARGB1555 (3 << 0) +#define R200_TXFORMAT_RGB565 (4 << 0) +#define R200_TXFORMAT_ARGB4444 (5 << 0) +#define R200_TXFORMAT_ARGB8888 (6 << 0) +#define R200_TXFORMAT_RGBA8888 (7 << 0) +#define R200_TXFORMAT_Y8 (8 << 0) +#define R200_TXFORMAT_AVYU4444 (9 << 0) +#define R200_TXFORMAT_VYUY422 (10 << 0) +#define R200_TXFORMAT_YVYU422 (11 << 0) +#define R200_TXFORMAT_DXT1 (12 << 0) +#define R200_TXFORMAT_DXT23 (14 << 0) +#define R200_TXFORMAT_DXT45 (15 << 0) +#define R200_TXFORMAT_FORMAT_MASK (31 << 0) +#define R200_TXFORMAT_FORMAT_SHIFT 0 +#define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) +#define R200_TXFORMAT_NON_POWER2 (1 << 7) +#define R200_TXFORMAT_WIDTH_MASK (15 << 8) +#define R200_TXFORMAT_WIDTH_SHIFT 8 +#define R200_TXFORMAT_HEIGHT_MASK (15 << 12) +#define R200_TXFORMAT_HEIGHT_SHIFT 12 +#define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ +#define R200_TXFORMAT_F5_WIDTH_SHIFT 16 +#define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +#define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 +#define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +#define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +#define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +#define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) +#define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) +#define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) +#define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) +#define R200_TXFORMAT_ST_ROUTE_SHIFT 24 +#define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +#define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +#define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +#define R200_PP_TXFORMAT_X_0 0x2c08 +#define R200_DEPTH_LOG2_MASK (0xf << 0) +#define R200_DEPTH_LOG2_SHIFT 0 +#define R200_VOLUME_FILTER_SHIFT 4 +#define R200_VOLUME_FILTER_MASK (1 << 4) +#define R200_VOLUME_FILTER_NEAREST (0 << 4) +#define R200_VOLUME_FILTER_LINEAR (1 << 4) +#define R200_WRAPEN_Q (1 << 8) +#define R200_CLAMP_Q_WRAP (0 << 9) +#define R200_CLAMP_Q_MIRROR (1 << 9) +#define R200_CLAMP_Q_CLAMP_LAST (2 << 9) +#define R200_CLAMP_Q_MIRROR_CLAMP_LAST (3 << 9) +#define R200_CLAMP_Q_CLAMP_BORDER (4 << 9) +#define R200_CLAMP_Q_MIRROR_CLAMP_BORDER (5 << 9) +#define R200_CLAMP_Q_CLAMP_GL (6 << 9) +#define R200_CLAMP_Q_MIRROR_CLAMP_GL (7 << 9) +#define R200_CLAMP_Q_MASK (7 << 9) +#define R200_MIN_MIP_LEVEL_MASK (0xff << 12) +#define R200_MIN_MIP_LEVEL_SHIFT 12 +#define R200_TEXCOORD_NONPROJ (0 << 16) +#define R200_TEXCOORD_CUBIC_ENV (1 << 16) +#define R200_TEXCOORD_VOLUME (2 << 16) +#define R200_TEXCOORD_PROJ (3 << 16) +#define R200_TEXCOORD_DEPTH (4 << 16) +#define R200_TEXCOORD_1D_PROJ (5 << 16) +#define R200_TEXCOORD_1D (6 << 16) +#define R200_TEXCOORD_ZERO (7 << 16) +#define R200_TEXCOORD_MASK (7 << 16) +#define R200_LOD_BIAS_MASK (0xfff80000) +#define R200_LOD_BIAS_SHIFT 19 +#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ +#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ +#define R200_PP_BORDER_COLOR_0 0x2c14 +#define R200_PP_CUBIC_FACES_0 0x2c18 +#define R200_FACE_WIDTH_1_SHIFT 0 +#define R200_FACE_HEIGHT_1_SHIFT 4 +#define R200_FACE_WIDTH_1_MASK (0xf << 0) +#define R200_FACE_HEIGHT_1_MASK (0xf << 4) +#define R200_FACE_WIDTH_2_SHIFT 8 +#define R200_FACE_HEIGHT_2_SHIFT 12 +#define R200_FACE_WIDTH_2_MASK (0xf << 8) +#define R200_FACE_HEIGHT_2_MASK (0xf << 12) +#define R200_FACE_WIDTH_3_SHIFT 16 +#define R200_FACE_HEIGHT_3_SHIFT 20 +#define R200_FACE_WIDTH_3_MASK (0xf << 16) +#define R200_FACE_HEIGHT_3_MASK (0xf << 20) +#define R200_FACE_WIDTH_4_SHIFT 24 +#define R200_FACE_HEIGHT_4_SHIFT 28 +#define R200_FACE_WIDTH_4_MASK (0xf << 24) +#define R200_FACE_HEIGHT_4_MASK (0xf << 28) +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFORMAT_1 0x2c24 +#define R200_PP_TXFORMAT_X_1 0x2c28 +#define R200_PP_TXSIZE_1 0x2c2c +#define R200_PP_TXPITCH_1 0x2c30 +#define R200_PP_BORDER_COLOR_1 0x2c34 +#define R200_PP_CUBIC_FACES_1 0x2c38 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFORMAT_2 0x2c44 +#define R200_PP_TXSIZE_2 0x2c4c +#define R200_PP_TXFORMAT_X_2 0x2c48 +#define R200_PP_TXPITCH_2 0x2c50 +#define R200_PP_BORDER_COLOR_2 0x2c54 +#define R200_PP_CUBIC_FACES_2 0x2c58 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFORMAT_3 0x2c64 +#define R200_PP_TXSIZE_3 0x2c6c +#define R200_PP_TXFORMAT_X_3 0x2c68 +#define R200_PP_TXPITCH_3 0x2c70 +#define R200_PP_BORDER_COLOR_3 0x2c74 +#define R200_PP_CUBIC_FACES_3 0x2c78 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFORMAT_4 0x2c84 +#define R200_PP_TXSIZE_4 0x2c8c +#define R200_PP_TXFORMAT_X_4 0x2c88 +#define R200_PP_TXPITCH_4 0x2c90 +#define R200_PP_BORDER_COLOR_4 0x2c94 +#define R200_PP_CUBIC_FACES_4 0x2c98 +#define R200_PP_TXFILTER_5 0x2ca0 +#define R200_PP_TXFORMAT_5 0x2ca4 +#define R200_PP_TXSIZE_5 0x2cac +#define R200_PP_TXFORMAT_X_5 0x2ca8 +#define R200_PP_TXPITCH_5 0x2cb0 +#define R200_PP_BORDER_COLOR_5 0x2cb4 +#define R200_PP_CUBIC_FACES_5 0x2cb8 +/* gap */ +#define R200_PP_CNTL_X 0x2cc4 +/* gap */ +#define R200_PP_TXOFFSET_0 0x2d00 +#define R200_TXO_ENDIAN_NO_SWAP (0 << 0) +#define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) +#define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) +#define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +#define R200_TXO_OFFSET_MASK 0xffffffe0 +#define R200_TXO_OFFSET_SHIFT 5 +#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 +#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 +#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c +#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 +#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c +#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 +#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 +#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 +#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 +#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 +#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c +#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 +#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c +#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 +#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 +#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 +#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 +#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 +#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c +#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 +#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 +#define R200_PP_TXOFFSET_5 0x2d78 +#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c +#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 +#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 +#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 +#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c +/* gap */ +#define R200_PP_TAM_DEBUG3 0x2d9c +/* gap */ +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_PP_TFACTOR_1 0x2ee4 +#define R200_PP_TFACTOR_2 0x2ee8 +#define R200_PP_TFACTOR_3 0x2eec +#define R200_PP_TFACTOR_4 0x2ef0 +#define R200_PP_TFACTOR_5 0x2ef4 +/* gap */ +#define R200_PP_TXCBLEND_0 0x2f00 +#define R200_TXC_ARG_A_ZERO (0) +#define R200_TXC_ARG_A_CURRENT_COLOR (2) +#define R200_TXC_ARG_A_CURRENT_ALPHA (3) +#define R200_TXC_ARG_A_DIFFUSE_COLOR (4) +#define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) +#define R200_TXC_ARG_A_SPECULAR_COLOR (6) +#define R200_TXC_ARG_A_SPECULAR_ALPHA (7) +#define R200_TXC_ARG_A_TFACTOR_COLOR (8) +#define R200_TXC_ARG_A_TFACTOR_ALPHA (9) +#define R200_TXC_ARG_A_R0_COLOR (10) +#define R200_TXC_ARG_A_R0_ALPHA (11) +#define R200_TXC_ARG_A_R1_COLOR (12) +#define R200_TXC_ARG_A_R1_ALPHA (13) +#define R200_TXC_ARG_A_R2_COLOR (14) +#define R200_TXC_ARG_A_R2_ALPHA (15) +#define R200_TXC_ARG_A_R3_COLOR (16) +#define R200_TXC_ARG_A_R3_ALPHA (17) +#define R200_TXC_ARG_A_R4_COLOR (18) +#define R200_TXC_ARG_A_R4_ALPHA (19) +#define R200_TXC_ARG_A_R5_COLOR (20) +#define R200_TXC_ARG_A_R5_ALPHA (21) +#define R200_TXC_ARG_A_TFACTOR1_COLOR (26) +#define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) +#define R200_TXC_ARG_A_MASK (31 << 0) +#define R200_TXC_ARG_A_SHIFT 0 +#define R200_TXC_ARG_B_ZERO (0<<5) +#define R200_TXC_ARG_B_CURRENT_COLOR (2<<5) +#define R200_TXC_ARG_B_CURRENT_ALPHA (3<<5) +#define R200_TXC_ARG_B_DIFFUSE_COLOR (4<<5) +#define R200_TXC_ARG_B_DIFFUSE_ALPHA (5<<5) +#define R200_TXC_ARG_B_SPECULAR_COLOR (6<<5) +#define R200_TXC_ARG_B_SPECULAR_ALPHA (7<<5) +#define R200_TXC_ARG_B_TFACTOR_COLOR (8<<5) +#define R200_TXC_ARG_B_TFACTOR_ALPHA (9<<5) +#define R200_TXC_ARG_B_R0_COLOR (10<<5) +#define R200_TXC_ARG_B_R0_ALPHA (11<<5) +#define R200_TXC_ARG_B_R1_COLOR (12<<5) +#define R200_TXC_ARG_B_R1_ALPHA (13<<5) +#define R200_TXC_ARG_B_R2_COLOR (14<<5) +#define R200_TXC_ARG_B_R2_ALPHA (15<<5) +#define R200_TXC_ARG_B_R3_COLOR (16<<5) +#define R200_TXC_ARG_B_R3_ALPHA (17<<5) +#define R200_TXC_ARG_B_R4_COLOR (18<<5) +#define R200_TXC_ARG_B_R4_ALPHA (19<<5) +#define R200_TXC_ARG_B_R5_COLOR (20<<5) +#define R200_TXC_ARG_B_R5_ALPHA (21<<5) +#define R200_TXC_ARG_B_TFACTOR1_COLOR (26<<5) +#define R200_TXC_ARG_B_TFACTOR1_ALPHA (27<<5) +#define R200_TXC_ARG_B_MASK (31 << 5) +#define R200_TXC_ARG_B_SHIFT 5 +#define R200_TXC_ARG_C_ZERO (0<<10) +#define R200_TXC_ARG_C_CURRENT_COLOR (2<<10) +#define R200_TXC_ARG_C_CURRENT_ALPHA (3<<10) +#define R200_TXC_ARG_C_DIFFUSE_COLOR (4<<10) +#define R200_TXC_ARG_C_DIFFUSE_ALPHA (5<<10) +#define R200_TXC_ARG_C_SPECULAR_COLOR (6<<10) +#define R200_TXC_ARG_C_SPECULAR_ALPHA (7<<10) +#define R200_TXC_ARG_C_TFACTOR_COLOR (8<<10) +#define R200_TXC_ARG_C_TFACTOR_ALPHA (9<<10) +#define R200_TXC_ARG_C_R0_COLOR (10<<10) +#define R200_TXC_ARG_C_R0_ALPHA (11<<10) +#define R200_TXC_ARG_C_R1_COLOR (12<<10) +#define R200_TXC_ARG_C_R1_ALPHA (13<<10) +#define R200_TXC_ARG_C_R2_COLOR (14<<10) +#define R200_TXC_ARG_C_R2_ALPHA (15<<10) +#define R200_TXC_ARG_C_R3_COLOR (16<<10) +#define R200_TXC_ARG_C_R3_ALPHA (17<<10) +#define R200_TXC_ARG_C_R4_COLOR (18<<10) +#define R200_TXC_ARG_C_R4_ALPHA (19<<10) +#define R200_TXC_ARG_C_R5_COLOR (20<<10) +#define R200_TXC_ARG_C_R5_ALPHA (21<<10) +#define R200_TXC_ARG_C_TFACTOR1_COLOR (26<<10) +#define R200_TXC_ARG_C_TFACTOR1_ALPHA (27<<10) +#define R200_TXC_ARG_C_MASK (31 << 10) +#define R200_TXC_ARG_C_SHIFT 10 +#define R200_TXC_COMP_ARG_A (1 << 16) +#define R200_TXC_COMP_ARG_A_SHIFT (16) +#define R200_TXC_BIAS_ARG_A (1 << 17) +#define R200_TXC_SCALE_ARG_A (1 << 18) +#define R200_TXC_NEG_ARG_A (1 << 19) +#define R200_TXC_COMP_ARG_B (1 << 20) +#define R200_TXC_COMP_ARG_B_SHIFT (20) +#define R200_TXC_BIAS_ARG_B (1 << 21) +#define R200_TXC_SCALE_ARG_B (1 << 22) +#define R200_TXC_NEG_ARG_B (1 << 23) +#define R200_TXC_COMP_ARG_C (1 << 24) +#define R200_TXC_COMP_ARG_C_SHIFT (24) +#define R200_TXC_BIAS_ARG_C (1 << 25) +#define R200_TXC_SCALE_ARG_C (1 << 26) +#define R200_TXC_NEG_ARG_C (1 << 27) +#define R200_TXC_OP_MADD (0 << 28) +#define R200_TXC_OP_CND0 (2 << 28) +#define R200_TXC_OP_LERP (3 << 28) +#define R200_TXC_OP_DOT3 (4 << 28) +#define R200_TXC_OP_DOT4 (5 << 28) +#define R200_TXC_OP_CONDITIONAL (6 << 28) +#define R200_TXC_OP_DOT2_ADD (7 << 28) +#define R200_TXC_OP_MASK (7 << 28) +#define R200_PP_TXCBLEND2_0 0x2f04 +#define R200_TXC_TFACTOR_SEL_SHIFT 0 +#define R200_TXC_TFACTOR_SEL_MASK 0x7 +#define R200_TXC_TFACTOR1_SEL_SHIFT 4 +#define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) +#define R200_TXC_SCALE_SHIFT 8 +#define R200_TXC_SCALE_MASK (7 << 8) +#define R200_TXC_SCALE_1X (0 << 8) +#define R200_TXC_SCALE_2X (1 << 8) +#define R200_TXC_SCALE_4X (2 << 8) +#define R200_TXC_SCALE_8X (3 << 8) +#define R200_TXC_SCALE_INV2 (5 << 8) +#define R200_TXC_SCALE_INV4 (6 << 8) +#define R200_TXC_SCALE_INV8 (7 << 8) +#define R200_TXC_CLAMP_SHIFT 12 +#define R200_TXC_CLAMP_MASK (3 << 12) +#define R200_TXC_CLAMP_WRAP (0 << 12) +#define R200_TXC_CLAMP_0_1 (1 << 12) +#define R200_TXC_CLAMP_8_8 (2 << 12) +#define R200_TXC_OUTPUT_REG_MASK (7 << 16) +#define R200_TXC_OUTPUT_REG_NONE (0 << 16) +#define R200_TXC_OUTPUT_REG_R0 (1 << 16) +#define R200_TXC_OUTPUT_REG_R1 (2 << 16) +#define R200_TXC_OUTPUT_REG_R2 (3 << 16) +#define R200_TXC_OUTPUT_REG_R3 (4 << 16) +#define R200_TXC_OUTPUT_REG_R4 (5 << 16) +#define R200_TXC_OUTPUT_REG_R5 (6 << 16) +#define R200_TXC_OUTPUT_MASK_MASK (7 << 20) +#define R200_TXC_OUTPUT_MASK_RGB (0 << 20) +#define R200_TXC_OUTPUT_MASK_RG (1 << 20) +#define R200_TXC_OUTPUT_MASK_RB (2 << 20) +#define R200_TXC_OUTPUT_MASK_R (3 << 20) +#define R200_TXC_OUTPUT_MASK_GB (4 << 20) +#define R200_TXC_OUTPUT_MASK_G (5 << 20) +#define R200_TXC_OUTPUT_MASK_B (6 << 20) +#define R200_TXC_OUTPUT_MASK_NONE (7 << 20) +#define R200_TXC_REPL_NORMAL 0 +#define R200_TXC_REPL_RED 1 +#define R200_TXC_REPL_GREEN 2 +#define R200_TXC_REPL_BLUE 3 +#define R200_TXC_REPL_ARG_A_SHIFT 26 +#define R200_TXC_REPL_ARG_A_MASK (3 << 26) +#define R200_TXC_REPL_ARG_B_SHIFT 28 +#define R200_TXC_REPL_ARG_B_MASK (3 << 28) +#define R200_TXC_REPL_ARG_C_SHIFT 30 +#define R200_TXC_REPL_ARG_C_MASK (3 << 30) +#define R200_PP_TXABLEND_0 0x2f08 +#define R200_TXA_ARG_A_ZERO (0) +#define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ +#define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ +#define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) +#define R200_TXA_ARG_A_DIFFUSE_BLUE (5) +#define R200_TXA_ARG_A_SPECULAR_ALPHA (6) +#define R200_TXA_ARG_A_SPECULAR_BLUE (7) +#define R200_TXA_ARG_A_TFACTOR_ALPHA (8) +#define R200_TXA_ARG_A_TFACTOR_BLUE (9) +#define R200_TXA_ARG_A_R0_ALPHA (10) +#define R200_TXA_ARG_A_R0_BLUE (11) +#define R200_TXA_ARG_A_R1_ALPHA (12) +#define R200_TXA_ARG_A_R1_BLUE (13) +#define R200_TXA_ARG_A_R2_ALPHA (14) +#define R200_TXA_ARG_A_R2_BLUE (15) +#define R200_TXA_ARG_A_R3_ALPHA (16) +#define R200_TXA_ARG_A_R3_BLUE (17) +#define R200_TXA_ARG_A_R4_ALPHA (18) +#define R200_TXA_ARG_A_R4_BLUE (19) +#define R200_TXA_ARG_A_R5_ALPHA (20) +#define R200_TXA_ARG_A_R5_BLUE (21) +#define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) +#define R200_TXA_ARG_A_TFACTOR1_BLUE (27) +#define R200_TXA_ARG_A_MASK (31 << 0) +#define R200_TXA_ARG_A_SHIFT 0 +#define R200_TXA_ARG_B_ZERO (0<<5) +#define R200_TXA_ARG_B_CURRENT_ALPHA (2<<5) /* guess */ +#define R200_TXA_ARG_B_CURRENT_BLUE (3<<5) /* guess */ +#define R200_TXA_ARG_B_DIFFUSE_ALPHA (4<<5) +#define R200_TXA_ARG_B_DIFFUSE_BLUE (5<<5) +#define R200_TXA_ARG_B_SPECULAR_ALPHA (6<<5) +#define R200_TXA_ARG_B_SPECULAR_BLUE (7<<5) +#define R200_TXA_ARG_B_TFACTOR_ALPHA (8<<5) +#define R200_TXA_ARG_B_TFACTOR_BLUE (9<<5) +#define R200_TXA_ARG_B_R0_ALPHA (10<<5) +#define R200_TXA_ARG_B_R0_BLUE (11<<5) +#define R200_TXA_ARG_B_R1_ALPHA (12<<5) +#define R200_TXA_ARG_B_R1_BLUE (13<<5) +#define R200_TXA_ARG_B_R2_ALPHA (14<<5) +#define R200_TXA_ARG_B_R2_BLUE (15<<5) +#define R200_TXA_ARG_B_R3_ALPHA (16<<5) +#define R200_TXA_ARG_B_R3_BLUE (17<<5) +#define R200_TXA_ARG_B_R4_ALPHA (18<<5) +#define R200_TXA_ARG_B_R4_BLUE (19<<5) +#define R200_TXA_ARG_B_R5_ALPHA (20<<5) +#define R200_TXA_ARG_B_R5_BLUE (21<<5) +#define R200_TXA_ARG_B_TFACTOR1_ALPHA (26<<5) +#define R200_TXA_ARG_B_TFACTOR1_BLUE (27<<5) +#define R200_TXA_ARG_B_MASK (31 << 5) +#define R200_TXA_ARG_B_SHIFT 5 +#define R200_TXA_ARG_C_ZERO (0<<10) +#define R200_TXA_ARG_C_CURRENT_ALPHA (2<<10) /* guess */ +#define R200_TXA_ARG_C_CURRENT_BLUE (3<<10) /* guess */ +#define R200_TXA_ARG_C_DIFFUSE_ALPHA (4<<10) +#define R200_TXA_ARG_C_DIFFUSE_BLUE (5<<10) +#define R200_TXA_ARG_C_SPECULAR_ALPHA (6<<10) +#define R200_TXA_ARG_C_SPECULAR_BLUE (7<<10) +#define R200_TXA_ARG_C_TFACTOR_ALPHA (8<<10) +#define R200_TXA_ARG_C_TFACTOR_BLUE (9<<10) +#define R200_TXA_ARG_C_R0_ALPHA (10<<10) +#define R200_TXA_ARG_C_R0_BLUE (11<<10) +#define R200_TXA_ARG_C_R1_ALPHA (12<<10) +#define R200_TXA_ARG_C_R1_BLUE (13<<10) +#define R200_TXA_ARG_C_R2_ALPHA (14<<10) +#define R200_TXA_ARG_C_R2_BLUE (15<<10) +#define R200_TXA_ARG_C_R3_ALPHA (16<<10) +#define R200_TXA_ARG_C_R3_BLUE (17<<10) +#define R200_TXA_ARG_C_R4_ALPHA (18<<10) +#define R200_TXA_ARG_C_R4_BLUE (19<<10) +#define R200_TXA_ARG_C_R5_ALPHA (20<<10) +#define R200_TXA_ARG_C_R5_BLUE (21<<10) +#define R200_TXA_ARG_C_TFACTOR1_ALPHA (26<<10) +#define R200_TXA_ARG_C_TFACTOR1_BLUE (27<<10) +#define R200_TXA_ARG_C_MASK (31 << 10) +#define R200_TXA_ARG_C_SHIFT 10 +#define R200_TXA_COMP_ARG_A (1 << 16) +#define R200_TXA_COMP_ARG_A_SHIFT (16) +#define R200_TXA_BIAS_ARG_A (1 << 17) +#define R200_TXA_SCALE_ARG_A (1 << 18) +#define R200_TXA_NEG_ARG_A (1 << 19) +#define R200_TXA_COMP_ARG_B (1 << 20) +#define R200_TXA_COMP_ARG_B_SHIFT (20) +#define R200_TXA_BIAS_ARG_B (1 << 21) +#define R200_TXA_SCALE_ARG_B (1 << 22) +#define R200_TXA_NEG_ARG_B (1 << 23) +#define R200_TXA_COMP_ARG_C (1 << 24) +#define R200_TXA_COMP_ARG_C_SHIFT (24) +#define R200_TXA_BIAS_ARG_C (1 << 25) +#define R200_TXA_SCALE_ARG_C (1 << 26) +#define R200_TXA_NEG_ARG_C (1 << 27) +#define R200_TXA_OP_MADD (0 << 28) +#define R200_TXA_OP_CND0 (2 << 28) +#define R200_TXA_OP_LERP (3 << 28) +#define R200_TXA_OP_CONDITIONAL (6 << 28) +#define R200_TXA_OP_MASK (7 << 28) +#define R200_PP_TXABLEND2_0 0x2f0c +#define R200_TXA_TFACTOR_SEL_SHIFT 0 +#define R200_TXA_TFACTOR_SEL_MASK 0x7 +#define R200_TXA_TFACTOR1_SEL_SHIFT 4 +#define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) +#define R200_TXA_SCALE_SHIFT 8 +#define R200_TXA_SCALE_MASK (7 << 8) +#define R200_TXA_SCALE_1X (0 << 8) +#define R200_TXA_SCALE_2X (1 << 8) +#define R200_TXA_SCALE_4X (2 << 8) +#define R200_TXA_SCALE_8X (3 << 8) +#define R200_TXA_SCALE_INV2 (5 << 8) +#define R200_TXA_SCALE_INV4 (6 << 8) +#define R200_TXA_SCALE_INV8 (7 << 8) +#define R200_TXA_CLAMP_SHIFT 12 +#define R200_TXA_CLAMP_MASK (3 << 12) +#define R200_TXA_CLAMP_WRAP (0 << 12) +#define R200_TXA_CLAMP_0_1 (1 << 12) +#define R200_TXA_CLAMP_8_8 (2 << 12) +#define R200_TXA_OUTPUT_REG_MASK (7 << 16) +#define R200_TXA_OUTPUT_REG_NONE (0 << 16) +#define R200_TXA_OUTPUT_REG_R0 (1 << 16) +#define R200_TXA_OUTPUT_REG_R1 (2 << 16) +#define R200_TXA_OUTPUT_REG_R2 (3 << 16) +#define R200_TXA_OUTPUT_REG_R3 (4 << 16) +#define R200_TXA_OUTPUT_REG_R4 (5 << 16) +#define R200_TXA_OUTPUT_REG_R5 (6 << 16) +#define R200_TXA_DOT_ALPHA (1 << 20) +#define R200_TXA_REPL_NORMAL 0 +#define R200_TXA_REPL_RED 1 +#define R200_TXA_REPL_GREEN 2 +#define R200_TXA_REPL_ARG_A_SHIFT 26 +#define R200_TXA_REPL_ARG_A_MASK (3 << 26) +#define R200_TXA_REPL_ARG_B_SHIFT 28 +#define R200_TXA_REPL_ARG_B_MASK (3 << 28) +#define R200_TXA_REPL_ARG_C_SHIFT 30 +#define R200_TXA_REPL_ARG_C_MASK (3 << 30) +#define R200_PP_TXCBLEND_1 0x2f10 +#define R200_PP_TXCBLEND2_1 0x2f14 +#define R200_PP_TXABLEND_1 0x2f18 +#define R200_PP_TXABLEND2_1 0x2f1c +#define R200_PP_TXCBLEND_2 0x2f20 +#define R200_PP_TXCBLEND2_2 0x2f24 +#define R200_PP_TXABLEND_2 0x2f28 +#define R200_PP_TXABLEND2_2 0x2f2c +#define R200_PP_TXCBLEND_3 0x2f30 +#define R200_PP_TXCBLEND2_3 0x2f34 +#define R200_PP_TXABLEND_3 0x2f38 +#define R200_PP_TXABLEND2_3 0x2f3c +#define R200_PP_TXCBLEND_4 0x2f40 +#define R200_PP_TXCBLEND2_4 0x2f44 +#define R200_PP_TXABLEND_4 0x2f48 +#define R200_PP_TXABLEND2_4 0x2f4c +#define R200_PP_TXCBLEND_5 0x2f50 +#define R200_PP_TXCBLEND2_5 0x2f54 +#define R200_PP_TXABLEND_5 0x2f58 +#define R200_PP_TXABLEND2_5 0x2f5c +#define R200_PP_TXCBLEND_6 0x2f60 +#define R200_PP_TXCBLEND2_6 0x2f64 +#define R200_PP_TXABLEND_6 0x2f68 +#define R200_PP_TXABLEND2_6 0x2f6c +#define R200_PP_TXCBLEND_7 0x2f70 +#define R200_PP_TXCBLEND2_7 0x2f74 +#define R200_PP_TXABLEND_7 0x2f78 +#define R200_PP_TXABLEND2_7 0x2f7c +/* gap */ +#define R200_RB3D_BLENDCOLOR 0x3218 /* ARGB 8888 */ +#define R200_RB3D_ABLENDCNTL 0x321C /* see BLENDCTL */ +#define R200_RB3D_CBLENDCNTL 0x3220 /* see BLENDCTL */ + +/* + * Offsets in TCL vector state. NOTE: Hardwiring matrix positions. + * Multiple contexts could collaberate to eliminate state bouncing. + */ +#define R200_VS_LIGHT_AMBIENT_ADDR 0x00000028 +#define R200_VS_LIGHT_DIFFUSE_ADDR 0x00000030 +#define R200_VS_LIGHT_SPECULAR_ADDR 0x00000038 +#define R200_VS_LIGHT_DIRPOS_ADDR 0x00000040 +#define R200_VS_LIGHT_HWVSPOT_ADDR 0x00000048 +#define R200_VS_LIGHT_ATTENUATION_ADDR 0x00000050 +#define R200_VS_SPOT_DUAL_CONE 0x00000058 +#define R200_VS_GLOBAL_AMBIENT_ADDR 0x0000005C +#define R200_VS_FOG_PARAM_ADDR 0x0000005D +#define R200_VS_EYE_VECTOR_ADDR 0x0000005E +#define R200_VS_UCP_ADDR 0x00000060 +#define R200_VS_PNT_SPRITE_VPORT_SCALE 0x00000068 +#define R200_VS_MATRIX_0_MV 0x00000080 +#define R200_VS_MATRIX_1_INV_MV 0x00000084 +#define R200_VS_MATRIX_2_MVP 0x00000088 +#define R200_VS_MATRIX_3_TEX0 0x0000008C +#define R200_VS_MATRIX_4_TEX1 0x00000090 +#define R200_VS_MATRIX_5_TEX2 0x00000094 +#define R200_VS_MATRIX_6_TEX3 0x00000098 +#define R200_VS_MATRIX_7_TEX4 0x0000009C +#define R200_VS_MATRIX_8_TEX5 0x000000A0 +#define R200_VS_MAT_0_EMISS 0x000000B0 +#define R200_VS_MAT_0_AMB 0x000000B1 +#define R200_VS_MAT_0_DIF 0x000000B2 +#define R200_VS_MAT_0_SPEC 0x000000B3 +#define R200_VS_MAT_1_EMISS 0x000000B4 +#define R200_VS_MAT_1_AMB 0x000000B5 +#define R200_VS_MAT_1_DIF 0x000000B6 +#define R200_VS_MAT_1_SPEC 0x000000B7 +#define R200_VS_EYE2CLIP_MTX 0x000000B8 +#define R200_VS_PNT_SPRITE_ATT_CONST 0x000000BC +#define R200_VS_PNT_SPRITE_EYE_IN_MODEL 0x000000BD +#define R200_VS_PNT_SPRITE_CLAMP 0x000000BE +#define R200_VS_MAX 0x000001C0 + +/* + * Offsets in TCL scalar state + */ +#define R200_SS_LIGHT_DCD_ADDR 0x00000000 +#define R200_SS_LIGHT_DCM_ADDR 0x00000008 +#define R200_SS_LIGHT_SPOT_EXPONENT_ADDR 0x00000010 +#define R200_SS_LIGHT_SPOT_CUTOFF_ADDR 0x00000018 +#define R200_SS_LIGHT_SPECULAR_THRESH_ADDR 0x00000020 +#define R200_SS_LIGHT_RANGE_CUTOFF_SQRD 0x00000028 +#define R200_SS_LIGHT_RANGE_ATT_CONST 0x00000030 +#define R200_SS_VERT_GUARD_CLIP_ADJ_ADDR 0x00000080 +#define R200_SS_VERT_GUARD_DISCARD_ADJ_ADDR 0x00000081 +#define R200_SS_HORZ_GUARD_CLIP_ADJ_ADDR 0x00000082 +#define R200_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 0x00000083 +#define R200_SS_MAT_0_SHININESS 0x00000100 +#define R200_SS_MAT_1_SHININESS 0x00000101 + +/* + * Matrix indices + */ +#define R200_MTX_MV 0 +#define R200_MTX_IMV 1 +#define R200_MTX_MVP 2 +#define R200_MTX_TEX0 3 +#define R200_MTX_TEX1 4 +#define R200_MTX_TEX2 5 +#define R200_MTX_TEX3 6 +#define R200_MTX_TEX4 7 +#define R200_MTX_TEX5 8 + +/* Color formats for 2d packets + */ +#define R200_CP_COLOR_FORMAT_CI8 2 +#define R200_CP_COLOR_FORMAT_ARGB1555 3 +#define R200_CP_COLOR_FORMAT_RGB565 4 +#define R200_CP_COLOR_FORMAT_ARGB8888 6 +#define R200_CP_COLOR_FORMAT_RGB332 7 +#define R200_CP_COLOR_FORMAT_RGB8 9 +#define R200_CP_COLOR_FORMAT_ARGB4444 15 + +/* + * CP type-3 packets + */ +#define R200_CP_CMD_NOP 0xC0001000 +#define R200_CP_CMD_NEXT_CHAR 0xC0001900 +#define R200_CP_CMD_PLY_NEXTSCAN 0xC0001D00 +#define R200_CP_CMD_SET_SCISSORS 0xC0001E00 +#define R200_CP_CMD_LOAD_MICROCODE 0xC0002400 +#define R200_CP_CMD_WAIT_FOR_IDLE 0xC0002600 +#define R200_CP_CMD_3D_DRAW_VBUF 0xC0002800 +#define R200_CP_CMD_3D_DRAW_IMMD 0xC0002900 +#define R200_CP_CMD_3D_DRAW_INDX 0xC0002A00 +#define R200_CP_CMD_LOAD_PALETTE 0xC0002C00 +#define R200_CP_CMD_3D_LOAD_VBPNTR 0xC0002F00 +#define R200_CP_CMD_INDX_BUFFER 0xC0003300 +#define R200_CP_CMD_3D_DRAW_VBUF_2 0xC0003400 +#define R200_CP_CMD_3D_DRAW_IMMD_2 0xC0003500 +#define R200_CP_CMD_3D_DRAW_INDX_2 0xC0003600 +#define R200_CP_CMD_PAINT 0xC0009100 +#define R200_CP_CMD_BITBLT 0xC0009200 +#define R200_CP_CMD_SMALLTEXT 0xC0009300 +#define R200_CP_CMD_HOSTDATA_BLT 0xC0009400 +#define R200_CP_CMD_POLYLINE 0xC0009500 +#define R200_CP_CMD_POLYSCANLINES 0xC0009800 +#define R200_CP_CMD_PAINT_MULTI 0xC0009A00 +#define R200_CP_CMD_BITBLT_MULTI 0xC0009B00 +#define R200_CP_CMD_TRANS_BITBLT 0xC0009C00 + +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_sanity.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_sanity.h new file mode 100644 index 000000000..30852b490 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_sanity.h @@ -0,0 +1,7 @@ +#ifndef R200_SANITY_H +#define R200_SANITY_H + +extern int r200SanityCmdBuffer(r200ContextPtr rmesa, + int nbox, drm_clip_rect_t * boxes); + +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_state.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_state.h new file mode 100644 index 000000000..3e1a9c8ba --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_state.h @@ -0,0 +1,58 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __R200_STATE_H__ +#define __R200_STATE_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "r200_context.h" + +extern void r200InitState(r200ContextPtr rmesa); +extern void r200InitStateFuncs(struct dd_function_table *functions); +extern void r200InitTnlFuncs(GLcontext * ctx); + +extern void r200UpdateMaterial(GLcontext * ctx); + +extern void r200UpdateViewportOffset(GLcontext * ctx); +extern void r200UpdateWindow(GLcontext * ctx); + +extern void r200ValidateState(GLcontext * ctx); + +extern void r200PrintDirty(r200ContextPtr rmesa, const char *msg); + +extern void r200LightingSpaceChange(GLcontext * ctx); + +#endif +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_tcl.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_tcl.h new file mode 100644 index 000000000..4528cf152 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_tcl.h @@ -0,0 +1,50 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_tcl.h,v 1.2 2002/12/16 16:18:55 dawes Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __R200_TCL_H__ +#define __R200_TCL_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "r200_context.h" + +extern void r200TclPrimitive(GLcontext * ctx, GLenum prim, int hw_prim); +extern void r200EmitEltPrimitive(GLcontext * ctx, GLuint first, GLuint last, + GLuint flags); +extern void r200EmitPrimitive(GLcontext * ctx, GLuint first, GLuint last, + GLuint flags); + +#endif +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_tex.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_tex.h new file mode 100644 index 000000000..bc0dbc3fb --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r200_tex.h @@ -0,0 +1,51 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_tex.h,v 1.1 2002/10/30 12:51:53 alanh Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __R200_TEX_H__ +#define __R200_TEX_H__ + +#ifdef GLX_DIRECT_RENDERING + +extern void r200UpdateTextureState(GLcontext * ctx); + +extern int r200UploadTexImages(r200ContextPtr rmesa, r200TexObjPtr t, + GLuint face); + +extern void r200DestroyTexObj(r200ContextPtr rmesa, r200TexObjPtr t); + +extern void r200InitTextureFuncs(struct dd_function_table *functions); + +#endif +#endif /* __R200_TEX_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_cmdbuf.c new file mode 100644 index 000000000..d3c22fda1 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -0,0 +1,655 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#include "glheader.h" +#include "state.h" +#include "imports.h" +#include "macros.h" +#include "context.h" +#include "swrast/swrast.h" +#include "simple_list.h" + +#include "drm.h" +#include "radeon_drm.h" + +#include "radeon_ioctl.h" +#include "r300_context.h" +#include "r300_ioctl.h" +#include "radeon_reg.h" +#include "r300_reg.h" +#include "r300_cmdbuf.h" +#include "r300_emit.h" + + +// Set this to 1 for extremely verbose debugging of command buffers +#define DEBUG_CMDBUF 0 + + +/** + * Send the current command buffer via ioctl to the hardware. + */ +int r300FlushCmdBufLocked(r300ContextPtr r300, const char* caller) +{ + int ret; + int i; + drm_radeon_cmd_buffer_t cmd; + int start; + + if (r300->radeon.lost_context) { + start = 0; + r300->radeon.lost_context = GL_FALSE; + } else + start = r300->cmdbuf.count_reemit; + + if (RADEON_DEBUG & DEBUG_IOCTL) { + fprintf(stderr, "%s from %s - %i cliprects\n", + __FUNCTION__, caller, r300->radeon.numClipRects); + + if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_VERBOSE) + for (i = start; i < r300->cmdbuf.count_used; ++i) + fprintf(stderr, "%d: %08x\n", i, + r300->cmdbuf.cmd_buf[i]); + } + + cmd.buf = (char*)(r300->cmdbuf.cmd_buf + start); + cmd.bufsz = (r300->cmdbuf.count_used - start) * 4; + + if (r300->radeon.state.scissor.enabled) { + cmd.nbox = r300->radeon.state.scissor.numClipRects; + cmd.boxes = (drm_clip_rect_t *)r300->radeon.state.scissor.pClipRects; + } else { + cmd.nbox = r300->radeon.numClipRects; + cmd.boxes = (drm_clip_rect_t *)r300->radeon.pClipRects; + } + + ret = drmCommandWrite(r300->radeon.dri.fd, + DRM_RADEON_CMDBUF, &cmd, sizeof(cmd)); + + if (RADEON_DEBUG & DEBUG_SYNC) { + fprintf(stderr, "Syncing in %s (from %s)\n\n", __FUNCTION__, caller); + radeonWaitForIdleLocked(&r300->radeon); + } + + r300->dma.nr_released_bufs = 0; + r300->cmdbuf.count_used = 0; + r300->cmdbuf.count_reemit = 0; + + return ret; +} + + +int r300FlushCmdBuf(r300ContextPtr r300, const char* caller) +{ + int ret; + int i; + drm_radeon_cmd_buffer_t cmd; + int start; + + LOCK_HARDWARE(&r300->radeon); + + ret=r300FlushCmdBufLocked(r300, caller); + + UNLOCK_HARDWARE(&r300->radeon); + + if (ret) { + fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret); + exit(ret); + } + + return ret; +} + + +static void print_state_atom(struct r300_state_atom *state, int dwords) +{ + int i; + + fprintf(stderr, " emit %s/%d/%d\n", state->name, dwords, state->cmd_size); + + if (RADEON_DEBUG & DEBUG_VERBOSE) + for (i = 0; i < dwords; i++) + fprintf(stderr, " %s[%d]: %08X\n", state->name, i, + state->cmd[i]); +} + +/** + * Emit all atoms with a dirty field equal to dirty. + * + * The caller must have ensured that there is enough space in the command + * buffer. + */ +static __inline__ void r300DoEmitState(r300ContextPtr r300, GLboolean dirty) +{ + struct r300_state_atom* atom; + uint32_t* dest; + + dest = r300->cmdbuf.cmd_buf + r300->cmdbuf.count_used; + + if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) { + foreach(atom, &r300->hw.atomlist) { + if ((atom->dirty || r300->hw.all_dirty) == dirty) { + int dwords = (*atom->check)(r300, atom); + + if (dwords) + print_state_atom(atom, dwords); + else + fprintf(stderr, " skip state %s\n", + atom->name); + } + } + } + + + /* Emit WAIT */ + *dest = cmdwait(R300_WAIT_3D | R300_WAIT_3D_CLEAN); + dest ++; + r300->cmdbuf.count_used ++; + + /* Emit END3D */ + *dest = cmdpacify(); + dest ++; + r300->cmdbuf.count_used ++; + + /* Emit actual atoms */ + + foreach(atom, &r300->hw.atomlist) { + if ((atom->dirty || r300->hw.all_dirty) == dirty) { + int dwords = (*atom->check)(r300, atom); + + if (dwords) { + memcpy(dest, atom->cmd, dwords*4); + dest += dwords; + r300->cmdbuf.count_used += dwords; + atom->dirty = GL_FALSE; + } + } + } +} + +/** + * Copy dirty hardware state atoms into the command buffer. + * + * We also copy out clean state if we're at the start of a buffer. That makes + * it easy to recover from lost contexts. + */ +void r300EmitState(r300ContextPtr r300) +{ + if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_PRIMS)) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (r300->cmdbuf.count_used && !r300->hw.is_dirty && !r300->hw.all_dirty) + return; + + /* To avoid going across the entire set of states multiple times, just check + * for enough space for the case of emitting all state, and inline the + * r300AllocCmdBuf code here without all the checks. + */ + r300EnsureCmdBufSpace(r300, r300->hw.max_state_size, __FUNCTION__); + + if (!r300->cmdbuf.count_used) { + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "Begin reemit state\n"); + + r300DoEmitState(r300, GL_FALSE); + r300->cmdbuf.count_reemit = r300->cmdbuf.count_used; + } + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "Begin dirty state\n"); + + r300DoEmitState(r300, GL_TRUE); + + assert(r300->cmdbuf.count_used < r300->cmdbuf.size); + + r300->hw.is_dirty = GL_FALSE; + r300->hw.all_dirty = GL_FALSE; +} + +#define CHECK( NM, COUNT ) \ +static int check_##NM( r300ContextPtr r300, \ + struct r300_state_atom* atom ) \ +{ \ + (void) atom; (void) r300; \ + return (COUNT); \ +} + +#define packet0_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->packet0.count) +#define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count) + +CHECK( always, atom->cmd_size ) +CHECK( never, 0 ) +CHECK( variable, packet0_count(atom->cmd) ? (1 + packet0_count(atom->cmd)) : 0 ) +CHECK( vpu, vpu_count(atom->cmd) ? (1 + vpu_count(atom->cmd)*4) : 0 ) + +#undef packet0_count +#undef vpu_count + +#define ALLOC_STATE( ATOM, CHK, SZ, NM, IDX ) \ + do { \ + r300->hw.ATOM.cmd_size = (SZ); \ + r300->hw.ATOM.cmd = (uint32_t*)CALLOC((SZ) * sizeof(uint32_t)); \ + r300->hw.ATOM.name = (NM); \ + r300->hw.ATOM.idx = (IDX); \ + r300->hw.ATOM.check = check_##CHK; \ + r300->hw.ATOM.dirty = GL_FALSE; \ + r300->hw.max_state_size += (SZ); \ + } while (0) + + +/** + * Allocate memory for the command buffer and initialize the state atom + * list. Note that the initial hardware state is set by r300InitState(). + */ +void r300InitCmdBuf(r300ContextPtr r300) +{ + int size, i, mtu; + + r300->hw.max_state_size = 2; /* reserve extra space for WAIT_IDLE */ + + mtu = r300->radeon.glCtx->Const.MaxTextureUnits; + if (RADEON_DEBUG & DEBUG_TEXTURE) { + fprintf(stderr, "Using %d maximum texture units..\n", mtu); + } + + /* Initialize state atoms */ + ALLOC_STATE( vpt, always, R300_VPT_CMDSIZE, "vpt", 0 ); + r300->hw.vpt.cmd[R300_VPT_CMD_0] = cmdpacket0(R300_SE_VPORT_XSCALE, 6); + ALLOC_STATE( unk2080, always, 2, "unk2080", 0 ); + r300->hw.unk2080.cmd[0] = cmdpacket0(0x2080, 1); + ALLOC_STATE( vte, always, 3, "vte", 0 ); + r300->hw.vte.cmd[0] = cmdpacket0(R300_SE_VTE_CNTL, 2); + ALLOC_STATE( unk2134, always, 3, "unk2134", 0 ); + r300->hw.unk2134.cmd[0] = cmdpacket0(0x2134, 2); + ALLOC_STATE( unk2140, always, 2, "unk2140", 0 ); + r300->hw.unk2140.cmd[0] = cmdpacket0(0x2140, 1); + ALLOC_STATE( vir[0], variable, R300_VIR_CMDSIZE, "vir/0", 0 ); + r300->hw.vir[0].cmd[R300_VIR_CMD_0] = cmdpacket0(R300_VAP_INPUT_ROUTE_0_0, 1); + ALLOC_STATE( vir[1], variable, R300_VIR_CMDSIZE, "vir/1", 1 ); + r300->hw.vir[1].cmd[R300_VIR_CMD_0] = cmdpacket0(R300_VAP_INPUT_ROUTE_1_0, 1); + ALLOC_STATE( vic, always, R300_VIC_CMDSIZE, "vic", 0 ); + r300->hw.vic.cmd[R300_VIC_CMD_0] = cmdpacket0(R300_VAP_INPUT_CNTL_0, 2); + ALLOC_STATE( unk21DC, always, 2, "unk21DC", 0 ); + r300->hw.unk21DC.cmd[0] = cmdpacket0(0x21DC, 1); + ALLOC_STATE( unk221C, always, 2, "unk221C", 0 ); + r300->hw.unk221C.cmd[0] = cmdpacket0(0x221C, 1); + ALLOC_STATE( unk2220, always, 5, "unk2220", 0 ); + r300->hw.unk2220.cmd[0] = cmdpacket0(0x2220, 4); + ALLOC_STATE( unk2288, always, 2, "unk2288", 0 ); + r300->hw.unk2288.cmd[0] = cmdpacket0(0x2288, 1); + ALLOC_STATE( vof, always, R300_VOF_CMDSIZE, "vof", 0 ); + r300->hw.vof.cmd[R300_VOF_CMD_0] = cmdpacket0(R300_VAP_OUTPUT_VTX_FMT_0, 2); + ALLOC_STATE( pvs, always, R300_PVS_CMDSIZE, "pvs", 0 ); + r300->hw.pvs.cmd[R300_PVS_CMD_0] = cmdpacket0(R300_VAP_PVS_CNTL_1, 3); + ALLOC_STATE( gb_enable, always, 2, "gb_enable", 0 ); + r300->hw.gb_enable.cmd[0] = cmdpacket0(R300_GB_ENABLE, 1); + ALLOC_STATE( gb_misc, always, R300_GB_MISC_CMDSIZE, "gb_misc", 0 ); + r300->hw.gb_misc.cmd[0] = cmdpacket0(R300_GB_MSPOS0, 5); + ALLOC_STATE( txe, always, R300_TXE_CMDSIZE, "txe", 0 ); + r300->hw.txe.cmd[R300_TXE_CMD_0] = cmdpacket0(R300_TX_ENABLE, 1); + ALLOC_STATE( unk4200, always, 5, "unk4200", 0 ); + r300->hw.unk4200.cmd[0] = cmdpacket0(0x4200, 4); + ALLOC_STATE( unk4214, always, 2, "unk4214", 0 ); + r300->hw.unk4214.cmd[0] = cmdpacket0(0x4214, 1); + ALLOC_STATE( ps, always, R300_PS_CMDSIZE, "ps", 0 ); + r300->hw.ps.cmd[0] = cmdpacket0(R300_RE_POINTSIZE, 1); + ALLOC_STATE( unk4230, always, 4, "unk4230", 0 ); + r300->hw.unk4230.cmd[0] = cmdpacket0(0x4230, 3); + ALLOC_STATE( lcntl, always, 2, "lcntl", 0 ); + r300->hw.lcntl.cmd[0] = cmdpacket0(R300_RE_LINE_CNT, 1); + ALLOC_STATE( unk4260, always, 4, "unk4260", 0 ); + r300->hw.unk4260.cmd[0] = cmdpacket0(0x4260, 3); + ALLOC_STATE( unk4274, always, 5, "unk4274", 0 ); + r300->hw.unk4274.cmd[0] = cmdpacket0(0x4274, 4); + ALLOC_STATE( unk4288, always, 6, "unk4288", 0 ); + r300->hw.unk4288.cmd[0] = cmdpacket0(0x4288, 5); + ALLOC_STATE( unk42A0, always, 2, "unk42A0", 0 ); + r300->hw.unk42A0.cmd[0] = cmdpacket0(0x42A0, 1); + ALLOC_STATE( zbs, always, R300_ZBS_CMDSIZE, "zbs", 0 ); + r300->hw.zbs.cmd[R300_ZBS_CMD_0] = cmdpacket0(R300_RE_ZBIAS_T_FACTOR, 4); + ALLOC_STATE( unk42B4, always, 2, "unk42B4", 0 ); + r300->hw.unk42B4.cmd[0] = cmdpacket0(0x42B4, 1); + ALLOC_STATE( cul, always, R300_CUL_CMDSIZE, "cul", 0 ); + r300->hw.cul.cmd[R300_CUL_CMD_0] = cmdpacket0(R300_RE_CULL_CNTL, 1); + ALLOC_STATE( unk42C0, always, 3, "unk42C0", 0 ); + r300->hw.unk42C0.cmd[0] = cmdpacket0(0x42C0, 2); + ALLOC_STATE( rc, always, R300_RC_CMDSIZE, "rc", 0 ); + r300->hw.rc.cmd[R300_RC_CMD_0] = cmdpacket0(R300_RS_CNTL_0, 2); + ALLOC_STATE( ri, always, R300_RI_CMDSIZE, "ri", 0 ); + r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(R300_RS_INTERP_0, 8); + ALLOC_STATE( rr, variable, R300_RR_CMDSIZE, "rr", 0 ); + r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, 1); + ALLOC_STATE( unk43A4, always, 3, "unk43A4", 0 ); + r300->hw.unk43A4.cmd[0] = cmdpacket0(0x43A4, 2); + ALLOC_STATE( unk43E8, always, 2, "unk43E8", 0 ); + r300->hw.unk43E8.cmd[0] = cmdpacket0(0x43E8, 1); + ALLOC_STATE( fp, always, R300_FP_CMDSIZE, "fp", 0 ); + r300->hw.fp.cmd[R300_FP_CMD_0] = cmdpacket0(R300_PFS_CNTL_0, 3); + r300->hw.fp.cmd[R300_FP_CMD_1] = cmdpacket0(R300_PFS_NODE_0, 4); + ALLOC_STATE( fpt, variable, R300_FPT_CMDSIZE, "fpt", 0 ); + r300->hw.fpt.cmd[R300_FPT_CMD_0] = cmdpacket0(R300_PFS_TEXI_0, 0); + ALLOC_STATE( unk46A4, always, 6, "unk46A4", 0 ); + r300->hw.unk46A4.cmd[0] = cmdpacket0(0x46A4, 5); + ALLOC_STATE( fpi[0], variable, R300_FPI_CMDSIZE, "fpi/0", 0 ); + r300->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR0_0, 1); + ALLOC_STATE( fpi[1], variable, R300_FPI_CMDSIZE, "fpi/1", 1 ); + r300->hw.fpi[1].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR1_0, 1); + ALLOC_STATE( fpi[2], variable, R300_FPI_CMDSIZE, "fpi/2", 2 ); + r300->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR2_0, 1); + ALLOC_STATE( fpi[3], variable, R300_FPI_CMDSIZE, "fpi/3", 3 ); + r300->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR3_0, 1); + ALLOC_STATE( unk4BC0, always, 2, "unk4BC0", 0 ); + r300->hw.unk4BC0.cmd[0] = cmdpacket0(0x4BC0, 1); + ALLOC_STATE( unk4BC8, always, 4, "unk4BC8", 0 ); + r300->hw.unk4BC8.cmd[0] = cmdpacket0(0x4BC8, 3); + ALLOC_STATE( at, always, R300_AT_CMDSIZE, "at", 0 ); + r300->hw.at.cmd[R300_AT_CMD_0] = cmdpacket0(R300_PP_ALPHA_TEST, 2); + ALLOC_STATE( unk4BD8, always, 2, "unk4BD8", 0 ); + r300->hw.unk4BD8.cmd[0] = cmdpacket0(0x4BD8, 1); + ALLOC_STATE( fpp, variable, R300_FPP_CMDSIZE, "fpp", 0 ); + r300->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(R300_PFS_PARAM_0_X, 0); + ALLOC_STATE( unk4E00, always, 2, "unk4E00", 0 ); + r300->hw.unk4E00.cmd[0] = cmdpacket0(0x4E00, 1); + ALLOC_STATE( bld, always, R300_BLD_CMDSIZE, "bld", 0 ); + r300->hw.bld.cmd[R300_BLD_CMD_0] = cmdpacket0(R300_RB3D_CBLEND, 2); + ALLOC_STATE( cmk, always, R300_CMK_CMDSIZE, "cmk", 0 ); + r300->hw.cmk.cmd[R300_CMK_CMD_0] = cmdpacket0(R300_RB3D_COLORMASK, 1); + ALLOC_STATE( unk4E10, always, 4, "unk4E10", 0 ); + r300->hw.unk4E10.cmd[0] = cmdpacket0(0x4E10, 3); + ALLOC_STATE( cb, always, R300_CB_CMDSIZE, "cb", 0 ); + r300->hw.cb.cmd[R300_CB_CMD_0] = cmdpacket0(R300_RB3D_COLOROFFSET0, 1); + r300->hw.cb.cmd[R300_CB_CMD_1] = cmdpacket0(R300_RB3D_COLORPITCH0, 1); + ALLOC_STATE( unk4E50, always, 10, "unk4E50", 0 ); + r300->hw.unk4E50.cmd[0] = cmdpacket0(0x4E50, 9); + ALLOC_STATE( unk4E88, always, 2, "unk4E88", 0 ); + r300->hw.unk4E88.cmd[0] = cmdpacket0(0x4E88, 1); + ALLOC_STATE( unk4EA0, always, 3, "unk4EA0 R350 only", 0 ); + r300->hw.unk4EA0.cmd[0] = cmdpacket0(0x4EA0, 2); + ALLOC_STATE( zs, always, R300_ZS_CMDSIZE, "zstencil", 0 ); + r300->hw.zs.cmd[R300_ZS_CMD_0] = cmdpacket0(R300_RB3D_ZSTENCIL_CNTL_0, 3); + ALLOC_STATE( unk4F10, always, 5, "unk4F10", 0 ); + r300->hw.unk4F10.cmd[0] = cmdpacket0(0x4F10, 4); + ALLOC_STATE( zb, always, R300_ZB_CMDSIZE, "zb", 0 ); + r300->hw.zb.cmd[R300_ZB_CMD_0] = cmdpacket0(R300_RB3D_DEPTHOFFSET, 2); + ALLOC_STATE( unk4F28, always, 2, "unk4F28", 0 ); + r300->hw.unk4F28.cmd[0] = cmdpacket0(0x4F28, 1); + ALLOC_STATE( unk4F30, always, 3, "unk4F30", 0 ); + r300->hw.unk4F30.cmd[0] = cmdpacket0(0x4F30, 2); + ALLOC_STATE( unk4F44, always, 2, "unk4F44", 0 ); + r300->hw.unk4F44.cmd[0] = cmdpacket0(0x4F44, 1); + ALLOC_STATE( unk4F54, always, 2, "unk4F54", 0 ); + r300->hw.unk4F54.cmd[0] = cmdpacket0(0x4F54, 1); + + ALLOC_STATE( vpi, vpu, R300_VPI_CMDSIZE, "vpi", 0 ); + r300->hw.vpi.cmd[R300_VPI_CMD_0] = cmdvpu(R300_PVS_UPLOAD_PROGRAM, 0); + ALLOC_STATE( vpp, vpu, R300_VPP_CMDSIZE, "vpp", 0 ); + r300->hw.vpp.cmd[R300_VPP_CMD_0] = cmdvpu(R300_PVS_UPLOAD_PARAMETERS, 0); + ALLOC_STATE( vps, vpu, R300_VPS_CMDSIZE, "vps", 0 ); + r300->hw.vps.cmd[R300_VPS_CMD_0] = cmdvpu(R300_PVS_UPLOAD_POINTSIZE, 1); + + /* Textures */ + ALLOC_STATE( tex.filter, variable, mtu+1, "tex_filter", 0 ); + r300->hw.tex.filter.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FILTER_0, 0); + + ALLOC_STATE( tex.unknown1, variable, mtu+1, "tex_unknown1", 0 ); + r300->hw.tex.unknown1.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_UNK1_0, 0); + + ALLOC_STATE( tex.size, variable, mtu+1, "tex_size", 0 ); + r300->hw.tex.size.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_SIZE_0, 0); + + ALLOC_STATE( tex.format, variable, mtu+1, "tex_format", 0 ); + r300->hw.tex.format.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FORMAT_0, 0); + + ALLOC_STATE( tex.offset, variable, mtu+1, "tex_offset", 0 ); + r300->hw.tex.offset.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_OFFSET_0, 0); + + ALLOC_STATE( tex.unknown4, variable, mtu+1, "tex_unknown4", 0 ); + r300->hw.tex.unknown4.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_UNK4_0, 0); + + ALLOC_STATE( tex.border_color, variable, mtu+1, "tex_border_color", 0 ); + r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_BORDER_COLOR_0, 0); + + + /* Setup the atom linked list */ + make_empty_list(&r300->hw.atomlist); + r300->hw.atomlist.name = "atom-list"; + + insert_at_tail(&r300->hw.atomlist, &r300->hw.vpt); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk2080); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vte); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk2134); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk2140); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vir[0]); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vir[1]); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vic); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk21DC); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk221C); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk2220); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk2288); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vof); + insert_at_tail(&r300->hw.atomlist, &r300->hw.pvs); + insert_at_tail(&r300->hw.atomlist, &r300->hw.gb_enable); + insert_at_tail(&r300->hw.atomlist, &r300->hw.gb_misc); + insert_at_tail(&r300->hw.atomlist, &r300->hw.txe); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4200); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4214); + insert_at_tail(&r300->hw.atomlist, &r300->hw.ps); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4230); + insert_at_tail(&r300->hw.atomlist, &r300->hw.lcntl); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4260); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4274); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4288); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42A0); + insert_at_tail(&r300->hw.atomlist, &r300->hw.zbs); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42B4); + insert_at_tail(&r300->hw.atomlist, &r300->hw.cul); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42C0); + insert_at_tail(&r300->hw.atomlist, &r300->hw.rc); + insert_at_tail(&r300->hw.atomlist, &r300->hw.ri); + insert_at_tail(&r300->hw.atomlist, &r300->hw.rr); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk43A4); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk43E8); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fp); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fpt); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk46A4); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[0]); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[1]); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[2]); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[3]); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BC0); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BC8); + insert_at_tail(&r300->hw.atomlist, &r300->hw.at); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BD8); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fpp); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4E00); + insert_at_tail(&r300->hw.atomlist, &r300->hw.bld); + insert_at_tail(&r300->hw.atomlist, &r300->hw.cmk); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4E10); + insert_at_tail(&r300->hw.atomlist, &r300->hw.cb); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4E50); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4E88); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4EA0); + insert_at_tail(&r300->hw.atomlist, &r300->hw.zs); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4F10); + insert_at_tail(&r300->hw.atomlist, &r300->hw.zb); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4F28); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4F30); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4F44); + insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4F54); + + insert_at_tail(&r300->hw.atomlist, &r300->hw.vpi); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vpp); + insert_at_tail(&r300->hw.atomlist, &r300->hw.vps); + + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.filter); + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.unknown1); + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.size); + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.format); + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.offset); + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.unknown4); + insert_at_tail(&r300->hw.atomlist, &r300->hw.tex.border_color); + + r300->hw.is_dirty = GL_TRUE; + r300->hw.all_dirty = GL_TRUE; + + /* Initialize command buffer */ + size = 256 * driQueryOptioni(&r300->radeon.optionCache, "command_buffer_size"); + if (size < 2*r300->hw.max_state_size) { + size = 2*r300->hw.max_state_size+65535; + } + if (size > 64*256) + size = 64*256; + + if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) { + fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%d\n", + sizeof(drm_r300_cmd_header_t)); + fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%d\n", + sizeof(drm_radeon_cmd_buffer_t)); + fprintf(stderr, + "Allocating %d bytes command buffer (max state is %d bytes)\n", + size*4, r300->hw.max_state_size*4); + } + + r300->cmdbuf.size = size; + r300->cmdbuf.cmd_buf = (uint32_t*)CALLOC(size*4); + r300->cmdbuf.count_used = 0; + r300->cmdbuf.count_reemit = 0; +} + + +/** + * Destroy the command buffer and state atoms. + */ +void r300DestroyCmdBuf(r300ContextPtr r300) +{ + struct r300_state_atom* atom; + + FREE(r300->cmdbuf.cmd_buf); + + foreach(atom, &r300->hw.atomlist) { + FREE(atom->cmd); + } +} + +void r300EmitBlit(r300ContextPtr rmesa, + GLuint color_fmt, + GLuint src_pitch, + GLuint src_offset, + GLuint dst_pitch, + GLuint dst_offset, + GLint srcx, GLint srcy, + GLint dstx, GLint dsty, GLuint w, GLuint h) +{ + drm_radeon_cmd_header_t *cmd; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, + "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n", + __FUNCTION__, src_pitch, src_offset, srcx, srcy, + dst_pitch, dst_offset, dstx, dsty, w, h); + + assert((src_pitch & 63) == 0); + assert((dst_pitch & 63) == 0); + assert((src_offset & 1023) == 0); + assert((dst_offset & 1023) == 0); + assert(w < (1 << 16)); + assert(h < (1 << 16)); + + cmd = + (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 8, + __FUNCTION__); + + cmd[0].header.cmd_type = R300_CMD_PACKET3; + cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16); + cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); + + cmd[3].i = ((src_pitch / 64) << 22) | (src_offset >> 10); + cmd[4].i = ((dst_pitch / 64) << 22) | (dst_offset >> 10); + cmd[5].i = (srcx << 16) | srcy; + cmd[6].i = (dstx << 16) | dsty; /* dst */ + cmd[7].i = (w << 16) | h; +} + +void r300EmitWait(r300ContextPtr rmesa, GLuint flags) +{ + if (rmesa->radeon.dri.drmMinor >= 6) { + drm_radeon_cmd_header_t *cmd; + + assert(!(flags & ~(R300_WAIT_2D | R300_WAIT_3D))); + + cmd = + (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, + 1, + __FUNCTION__); + cmd[0].i = 0; + cmd[0].wait.cmd_type = R300_CMD_WAIT; + cmd[0].wait.flags = flags; + } +} + +void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset) +{ + int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2; + int i; + LOCAL_VARS + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __func__, nr, offset); + + start_packet3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz-1); + e32(nr); + for(i=0;i+1<nr;i+=2){ + e32( (rmesa->state.aos[i].aos_size << 0) + |(rmesa->state.aos[i].aos_stride << 8) + |(rmesa->state.aos[i+1].aos_size << 16) + |(rmesa->state.aos[i+1].aos_stride << 24) + ); + e32(rmesa->state.aos[i].aos_offset+offset*4*rmesa->state.aos[i].aos_stride); + e32(rmesa->state.aos[i+1].aos_offset+offset*4*rmesa->state.aos[i+1].aos_stride); + } + if(nr & 1){ + e32( (rmesa->state.aos[nr-1].aos_size << 0) + |(rmesa->state.aos[nr-1].aos_stride << 8) + ); + e32(rmesa->state.aos[nr-1].aos_offset+offset*4*rmesa->state.aos[nr-1].aos_stride); + } + +} + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_cmdbuf.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_cmdbuf.h new file mode 100644 index 000000000..b471f2ac4 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_cmdbuf.h @@ -0,0 +1,118 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __R300_CMDBUF_H__ +#define __R300_CMDBUF_H__ + +#include "r300_context.h" + + +extern int r300FlushCmdBufLocked(r300ContextPtr r300, const char* caller); +extern int r300FlushCmdBuf(r300ContextPtr r300, const char* caller); + +extern void r300EmitState(r300ContextPtr r300); + +extern void r300InitCmdBuf(r300ContextPtr r300); +extern void r300DestroyCmdBuf(r300ContextPtr r300); + +extern void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset); + + +/** + * Make sure that enough space is available in the command buffer + * by flushing if necessary. + */ +static __inline__ void r300EnsureCmdBufSpace(r300ContextPtr r300, + int dwords, const char* caller) +{ + assert(dwords < r300->cmdbuf.size); + + if (r300->cmdbuf.count_used + dwords > r300->cmdbuf.size) + r300FlushCmdBuf(r300, caller); +} + + +/** + * Allocate the given number of dwords in the command buffer and return + * a pointer to the allocated area. + * When necessary, these functions cause a flush. r300AllocCmdBuf() also + * causes state reemission after a flush. This is necessary to ensure + * correct hardware state after an unlock. + */ +static __inline__ uint32_t* r300RawAllocCmdBuf(r300ContextPtr r300, + int dwords, const char* caller) +{ + uint32_t* ptr; + + r300EnsureCmdBufSpace(r300, dwords, caller); + + ptr = &r300->cmdbuf.cmd_buf[r300->cmdbuf.count_used]; + r300->cmdbuf.count_used += dwords; + return ptr; +} + +static __inline__ uint32_t* r300AllocCmdBuf(r300ContextPtr r300, + int dwords, const char* caller) +{ + uint32_t* ptr; + + r300EnsureCmdBufSpace(r300, dwords, caller); + + if (!r300->cmdbuf.count_used) { + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "Reemit state after flush (from %s)\n", + caller); + r300EmitState(r300); + } + + ptr = &r300->cmdbuf.cmd_buf[r300->cmdbuf.count_used]; + r300->cmdbuf.count_used += dwords; + return ptr; +} + +extern void r300EmitBlit(r300ContextPtr rmesa, + GLuint color_fmt, + GLuint src_pitch, + GLuint src_offset, + GLuint dst_pitch, + GLuint dst_offset, + GLint srcx, GLint srcy, + GLint dstx, GLint dsty, GLuint w, GLuint h); + +extern void r300EmitWait(r300ContextPtr rmesa, GLuint flags); +extern void r300EmitLOAD_VBPNTR(r300ContextPtr rmesa, int start); +extern void r300EmitVertexShader(r300ContextPtr rmesa); +extern void r300EmitPixelShader(r300ContextPtr rmesa); + +#endif /* __R300_CMDBUF_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_context.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_context.c new file mode 100644 index 000000000..ba0c55069 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_context.c @@ -0,0 +1,453 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Nicolai Haehnle <prefect_@gmx.net> + */ +#include "glheader.h" +#include "api_arrayelt.h" +#include "context.h" +#include "simple_list.h" +#include "imports.h" +#include "matrix.h" +#include "extensions.h" +#include "state.h" +#include "bufferobj.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" + +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" + +#include "drivers/common/driverfuncs.h" + +#include "radeon_ioctl.h" +#include "radeon_span.h" +#include "r300_context.h" +#include "r300_cmdbuf.h" +#include "r300_state.h" +#include "r300_ioctl.h" +#include "r300_tex.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=0; +int hw_tcl_on=0; + +#define need_GL_ARB_multisample +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_buffer_object +#define need_GL_ARB_vertex_program +#define need_GL_EXT_blend_minmax +#define need_GL_EXT_secondary_color +#define need_GL_EXT_blend_equation_separate +#define need_GL_EXT_blend_func_separate +#define need_GL_NV_vertex_program +#include "extension_helper.h" + +const struct dri_extension card_extensions[] = { + {"GL_ARB_multisample", GL_ARB_multisample_functions}, + {"GL_ARB_multitexture", NULL}, + {"GL_ARB_texture_border_clamp", NULL}, + {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, +/* disable until we support it, fixes a few things in ut2004 */ +/* {"GL_ARB_texture_cube_map", NULL}, */ + {"GL_ARB_texture_env_add", NULL}, + {"GL_ARB_texture_env_combine", NULL}, + {"GL_ARB_texture_env_crossbar", NULL}, + {"GL_ARB_texture_env_dot3", NULL}, + {"GL_ARB_texture_mirrored_repeat", NULL}, + {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, + {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, +#if USE_ARB_F_P == 1 + {"GL_ARB_fragment_program", NULL}, +#endif + {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, + {"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_secondary_color", GL_EXT_secondary_color_functions}, + {"GL_EXT_stencil_wrap", NULL}, + {"GL_EXT_texture_edge_clamp", NULL}, + {"GL_EXT_texture_env_combine", NULL}, + {"GL_EXT_texture_env_dot3", NULL}, + {"GL_EXT_texture_filter_anisotropic", NULL}, + {"GL_EXT_texture_lod_bias", NULL}, + {"GL_EXT_texture_mirror_clamp", NULL}, + {"GL_EXT_texture_rectangle", NULL}, + {"GL_ATI_texture_env_combine3", NULL}, + {"GL_ATI_texture_mirror_once", NULL}, + {"GL_MESA_pack_invert", NULL}, + {"GL_MESA_ycbcr_texture", NULL}, + {"GL_NV_blend_square", NULL}, + {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, + {"GL_SGIS_generate_mipmap", NULL}, + {NULL, NULL} +}; + +extern struct tnl_pipeline_stage _r300_render_stage; +extern 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, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_arb_vertex_program_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 */ + 0, +}; + +static void r300BufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size, + const GLvoid *data, GLenum usage, struct gl_buffer_object *obj) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + drm_radeon_mem_alloc_t alloc; + int offset, ret; + + /* Free previous buffer */ + if (obj->OnCard) { + drm_radeon_mem_free_t memfree; + + memfree.region = RADEON_MEM_REGION_GART; + memfree.region_offset = (char *)obj->Data - (char *)rmesa->radeon.radeonScreen->gartTextures.map; + + ret = drmCommandWrite(rmesa->radeon.radeonScreen->driScreen->fd, + DRM_RADEON_FREE, &memfree, sizeof(memfree)); + + if (ret) { + WARN_ONCE("Failed to free GART memroy!\n"); + } + obj->OnCard = GL_FALSE; + } + + alloc.region = RADEON_MEM_REGION_GART; + alloc.alignment = 4; + alloc.size = size; + alloc.region_offset = &offset; + + ret = drmCommandWriteRead( rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc, sizeof(alloc)); + if (ret) { + WARN_ONCE("Ran out of GART memory!\n"); + obj->Data = NULL; + _mesa_buffer_data(ctx, target, size, data, usage, obj); + return ; + } + obj->Data = ((char *)rmesa->radeon.radeonScreen->gartTextures.map) + offset; + + if (data) + memcpy(obj->Data, data, size); + + obj->Size = size; + obj->Usage = usage; + obj->OnCard = GL_TRUE; +#if 0 + fprintf(stderr, "allocated %d bytes at %p, offset=%d\n", size, obj->Data, offset); +#endif +} + +static void r300DeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + if(r300IsGartMemory(rmesa, obj->Data, obj->Size)){ + drm_radeon_mem_free_t memfree; + int ret; + + memfree.region = RADEON_MEM_REGION_GART; + memfree.region_offset = (char *)obj->Data - (char *)rmesa->radeon.radeonScreen->gartTextures.map; + + ret = drmCommandWrite(rmesa->radeon.radeonScreen->driScreen->fd, + DRM_RADEON_FREE, &memfree, sizeof(memfree)); + + if(ret){ + WARN_ONCE("Failed to free GART memroy!\n"); + } + obj->Data = NULL; + } + _mesa_delete_buffer_object(ctx, obj); +} + +/* 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; + int tcl_mode, i; + + assert(glVisual); + assert(driContextPriv); + assert(screen); + + /* Allocate the R300 context */ + r300 = (r300ContextPtr)CALLOC(sizeof(*r300)); + if (!r300) + return GL_FALSE; + + /* 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"); + + /* 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); + +#if 0 /* Needs various Mesa changes... */ + if (hw_tcl_on) { + functions.BufferData = r300BufferData; + functions.DeleteBuffer = r300DeleteBuffer; + } +#endif + + if (!radeonInitContext(&r300->radeon, &functions, + glVisual, driContextPriv, sharedContextPrivate)) { + FREE(r300); + return 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 < R200_NR_TEX_HEAPS); + for (i = 0; i < r300->nr_heaps; i++) { + 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); + } + 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. + */ + + ctx = r300->radeon.glCtx; + + 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.MaxTextureCoordUnits); + ctx->Const.MaxTextureMaxAnisotropy = 16.0; + + ctx->Const.MinPointSize = 1.0; + ctx->Const.MinPointSizeAA = 1.0; + ctx->Const.MaxPointSize = R300_POINTSIZE_MAX; + ctx->Const.MaxPointSizeAA = R300_POINTSIZE_MAX; + + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = R300_LINESIZE_MAX; + ctx->Const.MaxLineWidthAA = R300_LINESIZE_MAX; + + /* Initialize the software rasterizer and helper modules. + */ + _swrast_CreateContext(ctx); + _ac_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 */ + ctx->Const.MaxVertexProgramInstructions=VSF_MAX_FRAGMENT_LENGTH; + ctx->Const.MaxVertexProgramAttribs=16; // r420 + ctx->Const.MaxVertexProgramTemps=VSF_MAX_FRAGMENT_TEMPS; + ctx->Const.MaxVertexProgramLocalParams=256; // r420 + ctx->Const.MaxVertexProgramEnvParams=256; // r420 + ctx->Const.MaxVertexProgramAddressRegs=1; + +#if USE_ARB_F_P + ctx->Const.MaxFragmentProgramTemps = PFS_NUM_TEMP_REGS; + ctx->Const.MaxFragmentProgramAttribs = 11; /* copy i915... */ + ctx->Const.MaxFragmentProgramLocalParams = PFS_NUM_CONST_REGS; + ctx->Const.MaxFragmentProgramEnvParams = PFS_NUM_CONST_REGS; + ctx->Const.MaxFragmentProgramAluInstructions = PFS_MAX_ALU_INST; + ctx->Const.MaxFragmentProgramTexInstructions = PFS_MAX_TEX_INST; + ctx->Const.MaxFragmentProgramInstructions = PFS_MAX_ALU_INST+PFS_MAX_TEX_INST; + ctx->Const.MaxFragmentProgramTexIndirections = PFS_MAX_TEX_INDIRECT; + ctx->Const.MaxFragmentProgramAddressRegs = 0; /* and these are?? */ + ctx->_MaintainTexEnvProgram = GL_TRUE; +#endif + + driInitExtensions(ctx, card_extensions, GL_TRUE); + + radeonInitSpanFuncs(ctx); + r300InitCmdBuf(r300); + r300InitState(r300); + +#if 0 + /* plug in a few more device driver functions */ + /* XXX these should really go right after _mesa_init_driver_functions() */ + r300InitPixelFuncs(ctx); + r300InitSwtcl(ctx); +#endif + TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; + + 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->chipset & RADEON_CHIPSET_TCL)) { + if (r300->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL) { + r300->radeon.radeonScreen->chipset &= ~RADEON_CHIPSET_TCL; + fprintf(stderr, "Disabling HW TCL support\n"); + } + TCL_FALLBACK(r300->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1); + } + + return GL_TRUE; +} + +/* Destroy the device specific context. + */ +void r300DestroyContext(__DRIcontextPrivate * driContextPriv) +{ + GET_CURRENT_CONTEXT(ctx); + r300ContextPtr r300 = (r300ContextPtr) driContextPriv->driverPrivate; + radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL; + + if (RADEON_DEBUG & DEBUG_DRI) { + fprintf(stderr, "Destroying context !\n"); + } + + /* check if we're deleting the currently bound context */ + if (&r300->radeon == current) { + radeonFlush(r300->radeon.glCtx); + _mesa_make_current(NULL, NULL, NULL); + } + + /* 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); + _ac_DestroyContext(r300->radeon.glCtx); + _swrast_DestroyContext(r300->radeon.glCtx); + + r300DestroyCmdBuf(r300); + + radeonCleanupContext(&r300->radeon); + + /* free the option cache */ + driDestroyOptionCache(&r300->radeon.optionCache); + + FREE(r300); + } +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_context.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_context.h new file mode 100644 index 000000000..b59f184e3 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_context.h @@ -0,0 +1,844 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __R300_CONTEXT_H__ +#define __R300_CONTEXT_H__ + +#include "tnl/t_vertex.h" +#include "drm.h" +#include "radeon_drm.h" +#include "dri_util.h" +#include "texmem.h" + +#include "macros.h" +#include "mtypes.h" +#include "colormac.h" +#include "radeon_context.h" + +#define USE_ARB_F_P 1 + +struct r300_context; +typedef struct r300_context r300ContextRec; +typedef struct r300_context *r300ContextPtr; + +#include "radeon_lock.h" +#include "mm.h" + +/* Checkpoint.. for convenience */ +#define CPT { fprintf(stderr, "%s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__); } +/* From http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Variadic-Macros.html . + I suppose we could inline this and use macro to fetch out __LINE__ and stuff in case we run into trouble + with other compilers ... GLUE! +*/ +#if 1 +#define WARN_ONCE(a, ...) { \ + static int warn##__LINE__=1; \ + if(warn##__LINE__){ \ + fprintf(stderr, "*********************************WARN_ONCE*********************************\n"); \ + fprintf(stderr, "File %s function %s line %d\n", \ + __FILE__, __FUNCTION__, __LINE__); \ + fprintf(stderr, a, ## __VA_ARGS__);\ + fprintf(stderr, "***************************************************************************\n"); \ + warn##__LINE__=0;\ + } \ + } +#else +#define WARN_ONCE(a, ...) {} +#endif + +typedef GLuint uint32_t; +typedef GLubyte uint8_t; +struct r300_fragment_program; + + /* We should probably change types within vertex_shader + and pixel_shader structure later on */ +#define CARD32 GLuint +#include "vertex_shader.h" +#if USE_ARB_F_P == 1 +#include "r300_fragprog.h" +#else +#include "pixel_shader.h" +#endif +#undef CARD32 + +static __inline__ uint32_t r300PackFloat32(float fl) +{ + union { float fl; uint32_t u; } u; + + u.fl = fl; + return u.u; +} + + +/************ DMA BUFFERS **************/ + +/* Need refcounting on dma buffers: + */ +struct r300_dma_buffer { + int refcount; /* the number of retained regions in buf */ + drmBufPtr buf; +}; + +#define GET_START(rvb) (rmesa->radeon.radeonScreen->gart_buffer_offset + \ + (rvb)->address - rmesa->dma.buf0_address + \ + (rvb)->start) + +/* A retained region, eg vertices for indexed vertices. + */ +struct r300_dma_region { + struct r300_dma_buffer *buf; + char *address; /* == buf->address */ + int start, end, ptr; /* offsets from start of buf */ + + int aos_offset; /* address in GART memory */ + int aos_stride; /* distance between elements, in dwords */ + int aos_size; /* number of components (1-4) */ + int aos_format; /* format of components */ + int aos_reg; /* VAP register assignment */ +}; + +struct r300_dma { + /* Active dma region. Allocations for vertices and retained + * regions come from here. Also used for emitting random vertices, + * these may be flushed by calling flush_current(); + */ + struct r300_dma_region current; + + void (*flush) (r300ContextPtr); + + char *buf0_address; /* start of buf[0], for index calcs */ + + /* Number of "in-flight" DMA buffers, i.e. the number of buffers + * for which a DISCARD command is currently queued in the command buffer. + */ + GLuint nr_released_bufs; +}; + + /* Texture related */ + +typedef struct r300_tex_obj r300TexObj, *r300TexObjPtr; + +/* Texture object in locally shared texture space. + */ +struct r300_tex_obj { + driTextureObject base; + + GLuint bufAddr; /* Offset to start of locally + shared texture block */ + + GLuint dirty_state; /* Flags (1 per texunit) for + whether or not this texobj + has dirty hardware state + (pp_*) that needs to be + brought into the + texunit. */ + + drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS]; + /* Six, for the cube faces */ + + + /* hardware register values */ + /* Note that R200 has 8 registers per texture and R300 only 7 */ + GLuint filter; + GLuint pitch; /* one of the unknown registers.. unknown 1 ?*/ + GLuint size; /* npot only */ + GLuint format; + GLuint offset; /* Image location in the card's address space. + All cube faces follow. */ + GLuint unknown4; + GLuint unknown5; + /* end hardware registers */ + + /* registers computed by r200 code - keep them here to + compare against what is actually written. + + to be removed later.. */ + GLuint pp_border_color; + GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */ + GLuint format_x; + + + GLboolean border_fallback; +}; + +struct r300_texture_env_state { + r300TexObjPtr texobj; + GLenum format; + GLenum envMode; +}; + +#define R300_MAX_TEXTURE_UNITS 8 + +struct r300_texture_state { + struct r300_texture_env_state unit[R300_MAX_TEXTURE_UNITS]; + int tc_count; /* number of incoming texture coordinates from VAP */ +}; + +/** + * A block of hardware state. + * + * When check returns non-zero, the returned number of dwords must be + * copied verbatim into the command buffer in order to update a state atom + * when it is dirty. + */ +struct r300_state_atom { + struct r300_state_atom *next, *prev; + const char* name; /* for debug */ + int cmd_size; /* maximum size in dwords */ + GLuint idx; /* index in an array (e.g. textures) */ + uint32_t* cmd; + GLboolean dirty; + + int (*check)(r300ContextPtr, struct r300_state_atom* atom); +}; + + +#define R300_VPT_CMD_0 0 +#define R300_VPT_XSCALE 1 +#define R300_VPT_XOFFSET 2 +#define R300_VPT_YSCALE 3 +#define R300_VPT_YOFFSET 4 +#define R300_VPT_ZSCALE 5 +#define R300_VPT_ZOFFSET 6 +#define R300_VPT_CMDSIZE 7 + +#define R300_VIR_CMD_0 0 /* vir is variable size (at least 1) */ +#define R300_VIR_CNTL_0 1 +#define R300_VIR_CNTL_1 2 +#define R300_VIR_CNTL_2 3 +#define R300_VIR_CNTL_3 4 +#define R300_VIR_CNTL_4 5 +#define R300_VIR_CNTL_5 6 +#define R300_VIR_CNTL_6 7 +#define R300_VIR_CNTL_7 8 +#define R300_VIR_CMDSIZE 9 + +#define R300_VIC_CMD_0 0 +#define R300_VIC_CNTL_0 1 +#define R300_VIC_CNTL_1 2 +#define R300_VIC_CMDSIZE 3 + +#define R300_VOF_CMD_0 0 +#define R300_VOF_CNTL_0 1 +#define R300_VOF_CNTL_1 2 +#define R300_VOF_CMDSIZE 3 + + +#define R300_PVS_CMD_0 0 +#define R300_PVS_CNTL_1 1 +#define R300_PVS_CNTL_2 2 +#define R300_PVS_CNTL_3 3 +#define R300_PVS_CMDSIZE 4 + +#define R300_GB_MISC_CMD_0 0 +#define R300_GB_MISC_MSPOS_0 1 +#define R300_GB_MISC_MSPOS_1 2 +#define R300_GB_MISC_TILE_CONFIG 3 +#define R300_GB_MISC_SELECT 4 +#define R300_GB_MISC_AA_CONFIG 5 +#define R300_GB_MISC_CMDSIZE 6 + +#define R300_TXE_CMD_0 0 +#define R300_TXE_ENABLE 1 +#define R300_TXE_CMDSIZE 2 + +#define R300_PS_CMD_0 0 +#define R300_PS_POINTSIZE 1 +#define R300_PS_CMDSIZE 2 + +#define R300_ZBS_CMD_0 0 +#define R300_ZBS_T_FACTOR 1 +#define R300_ZBS_T_CONSTANT 2 +#define R300_ZBS_W_FACTOR 3 +#define R300_ZBS_W_CONSTANT 4 +#define R300_ZBS_CMDSIZE 5 + +#define R300_CUL_CMD_0 0 +#define R300_CUL_CULL 1 +#define R300_CUL_CMDSIZE 2 + +#define R300_RC_CMD_0 0 +#define R300_RC_CNTL_0 1 +#define R300_RC_CNTL_1 2 +#define R300_RC_CMDSIZE 3 + +#define R300_RI_CMD_0 0 +#define R300_RI_INTERP_0 1 +#define R300_RI_INTERP_1 2 +#define R300_RI_INTERP_2 3 +#define R300_RI_INTERP_3 4 +#define R300_RI_INTERP_4 5 +#define R300_RI_INTERP_5 6 +#define R300_RI_INTERP_6 7 +#define R300_RI_INTERP_7 8 +#define R300_RI_CMDSIZE 9 + +#define R300_RR_CMD_0 0 /* rr is variable size (at least 1) */ +#define R300_RR_ROUTE_0 1 +#define R300_RR_ROUTE_1 2 +#define R300_RR_ROUTE_2 3 +#define R300_RR_ROUTE_3 4 +#define R300_RR_ROUTE_4 5 +#define R300_RR_ROUTE_5 6 +#define R300_RR_ROUTE_6 7 +#define R300_RR_ROUTE_7 8 +#define R300_RR_CMDSIZE 9 + +#define R300_FP_CMD_0 0 +#define R300_FP_CNTL0 1 +#define R300_FP_CNTL1 2 +#define R300_FP_CNTL2 3 +#define R300_FP_CMD_1 4 +#define R300_FP_NODE0 5 +#define R300_FP_NODE1 6 +#define R300_FP_NODE2 7 +#define R300_FP_NODE3 8 +#define R300_FP_CMDSIZE 9 + +#define R300_FPT_CMD_0 0 +#define R300_FPT_INSTR_0 1 +#define R300_FPT_CMDSIZE 65 + +#define R300_FPI_CMD_0 0 +#define R300_FPI_INSTR_0 1 +#define R300_FPI_CMDSIZE 65 + +#define R300_FPP_CMD_0 0 +#define R300_FPP_PARAM_0 1 +#define R300_FPP_CMDSIZE (32*4+1) + +#define R300_AT_CMD_0 0 +#define R300_AT_ALPHA_TEST 1 +#define R300_AT_UNKNOWN 2 +#define R300_AT_CMDSIZE 3 + +#define R300_BLD_CMD_0 0 +#define R300_BLD_CBLEND 1 +#define R300_BLD_ABLEND 2 +#define R300_BLD_CMDSIZE 3 + +#define R300_CMK_CMD_0 0 +#define R300_CMK_COLORMASK 1 +#define R300_CMK_CMDSIZE 2 + +#define R300_CB_CMD_0 0 +#define R300_CB_OFFSET 1 +#define R300_CB_CMD_1 2 +#define R300_CB_PITCH 3 +#define R300_CB_CMDSIZE 4 + +#define R300_ZS_CMD_0 0 +#define R300_ZS_CNTL_0 1 +#define R300_ZS_CNTL_1 2 +#define R300_ZS_CNTL_2 3 +#define R300_ZS_CMDSIZE 4 + +#define R300_ZB_CMD_0 0 +#define R300_ZB_OFFSET 1 +#define R300_ZB_PITCH 2 +#define R300_ZB_CMDSIZE 3 + +#define R300_VPI_CMD_0 0 +#define R300_VPI_INSTR_0 1 +#define R300_VPI_CMDSIZE 1025 /* 256 16 byte instructions */ + +#define R300_VPP_CMD_0 0 +#define R300_VPP_PARAM_0 1 +#define R300_VPP_CMDSIZE 1025 /* 256 4-component parameters */ + +#define R300_VPS_CMD_0 0 +#define R300_VPS_ZERO_0 1 +#define R300_VPS_ZERO_1 2 +#define R300_VPS_POINTSIZE 3 +#define R300_VPS_ZERO_3 4 +#define R300_VPS_CMDSIZE 5 + + /* the layout is common for all fields inside tex */ +#define R300_TEX_CMD_0 0 +#define R300_TEX_VALUE_0 1 +/* We don't really use this, instead specify mtu+1 dynamically +#define R300_TEX_CMDSIZE (MAX_TEXTURE_UNITS+1) +*/ + +/** + * Cache for hardware register state. + */ +struct r300_hw_state { + struct r300_state_atom atomlist; + + GLboolean is_dirty; + GLboolean all_dirty; + int max_state_size; /* in dwords */ + + struct r300_state_atom vpt; /* viewport (1D98) */ + struct r300_state_atom unk2080; /* (2080) */ + struct r300_state_atom vof; /* VAP output format register 0x2090 */ + struct r300_state_atom vte; /* (20B0) */ + struct r300_state_atom unk2134; /* (2134) */ + struct r300_state_atom unk2140; /* (2140) */ + struct r300_state_atom vir[2]; /* vap input route (2150/21E0) */ + struct r300_state_atom vic; /* vap input control (2180) */ + struct r300_state_atom unk21DC; /* (21DC) */ + struct r300_state_atom unk221C; /* (221C) */ + struct r300_state_atom unk2220; /* (2220) */ + struct r300_state_atom unk2288; /* (2288) */ + struct r300_state_atom pvs; /* pvs_cntl (22D0) */ + struct r300_state_atom gb_enable; /* (4008) */ + struct r300_state_atom gb_misc; /* Multisampling position shifts ? (4010) */ + struct r300_state_atom unk4200; /* (4200) */ + struct r300_state_atom unk4214; /* (4214) */ + struct r300_state_atom ps; /* pointsize (421C) */ + struct r300_state_atom unk4230; /* (4230) */ + struct r300_state_atom lcntl; /* line control */ + struct r300_state_atom unk4260; /* (4260) */ + struct r300_state_atom unk4274; /* (4274) */ + struct r300_state_atom unk4288; /* (4288) */ + struct r300_state_atom unk42A0; /* (42A0) */ + struct r300_state_atom zbs; /* zbias (42A4) */ + struct r300_state_atom unk42B4; /* (42B4) */ + struct r300_state_atom cul; /* cull cntl (42B8) */ + struct r300_state_atom unk42C0; /* (42C0) */ + struct r300_state_atom rc; /* rs control (4300) */ + struct r300_state_atom ri; /* rs interpolators (4310) */ + struct r300_state_atom rr; /* rs route (4330) */ + struct r300_state_atom unk43A4; /* (43A4) */ + struct r300_state_atom unk43E8; /* (43E8) */ + struct r300_state_atom fp; /* fragment program cntl + nodes (4600) */ + struct r300_state_atom fpt; /* texi - (4620) */ + struct r300_state_atom unk46A4; /* (46A4) */ + struct r300_state_atom fpi[4]; /* fp instructions (46C0/47C0/48C0/49C0) */ + struct r300_state_atom unk4BC0; /* (4BC0) */ + struct r300_state_atom unk4BC8; /* (4BC8) */ + struct r300_state_atom at; /* alpha test (4BD4) */ + struct r300_state_atom unk4BD8; /* (4BD8) */ + struct r300_state_atom fpp; /* 0x4C00 and following */ + struct r300_state_atom unk4E00; /* (4E00) */ + struct r300_state_atom bld; /* blending (4E04) */ + struct r300_state_atom cmk; /* colormask (4E0C) */ + struct r300_state_atom unk4E10; /* (4E10) */ + struct r300_state_atom cb; /* colorbuffer (4E28) */ + struct r300_state_atom unk4E50; /* (4E50) */ + struct r300_state_atom unk4E88; /* (4E88) */ + struct r300_state_atom unk4EA0; /* (4E88) I saw it only written on RV350 hardware.. */ + struct r300_state_atom zs; /* zstencil control (4F00) */ + struct r300_state_atom unk4F10; /* (4F10) */ + struct r300_state_atom zb; /* z buffer (4F20) */ + struct r300_state_atom unk4F28; /* (4F28) */ + struct r300_state_atom unk4F30; /* (4F30) */ + struct r300_state_atom unk4F44; /* (4F44) */ + struct r300_state_atom unk4F54; /* (4F54) */ + + struct r300_state_atom vpi; /* vp instructions */ + struct r300_state_atom vpp; /* vp parameters */ + struct r300_state_atom vps; /* vertex point size (?) */ + /* 8 texture units */ + /* the state is grouped by function and not by + texture unit. This makes single unit updates + really awkward - we are much better off + updating the whole thing at once */ + struct { + struct r300_state_atom filter; + struct r300_state_atom unknown1; + struct r300_state_atom size; + struct r300_state_atom format; + struct r300_state_atom offset; + struct r300_state_atom unknown4; + struct r300_state_atom border_color; + } tex; + struct r300_state_atom txe; /* tex enable (4104) */ +}; + + +/** + * This structure holds the command buffer while it is being constructed. + * + * The first batch of commands in the buffer is always the state that needs + * to be re-emitted when the context is lost. This batch can be skipped + * otherwise. + */ +struct r300_cmdbuf { + int size; /* DWORDs allocated for buffer */ + uint32_t* cmd_buf; + int count_used; /* DWORDs filled so far */ + int count_reemit; /* size of re-emission batch */ +}; + + +/** + * State cache + */ + +struct r300_depthbuffer_state { + GLfloat scale; +}; + +struct r300_stencilbuffer_state { + GLuint clear; + GLboolean hw_stencil; + +}; + +struct r300_vap_reg_state { + /* input register assigments */ + int i_coords; + int i_normal; + int i_color[2]; + int i_fog; + int i_tex[R300_MAX_TEXTURE_UNITS]; + int i_index; + int i_pointsize; + }; + +/* Vertex shader state */ + +/* Tested with rv350 and verified from misc web pages. */ +#define VSF_MAX_FRAGMENT_LENGTH (256*4) + +/* Tested with rv350 and verified from misc web pages. */ +#define VSF_MAX_FRAGMENT_TEMPS (32) + + +struct r300_vertex_shader_fragment { + int length; + union { + GLuint d[VSF_MAX_FRAGMENT_LENGTH]; + float f[VSF_MAX_FRAGMENT_LENGTH]; + VERTEX_SHADER_INSTRUCTION i[VSF_MAX_FRAGMENT_LENGTH/4]; + } body; + }; + +#define VSF_DEST_PROGRAM 0x0 +#define VSF_DEST_MATRIX0 0x200 +#define VSF_DEST_MATRIX1 0x204 +#define VSF_DEST_MATRIX2 0x208 +#define VSF_DEST_VECTOR0 0x20c +#define VSF_DEST_VECTOR1 0x20d +#define VSF_DEST_UNKNOWN1 0x400 +#define VSF_DEST_UNKNOWN2 0x406 + +struct r300_vertex_shader_state { + struct r300_vertex_shader_fragment program; + + /* a bit of a waste - each uses only a subset of allocated space.. + but easier to program */ + struct r300_vertex_shader_fragment matrix[3]; + struct r300_vertex_shader_fragment vector[2]; + + struct r300_vertex_shader_fragment unknown1; + struct r300_vertex_shader_fragment unknown2; + + int program_start; + int unknown_ptr1; /* pointer within program space */ + int program_end; + + int param_offset; + int param_count; + + int unknown_ptr2; /* pointer within program space */ + int unknown_ptr3; /* pointer within program space */ + }; + +extern int hw_tcl_on; + +#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Enabled ? ctx->VertexProgram.Current : ctx->_TnlProgram) + +//#define TMU_ENABLED(ctx, unit) (hw_tcl_on ? ctx->Texture.Unit[unit]._ReallyEnabled && (OutputsWritten & (1<<(VERT_RESULT_TEX0+(unit)))) : +// (r300->state.render_inputs & (_TNL_BIT_TEX0<<(unit)))) +#define TMU_ENABLED(ctx, unit) (hw_tcl_on ? ctx->Texture.Unit[unit]._ReallyEnabled && OutputsWritten & (1<<(VERT_RESULT_TEX0+(unit))) : \ + ctx->Texture.Unit[unit]._ReallyEnabled && r300->state.render_inputs & (_TNL_BIT_TEX0<<(unit))) + +/* r300_vertex_shader_state and r300_vertex_program should probably be merged together someday. + * Keeping them them seperate for now should ensure fixed pipeline keeps functioning properly. + */ +struct r300_vertex_program { + struct vertex_program mesa_program; /* Must be first */ + int translated; + + struct r300_vertex_shader_fragment program; + struct r300_vertex_shader_fragment params; + + int pos_end; + unsigned long num_temporaries; /* Number of temp vars used by program */ + int inputs[VERT_ATTRIB_MAX]; + int outputs[VERT_RESULT_MAX]; +}; + +#if USE_ARB_F_P == 1 +#define PFS_MAX_ALU_INST 64 +#define PFS_MAX_TEX_INST 64 +#define PFS_MAX_TEX_INDIRECT 4 +#define PFS_NUM_TEMP_REGS 32 +#define PFS_NUM_CONST_REGS 32 +struct r300_fragment_program { + struct fragment_program mesa_program; + + GLcontext *ctx; + GLboolean translated; + GLboolean error; + + struct { + int length; + GLuint inst[PFS_MAX_TEX_INST]; + } tex; + + struct { + struct { + GLuint inst0; + GLuint inst1; + GLuint inst2; + GLuint inst3; + } inst[PFS_MAX_ALU_INST]; + } alu; + int v_pos; + int s_pos; + + struct { + int tex_offset; + int tex_end; + int alu_offset; + int alu_end; + } node[4]; + int cur_node; + int first_node_has_tex; + + int alu_offset; + int alu_end; + int tex_offset; + int tex_end; + + /* Hardware constants */ + GLfloat constant[PFS_NUM_CONST_REGS][4]; + int const_nr; + + /* Tracked parameters */ + struct { + int idx; /* hardware index */ + GLfloat *values; /* pointer to values */ + } param[PFS_NUM_CONST_REGS]; + int param_nr; + GLboolean params_uptodate; + + GLuint temps[PFS_NUM_TEMP_REGS]; + int temp_in_use; + GLuint used_in_node; + GLuint dest_in_node; + GLuint inputs[32]; /* don't actually need 32... */ + + int hwreg_in_use; + int max_temp_idx; +}; + +#else +/* 64 appears to be the maximum */ +#define PSF_MAX_PROGRAM_LENGTH 64 + +struct r300_pixel_shader_program { + struct { + int length; + GLuint inst[PSF_MAX_PROGRAM_LENGTH]; + } tex; + + /* ALU intructions (logic and integer) */ + struct { + int length; + struct { + GLuint inst0; + GLuint inst1; + GLuint inst2; + GLuint inst3; + } inst[PSF_MAX_PROGRAM_LENGTH]; + } alu; + + /* node information */ + /* nodes are used to synchronize ALU and TEX streams */ + /* There could be up to 4 nodes each consisting of + a number of TEX instructions followed by some ALU + instructions */ + /* the last node of a program should always be node3 */ + struct { + int tex_offset; + int tex_end; + int alu_offset; + int alu_end; + } node[4]; + + int active_nodes; /* must be between 1 and 4, inclusive */ + int first_node_has_tex; /* other nodes always have it */ + + int temp_register_count; /* magic value goes into PFS_CNTL_1 */ + + /* entire program */ + int tex_offset; + int tex_end; + int alu_offset; + int alu_end; + + }; + +#define MAX_PIXEL_SHADER_PARAMS 32 +struct r300_pixel_shader_state { + struct r300_pixel_shader_program program; + + int translated; + int have_sample; + GLuint color_reg; + GLuint src_previous; + + /* parameters */ + int param_length; /* to limit the number of unnecessary writes */ + struct { + float x; + float y; + float z; + float w; + } param[MAX_PIXEL_SHADER_PARAMS]; + }; +#endif // USE_ARB_F_P + +/* 8 is somewhat bogus... it is probably something like 24 */ +#define R300_MAX_AOS_ARRAYS 16 + +#define AOS_FORMAT_FLOAT 1 +#define AOS_FORMAT_UBYTE 2 +#define AOS_FORMAT_FLOAT_COLOR 3 + +#define REG_COORDS 0 +#define REG_COLOR0 1 +#define REG_TEX0 2 + +struct r300_aos_rec { + GLuint offset; + int element_size; /* in dwords */ + int stride; /* distance between elements, in dwords */ + + int format; + + int ncomponents; /* number of components - between 1 and 4, inclusive */ + + int reg; /* which register they are assigned to. */ + + }; + +struct r300_state { + struct r300_depthbuffer_state depth; + struct r300_texture_state texture; + struct r300_vap_reg_state vap_reg; + struct r300_vertex_shader_state vertex_shader; +#if USE_ARB_F_P == 0 + struct r300_pixel_shader_state pixel_shader; +#endif + struct r300_dma_region aos[R300_MAX_AOS_ARRAYS]; + int aos_count; + + GLuint *Elts; + struct r300_dma_region elt_dma; + + GLuint render_inputs; /* actual render inputs that R300 was configured for. + They are the same as tnl->render_inputs for fixed pipeline */ + + struct { + int transform_offset; /* Transform matrix offset, -1 if none */ + } vap_param; /* vertex processor parameter allocation - tells where to write parameters */ + + struct r300_stencilbuffer_state stencil; + +}; + + +/** + * R300 context structure. + */ +struct r300_context { + struct radeon_context radeon; /* parent class, must be first */ + + struct r300_hw_state hw; + struct r300_cmdbuf cmdbuf; + struct r300_state state; + + /* Vertex buffers + */ + struct r300_dma dma; + GLboolean save_on_next_unlock; + + /* Texture object bookkeeping + */ + unsigned nr_heaps; + driTexHeap *texture_heaps[R200_NR_TEX_HEAPS]; + driTextureObject swapped; + int texture_depth; + float initialMaxAnisotropy; + + /* Clientdata textures; + */ + GLuint prefer_gart_client_texturing; + + /* TCL stuff + */ + GLmatrix TexGenMatrix[R300_MAX_TEXTURE_UNITS]; + GLboolean recheck_texgen[R300_MAX_TEXTURE_UNITS]; + GLboolean TexGenNeedNormals[R300_MAX_TEXTURE_UNITS]; + GLuint TexMatEnabled; + GLuint TexMatCompSel; + GLuint TexGenEnabled; + GLuint TexGenInputs; + GLuint TexGenCompSel; + GLmatrix tmpmat; +}; + +#define R300_CONTEXT(ctx) ((r300ContextPtr)(ctx->DriverCtx)) + +static __inline GLuint r300PackColor( GLuint cpp, + GLubyte r, GLubyte g, + GLubyte b, GLubyte a ) +{ + switch ( cpp ) { + case 2: + return PACK_COLOR_565( r, g, b ); + case 4: + return PACK_COLOR_8888( r, g, b, a ); + default: + return 0; + } +} +extern void r300DestroyContext(__DRIcontextPrivate * driContextPriv); +extern GLboolean r300CreateContext(const __GLcontextModes * glVisual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate); + +void translate_vertex_shader(struct r300_vertex_program *vp); +extern void r300InitShaderFuncs(struct dd_function_table *functions); +extern void r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp); + +#endif /* __R300_CONTEXT_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_emit.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_emit.h new file mode 100644 index 000000000..c7cb93d0a --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_emit.h @@ -0,0 +1,282 @@ +#ifndef __EMIT_H__ +#define __EMIT_H__ +#include "glheader.h" +#include "r300_context.h" +#include "r300_cmdbuf.h" + +/* convenience macros */ +#define RADEON_CP_PACKET0 0x00000000 +#define RADEON_CP_PACKET1 0x40000000 +#define RADEON_CP_PACKET2 0x80000000 +#define RADEON_CP_PACKET3 0xC0000000 + +#define RADEON_CP_PACKET3_NOP 0xC0001000 +#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900 +#define RADEON_CP_PACKET3_UNK1B 0xC0001B00 +#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00 +#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00 +#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 +#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400 +#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600 +#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800 +#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 +#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 +#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 +#define RADEON_CP_PACKET3_INDX_BUFFER 0xC0003300 +#define RADEON_CP_PACKET3_3D_DRAW_VBUF_2 0xC0003400 +#define RADEON_CP_PACKET3_3D_DRAW_IMMD_2 0xC0003500 +#define RADEON_CP_PACKET3_3D_DRAW_INDX_2 0xC0003600 +#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 +#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 +#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 +#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300 +#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 +#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500 +#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800 +#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 +#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 +#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 +#define RADEON_CP_PACKET3_3D_CLEAR_ZMASK 0xC0003202 +#define RADEON_CP_PACKET3_3D_CLEAR_CMASK 0xC0003802 +#define RADEON_CP_PACKET3_3D_CLEAR_HIZ 0xC0003702 + +#define CP_PACKET0(reg, n) (RADEON_CP_PACKET0 | ((n)<<16) | ((reg)>>2)) + +/* Glue to R300 Mesa driver */ +#define LOCAL_VARS int cmd_reserved=0;\ + int cmd_written=0; \ + drm_radeon_cmd_header_t *cmd=NULL; + +#define PREFIX_VOID r300ContextPtr rmesa + +#define PREFIX PREFIX_VOID , + +#define PASS_PREFIX_VOID rmesa +#define PASS_PREFIX rmesa , + +typedef GLuint CARD32; + +/* This files defines functions for accessing R300 hardware. + It needs to be customized to whatever code r300_lib.c is used + in */ + +void static inline check_space(int dwords) +{ +} + +static __inline__ uint32_t cmdpacket0(int reg, int count) +{ + drm_r300_cmd_header_t cmd; + + cmd.packet0.cmd_type = R300_CMD_PACKET0; + cmd.packet0.count = count; + cmd.packet0.reghi = ((unsigned int)reg & 0xFF00) >> 8; + cmd.packet0.reglo = ((unsigned int)reg & 0x00FF); + + return cmd.u; +} + +static __inline__ uint32_t cmdvpu(int addr, int count) +{ + drm_r300_cmd_header_t cmd; + + cmd.vpu.cmd_type = R300_CMD_VPU; + cmd.vpu.count = count; + cmd.vpu.adrhi = ((unsigned int)addr & 0xFF00) >> 8; + cmd.vpu.adrlo = ((unsigned int)addr & 0x00FF); + + return cmd.u; +} + +static __inline__ uint32_t cmdpacket3(int packet) +{ + drm_r300_cmd_header_t cmd; + + cmd.packet3.cmd_type = R300_CMD_PACKET3; + cmd.packet3.packet = packet; + + return cmd.u; +} + +static __inline__ uint32_t cmdcpdelay(unsigned short count) +{ + drm_r300_cmd_header_t cmd; + + cmd.delay.cmd_type = R300_CMD_CP_DELAY; + cmd.delay.count = count; + + return cmd.u; +} + +static __inline__ uint32_t cmdwait(unsigned char flags) +{ + drm_r300_cmd_header_t cmd; + + cmd.wait.cmd_type = R300_CMD_WAIT; + cmd.wait.flags = flags; + + return cmd.u; +} + +static __inline__ uint32_t cmdpacify(void) +{ + drm_r300_cmd_header_t cmd; + + cmd.header.cmd_type = R300_CMD_END3D; + + return cmd.u; +} + +/* Prepare to write a register value to register at address reg. + If num_extra > 0 then the following extra values are written + to registers with address +4, +8 and so on.. */ +#define reg_start(reg, num_extra) \ + { \ + int _n; \ + _n=(num_extra); \ + cmd=(drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, \ + (_n+2), \ + __FUNCTION__); \ + cmd_reserved=_n+2; \ + cmd_written=1; \ + cmd[0].i=cmdpacket0((reg), _n+1); \ + } + +/* Prepare to write a register value to register at address reg. + If num_extra > 0 then the following extra values are written + into the same register. */ +/* It is here to permit r300_lib to compile and link anyway, but + complain if actually called */ +#define reg_start_pump(reg, num_extra) \ + { \ + fprintf(stderr, "I am not defined.. Error ! in %s::%s at line %d\n", \ + __FILE__, __FUNCTION__, __LINE__); \ + exit(-1); \ + } + +/* Emit CARD32 freestyle*/ +#define e32(dword) { \ + if(cmd_written<cmd_reserved){\ + cmd[cmd_written].i=(dword); \ + cmd_written++; \ + } else { \ + fprintf(stderr, "e32 but no previous packet declaration.. Aborting! in %s::%s at line %d, cmd_written=%d cmd_reserved=%d\n", \ + __FILE__, __FUNCTION__, __LINE__, cmd_written, cmd_reserved); \ + exit(-1); \ + } \ + } + +#define efloat(f) e32(r300PackFloat32(f)) + +#define vsf_start_fragment(dest, length) \ + { \ + int _n; \ + _n=(length); \ + cmd=(drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, \ + (_n+1), \ + __FUNCTION__); \ + cmd_reserved=_n+2; \ + cmd_written=1; \ + cmd[0].i=cmdvpu((dest), _n/4); \ + } + +#define start_packet3(packet, count) \ + { \ + int _n; \ + CARD32 _p; \ + _n=(count); \ + _p=(packet); \ + cmd=(drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, \ + (_n+3), \ + __FUNCTION__); \ + cmd_reserved=_n+3; \ + cmd_written=2; \ + if(_n>0x3fff) {\ + fprintf(stderr,"Too big packet3 %08x: cannot store %d dwords\n", \ + _p, _n); \ + exit(-1); \ + } \ + cmd[0].i=cmdpacket3(R300_CMD_PACKET3_RAW); \ + cmd[1].i=_p | ((_n & 0x3fff)<<16); \ + } + + /* must be sent to switch to 2d commands */ + +void static inline end_3d(PREFIX_VOID) +{ +LOCAL_VARS +(void)cmd_reserved; (void)cmd_written; + +cmd=(drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, \ + 1, \ + __FUNCTION__); \ + +cmd[0].header.cmd_type=R300_CMD_END3D; +} + +void static inline cp_delay(PREFIX unsigned short count) +{ +LOCAL_VARS +(void)cmd_reserved; (void)cmd_written; + +cmd=(drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, \ + 1, \ + __FUNCTION__); \ + +cmd[0].i=cmdcpdelay(count); +} + +void static inline cp_wait(PREFIX unsigned char flags) +{ +LOCAL_VARS +(void)cmd_reserved; (void)cmd_written; + +cmd=(drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, \ + 1, \ + __FUNCTION__); \ + +cmd[0].i=cmdwait(flags); +} + +/* fire vertex buffer */ +static void inline fire_AOS(PREFIX int vertex_count, int type) +{ +LOCAL_VARS +check_space(9); + +start_packet3(RADEON_CP_PACKET3_3D_DRAW_VBUF_2, 0); +/* e32(0x840c0024); */ + e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count<<16) | type); +} + +/* these are followed by the corresponding data */ +#define start_index32_packet(vertex_count, type) \ + {\ + int _vc;\ + _vc=(vertex_count); \ + start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, _vc); \ + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (_vc<<16) | type \ + | R300_VAP_VF_CNTL__INDEX_SIZE_32bit); \ + } + +#define start_index16_packet(vertex_count, type) \ + {\ + int _vc, _n;\ + _vc=(vertex_count); \ + _n=(vertex_count+1)>>1; \ + start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, _n); \ + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (_vc<<16) | type); \ + } + +/* Interestingly enough this ones needs the call to setup_AOS, even thought + some of the data so setup is not needed and some is not as arbitrary + as when used by DRAW_VBUF_2 or DRAW_INDX_2 */ +#define start_immediate_packet(vertex_count, type, vertex_size) \ + {\ + int _vc; \ + _vc=(vertex_count); \ + start_packet3(RADEON_CP_PACKET3_3D_DRAW_IMMD_2, _vc*(vertex_size)); \ + e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (_vc<<16) | type); \ + } + +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fixed_pipelines.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fixed_pipelines.h new file mode 100644 index 000000000..65e1836af --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fixed_pipelines.h @@ -0,0 +1,294 @@ +#ifndef __R300_FIXED_PIPELINES_H__ +#define __R300_FIXED_PIPELINES_H__ + +/******** Flat color pipeline **********/ +static struct r300_vertex_shader_state FLAT_COLOR_VERTEX_SHADER={ + program: { + length: 20, + + body:{ d: { + EASY_VSF_OP(MUL, 0, ALL, TMP), + VSF_PARAM(3), + VSF_ATTR_W(0), + EASY_VSF_SOURCE(0, W, W, W, W, NONE, NONE), + + EASY_VSF_OP(MUL, 1, ALL, RESULT), + VSF_REG(1), + VSF_ATTR_UNITY(1), + VSF_UNITY(1), + + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(2), + VSF_ATTR_Z(0), + VSF_TMP(0), + + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(1), + VSF_ATTR_Y(0), + VSF_TMP(0), + + EASY_VSF_OP(MAD, 0, ALL, RESULT), + VSF_PARAM(0), + VSF_ATTR_X(0), + VSF_TMP(0), + } } + }, + + matrix:{ + { + length: 16, + body: { f: { + 2.0, + 0, + 0.0, + 0.0, + 0, + 2.5, + 0, + 0, + 0.0, + 0, + -1.00, + -1.0, + -3.0, + 0, + 6.0, + 6.0 + } } + }, + { + length: 0, + }, + { + length: 0, + } + }, + + vector: { + { + length: 0, + }, + { + length: 0, + } + }, + + unknown1: { + length: 0 + }, + + unknown2: { + length: 0 + }, + + program_start: 0, + unknown_ptr1: 4, + program_end: 4, + + param_offset: 0, + param_count: 4, + + unknown_ptr2: 0, + unknown_ptr3: 4 + }; + +static struct r300_pixel_shader_state FLAT_COLOR_PIXEL_SHADER={ + program: { + tex: { + length: 0 + }, + alu: { + length: 1, + /* My understanding is that we need at least 1 instructions for pixel shader, + in particular because alu_end==0 means there is one instruction */ + inst: { + PFS_NOP + } + }, + node: { + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0} + }, + active_nodes: 1, + first_node_has_tex: 0, + temp_register_count: 0, + + tex_offset: 0, + tex_end: 0, + alu_offset: 0, + alu_end: 0 + }, + + param_length: 0 + }; + + +/******** Single texture pipeline ***********/ +static struct r300_vertex_shader_state SINGLE_TEXTURE_VERTEX_SHADER={ + program: { + length: 24, + + body: { d: { + EASY_VSF_OP(MUL, 0, ALL, TMP), + VSF_PARAM(3), + VSF_ATTR_W(0), + EASY_VSF_SOURCE(0, W, W, W, W, NONE, NONE), + + EASY_VSF_OP(MUL, 2, ALL, RESULT), + VSF_REG(2), + VSF_ATTR_UNITY(2), + VSF_UNITY(2), + + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(2), + VSF_ATTR_Z(0), + VSF_TMP(0), + + EASY_VSF_OP(MUL, 1, ALL, RESULT), + VSF_REG(1), + VSF_ATTR_UNITY(1), + VSF_UNITY(1), + + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(1), + VSF_ATTR_Y(0), + VSF_TMP(0), + + EASY_VSF_OP(MAD, 0, ALL, RESULT), + VSF_PARAM(0), + VSF_ATTR_X(0), + VSF_TMP(0), + } } + }, + + matrix:{ + { + length: 16, + body: { f: { + 2.0, + 0, + 0.0, + 0.0, + 0, + 2.5, + 0, + 0, + 0.0, + 0, + -1.00, + -1.0, + -3.0, + 0, + 6.0, + 6.0 + } } + }, + { + length: 0, + }, + { + length: 0, + } + }, + + vector: { + { + length: 0, + }, + { + length: 0, + } + }, + + unknown1: { + length: 0 + }, + + unknown2: { + length: 4, + body: { f: { + 0.0, + 0.0, + 1.0, + 0.0 + } } + }, + + program_start: 0, + unknown_ptr1: 5, + program_end: 5, + + param_offset: 0, + param_count: 4, + + unknown_ptr2: 0, + unknown_ptr3: 5 + }; + +static struct r300_pixel_shader_state SINGLE_TEXTURE_PIXEL_SHADER={ + program: { + tex: { + length: 1, + inst: { 0x00018000 } + }, + alu: { + length: 2, + inst: + { +/* I get misc problems without this after doing cold-reboot. + This would imply that alu programming is buggy. --aet */ +#if 1 + PFS_NOP, +#endif + + /* What are 0's ORed with flags ? They are register numbers that + just happen to be 0 */ + { + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, SRC1C_XYZ, ZERO), + EASY_PFS_INSTR1(0, 0, 1, 0 | PFS_FLAG_CONST, NONE, ALL), + +#if 0 + /* no alpha in textures */ + EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO), + EASY_PFS_INSTR3(0, 1, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT) +#endif + + /* alpha in textures */ + EASY_PFS_INSTR2(MAD, SRC0A, SRC1A, ZERO), + EASY_PFS_INSTR3(0, 0, 1, 0 | PFS_FLAG_CONST, OUTPUT) + } + } + }, + node: { + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0} + }, + + active_nodes: 1, + first_node_has_tex: 1, + temp_register_count: 1, + + tex_offset: 0, + tex_end: 0, + alu_offset: 0, + alu_end: 0 + }, + + param_length: 8, + param: { + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0, 0.0} + } + }; + +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog.c new file mode 100644 index 000000000..8750ff60c --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog.c @@ -0,0 +1,1090 @@ +/* + * Copyright (C) 2005 Ben Skeggs. + * + * 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. + * + */ + +/* + * Authors: + * Ben Skeggs <darktama@iinet.net.au> + */ + +/*TODO'S + * + * - Implement remaining arb_f_p opcodes + * - Depth write + * - Negate on individual components (implement in swizzle code?) + * - Reuse input/temp regs, if they're no longer needed. + * - Find out whether there's any benifit in ordering registers the way + * fglrx does (see r300_reg.h). + * - Verify results of opcodes for accuracy, I've only checked them + * in specific cases. + * - and more... + */ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" +#include "arbfragparse.h" + +#include "program.h" +#include "nvfragprog.h" +#include "r300_context.h" +#if USE_ARB_F_P == 1 +#include "r300_fragprog.h" +#include "r300_reg.h" + +#define PFS_INVAL 0xFFFFFFFF + +static void dump_program(struct r300_fragment_program *rp); +static void emit_arith(struct r300_fragment_program *rp, int op, + pfs_reg_t dest, int mask, + pfs_reg_t src0, pfs_reg_t src1, pfs_reg_t src2, + int flags); + +/*************************************** + * begin: useful data structions for fragment program generation + ***************************************/ + +/* description of r300 native hw instructions */ +const struct { + const char *name; + int argc; + int v_op; + int s_op; +} r300_fpop[] = { + { "MAD", 3, R300_FPI0_OUTC_MAD, R300_FPI2_OUTA_MAD }, + { "DP3", 2, R300_FPI0_OUTC_DP3, PFS_INVAL }, + { "DP4", 2, R300_FPI0_OUTC_DP4, R300_FPI2_OUTA_DP4 }, + { "MIN", 2, R300_FPI0_OUTC_MIN, R300_FPI2_OUTA_MIN }, + { "MAX", 2, R300_FPI0_OUTC_MAX, R300_FPI2_OUTA_MAX }, + { "CMP", 3, R300_FPI0_OUTC_CMP, R300_FPI2_OUTA_CMP }, + { "FRC", 1, R300_FPI0_OUTC_FRC, R300_FPI2_OUTA_FRC }, + { "EX2", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_EX2 }, + { "LG2", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_LG2 }, + { "RCP", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_RCP }, + { "RSQ", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_RSQ }, + { "REPL_ALPHA", 1, R300_FPI0_OUTC_REPL_ALPHA, PFS_INVAL } +}; + +#define MAKE_SWZ3(x, y, z) (MAKE_SWIZZLE4(SWIZZLE_##x, \ + SWIZZLE_##y, \ + SWIZZLE_##z, \ + SWIZZLE_ZERO)) + +/* vector swizzles r300 can support natively, with a couple of + * cases we handle specially + * + * pfs_reg_t.v_swz/pfs_reg_t.s_swz is an index into this table + **/ +static const struct r300_pfv_swizzle { + const char *name; + GLuint hash; /* swizzle value this matches */ + GLboolean native; + GLuint base; /* base value for hw swizzle */ + GLuint stride; /* difference in base between arg0/1/2 */ + GLboolean dep_sca; +} v_swiz[] = { +/* native swizzles */ + { "xyz", MAKE_SWZ3(X, Y, Z), GL_TRUE, R300_FPI0_ARGC_SRC0C_XYZ, 4, GL_FALSE }, + { "xxx", MAKE_SWZ3(X, X, X), GL_TRUE, R300_FPI0_ARGC_SRC0C_XXX, 4, GL_FALSE }, + { "yyy", MAKE_SWZ3(Y, Y, Y), GL_TRUE, R300_FPI0_ARGC_SRC0C_YYY, 4, GL_FALSE }, + { "zzz", MAKE_SWZ3(Z, Z, Z), GL_TRUE, R300_FPI0_ARGC_SRC0C_ZZZ, 4, GL_FALSE }, + { "www", MAKE_SWZ3(W, W, W), GL_TRUE, R300_FPI0_ARGC_SRC0A, 1, GL_TRUE }, + { "yzx", MAKE_SWZ3(Y, Z, X), GL_TRUE, R300_FPI0_ARGC_SRC0C_YZX, 1, GL_FALSE }, + { "zxy", MAKE_SWZ3(Z, X, Y), GL_TRUE, R300_FPI0_ARGC_SRC0C_ZXY, 1, GL_FALSE }, +/* disable this for now, until I find a clean way of making sure xyz/w streams + * have a source in the same register slot.. */ +// { "wzy", MAKE_SWZ3(W, Z, Y), GL_TRUE, R300_FPI0_ARGC_SRC0CA_WZY, 1, GL_TRUE }, +/* special cases */ + { NULL, MAKE_SWZ3(ONE, ONE, ONE), GL_FALSE, R300_FPI0_ARGC_ONE, 0, GL_FALSE}, + { NULL, MAKE_SWZ3(ZERO, ZERO, ZERO), GL_FALSE, R300_FPI0_ARGC_ZERO, 0, GL_FALSE}, + { NULL, PFS_INVAL, GL_FALSE, R300_FPI0_ARGC_HALF, 0, GL_FALSE}, + { NULL, PFS_INVAL, GL_FALSE, 0, 0, 0 }, +}; +#define SWIZZLE_XYZ 0 +#define SWIZZLE_XXX 1 +#define SWIZZLE_WWW 4 +#define SWIZZLE_111 7 +#define SWIZZLE_000 8 +#define SWIZZLE_HHH 9 + +#define SWZ_X_MASK (7 << 0) +#define SWZ_Y_MASK (7 << 3) +#define SWZ_Z_MASK (7 << 6) +#define SWZ_W_MASK (7 << 9) +/* used during matching of non-native swizzles */ +static const struct { + GLuint hash; /* used to mask matching swizzle components */ + int mask; /* actual outmask */ + int count; /* count of components matched */ +} s_mask[] = { + { SWZ_X_MASK|SWZ_Y_MASK|SWZ_Z_MASK, 1|2|4, 3}, + { SWZ_X_MASK|SWZ_Y_MASK, 1|2, 2}, + { SWZ_X_MASK|SWZ_Z_MASK, 1|4, 2}, + { SWZ_Y_MASK|SWZ_Z_MASK, 2|4, 2}, + { SWZ_X_MASK, 1, 1}, + { SWZ_Y_MASK, 2, 1}, + { SWZ_Z_MASK, 4, 1}, + { PFS_INVAL, PFS_INVAL, PFS_INVAL} +}; + +/* mapping from SWIZZLE_* to r300 native values for scalar insns */ +static const struct { + const char *name; + int base; /* hw value of swizzle */ + int stride; /* difference between SRC0/1/2 */ + GLboolean dep_vec; +} s_swiz[] = { + { "x", R300_FPI2_ARGA_SRC0C_X, 3, GL_TRUE }, + { "y", R300_FPI2_ARGA_SRC0C_Y, 3, GL_TRUE }, + { "z", R300_FPI2_ARGA_SRC0C_Z, 3, GL_TRUE }, + { "w", R300_FPI2_ARGA_SRC0A , 1, GL_FALSE }, + { "0", R300_FPI2_ARGA_ZERO , 0, GL_FALSE }, + { "1", R300_FPI2_ARGA_ONE , 0, GL_FALSE }, + { ".5", R300_FPI2_ARGA_HALF, 0, GL_FALSE } +}; +#define SWIZZLE_HALF 6 + +/* boiler-plate reg, for convenience */ +const pfs_reg_t pfs_default_reg = { + type: REG_TYPE_TEMP, + index: 0, + v_swz: 0 /* matches XYZ in table */, + s_swz: SWIZZLE_W, + negate: 0, + valid: GL_FALSE +}; + +/* constant zero source */ +const pfs_reg_t pfs_one = { + type: REG_TYPE_CONST, + index: 0, + v_swz: SWIZZLE_111, + s_swz: SWIZZLE_ONE, + valid: GL_TRUE +}; + +/* constant one source */ +const pfs_reg_t pfs_zero = { + type: REG_TYPE_CONST, + index: 0, + v_swz: SWIZZLE_000, + s_swz: SWIZZLE_ZERO, + valid: GL_TRUE +}; + +/*************************************** + * end: data structures + ***************************************/ + +#define ERROR(fmt, args...) do { \ + fprintf(stderr, "%s::%s(): " fmt "\n", __FILE__, __func__, ##args); \ + rp->error = GL_TRUE; \ +} while(0) + +static int get_hw_temp(struct r300_fragment_program *rp) +{ + int r = ffs(~rp->hwreg_in_use); + if (!r) { + ERROR("Out of hardware temps\n"); + return 0; + } + + rp->hwreg_in_use |= (1 << --r); + if (r > rp->max_temp_idx) + rp->max_temp_idx = r; + + return r; +} + +static void free_hw_temp(struct r300_fragment_program *rp, int idx) +{ + rp->hwreg_in_use &= ~(1<<idx); +} + +static pfs_reg_t get_temp_reg(struct r300_fragment_program *rp) +{ + pfs_reg_t r = pfs_default_reg; + + r.index = ffs(~rp->temp_in_use); + if (!r.index) { + ERROR("Out of program temps\n"); + return r; + } + rp->temp_in_use |= (1 << --r.index); + + rp->temps[r.index] = get_hw_temp(rp); + r.valid = GL_TRUE; + return r; +} + +static pfs_reg_t get_temp_reg_tex(struct r300_fragment_program *rp) +{ + pfs_reg_t r = pfs_default_reg; + int hwreg; + + hwreg = ffs(~(rp->hwreg_in_use | rp->used_in_node)); + if (!hwreg) { + /* Try and grab an already used temp, will + * cause an indirection, but better than failing */ + return get_temp_reg(rp); + } + if (hwreg > rp->max_temp_idx) + rp->max_temp_idx = hwreg; + + r.index = ffs(~rp->temp_in_use); + if (!r.index) { + ERROR("Out of program temps\n"); + return r; + } + rp->temp_in_use |= (1 << --r.index); + rp->temps[r.index] = --hwreg; + + r.valid = GL_TRUE; + return r; +} + +static void free_temp(struct r300_fragment_program *rp, pfs_reg_t r) +{ + if (!rp || !(rp->temp_in_use & (1<<r.index))) return; + + free_hw_temp(rp, rp->temps[r.index]); + rp->temp_in_use &= ~(1<<r.index); +} + +static pfs_reg_t emit_param4fv(struct r300_fragment_program *rp, GLfloat *values) +{ + pfs_reg_t r = pfs_default_reg; + int pidx; + + r.type = REG_TYPE_CONST; + pidx = rp->param_nr++; + r.index = rp->const_nr++; + if (pidx >= PFS_NUM_CONST_REGS || r.index >= PFS_NUM_CONST_REGS) { + ERROR("Out of const/param slots!\n"); + return r; + } + + rp->param[pidx].idx = r.index; + rp->param[pidx].values = values; + rp->params_uptodate = GL_FALSE; + + r.valid = GL_TRUE; + return r; +} + +static pfs_reg_t emit_const4fv(struct r300_fragment_program *rp, GLfloat *cp) +{ + pfs_reg_t r = pfs_default_reg; + r.type = REG_TYPE_CONST; + + r.index = rp->const_nr++; + if (r.index >= PFS_NUM_CONST_REGS) { + ERROR("Out of hw constants!\n"); + return r; + } + + COPY_4V(rp->constant[r.index], cp); + + r.valid = GL_TRUE; + return r; +} + +static pfs_reg_t negate(pfs_reg_t r) +{ + r.negate = 1; + return r; +} + +static int swz_native(struct r300_fragment_program *rp, + pfs_reg_t src, pfs_reg_t *r) +{ + /* Native swizzle, nothing to see here */ + *r = src; + return 3; +} + +static int swz_emit_partial(struct r300_fragment_program *rp, + pfs_reg_t src, pfs_reg_t *r, int mask, int mc) +{ + if (!r->valid) + *r = get_temp_reg(rp); + + /* A partial match, src.v_swz/mask define what parts of the + * desired swizzle we match */ + if (mc + s_mask[mask].count == 3) + emit_arith(rp, PFS_OP_MAD, *r, s_mask[mask].mask|WRITEMASK_W, src, pfs_one, pfs_zero, 0); + else + emit_arith(rp, PFS_OP_MAD, *r, s_mask[mask].mask, src, pfs_one, pfs_zero, 0); + return s_mask[mask].count; +} + +static int swz_special_case(struct r300_fragment_program *rp, + pfs_reg_t src, pfs_reg_t *r, int mask, int mc) +{ + switch(GET_SWZ(v_swiz[src.v_swz].hash, 0)) { + case SWIZZLE_ONE: + case SWIZZLE_ZERO: + if (!r->valid) + *r = get_temp_reg(rp); + if (mc + s_mask[mask].count == 3) + emit_arith(rp, PFS_OP_MAD, *r, s_mask[mask].mask|WRITEMASK_W, src, pfs_one, pfs_zero, 0); + else + emit_arith(rp, PFS_OP_MAD, *r, s_mask[mask].mask, src, pfs_one, pfs_zero, 0); + break; + default: + ERROR("Unknown special-case swizzle! %d\n", src.v_swz); + return 0; + } + + return s_mask[mask].count; +} + +static pfs_reg_t swizzle(struct r300_fragment_program *rp, + pfs_reg_t src, + GLuint arbswz) +{ + pfs_reg_t r = pfs_default_reg; + + int c_mask = 0; + int v_matched = 0; + src.v_swz = SWIZZLE_XYZ; + src.s_swz = GET_SWZ(arbswz, 3); + + do { + do { +#define CUR_HASH (v_swiz[src.v_swz].hash & s_mask[c_mask].hash) + if (CUR_HASH == (arbswz & s_mask[c_mask].hash)) { + if (v_swiz[src.v_swz].native == GL_FALSE) + v_matched += swz_special_case(rp, src, &r, c_mask, v_matched); + else if (s_mask[c_mask].count == 3) + v_matched += swz_native(rp, src, &r); + else + v_matched += swz_emit_partial(rp, src, &r, c_mask, v_matched); + + if (v_matched == 3) + return r; + + /* Fill with something invalid.. all 0's was wrong before, matched + * SWIZZLE_X. So all 1's will be okay for now */ + arbswz |= (PFS_INVAL & s_mask[c_mask].hash); + } + } while(v_swiz[++src.v_swz].hash != PFS_INVAL); + src.v_swz = SWIZZLE_XYZ; + } while (s_mask[++c_mask].hash != PFS_INVAL); + + ERROR("should NEVER get here\n"); + return r; +} + +static pfs_reg_t t_src(struct r300_fragment_program *rp, + struct fp_src_register fpsrc) { + pfs_reg_t r = pfs_default_reg; + + switch (fpsrc.File) { + case PROGRAM_TEMPORARY: + r.index = fpsrc.Index; + r.valid = GL_TRUE; + break; + case PROGRAM_INPUT: + r.index = fpsrc.Index; + r.type = REG_TYPE_INPUT; + r.valid = GL_TRUE; + break; + case PROGRAM_LOCAL_PARAM: + r = emit_param4fv(rp, rp->mesa_program.Base.LocalParams[fpsrc.Index]); + break; + case PROGRAM_ENV_PARAM: + r = emit_param4fv(rp, rp->ctx->FragmentProgram.Parameters[fpsrc.Index]); + break; + case PROGRAM_STATE_VAR: + case PROGRAM_NAMED_PARAM: + r = emit_param4fv(rp, rp->mesa_program.Parameters->ParameterValues[fpsrc.Index]); + break; + default: + ERROR("unknown SrcReg->File %x\n", fpsrc.File); + return r; + } + + /* no point swizzling ONE/ZERO/HALF constants... */ + if (r.v_swz < SWIZZLE_111 && r.s_swz < SWIZZLE_ZERO) + r = swizzle(rp, r, fpsrc.Swizzle); + + /* WRONG! Need to be able to do individual component negation, + * should probably handle this in the swizzling code unless + * all components are negated, then we can do this natively */ + if (fpsrc.NegateBase) + r.negate = GL_TRUE; + + return r; +} + +static pfs_reg_t t_dst(struct r300_fragment_program *rp, + struct fp_dst_register dest) { + pfs_reg_t r = pfs_default_reg; + + switch (dest.File) { + case PROGRAM_TEMPORARY: + r.index = dest.Index; + r.valid = GL_TRUE; + return r; + case PROGRAM_OUTPUT: + r.type = REG_TYPE_OUTPUT; + switch (dest.Index) { + case 0: + r.valid = GL_TRUE; + return r; + case 1: + ERROR("I don't know how to write depth!\n"); + return r; + default: + ERROR("Bad DstReg->Index 0x%x\n", dest.Index); + return r; + } + default: + ERROR("Bad DstReg->File 0x%x\n", dest.File); + return r; + } +} + +static void sync_streams(struct r300_fragment_program *rp) { + /* Bring vector/scalar streams into sync, inserting nops into + * whatever stream is lagging behind + * + * Using NOP == MAD out.none, 0, 0, 0 + */ + while (rp->v_pos != rp->s_pos) { + if (rp->s_pos > rp->v_pos) { + rp->alu.inst[rp->v_pos].inst0 = 0x00050A14; + rp->alu.inst[rp->v_pos].inst1 = 0x00020820; + rp->v_pos++; + } else { + rp->alu.inst[rp->s_pos].inst2 = 0x00040810; + rp->alu.inst[rp->s_pos].inst3 = 0x00020820; + rp->s_pos++; + } + } +} + +static void emit_tex(struct r300_fragment_program *rp, + struct fp_instruction *fpi, + int opcode) +{ + pfs_reg_t coord = t_src(rp, fpi->SrcReg[0]); + pfs_reg_t dest = t_dst(rp, fpi->DstReg), rdest = pfs_default_reg; + int unit = fpi->TexSrcUnit; + int hwsrc, hwdest, flags = 0; + + if (dest.type == REG_TYPE_OUTPUT) { + rdest = dest; + dest = get_temp_reg_tex(rp); + } + + switch (coord.type) { + case REG_TYPE_TEMP: + hwsrc = rp->temps[coord.index]; + break; + case REG_TYPE_INPUT: + hwsrc = rp->inputs[coord.index]; + break; + case REG_TYPE_CONST: + hwsrc = coord.index; + flags = R300_FPITX_SRC_CONST; + break; + default: + ERROR("Unknown coord.type = %d\n", coord.type); + return; + } + hwdest = rp->temps[dest.index]; + + /* Indirection if source has been written in this node, or if the dest has + * been read/written in this node + */ + if ((coord.type != REG_TYPE_CONST && (rp->dest_in_node & (1<<hwsrc))) || + (rp->used_in_node & (1<<hwdest))) { + + if (rp->cur_node == 3) { /* We only support 4 natively */ + ERROR("too many levels of texture indirection\n"); + return; + } + + /* Finish off current node */ + sync_streams(rp); + rp->node[rp->cur_node].alu_end = rp->v_pos - 1; + + /* Start new node */ + rp->cur_node++; + rp->used_in_node = 0; + rp->dest_in_node = 0; + rp->node[rp->cur_node].tex_offset = rp->tex.length; + rp->node[rp->cur_node].alu_offset = rp->v_pos; + rp->node[rp->cur_node].tex_end = -1; + rp->node[rp->cur_node].alu_end = -1; + } + + if (rp->cur_node == 0) rp->first_node_has_tex = 1; + + rp->tex.inst[rp->tex.length++] = 0 + | (hwsrc << R300_FPITX_SRC_SHIFT) + | (hwdest << R300_FPITX_DST_SHIFT) + | (unit << R300_FPITX_IMAGE_SHIFT) + | (opcode << R300_FPITX_OPCODE_SHIFT) /* not entirely sure about this */ + | flags; + rp->dest_in_node |= (1 << hwdest); + if (coord.type != REG_TYPE_CONST) + rp->used_in_node |= (1 << hwsrc); + + rp->node[rp->cur_node].tex_end++; + + /* Copy from temp to output if needed */ + if (rdest.valid) { + emit_arith(rp, PFS_OP_MAD, rdest, WRITEMASK_XYZW, dest, pfs_one, pfs_zero, 0); + free_temp(rp, dest); + } +} + +#define ARG_NEG (1<<5) +#define ARG_ABS (1<<6) +#define SRC_CONST (1<<5) +#define SRC_STRIDE 6 + +static int t_hw_src(struct r300_fragment_program *rp, pfs_reg_t src) +{ + int idx; + + switch (src.type) { + case REG_TYPE_TEMP: + idx = rp->temps[src.index]; + break; + case REG_TYPE_INPUT: + idx = rp->inputs[src.index]; + break; + case REG_TYPE_CONST: + return (src.index | SRC_CONST); + default: + ERROR("Invalid type for source reg\n"); + return (0 | SRC_CONST); + } + + rp->used_in_node |= (1 << idx); + return idx; +} + +/* Add sources to FPI1/FPI3 lists. If source is already on list, + * reuse the index instead of wasting a source. + */ +static inline int add_src(int src[3], int *cnt, int reg) { + int i; + + for (i=0;i<*cnt;i++) + if (src[i] == reg) return i; + + if (*cnt == 3) assert(0); /* I don't *think* this can happen */ + + src[*cnt] = reg; + return (*cnt)++; +} + +static void emit_arith(struct r300_fragment_program *rp, int op, + pfs_reg_t dest, int mask, + pfs_reg_t src0, pfs_reg_t src1, pfs_reg_t src2, + int flags) +{ + pfs_reg_t src[3] = { src0, src1, src2 }; + /* XYZ/W emit control */ + int v_idx = rp->v_pos, s_idx = rp->s_pos; + GLboolean emit_v = GL_FALSE, emit_s = GL_FALSE; + /* INST1/INST3 sources */ + int vsrc[3], ssrc[3]; + int nvs = 0, nss = 0; + /* INST0/INST2 sources */ + int vswz[3], sswz[3]; + /* temp stuff */ + int hwdest, hwsrc; + int argc; + int vop, sop; + int i; + int str; + + if (!dest.valid || !src0.valid || !src1.valid || !src2.valid) { + ERROR("invalid register. dest/src0/src1/src2 valid = %d/%d/%d/%d\n", + dest.valid, src0.valid, src1.valid, src2.valid); + return; + } + + /* check opcode */ + if (op > MAX_PFS_OP) { + ERROR("unknown opcode!\n"); + return; + } + argc = r300_fpop[op].argc; + vop = r300_fpop[op].v_op; + sop = r300_fpop[op].s_op; + + /* grab hwregs of dest */ + switch (dest.type) { + case REG_TYPE_TEMP: + hwdest = rp->temps[dest.index]; + rp->dest_in_node |= (1 << hwdest); + rp->used_in_node |= (1 << hwdest); + break; + case REG_TYPE_OUTPUT: + hwdest = 0; + break; + default: + ERROR("invalid dest reg type %d\n", dest.type); + return; + } + + for (i=0;i<3;i++) { + if (i<argc) { + hwsrc = t_hw_src(rp, src[i]); + if (mask & WRITEMASK_XYZ && vop != R300_FPI0_OUTC_REPL_ALPHA) { + if (v_swiz[src[i].v_swz].dep_sca) { + sync_streams(rp); + v_idx = s_idx = rp->v_pos; + emit_s = GL_TRUE; + str = add_src(ssrc, &nss, hwsrc); + } else + str = add_src(vsrc, &nvs, hwsrc); + vswz[i] = v_swiz[src[i].v_swz].base + (str * v_swiz[src[i].v_swz].stride); + } else + vswz[i] = R300_FPI0_ARGC_ZERO; + + if (mask & WRITEMASK_W || vop == R300_FPI0_OUTC_REPL_ALPHA) { + if (s_swiz[src[i].s_swz].dep_vec) { + sync_streams(rp); + v_idx = s_idx = rp->v_pos; + emit_v = GL_TRUE; + str = add_src(vsrc, &nvs, hwsrc); + } else + str = add_src(ssrc, &nss, hwsrc); + sswz[i] = s_swiz[src[i].s_swz].base + (str * s_swiz[src[i].s_swz].stride); + } else + sswz[i] = R300_FPI2_ARGA_ZERO; + + if (src[i].negate) { + vswz[i] |= ARG_NEG; + sswz[i] |= ARG_NEG; + } + + if (flags & PFS_FLAG_ABS) { + vswz[i] |= ARG_ABS; + sswz[i] |= ARG_ABS; + } + } else { + vswz[i] = R300_FPI0_ARGC_ZERO; + sswz[i] = R300_FPI2_ARGA_ZERO; + } + } + /* Unused sources, read constant reg 0 */ + for (i=nvs;i<3;i++) + vsrc[i] = 0 | SRC_CONST; + for (i=nss;i<3;i++) + ssrc[i] = 0 | SRC_CONST; + + if (flags & PFS_FLAG_SAT) { + vop |= R300_FPI0_OUTC_SAT; + sop |= R300_FPI2_OUTA_SAT; + } + + if (mask & WRITEMASK_XYZ || emit_v) { + if (r300_fpop[op].v_op == R300_FPI0_OUTC_REPL_ALPHA) { + sync_streams(rp); + s_idx = v_idx = rp->v_pos; + } + rp->alu.inst[v_idx].inst0 = vop | + vswz[0] << R300_FPI0_ARG0C_SHIFT | + vswz[1] << R300_FPI0_ARG1C_SHIFT | + vswz[2] << R300_FPI0_ARG2C_SHIFT; + rp->alu.inst[v_idx].inst1 = hwdest << R300_FPI1_DSTC_SHIFT | + vsrc[0] << R300_FPI1_SRC0C_SHIFT | + vsrc[1] << R300_FPI1_SRC1C_SHIFT | + vsrc[2] << R300_FPI1_SRC2C_SHIFT | + ((mask & WRITEMASK_XYZ) << (dest.type == REG_TYPE_OUTPUT ? 26 : 23)); + rp->v_pos = v_idx + 1; + } + + if (mask & WRITEMASK_W || emit_s || vop == R300_FPI0_OUTC_REPL_ALPHA) { + rp->alu.inst[s_idx].inst2 = sop | + sswz[0] << R300_FPI2_ARG0A_SHIFT | + sswz[1] << R300_FPI2_ARG1A_SHIFT | + sswz[2] << R300_FPI2_ARG2A_SHIFT; + rp->alu.inst[s_idx].inst3 = hwdest << R300_FPI3_DSTA_SHIFT | + ssrc[0] << R300_FPI3_SRC0A_SHIFT | + ssrc[1] << R300_FPI3_SRC1A_SHIFT | + ssrc[2] << R300_FPI3_SRC2A_SHIFT | + (((mask & WRITEMASK_W)?1:0) << (dest.type == REG_TYPE_OUTPUT ? 24 : 23)); + rp->s_pos = s_idx + 1; + } + +/* sync_streams(rp); */ + return; +}; + +static GLboolean parse_program(struct r300_fragment_program *rp) +{ + struct fragment_program *mp = &rp->mesa_program; + const struct fp_instruction *inst = mp->Instructions; + struct fp_instruction *fpi; + pfs_reg_t src0, src1, src2, dest, temp; + int flags = 0; + + if (!inst || inst[0].Opcode == FP_OPCODE_END) { + ERROR("empty program?\n"); + return GL_FALSE; + } + + for (fpi=mp->Instructions; fpi->Opcode != FP_OPCODE_END; fpi++) { + if (fpi->Saturate) { + flags = PFS_FLAG_SAT; + } + + switch (fpi->Opcode) { + case FP_OPCODE_ABS: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + case FP_OPCODE_ADD: + emit_arith(rp, PFS_OP_MAD, t_dst(rp, fpi->DstReg), fpi->DstReg.WriteMask, + t_src(rp, fpi->SrcReg[0]), + pfs_one, + t_src(rp, fpi->SrcReg[1]), + flags); + break; + case FP_OPCODE_CMP: + case FP_OPCODE_COS: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + case FP_OPCODE_DP3: + dest = t_dst(rp, fpi->DstReg); + if (fpi->DstReg.WriteMask & WRITEMASK_W) { + /* I assume these need to share the same alu slot */ + sync_streams(rp); + emit_arith(rp, PFS_OP_DP4, dest, WRITEMASK_W, + pfs_zero, pfs_zero, pfs_zero, + flags); + } + emit_arith(rp, PFS_OP_DP3, t_dst(rp, fpi->DstReg), + fpi->DstReg.WriteMask & WRITEMASK_XYZ, + t_src(rp, fpi->SrcReg[0]), + t_src(rp, fpi->SrcReg[1]), + pfs_zero, flags); + break; + case FP_OPCODE_DP4: + case FP_OPCODE_DPH: + case FP_OPCODE_DST: + case FP_OPCODE_EX2: + case FP_OPCODE_FLR: + case FP_OPCODE_FRC: + case FP_OPCODE_KIL: + case FP_OPCODE_LG2: + case FP_OPCODE_LIT: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + case FP_OPCODE_LRP: + /* TODO: use the special LRP form if possible */ + src0 = t_src(rp, fpi->SrcReg[0]); + src1 = t_src(rp, fpi->SrcReg[1]); + src2 = t_src(rp, fpi->SrcReg[2]); + // result = tmp0tmp1 + (1 - tmp0)tmp2 + // = tmp0tmp1 + tmp2 + (-tmp0)tmp2 + // MAD temp, -tmp0, tmp2, tmp2 + // MAD result, tmp0, tmp1, temp + temp = get_temp_reg(rp); + emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_XYZW, + negate(src0), src2, src2, 0); + emit_arith(rp, PFS_OP_MAD, t_dst(rp, fpi->DstReg), fpi->DstReg.WriteMask, + src0, src1, temp, flags); + free_temp(rp, temp); + break; + case FP_OPCODE_MAD: + emit_arith(rp, PFS_OP_MAD, t_dst(rp, fpi->DstReg), fpi->DstReg.WriteMask, + t_src(rp, fpi->SrcReg[0]), + t_src(rp, fpi->SrcReg[1]), + t_src(rp, fpi->SrcReg[2]), + flags); + break; + case FP_OPCODE_MAX: + case FP_OPCODE_MIN: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + case FP_OPCODE_MOV: + case FP_OPCODE_SWZ: + emit_arith(rp, PFS_OP_MAD, t_dst(rp, fpi->DstReg), fpi->DstReg.WriteMask, + t_src(rp, fpi->SrcReg[0]), pfs_one, pfs_zero, + flags); + break; + case FP_OPCODE_MUL: + emit_arith(rp, PFS_OP_MAD, t_dst(rp, fpi->DstReg), fpi->DstReg.WriteMask, + t_src(rp, fpi->SrcReg[0]), + t_src(rp, fpi->SrcReg[1]), + pfs_zero, + flags); + break; + case FP_OPCODE_POW: + src0 = t_src(rp, fpi->SrcReg[0]); + src1 = t_src(rp, fpi->SrcReg[1]); + dest = t_dst(rp, fpi->DstReg); + temp = get_temp_reg(rp); + + emit_arith(rp, PFS_OP_LG2, temp, WRITEMASK_W, + src0, pfs_zero, pfs_zero, 0); + emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_W, + temp, src1, pfs_zero, 0); + emit_arith(rp, PFS_OP_EX2, dest, fpi->DstReg.WriteMask, + temp, pfs_zero, pfs_zero, 0); + free_temp(rp, temp); + break; + case FP_OPCODE_RCP: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + case FP_OPCODE_RSQ: + emit_arith(rp, PFS_OP_RSQ, t_dst(rp, fpi->DstReg), + fpi->DstReg.WriteMask, + t_src(rp, fpi->SrcReg[0]), pfs_zero, pfs_zero, + flags | PFS_FLAG_ABS); + break; + case FP_OPCODE_SCS: + case FP_OPCODE_SGE: + case FP_OPCODE_SIN: + case FP_OPCODE_SLT: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + case FP_OPCODE_SUB: + emit_arith(rp, PFS_OP_MAD, t_dst(rp, fpi->DstReg), fpi->DstReg.WriteMask, + t_src(rp, fpi->SrcReg[0]), + pfs_one, + negate(t_src(rp, fpi->SrcReg[1])), + flags); + break; + case FP_OPCODE_TEX: + emit_tex(rp, fpi, R300_FPITX_OP_TEX); + break; + case FP_OPCODE_TXB: + emit_tex(rp, fpi, R300_FPITX_OP_TXB); + break; + case FP_OPCODE_TXP: + emit_tex(rp, fpi, R300_FPITX_OP_TXP); + break; + case FP_OPCODE_XPD: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + default: + ERROR("unknown fpi->Opcode %d\n", fpi->Opcode); + break; + } + + if (rp->error) + return GL_FALSE; + } + + return GL_TRUE; +} + +/* - Init structures + * - Determine what hwregs each input corresponds to + */ +static void init_program(struct r300_fragment_program *rp) +{ + struct fragment_program *mp = &rp->mesa_program; + struct fp_instruction *fpi; + GLuint InputsRead = mp->InputsRead; + GLuint fp_reg = 0; + GLuint temps_used = 0; /* for rp->temps[] */ + int i; + + rp->translated = GL_FALSE; + rp->error = GL_FALSE; + + rp->v_pos = 0; + rp->s_pos = 0; + + rp->tex.length = 0; + rp->node[0].alu_offset = 0; + rp->node[0].alu_end = -1; + rp->node[0].tex_offset = 0; + rp->node[0].tex_end = -1; + rp->cur_node = 0; + rp->first_node_has_tex = 0; + rp->used_in_node = 0; + rp->dest_in_node = 0; + + rp->const_nr = 0; + rp->param_nr = 0; + rp->params_uptodate = GL_FALSE; + + rp->temp_in_use = 0; + rp->hwreg_in_use = 0; + rp->max_temp_idx = 0; + + /* Work out what temps the Mesa inputs correspond to, this must match + * what setup_rs_unit does, which shouldn't be a problem as rs_unit + * configures itself based on the fragprog's InputsRead + * + * I'm using get_hw_temp() here now rather than doing this manually. + * This depends on get_hw_temp() allocating registers in order, starting + * at 0 (which it currently does). + */ + + /* Texcoords come first */ + for (i=0;i<rp->ctx->Const.MaxTextureUnits;i++) { + if (InputsRead & (FRAG_BIT_TEX0 << i)) + rp->inputs[FRAG_ATTRIB_TEX0+i] = get_hw_temp(rp); + } + InputsRead &= ~FRAG_BITS_TEX_ANY; + + /* Then primary colour */ + if (InputsRead & FRAG_BIT_COL0) + rp->inputs[FRAG_ATTRIB_COL0] = get_hw_temp(rp); + InputsRead &= ~FRAG_BIT_COL0; + + /* Secondary color */ + if (InputsRead & FRAG_BIT_COL1) + rp->inputs[FRAG_ATTRIB_COL1] = get_hw_temp(rp); + InputsRead &= ~FRAG_BIT_COL1; + + /* Anything else */ + if (InputsRead) { + WARN_ONCE("Don't know how to handle inputs 0x%x\n", InputsRead); + /* force read from hwreg 0 for now */ + for (i=0;i<32;i++) + if (InputsRead & (1<<i)) rp->inputs[i] = 0; + } + + /* Possibly the worst part of how I went about this... Find out what + * temps are used by the mesa program so we don't clobber something + * when we need a temp for other reasons. + * + * Possibly not too bad actually, as we could add to this later and + * find out when inputs are last used so we can reuse them as temps. + */ + if (!mp->Instructions) { + ERROR("No instructions found in program\n"); + return; + } + for (fpi=mp->Instructions;fpi->Opcode != FP_OPCODE_END; fpi++) { + for (i=0;i<3;i++) { + if (fpi->SrcReg[i].File == PROGRAM_TEMPORARY) { + if (!(temps_used & (1 << fpi->SrcReg[i].Index))) { + temps_used |= (1 << fpi->SrcReg[i].Index); + rp->temps[fpi->SrcReg[i].Index] = get_hw_temp(rp); + } + } + } + /* needed? surely if a program writes a temp it'll read it again */ + if (fpi->DstReg.File == PROGRAM_TEMPORARY) { + if (!(temps_used & (1 << fpi->DstReg.Index))) { + temps_used |= (1 << fpi->DstReg.Index); + rp->temps[fpi->DstReg.Index] = get_hw_temp(rp); + } + } + } + rp->temp_in_use = temps_used; +} + +static void update_params(struct r300_fragment_program *rp) { + struct fragment_program *mp = &rp->mesa_program; + int i; + + /* Ask Mesa nicely to fill in ParameterValues for us */ + if (rp->param_nr) + _mesa_load_state_parameters(rp->ctx, mp->Parameters); + + for (i=0;i<rp->param_nr;i++) + COPY_4V(rp->constant[rp->param[i].idx], rp->param[i].values); + + rp->params_uptodate = GL_TRUE; +} + +void translate_fragment_shader(struct r300_fragment_program *rp) +{ + int i; + + if (!rp->translated) { + init_program(rp); + + if (parse_program(rp) == GL_FALSE) { + dump_program(rp); + return; + } + + /* Finish off */ + sync_streams(rp); + rp->node[rp->cur_node].alu_end = rp->v_pos - 1; + rp->alu_offset = 0; + rp->alu_end = rp->v_pos - 1; + rp->tex_offset = 0; + rp->tex_end = rp->tex.length - 1; + + rp->translated = GL_TRUE; + if (0) dump_program(rp); + } + + + update_params(rp); +} + +/* just some random things... */ +static void dump_program(struct r300_fragment_program *rp) +{ + int i; + static int pc = 0; + + fprintf(stderr, "pc=%d*************************************\n", pc++); + + fprintf(stderr, "Mesa program:\n"); + fprintf(stderr, "-------------\n"); + _mesa_debug_fp_inst(rp->mesa_program.NumTexInstructions + + rp->mesa_program.NumAluInstructions, + rp->mesa_program.Instructions); + fflush(stdout); + + fprintf(stderr, "Hardware program\n"); + fprintf(stderr, "----------------\n"); + for (i=0;i<(rp->cur_node+1);i++) { + fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, alu_end: %d, tex_end: %d\n", i, + rp->node[i].alu_offset, + rp->node[i].tex_offset, + rp->node[i].alu_end, + rp->node[i].tex_end); + } + +/* dump program in pretty_print_command_stream.tcl-readable format */ + fprintf(stderr, "%08x\n", ((rp->alu_end << 16) | (R300_PFS_INSTR0_0 >> 2))); + for (i=0;i<=rp->alu_end;i++) + fprintf(stderr, "%08x\n", rp->alu.inst[i].inst0); + fprintf(stderr, "%08x\n", ((rp->alu_end << 16) | (R300_PFS_INSTR1_0 >> 2))); + for (i=0;i<=rp->alu_end;i++) + fprintf(stderr, "%08x\n", rp->alu.inst[i].inst1); + fprintf(stderr, "%08x\n", ((rp->alu_end << 16) | (R300_PFS_INSTR2_0 >> 2))); + for (i=0;i<=rp->alu_end;i++) + fprintf(stderr, "%08x\n", rp->alu.inst[i].inst2); + fprintf(stderr, "%08x\n", ((rp->alu_end << 16) | (R300_PFS_INSTR3_0 >> 2))); + for (i=0;i<=rp->alu_end;i++) + fprintf(stderr, "%08x\n", rp->alu.inst[i].inst3); + fprintf(stderr, "00000000\n"); + +} +#endif // USE_ARB_F_P == 1 diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog.h new file mode 100644 index 000000000..ed318eb6a --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog.h @@ -0,0 +1,49 @@ +#ifndef __R300_FRAGPROG_H_ +#define __R300_FRAGPROG_H_ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "program.h" +#include "r300_context.h" +#include "nvfragprog.h" + +/* representation of a register for emit_arith/swizzle */ +typedef struct _pfs_reg_t { + enum { + REG_TYPE_INPUT, + REG_TYPE_OUTPUT, + REG_TYPE_TEMP, + REG_TYPE_CONST + } type:2; + GLuint index:6; + GLuint v_swz:5; + GLuint s_swz:5; + GLuint negate:1; //XXX: we need to handle negate individually + GLboolean valid:1; +} pfs_reg_t; + +/* supported hw opcodes */ +#define PFS_OP_MAD 0 +#define PFS_OP_DP3 1 +#define PFS_OP_DP4 2 +#define PFS_OP_MIN 3 +#define PFS_OP_MAX 4 +#define PFS_OP_CMP 5 +#define PFS_OP_FRC 6 +#define PFS_OP_EX2 7 +#define PFS_OP_LG2 8 +#define PFS_OP_RCP 9 +#define PFS_OP_RSQ 10 +#define PFS_OP_REPL_ALPHA 11 +#define MAX_PFS_OP 11 +#define OP(n) PFS_OP_##n + +#define PFS_FLAG_SAT (1 << 0) +#define PFS_FLAG_ABS (1 << 1) + +extern void translate_fragment_shader(struct r300_fragment_program *rp); + +#endif /* __R300_FRAGPROG_H_ */ + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog_swz.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog_swz.c new file mode 100644 index 000000000..00977ce68 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_fragprog_swz.c @@ -0,0 +1,1343 @@ +/* + * Copyright (C) 2005 Jerome Glisse. 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. + * + */ +#include "r300_fragprog.h" +#include "r300_reg.h" + + +#define I0_000 ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_ZERO) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_111 ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_ZERO) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG2C_SHIFT) ) +#define I0_XXX ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0C_XXX) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_YYY ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0C_YYY) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_ZZZ ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0C_ZZZ) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_XYZ ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0C_XYZ) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_YZX ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0C_YZX) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_ZXY ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0C_ZXY) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) +#define I0_WZY ( (R300_FPI0_OUTC_MAD) | \ + (R300_FPI0_ARGC_SRC0CA_WZY) | \ + (R300_FPI0_ARGC_ONE << R300_FPI0_ARG1C_SHIFT) | \ + (R300_FPI0_ARGC_ZERO << R300_FPI0_ARG2C_SHIFT) ) + +#define IEMPTY 0 +#define I1_CST R300_FPI1_SRC0C_CONST + +#define I1_XYZ ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_X | \ + R300_FPI1_DSTC_REG_Y | \ + R300_FPI1_DSTC_REG_Z ) +#define I1_XY_ ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_X | \ + R300_FPI1_DSTC_REG_Y ) +#define I1_X_Z ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_X | \ + R300_FPI1_DSTC_REG_Z ) +#define I1__YZ ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_Y | \ + R300_FPI1_DSTC_REG_Z ) +#define I1_X__ ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_X ) +#define I1__Y_ ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_Y ) +#define I1___Z ( R300_FPI1_SRC1C_CONST | \ + R300_FPI1_SRC2C_CONST | \ + R300_FPI1_DSTC_REG_Z ) + +#define SEMPTY {0,{0,0,0,0},{0,0,0,0,0,0,0,0}} + +struct r300_fragment_program_swizzle r300_swizzle [512] = { + /* XXX */ + {1,{0,0,0,0},{ I0_XXX, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* YXX */ + {2,{0,0,0,0},{ I0_YYY, I1_X__, + I0_XXX, I1__YZ, + 0,0, + 0,0 } }, + /* ZXX */ + {2,{0,0,0,0},{ I0_ZZZ, I1_X__, + I0_XXX, I1__YZ, + 0,0, + 0,0 } }, + /* WXX */ + {2,{0,0,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__YZ, + 0,0, + 0,0} }, + /* 0XX */ + {2,{0,2,0,0},{ I0_XXX, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0, + 0,0 } }, + /* 1XX */ + {2,{0,2,0,0},{ I0_XXX, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XYX */ + {2,{0,0,0,0},{ I0_YYY, I1__Y_, + I0_XXX, I1_X_Z, + 0,0,0,0}}, + /* YYX */ + {2,{0,0,0,0},{ I0_YYY, I1_XY_, + I0_XXX, I1___Z, + 0,0,0,0}}, + /* ZYX */ + {3,{0,0,0,0},{ I0_ZZZ, I1_X__, + I0_YYY, I1__Y_, + I0_XXX, I1___Z, + 0,0}}, + /* WYX */ + {3,{0,0,0,0},{ I0_WZY, I1_X__, + I0_YYY, I1__Y_, + I0_XXX, I1___Z, + 0,0}}, + /* 0YX */ + {3,{0,0,2,0},{ I0_YYY, I1__Y_, + I0_XXX, I1___Z, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 1YX */ + {3,{0,0,2,0},{ I0_YYY, I1__Y_, + I0_XXX, I1___Z, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* XZX */ + {2,{0,0,0,0},{ I0_YZX, I1__YZ, + I0_XXX, I1_X__, + 0,0,0,0}}, + /* YZX */ + {1,{0,0,0,0},{ I0_YZX, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* ZZX */ + {2,{0,0,0,0},{ I0_YZX, I1__YZ, + I0_ZZZ, I1_X__,0,0,0,0}}, + /* WZX */ + {2,{0,0,0,0},{ I0_WZY, I1__YZ, + I0_XXX, I1_X__,0,0,0,0}}, + /* 0ZX */ + {2,{0,2,0,0},{ I0_YZX, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 1ZX */ + {2,{0,2,0,0},{ I0_YZX, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XWX */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_XXX, I1_X_Z, + 0,0}}, + /* YWX */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_YZX, I1_X_Z, + 0,0}}, + /* ZWX */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_ZZZ, I1_X__, + I0_XXX, I1___Z } }, + /* WWX */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_XY_, + I0_YZX, I1___Z, + 0,0}}, + /* 0WX */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_YZX, I1___Z, + I0_000, I1_X__ | I1_CST } }, + /* 1WX */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_YZX, I1___Z, + I0_111, I1_X__ | I1_CST } }, + SEMPTY,SEMPTY, + /* X0X */ + {2,{0,2,0,0},{ I0_XXX, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Y0X */ + {2,{0,2,0,0},{ I0_YZX, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Z0X */ + {3,{0,2,0,0},{ I0_XXX, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_ZZZ, I1_X__, + 0,0}}, + /* W0X */ + {3,{0,2,0,0},{ I0_XXX, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_WZY, I1_X__, + 0,0}}, + /* 00X */ + {2,{0,2,0,0},{ I0_XXX, I1___Z, + I0_000, I1_XY_ | I1_CST, + 0,0,0,0}}, + /* 10X */ + {3,{0,2,0,0},{ I0_XXX, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* X1X */ + {2,{0,2,0,0},{ I0_XXX, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Y1X */ + {2,{0,2,0,0},{ I0_YZX, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Z1X */ + {3,{0,2,0,0},{ I0_XXX, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_ZZZ, I1_X__, + 0,0}}, + /* W1X */ + {3,{0,2,0,0},{ I0_XXX, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_WZY, I1_X__, + 0,0}}, + /* 01X */ + {3,{0,2,0,0},{ I0_XXX, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 11X */ + {2,{0,2,0,0},{ I0_XXX, I1___Z, + I0_111, I1_XY_ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + /* XXY */ + {2,{0,0,0,0},{ I0_YYY, I1___Z, + I0_XXX, I1_XY_, + 0,0,0,0}}, + /* YXY */ + {2,{0,0,0,0},{ I0_YYY, I1_X_Z, + I0_XXX, I1__Y_, + 0,0,0,0}}, + /* ZXY */ + {1,{0,0,0,0},{ I0_ZXY, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* WXY */ + {2,{0,0,0,0},{ I0_WZY, I1_X__, + I0_ZXY, I1__YZ, + 0,0,0,0}}, + /* 0XY */ + {2,{0,0,0,0},{ I0_ZXY, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 1XY */ + {2,{0,0,0,0},{ I0_ZXY, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XYY */ + {2,{0,0,0,0},{ I0_YYY, I1__YZ, + I0_XXX, I1_X__, + 0,0,0,0}}, + /* YYY */ + {1,{0,0,0,0},{ I0_YYY, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* ZYY */ + {2,{0,0,0,0},{ I0_YYY, I1__YZ, + I0_ZZZ, I1_X__, + 0,0,0,0}}, + /* WYY */ + {2,{0,0,0,0},{ I0_YYY, I1__YZ, + I0_WZY, I1_X__, + 0,0,0,0}}, + /* 0YY */ + {2,{0,0,0,0},{ I0_YYY, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 1YY */ + {2,{0,0,0,0},{ I0_YYY, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XZY */ + {2,{0,0,0,0},{ I0_WZY, I1__YZ, + I0_XXX, I1_X__, + 0,0,0,0}}, + /* YZY */ + {2,{0,0,0,0},{ I0_WZY, I1__YZ, + I0_YYY, I1_X__, + 0,0,0,0}}, + /* ZZY */ + {2,{0,0,0,0},{ I0_WZY, I1__YZ, + I0_ZZZ, I1_X__, + 0,0,0,0}}, + /* WZY */ + {1,{0,0,0,0},{ I0_WZY, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* 0ZY */ + {2,{0,0,0,0},{ I0_WZY, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 1ZY */ + {2,{0,0,0,0},{ I0_WZY, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XWY */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_XXX, I1_X__, + I0_YYY, I1___Z } }, + /* YWY */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_YYY, I1_X_Z, + 0,0}}, + /* ZWY */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_ZXY, I1_X_Z, + 0,0}}, + /* WWY */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_XY_, + I0_ZXY, I1___Z, + 0,0}}, + /* 0WY */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_ZXY, I1___Z, + I0_000, I1_X__ | I1_CST } }, + /* 1WY */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_ZXY, I1___Z, + I0_111, I1_X__ | I1_CST } }, + SEMPTY,SEMPTY, + /* X0Y */ + {3,{0,2,0,0},{ I0_XXX, I1_X__, + I0_000, I1__Y_ | I1_CST, + I0_YYY, I1___Z, + 0,0}}, + /* Y0Y */ + {2,{0,2,0,0},{ I0_YYY, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Z0Y */ + {2,{0,2,0,0},{ I0_ZXY, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* W0Y */ + {2,{0,2,0,0},{ I0_WZY, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* 00Y */ + {2,{0,2,0,0},{ I0_YYY, I1___Z, + I0_000, I1_XY_ | I1_CST, + 0,0,0,0}}, + /* 10Y */ + {3,{0,2,0,0},{ I0_YYY, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* X1Y */ + {3,{0,2,0,0},{ I0_XXX, I1_X__, + I0_111, I1__Y_ | I1_CST, + I0_YYY, I1___Z, + 0,0}}, + /* Y1Y */ + {2,{0,2,0,0},{ I0_YYY, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Z1Y */ + {2,{0,2,0,0},{ I0_ZXY, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* W1Y */ + {3,{0,2,0,0},{ I0_WZY, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* 01Y */ + {3,{0,2,0,0},{ I0_YYY, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 11Y */ + {2,{0,2,0,0},{ I0_YYY, I1___Z, + I0_111, I1_XY_ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + /* XXZ */ + {2,{0,0,0,0},{ I0_XXX, I1_XY_, + I0_ZZZ, I1___Z, + 0,0,0,0}}, + /* YXZ */ + {3,{0,0,0,0},{ I0_XXX, I1__Y_, + I0_YYY, I1_X__, + I0_ZZZ, I1___Z, + 0,0}}, + /* ZXZ */ + {2,{0,0,0,0},{ I0_XXX, I1__Y_, + I0_ZZZ, I1_X_Z, + 0,0,0,0}}, + /* WXZ */ + {3,{0,0,0,0},{ I0_XXX, I1__Y_, + I0_ZZZ, I1___Z, + I0_WZY, I1_X__, + 0,0}}, + /* 0XZ */ + {3,{0,0,2,0},{ I0_XXX, I1__Y_, + I0_ZZZ, I1___Z, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 1XZ */ + {3,{0,0,2,0},{ I0_XXX, I1__Y_, + I0_ZZZ, I1___Z, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* XYZ */ + {1,{0,0,0,0},{ I0_XYZ, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* YYZ */ + {2,{0,0,0,0},{ I0_ZZZ, I1___Z, + I0_YYY, I1_XY_, + 0,0,0,0}}, + /* ZYZ */ + {2,{0,0,0,0},{ I0_ZZZ, I1_X_Z, + I0_YYY, I1__Y_, + 0,0,0,0}}, + /* WYZ */ + {2,{0,0,0,0},{ I0_XYZ, I1__YZ, + I0_WZY, I1_X__, + 0,0,0,0}}, + /* 0YZ */ + {2,{0,2,0,0},{ I0_XYZ, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 1YZ */ + {2,{0,2,0,0},{ I0_XYZ, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XZZ */ + {2,{0,0,0,0},{ I0_ZZZ, I1__YZ, + I0_XXX, I1_X__, + 0,0,0,0}}, + /* YZZ */ + {2,{0,0,0,0},{ I0_ZZZ, I1__YZ, + I0_YYY, I1_X__, + 0,0,0,0}}, + /* ZZZ */ + {1,{0,0,0,0},{ I0_ZZZ, I1_XYZ, + 0, 0, 0, 0, 0, 0 } }, + /* WZZ */ + {2,{0,0,0,0},{ I0_ZZZ, I1__YZ, + I0_WZY, I1_X__, + 0,0,0,0}}, + /* 0ZZ */ + {2,{0,2,0,0},{ I0_ZZZ, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 1ZZ */ + {2,{0,2,0,0},{ I0_ZZZ, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XWZ */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_XYZ, I1_X_Z, + 0,0}}, + /* YWZ */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_YYY, I1_X__, + I0_XYZ, I1___Z } }, + /* ZWZ */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_ZZZ, I1_X_Z, + 0,0}}, + /* WWZ */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_XY_, + I0_XYZ, I1___Z, + 0,0}}, + /* 0WZ */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_XYZ, I1___Z, + I0_000, I1_X__ | I1_CST } }, + /* 1WZ */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1__Y_, + I0_XYZ, I1___Z, + I0_111, I1_X__ | I1_CST } }, + SEMPTY,SEMPTY, + /* X0Z */ + {2,{0,2,0,0},{ I0_XYZ, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Y0Z */ + {3,{0,2,0,0},{ I0_ZZZ, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_YYY, I1_X__, + 0,0}}, + /* Z0Z */ + {2,{0,2,0,0},{ I0_ZZZ, I1_X_Z, + I0_000, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* W0Z */ + {3,{0,2,0,0},{ I0_ZZZ, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_WZY, I1_X__, + 0,0}}, + /* 00Z */ + {2,{0,2,0,0},{ I0_ZZZ, I1___Z, + I0_000, I1_XY_ | I1_CST, + 0,0,0,0}}, + /* 10Z */ + {3,{0,2,2,0},{ I0_ZZZ, I1___Z, + I0_000, I1__Y_ | I1_CST, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* X1Z */ + {2,{0,2,0,0},{ I0_XYZ, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* Y1Z */ + {3,{0,2,0,0},{ I0_ZZZ, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_YYY, I1_X__, + 0,0}}, + /* Z1Z */ + {2,{0,2,0,0},{ I0_ZZZ, I1_X_Z, + I0_111, I1__Y_ | I1_CST, + 0,0,0,0}}, + /* W1Z */ + {3,{0,2,0,0},{ I0_ZZZ, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_WZY, I1_X__, + 0,0}}, + /* 01Z */ + {3,{0,2,2,0},{ I0_ZZZ, I1___Z, + I0_111, I1__Y_ | I1_CST, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 11Z */ + {2,{0,2,0,0},{ I0_ZZZ, I1___Z, + I0_111, I1_XY_ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + /* XXW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XXX, I1_XY_, + 0,0}}, + /* YXW */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XXX, I1__Y_, + I0_YYY, I1_X__ } }, + /* ZXW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_ZXY, I1_XY_, + 0,0}}, + /* WXW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_X_Z, + I0_XXX, I1__Y_, + 0,0}}, + /* 0XW */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XXX, I1__Y_, + I0_000, I1_X__ | I1_CST } }, + /* 1XW */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XXX, I1__Y_, + I0_111, I1_X__ | I1_CST } }, + SEMPTY,SEMPTY, + /* XYW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XYZ, I1_XY_, + 0,0}}, + /* YYW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_YYY, I1_XY_, + 0,0}}, + /* ZYW */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XYZ, I1__Y_, + I0_ZZZ, I1_X__ } }, + /* WYW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_X_Z, + I0_YYY, I1__Y_, + 0,0}}, + /* 0YW */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_YYY, I1__Y_, + I0_000, I1_X__ | I1_CST } }, + /* 1YW */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_YYY, I1__Y_, + I0_111, I1_X__ | I1_CST } }, + + SEMPTY,SEMPTY, + /* XZW */ + {4,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XYZ, I1_X__, + I0_ZZZ, I1__Y_ } }, + /* YZW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_YZX, I1_XY_, + 0,0}}, + /* ZZW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_ZZZ, I1_XY_, + 0,0}}, + /* WZW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_X_Z, + I0_ZZZ, I1__Y_, + 0,0}}, + /* 0ZW */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_ZZZ, I1__Y_, + I0_000, I1_X__ | I1_CST } }, + /* 1ZW */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_ZZZ, I1__Y_, + I0_111, I1_X__ | I1_CST } }, + + SEMPTY,SEMPTY, + /* XWW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__YZ, + I0_XYZ, I1_X__, + 0,0}}, + /* YWW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__YZ, + I0_YYY, I1_X__, + 0,0}}, + /* ZWW */ + {3,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1__YZ, + I0_ZZZ, I1_X__, + 0,0}}, + /* WWW */ + {2,{0,1,0,0},{ I0_WZY, I1_X__, + I0_XXX, I1_XYZ, + 0,0,0,0}}, + /* 0WW */ + {3,{0,1,2,0},{ I0_WZY, I1_X__, + I0_XXX, I1__YZ, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 1WW */ + {3,{0,1,2,0},{ I0_WZY, I1_X__, + I0_XXX, I1__YZ, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* X0W */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XYZ, I1_X__, + I0_000, I1__Y_ | I1_CST } }, + /* Y0W */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_YYY, I1_X__, + I0_000, I1__Y_ | I1_CST } }, + /* Z0W */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_ZZZ, I1_X__, + I0_000, I1__Y_ | I1_CST } }, + /* 00W */ + {3,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_000, I1_XY_ | I1_CST, + 0,0}}, + /* 10W */ + {4,{0,1,2,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_111, I1_X__ | I1_CST, + I0_000, I1__Y_ | I1_CST } }, + SEMPTY,SEMPTY, + /* X1W */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_XYZ, I1_X__, + I0_111, I1__Y_ | I1_CST } }, + /* Y1W */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_YYY, I1_X__, + I0_111, I1__Y_ | I1_CST } }, + /* Z1W */ + {4,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_ZZZ, I1_X__, + I0_111, I1__Y_ | I1_CST } }, + /* 01W */ + {4,{0,1,2,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_000, I1_X__ | I1_CST, + I0_111, I1__Y_ | I1_CST } }, + /* 11W */ + {3,{0,1,0,2},{ I0_WZY, I1_X__, + I0_XXX, I1___Z, + I0_111, I1_XY_ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + /* XX0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_XXX, I1_XY_, + 0,0,0,0}}, + /* YX0 */ + {3,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_XXX, I1__Y_, + I0_YYY, I1_X__, + 0,0}}, + /* ZX0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_ZXY, I1_XY_, + 0,0,0,0}}, + /* WX0 */ + {3,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_XXX, I1__Y_, + I0_WZY, I1_X__, + 0,0}}, + /* 0X0 */ + {2,{2,0,0,0},{ I0_000, I1_X_Z | I1_CST, + I0_XXX, I1__Y_, + 0,0,0,0}}, + /* 1X0 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_XXX, I1__Y_, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* XY0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_XYZ, I1_XY_, + 0,0,0,0}}, + /* YY0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_YYY, I1_XY_, + 0,0,0,0}}, + /* ZY0 */ + {3,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_ZZZ, I1_X__, + I0_YYY, I1__Y_, + 0,0}}, + /* WY0 */ + {3,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_XYZ, I1__Y_, + I0_WZY, I1_X__, + 0,0}}, + /* 0Y0 */ + {2,{2,0,0,0},{ I0_000, I1_X_Z | I1_CST, + I0_XYZ, I1__Y_, + 0,0,0,0}}, + /* 1Y0 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_XYZ, I1__Y_, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* XZ0 */ + {3,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_XYZ, I1_X__, + I0_ZZZ, I1__Y_, + 0,0}}, + /* YZ0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_YZX, I1_XY_, + 0,0,0,0}}, + /* ZZ0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_ZZZ, I1_XY_, + 0,0,0,0}}, + /* WZ0 */ + {2,{2,0,0,0},{ I0_000, I1___Z | I1_CST, + I0_WZY, I1_XY_, + 0,0,0,0}}, + /* 0Z0 */ + {2,{2,0,0,0},{ I0_000, I1_X_Z | I1_CST, + I0_ZZZ, I1__Y_, + 0,0,0,0}}, + /* 1Z0 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_ZZZ, I1__Y_, + I0_111, I1_X__ | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* XW0 */ + {4,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_000, I1___Z | I1_CST, + I0_XYZ, I1_X__ } }, + /* YW0 */ + {4,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_000, I1___Z | I1_CST, + I0_YYY, I1_X__ } }, + /* ZW0 */ + {4,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_000, I1___Z | I1_CST, + I0_ZZZ, I1_X__ } }, + /* WW0 */ + {3,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1_XY_, + I0_000, I1___Z | I1_CST, + 0,0}}, + /* 0W0 */ + {3,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_000, I1_X_Z | I1_CST, + 0,0}}, + /* 1W0 */ + {4,{0,1,2,2},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_000, I1___Z | I1_CST, + I0_111, I1_X__ | I1_CST } }, + SEMPTY,SEMPTY, + /* X00 */ + {2,{2,0,0,0},{ I0_000, I1__YZ | I1_CST, + I0_XYZ, I1_X__, + 0,0,0,0}}, + /* Y00 */ + {2,{2,0,0,0},{ I0_000, I1__YZ | I1_CST, + I0_YYY, I1_X__, + 0,0,0,0}}, + /* Z00 */ + {2,{2,0,0,0},{ I0_000, I1__YZ | I1_CST, + I0_ZZZ, I1_X__, + 0,0,0,0}}, + /* W00 */ + {2,{2,0,0,0},{ I0_000, I1__YZ | I1_CST, + I0_WZY, I1_X__, + 0,0,0,0}}, + /* 000 */ + {1,{2,0,0,0},{ I0_000, I1_XYZ | I1_CST, + 0, 0, 0, 0, 0, 0 } }, + /* 100 */ + {2,{2,2,0,0},{ I0_000, I1__YZ | I1_CST, + I0_111, I1_X__ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* X10 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_XYZ, I1_X__, + I0_111, I1__Y_ | I1_CST, + 0,0}}, + /* Y10 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_YYY, I1_X__, + I0_111, I1__Y_ | I1_CST, + 0,0}}, + /* Z10 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_ZZZ, I1_X__, + I0_111, I1__Y_ | I1_CST, + 0,0}}, + /* W10 */ + {3,{2,0,2,0},{ I0_000, I1___Z | I1_CST, + I0_WZY, I1_X__, + I0_111, I1__Y_ | I1_CST, + 0,0}}, + /* 010 */ + {2,{2,2,0,0},{ I0_000, I1_X_Z | I1_CST, + I0_111, I1__Y_ | I1_CST, + 0, 0, 0, 0 } }, + /* 110 */ + {2,{2,2,0,0},{ I0_000, I1___Z | I1_CST, + I0_111, I1_XY_ | I1_CST, + 0,0,0,0}}, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + + + + /* XX1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_XXX, I1_XY_, + 0,0,0,0}}, + /* YX1 */ + {3,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_XXX, I1__Y_, + I0_YYY, I1_X__, + 0,0}}, + /* ZX1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_ZXY, I1_XY_, + 0,0,0,0}}, + /* WX1 */ + {3,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_XXX, I1__Y_, + I0_WZY, I1_X__, + 0,0}}, + /* 0X1 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_XXX, I1__Y_, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 1X1 */ + {2,{2,0,0,0},{ I0_111, I1_X_Z | I1_CST, + I0_XXX, I1__Y_, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XY1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_XYZ, I1_XY_, + 0,0,0,0}}, + /* YY1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_YYY, I1_XY_, + 0,0,0,0}}, + /* ZY1 */ + {3,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_ZZZ, I1_X__, + I0_YYY, I1__Y_, + 0,0}}, + /* WY1 */ + {3,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_XYZ, I1__Y_, + I0_WZY, I1_X__, + 0,0}}, + /* 0Y1 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_XYZ, I1__Y_, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 1Y1 */ + {2,{2,0,0,0},{ I0_111, I1_X_Z | I1_CST, + I0_XYZ, I1__Y_, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XZ1 */ + {3,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_XYZ, I1_X__, + I0_ZZZ, I1__Y_, + 0,0}}, + /* YZ1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_YZX, I1_XY_, + 0,0,0,0}}, + /* ZZ1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_ZZZ, I1_XY_, + 0,0,0,0}}, + /* WZ1 */ + {2,{2,0,0,0},{ I0_111, I1___Z | I1_CST, + I0_WZY, I1_XY_, + 0,0,0,0}}, + /* 0Z1 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_ZZZ, I1__Y_, + I0_000, I1_X__ | I1_CST, + 0,0}}, + /* 1Z1 */ + {2,{2,0,0,0},{ I0_111, I1_X_Z | I1_CST, + I0_ZZZ, I1__Y_, + 0,0,0,0}}, + SEMPTY,SEMPTY, + /* XW1 */ + {4,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_000, I1___Z | I1_CST, + I0_XYZ, I1_X__ } }, + /* YW1 */ + {4,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_111, I1___Z | I1_CST, + I0_YYY, I1_X__ } }, + /* ZW1 */ + {4,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_111, I1___Z | I1_CST, + I0_ZZZ, I1_X__ } }, + /* WW1 */ + {3,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1_XY_, + I0_111, I1___Z | I1_CST, + 0,0}}, + /* 0W1 */ + {4,{0,1,2,2},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_111, I1___Z | I1_CST, + I0_000, I1_X__ | I1_CST } }, + /* 1W1 */ + {3,{0,1,2,0},{ I0_WZY, I1_XYZ, + I0_XXX, I1__Y_, + I0_111, I1_X_Z | I1_CST, + 0,0}}, + SEMPTY,SEMPTY, + /* X01 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_XYZ, I1_X__, + I0_000, I1__Y_ | I1_CST, + 0,0}}, + /* Y01 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_YYY, I1_X__, + I0_000, I1__Y_ | I1_CST, + 0,0}}, + /* Z01 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_ZZZ, I1_X__, + I0_000, I1__Y_ | I1_CST, + 0,0}}, + /* W01 */ + {3,{2,0,2,0},{ I0_111, I1___Z | I1_CST, + I0_WZY, I1_X__, + I0_000, I1__Y_ | I1_CST, + 0,0}}, + /* 001 */ + {2,{2,2,0,0},{ I0_111, I1___Z | I1_CST, + I0_000, I1_XY_ | I1_CST, + 0,0,0,0}}, + /* 101 */ + {2,{2,2,0,0},{ I0_111, I1_X_Z | I1_CST, + I0_000, I1__Y_ | I1_CST, + 0, 0, 0, 0 } }, + SEMPTY,SEMPTY, + /* X11 */ + {2,{2,0,0,0},{ I0_111, I1__YZ | I1_CST, + I0_XYZ, I1_X__, + 0,0,0,0}}, + /* Y11 */ + {2,{2,0,0,0},{ I0_111, I1__YZ | I1_CST, + I0_YYY, I1_X__, + 0,0,0,0}}, + /* Z11 */ + {2,{2,0,0,0},{ I0_111, I1__YZ | I1_CST, + I0_ZZZ, I1_X__, + 0,0,0,0}}, + /* W11 */ + {2,{2,0,0,0},{ I0_111, I1__YZ | I1_CST, + I0_WZY, I1_X__, + 0,0,0,0}}, + /* 011 */ + {2,{2,2,0,0},{ I0_111, I1__YZ | I1_CST, + I0_000, I1_X__ | I1_CST, + 0,0,0,0}}, + /* 111 */ + {1,{2,0,0,0},{ I0_111, I1_XYZ | I1_CST, + 0, 0, 0, 0, 0, 0 } }, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY, + SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY,SEMPTY +}; + +/****************************************************************************** +* Color source mask table +******************************************************************************/ + +#define S_111 R300_FPI0_ARGC_ONE +#define S_000 R300_FPI0_ARGC_ZERO + +#define S0XXX R300_FPI0_ARGC_SRC0C_XXX +#define S0YYY R300_FPI0_ARGC_SRC0C_YYY +#define S0ZZZ R300_FPI0_ARGC_SRC0C_ZZZ +#define S0XYZ R300_FPI0_ARGC_SRC0C_XYZ +#define S0ZXY R300_FPI0_ARGC_SRC0C_ZXY +#define S0YZX R300_FPI0_ARGC_SRC0C_YZX +#define S0WZY R300_FPI0_ARGC_SRC0CA_WZY +#define S0WZY R300_FPI0_ARGC_SRC0CA_WZY + +#define S1XXX R300_FPI0_ARGC_SRC1C_XXX +#define S1YYY R300_FPI0_ARGC_SRC1C_YYY +#define S1ZZZ R300_FPI0_ARGC_SRC1C_ZZZ +#define S1XYZ R300_FPI0_ARGC_SRC1C_XYZ +#define S1ZXY R300_FPI0_ARGC_SRC1C_ZXY +#define S1YZX R300_FPI0_ARGC_SRC1C_YZX +#define S1WZY R300_FPI0_ARGC_SRC1CA_WZY + +#define S2XXX R300_FPI0_ARGC_SRC2C_XXX +#define S2YYY R300_FPI0_ARGC_SRC2C_YYY +#define S2ZZZ R300_FPI0_ARGC_SRC2C_ZZZ +#define S2XYZ R300_FPI0_ARGC_SRC2C_XYZ +#define S2ZXY R300_FPI0_ARGC_SRC2C_ZXY +#define S2YZX R300_FPI0_ARGC_SRC2C_YZX +#define S2WZY R300_FPI0_ARGC_SRC2CA_WZY + +#define ntnat 32 + +const GLuint r300_swz_srcc_mask[3][512] = { + { + S0XXX,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S0YZX,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S0ZXY,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,S0YYY,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,S0WZY,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S0XYZ,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S0ZZZ,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,S_000,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,S_111,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat + }, + { + S1XXX,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S1YZX,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S1ZXY,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,S1YYY,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,S1WZY,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S1XYZ,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S1ZZZ,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,S_000,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,S_111,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat + }, + { + S2XXX,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S2YZX,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S2ZXY,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,S2YYY,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,S2WZY,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S2XYZ,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,S2ZZZ,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,S_000,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,S_111,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat,ntnat, + ntnat,ntnat + } +}; + +/****************************************************************************** +* Alpha source mask table +******************************************************************************/ + +GLuint r300_swz_srca_mask[3][6] = { + { R300_FPI2_ARGA_SRC0C_X, + R300_FPI2_ARGA_SRC0C_Y, + R300_FPI2_ARGA_SRC0C_Z, + R300_FPI2_ARGA_SRC0A, + R300_FPI2_ARGA_ZERO, + R300_FPI2_ARGA_ONE }, + { R300_FPI2_ARGA_SRC1C_X, + R300_FPI2_ARGA_SRC1C_Y, + R300_FPI2_ARGA_SRC1C_Z, + R300_FPI2_ARGA_SRC1A, + R300_FPI2_ARGA_ZERO, + R300_FPI2_ARGA_ONE }, + { R300_FPI2_ARGA_SRC2C_X, + R300_FPI2_ARGA_SRC2C_Y, + R300_FPI2_ARGA_SRC2C_Z, + R300_FPI2_ARGA_SRC2A, + R300_FPI2_ARGA_ZERO, + R300_FPI2_ARGA_ONE }, +}; diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_ioctl.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_ioctl.c new file mode 100644 index 000000000..82379ebb3 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_ioctl.c @@ -0,0 +1,774 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. +Copyright (C) 2004 Nicolai Haehnle. +All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#include <sched.h> +#include <errno.h> + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "context.h" +#include "swrast/swrast.h" + +#include "r300_context.h" +#include "radeon_ioctl.h" +#include "r300_ioctl.h" +#include "r300_cmdbuf.h" +#include "r300_state.h" +#include "r300_program.h" +#include "radeon_reg.h" +#include "r300_emit.h" + +#include "vblank.h" + +//#define CB_DPATH + +#define CLEARBUFFER_COLOR 0x1 +#define CLEARBUFFER_DEPTH 0x2 +#define CLEARBUFFER_STENCIL 0x4 + +static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer) +{ + GLcontext* ctx = r300->radeon.glCtx; + __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable; + GLuint cboffset, cbpitch; + drm_r300_cmd_header_t* cmd2; +#ifdef CB_DPATH + r300ContextPtr rmesa=r300; + LOCAL_VARS; +#else + int i; +#endif + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s: %s buffer (%i,%i %ix%i)\n", + __FUNCTION__, buffer ? "back" : "front", + dPriv->x, dPriv->y, dPriv->w, dPriv->h); + + if (buffer) { + cboffset = r300->radeon.radeonScreen->backOffset; + cbpitch = r300->radeon.radeonScreen->backPitch; + } else { + cboffset = r300->radeon.radeonScreen->frontOffset; + cbpitch = r300->radeon.radeonScreen->frontPitch; + } + + cboffset += r300->radeon.radeonScreen->fbLocation; + +#ifndef CB_DPATH + R300_STATECHANGE(r300, vir[0]); + ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = 1; + r300->hw.vir[0].cmd[1] = 0x21030003; + + R300_STATECHANGE(r300, vir[1]); + ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->packet0.count = 1; + r300->hw.vir[1].cmd[1] = 0xF688F688; + + R300_STATECHANGE(r300, vic); + r300->hw.vic.cmd[R300_VIC_CNTL_0] = 0x00000001; + r300->hw.vic.cmd[R300_VIC_CNTL_1] = 0x00000405; + + R300_STATECHANGE(r300, vof); + r300->hw.vof.cmd[R300_VOF_CNTL_0] = R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT + | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; /* no textures */ + + R300_STATECHANGE(r300, txe); + r300->hw.txe.cmd[R300_TXE_ENABLE] = 0; + + R300_STATECHANGE(r300, vpt); + r300->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(1.0); + r300->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(dPriv->x); + r300->hw.vpt.cmd[R300_VPT_YSCALE] = r300PackFloat32(1.0); + r300->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(dPriv->y); + r300->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(1.0); + r300->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(0.0); + + R300_STATECHANGE(r300, at); + r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0; + + R300_STATECHANGE(r300, bld); + r300->hw.bld.cmd[R300_BLD_CBLEND] = 0; + r300->hw.bld.cmd[R300_BLD_ABLEND] = 0; + + if (r300->radeon.radeonScreen->cpp == 4) + cbpitch |= R300_COLOR_FORMAT_ARGB8888; + else + cbpitch |= R300_COLOR_FORMAT_RGB565; + + if (r300->radeon.sarea->tiling_enabled) + cbpitch |= R300_COLOR_TILE_ENABLE; + + R300_STATECHANGE(r300, cb); + r300->hw.cb.cmd[R300_CB_OFFSET] = cboffset; + r300->hw.cb.cmd[R300_CB_PITCH] = cbpitch; + + R300_STATECHANGE(r300, unk221C); + r300->hw.unk221C.cmd[1] = R300_221C_CLEAR; + + R300_STATECHANGE(r300, ps); + r300->hw.ps.cmd[R300_PS_POINTSIZE] = + ((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) | + ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT); + + R300_STATECHANGE(r300, ri); + for(i = 1; i <= 8; ++i) + r300->hw.ri.cmd[i] = R300_RS_INTERP_USED; + + R300_STATECHANGE(r300, rc); + /* The second constant is needed to get glxgears display anything .. */ + r300->hw.rc.cmd[1] = (1 << R300_RS_CNTL_CI_CNT_SHIFT) | R300_RS_CNTL_0_UNKNOWN_18; + r300->hw.rc.cmd[2] = 0; + + R300_STATECHANGE(r300, rr); + ((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->packet0.count = 1; + r300->hw.rr.cmd[1] = 0x00004000; + + R300_STATECHANGE(r300, cmk); + if (flags & CLEARBUFFER_COLOR) { + r300->hw.cmk.cmd[R300_CMK_COLORMASK] = + (ctx->Color.ColorMask[BCOMP] ? R300_COLORMASK0_B : 0) | + (ctx->Color.ColorMask[GCOMP] ? R300_COLORMASK0_G : 0) | + (ctx->Color.ColorMask[RCOMP] ? R300_COLORMASK0_R : 0) | + (ctx->Color.ColorMask[ACOMP] ? R300_COLORMASK0_A : 0); + } else { + r300->hw.cmk.cmd[R300_CMK_COLORMASK] = 0; + } + + R300_STATECHANGE(r300, fp); + r300->hw.fp.cmd[R300_FP_CNTL0] = 0; /* 1 pass, no textures */ + r300->hw.fp.cmd[R300_FP_CNTL1] = 0; /* no temporaries */ + r300->hw.fp.cmd[R300_FP_CNTL2] = 0; /* no offset, one ALU instr */ + r300->hw.fp.cmd[R300_FP_NODE0] = 0; + r300->hw.fp.cmd[R300_FP_NODE1] = 0; + r300->hw.fp.cmd[R300_FP_NODE2] = 0; + r300->hw.fp.cmd[R300_FP_NODE3] = R300_PFS_NODE_LAST_NODE; + + R300_STATECHANGE(r300, fpi[0]); + R300_STATECHANGE(r300, fpi[1]); + R300_STATECHANGE(r300, fpi[2]); + R300_STATECHANGE(r300, fpi[3]); + ((drm_r300_cmd_header_t*)r300->hw.fpi[0].cmd)->packet0.count = 1; + ((drm_r300_cmd_header_t*)r300->hw.fpi[1].cmd)->packet0.count = 1; + ((drm_r300_cmd_header_t*)r300->hw.fpi[2].cmd)->packet0.count = 1; + ((drm_r300_cmd_header_t*)r300->hw.fpi[3].cmd)->packet0.count = 1; + + /* MOV o0, t0 */ + r300->hw.fpi[0].cmd[1] = FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)); + r300->hw.fpi[1].cmd[1] = FP_SELC(0,NO,XYZ,FP_TMP(0),0,0); + r300->hw.fpi[2].cmd[1] = FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)); + r300->hw.fpi[3].cmd[1] = FP_SELA(0,NO,W,FP_TMP(0),0,0); + + R300_STATECHANGE(r300, pvs); + r300->hw.pvs.cmd[R300_PVS_CNTL_1] = + (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) | + (0 << R300_PVS_CNTL_1_POS_END_SHIFT) | + (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); + r300->hw.pvs.cmd[R300_PVS_CNTL_2] = 0; /* no parameters */ + r300->hw.pvs.cmd[R300_PVS_CNTL_3] = + (1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT); + + R300_STATECHANGE(r300, vpi); + ((drm_r300_cmd_header_t*)r300->hw.vpi.cmd)->packet0.count = 8; + + /* MOV o0, i0; */ + r300->hw.vpi.cmd[1] = VP_OUT(ADD,OUT,0,XYZW); + r300->hw.vpi.cmd[2] = VP_IN(IN,0); + r300->hw.vpi.cmd[3] = VP_ZERO(); + r300->hw.vpi.cmd[4] = 0; + + /* MOV o1, i1; */ + r300->hw.vpi.cmd[5] = VP_OUT(ADD,OUT,1,XYZW); + r300->hw.vpi.cmd[6] = VP_IN(IN,1); + r300->hw.vpi.cmd[7] = VP_ZERO(); + r300->hw.vpi.cmd[8] = 0; + + R300_STATECHANGE(r300, zs); + if (flags & CLEARBUFFER_DEPTH) { + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= 0x6; // test and write + r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= (R300_ZS_ALWAYS<<R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); +/* + R300_STATECHANGE(r300, zb); + r300->hw.zb.cmd[R300_ZB_OFFSET] = + 1024*4*300 + + r300->radeon.radeonScreen->frontOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.zb.cmd[R300_ZB_PITCH] = + r300->radeon.radeonScreen->depthPitch; +*/ + } else { + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_Z_DISABLED_1; // disable + r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); + } + + R300_STATECHANGE(r300, zs); + if (flags & CLEARBUFFER_STENCIL) { + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= ~R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_1] &= + ~((R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT)); + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= + (R300_ZS_ALWAYS<<R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) | + (R300_ZS_ALWAYS<<R300_RB3D_ZS1_BACK_FUNC_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT) ; + r300->hw.zs.cmd[R300_ZS_CNTL_2] = r300->state.stencil.clear; + } + + /* Make sure we have enough space */ + r300EnsureCmdBufSpace(r300, r300->hw.max_state_size + 9+8, __FUNCTION__); + + r300EmitState(r300); +#else + R300_STATECHANGE(r300, cb); + reg_start(R300_RB3D_COLOROFFSET0, 0); + e32(cboffset); + + if (r300->radeon.radeonScreen->cpp == 4) + cbpitch |= R300_COLOR_FORMAT_ARGB8888; + else + cbpitch |= R300_COLOR_FORMAT_RGB565; + + reg_start(R300_RB3D_COLORPITCH0, 0); + e32(cbpitch); + + R300_STATECHANGE(r300, cmk); + reg_start(R300_RB3D_COLORMASK, 0); + + if (flags & CLEARBUFFER_COLOR) { + e32((ctx->Color.ColorMask[BCOMP] ? R300_COLORMASK0_B : 0) | + (ctx->Color.ColorMask[GCOMP] ? R300_COLORMASK0_G : 0) | + (ctx->Color.ColorMask[RCOMP] ? R300_COLORMASK0_R : 0) | + (ctx->Color.ColorMask[ACOMP] ? R300_COLORMASK0_A : 0)); + } else { + e32(0); + } + + R300_STATECHANGE(r300, zs); + reg_start(R300_RB3D_ZSTENCIL_CNTL_0, 2); + + { + uint32_t t1, t2; + + t1 = r300->hw.zs.cmd[R300_ZS_CNTL_0]; + t2 = r300->hw.zs.cmd[R300_ZS_CNTL_1]; + + if (flags & CLEARBUFFER_DEPTH) { + t1 &= R300_RB3D_STENCIL_ENABLE; + t1 |= 0x6; // test and write + + t2 &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); + t2 |= (R300_ZS_ALWAYS<<R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); +/* + R300_STATECHANGE(r300, zb); + r300->hw.zb.cmd[R300_ZB_OFFSET] = + 1024*4*300 + + r300->radeon.radeonScreen->frontOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.zb.cmd[R300_ZB_PITCH] = + r300->radeon.radeonScreen->depthPitch; +*/ + } else { + t1 &= R300_RB3D_STENCIL_ENABLE; + t1 |= R300_RB3D_Z_DISABLED_1; // disable + + t2 &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); + } + + if (flags & CLEARBUFFER_STENCIL) { + t1 &= ~R300_RB3D_STENCIL_ENABLE; + t1 |= R300_RB3D_STENCIL_ENABLE; + + t2 &= + ~((R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT)); + t2 |= + (R300_ZS_ALWAYS<<R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) | + (R300_ZS_ALWAYS<<R300_RB3D_ZS1_BACK_FUNC_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) | + (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT) ; + } + + e32(t1); + e32(t2); + e32(r300->state.stencil.clear); + } + +#endif + + cmd2 = (drm_r300_cmd_header_t*)r300AllocCmdBuf(r300, 9, __FUNCTION__); + cmd2[0].packet3.cmd_type = R300_CMD_PACKET3; + cmd2[0].packet3.packet = R300_CMD_PACKET3_CLEAR; + cmd2[1].u = r300PackFloat32(dPriv->w / 2.0); + cmd2[2].u = r300PackFloat32(dPriv->h / 2.0); + cmd2[3].u = r300PackFloat32(ctx->Depth.Clear); + cmd2[4].u = r300PackFloat32(1.0); + cmd2[5].u = r300PackFloat32(ctx->Color.ClearColor[0]); + cmd2[6].u = r300PackFloat32(ctx->Color.ClearColor[1]); + cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]); + cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]); + +} + +#ifdef CB_DPATH +static void r300EmitClearState(GLcontext * ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + r300ContextPtr rmesa=r300; + __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable; + int i; + LOCAL_VARS; + + R300_STATECHANGE(r300, vir[0]); + reg_start(R300_VAP_INPUT_ROUTE_0_0, 0); + e32(0x21030003); + + R300_STATECHANGE(r300, vir[1]); + reg_start(R300_VAP_INPUT_ROUTE_1_0, 0); + e32(0xF688F688); + + R300_STATECHANGE(r300, vic); + reg_start(R300_VAP_INPUT_CNTL_0, 1); + e32(0x00000001); + e32(0x00000405); + + R300_STATECHANGE(r300, vof); + reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1); + e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT); + e32(0); /* no textures */ + + + R300_STATECHANGE(r300, txe); + reg_start(R300_TX_ENABLE, 0); + e32(0); + + R300_STATECHANGE(r300, vpt); + reg_start(R300_SE_VPORT_XSCALE, 5); + efloat(1.0); + efloat(dPriv->x); + efloat(1.0); + efloat(dPriv->y); + efloat(1.0); + efloat(0.0); + + R300_STATECHANGE(r300, at); + reg_start(R300_PP_ALPHA_TEST, 0); + e32(0); + + R300_STATECHANGE(r300, bld); + reg_start(R300_RB3D_CBLEND, 1); + e32(0); + e32(0); + + R300_STATECHANGE(r300, unk221C); + reg_start(0x221C, 0); + e32(R300_221C_CLEAR); + + R300_STATECHANGE(r300, ps); + reg_start(R300_RE_POINTSIZE, 0); + e32(((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) | + ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT)); + + R300_STATECHANGE(r300, ri); + reg_start(R300_RS_INTERP_0, 8); + for(i = 0; i < 8; ++i){ + e32(R300_RS_INTERP_USED); + } + + R300_STATECHANGE(r300, rc); + /* The second constant is needed to get glxgears display anything .. */ + reg_start(R300_RS_CNTL_0, 1); + e32(R300_RS_CNTL_0_UNKNOWN_7 | R300_RS_CNTL_0_UNKNOWN_18); + e32(0); + + R300_STATECHANGE(r300, rr); + reg_start(R300_RS_ROUTE_0, 0); + e32(0x00004000); + + R300_STATECHANGE(r300, fp); + reg_start(R300_PFS_CNTL_0, 2); + e32(0); + e32(0); + e32(0); + reg_start(R300_PFS_NODE_0, 3); + e32(0); + e32(0); + e32(0); + e32(R300_PFS_NODE_LAST_NODE); + + R300_STATECHANGE(r300, fpi[0]); + R300_STATECHANGE(r300, fpi[1]); + R300_STATECHANGE(r300, fpi[2]); + R300_STATECHANGE(r300, fpi[3]); + + reg_start(R300_PFS_INSTR0_0, 0); + e32(FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO))); + + reg_start(R300_PFS_INSTR1_0, 0); + e32(FP_SELC(0,NO,XYZ,FP_TMP(0),0,0)); + + reg_start(R300_PFS_INSTR2_0, 0); + e32(FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO))); + + reg_start(R300_PFS_INSTR3_0, 0); + e32(FP_SELA(0,NO,W,FP_TMP(0),0,0)); + + R300_STATECHANGE(r300, pvs); + reg_start(R300_VAP_PVS_CNTL_1, 2); + e32((0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) | + (0 << R300_PVS_CNTL_1_POS_END_SHIFT) | + (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT)); + e32(0); + e32(1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT); + + R300_STATECHANGE(r300, vpi); + vsf_start_fragment(0x0, 8); + e32(VP_OUT(ADD,OUT,0,XYZW)); + e32(VP_IN(IN,0)); + e32(VP_ZERO()); + e32(0); + + e32(VP_OUT(ADD,OUT,1,XYZW)); + e32(VP_IN(IN,1)); + e32(VP_ZERO()); + e32(0); + +} +#endif + +/** + * Buffer clear + */ +static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable; + int flags = 0; + int bits = 0; + int swapped; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n", + __FUNCTION__, all, cx, cy, cw, ch); + + { + LOCK_HARDWARE(&r300->radeon); + UNLOCK_HARDWARE(&r300->radeon); + if (dPriv->numClipRects == 0) + return; + } + + if (mask & BUFFER_BIT_FRONT_LEFT) { + flags |= BUFFER_BIT_FRONT_LEFT; + mask &= ~BUFFER_BIT_FRONT_LEFT; + } + + if (mask & BUFFER_BIT_BACK_LEFT) { + flags |= BUFFER_BIT_BACK_LEFT; + mask &= ~BUFFER_BIT_BACK_LEFT; + } + + if (mask & BUFFER_BIT_DEPTH) { + bits |= CLEARBUFFER_DEPTH; + mask &= ~BUFFER_BIT_DEPTH; + } + + if ( (mask & BUFFER_BIT_STENCIL) && r300->state.stencil.hw_stencil) { + bits |= CLEARBUFFER_STENCIL; + mask &= ~BUFFER_BIT_STENCIL; + } + + if (mask) { + if (RADEON_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "%s: swrast clear, mask: %x\n", + __FUNCTION__, mask); + _swrast_Clear(ctx, mask, all, cx, cy, cw, ch); + } + + swapped = r300->radeon.doPageFlip && (r300->radeon.sarea->pfCurrentPage == 1); + +#ifdef CB_DPATH + if(flags || bits) + r300EmitClearState(ctx); +#endif + + if (flags & BUFFER_BIT_FRONT_LEFT) { + r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped); + bits = 0; + } + + if (flags & BUFFER_BIT_BACK_LEFT) { + r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1); + bits = 0; + } + + if (bits) + r300ClearBuffer(r300, bits, 0); + +#ifndef CB_DPATH + /* Recalculate the hardware state. This could be done more efficiently, + * but do keep it like this for now. + */ + r300ResetHwState(r300); + + /* r300ClearBuffer has trampled all over the hardware state.. */ + r300->hw.all_dirty=GL_TRUE; +#endif +} + +void r300Flush(GLcontext * ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit) + r300FlushCmdBuf(r300, __FUNCTION__); +} + +void r300RefillCurrentDmaRegion(r300ContextPtr rmesa) +{ + struct r300_dma_buffer *dmabuf; + int fd = rmesa->radeon.dri.fd; + int index = 0; + int size = 0; + drmDMAReq dma; + int ret; + + if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA)) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (rmesa->dma.flush) { + rmesa->dma.flush(rmesa); + } + + if (rmesa->dma.current.buf) + r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__); + + if (rmesa->dma.nr_released_bufs > 4) + r300FlushCmdBuf(rmesa, __FUNCTION__); + + dma.context = rmesa->radeon.dri.hwContext; + dma.send_count = 0; + dma.send_list = NULL; + dma.send_sizes = NULL; + dma.flags = 0; + dma.request_count = 1; + dma.request_size = RADEON_BUFFER_SIZE; + dma.request_list = &index; + dma.request_sizes = &size; + dma.granted_count = 0; + + LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */ + + ret = drmDMA(fd, &dma); + + if (ret != 0) { + /* Try to release some buffers and wait until we can't get any more */ + if (rmesa->dma.nr_released_bufs) { + r300FlushCmdBufLocked(rmesa, __FUNCTION__); + } + + if (RADEON_DEBUG & DEBUG_DMA) + fprintf(stderr, "Waiting for buffers\n"); + + radeonWaitForIdleLocked(&rmesa->radeon); + ret = drmDMA(fd, &dma); + + if (ret != 0) { + UNLOCK_HARDWARE(&rmesa->radeon); + fprintf(stderr, "Error: Could not get dma buffer... exiting\n"); + exit(-1); + } + } + + UNLOCK_HARDWARE(&rmesa->radeon); + + if (RADEON_DEBUG & DEBUG_DMA) + fprintf(stderr, "Allocated buffer %d\n", index); + + dmabuf = CALLOC_STRUCT(r300_dma_buffer); + dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index]; + dmabuf->refcount = 1; + + rmesa->dma.current.buf = dmabuf; + rmesa->dma.current.address = dmabuf->buf->address; + rmesa->dma.current.end = dmabuf->buf->total; + rmesa->dma.current.start = 0; + rmesa->dma.current.ptr = 0; +} + +void r300ReleaseDmaRegion(r300ContextPtr rmesa, + struct r300_dma_region *region, const char *caller) +{ + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); + + if (!region->buf) + return; + + if (rmesa->dma.flush) + rmesa->dma.flush(rmesa); + + if (--region->buf->refcount == 0) { + drm_radeon_cmd_header_t *cmd; + + if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA)) + fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__, + region->buf->buf->idx); + cmd = + (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, + sizeof(*cmd) / 4, + __FUNCTION__); + cmd->dma.cmd_type = R300_CMD_DMA_DISCARD; + cmd->dma.buf_idx = region->buf->buf->idx; + + FREE(region->buf); + rmesa->dma.nr_released_bufs++; + } + + region->buf = 0; + region->start = 0; +} + +/* Allocates a region from rmesa->dma.current. If there isn't enough + * space in current, grab a new buffer (and discard what was left of current) + */ +void r300AllocDmaRegion(r300ContextPtr rmesa, + struct r300_dma_region *region, + int bytes, int alignment) +{ + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); + + if (rmesa->dma.flush) + rmesa->dma.flush(rmesa); + + if (region->buf) + r300ReleaseDmaRegion(rmesa, region, __FUNCTION__); + + alignment--; + rmesa->dma.current.start = rmesa->dma.current.ptr = + (rmesa->dma.current.ptr + alignment) & ~alignment; + + if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end) + r300RefillCurrentDmaRegion(rmesa); + + region->start = rmesa->dma.current.start; + region->ptr = rmesa->dma.current.start; + region->end = rmesa->dma.current.start + bytes; + region->address = rmesa->dma.current.address; + region->buf = rmesa->dma.current.buf; + region->buf->refcount++; + + rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */ + rmesa->dma.current.start = + rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7; + + assert(rmesa->dma.current.ptr <= rmesa->dma.current.end); +} + +/* Called via glXGetMemoryOffsetMESA() */ +GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn, + const GLvoid * pointer) +{ + GET_CURRENT_CONTEXT(ctx); + r300ContextPtr rmesa; + GLuint card_offset; + + if (!ctx || !(rmesa = R300_CONTEXT(ctx))) { + fprintf(stderr, "%s: no context\n", __FUNCTION__); + return ~0; + } + + if (!r300IsGartMemory(rmesa, pointer, 0)) + return ~0; + + if (rmesa->radeon.dri.drmMinor < 6) + return ~0; + + card_offset = r300GartOffsetFromVirtual(rmesa, pointer); + + return card_offset - rmesa->radeon.radeonScreen->gart_base; +} + +GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer, + GLint size) +{ + int offset = + (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map; + int valid = (size >= 0 && offset >= 0 + && offset + size < rmesa->radeon.radeonScreen->gartTextures.size); + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer, + valid); + + return valid; +} + +GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer) +{ + int offset = + (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map; + + //fprintf(stderr, "offset=%08x\n", offset); + + if (offset < 0 || offset > rmesa->radeon.radeonScreen->gartTextures.size) + return ~0; + else + return rmesa->radeon.radeonScreen->gart_texture_offset + offset; +} + +void r300InitIoctlFuncs(struct dd_function_table *functions) +{ + functions->Clear = r300Clear; + functions->Finish = radeonFinish; + functions->Flush = r300Flush; +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_ioctl.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_ioctl.h new file mode 100644 index 000000000..5514214cc --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_ioctl.h @@ -0,0 +1,62 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __R300_IOCTL_H__ +#define __R300_IOCTL_H__ + +#include "r300_context.h" +#include "radeon_drm.h" + +extern GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn, + const GLvoid * pointer); + +extern GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer, + GLint size); + +extern GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, + const GLvoid * pointer); + +extern void r300Flush(GLcontext * ctx); + +extern void r300RefillCurrentDmaRegion(r300ContextPtr rmesa); +extern void r300ReleaseDmaRegion(r300ContextPtr rmesa, + struct r300_dma_region *region, const char *caller); +extern void r300AllocDmaRegion(r300ContextPtr rmesa, + struct r300_dma_region *region, + int bytes, int alignment); + +extern void r300InitIoctlFuncs(struct dd_function_table *functions); + +#endif /* __R300_IOCTL_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_maos.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_maos.c new file mode 100644 index 000000000..1908ac07a --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_maos.c @@ -0,0 +1,561 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_maos_arrays.c,v 1.3 2003/02/23 23:59:01 dawes Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "mtypes.h" +#include "colormac.h" +#include "imports.h" +#include "macros.h" + +#include "swrast_setup/swrast_setup.h" +#include "math/m_translate.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +#include "r300_context.h" +#include "radeon_ioctl.h" +#include "r300_state.h" +#include "r300_maos.h" +#include "r300_ioctl.h" + +#define DEBUG_ALL DEBUG_VERTS + + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( dst, src, nr ) \ +do { \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \ + : "0" (nr), \ + "D" ((long)dst), \ + "S" ((long)src) ); \ +} while (0) +#else +#define COPY_DWORDS( dst, src, nr ) \ +do { \ + int j; \ + for ( j = 0 ; j < nr ; j++ ) \ + dst[j] = ((int *)src)[j]; \ + dst += nr; \ +} while (0) +#endif + +static void emit_vec4(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid *data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 4) + COPY_DWORDS(out, data, count); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out++; + data += stride; + } +} + +static void emit_vec8(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid *data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 8) + COPY_DWORDS(out, data, count * 2); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data + 4); + out += 2; + data += stride; + } +} + +static void emit_vec12(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid *data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d out %p data %p\n", + __FUNCTION__, count, stride, (void *)out, (void *)data); + + if (stride == 12) + COPY_DWORDS(out, data, count * 3); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data + 4); + out[2] = *(int *)(data + 8); + out += 3; + data += stride; + } +} + +static void emit_vec16(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid *data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 16) + COPY_DWORDS(out, data, count * 4); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data + 4); + out[2] = *(int *)(data + 8); + out[3] = *(int *)(data + 12); + out += 4; + data += stride; + } +} + +static void emit_vector(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid *data, int size, int stride, int count) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d size %d stride %d\n", + __FUNCTION__, count, size, stride); + + if(r300IsGartMemory(rmesa, data, size*stride)){ + rvb->address = rmesa->radeon.radeonScreen->gartTextures.map; + rvb->start = (char *)data - rvb->address; + rvb->aos_offset = r300GartOffsetFromVirtual(rmesa, data); + + if(stride == 0) + rvb->aos_stride = 0; + else + rvb->aos_stride = stride / 4; + + rvb->aos_size = size; + return; + } + + /* Gets triggered when playing with future_hw_tcl_on ...*/ + //assert(!rvb->buf); + + if (stride == 0) { + r300AllocDmaRegion(rmesa, rvb, size * 4, 4); + count = 1; + rvb->aos_offset = GET_START(rvb); + rvb->aos_stride = 0; + rvb->aos_size = size; + } else { + r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4); /* alignment? */ + rvb->aos_offset = GET_START(rvb); + rvb->aos_stride = size; + rvb->aos_size = size; + } + + /* Emit the data + */ + switch (size) { + case 1: + emit_vec4(ctx, rvb, data, stride, count); + break; + case 2: + emit_vec8(ctx, rvb, data, stride, count); + break; + case 3: + emit_vec12(ctx, rvb, data, stride, count); + break; + case 4: + emit_vec16(ctx, rvb, data, stride, count); + break; + default: + assert(0); + exit(1); + break; + } + +} + +void r300EmitElts(GLcontext * ctx, GLuint *elts, unsigned long n_elts) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct r300_dma_region *rvb=&rmesa->state.elt_dma; + unsigned short int *out; + int i; + + if(r300IsGartMemory(rmesa, elts, n_elts*sizeof(unsigned short int))){ + rvb->address = rmesa->radeon.radeonScreen->gartTextures.map; + rvb->start = (char *)elts - rvb->address; + rvb->aos_offset = rmesa->radeon.radeonScreen->gart_texture_offset + rvb->start; + return ; + } + + r300AllocDmaRegion(rmesa, rvb, n_elts*sizeof(unsigned short int), 2); + + out = (unsigned short int *)(rvb->address + rvb->start); + + for(i=0; i < n_elts; i++) + out[i]=(unsigned short int)elts[i]; +} + +/* Emit vertex data to GART memory (unless immediate mode) + * Route inputs to the vertex processor + */ +void r300EmitArrays(GLcontext * ctx, GLboolean immd) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + r300ContextPtr r300 = rmesa; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLuint nr = 0; + GLuint count = VB->Count; + GLuint dw,mask; + GLuint vic_1 = 0; /* R300_VAP_INPUT_CNTL_1 */ + GLuint aa_vap_reg = 0; /* VAP register assignment */ + GLuint i; + GLuint inputs = 0; + + +#define CONFIGURE_AOS(r, f, v, sz, cn) { \ + if (RADEON_DEBUG & DEBUG_STATE) \ + fprintf(stderr, "Enabling "#v "\n"); \ + if (++nr >= R300_MAX_AOS_ARRAYS) { \ + fprintf(stderr, "Aieee! AOS array count exceeded!\n"); \ + exit(-1); \ + } \ + \ + if (hw_tcl_on == GL_FALSE) \ + rmesa->state.aos[nr-1].aos_reg = aa_vap_reg++; \ + rmesa->state.aos[nr-1].aos_format = f; \ + if (immd) { \ + rmesa->state.aos[nr-1].aos_size = 4; \ + rmesa->state.aos[nr-1].aos_stride = 4; \ + rmesa->state.aos[nr-1].aos_offset = 0; \ + } else { \ + emit_vector(ctx, \ + &rmesa->state.aos[nr-1], \ + v->data, \ + sz, \ + v->stride, \ + cn); \ + rmesa->state.vap_reg.r=rmesa->state.aos[nr-1].aos_reg; \ + } \ +} + + if (hw_tcl_on) { + GLuint InputsRead = CURRENT_VERTEX_SHADER(ctx)->InputsRead; + struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); + if (InputsRead & (1<<VERT_ATTRIB_POS)) { + inputs |= _TNL_BIT_POS; + rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_POS]; + } + if (InputsRead & (1<<VERT_ATTRIB_NORMAL)) { + inputs |= _TNL_BIT_NORMAL; + rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_NORMAL]; + } + if (InputsRead & (1<<VERT_ATTRIB_COLOR0)) { + inputs |= _TNL_BIT_COLOR0; + rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR0]; + } + if (InputsRead & (1<<VERT_ATTRIB_COLOR1)) { + inputs |= _TNL_BIT_COLOR1; + rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR1]; + } + if (InputsRead & (1<<VERT_ATTRIB_FOG)) { + inputs |= _TNL_BIT_FOG; + rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_FOG]; + } + if(ctx->Const.MaxTextureUnits > 8) { /* Not sure if this can even happen... */ + fprintf(stderr, "%s: Cant handle that many inputs\n", __FUNCTION__); + exit(-1); + } + for (i=0;i<ctx->Const.MaxTextureUnits;i++) { + if (InputsRead & (1<<(VERT_ATTRIB_TEX0+i))) { + inputs |= _TNL_BIT_TEX0<<i; + rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_TEX0+i]; + } + } + nr = 0; + } else { + inputs = TNL_CONTEXT(ctx)->render_inputs; + } + rmesa->state.render_inputs = inputs; + + if (inputs & _TNL_BIT_POS) { + CONFIGURE_AOS(i_coords, AOS_FORMAT_FLOAT, + VB->ObjPtr, + immd ? 4 : VB->ObjPtr->size, + count); + + vic_1 |= R300_INPUT_CNTL_POS; + } + + if (inputs & _TNL_BIT_NORMAL) { + CONFIGURE_AOS(i_normal, AOS_FORMAT_FLOAT, + VB->NormalPtr, + immd ? 4 : VB->NormalPtr->size, + count); + + vic_1 |= R300_INPUT_CNTL_NORMAL; + } + + if (inputs & _TNL_BIT_COLOR0) { + int emitsize=4; + + if (!immd) { + if (VB->ColorPtr[0]->size == 4 && + (VB->ColorPtr[0]->stride != 0 || + VB->ColorPtr[0]->data[0][3] != 1.0)) { + emitsize = 4; + } else { + emitsize = 3; + } + } + + CONFIGURE_AOS(i_color[0], AOS_FORMAT_FLOAT_COLOR, + VB->ColorPtr[0], + immd ? 4 : emitsize, + count); + + vic_1 |= R300_INPUT_CNTL_COLOR; + } + + if (inputs & _TNL_BIT_COLOR1) { + CONFIGURE_AOS(i_color[1], AOS_FORMAT_FLOAT_COLOR, + VB->SecondaryColorPtr[0], + immd ? 4 : VB->SecondaryColorPtr[0]->size, + count); + } + +#if 0 + if (inputs & _TNL_BIT_FOG) { + CONFIGURE_AOS( AOS_FORMAT_FLOAT, + VB->FogCoordPtr, + immd ? 4 : VB->FogCoordPtr->size, + count); + } +#endif + + r300->state.texture.tc_count = 0; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + if (inputs & (_TNL_BIT_TEX0 << i)) { + CONFIGURE_AOS(i_tex[i], AOS_FORMAT_FLOAT, + VB->TexCoordPtr[i], + immd ? 4 : VB->TexCoordPtr[i]->size, + count); + + vic_1 |= R300_INPUT_CNTL_TC0 << i; + r300->state.texture.tc_count++; + } + } + +#define SHOW_INFO(n) do { \ + if (RADEON_DEBUG & DEBUG_ALL) { \ + fprintf(stderr, "RR[%d] - sz=%d, reg=%d, fmt=%d -- st=%d, of=0x%08x\n", \ + n, \ + r300->state.aos[n].aos_size, \ + r300->state.aos[n].aos_reg, \ + r300->state.aos[n].aos_format, \ + r300->state.aos[n].aos_stride, \ + r300->state.aos[n].aos_offset); \ + } \ +} while(0); + + /* setup INPUT_ROUTE */ + R300_STATECHANGE(r300, vir[0]); + for(i=0;i+1<nr;i+=2){ + SHOW_INFO(i) + SHOW_INFO(i+1) + dw=(r300->state.aos[i].aos_size-1) + | ((r300->state.aos[i].aos_reg)<<8) + | (r300->state.aos[i].aos_format<<14) + | (((r300->state.aos[i+1].aos_size-1) + | ((r300->state.aos[i+1].aos_reg)<<8) + | (r300->state.aos[i+1].aos_format<<14))<<16); + + if(i+2==nr){ + dw|=(1<<(13+16)); + } + r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(i>>1)]=dw; + } + if(nr & 1){ + SHOW_INFO(nr-1) + dw=(r300->state.aos[nr-1].aos_size-1) + | (r300->state.aos[nr-1].aos_format<<14) + | ((r300->state.aos[nr-1].aos_reg)<<8) + | (1<<13); + r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw; + //fprintf(stderr, "vir0 dw=%08x\n", dw); + } + /* Set the rest of INPUT_ROUTE_0 to 0 */ + //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[0].cmd[R300_VIR_CNTL_0+i]=(0x0); + ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = (nr+1)>>1; + + + /* Mesa assumes that all missing components are from (0, 0, 0, 1) */ +#define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT)) + +#define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT)) + + R300_STATECHANGE(r300, vir[1]); + + for(i=0;i+1<nr;i+=2){ + /* do i first.. */ + mask=(1<<(r300->state.aos[i].aos_size*3))-1; + dw=(ALL_COMPONENTS & mask) + | (ALL_DEFAULT & ~mask) + | R300_INPUT_ROUTE_ENABLE; + + /* i+1 */ + mask=(1<<(r300->state.aos[i+1].aos_size*3))-1; + dw|=( + (ALL_COMPONENTS & mask) + | (ALL_DEFAULT & ~mask) + | R300_INPUT_ROUTE_ENABLE + )<<16; + + r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(i>>1)]=dw; + } + if(nr & 1){ + mask=(1<<(r300->state.aos[nr-1].aos_size*3))-1; + dw=(ALL_COMPONENTS & mask) + | (ALL_DEFAULT & ~mask) + | R300_INPUT_ROUTE_ENABLE; + r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw; + //fprintf(stderr, "vir1 dw=%08x\n", dw); + } + /* Set the rest of INPUT_ROUTE_1 to 0 */ + //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[1].cmd[R300_VIR_CNTL_0+i]=0x0; + ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->packet0.count = (nr+1)>>1; + + /* Set up input_cntl */ + /* I don't think this is needed for vertex buffers, but it doesn't hurt anything */ + R300_STATECHANGE(r300, vic); + r300->hw.vic.cmd[R300_VIC_CNTL_0]=0x5555; /* Hard coded value, no idea what it means */ + r300->hw.vic.cmd[R300_VIC_CNTL_1]=vic_1; + +#if 0 + r300->hw.vic.cmd[R300_VIC_CNTL_1]=0; + + if(r300->state.render_inputs & _TNL_BIT_POS) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_POS; + + if(r300->state.render_inputs & _TNL_BIT_NORMAL) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_NORMAL; + + if(r300->state.render_inputs & _TNL_BIT_COLOR0) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_COLOR; + + for(i=0;i < ctx->Const.MaxTextureUnits;i++) + if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=(R300_INPUT_CNTL_TC0<<i); +#endif + + /* Stage 3: VAP output */ + + R300_STATECHANGE(r300, vof); + + r300->hw.vof.cmd[R300_VOF_CNTL_0]=0; + r300->hw.vof.cmd[R300_VOF_CNTL_1]=0; + if (hw_tcl_on){ + GLuint OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten; + + if(OutputsWritten & (1<<VERT_RESULT_HPOS)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + if(OutputsWritten & (1<<VERT_RESULT_COL0)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + /*if(OutputsWritten & (1<<VERT_RESULT_COL1)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT; + if(OutputsWritten & (1<<VERT_RESULT_BFC0)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT; + if(OutputsWritten & (1<<VERT_RESULT_BFC1)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT;*/ + //if(OutputsWritten & (1<<VERT_RESULT_FOGC)) + + if(OutputsWritten & (1<<VERT_RESULT_PSIZ)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; + + for(i=0;i < ctx->Const.MaxTextureUnits;i++) + if(OutputsWritten & (1<<(VERT_RESULT_TEX0+i))) + r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4<<(3*i)); + } else { + if(inputs & _TNL_BIT_POS) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + if(inputs & _TNL_BIT_COLOR0) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + if(inputs & _TNL_BIT_COLOR1) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT; + + for(i=0;i < ctx->Const.MaxTextureUnits;i++) + if(inputs & (_TNL_BIT_TEX0<<i)) + r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i)); + } + + rmesa->state.aos_count = nr; +} + +void r300ReleaseArrays(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + int i; + + r300ReleaseDmaRegion(rmesa, &rmesa->state.elt_dma, __FUNCTION__); + for (i=0;i<rmesa->state.aos_count;i++) { + r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__); + } +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_maos.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_maos.h new file mode 100644 index 000000000..f76c94a21 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_maos.h @@ -0,0 +1,49 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_maos.h,v 1.1 2002/10/30 12:51:52 alanh Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __R300_MAOS_H__ +#define __R300_MAOS_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "r300_context.h" + +extern void r300EmitElts(GLcontext * ctx, GLuint *elts, unsigned long n_elts); +extern void r300EmitArrays(GLcontext * ctx, GLboolean immd); +extern void r300ReleaseArrays(GLcontext * ctx); + +#endif +#endif + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_program.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_program.h new file mode 100644 index 000000000..d1754c066 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_program.h @@ -0,0 +1,151 @@ +/* +Copyright (C) 2004 Nicolai Haehnle. 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. + +**************************************************************************/ + +/* + * Authors: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __R300_PROGRAM_H__ +#define __R300_PROGRAM_H__ + +#include "r300_reg.h" + +/** + * Vertex program helper macros + */ + +/* Produce out dword */ +#define VP_OUTCLASS_TMP R300_VPI_OUT_REG_CLASS_TEMPORARY +#define VP_OUTCLASS_OUT R300_VPI_OUT_REG_CLASS_RESULT + +#define VP_OUTMASK_X R300_VPI_OUT_WRITE_X +#define VP_OUTMASK_Y R300_VPI_OUT_WRITE_Y +#define VP_OUTMASK_Z R300_VPI_OUT_WRITE_Z +#define VP_OUTMASK_W R300_VPI_OUT_WRITE_W +#define VP_OUTMASK_XY (VP_OUTMASK_X|VP_OUTMASK_Y) +#define VP_OUTMASK_XZ (VP_OUTMASK_X|VP_OUTMASK_Z) +#define VP_OUTMASK_XW (VP_OUTMASK_X|VP_OUTMASK_W) +#define VP_OUTMASK_XYZ (VP_OUTMASK_XY|VP_OUTMASK_Z) +#define VP_OUTMASK_XYW (VP_OUTMASK_XY|VP_OUTMASK_W) +#define VP_OUTMASK_XZW (VP_OUTMASK_XZ|VP_OUTMASK_W) +#define VP_OUTMASK_XYZW (VP_OUTMASK_XYZ|VP_OUTMASK_W) +#define VP_OUTMASK_YZ (VP_OUTMASK_Y|VP_OUTMASK_Z) +#define VP_OUTMASK_YW (VP_OUTMASK_Y|VP_OUTMASK_W) +#define VP_OUTMASK_YZW (VP_OUTMASK_YZ|VP_OUTMASK_W) +#define VP_OUTMASK_ZW (VP_OUTMASK_Z|VP_OUTMASK_W) + +#define VP_OUT(instr,outclass,outidx,outmask) \ + (R300_VPI_OUT_OP_##instr | \ + ((outidx) << R300_VPI_OUT_REG_INDEX_SHIFT) | \ + VP_OUTCLASS_##outclass | \ + VP_OUTMASK_##outmask) + +/* Produce in dword */ +#define VP_INCLASS_TMP R300_VPI_IN_REG_CLASS_TEMPORARY +#define VP_INCLASS_IN R300_VPI_IN_REG_CLASS_ATTRIBUTE +#define VP_INCLASS_CONST R300_VPI_IN_REG_CLASS_PARAMETER + +#define VP_IN(class,idx) \ + (((idx) << R300_VPI_IN_REG_INDEX_SHIFT) | \ + VP_INCLASS_##class | \ + (R300_VPI_IN_SELECT_X << R300_VPI_IN_X_SHIFT) | \ + (R300_VPI_IN_SELECT_Y << R300_VPI_IN_Y_SHIFT) | \ + (R300_VPI_IN_SELECT_Z << R300_VPI_IN_Z_SHIFT) | \ + (R300_VPI_IN_SELECT_W << R300_VPI_IN_W_SHIFT)) +#define VP_ZERO() \ + ((R300_VPI_IN_SELECT_ZERO << R300_VPI_IN_X_SHIFT) | \ + (R300_VPI_IN_SELECT_ZERO << R300_VPI_IN_Y_SHIFT) | \ + (R300_VPI_IN_SELECT_ZERO << R300_VPI_IN_Z_SHIFT) | \ + (R300_VPI_IN_SELECT_ZERO << R300_VPI_IN_W_SHIFT)) +#define VP_ONE() \ + ((R300_VPI_IN_SELECT_ONE << R300_VPI_IN_X_SHIFT) | \ + (R300_VPI_IN_SELECT_ONE << R300_VPI_IN_Y_SHIFT) | \ + (R300_VPI_IN_SELECT_ONE << R300_VPI_IN_Z_SHIFT) | \ + (R300_VPI_IN_SELECT_ONE << R300_VPI_IN_W_SHIFT)) + +#define VP_NEG(in,comp) ((in) ^ (R300_VPI_IN_NEG_##comp)) +#define VP_NEGALL(in,comp) VP_NEG(VP_NEG(VP_NEG(VP_NEG((in),X),Y),Z),W) + +/** + * Fragment program helper macros + */ + +/* Produce unshifted source selectors */ +#define FP_TMP(idx) (idx) +#define FP_CONST(idx) ((idx) | (1 << 5)) + +/* Produce source/dest selector dword */ +#define FP_SELC_MASK_NO 0 +#define FP_SELC_MASK_X 1 +#define FP_SELC_MASK_Y 2 +#define FP_SELC_MASK_XY 3 +#define FP_SELC_MASK_Z 4 +#define FP_SELC_MASK_XZ 5 +#define FP_SELC_MASK_YZ 6 +#define FP_SELC_MASK_XYZ 7 + +#define FP_SELC(destidx,regmask,outmask,src0,src1,src2) \ + (((destidx) << R300_FPI1_DSTC_SHIFT) | \ + (FP_SELC_MASK_##regmask << 23) | \ + (FP_SELC_MASK_##outmask << 26) | \ + ((src0) << R300_FPI1_SRC0C_SHIFT) | \ + ((src1) << R300_FPI1_SRC1C_SHIFT) | \ + ((src2) << R300_FPI1_SRC2C_SHIFT)) + +#define FP_SELA_MASK_NO 0 +#define FP_SELA_MASK_W 1 + +#define FP_SELA(destidx,regmask,outmask,src0,src1,src2) \ + (((destidx) << R300_FPI3_DSTA_SHIFT) | \ + (FP_SELA_MASK_##regmask << 23) | \ + (FP_SELA_MASK_##outmask << 24) | \ + ((src0) << R300_FPI3_SRC0A_SHIFT) | \ + ((src1) << R300_FPI3_SRC1A_SHIFT) | \ + ((src2) << R300_FPI3_SRC2A_SHIFT)) + +/* Produce unshifted argument selectors */ +#define FP_ARGC(source) R300_FPI0_ARGC_##source +#define FP_ARGA(source) R300_FPI2_ARGA_##source +#define FP_ABS(arg) ((arg) | (1 << 6)) +#define FP_NEG(arg) ((arg) ^ (1 << 5)) + +/* Produce instruction dword */ +#define FP_INSTRC(opcode,arg0,arg1,arg2) \ + (R300_FPI0_OUTC_##opcode | \ + ((arg0) << R300_FPI0_ARG0C_SHIFT) | \ + ((arg1) << R300_FPI0_ARG1C_SHIFT) | \ + ((arg2) << R300_FPI0_ARG2C_SHIFT)) + +#define FP_INSTRA(opcode,arg0,arg1,arg2) \ + (R300_FPI2_OUTA_##opcode | \ + ((arg0) << R300_FPI2_ARG0A_SHIFT) | \ + ((arg1) << R300_FPI2_ARG1A_SHIFT) | \ + ((arg2) << R300_FPI2_ARG2A_SHIFT)) + +extern void debug_vp(GLcontext *ctx, struct vertex_program *vp); +extern void dump_program_params(GLcontext *ctx, struct vertex_program *vp); + +#endif /* __R300_PROGRAM_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_reg.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_reg.h new file mode 100644 index 000000000..3ea4f4fe8 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_reg.h @@ -0,0 +1,1387 @@ +#ifndef _R300_REG_H +#define _R300_REG_H + +#define R300_MC_INIT_MISC_LAT_TIMER 0x180 +# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 +# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4 +# define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8 +# define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12 +# define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16 +# define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20 +# define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24 +# define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28 + + +#define R300_MC_INIT_GFX_LAT_TIMER 0x154 +# define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0 +# define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4 +# define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8 +# define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12 +# define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16 +# define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20 +# define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24 +# define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28 + +/* +This file contains registers and constants for the R300. They have been +found mostly by examining command buffers captured using glxtest, as well +as by extrapolating some known registers and constants from the R200. + +I am fairly certain that they are correct unless stated otherwise in comments. +*/ + +#define R300_SE_VPORT_XSCALE 0x1D98 +#define R300_SE_VPORT_XOFFSET 0x1D9C +#define R300_SE_VPORT_YSCALE 0x1DA0 +#define R300_SE_VPORT_YOFFSET 0x1DA4 +#define R300_SE_VPORT_ZSCALE 0x1DA8 +#define R300_SE_VPORT_ZOFFSET 0x1DAC + + +/* This register is written directly and also starts data section in many 3d CP_PACKET3's */ +#define R300_VAP_VF_CNTL 0x2084 + +# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0 +# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0) +# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0) +# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0) +# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0) +# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0) +# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0) +# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0) +# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0) +# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0) +# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0) +# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0) + +# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4 + /* State based - direct writes to registers trigger vertex generation */ +# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4) +# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4) +# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4) +# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4) + + /* I don't think I saw these three used.. */ +# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6 +# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9 +# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10 + + /* index size - when not set the indices are assumed to be 16 bit */ +# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11) + /* number of vertices */ +# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16 + +/* BEGIN: Wild guesses */ +#define R300_VAP_OUTPUT_VTX_FMT_0 0x2090 +# define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0) +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1) +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */ +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */ +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */ +# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */ + +#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 +/* END */ + +#define R300_SE_VTE_CNTL 0x20b0 +# define R300_VPORT_X_SCALE_ENA 0x00000001 +# define R300_VPORT_X_OFFSET_ENA 0x00000002 +# define R300_VPORT_Y_SCALE_ENA 0x00000004 +# define R300_VPORT_Y_OFFSET_ENA 0x00000008 +# define R300_VPORT_Z_SCALE_ENA 0x00000010 +# define R300_VPORT_Z_OFFSET_ENA 0x00000020 +# define R300_VTX_XY_FMT 0x00000100 +# define R300_VTX_Z_FMT 0x00000200 +# define R300_VTX_W0_FMT 0x00000400 +# define R300_VTX_W0_NORMALIZE 0x00000800 +# define R300_VTX_ST_DENORMALIZED 0x00001000 + +/* BEGIN: Vertex data assembly - lots of uncertainties */ +/* gap */ +/* Where do we get our vertex data? +// +// Vertex data either comes either from immediate mode registers or from +// vertex arrays. +// There appears to be no mixed mode (though we can force the pitch of +// vertex arrays to 0, effectively reusing the same element over and over +// again). +// +// Immediate mode is controlled by the INPUT_CNTL registers. I am not sure +// if these registers influence vertex array processing. +// +// Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3. +// +// In both cases, vertex attributes are then passed through INPUT_ROUTE. + +// Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data +// into the vertex processor's input registers. +// The first word routes the first input, the second word the second, etc. +// The corresponding input is routed into the register with the given index. +// The list is ended by a word with INPUT_ROUTE_END set. +// +// Always set COMPONENTS_4 in immediate mode. */ + +#define R300_VAP_INPUT_ROUTE_0_0 0x2150 +# define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */ +# define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8 +# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */ +# define R300_VAP_INPUT_ROUTE_END (1 << 13) +# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */ +# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */ +# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */ +# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */ +#define R300_VAP_INPUT_ROUTE_0_1 0x2154 +#define R300_VAP_INPUT_ROUTE_0_2 0x2158 +#define R300_VAP_INPUT_ROUTE_0_3 0x215C +#define R300_VAP_INPUT_ROUTE_0_4 0x2160 +#define R300_VAP_INPUT_ROUTE_0_5 0x2164 +#define R300_VAP_INPUT_ROUTE_0_6 0x2168 +#define R300_VAP_INPUT_ROUTE_0_7 0x216C + +/* gap */ +/* Notes: +// - always set up to produce at least two attributes: +// if vertex program uses only position, fglrx will set normal, too +// - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */ +#define R300_VAP_INPUT_CNTL_0 0x2180 +# define R300_INPUT_CNTL_0_COLOR 0x00000001 +#define R300_VAP_INPUT_CNTL_1 0x2184 +# define R300_INPUT_CNTL_POS 0x00000001 +# define R300_INPUT_CNTL_NORMAL 0x00000002 +# define R300_INPUT_CNTL_COLOR 0x00000004 +# define R300_INPUT_CNTL_TC0 0x00000400 +# define R300_INPUT_CNTL_TC1 0x00000800 +# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */ +# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */ +# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */ +# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */ +# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */ +# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */ + +/* gap */ +/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0 +// are set to a swizzling bit pattern, other words are 0. +// +// In immediate mode, the pattern is always set to xyzw. In vertex array +// mode, the swizzling pattern is e.g. used to set zw components in texture +// coordinates with only tweo components. */ +#define R300_VAP_INPUT_ROUTE_1_0 0x21E0 +# define R300_INPUT_ROUTE_SELECT_X 0 +# define R300_INPUT_ROUTE_SELECT_Y 1 +# define R300_INPUT_ROUTE_SELECT_Z 2 +# define R300_INPUT_ROUTE_SELECT_W 3 +# define R300_INPUT_ROUTE_SELECT_ZERO 4 +# define R300_INPUT_ROUTE_SELECT_ONE 5 +# define R300_INPUT_ROUTE_SELECT_MASK 7 +# define R300_INPUT_ROUTE_X_SHIFT 0 +# define R300_INPUT_ROUTE_Y_SHIFT 3 +# define R300_INPUT_ROUTE_Z_SHIFT 6 +# define R300_INPUT_ROUTE_W_SHIFT 9 +# define R300_INPUT_ROUTE_ENABLE (15 << 12) +#define R300_VAP_INPUT_ROUTE_1_1 0x21E4 +#define R300_VAP_INPUT_ROUTE_1_2 0x21E8 +#define R300_VAP_INPUT_ROUTE_1_3 0x21EC +#define R300_VAP_INPUT_ROUTE_1_4 0x21F0 +#define R300_VAP_INPUT_ROUTE_1_5 0x21F4 +#define R300_VAP_INPUT_ROUTE_1_6 0x21F8 +#define R300_VAP_INPUT_ROUTE_1_7 0x21FC + +/* END */ + +/* gap */ +/* BEGIN: Upload vertex program and data +// The programmable vertex shader unit has a memory bank of unknown size +// that can be written to in 16 byte units by writing the address into +// UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs). +// +// Pointers into the memory bank are always in multiples of 16 bytes. +// +// The memory bank is divided into areas with fixed meaning. +// +// Starting at address UPLOAD_PROGRAM: Vertex program instructions. +// Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB), +// whereas the difference between known addresses suggests size 512. +// +// Starting at address UPLOAD_PARAMETERS: Vertex program parameters. +// Native reported limits and the VPI layout suggest size 256, whereas +// difference between known addresses suggests size 512. +// +// At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the +// floating point pointsize. The exact purpose of this state is uncertain, +// as there is also the R300_RE_POINTSIZE register. +// +// Multiple vertex programs and parameter sets can be loaded at once, +// which could explain the size discrepancy. */ +#define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200 +# define R300_PVS_UPLOAD_PROGRAM 0x00000000 +# define R300_PVS_UPLOAD_PARAMETERS 0x00000200 +# define R300_PVS_UPLOAD_POINTSIZE 0x00000406 +/* gap */ +#define R300_VAP_PVS_UPLOAD_DATA 0x2208 +/* END */ + +/* gap */ +/* I do not know the purpose of this register. However, I do know that +// it is set to 221C_CLEAR for clear operations and to 221C_NORMAL +// for normal rendering. */ +#define R300_VAP_UNKNOWN_221C 0x221C +# define R300_221C_NORMAL 0x00000000 +# define R300_221C_CLEAR 0x0001C000 + +/* gap */ +/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between +// rendering commands and overwriting vertex program parameters. +// Therefore, I suspect writing zero to 0x2284 synchronizes the engine and +// avoids bugs caused by still running shaders reading bad data from memory. */ +#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */ + +/* Absolutely no clue what this register is about. */ +#define R300_VAP_UNKNOWN_2288 0x2288 +# define R300_2288_R300 0x00750000 /* -- nh */ +# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */ + +/* gap */ +/* Addresses are relative to the vertex program instruction area of the +// memory bank. PROGRAM_END points to the last instruction of the active +// program +// +// The meaning of the two UNKNOWN fields is obviously not known. However, +// experiments so far have shown that both *must* point to an instruction +// inside the vertex program, otherwise the GPU locks up. +// fglrx usually sets CNTL_3_UNKNOWN to the end of the program and +// CNTL_1_UNKNOWN points to instruction where last write to position takes place. +// Most likely this is used to ignore rest of the program in cases where group of verts arent visible. +// For some reason this "section" is sometimes accepted other instruction that have +// no relationship with position calculations. +*/ +#define R300_VAP_PVS_CNTL_1 0x22D0 +# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 +# define R300_PVS_CNTL_1_POS_END_SHIFT 10 +# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 +/* Addresses are relative the the vertex program parameters area. */ +#define R300_VAP_PVS_CNTL_2 0x22D4 +# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 +# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 +#define R300_VAP_PVS_CNTL_3 0x22D8 +# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10 +# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0 + +/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for +// immediate vertices */ +#define R300_VAP_VTX_COLOR_R 0x2464 +#define R300_VAP_VTX_COLOR_G 0x2468 +#define R300_VAP_VTX_COLOR_B 0x246C +#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */ +#define R300_VAP_VTX_POS_0_Y_1 0x2494 +#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */ +#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */ +#define R300_VAP_VTX_POS_0_Y_2 0x24A4 +#define R300_VAP_VTX_POS_0_Z_2 0x24A8 +#define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */ + +/* gap */ + +/* These are values from r300_reg/r300_reg.h - they are known to be correct + and are here so we can use one register file instead of several + - Vladimir */ +#define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000 +# define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5) +# define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16) + +#define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004 + /* each of the following is 3 bits wide, specifies number + of components */ +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 + +/* UNK30 seems to enables point to quad transformation on textures + (or something closely related to that). + This bit is rather fatal at the time being due to lackings at pixel shader side */ +#define R300_GB_ENABLE 0x4008 +# define R300_GB_POINT_STUFF_ENABLE (1<<0) +# define R300_GB_LINE_STUFF_ENABLE (1<<1) +# define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2) +# define R300_GB_STENCIL_AUTO_ENABLE (1<<4) +# define R300_GB_UNK30 (1<<30) + /* each of the following is 2 bits wide */ +#define R300_GB_TEX_REPLICATE 0 +#define R300_GB_TEX_ST 1 +#define R300_GB_TEX_STR 2 +# define R300_GB_TEX0_SOURCE_SHIFT 16 +# define R300_GB_TEX1_SOURCE_SHIFT 18 +# define R300_GB_TEX2_SOURCE_SHIFT 20 +# define R300_GB_TEX3_SOURCE_SHIFT 22 +# define R300_GB_TEX4_SOURCE_SHIFT 24 +# define R300_GB_TEX5_SOURCE_SHIFT 26 +# define R300_GB_TEX6_SOURCE_SHIFT 28 +# define R300_GB_TEX7_SOURCE_SHIFT 30 + +/* MSPOS - positions for multisample antialiasing (?) */ +#define R300_GB_MSPOS0 0x4010 + /* shifts - each of the fields is 4 bits */ +# define R300_GB_MSPOS0__MS_X0_SHIFT 0 +# define R300_GB_MSPOS0__MS_Y0_SHIFT 4 +# define R300_GB_MSPOS0__MS_X1_SHIFT 8 +# define R300_GB_MSPOS0__MS_Y1_SHIFT 12 +# define R300_GB_MSPOS0__MS_X2_SHIFT 16 +# define R300_GB_MSPOS0__MS_Y2_SHIFT 20 +# define R300_GB_MSPOS0__MSBD0_Y 24 +# define R300_GB_MSPOS0__MSBD0_X 28 + +#define R300_GB_MSPOS1 0x4014 +# define R300_GB_MSPOS1__MS_X3_SHIFT 0 +# define R300_GB_MSPOS1__MS_Y3_SHIFT 4 +# define R300_GB_MSPOS1__MS_X4_SHIFT 8 +# define R300_GB_MSPOS1__MS_Y4_SHIFT 12 +# define R300_GB_MSPOS1__MS_X5_SHIFT 16 +# define R300_GB_MSPOS1__MS_Y5_SHIFT 20 +# define R300_GB_MSPOS1__MSBD1 24 + + +#define R300_GB_TILE_CONFIG 0x4018 +# define R300_GB_TILE_ENABLE (1<<0) +# define R300_GB_TILE_PIPE_COUNT_RV300 0 +# define R300_GB_TILE_PIPE_COUNT_R300 (3<<1) +# define R300_GB_TILE_PIPE_COUNT_R420 (7<<1) +# define R300_GB_TILE_SIZE_8 0 +# define R300_GB_TILE_SIZE_16 (1<<4) +# define R300_GB_TILE_SIZE_32 (2<<4) +# define R300_GB_SUPER_SIZE_1 (0<<6) +# define R300_GB_SUPER_SIZE_2 (1<<6) +# define R300_GB_SUPER_SIZE_4 (2<<6) +# define R300_GB_SUPER_SIZE_8 (3<<6) +# define R300_GB_SUPER_SIZE_16 (4<<6) +# define R300_GB_SUPER_SIZE_32 (5<<6) +# define R300_GB_SUPER_SIZE_64 (6<<6) +# define R300_GB_SUPER_SIZE_128 (7<<6) +# define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */ +# define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */ +# define R300_GB_SUPER_TILE_A 0 +# define R300_GB_SUPER_TILE_B (1<<15) +# define R300_GB_SUBPIXEL_1_12 0 +# define R300_GB_SUBPIXEL_1_16 (1<<16) + +#define R300_GB_FIFO_SIZE 0x4024 + /* each of the following is 2 bits wide */ +#define R300_GB_FIFO_SIZE_32 0 +#define R300_GB_FIFO_SIZE_64 1 +#define R300_GB_FIFO_SIZE_128 2 +#define R300_GB_FIFO_SIZE_256 3 +# define R300_SC_IFIFO_SIZE_SHIFT 0 +# define R300_SC_TZFIFO_SIZE_SHIFT 2 +# define R300_SC_BFIFO_SIZE_SHIFT 4 + +# define R300_US_OFIFO_SIZE_SHIFT 12 +# define R300_US_WFIFO_SIZE_SHIFT 14 + /* the following use the same constants as above, but meaning is + is times 2 (i.e. instead of 32 words it means 64 */ +# define R300_RS_TFIFO_SIZE_SHIFT 6 +# define R300_RS_CFIFO_SIZE_SHIFT 8 +# define R300_US_RAM_SIZE_SHIFT 10 + /* watermarks, 3 bits wide */ +# define R300_RS_HIGHWATER_COL_SHIFT 16 +# define R300_RS_HIGHWATER_TEX_SHIFT 19 +# define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */ +# define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24 + +#define R300_GB_SELECT 0x401C +# define R300_GB_FOG_SELECT_C0A 0 +# define R300_GB_FOG_SELECT_C1A 1 +# define R300_GB_FOG_SELECT_C2A 2 +# define R300_GB_FOG_SELECT_C3A 3 +# define R300_GB_FOG_SELECT_1_1_W 4 +# define R300_GB_FOG_SELECT_Z 5 +# define R300_GB_DEPTH_SELECT_Z 0 +# define R300_GB_DEPTH_SELECT_1_1_W (1<<3) +# define R300_GB_W_SELECT_1_W 0 +# define R300_GB_W_SELECT_1 (1<<4) + +#define R300_GB_AA_CONFIG 0x4020 +# define R300_AA_ENABLE 0x01 +# define R300_AA_SUBSAMPLES_2 0 +# define R300_AA_SUBSAMPLES_3 (1<<1) +# define R300_AA_SUBSAMPLES_4 (2<<1) +# define R300_AA_SUBSAMPLES_6 (3<<1) + +/* END */ + +/* gap */ +/* The upper enable bits are guessed, based on fglrx reported limits. */ +#define R300_TX_ENABLE 0x4104 +# define R300_TX_ENABLE_0 (1 << 0) +# define R300_TX_ENABLE_1 (1 << 1) +# define R300_TX_ENABLE_2 (1 << 2) +# define R300_TX_ENABLE_3 (1 << 3) +# define R300_TX_ENABLE_4 (1 << 4) +# define R300_TX_ENABLE_5 (1 << 5) +# define R300_TX_ENABLE_6 (1 << 6) +# define R300_TX_ENABLE_7 (1 << 7) +# define R300_TX_ENABLE_8 (1 << 8) +# define R300_TX_ENABLE_9 (1 << 9) +# define R300_TX_ENABLE_10 (1 << 10) +# define R300_TX_ENABLE_11 (1 << 11) +# define R300_TX_ENABLE_12 (1 << 12) +# define R300_TX_ENABLE_13 (1 << 13) +# define R300_TX_ENABLE_14 (1 << 14) +# define R300_TX_ENABLE_15 (1 << 15) + +/* The pointsize is given in multiples of 6. The pointsize can be +// enormous: Clear() renders a single point that fills the entire +// framebuffer. */ +#define R300_RE_POINTSIZE 0x421C +# define R300_POINTSIZE_Y_SHIFT 0 +# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */ +# define R300_POINTSIZE_X_SHIFT 16 +# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */ +# define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6) + +/* The line width is given in multiples of 6. + In default mode lines are classified as vertical lines. + HO: horizontal + VE: vertical or horizontal + HO & VE: no classification +*/ +#define R300_RE_LINE_CNT 0x4234 +# define R300_LINESIZE_SHIFT 0 +# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */ +# define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6) +# define R300_LINE_CNT_HO (1 << 16) +# define R300_LINE_CNT_VE (1 << 17) + +/* Some sort of scale or clamp value for texcoordless textures. */ +#define R300_RE_UNK4238 0x4238 + +#define R300_RE_SHADE_MODEL 0x4278 +# define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa +# define R300_RE_SHADE_MODEL_FLAT 0x39595 + +/* Dangerous */ +#define R300_RE_POLYGON_MODE 0x4288 +# define R300_PM_ENABLED (1 << 0) +# define R300_PM_FRONT_POINT (0 << 0) +# define R300_PM_BACK_POINT (0 << 0) +# define R300_PM_FRONT_LINE (1 << 4) +# define R300_PM_FRONT_FILL (1 << 5) +# define R300_PM_BACK_LINE (1 << 7) +# define R300_PM_BACK_FILL (1 << 8) + +/* Not sure why there are duplicate of factor and constant values. + My best guess so far is that there are seperate zbiases for test and write. + Ordering might be wrong. + Some of the tests indicate that fgl has a fallback implementation of zbias + via pixel shaders. */ +#define R300_RE_ZBIAS_T_FACTOR 0x42A4 +#define R300_RE_ZBIAS_T_CONSTANT 0x42A8 +#define R300_RE_ZBIAS_W_FACTOR 0x42AC +#define R300_RE_ZBIAS_W_CONSTANT 0x42B0 + +/* This register needs to be set to (1<<1) for RV350 to correctly + perform depth test (see --vb-triangles in r300_demo) + Don't know about other chips. - Vladimir + This is set to 3 when GL_POLYGON_OFFSET_FILL is on. + My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT). + One to enable depth test and one for depth write. + Yet this doesnt explain why depth writes work ... + */ +#define R300_RE_OCCLUSION_CNTL 0x42B4 +# define R300_OCCLUSION_ON (1<<1) + +#define R300_RE_CULL_CNTL 0x42B8 +# define R300_CULL_FRONT (1 << 0) +# define R300_CULL_BACK (1 << 1) +# define R300_FRONT_FACE_CCW (0 << 2) +# define R300_FRONT_FACE_CW (1 << 2) + + +/* BEGIN: Rasterization / Interpolators - many guesses +// 0_UNKNOWN_18 has always been set except for clear operations. +// TC_CNT is the number of incoming texture coordinate sets (i.e. it depends +// on the vertex program, *not* the fragment program) */ +#define R300_RS_CNTL_0 0x4300 +# define R300_RS_CNTL_TC_CNT_SHIFT 2 +# define R300_RS_CNTL_TC_CNT_MASK (7 << 2) +# define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */ +# define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18) +/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */ +#define R300_RS_CNTL_1 0x4304 + +/* gap */ +/* Only used for texture coordinates. +// Use the source field to route texture coordinate input from the vertex program +// to the desired interpolator. Note that the source field is relative to the +// outputs the vertex program *actually* writes. If a vertex program only writes +// texcoord[1], this will be source index 0. +// Set INTERP_USED on all interpolators that produce data used by the +// fragment program. INTERP_USED looks like a swizzling mask, but +// I haven't seen it used that way. +// +// Note: The _UNKNOWN constants are always set in their respective register. +// I don't know if this is necessary. */ +#define R300_RS_INTERP_0 0x4310 +#define R300_RS_INTERP_1 0x4314 +# define R300_RS_INTERP_1_UNKNOWN 0x40 +#define R300_RS_INTERP_2 0x4318 +# define R300_RS_INTERP_2_UNKNOWN 0x80 +#define R300_RS_INTERP_3 0x431C +# define R300_RS_INTERP_3_UNKNOWN 0xC0 +#define R300_RS_INTERP_4 0x4320 +#define R300_RS_INTERP_5 0x4324 +#define R300_RS_INTERP_6 0x4328 +#define R300_RS_INTERP_7 0x432C +# define R300_RS_INTERP_SRC_SHIFT 2 +# define R300_RS_INTERP_SRC_MASK (7 << 2) +# define R300_RS_INTERP_USED 0x00D10000 + +/* These DWORDs control how vertex data is routed into fragment program +// registers, after interpolators. */ +#define R300_RS_ROUTE_0 0x4330 +#define R300_RS_ROUTE_1 0x4334 +#define R300_RS_ROUTE_2 0x4338 +#define R300_RS_ROUTE_3 0x433C /* GUESS */ +#define R300_RS_ROUTE_4 0x4340 /* GUESS */ +#define R300_RS_ROUTE_5 0x4344 /* GUESS */ +#define R300_RS_ROUTE_6 0x4348 /* GUESS */ +#define R300_RS_ROUTE_7 0x434C /* GUESS */ +# define R300_RS_ROUTE_SOURCE_INTERP_0 0 +# define R300_RS_ROUTE_SOURCE_INTERP_1 1 +# define R300_RS_ROUTE_SOURCE_INTERP_2 2 +# define R300_RS_ROUTE_SOURCE_INTERP_3 3 +# define R300_RS_ROUTE_SOURCE_INTERP_4 4 +# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */ +# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */ +# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */ +# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */ +# define R300_RS_ROUTE_DEST_SHIFT 6 +# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */ + +/* Special handling for color: When the fragment program uses color, +// the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the +// color register index. */ +# define R300_RS_ROUTE_0_COLOR (1 << 14) +# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17 +# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */ +/* As above, but for secondary color */ +# define R300_RS_ROUTE_1_COLOR1 (1 << 14) +# define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17 +# define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17) +# define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11) +/* END */ + +/* BEGIN: Scissors and cliprects +// There are four clipping rectangles. Their corner coordinates are inclusive. +// Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending +// on whether the pixel is inside cliprects 0-3, respectively. For example, +// if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned +// the number 3 (binary 0011). +// Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set, +// the pixel is rasterized. +// +// In addition to this, there is a scissors rectangle. Only pixels inside the +// scissors rectangle are drawn. (coordinates are inclusive) +// +// For some reason, the top-left corner of the framebuffer is at (1440, 1440) +// for the purpose of clipping and scissors. */ +#define R300_RE_CLIPRECT_TL_0 0x43B0 +#define R300_RE_CLIPRECT_BR_0 0x43B4 +#define R300_RE_CLIPRECT_TL_1 0x43B8 +#define R300_RE_CLIPRECT_BR_1 0x43BC +#define R300_RE_CLIPRECT_TL_2 0x43C0 +#define R300_RE_CLIPRECT_BR_2 0x43C4 +#define R300_RE_CLIPRECT_TL_3 0x43C8 +#define R300_RE_CLIPRECT_BR_3 0x43CC +# define R300_CLIPRECT_OFFSET 1440 +# define R300_CLIPRECT_MASK 0x1FFF +# define R300_CLIPRECT_X_SHIFT 0 +# define R300_CLIPRECT_X_MASK (0x1FFF << 0) +# define R300_CLIPRECT_Y_SHIFT 13 +# define R300_CLIPRECT_Y_MASK (0x1FFF << 13) +#define R300_RE_CLIPRECT_CNTL 0x43D0 +# define R300_CLIP_OUT (1 << 0) +# define R300_CLIP_0 (1 << 1) +# define R300_CLIP_1 (1 << 2) +# define R300_CLIP_10 (1 << 3) +# define R300_CLIP_2 (1 << 4) +# define R300_CLIP_20 (1 << 5) +# define R300_CLIP_21 (1 << 6) +# define R300_CLIP_210 (1 << 7) +# define R300_CLIP_3 (1 << 8) +# define R300_CLIP_30 (1 << 9) +# define R300_CLIP_31 (1 << 10) +# define R300_CLIP_310 (1 << 11) +# define R300_CLIP_32 (1 << 12) +# define R300_CLIP_320 (1 << 13) +# define R300_CLIP_321 (1 << 14) +# define R300_CLIP_3210 (1 << 15) + +/* gap */ +#define R300_RE_SCISSORS_TL 0x43E0 +#define R300_RE_SCISSORS_BR 0x43E4 +# define R300_SCISSORS_OFFSET 1440 +# define R300_SCISSORS_X_SHIFT 0 +# define R300_SCISSORS_X_MASK (0x1FFF << 0) +# define R300_SCISSORS_Y_SHIFT 13 +# define R300_SCISSORS_Y_MASK (0x1FFF << 13) +/* END */ + +/* BEGIN: Texture specification +// The texture specification dwords are grouped by meaning and not by texture unit. +// This means that e.g. the offset for texture image unit N is found in register +// TX_OFFSET_0 + (4*N) */ +#define R300_TX_FILTER_0 0x4400 +# define R300_TX_REPEAT 0 +# define R300_TX_MIRRORED 1 +# define R300_TX_CLAMP 4 +# define R300_TX_CLAMP_TO_EDGE 2 +# define R300_TX_CLAMP_TO_BORDER 6 +# define R300_TX_WRAP_S_SHIFT 0 +# define R300_TX_WRAP_S_MASK (7 << 0) +# define R300_TX_WRAP_T_SHIFT 3 +# define R300_TX_WRAP_T_MASK (7 << 3) +# define R300_TX_WRAP_Q_SHIFT 6 +# define R300_TX_WRAP_Q_MASK (7 << 6) +# define R300_TX_MAG_FILTER_NEAREST (1 << 9) +# define R300_TX_MAG_FILTER_LINEAR (2 << 9) +# define R300_TX_MAG_FILTER_MASK (3 << 9) +# define R300_TX_MIN_FILTER_NEAREST (1 << 11) +# define R300_TX_MIN_FILTER_LINEAR (2 << 11) +# define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST (5 << 11) +# define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR (9 << 11) +# define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11) +# define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11) + +/* NOTE: NEAREST doesnt seem to exist. + Im not seting MAG_FILTER_MASK and (3 << 11) on for all + anisotropy modes because that would void selected mag filter */ +# define R300_TX_MIN_FILTER_ANISO_NEAREST ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) +# define R300_TX_MIN_FILTER_ANISO_LINEAR ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) +# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) +# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) +# define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) ) +# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21) +# define R300_TX_MAX_ANISO_2_TO_1 (2 << 21) +# define R300_TX_MAX_ANISO_4_TO_1 (4 << 21) +# define R300_TX_MAX_ANISO_8_TO_1 (6 << 21) +# define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) +# define R300_TX_MAX_ANISO_MASK (14 << 21) + +#define R300_TX_UNK1_0 0x4440 +# define R300_LOD_BIAS_MASK 0x1fff + +#define R300_TX_SIZE_0 0x4480 +# define R300_TX_WIDTHMASK_SHIFT 0 +# define R300_TX_WIDTHMASK_MASK (2047 << 0) +# define R300_TX_HEIGHTMASK_SHIFT 11 +# define R300_TX_HEIGHTMASK_MASK (2047 << 11) +# define R300_TX_UNK23 (1 << 23) +# define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ +# define R300_TX_SIZE_MASK (15 << 26) +#define R300_TX_FORMAT_0 0x44C0 + /* The interpretation of the format word by Wladimir van der Laan */ + /* The X, Y, Z and W refer to the layout of the components. + They are given meanings as R, G, B and Alpha by the swizzle + specification */ +# define R300_TX_FORMAT_X8 0x0 +# define R300_TX_FORMAT_X16 0x1 +# define R300_TX_FORMAT_Y4X4 0x2 +# define R300_TX_FORMAT_Y8X8 0x3 +# define R300_TX_FORMAT_Y16X16 0x4 +# define R300_TX_FORMAT_Z3Y3X2 0x5 +# define R300_TX_FORMAT_Z5Y6X5 0x6 +# define R300_TX_FORMAT_Z6Y5X5 0x7 +# define R300_TX_FORMAT_Z11Y11X10 0x8 +# define R300_TX_FORMAT_Z10Y11X11 0x9 +# define R300_TX_FORMAT_W4Z4Y4X4 0xA +# define R300_TX_FORMAT_W1Z5Y5X5 0xB +# define R300_TX_FORMAT_W8Z8Y8X8 0xC +# define R300_TX_FORMAT_W2Z10Y10X10 0xD +# define R300_TX_FORMAT_W16Z16Y16X16 0xE +# define R300_TX_FORMAT_DXT1 0xF +# define R300_TX_FORMAT_DXT3 0x10 +# define R300_TX_FORMAT_DXT5 0x11 +# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ +# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ +# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ +# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ + /* 0x16 - some 16 bit green format.. ?? */ +# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ + + /* gap */ + /* Floating point formats */ + /* Note - hardware supports both 16 and 32 bit floating point */ +# define R300_TX_FORMAT_FL_I16 0x18 +# define R300_TX_FORMAT_FL_I16A16 0x19 +# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A +# define R300_TX_FORMAT_FL_I32 0x1B +# define R300_TX_FORMAT_FL_I32A32 0x1C +# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D + /* alpha modes, convenience mostly */ + /* if you have alpha, pick constant appropriate to the + number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ +# define R300_TX_FORMAT_ALPHA_1CH 0x000 +# define R300_TX_FORMAT_ALPHA_2CH 0x200 +# define R300_TX_FORMAT_ALPHA_4CH 0x600 +# define R300_TX_FORMAT_ALPHA_NONE 0xA00 + /* Swizzling */ + /* constants */ +# define R300_TX_FORMAT_X 0 +# define R300_TX_FORMAT_Y 1 +# define R300_TX_FORMAT_Z 2 +# define R300_TX_FORMAT_W 3 +# define R300_TX_FORMAT_ZERO 4 +# define R300_TX_FORMAT_ONE 5 +# define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */ + +# define R300_TX_FORMAT_B_SHIFT 18 +# define R300_TX_FORMAT_G_SHIFT 15 +# define R300_TX_FORMAT_R_SHIFT 12 +# define R300_TX_FORMAT_A_SHIFT 9 + /* Convenience macro to take care of layout and swizzling */ +# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) (\ + ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \ + | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \ + | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \ + | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \ + | (R300_TX_FORMAT_##FMT) \ + ) + /* These can be ORed with result of R300_EASY_TX_FORMAT() */ + /* We don't really know what they do. Take values from a constant color ? */ +# define R300_TX_FORMAT_CONST_X (1<<5) +# define R300_TX_FORMAT_CONST_Y (2<<5) +# define R300_TX_FORMAT_CONST_Z (4<<5) +# define R300_TX_FORMAT_CONST_W (8<<5) + +# define R300_TX_FORMAT_YUV_MODE 0x00800000 + +#define R300_TX_OFFSET_0 0x4540 +/* BEGIN: Guess from R200 */ +# define R300_TXO_ENDIAN_NO_SWAP (0 << 0) +# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R300_TXO_OFFSET_MASK 0xffffffe0 +# define R300_TXO_OFFSET_SHIFT 5 +/* END */ +#define R300_TX_UNK4_0 0x4580 +#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } + +/* END */ + +/* BEGIN: Fragment program instruction set +// Fragment programs are written directly into register space. +// There are separate instruction streams for texture instructions and ALU +// instructions. +// In order to synchronize these streams, the program is divided into up +// to 4 nodes. Each node begins with a number of TEX operations, followed +// by a number of ALU operations. +// The first node can have zero TEX ops, all subsequent nodes must have at least +// one TEX ops. +// All nodes must have at least one ALU op. +// +// The index of the last node is stored in PFS_CNTL_0: A value of 0 means +// 1 node, a value of 3 means 4 nodes. +// The total amount of instructions is defined in PFS_CNTL_2. The offsets are +// offsets into the respective instruction streams, while *_END points to the +// last instruction relative to this offset. */ +#define R300_PFS_CNTL_0 0x4600 +# define R300_PFS_CNTL_LAST_NODES_SHIFT 0 +# define R300_PFS_CNTL_LAST_NODES_MASK (3 << 0) +# define R300_PFS_CNTL_FIRST_NODE_HAS_TEX (1 << 3) +#define R300_PFS_CNTL_1 0x4604 +/* There is an unshifted value here which has so far always been equal to the +// index of the highest used temporary register. */ +#define R300_PFS_CNTL_2 0x4608 +# define R300_PFS_CNTL_ALU_OFFSET_SHIFT 0 +# define R300_PFS_CNTL_ALU_OFFSET_MASK (63 << 0) +# define R300_PFS_CNTL_ALU_END_SHIFT 6 +# define R300_PFS_CNTL_ALU_END_MASK (63 << 0) +# define R300_PFS_CNTL_TEX_OFFSET_SHIFT 12 +# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */ +# define R300_PFS_CNTL_TEX_END_SHIFT 18 +# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */ + +/* gap */ +/* Nodes are stored backwards. The last active node is always stored in +// PFS_NODE_3. +// Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The +// first node is stored in NODE_2, the second node is stored in NODE_3. +// +// Offsets are relative to the master offset from PFS_CNTL_2. +// LAST_NODE is set for the last node, and only for the last node. */ +#define R300_PFS_NODE_0 0x4610 +#define R300_PFS_NODE_1 0x4614 +#define R300_PFS_NODE_2 0x4618 +#define R300_PFS_NODE_3 0x461C +# define R300_PFS_NODE_ALU_OFFSET_SHIFT 0 +# define R300_PFS_NODE_ALU_OFFSET_MASK (63 << 0) +# define R300_PFS_NODE_ALU_END_SHIFT 6 +# define R300_PFS_NODE_ALU_END_MASK (63 << 6) +# define R300_PFS_NODE_TEX_OFFSET_SHIFT 12 +# define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) +# define R300_PFS_NODE_TEX_END_SHIFT 17 +# define R300_PFS_NODE_TEX_END_MASK (31 << 17) +# define R300_PFS_NODE_LAST_NODE (1 << 22) + +/* TEX +// As far as I can tell, texture instructions cannot write into output +// registers directly. A subsequent ALU instruction is always necessary, +// even if it's just MAD o0, r0, 1, 0 */ +#define R300_PFS_TEXI_0 0x4620 +# define R300_FPITX_SRC_SHIFT 0 +# define R300_FPITX_SRC_MASK (31 << 0) +# define R300_FPITX_SRC_CONST (1 << 5) /* GUESS */ +# define R300_FPITX_DST_SHIFT 6 +# define R300_FPITX_DST_MASK (31 << 6) +# define R300_FPITX_IMAGE_SHIFT 11 +# define R300_FPITX_IMAGE_MASK (15 << 11) /* GUESS based on layout and native limits */ +/* Unsure if these are opcodes, or some kind of bitfield, but this is how + * they were set when I checked + */ +# define R300_FPITX_OPCODE_SHIFT 15 +# define R300_FPITX_OP_TEX 1 +# define R300_FPITX_OP_TXP 3 +# define R300_FPITX_OP_TXB 4 + +/* ALU +// The ALU instructions register blocks are enumerated according to the order +// in which fglrx. I assume there is space for 64 instructions, since +// each block has space for a maximum of 64 DWORDs, and this matches reported +// native limits. +// +// The basic functional block seems to be one MAD for each color and alpha, +// and an adder that adds all components after the MUL. +// - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands +// - DP4: Use OUTC_DP4, OUTA_DP4 +// - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands +// - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands +// - CMP: If ARG2 < 0, return ARG1, else return ARG0 +// - FLR: use FRC+MAD +// - XPD: use MAD+MAD +// - SGE, SLT: use MAD+CMP +// - RSQ: use ABS modifier for argument +// - Use OUTC_REPL_ALPHA to write results of an alpha-only operation (e.g. RCP) +// into color register +// - apparently, there's no quick DST operation +// - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2" +// - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0" +// - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1" +// +// Operand selection +// First stage selects three sources from the available registers and +// constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha). +// fglrx sorts the three source fields: Registers before constants, +// lower indices before higher indices; I do not know whether this is necessary. +// fglrx fills unused sources with "read constant 0" +// According to specs, you cannot select more than two different constants. +// +// Second stage selects the operands from the sources. This is defined in +// INSTR0 (color) and INSTR2 (alpha). You can also select the special constants +// zero and one. +// Swizzling and negation happens in this stage, as well. +// +// Important: Color and alpha seem to be mostly separate, i.e. their sources +// selection appears to be fully independent (the register storage is probably +// physically split into a color and an alpha section). +// However (because of the apparent physical split), there is some interaction +// WRT swizzling. If, for example, you want to load an R component into an +// Alpha operand, this R component is taken from a *color* source, not from +// an alpha source. The corresponding register doesn't even have to appear in +// the alpha sources list. (I hope this alll makes sense to you) +// +// Destination selection +// The destination register index is in FPI1 (color) and FPI3 (alpha) together +// with enable bits. +// There are separate enable bits for writing into temporary registers +// (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* /DSTA_OUTPUT). +// You can write to both at once, or not write at all (the same index +// must be used for both). +// +// Note: There is a special form for LRP +// - Argument order is the same as in ARB_fragment_program. +// - Operation is MAD +// - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP +// - Set FPI0/FPI2_SPECIAL_LRP +// Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD */ +#define R300_PFS_INSTR1_0 0x46C0 +# define R300_FPI1_SRC0C_SHIFT 0 +# define R300_FPI1_SRC0C_MASK (31 << 0) +# define R300_FPI1_SRC0C_CONST (1 << 5) +# define R300_FPI1_SRC1C_SHIFT 6 +# define R300_FPI1_SRC1C_MASK (31 << 6) +# define R300_FPI1_SRC1C_CONST (1 << 11) +# define R300_FPI1_SRC2C_SHIFT 12 +# define R300_FPI1_SRC2C_MASK (31 << 12) +# define R300_FPI1_SRC2C_CONST (1 << 17) +# define R300_FPI1_DSTC_SHIFT 18 +# define R300_FPI1_DSTC_MASK (31 << 18) +# define R300_FPI1_DSTC_REG_X (1 << 23) +# define R300_FPI1_DSTC_REG_Y (1 << 24) +# define R300_FPI1_DSTC_REG_Z (1 << 25) +# define R300_FPI1_DSTC_OUTPUT_X (1 << 26) +# define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) +# define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) + +#define R300_PFS_INSTR3_0 0x47C0 +# define R300_FPI3_SRC0A_SHIFT 0 +# define R300_FPI3_SRC0A_MASK (31 << 0) +# define R300_FPI3_SRC0A_CONST (1 << 5) +# define R300_FPI3_SRC1A_SHIFT 6 +# define R300_FPI3_SRC1A_MASK (31 << 6) +# define R300_FPI3_SRC1A_CONST (1 << 11) +# define R300_FPI3_SRC2A_SHIFT 12 +# define R300_FPI3_SRC2A_MASK (31 << 12) +# define R300_FPI3_SRC2A_CONST (1 << 17) +# define R300_FPI3_DSTA_SHIFT 18 +# define R300_FPI3_DSTA_MASK (31 << 18) +# define R300_FPI3_DSTA_REG (1 << 23) +# define R300_FPI3_DSTA_OUTPUT (1 << 24) + +#define R300_PFS_INSTR0_0 0x48C0 +# define R300_FPI0_ARGC_SRC0C_XYZ 0 +# define R300_FPI0_ARGC_SRC0C_XXX 1 +# define R300_FPI0_ARGC_SRC0C_YYY 2 +# define R300_FPI0_ARGC_SRC0C_ZZZ 3 +# define R300_FPI0_ARGC_SRC1C_XYZ 4 +# define R300_FPI0_ARGC_SRC1C_XXX 5 +# define R300_FPI0_ARGC_SRC1C_YYY 6 +# define R300_FPI0_ARGC_SRC1C_ZZZ 7 +# define R300_FPI0_ARGC_SRC2C_XYZ 8 +# define R300_FPI0_ARGC_SRC2C_XXX 9 +# define R300_FPI0_ARGC_SRC2C_YYY 10 +# define R300_FPI0_ARGC_SRC2C_ZZZ 11 +# define R300_FPI0_ARGC_SRC0A 12 +# define R300_FPI0_ARGC_SRC1A 13 +# define R300_FPI0_ARGC_SRC2A 14 +# define R300_FPI0_ARGC_SRC1C_LRP 15 +# define R300_FPI0_ARGC_ZERO 20 +# define R300_FPI0_ARGC_ONE 21 +# define R300_FPI0_ARGC_HALF 22 /* GUESS */ +# define R300_FPI0_ARGC_SRC0C_YZX 23 +# define R300_FPI0_ARGC_SRC1C_YZX 24 +# define R300_FPI0_ARGC_SRC2C_YZX 25 +# define R300_FPI0_ARGC_SRC0C_ZXY 26 +# define R300_FPI0_ARGC_SRC1C_ZXY 27 +# define R300_FPI0_ARGC_SRC2C_ZXY 28 +# define R300_FPI0_ARGC_SRC0CA_WZY 29 +# define R300_FPI0_ARGC_SRC1CA_WZY 30 +# define R300_FPI0_ARGC_SRC2CA_WZY 31 + +# define R300_FPI0_ARG0C_SHIFT 0 +# define R300_FPI0_ARG0C_MASK (31 << 0) +# define R300_FPI0_ARG0C_NEG (1 << 5) +# define R300_FPI0_ARG0C_ABS (1 << 6) +# define R300_FPI0_ARG1C_SHIFT 7 +# define R300_FPI0_ARG1C_MASK (31 << 7) +# define R300_FPI0_ARG1C_NEG (1 << 12) +# define R300_FPI0_ARG1C_ABS (1 << 13) +# define R300_FPI0_ARG2C_SHIFT 14 +# define R300_FPI0_ARG2C_MASK (31 << 14) +# define R300_FPI0_ARG2C_NEG (1 << 19) +# define R300_FPI0_ARG2C_ABS (1 << 20) +# define R300_FPI0_SPECIAL_LRP (1 << 21) +# define R300_FPI0_OUTC_MAD (0 << 23) +# define R300_FPI0_OUTC_DP3 (1 << 23) +# define R300_FPI0_OUTC_DP4 (2 << 23) +# define R300_FPI0_OUTC_MIN (4 << 23) +# define R300_FPI0_OUTC_MAX (5 << 23) +# define R300_FPI0_OUTC_CMP (8 << 23) +# define R300_FPI0_OUTC_FRC (9 << 23) +# define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) +# define R300_FPI0_OUTC_SAT (1 << 30) +# define R300_FPI0_UNKNOWN_31 (1 << 31) + +#define R300_PFS_INSTR2_0 0x49C0 +# define R300_FPI2_ARGA_SRC0C_X 0 +# define R300_FPI2_ARGA_SRC0C_Y 1 +# define R300_FPI2_ARGA_SRC0C_Z 2 +# define R300_FPI2_ARGA_SRC1C_X 3 +# define R300_FPI2_ARGA_SRC1C_Y 4 +# define R300_FPI2_ARGA_SRC1C_Z 5 +# define R300_FPI2_ARGA_SRC2C_X 6 +# define R300_FPI2_ARGA_SRC2C_Y 7 +# define R300_FPI2_ARGA_SRC2C_Z 8 +# define R300_FPI2_ARGA_SRC0A 9 +# define R300_FPI2_ARGA_SRC1A 10 +# define R300_FPI2_ARGA_SRC2A 11 +# define R300_FPI2_ARGA_SRC1A_LRP 15 +# define R300_FPI2_ARGA_ZERO 16 +# define R300_FPI2_ARGA_ONE 17 +# define R300_FPI2_ARGA_HALF 18 /* GUESS */ + +# define R300_FPI2_ARG0A_SHIFT 0 +# define R300_FPI2_ARG0A_MASK (31 << 0) +# define R300_FPI2_ARG0A_NEG (1 << 5) +# define R300_FPI2_ARG0A_ABS (1 << 6) /* GUESS */ +# define R300_FPI2_ARG1A_SHIFT 7 +# define R300_FPI2_ARG1A_MASK (31 << 7) +# define R300_FPI2_ARG1A_NEG (1 << 12) +# define R300_FPI2_ARG1A_ABS (1 << 13) /* GUESS */ +# define R300_FPI2_ARG2A_SHIFT 14 +# define R300_FPI2_ARG2A_MASK (31 << 14) +# define R300_FPI2_ARG2A_NEG (1 << 19) +# define R300_FPI2_ARG2A_ABS (1 << 20) /* GUESS */ +# define R300_FPI2_SPECIAL_LRP (1 << 21) +# define R300_FPI2_OUTA_MAD (0 << 23) +# define R300_FPI2_OUTA_DP4 (1 << 23) +# define R300_FPI2_OUTA_MIN (2 << 23) +# define R300_FPI2_OUTA_MAX (3 << 23) +# define R300_FPI2_OUTA_CMP (6 << 23) +# define R300_FPI2_OUTA_FRC (7 << 23) +# define R300_FPI2_OUTA_EX2 (8 << 23) +# define R300_FPI2_OUTA_LG2 (9 << 23) +# define R300_FPI2_OUTA_RCP (10 << 23) +# define R300_FPI2_OUTA_RSQ (11 << 23) +# define R300_FPI2_OUTA_SAT (1 << 30) +# define R300_FPI2_UNKNOWN_31 (1 << 31) +/* END */ + +/* gap */ +#define R300_PP_ALPHA_TEST 0x4BD4 +# define R300_REF_ALPHA_MASK 0x000000ff +# define R300_ALPHA_TEST_FAIL (0 << 8) +# define R300_ALPHA_TEST_LESS (1 << 8) +# define R300_ALPHA_TEST_LEQUAL (3 << 8) +# define R300_ALPHA_TEST_EQUAL (2 << 8) +# define R300_ALPHA_TEST_GEQUAL (6 << 8) +# define R300_ALPHA_TEST_GREATER (4 << 8) +# define R300_ALPHA_TEST_NEQUAL (5 << 8) +# define R300_ALPHA_TEST_PASS (7 << 8) +# define R300_ALPHA_TEST_OP_MASK (7 << 8) +# define R300_ALPHA_TEST_ENABLE (1 << 11) + +/* gap */ +/* Fragment program parameters in 7.16 floating point */ +#define R300_PFS_PARAM_0_X 0x4C00 +#define R300_PFS_PARAM_0_Y 0x4C04 +#define R300_PFS_PARAM_0_Z 0x4C08 +#define R300_PFS_PARAM_0_W 0x4C0C +/* GUESS: PARAM_31 is last, based on native limits reported by fglrx */ +#define R300_PFS_PARAM_31_X 0x4DF0 +#define R300_PFS_PARAM_31_Y 0x4DF4 +#define R300_PFS_PARAM_31_Z 0x4DF8 +#define R300_PFS_PARAM_31_W 0x4DFC + +/* Notes: +// - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in the application +// - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND are set to the same +// function (both registers are always set up completely in any case) +// - Most blend flags are simply copied from R200 and not tested yet */ +#define R300_RB3D_CBLEND 0x4E04 +#define R300_RB3D_ABLEND 0x4E08 + /* the following only appear in CBLEND */ +# define R300_BLEND_ENABLE (1 << 0) +# define R300_BLEND_UNKNOWN (3 << 1) +# define R300_BLEND_NO_SEPARATE (1 << 3) + /* the following are shared between CBLEND and ABLEND */ +# define R300_FCN_MASK (3 << 12) +# define R300_COMB_FCN_ADD_CLAMP (0 << 12) +# define R300_COMB_FCN_ADD_NOCLAMP (1 << 12) +# define R300_COMB_FCN_SUB_CLAMP (2 << 12) +# define R300_COMB_FCN_SUB_NOCLAMP (3 << 12) +# define R300_SRC_BLEND_GL_ZERO (32 << 16) +# define R300_SRC_BLEND_GL_ONE (33 << 16) +# define R300_SRC_BLEND_GL_SRC_COLOR (34 << 16) +# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) +# define R300_SRC_BLEND_GL_DST_COLOR (36 << 16) +# define R300_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) +# define R300_SRC_BLEND_GL_SRC_ALPHA (38 << 16) +# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) +# define R300_SRC_BLEND_GL_DST_ALPHA (40 << 16) +# define R300_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) +# define R300_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) +# define R300_SRC_BLEND_MASK (63 << 16) +# define R300_DST_BLEND_GL_ZERO (32 << 24) +# define R300_DST_BLEND_GL_ONE (33 << 24) +# define R300_DST_BLEND_GL_SRC_COLOR (34 << 24) +# define R300_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) +# define R300_DST_BLEND_GL_DST_COLOR (36 << 24) +# define R300_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) +# define R300_DST_BLEND_GL_SRC_ALPHA (38 << 24) +# define R300_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) +# define R300_DST_BLEND_GL_DST_ALPHA (40 << 24) +# define R300_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) +# define R300_DST_BLEND_MASK (63 << 24) +#define R300_RB3D_COLORMASK 0x4E0C +# define R300_COLORMASK0_B (1<<0) +# define R300_COLORMASK0_G (1<<1) +# define R300_COLORMASK0_R (1<<2) +# define R300_COLORMASK0_A (1<<3) + +/* gap */ +#define R300_RB3D_COLOROFFSET0 0x4E28 +# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */ +#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */ +#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */ +#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */ +/* gap */ +/* Bit 16: Larger tiles +// Bit 17: 4x2 tiles +// Bit 18: Extremely weird tile like, but some pixels duplicated? */ +#define R300_RB3D_COLORPITCH0 0x4E38 +# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */ +# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */ +# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */ +# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */ +# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */ +# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */ +# define R300_COLOR_FORMAT_RGB565 (2 << 22) +# define R300_COLOR_FORMAT_ARGB8888 (3 << 22) +#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */ +#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */ +#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */ + +/* gap */ +/* Guess by Vladimir. +// Set to 0A before 3D operations, set to 02 afterwards. */ +#define R300_RB3D_DSTCACHE_CTLSTAT 0x4E4C +# define R300_RB3D_DSTCACHE_02 0x00000002 +# define R300_RB3D_DSTCACHE_0A 0x0000000A + +/* gap */ +/* There seems to be no "write only" setting, so use Z-test = ALWAYS for this. */ +/* Bit (1<<8) is the "test" bit. so plain write is 6 - vd */ +#define R300_RB3D_ZSTENCIL_CNTL_0 0x4F00 +# define R300_RB3D_Z_DISABLED_1 0x00000010 /* GUESS */ +# define R300_RB3D_Z_DISABLED_2 0x00000014 /* GUESS */ +# define R300_RB3D_Z_TEST 0x00000012 +# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016 +# define R300_RB3D_Z_WRITE_ONLY 0x00000006 + +# define R300_RB3D_Z_TEST 0x00000012 +# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016 +# define R300_RB3D_Z_WRITE_ONLY 0x00000006 +# define R300_RB3D_STENCIL_ENABLE 0x00000001 + +#define R300_RB3D_ZSTENCIL_CNTL_1 0x4F04 + /* functions */ +# define R300_ZS_NEVER 0 +# define R300_ZS_LESS 1 +# define R300_ZS_LEQUAL 2 +# define R300_ZS_EQUAL 3 +# define R300_ZS_GEQUAL 4 +# define R300_ZS_GREATER 5 +# define R300_ZS_NOTEQUAL 6 +# define R300_ZS_ALWAYS 7 +# define R300_ZS_MASK 7 + /* operations */ +# define R300_ZS_KEEP 0 +# define R300_ZS_ZERO 1 +# define R300_ZS_REPLACE 2 +# define R300_ZS_INCR 3 +# define R300_ZS_DECR 4 +# define R300_ZS_INVERT 5 +# define R300_ZS_INCR_WRAP 6 +# define R300_ZS_DECR_WRAP 7 + + /* front and back refer to operations done for front + and back faces, i.e. separate stencil function support */ +# define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT 0 +# define R300_RB3D_ZS1_FRONT_FUNC_SHIFT 3 +# define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT 6 +# define R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT 9 +# define R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT 12 +# define R300_RB3D_ZS1_BACK_FUNC_SHIFT 15 +# define R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT 18 +# define R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT 21 +# define R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT 24 + + + +#define R300_RB3D_ZSTENCIL_CNTL_2 0x4F08 +# define R300_RB3D_ZS2_STENCIL_REF_SHIFT 0 +# define R300_RB3D_ZS2_STENCIL_MASK 0xFF +# define R300_RB3D_ZS2_STENCIL_MASK_SHIFT 8 +# define R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT 16 + +/* gap */ + +#define R300_RB3D_ZSTENCIL_FORMAT 0x4F10 +# define R300_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) +# define R300_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) + +/* gap */ +#define R300_RB3D_DEPTHOFFSET 0x4F20 +#define R300_RB3D_DEPTHPITCH 0x4F24 +# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */ +# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */ +# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */ +# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */ +# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */ +# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */ + +/* BEGIN: Vertex program instruction set +// Every instruction is four dwords long: +// DWORD 0: output and opcode +// DWORD 1: first argument +// DWORD 2: second argument +// DWORD 3: third argument +// +// Notes: +// - ABS r, a is implemented as MAX r, a, -a +// - MOV is implemented as ADD to zero +// - XPD is implemented as MUL + MAD +// - FLR is implemented as FRC + ADD +// - apparently, fglrx tries to schedule instructions so that there is at least +// one instruction between the write to a temporary and the first read +// from said temporary; however, violations of this scheduling are allowed +// - register indices seem to be unrelated with OpenGL aliasing to conventional state +// - only one attribute and one parameter can be loaded at a time; however, the +// same attribute/parameter can be used for more than one argument +// - the second software argument for POW is the third hardware argument (no idea why) +// - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2 +// +// There is some magic surrounding LIT: +// The single argument is replicated across all three inputs, but swizzled: +// First argument: xyzy +// Second argument: xyzx +// Third argument: xyzw +// Whenever the result is used later in the fragment program, fglrx forces x and w +// to be 1.0 in the input selection; I don't know whether this is strictly necessary */ +#define R300_VPI_OUT_OP_DOT (1 << 0) +#define R300_VPI_OUT_OP_MUL (2 << 0) +#define R300_VPI_OUT_OP_ADD (3 << 0) +#define R300_VPI_OUT_OP_MAD (4 << 0) +#define R300_VPI_OUT_OP_DST (5 << 0) +#define R300_VPI_OUT_OP_FRC (6 << 0) +#define R300_VPI_OUT_OP_MAX (7 << 0) +#define R300_VPI_OUT_OP_MIN (8 << 0) +#define R300_VPI_OUT_OP_SGE (9 << 0) +#define R300_VPI_OUT_OP_SLT (10 << 0) +#define R300_VPI_OUT_OP_UNK12 (12 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */ +#define R300_VPI_OUT_OP_EXP (65 << 0) +#define R300_VPI_OUT_OP_LOG (66 << 0) +#define R300_VPI_OUT_OP_UNK67 (67 << 0) /* Used in fog computations, scalar(scalar) */ +#define R300_VPI_OUT_OP_LIT (68 << 0) +#define R300_VPI_OUT_OP_POW (69 << 0) +#define R300_VPI_OUT_OP_RCP (70 << 0) +#define R300_VPI_OUT_OP_RSQ (72 << 0) +#define R300_VPI_OUT_OP_UNK73 (73 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */ +#define R300_VPI_OUT_OP_EX2 (75 << 0) +#define R300_VPI_OUT_OP_LG2 (76 << 0) +#define R300_VPI_OUT_OP_MAD_2 (128 << 0) +#define R300_VPI_OUT_OP_UNK129 (129 << 0) /* all temps, vector(scalar, vector, vector) */ + +#define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8) +#define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8) +#define R300_VPI_OUT_REG_CLASS_MASK (31 << 8) + +#define R300_VPI_OUT_REG_INDEX_SHIFT 13 +#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */ + +#define R300_VPI_OUT_WRITE_X (1 << 20) +#define R300_VPI_OUT_WRITE_Y (1 << 21) +#define R300_VPI_OUT_WRITE_Z (1 << 22) +#define R300_VPI_OUT_WRITE_W (1 << 23) + +#define R300_VPI_IN_REG_CLASS_TEMPORARY (0 << 0) +#define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0) +#define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0) +#define R300_VPI_IN_REG_CLASS_NONE (9 << 0) +#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */ + +#define R300_VPI_IN_REG_INDEX_SHIFT 5 +#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */ + +/* The R300 can select components from the input register arbitrarily. +// Use the following constants, shifted by the component shift you +// want to select */ +#define R300_VPI_IN_SELECT_X 0 +#define R300_VPI_IN_SELECT_Y 1 +#define R300_VPI_IN_SELECT_Z 2 +#define R300_VPI_IN_SELECT_W 3 +#define R300_VPI_IN_SELECT_ZERO 4 +#define R300_VPI_IN_SELECT_ONE 5 +#define R300_VPI_IN_SELECT_MASK 7 + +#define R300_VPI_IN_X_SHIFT 13 +#define R300_VPI_IN_Y_SHIFT 16 +#define R300_VPI_IN_Z_SHIFT 19 +#define R300_VPI_IN_W_SHIFT 22 + +#define R300_VPI_IN_NEG_X (1 << 25) +#define R300_VPI_IN_NEG_Y (1 << 26) +#define R300_VPI_IN_NEG_Z (1 << 27) +#define R300_VPI_IN_NEG_W (1 << 28) +/* END */ + +//BEGIN: Packet 3 commands + +// A primitive emission dword. +#define R300_PRIM_TYPE_NONE (0 << 0) +#define R300_PRIM_TYPE_POINT (1 << 0) +#define R300_PRIM_TYPE_LINE (2 << 0) +#define R300_PRIM_TYPE_LINE_STRIP (3 << 0) +#define R300_PRIM_TYPE_TRI_LIST (4 << 0) +#define R300_PRIM_TYPE_TRI_FAN (5 << 0) +#define R300_PRIM_TYPE_TRI_STRIP (6 << 0) +#define R300_PRIM_TYPE_TRI_TYPE2 (7 << 0) +#define R300_PRIM_TYPE_RECT_LIST (8 << 0) +#define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) +#define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) +#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) // GUESS (based on r200) +#define R300_PRIM_TYPE_LINE_LOOP (12 << 0) +#define R300_PRIM_TYPE_QUADS (13 << 0) +#define R300_PRIM_TYPE_QUAD_STRIP (14 << 0) +#define R300_PRIM_TYPE_POLYGON (15 << 0) +#define R300_PRIM_TYPE_MASK 0xF +#define R300_PRIM_WALK_IND (1 << 4) +#define R300_PRIM_WALK_LIST (2 << 4) +#define R300_PRIM_WALK_RING (3 << 4) +#define R300_PRIM_WALK_MASK (3 << 4) +#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) // GUESS (based on r200) +#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) // GUESS +#define R300_PRIM_NUM_VERTICES_SHIFT 16 + +// Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR. +// Two parameter dwords: +// 0. The first parameter appears to be always 0 +// 1. The second parameter is a standard primitive emission dword. +#define R300_PACKET3_3D_DRAW_VBUF 0x00002800 + +// Specify the full set of vertex arrays as (address, stride). +// The first parameter is the number of vertex arrays specified. +// The rest of the command is a variable length list of blocks, where +// each block is three dwords long and specifies two arrays. +// The first dword of a block is split into two words, the lower significant +// word refers to the first array, the more significant word to the second +// array in the block. +// The low byte of each word contains the size of an array entry in dwords, +// the high byte contains the stride of the array. +// The second dword of a block contains the pointer to the first array, +// the third dword of a block contains the pointer to the second array. +// Note that if the total number of arrays is odd, the third dword of +// the last block is omitted. +#define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00 + +#define R300_PACKET3_INDX_BUFFER 0x00003300 +# define R300_EB_UNK1_SHIFT 24 +# define R300_EB_UNK1 (0x80<<24) +# define R300_EB_UNK2 0x0810 +#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600 + +//END + +#endif /* _R300_REG_H */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c new file mode 100644 index 000000000..a0769e27f --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c @@ -0,0 +1,726 @@ +/************************************************************************** + +Copyright (C) 2004 Nicolai Haehnle. + +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 +ATI, VA LINUX SYSTEMS AND/OR THEIR 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: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#include "glheader.h" +#include "state.h" +#include "imports.h" +#include "enums.h" +#include "macros.h" +#include "context.h" +#include "dd.h" +#include "simple_list.h" + +#include "api_arrayelt.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_vp_build.h" + +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "r300_context.h" +#include "r300_ioctl.h" +#include "r300_state.h" +#include "r300_reg.h" +#include "r300_program.h" +#include "r300_tex.h" +#include "r300_maos.h" +#include "r300_emit.h" + +extern int future_hw_tcl_on; + +/********************************************************************** +* Hardware rasterization +* +* When we fell back to software TCL, we still try to use the +* rasterization hardware for rendering. +**********************************************************************/ + +static int r300_get_primitive_type(r300ContextPtr rmesa, GLcontext *ctx, int prim) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + int type=-1; + + switch (prim & PRIM_MODE_MASK) { + case GL_POINTS: + type=R300_VAP_VF_CNTL__PRIM_POINTS; + break; + case GL_LINES: + type=R300_VAP_VF_CNTL__PRIM_LINES; + break; + case GL_LINE_STRIP: + type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP; + break; + case GL_LINE_LOOP: + type=R300_VAP_VF_CNTL__PRIM_LINE_LOOP; + break; + case GL_TRIANGLES: + type=R300_VAP_VF_CNTL__PRIM_TRIANGLES; + break; + case GL_TRIANGLE_STRIP: + type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP; + break; + case GL_TRIANGLE_FAN: + type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN; + break; + case GL_QUADS: + type=R300_VAP_VF_CNTL__PRIM_QUADS; + break; + case GL_QUAD_STRIP: + type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP; + break; + case GL_POLYGON: + type=R300_VAP_VF_CNTL__PRIM_POLYGON; + break; + default: + fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n", + __FILE__, __FUNCTION__, + prim & PRIM_MODE_MASK); + return -1; + break; + } + return type; +} + +static int r300_get_num_verts(r300ContextPtr rmesa, + GLcontext *ctx, + int num_verts, + int prim) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + int type=-1, verts_off=0; + char *name="UNKNOWN"; + + switch (prim & PRIM_MODE_MASK) { + case GL_POINTS: + name="P"; + verts_off = 0; + break; + case GL_LINES: + name="L"; + verts_off = num_verts % 2; + break; + case GL_LINE_STRIP: + name="LS"; + if(num_verts < 2) + verts_off = num_verts; + break; + case GL_LINE_LOOP: + name="LL"; + if(num_verts < 2) + verts_off = num_verts; + break; + case GL_TRIANGLES: + name="T"; + verts_off = num_verts % 3; + break; + case GL_TRIANGLE_STRIP: + name="TS"; + if(num_verts < 3) + verts_off = num_verts; + break; + case GL_TRIANGLE_FAN: + name="TF"; + if(num_verts < 3) + verts_off = num_verts; + break; + case GL_QUADS: + name="Q"; + verts_off = num_verts % 4; + break; + case GL_QUAD_STRIP: + name="QS"; + if(num_verts < 4) + verts_off = num_verts; + else + verts_off = num_verts % 2; + break; + case GL_POLYGON: + name="P"; + if(num_verts < 3) + verts_off = num_verts; + break; + default: + fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n", + __FILE__, __FUNCTION__, + prim & PRIM_MODE_MASK); + return -1; + break; + } + + if(num_verts - verts_off == 0){ + WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts, name); + return 0; + } + + if(verts_off > 0){ + WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name); + } + + return num_verts - verts_off; +} + +/* This function compiles GL context into state registers that + describe data routing inside of R300 pipeline. + + In particular, it programs input_route, output_vtx_fmt, texture + unit configuration and gb_output_vtx_fmt + + This function encompasses setup_AOS() from r300_lib.c +*/ + + + + +/* Immediate implementation - vertex data is sent via command stream */ + +static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0}; + +#define output_vector(v, i) { \ + int _i; \ + for(_i=0;_i<v->size;_i++){ \ + if(VB->Elts){ \ + efloat(VEC_ELT(v, GLfloat, VB->Elts[i])[_i]); \ + }else{ \ + efloat(VEC_ELT(v, GLfloat, i)[_i]); \ + } \ + } \ + for(_i=v->size;_i<4;_i++){ \ + efloat(default_vector[_i]); \ + } \ +} + +/* Immediate implementation - vertex data is sent via command stream */ + +static void r300_render_immediate_primitive(r300ContextPtr rmesa, + GLcontext *ctx, + int start, + int end, + int prim) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i, render_inputs; + int k, type, num_verts; + LOCAL_VARS + + type=r300_get_primitive_type(rmesa, ctx, prim); + num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim); + +#if 0 + fprintf(stderr,"ObjPtr: size=%d stride=%d\n", + VB->ObjPtr->size, VB->ObjPtr->stride); + fprintf(stderr,"ColorPtr[0]: size=%d stride=%d\n", + VB->ColorPtr[0]->size, VB->ColorPtr[0]->stride); + fprintf(stderr,"TexCoordPtr[0]: size=%d stride=%d\n", + VB->TexCoordPtr[0]->size, VB->TexCoordPtr[0]->stride); +#endif + + if(type<0 || num_verts <= 0)return; + + if(!VB->ObjPtr){ + WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n"); + return; + } + /* A packet cannot have more than 16383 data words.. */ + if((num_verts*4*rmesa->state.aos_count)>16380){ + WARN_ONCE("Too many vertices to paint. Fix me !\n"); + return; + } + + //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end); + + if(rmesa->state.aos_count==0){ + WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n"); + return; + } + + render_inputs = rmesa->state.render_inputs; + + if(!render_inputs){ + WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n"); + return; + } + + + start_immediate_packet(num_verts, type, 4*rmesa->state.aos_count); + + for(i=start;i<start+num_verts;i++){ +#if 0 + fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n", + VEC_ELT(VB->ObjPtr, GLfloat, i)[0], + VEC_ELT(VB->ObjPtr, GLfloat, i)[1], + VEC_ELT(VB->ObjPtr, GLfloat, i)[2], + VEC_ELT(VB->ObjPtr, GLfloat, i)[3], + + VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0], + VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1], + VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2], + VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3] + ); +#endif + + + /* coordinates */ + if(render_inputs & _TNL_BIT_POS) + output_vector(VB->ObjPtr, i); + if(render_inputs & _TNL_BIT_NORMAL) + output_vector(VB->NormalPtr, i); + + /* color components */ + if(render_inputs & _TNL_BIT_COLOR0) + output_vector(VB->ColorPtr[0], i); + if(render_inputs & _TNL_BIT_COLOR1) + output_vector(VB->SecondaryColorPtr[0], i); + +/* if(render_inputs & _TNL_BIT_FOG) // Causes lock ups when immediate mode is on + output_vector(VB->FogCoordPtr, i);*/ + + /* texture coordinates */ + for(k=0;k < ctx->Const.MaxTextureUnits;k++) + if(render_inputs & (_TNL_BIT_TEX0<<k)) + output_vector(VB->TexCoordPtr[k], i); + + if(render_inputs & _TNL_BIT_INDEX) + output_vector(VB->IndexPtr[0], i); + if(render_inputs & _TNL_BIT_POINTSIZE) + output_vector(VB->PointSizePtr, i); + } + +} + + +static GLboolean r300_run_immediate_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + /* Only do 2d textures */ + struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D; + r300TexObjPtr t=to->DriverData; + LOCAL_VARS + + + /* Update texture state - needs to be done only when actually changed.. + All the time for now.. */ + + + if (RADEON_DEBUG == DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + +#if 1 /* we need this, somehow */ + /* Flush state - make sure command buffer is nice and large */ + r300Flush(ctx); + /* Make sure we have enough space */ +#else + /* Count is very imprecize, but should be good upper bound */ + r300EnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size + 4+2+30 + +VB->PrimitiveCount*(1+8)+VB->Count*4*rmesa->state.texture.tc_count+4, __FUNCTION__); +#endif + + /* needed before starting 3d operation .. */ + reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); + e32(0x0000000a); + + reg_start(0x4f18,0); + e32(0x00000003); + + +#if 0 /* looks like the Z offset issue got fixed */ + rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA + | R300_VPORT_X_OFFSET_ENA + | R300_VPORT_Y_SCALE_ENA + | R300_VPORT_Y_OFFSET_ENA + | R300_VTX_W0_FMT; + R300_STATECHANGE(rmesa, vte); +#endif + + + + /* Magic register - note it is right after 20b0 */ + + + if(rmesa->state.texture.tc_count>0){ + reg_start(0x20b4,0); + e32(0x0000000c); + + } + + r300EmitState(rmesa); + +/* Setup INPUT_ROUTE and INPUT_CNTL */ + r300EmitArrays(ctx, GL_TRUE); + +/* Why do we need this for immediate mode?? Vertex processor needs it to know proper regs */ +// r300EmitLOAD_VBPNTR(rmesa, 0); +/* Okay, it seems I misunderstood something, EmitAOS does the same thing */ + r300EmitAOS(rmesa, rmesa->state.aos_count, 0); + + for(i=0; i < VB->PrimitiveCount; i++){ + GLuint prim = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length = VB->Primitive[i].count; + + r300_render_immediate_primitive(rmesa, ctx, start, start + length, prim); + } + + /* This sequence is required after any 3d drawing packet + I suspect it work arounds a bug (or deficiency) in hardware */ + + reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); + e32(0x0000000a); + + reg_start(0x4f18,0); + e32(0x00000003); + + return GL_FALSE; +} + + +/* vertex buffer implementation */ + +static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type) +{ + LOCAL_VARS + unsigned long addr_a; + + if(addr & 1){ + WARN_ONCE("Badly aligned buffer\n"); + return ; + } + addr_a = 0; /*addr & 0x1c;*/ + + check_space(6); + + start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0); + /* TODO: R300_VAP_VF_CNTL__INDEX_SIZE_32bit . */ + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type); + + start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2); + e32(R300_EB_UNK1 | (addr_a << 16) | R300_EB_UNK2); + e32(addr /*& 0xffffffe3*/); + e32((vertex_count+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */ +} + +static void r300_render_vb_primitive(r300ContextPtr rmesa, + GLcontext *ctx, + int start, + int end, + int prim) +{ + int type, num_verts; + radeonScreenPtr rsp=rmesa->radeon.radeonScreen; + LOCAL_VARS + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + int i; + + type=r300_get_primitive_type(rmesa, ctx, prim); + num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim); + + if(type<0 || num_verts <= 0)return; + + if(rmesa->state.Elts){ + r300EmitAOS(rmesa, rmesa->state.aos_count, 0); +#if 0 + start_index32_packet(num_verts, type); + for(i=0; i < num_verts; i++) + e32(rmesa->state.Elts[start+i]); /* start ? */ +#else + WARN_ONCE("Rendering with elt buffers\n"); + if(num_verts == 1){ + start_index32_packet(num_verts, type); + e32(rmesa->state.Elts[start]); + return; + } + + if(num_verts > 65535){ /* not implemented yet */ + WARN_ONCE("Too many elts\n"); + return; + } + r300EmitElts(ctx, rmesa->state.Elts+start, num_verts); + fire_EB(PASS_PREFIX GET_START(&(rmesa->state.elt_dma)), num_verts, type); +#endif + }else{ + r300EmitAOS(rmesa, rmesa->state.aos_count, start); + fire_AOS(PASS_PREFIX num_verts, type); + } +} + +static GLboolean r300_run_vb_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + int i, j; + LOCAL_VARS + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + + + r300ReleaseArrays(ctx); + r300EmitArrays(ctx, GL_FALSE); + +// LOCK_HARDWARE(&(rmesa->radeon)); + + reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); + e32(0x0000000a); + + reg_start(0x4f18,0); + e32(0x00000003); + r300EmitState(rmesa); + + rmesa->state.Elts = VB->Elts; + + for(i=0; i < VB->PrimitiveCount; i++){ + GLuint prim = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length = VB->Primitive[i].count; + + r300_render_vb_primitive(rmesa, ctx, start, start + length, prim); + } + + reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); + e32(0x0000000a); + + reg_start(0x4f18,0); + e32(0x00000003); + +// end_3d(PASS_PREFIX_VOID); + + /* Flush state - we are done drawing.. */ +// r300FlushCmdBufLocked(rmesa, __FUNCTION__); +// radeonWaitForIdleLocked(&(rmesa->radeon)); + +// UNLOCK_HARDWARE(&(rmesa->radeon)); + return GL_FALSE; +} + +/** + * Called by the pipeline manager to render a batch of primitives. + * We can return true to pass on to the next stage (i.e. software + * rasterization) or false to indicate that the pipeline has finished + * after we render something. + */ +static GLboolean r300_run_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + + +#if 1 + +#if 0 + return r300_run_immediate_render(ctx, stage); +#else + return r300_run_vb_render(ctx, stage); +#endif +#else + return GL_TRUE; +#endif +} + + +/** + * Called by the pipeline manager once before rendering. + * We check the GL state here to + * a) decide whether we can do the current state in hardware and + * b) update hardware registers + */ +#define FALLBACK_IF(expr) \ +do { \ + if (expr) { \ + if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \ + fprintf(stderr, "%s: fallback:%s\n", \ + __FUNCTION__, #expr); \ + /*stage->active = GL_FALSE*/; \ + return; \ + } \ +} while(0) + +static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int i; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + + /* We only support rendering in hardware for now */ + if (ctx->RenderMode != GL_RENDER) { + //stage->active = GL_FALSE; + return; + } + + + /* I'm almost certain I forgot something here */ +#if 0 /* These should work now.. */ + FALLBACK_IF(ctx->Color.DitherFlag); + FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST + FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND + FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL +#endif + //FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT + //FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE + //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST + + //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this + //FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH disabling to get blender going + FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE + FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB + + FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?) + +#if 0 /* ut2k3 fails to start if this is on */ + /* One step at a time - let one texture pass.. */ + for (i = 1; i < ctx->Const.MaxTextureUnits; i++) + FALLBACK_IF(ctx->Texture.Unit[i].Enabled); +#endif + + /* Assumed factor reg is found but pattern is still missing */ + //FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE disabling to get blender going + + /* HW doesnt appear to directly support these */ + //FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH disabling to get blender going + FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH + /* Rest could be done with vertex fragments */ + if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) + FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV + //GL_POINT_DISTANCE_ATTENUATION_ARB + //GL_POINT_FADE_THRESHOLD_SIZE_ARB + + /* let r300_run_render do its job */ +#if 0 + stage->active = GL_FALSE; +#endif +} + + +static void dtr(struct tnl_pipeline_stage *stage) +{ + (void)stage; +} + +static GLboolean r300_create_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + return GL_TRUE; +} + + +const struct tnl_pipeline_stage _r300_render_stage = { + "r300 hw rasterize", + NULL, + r300_create_render, + dtr, /* destructor */ + r300_check_render, /* check */ + r300_run_render /* run */ +}; + +static GLboolean r300_run_tcl_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + struct r300_vertex_program *vp; + + hw_tcl_on=future_hw_tcl_on; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + if(hw_tcl_on == GL_FALSE) + return GL_TRUE; + if(ctx->VertexProgram._Enabled == GL_FALSE){ + _tnl_UpdateFixedFunctionProgram(ctx); + } + vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); + if(vp->translated == GL_FALSE) + translate_vertex_shader(vp); + if(vp->translated == GL_FALSE){ + fprintf(stderr, "Failing back to sw-tcl\n"); + debug_vp(ctx, &vp->mesa_program); + hw_tcl_on=future_hw_tcl_on=0; + r300ResetHwState(rmesa); + return GL_TRUE; + } + + r300_setup_textures(ctx); + r300_setup_rs_unit(ctx); + + r300SetupVertexShader(rmesa); + r300SetupPixelShader(rmesa); + + return r300_run_vb_render(ctx, stage); +} + +static void r300_check_tcl_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int i; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + + /* We only support rendering in hardware for now */ + if (ctx->RenderMode != GL_RENDER) { + //stage->active = GL_FALSE; + return; + } +} + +const struct tnl_pipeline_stage _r300_tcl_stage = { + "r300 tcl", + NULL, + r300_create_render, + dtr, /* destructor */ + r300_check_tcl_render, /* check */ + r300_run_tcl_render /* run */ +}; diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_shader.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_shader.c new file mode 100644 index 000000000..9c6788ec3 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_shader.c @@ -0,0 +1,112 @@ +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "program.h" +#include "r300_context.h" +#include "nvvertprog.h" +#if USE_ARB_F_P == 1 +#include "r300_fragprog.h" +#endif + +static void r300BindProgram(GLcontext *ctx, GLenum target, struct program *prog) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct r300_vertex_program *vp=(void *)prog; + + switch(target){ + case GL_VERTEX_PROGRAM_ARB: +#if USE_ARB_F_P == 1 + case GL_FRAGMENT_PROGRAM_ARB: +#endif + //rmesa->current_vp = vp; + break; + default: + WARN_ONCE("Target not supported yet!\n"); + break; + } +} + +static struct program *r300NewProgram(GLcontext *ctx, GLenum target, GLuint id) +{ + struct r300_vertex_program *vp; +#if USE_ARB_F_P == 1 + struct r300_fragment_program *fp; +#else + struct fragment_program *fp; +#endif + struct ati_fragment_shader *afs; + + switch(target){ + case GL_VERTEX_PROGRAM_ARB: + vp=CALLOC_STRUCT(r300_vertex_program); + return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id); + + case GL_FRAGMENT_PROGRAM_ARB: +#if USE_ARB_F_P == 1 + fp=CALLOC_STRUCT(r300_fragment_program); + fp->ctx = ctx; + return _mesa_init_fragment_program(ctx, &fp->mesa_program, target, id); +#else + fp=CALLOC_STRUCT(fragment_program); + return _mesa_init_fragment_program(ctx, fp, target, id); +#endif + case GL_FRAGMENT_PROGRAM_NV: + fp=CALLOC_STRUCT(fragment_program); + return _mesa_init_fragment_program(ctx, fp, target, id); + + case GL_FRAGMENT_SHADER_ATI: + afs=CALLOC_STRUCT(ati_fragment_shader); + return _mesa_init_ati_fragment_shader(ctx, afs, target, id); + } + + return NULL; +} + + +static void r300DeleteProgram(GLcontext *ctx, struct program *prog) +{ + //r300ContextPtr rmesa = R300_CONTEXT(ctx); + //struct r300_vertex_program *vp=(void *)prog; + + _mesa_delete_program(ctx, prog); +} + +static void r300ProgramStringNotify(GLcontext *ctx, GLenum target, + struct program *prog) +{ + struct r300_vertex_program *vp=(void *)prog; +#if USE_ARB_F_P == 1 + struct r300_fragment_program *fp=(void *)prog; +#endif + + switch(target) { + case GL_VERTEX_PROGRAM_ARB: + /*vp->translated=GL_FALSE; + translate_vertex_shader(vp);*/ + //debug_vp(ctx, vp); + break; + case GL_FRAGMENT_PROGRAM_ARB: +#if USE_ARB_F_P == 1 + fp->translated = GL_FALSE; +#endif + break; + } +} + +static GLboolean r300IsProgramNative(GLcontext *ctx, GLenum target, struct program *prog) +{ + //struct r300_vertex_program *vp=(void *)prog; + //r300ContextPtr rmesa = R300_CONTEXT(ctx); + + return 1; +} + +void r300InitShaderFuncs(struct dd_function_table *functions) +{ + functions->NewProgram=r300NewProgram; + functions->BindProgram=r300BindProgram; + functions->DeleteProgram=r300DeleteProgram; + functions->ProgramStringNotify=r300ProgramStringNotify; + functions->IsProgramNative=r300IsProgramNative; +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_state.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_state.c new file mode 100644 index 000000000..b6a03a227 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_state.c @@ -0,0 +1,2321 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. +Copyright (C) 2004 Nicolai Haehnle. +All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#include "glheader.h" +#include "state.h" +#include "imports.h" +#include "enums.h" +#include "macros.h" +#include "context.h" +#include "dd.h" +#include "simple_list.h" + +#include "api_arrayelt.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "texformat.h" + +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "r300_context.h" +#include "r300_ioctl.h" +#include "r300_state.h" +#include "r300_reg.h" +#include "r300_program.h" +#include "r300_emit.h" +#if USE_ARB_F_P == 1 +#include "r300_fragprog.h" +#else +#include "r300_fixed_pipelines.h" +#include "r300_texprog.h" +#endif +#include "r300_tex.h" +#include "r300_maos.h" + +static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + int pp_misc = rmesa->hw.at.cmd[R300_AT_ALPHA_TEST]; + GLubyte refByte; + + CLAMPED_FLOAT_TO_UBYTE(refByte, ref); + + R300_STATECHANGE(rmesa, at); + + pp_misc &= ~(R300_ALPHA_TEST_OP_MASK | R300_REF_ALPHA_MASK); + pp_misc |= (refByte & R300_REF_ALPHA_MASK); + + switch (func) { + case GL_NEVER: + pp_misc |= R300_ALPHA_TEST_FAIL; + break; + case GL_LESS: + pp_misc |= R300_ALPHA_TEST_LESS; + break; + case GL_EQUAL: + pp_misc |= R300_ALPHA_TEST_EQUAL; + break; + case GL_LEQUAL: + pp_misc |= R300_ALPHA_TEST_LEQUAL; + break; + case GL_GREATER: + pp_misc |= R300_ALPHA_TEST_GREATER; + break; + case GL_NOTEQUAL: + pp_misc |= R300_ALPHA_TEST_NEQUAL; + break; + case GL_GEQUAL: + pp_misc |= R300_ALPHA_TEST_GEQUAL; + break; + case GL_ALWAYS: + pp_misc |= R300_ALPHA_TEST_PASS; + //pp_misc &= ~R300_ALPHA_TEST_ENABLE; + break; + } + + rmesa->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc; +} + +static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4]) +{ + GLubyte color[4]; + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, unk4E10); + + /* Ordering might be wrong */ + CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]); + CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]); + CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]); + CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]); + + rmesa->hw.unk4E10.cmd[1]=r300PackColor(4, color[0], color[1], color[2], color[3]); +} + +/** + * Calculate the hardware blend factor setting. This same function is used + * for source and destination of both alpha and RGB. + * + * \returns + * The hardware register value for the specified blend factor. This value + * will need to be shifted into the correct position for either source or + * destination factor. + * + * \todo + * Since the two cases where source and destination are handled differently + * are essentially error cases, they should never happen. Determine if these + * cases can be removed. + */ +static int blend_factor(GLenum factor, GLboolean is_src) +{ + int func; + + switch (factor) { + case GL_ZERO: + func = R200_BLEND_GL_ZERO; + break; + case GL_ONE: + func = R200_BLEND_GL_ONE; + break; + case GL_DST_COLOR: + func = R200_BLEND_GL_DST_COLOR; + break; + case GL_ONE_MINUS_DST_COLOR: + func = R200_BLEND_GL_ONE_MINUS_DST_COLOR; + break; + case GL_SRC_COLOR: + func = R200_BLEND_GL_SRC_COLOR; + break; + case GL_ONE_MINUS_SRC_COLOR: + func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR; + break; + case GL_SRC_ALPHA: + func = R200_BLEND_GL_SRC_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA; + break; + case GL_DST_ALPHA: + func = R200_BLEND_GL_DST_ALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: + func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA; + break; + case GL_SRC_ALPHA_SATURATE: + func = + (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : + R200_BLEND_GL_ZERO; + break; + case GL_CONSTANT_COLOR: + func = R200_BLEND_GL_CONST_COLOR; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR; + break; + case GL_CONSTANT_ALPHA: + func = R200_BLEND_GL_CONST_ALPHA; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA; + break; + default: + func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO; + } + return func; +} + +/** + * Sets both the blend equation and the blend function. + * This is done in a single + * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) + * change the interpretation of the blend function. + * Also, make sure that blend function and blend equation are set to their default + * value if color blending is not enabled, since at least blend equations GL_MIN + * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for + * unknown reasons. + */ + +/* helper function */ +static void r300_set_blend_cntl(r300ContextPtr r300, int func, int eqn, int cbits, int funcA, int eqnA) +{ + GLuint new_ablend, new_cblend; + +#if 0 + fprintf(stderr, "eqnA=%08x funcA=%08x eqn=%08x func=%08x cbits=%08x\n", eqnA, funcA, eqn, func, cbits); +#endif + new_ablend = eqnA | funcA; + new_cblend = eqn | func; + + /* Some blend factor combinations don't seem to work when the + * BLEND_NO_SEPARATE bit is set. + * + * Especially problematic candidates are the ONE_MINUS_* flags, + * but I can't see a real pattern. + */ +#if 0 + if (new_ablend == new_cblend) { + new_cblend |= R300_BLEND_NO_SEPARATE; + } +#endif + new_cblend |= cbits; + + if((new_ablend != r300->hw.bld.cmd[R300_BLD_ABLEND]) || + (new_cblend != r300->hw.bld.cmd[R300_BLD_CBLEND])) { + R300_STATECHANGE(r300, bld); + r300->hw.bld.cmd[R300_BLD_ABLEND]=new_ablend; + r300->hw.bld.cmd[R300_BLD_CBLEND]=new_cblend; + } +} + + +static void r300_set_blend_state(GLcontext * ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); + int eqn = R200_COMB_FCN_ADD_CLAMP; + int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); + int eqnA = R200_COMB_FCN_ADD_CLAMP; + + if (ctx->Color._LogicOpEnabled || !ctx->Color.BlendEnabled) { + r300_set_blend_cntl(r300, + func, eqn, 0, + func, eqn); + return; + } + + func = (blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE) << R200_SRC_BLEND_SHIFT) | + (blend_factor(ctx->Color.BlendDstRGB, GL_FALSE) << R200_DST_BLEND_SHIFT); + + switch (ctx->Color.BlendEquationRGB) { + case GL_FUNC_ADD: + eqn = R300_COMB_FCN_ADD_CLAMP; + break; + + case GL_FUNC_SUBTRACT: + eqn = R300_COMB_FCN_SUB_CLAMP; + break; + + case GL_FUNC_REVERSE_SUBTRACT: + eqn = R200_COMB_FCN_RSUB_CLAMP; + break; + + case GL_MIN: + eqn = R200_COMB_FCN_MIN; + func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + case GL_MAX: + eqn = R200_COMB_FCN_MAX; + func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + default: + fprintf(stderr, + "[%s:%u] Invalid RGB blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationRGB); + return; + } + + + funcA = (blend_factor(ctx->Color.BlendSrcA, GL_TRUE) << R200_SRC_BLEND_SHIFT) | + (blend_factor(ctx->Color.BlendDstA, GL_FALSE) << R200_DST_BLEND_SHIFT); + + switch (ctx->Color.BlendEquationA) { + case GL_FUNC_ADD: + eqnA = R300_COMB_FCN_ADD_CLAMP; + break; + + case GL_FUNC_SUBTRACT: + eqnA = R300_COMB_FCN_SUB_CLAMP; + break; + + case GL_FUNC_REVERSE_SUBTRACT: + eqnA = R200_COMB_FCN_RSUB_CLAMP; + break; + + case GL_MIN: + eqnA = R200_COMB_FCN_MIN; + funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + case GL_MAX: + eqnA = R200_COMB_FCN_MAX; + funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + default: + fprintf(stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationA); + return; + } + + r300_set_blend_cntl(r300, + func, eqn, R300_BLEND_UNKNOWN | R300_BLEND_ENABLE, + funcA, eqnA); +} + +static void r300BlendEquationSeparate(GLcontext * ctx, + GLenum modeRGB, GLenum modeA) +{ + r300_set_blend_state(ctx); +} + +static void r300BlendFuncSeparate(GLcontext * ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + r300_set_blend_state(ctx); +} + +/** + * Update our tracked culling state based on Mesa's state. + */ +static void r300UpdateCulling(GLcontext* ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + uint32_t val = 0; + + R300_STATECHANGE(r300, cul); + if (ctx->Polygon.CullFlag) { + if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) + val = R300_CULL_FRONT|R300_CULL_BACK; + else if (ctx->Polygon.CullFaceMode == GL_FRONT) + val = R300_CULL_FRONT; + else + val = R300_CULL_BACK; + + if (ctx->Polygon.FrontFace == GL_CW) + val |= R300_FRONT_FACE_CW; + else + val |= R300_FRONT_FACE_CCW; + } + r300->hw.cul.cmd[R300_CUL_CULL] = val; +} + +static void update_early_z(GLcontext* ctx) +{ + /* updates register 0x4f14 + if depth test is not enabled it should be 0x00000000 + if depth is enabled and alpha not it should be 0x00000001 + if depth and alpha is enabled it should be 0x00000000 + */ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + R300_STATECHANGE(r300, unk4F10); + if (ctx->Color.AlphaEnabled) + /* disable early Z */ + r300->hw.unk4F10.cmd[2] = 0x00000000; + else { + if (ctx->Depth.Test) + /* enable early Z */ + r300->hw.unk4F10.cmd[2] = 0x00000001; + else + /* disable early Z */ + r300->hw.unk4F10.cmd[2] = 0x00000000; + } +} + +/** + * Handle glEnable()/glDisable(). + * + * \note Mesa already filters redundant calls to glEnable/glDisable. + */ +static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + uint32_t newval; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s( %s = %s )\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(cap), + state ? "GL_TRUE" : "GL_FALSE"); + + switch (cap) { + /* Fast track this one... + */ + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + break; + + case GL_ALPHA_TEST: + R300_STATECHANGE(r300, at); + if (state) { + r300->hw.at.cmd[R300_AT_ALPHA_TEST] |= + R300_ALPHA_TEST_ENABLE; + } else { + r300->hw.at.cmd[R300_AT_ALPHA_TEST] &= + ~R300_ALPHA_TEST_ENABLE; + } + update_early_z(ctx); + break; + + case GL_BLEND: + case GL_COLOR_LOGIC_OP: + r300_set_blend_state(ctx); + break; + + case GL_DEPTH_TEST: + R300_STATECHANGE(r300, zs); + + if (state) { + if (ctx->Depth.Mask) + newval = R300_RB3D_Z_TEST_AND_WRITE; + else + newval = R300_RB3D_Z_TEST; + } else + newval = R300_RB3D_Z_DISABLED_1; + + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= newval; + update_early_z(ctx); + break; + + case GL_STENCIL_TEST: + WARN_ONCE("TODO - double side stencil !\n"); + if (r300->state.stencil.hw_stencil) { + R300_STATECHANGE(r300, zs); + if (state) { + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= + R300_RB3D_STENCIL_ENABLE; + } else { + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= + ~R300_RB3D_STENCIL_ENABLE; + } + } else { +#if R200_MERGED + FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state); +#endif + } + break; + + case GL_CULL_FACE: + r300UpdateCulling(ctx); + break; + + case GL_POLYGON_OFFSET_POINT: + case GL_POLYGON_OFFSET_LINE: + break; + + case GL_POLYGON_OFFSET_FILL: + R300_STATECHANGE(r300, unk42B4); + if(state){ + r300->hw.unk42B4.cmd[1] |= (3<<0); + } else { + r300->hw.unk42B4.cmd[1] &= ~(3<<0); + } + break; + default: + radeonEnable(ctx, cap, state); + return; + } +} + + +static void r300UpdatePolygonMode(GLcontext *ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + uint32_t hw_mode=0; + + if (ctx->Polygon.FrontMode != GL_FILL || + ctx->Polygon.BackMode != GL_FILL) { + GLenum f, b; + + if (ctx->Polygon.FrontFace == GL_CCW) { + f = ctx->Polygon.FrontMode; + b = ctx->Polygon.BackMode; + } else { + f = ctx->Polygon.BackMode; + b = ctx->Polygon.FrontMode; + } + + hw_mode |= R300_PM_ENABLED; + + switch (f) { + case GL_LINE: + hw_mode |= R300_PM_FRONT_LINE; + break; + case GL_POINT: /* noop */ + hw_mode |= R300_PM_FRONT_POINT; + break; + case GL_FILL: + hw_mode |= R300_PM_FRONT_FILL; + break; + } + + switch (b) { + case GL_LINE: + hw_mode |= R300_PM_BACK_LINE; + break; + case GL_POINT: /* noop */ + hw_mode |= R300_PM_BACK_POINT; + break; + case GL_FILL: + hw_mode |= R300_PM_BACK_FILL; + break; + } + } + + if (r300->hw.unk4288.cmd[1] != hw_mode) { + R300_STATECHANGE(r300, unk4288); + r300->hw.unk4288.cmd[1] = hw_mode; + } +} + +/** + * Change the culling mode. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300CullFace(GLcontext* ctx, GLenum mode) +{ + (void)mode; + + r300UpdateCulling(ctx); +} + + +/** + * Change the polygon orientation. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300FrontFace(GLcontext* ctx, GLenum mode) +{ + (void)mode; + + r300UpdateCulling(ctx); + r300UpdatePolygonMode(ctx); +} + + +/** + * Change the depth testing function. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300DepthFunc(GLcontext* ctx, GLenum func) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + R300_STATECHANGE(r300, zs); + + r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); + + switch(func) { + case GL_NEVER: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_NEVER << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_LESS: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_LESS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_EQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_EQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_LEQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_LEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_GREATER: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_GREATER << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_NOTEQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_NOTEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_GEQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_GEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_ALWAYS: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_ALWAYS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + } +} + + +/** + * Enable/Disable depth writing. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300DepthMask(GLcontext* ctx, GLboolean mask) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + if (!ctx->Depth.Test) + return; + + R300_STATECHANGE(r300, zs); + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= mask + ? R300_RB3D_Z_TEST_AND_WRITE : R300_RB3D_Z_TEST; +} + + +/** + * Handle glColorMask() + */ +static void r300ColorMask(GLcontext* ctx, + GLboolean r, GLboolean g, GLboolean b, GLboolean a) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int mask = (r ? R300_COLORMASK0_R : 0) | + (g ? R300_COLORMASK0_G : 0) | + (b ? R300_COLORMASK0_B : 0) | + (a ? R300_COLORMASK0_A : 0); + + if (mask != r300->hw.cmk.cmd[R300_CMK_COLORMASK]) { + R300_STATECHANGE(r300, cmk); + r300->hw.cmk.cmd[R300_CMK_COLORMASK] = mask; + } +} + +/* ============================================================= + * Point state + */ +static void r300PointSize(GLcontext * ctx, GLfloat size) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + size = ctx->Point._Size; + + R300_STATECHANGE(r300, ps); + r300->hw.ps.cmd[R300_PS_POINTSIZE] = + ((int)(size * 6) << R300_POINTSIZE_X_SHIFT) | + ((int)(size * 6) << R300_POINTSIZE_Y_SHIFT); +} + +/* ============================================================= + * Line state + */ +static void r300LineWidth(GLcontext *ctx, GLfloat widthf) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + widthf = ctx->Line._Width; + + R300_STATECHANGE(r300, lcntl); + r300->hw.lcntl.cmd[1] = (int)(widthf * 6.0); + r300->hw.lcntl.cmd[1] |= R300_LINE_CNT_VE; +} + +static void r300PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + (void)face; + (void)mode; + + r300UpdatePolygonMode(ctx); +} + +/* ============================================================= + * Stencil + */ + +static int translate_stencil_func(int func) +{ + switch (func) { + case GL_NEVER: + return R300_ZS_NEVER; + case GL_LESS: + return R300_ZS_LESS; + case GL_EQUAL: + return R300_ZS_EQUAL; + case GL_LEQUAL: + return R300_ZS_LEQUAL; + case GL_GREATER: + return R300_ZS_GREATER; + case GL_NOTEQUAL: + return R300_ZS_NOTEQUAL; + case GL_GEQUAL: + return R300_ZS_GEQUAL; + case GL_ALWAYS: + return R300_ZS_ALWAYS; + } + return 0; +} + +static int translate_stencil_op(int op) +{ + switch (op) { + case GL_KEEP: + return R300_ZS_KEEP; + case GL_ZERO: + return R300_ZS_ZERO; + case GL_REPLACE: + return R300_ZS_REPLACE; + case GL_INCR: + return R300_ZS_INCR; + case GL_DECR: + return R300_ZS_DECR; + case GL_INCR_WRAP_EXT: + return R300_ZS_INCR_WRAP; + case GL_DECR_WRAP_EXT: + return R300_ZS_DECR_WRAP; + case GL_INVERT: + return R300_ZS_INVERT; + default: + WARN_ONCE("Do not know how to translate stencil op"); + return R300_ZS_KEEP; + } + return 0; +} + +static void r300ShadeModel(GLcontext * ctx, GLenum mode) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, unk4274); + switch (mode) { + case GL_FLAT: + rmesa->hw.unk4274.cmd[2] = R300_RE_SHADE_MODEL_FLAT; + break; + case GL_SMOOTH: + rmesa->hw.unk4274.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH; + break; + default: + return; + } +} + +static void r300StencilFunc(GLcontext * ctx, GLenum func, + GLint ref, GLuint mask) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) | + (ctx->Stencil.ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT)); + + GLuint flag; + + R300_STATECHANGE(rmesa, zs); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~( + (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) + | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT)); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~((R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_REF_SHIFT) | + (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT)); + + flag = translate_stencil_func(ctx->Stencil.Function[0]); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) + | (flag << R300_RB3D_ZS1_BACK_FUNC_SHIFT); + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask; +} + +static void r300StencilMask(GLcontext * ctx, GLuint mask) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, zs); + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT); + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT; +} + + +static void r300StencilOp(GLcontext * ctx, GLenum fail, + GLenum zfail, GLenum zpass) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, zs); + /* It is easier to mask what's left.. */ + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= + (R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT) | + (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | + (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= + (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT); +} + +static void r300ClearStencil(GLcontext * ctx, GLint s) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + rmesa->state.stencil.clear = + ((GLuint) ctx->Stencil.Clear | + (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT) | + (ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT)); +} + +/* ============================================================= + * Window position and viewport transformation + */ + +/* + * To correctly position primitives: + */ +#define SUBPIXEL_X 0.125 +#define SUBPIXEL_Y 0.125 + +static void r300UpdateWindow(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable; + GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0; + GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0; + const GLfloat *v = ctx->Viewport._WindowMap.m; + + GLfloat sx = v[MAT_SX]; + GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; + GLfloat sy = -v[MAT_SY]; + GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y; + GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale; + GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale; + + R300_FIREVERTICES(rmesa); + R300_STATECHANGE(rmesa, vpt); + + rmesa->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(sx); + rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(tx); + rmesa->hw.vpt.cmd[R300_VPT_YSCALE] = r300PackFloat32(sy); + rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(ty); + rmesa->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(sz); + rmesa->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(tz); +} + +static void r300Viewport(GLcontext * ctx, GLint x, GLint y, + GLsizei width, GLsizei height) +{ + /* Don't pipeline viewport changes, conflict with window offset + * setting below. Could apply deltas to rescue pipelined viewport + * values, or keep the originals hanging around. + */ + R300_FIREVERTICES(R300_CONTEXT(ctx)); + r300UpdateWindow(ctx); +} + +static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval) +{ + r300UpdateWindow(ctx); +} + +/* ============================================================= + * Polygon state + */ +static void r300PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLfloat constant = units; + + switch (ctx->Visual.depthBits) { + case 16: + constant *= 4.0; + break; + case 24: + constant *= 2.0; + break; + } + + factor *= 12.0; + +/* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ + + R300_STATECHANGE(rmesa, zbs); + rmesa->hw.zbs.cmd[R300_ZBS_T_FACTOR] = r300PackFloat32(factor); + rmesa->hw.zbs.cmd[R300_ZBS_T_CONSTANT] = r300PackFloat32(constant); + rmesa->hw.zbs.cmd[R300_ZBS_W_FACTOR] = r300PackFloat32(factor); + rmesa->hw.zbs.cmd[R300_ZBS_W_CONSTANT] = r300PackFloat32(constant); +} + +/* Routing and texture-related */ + +static r300TexObj default_tex_obj={ + filter:R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR, + pitch: 0x8000, + size: (0xff << R300_TX_WIDTHMASK_SHIFT) + | (0xff << R300_TX_HEIGHTMASK_SHIFT) + | (0x8 << R300_TX_SIZE_SHIFT), + format: 0x88a0c, + offset: 0x0, + unknown4: 0x0, + unknown5: 0x0 + }; + + /* there is probably a system to these value, but, for now, + we just try by hand */ + +static int inline translate_src(int src) +{ + switch (src) { + case GL_TEXTURE: + return 1; + break; + case GL_CONSTANT: + return 2; + break; + case GL_PRIMARY_COLOR: + return 3; + break; + case GL_PREVIOUS: + return 4; + break; + case GL_ZERO: + return 5; + break; + case GL_ONE: + return 6; + break; + default: + return 0; + } +} + +/* r300 doesnt handle GL_CLAMP and GL_MIRROR_CLAMP_EXT correctly when filter is NEAREST. + * Since texwrap produces same results for GL_CLAMP and GL_CLAMP_TO_EDGE we use them instead. + * We need to recalculate wrap modes whenever filter mode is changed because someone might do: + * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + * Since r300 completely ignores R300_TX_CLAMP when either min or mag is nearest it cant handle + * combinations where only one of them is nearest. + */ +static unsigned long gen_fixed_filter(unsigned long f) +{ + unsigned long mag, min, needs_fixing=0; + //return f; + + /* We ignore MIRROR bit so we dont have to do everything twice */ + if((f & ((7-1) << R300_TX_WRAP_S_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_S_SHIFT)){ + needs_fixing |= 1; + } + if((f & ((7-1) << R300_TX_WRAP_T_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_T_SHIFT)){ + needs_fixing |= 2; + } + if((f & ((7-1) << R300_TX_WRAP_Q_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_Q_SHIFT)){ + needs_fixing |= 4; + } + + if(!needs_fixing) + return f; + + mag=f & R300_TX_MAG_FILTER_MASK; + min=f & R300_TX_MIN_FILTER_MASK; + + /* TODO: Check for anisto filters too */ + if((mag != R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)) + return f; + + /* r300 cant handle these modes hence we force nearest to linear */ + if((mag == R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)){ + f &= ~R300_TX_MAG_FILTER_NEAREST; + f |= R300_TX_MAG_FILTER_LINEAR; + return f; + } + + if((min == R300_TX_MIN_FILTER_NEAREST) && (mag != R300_TX_MAG_FILTER_NEAREST)){ + f &= ~R300_TX_MIN_FILTER_NEAREST; + f |= R300_TX_MIN_FILTER_LINEAR; + return f; + } + + /* Both are nearest */ + if(needs_fixing & 1){ + f &= ~((7-1) << R300_TX_WRAP_S_SHIFT); + f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_S_SHIFT; + } + if(needs_fixing & 2){ + f &= ~((7-1) << R300_TX_WRAP_T_SHIFT); + f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_T_SHIFT; + } + if(needs_fixing & 4){ + f &= ~((7-1) << R300_TX_WRAP_Q_SHIFT); + f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_Q_SHIFT; + } + return f; +} + +void r300_setup_textures(GLcontext *ctx) +{ + int i, mtu; + struct r300_tex_obj *t; + r300ContextPtr r300 = R300_CONTEXT(ctx); + int max_texture_unit=-1; /* -1 translates into no setup costs for fields */ + struct gl_texture_unit *texUnit; + GLuint OutputsWritten; + + if(hw_tcl_on) + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten; + + R300_STATECHANGE(r300, txe); + R300_STATECHANGE(r300, tex.filter); + R300_STATECHANGE(r300, tex.unknown1); + R300_STATECHANGE(r300, tex.size); + R300_STATECHANGE(r300, tex.format); + R300_STATECHANGE(r300, tex.offset); + R300_STATECHANGE(r300, tex.unknown4); + R300_STATECHANGE(r300, tex.border_color); + + r300->hw.txe.cmd[R300_TXE_ENABLE]=0x0; + + mtu = r300->radeon.glCtx->Const.MaxTextureUnits; + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "mtu=%d\n", mtu); + + if(mtu > R300_MAX_TEXTURE_UNITS) { + fprintf(stderr, "Aiiee ! mtu=%d is greater than R300_MAX_TEXTURE_UNITS=%d\n", + mtu, R300_MAX_TEXTURE_UNITS); + exit(-1); + } + + for(i=0; i < mtu; i++) { + /*if( ((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0) != ((ctx->Texture.Unit[i].Enabled)!=0) ) { + WARN_ONCE("Mismatch between render_inputs and ctx->Texture.Unit[i].Enabled value(%d vs %d).\n", + ((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0), ((ctx->Texture.Unit[i].Enabled)!=0)); + }*/ + + if(TMU_ENABLED(ctx, i)) { + t=r300->state.texture.unit[i].texobj; + //fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format); + + if(t == NULL){ + fprintf(stderr, "Texture unit %d enabled, but corresponding texobj is NULL, using default object.\n", i); + //exit(-1); + t=&default_tex_obj; + } + + //fprintf(stderr, "t->format=%08x\n", t->format); + if((t->format & 0xffffff00)==0xffffff00) { + WARN_ONCE("unknown texture format (entry %x) encountered. Help me !\n", t->format & 0xff); + //fprintf(stderr, "t->format=%08x\n", t->format); + } + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "Activating texture unit %d\n", i); + max_texture_unit=i; + r300->hw.txe.cmd[R300_TXE_ENABLE]|=(1<<i); + + r300->hw.tex.filter.cmd[R300_TEX_VALUE_0+i]=gen_fixed_filter(t->filter) | (i << 28); + //r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=0x0; /* move lod bias here? */ + + /* No idea why linear filtered textures shake when puting random data */ + /*r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=(rand()%0xffffffff) & (~0x1fff);*/ + r300->hw.tex.size.cmd[R300_TEX_VALUE_0+i]=t->size; + r300->hw.tex.format.cmd[R300_TEX_VALUE_0+i]=t->format; + //fprintf(stderr, "t->format=%08x\n", t->format); + r300->hw.tex.offset.cmd[R300_TEX_VALUE_0+i]=t->offset; + r300->hw.tex.unknown4.cmd[R300_TEX_VALUE_0+i]=0x0; + r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0+i]=t->pp_border_color; + } + } + + ((drm_r300_cmd_header_t*)r300->hw.tex.filter.cmd)->packet0.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.unknown1.cmd)->packet0.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.size.cmd)->packet0.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.format.cmd)->packet0.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.offset.cmd)->packet0.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.unknown4.cmd)->packet0.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.border_color.cmd)->packet0.count = max_texture_unit+1; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "TX_ENABLE: %08x max_texture_unit=%d\n", r300->hw.txe.cmd[R300_TXE_ENABLE], max_texture_unit); +} + +#if USE_ARB_F_P == 1 +void r300_setup_rs_unit(GLcontext *ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + /* I'm still unsure if these are needed */ + GLuint interp_magic[8] = { + 0x00, + 0x40, + 0x80, + 0xC0, + 0x00, + 0x00, + 0x00, + 0x00 + }; + GLuint OutputsWritten; + GLuint InputsRead; + int vp_reg, fp_reg, high_rr; + int in_texcoords, col_interp_nr; + int i; + + if(hw_tcl_on) + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten; + else + OutputsWritten = r300->state.render_inputs; + + if (ctx->FragmentProgram._Current) + InputsRead = ctx->FragmentProgram._Current->InputsRead; + else { + fprintf(stderr, "No ctx->FragmentProgram._Current!!\n"); + return; /* This should only ever happen once.. */ + } + + R300_STATECHANGE(r300, ri); + R300_STATECHANGE(r300, rc); + R300_STATECHANGE(r300, rr); + + vp_reg = fp_reg = in_texcoords = col_interp_nr = high_rr = 0; + r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0; + r300->hw.rr.cmd[R300_RR_ROUTE_1] = 0; + + for (i=0;i<ctx->Const.MaxTextureUnits;i++) { + if (OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i))) + in_texcoords++; + + r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0 + | R300_RS_INTERP_USED + | (vp_reg << R300_RS_INTERP_SRC_SHIFT) + | interp_magic[i]; + + if (InputsRead & (FRAG_BIT_TEX0<<i)) { + //assert(r300->state.texture.tc_count != 0); + r300->hw.rr.cmd[R300_RR_ROUTE_0 + fp_reg] = 0 + | R300_RS_ROUTE_ENABLE + | i /* source INTERP */ + | (fp_reg << R300_RS_ROUTE_DEST_SHIFT); + high_rr = fp_reg; + + if (OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i))) { + vp_reg++; + } else { + /* Unsure of how to handle this situation, for now print errors and + * the program will just recieve bogus data + */ + fprintf(stderr, "fragprog wants coords for tex%d, vp doesn't provide them!\n", i); + } + InputsRead &= ~(FRAG_BIT_TEX0<<i); + fp_reg++; + } + } + + if (InputsRead & FRAG_BIT_COL0) { + if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL0) : _TNL_BIT_COLOR0))) + fprintf(stderr, "fragprog wants col0, vp doesn't provide it\n"); + + r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 + | R300_RS_ROUTE_0_COLOR + | (fp_reg++ << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); + InputsRead &= ~FRAG_BIT_COL0; + col_interp_nr++; + } + + if (InputsRead & FRAG_BIT_COL1) { + if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL1) : _TNL_BIT_COLOR1))) + fprintf(stderr, "fragprog wants col1, vp doesn't provide it\n"); + + r300->hw.rr.cmd[R300_RR_ROUTE_1] |= R300_RS_ROUTE_1_UNKNOWN11 + | R300_RS_ROUTE_1_COLOR1 + | (fp_reg++ << R300_RS_ROUTE_1_COLOR1_DEST_SHIFT); + InputsRead &= ~FRAG_BIT_COL1; + if (high_rr < 1) high_rr = 1; + col_interp_nr++; + } + + r300->hw.rc.cmd[1] = 0 + | (in_texcoords << R300_RS_CNTL_TC_CNT_SHIFT) + | (col_interp_nr << R300_RS_CNTL_CI_CNT_SHIFT) + | R300_RS_CNTL_0_UNKNOWN_18; + + assert(high_rr >= 0); + r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, high_rr+1); + r300->hw.rc.cmd[2] = 0xC0 | high_rr; + + if (InputsRead) + WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead); +} +#else +void r300_setup_rs_unit(GLcontext *ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int i, cur_reg; + /* I'm still unsure if these are needed */ + GLuint interp_magic[8] = { + 0x00, + 0x40, + 0x80, + 0xC0, + 0x00, + 0x00, + 0x00, + 0x00 + }; + GLuint OutputsWritten; + + if(hw_tcl_on) + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten; + + /* This needs to be rewritten - it is a hack at best */ + + R300_STATECHANGE(r300, ri); + R300_STATECHANGE(r300, rc); + R300_STATECHANGE(r300, rr); + + cur_reg = 0; + r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0; + + for (i=0;i<ctx->Const.MaxTextureUnits;i++) { + r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0 + | R300_RS_INTERP_USED + | (cur_reg << R300_RS_INTERP_SRC_SHIFT) + | interp_magic[i]; +// fprintf(stderr, "RS_INTERP[%d] = 0x%x\n", i, r300->hw.ri.cmd[R300_RI_INTERP_0+i]); + + if (TMU_ENABLED(ctx, i)) { + assert(r300->state.texture.tc_count != 0); + r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg] = 0 + | R300_RS_ROUTE_ENABLE + | i /* source INTERP */ + | (cur_reg << R300_RS_ROUTE_DEST_SHIFT); +// fprintf(stderr, "RS_ROUTE[%d] = 0x%x\n", cur_reg, r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg]); + cur_reg++; + } + } + if (hw_tcl_on ? OutputsWritten & (1<<VERT_RESULT_COL0) : r300->state.render_inputs & _TNL_BIT_COLOR0) + r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 + | R300_RS_ROUTE_0_COLOR + | (cur_reg << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); + +// fprintf(stderr, "ADJ_RR0 = 0x%x\n", r300->hw.rr.cmd[R300_RR_ROUTE_0]); + + r300->hw.rc.cmd[1] = 0 + | (cur_reg /* count */ << R300_RS_CNTL_TC_CNT_SHIFT) + | R300_RS_CNTL_0_UNKNOWN_7 + | R300_RS_CNTL_0_UNKNOWN_18; + + if (r300->state.texture.tc_count > 0) { + r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, cur_reg); + r300->hw.rc.cmd[2] = 0xC0 | (cur_reg-1); /* index of highest */ + } else { + r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, 1); + r300->hw.rc.cmd[2] = 0x0; + } + + +// fprintf(stderr, "rendering with %d texture co-ordinate sets\n", cur_reg); +} +#endif // USE_ARB_F_P + +#define vpucount(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count) + +#define bump_vpu_count(ptr, new_count) do{\ + drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr));\ + int _nc=(new_count)/4; \ + if(_nc>_p->vpu.count)_p->vpu.count=_nc;\ + }while(0) + +void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, struct r300_vertex_shader_fragment *vsf) +{ + int i; + + if(vsf->length==0)return; + + if(vsf->length & 0x3){ + fprintf(stderr,"VERTEX_SHADER_FRAGMENT must have length divisible by 4\n"); + exit(-1); + } + + switch((dest>>8) & 0xf){ + case 0: + R300_STATECHANGE(r300, vpi); + for(i=0;i<vsf->length;i++) + r300->hw.vpi.cmd[R300_VPI_INSTR_0+i+4*(dest & 0xff)]=(vsf->body.d[i]); + bump_vpu_count(r300->hw.vpi.cmd, vsf->length+4*(dest & 0xff)); + break; + + case 2: + R300_STATECHANGE(r300, vpp); + for(i=0;i<vsf->length;i++) + r300->hw.vpp.cmd[R300_VPP_PARAM_0+i+4*(dest & 0xff)]=(vsf->body.d[i]); + bump_vpu_count(r300->hw.vpp.cmd, vsf->length+4*(dest & 0xff)); + break; + case 4: + R300_STATECHANGE(r300, vps); + for(i=0;i<vsf->length;i++) + r300->hw.vps.cmd[1+i+4*(dest & 0xff)]=(vsf->body.d[i]); + bump_vpu_count(r300->hw.vps.cmd, vsf->length+4*(dest & 0xff)); + break; + default: + fprintf(stderr, "%s:%s don't know how to handle dest %04x\n", __FILE__, __FUNCTION__, dest); + exit(-1); + } +} + +void r300SetupVertexProgram(r300ContextPtr rmesa); + +/* just a skeleton for now.. */ + +/* Generate a vertex shader that simply transforms vertex and texture coordinates, + while leaving colors intact. Nothing fancy (like lights) + + If implementing lights make a copy first, so it is easy to switch between the two versions */ +static void r300GenerateSimpleVertexShader(r300ContextPtr r300) +{ + int i; + GLuint o_reg = 0; + + /* Allocate parameters */ + r300->state.vap_param.transform_offset=0x0; /* transform matrix */ + r300->state.vertex_shader.param_offset=0x0; + r300->state.vertex_shader.param_count=0x4; /* 4 vector values - 4x4 matrix */ + + r300->state.vertex_shader.program_start=0x0; + r300->state.vertex_shader.unknown_ptr1=0x4; /* magic value ? */ + r300->state.vertex_shader.program_end=0x0; + + r300->state.vertex_shader.unknown_ptr2=0x0; /* magic value */ + r300->state.vertex_shader.unknown_ptr3=0x4; /* magic value */ + + /* Initialize matrix and vector parameters.. these should really be restructured */ + /* TODO: fix vertex_shader structure */ + r300->state.vertex_shader.matrix[0].length=16; + r300->state.vertex_shader.matrix[1].length=0; + r300->state.vertex_shader.matrix[2].length=0; + r300->state.vertex_shader.vector[0].length=0; + r300->state.vertex_shader.vector[1].length=0; + r300->state.vertex_shader.unknown1.length=0; + r300->state.vertex_shader.unknown2.length=0; + +#define WRITE_OP(oper,source1,source2,source3) {\ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].op=(oper); \ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src1=(source1); \ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src2=(source2); \ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src3=(source3); \ + r300->state.vertex_shader.program_end++; \ + } + + /* Multiply vertex coordinates with transform matrix */ + + WRITE_OP( + EASY_VSF_OP(MUL, 0, ALL, TMP), + VSF_PARAM(3), + VSF_ATTR_W(0), + EASY_VSF_SOURCE(0, W, W, W, W, NONE, NONE) + ) + + WRITE_OP( + EASY_VSF_OP(MUL, 1, ALL, RESULT), + VSF_REG(1), + VSF_ATTR_UNITY(1), + VSF_UNITY(1) + ) + + WRITE_OP( + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(2), + VSF_ATTR_Z(0), + VSF_TMP(0) + ) + + WRITE_OP( + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(1), + VSF_ATTR_Y(0), + VSF_TMP(0) + ) + + WRITE_OP( + EASY_VSF_OP(MAD, 0, ALL, RESULT), + VSF_PARAM(0), + VSF_ATTR_X(0), + VSF_TMP(0) + ) + o_reg += 2; + + if (r300->state.render_inputs & _TNL_BIT_COLOR1) { + WRITE_OP( + EASY_VSF_OP(MUL, o_reg++, ALL, RESULT), + VSF_REG(r300->state.vap_reg.i_color[1]), + VSF_ATTR_UNITY(r300->state.vap_reg.i_color[1]), + VSF_UNITY(r300->state.vap_reg.i_color[1]) + ) + } + + /* Pass through texture coordinates, if any */ + for(i=0;i < r300->radeon.glCtx->Const.MaxTextureUnits;i++) + if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)){ + // fprintf(stderr, "i_tex[%d]=%d\n", i, r300->state.vap_reg.i_tex[i]); + WRITE_OP( + EASY_VSF_OP(MUL, o_reg++ /* 2+i */, ALL, RESULT), + VSF_REG(r300->state.vap_reg.i_tex[i]), + VSF_ATTR_UNITY(r300->state.vap_reg.i_tex[i]), + VSF_UNITY(r300->state.vap_reg.i_tex[i]) + ) + } + + r300->state.vertex_shader.program_end--; /* r300 wants program length to be one more - no idea why */ + r300->state.vertex_shader.program.length=(r300->state.vertex_shader.program_end+1)*4; + + r300->state.vertex_shader.unknown_ptr1=r300->state.vertex_shader.program_end; /* magic value ? */ + r300->state.vertex_shader.unknown_ptr2=r300->state.vertex_shader.program_end; /* magic value ? */ + r300->state.vertex_shader.unknown_ptr3=r300->state.vertex_shader.program_end; /* magic value ? */ + +} + + +void r300SetupVertexShader(r300ContextPtr rmesa) +{ + GLcontext* ctx = rmesa->radeon.glCtx; + struct r300_vertex_shader_fragment unk4={ + length: 4, + body: { f: { + /*0.0*/(rand()%100)/10.0, + /*0.0*/(rand()%100)/10.0, + /*1.0*/(rand()%100)/10.0, + /*0.0*/(rand()%100)/10.0 + } } + }; + LOCAL_VARS + + /* Reset state, in case we don't use something */ + ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0; + ((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0; + ((drm_r300_cmd_header_t*)rmesa->hw.vps.cmd)->vpu.count = 0; + + /* Not sure why this doesnt work... + 0x400 area might have something to do with pixel shaders as it appears right after pfs programming. + 0x406 is set to { 0.0, 0.0, 1.0, 0.0 } most of the time but should change with smooth points and in other rare cases. */ + //setup_vertex_shader_fragment(rmesa, 0x406, &unk4); + if(hw_tcl_on && ((struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx))->translated){ + r300SetupVertexProgram(rmesa); + return ; + } + +/* This needs to be replaced by vertex shader generation code */ + + +#if 0 + /* textures enabled ? */ + if(rmesa->state.texture.tc_count>0){ + rmesa->state.vertex_shader=SINGLE_TEXTURE_VERTEX_SHADER; + } else { + rmesa->state.vertex_shader=FLAT_COLOR_VERTEX_SHADER; + } +#endif + + r300GenerateSimpleVertexShader(rmesa); + + rmesa->state.vertex_shader.matrix[0].length=16; + memcpy(rmesa->state.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->state.vertex_shader.program)); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(rmesa->state.vertex_shader.matrix[0])); +#if 0 + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX1, &(rmesa->state.vertex_shader.matrix[0])); + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX2, &(rmesa->state.vertex_shader.matrix[0])); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_VECTOR0, &(rmesa->state.vertex_shader.vector[0])); + setup_vertex_shader_fragment(rmesa, VSF_DEST_VECTOR1, &(rmesa->state.vertex_shader.vector[1])); +#endif + +#if 0 + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1)); + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2)); +#endif + + R300_STATECHANGE(rmesa, pvs); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(rmesa->state.vertex_shader.program_start << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) + | (rmesa->state.vertex_shader.unknown_ptr1 << R300_PVS_CNTL_1_POS_END_SHIFT) + | (rmesa->state.vertex_shader.program_end << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(rmesa->state.vertex_shader.param_offset << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT) + | (rmesa->state.vertex_shader.param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(rmesa->state.vertex_shader.unknown_ptr2 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) + | (rmesa->state.vertex_shader.unknown_ptr3 << 0); + + /* This is done for vertex shader fragments, but also needs to be done for vap_pvs, + so I leave it as a reminder */ +#if 0 + reg_start(R300_VAP_PVS_WAITIDLE,0); + e32(0x00000000); +#endif +} + +void r300SetupVertexProgram(r300ContextPtr rmesa) +{ + GLcontext* ctx = rmesa->radeon.glCtx; + int inst_count; + int param_count; + LOCAL_VARS + struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); + + + /* Reset state, in case we don't use something */ + ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0; + ((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0; + ((drm_r300_cmd_header_t*)rmesa->hw.vps.cmd)->vpu.count = 0; + + r300VertexProgUpdateParams(ctx, prog); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(prog->program)); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(prog->params)); + +#if 0 + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1)); + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2)); +#endif + + inst_count=prog->program.length/4 - 1; + param_count=prog->params.length/4; + + R300_STATECHANGE(rmesa, pvs); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) + | (inst_count/*pos_end*/ << R300_PVS_CNTL_1_POS_END_SHIFT) + | (inst_count << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(0 << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT) + | (param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(0/*rmesa->state.vertex_shader.unknown_ptr2*/ << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) + | (inst_count /*rmesa->state.vertex_shader.unknown_ptr3*/ << 0); + + /* This is done for vertex shader fragments, but also needs to be done for vap_pvs, + so I leave it as a reminder */ +#if 0 + reg_start(R300_VAP_PVS_WAITIDLE,0); + e32(0x00000000); +#endif +} + +/* This is probably wrong for some values, I need to test this + * some more. Range checking would be a good idea also.. + * + * But it works for most things. I'll fix it later if someone + * else with a better clue doesn't + */ +static unsigned int r300PackFloat24(float f) +{ + float mantissa; + int exponent; + unsigned int float24 = 0; + + if (f == 0.0) return 0; + + mantissa = frexpf(f, &exponent); + + /* Handle -ve */ + if (mantissa < 0) { + float24 |= (1<<23); + mantissa = mantissa * -1.0; + } + /* Handle exponent, bias of 63 */ + exponent += 62; + float24 |= (exponent << 16); + /* Kill 7 LSB of mantissa */ + float24 |= (r300PackFloat32(mantissa) & 0x7FFFFF) >> 7; + + return float24; +} + +#if USE_ARB_F_P == 1 +void r300SetupPixelShader(r300ContextPtr rmesa) +{ + GLcontext *ctx = rmesa->radeon.glCtx; + struct r300_fragment_program *rp = + (struct r300_fragment_program *)ctx->FragmentProgram._Current; + int i,k; + + if (!rp) /* should only happenen once, just after context is created */ + return; + + translate_fragment_shader(rp); + if (!rp->translated) { + fprintf(stderr, "%s: No valid fragment shader, exiting\n", __func__); + exit(-1); + } + + R300_STATECHANGE(rmesa, fpt); + for(i=0;i<rp->tex.length;i++) + rmesa->hw.fpt.cmd[R300_FPT_INSTR_0+i]=rp->tex.inst[i]; + rmesa->hw.fpt.cmd[R300_FPT_CMD_0]=cmdpacket0(R300_PFS_TEXI_0, rp->tex.length); + +#define OUTPUT_FIELD(st, reg, field) \ + R300_STATECHANGE(rmesa, st); \ + for(i=0;i<=rp->alu_end;i++) \ + rmesa->hw.st.cmd[R300_FPI_INSTR_0+i]=rp->alu.inst[i].field;\ + rmesa->hw.st.cmd[R300_FPI_CMD_0]=cmdpacket0(reg, rp->alu_end+1); + + OUTPUT_FIELD(fpi[0], R300_PFS_INSTR0_0, inst0); + OUTPUT_FIELD(fpi[1], R300_PFS_INSTR1_0, inst1); + OUTPUT_FIELD(fpi[2], R300_PFS_INSTR2_0, inst2); + OUTPUT_FIELD(fpi[3], R300_PFS_INSTR3_0, inst3); +#undef OUTPUT_FIELD + + R300_STATECHANGE(rmesa, fp); + /* I just want to say, the way these nodes are stored.. weird.. */ + for (i=0,k=(4-(rp->cur_node+1));i<4;i++,k++) { + if (i<(rp->cur_node+1)) { + rmesa->hw.fp.cmd[R300_FP_NODE0+k]= + (rp->node[i].alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT) + | (rp->node[i].alu_end << R300_PFS_NODE_ALU_END_SHIFT) + | (rp->node[i].tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT) + | (rp->node[i].tex_end << R300_PFS_NODE_TEX_END_SHIFT) + | ( (k==3) ? R300_PFS_NODE_LAST_NODE : 0); + } else { + rmesa->hw.fp.cmd[R300_FP_NODE0+(3-i)] = 0; + } + } + + /* PFS_CNTL_0 */ + rmesa->hw.fp.cmd[R300_FP_CNTL0]= + rp->cur_node + | (rp->first_node_has_tex<<3); + /* PFS_CNTL_1 */ + rmesa->hw.fp.cmd[R300_FP_CNTL1]=rp->max_temp_idx; + /* PFS_CNTL_2 */ + rmesa->hw.fp.cmd[R300_FP_CNTL2]= + (rp->alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT) + | (rp->alu_end << R300_PFS_CNTL_ALU_END_SHIFT) + | (rp->tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT) + | (rp->tex_end << R300_PFS_CNTL_TEX_END_SHIFT); + + R300_STATECHANGE(rmesa, fpp); + for(i=0;i<rp->const_nr;i++){ + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+0]=r300PackFloat24(rp->constant[i][0]); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+1]=r300PackFloat24(rp->constant[i][1]); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+2]=r300PackFloat24(rp->constant[i][2]); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+3]=r300PackFloat24(rp->constant[i][3]); + } + rmesa->hw.fpp.cmd[R300_FPP_CMD_0]=cmdpacket0(R300_PFS_PARAM_0_X, rp->const_nr*4); +} +#else +/* just a skeleton for now.. */ +void r300GenerateTexturePixelShader(r300ContextPtr r300) +{ + int i, mtu; + mtu = r300->radeon.glCtx->Const.MaxTextureUnits; + GLenum envMode; + GLuint OutputsWritten = CURRENT_VERTEX_SHADER(r300->radeon.glCtx)->OutputsWritten; + + int tex_inst=0, alu_inst=0; + + for(i=0;i<mtu;i++){ + /* No need to proliferate {} */ + if(!TMU_ENABLED(r300->radeon.glCtx, i))continue; + + envMode = r300->radeon.glCtx->Texture.Unit[i].EnvMode; + //fprintf(stderr, "envMode=%s\n", _mesa_lookup_enum_by_nr(envMode)); + + /* Fetch textured pixel */ + + r300->state.pixel_shader.program.tex.inst[tex_inst]=0x00018000; + tex_inst++; + + switch(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeRGB){ + case GL_REPLACE: + WARN_ONCE("ModeA==GL_REPLACE is possibly broken.\n"); + r300->state.pixel_shader.program.alu.inst[alu_inst].inst0= + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst1= + EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL); + break; + case GL_MODULATE: + WARN_ONCE("ModeRGB==GL_MODULATE is possibly broken.\n"); + r300->state.pixel_shader.program.alu.inst[alu_inst].inst0= + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, SRC1C_XYZ, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst1= + EASY_PFS_INSTR1(0, 0, 1, 0 | PFS_FLAG_CONST, NONE, ALL); + + break; + default: + WARN_ONCE("ModeRGB=%s is not implemented yet !\n", + _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeRGB)); + /* PFS_NOP */ + r300->state.pixel_shader.program.alu.inst[alu_inst].inst0= + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst1= + EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL); + } + switch(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeA){ + case GL_REPLACE: + WARN_ONCE("ModeA==GL_REPLACE is possibly broken.\n"); + r300->state.pixel_shader.program.alu.inst[alu_inst].inst2= + EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst3= + EASY_PFS_INSTR3(0, 0, 0| PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT); + +#if 0 + fprintf(stderr, "numArgsA=%d sourceA[0]=%s op=%d\n", + r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->_NumArgsA, + _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->SourceA[0]), + r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->OperandA[0]-GL_SRC_ALPHA); +#endif + break; + case GL_MODULATE: + WARN_ONCE("ModeA==GL_MODULATE is possibly broken.\n"); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst2= + EASY_PFS_INSTR2(MAD, SRC0A, SRC1A, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst3= + EASY_PFS_INSTR3(0, 0, 1, 0 | PFS_FLAG_CONST, OUTPUT); + + break; + default: + WARN_ONCE("ModeA=%s is not implemented yet !\n", + _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeA)); + /* PFS_NOP */ + r300->state.pixel_shader.program.alu.inst[alu_inst].inst2= + EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst3= + EASY_PFS_INSTR3(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT); + + } + + alu_inst++; + } + + r300->state.pixel_shader.program.tex.length=tex_inst; + r300->state.pixel_shader.program.tex_offset=0; + r300->state.pixel_shader.program.tex_end=tex_inst-1; + +#if 0 + /* saturate last instruction, like i915 driver does */ + r300->state.pixel_shader.program.alu.inst[alu_inst-1].inst0|=R300_FPI0_OUTC_SAT; + r300->state.pixel_shader.program.alu.inst[alu_inst-1].inst2|=R300_FPI2_OUTA_SAT; +#endif + + r300->state.pixel_shader.program.alu.length=alu_inst; + r300->state.pixel_shader.program.alu_offset=0; + r300->state.pixel_shader.program.alu_end=alu_inst-1; +} + +void r300SetupPixelShader(r300ContextPtr rmesa) +{ +int i,k; + + /* This needs to be replaced by pixel shader generation code */ + + /* textures enabled ? */ + if(rmesa->state.texture.tc_count>0){ +#if 1 + r300GenerateTextureFragmentShader(rmesa); +#else + rmesa->state.pixel_shader=SINGLE_TEXTURE_PIXEL_SHADER; + r300GenerateTexturePixelShader(rmesa); +#endif + } else { + rmesa->state.pixel_shader=FLAT_COLOR_PIXEL_SHADER; + } + + R300_STATECHANGE(rmesa, fpt); + for(i=0;i<rmesa->state.pixel_shader.program.tex.length;i++) + rmesa->hw.fpt.cmd[R300_FPT_INSTR_0+i]=rmesa->state.pixel_shader.program.tex.inst[i]; + rmesa->hw.fpt.cmd[R300_FPT_CMD_0]=cmdpacket0(R300_PFS_TEXI_0, rmesa->state.pixel_shader.program.tex.length); + +#define OUTPUT_FIELD(st, reg, field) \ + R300_STATECHANGE(rmesa, st); \ + for(i=0;i<rmesa->state.pixel_shader.program.alu.length;i++) \ + rmesa->hw.st.cmd[R300_FPI_INSTR_0+i]=rmesa->state.pixel_shader.program.alu.inst[i].field;\ + rmesa->hw.st.cmd[R300_FPI_CMD_0]=cmdpacket0(reg, rmesa->state.pixel_shader.program.alu.length); + + OUTPUT_FIELD(fpi[0], R300_PFS_INSTR0_0, inst0); + OUTPUT_FIELD(fpi[1], R300_PFS_INSTR1_0, inst1); + OUTPUT_FIELD(fpi[2], R300_PFS_INSTR2_0, inst2); + OUTPUT_FIELD(fpi[3], R300_PFS_INSTR3_0, inst3); +#undef OUTPUT_FIELD + + R300_STATECHANGE(rmesa, fp); + for(i=0;i<4;i++){ + rmesa->hw.fp.cmd[R300_FP_NODE0+i]= + (rmesa->state.pixel_shader.program.node[i].alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.node[i].alu_end << R300_PFS_NODE_ALU_END_SHIFT) + | (rmesa->state.pixel_shader.program.node[i].tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.node[i].tex_end << R300_PFS_NODE_TEX_END_SHIFT) + | ( (i==3) ? R300_PFS_NODE_LAST_NODE : 0); + } + + /* PFS_CNTL_0 */ + rmesa->hw.fp.cmd[R300_FP_CNTL0]= + (rmesa->state.pixel_shader.program.active_nodes-1) + | (rmesa->state.pixel_shader.program.first_node_has_tex<<3); + /* PFS_CNTL_1 */ + rmesa->hw.fp.cmd[R300_FP_CNTL1]=rmesa->state.pixel_shader.program.temp_register_count; + /* PFS_CNTL_2 */ + rmesa->hw.fp.cmd[R300_FP_CNTL2]= + (rmesa->state.pixel_shader.program.alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.alu_end << R300_PFS_CNTL_ALU_END_SHIFT) + | (rmesa->state.pixel_shader.program.tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.tex_end << R300_PFS_CNTL_TEX_END_SHIFT); + + R300_STATECHANGE(rmesa, fpp); + for(i=0;i<rmesa->state.pixel_shader.param_length;i++){ + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+0]=r300PackFloat32(rmesa->state.pixel_shader.param[i].x); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+1]=r300PackFloat32(rmesa->state.pixel_shader.param[i].y); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+2]=r300PackFloat32(rmesa->state.pixel_shader.param[i].z); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+3]=r300PackFloat32(rmesa->state.pixel_shader.param[i].w); + } + rmesa->hw.fpp.cmd[R300_FPP_CMD_0]=cmdpacket0(R300_PFS_PARAM_0_X, rmesa->state.pixel_shader.param_length); + +} +#endif + +/** + * Called by Mesa after an internal state update. + */ +static void r300InvalidateState(GLcontext * ctx, GLuint new_state) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + _swrast_InvalidateState(ctx, new_state); + _swsetup_InvalidateState(ctx, new_state); + _ac_InvalidateState(ctx, new_state); + _tnl_InvalidateState(ctx, new_state); + _ae_invalidate_state(ctx, new_state); + + /* Go inefficiency! */ + r300ResetHwState(r300); +} + +/* Checks that r300ResetHwState actually modifies all states. + Should probably be burried in somewhere else as this file is getting longish. */ +static void verify_r300ResetHwState(r300ContextPtr r300, int stage) +{ + struct r300_state_atom* atom; + int i; + drm_r300_cmd_header_t cmd; + + if(stage){ /* mess around with states */ + unsigned long fp1, cb1; + + fp1=r300->hw.fp.cmd[R300_FP_CMD_1]; /* some special cases... */ + cb1=r300->hw.cb.cmd[R300_CB_CMD_1]; + + fprintf(stderr, "verify begin:\n"); + + foreach(atom, &r300->hw.atomlist) { + for(i=1; i < (*atom->check)(r300, atom); i++) + atom->cmd[i]=0xdeadbeef; + } + r300->hw.fp.cmd[R300_FP_CMD_1]=fp1; + r300->hw.cb.cmd[R300_CB_CMD_1]=cb1; + + foreach(atom, &r300->hw.atomlist) { + cmd.u=atom->cmd[0]; + switch(cmd.header.cmd_type){ + case R300_CMD_PACKET0: + case R300_CMD_VPU: + case R300_CMD_PACKET3: + case R300_CMD_END3D: + case R300_CMD_CP_DELAY: + case R300_CMD_DMA_DISCARD: + break; + default: fprintf(stderr, "unknown cmd_type %d in atom %s\n", + cmd.header.cmd_type, atom->name); + } + + } + } else { /* check that they were set */ + foreach(atom, &r300->hw.atomlist) { + for(i=1; i < (*atom->check)(r300, atom); i++) + if(atom->cmd[i]==0xdeadbeef) + fprintf(stderr, "atom %s is untouched\n", atom->name); + } + } +} + +/** + * Completely recalculates hardware state based on the Mesa state. + */ +void r300ResetHwState(r300ContextPtr r300) +{ + GLcontext* ctx = r300->radeon.glCtx; + int i; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + + //verify_r300ResetHwState(r300, 1); + + /* This is a place to initialize registers which + have bitfields accessed by different functions + and not all bits are used */ +#if 0 + /* initialize similiar to r200 */ + r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0; + r300->hw.zs.cmd[R300_ZS_CNTL_1] = + (R300_ZS_ALWAYS << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) | + (R300_ZS_ALWAYS << R300_RB3D_ZS1_BACK_FUNC_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT); + r300->hw.zs.cmd[R300_ZS_CNTL_2] = 0x00ffff00; +#endif + + /* go and compute register values from GL state */ + + r300UpdateWindow(ctx); + + r300ColorMask(ctx, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP]); + + r300Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test); + r300DepthMask(ctx, ctx->Depth.Mask); + r300DepthFunc(ctx, ctx->Depth.Func); + + /* stencil */ + r300Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); + r300StencilMask(ctx, ctx->Stencil.WriteMask[0]); + r300StencilFunc(ctx, ctx->Stencil.Function[0], ctx->Stencil.Ref[0], ctx->Stencil.ValueMask[0]); + r300StencilOp(ctx, ctx->Stencil.FailFunc[0], ctx->Stencil.ZFailFunc[0], ctx->Stencil.ZPassFunc[0]); + + r300UpdateCulling(ctx); + + r300UpdateTextureState(ctx); + +// r300_setup_routing(ctx, GL_TRUE); + if(hw_tcl_on == GL_FALSE){ + r300EmitArrays(ctx, GL_TRUE); /* Just do the routing */ + r300_setup_textures(ctx); + r300_setup_rs_unit(ctx); + + r300SetupVertexShader(r300); + r300SetupPixelShader(r300); + } + + r300_set_blend_state(ctx); + + r300AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef); + r300Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled); + + /* Initialize magic registers + TODO : learn what they really do, or get rid of + those we don't have to touch */ + r300->hw.unk2080.cmd[1] = 0x0030045A; /* Dangerous */ + + r300->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA + | R300_VPORT_X_OFFSET_ENA + | R300_VPORT_Y_SCALE_ENA + | R300_VPORT_Y_OFFSET_ENA + | R300_VPORT_Z_SCALE_ENA + | R300_VPORT_Z_OFFSET_ENA + | R300_VTX_W0_FMT; + r300->hw.vte.cmd[2] = 0x00000008; + + r300->hw.unk2134.cmd[1] = 0x00FFFFFF; + r300->hw.unk2134.cmd[2] = 0x00000000; +#ifdef MESA_BIG_ENDIAN + r300->hw.unk2140.cmd[1] = 0x00000002; +#else + r300->hw.unk2140.cmd[1] = 0x00000000; +#endif + +#if 0 /* Done in setup routing */ + ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = 1; + r300->hw.vir[0].cmd[1] = 0x21030003; + + ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->packet0.count = 1; + r300->hw.vir[1].cmd[1] = 0xF688F688; + + r300->hw.vic.cmd[R300_VIR_CNTL_0] = 0x00000001; + r300->hw.vic.cmd[R300_VIR_CNTL_1] = 0x00000405; +#endif + + r300->hw.unk21DC.cmd[1] = 0xAAAAAAAA; + + r300->hw.unk221C.cmd[1] = R300_221C_NORMAL; + + r300->hw.unk2220.cmd[1] = r300PackFloat32(1.0); + r300->hw.unk2220.cmd[2] = r300PackFloat32(1.0); + r300->hw.unk2220.cmd[3] = r300PackFloat32(1.0); + r300->hw.unk2220.cmd[4] = r300PackFloat32(1.0); + + if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R300) + r300->hw.unk2288.cmd[1] = R300_2288_R300; + else + r300->hw.unk2288.cmd[1] = R300_2288_RV350; + +#if 0 + r300->hw.vof.cmd[R300_VOF_CNTL_0] = R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT + | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; /* no textures */ + + + r300->hw.pvs.cmd[R300_PVS_CNTL_1] = 0; + r300->hw.pvs.cmd[R300_PVS_CNTL_2] = 0; + r300->hw.pvs.cmd[R300_PVS_CNTL_3] = 0; +#endif + + r300->hw.gb_enable.cmd[1] = R300_GB_POINT_STUFF_ENABLE + | R300_GB_LINE_STUFF_ENABLE + | R300_GB_TRIANGLE_STUFF_ENABLE /*| R300_GB_UNK30*/; + + r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_0] = 0x66666666; + r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_1] = 0x06666666; + if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R300) + r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE + | R300_GB_TILE_PIPE_COUNT_R300 + | R300_GB_TILE_SIZE_16; + else if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R420) + r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE + | R300_GB_TILE_PIPE_COUNT_R420 + | R300_GB_TILE_SIZE_16; + else + r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE + | R300_GB_TILE_PIPE_COUNT_RV300 + | R300_GB_TILE_SIZE_16; + r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = 0x00000000; + r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = 0x00000000; /* No antialiasing */ + + //r300->hw.txe.cmd[R300_TXE_ENABLE] = 0; + + r300->hw.unk4200.cmd[1] = r300PackFloat32(0.0); + r300->hw.unk4200.cmd[2] = r300PackFloat32(0.0); + r300->hw.unk4200.cmd[3] = r300PackFloat32(1.0); + r300->hw.unk4200.cmd[4] = r300PackFloat32(1.0); + + r300->hw.unk4214.cmd[1] = 0x00050005; + + r300PointSize(ctx, 0.0); +#if 0 + r300->hw.ps.cmd[R300_PS_POINTSIZE] = (6 << R300_POINTSIZE_X_SHIFT) | + (6 << R300_POINTSIZE_Y_SHIFT); +#endif + + r300->hw.unk4230.cmd[1] = 0x01800000;//18000006; + r300->hw.unk4230.cmd[2] = 0x00020006; + r300->hw.unk4230.cmd[3] = r300PackFloat32(1.0 / 192.0); + + r300LineWidth(ctx, 0.0); + + r300->hw.unk4260.cmd[1] = 0; + r300->hw.unk4260.cmd[2] = r300PackFloat32(0.0); + r300->hw.unk4260.cmd[3] = r300PackFloat32(1.0); + + r300->hw.unk4274.cmd[1] = 0x00000002; + r300ShadeModel(ctx, ctx->Light.ShadeModel); + r300->hw.unk4274.cmd[3] = 0x00000000; + r300->hw.unk4274.cmd[4] = 0x00000000; + + r300PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode); + r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode); + r300->hw.unk4288.cmd[2] = 0x00000001; + r300->hw.unk4288.cmd[3] = 0x00000000; + r300->hw.unk4288.cmd[4] = 0x00000000; + r300->hw.unk4288.cmd[5] = 0x00000000; + + r300->hw.unk42A0.cmd[1] = 0x00000000; + + r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits); + r300Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill); + + r300->hw.unk42C0.cmd[1] = 0x4B7FFFFF; + r300->hw.unk42C0.cmd[2] = 0x00000000; + + + r300->hw.unk43A4.cmd[1] = 0x0000001C; + r300->hw.unk43A4.cmd[2] = 0x2DA49525; + + r300->hw.unk43E8.cmd[1] = 0x00FFFFFF; + +#if 0 + r300->hw.fp.cmd[R300_FP_CNTL0] = 0; + r300->hw.fp.cmd[R300_FP_CNTL1] = 0; + r300->hw.fp.cmd[R300_FP_CNTL2] = 0; + r300->hw.fp.cmd[R300_FP_NODE0] = 0; + r300->hw.fp.cmd[R300_FP_NODE1] = 0; + r300->hw.fp.cmd[R300_FP_NODE2] = 0; + r300->hw.fp.cmd[R300_FP_NODE3] = 0; +#endif + + r300->hw.unk46A4.cmd[1] = 0x00001B01; + r300->hw.unk46A4.cmd[2] = 0x00001B0F; + r300->hw.unk46A4.cmd[3] = 0x00001B0F; + r300->hw.unk46A4.cmd[4] = 0x00001B0F; + r300->hw.unk46A4.cmd[5] = 0x00000001; + +#if 0 + for(i = 1; i <= 64; ++i) { + /* create NOP instructions */ + r300->hw.fpi[0].cmd[i] = FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)); + r300->hw.fpi[1].cmd[i] = FP_SELC(0,XYZ,NO,FP_TMP(0),0,0); + r300->hw.fpi[2].cmd[i] = FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)); + r300->hw.fpi[3].cmd[i] = FP_SELA(0,W,NO,FP_TMP(0),0,0); + } +#endif + + r300->hw.unk4BC0.cmd[1] = 0; + + r300->hw.unk4BC8.cmd[1] = 0; + r300->hw.unk4BC8.cmd[2] = 0; + r300->hw.unk4BC8.cmd[3] = 0; + + + r300->hw.at.cmd[R300_AT_UNKNOWN] = 0; + r300->hw.unk4BD8.cmd[1] = 0; + + r300->hw.unk4E00.cmd[1] = 0; + +#if 0 + r300->hw.bld.cmd[R300_BLD_CBLEND] = 0; + r300->hw.bld.cmd[R300_BLD_ABLEND] = 0; +#endif + + r300BlendColor(ctx, ctx->Color.BlendColor); + r300->hw.unk4E10.cmd[2] = 0; + r300->hw.unk4E10.cmd[3] = 0; + + /* Again, r300ClearBuffer uses this */ + r300->hw.cb.cmd[R300_CB_OFFSET] = r300->radeon.state.color.drawOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.state.color.drawPitch; + + if (r300->radeon.radeonScreen->cpp == 4) + r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888; + else + r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565; + + if (r300->radeon.sarea->tiling_enabled) + r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE; + + r300->hw.unk4E50.cmd[1] = 0; + r300->hw.unk4E50.cmd[2] = 0; + r300->hw.unk4E50.cmd[3] = 0; + r300->hw.unk4E50.cmd[4] = 0; + r300->hw.unk4E50.cmd[5] = 0; + r300->hw.unk4E50.cmd[6] = 0; + r300->hw.unk4E50.cmd[7] = 0; + r300->hw.unk4E50.cmd[8] = 0; + r300->hw.unk4E50.cmd[9] = 0; + + r300->hw.unk4E88.cmd[1] = 0; + + r300->hw.unk4EA0.cmd[1] = 0x00000000; + r300->hw.unk4EA0.cmd[2] = 0xffffffff; + + switch (ctx->Visual.depthBits) { + case 16: + r300->hw.unk4F10.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z; + break; + case 24: + r300->hw.unk4F10.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z; + break; + default: + fprintf(stderr, "Error: Unsupported depth %d... exiting\n", + ctx->Visual.depthBits); + exit(-1); + + } + r300->hw.unk4F10.cmd[3] = 0x00000003; + r300->hw.unk4F10.cmd[4] = 0x00000000; + + r300->hw.zb.cmd[R300_ZB_OFFSET] = + r300->radeon.radeonScreen->depthOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.zb.cmd[R300_ZB_PITCH] = r300->radeon.radeonScreen->depthPitch; + + if (r300->radeon.sarea->tiling_enabled) { + /* Turn off when clearing buffers ? */ + r300->hw.zb.cmd[R300_ZB_PITCH] |= R300_DEPTH_TILE_ENABLE; + + if (ctx->Visual.depthBits == 24) + r300->hw.zb.cmd[R300_ZB_PITCH] |= R300_DEPTH_MICROTILE_ENABLE; + } + + r300->hw.unk4F28.cmd[1] = 0; + + r300->hw.unk4F30.cmd[1] = 0; + r300->hw.unk4F30.cmd[2] = 0; + + r300->hw.unk4F44.cmd[1] = 0; + + r300->hw.unk4F54.cmd[1] = 0; + +#if 0 + ((drm_r300_cmd_header_t*)r300->hw.vpi.cmd)->vpu.count = 0; + for(i = 1; i < R300_VPI_CMDSIZE; i += 4) { + /* MOV t0, t0 */ + r300->hw.vpi.cmd[i+0] = VP_OUT(ADD,TMP,0,XYZW); + r300->hw.vpi.cmd[i+1] = VP_IN(TMP,0); + r300->hw.vpi.cmd[i+2] = VP_ZERO(); + r300->hw.vpi.cmd[i+3] = VP_ZERO(); + } + + ((drm_r300_cmd_header_t*)r300->hw.vpp.cmd)->vpu.count = 0; + for(i = 1; i < R300_VPP_CMDSIZE; ++i) + r300->hw.vpp.cmd[i] = 0; +#endif + + r300->hw.vps.cmd[R300_VPS_ZERO_0] = 0; + r300->hw.vps.cmd[R300_VPS_ZERO_1] = 0; + r300->hw.vps.cmd[R300_VPS_POINTSIZE] = r300PackFloat32(1.0); + r300->hw.vps.cmd[R300_VPS_ZERO_3] = 0; + +//END: TODO + //verify_r300ResetHwState(r300, 0); + r300->hw.all_dirty = GL_TRUE; +} + + + +/** + * Calculate initial hardware state and register state functions. + * Assumes that the command buffer and state atoms have been + * initialized already. + */ +void r300InitState(r300ContextPtr r300) +{ + GLcontext *ctx = r300->radeon.glCtx; + GLuint depth_fmt; + + radeonInitState(&r300->radeon); + + switch (ctx->Visual.depthBits) { + case 16: + r300->state.depth.scale = 1.0 / (GLfloat) 0xffff; + depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z; + r300->state.stencil.clear = 0x00000000; + break; + case 24: + r300->state.depth.scale = 1.0 / (GLfloat) 0xffffff; + depth_fmt = R200_DEPTH_FORMAT_24BIT_INT_Z; + r300->state.stencil.clear = 0x00ff0000; + break; + default: + fprintf(stderr, "Error: Unsupported depth %d... exiting\n", + ctx->Visual.depthBits); + exit(-1); + } + + /* Only have hw stencil when depth buffer is 24 bits deep */ + r300->state.stencil.hw_stencil = (ctx->Visual.stencilBits > 0 && + ctx->Visual.depthBits == 24); + + memset(&(r300->state.texture), 0, sizeof(r300->state.texture)); + + r300ResetHwState(r300); +} + +static void r300RenderMode( GLcontext *ctx, GLenum mode ) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + WARN_ONCE("TODO: fallback properly when rendering mode is not GL_RENDER\n" + "\tThe way things are now neither selection nor feedback modes work\n") +// FALLBACK( rmesa, R300_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); +} + +/** + * Initialize driver's state callback functions + */ +void r300InitStateFuncs(struct dd_function_table* functions) +{ + radeonInitStateFuncs(functions); + + functions->UpdateState = r300InvalidateState; + functions->AlphaFunc = r300AlphaFunc; + functions->BlendColor = r300BlendColor; + functions->BlendEquationSeparate = r300BlendEquationSeparate; + functions->BlendFuncSeparate = r300BlendFuncSeparate; + functions->Enable = r300Enable; + functions->ColorMask = r300ColorMask; + functions->DepthFunc = r300DepthFunc; + functions->DepthMask = r300DepthMask; + functions->CullFace = r300CullFace; + functions->FrontFace = r300FrontFace; + functions->ShadeModel = r300ShadeModel; + + /* Stencil related */ + functions->ClearStencil = r300ClearStencil; + functions->StencilFunc = r300StencilFunc; + functions->StencilMask = r300StencilMask; + functions->StencilOp = r300StencilOp; + + /* Viewport related */ + functions->Viewport = r300Viewport; + functions->DepthRange = r300DepthRange; + functions->PointSize = r300PointSize; + functions->LineWidth = r300LineWidth; + + functions->PolygonOffset = r300PolygonOffset; + functions->PolygonMode = r300PolygonMode; + + functions->RenderMode = r300RenderMode; +} + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_state.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_state.h new file mode 100644 index 000000000..131834fa7 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_state.h @@ -0,0 +1,69 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __R300_STATE_H__ +#define __R300_STATE_H__ + +#include "r300_context.h" + +#define R300_STATECHANGE(r300, atom) \ + do { \ + r300->hw.atom.dirty = GL_TRUE; \ + r300->hw.is_dirty = GL_TRUE; \ + } while(0) + +/* Fire the buffered vertices no matter what. + TODO: This has not been implemented yet + */ +#define R300_FIREVERTICES( r300 ) \ +do { \ + \ + if ( (r300)->cmdbuf.count_used || (r300)->dma.flush ) { \ + r300Flush( (r300)->radeon.glCtx ); \ + } \ + \ +} while (0) + + +extern void r300ResetHwState(r300ContextPtr r300); + +extern void r300InitState(r300ContextPtr r300); +extern void r300InitStateFuncs(struct dd_function_table* functions); +extern void r300SetupVertexShader(r300ContextPtr rmesa); +extern void r300SetupPixelShader(r300ContextPtr rmesa); + +extern void r300_setup_textures(GLcontext *ctx); +extern void r300_setup_rs_unit(GLcontext *ctx); + +#endif /* __R300_STATE_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_tex.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_tex.c new file mode 100644 index 000000000..e6c8c1801 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_tex.c @@ -0,0 +1,1051 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_tex.c,v 1.2 2002/11/05 17:46:08 tsi Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. +*/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "imports.h" +#include "colormac.h" +#include "context.h" +#include "enums.h" +#include "image.h" +#include "simple_list.h" +#include "texformat.h" +#include "texstore.h" +#include "texmem.h" +#include "teximage.h" +#include "texobj.h" + +#include "r300_context.h" +#include "r300_state.h" +#include "r300_ioctl.h" +//#include "r300_swtcl.h" +#include "r300_tex.h" + +#include "xmlpool.h" + +/** + * Set the texture wrap modes. + * + * \param t Texture object whose wrap modes are to be set + * \param swrap Wrap mode for the \a s texture coordinate + * \param twrap Wrap mode for the \a t texture coordinate + */ + +static void r300SetTexWrap(r300TexObjPtr t, GLenum swrap, GLenum twrap, + GLenum rwrap) +{ + GLboolean is_clamp = GL_FALSE; + unsigned long hw_swrap=0, hw_twrap=0, hw_qwrap=0; + + t->filter &= + ~(R300_TX_WRAP_S_MASK | R300_TX_WRAP_T_MASK | R300_TX_WRAP_Q_MASK); + + switch (swrap) { + case GL_REPEAT: + hw_swrap |= R300_TX_REPEAT; + break; + case GL_CLAMP: + hw_swrap |= R300_TX_CLAMP; + is_clamp = GL_TRUE; + break; + case GL_CLAMP_TO_EDGE: + hw_swrap |= R300_TX_CLAMP_TO_EDGE; + break; + case GL_CLAMP_TO_BORDER: + hw_swrap |= R300_TX_CLAMP_TO_BORDER; + break; + case GL_MIRRORED_REPEAT: + hw_swrap |= R300_TX_REPEAT | R300_TX_MIRRORED; + break; + case GL_MIRROR_CLAMP_EXT: + hw_swrap |= R300_TX_CLAMP | R300_TX_MIRRORED; + is_clamp = GL_TRUE; + break; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + hw_swrap |= R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; + break; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + hw_swrap |= R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED; + break; + default: + _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__); + } + + switch (twrap) { + case GL_REPEAT: + hw_twrap |= R300_TX_REPEAT; + break; + case GL_CLAMP: + hw_twrap |= R300_TX_CLAMP; + is_clamp = GL_TRUE; + break; + case GL_CLAMP_TO_EDGE: + hw_twrap |= R300_TX_CLAMP_TO_EDGE; + break; + case GL_CLAMP_TO_BORDER: + hw_twrap |= R300_TX_CLAMP_TO_BORDER; + break; + case GL_MIRRORED_REPEAT: + hw_twrap |= R300_TX_REPEAT | R300_TX_MIRRORED; + break; + case GL_MIRROR_CLAMP_EXT: + hw_twrap |= R300_TX_CLAMP | R300_TX_MIRRORED; + is_clamp = GL_TRUE; + break; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + hw_twrap |= R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; + break; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + hw_twrap |= R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED; + break; + default: + _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__); + } + + switch (rwrap) { + case GL_REPEAT: + hw_qwrap |= R300_TX_REPEAT; + break; + case GL_CLAMP: + hw_qwrap |= R300_TX_CLAMP; + is_clamp = GL_TRUE; + break; + case GL_CLAMP_TO_EDGE: + hw_qwrap |= R300_TX_CLAMP_TO_EDGE; + break; + case GL_CLAMP_TO_BORDER: + hw_qwrap |= R300_TX_CLAMP_TO_BORDER; + break; + case GL_MIRRORED_REPEAT: + hw_qwrap |= R300_TX_REPEAT | R300_TX_MIRRORED; + break; + case GL_MIRROR_CLAMP_EXT: + hw_qwrap |= R300_TX_CLAMP | R300_TX_MIRRORED; + is_clamp = GL_TRUE; + break; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + hw_qwrap |= R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; + break; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + hw_qwrap |= R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED; + break; + default: + _mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__); + } + + t->filter |= hw_swrap << R300_TX_WRAP_S_SHIFT; + t->filter |= hw_twrap << R300_TX_WRAP_T_SHIFT; + t->filter |= hw_qwrap << R300_TX_WRAP_Q_SHIFT; + +#if 0 + t->format_x &= ~R200_CLAMP_Q_MASK; + t->border_fallback = (is_clamp && is_clamp_to_border); +#endif +} + +static void r300SetTexMaxAnisotropy(r300TexObjPtr t, GLfloat max) +{ + + t->filter &= ~R300_TX_MAX_ANISO_MASK; + + if (max <= 1.0) { + t->filter |= R300_TX_MAX_ANISO_1_TO_1; + } else if (max <= 2.0) { + t->filter |= R300_TX_MAX_ANISO_2_TO_1; + } else if (max <= 4.0) { + t->filter |= R300_TX_MAX_ANISO_4_TO_1; + } else if (max <= 8.0) { + t->filter |= R300_TX_MAX_ANISO_8_TO_1; + } else { + t->filter |= R300_TX_MAX_ANISO_16_TO_1; + } +} + +/** + * Set the texture magnification and minification modes. + * + * \param t Texture whose filter modes are to be set + * \param minf Texture minification mode + * \param magf Texture magnification mode + */ + +static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf) +{ + GLuint anisotropy = (t->filter & R300_TX_MAX_ANISO_MASK); + + t->filter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MAG_FILTER_MASK); +#if 0 + //t->format_x &= ~R200_VOLUME_FILTER_MASK; +#endif + + if (anisotropy == R300_TX_MAX_ANISO_1_TO_1) { + switch (minf) { + case GL_NEAREST: + t->filter |= R300_TX_MIN_FILTER_NEAREST; + break; + case GL_LINEAR: + t->filter |= R300_TX_MIN_FILTER_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + t->filter |= R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + t->filter |= R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + t->filter |= R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + t->filter |= R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR; + break; + } + } else { + switch (minf) { + case GL_NEAREST: + t->filter |= R300_TX_MIN_FILTER_ANISO_NEAREST; + break; + case GL_LINEAR: + t->filter |= R300_TX_MIN_FILTER_ANISO_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + t->filter |= + R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + t->filter |= + R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR; + break; + } + } + + /* Note we don't have 3D mipmaps so only use the mag filter setting + * to set the 3D texture filter mode. + */ + switch (magf) { + case GL_NEAREST: + t->filter |= R300_TX_MAG_FILTER_NEAREST; + /*t->format_x |= R200_VOLUME_FILTER_NEAREST;*/ + break; + case GL_LINEAR: + t->filter |= R300_TX_MAG_FILTER_LINEAR; + /*t->format_x |= R200_VOLUME_FILTER_LINEAR;*/ + break; + } +} + +static void r300SetTexBorderColor(r300TexObjPtr t, GLubyte c[4]) +{ + t->pp_border_color = r300PackColor(4, c[0], c[1], c[2], c[3]); +} + +/** + * Allocate space for and load the mesa images into the texture memory block. + * This will happen before drawing with a new texture, or drawing with a + * texture after it was swapped out or teximaged again. + */ + +static r300TexObjPtr r300AllocTexObj(struct gl_texture_object *texObj) +{ + r300TexObjPtr t; + + t = CALLOC_STRUCT(r300_tex_obj); + texObj->DriverData = t; + if (t != NULL) { + if (RADEON_DEBUG & DEBUG_TEXTURE) { + fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__, + (void *)texObj, (void *)t); + } + + /* Initialize non-image-dependent parts of the state: + */ + t->base.tObj = texObj; + t->border_fallback = GL_FALSE; + + make_empty_list(&t->base); + + r300SetTexWrap(t, texObj->WrapS, texObj->WrapT, texObj->WrapR); + r300SetTexMaxAnisotropy(t, texObj->MaxAnisotropy); + r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter); + r300SetTexBorderColor(t, texObj->_BorderChan); + } + + return t; +} + +static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx, + GLint + internalFormat, + GLenum format, + GLenum type) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + const GLboolean do32bpt = + (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32); + const GLboolean force16bpt = + (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16); + (void)format; + +#if 0 + fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n", + _mesa_lookup_enum_by_nr(internalFormat), internalFormat, + _mesa_lookup_enum_by_nr(type), + _mesa_lookup_enum_by_nr(format)); + fprintf(stderr, "do32bpt=%d force16bpt=%d\n", + do32bpt, force16bpt); +#endif + + switch (internalFormat) { + case 4: + case GL_RGBA: + case GL_COMPRESSED_RGBA: + switch (type) { + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return do32bpt ? _dri_texformat_argb8888 : + _dri_texformat_argb1555; + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return _dri_texformat_argb4444; + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return _dri_texformat_argb1555; + default: + return do32bpt ? _dri_texformat_rgba8888 : + _dri_texformat_argb4444; + } + + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB: + switch (type) { + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return _dri_texformat_argb4444; + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return _dri_texformat_argb1555; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return _dri_texformat_rgb565; + default: + return do32bpt ? _dri_texformat_rgba8888 : + _dri_texformat_rgb565; + } + + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return !force16bpt ? + _dri_texformat_rgba8888 : _dri_texformat_argb4444; + + case GL_RGBA4: + case GL_RGBA2: + return _dri_texformat_argb4444; + + case GL_RGB5_A1: + return _dri_texformat_argb1555; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return !force16bpt ? _dri_texformat_rgba8888 : + _dri_texformat_rgb565; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + return _dri_texformat_rgb565; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_COMPRESSED_ALPHA: + return _dri_texformat_a8; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE: + return _dri_texformat_l8; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA: + return _dri_texformat_al88; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY: + return _dri_texformat_i8; + + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_APPLE || + type == GL_UNSIGNED_BYTE) + return &_mesa_texformat_ycbcr; + else + return &_mesa_texformat_ycbcr_rev; + + default: + _mesa_problem(ctx, + "unexpected internalFormat 0x%x in r300ChooseTextureFormat", + (int)internalFormat); + return NULL; + } + + return NULL; /* never get here */ +} + +static GLboolean +r300ValidateClientStorage(GLcontext * ctx, GLenum target, + GLint internalFormat, + GLint srcWidth, GLint srcHeight, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + if (0) + fprintf(stderr, "intformat %s format %s type %s\n", + _mesa_lookup_enum_by_nr(internalFormat), + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type)); + + if (!ctx->Unpack.ClientStorage) + return 0; + + if (ctx->_ImageTransferState || + texImage->IsCompressed || texObj->GenerateMipmap) + return 0; + + /* This list is incomplete, may be different on ppc??? + */ + switch (internalFormat) { + case GL_RGBA: + if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) { + texImage->TexFormat = _dri_texformat_argb8888; + } else + return 0; + break; + + case GL_RGB: + if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) { + texImage->TexFormat = _dri_texformat_rgb565; + } else + return 0; + break; + + case GL_YCBCR_MESA: + if (format == GL_YCBCR_MESA && + type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) { + texImage->TexFormat = &_mesa_texformat_ycbcr_rev; + } else if (format == GL_YCBCR_MESA && + (type == GL_UNSIGNED_SHORT_8_8_APPLE || + type == GL_UNSIGNED_BYTE)) { + texImage->TexFormat = &_mesa_texformat_ycbcr; + } else + return 0; + break; + + default: + return 0; + } + + /* Could deal with these packing issues, but currently don't: + */ + if (packing->SkipPixels || + packing->SkipRows || packing->SwapBytes || packing->LsbFirst) { + return 0; + } + + { + GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, + format, type); + + if (0) + fprintf(stderr, "%s: srcRowStride %d/%x\n", + __FUNCTION__, srcRowStride, srcRowStride); + + /* Could check this later in upload, pitch restrictions could be + * relaxed, but would need to store the image pitch somewhere, + * as packing details might change before image is uploaded: + */ + if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride) + || (srcRowStride & 63)) + return 0; + + /* Have validated that _mesa_transfer_teximage would be a straight + * memcpy at this point. NOTE: future calls to TexSubImage will + * overwrite the client data. This is explicitly mentioned in the + * extension spec. + */ + texImage->Data = (void *)pixels; + texImage->IsClientData = GL_TRUE; + texImage->RowStride = + srcRowStride / texImage->TexFormat->TexelBytes; + + return 1; + } +} + +static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + driTextureObject *t = (driTextureObject *) texObj->DriverData; + + if (t) { + driSwapOutTextureObject(t); + } else { + t = (driTextureObject *) r300AllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); + return; + } + } + + /* Note, this will call ChooseTextureFormat */ + _mesa_store_teximage1d(ctx, target, level, internalFormat, + width, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); + + t->dirty_images[0] |= (1 << level); +} + +static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + driTextureObject *t = (driTextureObject *) texObj->DriverData; + + assert(t); /* this _should_ be true */ + if (t) { + driSwapOutTextureObject(t); + } else { + t = (driTextureObject *) r300AllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); + return; + } + } + + _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, + format, type, pixels, packing, texObj, + texImage); + + t->dirty_images[0] |= (1 << level); +} + +static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + driTextureObject *t = (driTextureObject *) texObj->DriverData; + GLuint face; + + /* which cube face or ordinary 2D image */ + switch (target) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = + (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; + ASSERT(face < 6); + break; + default: + face = 0; + } + + if (t != NULL) { + driSwapOutTextureObject(t); + } else { + t = (driTextureObject *) r300AllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + return; + } + } + + texImage->IsClientData = GL_FALSE; + + if (r300ValidateClientStorage(ctx, target, + internalFormat, + width, height, + format, type, pixels, + packing, texObj, texImage)) { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: Using client storage\n", + __FUNCTION__); + } else { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: Using normal storage\n", + __FUNCTION__); + + /* Normal path: copy (to cached memory) and eventually upload + * via another copy to GART memory and then a blit... Could + * eliminate one copy by going straight to (permanent) GART. + * + * Note, this will call r300ChooseTextureFormat. + */ + _mesa_store_teximage2d(ctx, target, level, internalFormat, + width, height, border, format, type, + pixels, &ctx->Unpack, texObj, texImage); + + t->dirty_images[face] |= (1 << level); + } +} + +static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + driTextureObject *t = (driTextureObject *) texObj->DriverData; + GLuint face; + + /* which cube face or ordinary 2D image */ + switch (target) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = + (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; + ASSERT(face < 6); + break; + default: + face = 0; + } + + assert(t); /* this _should_ be true */ + if (t) { + driSwapOutTextureObject(t); + } else { + t = (driTextureObject *) r300AllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); + return; + } + } + + _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, + height, format, type, pixels, packing, texObj, + texImage); + + t->dirty_images[face] |= (1 << level); +} + +#if ENABLE_HW_3D_TEXTURE +static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, + GLint border, + GLenum format, GLenum type, const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + driTextureObject *t = (driTextureObject *) texObj->DriverData; + + if (t) { + driSwapOutTextureObject(t); + } else { + t = (driTextureObject *) r300AllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); + return; + } + } + + texImage->IsClientData = GL_FALSE; + +#if 0 + if (r300ValidateClientStorage(ctx, target, + internalFormat, + width, height, + format, type, pixels, + packing, texObj, texImage)) { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: Using client storage\n", + __FUNCTION__); + } else +#endif + { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: Using normal storage\n", + __FUNCTION__); + + /* Normal path: copy (to cached memory) and eventually upload + * via another copy to GART memory and then a blit... Could + * eliminate one copy by going straight to (permanent) GART. + * + * Note, this will call r300ChooseTextureFormat. + */ + _mesa_store_teximage3d(ctx, target, level, internalFormat, + width, height, depth, border, + format, type, pixels, + &ctx->Unpack, texObj, texImage); + + t->dirty_images[0] |= (1 << level); + } +} +#endif + +#if ENABLE_HW_3D_TEXTURE +static void +r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + driTextureObject *t = (driTextureObject *) texObj->DriverData; + +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + + assert(t); /* this _should_ be true */ + if (t) { + driSwapOutTextureObject(t); + } else { + t = (driTextureObject *) r300AllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); + return; + } + texObj->DriverData = t; + } + + _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, packing, texObj, + texImage); + + t->dirty_images[0] |= (1 << level); +} +#endif + +static void r300TexEnv(GLcontext * ctx, GLenum target, + GLenum pname, const GLfloat * param) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + if (RADEON_DEBUG & DEBUG_STATE) { + fprintf(stderr, "%s( %s )\n", + __FUNCTION__, _mesa_lookup_enum_by_nr(pname)); + } + + /* This is incorrect: Need to maintain this data for each of + * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch + * between them according to _ReallyEnabled. + */ + switch (pname) { + case GL_TEXTURE_ENV_COLOR:{ + WARN_ONCE("I am broken - Fixme !\n"); + /* + GLubyte c[4]; + GLuint envColor; + UNCLAMPED_FLOAT_TO_RGBA_CHAN(c, texUnit->EnvColor); + envColor = radeonPackColor(4, c[0], c[1], c[2], c[3]); + if (rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor) { + R200_STATECHANGE(rmesa, tf); + rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = + envColor; + } + break; + */} + + case GL_TEXTURE_LOD_BIAS_EXT:{ + GLfloat bias, min; + GLuint b; + + /* The R300's LOD bias is a signed 2's complement value with a + * range of -16.0 <= bias < 16.0. + * + * NOTE: Add a small bias to the bias for conform mipsel.c test. + */ + bias = *param + .01; + min = + driQueryOptionb(&rmesa->radeon.optionCache, + "no_neg_lod_bias") ? 0.0 : -16.0; + bias = CLAMP(bias, min, 16.0); + + /* 0.0 - 16.0 == 0x0 - 0x1000 */ + /* 0.0 - -16.0 == 0x1001 - 0x1fff */ + b = 0x1000 / 16.0 * bias; + b &= R300_LOD_BIAS_MASK; + + if(b != (rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] & R300_LOD_BIAS_MASK)){ + R300_STATECHANGE(rmesa, tex.unknown1); + rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] &= ~R300_LOD_BIAS_MASK; + rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] |= b; + } + break; + } + + default: + return; + } +} + +/** + * Changes variables and flags for a state update, which will happen at the + * next UpdateTextureState + */ + +static void r300TexParameter(GLcontext * ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat * params) +{ + r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData; + + if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) { + fprintf(stderr, "%s( %s )\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(pname)); + } + + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + r300SetTexMaxAnisotropy(t, texObj->MaxAnisotropy); + r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter); + break; + + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_WRAP_R: + r300SetTexWrap(t, texObj->WrapS, texObj->WrapT, texObj->WrapR); + break; + + case GL_TEXTURE_BORDER_COLOR: + r300SetTexBorderColor(t, texObj->_BorderChan); + break; + + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + /* This isn't the most efficient solution but there doesn't appear to + * be a nice alternative. Since there's no LOD clamping, + * we just have to rely on loading the right subset of mipmap levels + * to simulate a clamped LOD. + */ + driSwapOutTextureObject((driTextureObject *) t); + break; + + default: + return; + } + + /* Mark this texobj as dirty (one bit per tex unit) + */ + t->dirty_state = TEX_ALL; +} + +static void r300BindTexture(GLcontext * ctx, GLenum target, + struct gl_texture_object *texObj) +{ + if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) { + fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__, + (void *)texObj, ctx->Texture.CurrentUnit); + } + + if ((target == GL_TEXTURE_1D) + || (target == GL_TEXTURE_2D) +#if ENABLE_HW_3D_TEXTURE + || (target == GL_TEXTURE_3D) +#endif + || (target == GL_TEXTURE_CUBE_MAP) + || (target == GL_TEXTURE_RECTANGLE_NV)) { + assert(texObj->DriverData != NULL); + } +} + +static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + driTextureObject *t = (driTextureObject *) texObj->DriverData; + + if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) { + fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__, + (void *)texObj, + _mesa_lookup_enum_by_nr(texObj->Target)); + } + + if (t != NULL) { + if (rmesa) { + R300_FIREVERTICES(rmesa); + } + + driDestroyTextureObject(t); + } + /* Free mipmap images and the texture object itself */ + _mesa_delete_texture_object(ctx, texObj); +} + +/* Need: + * - Same GEN_MODE for all active bits + * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj + * - STRQ presumably all supported (matrix means incoming R values + * can end up in STQ, this has implications for vertex support, + * presumably ok if maos is used, though?) + * + * Basically impossible to do this on the fly - just collect some + * basic info & do the checks from ValidateState(). + */ +static void r300TexGen(GLcontext * ctx, + GLenum coord, GLenum pname, const GLfloat * params) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLuint unit = ctx->Texture.CurrentUnit; +#if 0 /* Disable this for now - looks like we will be recalculating everything + anyway */ + rmesa->recheck_texgen[unit] = GL_TRUE; +#endif +} + +/** + * Allocate a new texture object. + * Called via ctx->Driver.NewTextureObject. + * Note: this function will be called during context creation to + * allocate the default texture objects. + * Note: we could use containment here to 'derive' the driver-specific + * texture object from the core mesa gl_texture_object. Not done at this time. + * Fixup MaxAnisotropy according to user preference. + */ +static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx, + GLuint name, + GLenum target) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct gl_texture_object *obj; + obj = _mesa_new_texture_object(ctx, name, target); + if (!obj) + return NULL; + obj->MaxAnisotropy = rmesa->initialMaxAnisotropy; + + r300AllocTexObj(obj); + return obj; +} + +void r300InitTextureFuncs(struct dd_function_table *functions) +{ + /* Note: we only plug in the functions we implement in the driver + * since _mesa_init_driver_functions() was already called. + */ + functions->ChooseTextureFormat = r300ChooseTextureFormat; + functions->TexImage1D = r300TexImage1D; + functions->TexImage2D = r300TexImage2D; +#if ENABLE_HW_3D_TEXTURE + functions->TexImage3D = r300TexImage3D; +#else + functions->TexImage3D = _mesa_store_teximage3d; +#endif + functions->TexSubImage1D = r300TexSubImage1D; + functions->TexSubImage2D = r300TexSubImage2D; +#if ENABLE_HW_3D_TEXTURE + functions->TexSubImage3D = r300TexSubImage3D; +#else + functions->TexSubImage3D = _mesa_store_texsubimage3d; +#endif + functions->NewTextureObject = r300NewTextureObject; + functions->BindTexture = r300BindTexture; + functions->DeleteTexture = r300DeleteTexture; + functions->IsTextureResident = driIsTextureResident; + + functions->TexEnv = r300TexEnv; + functions->TexParameter = r300TexParameter; + functions->TexGen = r300TexGen; + + driInitTextureFormats(); + +#if 0 + /* moved or obsolete code */ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + driInitTextureObjects(ctx, &rmesa->swapped, + DRI_TEXMGR_DO_TEXTURE_1D + | DRI_TEXMGR_DO_TEXTURE_2D); + + /* Hack: r300NewTextureObject is not yet installed when the + * default textures are created. Therefore set MaxAnisotropy of the + * default 2D texture now. */ + ctx->Shared->Default2D->MaxAnisotropy = + driQueryOptionf(&rmesa->optionCache, "def_max_anisotropy"); +#endif +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_tex.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_tex.h new file mode 100644 index 000000000..a18ff0e2c --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_tex.h @@ -0,0 +1,51 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_tex.h,v 1.1 2002/10/30 12:51:53 alanh Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __r300_TEX_H__ +#define __r300_TEX_H__ + +#ifdef GLX_DIRECT_RENDERING + +extern void r300UpdateTextureState(GLcontext * ctx); + +extern int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t, + GLuint face); + +extern void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t); + +extern void r300InitTextureFuncs(struct dd_function_table *functions); + +#endif +#endif /* __r300_TEX_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texmem.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texmem.c new file mode 100644 index 000000000..5c70e2e3c --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texmem.c @@ -0,0 +1,514 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_texmem.c,v 1.5 2002/12/17 00:32:56 dawes Exp $ */ +/************************************************************************** + +Copyright (C) Tungsten Graphics 2002. All Rights Reserved. +The Weather Channel, Inc. funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 +license. This notice must be preserved. + +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 ATI, VA LINUX SYSTEMS AND/OR THEIR +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: + * Kevin E. Martin <martin@valinux.com> + * Gareth Hughes <gareth@valinux.com> + * + */ + +#include <errno.h> + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "colormac.h" +#include "macros.h" +#include "simple_list.h" +#include "radeon_reg.h" /* gets definition for usleep */ +#include "r300_context.h" +#include "r300_state.h" +#include "r300_cmdbuf.h" +#include "radeon_ioctl.h" +/* +#include "r300_swtcl.h" +*/ +#include "r300_tex.h" +#include "r300_ioctl.h" +#include <unistd.h> /* for usleep() */ + +/** + * Destroy any device-dependent state associated with the texture. This may + * include NULLing out hardware state that points to the texture. + */ +void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t) +{ + if (RADEON_DEBUG & DEBUG_TEXTURE) { + fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__, + (void *)t, (void *)t->base.tObj); + } + + if (rmesa != NULL) { + unsigned i; + + for (i = 0; i < rmesa->radeon.glCtx->Const.MaxTextureUnits; i++) { + if (t == rmesa->state.texture.unit[i].texobj) { + rmesa->state.texture.unit[i].texobj = NULL; + /* This code below is meant to shorten state + pushed to the hardware by not programming + unneeded units. + + This does not appear to be worthwhile on R300 */ +#if 0 + remove_from_list(&rmesa->hw.tex[i]); + make_empty_list(&rmesa->hw.tex[i]); + remove_from_list(&rmesa->hw.cube[i]); + make_empty_list(&rmesa->hw.cube[i]); +#endif + } + } + } +} + +/* ------------------------------------------------------------ + * Texture image conversions + */ + +static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, + r300TexObjPtr t, + struct gl_texture_image *texImage, + GLint hwlevel, + GLint x, GLint y, + GLint width, GLint height) +{ + const struct gl_texture_format *texFormat = texImage->TexFormat; + GLuint srcPitch, dstPitch; + int blit_format; + int srcOffset; + + /* + * XXX it appears that we always upload the full image, not a subimage. + * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever + * changed, the src pitch will have to change. + */ + switch (texFormat->TexelBytes) { + case 1: + blit_format = R200_CP_COLOR_FORMAT_CI8; + srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes; + break; + case 2: + blit_format = R200_CP_COLOR_FORMAT_RGB565; + srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes; + break; + case 4: + blit_format = R200_CP_COLOR_FORMAT_ARGB8888; + srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes; + break; + default: + return; + } + + t->image[0][hwlevel].data = texImage->Data; + srcOffset = r300GartOffsetFromVirtual(rmesa, texImage->Data); + + assert(srcOffset != ~0); + + /* Don't currently need to cope with small pitches? + */ + width = texImage->Width; + height = texImage->Height; + + r300EmitWait(rmesa, R300_WAIT_3D); + + r300EmitBlit(rmesa, blit_format, + srcPitch, + srcOffset, + dstPitch, + t->bufAddr, + x, + y, + t->image[0][hwlevel].x + x, + t->image[0][hwlevel].y + y, width, height); + + r300EmitWait(rmesa, R300_WAIT_2D); +} + +static void r300UploadRectSubImage(r300ContextPtr rmesa, + r300TexObjPtr t, + struct gl_texture_image *texImage, + GLint x, GLint y, GLint width, GLint height) +{ + const struct gl_texture_format *texFormat = texImage->TexFormat; + int blit_format, dstPitch, done; + + switch (texFormat->TexelBytes) { + case 1: + blit_format = R200_CP_COLOR_FORMAT_CI8; + break; + case 2: + blit_format = R200_CP_COLOR_FORMAT_RGB565; + break; + case 4: + blit_format = R200_CP_COLOR_FORMAT_ARGB8888; + break; + default: + return; + } + + t->image[0][0].data = texImage->Data; + + /* Currently don't need to cope with small pitches. + */ + width = texImage->Width; + height = texImage->Height; + dstPitch = t->pitch + 32; + + if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) { + /* In this case, could also use GART texturing. This is + * currently disabled, but has been tested & works. + */ + t->offset = + r300GartOffsetFromVirtual(rmesa, texImage->Data); + t->pitch = + texImage->RowStride * texFormat->TexelBytes - 32; + + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, + "Using GART texturing for rectangular client texture\n"); + + /* Release FB memory allocated for this image: + */ + /* FIXME This may not be correct as driSwapOutTextureObject sets + * FIXME dirty_images. It may be fine, though. + */ + if (t->base.memBlock) { + driSwapOutTextureObject((driTextureObject *) t); + } + } else if (texImage->IsClientData) { + /* Data already in GART memory, with usable pitch. + */ + GLuint srcPitch; + srcPitch = texImage->RowStride * texFormat->TexelBytes; + r300EmitBlit(rmesa, + blit_format, + srcPitch, + r300GartOffsetFromVirtual(rmesa, texImage->Data), + dstPitch, t->bufAddr, 0, 0, 0, 0, width, height); + } else { + /* Data not in GART memory, or bad pitch. + */ + for (done = 0; done < height;) { + struct r300_dma_region region; + int lines = + MIN2(height - done, RADEON_BUFFER_SIZE / dstPitch); + int src_pitch; + char *tex; + + src_pitch = texImage->RowStride * texFormat->TexelBytes; + + tex = (char *)texImage->Data + done * src_pitch; + + memset(®ion, 0, sizeof(region)); + r300AllocDmaRegion(rmesa, ®ion, lines * dstPitch, + 1024); + + /* Copy texdata to dma: + */ + if (0) + fprintf(stderr, + "%s: src_pitch %d dst_pitch %d\n", + __FUNCTION__, src_pitch, dstPitch); + + if (src_pitch == dstPitch) { + memcpy(region.address + region.start, tex, + lines * src_pitch); + } else { + char *buf = region.address + region.start; + int i; + for (i = 0; i < lines; i++) { + memcpy(buf, tex, src_pitch); + buf += dstPitch; + tex += src_pitch; + } + } + + r300EmitWait(rmesa, R300_WAIT_3D); + + /* Blit to framebuffer + */ + r300EmitBlit(rmesa, + blit_format, + dstPitch, GET_START(®ion), + dstPitch, t->bufAddr, + 0, 0, 0, done, width, lines); + + r300EmitWait(rmesa, R300_WAIT_2D); + + r300ReleaseDmaRegion(rmesa, ®ion, __FUNCTION__); + done += lines; + } + } +} + +/** + * Upload the texture image associated with texture \a t at the specified + * level at the address relative to \a start. + */ +static void uploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t, + GLint hwlevel, + GLint x, GLint y, GLint width, GLint height, + GLuint face) +{ + struct gl_texture_image *texImage = NULL; + GLuint offset; + GLint imageWidth, imageHeight; + GLint ret; + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + const int level = hwlevel + t->base.firstLevel; + + if (RADEON_DEBUG & DEBUG_TEXTURE) { + fprintf(stderr, + "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n", + __FUNCTION__, (void *)t, (void *)t->base.tObj, level, + width, height, face); + } + + ASSERT(face < 6); + + /* Ensure we have a valid texture to upload */ + if ((hwlevel < 0) || (hwlevel >= RADEON_MAX_TEXTURE_LEVELS)) { + _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__); + return; + } + + texImage = t->base.tObj->Image[face][level]; + + if (!texImage) { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: texImage %d is NULL!\n", + __FUNCTION__, level); + return; + } + if (!texImage->Data) { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: image data is NULL!\n", + __FUNCTION__); + return; + } + + if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) { + assert(level == 0); + assert(hwlevel == 0); + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: image data is rectangular\n", + __FUNCTION__); + r300UploadRectSubImage(rmesa, t, texImage, x, y, width, height); + return; + } else if (texImage->IsClientData) { + if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, + "%s: image data is in GART client storage\n", + __FUNCTION__); + r300UploadGARTClientSubImage(rmesa, t, texImage, hwlevel, x, y, + width, height); + return; + } else if (RADEON_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: image data is in normal memory\n", + __FUNCTION__); + + imageWidth = texImage->Width; + imageHeight = texImage->Height; + + offset = t->bufAddr; + + if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) { + GLint imageX = 0; + GLint imageY = 0; + GLint blitX = t->image[face][hwlevel].x; + GLint blitY = t->image[face][hwlevel].y; + GLint blitWidth = t->image[face][hwlevel].width; + GLint blitHeight = t->image[face][hwlevel].height; + fprintf(stderr, " upload image: %d,%d at %d,%d\n", + imageWidth, imageHeight, imageX, imageY); + fprintf(stderr, " upload blit: %d,%d at %d,%d\n", + blitWidth, blitHeight, blitX, blitY); + fprintf(stderr, " blit ofs: 0x%07x level: %d/%d\n", + (GLuint) offset, hwlevel, level); + } + + t->image[face][hwlevel].data = texImage->Data; + + /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct. + * NOTE: we're always use a 1KB-wide blit and I8 texture format. + * We used to use 1, 2 and 4-byte texels and used to use the texture + * width to dictate the blit width - but that won't work for compressed + * textures. (Brian) + */ + + tex.offset = offset; + tex.pitch = BLIT_WIDTH_BYTES / 64; + tex.format = R200_TXFORMAT_I8; /* any 1-byte texel format */ +#if 0 /* I am not sure HOSTDATA_BLT actually works.. Experiment here - V.D */ + tex.format = R200_TXFORMAT_RGBA8888; /* any 4-byte texel format */ +#endif + if (texImage->TexFormat->TexelBytes) { + tex.width = imageWidth * texImage->TexFormat->TexelBytes; /* in bytes */ + tex.height = imageHeight; + } else { + tex.width = imageWidth; /* compressed */ + tex.height = imageHeight; + if (tex.height < 4) + tex.height = 4; + } + tex.image = &tmp; +#if 0 + tex.width /= 4; +#endif + + /* copy (x,y,width,height,data) */ + memcpy(&tmp, &t->image[face][hwlevel], sizeof(tmp)); +#if 0 + tex.image->width /=4; +#endif + +#if 0 + sleep(1); + + fprintf(stderr, "*** Uploading texture\n"); + fprintf(stderr, " offset=0x%08x\n", offset); + fprintf(stderr, " image width=%d height=%d\n", + imageWidth, imageHeight); + fprintf(stderr, " blit width=%d height=%d data=%p\n", + t->image[face][hwlevel].width, + t->image[face][hwlevel].height, + t->image[face][hwlevel].data); +#endif + + LOCK_HARDWARE(&rmesa->radeon); + do { + ret = drmCommandWriteRead(rmesa->radeon.dri.fd, DRM_RADEON_TEXTURE, + &tex, sizeof(drm_radeon_texture_t)); + if (ret) { + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, + "DRM_RADEON_TEXTURE: again!\n"); + usleep(1); + } + } while (ret && errno == EAGAIN); + + UNLOCK_HARDWARE(&rmesa->radeon); + + if (ret) { + fprintf(stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret); + fprintf(stderr, " offset=0x%08x\n", offset); + fprintf(stderr, " image width=%d height=%d\n", + imageWidth, imageHeight); + fprintf(stderr, " blit width=%d height=%d data=%p\n", + t->image[face][hwlevel].width, + t->image[face][hwlevel].height, + t->image[face][hwlevel].data); + exit(1); + } +} + +/** + * Upload the texture images associated with texture \a t. This might + * require the allocation of texture memory. + * + * \param rmesa Context pointer + * \param t Texture to be uploaded + * \param face Cube map face to be uploaded. Zero for non-cube maps. + */ + +int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t, GLuint face) +{ + const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; + + if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) { + fprintf(stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__, + (void *)rmesa->radeon.glCtx, (void *)t->base.tObj, + t->base.totalSize, t->base.firstLevel, + t->base.lastLevel); + } + + if (!t || t->base.totalSize == 0) + return 0; + + if (RADEON_DEBUG & DEBUG_SYNC) { + fprintf(stderr, "%s: Syncing\n", __FUNCTION__); + radeonFinish(rmesa->radeon.glCtx); + } + + LOCK_HARDWARE(&rmesa->radeon); + + if (t->base.memBlock == NULL) { + int heap; + + heap = driAllocateTexture(rmesa->texture_heaps, rmesa->nr_heaps, + (driTextureObject *) t); + if (heap == -1) { + UNLOCK_HARDWARE(&rmesa->radeon); + return -1; + } + + /* Set the base offset of the texture image */ + t->bufAddr = rmesa->radeon.radeonScreen->texOffset[heap] + + t->base.memBlock->ofs; + t->offset = t->bufAddr; + + /* Mark this texobj as dirty on all units: + */ + t->dirty_state = TEX_ALL; + } + + /* Let the world know we've used this memory recently. + */ + driUpdateTextureLRU((driTextureObject *) t); + UNLOCK_HARDWARE(&rmesa->radeon); + + /* Upload any images that are new */ + if (t->base.dirty_images[face]) { + int i; + for (i = 0; i < numLevels; i++) { + if ((t->base. + dirty_images[face] & (1 << + (i + t->base.firstLevel))) != + 0) { + uploadSubImage(rmesa, t, i, 0, 0, + t->image[face][i].width, + t->image[face][i].height, face); + } + } + t->base.dirty_images[face] = 0; + } + + if (RADEON_DEBUG & DEBUG_SYNC) { + fprintf(stderr, "%s: Syncing\n", __FUNCTION__); + radeonFinish(rmesa->radeon.glCtx); + } + + return 0; +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c new file mode 100644 index 000000000..71d28db05 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c @@ -0,0 +1,270 @@ +#include "glheader.h" +#include "state.h" +#include "imports.h" +#include "enums.h" +#include "macros.h" +#include "context.h" +#include "dd.h" +#include "simple_list.h" + +#include "api_arrayelt.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "texformat.h" + +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "r300_context.h" +#if USE_ARB_F_P == 0 +#include "r300_ioctl.h" +#include "r300_state.h" +#include "r300_reg.h" +#include "r300_program.h" +#include "r300_emit.h" +#include "r300_fixed_pipelines.h" +#include "r300_tex.h" +#include "pixel_shader.h" +#include "r300_texprog.h" + +/* TODO: we probably should have a better way to emit alu instructions */ +#define INST0 p->alu.inst[p->alu.length].inst0 = +#define INST1 p->alu.inst[p->alu.length].inst1 = +#define INST2 p->alu.inst[p->alu.length].inst2 = +#define INST3 p->alu.inst[p->alu.length].inst3 = +#define EMIT_INST p->alu.length++ + +void emit_tex(struct r300_pixel_shader_program *p, GLuint dest, GLuint unit, GLuint src) +{ + p->tex.inst[p->tex.length++] = 0 + | (src << R300_FPITX_SRC_SHIFT) + | (dest << R300_FPITX_DST_SHIFT) + | (unit << R300_FPITX_IMAGE_SHIFT) + /* I don't know if this is needed, but the hardcoded 0x18000 set it, so I will too */ + | (3 << 15); +// fprintf(stderr, "emit texinst: 0x%x\n", p->tex.inst[p->tex.length-1]); +} + +GLuint get_source(struct r300_pixel_shader_state *ps, GLenum src, GLuint unit, GLuint tc_reg) { + switch (src) { + case GL_TEXTURE: + if (!ps->have_sample) { + emit_tex(&ps->program, tc_reg, unit, tc_reg); + ps->have_sample = 1; + } + return tc_reg; + case GL_CONSTANT: + WARN_ONCE("TODO: Implement envcolor\n"); + return ps->color_reg; + case GL_PRIMARY_COLOR: + return ps->color_reg; + case GL_PREVIOUS: + return ps->src_previous; + default: + WARN_ONCE("Unknown source enum\n"); + return ps->src_previous; + } +} + +GLuint get_temp(struct r300_pixel_shader_program *p) +{ + return p->temp_register_count++; +} + +inline void emit_texenv_color(r300ContextPtr r300, struct r300_pixel_shader_state *ps, + GLuint out, GLenum envmode, GLenum format, GLuint unit, GLuint tc_reg) { + struct r300_pixel_shader_program *p = &ps->program; + + const GLuint Cp = get_source(ps, GL_PREVIOUS, unit, tc_reg); + const GLuint Cs = get_source(ps, GL_TEXTURE, unit, tc_reg); + + switch(envmode) { + case GL_DECAL: /* TODO */ + case GL_BLEND: /* TODO */ + case GL_REPLACE: + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + switch (format) { + case GL_ALPHA: + // Cv = Cp + INST1 EASY_PFS_INSTR1(out, Cp, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + default: + // Cv = Cs + INST1 EASY_PFS_INSTR1(out, Cs, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + } + break; + case GL_MODULATE: + switch (format) { + case GL_ALPHA: + // Cv = Cp + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + INST1 EASY_PFS_INSTR1(out, Cp, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + default: + // Cv = CpCs + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, SRC1C_XYZ, ZERO); + INST1 EASY_PFS_INSTR1(out, Cp, Cs, PFS_FLAG_CONST, ALL, NONE); + break; + } + break; + case GL_ADD: + switch (format) { + case GL_ALPHA: + // Cv = Cp + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + INST1 EASY_PFS_INSTR1(out, Cp, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + default: + // Cv = Cp + Cs + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, SRC1C_XYZ); + INST1 EASY_PFS_INSTR1(out, Cp, Cs, PFS_FLAG_CONST, ALL, NONE); + break; + } + break; + default: + fprintf(stderr, "%s: should never get here!\n", __func__); + break; + } + + return; +} + +inline void emit_texenv_alpha(r300ContextPtr r300, struct r300_pixel_shader_state *ps, + GLuint out, GLenum envmode, GLenum format, GLuint unit, GLuint tc_reg) { + struct r300_pixel_shader_program *p = &ps->program; + + const GLuint Ap = get_source(ps, GL_PREVIOUS, unit, tc_reg); + const GLuint As = get_source(ps, GL_TEXTURE, unit, tc_reg); + + switch(envmode) { + case GL_DECAL: /* TODO */ + case GL_BLEND: /* TODO */ + case GL_REPLACE: + INST2 EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + switch (format) { + case GL_LUMINANCE: + case GL_RGB: + // Av = Ap + INST3 EASY_PFS_INSTR3(out, Ap, PFS_FLAG_CONST, PFS_FLAG_CONST, REG); + break; + default: + INST3 EASY_PFS_INSTR3(out, As, PFS_FLAG_CONST, PFS_FLAG_CONST, REG); + break; + } + break; + case GL_MODULATE: + case GL_ADD: + switch (format) { + case GL_LUMINANCE: + case GL_RGB: + // Av = Ap + INST2 EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + INST3 EASY_PFS_INSTR3(out, Ap, PFS_FLAG_CONST, PFS_FLAG_CONST, REG); + break; + default: + // Av = ApAs + INST2 EASY_PFS_INSTR2(MAD, SRC0A, SRC1A, ZERO); + INST3 EASY_PFS_INSTR3(out, Ap, As, PFS_FLAG_CONST, REG); + break; + } + break; + default: + fprintf(stderr, "%s: should never get here!\n", __func__); + break; + } + + return; +} + +GLuint emit_texenv(r300ContextPtr r300, GLuint tc_reg, GLuint unit) +{ + struct r300_pixel_shader_state *ps = &r300->state.pixel_shader; + struct r300_pixel_shader_program *p = &ps->program; + GLcontext *ctx = r300->radeon.glCtx; + struct gl_texture_object *texobj = ctx->Texture.Unit[unit]._Current; + GLenum envmode = ctx->Texture.Unit[unit].EnvMode; + GLenum format = texobj->Image[0][texobj->BaseLevel]->Format; + + const GLuint out = tc_reg; + const GLuint Cf = get_source(ps, GL_PRIMARY_COLOR, unit, tc_reg); + + WARN_ONCE("Texture environments are currently incomplete / wrong! Help me!\n"); +// fprintf(stderr, "EnvMode = %s\n", _mesa_lookup_enum_by_nr(ctx->Texture.Unit[unit].EnvMode)); + + switch (envmode) { + case GL_REPLACE: + case GL_MODULATE: + case GL_DECAL: + case GL_BLEND: + case GL_ADD: + /* Maybe these should be combined? I thought it'd be messy */ + emit_texenv_color(r300, ps, out, envmode, format, unit, tc_reg); + emit_texenv_alpha(r300, ps, out, envmode, format, unit, tc_reg); + EMIT_INST; + return out; + break; + case GL_COMBINE: + WARN_ONCE("EnvMode == GL_COMBINE unsupported! Help Me!!\n"); + return get_source(ps, GL_TEXTURE, unit, tc_reg); + break; + default: + WARN_ONCE("Unknown EnvMode == %d, name=%s\n", envmode, + _mesa_lookup_enum_by_nr(envmode)); + return get_source(ps, GL_TEXTURE, unit, tc_reg); + break; + } + +} + +void r300GenerateTextureFragmentShader(r300ContextPtr r300) +{ + struct r300_pixel_shader_state *ps = &r300->state.pixel_shader; + struct r300_pixel_shader_program *p = &ps->program; + GLcontext *ctx = r300->radeon.glCtx; + int i, tc_reg; + GLuint OutputsWritten; + + if(hw_tcl_on) + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten; + + p->tex.length = 0; + p->alu.length = 0; + p->active_nodes = 1; + p->first_node_has_tex = 1; + p->temp_register_count = r300->state.texture.tc_count + 1; /* texcoords and colour reg */ + + ps->color_reg = r300->state.texture.tc_count; + ps->src_previous = ps->color_reg; + + tc_reg = 0; + for (i=0;i<ctx->Const.MaxTextureUnits;i++) { + if (TMU_ENABLED(ctx, i)) { + ps->have_sample = 0; + ps->src_previous = emit_texenv(r300, tc_reg, i); + tc_reg++; + } + } + +/* Do a MOV from last output, to destination reg.. This won't be needed when we + * have a better way of emitting alu instructions + */ + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + INST1 EASY_PFS_INSTR1(0, ps->src_previous, PFS_FLAG_CONST, PFS_FLAG_CONST, NONE, ALL); + INST2 EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + INST3 EASY_PFS_INSTR3(0, ps->src_previous, PFS_FLAG_CONST, PFS_FLAG_CONST, OUTPUT); + EMIT_INST; + + p->node[3].tex_end = ps->program.tex.length - 1; + p->node[3].tex_offset = 0; + p->node[3].alu_end = ps->program.alu.length - 1; + p->node[3].alu_offset = 0; + + p->tex_end = ps->program.tex.length - 1; + p->tex_offset = 0; + p->alu_end = ps->program.alu.length - 1; + p->alu_offset = 0; +} +#endif // USE_ARB_F_P == 0 + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.h new file mode 100644 index 000000000..4e91a1169 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.h @@ -0,0 +1,9 @@ +#ifndef __R300_TEXPROG_H_ +#define __R300_TEXPROG_H_ + +#include "r300_context.h" + +void r300GenerateTextureFragmentShader(r300ContextPtr r300); + +#endif + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texstate.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texstate.c new file mode 100644 index 000000000..b06629ca1 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texstate.c @@ -0,0 +1,1465 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_texstate.c,v 1.3 2003/02/15 22:18:47 dawes Exp $ */ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "macros.h" +#include "texformat.h" +#include "enums.h" + +#include "r300_context.h" +#include "r300_state.h" +#include "r300_ioctl.h" +#include "radeon_ioctl.h" +//#include "r300_swtcl.h" +#include "r300_tex.h" +//#include "r300_tcl.h" +#include "r300_reg.h" + +#define R200_TXFORMAT_A8 R200_TXFORMAT_I8 +#define R200_TXFORMAT_L8 R200_TXFORMAT_I8 +#define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88 +#define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422 +#define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422 + +#define _COLOR(f) \ + [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 } +#define _COLOR_REV(f) \ + [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 } +#define _ALPHA(f) \ + [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 } +#define _ALPHA_REV(f) \ + [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 } +#define _YUV(f) \ + [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB } +#define _INVALID(f) \ + [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 } +#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \ + && tx_table[f].flag ) + +#define _ASSIGN(entry, format) \ + [ MESA_FORMAT_ ## entry ] = { format, 0, 1} + +static const struct { + GLuint format, filter; +} tx_table0[] = { + _ALPHA(RGBA8888), + _ALPHA_REV(RGBA8888), + _ALPHA(ARGB8888), + _ALPHA_REV(ARGB8888), + _INVALID(RGB888), + _COLOR(RGB565), + _COLOR_REV(RGB565), + _ALPHA(ARGB4444), + _ALPHA_REV(ARGB4444), + _ALPHA(ARGB1555), + _ALPHA_REV(ARGB1555), + _ALPHA(AL88), + _ALPHA_REV(AL88), + _ALPHA(A8), + _COLOR(L8), + _ALPHA(I8), + _INVALID(CI8), + _YUV(YCBCR), + _YUV(YCBCR_REV), + }; + +static const struct { + GLuint format, filter, flag; +} tx_table[] = { + /* + * Note that the _REV formats are the same as the non-REV formats. + * This is because the REV and non-REV formats are identical as a + * byte string, but differ when accessed as 16-bit or 32-bit words + * depending on the endianness of the host. Since the textures are + * transferred to the R300 as a byte string (i.e. without any + * byte-swapping), the R300 sees the REV and non-REV formats + * identically. -- paulus + */ + _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), + _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), + _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), + _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), + _ASSIGN(RGB888, 0xffffffff), + _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), + _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), + _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)), + _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)), + _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(Z, Y, X, W, W1Z5Y5X5)), + _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(Z, Y, X, W, W1Z5Y5X5)), + _ASSIGN(AL88, R300_EASY_TX_FORMAT(Y, Y, Y, X, Y8X8)), + _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(Y, Y, Y, X, Y8X8)), + _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)), + _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)), + _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)), + _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)), + _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)), + _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ), + _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE), + }; + +#undef _COLOR +#undef _ALPHA +#undef _INVALID +#undef _ASSIGN + + +/** + * This function computes the number of bytes of storage needed for + * the given texture object (all mipmap levels, all cube faces). + * The \c image[face][level].x/y/width/height parameters for upload/blitting + * are computed here. \c filter, \c format, etc. will be set here + * too. + * + * \param rmesa Context pointer + * \param tObj GL texture object whose images are to be posted to + * hardware state. + */ +static void r300SetTexImages(r300ContextPtr rmesa, + struct gl_texture_object *tObj) +{ + r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; + const struct gl_texture_image *baseImage = + tObj->Image[0][tObj->BaseLevel]; + GLint curOffset; + GLint i; + GLint numLevels; + GLint log2Width, log2Height, log2Depth; + + /* Set the hardware texture format + */ + + t->format &= ~(R200_TXFORMAT_FORMAT_MASK | + R200_TXFORMAT_ALPHA_IN_MAP); +#if 0 + t->filter &= ~R200_YUV_TO_RGB; +#endif + if (VALID_FORMAT(baseImage->TexFormat->MesaFormat)) { + t->format = + tx_table[baseImage->TexFormat->MesaFormat].format; +#if 1 + t->filter |= + tx_table[baseImage->TexFormat->MesaFormat].filter; +#endif + } else { + _mesa_problem(NULL, "unexpected texture format in %s", + __FUNCTION__); + return; + } + + /* Compute which mipmap levels we really want to send to the hardware. + */ + + driCalculateTextureFirstLastLevel((driTextureObject *) t); + log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; + log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; + log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2; + + numLevels = t->base.lastLevel - t->base.firstLevel + 1; + + assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS); + + /* Calculate mipmap offsets and dimensions for blitting (uploading) + * The idea is that we lay out the mipmap levels within a block of + * memory organized as a rectangle of width BLIT_WIDTH_BYTES. + */ + curOffset = 0; + + for (i = 0; i < numLevels; i++) { + const struct gl_texture_image *texImage; + GLuint size; + + texImage = tObj->Image[0][i + t->base.firstLevel]; + if (!texImage) + break; + + /* find image size in bytes */ + if (texImage->IsCompressed) { + size = texImage->CompressedSize; + } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) { + size = + ((texImage->Width * + texImage->TexFormat->TexelBytes + 63) + & ~63) * texImage->Height; + } else { + int w = + texImage->Width * texImage->TexFormat->TexelBytes; + if (w < 32) + w = 32; + size = w * texImage->Height * texImage->Depth; + } + assert(size > 0); + + if(0) + fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage->Width, texImage->Height, + texImage->Depth, texImage->TexFormat->TexelBytes, + texImage->IntFormat); + + /* Align to 32-byte offset. It is faster to do this unconditionally + * (no branch penalty). + */ + + curOffset = (curOffset + 0x1f) & ~0x1f; + + t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES; + t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES; + t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES); + t->image[0][i].height = size / t->image[0][i].width; + +#if 0 + /* for debugging only and only applicable to non-rectangle targets */ + assert(size % t->image[0][i].width == 0); + assert(t->image[0][i].x == 0 + || (size < BLIT_WIDTH_BYTES + && t->image[0][i].height == 1)); +#endif + + if (0) + fprintf(stderr, + "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n", + i, texImage->Width, texImage->Height, + t->image[0][i].x, t->image[0][i].y, + t->image[0][i].width, t->image[0][i].height, + size, curOffset); + + curOffset += size; + + } + + /* Align the total size of texture memory block. + */ + t->base.totalSize = + (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK; + + /* Setup remaining cube face blits, if needed */ + if (tObj->Target == GL_TEXTURE_CUBE_MAP) { + /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */ + const GLuint faceSize = + (t->base.totalSize + BLIT_WIDTH_BYTES - 1) + & ~(BLIT_WIDTH_BYTES - 1); + const GLuint lines = faceSize / BLIT_WIDTH_BYTES; + GLuint face; + /* reuse face 0 x/y/width/height - just adjust y */ + for (face = 1; face < 6; face++) { + for (i = 0; i < numLevels; i++) { + t->image[face][i].x = t->image[0][i].x; + t->image[face][i].y = + t->image[0][i].y + face * lines; + t->image[face][i].width = t->image[0][i].width; + t->image[face][i].height = + t->image[0][i].height; + } + } + t->base.totalSize = 6 * faceSize; /* total texmem needed */ + } + + /* Hardware state: + */ +#if 0 + t->filter &= ~R200_MAX_MIP_LEVEL_MASK; + t->filter |= (numLevels - 1) << R200_MAX_MIP_LEVEL_SHIFT; +#endif +#if 0 + t->format &= ~(R200_TXFORMAT_WIDTH_MASK | + R200_TXFORMAT_HEIGHT_MASK | + R200_TXFORMAT_CUBIC_MAP_ENABLE | + R200_TXFORMAT_F5_WIDTH_MASK | + R200_TXFORMAT_F5_HEIGHT_MASK); + t->format |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) | + (log2Height << R200_TXFORMAT_HEIGHT_SHIFT)); +#endif + + t->format_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK); + if (tObj->Target == GL_TEXTURE_3D) { + t->format_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT); + t->format_x |= R200_TEXCOORD_VOLUME; + } else if (tObj->Target == GL_TEXTURE_CUBE_MAP) { + ASSERT(log2Width == log2Height); + t->format |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) | + (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) + | (R200_TXFORMAT_CUBIC_MAP_ENABLE)); + t->format_x |= R200_TEXCOORD_CUBIC_ENV; + t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) | + (log2Height << R200_FACE_HEIGHT_1_SHIFT) | + (log2Width << R200_FACE_WIDTH_2_SHIFT) | + (log2Height << R200_FACE_HEIGHT_2_SHIFT) | + (log2Width << R200_FACE_WIDTH_3_SHIFT) | + (log2Height << R200_FACE_HEIGHT_3_SHIFT) | + (log2Width << R200_FACE_WIDTH_4_SHIFT) | + (log2Height << R200_FACE_HEIGHT_4_SHIFT)); + } + + t->size = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << R300_TX_WIDTHMASK_SHIFT) + |((tObj->Image[0][t->base.firstLevel]->Height - 1) << R300_TX_HEIGHTMASK_SHIFT) + |((log2Width>log2Height)?log2Width:log2Height)<<R300_TX_SIZE_SHIFT); + + /* Only need to round to nearest 32 for textures, but the blitter + * requires 64-byte aligned pitches, and we may/may not need the + * blitter. NPOT only! + */ + if (baseImage->IsCompressed) + t->pitch = + (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63); + else + t->pitch = + ((tObj->Image[0][t->base.firstLevel]->Width * + baseImage->TexFormat->TexelBytes) + 63) & ~(63); + t->pitch -= 32; + + t->dirty_state = TEX_ALL; + + /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */ +} + +/* ================================================================ + * Texture combine functions + */ + +/* GL_ARB_texture_env_combine support + */ + +/* The color tables have combine functions for GL_SRC_COLOR, + * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. + */ +static GLuint r300_register_color[][R200_MAX_TEXTURE_UNITS] = { + { + R200_TXC_ARG_A_R0_COLOR, + R200_TXC_ARG_A_R1_COLOR, + R200_TXC_ARG_A_R2_COLOR, + R200_TXC_ARG_A_R3_COLOR, + R200_TXC_ARG_A_R4_COLOR, + R200_TXC_ARG_A_R5_COLOR}, + { + R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A}, + { + R200_TXC_ARG_A_R0_ALPHA, + R200_TXC_ARG_A_R1_ALPHA, + R200_TXC_ARG_A_R2_ALPHA, + R200_TXC_ARG_A_R3_ALPHA, + R200_TXC_ARG_A_R4_ALPHA, + R200_TXC_ARG_A_R5_ALPHA}, + { + R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A}, +}; + +static GLuint r300_tfactor_color[] = { + R200_TXC_ARG_A_TFACTOR_COLOR, + R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_TFACTOR_ALPHA, + R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A +}; + +static GLuint r300_primary_color[] = { + R200_TXC_ARG_A_DIFFUSE_COLOR, + R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_DIFFUSE_ALPHA, + R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A +}; + +/* GL_ZERO table - indices 0-3 + * GL_ONE table - indices 1-4 + */ +static GLuint r300_zero_color[] = { + R200_TXC_ARG_A_ZERO, + R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_ZERO, + R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A, + R200_TXC_ARG_A_ZERO +}; + +/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. + */ +static GLuint r300_register_alpha[][R200_MAX_TEXTURE_UNITS] = { + { + R200_TXA_ARG_A_R0_ALPHA, + R200_TXA_ARG_A_R1_ALPHA, + R200_TXA_ARG_A_R2_ALPHA, + R200_TXA_ARG_A_R3_ALPHA, + R200_TXA_ARG_A_R4_ALPHA, + R200_TXA_ARG_A_R5_ALPHA}, + { + R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A, + R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A, + R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A, + R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A, + R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A, + R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A}, +}; + +static GLuint r300_tfactor_alpha[] = { + R200_TXA_ARG_A_TFACTOR_ALPHA, + R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A +}; + +static GLuint r300_primary_alpha[] = { + R200_TXA_ARG_A_DIFFUSE_ALPHA, + R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A +}; + +/* GL_ZERO table - indices 0-1 + * GL_ONE table - indices 1-2 + */ +static GLuint r300_zero_alpha[] = { + R200_TXA_ARG_A_ZERO, + R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A, + R200_TXA_ARG_A_ZERO, +}; + +/* Extract the arg from slot A, shift it into the correct argument slot + * and set the corresponding complement bit. + */ +#define R200_COLOR_ARG( n, arg ) \ +do { \ + color_combine |= \ + ((color_arg[n] & R200_TXC_ARG_A_MASK) \ + << R200_TXC_ARG_##arg##_SHIFT); \ + color_combine |= \ + ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \ + << R200_TXC_COMP_ARG_##arg##_SHIFT); \ +} while (0) + +#define R200_ALPHA_ARG( n, arg ) \ +do { \ + alpha_combine |= \ + ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \ + << R200_TXA_ARG_##arg##_SHIFT); \ + alpha_combine |= \ + ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \ + << R200_TXA_COMP_ARG_##arg##_SHIFT); \ +} while (0) + +/* ================================================================ + * Texture unit state management + */ + +static GLboolean r300UpdateTextureEnv(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint color_combine, alpha_combine; + +#if 0 /* disable for now.. */ + GLuint color_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] & + ~(R200_TXC_SCALE_MASK); + GLuint alpha_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] & + ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK); +#endif + + GLuint color_scale=0, alpha_scale=0; + + /* texUnit->_Current can be NULL if and only if the texture unit is + * not actually enabled. + */ + assert((texUnit->_ReallyEnabled == 0) + || (texUnit->_Current != NULL)); + + if (RADEON_DEBUG & DEBUG_TEXTURE) { + fprintf(stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, + unit); + } + + /* Set the texture environment state. Isn't this nice and clean? + * The chip will automagically set the texture alpha to 0xff when + * the texture format does not include an alpha component. This + * reduces the amount of special-casing we have to do, alpha-only + * textures being a notable exception. + */ + /* Don't cache these results. + */ +#if 0 + rmesa->state.texture.unit[unit].format = 0; +#endif + rmesa->state.texture.unit[unit].envMode = 0; + + + if (!texUnit->_ReallyEnabled) { + if (unit == 0) { + color_combine = + R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD; + alpha_combine = + R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD; + } else { + color_combine = + R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R0_COLOR | R200_TXC_OP_MADD; + alpha_combine = + R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R0_ALPHA | R200_TXA_OP_MADD; + } + } else { + GLuint color_arg[3], alpha_arg[3]; + GLuint i; + const GLuint numColorArgs = + texUnit->_CurrentCombine->_NumArgsRGB; + const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; + GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB; + GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA; + + /* Step 1: + * Extract the color and alpha combine function arguments. + */ + for (i = 0; i < numColorArgs; i++) { + const GLint op = + texUnit->_CurrentCombine->OperandRGB[i] - + GL_SRC_COLOR; + assert(op >= 0); + assert(op <= 3); + switch (texUnit->_CurrentCombine->SourceRGB[i]) { + case GL_TEXTURE: + color_arg[i] = r300_register_color[op][unit]; + break; + case GL_CONSTANT: + color_arg[i] = r300_tfactor_color[op]; + break; + case GL_PRIMARY_COLOR: + color_arg[i] = r300_primary_color[op]; + break; + case GL_PREVIOUS: + if (unit == 0) + color_arg[i] = r300_primary_color[op]; + else + color_arg[i] = + r300_register_color[op][0]; + break; + case GL_ZERO: + color_arg[i] = r300_zero_color[op]; + break; + case GL_ONE: + color_arg[i] = r300_zero_color[op + 1]; + break; + default: + return GL_FALSE; + } + } + + for (i = 0; i < numAlphaArgs; i++) { + const GLint op = + texUnit->_CurrentCombine->OperandA[i] - + GL_SRC_ALPHA; + assert(op >= 0); + assert(op <= 1); + switch (texUnit->_CurrentCombine->SourceA[i]) { + case GL_TEXTURE: + alpha_arg[i] = r300_register_alpha[op][unit]; + break; + case GL_CONSTANT: + alpha_arg[i] = r300_tfactor_alpha[op]; + break; + case GL_PRIMARY_COLOR: + alpha_arg[i] = r300_primary_alpha[op]; + break; + case GL_PREVIOUS: + if (unit == 0) + alpha_arg[i] = r300_primary_alpha[op]; + else + alpha_arg[i] = + r300_register_alpha[op][0]; + break; + case GL_ZERO: + alpha_arg[i] = r300_zero_alpha[op]; + break; + case GL_ONE: + alpha_arg[i] = r300_zero_alpha[op + 1]; + break; + default: + return GL_FALSE; + } + } + + /* Step 2: + * Build up the color and alpha combine functions. + */ + switch (texUnit->_CurrentCombine->ModeRGB) { + case GL_REPLACE: + color_combine = (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_OP_MADD); + R200_COLOR_ARG(0, C); + break; + case GL_MODULATE: + color_combine = (R200_TXC_ARG_C_ZERO | + R200_TXC_OP_MADD); + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, B); + break; + case GL_ADD: + color_combine = (R200_TXC_ARG_B_ZERO | + R200_TXC_COMP_ARG_B | + R200_TXC_OP_MADD); + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, C); + break; + case GL_ADD_SIGNED: + color_combine = (R200_TXC_ARG_B_ZERO | R200_TXC_COMP_ARG_B | R200_TXC_BIAS_ARG_C | /* new */ + R200_TXC_OP_MADD); /* was ADDSIGNED */ + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, C); + break; + case GL_SUBTRACT: + color_combine = (R200_TXC_ARG_B_ZERO | + R200_TXC_COMP_ARG_B | + R200_TXC_NEG_ARG_C | R200_TXC_OP_MADD); + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, C); + break; + case GL_INTERPOLATE: + color_combine = (R200_TXC_OP_LERP); + R200_COLOR_ARG(0, B); + R200_COLOR_ARG(1, A); + R200_COLOR_ARG(2, C); + break; + + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + /* The EXT version of the DOT3 extension does not support the + * scale factor, but the ARB version (and the version in OpenGL + * 1.3) does. + */ + RGBshift = 0; + /* FALLTHROUGH */ + + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + /* DOT3 works differently on R200 than on R100. On R100, just + * setting the DOT3 mode did everything for you. On R200, the + * driver has to enable the biasing and scale in the inputs to + * put them in the proper [-1,1] range. This is what the 4x and + * the -0.5 in the DOT3 spec do. The post-scale is then set + * normally. + */ + + color_combine = (R200_TXC_ARG_C_ZERO | + R200_TXC_OP_DOT3 | + R200_TXC_BIAS_ARG_A | + R200_TXC_BIAS_ARG_B | + R200_TXC_SCALE_ARG_A | + R200_TXC_SCALE_ARG_B); + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, B); + break; + + case GL_MODULATE_ADD_ATI: + color_combine = (R200_TXC_OP_MADD); + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, C); + R200_COLOR_ARG(2, B); + break; + case GL_MODULATE_SIGNED_ADD_ATI: + color_combine = (R200_TXC_BIAS_ARG_C | /* new */ + R200_TXC_OP_MADD); /* was ADDSIGNED */ + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, C); + R200_COLOR_ARG(2, B); + break; + case GL_MODULATE_SUBTRACT_ATI: + color_combine = (R200_TXC_NEG_ARG_C | R200_TXC_OP_MADD); + R200_COLOR_ARG(0, A); + R200_COLOR_ARG(1, C); + R200_COLOR_ARG(2, B); + break; + default: + return GL_FALSE; + } + + switch (texUnit->_CurrentCombine->ModeA) { + case GL_REPLACE: + alpha_combine = (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_OP_MADD); + R200_ALPHA_ARG(0, C); + break; + case GL_MODULATE: + alpha_combine = (R200_TXA_ARG_C_ZERO | + R200_TXA_OP_MADD); + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, B); + break; + case GL_ADD: + alpha_combine = (R200_TXA_ARG_B_ZERO | + R200_TXA_COMP_ARG_B | + R200_TXA_OP_MADD); + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, C); + break; + case GL_ADD_SIGNED: + alpha_combine = (R200_TXA_ARG_B_ZERO | R200_TXA_COMP_ARG_B | R200_TXA_BIAS_ARG_C | /* new */ + R200_TXA_OP_MADD); /* was ADDSIGNED */ + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, C); + break; + case GL_SUBTRACT: + alpha_combine = (R200_TXA_ARG_B_ZERO | + R200_TXA_COMP_ARG_B | + R200_TXA_NEG_ARG_C | R200_TXA_OP_MADD); + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, C); + break; + case GL_INTERPOLATE: + alpha_combine = (R200_TXA_OP_LERP); + R200_ALPHA_ARG(0, B); + R200_ALPHA_ARG(1, A); + R200_ALPHA_ARG(2, C); + break; + + case GL_MODULATE_ADD_ATI: + alpha_combine = (R200_TXA_OP_MADD); + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, C); + R200_ALPHA_ARG(2, B); + break; + case GL_MODULATE_SIGNED_ADD_ATI: + alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */ + R200_TXA_OP_MADD); /* was ADDSIGNED */ + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, C); + R200_ALPHA_ARG(2, B); + break; + case GL_MODULATE_SUBTRACT_ATI: + alpha_combine = (R200_TXA_NEG_ARG_C | R200_TXA_OP_MADD); + R200_ALPHA_ARG(0, A); + R200_ALPHA_ARG(1, C); + R200_ALPHA_ARG(2, B); + break; + default: + return GL_FALSE; + } + + if ((texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT) + || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA)) { + alpha_scale |= R200_TXA_DOT_ALPHA; + Ashift = RGBshift; + } + + /* Step 3: + * Apply the scale factor. + */ + color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT); + alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT); + + /* All done! + */ + } + +#if 0 + fprintf(stderr, "color_combine=%08x alpha_combine=%08x color_scale=%08x alpha_scale=%08x\n", + color_combine, alpha_combine, color_scale, alpha_scale); +#endif + +#if 0 + if (rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] != color_combine || + rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] != alpha_combine || + rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] != color_scale || + rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] != alpha_scale) { + R300_STATECHANGE(rmesa, pix[unit]); + rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] = color_combine; + rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] = alpha_combine; + rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] = color_scale; + rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] = alpha_scale; + } + +#endif + + return GL_TRUE; +} + +#define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \ + R200_MIN_FILTER_MASK | \ + R200_MAG_FILTER_MASK | \ + R200_MAX_ANISO_MASK | \ + R200_YUV_TO_RGB | \ + R200_YUV_TEMPERATURE_MASK | \ + R200_CLAMP_S_MASK | \ + R200_CLAMP_T_MASK | \ + R200_BORDER_MODE_D3D ) + +#define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \ + R200_TXFORMAT_HEIGHT_MASK | \ + R200_TXFORMAT_FORMAT_MASK | \ + R200_TXFORMAT_F5_WIDTH_MASK | \ + R200_TXFORMAT_F5_HEIGHT_MASK | \ + R200_TXFORMAT_ALPHA_IN_MAP | \ + R200_TXFORMAT_CUBIC_MAP_ENABLE | \ + R200_TXFORMAT_NON_POWER2) + +#define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \ + R200_TEXCOORD_MASK | \ + R200_CLAMP_Q_MASK | \ + R200_VOLUME_FILTER_MASK) + +static void import_tex_obj_state(r300ContextPtr rmesa, + int unit, r300TexObjPtr texobj) +{ +#if 0 /* needs fixing.. or should be done elsewhere */ + GLuint *cmd = R300_DB_STATE(tex[unit]); + + cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK; + cmd[TEX_PP_TXFILTER] |= texobj->filter & TEXOBJ_TXFILTER_MASK; + cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; + cmd[TEX_PP_TXFORMAT] |= texobj->format & TEXOBJ_TXFORMAT_MASK; + cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK; + cmd[TEX_PP_TXFORMAT_X] |= + texobj->format_x & TEXOBJ_TXFORMAT_X_MASK; + cmd[TEX_PP_TXSIZE] = texobj->size; /* NPOT only! */ + cmd[TEX_PP_TXPITCH] = texobj->pitch; /* NPOT only! */ + cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset; + cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color; + R200_DB_STATECHANGE(rmesa, &rmesa->hw.tex[unit]); + + if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) { + GLuint *cube_cmd = R200_DB_STATE(cube[unit]); + GLuint bytesPerFace = texobj->base.totalSize / 6; + ASSERT(texobj->totalSize % 6 == 0); + cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; + cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = + texobj->pp_txoffset + 1 * bytesPerFace; + cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = + texobj->pp_txoffset + 2 * bytesPerFace; + cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = + texobj->pp_txoffset + 3 * bytesPerFace; + cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = + texobj->pp_txoffset + 4 * bytesPerFace; + cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = + texobj->pp_txoffset + 5 * bytesPerFace; + R200_DB_STATECHANGE(rmesa, &rmesa->hw.cube[unit]); + } + + texobj->dirty_state &= ~(1 << unit); +#endif +} + +static void set_texgen_matrix(r300ContextPtr rmesa, + GLuint unit, + const GLfloat * s_plane, + const GLfloat * t_plane, const GLfloat * r_plane) +{ + static const GLfloat scale_identity[4] = { 1, 1, 1, 1 }; + + if (!TEST_EQ_4V(s_plane, scale_identity) || + !TEST_EQ_4V(t_plane, scale_identity) || + !TEST_EQ_4V(r_plane, scale_identity)) { + rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE << unit; + rmesa->TexGenMatrix[unit].m[0] = s_plane[0]; + rmesa->TexGenMatrix[unit].m[4] = s_plane[1]; + rmesa->TexGenMatrix[unit].m[8] = s_plane[2]; + rmesa->TexGenMatrix[unit].m[12] = s_plane[3]; + + rmesa->TexGenMatrix[unit].m[1] = t_plane[0]; + rmesa->TexGenMatrix[unit].m[5] = t_plane[1]; + rmesa->TexGenMatrix[unit].m[9] = t_plane[2]; + rmesa->TexGenMatrix[unit].m[13] = t_plane[3]; + + /* NOTE: r_plane goes in the 4th row, not 3rd! */ + rmesa->TexGenMatrix[unit].m[3] = r_plane[0]; + rmesa->TexGenMatrix[unit].m[7] = r_plane[1]; + rmesa->TexGenMatrix[unit].m[11] = r_plane[2]; + rmesa->TexGenMatrix[unit].m[15] = r_plane[3]; + + //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; + } +} + +/* Need this special matrix to get correct reflection map coords */ +static void set_texgen_reflection_matrix(r300ContextPtr rmesa, GLuint unit) +{ + static const GLfloat m[16] = { + -1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 0, -1, + 0, 0, -1, 0 + }; + _math_matrix_loadf(&(rmesa->TexGenMatrix[unit]), m); + _math_matrix_analyse(&(rmesa->TexGenMatrix[unit])); + rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE << unit; +} + +/* Need this special matrix to get correct normal map coords */ +static void set_texgen_normal_map_matrix(r300ContextPtr rmesa, GLuint unit) +{ + static const GLfloat m[16] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 1, + 0, 0, 1, 0 + }; + _math_matrix_loadf(&(rmesa->TexGenMatrix[unit]), m); + _math_matrix_analyse(&(rmesa->TexGenMatrix[unit])); + rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE << unit; +} + +/* Ignoring the Q texcoord for now. + * + * Returns GL_FALSE if fallback required. + */ +static GLboolean r300_validate_texgen(GLcontext * ctx, GLuint unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit * 4; + GLuint tmp = rmesa->TexGenEnabled; + + rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); + rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE << unit); + rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE << unit); + rmesa->TexGenInputs &= ~(R200_TEXGEN_INPUT_MASK << inputshift); + rmesa->TexGenNeedNormals[unit] = 0; + + if (0) + fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit); + + if ((texUnit->TexGenEnabled & (S_BIT | T_BIT | R_BIT)) == 0) { + /* Disabled, no fallback: + */ + rmesa->TexGenInputs |= + (R200_TEXGEN_INPUT_TEXCOORD_0 + unit) << inputshift; + return GL_TRUE; + } else if (texUnit->TexGenEnabled & Q_BIT) { + /* Very easy to do this, in fact would remove a fallback case + * elsewhere, but I haven't done it yet... Fallback: + */ + /*fprintf(stderr, "fallback Q_BIT\n"); */ + return GL_FALSE; + } else if (texUnit->TexGenEnabled == (S_BIT | T_BIT) && + texUnit->GenModeS == texUnit->GenModeT) { + /* OK */ + rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit; + /* continue */ + } else if (texUnit->TexGenEnabled == (S_BIT | T_BIT | R_BIT) && + texUnit->GenModeS == texUnit->GenModeT && + texUnit->GenModeT == texUnit->GenModeR) { + /* OK */ + rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit; + /* continue */ + } else { + /* Mixed modes, fallback: + */ + /* fprintf(stderr, "fallback mixed texgen\n"); */ + return GL_FALSE; + } + + rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit; + + switch (texUnit->GenModeS) { + case GL_OBJECT_LINEAR: + rmesa->TexGenInputs |= R200_TEXGEN_INPUT_OBJ << inputshift; + set_texgen_matrix(rmesa, unit, + texUnit->ObjectPlaneS, + texUnit->ObjectPlaneT, texUnit->ObjectPlaneR); + break; + + case GL_EYE_LINEAR: + rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE << inputshift; + set_texgen_matrix(rmesa, unit, + texUnit->EyePlaneS, + texUnit->EyePlaneT, texUnit->EyePlaneR); + break; + + case GL_REFLECTION_MAP_NV: + rmesa->TexGenNeedNormals[unit] = GL_TRUE; + rmesa->TexGenInputs |= + R200_TEXGEN_INPUT_EYE_REFLECT << inputshift; + set_texgen_reflection_matrix(rmesa, unit); + break; + + case GL_NORMAL_MAP_NV: + rmesa->TexGenNeedNormals[unit] = GL_TRUE; + rmesa->TexGenInputs |= + R200_TEXGEN_INPUT_EYE_NORMAL << inputshift; + set_texgen_normal_map_matrix(rmesa, unit); + break; + + case GL_SPHERE_MAP: + rmesa->TexGenNeedNormals[unit] = GL_TRUE; + rmesa->TexGenInputs |= R200_TEXGEN_INPUT_SPHERE << inputshift; + break; + + default: + /* Unsupported mode, fallback: + */ + /* fprintf(stderr, "fallback unsupported texgen\n"); */ + return GL_FALSE; + } + + rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit; + + if (tmp != rmesa->TexGenEnabled) { + //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; + } + + return GL_TRUE; +} + +static void disable_tex(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + +#if 0 /* This needs to be redone.. or done elsewhere */ + if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE << unit)) { + /* Texture unit disabled */ + if (rmesa->state.texture.unit[unit].texobj != NULL) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + rmesa->state.texture.unit[unit].texobj->base.bound &= + ~(1UL << unit); + rmesa->state.texture.unit[unit].texobj = NULL; + } + + R300_STATECHANGE(rmesa, ctx); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((R200_TEX_0_ENABLE | + R200_TEX_BLEND_0_ENABLE) << + unit); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_BLEND_0_ENABLE; + + R300_STATECHANGE(rmesa, tcl); + rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= + ~(7 << (unit * 3)); + + if (rmesa->radeon.TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0 << unit)) { + TCL_FALLBACK(ctx, (RADEON_TCL_FALLBACK_TEXGEN_0 << unit), + GL_FALSE); + } + + /* Actually want to keep all units less than max active texture + * enabled, right? Fix this for >2 texunits. + */ + /* FIXME: What should happen here if r300UpdateTextureEnv fails? */ + if (unit == 0) + r300UpdateTextureEnv(ctx, unit); + + { + GLuint inputshift = + R200_TEXGEN_0_INPUT_SHIFT + unit * 4; + GLuint tmp = rmesa->TexGenEnabled; + + rmesa->TexGenEnabled &= + ~(R200_TEXGEN_TEXMAT_0_ENABLE << unit); + rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE << unit); + rmesa->TexGenEnabled &= + ~(R200_TEXGEN_INPUT_MASK << inputshift); + rmesa->TexGenNeedNormals[unit] = 0; + rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); + rmesa->TexGenInputs &= + ~(R200_TEXGEN_INPUT_MASK << inputshift); + + if (tmp != rmesa->TexGenEnabled) { + rmesa->recheck_texgen[unit] = GL_TRUE; + rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; + } + } + } +#endif +} + +static GLboolean enable_tex_2d(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; + + /* Need to load the 2d images associated with this unit. + */ +#if 0 + if (t->format & R200_TXFORMAT_NON_POWER2) { + t->format &= ~R200_TXFORMAT_NON_POWER2; + t->base.dirty_images[0] = ~0; + } +#endif + + ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D); + + if (t->base.dirty_images[0]) { + R300_FIREVERTICES(rmesa); + r300SetTexImages(rmesa, tObj); + r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0); + if (!t->base.memBlock) + return GL_FALSE; + } + + return GL_TRUE; +} + +#if ENABLE_HW_3D_TEXTURE +static GLboolean enable_tex_3d(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; + + /* Need to load the 3d images associated with this unit. + */ + if (t->format & R200_TXFORMAT_NON_POWER2) { + t->format &= ~R200_TXFORMAT_NON_POWER2; + t->base.dirty_images[0] = ~0; + } + + ASSERT(tObj->Target == GL_TEXTURE_3D); + + /* R100 & R200 do not support mipmaps for 3D textures. + */ + if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) { + return GL_FALSE; + } + + if (t->base.dirty_images[0]) { + R300_FIREVERTICES(rmesa); + r300SetTexImages(rmesa, tObj); + r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0); + if (!t->base.memBlock) + return GL_FALSE; + } + + return GL_TRUE; +} +#endif + +static GLboolean enable_tex_cube(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; + GLuint face; + + /* Need to load the 2d images associated with this unit. + */ + if (t->format & R200_TXFORMAT_NON_POWER2) { + t->format &= ~R200_TXFORMAT_NON_POWER2; + for (face = 0; face < 6; face++) + t->base.dirty_images[face] = ~0; + } + + ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP); + + if (t->base.dirty_images[0] || t->base.dirty_images[1] || + t->base.dirty_images[2] || t->base.dirty_images[3] || + t->base.dirty_images[4] || t->base.dirty_images[5]) { + /* flush */ + R300_FIREVERTICES(rmesa); + /* layout memory space, once for all faces */ + r300SetTexImages(rmesa, tObj); + } + + /* upload (per face) */ + for (face = 0; face < 6; face++) { + if (t->base.dirty_images[face]) { + r300UploadTexImages(rmesa, + (r300TexObjPtr) tObj->DriverData, + face); + } + } + + if (!t->base.memBlock) { + /* texmem alloc failed, use s/w fallback */ + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean enable_tex_rect(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; + +#if 0 + if (!(t->format & R200_TXFORMAT_NON_POWER2)) { + t->format |= R200_TXFORMAT_NON_POWER2; + t->base.dirty_images[0] = ~0; + } +#endif + + ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV); + + if (t->base.dirty_images[0]) { + R300_FIREVERTICES(rmesa); + r300SetTexImages(rmesa, tObj); + r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0); + if (!t->base.memBlock && !rmesa->prefer_gart_client_texturing) + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean update_tex_common(GLcontext * ctx, int unit) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; + GLenum format; + + /* Fallback if there's a texture border */ + if (tObj->Image[0][tObj->BaseLevel]->Border > 0) + return GL_FALSE; + + /* Update state if this is a different texture object to last + * time. + */ + if (rmesa->state.texture.unit[unit].texobj != t) { + if (rmesa->state.texture.unit[unit].texobj != NULL) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + rmesa->state.texture.unit[unit].texobj->base.bound &= + ~(1UL << unit); + } + + rmesa->state.texture.unit[unit].texobj = t; + t->base.bound |= (1UL << unit); + t->dirty_state |= 1 << unit; + driUpdateTextureLRU((driTextureObject *) t); /* XXX: should be locked! */ + } + +#if 0 /* do elsewhere ? */ + /* Newly enabled? + */ + if (1 + || !(rmesa->hw.ctx. + cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE << unit))) { + R300_STATECHANGE(rmesa, ctx); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_0_ENABLE | + R200_TEX_BLEND_0_ENABLE) << + unit; + + R300_STATECHANGE(rmesa, vtx); + rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3); + + rmesa->recheck_texgen[unit] = GL_TRUE; + } + + if (t->dirty_state & (1 << unit)) { + import_tex_obj_state(rmesa, unit, t); + } + + if (rmesa->recheck_texgen[unit]) { + GLboolean fallback = !r300_validate_texgen(ctx, unit); + TCL_FALLBACK(ctx, (RADEON_TCL_FALLBACK_TEXGEN_0 << unit), + fallback); + rmesa->recheck_texgen[unit] = 0; + rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; + } +#endif + + format = tObj->Image[0][tObj->BaseLevel]->Format; + if (rmesa->state.texture.unit[unit].format != format || + rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode) { + //rmesa->state.texture.unit[unit].format = format; + rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode; + if (!r300UpdateTextureEnv(ctx, unit)) { + return GL_FALSE; + } + } + +#if R200_MERGED + FALLBACK(&rmesa->radeon, RADEON_FALLBACK_BORDER_MODE, t->border_fallback); +#endif + + return !t->border_fallback; +} + +static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + if (texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT)) { + return (enable_tex_rect(ctx, unit) && + update_tex_common(ctx, unit)); + } else if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) { + return (enable_tex_2d(ctx, unit) && + update_tex_common(ctx, unit)); + } +#if ENABLE_HW_3D_TEXTURE + else if (texUnit->_ReallyEnabled & (TEXTURE_3D_BIT)) { + return (enable_tex_3d(ctx, unit) && + update_tex_common(ctx, unit)); + } +#endif + else if (texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) { + return (enable_tex_cube(ctx, unit) && + update_tex_common(ctx, unit)); + } else if (texUnit->_ReallyEnabled) { + return GL_FALSE; + } else { + disable_tex(ctx, unit); + return GL_TRUE; + } +} + +void r300UpdateTextureState(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLboolean ok; + GLuint dbg; + int i; + + ok = (r300UpdateTextureUnit(ctx, 0) && + r300UpdateTextureUnit(ctx, 1) && + r300UpdateTextureUnit(ctx, 2) && + r300UpdateTextureUnit(ctx, 3) && + r300UpdateTextureUnit(ctx, 4) && + r300UpdateTextureUnit(ctx, 5) && + r300UpdateTextureUnit(ctx, 6) && + r300UpdateTextureUnit(ctx, 7) + ); + +#if R200_MERGED + FALLBACK(&rmesa->radeon, RADEON_FALLBACK_TEXTURE, !ok); +#endif + + /* This needs correction, or just be done elsewhere + if (rmesa->radeon.TclFallback) + r300ChooseVertexState(ctx); + */ + +#if 0 /* Workaround - disable.. */ + if (GET_CHIP(rmesa->radeon.radeonScreen) == RADEON_CHIP_REAL_R200) { + /* + * T0 hang workaround ------------- + * not needed for r200 derivatives? + */ + if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == + R200_TEX_0_ENABLE + && (rmesa->hw.tex[0]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > + R200_MIN_FILTER_LINEAR) { + + R300_STATECHANGE(rmesa, ctx); + R300_STATECHANGE(rmesa, tex[1]); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE; + rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= + ~TEXOBJ_TXFORMAT_MASK; + rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= 0x08000000; + } else { + if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) + && (rmesa->hw.tex[1]. + cmd[TEX_PP_TXFORMAT] & 0x08000000)) { + R300_STATECHANGE(rmesa, tex[1]); + rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= + ~0x08000000; + } + } + + /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ? + looks like that's not the case, if 8500/9100 owners don't complain remove this... + for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) { + if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE | + R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) && + ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > + R200_MIN_FILTER_LINEAR)) { + R300_STATECHANGE(rmesa, ctx); + R300_STATECHANGE(rmesa, tex[i+1]); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i); + rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; + rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000; + } + else { + if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) && + (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) { + R300_STATECHANGE(rmesa, tex[i+1]); + rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000; + } + } + } */ + + /* + * Texture cache LRU hang workaround ------------- + * not needed for r200 derivatives? + */ + dbg = 0x0; + + if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE)) && + ((((rmesa->hw.tex[0]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) + == 0)) + || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) + && + ((((rmesa->hw.tex[2]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & + 0x04) == 0)) + || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) + && + ((((rmesa->hw.tex[4]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & + 0x04) == 0))) { + dbg |= 0x02; + } + + if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE)) && + ((((rmesa->hw.tex[1]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) + == 0)) + || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) + && + ((((rmesa->hw.tex[3]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & + 0x04) == 0)) + || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) + && + ((((rmesa->hw.tex[5]. + cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & + 0x04) == 0))) { + dbg |= 0x04; + } + + if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) { + R300_STATECHANGE(rmesa, tam); + rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg; + if (0) + printf("TEXCACHE LRU HANG WORKAROUND %x\n", + dbg); + } + } +#endif +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_vertexprog.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_vertexprog.c new file mode 100644 index 000000000..717832048 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_vertexprog.c @@ -0,0 +1,952 @@ +/************************************************************************** + +Copyright (C) 2005 Aapo Tahkola. + +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 +ATI, VA LINUX SYSTEMS AND/OR THEIR 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: + * Aapo Tahkola <aet@rasterburn.org> + */ +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "program.h" +#include "r300_context.h" +#include "r300_program.h" +#include "nvvertprog.h" + +#define SCALAR_FLAG (1<<31) +#define FLAG_MASK (1<<31) +#define OP_MASK (0xf) /* we are unlikely to have more than 15 */ +#define OPN(operator, ip, op) {#operator, VP_OPCODE_##operator, ip, op} + +static struct{ + char *name; + int opcode; + unsigned long ip; /* number of input operands and flags */ + unsigned long op; +}op_names[]={ + OPN(ABS, 1, 1), + OPN(ADD, 2, 1), + OPN(ARL, 1, 1|SCALAR_FLAG), + OPN(DP3, 2, 3|SCALAR_FLAG), + OPN(DP4, 2, 3|SCALAR_FLAG), + OPN(DPH, 2, 3|SCALAR_FLAG), + OPN(DST, 2, 1), + OPN(EX2, 1|SCALAR_FLAG, 4|SCALAR_FLAG), + OPN(EXP, 1|SCALAR_FLAG, 1), + OPN(FLR, 1, 1), + OPN(FRC, 1, 1), + OPN(LG2, 1|SCALAR_FLAG, 4|SCALAR_FLAG), + OPN(LIT, 1, 1), + OPN(LOG, 1|SCALAR_FLAG, 1), + OPN(MAD, 3, 1), + OPN(MAX, 2, 1), + OPN(MIN, 2, 1), + OPN(MOV, 1, 1), + OPN(MUL, 2, 1), + OPN(POW, 2|SCALAR_FLAG, 4|SCALAR_FLAG), + OPN(RCP, 1|SCALAR_FLAG, 4|SCALAR_FLAG), + OPN(RSQ, 1|SCALAR_FLAG, 4|SCALAR_FLAG), + OPN(SGE, 2, 1), + OPN(SLT, 2, 1), + OPN(SUB, 2, 1), + OPN(SWZ, 1, 1), + OPN(XPD, 2, 1), + OPN(RCC, 0, 0), //extra + OPN(PRINT, 0, 0), + OPN(END, 0, 0), +}; +#undef OPN +#define OPN(rf) {#rf, PROGRAM_##rf} + +static struct{ + char *name; + int id; +}register_file_names[]={ + OPN(TEMPORARY), + OPN(INPUT), + OPN(OUTPUT), + OPN(LOCAL_PARAM), + OPN(ENV_PARAM), + OPN(NAMED_PARAM), + OPN(STATE_VAR), + OPN(WRITE_ONLY), + OPN(ADDRESS), +}; + +static char *dst_mask_names[4]={ "X", "Y", "Z", "W" }; + +/* from vertex program spec: + Instruction Inputs Output Description + ----------- ------ ------ -------------------------------- + ABS v v absolute value + ADD v,v v add + ARL v a address register load + DP3 v,v ssss 3-component dot product + DP4 v,v ssss 4-component dot product + DPH v,v ssss homogeneous dot product + DST v,v v distance vector + EX2 s ssss exponential base 2 + EXP s v exponential base 2 (approximate) + FLR v v floor + FRC v v fraction + LG2 s ssss logarithm base 2 + LIT v v compute light coefficients + LOG s v logarithm base 2 (approximate) + MAD v,v,v v multiply and add + MAX v,v v maximum + MIN v,v v minimum + MOV v v move + MUL v,v v multiply + POW s,s ssss exponentiate + RCP s ssss reciprocal + RSQ s ssss reciprocal square root + SGE v,v v set on greater than or equal + SLT v,v v set on less than + SUB v,v v subtract + SWZ v v extended swizzle + XPD v,v v cross product +*/ + +void dump_program_params(GLcontext *ctx, struct vertex_program *vp) +{ + int i; + int pi; + + fprintf(stderr, "NumInstructions=%d\n", vp->Base.NumInstructions); + fprintf(stderr, "NumTemporaries=%d\n", vp->Base.NumTemporaries); + fprintf(stderr, "NumParameters=%d\n", vp->Base.NumParameters); + fprintf(stderr, "NumAttributes=%d\n", vp->Base.NumAttributes); + fprintf(stderr, "NumAddressRegs=%d\n", vp->Base.NumAddressRegs); + + _mesa_load_state_parameters(ctx, vp->Parameters); + +#if 0 + for(pi=0; pi < vp->Base.NumParameters; pi++){ + fprintf(stderr, "{ "); + for(i=0; i < 4; i++) + fprintf(stderr, "%f ", vp->Base.LocalParams[pi][i]); + fprintf(stderr, "}\n"); + } +#endif + for(pi=0; pi < vp->Parameters->NumParameters; pi++){ + fprintf(stderr, "param %02d:", pi); + + switch(vp->Parameters->Parameters[pi].Type){ + + case NAMED_PARAMETER: + fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name); + fprintf(stderr, "(NAMED_PARAMETER)"); + break; + + case CONSTANT: + fprintf(stderr, "(CONSTANT)"); + break; + + case STATE: + fprintf(stderr, "(STATE)\n"); + break; + + } + + fprintf(stderr, "{ "); + for(i=0; i < 4; i++) + fprintf(stderr, "%f ", vp->Parameters->ParameterValues[pi][i]); + fprintf(stderr, "}\n"); + + } +} + +void debug_vp(GLcontext *ctx, struct vertex_program *vp) +{ + struct vp_instruction *vpi; + int i, operand_index; + int operator_index; + + dump_program_params(ctx, vp); + + vpi=vp->Instructions; + + for(;; vpi++){ + if(vpi->Opcode == VP_OPCODE_END) + break; + + for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++){ + if(vpi->Opcode == op_names[i].opcode){ + fprintf(stderr, "%s ", op_names[i].name); + break; + } + } + operator_index=i; + + for(i=0; i < sizeof(register_file_names) / sizeof(*register_file_names); i++){ + if(vpi->DstReg.File == register_file_names[i].id){ + fprintf(stderr, "%s ", register_file_names[i].name); + break; + } + } + + fprintf(stderr, "%d.", vpi->DstReg.Index); + + for(i=0; i < 4; i++) + if(vpi->DstReg.WriteMask & (1<<i)) + fprintf(stderr, "%s", dst_mask_names[i]); + fprintf(stderr, " "); + + for(operand_index=0; operand_index < (op_names[operator_index].ip & (~FLAG_MASK)); + operand_index++){ + + if(vpi->SrcReg[operand_index].Negate) + fprintf(stderr, "-"); + + for(i=0; i < sizeof(register_file_names) / sizeof(*register_file_names); i++){ + if(vpi->SrcReg[operand_index].File == register_file_names[i].id){ + fprintf(stderr, "%s ", register_file_names[i].name); + break; + } + } + fprintf(stderr, "%d.", vpi->SrcReg[operand_index].Index); + + for(i=0; i < 4; i++) + fprintf(stderr, "%s", dst_mask_names[GET_SWZ(vpi->SrcReg[operand_index].Swizzle, i)]); + + if(operand_index+1 < (op_names[operator_index].ip & (~FLAG_MASK)) ) + fprintf(stderr, ","); + } + fprintf(stderr, "\n"); + } + +} + +void r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp) +{ + int pi; + struct vertex_program *mesa_vp=(void *)vp; + int dst_index; + + _mesa_load_state_parameters(ctx, mesa_vp->Parameters); + + //debug_vp(ctx, mesa_vp); + if(mesa_vp->Parameters->NumParameters * 4 > VSF_MAX_FRAGMENT_LENGTH){ + fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__); + exit(-1); + } + dst_index=0; + for(pi=0; pi < mesa_vp->Parameters->NumParameters; pi++){ + switch(mesa_vp->Parameters->Parameters[pi].Type){ + + case STATE: + case NAMED_PARAMETER: + //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name); + case CONSTANT: + vp->params.body.f[dst_index++]=mesa_vp->Parameters->ParameterValues[pi][0]; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->ParameterValues[pi][1]; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->ParameterValues[pi][2]; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->ParameterValues[pi][3]; + break; + + default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__); + } + + } + + vp->params.length=dst_index; +} + +static unsigned long t_dst_mask(GLuint mask) +{ + unsigned long flags=0; + + if(mask & WRITEMASK_X) flags |= VSF_FLAG_X; + if(mask & WRITEMASK_Y) flags |= VSF_FLAG_Y; + if(mask & WRITEMASK_Z) flags |= VSF_FLAG_Z; + if(mask & WRITEMASK_W) flags |= VSF_FLAG_W; + + return flags; +} + +static unsigned long t_dst_class(enum register_file file) +{ + + switch(file){ + case PROGRAM_TEMPORARY: + return VSF_OUT_CLASS_TMP; + case PROGRAM_OUTPUT: + return VSF_OUT_CLASS_RESULT; + /* + case PROGRAM_INPUT: + case PROGRAM_LOCAL_PARAM: + case PROGRAM_ENV_PARAM: + case PROGRAM_NAMED_PARAM: + case PROGRAM_STATE_VAR: + case PROGRAM_WRITE_ONLY: + case PROGRAM_ADDRESS: + */ + default: + fprintf(stderr, "problem in %s", __FUNCTION__); + exit(0); + } +} + +static unsigned long t_dst_index(struct r300_vertex_program *vp, struct vp_dst_register *dst) +{ + if(dst->File == PROGRAM_OUTPUT) { + if (vp->outputs[dst->Index] != -1) + return vp->outputs[dst->Index]; + else { + WARN_ONCE("Unknown output %d\n", dst->Index); + return 10; + } + } + return dst->Index; +} + +static unsigned long t_src_class(enum register_file file) +{ + + switch(file){ + case PROGRAM_TEMPORARY: + return VSF_IN_CLASS_TMP; + + case PROGRAM_INPUT: + return VSF_IN_CLASS_ATTR; + + case PROGRAM_LOCAL_PARAM: + case PROGRAM_ENV_PARAM: + case PROGRAM_NAMED_PARAM: + case PROGRAM_STATE_VAR: + return VSF_IN_CLASS_PARAM; + /* + case PROGRAM_OUTPUT: + case PROGRAM_WRITE_ONLY: + case PROGRAM_ADDRESS: + */ + default: + fprintf(stderr, "problem in %s", __FUNCTION__); + exit(0); + } +} + +static unsigned long t_swizzle(GLubyte swizzle) +{ + switch(swizzle){ + case SWIZZLE_X: return VSF_IN_COMPONENT_X; + case SWIZZLE_Y: return VSF_IN_COMPONENT_Y; + case SWIZZLE_Z: return VSF_IN_COMPONENT_Z; + case SWIZZLE_W: return VSF_IN_COMPONENT_W; + case SWIZZLE_ZERO: return VSF_IN_COMPONENT_ZERO; + case SWIZZLE_ONE: return VSF_IN_COMPONENT_ONE; + default: + fprintf(stderr, "problem in %s", __FUNCTION__); + exit(0); + } +} + +static void vp_dump_inputs(struct r300_vertex_program *vp, char *caller) +{ + int i; + + if(vp == NULL){ + fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, caller); + return ; + } + + fprintf(stderr, "%s:<", caller); + for(i=0; i < VERT_ATTRIB_MAX; i++) + fprintf(stderr, "%d ", vp->inputs[i]); + fprintf(stderr, ">\n"); + +} + +static unsigned long t_src_index(struct r300_vertex_program *vp, struct vp_src_register *src) +{ + int i; + int max_reg=-1; + + if(src->File == PROGRAM_INPUT){ + if(vp->inputs[src->Index] != -1) + return vp->inputs[src->Index]; + + for(i=0; i < VERT_ATTRIB_MAX; i++) + if(vp->inputs[i] > max_reg) + max_reg=vp->inputs[i]; + + vp->inputs[src->Index]=max_reg+1; + + //vp_dump_inputs(vp, __FUNCTION__); + + return vp->inputs[src->Index]; + }else{ + return src->Index; + } +} + +static unsigned long t_src(struct r300_vertex_program *vp, struct vp_src_register *src) +{ + + return MAKE_VSF_SOURCE(t_src_index(vp, src), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 1)), + t_swizzle(GET_SWZ(src->Swizzle, 2)), + t_swizzle(GET_SWZ(src->Swizzle, 3)), + t_src_class(src->File), + src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); +} + +static unsigned long t_src_scalar(struct r300_vertex_program *vp, struct vp_src_register *src) +{ + + return MAKE_VSF_SOURCE(t_src_index(vp, src), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_src_class(src->File), + src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); +} + +static unsigned long t_opcode(enum vp_opcode opcode) +{ + + switch(opcode){ + case VP_OPCODE_DST: return R300_VPI_OUT_OP_DST; + case VP_OPCODE_EX2: return R300_VPI_OUT_OP_EX2; + case VP_OPCODE_EXP: return R300_VPI_OUT_OP_EXP; + case VP_OPCODE_FRC: return R300_VPI_OUT_OP_FRC; + case VP_OPCODE_LG2: return R300_VPI_OUT_OP_LG2; + case VP_OPCODE_LOG: return R300_VPI_OUT_OP_LOG; + case VP_OPCODE_MAX: return R300_VPI_OUT_OP_MAX; + case VP_OPCODE_MIN: return R300_VPI_OUT_OP_MIN; + case VP_OPCODE_MUL: return R300_VPI_OUT_OP_MUL; + case VP_OPCODE_POW: return R300_VPI_OUT_OP_POW; + case VP_OPCODE_RCP: return R300_VPI_OUT_OP_RCP; + case VP_OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ; + case VP_OPCODE_SGE: return R300_VPI_OUT_OP_SGE; + case VP_OPCODE_SLT: return R300_VPI_OUT_OP_SLT; + case VP_OPCODE_DP4: return R300_VPI_OUT_OP_DOT; + + default: + fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode); + } + exit(-1); + return 0; +} + +static unsigned long op_operands(enum vp_opcode opcode) +{ + int i; + + /* Can we trust mesas opcodes to be in order ? */ + for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++) + if(op_names[i].opcode == opcode) + return op_names[i].ip; + + fprintf(stderr, "op %d not found in op_names\n", opcode); + exit(-1); + return 0; +} + +/* TODO: Get rid of t_src_class call */ +#define CMP_SRCS(a, b) (a.Index != b.Index && \ + ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ + t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \ + (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \ + t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \ + +#define SRCS_WRITABLE 1 +void translate_vertex_shader(struct r300_vertex_program *vp) +{ + struct vertex_program *mesa_vp=(void *)vp; + struct vp_instruction *vpi; + int i, cur_reg=0; + VERTEX_SHADER_INSTRUCTION *o_inst; + unsigned long operands; + int are_srcs_scalar; + unsigned long hw_op; + /* Initial value should be last tmp reg that hw supports. + Strangely enough r300 doesnt mind even though these would be out of range. + Smart enough to realize that it doesnt need it? */ + int u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; +#ifdef SRCS_WRITABLE + struct vp_src_register src[3]; +#else +#define src vpi->SrcReg +#endif + vp->pos_end=0; /* Not supported yet */ + vp->program.length=0; + vp->num_temporaries=mesa_vp->Base.NumTemporaries; + + for(i=0; i < VERT_ATTRIB_MAX; i++) + vp->inputs[i] = -1; + + for(i=0; i < VERT_RESULT_MAX; i++) + vp->outputs[i] = -1; + + assert(mesa_vp->OutputsWritten & (1 << VERT_RESULT_HPOS)); + assert(mesa_vp->OutputsWritten & (1 << VERT_RESULT_COL0)); + + /* Assign outputs */ + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_HPOS)) + vp->outputs[VERT_RESULT_HPOS] = cur_reg++; + + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_PSIZ)) + vp->outputs[VERT_RESULT_PSIZ] = cur_reg++; + + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_COL0)) + vp->outputs[VERT_RESULT_COL0] = cur_reg++; + +#if 0 /* Not supported yet */ + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_BFC0)) + vp->outputs[VERT_RESULT_BFC0] = cur_reg++; + + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_COL1)) + vp->outputs[VERT_RESULT_COL1] = cur_reg++; + + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_BFC1)) + vp->outputs[VERT_RESULT_BFC1] = cur_reg++; + + if(mesa_vp->OutputsWritten & (1 << VERT_RESULT_FOGC)) + vp->outputs[VERT_RESULT_FOGC] = cur_reg++; +#endif + + for(i=VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) + if(mesa_vp->OutputsWritten & (1 << i)) + vp->outputs[i] = cur_reg++; + + o_inst=vp->program.body.i; + for(vpi=mesa_vp->Instructions; vpi->Opcode != VP_OPCODE_END; vpi++, o_inst++){ + + operands=op_operands(vpi->Opcode); + are_srcs_scalar=operands & SCALAR_FLAG; + operands &= OP_MASK; + + for(i=0; i < operands; i++) + src[i]=vpi->SrcReg[i]; +#if 1 + if(operands == 3){ /* TODO: scalars */ + if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){ + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i, + VSF_FLAG_ALL, VSF_OUT_CLASS_TMP); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), + SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_W, + t_src_class(src[2].File), VSF_FLAG_NONE); + + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), + SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ZERO, + t_src_class(src[2].File), VSF_FLAG_NONE); + o_inst->src3=0; + o_inst++; + + src[2].File=PROGRAM_TEMPORARY; + src[2].Index=u_temp_i; + u_temp_i--; + } + + } + if(operands >= 2){ + if( CMP_SRCS(src[1], src[0]) ){ + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i, + VSF_FLAG_ALL, VSF_OUT_CLASS_TMP); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_W, + t_src_class(src[0].File), VSF_FLAG_NONE); + + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ZERO, + t_src_class(src[0].File), VSF_FLAG_NONE); + o_inst->src3=0; + o_inst++; + + src[0].File=PROGRAM_TEMPORARY; + src[0].Index=u_temp_i; + u_temp_i--; + } + } +#endif + /* these ops need special handling. + Ops that need temp vars should probably be given reg indexes starting at the end of tmp area. */ + switch(vpi->Opcode){ + case VP_OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ZERO, + t_src_class(src[0].File), VSF_FLAG_NONE); + + o_inst->src3=0; + + goto next; + + case VP_OPCODE_ADD: + hw_op=(src[0].File == PROGRAM_TEMPORARY && + src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD; + + o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + SWIZZLE_ONE, SWIZZLE_ONE, + SWIZZLE_ONE, SWIZZLE_ONE, + t_src_class(src[0].File), VSF_FLAG_NONE); + o_inst->src3=t_src(vp, &src[1]); + goto next; + + case VP_OPCODE_MAD: + hw_op=(src[0].File == PROGRAM_TEMPORARY && + src[1].File == PROGRAM_TEMPORARY && + src[2].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD; + + o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=t_src(vp, &src[1]); + o_inst->src3=t_src(vp, &src[2]); + goto next; + + case VP_OPCODE_MUL: /* HW mul can take third arg but appears to have some other limitations. */ + hw_op=(src[0].File == PROGRAM_TEMPORARY && + src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD; + + o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=t_src(vp, &src[1]); + + o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ZERO, + t_src_class(src[1].File), VSF_FLAG_NONE); + goto next; + + case VP_OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), + SWIZZLE_ZERO, + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_XYZ : VSF_FLAG_NONE); + + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), + t_swizzle(GET_SWZ(src[1].Swizzle, 1)), + t_swizzle(GET_SWZ(src[1].Swizzle, 2)), + SWIZZLE_ZERO, + t_src_class(src[1].File), + src[1].Negate ? VSF_FLAG_XYZ : VSF_FLAG_NONE); + + o_inst->src3=0; + goto next; + + case VP_OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W +#if 1 + hw_op=(src[0].File == PROGRAM_TEMPORARY && + src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD; + + o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + SWIZZLE_ONE, SWIZZLE_ONE, + SWIZZLE_ONE, SWIZZLE_ONE, + t_src_class(src[0].File), VSF_FLAG_NONE); + o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), + t_swizzle(GET_SWZ(src[1].Swizzle, 1)), + t_swizzle(GET_SWZ(src[1].Swizzle, 2)), + t_swizzle(GET_SWZ(src[1].Swizzle, 3)), + t_src_class(src[1].File), + (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE); +#else + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), + t_swizzle(GET_SWZ(src[1].Swizzle, 1)), + t_swizzle(GET_SWZ(src[1].Swizzle, 2)), + t_swizzle(GET_SWZ(src[1].Swizzle, 3)), + t_src_class(src[1].File), + (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE); + o_inst->src3=0; +#endif + goto next; + + case VP_OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), + t_src_class(src[0].File), + (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE); + o_inst->src3=0; + goto next; + + case VP_OPCODE_FLR: + /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} + ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */ + + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, u_temp_i, + t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP); + + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=0; + o_inst->src3=0; + o_inst++; + + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=MAKE_VSF_SOURCE(u_temp_i, + VSF_IN_COMPONENT_X, + VSF_IN_COMPONENT_Y, + VSF_IN_COMPONENT_Z, + VSF_IN_COMPONENT_W, + VSF_IN_CLASS_TMP, + /* Not 100% sure about this */ + (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/); + + o_inst->src3=0; + u_temp_i--; + goto next; + + case VP_OPCODE_LG2:// LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_LG2, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + o_inst->src2=0; + o_inst->src3=0; + goto next; + + case VP_OPCODE_LIT://LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_LIT, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + /* NOTE: Users swizzling might not work. */ + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + goto next; + + case VP_OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), + VSF_IN_COMPONENT_ONE, + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_XYZ : VSF_FLAG_NONE); + o_inst->src2=t_src(vp, &src[1]); + o_inst->src3=0; + goto next; + + case VP_OPCODE_XPD: + /* mul r0, r1.yzxw, r2.zxyw + mad r0, -r2.yzxw, r1.zxyw, r0 + NOTE: might need MAD_2 + */ + + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, u_temp_i, + t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w + t_src_class(src[1].File), + src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + + o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ZERO, + t_src_class(src[1].File), + VSF_FLAG_NONE); + o_inst++; + u_temp_i--; + + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w + t_src_class(src[1].File), + (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE); + + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_src_class(src[0].File), + src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + + o_inst->src3=MAKE_VSF_SOURCE(u_temp_i+1, + VSF_IN_COMPONENT_X, + VSF_IN_COMPONENT_Y, + VSF_IN_COMPONENT_Z, + VSF_IN_COMPONENT_W, + VSF_IN_CLASS_TMP, + VSF_FLAG_NONE); + + goto next; + + case VP_OPCODE_ARL: + case VP_OPCODE_SWZ: + case VP_OPCODE_RCC: + case VP_OPCODE_PRINT: + //vp->num_temporaries++; + fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode); + exit(-1); + break; + case VP_OPCODE_END: + break; + default: + break; + } + + o_inst->op=MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + if(are_srcs_scalar){ + switch(operands){ + case 1: + o_inst->src1=t_src_scalar(vp, &src[0]); + o_inst->src2=0; + o_inst->src3=0; + break; + + case 2: + o_inst->src1=t_src_scalar(vp, &src[0]); + o_inst->src2=t_src_scalar(vp, &src[1]); + o_inst->src3=0; + break; + + case 3: + o_inst->src1=t_src_scalar(vp, &src[0]); + o_inst->src2=t_src_scalar(vp, &src[1]); + o_inst->src3=t_src_scalar(vp, &src[2]); + break; + + default: + fprintf(stderr, "scalars and op RCC not handled yet"); + exit(-1); + break; + } + }else{ + switch(operands){ + case 1: + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=0; + o_inst->src3=0; + break; + + case 2: + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=t_src(vp, &src[1]); + o_inst->src3=0; + break; + + case 3: + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=t_src(vp, &src[1]); + o_inst->src3=t_src(vp, &src[2]); + break; + + default: + fprintf(stderr, "scalars and op RCC not handled yet"); + exit(-1); + break; + } + } + next: ; + } + + vp->program.length=(o_inst - vp->program.body.i) * 4; + + if(u_temp_i < vp->num_temporaries) + vp->translated=GL_FALSE; /* temps exhausted - program cannot be run */ + else + vp->translated=GL_TRUE; +} + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_context.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_context.c new file mode 100644 index 000000000..97507617c --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_context.c @@ -0,0 +1,312 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/** + * \file radeon_context.c + * Common context initialization. + * + * \author Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <dlfcn.h> + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "state.h" +#include "matrix.h" +#include "framebuffer.h" + +#include "drivers/common/driverfuncs.h" +#include "swrast/swrast.h" + +#include "radeon_screen.h" +#include "r200_context.h" +#include "radeon_ioctl.h" +#include "radeon_macros.h" +#include "radeon_reg.h" +#include "r200_state.h" + +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" /* for symbolic values of enum-type options */ + +#define DRIVER_DATE "20040924" + + +/* Return various strings for glGetString(). + */ +static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + static char buffer[128]; + + switch (name) { + case GL_VENDOR: + return (GLubyte *) "Tungsten Graphics, Inc."; + + case GL_RENDERER: + { + unsigned offset; + GLuint agp_mode = radeon->radeonScreen->IsPCI ? 0 : + radeon->radeonScreen->AGPMode; + const char* chipname; + + if (IS_FAMILY_R300(radeon)) + chipname = "R300"; + else + chipname = "R200"; + + offset = driGetRendererString(buffer, chipname, DRIVER_DATE, + agp_mode); + + sprintf(&buffer[offset], " %sTCL", + !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) + ? "" : "NO-"); + + return (GLubyte *) buffer; + } + + default: + return NULL; + } +} + + +/* Return the width and height of the given buffer. + */ +static void radeonGetBufferSize(GLframebuffer * buffer, + GLuint * width, GLuint * height) +{ + GET_CURRENT_CONTEXT(ctx); + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + LOCK_HARDWARE(radeon); + *width = radeon->dri.drawable->w; + *height = radeon->dri.drawable->h; + UNLOCK_HARDWARE(radeon); +} + + +/* Initialize the driver's misc functions. + */ +static void radeonInitDriverFuncs(struct dd_function_table *functions) +{ + functions->GetBufferSize = radeonGetBufferSize; + functions->ResizeBuffers = _mesa_resize_framebuffer; + functions->GetString = radeonGetString; +} + + +/** + * Create and initialize all common fields of the context, + * including the Mesa context itself. + */ +GLboolean radeonInitContext(radeonContextPtr radeon, + struct dd_function_table* functions, + const __GLcontextModes * glVisual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate) +{ + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private); + GLcontext* ctx; + GLcontext* shareCtx; + int fthrottle_mode; + + /* Fill in additional standard functions. */ + radeonInitDriverFuncs(functions); + + /* Allocate and initialize the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + radeon->glCtx = _mesa_create_context(glVisual, shareCtx, + functions, (void *)radeon); + if (!radeon->glCtx) + return GL_FALSE; + + ctx = radeon->glCtx; + driContextPriv->driverPrivate = radeon; + + /* DRI fields */ + radeon->dri.context = driContextPriv; + radeon->dri.screen = sPriv; + radeon->dri.drawable = NULL; /* Set by XMesaMakeCurrent */ + radeon->dri.hwContext = driContextPriv->hHWContext; + radeon->dri.hwLock = &sPriv->pSAREA->lock; + radeon->dri.fd = sPriv->fd; + radeon->dri.drmMinor = sPriv->drmMinor; + + radeon->radeonScreen = screen; + radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA + + screen->sarea_priv_offset); + + /* Setup IRQs */ + fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode"); + radeon->iw.irq_seq = -1; + radeon->irqsEmitted = 0; + radeon->do_irqs = (radeon->dri.drmMinor >= 6 && + fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS && + radeon->radeonScreen->irq); + + radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); + + if (!radeon->do_irqs) + fprintf(stderr, + "IRQ's not enabled, falling back to %s: %d %d %d\n", + radeon->do_usleeps ? "usleeps" : "busy waits", + radeon->dri.drmMinor, + fthrottle_mode, radeon->radeonScreen->irq); + + radeon->vblank_flags = (radeon->radeonScreen->irq != 0) + ? driGetDefaultVBlankFlags(&radeon->optionCache) : VBLANK_FLAG_NO_IRQ; + + (*dri_interface->getUST) (&radeon->swap_ust); + + return GL_TRUE; +} + + +/** + * Cleanup common context fields. + * Called by r200DestroyContext/r300DestroyContext + */ +void radeonCleanupContext(radeonContextPtr radeon) +{ + /* free the Mesa context */ + radeon->glCtx->DriverCtx = NULL; + _mesa_destroy_context(radeon->glCtx); + + if (radeon->state.scissor.pClipRects) { + FREE(radeon->state.scissor.pClipRects); + radeon->state.scissor.pClipRects = 0; + } +} + + +/** + * Swap front and back buffer. + */ +void radeonSwapBuffers(__DRIdrawablePrivate * dPriv) +{ + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + radeonContextPtr radeon; + GLcontext *ctx; + + radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; + ctx = radeon->glCtx; + + if (ctx->Visual.doubleBufferMode) { + _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ + if (radeon->doPageFlip) { + radeonPageFlip(dPriv); + } else { + radeonCopyBuffer(dPriv); + } + } + } else { + /* XXX this shouldn't be an error but we can't handle it for now */ + _mesa_problem(NULL, "%s: drawable has no context!", + __FUNCTION__); + } +} + + +/* Force the context `c' to be the current context and associate with it + * buffer `b'. + */ +GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv) +{ + if (driContextPriv) { + radeonContextPtr radeon = + (radeonContextPtr) driContextPriv->driverPrivate; + + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, + radeon->glCtx); + + if (radeon->dri.drawable != driDrawPriv) { + driDrawableInitVBlank(driDrawPriv, + radeon->vblank_flags); + radeon->dri.drawable = driDrawPriv; + +#if R200_MERGED + if (IS_FAMILY_R200(radeon)) { + r200UpdateWindow(radeon->glCtx); + r200UpdateViewportOffset(radeon->glCtx); + } +#endif + } + + _mesa_make_current(radeon->glCtx, + (GLframebuffer *) driDrawPriv-> + driverPrivate, + (GLframebuffer *) driReadPriv-> + driverPrivate); + + if (!radeon->glCtx->Viewport.Width) { + _mesa_set_viewport(radeon->glCtx, 0, 0, + driDrawPriv->w, driDrawPriv->h); + } + + _mesa_update_state(radeon->glCtx); + +#if R200_MERGED + if (IS_FAMILY_R200(radeon)) + r200ValidateState(radeon->glCtx); +#endif + + } else { + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx is null\n", __FUNCTION__); + _mesa_make_current(0, 0, 0); + } + + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "End %s\n", __FUNCTION__); + return GL_TRUE; +} + +/* Force the context `c' to be unbound from its buffer. + */ +GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv) +{ + radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate; + + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, + radeon->glCtx); + + return GL_TRUE; +} + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_context.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_context.h new file mode 100644 index 000000000..189bc6ad0 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_context.h @@ -0,0 +1,249 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __RADEON_CONTEXT_H__ +#define __RADEON_CONTEXT_H__ + +#include "mtypes.h" +#include "radeon_screen.h" +#include "drm.h" +#include "dri_util.h" + +struct radeon_context; +typedef struct radeon_context radeonContextRec; +typedef struct radeon_context* radeonContextPtr; + +static __inline GLuint radeonPackColor(GLuint cpp, + GLubyte r, GLubyte g, GLubyte b, GLubyte a) +{ + switch (cpp) { + case 2: + return PACK_COLOR_565(r, g, b); + case 4: + return PACK_COLOR_8888(a, r, g, b); + default: + return 0; + } +} + +#define TEX_0 0x1 +#define TEX_1 0x2 +#define TEX_2 0x4 +#define TEX_3 0x8 +#define TEX_4 0x10 +#define TEX_5 0x20 +#define TEX_6 0x40 +#define TEX_7 0x80 +#define TEX_ALL 0xff + + +/* Rasterizing fallbacks */ +/* See correponding strings in r200_swtcl.c */ +#define RADEON_FALLBACK_TEXTURE 0x01 +#define RADEON_FALLBACK_DRAW_BUFFER 0x02 +#define RADEON_FALLBACK_STENCIL 0x04 +#define RADEON_FALLBACK_RENDER_MODE 0x08 +#define RADEON_FALLBACK_BLEND_EQ 0x10 +#define RADEON_FALLBACK_BLEND_FUNC 0x20 +#define RADEON_FALLBACK_DISABLE 0x40 +#define RADEON_FALLBACK_BORDER_MODE 0x80 + +#if R200_MERGED +extern void radeonFallback(GLcontext * ctx, GLuint bit, GLboolean mode); + +#define FALLBACK( radeon, bit, mode ) do { \ + if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \ + __FUNCTION__, bit, mode ); \ + radeonFallback( (radeon)->glCtx, bit, mode ); \ +} while (0) +#else +#define FALLBACK( radeon, bit, mode ) fprintf(stderr, "%s:%s\n", __LINE__, __FILE__); +#endif + +/* TCL fallbacks */ +extern void radeonTclFallback(GLcontext * ctx, GLuint bit, GLboolean mode); + +#define RADEON_TCL_FALLBACK_RASTER 0x0001 /* rasterization */ +#define RADEON_TCL_FALLBACK_UNFILLED 0x0002 /* unfilled tris */ +#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x0004 /* twoside tris */ +#define RADEON_TCL_FALLBACK_MATERIAL 0x0008 /* material in vb */ +#define RADEON_TCL_FALLBACK_TEXGEN_0 0x0010 /* texgen, unit 0 */ +#define RADEON_TCL_FALLBACK_TEXGEN_1 0x0020 /* texgen, unit 1 */ +#define RADEON_TCL_FALLBACK_TEXGEN_2 0x0040 /* texgen, unit 2 */ +#define RADEON_TCL_FALLBACK_TEXGEN_3 0x0080 /* texgen, unit 3 */ +#define RADEON_TCL_FALLBACK_TEXGEN_4 0x0100 /* texgen, unit 4 */ +#define RADEON_TCL_FALLBACK_TEXGEN_5 0x0200 /* texgen, unit 5 */ +#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x0400 /* user disable */ +#define RADEON_TCL_FALLBACK_BITMAP 0x0800 /* draw bitmap with points */ +#define RADEON_TCL_FALLBACK_VERTEX_PROGRAM 0x1000 /* vertex program active */ + +#if R200_MERGED +#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode ) +#else +#define TCL_FALLBACK( ctx, bit, mode ) ; +#endif + + +struct radeon_dri_mirror { + __DRIcontextPrivate *context; /* DRI context */ + __DRIscreenPrivate *screen; /* DRI screen */ + __DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */ + + drm_context_t hwContext; + drm_hw_lock_t *hwLock; + int fd; + int drmMinor; +}; + +/** + * Derived state for internal purposes. + */ +struct radeon_scissor_state { + drm_clip_rect_t rect; + GLboolean enabled; + + GLuint numClipRects; /* Cliprects active */ + GLuint numAllocedClipRects; /* Cliprects available */ + drm_clip_rect_t *pClipRects; +}; + +struct radeon_colorbuffer_state { + GLuint clear; + GLint drawOffset, drawPitch; +}; + +struct radeon_pixel_state { + GLint readOffset, readPitch; +}; + +struct radeon_state { + struct radeon_colorbuffer_state color; + struct radeon_pixel_state pixel; + struct radeon_scissor_state scissor; +}; + +/** + * Common per-context variables shared by R200 and R300. + * R200- and R300-specific code "derive" their own context from this + * structure. + */ +struct radeon_context { + GLcontext *glCtx; /* Mesa context */ + radeonScreenPtr radeonScreen; /* Screen private DRI data */ + + /* Fallback state */ + GLuint Fallback; + GLuint TclFallback; + + /* Page flipping */ + GLuint doPageFlip; + + /* Drawable, cliprect and scissor information */ + GLuint numClipRects; /* Cliprects for the draw buffer */ + drm_clip_rect_t *pClipRects; + unsigned int lastStamp; + GLboolean lost_context; + drm_radeon_sarea_t *sarea; /* Private SAREA data */ + + /* Mirrors of some DRI state */ + struct radeon_dri_mirror dri; + + /* Busy waiting */ + GLuint do_usleeps; + GLuint do_irqs; + GLuint irqsEmitted; + drm_radeon_irq_wait_t iw; + + /* VBI / buffer swap */ + GLuint vbl_seq; + GLuint vblank_flags; + + int64_t swap_ust; + int64_t swap_missed_ust; + + GLuint swap_count; + GLuint swap_missed_count; + + + /* Derived state */ + struct radeon_state state; + + /* Configuration cache + */ + driOptionCache optionCache; +}; + +#define RADEON_CONTEXT(glctx) ((radeonContextPtr)(ctx->DriverCtx)) + +extern void radeonSwapBuffers(__DRIdrawablePrivate * dPriv); +extern GLboolean radeonInitContext(radeonContextPtr radeon, + struct dd_function_table* functions, + const __GLcontextModes * glVisual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate); +extern void radeonCleanupContext(radeonContextPtr radeon); +extern GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv); +extern GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv); + +/* ================================================================ + * Debugging: + */ +#define DO_DEBUG 1 + +#if DO_DEBUG +extern int RADEON_DEBUG; +#else +#define RADEON_DEBUG 0 +#endif + +#define DEBUG_TEXTURE 0x0001 +#define DEBUG_STATE 0x0002 +#define DEBUG_IOCTL 0x0004 +#define DEBUG_PRIMS 0x0008 +#define DEBUG_VERTS 0x0010 +#define DEBUG_FALLBACKS 0x0020 +#define DEBUG_VFMT 0x0040 +#define DEBUG_CODEGEN 0x0080 +#define DEBUG_VERBOSE 0x0100 +#define DEBUG_DRI 0x0200 +#define DEBUG_DMA 0x0400 +#define DEBUG_SANITY 0x0800 +#define DEBUG_SYNC 0x1000 +#define DEBUG_PIXEL 0x2000 +#define DEBUG_MEMORY 0x4000 + +#endif /* __RADEON_CONTEXT_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_ioctl.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_ioctl.c new file mode 100644 index 000000000..af489e2a8 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_ioctl.c @@ -0,0 +1,372 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <sched.h> +#include <errno.h> + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "context.h" +#include "swrast/swrast.h" +#include "r200_context.h" +#include "r300_context.h" +#include "r200_state.h" +#include "radeon_ioctl.h" +#include "r200_ioctl.h" +#include "r300_ioctl.h" +#include "r200_tcl.h" +#include "r200_sanity.h" +#include "r300_state.h" +#include "radeon_reg.h" + +#include "vblank.h" + +static void radeonWaitForIdle(radeonContextPtr radeon); + +/* ================================================================ + * SwapBuffers with client-side throttling + */ + +static uint32_t radeonGetLastFrame(radeonContextPtr radeon) +{ + drm_radeon_getparam_t gp; + int ret; + uint32_t frame; + + gp.param = RADEON_PARAM_LAST_FRAME; + gp.value = (int *)&frame; + ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, + ret); + exit(1); + } + + return frame; +} + +static void radeonEmitIrqLocked(radeonContextPtr radeon) +{ + drm_radeon_irq_emit_t ie; + int ret; + + ie.irq_seq = &radeon->iw.irq_seq; + ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_IRQ_EMIT, + &ie, sizeof(ie)); + if (ret) { + fprintf(stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, + ret); + exit(1); + } +} + +static void radeonWaitIrq(radeonContextPtr radeon) +{ + int ret; + + do { + ret = drmCommandWrite(radeon->dri.fd, DRM_RADEON_IRQ_WAIT, + &radeon->iw, sizeof(radeon->iw)); + } while (ret && (errno == EINTR || errno == EAGAIN)); + + if (ret) { + fprintf(stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, + ret); + exit(1); + } +} + +static void radeonWaitForFrameCompletion(radeonContextPtr radeon) +{ + drm_radeon_sarea_t *sarea = radeon->sarea; + + if (radeon->do_irqs) { + if (radeonGetLastFrame(radeon) < sarea->last_frame) { + if (!radeon->irqsEmitted) { + while (radeonGetLastFrame(radeon) < + sarea->last_frame) ; + } else { + UNLOCK_HARDWARE(radeon); + radeonWaitIrq(radeon); + LOCK_HARDWARE(radeon); + } + radeon->irqsEmitted = 10; + } + + if (radeon->irqsEmitted) { + radeonEmitIrqLocked(radeon); + radeon->irqsEmitted--; + } + } else { + while (radeonGetLastFrame(radeon) < sarea->last_frame) { + UNLOCK_HARDWARE(radeon); + if (radeon->do_usleeps) + DO_USLEEP(1); + LOCK_HARDWARE(radeon); + } + } +} + +/* Copy the back color buffer to the front color buffer. + */ +void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv) +{ + radeonContextPtr radeon; + GLint nbox, i, ret; + GLboolean missed_target; + int64_t ust; + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; + + if (RADEON_DEBUG & DEBUG_IOCTL) { + fprintf(stderr, "\n%s( %p )\n\n", __FUNCTION__, + (void *)radeon->glCtx); + } + + if (IS_FAMILY_R200(radeon)) + R200_FIREVERTICES((r200ContextPtr)radeon); + else + r300Flush(radeon->glCtx); + + LOCK_HARDWARE(radeon); + + /* Throttle the frame rate -- only allow one pending swap buffers + * request at a time. + */ + radeonWaitForFrameCompletion(radeon); + UNLOCK_HARDWARE(radeon); + driWaitForVBlank(dPriv, &radeon->vbl_seq, radeon->vblank_flags, + &missed_target); + LOCK_HARDWARE(radeon); + + nbox = dPriv->numClipRects; /* must be in locked region */ + + for (i = 0; i < nbox;) { + GLint nr = MIN2(i + RADEON_NR_SAREA_CLIPRECTS, nbox); + drm_clip_rect_t *box = dPriv->pClipRects; + drm_clip_rect_t *b = radeon->sarea->boxes; + GLint n = 0; + + for (; i < nr; i++) { + *b++ = box[i]; + n++; + } + radeon->sarea->nbox = n; + + ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_SWAP); + + if (ret) { + fprintf(stderr, "DRM_RADEON_SWAP: return = %d\n", + ret); + UNLOCK_HARDWARE(radeon); + exit(1); + } + } + + UNLOCK_HARDWARE(radeon); + + if (IS_FAMILY_R200(radeon)) + ((r200ContextPtr)radeon)->hw.all_dirty = GL_TRUE; + else + ((r300ContextPtr)radeon)->hw.all_dirty = GL_TRUE; + + radeon->swap_count++; + (*dri_interface->getUST) (&ust); + if (missed_target) { + radeon->swap_missed_count++; + radeon->swap_missed_ust = ust - radeon->swap_ust; + } + + radeon->swap_ust = ust; + + sched_yield(); +} + +void radeonPageFlip(const __DRIdrawablePrivate * dPriv) +{ + radeonContextPtr radeon; + GLint ret; + GLboolean missed_target; + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; + + if (RADEON_DEBUG & DEBUG_IOCTL) { + fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__, + radeon->sarea->pfCurrentPage); + } + + if (IS_FAMILY_R200(radeon)) + R200_FIREVERTICES((r200ContextPtr)radeon); + else + r300Flush(radeon->glCtx); + LOCK_HARDWARE(radeon); + + if (!dPriv->numClipRects) { + UNLOCK_HARDWARE(radeon); + usleep(10000); /* throttle invisible client 10ms */ + return; + } + + /* Need to do this for the perf box placement: + */ + { + drm_clip_rect_t *box = dPriv->pClipRects; + drm_clip_rect_t *b = radeon->sarea->boxes; + b[0] = box[0]; + radeon->sarea->nbox = 1; + } + + /* Throttle the frame rate -- only allow a few pending swap buffers + * request at a time. + */ + radeonWaitForFrameCompletion(radeon); + UNLOCK_HARDWARE(radeon); + driWaitForVBlank(dPriv, &radeon->vbl_seq, radeon->vblank_flags, + &missed_target); + if (missed_target) { + radeon->swap_missed_count++; + (void)(*dri_interface->getUST) (&radeon->swap_missed_ust); + } + LOCK_HARDWARE(radeon); + + ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_FLIP); + + UNLOCK_HARDWARE(radeon); + + if (ret) { + fprintf(stderr, "DRM_RADEON_FLIP: return = %d\n", ret); + exit(1); + } + + radeon->swap_count++; + (void)(*dri_interface->getUST) (&radeon->swap_ust); + + if (radeon->sarea->pfCurrentPage == 1) { + radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset; + radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch; + } else { + radeon->state.color.drawOffset = radeon->radeonScreen->backOffset; + radeon->state.color.drawPitch = radeon->radeonScreen->backPitch; + } + + if (IS_FAMILY_R200(radeon)) { + r200ContextPtr r200 = (r200ContextPtr)radeon; + + R200_STATECHANGE(r200, ctx); + r200->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = radeon->state.color.drawOffset + + radeon->radeonScreen->fbLocation; + r200->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = radeon->state.color.drawPitch; + } + if (IS_FAMILY_R300(radeon)) { + r300ContextPtr r300 = (r300ContextPtr)radeon; + R300_STATECHANGE(r300, cb); + r300->hw.cb.cmd[R300_CB_OFFSET] = r300->radeon.state.color.drawOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.state.color.drawPitch; + + if (r300->radeon.radeonScreen->cpp == 4) + r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888; + else + r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565; + + if (r300->radeon.sarea->tiling_enabled) + r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE; + } +} + +void radeonWaitForIdleLocked(radeonContextPtr radeon) +{ + int ret; + int i = 0; + + do { + ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_CP_IDLE); + if (ret) + DO_USLEEP(1); + } while (ret && ++i < 100); + + if (ret < 0) { + UNLOCK_HARDWARE(radeon); + fprintf(stderr, "Error: R200 timed out... exiting\n"); + exit(-1); + } +} + +static void radeonWaitForIdle(radeonContextPtr radeon) +{ + LOCK_HARDWARE(radeon); + radeonWaitForIdleLocked(radeon); + UNLOCK_HARDWARE(radeon); +} + +void radeonFlush(GLcontext * ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + if (IS_FAMILY_R300(radeon)) + r300Flush(ctx); +#if R200_MERGED + else + r200Flush(ctx); +#endif +} + + +/* Make sure all commands have been sent to the hardware and have + * completed processing. + */ +void radeonFinish(GLcontext * ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + radeonFlush(ctx); + + if (radeon->do_irqs) { + LOCK_HARDWARE(radeon); + radeonEmitIrqLocked(radeon); + UNLOCK_HARDWARE(radeon); + radeonWaitIrq(radeon); + } else + radeonWaitForIdle(radeon); +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_ioctl.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_ioctl.h new file mode 100644 index 000000000..7c19325dd --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_ioctl.h @@ -0,0 +1,53 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __RADEON_IOCTL_H__ +#define __RADEON_IOCTL_H__ + +#include "simple_list.h" +#include "radeon_dri.h" +#include "radeon_lock.h" + +#include "xf86drm.h" +#include "drm.h" +#include "r200_context.h" +#include "radeon_drm.h" + +extern void radeonCopyBuffer(const __DRIdrawablePrivate * drawable); +extern void radeonPageFlip(const __DRIdrawablePrivate * drawable); +extern void radeonFlush(GLcontext * ctx); +extern void radeonFinish(GLcontext * ctx); +extern void radeonWaitForIdleLocked(radeonContextPtr radeon); + +#endif /* __RADEON_IOCTL_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_lock.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_lock.c new file mode 100644 index 000000000..3c7fc72a4 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_lock.c @@ -0,0 +1,166 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +#include <string.h> + +#include "r200_context.h" +#include "radeon_lock.h" +#include "r200_tex.h" +#include "r200_state.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" + +#include "framebuffer.h" + +#if DEBUG_LOCKING +char *prevLockFile = NULL; +int prevLockLine = 0; +#endif + +/* Turn on/off page flipping according to the flags in the sarea: + */ +static void radeonUpdatePageFlipping(radeonContextPtr radeon) +{ + int use_back; + + radeon->doPageFlip = radeon->sarea->pfState; + + use_back = (radeon->glCtx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT); + use_back ^= (radeon->sarea->pfCurrentPage == 1); + + if (use_back) { + radeon->state.color.drawOffset = radeon->radeonScreen->backOffset; + radeon->state.color.drawPitch = radeon->radeonScreen->backPitch; + } else { + radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset; + radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch; + } +} + +/** + * Called by radeonGetLock() after the lock has been obtained. + */ +#if R200_MERGED +static void r200RegainedLock(r200ContextPtr r200) +{ + __DRIdrawablePrivate *dPriv = r200->radeon.dri.drawable; + int i; + + if (r200->radeon.lastStamp != dPriv->lastStamp) { + radeonUpdatePageFlipping(&r200->radeon); + R200_STATECHANGE(r200, ctx); + r200->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = + r200->radeon.state.color.drawOffset + + r200->radeon.radeonScreen->fbLocation; + r200->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = + r200->radeon.state.color.drawPitch; + + if (r200->radeon.glCtx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) + radeonSetCliprects(&r200->radeon, GL_BACK_LEFT); + else + radeonSetCliprects(&r200->radeon, GL_FRONT_LEFT); + r200UpdateViewportOffset(r200->radeon.glCtx); + r200->radeon.lastStamp = dPriv->lastStamp; + } + + for (i = 0; i < r200->nr_heaps; i++) { + DRI_AGE_TEXTURES(r200->texture_heaps[i]); + } +} +#endif + +static void r300RegainedLock(radeonContextPtr radeon) +{ + __DRIdrawablePrivate *dPriv = radeon->dri.drawable; + + if (radeon->lastStamp != dPriv->lastStamp) { + _mesa_resize_framebuffer(radeon->glCtx, + (GLframebuffer*)dPriv->driverPrivate, + dPriv->w, dPriv->h); + + radeonUpdatePageFlipping(radeon); + + if (radeon->glCtx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) + radeonSetCliprects(radeon, GL_BACK_LEFT); + else + radeonSetCliprects(radeon, GL_FRONT_LEFT); + + radeonUpdateScissor(radeon->glCtx); + radeon->lastStamp = dPriv->lastStamp; + } + +#if R200_MERGED + for (i = 0; i < r200->nr_heaps; i++) { + DRI_AGE_TEXTURES(r200->texture_heaps[i]); + } +#endif +} + +/* Update the hardware state. This is called if another context has + * grabbed the hardware lock, which includes the X server. This + * function also updates the driver's window state after the X server + * moves, resizes or restacks a window -- the change will be reflected + * in the drawable position and clip rects. Since the X server grabs + * the hardware lock when it changes the window state, this routine will + * automatically be called after such a change. + */ +void radeonGetLock(radeonContextPtr radeon, GLuint flags) +{ + __DRIdrawablePrivate *dPriv = radeon->dri.drawable; + __DRIscreenPrivate *sPriv = radeon->dri.screen; + drm_radeon_sarea_t *sarea = radeon->sarea; + + drmGetLock(radeon->dri.fd, radeon->dri.hwContext, flags); + + /* The window might have moved, so we might need to get new clip + * rects. + * + * NOTE: This releases and regrabs the hw lock to allow the X server + * to respond to the DRI protocol request for new drawable info. + * Since the hardware state depends on having the latest drawable + * clip rects, all state checking must be done _after_ this call. + */ + DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); + + if (sarea->ctx_owner != radeon->dri.hwContext) + sarea->ctx_owner = radeon->dri.hwContext; + + if (IS_FAMILY_R300(radeon)) + r300RegainedLock(radeon); +#if R200_MERGED + else + r200RegainedLock((r200ContextPtr)radeon); +#endif + + radeon->lost_context = GL_TRUE; +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_lock.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_lock.h new file mode 100644 index 000000000..c9acbce0c --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_lock.h @@ -0,0 +1,122 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __RADEON_LOCK_H__ +#define __RADEON_LOCK_H__ + +#include "r200_ioctl.h" + +extern void radeonGetLock(radeonContextPtr radeon, GLuint flags); + +/* Turn DEBUG_LOCKING on to find locking conflicts. + */ +#define DEBUG_LOCKING 0 + +#if DEBUG_LOCKING +extern char *prevLockFile; +extern int prevLockLine; + +#define DEBUG_LOCK() \ + do { \ + prevLockFile = (__FILE__); \ + prevLockLine = (__LINE__); \ + } while (0) + +#define DEBUG_RESET() \ + do { \ + prevLockFile = 0; \ + prevLockLine = 0; \ + } while (0) + +#define DEBUG_CHECK_LOCK() \ + do { \ + if ( prevLockFile ) { \ + fprintf( stderr, \ + "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \ + prevLockFile, prevLockLine, __FILE__, __LINE__ ); \ + exit( 1 ); \ + } \ + } while (0) + +#else + +#define DEBUG_LOCK() +#define DEBUG_RESET() +#define DEBUG_CHECK_LOCK() + +#endif + +/* + * !!! We may want to separate locks from locks with validation. This + * could be used to improve performance for those things commands that + * do not do any drawing !!! + */ + +/* Lock the hardware and validate our state. + */ +#define LOCK_HARDWARE( radeon ) \ + do { \ + char __ret = 0; \ + DEBUG_CHECK_LOCK(); \ + DRM_CAS( (radeon)->dri.hwLock, (radeon)->dri.hwContext, \ + (DRM_LOCK_HELD | (radeon)->dri.hwContext), __ret ); \ + if ( __ret ) \ + radeonGetLock( (radeon), 0 ); \ + DEBUG_LOCK(); \ + } while (0) + +#if R200_MERGED +#define UNLOCK_HARDWARE( radeon ) \ + do { \ + DRM_UNLOCK( (radeon)->dri.fd, \ + (radeon)->dri.hwLock, \ + (radeon)->dri.hwContext ); \ + DEBUG_RESET(); \ + if (IS_FAMILY_R200((radeon))) { \ + r200ContextPtr __r200 = (r200ContextPtr)(radeon); \ + if (__r200->save_on_next_unlock) \ + r200SaveHwState( __r200 ); \ + __r200->save_on_next_unlock = GL_FALSE; \ + } \ + } while (0) +#else +#define UNLOCK_HARDWARE( radeon ) \ + do { \ + DRM_UNLOCK( (radeon)->dri.fd, \ + (radeon)->dri.hwLock, \ + (radeon)->dri.hwContext ); \ + DEBUG_RESET(); \ + } while (0) +#endif +#endif /* __RADEON_LOCK_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_screen.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_screen.c new file mode 100644 index 000000000..663bc973b --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_screen.c @@ -0,0 +1,879 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/** + * \file radeon_screen.c + * Screen initialization functions for the R200 driver. + * + * \author Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <dlfcn.h> + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "mtypes.h" +#include "framebuffer.h" +#include "renderbuffer.h" + +#define STANDALONE_MMIO +#include "radeon_screen.h" +#include "r200_context.h" +#include "r300_context.h" +#include "radeon_ioctl.h" +#include "r200_ioctl.h" +#include "radeon_macros.h" +#include "radeon_reg.h" +#include "radeon_span.h" + +#include "utils.h" +#include "vblank.h" +#include "GL/internal/dri_interface.h" +#include "drirenderbuffer.h" + +/* R200 configuration + */ +#include "xmlpool.h" + +const char __driR200ConfigOptions[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN) + DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_MAX_TEXTURE_UNITS(4, 2, 6) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_QUALITY + DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB) + DRI_CONF_DEF_MAX_ANISOTROPY(1.0, "1.0,2.0,4.0,8.0,16.0") + DRI_CONF_NO_NEG_LOD_BIAS(false) + DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER) + DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC) + DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_DEBUG + DRI_CONF_NO_RAST(false) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_SOFTWARE + DRI_CONF_ARB_VERTEX_PROGRAM(true) + DRI_CONF_NV_VERTEX_PROGRAM(false) + DRI_CONF_SECTION_END +DRI_CONF_END; +static const GLuint __driR200NConfigOptions = 13; + +/* TODO: integrate these into xmlpool.h! */ +#define DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(texture_image_units,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,"Number of texture image units") \ + DRI_CONF_DESC(de,"Anzahl der Textureinheiten") \ +DRI_CONF_OPT_END + +#define DRI_CONF_MAX_TEXTURE_COORD_UNITS(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(texture_coord_units,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,"Number of texture coordinate units") \ + DRI_CONF_DESC(de,"Anzahl der Texturkoordinateneinheiten") \ +DRI_CONF_OPT_END + +#define DRI_CONF_COMMAND_BUFFER_SIZE(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(command_buffer_size,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,"Size of command buffer (in KB)") \ + DRI_CONF_DESC(de,"Grösse des Befehlspuffers (in KB)") \ +DRI_CONF_OPT_END + + +const char __driR300ConfigOptions[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN) + DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(16, 2, 16) + DRI_CONF_MAX_TEXTURE_COORD_UNITS(8, 2, 8) + DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_QUALITY + DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB) + DRI_CONF_DEF_MAX_ANISOTROPY(1.0, "1.0,2.0,4.0,8.0,16.0") + DRI_CONF_NO_NEG_LOD_BIAS(false) + DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER) + DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC) + DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_DEBUG + DRI_CONF_NO_RAST(false) + DRI_CONF_SECTION_END +DRI_CONF_END; +static const GLuint __driR300NConfigOptions = 13; + +extern const struct dri_extension card_extensions[]; + +#ifndef RADEON_DEBUG +int RADEON_DEBUG = 0; +#endif + +static const struct dri_debug_control debug_control[] = { + {"fall", DEBUG_FALLBACKS}, + {"tex", DEBUG_TEXTURE}, + {"ioctl", DEBUG_IOCTL}, + {"prim", DEBUG_PRIMS}, + {"vert", DEBUG_VERTS}, + {"state", DEBUG_STATE}, + {"code", DEBUG_CODEGEN}, + {"vfmt", DEBUG_VFMT}, + {"vtxf", DEBUG_VFMT}, + {"verb", DEBUG_VERBOSE}, + {"dri", DEBUG_DRI}, + {"dma", DEBUG_DMA}, + {"san", DEBUG_SANITY}, + {"sync", DEBUG_SYNC}, + {"pix", DEBUG_PIXEL}, + {"mem", DEBUG_MEMORY}, + {"allmsg", ~DEBUG_SYNC}, /* avoid the term "sync" because the parser uses strstr */ + {NULL, 0} +}; + +#if 1 +/* Including xf86PciInfo.h introduces a bunch of errors... + */ +#define PCI_CHIP_R200_QD 0x5144 /* why do they have r200 names? */ +#define PCI_CHIP_R200_QE 0x5145 /* Those are all standard radeons */ +#define PCI_CHIP_R200_QF 0x5146 +#define PCI_CHIP_R200_QG 0x5147 +#define PCI_CHIP_R200_QY 0x5159 +#define PCI_CHIP_R200_QZ 0x515A +#define PCI_CHIP_R200_LW 0x4C57 +#define PCI_CHIP_R200_LY 0x4C59 +#define PCI_CHIP_R200_LZ 0x4C5A +#define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */ +#define PCI_CHIP_RV200_QX 0x5158 +#define PCI_CHIP_RS100_4136 0x4136 /* IGP RS100, RS200, RS250 are not R200 */ +#define PCI_CHIP_RS200_4137 0x4137 +#define PCI_CHIP_RS250_4237 0x4237 +#define PCI_CHIP_RS100_4336 0x4336 +#define PCI_CHIP_RS200_4337 0x4337 +#define PCI_CHIP_RS250_4437 0x4437 +#define PCI_CHIP_RS300_5834 0x5834 /* All RS300's are R200 */ +#define PCI_CHIP_RS300_5835 0x5835 +#define PCI_CHIP_RS300_5836 0x5836 +#define PCI_CHIP_RS300_5837 0x5837 +#define PCI_CHIP_R200_BB 0x4242 /* r200 (non-derived) start */ +#define PCI_CHIP_R200_BC 0x4243 +#define PCI_CHIP_R200_QH 0x5148 +#define PCI_CHIP_R200_QI 0x5149 +#define PCI_CHIP_R200_QJ 0x514A +#define PCI_CHIP_R200_QK 0x514B +#define PCI_CHIP_R200_QL 0x514C +#define PCI_CHIP_R200_QM 0x514D +#define PCI_CHIP_R200_QN 0x514E +#define PCI_CHIP_R200_QO 0x514F /* r200 (non-derived) end */ +/* are the R200 Qh (0x5168) and following needed too? They are not in xf86PciInfo.h + but in the pci database. Maybe just secondary ports or something ? */ + +#define PCI_CHIP_R300_AD 0x4144 +#define PCI_CHIP_R300_AE 0x4145 +#define PCI_CHIP_R300_AF 0x4146 +#define PCI_CHIP_R300_AG 0x4147 +#define PCI_CHIP_RV350_AP 0x4150 +#define PCI_CHIP_RV350_AR 0x4152 +#define PCI_CHIP_RV350_AS 0x4153 +#define PCI_CHIP_RV350_NJ 0x4E4A +#define PCI_CHIP_RV350_NP 0x4E50 +#define PCI_CHIP_RV350_NQ 0x4E51 /* Saphire 9600 256MB card */ +#define PCI_CHIP_RV350_NT 0x4E54 +#define PCI_CHIP_RV350_NQ_2 0x4E71 /* Saphire 9600 256MB card - Second Head */ +#define PCI_CHIP_R300_ND 0x4E44 +#define PCI_CHIP_R300_NE 0x4E45 +#define PCI_CHIP_R300_NF 0x4E46 +#define PCI_CHIP_R300_NG 0x4E47 +#define PCI_CHIP_R350_NH 0x4E48 +#define PCI_CHIP_R420_JI 0x4A49 +#define PCI_CHIP_R420_JK 0x4a4b +#endif + + +static radeonScreenPtr __radeonScreen; + +static int getSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo); + +static __GLcontextModes *radeonFillInModes(unsigned pixel_bits, + unsigned depth_bits, + unsigned stencil_bits, + GLboolean have_back_buffer) +{ + __GLcontextModes *modes; + __GLcontextModes *m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy + * enough to add support. Basically, if a context is created with an + * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping + * will never be used. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */ + }; + + uint8_t depth_bits_array[2]; + uint8_t stencil_bits_array[2]; + + depth_bits_array[0] = depth_bits; + depth_bits_array[1] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; + + depth_buffer_factor = ((depth_bits != 0) + || (stencil_bits != 0)) ? 2 : 1; + back_buffer_factor = (have_back_buffer) ? 2 : 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if (pixel_bits == 16) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } else { + fb_format = GL_BGRA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + modes = (*dri_interface->createContextModes) (num_modes, sizeof(__GLcontextModes)); + m = modes; + if (!driFillInModes(&m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + back_buffer_factor, GLX_TRUE_COLOR)) { + fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, + __LINE__); + return NULL; + } + + if (!driFillInModes(&m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + back_buffer_factor, GLX_DIRECT_COLOR)) { + fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, + __LINE__); + return NULL; + } + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for (m = modes; m != NULL; m = m->next) { + if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { + m->visualRating = GLX_SLOW_CONFIG; + } + } + + return modes; +} + + +/* Create the device specific screen private data struct. + */ +static radeonScreenPtr radeonCreateScreen(__DRIscreenPrivate * sPriv) +{ + radeonScreenPtr screen; + RADEONDRIPtr dri_priv = (RADEONDRIPtr) sPriv->pDevPriv; + unsigned char *RADEONMMIO; + PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = + (PFNGLXSCRENABLEEXTENSIONPROC) + (*dri_interface->getProcAddress("glxEnableExtension")); + void *const psc = sPriv->psc->screenConfigs; + + if (sPriv->devPrivSize != sizeof(RADEONDRIRec)) { + fprintf(stderr,"\nERROR! sizeof(RADEONDRIRec) does not match passed size from device driver\n"); + return GL_FALSE; + } + + /* Allocate the private area */ + screen = (radeonScreenPtr) CALLOC(sizeof(*screen)); + if (!screen) { + __driUtilMessage + ("%s: Could not allocate memory for screen structure", + __FUNCTION__); + return NULL; + } + +#if DO_DEBUG + RADEON_DEBUG = driParseDebugString(getenv("RADEON_DEBUG"), debug_control); +#endif + + /* Get family and potential quirks from the PCI device ID. + */ + switch (dri_priv->deviceID) { + case PCI_CHIP_R200_QD: + case PCI_CHIP_R200_QE: + case PCI_CHIP_R200_QF: + case PCI_CHIP_R200_QG: + case PCI_CHIP_R200_QY: + case PCI_CHIP_R200_QZ: + case PCI_CHIP_RV200_QW: + case PCI_CHIP_RV200_QX: + case PCI_CHIP_R200_LW: + case PCI_CHIP_R200_LY: + case PCI_CHIP_R200_LZ: + case PCI_CHIP_RS100_4136: + case PCI_CHIP_RS200_4137: + case PCI_CHIP_RS250_4237: + case PCI_CHIP_RS100_4336: + case PCI_CHIP_RS200_4337: + case PCI_CHIP_RS250_4437: + __driUtilMessage("radeonCreateScreen(): Device isn't an r200!\n"); + FREE(screen); + return NULL; + + case PCI_CHIP_RS300_5834: + case PCI_CHIP_RS300_5835: + case PCI_CHIP_RS300_5836: + case PCI_CHIP_RS300_5837: + screen->chipset = RADEON_CHIP_UNREAL_R200; + break; + + case PCI_CHIP_R200_BB: + case PCI_CHIP_R200_BC: + case PCI_CHIP_R200_QH: + case PCI_CHIP_R200_QI: + case PCI_CHIP_R200_QJ: + case PCI_CHIP_R200_QK: + case PCI_CHIP_R200_QL: + case PCI_CHIP_R200_QM: + case PCI_CHIP_R200_QN: + case PCI_CHIP_R200_QO: + screen->chipset = RADEON_CHIP_REAL_R200 | RADEON_CHIPSET_TCL; + break; + + /* TODO: Check all those chips for the exact flags required. + */ + case PCI_CHIP_R300_AD: + case PCI_CHIP_R300_AE: + case PCI_CHIP_R300_AF: + case PCI_CHIP_R300_AG: + case PCI_CHIP_RV350_AP: + case PCI_CHIP_RV350_AR: + case PCI_CHIP_RV350_AS: + case PCI_CHIP_RV350_NJ: + case PCI_CHIP_RV350_NP: + case PCI_CHIP_RV350_NT: + case PCI_CHIP_RV350_NQ: +/* case PCI_CHIP_RV350_NQ: -- Should we have the second head in here too? */ + screen->chipset = RADEON_CHIP_RV350; + break; + + case PCI_CHIP_R300_ND: /* confirmed -- nh */ + case PCI_CHIP_R300_NE: + case PCI_CHIP_R300_NF: + case PCI_CHIP_R300_NG: + case PCI_CHIP_R350_NH: + screen->chipset = RADEON_CHIP_R300; + break; + + case PCI_CHIP_R420_JI: + case PCI_CHIP_R420_JK: + screen->chipset = RADEON_CHIP_R420; + break; + + default: + fprintf(stderr, + "Unknown device ID %04X, please report. Assuming plain R300.\n", + dri_priv->deviceID); + screen->chipset = RADEON_CHIP_R300; + } + + /* Parse configuration */ + if (GET_CHIP(screen) >= RADEON_CHIP_R300) { + driParseOptionInfo(&screen->optionCache, + __driR300ConfigOptions, __driR300NConfigOptions); + } else { + driParseOptionInfo(&screen->optionCache, + __driR200ConfigOptions, __driR200NConfigOptions); + } + + /* This is first since which regions we map depends on whether or + * not we are using a PCI card. + */ + screen->IsPCI = dri_priv->IsPCI; + + { + int ret; + drm_radeon_getparam_t gp; + + gp.param = RADEON_PARAM_GART_BUFFER_OFFSET; + gp.value = &screen->gart_buffer_offset; + + ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + FREE(screen); + fprintf(stderr, + "drmRadeonGetParam (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", + ret); + return NULL; + } + + if (sPriv->drmMinor >= 6) { + gp.param = RADEON_PARAM_GART_BASE; + gp.value = &screen->gart_base; + + ret = + drmCommandWriteRead(sPriv->fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + FREE(screen); + fprintf(stderr, + "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", + ret); + return NULL; + } + + gp.param = RADEON_PARAM_IRQ_NR; + gp.value = &screen->irq; + + ret = + drmCommandWriteRead(sPriv->fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + FREE(screen); + fprintf(stderr, + "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", + ret); + return NULL; + } + + /* Check if kernel module is new enough to support cube maps */ + screen->drmSupportsCubeMaps = (sPriv->drmMinor >= 7); + /* Check if kernel module is new enough to support blend color and + separate blend functions/equations */ + screen->drmSupportsBlendColor = (sPriv->drmMinor >= 11); + + } + } + + screen->mmio.handle = dri_priv->registerHandle; + screen->mmio.size = dri_priv->registerSize; + if (drmMap(sPriv->fd, + screen->mmio.handle, screen->mmio.size, &screen->mmio.map)) { + FREE(screen); + __driUtilMessage("%s: drmMap failed\n", __FUNCTION__); + return NULL; + } + + RADEONMMIO = screen->mmio.map; + + screen->status.handle = dri_priv->statusHandle; + screen->status.size = dri_priv->statusSize; + if (drmMap(sPriv->fd, + screen->status.handle, + screen->status.size, &screen->status.map)) { + drmUnmap(screen->mmio.map, screen->mmio.size); + FREE(screen); + __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__); + return NULL; + } + screen->scratch = (__volatile__ uint32_t *) + ((GLubyte *) screen->status.map + RADEON_SCRATCH_REG_OFFSET); + + screen->buffers = drmMapBufs(sPriv->fd); + if (!screen->buffers) { + drmUnmap(screen->status.map, screen->status.size); + drmUnmap(screen->mmio.map, screen->mmio.size); + FREE(screen); + __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__); + return NULL; + } + + if (dri_priv->gartTexHandle && dri_priv->gartTexMapSize) { + + screen->gartTextures.handle = dri_priv->gartTexHandle; + screen->gartTextures.size = dri_priv->gartTexMapSize; + if (drmMap(sPriv->fd, + screen->gartTextures.handle, + screen->gartTextures.size, + (drmAddressPtr) & screen->gartTextures.map)) { + drmUnmapBufs(screen->buffers); + drmUnmap(screen->status.map, screen->status.size); + drmUnmap(screen->mmio.map, screen->mmio.size); + FREE(screen); + __driUtilMessage + ("%s: drmMAP failed for GART texture area\n", + __FUNCTION__); + return NULL; + } + + screen->gart_texture_offset = + dri_priv->gartTexOffset + + (screen->IsPCI ? INREG(RADEON_AIC_LO_ADDR) + : ((INREG(RADEON_MC_AGP_LOCATION) & 0x0ffffU) << 16)); + } + + screen->cpp = dri_priv->bpp / 8; + screen->AGPMode = dri_priv->AGPMode; + + screen->fbLocation = (INREG(RADEON_MC_FB_LOCATION) & 0xffff) << 16; + + if (sPriv->drmMinor >= 10) { + drm_radeon_setparam_t sp; + + sp.param = RADEON_SETPARAM_FB_LOCATION; + sp.value = screen->fbLocation; + + drmCommandWrite(sPriv->fd, DRM_RADEON_SETPARAM, + &sp, sizeof(sp)); + } + + screen->frontOffset = dri_priv->frontOffset; + screen->frontPitch = dri_priv->frontPitch; + screen->backOffset = dri_priv->backOffset; + screen->backPitch = dri_priv->backPitch; + screen->depthOffset = dri_priv->depthOffset; + screen->depthPitch = dri_priv->depthPitch; + + if ( dri_priv->textureSize == 0 ) { + screen->texOffset[RADEON_LOCAL_TEX_HEAP] = screen->gart_texture_offset; + screen->texSize[RADEON_GART_TEX_HEAP] = dri_priv->gartTexMapSize; + screen->logTexGranularity[RADEON_GART_TEX_HEAP] = + dri_priv->log2GARTTexGran; + } else { + screen->texOffset[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureOffset + + screen->fbLocation; + screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureSize; + screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] = + dri_priv->log2TexGran; + } + + if (!screen->gartTextures.map || dri_priv->textureSize == 0) { + screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1; + screen->texOffset[RADEON_GART_TEX_HEAP] = 0; + screen->texSize[RADEON_GART_TEX_HEAP] = 0; + screen->logTexGranularity[RADEON_GART_TEX_HEAP] = 0; + } else { + screen->numTexHeaps = RADEON_NR_TEX_HEAPS; + screen->texOffset[RADEON_GART_TEX_HEAP] = + screen->gart_texture_offset; + screen->texSize[RADEON_GART_TEX_HEAP] = + dri_priv->gartTexMapSize; + screen->logTexGranularity[RADEON_GART_TEX_HEAP] = + dri_priv->log2GARTTexGran; + } + + screen->driScreen = sPriv; + screen->sarea_priv_offset = dri_priv->sarea_priv_offset; + + if (glx_enable_extension != NULL) { + if (screen->irq != 0) { + (*glx_enable_extension) (psc, "GLX_SGI_swap_control"); + (*glx_enable_extension) (psc, "GLX_SGI_video_sync"); + (*glx_enable_extension) (psc, "GLX_MESA_swap_control"); + } + + (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage"); + } + +#if R200_MERGED + sPriv->psc->allocateMemory = (void *)r200AllocateMemoryMESA; + sPriv->psc->freeMemory = (void *)r200FreeMemoryMESA; + sPriv->psc->memoryOffset = (void *)r200GetMemoryOffsetMESA; + + if (glx_enable_extension != NULL) { + (*glx_enable_extension) (psc, "GLX_MESA_allocate_memory"); + } +#endif + + return screen; +} + +/* Destroy the device specific screen private data struct. + */ +static void radeonDestroyScreen(__DRIscreenPrivate * sPriv) +{ + radeonScreenPtr screen = (radeonScreenPtr) sPriv->private; + + if (!screen) + return; + + if (screen->gartTextures.map) { + drmUnmap(screen->gartTextures.map, screen->gartTextures.size); + } + drmUnmapBufs(screen->buffers); + drmUnmap(screen->status.map, screen->status.size); + drmUnmap(screen->mmio.map, screen->mmio.size); + + /* free all option information */ + driDestroyOptionInfo(&screen->optionCache); + + FREE(screen); + sPriv->private = NULL; +} + +/* Initialize the driver specific screen private data. + */ +static GLboolean radeonInitDriver(__DRIscreenPrivate * sPriv) +{ + __radeonScreen = radeonCreateScreen(sPriv); + + sPriv->private = (void *)__radeonScreen; + + return sPriv->private ? GL_TRUE : GL_FALSE; +} + +/** + * Create and initialize the Mesa and driver specific pixmap buffer + * data. + * + * \todo This function (and its interface) will need to be updated to support + * pbuffers. + */ +static GLboolean +radeonCreateBuffer(__DRIscreenPrivate * driScrnPriv, + __DRIdrawablePrivate * driDrawPriv, + const __GLcontextModes * mesaVis, GLboolean isPixmap) +{ + radeonScreenPtr screen = (radeonScreenPtr)driScrnPriv->private; + + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } else { + const GLboolean swDepth = GL_FALSE; + const GLboolean swAlpha = GL_FALSE; + const GLboolean swAccum = mesaVis->accumRedBits > 0; + const GLboolean swStencil = mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24; +#if 0 + driDrawPriv->driverPrivate = (void *) + _mesa_create_framebuffer(mesaVis, + swDepth, + swStencil, swAccum, swAlpha); +#else + struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + { + driRenderbuffer *frontRb + = driNewRenderbuffer(GL_RGBA, screen->cpp, + screen->frontOffset, screen->frontPitch); + radeonSetSpanFunctions(frontRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + } + if (mesaVis->doubleBufferMode) { + driRenderbuffer *backRb + = driNewRenderbuffer(GL_RGBA, screen->cpp, + screen->backOffset, screen->backPitch); + radeonSetSpanFunctions(backRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + } + if (mesaVis->depthBits == 16) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT16, screen->cpp, + screen->depthOffset, screen->depthPitch); + radeonSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + else if (mesaVis->depthBits == 24) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT24, screen->cpp, + screen->depthOffset, screen->depthPitch); + radeonSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + + if (mesaVis->stencilBits > 0 && !swStencil) { + driRenderbuffer *stencilRb + = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, screen->cpp, + screen->depthOffset, screen->depthPitch); + radeonSetSpanFunctions(stencilRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + swDepth, + swStencil, + swAccum, + swAlpha, + GL_FALSE /* aux */); + driDrawPriv->driverPrivate = (void *) fb; +#endif + return (driDrawPriv->driverPrivate != NULL); + } +} + +static void radeonDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) +{ + _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv-> + driverPrivate)); +} + + +/** + * Choose the appropriate CreateContext function based on the chipset. + */ +static GLboolean radeonCreateContext(const __GLcontextModes * glVisual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPriv) +{ + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private); + int chip = GET_CHIP(screen); + + if (chip >= RADEON_CHIP_R300) + return r300CreateContext(glVisual, driContextPriv, sharedContextPriv); +#if R200_MERGED + else + return r200CreateContext(glVisual, driContextPriv, sharedContextPriv); +#endif +} + + +/** + * Choose the appropriate DestroyContext function based on the chipset. + */ +static void radeonDestroyContext(__DRIcontextPrivate * driContextPriv) +{ + radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate; + int chip = GET_CHIP(radeon->radeonScreen); + + if (chip >= RADEON_CHIP_R300) + return r300DestroyContext(driContextPriv); +#if R200_MERGED + else + return r200DestroyContext(driContextPriv); +#endif +} + + +static const struct __DriverAPIRec radeonAPI = { + .InitDriver = radeonInitDriver, + .DestroyScreen = radeonDestroyScreen, + .CreateContext = radeonCreateContext, + .DestroyContext = radeonDestroyContext, + .CreateBuffer = radeonCreateBuffer, + .DestroyBuffer = radeonDestroyBuffer, + .SwapBuffers = radeonSwapBuffers, + .MakeCurrent = radeonMakeCurrent, + .UnbindContext = radeonUnbindContext, + .GetSwapInfo = getSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL +}; + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +void *__driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn, + __DRIscreen * psc, const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes) +{ + __DRIscreenPrivate *psp; + static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 17, 0 }; + + dri_interface = interface; + + if (!driCheckDriDdxDrmVersions3("R300", + dri_version, &dri_expected, + ddx_version, &ddx_expected, + drm_version, &drm_expected)) { + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &radeonAPI); + if (psp != NULL) { + RADEONDRIPtr dri_priv = (RADEONDRIPtr) psp->pDevPriv; + *driver_modes = radeonFillInModes(dri_priv->bpp, + (dri_priv->bpp == + 16) ? 16 : 24, + (dri_priv->bpp == + 16) ? 0 : 8, + (dri_priv->backOffset != + dri_priv->depthOffset)); + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + driInitExtensions( NULL, card_extensions, GL_FALSE ); + } + + return (void *)psp; +} + + +/** + * Get information about previous buffer swaps. + */ +static int getSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) +{ + radeonContextPtr radeon; + + if ((dPriv == NULL) || (dPriv->driContextPriv == NULL) + || (dPriv->driContextPriv->driverPrivate == NULL) + || (sInfo == NULL)) { + return -1; + } + + radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; + sInfo->swap_count = radeon->swap_count; + sInfo->swap_ust = radeon->swap_ust; + sInfo->swap_missed_count = radeon->swap_missed_count; + + sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) + ? driCalculateSwapUsage(dPriv, 0, radeon->swap_missed_ust) + : 0.0; + + return 0; +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_screen.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_screen.h new file mode 100644 index 000000000..ac8471fea --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_screen.h @@ -0,0 +1,112 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __RADEON_SCREEN_H__ +#define __RADEON_SCREEN_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "xf86drm.h" +#include "drm.h" +#include "radeon_drm.h" +#include "dri_util.h" +#include "xmlconfig.h" + +typedef struct { + drm_handle_t handle; /* Handle to the DRM region */ + drmSize size; /* Size of the DRM region */ + drmAddress map; /* Mapping of the DRM region */ +} radeonRegionRec, *radeonRegionPtr; + +/* chipset features */ +#define RADEON_CHIP_UNREAL_R200 0 +#define RADEON_CHIP_REAL_R200 1 +#define RADEON_CHIP_R300 2 +#define RADEON_CHIP_RV350 3 +#define RADEON_CHIP_R420 4 +#define RADEON_CHIP_MASK 0x0f + +#define RADEON_CHIPSET_TCL (1 << 8) + +#define GET_CHIP(screen) ((screen)->chipset & RADEON_CHIP_MASK) +#define IS_FAMILY_R200(radeon) (GET_CHIP((radeon)->radeonScreen) < RADEON_CHIP_R300) +#define IS_FAMILY_R300(radeon) (GET_CHIP((radeon)->radeonScreen) >= RADEON_CHIP_R300) + +#define R200_NR_TEX_HEAPS 2 + +typedef struct { + int chipset; + int cpp; + int IsPCI; /* Current card is a PCI card */ + int AGPMode; + unsigned int irq; /* IRQ number (0 means none) */ + + unsigned int fbLocation; + unsigned int frontOffset; + unsigned int frontPitch; + unsigned int backOffset; + unsigned int backPitch; + + unsigned int depthOffset; + unsigned int depthPitch; + + /* Shared texture data */ + int numTexHeaps; + int texOffset[R200_NR_TEX_HEAPS]; + int texSize[R200_NR_TEX_HEAPS]; + int logTexGranularity[R200_NR_TEX_HEAPS]; + + radeonRegionRec mmio; + radeonRegionRec status; + radeonRegionRec gartTextures; + + drmBufMapPtr buffers; + + __volatile__ int32_t *scratch; + + __DRIscreenPrivate *driScreen; + unsigned int sarea_priv_offset; + unsigned int gart_buffer_offset; /* offset in card memory space */ + unsigned int gart_texture_offset; /* offset in card memory space */ + unsigned int gart_base; + + GLboolean drmSupportsCubeMaps; /* need radeon kernel module >=1.7 */ + GLboolean drmSupportsBlendColor; /* need radeon kernel module >= 1.11 */ + + /* Configuration cache with default values for all contexts */ + driOptionCache optionCache; +} radeonScreenRec, *radeonScreenPtr; + +#endif +#endif /* __RADEON_SCREEN_H__ */ diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_span.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_span.c new file mode 100644 index 000000000..8902c93e5 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_span.c @@ -0,0 +1,391 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "imports.h" +#include "swrast/swrast.h" +#include "colormac.h" + +#include "r200_context.h" +#include "radeon_ioctl.h" +#include "r300_ioctl.h" +#include "radeon_span.h" + +#define DBG 0 + +#define LOCAL_VARS \ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); \ + driRenderbuffer* drb = (driRenderbuffer*)rb; \ + __DRIscreenPrivate *sPriv = radeon->dri.screen; \ + __DRIdrawablePrivate *dPriv = radeon->dri.drawable; \ + GLuint pitch = drb->pitch * drb->cpp; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(sPriv->pFB + \ + drb->offset + \ + (dPriv->x * drb->cpp) + \ + (dPriv->y * pitch)); \ + GLuint p; \ + (void) p + +#define LOCAL_DEPTH_VARS \ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); \ + driRenderbuffer* drb = (driRenderbuffer*)rb; \ + __DRIscreenPrivate *sPriv = radeon->dri.screen; \ + __DRIdrawablePrivate *dPriv = radeon->dri.drawable; \ + GLuint pitch = drb->pitch; \ + GLuint height = dPriv->h; \ + GLuint xo = dPriv->x; \ + GLuint yo = dPriv->y; \ + char *buf = (char *)(sPriv->pFB + drb->offset); \ + (void) buf; (void) pitch + +#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS + +#define CLIPPIXEL( _x, _y ) \ + ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy)) + +#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \ + if ( _y < miny || _y >= maxy ) { \ + _n1 = 0, _x1 = x; \ + } else { \ + _n1 = _n; \ + _x1 = _x; \ + if ( _x1 < minx ) _i += (minx-_x1), _n1 -= (minx-_x1), _x1 = minx; \ + if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + _n1 - maxx); \ + } + +#define Y_FLIP( _y ) (height - _y - 1) + +#define HW_LOCK() + +#define HW_CLIPLOOP() \ + do { \ + int _nc = dPriv->numClipRects; \ + \ + while ( _nc-- ) { \ + int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \ + int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \ + int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \ + int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y; + +#define HW_ENDCLIPLOOP() \ + } \ + } while (0) + +#define HW_UNLOCK() + +/* ================================================================ + * Color buffer + */ + +/* 16 bit, RGB565 color spanline and pixel functions + */ +#define INIT_MONO_PIXEL(p, color) \ + p = PACK_COLOR_565( color[0], color[1], color[2] ) + +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \ + (((int)g & 0xfc) << 3) | \ + (((int)b & 0xf8) >> 3)) + +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \ + rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \ + rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \ + rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \ + rgba[3] = 0xff; \ + } while (0) + +#define TAG(x) radeon##x##_RGB565 +#include "spantmp.h" + +/* 32 bit, ARGB8888 color spanline and pixel functions + */ +#undef INIT_MONO_PIXEL +#define INIT_MONO_PIXEL(p, color) \ + p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] ) + +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ +do { \ + *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \ + (g << 8) | \ + (r << 16) | \ + (a << 24) ); \ +} while (0) + +#define WRITE_PIXEL( _x, _y, p ) \ +do { \ + *(GLuint *)(buf + _x*4 + _y*pitch) = p; \ +} while (0) + +#define READ_RGBA( rgba, _x, _y ) \ +do { \ + volatile GLuint *ptr = (volatile GLuint *)(buf + _x*4 + _y*pitch); \ + GLuint p = *ptr; \ + rgba[0] = (p >> 16) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 0) & 0xff; \ + rgba[3] = (p >> 24) & 0xff; \ +} while (0) + +#define TAG(x) radeon##x##_ARGB8888 +#include "spantmp.h" + +/* ================================================================ + * Depth buffer + */ + +/* 16-bit depth buffer functions + */ +#define WRITE_DEPTH( _x, _y, d ) \ + *(GLushort *)(buf + (_x + xo + (_y + yo)*pitch)*2 ) = d; + +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLushort *)(buf + (_x + xo + (_y + yo)*pitch)*2 ); + +#define TAG(x) radeon##x##_16_LINEAR +#include "depthtmp.h" + +/* 24 bit depth, 8 bit stencil depthbuffer functions + * + * Careful: It looks like the R300 uses ZZZS byte order while the R200 + * uses SZZZ for 24 bit depth, 8 bit stencil mode. + */ +#define WRITE_DEPTH( _x, _y, d ) \ +do { \ + GLuint offset = ((_x) + xo + ((_y) + yo)*pitch)*4; \ + GLuint tmp = *(GLuint *)(buf + offset); \ + tmp &= 0x000000ff; \ + tmp |= ((d << 8) & 0xffffff00); \ + *(GLuint *)(buf + offset) = tmp; \ +} while (0) + +#define READ_DEPTH( d, _x, _y ) \ +do { \ + d = (*(GLuint *)(buf + ((_x) + xo + ((_y) + yo)*pitch)*4) & 0xffffff00) >> 8; \ +} while(0) + +#define TAG(x) radeon##x##_24_8_LINEAR +#include "depthtmp.h" + +/* ================================================================ + * Stencil buffer + */ + +/* 24 bit depth, 8 bit stencil depthbuffer functions + */ +#define WRITE_STENCIL( _x, _y, d ) \ +do { \ + GLuint offset = (_x + xo + (_y + yo)*pitch)*4; \ + GLuint tmp = *(GLuint *)(buf + offset); \ + tmp &= 0xffffff00; \ + tmp |= (d) & 0xff; \ + *(GLuint *)(buf + offset) = tmp; \ +} while (0) + +#define READ_STENCIL( d, _x, _y ) \ +do { \ + GLuint offset = (_x + xo + (_y + yo)*pitch)*4; \ + GLuint tmp = *(GLuint *)(buf + offset); \ + d = tmp & 0x000000ff; \ +} while (0) + +#define TAG(x) radeon##x##_24_8_LINEAR +#include "stenciltmp.h" + +/* + * This function is called to specify which buffer to read and write + * for software rasterization (swrast) fallbacks. This doesn't necessarily + * correspond to glDrawBuffer() or glReadBuffer() calls. + */ +static void radeonSetBuffer(GLcontext * ctx, + GLframebuffer * colorBuffer, GLuint bufferBit) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + int buffer; + + switch (bufferBit) { + case BUFFER_BIT_FRONT_LEFT: + buffer = 0; + break; + + case BUFFER_BIT_BACK_LEFT: + buffer = 1; + break; + + default: + _mesa_problem(ctx, "Bad bufferBit in %s", __FUNCTION__); + return; + } + + if (radeon->doPageFlip && radeon->sarea->pfCurrentPage == 1) + buffer ^= 1; + +#if 0 + fprintf(stderr, "%s: using %s buffer\n", __FUNCTION__, + buffer ? "back" : "front"); +#endif + + if (buffer) { + radeon->state.pixel.readOffset = + radeon->radeonScreen->backOffset; + radeon->state.pixel.readPitch = + radeon->radeonScreen->backPitch; + radeon->state.color.drawOffset = + radeon->radeonScreen->backOffset; + radeon->state.color.drawPitch = + radeon->radeonScreen->backPitch; + } else { + radeon->state.pixel.readOffset = + radeon->radeonScreen->frontOffset; + radeon->state.pixel.readPitch = + radeon->radeonScreen->frontPitch; + radeon->state.color.drawOffset = + radeon->radeonScreen->frontOffset; + radeon->state.color.drawPitch = + radeon->radeonScreen->frontPitch; + } +} + +/* Move locking out to get reasonable span performance (10x better + * than doing this in HW_LOCK above). WaitForIdle() is the main + * culprit. + */ + +static void radeonSpanRenderStart(GLcontext * ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + if (IS_FAMILY_R200(radeon)) + R200_FIREVERTICES((r200ContextPtr)radeon); + else + r300Flush(ctx); + + LOCK_HARDWARE(radeon); + radeonWaitForIdleLocked(radeon); + + /* Read & rewrite the first pixel in the frame buffer. This should + * be a noop, right? In fact without this conform fails as reading + * from the framebuffer sometimes produces old results -- the + * on-card read cache gets mixed up and doesn't notice that the + * framebuffer has been updated. + * + * In the worst case this is buggy too as p might get the wrong + * value first time, so really need a hidden pixel somewhere for this. + */ + { + int p; + volatile int *read_buf = + (volatile int *)(radeon->dri.screen->pFB + + radeon->state.pixel.readOffset); + p = *read_buf; + *read_buf = p; + } +} + +static void radeonSpanRenderFinish(GLcontext * ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + _swrast_flush(ctx); + UNLOCK_HARDWARE(radeon); +} + +void radeonInitSpanFuncs(GLcontext * ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + struct swrast_device_driver *swdd = + _swrast_GetDeviceDriverReference(ctx); + + swdd->SetBuffer = radeonSetBuffer; + + swdd->SpanRenderStart = radeonSpanRenderStart; + swdd->SpanRenderFinish = radeonSpanRenderFinish; +} + +/** + * Plug in the Get/Put routines for the given driRenderbuffer. + */ +void radeonSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) +{ + if (drb->Base.InternalFormat == GL_RGBA) { + if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { + drb->Base.GetRow = radeonReadRGBASpan_RGB565; + drb->Base.GetValues = radeonReadRGBAPixels_RGB565; + drb->Base.PutRow = radeonWriteRGBASpan_RGB565; + drb->Base.PutRowRGB = radeonWriteRGBSpan_RGB565; + drb->Base.PutMonoRow = radeonWriteMonoRGBASpan_RGB565; + drb->Base.PutValues = radeonWriteRGBAPixels_RGB565; + drb->Base.PutMonoValues = radeonWriteMonoRGBAPixels_RGB565; + } + else { + drb->Base.GetRow = radeonReadRGBASpan_ARGB8888; + drb->Base.GetValues = radeonReadRGBAPixels_ARGB8888; + drb->Base.PutRow = radeonWriteRGBASpan_ARGB8888; + drb->Base.PutRowRGB = radeonWriteRGBSpan_ARGB8888; + drb->Base.PutMonoRow = radeonWriteMonoRGBASpan_ARGB8888; + drb->Base.PutValues = radeonWriteRGBAPixels_ARGB8888; + drb->Base.PutMonoValues = radeonWriteMonoRGBAPixels_ARGB8888; + } + } + else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) { + drb->Base.GetRow = radeonReadDepthSpan_16_LINEAR; + drb->Base.GetValues = radeonReadDepthPixels_16_LINEAR; + drb->Base.PutRow = radeonWriteDepthSpan_16_LINEAR; + drb->Base.PutMonoRow = radeonWriteMonoDepthSpan_16_LINEAR; + drb->Base.PutValues = radeonWriteDepthPixels_16_LINEAR; + drb->Base.PutMonoValues = NULL; + } + else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) { + drb->Base.GetRow = radeonReadDepthSpan_24_8_LINEAR; + drb->Base.GetValues = radeonReadDepthPixels_24_8_LINEAR; + drb->Base.PutRow = radeonWriteDepthSpan_24_8_LINEAR; + drb->Base.PutMonoRow = radeonWriteMonoDepthSpan_24_8_LINEAR; + drb->Base.PutValues = radeonWriteDepthPixels_24_8_LINEAR; + drb->Base.PutMonoValues = NULL; + } + else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) { + drb->Base.GetRow = radeonReadStencilSpan_24_8_LINEAR; + drb->Base.GetValues = radeonReadStencilPixels_24_8_LINEAR; + drb->Base.PutRow = radeonWriteStencilSpan_24_8_LINEAR; + drb->Base.PutMonoRow = radeonWriteMonoStencilSpan_24_8_LINEAR; + drb->Base.PutValues = radeonWriteStencilPixels_24_8_LINEAR; + drb->Base.PutMonoValues = NULL; + } +} + diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_span.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_span.h new file mode 100644 index 000000000..c4280b1b6 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_span.h @@ -0,0 +1,46 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef __RADEON_SPAN_H__ +#define __RADEON_SPAN_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "drirenderbuffer.h" + +extern void radeonInitSpanFuncs(GLcontext * ctx); +extern void radeonSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis); + +#endif +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_state.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_state.c new file mode 100644 index 000000000..0cacbb5eb --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_state.c @@ -0,0 +1,245 @@ +/************************************************************************** + +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +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. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "imports.h" +#include "api_arrayelt.h" +#include "enums.h" +#include "colormac.h" +#include "light.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "swrast_setup/swrast_setup.h" + +#include "r200_context.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "r200_state.h" +#include "r300_ioctl.h" + + +/* ============================================================= + * Scissoring + */ + +static GLboolean intersect_rect(drm_clip_rect_t * out, + drm_clip_rect_t * a, drm_clip_rect_t * b) +{ + *out = *a; + if (b->x1 > out->x1) + out->x1 = b->x1; + if (b->y1 > out->y1) + out->y1 = b->y1; + if (b->x2 < out->x2) + out->x2 = b->x2; + if (b->y2 < out->y2) + out->y2 = b->y2; + if (out->x1 >= out->x2) + return GL_FALSE; + if (out->y1 >= out->y2) + return GL_FALSE; + return GL_TRUE; +} + +void radeonRecalcScissorRects(radeonContextPtr radeon) +{ + drm_clip_rect_t *out; + int i; + + /* Grow cliprect store? + */ + if (radeon->state.scissor.numAllocedClipRects < radeon->numClipRects) { + while (radeon->state.scissor.numAllocedClipRects < + radeon->numClipRects) { + radeon->state.scissor.numAllocedClipRects += 1; /* zero case */ + radeon->state.scissor.numAllocedClipRects *= 2; + } + + if (radeon->state.scissor.pClipRects) + FREE(radeon->state.scissor.pClipRects); + + radeon->state.scissor.pClipRects = + MALLOC(radeon->state.scissor.numAllocedClipRects * + sizeof(drm_clip_rect_t)); + + if (radeon->state.scissor.pClipRects == NULL) { + radeon->state.scissor.numAllocedClipRects = 0; + return; + } + } + + out = radeon->state.scissor.pClipRects; + radeon->state.scissor.numClipRects = 0; + + for (i = 0; i < radeon->numClipRects; i++) { + if (intersect_rect(out, + &radeon->pClipRects[i], + &radeon->state.scissor.rect)) { + radeon->state.scissor.numClipRects++; + out++; + } + } +} + +void radeonUpdateScissor(GLcontext* ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + assert(radeon->state.scissor.enabled == ctx->Scissor.Enabled); + + if (radeon->dri.drawable) { + __DRIdrawablePrivate *dPriv = radeon->dri.drawable; + int x1 = dPriv->x + ctx->Scissor.X; + int y1 = dPriv->y + dPriv->h - (ctx->Scissor.Y + ctx->Scissor.Height); + + radeon->state.scissor.rect.x1 = x1; + radeon->state.scissor.rect.y1 = y1; + radeon->state.scissor.rect.x2 = x1 + ctx->Scissor.Width - 1; + radeon->state.scissor.rect.y2 = y1 + ctx->Scissor.Height - 1; + + radeonRecalcScissorRects(radeon); + } +} + +static void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + if (ctx->Scissor.Enabled) { + /* We don't pipeline cliprect changes */ + if (IS_FAMILY_R200(radeon)) + R200_FIREVERTICES((r200ContextPtr)radeon); + else + r300Flush(ctx); + + radeonUpdateScissor(ctx); + } +} + + +/** + * Update cliprects and scissors. + */ +void radeonSetCliprects(radeonContextPtr radeon, GLenum mode) +{ + __DRIdrawablePrivate *dPriv = radeon->dri.drawable; + + switch (mode) { + case GL_FRONT_LEFT: + radeon->numClipRects = dPriv->numClipRects; + radeon->pClipRects = dPriv->pClipRects; + break; + case GL_BACK_LEFT: + /* Can't ignore 2d windows if we are page flipping. + */ + if (dPriv->numBackClipRects == 0 || radeon->doPageFlip) { + radeon->numClipRects = dPriv->numClipRects; + radeon->pClipRects = dPriv->pClipRects; + } else { + radeon->numClipRects = dPriv->numBackClipRects; + radeon->pClipRects = dPriv->pBackClipRects; + } + break; + default: + fprintf(stderr, "bad mode in radeonSetCliprects\n"); + radeon->numClipRects = 0; + radeon->pClipRects = 0; + return; + } + + if (radeon->state.scissor.enabled) + radeonRecalcScissorRects(radeon); +} + + +/** + * Handle common enable bits. + * Called as a fallback by r200Enable/r300Enable. + */ +void radeonEnable(GLcontext* ctx, GLenum cap, GLboolean state) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + switch(cap) { + case GL_SCISSOR_TEST: + /* We don't pipeline cliprect & scissor changes */ + if (IS_FAMILY_R200(radeon)) + R200_FIREVERTICES((r200ContextPtr)radeon); + else + r300Flush(ctx); + + radeon->state.scissor.enabled = state; + radeonUpdateScissor(ctx); + break; + + default: + return; + } +} + + +/** + * Initialize default state. + * This function is called once at context init time from + * r200InitState/r300InitState + */ +void radeonInitState(radeonContextPtr radeon) +{ + radeon->Fallback = 0; + + if (radeon->glCtx->Visual.doubleBufferMode && radeon->sarea->pfCurrentPage == 0) { + radeon->state.color.drawOffset = radeon->radeonScreen->backOffset; + radeon->state.color.drawPitch = radeon->radeonScreen->backPitch; + } else { + radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset; + radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch; + } + + radeon->state.pixel.readOffset = radeon->state.color.drawOffset; + radeon->state.pixel.readPitch = radeon->state.color.drawPitch; +} + + +/** + * Initialize common state functions. + * Called by r200InitStateFuncs/r300InitStateFuncs + */ +void radeonInitStateFuncs(struct dd_function_table *functions) +{ + functions->Scissor = radeonScissor; +} diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_state.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_state.h new file mode 100644 index 000000000..636bf5d00 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/radeon_state.h @@ -0,0 +1,45 @@ +/* +Copyright (C) 2004 Nicolai Haehnle. 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. + +**************************************************************************/ + +/* + * Authors: + * Nicolai Haehnle <prefect_@gmx.net> + */ + +#ifndef __RADEON_STATE_H__ +#define __RADEON_STATE_H__ + +#include "radeon_context.h" + +extern void radeonRecalcScissorRects(radeonContextPtr radeon); +extern void radeonSetCliprects(radeonContextPtr radeon, GLenum mode); +extern void radeonUpdateScissor(GLcontext* ctx); + +extern void radeonEnable(GLcontext* ctx, GLenum cap, GLboolean state); + +extern void radeonInitState(radeonContextPtr radeon); +extern void radeonInitStateFuncs(struct dd_function_table* functions); + +#endif diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/vertex_shader.h b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/vertex_shader.h new file mode 100644 index 000000000..6293915bf --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/vertex_shader.h @@ -0,0 +1,91 @@ +#ifndef __VERTEX_SHADER_H__ +#define __VERTEX_SHADER_H__ + +#include "r300_reg.h" + +typedef struct { + CARD32 op; + CARD32 src1; + CARD32 src2; + CARD32 src3; + } VERTEX_SHADER_INSTRUCTION; + +#define VSF_FLAG_X 1 +#define VSF_FLAG_Y 2 +#define VSF_FLAG_Z 4 +#define VSF_FLAG_W 8 +#define VSF_FLAG_XYZ (VSF_FLAG_X | VSF_FLAG_Y | VSF_FLAG_Z) +#define VSF_FLAG_ALL 0xf +#define VSF_FLAG_NONE 0 + +#define VSF_OUT_CLASS_TMP 0 +#define VSF_OUT_CLASS_RESULT 2 + + +/* first CARD32 of an instruction */ + +/* possible operations: + DOT, MUL, ADD, MAD, FRC, MAX, MIN, SGE, SLT, EXP, LOG, LIT, POW, RCP, RSQ, EX2, + LG2, MAD_2 */ + +#define MAKE_VSF_OP(op, out_reg_index, out_reg_fields, class) \ + ((op) \ + | ((out_reg_index) << R300_VPI_OUT_REG_INDEX_SHIFT) \ + | ((out_reg_fields) << 20) \ + | ( (class) << 8 ) ) + +#define EASY_VSF_OP(op, out_reg_index, out_reg_fields, class) \ + MAKE_VSF_OP(R300_VPI_OUT_OP_##op, out_reg_index, VSF_FLAG_##out_reg_fields, VSF_OUT_CLASS_##class) \ + +/* according to Nikolai, the subsequent 3 CARD32 are sources, use same define for each */ + +#define VSF_IN_CLASS_TMP 0 +#define VSF_IN_CLASS_ATTR 1 +#define VSF_IN_CLASS_PARAM 2 +#define VSF_IN_CLASS_NONE 9 + +#define VSF_IN_COMPONENT_X 0 +#define VSF_IN_COMPONENT_Y 1 +#define VSF_IN_COMPONENT_Z 2 +#define VSF_IN_COMPONENT_W 3 +#define VSF_IN_COMPONENT_ZERO 4 +#define VSF_IN_COMPONENT_ONE 5 + +#define MAKE_VSF_SOURCE(in_reg_index, comp_x, comp_y, comp_z, comp_w, class, negate) \ + ( ((in_reg_index)<<R300_VPI_IN_REG_INDEX_SHIFT) \ + | ((comp_x)<<R300_VPI_IN_X_SHIFT) \ + | ((comp_y)<<R300_VPI_IN_Y_SHIFT) \ + | ((comp_z)<<R300_VPI_IN_Z_SHIFT) \ + | ((comp_w)<<R300_VPI_IN_W_SHIFT) \ + | ((negate)<<25) | ((class))) + +#define EASY_VSF_SOURCE(in_reg_index, comp_x, comp_y, comp_z, comp_w, class, negate) \ + MAKE_VSF_SOURCE(in_reg_index, \ + VSF_IN_COMPONENT_##comp_x, \ + VSF_IN_COMPONENT_##comp_y, \ + VSF_IN_COMPONENT_##comp_z, \ + VSF_IN_COMPONENT_##comp_w, \ + VSF_IN_CLASS_##class, VSF_FLAG_##negate) + +/* special sources: */ + +/* (1.0,1.0,1.0,1.0) vector (ATTR, plain ) */ +#define VSF_ATTR_UNITY(reg) EASY_VSF_SOURCE(reg, ONE, ONE, ONE, ONE, ATTR, NONE) +#define VSF_UNITY(reg) EASY_VSF_SOURCE(reg, ONE, ONE, ONE, ONE, NONE, NONE) + +/* contents of unmodified register */ +#define VSF_REG(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, ATTR, NONE) + +/* contents of unmodified parameter */ +#define VSF_PARAM(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, PARAM, NONE) + +/* contents of unmodified temporary register */ +#define VSF_TMP(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, TMP, NONE) + +/* components of ATTR register */ +#define VSF_ATTR_X(reg) EASY_VSF_SOURCE(reg, X, X, X, X, ATTR, NONE) +#define VSF_ATTR_Y(reg) EASY_VSF_SOURCE(reg, Y, Y, Y, Y, ATTR, NONE) +#define VSF_ATTR_Z(reg) EASY_VSF_SOURCE(reg, Z, Z, Z, Z, ATTR, NONE) +#define VSF_ATTR_W(reg) EASY_VSF_SOURCE(reg, W, W, W, W, ATTR, NONE) + +#endif |