linux/drivers/gpu/drm/drm_drawable.c
<<
>>
Prefs
   1/**
   2 * \file drm_drawable.c
   3 * IOCTLs for drawables
   4 *
   5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
   6 * \author Gareth Hughes <gareth@valinux.com>
   7 * \author Michel Dänzer <michel@tungstengraphics.com>
   8 */
   9
  10/*
  11 * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
  12 *
  13 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  14 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  15 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota.
  16 * All Rights Reserved.
  17 *
  18 * Permission is hereby granted, free of charge, to any person obtaining a
  19 * copy of this software and associated documentation files (the "Software"),
  20 * to deal in the Software without restriction, including without limitation
  21 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  22 * and/or sell copies of the Software, and to permit persons to whom the
  23 * Software is furnished to do so, subject to the following conditions:
  24 *
  25 * The above copyright notice and this permission notice (including the next
  26 * paragraph) shall be included in all copies or substantial portions of the
  27 * Software.
  28 *
  29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  32 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  33 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  34 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  35 * OTHER DEALINGS IN THE SOFTWARE.
  36 */
  37
  38#include "drmP.h"
  39
  40/**
  41 * Allocate drawable ID and memory to store information about it.
  42 */
  43int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
  44{
  45        unsigned long irqflags;
  46        struct drm_draw *draw = data;
  47        int new_id = 0;
  48        int ret;
  49
  50again:
  51        if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
  52                DRM_ERROR("Out of memory expanding drawable idr\n");
  53                return -ENOMEM;
  54        }
  55
  56        spin_lock_irqsave(&dev->drw_lock, irqflags);
  57        ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
  58        if (ret == -EAGAIN) {
  59                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
  60                goto again;
  61        }
  62
  63        spin_unlock_irqrestore(&dev->drw_lock, irqflags);
  64
  65        draw->handle = new_id;
  66
  67        DRM_DEBUG("%d\n", draw->handle);
  68
  69        return 0;
  70}
  71
  72/**
  73 * Free drawable ID and memory to store information about it.
  74 */
  75int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
  76{
  77        struct drm_draw *draw = data;
  78        unsigned long irqflags;
  79        struct drm_drawable_info *info;
  80
  81        spin_lock_irqsave(&dev->drw_lock, irqflags);
  82
  83        info = drm_get_drawable_info(dev, draw->handle);
  84        if (info == NULL) {
  85                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
  86                return -EINVAL;
  87        }
  88        drm_free(info->rects, info->num_rects * sizeof(struct drm_clip_rect),
  89                        DRM_MEM_BUFS);
  90        drm_free(info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
  91
  92        idr_remove(&dev->drw_idr, draw->handle);
  93
  94        spin_unlock_irqrestore(&dev->drw_lock, irqflags);
  95        DRM_DEBUG("%d\n", draw->handle);
  96        return 0;
  97}
  98
  99int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv)
 100{
 101        struct drm_update_draw *update = data;
 102        unsigned long irqflags;
 103        struct drm_clip_rect *rects;
 104        struct drm_drawable_info *info;
 105        int err;
 106
 107        info = idr_find(&dev->drw_idr, update->handle);
 108        if (!info) {
 109                info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
 110                if (!info)
 111                        return -ENOMEM;
 112                if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
 113                        DRM_ERROR("No such drawable %d\n", update->handle);
 114                        drm_free(info, sizeof(*info), DRM_MEM_BUFS);
 115                        return -EINVAL;
 116                }
 117        }
 118
 119        switch (update->type) {
 120        case DRM_DRAWABLE_CLIPRECTS:
 121                if (update->num == 0)
 122                        rects = NULL;
 123                else if (update->num != info->num_rects) {
 124                        rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
 125                                         DRM_MEM_BUFS);
 126                } else
 127                        rects = info->rects;
 128
 129                if (update->num && !rects) {
 130                        DRM_ERROR("Failed to allocate cliprect memory\n");
 131                        err = -ENOMEM;
 132                        goto error;
 133                }
 134
 135                if (update->num && DRM_COPY_FROM_USER(rects,
 136                                                     (struct drm_clip_rect __user *)
 137                                                     (unsigned long)update->data,
 138                                                     update->num *
 139                                                     sizeof(*rects))) {
 140                        DRM_ERROR("Failed to copy cliprects from userspace\n");
 141                        err = -EFAULT;
 142                        goto error;
 143                }
 144
 145                spin_lock_irqsave(&dev->drw_lock, irqflags);
 146
 147                if (rects != info->rects) {
 148                        drm_free(info->rects, info->num_rects *
 149                                 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
 150                }
 151
 152                info->rects = rects;
 153                info->num_rects = update->num;
 154
 155                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 156
 157                DRM_DEBUG("Updated %d cliprects for drawable %d\n",
 158                          info->num_rects, update->handle);
 159                break;
 160        default:
 161                DRM_ERROR("Invalid update type %d\n", update->type);
 162                return -EINVAL;
 163        }
 164
 165        return 0;
 166
 167error:
 168        if (rects != info->rects)
 169                drm_free(rects, update->num * sizeof(struct drm_clip_rect),
 170                         DRM_MEM_BUFS);
 171
 172        return err;
 173}
 174
 175/**
 176 * Caller must hold the drawable spinlock!
 177 */
 178struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
 179{
 180        return idr_find(&dev->drw_idr, id);
 181}
 182EXPORT_SYMBOL(drm_get_drawable_info);
 183
 184static int drm_drawable_free(int idr, void *p, void *data)
 185{
 186        struct drm_drawable_info *info = p;
 187
 188        if (info) {
 189                drm_free(info->rects, info->num_rects *
 190                         sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
 191                drm_free(info, sizeof(*info), DRM_MEM_BUFS);
 192        }
 193
 194        return 0;
 195}
 196
 197void drm_drawable_free_all(struct drm_device *dev)
 198{
 199        idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
 200        idr_remove_all(&dev->drw_idr);
 201}
 202
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.