Initial revision

This commit is contained in:
Nicolai Haehnle 2004-09-28 10:59:23 +00:00
parent bbe364603c
commit f30d53e049
28 changed files with 8258 additions and 0 deletions

View file

@ -0,0 +1,72 @@
# src/mesa/drivers/dri/r300/Makefile
TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = r300_dri.so
DEFINES += -DCOMPILE_R300
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 \
../common/glcontextmodes.c
DRIVER_SOURCES = \
radeon_screen.c \
radeon_context.c \
radeon_ioctl.c \
radeon_lock.c \
radeon_span.c \
\
r300_context.c \
r300_ioctl.c \
r300_cmdbuf.c \
r300_state.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_tcl.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)

View file

@ -0,0 +1,840 @@
/* $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_scissor_state {
drm_clip_rect_t rect;
GLboolean enabled;
GLuint numClipRects; /* Cliprects active */
GLuint numAllocedClipRects; /* Cliprects available */
drm_clip_rect_t *pClipRects;
};
struct r200_stencilbuffer_state {
GLboolean hwBuffer;
GLuint clear; /* rb3d_stencilrefmask value */
};
struct r200_stipple_state {
GLuint mask[32];
};
#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_ALL 0x3f
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_scissor_state scissor;
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__ */

View file

@ -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__ */

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -0,0 +1,61 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_state.h,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>
*/
#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 r200SetCliprects(r200ContextPtr rmesa, GLenum mode);
extern void r200RecalcScissorRects(r200ContextPtr rmesa);
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

View file

@ -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

View file

@ -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__ */

View file

@ -0,0 +1,489 @@
/*
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 "r300_reg.h"
#include "r300_cmdbuf.h"
/**
* Send the current command buffer via ioctl to the hardware.
*/
int r300FlushCmdBuf(r300ContextPtr r300, const char* caller)
{
int ret;
int i;
drm_radeon_cmd_buffer_t cmd;
int start;
if (r300->radeon.lost_context)
start = 0;
else
start = r300->cmdbuf.count_reemit;
if (RADEON_DEBUG & DEBUG_IOCTL) {
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
if (RADEON_DEBUG & DEBUG_VERBOSE)
for (i = start; i < r300->cmdbuf.count_used; ++i)
fprintf(stderr, "%d: %08x\n", i,
r300->cmdbuf.cmd_buf[i]);
}
LOCK_HARDWARE(&r300->radeon);
cmd.buf = (char*)(r300->cmdbuf.cmd_buf + start);
cmd.bufsz = (r300->cmdbuf.count_used - start) * 4;
#if 0 // TODO: scissors
if (rmesa->state.scissor.enabled) {
cmd.nbox = rmesa->state.scissor.numClipRects;
cmd.boxes = (drm_clip_rect_t *) rmesa->state.scissor.pClipRects;
} else {
#endif
cmd.nbox = r300->radeon.numClipRects;
cmd.boxes = (drm_clip_rect_t *) r300->radeon.pClipRects;
#if 0
}
#endif
ret = drmCommandWrite(r300->radeon.dri.fd,
DRM_RADEON_CMDBUF, &cmd, sizeof(cmd));
if (ret) {
UNLOCK_HARDWARE(&r300->radeon);
fprintf(stderr, "drmCommandWrite: %d\n", ret);
exit(-1);
}
if (RADEON_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "Syncing in %s\n\n", __FUNCTION__);
radeonWaitForIdleLocked(&r300->radeon);
}
UNLOCK_HARDWARE(&r300->radeon);
r300->cmdbuf.count_used = 0;
r300->cmdbuf.count_reemit = 0;
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 (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);
}
}
}
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;
}
static __inline__ uint32_t cmducs(int reg, int count)
{
drm_r300_cmd_header_t cmd;
cmd.unchecked_state.cmd_type = R300_CMD_UNCHECKED_STATE;
cmd.unchecked_state.count = count;
cmd.unchecked_state.reghi = ((unsigned int)reg & 0xFF00) >> 8;
cmd.unchecked_state.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;
}
#define CHECK( NM, COUNT ) \
static int check_##NM( r300ContextPtr r300, \
struct r300_state_atom* atom ) \
{ \
(void) atom; (void) r300; \
return (COUNT); \
}
#define ucscount(ptr) (((drm_r300_cmd_header_t*)(ptr))->unchecked_state.count)
#define vpucount(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)
CHECK( always, atom->cmd_size )
CHECK( never, 0 )
CHECK( variable, ucscount(atom->cmd) ? (1 + ucscount(atom->cmd)) : 0 )
CHECK( vpu, vpucount(atom->cmd) ? (1 + vpucount(atom->cmd)*4) : 0 )
#undef ucscount
#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;
r300->hw.max_state_size = 0;
/* Initialize state atoms */
ALLOC_STATE( vpt, always, R300_VPT_CMDSIZE, "vpt", 0 );
r300->hw.vpt.cmd[R300_VPT_CMD_0] = cmducs(R300_SE_VPORT_XSCALE, 6);
ALLOC_STATE( unk2080, always, 2, "unk2080", 0 );
r300->hw.unk2080.cmd[0] = cmducs(0x2080, 1);
ALLOC_STATE( ovf, always, R300_OVF_CMDSIZE, "ovf", 0 );
r300->hw.ovf.cmd[R300_OVF_CMD_0] = cmducs(R300_VAP_OUTPUT_VTX_FMT_0, 2);
ALLOC_STATE( unk20B0, always, 3, "unk20B0", 0 );
r300->hw.unk20B0.cmd[0] = cmducs(0x20B0, 2);
ALLOC_STATE( unk2134, always, 3, "unk2134", 0 );
r300->hw.unk2134.cmd[0] = cmducs(0x2134, 2);
ALLOC_STATE( unk2140, always, 2, "unk2140", 0 );
r300->hw.unk2140.cmd[0] = cmducs(0x2140, 1);
ALLOC_STATE( vir[0], variable, R300_VIR_CMDSIZE, "vir/0", 0 );
r300->hw.vir[0].cmd[R300_VIR_CMD_0] = cmducs(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] = cmducs(R300_VAP_INPUT_ROUTE_1_0, 1);
ALLOC_STATE( vic, always, R300_VIC_CMDSIZE, "vic", 0 );
r300->hw.vic.cmd[R300_VIC_CMD_0] = cmducs(R300_VAP_INPUT_CNTL_0, 2);
ALLOC_STATE( unk21DC, always, 2, "unk21DC", 0 );
r300->hw.unk21DC.cmd[0] = cmducs(0x21DC, 1);
ALLOC_STATE( unk221C, always, 2, "unk221C", 0 );
r300->hw.unk221C.cmd[0] = cmducs(0x221C, 1);
ALLOC_STATE( unk2220, always, 5, "unk2220", 0 );
r300->hw.unk2220.cmd[0] = cmducs(0x2220, 4);
ALLOC_STATE( unk2288, always, 2, "unk2288", 0 );
r300->hw.unk2288.cmd[0] = cmducs(0x2288, 1);
ALLOC_STATE( pvs, always, R300_PVS_CMDSIZE, "pvs", 0 );
r300->hw.pvs.cmd[R300_PVS_CMD_0] = cmducs(R300_VAP_PVS_CNTL_1, 3);
ALLOC_STATE( unk4008, always, 2, "unk4008", 0 );
r300->hw.unk4008.cmd[0] = cmducs(0x4008, 1);
ALLOC_STATE( unk4010, always, 6, "unk4010", 0 );
r300->hw.unk4010.cmd[0] = cmducs(0x4010, 5);
ALLOC_STATE( txe, always, R300_TXE_CMDSIZE, "txe", 0 );
r300->hw.txe.cmd[R300_TXE_CMD_0] = cmducs(R300_TX_ENABLE, 1);
ALLOC_STATE( unk4200, always, 5, "unk4200", 0 );
r300->hw.unk4200.cmd[0] = cmducs(0x4200, 4);
ALLOC_STATE( unk4214, always, 2, "unk4214", 0 );
r300->hw.unk4214.cmd[0] = cmducs(0x4214, 1);
ALLOC_STATE( unk4230, always, 4, "unk4230", 0 );
r300->hw.unk4230.cmd[0] = cmducs(0x4230, 3);
ALLOC_STATE( unk4260, always, 4, "unk4260", 0 );
r300->hw.unk4260.cmd[0] = cmducs(0x4260, 3);
ALLOC_STATE( unk4274, always, 5, "unk4274", 0 );
r300->hw.unk4274.cmd[0] = cmducs(0x4274, 4);
ALLOC_STATE( unk4288, always, 6, "unk4288", 0 );
r300->hw.unk4288.cmd[0] = cmducs(0x4288, 5);
ALLOC_STATE( unk42A0, always, 2, "unk42A0", 0 );
r300->hw.unk42A0.cmd[0] = cmducs(0x42A0, 1);
ALLOC_STATE( unk42B4, always, 3, "unk42B4", 0 );
r300->hw.unk42B4.cmd[0] = cmducs(0x42B4, 2);
ALLOC_STATE( unk42C0, always, 3, "unk42C0", 0 );
r300->hw.unk42C0.cmd[0] = cmducs(0x42C0, 2);
ALLOC_STATE( rc, always, R300_RC_CMDSIZE, "rc", 0 );
r300->hw.rc.cmd[R300_RC_CMD_0] = cmducs(R300_RS_CNTL_0, 2);
ALLOC_STATE( ri, always, R300_RI_CMDSIZE, "ri", 0 );
r300->hw.ri.cmd[R300_RI_CMD_0] = cmducs(R300_RS_INTERP_0, 8);
ALLOC_STATE( rr, variable, R300_RR_CMDSIZE, "rr", 0 );
r300->hw.rr.cmd[R300_RR_CMD_0] = cmducs(R300_RS_ROUTE_0, 1);
ALLOC_STATE( unk43A4, always, 3, "unk43A4", 0 );
r300->hw.unk43A4.cmd[0] = cmducs(0x43A4, 2);
ALLOC_STATE( unk43E0, always, 4, "unk43E0", 0 );
r300->hw.unk43E0.cmd[0] = cmducs(0x43E0, 3);
ALLOC_STATE( fp, always, R300_FP_CMDSIZE, "fp", 0 );
r300->hw.fp.cmd[R300_FP_CMD_0] = cmducs(R300_PFS_CNTL_0, 3);
r300->hw.fp.cmd[R300_FP_CMD_1] = cmducs(R300_PFS_NODE_0, 4);
ALLOC_STATE( unk46A4, always, 6, "unk46A4", 0 );
r300->hw.unk46A4.cmd[0] = cmducs(0x46A4, 5);
ALLOC_STATE( fpi[0], variable, R300_FPI_CMDSIZE, "fpi/0", 0 );
r300->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmducs(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] = cmducs(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] = cmducs(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] = cmducs(R300_PFS_INSTR3_0, 1);
ALLOC_STATE( unk4BC0, always, 2, "unk4BC0", 0 );
r300->hw.unk4BC0.cmd[0] = cmducs(0x4BC0, 1);
ALLOC_STATE( unk4BC8, always, 4, "unk4BC8", 0 );
r300->hw.unk4BC8.cmd[0] = cmducs(0x4BC8, 3);
ALLOC_STATE( at, always, R300_AT_CMDSIZE, "at", 0 );
r300->hw.at.cmd[R300_AT_CMD_0] = cmducs(R300_PP_ALPHA_TEST, 1);
ALLOC_STATE( unk4BD8, always, 2, "unk4BD8", 0 );
r300->hw.unk4BD8.cmd[0] = cmducs(0x4BD8, 1);
ALLOC_STATE( unk4E00, always, 2, "unk4E00", 0 );
r300->hw.unk4E00.cmd[0] = cmducs(0x4E00, 1);
ALLOC_STATE( bld, always, R300_BLD_CMDSIZE, "bld", 0 );
r300->hw.bld.cmd[R300_BLD_CMD_0] = cmducs(R300_RB3D_CBLEND, 2);
ALLOC_STATE( cmk, always, R300_CMK_CMDSIZE, "cmk", 0 );
r300->hw.cmk.cmd[R300_CMK_CMD_0] = cmducs(R300_RB3D_COLORMASK, 1);
ALLOC_STATE( unk4E10, always, 4, "unk4E10", 0 );
r300->hw.unk4E10.cmd[0] = cmducs(0x4E10, 3);
ALLOC_STATE( cb, always, R300_CB_CMDSIZE, "cb", 0 );
r300->hw.cb.cmd[R300_CB_CMD_0] = cmducs(R300_RB3D_COLOROFFSET0, 1);
r300->hw.cb.cmd[R300_CB_CMD_1] = cmducs(R300_RB3D_COLORPITCH0, 1);
ALLOC_STATE( unk4E50, always, 10, "unk4E50", 0 );
r300->hw.unk4E50.cmd[0] = cmducs(0x4E50, 9);
ALLOC_STATE( unk4E88, always, 2, "unk4E88", 0 );
r300->hw.unk4E88.cmd[0] = cmducs(0x4E88, 1);
ALLOC_STATE( zc, always, R300_ZC_CMDSIZE, "zc", 0 );
r300->hw.zc.cmd[R300_ZC_CMD_0] = cmducs(R300_RB3D_ZCNTL_0, 2);
ALLOC_STATE( unk4F08, always, 6, "unk4F08", 0 );
r300->hw.unk4F08.cmd[0] = cmducs(0x4F08, 5);
ALLOC_STATE( zb, always, R300_ZB_CMDSIZE, "zb", 0 );
r300->hw.zb.cmd[R300_ZB_CMD_0] = cmducs(R300_RB3D_DEPTHOFFSET, 2);
ALLOC_STATE( unk4F28, always, 2, "unk4F28", 0 );
r300->hw.unk4F28.cmd[0] = cmducs(0x4F28, 1);
ALLOC_STATE( unk4F30, always, 3, "unk4F30", 0 );
r300->hw.unk4F30.cmd[0] = cmducs(0x4F30, 2);
ALLOC_STATE( unk4F44, always, 2, "unk4F44", 0 );
r300->hw.unk4F44.cmd[0] = cmducs(0x4F44, 1);
ALLOC_STATE( unk4F54, always, 2, "unk4F54", 0 );
r300->hw.unk4F54.cmd[0] = cmducs(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);
/* 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.ovf);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk20B0);
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.pvs);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4008);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4010);
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.unk4230);
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.unk42B4);
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.unk43E0);
insert_at_tail(&r300->hw.atomlist, &r300->hw.fp);
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.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.zc);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4F08);
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);
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;
if (RADEON_DEBUG & DEBUG_IOCTL)
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);
}
}

View file

@ -0,0 +1,102 @@
/*
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 r300FlushCmdBuf(r300ContextPtr r300, const char* caller);
extern void r300EmitState(r300ContextPtr r300);
extern void r300InitCmdBuf(r300ContextPtr r300);
extern void r300DestroyCmdBuf(r300ContextPtr r300);
/**
* 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;
}
#endif /* __R300_CMDBUF_H__ */

