1 /**************************************************************************
3 Copyright (C) 2004 Nicolai Haehnle.
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
12 Permission is hereby granted, free of charge, to any person obtaining a
13 copy of this software and associated documentation files (the "Software"),
14 to deal in the Software without restriction, including without limitation
15 on the rights to use, copy, modify, merge, publish, distribute, sub
16 license, and/or sell copies of the Software, and to permit persons to whom
17 the Software is furnished to do so, subject to the following conditions:
19 The above copyright notice and this permission notice (including the next
20 paragraph) shall be included in all copies or substantial portions of the
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
26 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
27 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
28 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
29 USE OR OTHER DEALINGS IN THE SOFTWARE.
31 **************************************************************************/
33 #include "radeon_common.h"
35 #if defined(USE_X86_ASM)
36 #define COPY_DWORDS( dst, src, nr ) \
39 __asm__ __volatile__( "rep ; movsl" \
40 : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
46 #define COPY_DWORDS( dst, src, nr ) \
49 for ( j = 0 ; j < nr ; j++ ) \
50 dst[j] = ((int *)src)[j]; \
55 static void radeonEmitVec4(uint32_t *out
, const GLvoid
* data
, int stride
, int count
)
59 if (RADEON_DEBUG
& DEBUG_VERTS
)
60 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
61 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
64 COPY_DWORDS(out
, data
, count
);
66 for (i
= 0; i
< count
; i
++) {
67 out
[0] = *(int *)data
;
73 void radeonEmitVec8(uint32_t *out
, const GLvoid
* data
, int stride
, int count
)
77 if (RADEON_DEBUG
& DEBUG_VERTS
)
78 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
79 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
82 COPY_DWORDS(out
, data
, count
* 2);
84 for (i
= 0; i
< count
; i
++) {
85 out
[0] = *(int *)data
;
86 out
[1] = *(int *)(data
+ 4);
92 void radeonEmitVec12(uint32_t *out
, const GLvoid
* data
, int stride
, int count
)
96 if (RADEON_DEBUG
& DEBUG_VERTS
)
97 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
98 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
101 COPY_DWORDS(out
, data
, count
* 3);
104 for (i
= 0; i
< count
; i
++) {
105 out
[0] = *(int *)data
;
106 out
[1] = *(int *)(data
+ 4);
107 out
[2] = *(int *)(data
+ 8);
113 static void radeonEmitVec16(uint32_t *out
, const GLvoid
* data
, int stride
, int count
)
117 if (RADEON_DEBUG
& DEBUG_VERTS
)
118 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
119 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
122 COPY_DWORDS(out
, data
, count
* 4);
124 for (i
= 0; i
< count
; i
++) {
125 out
[0] = *(int *)data
;
126 out
[1] = *(int *)(data
+ 4);
127 out
[2] = *(int *)(data
+ 8);
128 out
[3] = *(int *)(data
+ 12);
134 void rcommon_emit_vector(GLcontext
* ctx
, struct radeon_aos
*aos
,
135 const GLvoid
* data
, int size
, int stride
, int count
)
137 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
141 radeonAllocDmaRegion(rmesa
, &aos
->bo
, &aos
->offset
, size
* 4, 32);
145 radeonAllocDmaRegion(rmesa
, &aos
->bo
, &aos
->offset
, size
* count
* 4, 32);
149 aos
->components
= size
;
152 out
= (uint32_t*)((char*)aos
->bo
->ptr
+ aos
->offset
);
154 case 1: radeonEmitVec4(out
, data
, stride
, count
); break;
155 case 2: radeonEmitVec8(out
, data
, stride
, count
); break;
156 case 3: radeonEmitVec12(out
, data
, stride
, count
); break;
157 case 4: radeonEmitVec16(out
, data
, stride
, count
); break;
164 void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa
, int size
)
167 size
= MAX2(size
, MAX_DMA_BUF_SZ
);
169 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
))
170 fprintf(stderr
, "%s\n", __FUNCTION__
);
172 if (rmesa
->dma
.flush
) {
173 rmesa
->dma
.flush(rmesa
->glCtx
);
176 if (rmesa
->dma
.nr_released_bufs
> 4) {
177 rcommonFlushCmdBuf(rmesa
, __FUNCTION__
);
178 rmesa
->dma
.nr_released_bufs
= 0;
181 if (rmesa
->dma
.current
) {
182 radeon_bo_unmap(rmesa
->dma
.current
);
183 radeon_bo_unref(rmesa
->dma
.current
);
184 rmesa
->dma
.current
= 0;
188 #ifdef RADEON_DEBUG_BO
189 rmesa
->dma
.current
= radeon_bo_open(rmesa
->radeonScreen
->bom
,
190 0, size
, 4, RADEON_GEM_DOMAIN_GTT
,
193 rmesa
->dma
.current
= radeon_bo_open(rmesa
->radeonScreen
->bom
,
194 0, size
, 4, RADEON_GEM_DOMAIN_GTT
,
196 #endif /* RADEON_DEBUG_BO */
198 if (!rmesa
->dma
.current
) {
199 rcommonFlushCmdBuf(rmesa
, __FUNCTION__
);
200 rmesa
->dma
.nr_released_bufs
= 0;
204 rmesa
->dma
.current_used
= 0;
205 rmesa
->dma
.current_vertexptr
= 0;
207 if (radeon_cs_space_check_with_bo(rmesa
->cmdbuf
.cs
,
209 RADEON_GEM_DOMAIN_GTT
, 0))
210 fprintf(stderr
,"failure to revalidate BOs - badness\n");
212 if (!rmesa
->dma
.current
) {
213 /* Cmd buff have been flushed in radeon_revalidate_bos */
214 rmesa
->dma
.nr_released_bufs
= 0;
218 radeon_bo_map(rmesa
->dma
.current
, 1);
221 /* Allocates a region from rmesa->dma.current. If there isn't enough
222 * space in current, grab a new buffer (and discard what was left of current)
224 void radeonAllocDmaRegion(radeonContextPtr rmesa
,
225 struct radeon_bo
**pbo
, int *poffset
,
226 int bytes
, int alignment
)
228 if (RADEON_DEBUG
& DEBUG_IOCTL
)
229 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
231 if (rmesa
->dma
.flush
)
232 rmesa
->dma
.flush(rmesa
->glCtx
);
234 assert(rmesa
->dma
.current_used
== rmesa
->dma
.current_vertexptr
);
237 rmesa
->dma
.current_used
= (rmesa
->dma
.current_used
+ alignment
) & ~alignment
;
239 if (!rmesa
->dma
.current
|| rmesa
->dma
.current_used
+ bytes
> rmesa
->dma
.current
->size
)
240 radeonRefillCurrentDmaRegion(rmesa
, (bytes
+ 15) & ~15);
242 *poffset
= rmesa
->dma
.current_used
;
243 *pbo
= rmesa
->dma
.current
;
246 /* Always align to at least 16 bytes */
247 rmesa
->dma
.current_used
= (rmesa
->dma
.current_used
+ bytes
+ 15) & ~15;
248 rmesa
->dma
.current_vertexptr
= rmesa
->dma
.current_used
;
250 assert(rmesa
->dma
.current_used
<= rmesa
->dma
.current
->size
);
253 void radeonReleaseDmaRegion(radeonContextPtr rmesa
)
255 if (RADEON_DEBUG
& DEBUG_IOCTL
)
256 fprintf(stderr
, "%s %p\n", __FUNCTION__
, rmesa
->dma
.current
);
257 if (rmesa
->dma
.current
) {
258 rmesa
->dma
.nr_released_bufs
++;
259 radeon_bo_unmap(rmesa
->dma
.current
);
260 radeon_bo_unref(rmesa
->dma
.current
);
262 rmesa
->dma
.current
= NULL
;
266 /* Flush vertices in the current dma region.
268 void rcommon_flush_last_swtcl_prim( GLcontext
*ctx
)
270 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
271 struct radeon_dma
*dma
= &rmesa
->dma
;
274 if (RADEON_DEBUG
& DEBUG_IOCTL
)
275 fprintf(stderr
, "%s %p\n", __FUNCTION__
, dma
->current
);
279 GLuint current_offset
= dma
->current_used
;
281 assert (dma
->current_used
+
282 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
283 dma
->current_vertexptr
);
285 if (dma
->current_used
!= dma
->current_vertexptr
) {
286 dma
->current_used
= dma
->current_vertexptr
;
288 rmesa
->vtbl
.swtcl_flush(ctx
, current_offset
);
290 rmesa
->swtcl
.numverts
= 0;
293 /* Alloc space in the current dma region.
296 rcommonAllocDmaLowVerts( radeonContextPtr rmesa
, int nverts
, int vsize
)
298 GLuint bytes
= vsize
* nverts
;
301 if (!rmesa
->dma
.current
|| rmesa
->dma
.current_vertexptr
+ bytes
> rmesa
->dma
.current
->size
) {
302 radeonRefillCurrentDmaRegion(rmesa
, bytes
);
305 if (!rmesa
->dma
.flush
) {
306 /* make sure we have enough space to use this in cmdbuf */
307 rcommonEnsureCmdBufSpace(rmesa
,
308 rmesa
->hw
.max_state_size
+ (20*sizeof(int)),
310 /* if cmdbuf flushed DMA restart */
311 if (!rmesa
->dma
.current
)
313 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
314 rmesa
->dma
.flush
= rcommon_flush_last_swtcl_prim
;
317 ASSERT( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
318 ASSERT( rmesa
->dma
.flush
== rcommon_flush_last_swtcl_prim
);
319 ASSERT( rmesa
->dma
.current_used
+
320 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
321 rmesa
->dma
.current_vertexptr
);
323 head
= (rmesa
->dma
.current
->ptr
+ rmesa
->dma
.current_vertexptr
);
324 rmesa
->dma
.current_vertexptr
+= bytes
;
325 rmesa
->swtcl
.numverts
+= nverts
;
329 void radeonReleaseArrays( GLcontext
*ctx
, GLuint newinputs
)
331 radeonContextPtr radeon
= RADEON_CONTEXT( ctx
);
334 if (radeon
->dma
.flush
) {
335 radeon
->dma
.flush(radeon
->glCtx
);
337 if (radeon
->tcl
.elt_dma_bo
) {
338 radeon_bo_unref(radeon
->tcl
.elt_dma_bo
);
339 radeon
->tcl
.elt_dma_bo
= NULL
;
341 for (i
= 0; i
< radeon
->tcl
.aos_count
; i
++) {
342 if (radeon
->tcl
.aos
[i
].bo
) {
343 radeon_bo_unref(radeon
->tcl
.aos
[i
].bo
);
344 radeon
->tcl
.aos
[i
].bo
= NULL
;