301 lines
10 KiB
C
301 lines
10 KiB
C
/*
|
|
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
|
|
|
|
The Weather Channel (TM) funded Tungsten Graphics to develop the
|
|
initial release of the Radeon 8500 driver under the XFree86 license.
|
|
This notice must be preserved.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
"Software"), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice (including the
|
|
next paragraph) shall be included in all copies or substantial
|
|
portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
* Authors:
|
|
* Keith Whitwell <keithw@vmware.com>
|
|
*/
|
|
|
|
#include "main/glheader.h"
|
|
|
|
#include "main/macros.h"
|
|
#include "main/context.h"
|
|
#include "util/simple_list.h"
|
|
|
|
#include "radeon_common.h"
|
|
#include "r200_context.h"
|
|
#include "r200_ioctl.h"
|
|
#include "radeon_reg.h"
|
|
|
|
/* The state atoms will be emitted in the order they appear in the atom list,
|
|
* so this step is important.
|
|
*/
|
|
#define insert_at_tail_if(atom_list, atom) \
|
|
do { \
|
|
struct radeon_state_atom* current_atom = (atom); \
|
|
if (current_atom->check) \
|
|
insert_at_tail((atom_list), current_atom); \
|
|
} while(0)
|
|
|
|
void r200SetUpAtomList( r200ContextPtr rmesa )
|
|
{
|
|
int i, mtu;
|
|
|
|
mtu = rmesa->radeon.glCtx.Const.MaxTextureUnits;
|
|
|
|
make_empty_list(&rmesa->radeon.hw.atomlist);
|
|
rmesa->radeon.hw.atomlist.name = "atom-list";
|
|
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ctx );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.set );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lin );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msk );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpt );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vtx );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vap );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vte );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msc );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cst );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.zbs );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcl );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msl );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcg );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.grd );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.fog );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tam );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tf );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.atf );
|
|
for (i = 0; i < mtu; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i] );
|
|
for (i = 0; i < mtu; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i] );
|
|
for (i = 0; i < 6; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.stp );
|
|
for (i = 0; i < 8; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] );
|
|
for (i = 0; i < 3 + mtu; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.eye );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.glt );
|
|
for (i = 0; i < 2; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mtl[i] );
|
|
for (i = 0; i < 6; ++i)
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.spr );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ptp );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.prf );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pvs );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[0] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[1] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[0] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[1] );
|
|
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.sci );
|
|
}
|
|
|
|
/* Fire a section of the retained (indexed_verts) buffer as a regular
|
|
* primtive.
|
|
*/
|
|
void r200EmitVbufPrim( r200ContextPtr rmesa,
|
|
GLuint primitive,
|
|
GLuint vertex_nr )
|
|
{
|
|
BATCH_LOCALS(&rmesa->radeon);
|
|
|
|
assert(!(primitive & R200_VF_PRIM_WALK_IND));
|
|
|
|
radeonEmitState(&rmesa->radeon);
|
|
|
|
radeon_print(RADEON_RENDER|RADEON_SWRENDER,RADEON_VERBOSE,
|
|
"%s cmd_used/4: %d prim %x nr %d\n", __func__,
|
|
rmesa->store.cmd_used/4, primitive, vertex_nr);
|
|
|
|
BEGIN_BATCH(3);
|
|
OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_VBUF_2, 0);
|
|
OUT_BATCH(primitive | R200_VF_PRIM_WALK_LIST | R200_VF_COLOR_ORDER_RGBA |
|
|
(vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
|
|
END_BATCH();
|
|
}
|
|
|
|
static void r200FireEB(r200ContextPtr rmesa, int vertex_count, int type)
|
|
{
|
|
BATCH_LOCALS(&rmesa->radeon);
|
|
|
|
if (vertex_count > 0) {
|
|
BEGIN_BATCH(8+2);
|
|
OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_INDX_2, 0);
|
|
OUT_BATCH(R200_VF_PRIM_WALK_IND |
|
|
R200_VF_COLOR_ORDER_RGBA |
|
|
((vertex_count + 0) << 16) |
|
|
type);
|
|
|
|
OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
|
|
OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
|
|
OUT_BATCH(rmesa->radeon.tcl.elt_dma_offset);
|
|
OUT_BATCH((vertex_count + 1)/2);
|
|
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
|
|
rmesa->radeon.tcl.elt_dma_bo,
|
|
RADEON_GEM_DOMAIN_GTT, 0, 0);
|
|
END_BATCH();
|
|
}
|
|
}
|
|
|
|
void r200FlushElts(struct gl_context *ctx)
|
|
{
|
|
r200ContextPtr rmesa = R200_CONTEXT(ctx);
|
|
int nr, elt_used = rmesa->tcl.elt_used;
|
|
|
|
radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x %d\n", __func__, rmesa->tcl.hw_primitive, elt_used);
|
|
|
|
assert( rmesa->radeon.dma.flush == r200FlushElts );
|
|
rmesa->radeon.dma.flush = NULL;
|
|
|
|
nr = elt_used / 2;
|
|
|
|
radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo);
|
|
|
|
r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive);
|
|
|
|
radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo);
|
|
rmesa->radeon.tcl.elt_dma_bo = NULL;
|
|
|
|
if (R200_ELT_BUF_SZ > elt_used)
|
|
radeonReturnDmaRegion(&rmesa->radeon, R200_ELT_BUF_SZ - elt_used);
|
|
}
|
|
|
|
|
|
GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
|
|
GLuint primitive,
|
|
GLuint min_nr )
|
|
{
|
|
GLushort *retval;
|
|
|
|
radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %d prim %x\n", __func__, min_nr, primitive);
|
|
|
|
assert((primitive & R200_VF_PRIM_WALK_IND));
|
|
|
|
radeonEmitState(&rmesa->radeon);
|
|
|
|
radeonAllocDmaRegion(&rmesa->radeon, &rmesa->radeon.tcl.elt_dma_bo,
|
|
&rmesa->radeon.tcl.elt_dma_offset, R200_ELT_BUF_SZ, 4);
|
|
rmesa->tcl.elt_used = min_nr * 2;
|
|
|
|
radeon_bo_map(rmesa->radeon.tcl.elt_dma_bo, 1);
|
|
retval = rmesa->radeon.tcl.elt_dma_bo->ptr + rmesa->radeon.tcl.elt_dma_offset;
|
|
|
|
assert(!rmesa->radeon.dma.flush);
|
|
rmesa->radeon.glCtx.Driver.NeedFlush |= FLUSH_STORED_VERTICES;
|
|
rmesa->radeon.dma.flush = r200FlushElts;
|
|
|
|
return retval;
|
|
}
|
|
|
|
void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count)
|
|
{
|
|
BATCH_LOCALS(&rmesa->radeon);
|
|
|
|
BEGIN_BATCH(2);
|
|
OUT_BATCH(CP_PACKET0(R200_SE_VF_MAX_VTX_INDX, 0));
|
|
OUT_BATCH(count);
|
|
END_BATCH();
|
|
}
|
|
|
|
void r200EmitVertexAOS( r200ContextPtr rmesa,
|
|
GLuint vertex_size,
|
|
struct radeon_bo *bo,
|
|
GLuint offset )
|
|
{
|
|
BATCH_LOCALS(&rmesa->radeon);
|
|
|
|
radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s: vertex_size 0x%x offset 0x%x \n",
|
|
__func__, vertex_size, offset);
|
|
|
|
|
|
BEGIN_BATCH(7);
|
|
OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, 2);
|
|
OUT_BATCH(1);
|
|
OUT_BATCH(vertex_size | (vertex_size << 8));
|
|
OUT_BATCH_RELOC(bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
|
|
END_BATCH();
|
|
}
|
|
|
|
void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset)
|
|
{
|
|
BATCH_LOCALS(&rmesa->radeon);
|
|
uint32_t voffset;
|
|
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
|
|
int i;
|
|
|
|
radeon_print(RADEON_RENDER, RADEON_VERBOSE,
|
|
"%s: nr=%d, ofs=0x%08x\n",
|
|
__func__, nr, offset);
|
|
|
|
BEGIN_BATCH(sz+2+ (nr*2));
|
|
OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, sz - 1);
|
|
OUT_BATCH(nr);
|
|
|
|
{
|
|
for (i = 0; i + 1 < nr; i += 2) {
|
|
OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
|
|
(rmesa->radeon.tcl.aos[i].stride << 8) |
|
|
(rmesa->radeon.tcl.aos[i + 1].components << 16) |
|
|
(rmesa->radeon.tcl.aos[i + 1].stride << 24));
|
|
|
|
voffset = rmesa->radeon.tcl.aos[i + 0].offset +
|
|
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
|
|
OUT_BATCH(voffset);
|
|
voffset = rmesa->radeon.tcl.aos[i + 1].offset +
|
|
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
|
|
OUT_BATCH(voffset);
|
|
}
|
|
|
|
if (nr & 1) {
|
|
OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
|
|
(rmesa->radeon.tcl.aos[nr - 1].stride << 8));
|
|
voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
|
|
offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
|
|
OUT_BATCH(voffset);
|
|
}
|
|
for (i = 0; i + 1 < nr; i += 2) {
|
|
voffset = rmesa->radeon.tcl.aos[i + 0].offset +
|
|
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
|
|
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
|
|
rmesa->radeon.tcl.aos[i+0].bo,
|
|
RADEON_GEM_DOMAIN_GTT,
|
|
0, 0);
|
|
voffset = rmesa->radeon.tcl.aos[i + 1].offset +
|
|
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
|
|
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
|
|
rmesa->radeon.tcl.aos[i+1].bo,
|
|
RADEON_GEM_DOMAIN_GTT,
|
|
0, 0);
|
|
}
|
|
if (nr & 1) {
|
|
voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
|
|
offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
|
|
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
|
|
rmesa->radeon.tcl.aos[nr-1].bo,
|
|
RADEON_GEM_DOMAIN_GTT,
|
|
0, 0);
|
|
}
|
|
}
|
|
END_BATCH();
|
|
}
|