⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r300_cmdbuf.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
/*Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.The Weather Channel (TM) funded Tungsten Graphics to develop theinitial 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 obtaininga copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice (including thenext paragraph) shall be included in all copies or substantialportions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BELIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIONOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTIONWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**************************************************************************//** * \file * * \author Nicolai Haehnle <prefect_@gmx.net> */#include "glheader.h"#include "state.h"#include "imports.h"#include "macros.h"#include "context.h"#include "swrast/swrast.h"#include "simple_list.h"#include "drm.h"#include "radeon_drm.h"#include "radeon_ioctl.h"#include "r300_context.h"#include "r300_ioctl.h"#include "radeon_reg.h"#include "r300_reg.h"#include "r300_cmdbuf.h"#include "r300_emit.h"#include "r300_state.h"// Set this to 1 for extremely verbose debugging of command buffers#define DEBUG_CMDBUF		0/** * Send the current command buffer via ioctl to the hardware. */int r300FlushCmdBufLocked(r300ContextPtr r300, const char *caller){	int ret;	int i;	drm_radeon_cmd_buffer_t cmd;	int start;	if (r300->radeon.lost_context) {		start = 0;		r300->radeon.lost_context = GL_FALSE;	} else		start = r300->cmdbuf.count_reemit;	if (RADEON_DEBUG & DEBUG_IOCTL) {		fprintf(stderr, "%s from %s - %i cliprects\n",			__FUNCTION__, caller, r300->radeon.numClipRects);		if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_VERBOSE)			for (i = start; i < r300->cmdbuf.count_used; ++i)				fprintf(stderr, "%d: %08x\n", i,					r300->cmdbuf.cmd_buf[i]);	}	cmd.buf = (char *)(r300->cmdbuf.cmd_buf + start);	cmd.bufsz = (r300->cmdbuf.count_used - start) * 4;	if (r300->radeon.state.scissor.enabled) {		cmd.nbox = r300->radeon.state.scissor.numClipRects;		cmd.boxes =		    (drm_clip_rect_t *) r300->radeon.state.scissor.pClipRects;	} else {		cmd.nbox = r300->radeon.numClipRects;		cmd.boxes = (drm_clip_rect_t *) r300->radeon.pClipRects;	}	ret = drmCommandWrite(r300->radeon.dri.fd,			      DRM_RADEON_CMDBUF, &cmd, sizeof(cmd));	if (RADEON_DEBUG & DEBUG_SYNC) {		fprintf(stderr, "Syncing in %s (from %s)\n\n",			__FUNCTION__, caller);		radeonWaitForIdleLocked(&r300->radeon);	}	r300->dma.nr_released_bufs = 0;	r300->cmdbuf.count_used = 0;	r300->cmdbuf.count_reemit = 0;	return ret;}int r300FlushCmdBuf(r300ContextPtr r300, const char *caller){	int ret;	LOCK_HARDWARE(&r300->radeon);	ret = r300FlushCmdBufLocked(r300, caller);	UNLOCK_HARDWARE(&r300->radeon);	if (ret) {		fprintf(stderr, "drmRadeonCmdBuffer: %d\n", ret);		_mesa_exit(ret);	}	return ret;}static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *state){	int i;	int dwords = (*state->check) (r300, state);	fprintf(stderr, "  emit %s %d/%d\n", state->name, dwords,		state->cmd_size);	if (RADEON_DEBUG & DEBUG_VERBOSE) {		for (i = 0; i < dwords; i++) {			fprintf(stderr, "      %s[%d]: %08x\n",				state->name, i, state->cmd[i]);		}	}}/** * Emit all atoms with a dirty field equal to dirty. * * The caller must have ensured that there is enough space in the command * buffer. */static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty){	struct r300_state_atom *atom;	uint32_t *dest;	int dwords;	dest = r300->cmdbuf.cmd_buf + r300->cmdbuf.count_used;	/* Emit WAIT */	*dest = cmdwait(R300_WAIT_3D | R300_WAIT_3D_CLEAN);	dest++;	r300->cmdbuf.count_used++;	/* Emit cache flush */	*dest = cmdpacket0(R300_TX_INVALTAGS, 1);	dest++;	r300->cmdbuf.count_used++;	*dest = R300_TX_FLUSH;	dest++;	r300->cmdbuf.count_used++;	/* Emit END3D */	*dest = cmdpacify();	dest++;	r300->cmdbuf.count_used++;	/* Emit actual atoms */	foreach(atom, &r300->hw.atomlist) {		if ((atom->dirty || r300->hw.all_dirty) == dirty) {			dwords = (*atom->check) (r300, atom);			if (dwords) {				if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {					r300PrintStateAtom(r300, atom);				}				memcpy(dest, atom->cmd, dwords * 4);				dest += dwords;				r300->cmdbuf.count_used += dwords;				atom->dirty = GL_FALSE;			} else {				if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {					fprintf(stderr, "  skip state %s\n",						atom->name);				}			}		}	}}/** * Copy dirty hardware state atoms into the command buffer. * * We also copy out clean state if we're at the start of a buffer. That makes * it easy to recover from lost contexts. */void r300EmitState(r300ContextPtr r300){	if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_PRIMS))		fprintf(stderr, "%s\n", __FUNCTION__);	if (r300->cmdbuf.count_used && !r300->hw.is_dirty	    && !r300->hw.all_dirty)		return;	/* To avoid going across the entire set of states multiple times, just check	 * for enough space for the case of emitting all state, and inline the	 * r300AllocCmdBuf code here without all the checks.	 */	r300EnsureCmdBufSpace(r300, r300->hw.max_state_size, __FUNCTION__);	if (!r300->cmdbuf.count_used) {		if (RADEON_DEBUG & DEBUG_STATE)			fprintf(stderr, "Begin reemit state\n");		r300EmitAtoms(r300, GL_FALSE);		r300->cmdbuf.count_reemit = r300->cmdbuf.count_used;	}	if (RADEON_DEBUG & DEBUG_STATE)		fprintf(stderr, "Begin dirty state\n");	r300EmitAtoms(r300, GL_TRUE);	assert(r300->cmdbuf.count_used < r300->cmdbuf.size);	r300->hw.is_dirty = GL_FALSE;	r300->hw.all_dirty = GL_FALSE;}#define packet0_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->packet0.count)#define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)#define r500fp_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->r500fp.count)static int check_always(r300ContextPtr r300, struct r300_state_atom *atom){	return atom->cmd_size;}static int check_variable(r300ContextPtr r300, struct r300_state_atom *atom){	int cnt;	cnt = packet0_count(atom->cmd);	return cnt ? cnt + 1 : 0;}static int check_vpu(r300ContextPtr r300, struct r300_state_atom *atom){	int cnt;	cnt = vpu_count(atom->cmd);	return cnt ? (cnt * 4) + 1 : 0;}static int check_r500fp(r300ContextPtr r300, struct r300_state_atom *atom){	int cnt;	cnt = r500fp_count(atom->cmd);	return cnt ? (cnt * 6) + 1 : 0;}static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom){	int cnt;	cnt = r500fp_count(atom->cmd);	return cnt ? (cnt * 4) + 1 : 0;}#define ALLOC_STATE( ATOM, CHK, SZ, IDX )				\   do {									\      r300->hw.ATOM.cmd_size = (SZ);					\      r300->hw.ATOM.cmd = (uint32_t*)CALLOC((SZ) * sizeof(uint32_t));	\      r300->hw.ATOM.name = #ATOM;					\      r300->hw.ATOM.idx = (IDX);					\      r300->hw.ATOM.check = check_##CHK;				\      r300->hw.ATOM.dirty = GL_FALSE;					\      r300->hw.max_state_size += (SZ);					\      insert_at_tail(&r300->hw.atomlist, &r300->hw.ATOM);		\   } while (0)/** * Allocate memory for the command buffer and initialize the state atom * list. Note that the initial hardware state is set by r300InitState(). */void r300InitCmdBuf(r300ContextPtr r300){	int size, mtu;	int has_tcl = 1;	int is_r500 = 0;	int i;	if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))		has_tcl = 0;	if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)		is_r500 = 1;	r300->hw.max_state_size = 2 + 2;	/* reserve extra space for WAIT_IDLE and tex cache flush */	mtu = r300->radeon.glCtx->Const.MaxTextureUnits;	if (RADEON_DEBUG & DEBUG_TEXTURE) {		fprintf(stderr, "Using %d maximum texture units..\n", mtu);	}	/* Setup the atom linked list */	make_empty_list(&r300->hw.atomlist);	r300->hw.atomlist.name = "atom-list";	/* Initialize state atoms */	ALLOC_STATE(vpt, always, R300_VPT_CMDSIZE, 0);	r300->hw.vpt.cmd[R300_VPT_CMD_0] = cmdpacket0(R300_SE_VPORT_XSCALE, 6);	ALLOC_STATE(vap_cntl, always, R300_VAP_CNTL_SIZE, 0);	r300->hw.vap_cntl.cmd[R300_VAP_CNTL_FLUSH] = cmdpacket0(R300_VAP_PVS_STATE_FLUSH_REG, 1);	r300->hw.vap_cntl.cmd[R300_VAP_CNTL_FLUSH_1] = 0;	r300->hw.vap_cntl.cmd[R300_VAP_CNTL_CMD] = cmdpacket0(R300_VAP_CNTL, 1);	if (is_r500) {	    ALLOC_STATE(vap_index_offset, always, 2, 0);	    r300->hw.vap_index_offset.cmd[0] = cmdpacket0(R500_VAP_INDEX_OFFSET, 1);	    r300->hw.vap_index_offset.cmd[1] = 0;	}	ALLOC_STATE(vte, always, 3, 0);	r300->hw.vte.cmd[0] = cmdpacket0(R300_SE_VTE_CNTL, 2);	ALLOC_STATE(vap_vf_max_vtx_indx, always, 3, 0);	r300->hw.vap_vf_max_vtx_indx.cmd[0] = cmdpacket0(R300_VAP_VF_MAX_VTX_INDX, 2);	ALLOC_STATE(vap_cntl_status, always, 2, 0);	r300->hw.vap_cntl_status.cmd[0] = cmdpacket0(R300_VAP_CNTL_STATUS, 1);	ALLOC_STATE(vir[0], variable, R300_VIR_CMDSIZE, 0);	r300->hw.vir[0].cmd[R300_VIR_CMD_0] =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -