2 * Copyright (C) 2005 Aapo Tahkola.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * \author Aapo Tahkola <aet@rasterburn.org>
36 #include "r300_context.h"
37 #include "r300_cmdbuf.h"
38 #include "r300_ioctl.h"
40 #include "radeon_ioctl.h"
44 static void resize_u_list(r300ContextPtr rmesa
)
49 temp
= rmesa
->rmm
->u_list
;
50 nsize
= rmesa
->rmm
->u_size
* 2;
52 rmesa
->rmm
->u_list
= _mesa_malloc(nsize
* sizeof(*rmesa
->rmm
->u_list
));
53 _mesa_memset(rmesa
->rmm
->u_list
, 0,
54 nsize
* sizeof(*rmesa
->rmm
->u_list
));
57 r300FlushCmdBuf(rmesa
, __FUNCTION__
);
59 _mesa_memcpy(rmesa
->rmm
->u_list
, temp
,
60 rmesa
->rmm
->u_size
* sizeof(*rmesa
->rmm
->u_list
));
64 rmesa
->rmm
->u_size
= nsize
;
67 void r300_mem_init(r300ContextPtr rmesa
)
69 rmesa
->rmm
= malloc(sizeof(struct r300_memory_manager
));
70 memset(rmesa
->rmm
, 0, sizeof(struct r300_memory_manager
));
72 rmesa
->rmm
->u_size
= 128;
76 void r300_mem_destroy(r300ContextPtr rmesa
)
78 _mesa_free(rmesa
->rmm
->u_list
);
79 rmesa
->rmm
->u_list
= NULL
;
81 _mesa_free(rmesa
->rmm
);
85 void *r300_mem_ptr(r300ContextPtr rmesa
, int id
)
87 assert(id
<= rmesa
->rmm
->u_last
);
88 return rmesa
->rmm
->u_list
[id
].ptr
;
91 int r300_mem_find(r300ContextPtr rmesa
, void *ptr
)
95 for (i
= 1; i
< rmesa
->rmm
->u_size
+ 1; i
++)
96 if (rmesa
->rmm
->u_list
[i
].ptr
&&
97 ptr
>= rmesa
->rmm
->u_list
[i
].ptr
&&
99 rmesa
->rmm
->u_list
[i
].ptr
+ rmesa
->rmm
->u_list
[i
].size
)
102 if (i
< rmesa
->rmm
->u_size
+ 1)
105 fprintf(stderr
, "%p failed\n", ptr
);
110 int r300_mem_alloc(r300ContextPtr rmesa
, int alignment
, int size
)
112 drm_radeon_mem_alloc_t alloc
;
116 drm_radeon_mem_free_t memfree
;
118 static int bytes_wasted
= 0, allocated
= 0;
121 bytes_wasted
+= 4096 - size
;
127 if (t
!= time(NULL
)) {
129 fprintf(stderr
, "slots used %d, wasted %d kb, allocated %d\n",
130 rmesa
->rmm
->u_last
, bytes_wasted
/ 1024,
135 memfree
.region
= RADEON_MEM_REGION_GART
;
139 done_age
= radeonGetAge((radeonContextPtr
) rmesa
);
141 if (rmesa
->rmm
->u_last
+ 1 >= rmesa
->rmm
->u_size
)
142 resize_u_list(rmesa
);
144 for (i
= rmesa
->rmm
->u_last
+ 1; i
> 0; i
--) {
145 if (rmesa
->rmm
->u_list
[i
].ptr
== NULL
) {
150 if (rmesa
->rmm
->u_list
[i
].h_pending
== 0 &&
151 rmesa
->rmm
->u_list
[i
].pending
152 && rmesa
->rmm
->u_list
[i
].age
<= done_age
) {
153 memfree
.region_offset
=
154 (char *)rmesa
->rmm
->u_list
[i
].ptr
-
155 (char *)rmesa
->radeon
.radeonScreen
->gartTextures
.
159 drmCommandWrite(rmesa
->radeon
.radeonScreen
->
160 driScreen
->fd
, DRM_RADEON_FREE
,
161 &memfree
, sizeof(memfree
));
164 fprintf(stderr
, "Failed to free at %p\n",
165 rmesa
->rmm
->u_list
[i
].ptr
);
166 fprintf(stderr
, "ret = %s\n", strerror(-ret
));
170 fprintf(stderr
, "really freed %d at age %x\n",
172 radeonGetAge((radeonContextPtr
) rmesa
));
174 if (i
== rmesa
->rmm
->u_last
)
175 rmesa
->rmm
->u_last
--;
177 if (rmesa
->rmm
->u_list
[i
].size
< 4096)
179 4096 - rmesa
->rmm
->u_list
[i
].size
;
181 allocated
-= rmesa
->rmm
->u_list
[i
].size
;
182 rmesa
->rmm
->u_list
[i
].pending
= 0;
183 rmesa
->rmm
->u_list
[i
].ptr
= NULL
;
188 rmesa
->rmm
->u_head
= i
;
191 WARN_ONCE("Ran out of slots!\n");
193 r300FlushCmdBuf(rmesa
, __FUNCTION__
);
196 WARN_ONCE("Ran out of slots!\n");
202 alloc
.region
= RADEON_MEM_REGION_GART
;
203 alloc
.alignment
= alignment
;
205 alloc
.region_offset
= &offset
;
208 drmCommandWriteRead(rmesa
->radeon
.dri
.fd
, DRM_RADEON_ALLOC
, &alloc
,
212 WARN_ONCE("Ran out of mem!\n");
213 r300FlushCmdBuf(rmesa
, __FUNCTION__
);
218 WARN_ONCE("Ran out of GART memory!\n");
224 ("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n",
232 if (i
> rmesa
->rmm
->u_last
)
233 rmesa
->rmm
->u_last
= i
;
235 rmesa
->rmm
->u_list
[i
].ptr
=
236 ((GLubyte
*) rmesa
->radeon
.radeonScreen
->gartTextures
.map
) + offset
;
237 rmesa
->rmm
->u_list
[i
].size
= size
;
238 rmesa
->rmm
->u_list
[i
].age
= 0;
239 //fprintf(stderr, "alloc %p at id %d\n", rmesa->rmm->u_list[i].ptr, i);
242 fprintf(stderr
, "allocated %d at age %x\n", i
,
243 radeonGetAge((radeonContextPtr
) rmesa
));
249 void r300_mem_use(r300ContextPtr rmesa
, int id
)
253 fprintf(stderr
, "%s: %d at age %x\n", __FUNCTION__
, id
,
254 radeonGetAge((radeonContextPtr
) rmesa
));
256 drm_r300_cmd_header_t
*cmd
;
258 assert(id
<= rmesa
->rmm
->u_last
);
264 (drm_r300_cmd_header_t
*) r300AllocCmdBuf(rmesa
,
267 cmd
[0].scratch
.cmd_type
= R300_CMD_SCRATCH
;
268 cmd
[0].scratch
.reg
= R300_MEM_SCRATCH
;
269 cmd
[0].scratch
.n_bufs
= 1;
270 cmd
[0].scratch
.flags
= 0;
273 ull
= (uint64_t) (intptr_t) & rmesa
->rmm
->u_list
[id
].age
;
274 _mesa_memcpy(cmd
, &ull
, sizeof(ull
));
275 cmd
+= sizeof(ull
) / 4;
277 cmd
[0].u
= /*id */ 0;
279 LOCK_HARDWARE(&rmesa
->radeon
); /* Protect from DRM. */
280 rmesa
->rmm
->u_list
[id
].h_pending
++;
281 UNLOCK_HARDWARE(&rmesa
->radeon
);
284 unsigned long r300_mem_offset(r300ContextPtr rmesa
, int id
)
286 unsigned long offset
;
288 assert(id
<= rmesa
->rmm
->u_last
);
290 offset
= (char *)rmesa
->rmm
->u_list
[id
].ptr
-
291 (char *)rmesa
->radeon
.radeonScreen
->gartTextures
.map
;
292 offset
+= rmesa
->radeon
.radeonScreen
->gart_texture_offset
;
297 void *r300_mem_map(r300ContextPtr rmesa
, int id
, int access
)
300 fprintf(stderr
, "%s: %d at age %x\n", __FUNCTION__
, id
,
301 radeonGetAge((radeonContextPtr
) rmesa
));
306 assert(id
<= rmesa
->rmm
->u_last
);
308 if (access
== R300_MEM_R
) {
310 if (rmesa
->rmm
->u_list
[id
].mapped
== 1)
311 WARN_ONCE("buffer %d already mapped\n", id
);
313 rmesa
->rmm
->u_list
[id
].mapped
= 1;
314 ptr
= r300_mem_ptr(rmesa
, id
);
319 if (rmesa
->rmm
->u_list
[id
].h_pending
)
320 r300FlushCmdBuf(rmesa
, __FUNCTION__
);
322 if (rmesa
->rmm
->u_list
[id
].h_pending
) {
326 while (rmesa
->rmm
->u_list
[id
].age
>
327 radeonGetAge((radeonContextPtr
) rmesa
) && tries
++ < 1000)
331 fprintf(stderr
, "Idling failed (%x vs %x)\n",
332 rmesa
->rmm
->u_list
[id
].age
,
333 radeonGetAge((radeonContextPtr
) rmesa
));
337 if (rmesa
->rmm
->u_list
[id
].mapped
== 1)
338 WARN_ONCE("buffer %d already mapped\n", id
);
340 rmesa
->rmm
->u_list
[id
].mapped
= 1;
341 ptr
= r300_mem_ptr(rmesa
, id
);
346 void r300_mem_unmap(r300ContextPtr rmesa
, int id
)
349 fprintf(stderr
, "%s: %d at age %x\n", __FUNCTION__
, id
,
350 radeonGetAge((radeonContextPtr
) rmesa
));
353 assert(id
<= rmesa
->rmm
->u_last
);
355 if (rmesa
->rmm
->u_list
[id
].mapped
== 0)
356 WARN_ONCE("buffer %d not mapped\n", id
);
358 rmesa
->rmm
->u_list
[id
].mapped
= 0;
361 void r300_mem_free(r300ContextPtr rmesa
, int id
)
364 fprintf(stderr
, "%s: %d at age %x\n", __FUNCTION__
, id
,
365 radeonGetAge((radeonContextPtr
) rmesa
));
368 assert(id
<= rmesa
->rmm
->u_last
);
373 if (rmesa
->rmm
->u_list
[id
].ptr
== NULL
) {
374 WARN_ONCE("Not allocated!\n");
378 if (rmesa
->rmm
->u_list
[id
].pending
) {
379 WARN_ONCE("%p already pended!\n", rmesa
->rmm
->u_list
[id
].ptr
);
383 rmesa
->rmm
->u_list
[id
].pending
= 1;