radeon_dma.c revision e9c2c4a76466fc1ccfbf4d5de048414f7126b940
1cf5933a716e7eb6bd5ff49aa62f3e76379ebaf51Chris Lattner/**************************************************************************
2fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman
3b576c94c15af9a440f69d9d03c2afead7971118cJohn CriswellCopyright (C) 2004 Nicolai Haehnle.
4b576c94c15af9a440f69d9d03c2afead7971118cJohn CriswellCopyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner
64ee451de366474b9c228b4e5fa573795a715216dChris LattnerThe Weather Channel (TM) funded Tungsten Graphics to develop the
7fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukmaninitial release of the Radeon 8500 driver under the XFree86 license.
8b576c94c15af9a440f69d9d03c2afead7971118cJohn CriswellThis notice must be preserved.
9237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner
10befa499d45ffcc32bd9902518aec18589464e47cChris LattnerAll Rights Reserved.
11befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
12befa499d45ffcc32bd9902518aec18589464e47cChris LattnerPermission is hereby granted, free of charge, to any person obtaining a
13237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattnercopy of this software and associated documentation files (the "Software"),
14237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattnerto deal in the Software without restriction, including without limitation
15237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattneron the rights to use, copy, modify, merge, publish, distribute, sub
1686453c52ba02e743d29c08456e51006500041456Chris Lattnerlicense, and/or sell copies of the Software, and to permit persons to whom
17237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattnerthe Software is furnished to do so, subject to the following conditions:
1847b14a4a6a455c7be169cfd312fcbe796f0ad426Misha Brukman
191f67ce4aa3f65619f54c8a3072539da5b0022841Dale JohannesenThe above copyright notice and this permission notice (including the next
20237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattnerparagraph) shall be included in all copies or substantial portions of the
21237ef567f6764f24a47c63121cc0a599ddc8f56dChris LattnerSoftware.
22ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner
236f7426ec2e46bb19cc9f9e75f1c355b35cf12d7dTanya LattnerTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24237ef567f6764f24a47c63121cc0a599ddc8f56dChris LattnerIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid SpencerFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
26551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid SpencerATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid SpencerDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
28befa499d45ffcc32bd9902518aec18589464e47cChris LattnerOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
29a51bcb50b0c74adc741361824ef81dbefb715c53Chris LattnerUSE OR OTHER DEALINGS IN THE SOFTWARE.
30d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
3186453c52ba02e743d29c08456e51006500041456Chris Lattner**************************************************************************/
3286453c52ba02e743d29c08456e51006500041456Chris Lattner
3386453c52ba02e743d29c08456e51006500041456Chris Lattner#include <errno.h>
34844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "radeon_common.h"
35cbfdf9644ce38fd3404469c26ac3c8466c940b6eDale Johannesen#include "main/simple_list.h"
36cbfdf9644ce38fd3404469c26ac3c8466c940b6eDale Johannesen
37237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner#if defined(USE_X86_ASM)
38ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman#define COPY_DWORDS( dst, src, nr )					\
39ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohmando {									\
40237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner	int __tmp;							\
41ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman	__asm__ __volatile__( "rep ; movsl"				\
42ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman			      : "=%c" (__tmp), "=D" (dst), "=S" (__tmp)	\
43120d053e3ba810b44047fbcb719824bed5673ca9Chris Lattner			      : "0" (nr),				\
44ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner			        "D" ((long)dst),			\
45ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner			        "S" ((long)src) );			\
46ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner} while (0)
47ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#else
48ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#define COPY_DWORDS( dst, src, nr )		\
49ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattnerdo {						\
50ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner   int j;					\
51ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner   for ( j = 0 ; j < nr ; j++ )			\
52befa499d45ffcc32bd9902518aec18589464e47cChris Lattner      dst[j] = ((int *)src)[j];			\
53befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   dst += nr;					\
541f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen} while (0)
55ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#endif
56ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner
57befa499d45ffcc32bd9902518aec18589464e47cChris Lattnervoid radeonEmitVec4(uint32_t *out, const GLvoid * data, int stride, int count)
5866c75aaa028683c389c55b377ee2411b61081677Bill Wendling{
5966c75aaa028683c389c55b377ee2411b61081677Bill Wendling	int i;
60ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner
61fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman	if (RADEON_DEBUG & RADEON_VERTS)
628c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling		fprintf(stderr, "%s count %d stride %d out %p data %p\n",
638c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling			__FUNCTION__, count, stride, (void *)out, (void *)data);
648c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling
658c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling	if (stride == 4)
668c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling		COPY_DWORDS(out, data, count);
678c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling	else
688c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling		for (i = 0; i < count; i++) {
698c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling			out[0] = *(int *)data;
7054970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner			out++;
7154970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner			data += stride;
72bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola		}
73befa499d45ffcc32bd9902518aec18589464e47cChris Lattner}
740a81aac4b46eed130d20714af5a1c01b05d0275eBill Wendling
756f0a7687ab9a0509e847279fae27554ce7da0ba1Duncan Sandsvoid radeonEmitVec8(uint32_t *out, const GLvoid * data, int stride, int count)
76fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman{
77befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	int i;
786f0a7687ab9a0509e847279fae27554ce7da0ba1Duncan Sands
79fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman	if (RADEON_DEBUG & RADEON_VERTS)
801f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen		fprintf(stderr, "%s count %d stride %d out %p data %p\n",
811f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen			__FUNCTION__, count, stride, (void *)out, (void *)data);
82befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
83befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	if (stride == 8)
84befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		COPY_DWORDS(out, data, count * 2);
85befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	else
86befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		for (i = 0; i < count; i++) {
87237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner			out[0] = *(int *)data;
881a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			out[1] = *(int *)(data + 4);
891a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			out += 2;
901a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			data += stride;
911a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar		}
92c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar}
931a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
941a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbarvoid radeonEmitVec12(uint32_t *out, const GLvoid * data, int stride, int count)
95c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar{
96c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar	int i;
97c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar
98c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar	if (RADEON_DEBUG & RADEON_VERTS)
99c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar		fprintf(stderr, "%s count %d stride %d out %p data %p\n",
100c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar			__FUNCTION__, count, stride, (void *)out, (void *)data);
101c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar
102c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar	if (stride == 12) {
103c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar		COPY_DWORDS(out, data, count * 3);
104c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar    }
105c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar	else
106c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar		for (i = 0; i < count; i++) {
107c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar			out[0] = *(int *)data;
1081a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			out[1] = *(int *)(data + 4);
1091a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			out[2] = *(int *)(data + 8);
1101a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			out += 3;
1111a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			data += stride;
1121a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar		}
1131a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar}
1141a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
1151a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbarvoid radeonEmitVec16(uint32_t *out, const GLvoid * data, int stride, int count)
1161a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar{
1171a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar	int i;
1181a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
1191a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar	if (RADEON_DEBUG & RADEON_VERTS)
1201a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar		fprintf(stderr, "%s count %d stride %d out %p data %p\n",
1211a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar			__FUNCTION__, count, stride, (void *)out, (void *)data);
1221a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
1231a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar	if (stride == 16)
1241a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar		COPY_DWORDS(out, data, count * 4);
1251a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar	else
126237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner		for (i = 0; i < count; i++) {
127237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner			out[0] = *(int *)data;
128237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner			out[1] = *(int *)(data + 4);
1291f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen			out[2] = *(int *)(data + 8);
130237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner			out[3] = *(int *)(data + 12);
131237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner			out += 4;
1320a81aac4b46eed130d20714af5a1c01b05d0275eBill Wendling			data += stride;
133237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner		}
134befa499d45ffcc32bd9902518aec18589464e47cChris Lattner}
135befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
1360a81aac4b46eed130d20714af5a1c01b05d0275eBill Wendlingvoid rcommon_emit_vector(GLcontext * ctx, struct radeon_aos *aos,
137237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner			 const GLvoid * data, int size, int stride, int count)
138237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner{
139befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
140befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	uint32_t *out;
141befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
142befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	if (stride == 0) {
143befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
144cf5933a716e7eb6bd5ff49aa62f3e76379ebaf51Chris Lattner		count = 1;
145cf5933a716e7eb6bd5ff49aa62f3e76379ebaf51Chris Lattner		aos->stride = 0;
146befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	} else {
147befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * count * 4, 32);
148befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		aos->stride = size;
1491f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen	}
1501f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen
1515cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer	aos->components = size;
152befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	aos->count = count;
153befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
154237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner	radeon_bo_map(aos->bo, 1);
1550a81aac4b46eed130d20714af5a1c01b05d0275eBill Wendling	out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
156fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman	switch (size) {
157befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	case 1: radeonEmitVec4(out, data, stride, count); break;
158befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	case 2: radeonEmitVec8(out, data, stride, count); break;
159befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	case 3: radeonEmitVec12(out, data, stride, count); break;
160befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	case 4: radeonEmitVec16(out, data, stride, count); break;
161befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	default:
162befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		assert(0);
163befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		break;
164fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman	}
165befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	radeon_bo_unmap(aos->bo);
166befa499d45ffcc32bd9902518aec18589464e47cChris Lattner}
167befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
168befa499d45ffcc32bd9902518aec18589464e47cChris Lattnervoid radeon_init_dma(radeonContextPtr rmesa)
169befa499d45ffcc32bd9902518aec18589464e47cChris Lattner{
170befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	make_empty_list(&rmesa->dma.free);
171befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	make_empty_list(&rmesa->dma.wait);
172befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	make_empty_list(&rmesa->dma.reserved);
173befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	rmesa->dma.minimum_size = MAX_DMA_BUF_SZ;
174befa499d45ffcc32bd9902518aec18589464e47cChris Lattner}
175befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
176cbfdf9644ce38fd3404469c26ac3c8466c940b6eDale Johannesenvoid radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size)
17708ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner{
17808ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner	struct radeon_dma_bo *dma_bo = NULL;
17908ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner	/* we set minimum sizes to at least requested size
18008ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner	   aligned to next 16 bytes. */
18108ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner	if (size > rmesa->dma.minimum_size)
18208ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		rmesa->dma.minimum_size = (size + 15) & (~15);
18308ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner
184befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	radeon_print(RADEON_DMA, RADEON_NORMAL, "%s size %d minimum_size %d\n",
185befa499d45ffcc32bd9902518aec18589464e47cChris Lattner			__FUNCTION__, size, rmesa->dma.minimum_size);
186befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
187befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	if (is_empty_list(&rmesa->dma.free)
188befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	      || last_elem(&rmesa->dma.free)->bo->size < size) {
189befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		dma_bo = CALLOC_STRUCT(radeon_dma_bo);
190befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		assert(dma_bo);
1911a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
192e345566f8eaeeda45e29e3709114a42209a360ccDale Johannesenagain_alloc:
193befa499d45ffcc32bd9902518aec18589464e47cChris Lattner		dma_bo->bo = radeon_bo_open(rmesa->radeonScreen->bom,
1941f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen					    0, rmesa->dma.minimum_size, 4,
1951f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen					    RADEON_GEM_DOMAIN_GTT, 0);
1961f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen
1971f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen		if (!dma_bo->bo) {
198e345566f8eaeeda45e29e3709114a42209a360ccDale Johannesen			rcommonFlushCmdBuf(rmesa, __FUNCTION__);
199e345566f8eaeeda45e29e3709114a42209a360ccDale Johannesen			goto again_alloc;
20008ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		}
20108ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		insert_at_head(&rmesa->dma.reserved, dma_bo);
20208ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner	} else {
20308ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		/* We push and pop buffers from end of list so we can keep
20408ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		   counter on unused buffers for later freeing them from
20508ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		   begin of list */
20608ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		dma_bo = last_elem(&rmesa->dma.free);
20708ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		remove_from_list(dma_bo);
20808ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner		insert_at_head(&rmesa->dma.reserved, dma_bo);
20908ff1480ffcb22e946c7bb6c7d66c5d977ae3d6eChris Lattner	}
210befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
211befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	rmesa->dma.current_used = 0;
212befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	rmesa->dma.current_vertexptr = 0;
213befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
214befa499d45ffcc32bd9902518aec18589464e47cChris Lattner	if (radeon_cs_space_check_with_bo(rmesa->cmdbuf.cs,
215775cbdd51a3b33dd5eb343689f65ab5cc8ac7118Chris Lattner					  first_elem(&rmesa->dma.reserved)->bo,
216237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner					  RADEON_GEM_DOMAIN_GTT, 0))
217237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner		fprintf(stderr,"failure to revalidate BOs - badness\n");
218befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
219237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner	if (is_empty_list(&rmesa->dma.reserved)) {
220775cbdd51a3b33dd5eb343689f65ab5cc8ac7118Chris Lattner        /* Cmd buff have been flushed in radeon_revalidate_bos */
221237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner		goto again_alloc;
222d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke	}
22368d57e7ae80044401efd889270a12c71b3efb9abChris Lattner	radeon_bo_map(first_elem(&rmesa->dma.reserved)->bo, 1);
22468d57e7ae80044401efd889270a12c71b3efb9abChris Lattner}
22568d57e7ae80044401efd889270a12c71b3efb9abChris Lattner
226b7c6bf1e073088635951435acedff793add1cefdDevang Patel/* Allocates a region from rmesa->dma.current.  If there isn't enough
227b7c6bf1e073088635951435acedff793add1cefdDevang Patel * space in current, grab a new buffer (and discard what was left of current)
228b7c6bf1e073088635951435acedff793add1cefdDevang Patel */
229b7c6bf1e073088635951435acedff793add1cefdDevang Patelvoid radeonAllocDmaRegion(radeonContextPtr rmesa,
230b7c6bf1e073088635951435acedff793add1cefdDevang Patel			  struct radeon_bo **pbo, int *poffset,
231b7c6bf1e073088635951435acedff793add1cefdDevang Patel			  int bytes, int alignment)
232b7c6bf1e073088635951435acedff793add1cefdDevang Patel{
2333e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	if (RADEON_DEBUG & RADEON_IOCTL)
2343e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
2353e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner
2363e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	if (rmesa->dma.flush)
2373e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		rmesa->dma.flush(rmesa->glCtx);
2383e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner
23954970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner	assert(rmesa->dma.current_used == rmesa->dma.current_vertexptr);
2400c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner
2410c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner	alignment--;
24254970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner	rmesa->dma.current_used = (rmesa->dma.current_used + alignment) & ~alignment;
24354970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner
244b7c6bf1e073088635951435acedff793add1cefdDevang Patel	if (is_empty_list(&rmesa->dma.reserved)
245b7c6bf1e073088635951435acedff793add1cefdDevang Patel		|| rmesa->dma.current_used + bytes > first_elem(&rmesa->dma.reserved)->bo->size)
246b7c6bf1e073088635951435acedff793add1cefdDevang Patel		radeonRefillCurrentDmaRegion(rmesa, bytes);
247bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola
24854970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner	*poffset = rmesa->dma.current_used;
2490c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner	*pbo = first_elem(&rmesa->dma.reserved)->bo;
25054970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner	radeon_bo_ref(*pbo);
2516f0a7687ab9a0509e847279fae27554ce7da0ba1Duncan Sands
252fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman	/* Always align to at least 16 bytes */
2530c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner	rmesa->dma.current_used = (rmesa->dma.current_used + bytes + 15) & ~15;
2540c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner	rmesa->dma.current_vertexptr = rmesa->dma.current_used;
2550c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner
2560c0aa711b8a0550c21f032125c4663ff45864f81Chris Lattner	assert(rmesa->dma.current_used <= first_elem(&rmesa->dma.reserved)->bo->size);
257fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman}
25854970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner
25954970c032815edadb1b2988ea33f5a1173e5b29cChris Lattnervoid radeonFreeDmaRegions(radeonContextPtr rmesa)
26054970c032815edadb1b2988ea33f5a1173e5b29cChris Lattner{
26168d57e7ae80044401efd889270a12c71b3efb9abChris Lattner	struct radeon_dma_bo *dma_bo;
26268d57e7ae80044401efd889270a12c71b3efb9abChris Lattner	struct radeon_dma_bo *temp;
2633e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	if (RADEON_DEBUG & RADEON_DMA)
2643e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		fprintf(stderr, "%s\n", __FUNCTION__);
2653e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner
2663e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	foreach_s(dma_bo, temp, &rmesa->dma.free) {
2673e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		remove_from_list(dma_bo);
2683e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	        radeon_bo_unref(dma_bo->bo);
2693e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		FREE(dma_bo);
2701f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen	}
2713e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner
2723e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	foreach_s(dma_bo, temp, &rmesa->dma.wait) {
2733e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		remove_from_list(dma_bo);
2743e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner	        radeon_bo_unref(dma_bo->bo);
2753e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner		FREE(dma_bo);
27668d57e7ae80044401efd889270a12c71b3efb9abChris Lattner	}
27768d57e7ae80044401efd889270a12c71b3efb9abChris Lattner
278	foreach_s(dma_bo, temp, &rmesa->dma.reserved) {
279		remove_from_list(dma_bo);
280	        radeon_bo_unref(dma_bo->bo);
281		FREE(dma_bo);
282	}
283}
284
285void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes)
286{
287	if (is_empty_list(&rmesa->dma.reserved))
288		return;
289
290	if (RADEON_DEBUG & RADEON_IOCTL)
291		fprintf(stderr, "%s %d\n", __FUNCTION__, return_bytes);
292	rmesa->dma.current_used -= return_bytes;
293	rmesa->dma.current_vertexptr = rmesa->dma.current_used;
294}
295
296static int radeon_bo_is_idle(struct radeon_bo* bo)
297{
298	uint32_t domain;
299	int ret = radeon_bo_is_busy(bo, &domain);
300	if (ret == -EINVAL) {
301		WARN_ONCE("Your libdrm or kernel doesn't have support for busy query.\n"
302			"This may cause small performance drop for you.\n");
303	}
304	return ret != -EBUSY;
305}
306
307void radeonReleaseDmaRegions(radeonContextPtr rmesa)
308{
309	struct radeon_dma_bo *dma_bo;
310	struct radeon_dma_bo *temp;
311	const int expire_at = ++rmesa->dma.free.expire_counter + DMA_BO_FREE_TIME;
312	const int time = rmesa->dma.free.expire_counter;
313
314	if (RADEON_DEBUG & RADEON_DMA) {
315		size_t free = 0,
316		       wait = 0,
317		       reserved = 0;
318		foreach(dma_bo, &rmesa->dma.free)
319			++free;
320
321		foreach(dma_bo, &rmesa->dma.wait)
322			++wait;
323
324		foreach(dma_bo, &rmesa->dma.reserved)
325			++reserved;
326
327		fprintf(stderr, "%s: free %zu, wait %zu, reserved %zu, minimum_size: %zu\n",
328		      __FUNCTION__, free, wait, reserved, rmesa->dma.minimum_size);
329	}
330
331	if (!rmesa->radeonScreen->driScreen->dri2.enabled) {
332		/* request updated cs processing information from kernel */
333		legacy_track_pending(rmesa->radeonScreen->bom, 0);
334	}
335
336	/* move waiting bos to free list.
337	   wait list provides gpu time to handle data before reuse */
338	foreach_s(dma_bo, temp, &rmesa->dma.wait) {
339		if (dma_bo->expire_counter == time) {
340			WARN_ONCE("Leaking dma buffer object!\n");
341			radeon_bo_unref(dma_bo->bo);
342			remove_from_list(dma_bo);
343			FREE(dma_bo);
344			continue;
345		}
346		/* free objects that are too small to be used because of large request */
347		if (dma_bo->bo->size < rmesa->dma.minimum_size) {
348		   radeon_bo_unref(dma_bo->bo);
349		   remove_from_list(dma_bo);
350		   FREE(dma_bo);
351		   continue;
352		}
353		if (!radeon_bo_is_idle(dma_bo->bo)) {
354			if (rmesa->radeonScreen->driScreen->dri2.enabled)
355				break;
356			continue;
357		}
358		remove_from_list(dma_bo);
359		dma_bo->expire_counter = expire_at;
360		insert_at_tail(&rmesa->dma.free, dma_bo);
361	}
362
363	/* move reserved to wait list */
364	foreach_s(dma_bo, temp, &rmesa->dma.reserved) {
365		radeon_bo_unmap(dma_bo->bo);
366		/* free objects that are too small to be used because of large request */
367		if (dma_bo->bo->size < rmesa->dma.minimum_size) {
368		   radeon_bo_unref(dma_bo->bo);
369		   remove_from_list(dma_bo);
370		   FREE(dma_bo);
371		   continue;
372		}
373		remove_from_list(dma_bo);
374		dma_bo->expire_counter = expire_at;
375		insert_at_tail(&rmesa->dma.wait, dma_bo);
376	}
377
378	/* free bos that have been unused for some time */
379	foreach_s(dma_bo, temp, &rmesa->dma.free) {
380		if (dma_bo->expire_counter != time)
381			break;
382		remove_from_list(dma_bo);
383	        radeon_bo_unref(dma_bo->bo);
384		FREE(dma_bo);
385	}
386
387}
388
389
390/* Flush vertices in the current dma region.
391 */
392void rcommon_flush_last_swtcl_prim( GLcontext *ctx  )
393{
394	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
395	struct radeon_dma *dma = &rmesa->dma;
396
397	if (RADEON_DEBUG & RADEON_IOCTL)
398		fprintf(stderr, "%s\n", __FUNCTION__);
399	dma->flush = NULL;
400
401	radeon_bo_unmap(rmesa->swtcl.bo);
402
403	if (!is_empty_list(&dma->reserved)) {
404	    GLuint current_offset = dma->current_used;
405
406	    assert (dma->current_used +
407		    rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
408		    dma->current_vertexptr);
409
410	    if (dma->current_used != dma->current_vertexptr) {
411		    dma->current_used = dma->current_vertexptr;
412
413		    rmesa->vtbl.swtcl_flush(ctx, current_offset);
414	    }
415	    rmesa->swtcl.numverts = 0;
416	}
417	radeon_bo_unref(rmesa->swtcl.bo);
418	rmesa->swtcl.bo = NULL;
419}
420/* Alloc space in the current dma region.
421 */
422void *
423rcommonAllocDmaLowVerts( radeonContextPtr rmesa, int nverts, int vsize )
424{
425	GLuint bytes = vsize * nverts;
426	void *head;
427	if (RADEON_DEBUG & RADEON_IOCTL)
428		fprintf(stderr, "%s\n", __FUNCTION__);
429
430	if(is_empty_list(&rmesa->dma.reserved)
431	      ||rmesa->dma.current_vertexptr + bytes > first_elem(&rmesa->dma.reserved)->bo->size) {
432		if (rmesa->dma.flush) {
433			rmesa->dma.flush(rmesa->glCtx);
434		}
435
436                radeonRefillCurrentDmaRegion(rmesa, bytes);
437
438		return NULL;
439	}
440
441        if (!rmesa->dma.flush) {
442		/* if cmdbuf flushed DMA restart */
443                rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
444                rmesa->dma.flush = rcommon_flush_last_swtcl_prim;
445        }
446
447	ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
448        ASSERT( rmesa->dma.flush == rcommon_flush_last_swtcl_prim );
449        ASSERT( rmesa->dma.current_used +
450                rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
451                rmesa->dma.current_vertexptr );
452
453	if (!rmesa->swtcl.bo) {
454		rmesa->swtcl.bo = first_elem(&rmesa->dma.reserved)->bo;
455		radeon_bo_ref(rmesa->swtcl.bo);
456		radeon_bo_map(rmesa->swtcl.bo, 1);
457	}
458
459	head = (rmesa->swtcl.bo->ptr + rmesa->dma.current_vertexptr);
460	rmesa->dma.current_vertexptr += bytes;
461	rmesa->swtcl.numverts += nverts;
462	return head;
463}
464
465void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
466{
467   radeonContextPtr radeon = RADEON_CONTEXT( ctx );
468   int i;
469	if (RADEON_DEBUG & RADEON_IOCTL)
470		fprintf(stderr, "%s\n", __FUNCTION__);
471
472   if (radeon->dma.flush) {
473       radeon->dma.flush(radeon->glCtx);
474   }
475   for (i = 0; i < radeon->tcl.aos_count; i++) {
476      if (radeon->tcl.aos[i].bo) {
477         radeon_bo_unref(radeon->tcl.aos[i].bo);
478         radeon->tcl.aos[i].bo = NULL;
479
480      }
481   }
482}
483