A full radeon driver, seems to build ok, haven't run yet

This commit is contained in:
Keith Whitwell 2002-12-04 15:31:04 +00:00
parent 702b2802a0
commit 40af4d7662
39 changed files with 19353 additions and 0 deletions

View file

@ -0,0 +1,82 @@
# $Id: Makefile,v 1.1.2.1 2002/12/04 15:31:04 keithw Exp $
# Mesa 3-D graphics library
# Version: 5.0
# Copyright (C) 1995-2002 Brian Paul
MESA = ../../..
MESABUILDDIR = $(MESA)/src
INCLUDES = -I$(MESABUILDDIR) -I$(MESA)/include -I. -I../common -I$(MESABUILDDIR)/miniglx
CFLAGS = $(INCLUDES) -g -MD -DGLX_DIRECT_RENDERING
# The .a files for each mesa module required by this driver:
#
COREMESA = $(MESABUILDDIR)/swrast_setup/swrast_setup.a \
$(MESABUILDDIR)/tnl/tnl.a \
$(MESABUILDDIR)/math/math.a \
$(MESABUILDDIR)/array_cache/array_cache.a \
$(MESABUILDDIR)/swrast/swrast.a \
$(MESABUILDDIR)/mesa.a
DRIVER_SOURCES = radeon_compat.c \
radeon_context.c \
radeon_ioctl.c \
radeon_lock.c \
radeon_maos.c \
radeon_sanity.c \
radeon_screen.c \
radeon_span.c \
radeon_state.c \
radeon_state_init.c \
radeon_swtcl.c \
radeon_tcl.c \
radeon_tex.c \
radeon_texmem.c \
radeon_texstate.c \
radeon_vtxfmt.c \
radeon_vtxfmt_c.c \
radeon_vtxfmt_sse.c \
radeon_vtxfmt_x86.c \
../common/mm.c
C_SOURCES = $(DRIVER_SOURCES) \
$(DRI_SOURCES)
ASM_SOURCES =
OBJECTS = $(C_SOURCES:.c=.o) \
$(ASM_SOURCES:.S=.o)
##### RULES #####
.S.o:
$(CC) -c $(CFLAGS) $< -o $@
.c.o:
$(CC) -c $(CFLAGS) $< -o $@
##### TARGETS #####
default: radeon_dri.so
radeon_dri.so: $(COREMESA) $(OBJECTS) Makefile
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(COREMESA) -L$(MESA)/src/miniglx -lGL -lc -lm
clean:
-rm -f *.o *~ *.d .\#* *.so
tags:
etags `find . -name \*.[ch]` `find ../include`
##### DEPENDENCIES #####
include $(C_SOURCES:.c=.d)
.SUFFIXES: .c .d
.c.d:
$(CC) -M $(INCLUDES) $< -o $@

View file

@ -0,0 +1,444 @@
/* radeon_common.h -- common header definitions for Radeon 2D/3D/DRM suite
*
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, 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
* PRECISION INSIGHT 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.
*
* Author:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*
* Converted to common header format:
* Jens Owen <jens@tungstengraphics.com>
*
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h,v 1.6 2001/04/16 15:02:13 tsi Exp $
*
*/
#ifndef _RADEON_COMMON_H_
#define _RADEON_COMMON_H_
#include "xf86drm.h"
/* WARNING: If you change any of these defines, make sure to change
* the kernel include file as well (radeon_drm.h)
*/
/* Driver specific DRM command indices
* NOTE: these are not OS specific, but they are driver specific
*/
#define DRM_RADEON_CP_INIT 0x00
#define DRM_RADEON_CP_START 0x01
#define DRM_RADEON_CP_STOP 0x02
#define DRM_RADEON_CP_RESET 0x03
#define DRM_RADEON_CP_IDLE 0x04
#define DRM_RADEON_RESET 0x05
#define DRM_RADEON_FULLSCREEN 0x06
#define DRM_RADEON_SWAP 0x07
#define DRM_RADEON_CLEAR 0x08
#define DRM_RADEON_VERTEX 0x09
#define DRM_RADEON_INDICES 0x0a
#define DRM_RADEON_STIPPLE 0x0c
#define DRM_RADEON_INDIRECT 0x0d
#define DRM_RADEON_TEXTURE 0x0e
#define DRM_RADEON_VERTEX2 0x0f
#define DRM_RADEON_CMDBUF 0x10
#define DRM_RADEON_GETPARAM 0x11
#define DRM_RADEON_FLIP 0x12
#define DRM_RADEON_ALLOC 0x13
#define DRM_RADEON_FREE 0x14
#define DRM_RADEON_INIT_HEAP 0x15
#define DRM_RADEON_IRQ_EMIT 0x16
#define DRM_RADEON_IRQ_WAIT 0x17
#define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39
#define RADEON_FRONT 0x1
#define RADEON_BACK 0x2
#define RADEON_DEPTH 0x4
#define RADEON_STENCIL 0x8
#define RADEON_CLEAR_X1 0
#define RADEON_CLEAR_Y1 1
#define RADEON_CLEAR_X2 2
#define RADEON_CLEAR_Y2 3
#define RADEON_CLEAR_DEPTH 4
typedef struct {
enum {
DRM_RADEON_INIT_CP = 0x01,
DRM_RADEON_CLEANUP_CP = 0x02,
DRM_RADEON_INIT_R200_CP = 0x03
} func;
unsigned long sarea_priv_offset;
int is_pci;
int cp_mode;
int agp_size;
int ring_size;
int usec_timeout;
unsigned int fb_bpp;
unsigned int front_offset, front_pitch;
unsigned int back_offset, back_pitch;
unsigned int depth_bpp;
unsigned int depth_offset, depth_pitch;
unsigned long fb_offset;
unsigned long mmio_offset;
unsigned long ring_offset;
unsigned long ring_rptr_offset;
unsigned long buffers_offset;
unsigned long agp_textures_offset;
} drmRadeonInit;
typedef struct {
int flush;
int idle;
} drmRadeonCPStop;
typedef struct {
int idx;
int start;
int end;
int discard;
} drmRadeonIndirect;
typedef union drmRadeonClearR {
float f[5];
unsigned int ui[5];
} drmRadeonClearRect;
typedef struct drmRadeonClearT {
unsigned int flags;
unsigned int clear_color;
unsigned int clear_depth;
unsigned int color_mask;
unsigned int depth_mask; /* misnamed field: should be stencil */
drmRadeonClearRect *depth_boxes;
} drmRadeonClearType;
typedef struct drmRadeonFullscreenT {
enum {
RADEON_INIT_FULLSCREEN = 0x01,
RADEON_CLEANUP_FULLSCREEN = 0x02
} func;
} drmRadeonFullscreenType;
typedef struct {
unsigned int *mask;
} drmRadeonStipple;
typedef struct {
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
const void *data;
} drmRadeonTexImage;
typedef struct {
int offset;
int pitch;
int format;
int width; /* Texture image coordinates */
int height;
drmRadeonTexImage *image;
} drmRadeonTexture;
#define RADEON_MAX_TEXTURE_UNITS 3
/* Layout matches drm_radeon_state_t in linux drm_radeon.h.
*/
typedef struct {
struct {
unsigned int pp_misc; /* 0x1c14 */
unsigned int pp_fog_color;
unsigned int re_solid_color;
unsigned int rb3d_blendcntl;
unsigned int rb3d_depthoffset;
unsigned int rb3d_depthpitch;
unsigned int rb3d_zstencilcntl;
unsigned int pp_cntl; /* 0x1c38 */
unsigned int rb3d_cntl;
unsigned int rb3d_coloroffset;
unsigned int re_width_height;
unsigned int rb3d_colorpitch;
} context;
struct {
unsigned int se_cntl;
} setup1;
struct {
unsigned int se_coord_fmt; /* 0x1c50 */
} vertex;
struct {
unsigned int re_line_pattern; /* 0x1cd0 */
unsigned int re_line_state;
unsigned int se_line_width; /* 0x1db8 */
} line;
struct {
unsigned int pp_lum_matrix; /* 0x1d00 */
unsigned int pp_rot_matrix_0; /* 0x1d58 */
unsigned int pp_rot_matrix_1;
} bumpmap;
struct {
unsigned int rb3d_stencilrefmask; /* 0x1d7c */
unsigned int rb3d_ropcntl;
unsigned int rb3d_planemask;
} mask;
struct {
unsigned int se_vport_xscale; /* 0x1d98 */
unsigned int se_vport_xoffset;
unsigned int se_vport_yscale;
unsigned int se_vport_yoffset;
unsigned int se_vport_zscale;
unsigned int se_vport_zoffset;
} viewport;
struct {
unsigned int se_cntl_status; /* 0x2140 */
} setup2;
struct {
unsigned int re_top_left; /*ignored*/ /* 0x26c0 */
unsigned int re_misc;
} misc;
struct {
unsigned int pp_txfilter;
unsigned int pp_txformat;
unsigned int pp_txoffset;
unsigned int pp_txcblend;
unsigned int pp_txablend;
unsigned int pp_tfactor;
unsigned int pp_border_color;
} texture[RADEON_MAX_TEXTURE_UNITS];
struct {
unsigned int se_zbias_factor;
unsigned int se_zbias_constant;
} zbias;
unsigned int dirty;
} drmRadeonState;
/* 1.1 vertex ioctl. Used in compatibility modes.
*/
typedef struct {
int prim;
int idx; /* Index of vertex buffer */
int count; /* Number of vertices in buffer */
int discard; /* Client finished with buffer? */
} drmRadeonVertex;
typedef struct {
unsigned int start;
unsigned int finish;
unsigned int prim:8;
unsigned int stateidx:8;
unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
unsigned int vc_format;
} drmRadeonPrim;
typedef struct {
int idx; /* Index of vertex buffer */
int discard; /* Client finished with buffer? */
int nr_states;
drmRadeonState *state;
int nr_prims;
drmRadeonPrim *prim;
} drmRadeonVertex2;
#define RADEON_MAX_STATES 16
#define RADEON_MAX_PRIMS 64
/* Command buffer. Replace with true dma stream?
*/
typedef struct {
int bufsz;
char *buf;
int nbox;
drmClipRect *boxes;
} drmRadeonCmdBuffer;
/* New style per-packet identifiers for use in cmd_buffer ioctl with
* the RADEON_EMIT_PACKET command. Comments relate new packets to old
* state bits and the packet size:
*/
#define RADEON_EMIT_PP_MISC 0 /* context/7 */
#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/6 */
#define R200_EMIT_TFACTOR_0 30 /* tf/6 */
#define R200_EMIT_VTX_FMT_0 31 /* vtx/4 */
#define R200_EMIT_VAP_CTL 32 /* vap/1 */
#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
#define R200_EMIT_PP_CUBIC_FACES_0 61
#define R200_EMIT_PP_CUBIC_OFFSETS_0 62
#define R200_EMIT_PP_CUBIC_FACES_1 63
#define R200_EMIT_PP_CUBIC_OFFSETS_1 64
#define R200_EMIT_PP_CUBIC_FACES_2 65
#define R200_EMIT_PP_CUBIC_OFFSETS_2 66
#define R200_EMIT_PP_CUBIC_FACES_3 67
#define R200_EMIT_PP_CUBIC_OFFSETS_3 68
#define R200_EMIT_PP_CUBIC_FACES_4 69
#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
#define R200_EMIT_PP_CUBIC_FACES_5 71
#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
#define RADEON_MAX_STATE_PACKETS 73
/* Commands understood by cmd_buffer ioctl. More can be added but
* obviously these can't be removed or changed:
*/
#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
#define RADEON_CMD_SCALARS 2 /* emit scalar data */
#define RADEON_CMD_VECTORS 3 /* emit vector data */
#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
#define RADEON_CMD_PACKET3 5 /* emit hw packet */
#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
#define RADEON_CMD_SCALARS2 7 /* R200 stopgap */
#define RADEON_CMD_WAIT 8 /* synchronization */
typedef union {
int i;
struct {
unsigned char cmd_type, pad0, pad1, pad2;
} header;
struct {
unsigned char cmd_type, packet_id, pad0, pad1;
} packet;
struct {
unsigned char cmd_type, offset, stride, count;
} scalars;
struct {
unsigned char cmd_type, offset, stride, count;
} vectors;
struct {
unsigned char cmd_type, buf_idx, pad0, pad1;
} dma;
struct {
unsigned char cmd_type, flags, pad0, pad1;
} wait;
} drmRadeonCmdHeader;
#define RADEON_WAIT_2D 0x1
#define RADEON_WAIT_3D 0x2
typedef struct drm_radeon_getparam {
int param;
int *value;
} drmRadeonGetParam;
#define RADEON_PARAM_AGP_BUFFER_OFFSET 1
#define RADEON_PARAM_LAST_FRAME 2
#define RADEON_PARAM_LAST_DISPATCH 3
#define RADEON_PARAM_LAST_CLEAR 4
#define RADEON_PARAM_IRQ_NR 5
#define RADEON_PARAM_AGP_BASE 6
#define RADEON_MEM_REGION_AGP 1
#define RADEON_MEM_REGION_FB 2
typedef struct drm_radeon_mem_alloc {
int region;
int alignment;
int size;
int *region_offset; /* offset from start of fb or agp */
} drmRadeonMemAlloc;
typedef struct drm_radeon_mem_free {
int region;
int region_offset;
} drmRadeonMemFree;
typedef struct drm_radeon_mem_init_heap {
int region;
int size;
int start;
} drmRadeonMemInitHeap;
/* 1.6: Userspace can request & wait on irq's:
*/
typedef struct drm_radeon_irq_emit {
int *irq_seq;
} drmRadeonIrqEmit;
typedef struct drm_radeon_irq_wait {
int irq_seq;
} drmRadeonIrqWait;
#endif

View file

@ -0,0 +1,304 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Austin, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "radeon_context.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
static struct {
int start;
int len;
const char *name;
} packet[RADEON_MAX_STATE_PACKETS] = {
{ RADEON_PP_MISC,7,"RADEON_PP_MISC" },
{ RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
{ RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
{ RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
{ RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
{ RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
{ RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
{ RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
{ RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
{ RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
{ RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
{ RADEON_RE_MISC,1,"RADEON_RE_MISC" },
{ RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
{ RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
{ RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
{ RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
{ RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
{ RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
{ RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
{ RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
};
static void radeonCompatEmitPacket( radeonContextPtr rmesa,
struct radeon_state_atom *state )
{
RADEONSAREAPrivPtr sarea = rmesa->sarea;
radeon_context_regs_t *ctx = &sarea->ContextState;
radeon_texture_regs_t *tex0 = &sarea->TexState[0];
radeon_texture_regs_t *tex1 = &sarea->TexState[1];
int i;
int *buf = state->cmd;
for ( i = 0 ; i < state->cmd_size ; ) {
drmRadeonCmdHeader *header = (drmRadeonCmdHeader *)&buf[i++];
if (RADEON_DEBUG & DEBUG_STATE)
fprintf(stderr, "%s %d: %s\n", __FUNCTION__, header->packet.packet_id,
packet[(int)header->packet.packet_id].name);
switch (header->packet.packet_id) {
case RADEON_EMIT_PP_MISC:
ctx->pp_misc = buf[i++];
ctx->pp_fog_color = buf[i++];
ctx->re_solid_color = buf[i++];
ctx->rb3d_blendcntl = buf[i++];
ctx->rb3d_depthoffset = buf[i++];
ctx->rb3d_depthpitch = buf[i++];
ctx->rb3d_zstencilcntl = buf[i++];
sarea->dirty |= RADEON_UPLOAD_CONTEXT;
break;
case RADEON_EMIT_PP_CNTL:
ctx->pp_cntl = buf[i++];
ctx->rb3d_cntl = buf[i++];
ctx->rb3d_coloroffset = buf[i++];
sarea->dirty |= RADEON_UPLOAD_CONTEXT;
break;
case RADEON_EMIT_RB3D_COLORPITCH:
ctx->rb3d_colorpitch = buf[i++];
sarea->dirty |= RADEON_UPLOAD_CONTEXT;
break;
case RADEON_EMIT_RE_LINE_PATTERN:
ctx->re_line_pattern = buf[i++];
ctx->re_line_state = buf[i++];
sarea->dirty |= RADEON_UPLOAD_LINE;
break;
case RADEON_EMIT_SE_LINE_WIDTH:
ctx->se_line_width = buf[i++];
sarea->dirty |= RADEON_UPLOAD_LINE;
break;
case RADEON_EMIT_PP_LUM_MATRIX:
ctx->pp_lum_matrix = buf[i++];
sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
break;
case RADEON_EMIT_PP_ROT_MATRIX_0:
ctx->pp_rot_matrix_0 = buf[i++];
ctx->pp_rot_matrix_1 = buf[i++];
sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
break;
case RADEON_EMIT_RB3D_STENCILREFMASK:
ctx->rb3d_stencilrefmask = buf[i++];
ctx->rb3d_ropcntl = buf[i++];
ctx->rb3d_planemask = buf[i++];
sarea->dirty |= RADEON_UPLOAD_MASKS;
break;
case RADEON_EMIT_SE_VPORT_XSCALE:
ctx->se_vport_xscale = buf[i++];
ctx->se_vport_xoffset = buf[i++];
ctx->se_vport_yscale = buf[i++];
ctx->se_vport_yoffset = buf[i++];
ctx->se_vport_zscale = buf[i++];
ctx->se_vport_zoffset = buf[i++];
sarea->dirty |= RADEON_UPLOAD_VIEWPORT;
break;
case RADEON_EMIT_SE_CNTL:
ctx->se_cntl = buf[i++];
ctx->se_coord_fmt = buf[i++];
sarea->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_VERTFMT;
break;
case RADEON_EMIT_SE_CNTL_STATUS:
ctx->se_cntl_status = buf[i++];
sarea->dirty |= RADEON_UPLOAD_SETUP;
break;
case RADEON_EMIT_RE_MISC:
ctx->re_misc = buf[i++];
sarea->dirty |= RADEON_UPLOAD_MISC;
break;
case RADEON_EMIT_PP_TXFILTER_0:
tex0->pp_txfilter = buf[i++];
tex0->pp_txformat = buf[i++];
tex0->pp_txoffset = buf[i++];
tex0->pp_txcblend = buf[i++];
tex0->pp_txablend = buf[i++];
tex0->pp_tfactor = buf[i++];
sarea->dirty |= RADEON_UPLOAD_TEX0;
break;
case RADEON_EMIT_PP_BORDER_COLOR_0:
tex0->pp_border_color = buf[i++];
sarea->dirty |= RADEON_UPLOAD_TEX0;
break;
case RADEON_EMIT_PP_TXFILTER_1:
tex1->pp_txfilter = buf[i++];
tex1->pp_txformat = buf[i++];
tex1->pp_txoffset = buf[i++];
tex1->pp_txcblend = buf[i++];
tex1->pp_txablend = buf[i++];
tex1->pp_tfactor = buf[i++];
sarea->dirty |= RADEON_UPLOAD_TEX1;
break;
case RADEON_EMIT_PP_BORDER_COLOR_1:
tex1->pp_border_color = buf[i++];
sarea->dirty |= RADEON_UPLOAD_TEX1;
break;
case RADEON_EMIT_SE_ZBIAS_FACTOR:
i++;
i++;
break;
case RADEON_EMIT_PP_TXFILTER_2:
case RADEON_EMIT_PP_BORDER_COLOR_2:
case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
default:
/* These states aren't understood by radeon drm 1.1 */
fprintf(stderr, "Tried to emit unsupported state\n");
return;
}
}
}
static void radeonCompatEmitStateLocked( radeonContextPtr rmesa )
{
struct radeon_state_atom *state, *tmp;
if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
fprintf(stderr, "%s\n", __FUNCTION__);
if (rmesa->lost_context) {
if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
fprintf(stderr, "%s - lost context\n", __FUNCTION__);
foreach_s( state, tmp, &(rmesa->hw.clean) )
move_to_tail(&(rmesa->hw.dirty), state );
rmesa->lost_context = 0;
}
foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
if (!state->is_tcl)
radeonCompatEmitPacket( rmesa, state );
move_to_head( &(rmesa->hw.clean), state );
}
}
static void radeonCompatEmitPrimitiveLocked( radeonContextPtr rmesa,
GLuint hw_primitive,
GLuint nverts,
XF86DRIClipRectPtr pbox,
GLuint nbox )
{
int i;
for ( i = 0 ; i < nbox ; ) {
int nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, nbox );
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
drmRadeonVertex vtx;
rmesa->sarea->dirty |= RADEON_UPLOAD_CLIPRECTS;
rmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++)
*b++ = pbox[i];
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr,
"RadeonFlushVertexBuffer: prim %x buf %d verts %d "
"disc %d nbox %d\n",
hw_primitive,
rmesa->dma.current.buf->buf->idx,
nverts,
nr == nbox,
rmesa->sarea->nbox );
vtx.prim = hw_primitive;
vtx.idx = rmesa->dma.current.buf->buf->idx;
vtx.count = nverts;
vtx.discard = (nr == nbox);
drmCommandWrite( rmesa->dri.fd,
DRM_RADEON_VERTEX,
&vtx, sizeof(vtx));
}
}
/* No 'start' for 1.1 vertices ioctl: only one vertex prim/buffer!
*/
void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
GLuint vertex_format,
GLuint hw_primitive,
GLuint nrverts )
{
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
LOCK_HARDWARE( rmesa );
radeonCompatEmitStateLocked( rmesa );
rmesa->sarea->vc_format = vertex_format;
if (rmesa->state.scissor.enabled) {
radeonCompatEmitPrimitiveLocked( rmesa,
hw_primitive,
nrverts,
rmesa->state.scissor.pClipRects,
rmesa->state.scissor.numClipRects );
}
else {
radeonCompatEmitPrimitiveLocked( rmesa,
hw_primitive,
nrverts,
rmesa->pClipRects,
rmesa->numClipRects );
}
UNLOCK_HARDWARE( rmesa );
}

View file

@ -0,0 +1,789 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.4 2002/09/10 00:39:39 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "api_arrayelt.h"
#include "context.h"
#include "simple_list.h"
#include "matrix.h"
#include "extensions.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 "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_span.h"
#include "radeon_tex.h"
#include "radeon_swtcl.h"
#include "radeon_tcl.h"
#include "radeon_vtxfmt.h"
#include "radeon_maos.h"
#if defined(USE_X86_ASM)
#include "X86/common_x86_asm.h"
#endif
#define RADEON_DATE "20021125"
#ifndef RADEON_DEBUG
int RADEON_DEBUG = (0);
#endif
/* Return the width and height of the given buffer.
*/
static void radeonGetBufferSize( GLframebuffer *buffer,
GLuint *width, GLuint *height )
{
GET_CURRENT_CONTEXT(ctx);
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
LOCK_HARDWARE( rmesa );
*width = rmesa->dri.drawable->w;
*height = rmesa->dri.drawable->h;
UNLOCK_HARDWARE( rmesa );
}
/* Return various strings for glGetString().
*/
static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
static char buffer[128];
switch ( name ) {
case GL_VENDOR:
return (GLubyte *)"Tungsten Graphics, Inc.";
case GL_RENDERER:
sprintf( buffer, "Mesa DRI Radeon " RADEON_DATE);
/* Append any chipset-specific information. None yet.
*/
/* Append any AGP-specific information.
*/
switch ( rmesa->radeonScreen->AGPMode ) {
case 1:
strncat( buffer, " AGP 1x", 7 );
break;
case 2:
strncat( buffer, " AGP 2x", 7 );
break;
case 4:
strncat( buffer, " AGP 4x", 7 );
break;
}
/* Append any CPU-specific information.
*/
#ifdef USE_X86_ASM
if ( _mesa_x86_cpu_features ) {
strncat( buffer, " x86", 4 );
}
#ifdef USE_MMX_ASM
if ( cpu_has_mmx ) {
strncat( buffer, "/MMX", 4 );
}
#endif
#ifdef USE_3DNOW_ASM
if ( cpu_has_3dnow ) {
strncat( buffer, "/3DNow!", 7 );
}
#endif
#ifdef USE_SSE_ASM
if ( cpu_has_xmm ) {
strncat( buffer, "/SSE", 4 );
}
#endif
#endif
if ( rmesa->dri.drmMinor < 3 ) {
strncat( buffer, " DRM-COMPAT", 11 );
}
if ( !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) ) {
strncat( buffer, " TCL", 4 );
}
else {
strncat( buffer, " NO-TCL", 7 );
}
return (GLubyte *)buffer;
default:
return NULL;
}
}
/* Extension strings exported by the R100 driver.
*/
static const char * const radeon_extensions[] =
{
"GL_ARB_multisample",
"GL_ARB_multitexture",
"GL_ARB_texture_border_clamp",
"GL_ARB_texture_compression",
"GL_ARB_texture_env_add",
"GL_ARB_texture_env_combine",
"GL_ARB_texture_env_dot3",
"GL_ARB_texture_mirrored_repeat",
"GL_EXT_blend_logic_op",
"GL_EXT_blend_subtract",
/* "GL_EXT_fog_coord", */
"GL_EXT_secondary_color",
"GL_EXT_texture_env_add",
"GL_EXT_texture_env_combine",
"GL_EXT_texture_env_dot3",
"GL_EXT_texture_filter_anisotropic",
"GL_EXT_texture_lod_bias",
"GL_ATI_texture_mirror_once",
"GL_IBM_texture_mirrored_repeat",
"GL_NV_blend_square",
"GL_SGIS_generate_mipmap",
"GL_SGIS_texture_border_clamp",
NULL
};
/* Initialize the extensions supported by this driver.
*/
static void radeonInitExtensions( GLcontext *ctx )
{
unsigned i;
_mesa_enable_imaging_extensions( ctx );
for ( i = 0 ; radeon_extensions[i] != NULL ; i++ ) {
_mesa_enable_extension( ctx, radeon_extensions[i] );
}
}
extern const struct gl_pipeline_stage _radeon_render_stage;
extern const struct gl_pipeline_stage _radeon_tcl_stage;
static const struct gl_pipeline_stage *radeon_pipeline[] = {
/* Try and go straight to t&l
*/
&_radeon_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,
/* 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.
*/
&_radeon_render_stage,
&_tnl_render_stage, /* FALLBACK: */
0,
};
/* Initialize the driver's misc functions.
*/
static void radeonInitDriverFuncs( GLcontext *ctx )
{
ctx->Driver.GetBufferSize = radeonGetBufferSize;
ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
ctx->Driver.GetString = radeonGetString;
ctx->Driver.Error = NULL;
ctx->Driver.DrawPixels = NULL;
ctx->Driver.Bitmap = NULL;
}
/* Create the device specific context.
*/
static GLboolean
radeonCreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
radeonScreenPtr radeonScreen = (radeonScreenPtr)(sPriv->private);
radeonContextPtr rmesa;
GLcontext *ctx, *shareCtx;
int i;
assert(glVisual);
assert(driContextPriv);
assert(radeonScreen);
/* Allocate the Radeon context */
rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) );
if ( !rmesa )
return GL_FALSE;
/* Allocate the Mesa context */
if (sharedContextPrivate)
shareCtx = ((radeonContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
if (!rmesa->glCtx) {
FREE(rmesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = rmesa;
/* Init radeon context data */
rmesa->dri.context = driContextPriv;
rmesa->dri.screen = sPriv;
rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
rmesa->dri.hwContext = driContextPriv->hHWContext;
rmesa->dri.hwLock = &sPriv->pSAREA->lock;
rmesa->dri.fd = sPriv->fd;
/* If we don't have 1.3, fallback to the 1.1 interfaces.
*/
if (getenv("RADEON_COMPAT") || sPriv->drmMinor < 3 )
rmesa->dri.drmMinor = 1;
else
rmesa->dri.drmMinor = sPriv->drmMinor;
rmesa->radeonScreen = radeonScreen;
rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
radeonScreen->sarea_priv_offset);
rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address;
for ( i = 0 ; i < radeonScreen->numTexHeaps ; i++ ) {
make_empty_list( &rmesa->texture.objects[i] );
rmesa->texture.heap[i] = mmInit( 0, radeonScreen->texSize[i] );
rmesa->texture.age[i] = -1;
}
rmesa->texture.numHeaps = radeonScreen->numTexHeaps;
make_empty_list( &rmesa->texture.swapped );
rmesa->swtcl.RenderIndex = ~0;
rmesa->lost_context = 1;
/* KW: Set the maximum texture size small enough that we can
* guarentee that both texture units can bind a maximal texture
* and have them both in on-card memory at once.
* Test for 2 textures * 4 bytes/texel * size * size.
*/
ctx = rmesa->glCtx;
if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 2048 * 2048) {
ctx->Const.MaxTextureLevels = 12; /* 2048x2048 */
}
else if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 1024 * 1024) {
ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */
}
else if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 512 * 512) {
ctx->Const.MaxTextureLevels = 10; /* 512x512 */
}
else {
ctx->Const.MaxTextureLevels = 9; /* 256x256 */
}
ctx->Const.MaxTextureUnits = 2;
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 = 10.0;
ctx->Const.MaxLineWidthAA = 10.0;
ctx->Const.LineWidthGranularity = 0.0625;
/* Set maxlocksize (and hence vb size) small enough to avoid
* fallbacks in radeon_tcl.c. ie. guarentee that all vertices can
* fit in a single dma buffer for indexed rendering of quad strips,
* etc.
*/
/* ctx->Const.MaxArrayLockSize = */
/* MIN2( ctx->Const.MaxArrayLockSize, */
/* RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE ); */
if (getenv("LIBGL_PERFORMANCE_BOXES"))
rmesa->boxes = 1;
else
rmesa->boxes = 0;
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext( ctx );
_ac_CreateContext( ctx );
_tnl_CreateContext( ctx );
_swsetup_CreateContext( ctx );
_ae_create_context( ctx );
/* Install the customized pipeline:
*/
_tnl_destroy_pipeline( ctx );
_tnl_install_pipeline( ctx, radeon_pipeline );
/* Try and keep materials and vertices separate:
*/
_tnl_isolate_materials( ctx, GL_TRUE );
/* _mesa_allow_light_in_model( ctx, GL_FALSE ); */
/* Configure swrast to match hardware characteristics:
*/
_swrast_allow_pixel_fog( ctx, GL_FALSE );
_swrast_allow_vertex_fog( ctx, GL_TRUE );
_math_matrix_ctr( &rmesa->TexGenMatrix[0] );
_math_matrix_ctr( &rmesa->TexGenMatrix[1] );
_math_matrix_ctr( &rmesa->tmpmat );
_math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
_math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
_math_matrix_set_identity( &rmesa->tmpmat );
radeonInitExtensions( ctx );
radeonInitDriverFuncs( ctx );
radeonInitIoctlFuncs( ctx );
radeonInitStateFuncs( ctx );
radeonInitSpanFuncs( ctx );
radeonInitTextureFuncs( ctx );
radeonInitState( rmesa );
radeonInitSwtcl( ctx );
rmesa->do_irqs = (rmesa->radeonScreen->irq && !getenv("RADEON_NO_IRQS"));
rmesa->irqsEmitted = 0;
rmesa->iw.irq_seq = -1;
rmesa->do_usleeps = !getenv("RADEON_NO_USLEEPS");
#if DO_DEBUG
if (getenv("RADEON_DEBUG_FALLBACKS"))
RADEON_DEBUG |= DEBUG_FALLBACKS;
if (getenv("RADEON_DEBUG_TEXTURE"))
RADEON_DEBUG |= DEBUG_TEXTURE;
if (getenv("RADEON_DEBUG_IOCTL"))
RADEON_DEBUG |= DEBUG_IOCTL;
if (getenv("RADEON_DEBUG_PRIMS"))
RADEON_DEBUG |= DEBUG_PRIMS;
if (getenv("RADEON_DEBUG_VERTS"))
RADEON_DEBUG |= DEBUG_VERTS;
if (getenv("RADEON_DEBUG_STATE"))
RADEON_DEBUG |= DEBUG_STATE;
if (getenv("RADEON_DEBUG_CODEGEN"))
RADEON_DEBUG |= DEBUG_CODEGEN;
if (getenv("RADEON_DEBUG_VTXFMT"))
RADEON_DEBUG |= DEBUG_VFMT;
if (getenv("RADEON_DEBUG_VERBOSE"))
RADEON_DEBUG |= DEBUG_VERBOSE;
if (getenv("RADEON_DEBUG_DRI"))
RADEON_DEBUG |= DEBUG_DRI;
if (getenv("RADEON_DEBUG_DMA"))
RADEON_DEBUG |= DEBUG_DMA;
if (getenv("RADEON_DEBUG_SANITY"))
RADEON_DEBUG |= DEBUG_SANITY;
if (getenv("RADEON_DEBUG"))
{
const char *debug = getenv("RADEON_DEBUG");
if (strstr(debug, "fall"))
RADEON_DEBUG |= DEBUG_FALLBACKS;
if (strstr(debug, "tex"))
RADEON_DEBUG |= DEBUG_TEXTURE;
if (strstr(debug, "ioctl"))
RADEON_DEBUG |= DEBUG_IOCTL;
if (strstr(debug, "prim"))
RADEON_DEBUG |= DEBUG_PRIMS;
if (strstr(debug, "vert"))
RADEON_DEBUG |= DEBUG_VERTS;
if (strstr(debug, "state"))
RADEON_DEBUG |= DEBUG_STATE;
if (strstr(debug, "code"))
RADEON_DEBUG |= DEBUG_CODEGEN;
if (strstr(debug, "vfmt") || strstr(debug, "vtxf"))
RADEON_DEBUG |= DEBUG_VFMT;
if (strstr(debug, "verb"))
RADEON_DEBUG |= DEBUG_VERBOSE;
if (strstr(debug, "dri"))
RADEON_DEBUG |= DEBUG_DRI;
if (strstr(debug, "dma"))
RADEON_DEBUG |= DEBUG_DMA;
if (strstr(debug, "san"))
RADEON_DEBUG |= DEBUG_SANITY;
}
#endif
if (getenv("RADEON_NO_RAST")) {
fprintf(stderr, "disabling 3D acceleration\n");
FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1);
}
else if (getenv("RADEON_TCL_FORCE_ENABLE")) {
fprintf(stderr, "Enabling TCL support... this will probably crash\n");
fprintf(stderr, " your card if it isn't capable of TCL!\n");
rmesa->radeonScreen->chipset |= RADEON_CHIPSET_TCL;
} else if (getenv("RADEON_TCL_FORCE_DISABLE") ||
rmesa->dri.drmMinor < 3 ||
!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
rmesa->radeonScreen->chipset &= ~RADEON_CHIPSET_TCL;
fprintf(stderr, "disabling TCL support\n");
TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
}
if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) {
if (!getenv("RADEON_NO_VTXFMT"))
radeonVtxfmtInit( ctx );
_tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
}
return GL_TRUE;
}
/* Destroy the device specific context.
*/
/* Destroy the Mesa and driver specific context data.
*/
static void
radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
{
GET_CURRENT_CONTEXT(ctx);
radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
/* check if we're deleting the currently bound context */
if (rmesa == current) {
RADEON_FIREVERTICES( rmesa );
_mesa_make_current2(NULL, NULL, NULL);
}
/* Free radeon context resources */
assert(rmesa); /* should never be null */
if ( rmesa ) {
if (rmesa->glCtx->Shared->RefCount == 1) {
/* This share group is about to go away, free our private
* texture object data.
*/
radeonTexObjPtr t, next_t;
int i;
for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) {
foreach_s ( t, next_t, &rmesa->texture.objects[i] ) {
radeonDestroyTexObj( rmesa, t );
}
mmDestroy( rmesa->texture.heap[i] );
rmesa->texture.heap[i] = NULL;
}
foreach_s ( t, next_t, &rmesa->texture.swapped ) {
radeonDestroyTexObj( rmesa, t );
}
}
_swsetup_DestroyContext( rmesa->glCtx );
_tnl_DestroyContext( rmesa->glCtx );
_ac_DestroyContext( rmesa->glCtx );
_swrast_DestroyContext( rmesa->glCtx );
radeonDestroySwtcl( rmesa->glCtx );
radeonReleaseArrays( rmesa->glCtx, ~0 );
if (rmesa->dma.current.buf) {
radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
radeonFlushCmdBuf( rmesa, __FUNCTION__ );
}
if (!rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
if (!getenv("RADEON_NO_VTXFMT"))
radeonVtxfmtDestroy( rmesa->glCtx );
/* free the Mesa context */
rmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context( rmesa->glCtx );
if (rmesa->state.scissor.pClipRects) {
FREE(rmesa->state.scissor.pClipRects);
rmesa->state.scissor.pClipRects = 0;
}
FREE( rmesa );
}
#if 0
/* Use this to force shared object profiling. */
glx_fini_prof();
#endif
}
/* Initialize the driver specific screen private data.
*/
static GLboolean
radeonInitDriver( __DRIscreenPrivate *sPriv )
{
sPriv->private = (void *) radeonCreateScreen( sPriv );
if ( !sPriv->private ) {
radeonDestroyScreen( sPriv );
return GL_FALSE;
}
return GL_TRUE;
}
/* Create and initialize the Mesa and driver specific pixmap buffer
* data.
*/
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));
}
static void
radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
radeonContextPtr rmesa;
GLcontext *ctx;
rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
ctx = rmesa->glCtx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( rmesa->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, "radeonSwapBuffers: drawable has no context!\n");
}
}
/* Force the context `c' to be the current context and associate with it
* buffer `b'.
*/
static GLboolean
radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv )
{
if ( driContextPriv ) {
radeonContextPtr newRadeonCtx =
(radeonContextPtr) driContextPriv->driverPrivate;
if (RADEON_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newRadeonCtx->glCtx);
if ( newRadeonCtx->dri.drawable != driDrawPriv ) {
newRadeonCtx->dri.drawable = driDrawPriv;
radeonUpdateWindow( newRadeonCtx->glCtx );
radeonUpdateViewportOffset( newRadeonCtx->glCtx );
}
_mesa_make_current2( newRadeonCtx->glCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate );
if ( !newRadeonCtx->glCtx->Viewport.Width ) {
_mesa_set_viewport( newRadeonCtx->glCtx, 0, 0,
driDrawPriv->w, driDrawPriv->h );
}
if (newRadeonCtx->vb.enabled)
radeonVtxfmtMakeCurrent( newRadeonCtx->glCtx );
} else {
if (RADEON_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx %p\n", __FUNCTION__, NULL);
_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.
*/
static GLboolean
radeonUnbindContext( __DRIcontextPrivate *driContextPriv )
{
radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
if (RADEON_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
radeonVtxfmtUnbindContext( rmesa->glCtx );
return GL_TRUE;
}
/* Fullscreen mode isn't used for much -- could be a way to shrink
* front/back buffers & get more texture memory if the client has
* changed the video resolution.
*
* Pageflipping is now done automatically whenever there is a single
* 3d client.
*/
static GLboolean
radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
{
return GL_TRUE;
}
void
__driRegisterExtensions( void )
{
/* See r200 driver for info */
}
static struct __DriverAPIRec radeonAPI = {
radeonInitDriver,
radeonDestroyScreen,
radeonCreateContext,
radeonDestroyContext,
radeonCreateBuffer,
radeonDestroyBuffer,
radeonSwapBuffers,
radeonMakeCurrent,
radeonUnbindContext,
radeonOpenCloseFullScreen,
radeonOpenCloseFullScreen
};
/*
* This is the bootstrap function for the driver.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*/
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;
}

View file

@ -0,0 +1,814 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v 1.4 2002/09/10 00:39:39 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __RADEON_CONTEXT_H__
#define __RADEON_CONTEXT_H__
#ifdef GLX_DIRECT_RENDERING
struct radeon_context;
typedef struct radeon_context radeonContextRec;
typedef struct radeon_context *radeonContextPtr;
#include "mtypes.h"
#include "macros.h"
#include "radeon_lock.h"
#include "radeon_screen.h"
#include "mm.h"
/* Flags for software fallback cases */
/* See correponding strings in radeon_swtcl.c */
#define RADEON_FALLBACK_TEXTURE 0x0001
#define RADEON_FALLBACK_DRAW_BUFFER 0x0002
#define RADEON_FALLBACK_STENCIL 0x0004
#define RADEON_FALLBACK_RENDER_MODE 0x0008
#define RADEON_FALLBACK_BLEND_EQ 0x0010
#define RADEON_FALLBACK_BLEND_FUNC 0x0020
#define RADEON_FALLBACK_DISABLE 0x0040
/* Use the templated vertex format:
*/
#define COLOR_IS_RGBA
#define TAG(x) radeon##x
#include "tnl_dd/t_dd_vertex.h"
#undef TAG
typedef void (*radeon_tri_func)( radeonContextPtr,
radeonVertex *,
radeonVertex *,
radeonVertex * );
typedef void (*radeon_line_func)( radeonContextPtr,
radeonVertex *,
radeonVertex * );
typedef void (*radeon_point_func)( radeonContextPtr,
radeonVertex * );
struct radeon_colorbuffer_state {
GLuint clear;
GLint drawOffset, drawPitch;
};
struct radeon_depthbuffer_state {
GLuint clear;
GLfloat scale;
};
struct radeon_pixel_state {
GLint readOffset, readPitch;
};
struct radeon_scissor_state {
XF86DRIClipRectRec rect;
GLboolean enabled;
GLuint numClipRects; /* Cliprects active */
GLuint numAllocedClipRects; /* Cliprects available */
XF86DRIClipRectPtr pClipRects;
};
struct radeon_stencilbuffer_state {
GLboolean hwBuffer;
GLuint clear; /* rb3d_stencilrefmask value */
};
struct radeon_stipple_state {
GLuint mask[32];
};
#define TEX_0 0x1
#define TEX_1 0x2
#define TEX_ALL 0x3
typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
/* Texture object in locally shared texture space.
*/
struct radeon_tex_obj {
radeonTexObjPtr next, prev;
struct gl_texture_object *tObj; /* Mesa texture object */
PMemBlock memBlock; /* Memory block containing texture */
GLuint bufAddr; /* Offset to start of locally
shared texture block */
GLuint dirty_images; /* Flags for whether or not
images need to be uploaded to
local or AGP texture space */
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. */
GLint heap; /* Texture heap currently stored in */
drmRadeonTexImage image[RADEON_MAX_TEXTURE_LEVELS];
GLint totalSize; /* Total size of the texture
including all mipmap levels */
GLuint pp_txfilter; /* hardware register values */
GLuint pp_txformat;
GLuint pp_txoffset;
GLuint pp_border_color;
/* texObj->Image[firstLevel] through texObj->Image[lastLevel] are the
* images to upload.
*/
GLint firstLevel;
GLint lastLevel;
};
struct radeon_texture_env_state {
radeonTexObjPtr texobj;
GLenum format;
GLenum envMode;
};
struct radeon_texture_state {
struct radeon_texture_env_state unit[RADEON_MAX_TEXTURE_UNITS];
};
struct radeon_state_atom {
struct radeon_state_atom *next, *prev;
const char *name; /* for debug */
int cmd_size; /* size in bytes */
GLuint is_tcl;
int *cmd; /* one or more cmd's */
int *lastcmd; /* one or more cmd's */
GLboolean (*check)( GLcontext * ); /* is this state active? */
};
/* Trying to keep these relatively short as the variables are becoming
* extravagently long. Drop the RADEON_ off the front of everything -
* I think we know we're in the radeon driver 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
#define CTX_RB3D_COLORPITCH 13
#define CTX_STATE_SIZE 14
#define SET_CMD_0 0
#define SET_SE_CNTL 1
#define SET_SE_COORDFMT 2
#define SET_CMD_1 3
#define SET_SE_CNTL_STATUS 4
#define SET_STATE_SIZE 5
#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 MSC_CMD_0 0
#define MSC_RE_MISC 1
#define MSC_STATE_SIZE 2
#define TEX_CMD_0 0
#define TEX_PP_TXFILTER 1
#define TEX_PP_TXFORMAT 2
#define TEX_PP_TXOFFSET 3
#define TEX_PP_TXCBLEND 4
#define TEX_PP_TXABLEND 5
#define TEX_PP_TFACTOR 6
#define TEX_CMD_1 7
#define TEX_PP_BORDER_COLOR 8
#define TEX_STATE_SIZE 9
#define ZBS_CMD_0 0
#define ZBS_SE_ZBIAS_FACTOR 1
#define ZBS_SE_ZBIAS_CONSTANT 2
#define ZBS_STATE_SIZE 3
#define TCL_CMD_0 0
#define TCL_OUTPUT_VTXFMT 1
#define TCL_OUTPUT_VTXSEL 2
#define TCL_MATRIX_SELECT_0 3
#define TCL_MATRIX_SELECT_1 4
#define TCL_UCP_VERT_BLEND_CTL 5
#define TCL_TEXTURE_PROC_CTL 6
#define TCL_LIGHT_MODEL_CTL 7
#define TCL_PER_LIGHT_CTL_0 8
#define TCL_PER_LIGHT_CTL_1 9
#define TCL_PER_LIGHT_CTL_2 10
#define TCL_PER_LIGHT_CTL_3 11
#define TCL_STATE_SIZE 12
#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_SHININESS 17
#define MTL_STATE_SIZE 18
#define VTX_CMD_0 0
#define VTX_SE_COORD_FMT 1
#define VTX_STATE_SIZE 2
#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_CONST 21
#define LIT_ATTEN_LINEAR 22
#define LIT_ATTEN_QUADRATIC 23
#define LIT_ATTEN_XXX 24
#define LIT_CMD_1 25
#define LIT_SPOT_DCD 26
#define LIT_SPOT_EXPONENT 27
#define LIT_SPOT_CUTOFF 28
#define LIT_SPECULAR_THRESH 29
#define LIT_RANGE_CUTOFF 30 /* ? */
#define LIT_RANGE_ATTEN 31 /* ? */
#define LIT_STATE_SIZE 32
/* 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
#define SHN_CMD_0 0
#define SHN_SHININESS 1
#define SHN_STATE_SIZE 2
struct radeon_hw_state {
/* All state should be on one of these lists:
*/
struct radeon_state_atom dirty; /* dirty list head placeholder */
struct radeon_state_atom clean; /* clean list head placeholder */
/* 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 radeon_state_atom ctx;
struct radeon_state_atom set;
struct radeon_state_atom lin;
struct radeon_state_atom msk;
struct radeon_state_atom vpt;
struct radeon_state_atom tcl;
struct radeon_state_atom msc;
struct radeon_state_atom tex[2];
struct radeon_state_atom zbs;
struct radeon_state_atom mtl;
struct radeon_state_atom mat[5];
struct radeon_state_atom lit[8]; /* includes vec, scl commands */
struct radeon_state_atom ucp[6];
struct radeon_state_atom eye; /* eye pos */
struct radeon_state_atom grd; /* guard band clipping */
struct radeon_state_atom fog;
struct radeon_state_atom glt;
};
struct radeon_state {
/* Derived state for internal purposes:
*/
struct radeon_colorbuffer_state color;
struct radeon_depthbuffer_state depth;
struct radeon_pixel_state pixel;
struct radeon_scissor_state scissor;
struct radeon_stencilbuffer_state stencil;
struct radeon_stipple_state stipple;
struct radeon_texture_state texture;
};
struct radeon_texture {
radeonTexObj objects[RADEON_NR_TEX_HEAPS];
radeonTexObj swapped;
memHeap_t *heap[RADEON_NR_TEX_HEAPS];
GLint age[RADEON_NR_TEX_HEAPS];
GLint numHeaps;
};
/* Need refcounting on dma buffers:
*/
struct radeon_dma_buffer {
int refcount; /* the number of retained regions in buf */
drmBufPtr buf;
};
#define GET_START(rvb) (rmesa->radeonScreen->agp_buffer_offset + \
(rvb)->address - rmesa->dma.buf0_address + \
(rvb)->start)
/* A retained region, eg vertices for indexed vertices.
*/
struct radeon_dma_region {
struct radeon_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 radeon_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 radeon_dma_region current;
void (*flush)( radeonContextPtr );
char *buf0_address; /* start of buf[0], for index calcs */
GLuint nr_released_bufs; /* flush after so many buffers released */
};
struct radeon_dri_mirror {
__DRIcontextPrivate *context; /* DRI context */
__DRIscreenPrivate *screen; /* DRI screen */
__DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */
drmContext hwContext;
drmLock *hwLock;
int fd;
int drmMinor;
};
#define RADEON_CMD_BUF_SZ (8*1024)
struct radeon_store {
GLuint statenr;
GLuint primnr;
char cmd_buf[RADEON_CMD_BUF_SZ];
int cmd_used;
int elts_start;
};
/* radeon_tcl.c
*/
struct radeon_tcl_info {
GLuint vertex_format;
GLint last_offset;
GLuint hw_primitive;
struct radeon_dma_region *aos_components[8];
GLuint nr_aos_components;
GLuint *Elts;
struct radeon_dma_region indexed_verts;
struct radeon_dma_region obj;
struct radeon_dma_region rgba;
struct radeon_dma_region spec;
struct radeon_dma_region fog;
struct radeon_dma_region tex[RADEON_MAX_TEXTURE_UNITS];
struct radeon_dma_region norm;
};
/* radeon_swtcl.c
*/
struct radeon_swtcl_info {
GLuint SetupIndex;
GLuint SetupNewInputs;
GLuint RenderIndex;
GLuint vertex_size;
GLuint vertex_stride_shift;
GLuint vertex_format;
char *verts;
/* Fallback rasterization functions
*/
radeon_point_func draw_point;
radeon_line_func draw_line;
radeon_tri_func draw_tri;
GLuint hw_primitive;
GLenum render_primitive;
GLuint numverts;
struct radeon_dma_region indexed_verts;
};
struct radeon_ioctl {
GLuint vertex_offset;
GLuint vertex_size;
};
#define RADEON_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;
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 TexCoord2f;
struct dynfn TexCoord2fv;
struct dynfn TexCoord1f;
struct dynfn TexCoord1fv;
struct dynfn MultiTexCoord2fARB;
struct dynfn MultiTexCoord2fvARB;
struct dynfn MultiTexCoord1fARB;
struct dynfn MultiTexCoord1fvARB;
};
struct _vb;
struct dfn_generators {
struct dynfn *(*Vertex2f)( GLcontext *, int );
struct dynfn *(*Vertex2fv)( GLcontext *, int );
struct dynfn *(*Vertex3f)( GLcontext *, int );
struct dynfn *(*Vertex3fv)( GLcontext *, int );
struct dynfn *(*Color4ub)( GLcontext *, int );
struct dynfn *(*Color4ubv)( GLcontext *, int );
struct dynfn *(*Color3ub)( GLcontext *, int );
struct dynfn *(*Color3ubv)( GLcontext *, int );
struct dynfn *(*Color4f)( GLcontext *, int );
struct dynfn *(*Color4fv)( GLcontext *, int );
struct dynfn *(*Color3f)( GLcontext *, int );
struct dynfn *(*Color3fv)( GLcontext *, int );
struct dynfn *(*SecondaryColor3ubEXT)( GLcontext *, int );
struct dynfn *(*SecondaryColor3ubvEXT)( GLcontext *, int );
struct dynfn *(*SecondaryColor3fEXT)( GLcontext *, int );
struct dynfn *(*SecondaryColor3fvEXT)( GLcontext *, int );
struct dynfn *(*Normal3f)( GLcontext *, int );
struct dynfn *(*Normal3fv)( GLcontext *, int );
struct dynfn *(*TexCoord2f)( GLcontext *, int );
struct dynfn *(*TexCoord2fv)( GLcontext *, int );
struct dynfn *(*TexCoord1f)( GLcontext *, int );
struct dynfn *(*TexCoord1fv)( GLcontext *, int );
struct dynfn *(*MultiTexCoord2fARB)( GLcontext *, int );
struct dynfn *(*MultiTexCoord2fvARB)( GLcontext *, int );
struct dynfn *(*MultiTexCoord1fARB)( GLcontext *, int );
struct dynfn *(*MultiTexCoord1fvARB)( GLcontext *, int );
};
struct radeon_vb {
/* Keep these first: referenced from codegen templates:
*/
GLint counter, initial_counter;
GLint *dmaptr;
void (*notify)( void );
GLint vertex_size;
union { float f; int i; radeon_color_t color; } vertex[15];
GLfloat *normalptr;
GLfloat *floatcolorptr;
radeon_color_t *colorptr;
radeon_color_t *specptr;
GLfloat *texcoordptr[2];
GLcontext *context; /* current context : Single thread only! */
};
struct radeon_prim {
GLuint start;
GLuint end;
GLuint prim;
};
struct radeon_vbinfo {
GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */
GLuint primflags;
GLboolean enabled; /* RADEON_NO_VTXFMT//RADEON_NO_TCL env vars */
GLboolean installed;
GLboolean fell_back;
GLboolean recheck;
GLint initial_counter;
GLint nrverts;
GLuint vertex_format;
GLuint installed_vertex_format;
GLuint installed_color_3f_sz;
struct radeon_prim primlist[RADEON_MAX_PRIMS];
int nrprims;
struct dfn_lists dfn_cache;
struct dfn_generators codegen;
GLvertexformat vtxfmt;
};
struct radeon_context {
GLcontext *glCtx; /* Mesa context */
/* Driver and hardware state management
*/
struct radeon_hw_state hw;
struct radeon_state state;
/* Texture object bookkeeping
*/
struct radeon_texture texture;
/* Rasterization and vertex state:
*/
GLuint TclFallback;
GLuint Fallback;
GLuint NewGLState;
/* Temporaries for translating away float colors:
*/
struct gl_client_array UbyteColor;
struct gl_client_array UbyteSecondaryColor;
/* Vertex buffers
*/
struct radeon_ioctl ioctl;
struct radeon_dma dma;
struct radeon_store store;
/* Page flipping
*/
GLuint doPageFlip;
/* Busy waiting
*/
GLuint do_usleeps;
GLuint do_irqs;
GLuint irqsEmitted;
drmRadeonIrqWait iw;
/* Drawable, cliprect and scissor information
*/
GLuint numClipRects; /* Cliprects for the draw buffer */
XF86DRIClipRectPtr pClipRects;
unsigned int lastStamp;
GLboolean lost_context;
radeonScreenPtr radeonScreen; /* Screen private DRI data */
RADEONSAREAPrivPtr sarea; /* Private SAREA data */
/* TCL stuff
*/
GLmatrix TexGenMatrix[RADEON_MAX_TEXTURE_UNITS];
GLboolean recheck_texgen[RADEON_MAX_TEXTURE_UNITS];
GLboolean TexGenNeedNormals[RADEON_MAX_TEXTURE_UNITS];
GLuint TexMatEnabled;
GLuint TexGenEnabled;
GLmatrix tmpmat;
GLuint last_ReallyEnabled;
/* VBI
*/
GLuint vbl_seq;
/* radeon_tcl.c
*/
struct radeon_tcl_info tcl;
/* radeon_swtcl.c
*/
struct radeon_swtcl_info swtcl;
/* radeon_vtxfmt.c
*/
struct radeon_vbinfo vb;
/* Mirrors of some DRI state
*/
struct radeon_dri_mirror dri;
/* Performance counters
*/
GLuint boxes; /* Draw performance boxes */
GLuint hardwareWentIdle;
GLuint c_clears;
GLuint c_drawWaits;
GLuint c_textureSwaps;
GLuint c_textureBytes;
GLuint c_vertexBuffers;
};
#define RADEON_CONTEXT(ctx) ((radeonContextPtr)(ctx->DriverCtx))
static __inline GLuint radeonPackColor( GLuint cpp,
GLubyte r, GLubyte g,
GLubyte b, GLubyte a )
{
switch ( cpp ) {
case 2:
return PACK_COLOR_565( r, g, b );
case 4:
return PACK_COLOR_8888( a, r, g, b );
default:
return 0;
}
}
#define RADEON_OLD_PACKETS 1
/* ================================================================
* Debugging:
*/
#define DO_DEBUG 1
#if DO_DEBUG
extern int RADEON_DEBUG;
#else
#define RADEON_DEBUG 0
#endif
#define DEBUG_TEXTURE 0x001
#define DEBUG_STATE 0x002
#define DEBUG_IOCTL 0x004
#define DEBUG_PRIMS 0x008
#define DEBUG_VERTS 0x010
#define DEBUG_FALLBACKS 0x020
#define DEBUG_VFMT 0x040
#define DEBUG_CODEGEN 0x080
#define DEBUG_VERBOSE 0x100
#define DEBUG_DRI 0x200
#define DEBUG_DMA 0x400
#define DEBUG_SANITY 0x800
#endif
#endif /* __RADEON_CONTEXT_H__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,178 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h,v 1.4 2002/09/16 18:05:20 eich Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __RADEON_IOCTL_H__
#define __RADEON_IOCTL_H__
#ifdef GLX_DIRECT_RENDERING
#include "simple_list.h"
#include "radeon_lock.h"
extern void radeonEmitState( radeonContextPtr rmesa );
extern void radeonEmitVertexAOS( radeonContextPtr rmesa,
GLuint vertex_size,
GLuint offset );
extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
GLuint vertex_format,
GLuint primitive,
GLuint vertex_nr );
extern void radeonFlushElts( radeonContextPtr rmesa );
extern GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
GLuint vertex_format,
GLuint primitive,
GLuint min_nr );
extern void radeonEmitAOS( radeonContextPtr rmesa,
struct radeon_dma_region **regions,
GLuint n,
GLuint offset );
extern void radeonFlushCmdBuf( radeonContextPtr rmesa, const char * );
extern void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa );
extern void radeonAllocDmaRegion( radeonContextPtr rmesa,
struct radeon_dma_region *region,
int bytes,
int alignment );
extern void radeonAllocDmaRegionVerts( radeonContextPtr rmesa,
struct radeon_dma_region *region,
int numverts,
int vertsize,
int alignment );
extern void radeonReleaseDmaRegion( radeonContextPtr rmesa,
struct radeon_dma_region *region,
const char *caller );
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 rmesa );
extern void radeonWaitForVBlank( radeonContextPtr rmesa );
extern void radeonInitIoctlFuncs( GLcontext *ctx );
extern void radeonGetAllParams( radeonContextPtr rmesa );
/* radeon_compat.c:
*/
extern void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
GLuint vertex_format,
GLuint hw_primitive,
GLuint nrverts );
/* ================================================================
* Helper macros:
*/
/* Close off the last primitive, if it exists.
*/
#define RADEON_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 RADEON_STATECHANGE( rmesa, ATOM ) \
do { \
RADEON_NEWPRIM( rmesa ); \
move_to_head( &(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \
} while (0)
#define RADEON_DB_STATE( ATOM ) \
memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \
rmesa->hw.ATOM.cmd_size * 4)
static __inline int RADEON_DB_STATECHANGE(
radeonContextPtr rmesa,
struct radeon_state_atom *atom )
{
if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) {
int *tmp;
RADEON_NEWPRIM( rmesa );
move_to_head( &(rmesa->hw.dirty), atom );
tmp = atom->cmd;
atom->cmd = atom->lastcmd;
atom->lastcmd = tmp;
return 1;
}
else
return 0;
}
/* Fire the buffered vertices no matter what.
*/
#define RADEON_FIREVERTICES( rmesa ) \
do { \
if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \
radeonFlush( rmesa->glCtx ); \
} \
} while (0)
/* Alloc space in the command buffer
*/
static __inline char *radeonAllocCmdBuf( radeonContextPtr rmesa,
int bytes, const char *where )
{
if (rmesa->store.cmd_used + bytes > RADEON_CMD_BUF_SZ)
radeonFlushCmdBuf( rmesa, __FUNCTION__ );
assert(rmesa->dri.drmMinor >= 3);
{
char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used;
rmesa->store.cmd_used += bytes;
return head;
}
}
#endif
#endif /* __RADEON_IOCTL_H__ */