View file

@ -0,0 +1,308 @@
/*
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 "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 "vblank.h"
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
/* Extension strings exported by the R300 driver.
*/
static const char *const card_extensions[] = {
"GL_ARB_multisample",
"GL_ARB_multitexture",
"GL_ARB_texture_border_clamp",
"GL_ARB_texture_compression",
"GL_ARB_texture_cube_map",
"GL_ARB_texture_env_add",
"GL_ARB_texture_env_combine",
"GL_ARB_texture_env_dot3",
"GL_ARB_texture_mirrored_repeat",
"GL_ARB_vertex_buffer_object",
"GL_ARB_vertex_program",
"GL_EXT_blend_equation_separate",
"GL_EXT_blend_func_separate",
"GL_EXT_blend_minmax",
"GL_EXT_blend_subtract",
"GL_EXT_secondary_color",
"GL_EXT_stencil_wrap",
"GL_EXT_texture_edge_clamp",
"GL_EXT_texture_env_combine",
"GL_EXT_texture_env_dot3",
"GL_EXT_texture_filter_anisotropic",
"GL_EXT_texture_lod_bias",
"GL_EXT_texture_mirror_clamp",
"GL_EXT_texture_rectangle",
"GL_ATI_texture_env_combine3",
"GL_ATI_texture_mirror_once",
"GL_MESA_pack_invert",
"GL_MESA_ycbcr_texture",
"GL_NV_blend_square",
"GL_NV_vertex_program",
"GL_SGIS_generate_mipmap",
NULL
};
//extern const struct tnl_pipeline_stage _r300_render_stage;
//extern const struct tnl_pipeline_stage _r300_tcl_stage;
static const struct tnl_pipeline_stage *r300_pipeline[] = {
/* Try and go straight to t&l
*/
//&_r200_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_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,
};
/* 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 i;
int tcl_mode;
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);
//r200InitStateFuncs(&functions);
//r200InitTextureFuncs(&functions);
if (!radeonInitContext(&r300->radeon, &functions,
glVisual, driContextPriv, sharedContextPrivate)) {
FREE(r300);
return GL_FALSE;
}
/* Init r300 context data */
/* 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;
/* No wide points.
*/
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 1.0;
ctx->Const.MaxLineWidthAA = 1.0;
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext(ctx);
_ac_CreateContext(ctx);
_tnl_CreateContext(ctx);
_swsetup_CreateContext(ctx);
_ae_create_context(ctx);
#if 0
/* Install the customized pipeline:
*/
_tnl_destroy_pipeline(ctx);
_tnl_install_pipeline(ctx, r200_pipeline);
ctx->Driver.FlushVertices = r200FlushVertices;
#endif
/* 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);
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() */
r200InitPixelFuncs(ctx);
r200InitTnlFuncs(ctx);
r200InitSwtcl(ctx);
#endif
TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
tcl_mode = driQueryOptioni(&r300->radeon.optionCache, "tcl_mode");
if (1 ||
driQueryOptionb(&r300->radeon.optionCache, "no_rast")) {
fprintf(stderr, "disabling 3D acceleration\n");
FALLBACK(&r300->radeon, RADEON_FALLBACK_DISABLE, 1);
}
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;
/* check if we're deleting the currently bound context */
if (&r300->radeon == current) {
radeonFlush(r300->radeon.glCtx);
_mesa_make_current2(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);
/* free the Mesa context */
r300->radeon.glCtx->DriverCtx = NULL;
_mesa_destroy_context(r300->radeon.glCtx);
/* free the option cache */
driDestroyOptionCache(&r300->radeon.optionCache);
FREE(r300);
}
}

View file

