/* * Copyright © 2009 Thomas White * * Based on radeon_bo_gem.c, to which the following notice applies: * * Copyright © 2008 Dave Airlie * Copyright © 2008 Jérôme Glisse * 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 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 THE COPYRIGHT HOLDERS, AUTHORS * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. */ /* * Authors: * Dave Airlie * Jérôme Glisse * * * Memory mapping functions are based on intel_bufmgr_gem.c, to which the * following notice applies: * * Copyright © 2007 Red Hat Inc. * Copyright © 2007 Intel Corporation * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * **************************************************************************/ /* * Authors: Thomas Hellström * Keith Whitwell * Eric Anholt * Dave Airlie */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "xf86drm.h" #include "drm.h" #include "glamo_drm.h" #include "glamo_bo.h" #include "glamo_bo_gem.h" struct glamo_bo_gem { struct glamo_bo base; uint32_t name; int map_count; }; struct bo_manager_gem { struct glamo_bo_manager base; }; static struct glamo_bo *bo_open(struct glamo_bo_manager *bom, uint32_t handle, uint32_t size, uint32_t alignment, uint32_t domains, uint32_t flags) { struct glamo_bo_gem *bo; int r; bo = (struct glamo_bo_gem*)calloc(1, sizeof(struct glamo_bo_gem)); if (bo == NULL) { return NULL; } bo->base.bom = bom; bo->base.handle = 0; bo->base.size = size; bo->base.alignment = alignment; bo->base.domains = domains; bo->base.flags = flags; bo->map_count = 0; bo->base.virtual = NULL; if (handle) { struct drm_gem_open open_arg; memset(&open_arg, 0, sizeof(open_arg)); open_arg.name = handle; r = ioctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg); if (r != 0) { free(bo); return NULL; } bo->base.handle = open_arg.handle; bo->base.size = open_arg.size; bo->name = handle; } else { struct drm_glamo_gem_create args; args.size = size; args.alignment = alignment; args.initial_domain = bo->base.domains; args.no_backing_store = 0; args.handle = 0; r = drmCommandWriteRead(bom->fd, DRM_GLAMO_GEM_CREATE, &args, sizeof(args)); bo->base.handle = args.handle; if (r) { fprintf(stderr, "Failed to allocate :\n"); fprintf(stderr, " size : %d bytes\n", size); fprintf(stderr, " alignment : %d bytes\n", alignment); free(bo); return NULL; } } glamo_bo_ref((struct glamo_bo*)bo); return (struct glamo_bo*)bo; } static void bo_ref(struct glamo_bo *bo) { } static struct glamo_bo *bo_unref(struct glamo_bo *bo) { struct glamo_bo_gem *bo_gem = (struct glamo_bo_gem*)bo; struct drm_gem_close args; if (bo == NULL) { return NULL; } if (bo->cref) { return bo; } if (bo_gem->map_count) { fprintf(stderr, "Map count for %p isn't zero (=%i)," " so I am unmapping it (%p, %i)\n", bo_gem, bo_gem->map_count, bo->virtual, bo->size); munmap(bo->virtual, bo->size); } /* close object */ args.handle = bo->handle; ioctl(bo->bom->fd, DRM_IOCTL_GEM_CLOSE, &args); memset(bo_gem, 0, sizeof(struct glamo_bo_gem)); free(bo_gem); return NULL; } static int bo_map(struct glamo_bo *bo, int write) { struct glamo_bo_gem *bo_gem; struct glamo_bo_manager *bufmgr; int ret; bo_gem = (struct glamo_bo_gem *)bo; bufmgr = (struct glamo_bo_manager*)bo->bom; /* Get a mapping of the buffer if we haven't before. */ if (bo->virtual == NULL) { struct drm_glamo_gem_mmap mmap_arg; memset(&mmap_arg, 0, sizeof(mmap_arg)); mmap_arg.handle = bo->handle; /* Get the fake offset back... */ ret = ioctl(bufmgr->fd, DRM_IOCTL_GLAMO_GEM_MMAP, &mmap_arg); if (ret != 0) { fprintf(stderr, "%s:%d: Error preparing BO map %d (%d): %s .\n", __FILE__, __LINE__, bo->handle, bo_gem->name, strerror(errno)); return ret; } /* and mmap it */ bo->virtual = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufmgr->fd, mmap_arg.offset); if (bo->virtual == MAP_FAILED) { fprintf(stderr, "%s:%d: Error mapping buffer %d (%d): %s .\n", __FILE__, __LINE__, bo->handle, bo_gem->name, strerror(errno)); return errno; } bo_gem->map_count++; } return 0; } static int bo_unmap(struct glamo_bo *bo) { struct glamo_bo_gem *bo_gem = (struct glamo_bo_gem*)bo; if ( bo_gem->map_count == 0 ) { fprintf(stderr, "Not unmapping %p, because its map count" " is already zero.\n", bo_gem); return 0; } if (--bo_gem->map_count > 0) { return 0; } munmap(bo->virtual, bo->size); bo->virtual = NULL; return 0; } static int bo_wait(struct glamo_bo *bo) { struct drm_glamo_gem_wait_rendering args; int ret; args.handle = bo->handle; do { ret = drmCommandWriteRead(bo->bom->fd, DRM_GLAMO_GEM_WAIT_RENDERING, &args, sizeof(args)); } while (ret == -EAGAIN); return ret; } static struct glamo_bo_funcs bo_gem_funcs = { bo_open, bo_ref, bo_unref, bo_map, bo_unmap, bo_wait }; struct glamo_bo_manager *glamo_bo_manager_gem_ctor(int fd) { struct bo_manager_gem *bomg; bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem)); if (bomg == NULL) return NULL; bomg->base.funcs = &bo_gem_funcs; bomg->base.fd = fd; return (struct glamo_bo_manager*)bomg; } void glamo_bo_manager_gem_dtor(struct glamo_bo_manager *bom) { struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom; if (bom == NULL) return; free(bomg); } uint32_t glamo_gem_name_bo(struct glamo_bo *bo) { struct glamo_bo_gem *bo_gem = (struct glamo_bo_gem*)bo; return bo_gem->name; }