blob: 48c7ed4caa5c2741411da48e2203abe65b0de37b [file] [log] [blame]
/*
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* VIA, S3 GRAPHICS, 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.
*/
#include <assert.h>
#include "via_context.h"
#include "via_ioctl.h"
#include "via_fb.h"
#include "xf86drm.h"
#include "imports.h"
#include "simple_list.h"
#include <sys/ioctl.h>
GLboolean
via_alloc_draw_buffer(struct via_context *vmesa, struct via_renderbuffer *buf)
{
drm_via_mem_t mem;
mem.context = vmesa->hHWContext;
mem.size = buf->size;
mem.type = VIA_MEM_VIDEO;
mem.offset = 0;
mem.index = 0;
if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_ALLOCMEM, &mem))
return GL_FALSE;
buf->offset = mem.offset;
buf->map = (char *)vmesa->driScreen->pFB + mem.offset;
buf->index = mem.index;
return GL_TRUE;
}
void
via_free_draw_buffer(struct via_context *vmesa, struct via_renderbuffer *buf)
{
drm_via_mem_t mem;
if (!vmesa) return;
mem.context = vmesa->hHWContext;
mem.index = buf->index;
mem.type = VIA_MEM_VIDEO;
mem.offset = buf->offset;
mem.size = buf->size;
ioctl(vmesa->driFd, DRM_IOCTL_VIA_FREEMEM, &mem);
buf->map = NULL;
}
GLboolean
via_alloc_dma_buffer(struct via_context *vmesa)
{
drm_via_dma_init_t init;
vmesa->dma = (GLubyte *) malloc(VIA_DMA_BUFSIZ);
/*
* Check whether AGP DMA has been initialized.
*/
memset(&init, 0, sizeof(init));
init.func = VIA_DMA_INITIALIZED;
vmesa->useAgp =
( 0 == drmCommandWrite(vmesa->driFd, DRM_VIA_DMA_INIT,
&init, sizeof(init)));
if (VIA_DEBUG & DEBUG_DMA) {
if (vmesa->useAgp)
fprintf(stderr, "unichrome_dri.so: Using AGP.\n");
else
fprintf(stderr, "unichrome_dri.so: Using PCI.\n");
}
return ((vmesa->dma) ? GL_TRUE : GL_FALSE);
}
void
via_free_dma_buffer(struct via_context *vmesa)
{
if (!vmesa) return;
free(vmesa->dma);
vmesa->dma = 0;
}
/* These functions now allocate and free the via_tex_buffer struct as well:
*/
struct via_tex_buffer *
via_alloc_texture(struct via_context *vmesa,
GLuint size,
GLuint memType)
{
struct via_tex_buffer *t = CALLOC_STRUCT(via_tex_buffer);
if (!t)
goto cleanup;
t->size = size;
t->memType = memType;
insert_at_tail(&vmesa->tex_image_list[memType], t);
if (t->memType == VIA_MEM_AGP ||
t->memType == VIA_MEM_VIDEO) {
drm_via_mem_t fb;
fb.context = vmesa->hHWContext;
fb.size = t->size;
fb.type = t->memType;
fb.offset = 0;
fb.index = 0;
if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_ALLOCMEM, &fb) != 0 ||
fb.index == 0)
goto cleanup;
if (0)
fprintf(stderr, "offset %lx index %lx\n", fb.offset, fb.index);
t->offset = fb.offset;
t->index = fb.index;
if (t->memType == VIA_MEM_AGP) {
t->bufAddr = (GLubyte *)((unsigned long)vmesa->viaScreen->agpLinearStart +
fb.offset);
t->texBase = vmesa->agpBase + fb.offset;
}
else {
t->bufAddr = (GLubyte *)((unsigned long)vmesa->driScreen->pFB + fb.offset);
t->texBase = fb.offset;
}
vmesa->total_alloc[t->memType] += t->size;
return t;
}
else if (t->memType == VIA_MEM_SYSTEM) {
t->bufAddr = _mesa_malloc(t->size);
if (!t->bufAddr)
goto cleanup;
vmesa->total_alloc[t->memType] += t->size;
return t;
}
cleanup:
if (t) {
remove_from_list(t);
FREE(t);
}
return NULL;
}
static void
via_do_free_texture(struct via_context *vmesa, struct via_tex_buffer *t)
{
drm_via_mem_t fb;
remove_from_list( t );
vmesa->total_alloc[t->memType] -= t->size;
fb.context = vmesa->hHWContext;
fb.index = t->index;
fb.offset = t->offset;
fb.type = t->memType;
fb.size = t->size;
if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_FREEMEM, &fb)) {
fprintf(stderr, "via_free_texture fail\n");
}
FREE(t);
}
/* Release textures which were potentially still being referenced by
* hardware at the time when they were originally freed.
*/
void
via_release_pending_textures( struct via_context *vmesa )
{
struct via_tex_buffer *s, *tmp;
foreach_s( s, tmp, &vmesa->freed_tex_buffers ) {
if (!VIA_GEQ_WRAP(s->lastUsed, vmesa->lastBreadcrumbRead)) {
if (VIA_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: release tex sz %d lastUsed %x\n",
__FUNCTION__, s->size, s->lastUsed);
via_do_free_texture(vmesa, s);
}
}
}
void
via_free_texture(struct via_context *vmesa, struct via_tex_buffer *t)
{
if (!t) {
return;
}
else if (t->memType == VIA_MEM_SYSTEM) {
remove_from_list(t);
vmesa->total_alloc[t->memType] -= t->size;
_mesa_free(t->bufAddr);
_mesa_free(t);
}
else if (t->index && viaCheckBreadcrumb(vmesa, t->lastUsed)) {
via_do_free_texture( vmesa, t );
}
else {
/* Close current breadcrumb so that we can free this eventually:
*/
if (t->lastUsed == vmesa->lastBreadcrumbWrite)
viaEmitBreadcrumb(vmesa);
move_to_tail( &vmesa->freed_tex_buffers, t );
}
}