@ -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.
**************************************************************************/
/*
* 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"
struct r300_context;
typedef struct r300_context r300ContextRec;
typedef struct r300_context *r300ContextPtr;
#include "radeon_lock.h"
#include "mm.h"
static __inline__ uint32_t r300PackFloat32(float fl)
{
union { float fl; uint32_t u; } u;
u.fl = fl;
return u.u;
}
/**
* 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_OVF_CMD_0 0
#define R300_OVF_FMT_0 1
#define R300_OVF_FMT_1 2
#define R300_OVF_CMDSIZE 3
#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_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_TXE_CMD_0 0
#define R300_TXE_ENABLE 1
#define R300_TXE_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_FPI_CMD_0 0
#define R300_FPI_INSTR_0 1
#define R300_FPI_CMDSIZE 65
#define R300_AT_CMD_0 0
#define R300_AT_ALPHA_TEST 1
#define R300_AT_CMDSIZE 2
#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_ZC_CMD_0 0
#define R300_ZC_CNTL_0 1
#define R300_ZC_CNTL_1 2
#define R300_ZC_CMDSIZE 3
#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 */
/**
* 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 ovf; /* output vertex format (2090) */
struct r300_state_atom unk20B0; /* (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 unk4008; /* (4008) */
struct r300_state_atom unk4010; /* (4010) */
struct r300_state_atom txe; /* tex enable (4104) */
struct r300_state_atom unk4200; /* (4200) */
struct r300_state_atom unk4214; /* (4214) */
// what about UNKNOWN_421C? (see r300_reg.h)
struct r300_state_atom unk4230; /* (4230) */
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 unk42B4; /* (42B4) */
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 unk43E0; /* (43E0) */
struct r300_state_atom fp; /* fragment program cntl + nodes (4600) */
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 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 zc; /* z control (4F00) */
struct r300_state_atom unk4F08; /* (4F08) */
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 */
};
/**
* 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_state {
};
/**
* 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;
};
#define R300_CONTEXT(ctx) ((r300ContextPtr)(ctx->DriverCtx))
extern void r300DestroyContext(__DRIcontextPrivate * driContextPriv);
extern GLboolean r300CreateContext(const __GLcontextModes * glVisual,
__DRIcontextPrivate * driContextPriv,
void *sharedContextPrivate);
#endif /* __R300_CONTEXT_H__ */

View file

@ -0,0 +1,236 @@
/*
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 <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 "vblank.h"
static void r300ClearColorBuffer(r300ContextPtr r300, int buffer)
{
GLcontext* ctx = r300->radeon.glCtx;
__DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
int i;
GLuint cboffset, cbpitch;
drm_r300_cmd_header_t* cmd;
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s: %s buffer\n", __FUNCTION__,
buffer ? "back" : "front");
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;
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, cb);
r300->hw.cb.cmd[R300_CB_OFFSET] = cboffset;
r300->hw.cb.cmd[R300_CB_PITCH] = cbpitch | R300_COLOR_UNKNOWN_22_23;
R300_STATECHANGE(r300, unk221C);
r300->hw.unk221C.cmd[1] = R300_221C_CLEAR;
R300_STATECHANGE(r300, ri);
for(i = 1; i <= 8; ++i)
r300->hw.ri.cmd[i] = R300_RS_INTERP_USED;
R300_STATECHANGE(r300, rr);
((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1;
r300->hw.rr.cmd[1] = 0x00004000;
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)->unchecked_state.count = 1;
((drm_r300_cmd_header_t*)r300->hw.fpi[1].cmd)->unchecked_state.count = 1;
((drm_r300_cmd_header_t*)r300->hw.fpi[2].cmd)->unchecked_state.count = 1;
((drm_r300_cmd_header_t*)r300->hw.fpi[3].cmd)->unchecked_state.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_UNKNOWN_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)->unchecked_state.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;
/* Make sure we have enough space */
r300EnsureCmdBufSpace(r300, r300->hw.max_state_size + 9, __FUNCTION__);
r300EmitState(r300);
cmd = (drm_r300_cmd_header_t*)r300AllocCmdBuf(r300, 9, __FUNCTION__);
cmd[0].packet3.cmd_type = R300_CMD_PACKET3;
cmd[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
cmd[1].u = r300PackFloat32(dPriv->w / 2.0); /* my guess is as good as yours */
cmd[2].u = r300PackFloat32(dPriv->h / 2.0);
cmd[3].u = r300PackFloat32(0.0);
cmd[4].u = r300PackFloat32(1.0);
cmd[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
cmd[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
cmd[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
cmd[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
}
/**
* 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 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 & DD_FRONT_LEFT_BIT) {
flags |= DD_FRONT_LEFT_BIT;
mask &= ~DD_FRONT_LEFT_BIT;
}
if (mask & DD_BACK_LEFT_BIT) {
flags |= DD_BACK_LEFT_BIT;
mask &= ~DD_BACK_LEFT_BIT;
}
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);
if (flags & DD_FRONT_LEFT_BIT)
r300ClearColorBuffer(r300, swapped);
if (flags & DD_BACK_LEFT_BIT)
r300ClearColorBuffer(r300, swapped ^ 1);
/* Recalculate the hardware set. This could be done more efficiently,
* but do keep it like this for now.
*/
r300ResetHwState(r300);
}
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 r300InitIoctlFuncs(struct dd_function_table *functions)
{
functions->Clear = r300Clear;
functions->Finish = radeonFinish;
functions->Flush = r300Flush;
}

View file

@ -0,0 +1,42 @@
/*
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__
extern void r300Flush(GLcontext * ctx);
extern void r300InitIoctlFuncs(struct dd_function_table *functions);
#endif /* __R300_IOCTL_H__ */

View file

@ -0,0 +1,148 @@
/*
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))
#endif /* __R300_PROGRAM_H__ */

View file

@ -0,0 +1,847 @@
#ifndef _R300_REG_H
#define _R300_REG_H
/*
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
// 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
// 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
/* 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
// 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.
//
// 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_UNKNOWN 0x00000400
/* 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 somewhere in the middle, but the criteria are not clear.
#define R300_VAP_PVS_CNTL_1 0x22D0
# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
# define R300_PVS_CNTL_1_UNKNOWN_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
// 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 */
// BEGIN: !unverified!
#define R300_GB_TILE_CONFIG 0x4018
#define R300_GB_TILE_ENABLE (1 << 0)
#define R300_GB_TILE_PIPE_COUNT_R300 (0 << 1)
#define R300_GB_TILE_PIPE_COUNT_RV300 (3 << 1)
#define R300_GB_TILE_SIZE_8 (0 << 4)
#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 << 15)
#define R300_GB_SUPER_TILE_B (1 << 15)
#define R300_GB_SUBPIXEL_1_12 (0 << 16)
#define R300_GB_SUBPIXEL_1_16 (1 << 16)
// 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)
// No idea what the purpose is, but it is set to 421C_CLEAR just before
// issuing the clear command and then reset to 421C_NORMAL afterwards.
#define R300_UNKNOWN_421C 0x421C
# define R300_421C_NORMAL 0x00060006
# define R300_421C_CLEAR 0x0F000B40
// BEGIN: Rasterization / Interpolators - many guesses
// So far, 0_UNKOWN_7 has always been set.
// 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_0_UNKNOWN_7 (1 << 7)
# 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 (color seems to be always interpolated).
// 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 (1 << 17)
# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 6) // GUESS
// 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_CLAMP_TO_EDGE 1
# define R300_TX_CLAMP 2
# define R300_TX_CLAMP_TO_BORDER 3
# define R300_TX_WRAP_S_SHIFT 1
# define R300_TX_WRAP_S_MASK (3 << 1)
# define R300_TX_WRAP_T_SHIFT 4
# define R300_TX_WRAP_T_MASK (3 << 4)
# 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_UNK1_0 0x4440
#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_SIZE_SHIFT 26 // largest of width, height
# define R300_TX_SIZE_MASK (15 << 26)
#define R300_TX_FORMAT_0 0x44C0
#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_UNK5_0 0x45C0
// 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
// 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_ARG1A_SHIFT 7
# define R300_FPI2_ARG1A_MASK (31 << 7)
# define R300_FPI2_ARG1A_NEG (1 << 12)
# define R300_FPI2_ARG2A_SHIFT 14
# define R300_FPI2_AEG2A_MASK (31 << 14)
# define R300_FPI2_ARG2A_NEG (1 << 19)
# define R300_FPI2_SPECIAL_LRP (1 << 21)
# define R300_FPI2_OUTA_MAD (0 << 23)
# define R300_FPI2_OUTA_DP4 (1 << 23)
# define R300_RPI2_OUTA_MIN (2 << 23)
# define R300_RPI2_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 (2 << 8)
# define R300_ALPHA_TEST_EQUAL (3 << 8)
# define R300_ALPHA_TEST_GEQUAL (4 << 8)
# define R300_ALPHA_TEST_GREATER (5 << 8)
# define R300_ALPHA_TEST_NEQUAL (6 << 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_UNKNOWN_22_23 (3 << 22) // GUESS: Format?
#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.
#define R300_RB3D_ZCNTL_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_ZCNTL_1 0x4F04
# define R300_RB3D_Z_TEST_NEVER (0 << 0) // GUESS (based on R200)
# define R300_RB3D_Z_TEST_LESS (1 << 0)
# define R300_RB3D_Z_TEST_LEQUAL (2 << 0)
# define R300_RB3D_Z_TEST_EQUAL (3 << 0) // GUESS
# define R300_RB3D_Z_TEST_GEQUAL (4 << 0) // GUESS
# define R300_RB3D_Z_TEST_GREATER (5 << 0) // GUESS
# define R300_RB3D_Z_TEST_NEQUAL (6 << 0)
# define R300_RB3D_Z_TEST_ALWAYS (7 << 0)
# define R300_RB3D_Z_TEST_MASK (7 << 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_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_EXP (65 << 0)
#define R300_VPI_OUT_OP_LOG (66 << 0)
#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_EX2 (75 << 0)
#define R300_VPI_OUT_OP_LG2 (76 << 0)
#define R300_VPI_OUT_OP_MAD_2 (128 << 0)
#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
#endif // _R300_REG_H

View file

@ -0,0 +1,329 @@
/*
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 "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 "radeon_ioctl.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "r300_state.h"
#include "r300_reg.h"
#include "r300_program.h"
/**
* 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);
}
/**
* Completely recalculates hardware state based on the Mesa state.
*/
void r300ResetHwState(r300ContextPtr r300)
{
int i;
if (RADEON_DEBUG & DEBUG_STATE)
fprintf(stderr, "%s\n", __FUNCTION__);
{
__DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
const GLfloat *v = r300->radeon.glCtx->Viewport._WindowMap.m;
r300->hw.vpt.cmd[R300_VPT_XSCALE] =
r300PackFloat32(v[MAT_SX]);
r300->hw.vpt.cmd[R300_VPT_XOFFSET] =
r300PackFloat32(v[MAT_TX] + xoffset);
r300->hw.vpt.cmd[R300_VPT_YSCALE] =
r300PackFloat32(-v[MAT_SY]);
r300->hw.vpt.cmd[R300_VPT_YOFFSET] =
r300PackFloat32(-v[MAT_TY] + yoffset);
r300->hw.vpt.cmd[R300_VPT_YSCALE] =
r300PackFloat32(v[MAT_SZ]);
r300->hw.vpt.cmd[R300_VPT_YOFFSET] =
r300PackFloat32(v[MAT_TZ]);
}
//BEGIN: TODO
r300->hw.unk2080.cmd[1] = 0x0030045A;
r300->hw.ovf.cmd[R300_OVF_FMT_0] = 0x00000003;
r300->hw.ovf.cmd[R300_OVF_FMT_1] = 0x00000000;
r300->hw.unk20B0.cmd[1] = 0x0000040A;
r300->hw.unk20B0.cmd[2] = 0x00000008;
r300->hw.unk2134.cmd[1] = 0x00FFFFFF;
r300->hw.unk2134.cmd[2] = 0x00000000;
r300->hw.unk2140.cmd[1] = 0x00000000;
((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->unchecked_state.count = 1;
r300->hw.vir[0].cmd[1] = 0x21030003;
((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->unchecked_state.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;
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;
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;
r300->hw.unk4008.cmd[1] = 0x00000007;
r300->hw.unk4010.cmd[1] = 0x66666666;
r300->hw.unk4010.cmd[2] = 0x06666666;
if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R300)
r300->hw.unk4010.cmd[3] = 0x00000017;
else
r300->hw.unk4010.cmd[3] = 0x00000011;
r300->hw.unk4010.cmd[4] = 0x00000000;
r300->hw.unk4010.cmd[5] = 0x00000000;
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;
r300->hw.unk4230.cmd[1] = 0x01800000;
r300->hw.unk4230.cmd[2] = 0x00020006;
r300->hw.unk4230.cmd[3] = r300PackFloat32(1.0 / 192.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;
r300->hw.unk4274.cmd[2] = 0x0003AAAA;
r300->hw.unk4274.cmd[3] = 0x00000000;
r300->hw.unk4274.cmd[4] = 0x00000000;
r300->hw.unk4288.cmd[1] = 0x00000000;
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;
r300->hw.unk42B4.cmd[1] = 0x00000000;
r300->hw.unk42B4.cmd[2] = 0x00000000;
r300->hw.unk42C0.cmd[1] = 0x4B7FFFFF;
r300->hw.unk42C0.cmd[2] = 0x00000000;
r300->hw.rc.cmd[1] = R300_RS_CNTL_0_UNKNOWN_7;
r300->hw.rc.cmd[2] = 0;
for(i = 1; i <= 8; ++i)
r300->hw.ri.cmd[i] = 0;
((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1;
for(i = 1; i <= 8; ++i)
r300->hw.rr.cmd[1] = 0;
r300->hw.unk43A4.cmd[1] = 0x0000001C;
r300->hw.unk43A4.cmd[2] = 0x2DA49525;
r300->hw.unk43E0.cmd[1] = 0x00000000;
r300->hw.unk43E0.cmd[2] = 0x03FFFFFF;
r300->hw.unk43E0.cmd[3] = 0x00FFFFFF;
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;
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;
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);
}
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_ALPHA_TEST] = 0;
r300->hw.unk4BD8.cmd[1] = 0;
r300->hw.unk4E00.cmd[1] = 0;
r300->hw.bld.cmd[R300_BLD_CBLEND] = 0;
r300->hw.bld.cmd[R300_BLD_ABLEND] = 0;
r300->hw.cmk.cmd[R300_CMK_COLORMASK] = 0xF;
r300->hw.unk4E10.cmd[1] = 0;
r300->hw.unk4E10.cmd[2] = 0;
r300->hw.unk4E10.cmd[3] = 0;
r300->hw.cb.cmd[R300_CB_OFFSET] =
r300->radeon.radeonScreen->backOffset +
r300->radeon.radeonScreen->fbLocation;
r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->backPitch
| R300_COLOR_UNKNOWN_22_23;
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.zc.cmd[R300_ZC_CNTL_0] = 0;
r300->hw.zc.cmd[R300_ZC_CNTL_1] = 0;
r300->hw.unk4F08.cmd[1] = 0x00FFFF00;
r300->hw.unk4F08.cmd[2] = 0x00000002;
r300->hw.unk4F08.cmd[3] = 0x00000000;
r300->hw.unk4F08.cmd[4] = 0x00000003;
r300->hw.unk4F08.cmd[5] = 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;
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;
((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;
//END: TODO
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)
{
struct dd_function_table* functions;
r300ResetHwState(r300);
/* Setup state functions */
functions = &r300->radeon.glCtx->Driver;
functions->UpdateState = r300InvalidateState;
}

View file

@ -0,0 +1,49 @@
/*
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)
extern void r300ResetHwState(r300ContextPtr r300);
extern void r300InitState(r300ContextPtr r300);
#endif /* __R300_STATE_H__ */

View file

@ -0,0 +1,302 @@
/*
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 "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 = _swrast_alloc_buffers;
functions->GetString = radeonGetString;
}
static int get_ust_nop(int64_t * ust)
{
*ust = 1;
return 0;
}
/**
* 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;
radeon->get_ust =
(PFNGLXGETUSTPROC) glXGetProcAddress((const GLubyte *)
"__glXGetUST");
if (radeon->get_ust == NULL) {
radeon->get_ust = get_ust_nop;
}
(*radeon->get_ust) (&radeon->swap_ust);
return GL_TRUE;
}
/**
* 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 (IS_FAMILY_R200(radeon)) {
r200UpdateWindow(radeon->glCtx);
r200UpdateViewportOffset(radeon->glCtx);
}
}
_mesa_make_current2(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 (IS_FAMILY_R200(radeon))
r200ValidateState(radeon->glCtx);
} else {
if (RADEON_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
_mesa_make_current(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;
}

View file

@ -0,0 +1,222 @@
/*
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;
}
}
/* 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
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)
/* 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 */
#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode )
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_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;
};
/**
* 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;
PFNGLXGETUSTPROC get_ust;
/* 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 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__ */

View file

@ -0,0 +1,348 @@
/*
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 "r200_state.h"
#include "radeon_ioctl.h"
#include "r200_ioctl.h"
#include "r300_ioctl.h"
#include "r200_tcl.h"
#include "r200_sanity.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);
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_R200_SWAP_BUFFERS: return = %d\n",
ret);
UNLOCK_HARDWARE(radeon);
exit(1);
}
}
UNLOCK_HARDWARE(radeon);
if (IS_FAMILY_R200(radeon))
((r200ContextPtr)radeon)->hw.all_dirty = GL_TRUE;
radeon->swap_count++;
(*radeon->get_ust) (&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);
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)(*radeon->get_ust) (&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)(*radeon->get_ust) (&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;
}
}
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);
else
r200Flush(ctx);
}
/* 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);
}

View file

@ -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__ */

View file

@ -0,0 +1,159 @@
/*
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"
#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->Color._DrawDestMask == DD_BACK_LEFT_BIT);
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.
*/
static void r200RegainedLock(r200ContextPtr r200)
{
__DRIdrawablePrivate *dPriv = r200->radeon.dri.drawable;
__DRIscreenPrivate *sPriv = r200->radeon.dri.screen;
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->Color._DrawDestMask == DD_BACK_LEFT_BIT)
r200SetCliprects(r200, GL_BACK_LEFT);
else
r200SetCliprects(r200, 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]);
}
}
static void r300RegainedLock(radeonContextPtr radeon)
{
__DRIdrawablePrivate *dPriv = radeon->dri.drawable;
__DRIscreenPrivate *sPriv = radeon->dri.screen;
int i;
if (radeon->lastStamp != dPriv->lastStamp) {
radeonUpdatePageFlipping(radeon);
#if 0
if (radeon->glCtx->Color._DrawDestMask == DD_BACK_LEFT_BIT)
r200SetCliprects(r200, GL_BACK_LEFT);
else
r200SetCliprects(r200, GL_FRONT_LEFT);
r200UpdateViewportOffset(r200->radeon.glCtx);
#endif
radeon->lastStamp = dPriv->lastStamp;
}
#if 0
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);
else
r200RegainedLock((r200ContextPtr)radeon);
radeon->lost_context = GL_TRUE;
}

View file

@ -0,0 +1,113 @@
/*
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)
#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)
#endif /* __RADEON_LOCK_H__ */

View file

@ -0,0 +1,817 @@
/*
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"
#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 "utils.h"
#include "vblank.h"
#include "GL/internal/dri_interface.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;
#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},
{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_NP 0x4E50
#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
#endif
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
#endif /* USE_NEW_INTERFACE */
static radeonScreenPtr __radeonScreen;
static int getSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo);
#ifdef USE_NEW_INTERFACE
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 = (*create_context_modes) (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;
}
#endif /* USE_NEW_INTERFACE */
/* Create the device specific screen private data struct.
*/
static radeonScreenPtr radeonCreateScreen(__DRIscreenPrivate * sPriv)
{
radeonScreenPtr screen;
RADEONDRIPtr dri_priv = (RADEONDRIPtr) sPriv->pDevPriv;
unsigned char *RADEONMMIO;
/* 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_NP:
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;
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;
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) {
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 (driCompareGLXAPIVersion(20030813) >= 0) {
PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
(PFNGLXSCRENABLEEXTENSIONPROC)
glXGetProcAddress((const GLubyte *)
"__glXScrEnableExtension");
void *const psc = sPriv->psc->screenConfigs;
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 (driCompareGLXAPIVersion(20030818) >= 0) {
sPriv->psc->allocateMemory =
(void *)r200AllocateMemoryMESA;
sPriv->psc->freeMemory =
(void *)r200FreeMemoryMESA;
sPriv->psc->memoryOffset =
(void *)r200GetMemoryOffsetMESA;
(*glx_enable_extension) (psc,
"GLX_MESA_allocate_memory");
}
if (driCompareGLXAPIVersion(20030915) >= 0) {
(*glx_enable_extension) (psc,
"GLX_SGIX_fbconfig");
(*glx_enable_extension) (psc,
"GLX_OML_swap_method");
}
}
}
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)
{
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;
driDrawPriv->driverPrivate = (void *)
_mesa_create_framebuffer(mesaVis,
swDepth,
swStencil, swAccum, swAlpha);
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);
else
return r200CreateContext(glVisual, driContextPriv, sharedContextPriv);
}
/**
* 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);
else
return r200DestroyContext(driContextPriv);
}
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.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*
*/
#if !defined(DRI_NEW_INTERFACE_ONLY)
void *__driCreateScreen(Display * dpy, int scrn, __DRIscreen * psc,
int numConfigs, __GLXvisualConfig * config)
{
__DRIscreenPrivate *psp;
psp =
__driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &radeonAPI);
return (void *)psp;
}
#endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
/**
* 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.
*/
#ifdef USE_NEW_INTERFACE
void *__driCreateNewScreen(__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,
__GLcontextModes ** driver_modes)
{
__DRIscreenPrivate *psp;
static const __DRIversion ddx_expected = { 4, 0, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
static const __DRIversion drm_expected = { 1, 11, 1 };
if (!driCheckDriDdxDrmVersions2("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) {
create_context_modes = (PFNGLXCREATECONTEXTMODES)
glXGetProcAddress((const GLubyte *)
"__glXCreateContextModes");
if (create_context_modes != 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));
}
}
return (void *)psp;
}
#endif /* USE_NEW_INTERFACE */
/**
* 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;
}

View file

@ -0,0 +1,111 @@
/*
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_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__ */

View file

@ -0,0 +1,520 @@
/*
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); \
radeonScreenPtr radeonScreen = radeon->radeonScreen; \
__DRIscreenPrivate *sPriv = radeon->dri.screen; \
__DRIdrawablePrivate *dPriv = radeon->dri.drawable; \
GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(sPriv->pFB + \
radeon->state.color.drawOffset + \
(dPriv->x * radeonScreen->cpp) + \
(dPriv->y * pitch)); \
char *read_buf = (char *)(sPriv->pFB + \
radeon->state.pixel.readOffset + \
(dPriv->x * radeonScreen->cpp) + \
(dPriv->y * pitch)); \
GLuint p; \
(void) read_buf; (void) buf; (void) p
#define LOCAL_DEPTH_VARS \
radeonContextPtr radeon = RADEON_CONTEXT(ctx); \
radeonScreenPtr radeonScreen = radeon->radeonScreen; \
__DRIscreenPrivate *sPriv = radeon->dri.screen; \
__DRIdrawablePrivate *dPriv = radeon->dri.drawable; \
GLuint height = dPriv->h; \
GLuint xo = dPriv->x; \
GLuint yo = dPriv->y; \
char *buf = (char *)(sPriv->pFB + radeon->radeonScreen->depthOffset); \
GLuint pitch = radeon->radeonScreen->depthPitch; \
(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 { \
__DRIdrawablePrivate *dPriv = radeon->dri.drawable; \
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 *)(read_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 *)(read_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
*/
/* The Radeon family has depth tiling on all the time, so we have to convert
* the x,y coordinates into the memory bus address (mba) in the same
* manner as the engine. In each case, the linear block address (ba)
* is calculated, and then wired with x and y to produce the final
* memory address.
*/
#define BIT(x,b) ((x & (1<<b))>>b)
static GLuint radeon_mba_z32(radeonContextPtr radeon, GLint x, GLint y)
{
GLuint pitch = radeon->radeonScreen->depthPitch;
GLuint b =
((y & 0x3FF) >> 4) * ((pitch & 0xFFF) >> 5) + ((x & 0x3FF) >> 5);
GLuint a =
(BIT(x, 0) << 2) | (BIT(y, 0) << 3) | (BIT(x, 1) << 4) | (BIT(y, 1)
<< 5) |
(BIT(x, 3) << 6) | (BIT(x, 4) << 7) | (BIT(x, 2) << 8) | (BIT(y, 2)
<< 9) |
(BIT(y, 3) << 10) |
(((pitch & 0x20) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y, 4)))) << 11) |
((b >> 1) << 12);
return a;
}
static GLuint radeon_mba_z16(radeonContextPtr radeon, GLint x, GLint y)
{
GLuint pitch = radeon->radeonScreen->depthPitch;
GLuint b =
((y & 0x3FF) >> 4) * ((pitch & 0xFFF) >> 6) + ((x & 0x3FF) >> 6);
GLuint a =
(BIT(x, 0) << 1) | (BIT(y, 0) << 2) | (BIT(x, 1) << 3) | (BIT(y, 1)
<< 4) |
(BIT(x, 2) << 5) | (BIT(x, 4) << 6) | (BIT(x, 5) << 7) | (BIT(x, 3)
<< 8) |
(BIT(y, 2) << 9) | (BIT(y, 3) << 10) |
(((pitch & 0x40) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y, 4)))) << 11) |
((b >> 1) << 12);
return a;
}
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
*(GLushort *)(buf + radeon_mba_z16( radeon, _x + xo, _y + yo )) = d;
#define READ_DEPTH( d, _x, _y ) \
d = *(GLushort *)(buf + radeon_mba_z16( radeon, _x + xo, _y + yo ));
#define TAG(x) radeon##x##_16_TILE
#include "depthtmp.h"
/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
do { \
GLuint offset = radeon_mba_z32( radeon, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
tmp |= ((d) & 0x00ffffff); \
*(GLuint *)(buf + offset) = tmp; \
} while (0)
#define READ_DEPTH( d, _x, _y ) \
d = *(GLuint *)(buf + radeon_mba_z32( radeon, _x + xo, \
_y + yo )) & 0x00ffffff;
#define TAG(x) radeon##x##_24_8_TILE
#include "depthtmp.h"
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
*(GLushort *)(buf + (_x + xo)*2 + (_y + yo)*pitch ) = d;
#define READ_DEPTH( d, _x, _y ) \
d = *(GLushort *)(buf + (_x + xo)*2 + (_y + yo)*pitch );
#define TAG(x) radeon##x##_16_LINEAR
#include "depthtmp.h"
/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
do { \
GLuint offset = (_x + xo)*4 + (_y + yo)*pitch; \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
tmp |= ((d) & 0x00ffffff); \
*(GLuint *)(buf + offset) = tmp; \
} while (0)
#define READ_DEPTH( d, _x, _y ) \
d = *(GLuint *)(buf + (_x + xo)*4 + (_y + yo)*pitch) & 0x00ffffff;
#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 = radeon_mba_z32( radeon, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0x00ffffff; \
tmp |= (((d) & 0xff) << 24); \
*(GLuint *)(buf + offset) = tmp; \
} while (0)
#define READ_STENCIL( d, _x, _y ) \
do { \
GLuint offset = radeon_mba_z32( radeon, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
d = tmp >> 24; \
} while (0)
#define TAG(x) radeon##x##_24_8_TILE
#include "stenciltmp.h"
/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
#define WRITE_STENCIL( _x, _y, d ) \
do { \
GLuint offset = (_x + xo)*4 + (_y + yo)*pitch; \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0x00ffffff; \
tmp |= (((d) & 0xff) << 24); \
*(GLuint *)(buf + offset) = tmp; \
} while (0)
#define READ_STENCIL( d, _x, _y ) \
do { \
GLuint offset = (_x + xo)*4 + (_y + yo)*pitch; \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
d = tmp >> 24; \
} 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);
switch (bufferBit) {
case DD_FRONT_LEFT_BIT:
if (radeon->doPageFlip && radeon->sarea->pfCurrentPage == 1) {
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;
}
break;
case DD_BACK_LEFT_BIT:
if (radeon->doPageFlip && radeon->sarea->pfCurrentPage == 1) {
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;
} else {
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;
}
break;
default:
_mesa_problem(ctx, "Bad bufferBit in %s", __FUNCTION__);
break;
}
}
/* 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)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
struct swrast_device_driver *swdd =
_swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = radeonSetBuffer;
switch (radeon->radeonScreen->cpp) {
case 2:
swdd->WriteRGBASpan = radeonWriteRGBASpan_RGB565;
swdd->WriteRGBSpan = radeonWriteRGBSpan_RGB565;
swdd->WriteMonoRGBASpan = radeonWriteMonoRGBASpan_RGB565;
swdd->WriteRGBAPixels = radeonWriteRGBAPixels_RGB565;
swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_RGB565;
swdd->ReadRGBASpan = radeonReadRGBASpan_RGB565;
swdd->ReadRGBAPixels = radeonReadRGBAPixels_RGB565;
break;
case 4:
swdd->WriteRGBASpan = radeonWriteRGBASpan_ARGB8888;
swdd->WriteRGBSpan = radeonWriteRGBSpan_ARGB8888;
swdd->WriteMonoRGBASpan = radeonWriteMonoRGBASpan_ARGB8888;
swdd->WriteRGBAPixels = radeonWriteRGBAPixels_ARGB8888;
swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_ARGB8888;
swdd->ReadRGBASpan = radeonReadRGBASpan_ARGB8888;
swdd->ReadRGBAPixels = radeonReadRGBAPixels_ARGB8888;
break;
default:
break;
}
if (IS_FAMILY_R300(radeon))
{
switch (radeon->glCtx->Visual.depthBits) {
case 16:
swdd->ReadDepthSpan = radeonReadDepthSpan_16_LINEAR;
swdd->WriteDepthSpan = radeonWriteDepthSpan_16_LINEAR;
swdd->WriteMonoDepthSpan = radeonWriteMonoDepthSpan_16_LINEAR;
swdd->ReadDepthPixels = radeonReadDepthPixels_16_LINEAR;
swdd->WriteDepthPixels = radeonWriteDepthPixels_16_LINEAR;
break;
case 24:
swdd->ReadDepthSpan = radeonReadDepthSpan_24_8_LINEAR;
swdd->WriteDepthSpan = radeonWriteDepthSpan_24_8_LINEAR;
swdd->WriteMonoDepthSpan = radeonWriteMonoDepthSpan_24_8_LINEAR;
swdd->ReadDepthPixels = radeonReadDepthPixels_24_8_LINEAR;
swdd->WriteDepthPixels = radeonWriteDepthPixels_24_8_LINEAR;
swdd->ReadStencilSpan = radeonReadStencilSpan_24_8_LINEAR;
swdd->WriteStencilSpan = radeonWriteStencilSpan_24_8_LINEAR;
swdd->ReadStencilPixels = radeonReadStencilPixels_24_8_LINEAR;
swdd->WriteStencilPixels = radeonWriteStencilPixels_24_8_LINEAR;
break;
default:
break;
}
}
else
{
switch (radeon->glCtx->Visual.depthBits) {
case 16:
swdd->ReadDepthSpan = radeonReadDepthSpan_16_TILE;
swdd->WriteDepthSpan = radeonWriteDepthSpan_16_TILE;
swdd->WriteMonoDepthSpan = radeonWriteMonoDepthSpan_16_TILE;
swdd->ReadDepthPixels = radeonReadDepthPixels_16_TILE;
swdd->WriteDepthPixels = radeonWriteDepthPixels_16_TILE;
break;
case 24:
swdd->ReadDepthSpan = radeonReadDepthSpan_24_8_TILE;
swdd->WriteDepthSpan = radeonWriteDepthSpan_24_8_TILE;
swdd->WriteMonoDepthSpan = radeonWriteMonoDepthSpan_24_8_TILE;
swdd->ReadDepthPixels = radeonReadDepthPixels_24_8_TILE;
swdd->WriteDepthPixels = radeonWriteDepthPixels_24_8_TILE;
swdd->ReadStencilSpan = radeonReadStencilSpan_24_8_TILE;
swdd->WriteStencilSpan = radeonWriteStencilSpan_24_8_TILE;
swdd->ReadStencilPixels = radeonReadStencilPixels_24_8_TILE;
swdd->WriteStencilPixels = radeonWriteStencilPixels_24_8_TILE;
break;
default:
break;
}
}
swdd->SpanRenderStart = radeonSpanRenderStart;
swdd->SpanRenderFinish = radeonSpanRenderFinish;
}

View file

@ -0,0 +1,43 @@
/*
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
extern void radeonInitSpanFuncs(GLcontext * ctx);
#endif
#endif