View file

@ -0,0 +1,130 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c,v 1.4 2002/02/22 21:45:00 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#include "glheader.h"
#include "radeon_context.h"
#include "radeon_lock.h"
#include "radeon_tex.h"
#include "radeon_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 rmesa )
{
int use_back;
if (rmesa->dri.drmMinor < 3)
return;
rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
use_back ^= (rmesa->sarea->pfCurrentPage == 1);
if ( RADEON_DEBUG & DEBUG_VERBOSE )
fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__,
rmesa->doPageFlip,
rmesa->sarea->pfCurrentPage );
if ( use_back ) {
rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
} else {
rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
}
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
/* 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 rmesa, GLuint flags )
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
__DRIscreenPrivate *sPriv = rmesa->dri.screen;
RADEONSAREAPrivPtr sarea = rmesa->sarea;
int i;
drmGetLock( rmesa->dri.fd, rmesa->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 ( rmesa->lastStamp != dPriv->lastStamp ) {
radeonUpdatePageFlipping( rmesa );
if (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT)
radeonSetCliprects( rmesa, GL_BACK_LEFT );
else
radeonSetCliprects( rmesa, GL_FRONT_LEFT );
radeonUpdateViewportOffset( rmesa->glCtx );
rmesa->lastStamp = dPriv->lastStamp;
}
if ( sarea->ctxOwner != rmesa->dri.hwContext ) {
sarea->ctxOwner = rmesa->dri.hwContext;
for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) {
if ( rmesa->texture.heap[i] && sarea->texAge[i] != rmesa->texture.age[i] ) {
radeonAgeTextures( rmesa, i );
}
}
}
}

View file

@ -0,0 +1,113 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h,v 1.2 2002/02/22 21:45:00 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __RADEON_LOCK_H__
#define __RADEON_LOCK_H__
#ifdef GLX_DIRECT_RENDERING
extern void radeonGetLock( radeonContextPtr rmesa, 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( rmesa ) \
do { \
char __ret = 0; \
DEBUG_CHECK_LOCK(); \
DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \
(DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \
if ( __ret ) \
radeonGetLock( rmesa, 0 ); \
DEBUG_LOCK(); \
} while (0)
/* Unlock the hardware.
*/
#define UNLOCK_HARDWARE( rmesa ) \
do { \
DRM_UNLOCK( rmesa->dri.fd, \
rmesa->dri.hwLock, \
rmesa->dri.hwContext ); \
DEBUG_RESET(); \
} while (0)
#endif
#endif /* __RADEON_LOCK_H__ */

View file

@ -0,0 +1,134 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.20 2002/10/12 01:38:07 martin Exp $ */
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, 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
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
* THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Kevin E. Martin <martin@xfree86.org>
* Rickard E. Faith <faith@valinux.com>
* Alan Hourihane <alanh@fairlite.demon.co.uk>
*
* References:
*
* !!!! FIXME !!!!
* RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
* Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
* 1999.
*
* !!!! FIXME !!!!
* RAGE 128 Software Development Manual (Technical Reference Manual P/N
* SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
*
*/
#ifndef _RADEON_MACROS_H_
#define _RADEON_MACROS_H_
#ifdef XFree86Module
#include "xf86_ansic.h"
#endif
/* #include "compiler.h" */
/* Memory mapped register access macros */
#define INREG8(addr) MMIO_IN8(RADEONMMIO, addr)
#define INREG16(addr) MMIO_IN16(RADEONMMIO, addr)
#define INREG(addr) MMIO_IN32(RADEONMMIO, addr)
#define OUTREG8(addr, val) MMIO_OUT8(RADEONMMIO, addr, val)
#define OUTREG16(addr, val) MMIO_OUT16(RADEONMMIO, addr, val)
#define OUTREG(addr, val) MMIO_OUT32(RADEONMMIO, addr, val)
#define ADDRREG(addr) ((volatile GLuint *)(pointer)(RADEONMMIO + (addr)))
#define OUTREGP(addr, val, mask) \
do { \
GLuint tmp = INREG(addr); \
tmp &= (mask); \
tmp |= (val); \
OUTREG(addr, tmp); \
} while (0)
#define INPLL(pScrn, addr) RADEONINPLL(pScrn, addr)
#define OUTPLL(addr, val) \
do { \
OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \
RADEON_PLL_WR_EN)); \
OUTREG(RADEON_CLOCK_CNTL_DATA, val); \
} while (0)
#define OUTPLLP(pScrn, addr, val, mask) \
do { \
GLuint tmp = INPLL(pScrn, addr); \
tmp &= (mask); \
tmp |= (val); \
OUTPLL(addr, tmp); \
} while (0)
#define OUTPAL_START(idx) \
do { \
OUTREG8(RADEON_PALETTE_INDEX, (idx)); \
} while (0)
#define OUTPAL_NEXT(r, g, b) \
do { \
OUTREG(RADEON_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \
} while (0)
#define OUTPAL_NEXT_CARD32(v) \
do { \
OUTREG(RADEON_PALETTE_DATA, (v & 0x00ffffff)); \
} while (0)
#define OUTPAL(idx, r, g, b) \
do { \
OUTPAL_START((idx)); \
OUTPAL_NEXT((r), (g), (b)); \
} while (0)
#define INPAL_START(idx) \
do { \
OUTREG(RADEON_PALETTE_INDEX, (idx) << 16); \
} while (0)
#define INPAL_NEXT() INREG(RADEON_PALETTE_DATA)
#define PAL_SELECT(idx) \
do { \
if (!idx) { \
OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) & \
(GLuint)~RADEON_DAC2_PALETTE_ACC_CTL); \
} else { \
OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) | \
RADEON_DAC2_PALETTE_ACC_CTL); \
} \
} while (0)
#endif

View file

@ -0,0 +1,12 @@
/* If using new packets, can choose either verts or arrays.
* Otherwise, must use verts.
*/
#include "radeon_context.h"
#define RADEON_MAOS_VERTS 1
#if (RADEON_MAOS_VERTS) || (RADEON_OLD_PACKETS)
#include "radeon_maos_verts.c"
#else
#include "radeon_maos_arrays.c"
#endif

View file

@ -0,0 +1,47 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Grahpics Inc., Austin, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAHPICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#ifndef __RADEON_MAOS_H__
#define __RADEON_MAOS_H__
#ifdef GLX_DIRECT_RENDERING
#include "radeon_context.h"
extern void radeonEmitArrays( GLcontext *ctx, GLuint inputs );
extern void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs );
#endif
#endif

View file

@ -0,0 +1,591 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "mtypes.h"
#include "mmath.h"
#include "macros.h"
#include "swrast_setup/swrast_setup.h"
#include "math/m_translate.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_imm_debug.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_swtcl.h"
#include "radeon_maos.h"
/* Usage:
* - from radeon_tcl_render
* - call radeonEmitArrays to ensure uptodate arrays in dma
* - emit primitives (new type?) which reference the data
* -- need to use elts for lineloop, quads, quadstrip/flat
* -- other primitives are all well-formed (need tristrip-1,fake-poly)
*
*/
static void emit_ubyte_rgba3( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
radeon_color_t *out = (radeon_color_t *)(rvb->start + rvb->address);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p\n",
__FUNCTION__, count, stride, out);
for (i = 0; i < count; i++) {
out->red = *data;
out->green = *(data+1);
out->blue = *(data+2);
out->alpha = 0xFF;
out++;
data += stride;
}
}
#if defined(USE_X86_ASM)
#define COPY_DWORDS( dst, src, nr ) \
do { \
int __tmp; \
__asm__ __volatile__( "rep ; movsl" \
: "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
: "0" (nr), \
"D" ((long)dst), \
"S" ((long)src) ); \
} while (0)
#else
#define COPY_DWORDS( dst, src, nr ) \
do { \
int j; \
for ( j = 0 ; j < nr ; j++ ) \
dst[j] = ((int *)src)[j]; \
dst += nr; \
} while (0)
#endif
static void emit_ubyte_rgba4( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
if (stride == 4)
COPY_DWORDS( out, data, count );
else
for (i = 0; i < count; i++) {
*out++ = LE32_TO_CPU(*(int *)data);
data += stride;
}
}
static void emit_ubyte_rgba( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int size,
int stride,
int count )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
assert (!rvb->buf);
if (stride == 0) {
radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
count = 1;
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 0;
rvb->aos_size = 1;
}
else {
radeonAllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 1;
rvb->aos_size = 1;
}
/* Emit the data
*/
switch (size) {
case 3:
emit_ubyte_rgba3( ctx, rvb, data, stride, count );
break;
case 4:
emit_ubyte_rgba4( ctx, rvb, data, stride, count );
break;
default:
assert(0);
exit(1);
break;
}
}
static void emit_vec8( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
if (stride == 8)
COPY_DWORDS( out, data, count*2 );
else
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out += 2;
data += stride;
}
}
static void emit_vec12( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p data %p\n",
__FUNCTION__, count, stride, out, data);
if (stride == 12)
COPY_DWORDS( out, data, count*3 );
else
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out[2] = *(int *)(data+8);
out += 3;
data += stride;
}
}
static void emit_vec16( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
if (stride == 16)
COPY_DWORDS( out, data, count*4 );
else
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out[2] = *(int *)(data+8);
out[3] = *(int *)(data+12);
out += 4;
data += stride;
}
}
static void emit_vector( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int size,
int stride,
int count )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
assert (!rvb->buf);
if (stride == 0) {
radeonAllocDmaRegion( rmesa, rvb, size * 4, 4 );
count = 1;
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 0;
rvb->aos_size = size;
}
else {
radeonAllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = size;
rvb->aos_size = size;
}
/* Emit the data
*/
switch (size) {
case 2:
emit_vec8( ctx, rvb, data, stride, count );
break;
case 3:
emit_vec12( ctx, rvb, data, stride, count );
break;
case 4:
emit_vec16( ctx, rvb, data, stride, count );
break;
default:
assert(0);
exit(1);
break;
}
}
static void emit_s0_vec( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = 0;
out += 2;
data += stride;
}
}
static void emit_stq_vec( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out[2] = *(int *)(data+12);
out += 3;
data += stride;
}
}
static void emit_tex_vector( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int size,
int stride,
int count )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
int emitsize;
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
assert (!rvb->buf);
switch (size) {
case 4: emitsize = 3; break;
default: emitsize = 2; break;
}
if (stride == 0) {
radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize, 4 );
count = 1;
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 0;
rvb->aos_size = emitsize;
}
else {
radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize * count, 4 );
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = emitsize;
rvb->aos_size = emitsize;
}
/* Emit the data
*/
switch (size) {
case 1:
emit_s0_vec( ctx, rvb, data, stride, count );
break;
case 2:
emit_vec8( ctx, rvb, data, stride, count );
break;
case 3:
emit_vec8( ctx, rvb, data, stride, count );
break;
case 4:
emit_stq_vec( ctx, rvb, data, stride, count );
break;
default:
assert(0);
exit(1);
break;
}
}
/* Emit any changed arrays to new agp memory, re-emit a packet to
* update the arrays.
*/
void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
struct radeon_dma_region **component = rmesa->tcl.aos_components;
GLuint nr = 0;
GLuint vfmt = 0;
GLuint count = VB->Count;
GLuint vtx;
if (RADEON_DEBUG & DEBUG_VERTS)
_tnl_print_vert_flags( __FUNCTION__, inputs );
if (1) {
if (!rmesa->tcl.obj.buf)
emit_vector( ctx,
&rmesa->tcl.obj,
(char *)VB->ObjPtr->data,
VB->ObjPtr->size,
VB->ObjPtr->stride,
count);
switch( VB->ObjPtr->size ) {
case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
case 3: vfmt |= RADEON_CP_VC_FRMT_Z;
case 2: vfmt |= RADEON_CP_VC_FRMT_XY;
default:
}
component[nr++] = &rmesa->tcl.obj;
}
if (inputs & VERT_BIT_NORMAL) {
if (!rmesa->tcl.norm.buf)
emit_vector( ctx,
&(rmesa->tcl.norm),
(char *)VB->NormalPtr->data,
3,
VB->NormalPtr->stride,
count);
vfmt |= RADEON_CP_VC_FRMT_N0;
component[nr++] = &rmesa->tcl.norm;
}
if (inputs & VERT_BIT_COLOR0) {
if (VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE) {
if (!rmesa->tcl.rgba.buf)
emit_ubyte_rgba( ctx,
&rmesa->tcl.rgba,
(char *)VB->ColorPtr[0]->Ptr,
VB->ColorPtr[0]->Size,
VB->ColorPtr[0]->StrideB,
count);
vfmt |= RADEON_CP_VC_FRMT_PKCOLOR;
}
else {
int emitsize;
if (VB->ColorPtr[0]->Size == 4 &&
(VB->ColorPtr[0]->StrideB != 0 ||
((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) {
vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA;
emitsize = 4;
}
else {
vfmt |= RADEON_CP_VC_FRMT_FPCOLOR;
emitsize = 3;
}
if (!rmesa->tcl.rgba.buf)
emit_vector( ctx,
&(rmesa->tcl.rgba),
(char *)VB->ColorPtr[0]->Ptr,
emitsize,
VB->ColorPtr[0]->StrideB,
count);
}
component[nr++] = &rmesa->tcl.rgba;
}
if (inputs & VERT_BIT_COLOR1) {
if (!rmesa->tcl.spec.buf) {
if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
radeon_import_float_spec_colors( ctx );
emit_ubyte_rgba( ctx,
&rmesa->tcl.spec,
(char *)VB->SecondaryColorPtr[0]->Ptr,
3,
VB->SecondaryColorPtr[0]->StrideB,
count);
}
vfmt |= RADEON_CP_VC_FRMT_PKSPEC;
component[nr++] = &rmesa->tcl.spec;
}
vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1));
if (inputs & VERT_BIT_TEX0) {
if (!rmesa->tcl.tex[0].buf)
emit_tex_vector( ctx,
&(rmesa->tcl.tex[0]),
(char *)VB->TexCoordPtr[0]->data,
VB->TexCoordPtr[0]->size,
VB->TexCoordPtr[0]->stride,
count );
switch( VB->TexCoordPtr[0]->size ) {
case 4:
vtx |= RADEON_TCL_VTX_Q0;
vfmt |= RADEON_CP_VC_FRMT_Q0;
default:
vfmt |= RADEON_CP_VC_FRMT_ST0;
}
component[nr++] = &rmesa->tcl.tex[0];
}
if (inputs & VERT_BIT_TEX1) {
if (!rmesa->tcl.tex[1].buf)
emit_tex_vector( ctx,
&(rmesa->tcl.tex[1]),
(char *)VB->TexCoordPtr[1]->data,
VB->TexCoordPtr[1]->size,
VB->TexCoordPtr[1]->stride,
count );
switch( VB->TexCoordPtr[1]->size ) {
case 4:
vtx |= RADEON_TCL_VTX_Q1;
vfmt |= RADEON_CP_VC_FRMT_Q1;
default:
vfmt |= RADEON_CP_VC_FRMT_ST1;
}
component[nr++] = &rmesa->tcl.tex[1];
}
if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
RADEON_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
}
rmesa->tcl.nr_aos_components = nr;
rmesa->tcl.vertex_format = vfmt;
}
void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
if (RADEON_DEBUG & DEBUG_VERTS)
_tnl_print_vert_flags( __FUNCTION__, newinputs );
if (newinputs & VERT_BIT_POS)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
if (newinputs & VERT_BIT_NORMAL)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
if (newinputs & VERT_BIT_COLOR0)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
if (newinputs & VERT_BIT_COLOR1)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
if (newinputs & VERT_BIT_TEX0)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ );
if (newinputs & VERT_BIT_TEX1)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
}

View file

@ -0,0 +1,368 @@
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul 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 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
* BRIAN PAUL 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 LOCALVARS
#define LOCALVARS
#endif
#undef TCL_DEBUG
#ifndef TCL_DEBUG
#define TCL_DEBUG 0
#endif
static void TAG(emit)( GLcontext *ctx,
GLuint start, GLuint end,
void *dest )
{
LOCALVARS
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint (*tc0)[4], (*tc1)[4], (*tc2)[4];
GLfloat (*fog)[4];
GLuint (*norm)[4];
GLubyte (*col)[4], (*spec)[4];
GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
GLuint tc2_stride, norm_stride;
GLuint (*coord)[4];
GLuint coord_stride; /* object coordinates */
GLubyte dummy[4];
int i;
union emit_union *v = (union emit_union *)dest;
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s\n", __FUNCTION__);
/* The vertex code expects Obj to be clean to element 3. To fix
* this, add more vertex code (for obj-2, obj-3) or preferably move
* to maos.
*/
if (VB->ObjPtr->size < 3) {
if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 2 );
}
if (DO_W && VB->ObjPtr->size < 4) {
if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 3 );
}
coord = (GLuint (*)[4])VB->ObjPtr->data;
coord_stride = VB->ObjPtr->stride;
if (DO_TEX2) {
const GLuint t2 = GET_TEXSOURCE(2);
tc2 = (GLuint (*)[4])VB->TexCoordPtr[t2]->data;
tc2_stride = VB->TexCoordPtr[t2]->stride;
if (DO_PTEX && VB->TexCoordPtr[t2]->size < 4) {
if (VB->TexCoordPtr[t2]->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_BIT_TEX2, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->TexCoordPtr[t2], VB->Count, 3 );
}
}
if (DO_TEX1) {
if (VB->TexCoordPtr[1]) {
const GLuint t1 = GET_TEXSOURCE(1);
tc1 = (GLuint (*)[4])VB->TexCoordPtr[t1]->data;
tc1_stride = VB->TexCoordPtr[t1]->stride;
if (DO_PTEX && VB->TexCoordPtr[t1]->size < 4) {
if (VB->TexCoordPtr[t1]->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_BIT_TEX1, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->TexCoordPtr[t1], VB->Count, 3 );
}
} else {
tc1 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX1]; /* could be anything, really */
tc1_stride = 0;
}
}
if (DO_TEX0) {
if (VB->TexCoordPtr[0]) {
const GLuint t0 = GET_TEXSOURCE(0);
tc0_stride = VB->TexCoordPtr[t0]->stride;
tc0 = (GLuint (*)[4])VB->TexCoordPtr[t0]->data;
if (DO_PTEX && VB->TexCoordPtr[t0]->size < 4) {
if (VB->TexCoordPtr[t0]->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_BIT_TEX0, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->TexCoordPtr[t0], VB->Count, 3 );
}
} else {
tc0 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* could be anything, really */
tc0_stride = 0;
}
}
if (DO_NORM) {
if (VB->NormalPtr) {
norm_stride = VB->NormalPtr->stride;
norm = (GLuint (*)[4])VB->NormalPtr->data;
} else {
norm_stride = 0;
norm = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
}
}
if (DO_RGBA) {
if (VB->ColorPtr[0]) {
/* This is incorrect when colormaterial is enabled:
*/
if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) {
if (0) fprintf(stderr, "IMPORTING FLOAT COLORS\n");
IMPORT_FLOAT_COLORS( ctx );
}
col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
col_stride = VB->ColorPtr[0]->StrideB;
} else {
col = &dummy; /* any old memory is fine */
col_stride = 0;
}
}
if (DO_SPEC) {
if (VB->SecondaryColorPtr[0]) {
if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
IMPORT_FLOAT_SPEC_COLORS( ctx );
spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr;
spec_stride = VB->SecondaryColorPtr[0]->StrideB;
} else {
spec = &dummy;
spec_stride = 0;
}
}
if (DO_FOG) {
if (VB->FogCoordPtr) {
fog = VB->FogCoordPtr->data;
fog_stride = VB->FogCoordPtr->stride;
} else {
fog = (GLfloat (*)[4])&dummy; fog[0][0] = 0.0F;
fog_stride = 0;
}
}
if (VB->importable_data) {
if (start) {
coord = (GLuint (*)[4])((GLubyte *)coord + start * coord_stride);
if (DO_TEX0)
tc0 = (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride);
if (DO_TEX1)
tc1 = (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride);
if (DO_TEX2)
tc2 = (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride);
if (DO_NORM)
norm = (GLuint (*)[4])((GLubyte *)norm + start * norm_stride);
if (DO_RGBA)
STRIDE_4UB(col, start * col_stride);
if (DO_SPEC)
STRIDE_4UB(spec, start * spec_stride);
if (DO_FOG)
fog = (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
}
for (i=start; i < end; i++) {
v[0].ui = coord[0][0];
v[1].ui = coord[0][1];
v[2].ui = coord[0][2];
if (TCL_DEBUG) fprintf(stderr, "%d: %.2f %.2f %.2f ", i, v[0].f, v[1].f, v[2].f);
if (DO_W) {
v[3].ui = coord[0][3];
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[3].f);
v += 4;
}
else
v += 3;
coord = (GLuint (*)[4])((GLubyte *)coord + coord_stride);
if (DO_NORM) {
v[0].ui = norm[0][0];
v[1].ui = norm[0][1];
v[2].ui = norm[0][2];
if (TCL_DEBUG) fprintf(stderr, "norm: %.2f %.2f %.2f ", v[0].f, v[1].f, v[2].f);
v += 3;
norm = (GLuint (*)[4])((GLubyte *)norm + norm_stride);
}
if (DO_RGBA) {
v[0].ui = LE32_TO_CPU(*(GLuint *)&col[0]);
STRIDE_4UB(col, col_stride);
if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
v++;
}
if (DO_SPEC || DO_FOG) {
if (DO_SPEC) {
v[0].specular.red = spec[0][0];
v[0].specular.green = spec[0][1];
v[0].specular.blue = spec[0][2];
STRIDE_4UB(spec, spec_stride);
}
if (DO_FOG) {
v[0].specular.alpha = fog[0][0] * 255.0;
fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
}
if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
v++;
}
if (DO_TEX0) {
v[0].ui = tc0[0][0];
v[1].ui = tc0[0][1];
if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f);
if (DO_PTEX) {
v[2].ui = tc0[0][3];
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
v += 3;
}
else
v += 2;
tc0 = (GLuint (*)[4])((GLubyte *)tc0 + tc0_stride);
}
if (DO_TEX1) {
v[0].ui = tc1[0][0];
v[1].ui = tc1[0][1];
if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f);
if (DO_PTEX) {
v[2].ui = tc1[0][3];
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
v += 3;
}
else
v += 2;
tc1 = (GLuint (*)[4])((GLubyte *)tc1 + tc1_stride);
}
if (DO_TEX2) {
v[0].ui = tc2[0][0];
v[1].ui = tc2[0][1];
if (DO_PTEX) {
v[2].ui = tc2[0][3];
v += 3;
}
else
v += 2;
tc2 = (GLuint (*)[4])((GLubyte *)tc2 + tc2_stride);
}
if (TCL_DEBUG) fprintf(stderr, "\n");
}
} else {
for (i=start; i < end; i++) {
v[0].ui = coord[i][0];
v[1].ui = coord[i][1];
v[2].ui = coord[i][2];
if (DO_W) {
v[3].ui = coord[i][3];
v += 4;
}
else
v += 3;
if (DO_NORM) {
v[0].ui = norm[i][0];
v[1].ui = norm[i][1];
v[2].ui = norm[i][2];
v += 3;
}
if (DO_RGBA) {
v[0].ui = LE32_TO_CPU(*(GLuint *)&col[i]);
v++;
}
if (DO_SPEC || DO_FOG) {
if (DO_SPEC) {
v[0].specular.red = spec[i][0];
v[0].specular.green = spec[i][1];
v[0].specular.blue = spec[i][2];
}
if (DO_FOG) {
GLfloat *f = (GLfloat *) ((GLubyte *)fog + fog_stride);
v[0].specular.alpha = *f * 255.0;
}
v++;
}
if (DO_TEX0) {
v[0].ui = tc0[i][0];
v[1].ui = tc0[i][1];
if (DO_PTEX) {
v[2].ui = tc0[i][3];
v += 3;
}
else
v += 2;
}
if (DO_TEX1) {
v[0].ui = tc1[i][0];
v[1].ui = tc1[i][1];
if (DO_PTEX) {
v[2].ui = tc1[i][3];
v += 3;
}
else
v += 2;
}
if (DO_TEX2) {
v[0].ui = tc2[i][0];
v[1].ui = tc2[i][1];
if (DO_PTEX) {
v[2].ui = tc2[i][3];
v += 3;
}
else
v += 2;
}
}
}
}
static void TAG(init)( void )
{
int sz = 3;
if (DO_W) sz++;
if (DO_NORM) sz += 3;
if (DO_RGBA) sz++;
if (DO_SPEC || DO_FOG) sz++;
if (DO_TEX0) sz += 2;
if (DO_TEX0 && DO_PTEX) sz++;
if (DO_TEX1) sz += 2;
if (DO_TEX1 && DO_PTEX) sz++;
if (DO_TEX2) sz += 2;
if (DO_TEX2 && DO_PTEX) sz++;
setup_tab[IDX].emit = TAG(emit);
setup_tab[IDX].vertex_format = IND;
setup_tab[IDX].vertex_size = sz;
}
#undef IND
#undef TAG
#undef IDX

View file

@ -0,0 +1,335 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Austin, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "mtypes.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "tnl/t_imm_debug.h"
#include "radeon_context.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_tex.h"
#include "radeon_tcl.h"
#include "radeon_swtcl.h"
#include "radeon_maos.h"
#define RADEON_TCL_MAX_SETUP 13
union emit_union { float f; GLuint ui; radeon_color_t specular; };
static struct {
void (*emit)( GLcontext *, GLuint, GLuint, void * );
GLuint vertex_size;
GLuint vertex_format;
} setup_tab[RADEON_TCL_MAX_SETUP];
#define DO_W (IND & RADEON_CP_VC_FRMT_W0)
#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR)
#define DO_SPEC (IND & RADEON_CP_VC_FRMT_PKSPEC)
#define DO_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC)
#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
#define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0)
#define DO_NORM (IND & RADEON_CP_VC_FRMT_N0)
#define DO_TEX2 0
#define DO_TEX3 0
#define GET_TEXSOURCE(n) n
#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor
#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor
#define IMPORT_FLOAT_COLORS radeon_import_float_colors
#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors
/***********************************************************************
* Generate vertex emit functions *
***********************************************************************/
/* Defined in order of increasing vertex size:
*/
#define IDX 0
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR)
#define TAG(x) x##_rgba
#include "radeon_maos_vbtmp.h"
#define IDX 1
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_n
#include "radeon_maos_vbtmp.h"
#define IDX 2
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_ST0)
#define TAG(x) x##_rgba_st
#include "radeon_maos_vbtmp.h"
#define IDX 3
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_rgba_n
#include "radeon_maos_vbtmp.h"
#define IDX 4
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_st_n
#include "radeon_maos_vbtmp.h"
#define IDX 5
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_ST1)
#define TAG(x) x##_rgba_st_st
#include "radeon_maos_vbtmp.h"
#define IDX 6
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_rgba_st_n
#include "radeon_maos_vbtmp.h"
#define IDX 7
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_PKSPEC| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_ST1)
#define TAG(x) x##_rgba_spec_st_st
#include "radeon_maos_vbtmp.h"
#define IDX 8
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_ST1| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_st_st_n
#include "radeon_maos_vbtmp.h"
#define IDX 9
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_PKSPEC| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_ST1| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_rgpa_spec_st_st_n
#include "radeon_maos_vbtmp.h"
#define IDX 10
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_Q0)
#define TAG(x) x##_rgba_stq
#include "radeon_maos_vbtmp.h"
#define IDX 11
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_ST1| \
RADEON_CP_VC_FRMT_Q1| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_Q0)
#define TAG(x) x##_rgba_stq_stq
#include "radeon_maos_vbtmp.h"
#define IDX 12
#define IND (RADEON_CP_VC_FRMT_XY| \
RADEON_CP_VC_FRMT_Z| \
RADEON_CP_VC_FRMT_W0| \
RADEON_CP_VC_FRMT_PKCOLOR| \
RADEON_CP_VC_FRMT_PKSPEC| \
RADEON_CP_VC_FRMT_ST0| \
RADEON_CP_VC_FRMT_Q0| \
RADEON_CP_VC_FRMT_ST1| \
RADEON_CP_VC_FRMT_Q1| \
RADEON_CP_VC_FRMT_N0)
#define TAG(x) x##_w_rgpa_spec_stq_stq_n
#include "radeon_maos_vbtmp.h"
/***********************************************************************
* Initialization
***********************************************************************/
static void init_tcl_verts( void )
{
init_rgba();
init_n();
init_rgba_n();
init_rgba_st();
init_st_n();
init_rgba_st_st();
init_rgba_st_n();
init_rgba_spec_st_st();
init_st_st_n();
init_rgpa_spec_st_st_n();
init_rgba_stq();
init_rgba_stq_stq();
init_w_rgpa_spec_stq_stq_n();
}
void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint req = 0;
GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1));
int i;
static int firsttime = 1;
if (firsttime) {
init_tcl_verts();
firsttime = 0;
}
if (1) {
req |= RADEON_CP_VC_FRMT_Z;
if (VB->ObjPtr->size == 4) {
req |= RADEON_CP_VC_FRMT_W0;
}
}
if (inputs & VERT_BIT_NORMAL) {
req |= RADEON_CP_VC_FRMT_N0;
}
if (inputs & VERT_BIT_COLOR0) {
req |= RADEON_CP_VC_FRMT_PKCOLOR;
}
if (inputs & VERT_BIT_COLOR1) {
req |= RADEON_CP_VC_FRMT_PKSPEC;
}
if (inputs & VERT_BIT_TEX0) {
req |= RADEON_CP_VC_FRMT_ST0;
if (VB->TexCoordPtr[0]->size == 4) {
req |= RADEON_CP_VC_FRMT_Q0;
vtx |= RADEON_TCL_VTX_Q0;
}
}
if (inputs & VERT_BIT_TEX1) {
req |= RADEON_CP_VC_FRMT_ST1;
if (VB->TexCoordPtr[1]->size == 4) {
req |= RADEON_CP_VC_FRMT_Q1;
vtx |= RADEON_TCL_VTX_Q1;
}
}
if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
RADEON_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
}
for (i = 0 ; i < RADEON_TCL_MAX_SETUP ; i++)
if ((setup_tab[i].vertex_format & req) == req)
break;
if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format &&
rmesa->tcl.indexed_verts.buf)
return;
if (rmesa->tcl.indexed_verts.buf)
radeonReleaseArrays( ctx, ~0 );
radeonAllocDmaRegionVerts( rmesa,
&rmesa->tcl.indexed_verts,
VB->Count,
setup_tab[i].vertex_size * 4,
4);
setup_tab[i].emit( ctx, 0, VB->Count,
rmesa->tcl.indexed_verts.address +
rmesa->tcl.indexed_verts.start );
rmesa->tcl.vertex_format = setup_tab[i].vertex_format;
rmesa->tcl.indexed_verts.aos_start = GET_START( &rmesa->tcl.indexed_verts );
rmesa->tcl.indexed_verts.aos_size = setup_tab[i].vertex_size;
rmesa->tcl.indexed_verts.aos_stride = setup_tab[i].vertex_size;
rmesa->tcl.aos_components[0] = &rmesa->tcl.indexed_verts;
rmesa->tcl.nr_aos_components = 1;
}
void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
if (RADEON_DEBUG & DEBUG_VERTS)
_tnl_print_vert_flags( __FUNCTION__, newinputs );
if (newinputs)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ );
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,982 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc, Cedar Park, TX.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_sanity.h"
#include <errno.h>
/* Set this '1' to get more verbiage.
*/
#define MORE_VERBOSE 1
#if MORE_VERBOSE
#define VERBOSE (RADEON_DEBUG & DEBUG_VERBOSE)
#define NORMAL (1)
#else
#define VERBOSE 0
#define NORMAL (RADEON_DEBUG & DEBUG_VERBOSE)
#endif
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
* 1.3 cmdbuffers allow all previous state to be updated as well as
* the tcl scalar and vector areas.
*/
static struct {
int start;
int len;
const char *name;
} packet[RADEON_MAX_STATE_PACKETS] = {
{ RADEON_PP_MISC,7,"RADEON_PP_MISC" },
{ RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
{ RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
{ RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
{ RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
{ RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
{ RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
{ RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
{ RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
{ RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
{ RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
{ RADEON_RE_MISC,1,"RADEON_RE_MISC" },
{ RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
{ RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
{ RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
{ RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
{ RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
{ RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
{ RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
{ RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
};
struct reg_names {
int idx;
const char *name;
};
static struct reg_names reg_names[] = {
{ RADEON_PP_MISC, "RADEON_PP_MISC" },
{ RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" },
{ RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" },
{ RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" },
{ RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" },
{ RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" },
{ RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" },
{ RADEON_PP_CNTL, "RADEON_PP_CNTL" },
{ RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" },
{ RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" },
{ RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" },
{ RADEON_SE_CNTL, "RADEON_SE_CNTL" },
{ RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" },
{ RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" },
{ RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" },
{ RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" },
{ RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" },
{ RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" },
{ RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" },
{ RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" },
{ RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" },
{ RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" },
{ RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" },
{ RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" },
{ RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" },
{ RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" },
{ RADEON_RE_MISC, "RADEON_RE_MISC" },
{ RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" },
{ RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" },
{ RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" },
{ RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" },
{ RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" },
{ RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_3" },
{ RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" },
{ RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" },
{ RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_3" },
{ RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" },
{ RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" },
{ RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_3" },
{ RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" },
{ RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" },
{ RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_3" },
{ RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" },
{ RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" },
{ RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_3" },
{ RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" },
{ RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" },
{ RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_3" },
{ RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" },
{ RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" },
{ RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" },
{ RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" },
{ RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" },
{ RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" },
{ RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" },
{ RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" },
{ RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" },
{ RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" },
{ RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" },
{ RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" },
{ RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" },
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" },
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" },
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" },
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" },
{ RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" },
{ RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" },
{ RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" },
{ RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" },
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" },
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" },
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" },
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" },
{ RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" },
{ RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" },
{ RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" },
{ RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" },
{ RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" },
{ RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" }
};
static struct reg_names scalar_names[] = {
{ RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" },
{ RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" },
{ RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" },
{ RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" },
{ RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" },
{ RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" },
{ RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" },
{ RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" },
{ RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" },
{ RADEON_SS_SHININESS, "SHININESS" },
{ 1000, "" },
};
/* Puff these out to make them look like normal (dword) registers.
*/
static struct reg_names vector_names[] = {
{ RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" },
{ RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" },
{ RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" },
{ RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" },
{ RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" },
{ RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" },
{ RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" },
{ RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" },
{ RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" },
{ RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" },
{ RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" },
{ RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" },
{ RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" },
{ RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" },
{ RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" },
{ RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" },
{ RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" },
{ RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" },
{ RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" },
{ RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" },
{ RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" },
{ RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" },
{ RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" },
{ RADEON_VS_UCP_ADDR * 4, "UCP" },
{ RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" },
{ RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" },
{ RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" },
{ 1000, "" },
};
union fi { float f; int i; };
#define ISVEC 1
#define ISFLOAT 2
#define TOUCHED 4
struct reg {
int idx;
struct reg_names *closest;
int flags;
union fi current;
union fi *values;
int nvalues;
int nalloc;
float vmin, vmax;
};
static struct reg regs[Elements(reg_names)+1];
static struct reg scalars[512+1];
static struct reg vectors[512*4+1];
static int total, total_changed, bufs;
static void init_regs( void )
{
struct reg_names *tmp;
int i;
for (i = 0 ; i < Elements(regs) ; i++) {
regs[i].idx = reg_names[i].idx;
regs[i].closest = &reg_names[i];
regs[i].flags = 0;
}
for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) {
if (tmp[1].idx == i) tmp++;
scalars[i].idx = i;
scalars[i].closest = tmp;
scalars[i].flags = ISFLOAT;
}
for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) {
if (tmp[1].idx*4 == i) tmp++;
vectors[i].idx = i;
vectors[i].closest = tmp;
vectors[i].flags = ISFLOAT|ISVEC;
}
regs[Elements(regs)-1].idx = -1;
scalars[Elements(scalars)-1].idx = -1;
vectors[Elements(vectors)-1].idx = -1;
}
static int find_or_add_value( struct reg *reg, int val )
{
int j;
for ( j = 0 ; j < reg->nvalues ; j++)
if ( val == reg->values[j].i )
return 1;
if (j == reg->nalloc) {
reg->nalloc += 5;
reg->nalloc *= 2;
reg->values = (union fi *) realloc( reg->values,
reg->nalloc * sizeof(union fi) );
}
reg->values[reg->nvalues++].i = val;
return 0;
}
static struct reg *lookup_reg( struct reg *tab, int reg )
{
int i;
for (i = 0 ; tab[i].idx != -1 ; i++) {
if (tab[i].idx == reg)
return &tab[i];
}
fprintf(stderr, "*** unknown reg 0x%x\n", reg);
return 0;
}
static const char *get_reg_name( struct reg *reg )
{
static char tmp[80];
if (reg->idx == reg->closest->idx)
return reg->closest->name;
if (reg->flags & ISVEC) {
if (reg->idx/4 != reg->closest->idx)
sprintf(tmp, "%s+%d[%d]",
reg->closest->name,
(reg->idx/4) - reg->closest->idx,
reg->idx%4);
else
sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4);
}
else {
if (reg->idx != reg->closest->idx)
sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx);
else
sprintf(tmp, "%s", reg->closest->name);
}
return tmp;
}
static int print_int_reg_assignment( struct reg *reg, int data )
{
int changed = (reg->current.i != data);
int ever_seen = find_or_add_value( reg, data );
if (VERBOSE || (NORMAL && (changed || !ever_seen)))
fprintf(stderr, " %s <-- 0x%x", get_reg_name(reg), data);
if (NORMAL) {
if (!ever_seen)
fprintf(stderr, " *** BRAND NEW VALUE");
else if (changed)
fprintf(stderr, " *** CHANGED");
}
reg->current.i = data;
if (VERBOSE || (NORMAL && (changed || !ever_seen)))
fprintf(stderr, "\n");
return changed;
}
static int print_float_reg_assignment( struct reg *reg, float data )
{
int changed = (reg->current.f != data);
int newmin = (data < reg->vmin);
int newmax = (data > reg->vmax);
if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
fprintf(stderr, " %s <-- %.3f", get_reg_name(reg), data);
if (NORMAL) {
if (newmin) {
fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin);
reg->vmin = data;
}
else if (newmax) {
fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax);
reg->vmax = data;
}
else if (changed) {
fprintf(stderr, " *** CHANGED");
}
}
reg->current.f = data;
if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
fprintf(stderr, "\n");
return changed;
}
static int print_reg_assignment( struct reg *reg, int data )
{
reg->flags |= TOUCHED;
if (reg->flags & ISFLOAT)
return print_float_reg_assignment( reg, *(float *)&data );
else
return print_int_reg_assignment( reg, data );
}
static void print_reg( struct reg *reg )
{
if (reg->flags & TOUCHED) {
if (reg->flags & ISFLOAT) {
fprintf(stderr, " %s == %f\n", get_reg_name(reg), reg->current.f);
} else {
fprintf(stderr, " %s == 0x%x\n", get_reg_name(reg), reg->current.i);
}
}
}
static void dump_state( void )
{
int i;
for (i = 0 ; i < Elements(regs) ; i++)
print_reg( &regs[i] );
for (i = 0 ; i < Elements(scalars) ; i++)
print_reg( &scalars[i] );
for (i = 0 ; i < Elements(vectors) ; i++)
print_reg( &vectors[i] );
}
static int radeon_emit_packets(
drmRadeonCmdHeader header,
drmRadeonCmdBuffer *cmdbuf )
{
int id = (int)header.packet.packet_id;
int sz = packet[id].len;
int *data = (int *)cmdbuf->buf;
int i;
if (sz * sizeof(int) > cmdbuf->bufsz) {
fprintf(stderr, "Packet overflows cmdbuf\n");
return -EINVAL;
}
if (!packet[id].name) {
fprintf(stderr, "*** Unknown packet 0 nr %d\n", id );
return -EINVAL;
}
if (VERBOSE)
fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz );
for ( i = 0 ; i < sz ; i++) {
struct reg *reg = lookup_reg( regs, packet[id].start + i*4 );
if (print_reg_assignment( reg, data[i] ))
total_changed++;
total++;
}
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
return 0;
}
static int radeon_emit_scalars(
drmRadeonCmdHeader header,
drmRadeonCmdBuffer *cmdbuf )
{
int sz = header.scalars.count;
int *data = (int *)cmdbuf->buf;
int start = header.scalars.offset;
int stride = header.scalars.stride;
int i;
if (VERBOSE)
fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n",
start, stride, sz, start + stride * sz);
for (i = 0 ; i < sz ; i++, start += stride) {
struct reg *reg = lookup_reg( scalars, start );
if (print_reg_assignment( reg, data[i] ))
total_changed++;
total++;
}
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
return 0;
}
static int radeon_emit_scalars2(
drmRadeonCmdHeader header,
drmRadeonCmdBuffer *cmdbuf )
{
int sz = header.scalars.count;
int *data = (int *)cmdbuf->buf;
int start = header.scalars.offset + 0x100;
int stride = header.scalars.stride;
int i;
if (VERBOSE)
fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n",
start, stride, sz, start + stride * sz);
if (start + stride * sz > 257) {
fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz);
return -1;
}
for (i = 0 ; i < sz ; i++, start += stride) {
struct reg *reg = lookup_reg( scalars, start );
if (print_reg_assignment( reg, data[i] ))
total_changed++;
total++;
}
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
return 0;
}
/* Check: inf/nan/extreme-size?
* Check: table start, end, nr, etc.
*/
static int radeon_emit_vectors(
drmRadeonCmdHeader header,
drmRadeonCmdBuffer *cmdbuf )
{
int sz = header.vectors.count;
int *data = (int *)cmdbuf->buf;
int start = header.vectors.offset;
int stride = header.vectors.stride;
int i,j;
if (VERBOSE)
fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n",
start, stride, sz, start + stride * sz, header.i);
/* if (start + stride * (sz/4) > 128) { */
/* fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */
/* return -1; */
/* } */
for (i = 0 ; i < sz ; start += stride) {
int changed = 0;
for (j = 0 ; j < 4 ; i++,j++) {
struct reg *reg = lookup_reg( vectors, start*4+j );
if (print_reg_assignment( reg, data[i] ))
changed = 1;
}
if (changed)
total_changed += 4;
total += 4;
}
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
return 0;
}
static int print_vertex_format( int vfmt )
{
if (NORMAL) {
fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
"vertex format",
vfmt,
"xy,",
(vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "",
(vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "",
(vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "",
(vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "",
(vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "",
(vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "",
(vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "",
(vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "",
(vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "",
(vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "",
(vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "",
(vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "",
(vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "",
(vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "",
(vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "",
(vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "",
(vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "",
(vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "",
(vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "",
(vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "",
(vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : "");
/* if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */
/* fprintf(stderr, " *** NEW VALUE"); */
fprintf(stderr, "\n");
}
return 0;
}
static char *primname[0xf] = {
"NONE",
"POINT",
"LINE",
"LINE_STRIP",
"TRI_LIST",
"TRI_FAN",
"TRI_STRIP",
"TRI_TYPE_2",
"RECT_LIST",
"3VRT_POINT_LIST",
"3VRT_LINE_LIST",
};
static int print_prim_and_flags( int prim )
{
int numverts;
if (NORMAL)
fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s\n",
"prim flags",
prim,
((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "",
((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "",
((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "",
(prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ",
(prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "",
(prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "",
(prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : "");
if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) {
fprintf(stderr, " *** Bad primitive: %x\n", prim & 0xf);
return -1;
}
numverts = prim>>16;
if (NORMAL)
fprintf(stderr, " prim: %s numverts %d\n", primname[prim&0xf], numverts);
switch (prim & 0xf) {
case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
if (numverts < 1) {
fprintf(stderr, "Bad nr verts for line %d\n", numverts);
return -1;
}
break;
case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
if ((numverts & 1) || numverts == 0) {
fprintf(stderr, "Bad nr verts for line %d\n", numverts);
return -1;
}
break;
case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
if (numverts < 2) {
fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts);
return -1;
}
break;
case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
if (numverts % 3 || numverts == 0) {
fprintf(stderr, "Bad nr verts for tri %d\n", numverts);
return -1;
}
break;
case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
if (numverts < 3) {
fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts);
return -1;
}
break;
default:
fprintf(stderr, "Bad primitive\n");
return -1;
}
return 0;
}
/* build in knowledge about each packet type
*/
static int radeon_emit_packet3( drmRadeonCmdBuffer *cmdbuf )
{
int cmdsz;
int *cmd = (int *)cmdbuf->buf;
int *tmp;
int i, stride, size, start;
cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 ||
cmdsz * 4 > cmdbuf->bufsz ||
cmdsz > RADEON_CP_PACKET_MAX_DWORDS) {
fprintf(stderr, "Bad packet\n");
return -EINVAL;
}
switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) {
case RADEON_CP_PACKET3_NOP:
if (NORMAL)
fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_NEXT_CHAR:
if (NORMAL)
fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_PLY_NEXTSCAN:
if (NORMAL)
fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_SET_SCISSORS:
if (NORMAL)
fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM:
if (NORMAL)
fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n",
cmdsz);
break;
case RADEON_CP_PACKET3_LOAD_MICROCODE:
if (NORMAL)
fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_WAIT_FOR_IDLE:
if (NORMAL)
fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_3D_DRAW_VBUF:
if (NORMAL)
fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz);
print_vertex_format(cmd[1]);
print_prim_and_flags(cmd[2]);
break;
case RADEON_CP_PACKET3_3D_DRAW_IMMD:
if (NORMAL)
fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_3D_DRAW_INDX: {
int neltdwords;
if (NORMAL)
fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz);
print_vertex_format(cmd[1]);
print_prim_and_flags(cmd[2]);
neltdwords = cmd[2]>>16;
neltdwords += neltdwords & 1;
neltdwords /= 2;
if (neltdwords + 3 != cmdsz)
fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n",
neltdwords, cmdsz);
break;
}
case RADEON_CP_PACKET3_LOAD_PALETTE:
if (NORMAL)
fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_3D_LOAD_VBPNTR:
if (NORMAL) {
fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz);
fprintf(stderr, " nr arrays: %d\n", cmd[1]);
}
if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) {
fprintf(stderr, " ****** MISMATCH %d/%d *******\n",
cmd[1]/2 + cmd[1]%2 + 3, cmdsz);
return -EINVAL;
}
if (NORMAL) {
tmp = cmd+2;
for (i = 0 ; i < cmd[1] ; i++) {
if (i & 1) {
stride = (tmp[0]>>24) & 0xff;
size = (tmp[0]>>16) & 0xff;
start = tmp[2];
tmp += 3;
}
else {
stride = (tmp[0]>>8) & 0xff;
size = (tmp[0]) & 0xff;
start = tmp[1];
}
fprintf(stderr, " array %d: start 0x%x vsize %d vstride %d\n",
i, start, size, stride );
}
}
break;
case RADEON_CP_PACKET3_CNTL_PAINT:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_BITBLT:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_SMALLTEXT:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n",
cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_POLYLINE:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_POLYSCANLINES:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n",
cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_PAINT_MULTI:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n",
cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n",
cmdsz);
break;
case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT:
if (NORMAL)
fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n",
cmdsz);
break;
default:
fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz);
break;
}
cmdbuf->buf += cmdsz * 4;
cmdbuf->bufsz -= cmdsz * 4;
return 0;
}
/* Check cliprects for bounds, then pass on to above:
*/
static int radeon_emit_packet3_cliprect( drmRadeonCmdBuffer *cmdbuf )
{
XF86DRIClipRectRec *boxes = (XF86DRIClipRectRec *)cmdbuf->boxes;
int i = 0;
if (VERBOSE && total_changed) {
dump_state();
total_changed = 0;
}
else fprintf(stderr, "total_changed zero\n");
if (NORMAL) {
do {
if ( i < cmdbuf->nbox ) {
fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n",
i, cmdbuf->nbox,
boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
}
} while ( ++i < cmdbuf->nbox );
}
if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;
return radeon_emit_packet3( cmdbuf );
}
int radeonSanityCmdBuffer( radeonContextPtr rmesa,
int nbox,
XF86DRIClipRectRec *boxes )
{
int idx;
drmRadeonCmdBuffer cmdbuf;
drmRadeonCmdHeader header;
static int inited = 0;
if (!inited) {
init_regs();
inited = 1;
}
cmdbuf.buf = rmesa->store.cmd_buf;
cmdbuf.bufsz = rmesa->store.cmd_used;
cmdbuf.boxes = (drmClipRect *)boxes;
cmdbuf.nbox = nbox;
while ( cmdbuf.bufsz >= sizeof(header) ) {
header.i = *(int *)cmdbuf.buf;
cmdbuf.buf += sizeof(header);
cmdbuf.bufsz -= sizeof(header);
switch (header.header.cmd_type) {
case RADEON_CMD_PACKET:
if (radeon_emit_packets( header, &cmdbuf )) {
fprintf(stderr,"radeon_emit_packets failed\n");
return -EINVAL;
}
break;
case RADEON_CMD_SCALARS:
if (radeon_emit_scalars( header, &cmdbuf )) {
fprintf(stderr,"radeon_emit_scalars failed\n");
return -EINVAL;
}
break;
case RADEON_CMD_SCALARS2:
if (radeon_emit_scalars2( header, &cmdbuf )) {
fprintf(stderr,"radeon_emit_scalars failed\n");
return -EINVAL;
}
break;
case RADEON_CMD_VECTORS:
if (radeon_emit_vectors( header, &cmdbuf )) {
fprintf(stderr,"radeon_emit_vectors failed\n");
return -EINVAL;
}
break;
case RADEON_CMD_DMA_DISCARD:
idx = header.dma.buf_idx;
if (NORMAL)
fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx);
bufs++;
break;
case RADEON_CMD_PACKET3:
if (radeon_emit_packet3( &cmdbuf )) {
fprintf(stderr,"radeon_emit_packet3 failed\n");
return -EINVAL;
}
break;
case RADEON_CMD_PACKET3_CLIP:
if (radeon_emit_packet3_cliprect( &cmdbuf )) {
fprintf(stderr,"radeon_emit_packet3_clip failed\n");
return -EINVAL;
}
break;
case RADEON_CMD_WAIT:
break;
default:
fprintf(stderr,"bad cmd_type %d at %p\n",
header.header.cmd_type,
cmdbuf.buf - sizeof(header));
return -EINVAL;
}
}
if (0)
{
static int n = 0;
n++;
if (n == 10) {
fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n",
bufs,
total, total_changed,
((float)total_changed/(float)total*100.0));
fprintf(stderr, "Total emitted per buf: %.2f\n",
(float)total/(float)bufs);
fprintf(stderr, "Real changes per buf: %.2f\n",
(float)total_changed/(float)bufs);
bufs = n = total = total_changed = 0;
}
}
return 0;
}

View file

@ -0,0 +1,8 @@
#ifndef RADEON_SANITY_H
#define RADEON_SANITY_H
extern int radeonSanityCmdBuffer( radeonContextPtr rmesa,
int nbox,
XF86DRIClipRectRec *boxes );
#endif

View file

@ -0,0 +1,237 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v 1.4 2002/04/24 16:20:41 martin Exp $ */
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario,
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, 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
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
* THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Kevin E. Martin <martin@xfree86.org>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef _RADEON_SAREA_H_
#define _RADEON_SAREA_H_
/* WARNING: If you change any of these defines, make sure to change the
* defines in the kernel file (radeon_drm.h)
*/
#ifndef __RADEON_SAREA_DEFINES__
#define __RADEON_SAREA_DEFINES__
/* What needs to be changed for the current vertex buffer? */
#define RADEON_UPLOAD_CONTEXT 0x00000001
#define RADEON_UPLOAD_VERTFMT 0x00000002
#define RADEON_UPLOAD_LINE 0x00000004
#define RADEON_UPLOAD_BUMPMAP 0x00000008
#define RADEON_UPLOAD_MASKS 0x00000010
#define RADEON_UPLOAD_VIEWPORT 0x00000020
#define RADEON_UPLOAD_SETUP 0x00000040
#define RADEON_UPLOAD_TCL 0x00000080
#define RADEON_UPLOAD_MISC 0x00000100
#define RADEON_UPLOAD_TEX0 0x00000200
#define RADEON_UPLOAD_TEX1 0x00000400
#define RADEON_UPLOAD_TEX2 0x00000800
#define RADEON_UPLOAD_TEX0IMAGES 0x00001000
#define RADEON_UPLOAD_TEX1IMAGES 0x00002000
#define RADEON_UPLOAD_TEX2IMAGES 0x00004000
#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
#define RADEON_REQUIRE_QUIESCENCE 0x00010000
#define RADEON_UPLOAD_ZBIAS 0x00020000
#define RADEON_UPLOAD_ALL 0x0002ffff
#define RADEON_UPLOAD_CONTEXT_ALL 0x000201ff
#define RADEON_FRONT 0x1
#define RADEON_BACK 0x2
#define RADEON_DEPTH 0x4
#define RADEON_STENCIL 0x8
/* Primitive types */
#define RADEON_POINTS 0x1
#define RADEON_LINES 0x2
#define RADEON_LINE_STRIP 0x3
#define RADEON_TRIANGLES 0x4
#define RADEON_TRIANGLE_FAN 0x5
#define RADEON_TRIANGLE_STRIP 0x6
#define RADEON_3VTX_POINTS 0x9
#define RADEON_3VTX_LINES 0xa
/* Vertex/indirect buffer size */
#define RADEON_BUFFER_SIZE 65536
/* Byte offsets for indirect buffer data */
#define RADEON_INDEX_PRIM_OFFSET 20
#define RADEON_HOSTDATA_BLIT_OFFSET 32
#define RADEON_SCRATCH_REG_OFFSET 32
/* Keep these small for testing */
#define RADEON_NR_SAREA_CLIPRECTS 12
/* There are 2 heaps (local/AGP). Each region within a heap is a
* minimum of 64k, and there are at most 64 of them per heap.
*/
#define RADEON_CARD_HEAP 0
#define RADEON_AGP_HEAP 1
#define RADEON_NR_TEX_HEAPS 2
#define RADEON_NR_TEX_REGIONS 64
#define RADEON_LOG_TEX_GRANULARITY 16
#define RADEON_MAX_TEXTURE_LEVELS 12
#define RADEON_MAX_TEXTURE_UNITS 3
/* Blits have strict offset rules. All blit offset must be aligned on
* a 1K-byte boundary.
*/
#define RADEON_OFFSET_SHIFT 10
#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT)
#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1)
#endif /* __RADEON_SAREA_DEFINES__ */
typedef struct {
unsigned int red;
unsigned int green;
unsigned int blue;
unsigned int alpha;
} radeon_color_regs_t;
typedef struct {
/* Context state */
unsigned int pp_misc;
unsigned int pp_fog_color;
unsigned int re_solid_color;
unsigned int rb3d_blendcntl;
unsigned int rb3d_depthoffset;
unsigned int rb3d_depthpitch;
unsigned int rb3d_zstencilcntl;
unsigned int pp_cntl;
unsigned int rb3d_cntl;
unsigned int rb3d_coloroffset;
unsigned int re_width_height;
unsigned int rb3d_colorpitch;
unsigned int se_cntl;
/* Vertex format state */
unsigned int se_coord_fmt;
/* Line state */
unsigned int re_line_pattern;
unsigned int re_line_state;
unsigned int se_line_width;
/* Bumpmap state */
unsigned int pp_lum_matrix;
unsigned int pp_rot_matrix_0;
unsigned int pp_rot_matrix_1;
/* Mask state */
unsigned int rb3d_stencilrefmask;
unsigned int rb3d_ropcntl;
unsigned int rb3d_planemask;
/* Viewport state */
unsigned int se_vport_xscale;
unsigned int se_vport_xoffset;
unsigned int se_vport_yscale;
unsigned int se_vport_yoffset;
unsigned int se_vport_zscale;
unsigned int se_vport_zoffset;
/* Setup state */
unsigned int se_cntl_status;
/* Misc state */
unsigned int re_top_left;
unsigned int re_misc;
} radeon_context_regs_t;
/* Setup registers for each texture unit */
typedef struct {
unsigned int pp_txfilter;
unsigned int pp_txformat;
unsigned int pp_txoffset;
unsigned int pp_txcblend;
unsigned int pp_txablend;
unsigned int pp_tfactor;
unsigned int pp_border_color;
} radeon_texture_regs_t;
typedef struct {
unsigned char next, prev; /* indices to form a circular LRU */
unsigned char in_use; /* owned by a client, or free? */
int age; /* tracked by clients to update local LRU's */
} radeon_tex_region_t;
typedef struct {
/* The channel for communication of state information to the kernel
* on firing a vertex buffer.
*/
radeon_context_regs_t ContextState;
radeon_texture_regs_t TexState[RADEON_MAX_TEXTURE_UNITS];
unsigned int dirty;
unsigned int vertsize;
unsigned int vc_format;
/* The current cliprects, or a subset thereof */
XF86DRIClipRectRec boxes[RADEON_NR_SAREA_CLIPRECTS];
unsigned int nbox;
/* Counters for throttling of rendering clients */
unsigned int last_frame;
unsigned int last_dispatch;
unsigned int last_clear;
/* Maintain an LRU of contiguous regions of texture space. If you
* think you own a region of texture memory, and it has an age
* different to the one you set, then you are mistaken and it has
* been stolen by another client. If global texAge hasn't changed,
* there is no need to walk the list.
*
* These regions can be used as a proxy for the fine-grained texture
* information of other clients - by maintaining them in the same
* lru which is used to age their own textures, clients have an
* approximate lru for the whole of global texture space, and can
* make informed decisions as to which areas to kick out. There is
* no need to choose whether to kick out your own texture or someone
* else's - simply eject them all in LRU order.
*/
/* Last elt is sentinal */
radeon_tex_region_t texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
/* last time texture was uploaded */
int texAge[RADEON_NR_TEX_HEAPS];
int ctxOwner; /* last context to upload state */
int pfAllowPageFlip; /* set by the 2d driver, read by the client */
int pfCurrentPage; /* set by kernel, read by others */
int crtc2_base; /* for pageflipping with CloneMode */
} RADEONSAREAPriv, *RADEONSAREAPrivPtr;
#endif

View file

@ -0,0 +1,268 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c,v 1.4 2002/02/22 21:45:00 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "radeon_screen.h"
#if 1
/* Including xf86PciInfo.h introduces a bunch of errors...
*/
#define PCI_CHIP_RADEON_QD 0x5144
#define PCI_CHIP_RADEON_QE 0x5145
#define PCI_CHIP_RADEON_QF 0x5146
#define PCI_CHIP_RADEON_QG 0x5147
#define PCI_CHIP_RADEON_QY 0x5159
#define PCI_CHIP_RADEON_QZ 0x515A
#define PCI_CHIP_RADEON_LW 0x4C57 /* mobility 7 - has tcl */
#define PCI_CHIP_RADEON_LY 0x4C59
#define PCI_CHIP_RADEON_LZ 0x4C5A
#define PCI_CHIP_RV200_QW 0x5157 /* a confusing name for a radeon */
#endif
/* Create the device specific screen private data struct.
*/
radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
{
radeonScreenPtr radeonScreen;
RADEONDRIPtr radeonDRIPriv = (RADEONDRIPtr)sPriv->pDevPriv;
/* Check the DRI extension version */
if ( sPriv->driMajor != 4 || sPriv->driMinor < 0 ) {
__driUtilMessage( "Radeon DRI driver expected DRI version 4.0.x "
"but got version %d.%d.%d",
sPriv->driMajor, sPriv->driMinor, sPriv->driPatch );
return NULL;
}
/* Check that the DDX driver version is compatible */
if ( sPriv->ddxMajor != 4 ||
sPriv->ddxMinor < 0 ) {
__driUtilMessage( "Radeon DRI driver expected DDX driver version 4.0.x "
"but got version %d.%d.%d",
sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch );
return NULL;
}
/* Check that the DRM driver version is compatible */
if ( sPriv->drmMajor != 1 ) {
__driUtilMessage( "Radeon DRI driver expected DRM driver version 1.x.x "
"but got version %d.%d.%d",
sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch );
return NULL;
}
/* Allocate the private area */
radeonScreen = (radeonScreenPtr) CALLOC( sizeof(*radeonScreen) );
if ( !radeonScreen ) {
__driUtilMessage("%s: CALLOC radeonScreen struct failed",
__FUNCTION__);
return NULL;
}
if ( sPriv->drmMinor < 3 ||
getenv("RADEON_COMPAT")) {
fprintf( stderr, "Radeon DRI driver:\n\t"
"Compatibility mode for DRM driver version %d.%d.%d\n\t"
"TCL will be disabled, expect reduced performance\n\t"
"(prefer DRM radeon.o 1.3.x or newer)\n\t",
sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch );
}
/* This is first since which regions we map depends on whether or
* not we are using a PCI card.
*/
radeonScreen->IsPCI = radeonDRIPriv->IsPCI;
if (sPriv->drmMinor >= 3) {
int ret;
drmRadeonGetParam gp;
gp.param = RADEON_PARAM_AGP_BUFFER_OFFSET;
gp.value = &radeonScreen->agp_buffer_offset;
ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret);
return NULL;
}
if (sPriv->drmMinor >= 6) {
gp.param = RADEON_PARAM_IRQ_NR;
gp.value = &radeonScreen->irq;
ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
return NULL;
}
}
}
radeonScreen->mmio.handle = radeonDRIPriv->registerHandle;
radeonScreen->mmio.size = radeonDRIPriv->registerSize;
if ( drmMap( sPriv->fd,
radeonScreen->mmio.handle,
radeonScreen->mmio.size,
&radeonScreen->mmio.map ) ) {
FREE( radeonScreen );
__driUtilMessage("radeonCreateScreen(): drmMap failed\n");
return NULL;
}
radeonScreen->status.handle = radeonDRIPriv->statusHandle;
radeonScreen->status.size = radeonDRIPriv->statusSize;
if ( drmMap( sPriv->fd,
radeonScreen->status.handle,
radeonScreen->status.size,
&radeonScreen->status.map ) ) {
drmUnmap( radeonScreen->mmio.map, radeonScreen->mmio.size );
FREE( radeonScreen );
__driUtilMessage("radeonCreateScreen(): drmMap (2) failed\n");
return NULL;
}
radeonScreen->scratch = (__volatile__ GLuint *)
((GLubyte *)radeonScreen->status.map + RADEON_SCRATCH_REG_OFFSET);
radeonScreen->buffers = drmMapBufs( sPriv->fd );
if ( !radeonScreen->buffers ) {
drmUnmap( radeonScreen->status.map, radeonScreen->status.size );
drmUnmap( radeonScreen->mmio.map, radeonScreen->mmio.size );
FREE( radeonScreen );
__driUtilMessage("radeonCreateScreen(): drmMapBufs failed\n");
return NULL;
}
if ( !radeonScreen->IsPCI ) {
radeonScreen->agpTextures.handle = radeonDRIPriv->agpTexHandle;
radeonScreen->agpTextures.size = radeonDRIPriv->agpTexMapSize;
if ( drmMap( sPriv->fd,
radeonScreen->agpTextures.handle,
radeonScreen->agpTextures.size,
(drmAddressPtr)&radeonScreen->agpTextures.map ) ) {
drmUnmapBufs( radeonScreen->buffers );
drmUnmap( radeonScreen->status.map, radeonScreen->status.size );
drmUnmap( radeonScreen->mmio.map, radeonScreen->mmio.size );
FREE( radeonScreen );
__driUtilMessage("radeonCreateScreen(): IsPCI failed\n");
return NULL;
}
}
radeonScreen->chipset = 0;
switch ( radeonDRIPriv->deviceID ) {
default:
fprintf(stderr, "unknown chip id, assuming full radeon support\n");
case PCI_CHIP_RADEON_QD:
case PCI_CHIP_RADEON_QE:
case PCI_CHIP_RADEON_QF:
case PCI_CHIP_RADEON_QG:
case PCI_CHIP_RV200_QW:
case PCI_CHIP_RADEON_LW:
radeonScreen->chipset |= RADEON_CHIPSET_TCL;
case PCI_CHIP_RADEON_QY:
case PCI_CHIP_RADEON_QZ:
case PCI_CHIP_RADEON_LY:
case PCI_CHIP_RADEON_LZ:
break;
}
radeonScreen->cpp = radeonDRIPriv->bpp / 8;
radeonScreen->AGPMode = radeonDRIPriv->AGPMode;
radeonScreen->frontOffset = radeonDRIPriv->frontOffset;
radeonScreen->frontPitch = radeonDRIPriv->frontPitch;
radeonScreen->backOffset = radeonDRIPriv->backOffset;
radeonScreen->backPitch = radeonDRIPriv->backPitch;
radeonScreen->depthOffset = radeonDRIPriv->depthOffset;
radeonScreen->depthPitch = radeonDRIPriv->depthPitch;
radeonScreen->texOffset[RADEON_CARD_HEAP] = radeonDRIPriv->textureOffset;
radeonScreen->texSize[RADEON_CARD_HEAP] = radeonDRIPriv->textureSize;
radeonScreen->logTexGranularity[RADEON_CARD_HEAP] =
radeonDRIPriv->log2TexGran;
if ( radeonScreen->IsPCI ) {
radeonScreen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
radeonScreen->texOffset[RADEON_AGP_HEAP] = 0;
radeonScreen->texSize[RADEON_AGP_HEAP] = 0;
radeonScreen->logTexGranularity[RADEON_AGP_HEAP] = 0;
} else {
radeonScreen->numTexHeaps = RADEON_NR_TEX_HEAPS;
radeonScreen->texOffset[RADEON_AGP_HEAP] =
radeonDRIPriv->agpTexOffset + RADEON_AGP_TEX_OFFSET;
radeonScreen->texSize[RADEON_AGP_HEAP] = radeonDRIPriv->agpTexMapSize;
radeonScreen->logTexGranularity[RADEON_AGP_HEAP] =
radeonDRIPriv->log2AGPTexGran;
}
radeonScreen->driScreen = sPriv;
radeonScreen->sarea_priv_offset = radeonDRIPriv->sarea_priv_offset;
return radeonScreen;
}
/* Destroy the device specific screen private data struct.
*/
void radeonDestroyScreen( __DRIscreenPrivate *sPriv )
{
radeonScreenPtr radeonScreen = (radeonScreenPtr)sPriv->private;
if (!radeonScreen)
return;
if ( !radeonScreen->IsPCI ) {
drmUnmap( radeonScreen->agpTextures.map,
radeonScreen->agpTextures.size );
}
drmUnmapBufs( radeonScreen->buffers );
drmUnmap( radeonScreen->status.map, radeonScreen->status.size );
drmUnmap( radeonScreen->mmio.map, radeonScreen->mmio.size );
FREE( radeonScreen );
sPriv->private = NULL;
}

View file

@ -0,0 +1,101 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h,v 1.3 2002/02/22 21:45:01 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __RADEON_SCREEN_H__
#define __RADEON_SCREEN_H__
#ifdef GLX_DIRECT_RENDERING
/*
* IMPORTS: these headers contain all the DRI, X and kernel-related
* definitions that we need.
*/
#include "dri_util.h"
#include "radeon_common.h"
#include "radeon_dri.h"
#include "radeon_reg.h"
#include "radeon_sarea.h"
typedef struct {
drmHandle 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_CHIPSET_TCL (1 << 0)
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 frontOffset;
unsigned int frontPitch;
unsigned int backOffset;
unsigned int backPitch;
unsigned int depthOffset;
unsigned int depthPitch;
/* Shared texture data */
int numTexHeaps;
int texOffset[RADEON_NR_TEX_HEAPS];
int texSize[RADEON_NR_TEX_HEAPS];
int logTexGranularity[RADEON_NR_TEX_HEAPS];
radeonRegionRec mmio;
radeonRegionRec status;
radeonRegionRec agpTextures;
drmBufMapPtr buffers;
__volatile__ GLuint *scratch;
__DRIscreenPrivate *driScreen;
unsigned int sarea_priv_offset;
unsigned int agp_buffer_offset; /* offset in card memory space */
} radeonScreenRec, *radeonScreenPtr;
extern radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv );
extern void radeonDestroyScreen( __DRIscreenPrivate *sPriv );
#endif
#endif /* __RADEON_SCREEN_H__ */

View file

@ -0,0 +1,410 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.5 2002/02/22 21:45:01 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "swrast/swrast.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_span.h"
#include "radeon_tex.h"
#define DBG 0
#define LOCAL_VARS \
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
radeonScreenPtr radeonScreen = rmesa->radeonScreen; \
__DRIscreenPrivate *sPriv = rmesa->dri.screen; \
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(sPriv->pFB + \
rmesa->state.color.drawOffset + \
(dPriv->x * radeonScreen->cpp) + \
(dPriv->y * pitch)); \
char *read_buf = (char *)(sPriv->pFB + \
rmesa->state.pixel.readOffset + \
(dPriv->x * radeonScreen->cpp) + \
(dPriv->y * pitch)); \
GLuint p; \
(void) read_buf; (void) buf; (void) p
#define LOCAL_DEPTH_VARS \
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
radeonScreenPtr radeonScreen = rmesa->radeonScreen; \
__DRIscreenPrivate *sPriv = rmesa->dri.screen; \
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
GLuint height = dPriv->h; \
GLuint xo = dPriv->x; \
GLuint yo = dPriv->y; \
char *buf = (char *)(sPriv->pFB + radeonScreen->depthOffset); \
(void) buf
#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 = rmesa->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 ) \
*(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
(g << 8) | \
(r << 16) | \
(a << 24) )
#define WRITE_PIXEL( _x, _y, p ) \
*(GLuint *)(buf + _x*4 + _y*pitch) = p
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \
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 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.
*/
static __inline GLuint radeon_mba_z16( radeonContextPtr rmesa,
GLint x, GLint y )
{
radeonScreenPtr radeonScreen = rmesa->radeonScreen;
GLuint pitch = radeonScreen->frontPitch;
GLuint ba, address = 0; /* a[0] = 0 */
ba = (y / 16) * (pitch / 32) + (x / 32);
address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */
address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */
address |= (x & 0x8) << 4; /* a[7] = x[3] */
address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
address |= (y & 0x8) << 7; /* a[10] = y[3] */
address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */
address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
return address;
}
static GLuint radeon_mba_z32( radeonContextPtr rmesa,
GLint x, GLint y )
{
radeonScreenPtr radeonScreen = rmesa->radeonScreen;
GLuint pitch = radeonScreen->frontPitch;
GLuint ba, address = 0; /* a[0..1] = 0 */
ba = (y / 16) * (pitch / 16) + (x / 16);
address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */
address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */
address |=
(((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */
address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
address |= (y & 0x8) << 7; /* a[10] = y[3] */
address |=
(((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */
address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
return address;
}
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
*(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo )) = d;
#define READ_DEPTH( d, _x, _y ) \
d = *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo ));
#define TAG(x) radeon##x##_16
#include "depthtmp.h"
/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
do { \
GLuint offset = radeon_mba_z32( rmesa, _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( rmesa, _x + xo, \
_y + yo )) & 0x00ffffff;
#define TAG(x) radeon##x##_24_8
#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( rmesa, _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( rmesa, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
d = tmp >> 24; \
} while (0)
#define TAG(x) radeon##x##_24_8
#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 rmesa = RADEON_CONTEXT(ctx);
switch ( bufferBit ) {
case FRONT_LEFT_BIT:
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch;
rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
} else {
rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch;
rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
}
break;
case BACK_LEFT_BIT:
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch;
rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
} else {
rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch;
rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
}
break;
default:
assert(0);
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 rmesa = RADEON_CONTEXT( ctx );
RADEON_FIREVERTICES( rmesa );
LOCK_HARDWARE( rmesa );
radeonWaitForIdleLocked( rmesa );
}
static void radeonSpanRenderFinish( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
_swrast_flush( ctx );
UNLOCK_HARDWARE( rmesa );
}
void radeonInitSpanFuncs( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = radeonSetBuffer;
switch ( rmesa->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;
}
switch ( rmesa->glCtx->Visual.depthBits ) {
case 16:
swdd->ReadDepthSpan = radeonReadDepthSpan_16;
swdd->WriteDepthSpan = radeonWriteDepthSpan_16;
swdd->ReadDepthPixels = radeonReadDepthPixels_16;
swdd->WriteDepthPixels = radeonWriteDepthPixels_16;
break;
case 24:
swdd->ReadDepthSpan = radeonReadDepthSpan_24_8;
swdd->WriteDepthSpan = radeonWriteDepthSpan_24_8;
swdd->ReadDepthPixels = radeonReadDepthPixels_24_8;
swdd->WriteDepthPixels = radeonWriteDepthPixels_24_8;
swdd->ReadStencilSpan = radeonReadStencilSpan_24_8;
swdd->WriteStencilSpan = radeonWriteStencilSpan_24_8;
swdd->ReadStencilPixels = radeonReadStencilPixels_24_8;
swdd->WriteStencilPixels = radeonWriteStencilPixels_24_8;
break;
default:
break;
}
swdd->SpanRenderStart = radeonSpanRenderStart;
swdd->SpanRenderFinish = radeonSpanRenderFinish;
}

View file

@ -0,0 +1,45 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.h,v 1.2 2002/02/22 21:45:01 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __RADEON_SPAN_H__
#define __RADEON_SPAN_H__
#ifdef GLX_DIRECT_RENDERING
extern void radeonInitSpanFuncs( GLcontext *ctx );
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.h,v 1.3 2002/09/16 18:05:20 eich Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __RADEON_STATE_H__
#define __RADEON_STATE_H__
#ifdef GLX_DIRECT_RENDERING
#include "radeon_context.h"
extern void radeonInitState( radeonContextPtr rmesa );
extern void radeonInitStateFuncs( GLcontext *ctx );
extern void radeonUpdateMaterial( GLcontext *ctx );
extern void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode );
extern void radeonRecalcScissorRects( radeonContextPtr rmesa );
extern void radeonUpdateViewportOffset( GLcontext *ctx );
extern void radeonUpdateWindow( GLcontext *ctx );
extern void radeonValidateState( GLcontext *ctx );
extern void radeonPrintDirty( radeonContextPtr rmesa,
const char *msg );
extern void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) do { \
if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \
__FUNCTION__, bit, mode ); \
radeonFallback( rmesa->glCtx, bit, mode ); \
} while (0)
#define MODEL_PROJ 0
#define MODEL 1
#define MODEL_IT 2
#define TEXMAT_0 3
#define TEXMAT_1 4
#define TEXMAT_2 5
#endif
#endif

View file

@ -0,0 +1,558 @@
/* $XFree86$ */
/*
* Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mmath.h"
#include "api_arrayelt.h"
#include "swrast/swrast.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "swrast_setup/swrast_setup.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_tcl.h"
#include "radeon_tex.h"
#include "radeon_swtcl.h"
#include "radeon_vtxfmt.h"
/* =============================================================
* State initialization
*/
void radeonPrintDirty( radeonContextPtr rmesa, const char *msg )
{
struct radeon_state_atom *l;
fprintf(stderr, msg);
fprintf(stderr, ": ");
foreach(l, &(rmesa->hw.dirty)) {
fprintf(stderr, "%s, ", l->name);
}
fprintf(stderr, "\n");
}
static int cmdpkt( int id )
{
drmRadeonCmdHeader h;
h.i = 0;
h.packet.cmd_type = RADEON_CMD_PACKET;
h.packet.packet_id = id;
return h.i;
}
static int cmdvec( int offset, int stride, int count )
{
drmRadeonCmdHeader h;
h.i = 0;
h.vectors.cmd_type = RADEON_CMD_VECTORS;
h.vectors.offset = offset;
h.vectors.stride = stride;
h.vectors.count = count;
return h.i;
}
static int cmdscl( int offset, int stride, int count )
{
drmRadeonCmdHeader h;
h.i = 0;
h.scalars.cmd_type = RADEON_CMD_SCALARS;
h.scalars.offset = offset;
h.scalars.stride = stride;
h.scalars.count = count;
return h.i;
}
#define CHECK( NM, FLAG ) \
static GLboolean check_##NM( GLcontext *ctx ) \
{ \
return FLAG; \
}
#define TCL_CHECK( NM, FLAG ) \
static GLboolean check_##NM( GLcontext *ctx ) \
{ \
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
return !rmesa->TclFallback && (FLAG); \
}
CHECK( always, GL_TRUE )
CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled )
CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled )
CHECK( fog, ctx->Fog.Enabled )
TCL_CHECK( tcl, GL_TRUE )
TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled )
TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled )
TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled )
TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled )
TCL_CHECK( tcl_lit1, ctx->Light.Enabled && ctx->Light.Light[1].Enabled )
TCL_CHECK( tcl_lit2, ctx->Light.Enabled && ctx->Light.Light[2].Enabled )
TCL_CHECK( tcl_lit3, ctx->Light.Enabled && ctx->Light.Light[3].Enabled )
TCL_CHECK( tcl_lit4, ctx->Light.Enabled && ctx->Light.Light[4].Enabled )
TCL_CHECK( tcl_lit5, ctx->Light.Enabled && ctx->Light.Light[5].Enabled )
TCL_CHECK( tcl_lit6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled )
TCL_CHECK( tcl_lit7, ctx->Light.Enabled && ctx->Light.Light[7].Enabled )
TCL_CHECK( tcl_ucp0, (ctx->Transform.ClipPlanesEnabled & 0x1) )
TCL_CHECK( tcl_ucp1, (ctx->Transform.ClipPlanesEnabled & 0x2) )
TCL_CHECK( tcl_ucp2, (ctx->Transform.ClipPlanesEnabled & 0x4) )
TCL_CHECK( tcl_ucp3, (ctx->Transform.ClipPlanesEnabled & 0x8) )
TCL_CHECK( tcl_ucp4, (ctx->Transform.ClipPlanesEnabled & 0x10) )
TCL_CHECK( tcl_ucp5, (ctx->Transform.ClipPlanesEnabled & 0x20) )
TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled )
/* Initialize the context's hardware state.
*/
void radeonInitState( radeonContextPtr rmesa )
{
GLcontext *ctx = rmesa->glCtx;
GLuint color_fmt, depth_fmt, i;
switch ( rmesa->radeonScreen->cpp ) {
case 2:
color_fmt = RADEON_COLOR_FORMAT_RGB565;
break;
case 4:
color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
break;
default:
fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
exit( -1 );
}
rmesa->state.color.clear = 0x00000000;
switch ( ctx->Visual.depthBits ) {
case 16:
rmesa->state.depth.clear = 0x0000ffff;
rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff;
depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
rmesa->state.stencil.clear = 0x00000000;
break;
case 24:
rmesa->state.depth.clear = 0x00ffffff;
rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff;
depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
rmesa->state.stencil.clear = 0xff000000;
break;
default:
fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
ctx->Visual.depthBits );
exit( -1 );
}
/* Only have hw stencil when depth buffer is 24 bits deep */
rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 &&
ctx->Visual.depthBits == 24 );
rmesa->Fallback = 0;
if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
} else {
rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
}
rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset;
rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch;
/* Initialize lists:
*/
make_empty_list(&(rmesa->hw.dirty));
make_empty_list(&(rmesa->hw.clean));
#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG ) \
do { \
rmesa->hw.ATOM.cmd_size = SZ; \
rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \
rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \
rmesa->hw.ATOM.name = NM; \
rmesa->hw.ATOM.is_tcl = FLAG; \
rmesa->hw.ATOM.check = check_##CHK; \
insert_at_head(&(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \
} while (0)
/* Allocate state buffers:
*/
ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 );
ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 );
ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 );
ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 );
ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 );
ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 );
ALLOC_STATE( grd, always, GRD_STATE_SIZE, "GRD/guard-band", 1 );
ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 1 );
ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 1 );
ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 );
ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 );
ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 );
ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 );
ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
ALLOC_STATE( ucp[3], tcl_ucp3, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
ALLOC_STATE( ucp[4], tcl_ucp4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
ALLOC_STATE( ucp[5], tcl_ucp5, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
ALLOC_STATE( lit[0], tcl_lit0, LIT_STATE_SIZE, "LIT/light-0", 1 );
ALLOC_STATE( lit[1], tcl_lit1, LIT_STATE_SIZE, "LIT/light-1", 1 );
ALLOC_STATE( lit[2], tcl_lit2, LIT_STATE_SIZE, "LIT/light-2", 1 );
ALLOC_STATE( lit[3], tcl_lit3, LIT_STATE_SIZE, "LIT/light-3", 1 );
ALLOC_STATE( lit[4], tcl_lit4, LIT_STATE_SIZE, "LIT/light-4", 1 );
ALLOC_STATE( lit[5], tcl_lit5, LIT_STATE_SIZE, "LIT/light-5", 1 );
ALLOC_STATE( lit[6], tcl_lit6, LIT_STATE_SIZE, "LIT/light-6", 1 );
ALLOC_STATE( lit[7], tcl_lit7, LIT_STATE_SIZE, "LIT/light-7", 1 );
/* Fill in the packet headers:
*/
rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC);
rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL);
rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH);
rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN);
rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH);
rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK);
rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE);
rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL);
rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(RADEON_EMIT_SE_CNTL_STATUS);
rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC);
rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_0);
rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0);
rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1);
rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1);
rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
rmesa->hw.mtl.cmd[MTL_CMD_0] =
cmdpkt(RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED);
rmesa->hw.grd.cmd[GRD_CMD_0] =
cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 );
rmesa->hw.fog.cmd[FOG_CMD_0] =
cmdvec( RADEON_VS_FOG_PARAM_ADDR, 1, 4 );
rmesa->hw.glt.cmd[GLT_CMD_0] =
cmdvec( RADEON_VS_GLOBAL_AMBIENT_ADDR, 1, 4 );
rmesa->hw.eye.cmd[EYE_CMD_0] =
cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 );
for (i = 0 ; i < 5; i++) {
rmesa->hw.mat[i].cmd[MAT_CMD_0] =
cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16);
}
for (i = 0 ; i < 8; i++) {
rmesa->hw.lit[i].cmd[LIT_CMD_0] =
cmdvec( RADEON_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 );
rmesa->hw.lit[i].cmd[LIT_CMD_1] =
cmdscl( RADEON_SS_LIGHT_DCD_ADDR + i, 8, 6 );
}
for (i = 0 ; i < 6; i++) {
rmesa->hw.ucp[i].cmd[UCP_CMD_0] =
cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 );
}
rmesa->last_ReallyEnabled = -1;
/* Initial Harware state:
*/
rmesa->hw.ctx.cmd[CTX_PP_MISC] = (RADEON_ALPHA_TEST_PASS |
RADEON_CHROMA_FUNC_FAIL |
RADEON_CHROMA_KEY_NEAREST |
RADEON_SHADOW_FUNC_EQUAL |
RADEON_SHADOW_PASS_1 |
RADEON_RIGHT_HAND_CUBE_OGL);
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
RADEON_FOG_USE_DEPTH);
rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (RADEON_COMB_FCN_ADD_CLAMP |
RADEON_SRC_BLEND_GL_ONE |
RADEON_DST_BLEND_GL_ZERO );
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
rmesa->radeonScreen->depthOffset;
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
((rmesa->radeonScreen->depthPitch &
RADEON_DEPTHPITCH_MASK) |
RADEON_DEPTH_ENDIAN_NO_SWAP);
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt |
RADEON_Z_TEST_LESS |
RADEON_STENCIL_TEST_ALWAYS |
RADEON_STENCIL_FAIL_KEEP |
RADEON_STENCIL_ZPASS_KEEP |
RADEON_STENCIL_ZFAIL_KEEP |
RADEON_Z_WRITE_ENABLE);
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (RADEON_SCISSOR_ENABLE |
RADEON_ANTI_ALIAS_NONE);
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE |
color_fmt |
(1<<15));
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
RADEON_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
RADEON_COLORPITCH_MASK) |
RADEON_COLOR_ENDIAN_NO_SWAP);
rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW |
RADEON_BFACE_SOLID |
RADEON_FFACE_SOLID |
/* RADEON_BADVTX_CULL_DISABLE | */
RADEON_FLAT_SHADE_VTX_LAST |
RADEON_DIFFUSE_SHADE_GOURAUD |
RADEON_ALPHA_SHADE_GOURAUD |
RADEON_SPECULAR_SHADE_GOURAUD |
RADEON_FOG_SHADE_GOURAUD |
RADEON_VPORT_XY_XFORM_ENABLE |
RADEON_VPORT_Z_XFORM_ENABLE |
RADEON_VTX_PIX_CENTER_OGL |
RADEON_ROUND_MODE_TRUNC |
RADEON_ROUND_PREC_8TH_PIX);
rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] =
#ifdef MESA_BIG_ENDIAN
RADEON_VC_32BIT_SWAP;
#else
RADEON_VC_NO_SWAP;
#endif
if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS;
}
rmesa->hw.set.cmd[SET_SE_COORDFMT] = (
RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
RADEON_TEX1_W_ROUTING_USE_Q1);
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
((0x0000 & RADEON_LINE_PATTERN_MASK) |
(0 << RADEON_LINE_REPEAT_COUNT_SHIFT) |
(0 << RADEON_LINE_PATTERN_START_SHIFT) |
RADEON_LINE_PATTERN_LITTLE_BIT_ORDER);
rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] =
((0 << RADEON_LINE_CURRENT_PTR_SHIFT) |
(1 << RADEON_LINE_CURRENT_COUNT_SHIFT));
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4);
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] =
((0x00 << RADEON_STENCIL_REF_SHIFT) |
(0xff << RADEON_STENCIL_MASK_SHIFT) |
(0xff << RADEON_STENCIL_WRITEMASK_SHIFT));
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = RADEON_ROP_COPY;
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff;
rmesa->hw.msc.cmd[MSC_RE_MISC] =
((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) |
(0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) |
RADEON_STIPPLE_BIG_BIT_ORDER);
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000;
rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
rmesa->hw.tex[0].cmd[TEX_PP_TXFORMAT] =
(RADEON_TXFORMAT_ENDIAN_NO_SWAP |
RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
RADEON_TXFORMAT_ST_ROUTE_STQ0 |
(2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
(2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
rmesa->hw.tex[0].cmd[TEX_PP_TXOFFSET] = 0x2000;
rmesa->hw.tex[0].cmd[TEX_PP_BORDER_COLOR] = 0;
rmesa->hw.tex[0].cmd[TEX_PP_TXCBLEND] =
(RADEON_COLOR_ARG_A_ZERO |
RADEON_COLOR_ARG_B_ZERO |
RADEON_COLOR_ARG_C_CURRENT_COLOR |
RADEON_BLEND_CTL_ADD |
RADEON_SCALE_1X |
RADEON_CLAMP_TX);
rmesa->hw.tex[0].cmd[TEX_PP_TXABLEND] =
(RADEON_ALPHA_ARG_A_ZERO |
RADEON_ALPHA_ARG_B_ZERO |
RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
RADEON_BLEND_CTL_ADD |
RADEON_SCALE_1X |
RADEON_CLAMP_TX);
rmesa->hw.tex[0].cmd[TEX_PP_TFACTOR] = 0;
rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] =
(RADEON_TXFORMAT_ENDIAN_NO_SWAP |
RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
RADEON_TXFORMAT_ST_ROUTE_STQ1 |
(2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
(2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
rmesa->hw.tex[1].cmd[TEX_PP_TXOFFSET] = 0x8000;
rmesa->hw.tex[1].cmd[TEX_PP_BORDER_COLOR] = 0;
rmesa->hw.tex[1].cmd[TEX_PP_TXCBLEND] =
(RADEON_COLOR_ARG_A_ZERO |
RADEON_COLOR_ARG_B_ZERO |
RADEON_COLOR_ARG_C_CURRENT_COLOR |
RADEON_BLEND_CTL_ADD |
RADEON_SCALE_1X |
RADEON_CLAMP_TX);
rmesa->hw.tex[1].cmd[TEX_PP_TXABLEND] =
(RADEON_ALPHA_ARG_A_ZERO |
RADEON_ALPHA_ARG_B_ZERO |
RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
RADEON_BLEND_CTL_ADD |
RADEON_SCALE_1X |
RADEON_CLAMP_TX);
rmesa->hw.tex[1].cmd[TEX_PP_TFACTOR] = 0;
/* Can oly add ST1 at the time of doing some multitex but can keep
* it after that. Errors if DIFFUSE is missing.
*/
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] =
(RADEON_TCL_VTX_Z0 |
RADEON_TCL_VTX_W0 |
RADEON_TCL_VTX_PK_DIFFUSE
); /* need to keep this uptodate */
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] =
( RADEON_TCL_COMPUTE_XYZW |
(RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
(RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
(RADEON_TCL_TEX_INPUT_TEX_2 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
/* XXX */
rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_0] =
((MODEL << RADEON_MODELVIEW_0_SHIFT) |
(MODEL_IT << RADEON_IT_MODELVIEW_0_SHIFT));
rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] =
((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) |
(TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) |
(TEXMAT_1 << RADEON_TEXMAT_1_SHIFT));
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] =
(RADEON_UCP_IN_CLIP_SPACE |
RADEON_CULL_FRONT_IS_CCW);
rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = 0;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] =
(RADEON_SPECULAR_LIGHTS |
RADEON_DIFFUSE_SPECULAR_COMBINE |
RADEON_LOCAL_LIGHT_VEC_GL |
(RADEON_LM_SOURCE_STATE_PREMULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
(RADEON_LM_SOURCE_STATE_PREMULT << RADEON_AMBIENT_SOURCE_SHIFT) |
(RADEON_LM_SOURCE_STATE_PREMULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
(RADEON_LM_SOURCE_STATE_PREMULT << RADEON_SPECULAR_SOURCE_SHIFT));
for (i = 0 ; i < 8; i++) {
struct gl_light *l = &ctx->Light.Light[i];
GLenum p = GL_LIGHT0 + i;
*(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;
ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 );
ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 );
ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
&l->ConstantAttenuation );
ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION,
&l->LinearAttenuation );
ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION,
&l->QuadraticAttenuation );
}
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT,
ctx->Light.Model.Ambient );
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
for (i = 0 ; i < 6; i++) {
ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL );
}
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 );
/* Set up vector and scalar state commands:
*/
/* upload_matrix( rmesa, ctx->ModelView.m, MODEL ); */
/* upload_matrix_t( rmesa, ctx->ModelView.inv, MODEL_IT ); */
/* upload_matrix( rmesa, ctx->TextureMatrix[0].m, TEXMAT_0 ); */
/* upload_matrix( rmesa, ctx->TextureMatrix[1].m, TEXMAT_1 ); */
/* upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, TEXMAT_2 ); */
rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE;
rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE;
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE;
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE;
rmesa->hw.eye.cmd[EYE_X] = 0;
rmesa->hw.eye.cmd[EYE_Y] = 0;
rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#ifndef __RADEON_TRIS_H__
#define __RADEON_TRIS_H__
#include "mtypes.h"
#include "swrast/swrast.h"
#include "radeon_context.h"
extern void radeonInitSwtcl( GLcontext *ctx );
extern void radeonDestroySwtcl( GLcontext *ctx );
extern void radeonChooseRenderState( GLcontext *ctx );
extern void radeonChooseVertexState( GLcontext *ctx );
extern void radeonCheckTexSizes( GLcontext *ctx );
extern void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
GLuint newinputs );
extern void radeonPrintSetupFlags(char *msg, GLuint flags );
extern void radeon_emit_contiguous_verts( GLcontext *ctx,
GLuint start,
GLuint count );
extern void radeon_emit_indexed_verts( GLcontext *ctx,
GLuint start,
GLuint count );
extern void radeon_translate_vertex( GLcontext *ctx,
const radeonVertex *src,
SWvertex *dst );
extern void radeon_print_vertex( GLcontext *ctx, const radeonVertex *v );
extern void radeon_import_float_colors( GLcontext *ctx );
extern void radeon_import_float_spec_colors( GLcontext *ctx );
#endif

View file

@ -0,0 +1,546 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Austin, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "light.h"
#include "mmath.h"
#include "mtypes.h"
#include "enums.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "radeon_context.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_tex.h"
#include "radeon_tcl.h"
#include "radeon_swtcl.h"
#include "radeon_maos.h"
/*
* Render unclipped vertex buffers by emitting vertices directly to
* dma buffers. Use strip/fan hardware primitives where possible.
* Try to simulate missing primitives with indexed vertices.
*/
#define HAVE_POINTS 1
#define HAVE_LINES 1
#define HAVE_LINE_LOOP 0
#define HAVE_LINE_STRIPS 1
#define HAVE_TRIANGLES 1
#define HAVE_TRI_STRIPS 1
#define HAVE_TRI_STRIP_1 0
#define HAVE_TRI_FANS 1
#define HAVE_QUADS 0
#define HAVE_QUAD_STRIPS 0
#define HAVE_POLYGONS 1
#define HAVE_ELTS 1
#define HW_POINTS RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
#define HW_LINES RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
#define HW_LINE_LOOP 0
#define HW_LINE_STRIP RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
#define HW_TRIANGLES RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
#define HW_TRIANGLE_STRIP_0 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
#define HW_TRIANGLE_STRIP_1 0
#define HW_TRIANGLE_FAN RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
#define HW_QUADS 0
#define HW_QUAD_STRIP 0
#define HW_POLYGON RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
static GLboolean discreet_prim[0x10] = {
0, /* none */
1, /* points */
1, /* lines */
0, /* line_strip */
1, /* tri_list */
0, /* tri_fan */
0, /* tri_type_2 */
1, /* rect list (unused) */
1, /* 3 vert point */
1, /* 3 vert line */
0,
0,
0,
0,
0,
};
#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
#define ELTS_VARS GLushort *dest
#define ELT_INIT(prim, hw_prim) \
radeonTclPrimitive( ctx, prim, hw_prim | RADEON_CP_VC_CNTL_PRIM_WALK_IND )
#define GET_ELTS() rmesa->tcl.Elts
#define NEW_PRIMITIVE() RADEON_NEWPRIM( rmesa )
#define NEW_BUFFER() radeonRefillCurrentDmaRegion( rmesa )
/* Don't really know how many elts will fit in what's left of cmdbuf,
* as there is state to emit, etc:
*/
#if 0
#define GET_CURRENT_VB_MAX_ELTS() \
((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
#define GET_SUBSEQUENT_VB_MAX_ELTS() ((RADEON_CMD_BUF_SZ - 16) / 2)
#else
/* Testing on isosurf shows a maximum around here. Don't know if it's
* the card or driver or kernel module that is causing the behaviour.
*/
#define GET_CURRENT_VB_MAX_ELTS() 300
#define GET_SUBSEQUENT_VB_MAX_ELTS() 300
#endif
#define RESET_STIPPLE() do { \
RADEON_STATECHANGE( rmesa, lin ); \
radeonEmitState( rmesa ); \
} while (0)
#define AUTO_STIPPLE( mode ) do { \
RADEON_STATECHANGE( rmesa, lin ); \
if (mode) \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
RADEON_LINE_PATTERN_AUTO_RESET; \
else \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
~RADEON_LINE_PATTERN_AUTO_RESET; \
radeonEmitState( rmesa ); \
} while (0)
/* How do you extend an existing primitive?
*/
#define ALLOC_ELTS(nr) \
do { \
if (rmesa->dma.flush == radeonFlushElts && \
rmesa->store.cmd_used + nr*2 < RADEON_CMD_BUF_SZ) { \
\
dest = (GLushort *)(rmesa->store.cmd_buf + \
rmesa->store.cmd_used); \
rmesa->store.cmd_used += nr*2; \
} \
else { \
if (rmesa->dma.flush) \
rmesa->dma.flush( rmesa ); \
\
radeonEmitAOS( rmesa, \
rmesa->tcl.aos_components, \
rmesa->tcl.nr_aos_components, \
0 ); \
\
dest = radeonAllocEltsOpenEnded( rmesa, \
rmesa->tcl.vertex_format, \
rmesa->tcl.hw_primitive, \
nr ); \
} \
} while (0)
/* TODO: Try to extend existing primitive if both are identical,
* discreet and there are no intervening state changes. (Somewhat
* duplicates changes to DrawArrays code)
*/
static void EMIT_PRIM( GLcontext *ctx,
GLenum prim,
GLuint hwprim,
GLuint start,
GLuint count)
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
radeonTclPrimitive( ctx, prim, hwprim );
radeonEmitAOS( rmesa,
rmesa->tcl.aos_components,
rmesa->tcl.nr_aos_components,
start );
/* Why couldn't this packet have taken an offset param?
*/
radeonEmitVbufPrim( rmesa,
rmesa->tcl.vertex_format,
rmesa->tcl.hw_primitive,
count - start );
}
/* Try & join small primitives
*/
#if 0
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0
#else
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \
((NR) < 20 || \
((NR) < 40 && \
rmesa->tcl.hw_primitive == (PRIM| \
RADEON_CP_VC_CNTL_PRIM_WALK_IND| \
RADEON_CP_VC_CNTL_TCL_ENABLE)))
#endif
#ifdef MESA_BIG_ENDIAN
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
#define EMIT_ELT(offset, x) do { \
int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
(des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
#else
#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
#endif
#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
#define INCR_ELTS( nr ) dest += nr
#define RELEASE_ELT_VERTS() \
radeonReleaseArrays( ctx, ~0 )
#define TAG(x) tcl_##x
#include "tnl_dd/t_dd_dmatmp2.h"
/**********************************************************************/
/* External entrypoints */
/**********************************************************************/
void radeonEmitPrimitive( GLcontext *ctx,
GLuint first,
GLuint last,
GLuint flags )
{
tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
}
void radeonEmitEltPrimitive( GLcontext *ctx,
GLuint first,
GLuint last,
GLuint flags )
{
tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
}
void radeonTclPrimitive( GLcontext *ctx,
GLenum prim,
int hw_prim )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint se_cntl;
GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
if (newprim != rmesa->tcl.hw_primitive ||
!discreet_prim[hw_prim&0xf]) {
RADEON_NEWPRIM( rmesa );
rmesa->tcl.hw_primitive = newprim;
}
se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
if (prim == GL_POLYGON && (ctx->_TriangleCaps & DD_FLATSHADE))
se_cntl |= RADEON_FLAT_SHADE_VTX_0;
else
se_cntl |= RADEON_FLAT_SHADE_VTX_LAST;
if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
}
}
/**********************************************************************/
/* Render pipeline stage */
/**********************************************************************/
/* TCL render.
*/
static GLboolean radeon_run_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i,flags = 0,length;
/* TODO: separate this from the swtnl pipeline
*/
if (rmesa->TclFallback)
return GL_TRUE; /* fallback to software t&l */
if (VB->Count == 0)
return GL_FALSE;
radeonReleaseArrays( ctx, stage->changed_inputs );
radeonEmitArrays( ctx, stage->inputs );
rmesa->tcl.Elts = VB->Elts;
for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
{
flags = VB->Primitive[i];
length = VB->PrimitiveLength[i];
if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s: prim %s %d..%d\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
i, i+length);
if (!length)
continue;
if (rmesa->tcl.Elts)
radeonEmitEltPrimitive( ctx, i, i+length, flags );
else
radeonEmitPrimitive( ctx, i, i+length, flags );
}
return GL_FALSE; /* finished the pipe */
}
static void radeon_check_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint inputs = VERT_BIT_POS;
if (ctx->RenderMode == GL_RENDER) {
/* Make all this event-driven:
*/
if (ctx->Light.Enabled) {
inputs |= VERT_BIT_NORMAL;
if (ctx->Light.ColorMaterialEnabled) {
inputs |= VERT_BIT_COLOR0;
}
}
else {
inputs |= VERT_BIT_COLOR0;
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
inputs |= VERT_BIT_COLOR1;
}
}
if (ctx->Texture.Unit[0]._ReallyEnabled) {
if (ctx->Texture.Unit[0].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[0]) {
inputs |= VERT_BIT_NORMAL;
}
} else {
inputs |= VERT_BIT_TEX0;
}
}
if (ctx->Texture.Unit[1]._ReallyEnabled) {
if (ctx->Texture.Unit[1].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[1]) {
inputs |= VERT_BIT_NORMAL;
}
} else {
inputs |= VERT_BIT_TEX1;
}
}
stage->inputs = inputs;
stage->active = 1;
}
else
stage->active = 0;
}
static void radeon_init_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
stage->check = radeon_check_tcl_render;
stage->check( ctx, stage );
}
static void dtr( struct gl_pipeline_stage *stage )
{
(void)stage;
}
/* Initial state for tcl stage.
*/
const struct gl_pipeline_stage _radeon_tcl_stage =
{
"radeon render",
(_DD_NEW_SEPARATE_SPECULAR |
_NEW_LIGHT|
_NEW_TEXTURE|
_NEW_FOG|
_NEW_RENDERMODE), /* re-check (new inputs) */
0, /* re-run (always runs) */
GL_TRUE, /* active */
0, 0, /* inputs (set in check_render), outputs */
0, 0, /* changed_inputs, private */
dtr, /* destructor */
radeon_init_tcl_render, /* check - initially set to alloc data */
radeon_run_tcl_render /* run */
};
/**********************************************************************/
/* Validate state at pipeline start */
/**********************************************************************/
/*-----------------------------------------------------------------------
* Manage TCL fallbacks
*/
static void transition_to_swtnl( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint se_cntl;
RADEON_NEWPRIM( rmesa );
rmesa->swtcl.vertex_format = 0;
radeonChooseVertexState( ctx );
radeonChooseRenderState( ctx );
_mesa_validate_all_lighting_tables( ctx );
tnl->Driver.NotifyMaterialChange =
_mesa_validate_all_lighting_tables;
radeonReleaseArrays( ctx, ~0 );
se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
se_cntl |= RADEON_FLAT_SHADE_VTX_LAST;
if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
}
}
static void transition_to_hwtnl( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
RADEON_TEX1_W_ROUTING_USE_Q1);
if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
_tnl_need_projected_coords( ctx, GL_FALSE );
}
radeonUpdateMaterial( ctx );
tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial;
if ( rmesa->dma.flush )
rmesa->dma.flush( rmesa );
rmesa->dma.flush = 0;
rmesa->swtcl.vertex_format = 0;
if (rmesa->swtcl.indexed_verts.buf)
radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
__FUNCTION__ );
if (RADEON_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "Radeon end tcl fallback\n");
}
static char *fallbackStrings[] = {
"Rasterization fallback",
"Unfilled triangles",
"Twosided lighting, differing materials",
"Materials in VB (maybe between begin/end)",
"Texgen unit 0",
"Texgen unit 1",
"Texgen unit 2",
"User disable"
};
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint oldfallback = rmesa->TclFallback;
if (mode) {
rmesa->TclFallback |= bit;
if (oldfallback == 0) {
if (RADEON_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "Radeon begin tcl fallback %s\n",
getFallbackString( bit ));
transition_to_swtnl( ctx );
}
}
else {
rmesa->TclFallback &= ~bit;
if (oldfallback == bit) {
if (RADEON_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "Radeon end tcl fallback %s\n",
getFallbackString( bit ));
transition_to_hwtnl( ctx );
}
}
}

View file

@ -0,0 +1,66 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Grahpics Inc., Austin, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAHPICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#ifndef __RADEON_TCL_H__
#define __RADEON_TCL_H__
#ifdef GLX_DIRECT_RENDERING
#include "radeon_context.h"
extern void radeonTclPrimitive( GLcontext *ctx, GLenum prim, int hw_prim );
extern void radeonEmitEltPrimitive( GLcontext *ctx, GLuint first, GLuint last,
GLuint flags );
extern void radeonEmitPrimitive( GLcontext *ctx, GLuint first, GLuint last,
GLuint flags );
extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */
#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */
#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */
#define RADEON_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */
#define RADEON_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */
#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */
#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */
#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */
#define RADEON_MAX_TCL_VERTSIZE (4*4) /* using maos now... */
#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode )
#endif
#endif

View file

@ -0,0 +1,691 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */
/*
* Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*/
#include "glheader.h"
#include "imports.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "image.h"
#include "simple_list.h"
#include "texformat.h"
#include "texstore.h"
#include "radeon_context.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_swtcl.h"
#include "radeon_tex.h"
/* =============================================================
* Utility functions:
*/
static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap )
{
t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK);
switch ( swrap ) {
case GL_REPEAT:
t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
break;
case GL_CLAMP:
t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
break;
case GL_CLAMP_TO_EDGE:
t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
break;
case GL_CLAMP_TO_BORDER:
t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_BORDER;
break;
case GL_MIRRORED_REPEAT:
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR;
break;
case GL_MIRROR_CLAMP_ATI:
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_BORDER;
break;
case GL_MIRROR_CLAMP_TO_EDGE_ATI:
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST;
break;
}
switch ( twrap ) {
case GL_REPEAT:
t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
break;
case GL_CLAMP:
t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
break;
case GL_CLAMP_TO_EDGE:
t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
break;
case GL_CLAMP_TO_BORDER:
t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_BORDER;
break;
case GL_MIRRORED_REPEAT:
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR;
break;
case GL_MIRROR_CLAMP_ATI:
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_BORDER;
break;
case GL_MIRROR_CLAMP_TO_EDGE_ATI:
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST;
break;
}
}
static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
{
t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK;
if ( max == 1.0 ) {
t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1;
} else if ( max <= 2.0 ) {
t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1;
} else if ( max <= 4.0 ) {
t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1;
} else if ( max <= 8.0 ) {
t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1;
} else {
t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1;
}
}
static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
{
GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK);
t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK);
if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) {
switch ( minf ) {
case GL_NEAREST:
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
break;
case GL_LINEAR:
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
break;
}
} else {
switch ( minf ) {
case GL_NEAREST:
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST;
break;
case GL_LINEAR:
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
break;
}
}
switch ( magf ) {
case GL_NEAREST:
t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
break;
case GL_LINEAR:
t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
break;
}
}
static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] )
{
t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
}
static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
{
radeonTexObjPtr t;
t = CALLOC_STRUCT( radeon_tex_obj );
if (!t)
return NULL;
if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t );
}
t->tObj = texObj;
make_empty_list( t );
/* Initialize non-image-dependent parts of the state:
*/
radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
radeonSetTexBorderColor( t, texObj->_BorderChan );
return t;
}
static const struct gl_texture_format *
radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
const GLboolean do32bpt = ( rmesa->radeonScreen->cpp == 4 );
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
return &_mesa_texformat_al88;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_al88;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
default:
_mesa_problem(ctx, "unexpected texture format in radeonChoosTexFormat");
return NULL;
}
return NULL; /* never get here */
}
static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
if ( t ) {
radeonSwapOutTexObj( rmesa, t );
}
else {
t = radeonAllocTexObj( texObj );
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
return;
}
texObj->DriverData = t;
}
/* Note, this will call radeonChooseTextureFormat */
_mesa_store_teximage1d(ctx, target, level, internalFormat,
width, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images |= (1 << level);
}
static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData;
assert( t ); /* this _should_ be true */
if ( t ) {
radeonSwapOutTexObj( rmesa, t );
t->dirty_images |= (1 << level);
}
else {
t = radeonAllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
return;
}
texObj->DriverData = t;
}
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
t->dirty_images |= (1 << level);
}
static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData;
/* fprintf(stderr, "%s\n", __FUNCTION__); */
if ( t ) {
radeonSwapOutTexObj( rmesa, t );
}
else {
t = radeonAllocTexObj( texObj );
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
texObj->DriverData = t;
}
/* Note, this will call radeonChooseTextureFormat */
_mesa_store_teximage2d(ctx, target, level, internalFormat,
width, height, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images |= (1 << level);
}
static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
/* fprintf(stderr, "%s\n", __FUNCTION__); */
assert( t ); /* this _should_ be true */
if ( t ) {
radeonSwapOutTexObj( rmesa, t );
}
else {
t = radeonAllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
return;
}
texObj->DriverData = t;
}
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images |= (1 << level);
}
#define SCALED_FLOAT_TO_BYTE( x, scale ) \
(((GLuint)((255.0F / scale) * (x))) / 2)
static void radeonTexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint unit = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if ( RADEON_DEBUG & DEBUG_STATE ) {
fprintf( stderr, "%s( %s )\n",
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
}
switch ( pname ) {
case GL_TEXTURE_ENV_COLOR: {
GLubyte c[4];
GLuint envColor;
UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
RADEON_STATECHANGE( rmesa, tex[unit] );
rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
}
break;
}
case GL_TEXTURE_LOD_BIAS_EXT: {
GLfloat bias;
GLuint b;
/* The Radeon's LOD bias is a signed 2's complement value with a
* range of -1.0 <= bias < 4.0. We break this into two linear
* functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
* [0.0,4.0] to [0,127].
*/
bias = CLAMP( *param, -1.0, 4.0 );
if ( bias == 0 ) {
b = 0;
} else if ( bias > 0 ) {
b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT;
} else {
b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT;
}
if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) {
RADEON_STATECHANGE( rmesa, tex[unit] );
rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK;
rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK);
}
break;
}
default:
return;
}
}
static void radeonTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj,
GLenum pname, const GLfloat *params )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
fprintf( stderr, "%s( %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( pname ) );
}
if ( ( target != GL_TEXTURE_2D ) &&
( target != GL_TEXTURE_1D ) )
return;
switch ( pname ) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
break;
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
break;
case GL_TEXTURE_BORDER_COLOR:
radeonSetTexBorderColor( t, texObj->_BorderChan );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative for Radeon. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
radeonSwapOutTexObj( rmesa, t );
break;
default:
return;
}
/* Mark this texobj as dirty (one bit per tex unit)
*/
t->dirty_state = TEX_ALL;
}
static void radeonBindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj )
{
radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
GLuint unit = ctx->Texture.CurrentUnit;
if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, texObj, unit );
}
if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
if ( !t ) {
t = radeonAllocTexObj( texObj );
texObj->DriverData = t;
}
}
}
static void radeonDeleteTexture( GLcontext *ctx,
struct gl_texture_object *texObj )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
}
if ( t ) {
if ( rmesa ) {
RADEON_FIREVERTICES( rmesa );
}
radeonDestroyTexObj( rmesa, t );
texObj->DriverData = NULL;
}
}
static GLboolean radeonIsTextureResident( GLcontext *ctx,
struct gl_texture_object *texObj )
{
radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
return ( t && t->memBlock );
}
static void radeonInitTextureObjects( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
struct gl_texture_object *texObj;
GLuint tmp = ctx->Texture.CurrentUnit;
ctx->Texture.CurrentUnit = 0;
texObj = ctx->Texture.Unit[0].Current1D;
radeonBindTexture( ctx, GL_TEXTURE_1D, texObj );
move_to_tail( &rmesa->texture.swapped,
(radeonTexObjPtr)texObj->DriverData );
texObj = ctx->Texture.Unit[0].Current2D;
radeonBindTexture( ctx, GL_TEXTURE_2D, texObj );
move_to_tail( &rmesa->texture.swapped,
(radeonTexObjPtr)texObj->DriverData );
ctx->Texture.CurrentUnit = 1;
texObj = ctx->Texture.Unit[1].Current1D;
radeonBindTexture( ctx, GL_TEXTURE_1D, texObj );
move_to_tail( &rmesa->texture.swapped,
(radeonTexObjPtr)texObj->DriverData );
texObj = ctx->Texture.Unit[1].Current2D;
radeonBindTexture( ctx, GL_TEXTURE_2D, texObj );
move_to_tail( &rmesa->texture.swapped,
(radeonTexObjPtr)texObj->DriverData );
ctx->Texture.CurrentUnit = tmp;
}
/* Need:
* - Same GEN_MODE for all active bits
* - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
* - STRQ presumably all supported (matrix means incoming R values
* can end up in STQ, this has implications for vertex support,
* presumably ok if maos is used, though?)
*
* Basically impossible to do this on the fly - just collect some
* basic info & do the checks from ValidateState().
*/
static void radeonTexGen( GLcontext *ctx,
GLenum coord,
GLenum pname,
const GLfloat *params )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint unit = ctx->Texture.CurrentUnit;
rmesa->recheck_texgen[unit] = GL_TRUE;
}
void radeonInitTextureFuncs( GLcontext *ctx )
{
ctx->Driver.ChooseTextureFormat = radeonChooseTextureFormat;
ctx->Driver.TexImage1D = radeonTexImage1D;
ctx->Driver.TexImage2D = radeonTexImage2D;
ctx->Driver.TexImage3D = _mesa_store_teximage3d;
ctx->Driver.TexSubImage1D = radeonTexSubImage1D;
ctx->Driver.TexSubImage2D = radeonTexSubImage2D;
ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
ctx->Driver.BindTexture = radeonBindTexture;
ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */
ctx->Driver.DeleteTexture = radeonDeleteTexture;
ctx->Driver.IsTextureResident = radeonIsTextureResident;
ctx->Driver.PrioritizeTexture = NULL;
ctx->Driver.ActiveTexture = NULL;
ctx->Driver.UpdateTexturePalette = NULL;
ctx->Driver.TexEnv = radeonTexEnv;
ctx->Driver.TexParameter = radeonTexParameter;
ctx->Driver.TexGen = radeonTexGen;
radeonInitTextureObjects( ctx );
}

View file

@ -0,0 +1,57 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h,v 1.3 2002/02/22 21:45:01 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __RADEON_TEX_H__
#define __RADEON_TEX_H__
#ifdef GLX_DIRECT_RENDERING
extern void radeonUpdateTextureState( GLcontext *ctx );
extern int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t );
extern void radeonAgeTextures( radeonContextPtr rmesa, int heap );
extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
extern void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
extern void radeonPrintLocalLRU( radeonContextPtr rmesa, int heap );
extern void radeonPrintGlobalLRU( radeonContextPtr rmesa, int heap );
extern void radeonUpdateTexLRU( radeonContextPtr rmesa, radeonTexObjPtr t );
extern void radeonInitTextureFuncs( GLcontext *ctx );
#endif
#endif /* __RADEON_TEX_H__ */

View file

@ -0,0 +1,550 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v 1.4 2002/09/16 18:05:20 eich Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "mmath.h"
#include "macros.h"
#include "simple_list.h"
#include "radeon_context.h"
#include "radeon_tex.h"
#include <errno.h>
/* Destroy hardware state associated with texture `t'.
*/
void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
{
if ( !t )
return;
if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj );
}
if ( t->memBlock ) {
mmFreeMem( t->memBlock );
t->memBlock = NULL;
}
if ( t->tObj )
t->tObj->DriverData = NULL;
if ( rmesa ) {
/* Bump the performace counter */
rmesa->c_textureSwaps++;
if ( t == rmesa->state.texture.unit[0].texobj ) {
rmesa->state.texture.unit[0].texobj = NULL;
remove_from_list( &rmesa->hw.tex[0] );
make_empty_list( &rmesa->hw.tex[0] );
}
if ( t == rmesa->state.texture.unit[1].texobj ) {
rmesa->state.texture.unit[1].texobj = NULL;
remove_from_list( &rmesa->hw.tex[1] );
make_empty_list( &rmesa->hw.tex[1] );
}
}
remove_from_list( t );
FREE( t );
}
/* Keep track of swapped out texture objects.
*/
void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
{
if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj );
}
/* Bump the performace counter */
rmesa->c_textureSwaps++;
if ( t->memBlock ) {
mmFreeMem( t->memBlock );
t->memBlock = NULL;
}
t->dirty_images = ~0;
move_to_tail( &rmesa->texture.swapped, t );
}
/* Print out debugging information about texture LRU.
*/
void radeonPrintLocalLRU( radeonContextPtr rmesa, int heap )
{
radeonTexObjPtr t;
int sz = 1 << (rmesa->radeonScreen->logTexGranularity[heap]);
fprintf( stderr, "\nLocal LRU, heap %d:\n", heap );
foreach ( t, &rmesa->texture.objects[heap] ) {
if (!t->tObj) {
fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n",
t->memBlock->ofs / sz,
t->memBlock->ofs,
t->memBlock->size );
} else {
fprintf( stderr, "Texture at 0x%x sz 0x%x\n",
t->memBlock->ofs,
t->memBlock->size );
}
}
fprintf( stderr, "\n" );
}
void radeonPrintGlobalLRU( radeonContextPtr rmesa, int heap )
{
radeon_tex_region_t *list = rmesa->sarea->texList[heap];
int i, j;
fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list );
for ( i = 0, j = RADEON_NR_TEX_REGIONS ; i < RADEON_NR_TEX_REGIONS ; i++ ) {
fprintf( stderr, "list[%d] age %d next %d prev %d\n",
j, list[j].age, list[j].next, list[j].prev );
j = list[j].next;
if ( j == RADEON_NR_TEX_REGIONS ) break;
}
if ( j != RADEON_NR_TEX_REGIONS ) {
fprintf( stderr, "Loop detected in global LRU\n" );
for ( i = 0 ; i < RADEON_NR_TEX_REGIONS ; i++ ) {
fprintf( stderr, "list[%d] age %d next %d prev %d\n",
i, list[i].age, list[i].next, list[i].prev );
}
}
fprintf( stderr, "\n" );
}
/* Reset the global texture LRU.
*/
static void radeonResetGlobalLRU( radeonContextPtr rmesa, int heap )
{
radeon_tex_region_t *list = rmesa->sarea->texList[heap];
int sz = 1 << rmesa->radeonScreen->logTexGranularity[heap];
int i;
/*
* (Re)initialize the global circular LRU list. The last element in
* the array (RADEON_NR_TEX_REGIONS) is the sentinal. Keeping it at
* the end of the array allows it to be addressed rationally when
* looking up objects at a particular location in texture memory.
*/
for ( i = 0 ; (i+1) * sz <= rmesa->radeonScreen->texSize[heap] ; i++ ) {
list[i].prev = i-1;
list[i].next = i+1;
list[i].age = 0;
}
i--;
list[0].prev = RADEON_NR_TEX_REGIONS;
list[i].prev = i-1;
list[i].next = RADEON_NR_TEX_REGIONS;
list[RADEON_NR_TEX_REGIONS].prev = i;
list[RADEON_NR_TEX_REGIONS].next = 0;
rmesa->sarea->texAge[heap] = 0;
}
/* Update the local and glock texture LRUs.
*/
void radeonUpdateTexLRU(radeonContextPtr rmesa, radeonTexObjPtr t )
{
int heap = t->heap;
radeon_tex_region_t *list = rmesa->sarea->texList[heap];
int sz = rmesa->radeonScreen->logTexGranularity[heap];
int start = t->memBlock->ofs >> sz;
int end = (t->memBlock->ofs + t->memBlock->size-1) >> sz;
int i;
rmesa->texture.age[heap] = ++rmesa->sarea->texAge[heap];
if ( !t->memBlock ) {
fprintf( stderr, "no memblock\n\n" );
return;
}
/* Update our local LRU */
move_to_head( &rmesa->texture.objects[heap], t );
/* Update the global LRU */
for ( i = start ; i <= end ; i++ ) {
list[i].in_use = 1;
list[i].age = rmesa->texture.age[heap];
/* remove_from_list(i) */
list[(GLuint)list[i].next].prev = list[i].prev;
list[(GLuint)list[i].prev].next = list[i].next;
/* insert_at_head(list, i) */
list[i].prev = RADEON_NR_TEX_REGIONS;
list[i].next = list[RADEON_NR_TEX_REGIONS].next;
list[(GLuint)list[RADEON_NR_TEX_REGIONS].next].prev = i;
list[RADEON_NR_TEX_REGIONS].next = i;
}
if ( 0 ) {
radeonPrintGlobalLRU( rmesa, t->heap );
radeonPrintLocalLRU( rmesa, t->heap );
}
}
/* Update our notion of what textures have been changed since we last
* held the lock. This pertains to both our local textures and the
* textures belonging to other clients. Keep track of other client's
* textures by pushing a placeholder texture onto the LRU list -- these
* are denoted by (tObj == NULL).
*/
static void radeonTexturesGone( radeonContextPtr rmesa, int heap,
int offset, int size, int in_use )
{
radeonTexObjPtr t, tmp;
foreach_s ( t, tmp, &rmesa->texture.objects[heap] ) {
if ( t->memBlock->ofs >= offset + size ||
t->memBlock->ofs + t->memBlock->size <= offset )
continue;
/* It overlaps - kick it out. Need to hold onto the currently
* bound objects, however.
*/
radeonSwapOutTexObj( rmesa, t );
}
if ( in_use ) {
t = (radeonTexObjPtr) CALLOC( sizeof(*t) );
if ( !t ) return;
t->memBlock = mmAllocMem( rmesa->texture.heap[heap], size, 0, offset );
if ( !t->memBlock ) {
fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
(int)size, (int)offset );
mmDumpMemInfo( rmesa->texture.heap[heap] );
return;
}
insert_at_head( &rmesa->texture.objects[heap], t );
}
}
/* Update our client's shared texture state. If another client has
* modified a region in which we have textures, then we need to figure
* out which of our textures has been removed, and update our global
* LRU.
*/
void radeonAgeTextures( radeonContextPtr rmesa, int heap )
{
RADEONSAREAPrivPtr sarea = rmesa->sarea;
if ( sarea->texAge[heap] != rmesa->texture.age[heap] ) {
int sz = 1 << rmesa->radeonScreen->logTexGranularity[heap];
int nr = 0;
int idx;
for ( idx = sarea->texList[heap][RADEON_NR_TEX_REGIONS].prev ;
idx != RADEON_NR_TEX_REGIONS && nr < RADEON_NR_TEX_REGIONS ;
idx = sarea->texList[heap][idx].prev, nr++ )
{
/* If switching texturing schemes, then the SAREA might not
* have been properly cleared, so we need to reset the
* global texture LRU.
*/
if ( idx * sz > rmesa->radeonScreen->texSize[heap] ) {
nr = RADEON_NR_TEX_REGIONS;
break;
}
if ( sarea->texList[heap][idx].age > rmesa->texture.age[heap] ) {
radeonTexturesGone( rmesa, heap, idx * sz, sz,
sarea->texList[heap][idx].in_use );
}
}
if ( nr == RADEON_NR_TEX_REGIONS ) {
radeonTexturesGone( rmesa, heap, 0,
rmesa->radeonScreen->texSize[heap], 0 );
radeonResetGlobalLRU( rmesa, heap );
}
rmesa->texture.age[heap] = sarea->texAge[heap];
}
}
/* =============================================================
* Texture image conversions
*/
/* Upload the texture image associated with texture `t' at level `level'
* at the address relative to `start'.
*/
static void radeonUploadSubImage( radeonContextPtr rmesa,
radeonTexObjPtr t, GLint level,
GLint x, GLint y, GLint width, GLint height )
{
struct gl_texture_image *texImage;
const struct gl_texture_format *texFormat;
GLint texelsPerDword = 0;
GLuint format, pitch, offset;
GLint imageWidth, imageHeight;
GLint ret;
drmRadeonTexture tex;
drmRadeonTexImage tmp;
if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj );
}
/* Ensure we have a valid texture to upload */
level += t->firstLevel;
if ( ( level < 0 ) || ( level >= RADEON_MAX_TEXTURE_LEVELS ) ) {
_mesa_problem(NULL, "bad texture level in radeonUploadSubimage");
return;
}
texImage = t->tObj->Image[level];
if ( !texImage ) {
if ( RADEON_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
return;
}
if ( !texImage->Data ) {
if ( RADEON_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
return;
}
texFormat = texImage->TexFormat;
switch ( texFormat->TexelBytes ) {
case 1:
texelsPerDword = 4;
break;
case 2:
texelsPerDword = 2;
break;
case 4:
texelsPerDword = 1;
break;
}
format = t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK;
imageWidth = texImage->Width;
imageHeight = texImage->Height;
offset = t->bufAddr;
pitch = (t->image[0].width * texFormat->TexelBytes) / 64;
#if 0
/* Bump the performace counter */
rmesa->c_textureBytes += (dwords << 2);
#endif
if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
GLint imageX = 0;
GLint imageY = 0;
GLint blitX = t->image[level].x;
GLint blitY = t->image[level].y;
GLint blitWidth = t->image[level].width;
GLint blitHeight = t->image[level].height;
fprintf( stderr, " upload image: %d,%d at %d,%d\n",
imageWidth, imageHeight, imageX, imageY );
fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
blitWidth, blitHeight, blitX, blitY );
fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x "
"level: %d format: %x\n",
(GLuint)offset, (GLuint)pitch, level, format );
}
t->image[level].data = texImage->Data;
tex.offset = offset;
tex.pitch = pitch;
tex.format = format;
tex.width = imageWidth;
tex.height = imageHeight;
tex.image = &tmp;
memcpy( &tmp, &t->image[level], sizeof(drmRadeonTexImage) );
do {
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
&tex, sizeof(drmRadeonTexture) );
} while ( ret && errno == EAGAIN );
if ( ret ) {
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
fprintf( stderr, " offset=0x%08x pitch=0x%x format=%d\n",
offset, pitch, format );
fprintf( stderr, " image width=%d height=%d\n",
imageWidth, imageHeight );
fprintf( stderr, " blit width=%d height=%d data=%p\n",
t->image[level].width, t->image[level].height,
t->image[level].data );
exit( 1 );
}
}
/* Upload the texture images associated with texture `t'. This might
* require removing our own and/or other client's texture objects to
* make room for these images.
*/
int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t )
{
const int numLevels = t->lastLevel - t->firstLevel + 1;
int i;
int heap;
radeonTexObjPtr t0 = rmesa->state.texture.unit[0].texobj;
radeonTexObjPtr t1 = rmesa->state.texture.unit[1].texobj;
if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
rmesa->glCtx, t->tObj, t->totalSize,
t->firstLevel, t->lastLevel );
}
if ( !t || t->totalSize == 0 )
return 0;
LOCK_HARDWARE( rmesa );
/* Choose the heap appropriately */
heap = t->heap = RADEON_CARD_HEAP;
#if 0
if ( !rmesa->radeonScreen->IsPCI &&
t->totalSize > rmesa->radeonScreen->texSize[heap] ) {
heap = t->heap = RADEON_AGP_HEAP;
}
#endif
/* Do we need to eject LRU texture objects? */
if ( !t->memBlock ) {
/* Allocate a memory block on a 4k boundary (1<<12 == 4096) */
t->memBlock = mmAllocMem( rmesa->texture.heap[heap],
t->totalSize, 12, 0 );
#if 0
/* Try AGP before kicking anything out of local mem */
if ( !t->memBlock && heap == RADEON_CARD_HEAP ) {
t->memBlock = mmAllocMem( rmesa->texture.heap[RADEON_AGP_HEAP],
t->totalSize, 12, 0 );
if ( t->memBlock )
heap = t->heap = RADEON_AGP_HEAP;
}
#endif
/* Kick out textures until the requested texture fits */
while ( !t->memBlock ) {
if ( rmesa->texture.objects[heap].prev == t0 ||
rmesa->texture.objects[heap].prev == t1 ) {
fprintf( stderr,
"radeonUploadTexImages: ran into bound texture\n" );
UNLOCK_HARDWARE( rmesa );
return -1;
}
if ( rmesa->texture.objects[heap].prev ==
&rmesa->texture.objects[heap] ) {
if ( rmesa->radeonScreen->IsPCI ) {
fprintf( stderr, "radeonUploadTexImages: upload texture "
"failure on local texture heaps, sz=%d\n",
t->totalSize );
UNLOCK_HARDWARE( rmesa );
return -1;
#if 0
} else if ( heap == RADEON_CARD_HEAP ) {
heap = t->heap = RADEON_AGP_HEAP;
continue;
#endif
} else {
fprintf( stderr, "radeonUploadTexImages: upload texture "
"failure on both local and AGP texture heaps, "
"sz=%d\n",
t->totalSize );
UNLOCK_HARDWARE( rmesa );
return -1;
}
}
radeonSwapOutTexObj( rmesa, rmesa->texture.objects[heap].prev );
t->memBlock = mmAllocMem( rmesa->texture.heap[heap],
t->totalSize, 12, 0 );
}
/* Set the base offset of the texture image */
t->bufAddr = rmesa->radeonScreen->texOffset[heap] + t->memBlock->ofs;
t->pp_txoffset = t->bufAddr;
#if 0
/* Fix AGP texture offsets */
if ( heap == RADEON_AGP_HEAP ) {
t->setup.pp_tx_offset += RADEON_AGP_TEX_OFFSET +
rmesa->radeonScreen->agpTexOffset;
}
#endif
/* Mark this texobj as dirty on all units:
*/
t->dirty_state = TEX_ALL;
}
/* Let the world know we've used this memory recently */
radeonUpdateTexLRU( rmesa, t );
/* Upload any images that are new */
if (t->dirty_images) {
for ( i = 0 ; i < numLevels ; i++ ) {
if ( t->dirty_images & (1 << i) ) {
radeonUploadSubImage( rmesa, t, i, 0, 0,
t->image[i].width, t->image[i].height );
}
}
t->dirty_images = 0;
}
UNLOCK_HARDWARE( rmesa );
return 0;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#ifndef __RADEON_VTXFMT_H__
#define __RADEON_VTXFMT_H__
#ifdef GLX_DIRECT_RENDERING
#include "radeon_context.h"
extern struct radeon_vb vb;
extern void radeonVtxfmtUpdate( GLcontext *ctx );
extern void radeonVtxfmtInit( GLcontext *ctx );
extern void radeonVtxfmtInvalidate( GLcontext *ctx );
extern void radeonVtxfmtDestroy( GLcontext *ctx );
extern void radeonVtxfmtInitChoosers( GLvertexformat *vfmt );
extern void radeonVtxfmtMakeCurrent( GLcontext *ctx );
extern void radeonVtxfmtUnbindContext( GLcontext *ctx );
extern void radeon_copy_to_current( GLcontext *ctx );
#define DFN( FUNC, CACHE) \
do { \
char *start = (char *)&FUNC; \
char *end = (char *)&FUNC##_end; \
insert_at_head( &CACHE, dfn ); \
dfn->key = key; \
dfn->code = ALIGN_MALLOC( end - start, 16 ); \
memcpy (dfn->code, start, end - start); \
} \
while ( 0 )
#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
int *icode = (int *)(CODE+OFFSET); \
assert (*icode == CHECKVAL); \
*icode = (int)NEWVAL; \
} while (0)
/* Useful for figuring out the offsets:
*/
#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \
fprintf(stderr, "%s/%d CVAL %x OFFSET %d VAL %x\n", __FUNCTION__, \
__LINE__, CHECKVAL, OFFSET, (int)(NEWVAL)); \
*(int *)(CODE+OFFSET) = (int)(NEWVAL); \
OFFSET += 4; \
} while (0)
/*
*/
void radeonInitCodegen( struct dfn_generators *gen );
void radeonInitX86Codegen( struct dfn_generators *gen );
void radeonInitSSECodegen( struct dfn_generators *gen );
/* Defined in radeon_vtxfmt_x86.c
*/
struct dynfn *radeon_makeX86Vertex2f( GLcontext *, int );
struct dynfn *radeon_makeX86Vertex2fv( GLcontext *, int );
struct dynfn *radeon_makeX86Vertex3f( GLcontext *, int );
struct dynfn *radeon_makeX86Vertex3fv( GLcontext *, int );
struct dynfn *radeon_makeX86Color4ub( GLcontext *, int );
struct dynfn *radeon_makeX86Color4ubv( GLcontext *, int );
struct dynfn *radeon_makeX86Color3ub( GLcontext *, int );
struct dynfn *radeon_makeX86Color3ubv( GLcontext *, int );
struct dynfn *radeon_makeX86Color4f( GLcontext *, int );
struct dynfn *radeon_makeX86Color4fv( GLcontext *, int );
struct dynfn *radeon_makeX86Color3f( GLcontext *, int );
struct dynfn *radeon_makeX86Color3fv( GLcontext *, int );
struct dynfn *radeon_makeX86SecondaryColor3ubEXT( GLcontext *, int );
struct dynfn *radeon_makeX86SecondaryColor3ubvEXT( GLcontext *, int );
struct dynfn *radeon_makeX86SecondaryColor3fEXT( GLcontext *, int );
struct dynfn *radeon_makeX86SecondaryColor3fvEXT( GLcontext *, int );
struct dynfn *radeon_makeX86Normal3f( GLcontext *, int );
struct dynfn *radeon_makeX86Normal3fv( GLcontext *, int );
struct dynfn *radeon_makeX86TexCoord2f( GLcontext *, int );
struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *, int );
struct dynfn *radeon_makeX86TexCoord1f( GLcontext *, int );
struct dynfn *radeon_makeX86TexCoord1fv( GLcontext *, int );
struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *, int );
struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *, int );
struct dynfn *radeon_makeX86MultiTexCoord1fARB( GLcontext *, int );
struct dynfn *radeon_makeX86MultiTexCoord1fvARB( GLcontext *, int );
#endif
#endif

View file

@ -0,0 +1,728 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "simple_list.h"
#include "api_noop.h"
#include "vtxfmt.h"
#include "radeon_vtxfmt.h"
/* Fallback versions of all the entrypoints for situations where
* codegen isn't available. This is still a lot faster than the
* vb/pipeline implementation in Mesa.
*/
static void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
int i;
*vb.dmaptr++ = *(int *)&x;
*vb.dmaptr++ = *(int *)&y;
*vb.dmaptr++ = *(int *)&z;
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
static void radeon_Vertex3fv( const GLfloat *v )
{
int i;
*vb.dmaptr++ = *(int *)&v[0];
*vb.dmaptr++ = *(int *)&v[1];
*vb.dmaptr++ = *(int *)&v[2];
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
static void radeon_Vertex2f( GLfloat x, GLfloat y )
{
int i;
*vb.dmaptr++ = *(int *)&x;
*vb.dmaptr++ = *(int *)&y;
*vb.dmaptr++ = 0;
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = *(int *)&vb.vertex[i];
if (--vb.counter == 0)
vb.notify();
}
static void radeon_Vertex2fv( const GLfloat *v )
{
int i;
*vb.dmaptr++ = *(int *)&v[0];
*vb.dmaptr++ = *(int *)&v[1];
*vb.dmaptr++ = 0;
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
/* Color for ubyte (packed) color formats:
*/
static void radeon_Color3ub_ub( GLubyte r, GLubyte g, GLubyte b )
{
radeon_color_t *dest = vb.colorptr;
dest->red = r;
dest->green = g;
dest->blue = b;
dest->alpha = 0xff;
}
static void radeon_Color3ubv_ub( const GLubyte *v )
{
radeon_color_t *dest = vb.colorptr;
dest->red = v[0];
dest->green = v[1];
dest->blue = v[2];
dest->alpha = 0xff;
}
static void radeon_Color4ub_ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
radeon_color_t *dest = vb.colorptr;
dest->red = r;
dest->green = g;
dest->blue = b;
dest->alpha = a;
}
static void radeon_Color4ubv_ub( const GLubyte *v )
{
*(GLuint *)vb.colorptr = LE32_TO_CPU(*(GLuint *)v);
}
static void radeon_Color3f_ub( GLfloat r, GLfloat g, GLfloat b )
{
radeon_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
dest->alpha = 255;
}
static void radeon_Color3fv_ub( const GLfloat *v )
{
radeon_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
dest->alpha = 255;
}
static void radeon_Color4f_ub( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
radeon_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, a );
}
static void radeon_Color4fv_ub( const GLfloat *v )
{
radeon_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, v[3] );
}
/* Color for float color+alpha formats:
*/
static void radeon_Color3ub_4f( GLubyte r, GLubyte g, GLubyte b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
dest[3] = 1.0;
}
static void radeon_Color3ubv_4f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
dest[3] = 1.0;
}
static void radeon_Color4ub_4f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
dest[3] = UBYTE_TO_FLOAT(a);
}
static void radeon_Color4ubv_4f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
dest[3] = UBYTE_TO_FLOAT(v[3]);
}
static void radeon_Color3f_4f( GLfloat r, GLfloat g, GLfloat b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = 1.0;
}
static void radeon_Color3fv_4f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = 1.0;
}
static void radeon_Color4f_4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
}
static void radeon_Color4fv_4f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = v[3];
}
/* Color for float color formats:
*/
static void radeon_Color3ub_3f( GLubyte r, GLubyte g, GLubyte b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
}
static void radeon_Color3ubv_3f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
}
static void radeon_Color4ub_3f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(a);
}
static void radeon_Color4ubv_3f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(v[3]);
}
static void radeon_Color3f_3f( GLfloat r, GLfloat g, GLfloat b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
}
static void radeon_Color3fv_3f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
}
static void radeon_Color4f_3f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = a;
}
static void radeon_Color4fv_3f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = v[3];
}
/* Secondary Color:
*/
static void radeon_SecondaryColor3ubEXT( GLubyte r, GLubyte g, GLubyte b )
{
radeon_color_t *dest = vb.specptr;
dest->red = r;
dest->green = g;
dest->blue = b;
dest->alpha = 0xff;
}
static void radeon_SecondaryColor3ubvEXT( const GLubyte *v )
{
radeon_color_t *dest = vb.specptr;
dest->red = v[0];
dest->green = v[1];
dest->blue = v[2];
dest->alpha = 0xff;
}
static void radeon_SecondaryColor3fEXT( GLfloat r, GLfloat g, GLfloat b )
{
radeon_color_t *dest = vb.specptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
dest->alpha = 255;
}
static void radeon_SecondaryColor3fvEXT( const GLfloat *v )
{
radeon_color_t *dest = vb.specptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
dest->alpha = 255;
}
/* Normal
*/
static void radeon_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 )
{
GLfloat *dest = vb.normalptr;
dest[0] = n0;
dest[1] = n1;
dest[2] = n2;
}
static void radeon_Normal3fv( const GLfloat *v )
{
GLfloat *dest = vb.normalptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
}
/* TexCoord
*/
static void radeon_TexCoord1f( GLfloat s )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = s;
dest[1] = 0;
}
static void radeon_TexCoord1fv( const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = v[0];
dest[1] = 0;
}
static void radeon_TexCoord2f( GLfloat s, GLfloat t )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = s;
dest[1] = t;
}
static void radeon_TexCoord2fv( const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = v[0];
dest[1] = v[1];
}
/* MultiTexcoord
*/
static void radeon_MultiTexCoord1fARB( GLenum target, GLfloat s )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = s;
dest[1] = 0;
}
static void radeon_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = v[0];
dest[1] = 0;
}
static void radeon_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = s;
dest[1] = t;
}
static void radeon_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = v[0];
dest[1] = v[1];
}
static struct dynfn *lookup( struct dynfn *l, int key )
{
struct dynfn *f;
foreach( f, l ) {
if (f->key == key)
return f;
}
return 0;
}
/* Can't use the loopback template for this:
*/
#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
radeonContextPtr rmesa = RADEON_CONTEXT(vb.context); \
int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \
struct dynfn *dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
\
if (dfn == 0) \
dfn = rmesa->vb.codegen.FN( vb.context, key ); \
else if (RADEON_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ ); \
\
if (dfn) \
vb.context->Exec->FN = (FNTYPE)(dfn->code); \
else { \
if (RADEON_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \
vb.context->Exec->FN = radeon_##FN; \
} \
\
vb.context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
vb.context->Exec->FN ARGS2; \
}
/* For the _3f case, only allow one color function to be hooked in at
* a time. Eventually, use a similar mechanism to allow selecting the
* color component of the vertex format based on client behaviour.
*
* Note: Perform these actions even if there is a codegen or cached
* codegen version of the chosen function.
*/
#define CHOOSE_COLOR(FN, FNTYPE, NR, MASK, ACTIVE, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
GLcontext *ctx = vb.context; \
radeonContextPtr rmesa = RADEON_CONTEXT(vb.context); \
int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \
struct dynfn *dfn; \
\
if (rmesa->vb.vertex_format & ACTIVE_PKCOLOR) { \
ctx->Exec->FN = radeon_##FN##_ub; \
} \
else if ((rmesa->vb.vertex_format & \
(ACTIVE_FPCOLOR|ACTIVE_FPALPHA)) == ACTIVE_FPCOLOR) { \
\
if (rmesa->vb.installed_color_3f_sz != NR) { \
rmesa->vb.installed_color_3f_sz = NR; \
if (NR == 3) ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = 1.0; \
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) { \
radeon_copy_to_current( ctx ); \
_mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); \
ctx->Exec->FN ARGS2; \
return; \
} \
} \
\
ctx->Exec->FN = radeon_##FN##_3f; \
} \
else { \
ctx->Exec->FN = radeon_##FN##_4f; \
} \
\
\
dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
if (!dfn) dfn = rmesa->vb.codegen.FN( ctx, key ); \
\
if (dfn) { \
if (RADEON_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- codegen version\n", __FUNCTION__ ); \
ctx->Exec->FN = (FNTYPE)dfn->code; \
} \
else if (RADEON_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- 'c' version\n", __FUNCTION__ ); \
\
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
ctx->Exec->FN ARGS2; \
}
/* Shorthands
*/
#define ACTIVE_XYZW (RADEON_CP_VC_FRMT_W0|RADEON_CP_VC_FRMT_Z)
#define ACTIVE_NORM RADEON_CP_VC_FRMT_N0
#define ACTIVE_PKCOLOR RADEON_CP_VC_FRMT_PKCOLOR
#define ACTIVE_FPCOLOR RADEON_CP_VC_FRMT_FPCOLOR
#define ACTIVE_FPALPHA RADEON_CP_VC_FRMT_FPALPHA
#define ACTIVE_COLOR (ACTIVE_FPCOLOR|ACTIVE_PKCOLOR)
#define ACTIVE_SPEC RADEON_CP_VC_FRMT_PKSPEC
#define ACTIVE_ST0 RADEON_CP_VC_FRMT_ST0
#define ACTIVE_ST1 RADEON_CP_VC_FRMT_ST1
#define ACTIVE_ST_ALL (RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST0)
/* Each codegen function should be able to be fully specified by a
* subsetted version of rmesa->vb.vertex_format.
*/
#define MASK_NORM (ACTIVE_XYZW)
#define MASK_COLOR (MASK_NORM|ACTIVE_NORM)
#define MASK_SPEC (MASK_COLOR|ACTIVE_COLOR)
#define MASK_ST0 (MASK_SPEC|ACTIVE_SPEC)
#define MASK_ST1 (MASK_ST0|ACTIVE_ST0)
#define MASK_ST_ALL (MASK_ST1|ACTIVE_ST1)
#define MASK_VERTEX (MASK_ST_ALL|ACTIVE_FPALPHA)
typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
typedef void (*p2f)( GLfloat, GLfloat );
typedef void (*p1f)( GLfloat );
typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
typedef void (*pe1f)( GLenum, GLfloat );
typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
typedef void (*pfv)( const GLfloat * );
typedef void (*pefv)( GLenum, const GLfloat * );
typedef void (*pubv)( const GLubyte * );
CHOOSE(Normal3f, p3f, MASK_NORM, ACTIVE_NORM,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Normal3fv, pfv, MASK_NORM, ACTIVE_NORM,
(const GLfloat *v), (v))
CHOOSE_COLOR(Color4ub, p4ub, 4, MASK_COLOR, ACTIVE_COLOR,
(GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d))
CHOOSE_COLOR(Color4ubv, pubv, 4, MASK_COLOR, ACTIVE_COLOR,
(const GLubyte *v), (v))
CHOOSE_COLOR(Color3ub, p3ub, 3, MASK_COLOR, ACTIVE_COLOR,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE_COLOR(Color3ubv, pubv, 3, MASK_COLOR, ACTIVE_COLOR,
(const GLubyte *v), (v))
CHOOSE_COLOR(Color4f, p4f, 4, MASK_COLOR, ACTIVE_COLOR,
(GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d))
CHOOSE_COLOR(Color4fv, pfv, 4, MASK_COLOR, ACTIVE_COLOR,
(const GLfloat *v), (v))
CHOOSE_COLOR(Color3f, p3f, 3, MASK_COLOR, ACTIVE_COLOR,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE_COLOR(Color3fv, pfv, 3, MASK_COLOR, ACTIVE_COLOR,
(const GLfloat *v), (v))
CHOOSE(SecondaryColor3ubEXT, p3ub, MASK_SPEC, ACTIVE_SPEC,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE(SecondaryColor3ubvEXT, pubv, MASK_SPEC, ACTIVE_SPEC,
(const GLubyte *v), (v))
CHOOSE(SecondaryColor3fEXT, p3f, MASK_SPEC, ACTIVE_SPEC,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE(SecondaryColor3fvEXT, pfv, MASK_SPEC, ACTIVE_SPEC,
(const GLfloat *v), (v))
CHOOSE(TexCoord2f, p2f, MASK_ST0, ACTIVE_ST0,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(TexCoord2fv, pfv, MASK_ST0, ACTIVE_ST0,
(const GLfloat *v), (v))
CHOOSE(TexCoord1f, p1f, MASK_ST0, ACTIVE_ST0,
(GLfloat a), (a))
CHOOSE(TexCoord1fv, pfv, MASK_ST0, ACTIVE_ST0,
(const GLfloat *v), (v))
CHOOSE(MultiTexCoord2fARB, pe2f, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,GLfloat a,GLfloat b), (u,a,b))
CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,GLfloat a), (u,a))
CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(Vertex3f, p3f, MASK_VERTEX, MASK_VERTEX,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Vertex3fv, pfv, MASK_VERTEX, MASK_VERTEX,
(const GLfloat *v), (v))
CHOOSE(Vertex2f, p2f, MASK_VERTEX, MASK_VERTEX,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(Vertex2fv, pfv, MASK_VERTEX, MASK_VERTEX,
(const GLfloat *v), (v))
void radeonVtxfmtInitChoosers( GLvertexformat *vfmt )
{
vfmt->Color3f = choose_Color3f;
vfmt->Color3fv = choose_Color3fv;
vfmt->Color3ub = choose_Color3ub;
vfmt->Color3ubv = choose_Color3ubv;
vfmt->Color4f = choose_Color4f;
vfmt->Color4fv = choose_Color4fv;
vfmt->Color4ub = choose_Color4ub;
vfmt->Color4ubv = choose_Color4ubv;
vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT;
vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT;
vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT;
vfmt->MultiTexCoord1fARB = choose_MultiTexCoord1fARB;
vfmt->MultiTexCoord1fvARB = choose_MultiTexCoord1fvARB;
vfmt->MultiTexCoord2fARB = choose_MultiTexCoord2fARB;
vfmt->MultiTexCoord2fvARB = choose_MultiTexCoord2fvARB;
vfmt->Normal3f = choose_Normal3f;
vfmt->Normal3fv = choose_Normal3fv;
vfmt->TexCoord1f = choose_TexCoord1f;
vfmt->TexCoord1fv = choose_TexCoord1fv;
vfmt->TexCoord2f = choose_TexCoord2f;
vfmt->TexCoord2fv = choose_TexCoord2fv;
vfmt->Vertex2f = choose_Vertex2f;
vfmt->Vertex2fv = choose_Vertex2fv;
vfmt->Vertex3f = choose_Vertex3f;
vfmt->Vertex3fv = choose_Vertex3fv;
}
static struct dynfn *codegen_noop( GLcontext *ctx, int key )
{
(void) ctx; (void) key;
return 0;
}
void radeonInitCodegen( struct dfn_generators *gen )
{
gen->Vertex3f = codegen_noop;
gen->Vertex3fv = codegen_noop;
gen->Color4ub = codegen_noop;
gen->Color4ubv = codegen_noop;
gen->Normal3f = codegen_noop;
gen->Normal3fv = codegen_noop;
gen->TexCoord2f = codegen_noop;
gen->TexCoord2fv = codegen_noop;
gen->MultiTexCoord2fARB = codegen_noop;
gen->MultiTexCoord2fvARB = codegen_noop;
gen->Vertex2f = codegen_noop;
gen->Vertex2fv = codegen_noop;
gen->Color3ub = codegen_noop;
gen->Color3ubv = codegen_noop;
gen->Color4f = codegen_noop;
gen->Color4fv = codegen_noop;
gen->Color3f = codegen_noop;
gen->Color3fv = codegen_noop;
gen->SecondaryColor3fEXT = codegen_noop;
gen->SecondaryColor3fvEXT = codegen_noop;
gen->SecondaryColor3ubEXT = codegen_noop;
gen->SecondaryColor3ubvEXT = codegen_noop;
gen->TexCoord1f = codegen_noop;
gen->TexCoord1fv = codegen_noop;
gen->MultiTexCoord1fARB = codegen_noop;
gen->MultiTexCoord1fvARB = codegen_noop;
if (!getenv("RADEON_NO_CODEGEN")) {
#if defined(USE_X86_ASM)
radeonInitX86Codegen( gen );
#endif
#if defined(USE_SSE_ASM)
radeonInitSSECodegen( gen );
#endif
}
}

View file

@ -0,0 +1,87 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "simple_list.h"
#include "radeon_vtxfmt.h"
#if defined(USE_SSE_ASM)
#include "X86/common_x86_asm.h"
/* Build specialized versions of the immediate calls on the fly for
* the current state. ???P4 SSE2 versions???
*/
static struct dynfn *makeSSENormal3fv( GLcontext *ctx, int key )
{
/* Requires P4 (sse2?)
*/
static unsigned char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */
0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */
0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */
0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */
0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
insert_at_head( &rmesa->vb.dfn_cache.Normal3fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)vb.normalptr);
return dfn;
}
void radeonInitSSECodegen( struct dfn_generators *gen )
{
if ( cpu_has_xmm && cpu_has_xmm2 )
/*gen->Normal3fv = */ (void)makeSSENormal3fv;
}
#else
void radeonInitSSECodegen( struct dfn_generators *gen )
{
(void) gen;
}
#endif

View file

@ -0,0 +1,462 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mmath.h"
#include "simple_list.h"
#include "radeon_vtxfmt.h"
#if defined(USE_X86_ASM)
#define EXTERN( FUNC ) \
extern const char *FUNC; \
extern const char *FUNC##_end
EXTERN ( _x86_Normal3fv );
EXTERN ( _x86_Normal3f );
EXTERN ( _x86_Vertex3fv_6 );
EXTERN ( _x86_Vertex3fv_8 );
EXTERN ( _x86_Vertex3fv );
EXTERN ( _x86_Vertex3f_4 );
EXTERN ( _x86_Vertex3f_6 );
EXTERN ( _x86_Vertex3f );
EXTERN ( _x86_Color4ubv_ub );
EXTERN ( _x86_Color4ubv_4f );
EXTERN ( _x86_Color4ub_ub );
EXTERN ( _x86_Color3fv_3f );
EXTERN ( _x86_Color3f_3f );
EXTERN ( _x86_TexCoord2fv );
EXTERN ( _x86_TexCoord2f );
EXTERN ( _x86_MultiTexCoord2fvARB );
EXTERN ( _x86_MultiTexCoord2fvARB_2 );
EXTERN ( _x86_MultiTexCoord2fARB );
EXTERN ( _x86_MultiTexCoord2fARB_2 );
/* Build specialized versions of the immediate calls on the fly for
* the current state. Generic x86 versions.
*/
struct dynfn *radeon_makeX86Vertex3f( GLcontext *ctx, int key )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, vb.vertex_size );
switch (vb.vertex_size) {
case 4: {
DFN ( _x86_Vertex3f_4, rmesa->vb.dfn_cache.Vertex3f );
FIXUP(dfn->code, 2, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 25, 0x0, (int)&vb.vertex[3]);
FIXUP(dfn->code, 36, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 46, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 51, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 60, 0x0, (int)&vb.notify);
break;
}
case 6: {
DFN ( _x86_Vertex3f_6, rmesa->vb.dfn_cache.Vertex3f );
FIXUP(dfn->code, 3, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 28, 0x0, (int)&vb.vertex[3]);
FIXUP(dfn->code, 34, 0x0, (int)&vb.vertex[4]);
FIXUP(dfn->code, 40, 0x0, (int)&vb.vertex[5]);
FIXUP(dfn->code, 57, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 63, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 70, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 79, 0x0, (int)&vb.notify);
break;
}
default: {
DFN ( _x86_Vertex3f, rmesa->vb.dfn_cache.Vertex3f );
FIXUP(dfn->code, 3, 0x0, (int)&vb.vertex[3]);
FIXUP(dfn->code, 9, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 37, 0x0, vb.vertex_size-3);
FIXUP(dfn->code, 44, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 50, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 56, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 67, 0x0, (int)&vb.notify);
break;
}
}
return dfn;
}
struct dynfn *radeon_makeX86Vertex3fv( GLcontext *ctx, int key )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, vb.vertex_size );
switch (vb.vertex_size) {
case 6: {
DFN ( _x86_Vertex3fv_6, rmesa->vb.dfn_cache.Vertex3fv );
FIXUP(dfn->code, 1, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&vb.vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&vb.vertex[4]);
FIXUP(dfn->code, 45, 0x00000024, (int)&vb.vertex[5]);
FIXUP(dfn->code, 56, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 61, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 67, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 76, 0x00000008, (int)&vb.notify);
break;
}
case 8: {
DFN ( _x86_Vertex3fv_8, rmesa->vb.dfn_cache.Vertex3fv );
FIXUP(dfn->code, 1, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&vb.vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&vb.vertex[4]);
FIXUP(dfn->code, 45, 0x0000001c, (int)&vb.vertex[5]);
FIXUP(dfn->code, 51, 0x00000020, (int)&vb.vertex[6]);
FIXUP(dfn->code, 63, 0x00000024, (int)&vb.vertex[7]);
FIXUP(dfn->code, 74, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 79, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 85, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 94, 0x00000008, (int)&vb.notify);
break;
}
default: {
DFN ( _x86_Vertex3fv, rmesa->vb.dfn_cache.Vertex3fv );
FIXUP(dfn->code, 8, 0x01010101, (int)&vb.dmaptr);
FIXUP(dfn->code, 32, 0x00000006, vb.vertex_size-3);
FIXUP(dfn->code, 37, 0x00000058, (int)&vb.vertex[3]);
FIXUP(dfn->code, 45, 0x01010101, (int)&vb.dmaptr);
FIXUP(dfn->code, 50, 0x02020202, (int)&vb.counter);
FIXUP(dfn->code, 58, 0x02020202, (int)&vb.counter);
FIXUP(dfn->code, 67, 0x0, (int)&vb.notify);
break;
}
}
return dfn;
}
struct dynfn *radeon_makeX86Normal3fv( GLcontext *ctx, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
int i = 0;
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
DFN ( _x86_Normal3fv, rmesa->vb.dfn_cache.Normal3fv );
FIXUP2(dfn->code, i, 0x0, (int)vb.normalptr);
FIXUP2(dfn->code, i, 0x4, 4+(int)vb.normalptr);
FIXUP2(dfn->code, i, 0x8, 8+(int)vb.normalptr);
fprintf(stderr, "%s done\n", __FUNCTION__);
return dfn;
}
struct dynfn *radeon_makeX86Normal3f( GLcontext *ctx, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
DFN ( _x86_Normal3f, rmesa->vb.dfn_cache.Normal3f );
FIXUP(dfn->code, 1, 0x12345678, (int)vb.normalptr);
return dfn;
}
struct dynfn *radeon_makeX86Color4ubv( GLcontext *ctx, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
if (key & RADEON_CP_VC_FRMT_PKCOLOR) {
DFN ( _x86_Color4ubv_ub, rmesa->vb.dfn_cache.Color4ubv);
FIXUP(dfn->code, 5, 0x12345678, (int)vb.colorptr);
return dfn;
}
else {
DFN ( _x86_Color4ubv_4f, rmesa->vb.dfn_cache.Color4ubv);
FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab);
FIXUP(dfn->code, 27, 0xdeadbeaf, (int)vb.floatcolorptr);
FIXUP(dfn->code, 33, 0xdeadbeaf, (int)vb.floatcolorptr+4);
FIXUP(dfn->code, 55, 0xdeadbeaf, (int)vb.floatcolorptr+8);
FIXUP(dfn->code, 61, 0xdeadbeaf, (int)vb.floatcolorptr+12);
return dfn;
}
}
struct dynfn *radeon_makeX86Color4ub( GLcontext *ctx, int key )
{
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
if (key & RADEON_CP_VC_FRMT_PKCOLOR) {
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
DFN ( _x86_Color4ub_ub, rmesa->vb.dfn_cache.Color4ub );
FIXUP(dfn->code, 18, 0x0, (int)vb.colorptr);
FIXUP(dfn->code, 24, 0x0, (int)vb.colorptr+1);
FIXUP(dfn->code, 30, 0x0, (int)vb.colorptr+2);
FIXUP(dfn->code, 36, 0x0, (int)vb.colorptr+3);
return dfn;
}
else
return 0;
}
struct dynfn *radeon_makeX86Color3fv( GLcontext *ctx, int key )
{
if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
return 0;
else
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
DFN ( _x86_Color3fv_3f, rmesa->vb.dfn_cache.Color3fv );
FIXUP(dfn->code, 5, 0x0, (int)vb.floatcolorptr);
return dfn;
}
}
struct dynfn *radeon_makeX86Color3f( GLcontext *ctx, int key )
{
if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
return 0;
else
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
DFN ( _x86_Color3f_3f, rmesa->vb.dfn_cache.Color3f );
FIXUP(dfn->code, 1, 0x12345678, (int)vb.floatcolorptr);
return dfn;
}
}
struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *ctx, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
DFN ( _x86_TexCoord2fv, rmesa->vb.dfn_cache.TexCoord2fv );
FIXUP(dfn->code, 5, 0x12345678, (int)vb.texcoordptr[0]);
return dfn;
}
struct dynfn *radeon_makeX86TexCoord2f( GLcontext *ctx, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
DFN ( _x86_TexCoord2f, rmesa->vb.dfn_cache.TexCoord2f );
FIXUP(dfn->code, 1, 0x12345678, (int)vb.texcoordptr[0]);
return dfn;
}
struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *ctx, int key )
{
#if 0
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x11, /* mov (%ecx),%edx */
0xc1, 0xe0, 0x03, /* shl $0x3,%eax */
0x8b, 0x49, 0x04, /* mov 0x4(%ecx),%ecx */
0x89, 0x90, 0, 0, 0, 0,/* mov %edx,DEST(%eax) */
0x89, 0x88, 0, 0, 0, 0,/* mov %ecx,DEST+8(%eax) */
0xc3, /* ret */
};
static char temp2[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x14, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%edx */
0x8b, 0x01, /* mov (%ecx),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x41, 0x04, /* mov 0x4(%ecx),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0xc3, /* ret */
};
#endif
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
(RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
DFN ( _x86_MultiTexCoord2fvARB, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
FIXUP(dfn->code, 26, 0xdeadbeef, (int)vb.texcoordptr[0]);
FIXUP(dfn->code, 32, 0xdeadbeef, (int)vb.texcoordptr[0]+4);
} else {
DFN ( _x86_MultiTexCoord2fvARB_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
FIXUP(dfn->code, 19, 0x0, (int)vb.texcoordptr);
}
return dfn;
}
struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *ctx,
int key )
{
#if 0
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0xc1, 0xe0, 0x03, /* shl $0x3,%eax */
0x89, 0x90, 0, 0, 0, 0, /* mov %edx,DEST(%eax) */
0x89, 0x88, 0, 0, 0, 0, /* mov %ecx,DEST+8(%eax) */
0xc3, /* ret */
};
static char temp2[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x04, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%eax */
0x89, 0x10, /* mov %edx,(%eax) */
0x89, 0x48, 0x04, /* mov %ecx,0x4(%eax) */
0xc3, /* ret */
};
#endif
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
(RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
DFN ( _x86_MultiTexCoord2fARB, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
FIXUP(dfn->code, 25, 0xdeadbeef, (int)vb.texcoordptr[0]);
FIXUP(dfn->code, 31, 0xdeadbeef, (int)vb.texcoordptr[0]+4);
}
else {
/* Note: this might get generated multiple times, even though the
* actual emitted code is the same.
*/
DFN ( _x86_MultiTexCoord2fARB_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
FIXUP(dfn->code, 23, 0x0, (int)vb.texcoordptr);
}
return dfn;
}
void radeonInitX86Codegen( struct dfn_generators *gen )
{
gen->Vertex3f = radeon_makeX86Vertex3f;
gen->Vertex3fv = radeon_makeX86Vertex3fv;
gen->Color4ub = radeon_makeX86Color4ub; /* PKCOLOR only */
gen->Color4ubv = radeon_makeX86Color4ubv; /* PKCOLOR only */
gen->Normal3f = radeon_makeX86Normal3f;
gen->Normal3fv = radeon_makeX86Normal3fv;
gen->TexCoord2f = radeon_makeX86TexCoord2f;
gen->TexCoord2fv = radeon_makeX86TexCoord2fv;
gen->MultiTexCoord2fARB = radeon_makeX86MultiTexCoord2fARB;
gen->MultiTexCoord2fvARB = radeon_makeX86MultiTexCoord2fvARB;
gen->Color3f = radeon_makeX86Color3f;
gen->Color3fv = radeon_makeX86Color3fv;
/* Not done:
*/
/* gen->Vertex2f = radeon_makeX86Vertex2f; */
/* gen->Vertex2fv = radeon_makeX86Vertex2fv; */
/* gen->Color3ub = radeon_makeX86Color3ub; */
/* gen->Color3ubv = radeon_makeX86Color3ubv; */
/* gen->Color4f = radeon_makeX86Color4f; */
/* gen->Color4fv = radeon_makeX86Color4fv; */
/* gen->TexCoord1f = radeon_makeX86TexCoord1f; */
/* gen->TexCoord1fv = radeon_makeX86TexCoord1fv; */
/* gen->MultiTexCoord1fARB = radeon_makeX86MultiTexCoord1fARB; */
/* gen->MultiTexCoord1fvARB = radeon_makeX86MultiTexCoord1fvARB; */
}
#else
void radeonInitX86Codegen( struct dfn_generators *gen )
{
(void) gen;
}
#endif