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

📄 r300_mem.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
字号:
/* * Copyright (C) 2005 Aapo Tahkola. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *//** * \file * * \author Aapo Tahkola <aet@rasterburn.org> */#include <unistd.h>#include "r300_context.h"#include "r300_cmdbuf.h"#include "r300_ioctl.h"#include "r300_mem.h"#include "radeon_ioctl.h"#ifdef USER_BUFFERSstatic void resize_u_list(r300ContextPtr rmesa){	void *temp;	int nsize;	temp = rmesa->rmm->u_list;	nsize = rmesa->rmm->u_size * 2;	rmesa->rmm->u_list = _mesa_malloc(nsize * sizeof(*rmesa->rmm->u_list));	_mesa_memset(rmesa->rmm->u_list, 0,		     nsize * sizeof(*rmesa->rmm->u_list));	if (temp) {		r300FlushCmdBuf(rmesa, __FUNCTION__);		_mesa_memcpy(rmesa->rmm->u_list, temp,			     rmesa->rmm->u_size * sizeof(*rmesa->rmm->u_list));		_mesa_free(temp);	}	rmesa->rmm->u_size = nsize;}void r300_mem_init(r300ContextPtr rmesa){	rmesa->rmm = malloc(sizeof(struct r300_memory_manager));	memset(rmesa->rmm, 0, sizeof(struct r300_memory_manager));	rmesa->rmm->u_size = 128;	resize_u_list(rmesa);}void r300_mem_destroy(r300ContextPtr rmesa){	_mesa_free(rmesa->rmm->u_list);	rmesa->rmm->u_list = NULL;	_mesa_free(rmesa->rmm);	rmesa->rmm = NULL;}void *r300_mem_ptr(r300ContextPtr rmesa, int id){	assert(id <= rmesa->rmm->u_last);	return rmesa->rmm->u_list[id].ptr;}int r300_mem_find(r300ContextPtr rmesa, void *ptr){	int i;	for (i = 1; i < rmesa->rmm->u_size + 1; i++)		if (rmesa->rmm->u_list[i].ptr &&		    ptr >= rmesa->rmm->u_list[i].ptr &&		    ptr <		    rmesa->rmm->u_list[i].ptr + rmesa->rmm->u_list[i].size)			break;	if (i < rmesa->rmm->u_size + 1)		return i;	fprintf(stderr, "%p failed\n", ptr);	return 0;}//#define MM_DEBUGint r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size){	drm_radeon_mem_alloc_t alloc;	int offset = 0, ret;	int i, free = -1;	int done_age;	drm_radeon_mem_free_t memfree;	int tries = 0;	static int bytes_wasted = 0, allocated = 0;	if (size < 4096)		bytes_wasted += 4096 - size;	allocated += size;#if 0	static int t = 0;	if (t != time(NULL)) {		t = time(NULL);		fprintf(stderr, "slots used %d, wasted %d kb, allocated %d\n",			rmesa->rmm->u_last, bytes_wasted / 1024,			allocated / 1024);	}#endif	memfree.region = RADEON_MEM_REGION_GART;      again:	done_age = radeonGetAge((radeonContextPtr) rmesa);	if (rmesa->rmm->u_last + 1 >= rmesa->rmm->u_size)		resize_u_list(rmesa);	for (i = rmesa->rmm->u_last + 1; i > 0; i--) {		if (rmesa->rmm->u_list[i].ptr == NULL) {			free = i;			continue;		}		if (rmesa->rmm->u_list[i].h_pending == 0 &&		    rmesa->rmm->u_list[i].pending		    && rmesa->rmm->u_list[i].age <= done_age) {			memfree.region_offset =			    (char *)rmesa->rmm->u_list[i].ptr -			    (char *)rmesa->radeon.radeonScreen->gartTextures.			    map;			ret =			    drmCommandWrite(rmesa->radeon.radeonScreen->					    driScreen->fd, DRM_RADEON_FREE,					    &memfree, sizeof(memfree));			if (ret) {				fprintf(stderr, "Failed to free at %p\n",					rmesa->rmm->u_list[i].ptr);				fprintf(stderr, "ret = %s\n", strerror(-ret));				exit(1);			} else {#ifdef MM_DEBUG				fprintf(stderr, "really freed %d at age %x\n",					i,					radeonGetAge((radeonContextPtr) rmesa));#endif				if (i == rmesa->rmm->u_last)					rmesa->rmm->u_last--;				if (rmesa->rmm->u_list[i].size < 4096)					bytes_wasted -=					    4096 - rmesa->rmm->u_list[i].size;				allocated -= rmesa->rmm->u_list[i].size;				rmesa->rmm->u_list[i].pending = 0;				rmesa->rmm->u_list[i].ptr = NULL;				free = i;			}		}	}	rmesa->rmm->u_head = i;	if (free == -1) {		WARN_ONCE("Ran out of slots!\n");		//usleep(100);		r300FlushCmdBuf(rmesa, __FUNCTION__);		tries++;		if (tries > 100) {			WARN_ONCE("Ran out of slots!\n");			exit(1);		}		goto again;	}	alloc.region = RADEON_MEM_REGION_GART;	alloc.alignment = alignment;	alloc.size = size;	alloc.region_offset = &offset;	ret =	    drmCommandWriteRead(rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc,				sizeof(alloc));	if (ret) {#if 0		WARN_ONCE("Ran out of mem!\n");		r300FlushCmdBuf(rmesa, __FUNCTION__);		//usleep(100);		tries2++;		tries = 0;		if (tries2 > 100) {			WARN_ONCE("Ran out of GART memory!\n");			exit(1);		}		goto again;#else		WARN_ONCE		    ("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n",		     size);		return 0;#endif	}	i = free;	if (i > rmesa->rmm->u_last)		rmesa->rmm->u_last = i;	rmesa->rmm->u_list[i].ptr =	    ((GLubyte *) rmesa->radeon.radeonScreen->gartTextures.map) + offset;	rmesa->rmm->u_list[i].size = size;	rmesa->rmm->u_list[i].age = 0;	//fprintf(stderr, "alloc %p at id %d\n", rmesa->rmm->u_list[i].ptr, i);#ifdef MM_DEBUG	fprintf(stderr, "allocated %d at age %x\n", i,		radeonGetAge((radeonContextPtr) rmesa));#endif	return i;}void r300_mem_use(r300ContextPtr rmesa, int id){	uint64_t ull;#ifdef MM_DEBUG	fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,		radeonGetAge((radeonContextPtr) rmesa));#endif	drm_r300_cmd_header_t *cmd;	assert(id <= rmesa->rmm->u_last);	if (id == 0)		return;	cmd =	    (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa,						      2 + sizeof(ull) / 4,						      __FUNCTION__);	cmd[0].scratch.cmd_type = R300_CMD_SCRATCH;	cmd[0].scratch.reg = R300_MEM_SCRATCH;	cmd[0].scratch.n_bufs = 1;	cmd[0].scratch.flags = 0;	cmd++;	ull = (uint64_t) (intptr_t) & rmesa->rmm->u_list[id].age;	_mesa_memcpy(cmd, &ull, sizeof(ull));	cmd += sizeof(ull) / 4;	cmd[0].u = /*id */ 0;	LOCK_HARDWARE(&rmesa->radeon);	/* Protect from DRM. */	rmesa->rmm->u_list[id].h_pending++;	UNLOCK_HARDWARE(&rmesa->radeon);}unsigned long r300_mem_offset(r300ContextPtr rmesa, int id){	unsigned long offset;	assert(id <= rmesa->rmm->u_last);	offset = (char *)rmesa->rmm->u_list[id].ptr -	    (char *)rmesa->radeon.radeonScreen->gartTextures.map;	offset += rmesa->radeon.radeonScreen->gart_texture_offset;	return offset;}void *r300_mem_map(r300ContextPtr rmesa, int id, int access){#ifdef MM_DEBUG	fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,		radeonGetAge((radeonContextPtr) rmesa));#endif	void *ptr;	int tries = 0;	assert(id <= rmesa->rmm->u_last);	if (access == R300_MEM_R) {		if (rmesa->rmm->u_list[id].mapped == 1)			WARN_ONCE("buffer %d already mapped\n", id);		rmesa->rmm->u_list[id].mapped = 1;		ptr = r300_mem_ptr(rmesa, id);		return ptr;	}	if (rmesa->rmm->u_list[id].h_pending)		r300FlushCmdBuf(rmesa, __FUNCTION__);	if (rmesa->rmm->u_list[id].h_pending) {		return NULL;	}	while (rmesa->rmm->u_list[id].age >	       radeonGetAge((radeonContextPtr) rmesa) && tries++ < 1000)		usleep(10);	if (tries >= 1000) {		fprintf(stderr, "Idling failed (%x vs %x)\n",			rmesa->rmm->u_list[id].age,			radeonGetAge((radeonContextPtr) rmesa));		return NULL;	}	if (rmesa->rmm->u_list[id].mapped == 1)		WARN_ONCE("buffer %d already mapped\n", id);	rmesa->rmm->u_list[id].mapped = 1;	ptr = r300_mem_ptr(rmesa, id);	return ptr;}void r300_mem_unmap(r300ContextPtr rmesa, int id){#ifdef MM_DEBUG	fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,		radeonGetAge((radeonContextPtr) rmesa));#endif	assert(id <= rmesa->rmm->u_last);	if (rmesa->rmm->u_list[id].mapped == 0)		WARN_ONCE("buffer %d not mapped\n", id);	rmesa->rmm->u_list[id].mapped = 0;}void r300_mem_free(r300ContextPtr rmesa, int id){#ifdef MM_DEBUG	fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,		radeonGetAge((radeonContextPtr) rmesa));#endif	assert(id <= rmesa->rmm->u_last);	if (id == 0)		return;	if (rmesa->rmm->u_list[id].ptr == NULL) {		WARN_ONCE("Not allocated!\n");		return;	}	if (rmesa->rmm->u_list[id].pending) {		WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr);		return;	}	rmesa->rmm->u_list[id].pending = 1;}#endif

⌨️ 快捷键说明

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