1235783Skib/*- 2235783Skib * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 3235783Skib * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 4235783Skib * All Rights Reserved. 5235783Skib * 6235783Skib * Permission is hereby granted, free of charge, to any person obtaining a 7235783Skib * copy of this software and associated documentation files (the "Software"), 8235783Skib * to deal in the Software without restriction, including without limitation 9235783Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10235783Skib * and/or sell copies of the Software, and to permit persons to whom the 11235783Skib * Software is furnished to do so, subject to the following conditions: 12235783Skib * 13235783Skib * The above copyright notice and this permission notice (including the next 14235783Skib * paragraph) shall be included in all copies or substantial portions of the 15235783Skib * Software. 16235783Skib * 17235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20235783Skib * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21235783Skib * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22235783Skib * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23235783Skib * OTHER DEALINGS IN THE SOFTWARE. 24235783Skib * 25235783Skib * Authors: 26235783Skib * Rickard E. (Rik) Faith <faith@valinux.com> 27235783Skib * Gareth Hughes <gareth@valinux.com> 28235783Skib * 29235783Skib */ 30235783Skib 31235783Skib#include <sys/cdefs.h> 32235783Skib__FBSDID("$FreeBSD$"); 33235783Skib 34235783Skib/** @file drm_drawable.c 35235783Skib * This file implements ioctls to store information along with DRM drawables, 36235783Skib * such as the current set of cliprects for vblank-synced buffer swaps. 37235783Skib */ 38235783Skib 39235783Skib#include <dev/drm2/drmP.h> 40235783Skib 41235783Skibstruct bsd_drm_drawable_info { 42235783Skib struct drm_drawable_info info; 43235783Skib int handle; 44235783Skib RB_ENTRY(bsd_drm_drawable_info) tree; 45235783Skib}; 46235783Skib 47235783Skibstatic int 48235783Skibdrm_drawable_compare(struct bsd_drm_drawable_info *a, 49235783Skib struct bsd_drm_drawable_info *b) 50235783Skib{ 51235783Skib if (a->handle > b->handle) 52235783Skib return 1; 53235783Skib if (a->handle < b->handle) 54235783Skib return -1; 55235783Skib return 0; 56235783Skib} 57235783Skib 58235783SkibRB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree, 59235783Skib drm_drawable_compare); 60235783Skib 61235783Skibstruct drm_drawable_info * 62235783Skibdrm_get_drawable_info(struct drm_device *dev, int handle) 63235783Skib{ 64235783Skib struct bsd_drm_drawable_info find, *result; 65235783Skib 66235783Skib find.handle = handle; 67235783Skib result = RB_FIND(drawable_tree, &dev->drw_head, &find); 68235783Skib 69235783Skib return &result->info; 70235783Skib} 71235783Skib 72235783Skibint drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) 73235783Skib{ 74235783Skib struct drm_draw *draw = data; 75235783Skib struct bsd_drm_drawable_info *info; 76235783Skib 77235783Skib info = malloc(sizeof(struct bsd_drm_drawable_info), DRM_MEM_DRAWABLE, 78235783Skib M_NOWAIT | M_ZERO); 79235783Skib if (info == NULL) 80235783Skib return ENOMEM; 81235783Skib 82235783Skib info->handle = alloc_unr(dev->drw_unrhdr); 83235783Skib DRM_SPINLOCK(&dev->drw_lock); 84235783Skib RB_INSERT(drawable_tree, &dev->drw_head, info); 85235783Skib draw->handle = info->handle; 86235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 87235783Skib 88235783Skib DRM_DEBUG("%d\n", draw->handle); 89235783Skib 90235783Skib return 0; 91235783Skib} 92235783Skib 93235783Skibint drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) 94235783Skib{ 95235783Skib struct drm_draw *draw = (struct drm_draw *)data; 96235783Skib struct drm_drawable_info *info; 97235783Skib 98235783Skib DRM_SPINLOCK(&dev->drw_lock); 99235783Skib info = drm_get_drawable_info(dev, draw->handle); 100235783Skib if (info != NULL) { 101235783Skib RB_REMOVE(drawable_tree, &dev->drw_head, 102235783Skib (struct bsd_drm_drawable_info *)info); 103235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 104235783Skib free_unr(dev->drw_unrhdr, draw->handle); 105235783Skib free(info->rects, DRM_MEM_DRAWABLE); 106235783Skib free(info, DRM_MEM_DRAWABLE); 107235783Skib return 0; 108235783Skib } else { 109235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 110235783Skib return EINVAL; 111235783Skib } 112235783Skib} 113235783Skib 114235783Skibint drm_update_draw(struct drm_device *dev, void *data, 115235783Skib struct drm_file *file_priv) 116235783Skib{ 117235783Skib struct drm_drawable_info *info; 118235783Skib struct drm_update_draw *update = (struct drm_update_draw *)data; 119235783Skib int ret; 120235783Skib 121235783Skib info = drm_get_drawable_info(dev, update->handle); 122235783Skib if (info == NULL) 123235783Skib return EINVAL; 124235783Skib 125235783Skib switch (update->type) { 126235783Skib case DRM_DRAWABLE_CLIPRECTS: 127235783Skib DRM_SPINLOCK(&dev->drw_lock); 128235783Skib if (update->num != info->num_rects) { 129235783Skib free(info->rects, DRM_MEM_DRAWABLE); 130235783Skib info->rects = NULL; 131235783Skib info->num_rects = 0; 132235783Skib } 133235783Skib if (update->num == 0) { 134235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 135235783Skib return 0; 136235783Skib } 137235783Skib if (info->rects == NULL) { 138235783Skib info->rects = malloc(sizeof(*info->rects) * 139235783Skib update->num, DRM_MEM_DRAWABLE, M_NOWAIT); 140235783Skib if (info->rects == NULL) { 141235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 142235783Skib return ENOMEM; 143235783Skib } 144235783Skib info->num_rects = update->num; 145235783Skib } 146235783Skib /* For some reason the pointer arg is unsigned long long. */ 147235783Skib ret = copyin((void *)(intptr_t)update->data, info->rects, 148235783Skib sizeof(*info->rects) * info->num_rects); 149235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 150235783Skib return ret; 151235783Skib default: 152235783Skib return EINVAL; 153235783Skib } 154235783Skib} 155235783Skib 156235783Skibvoid drm_drawable_free_all(struct drm_device *dev) 157235783Skib{ 158235783Skib struct bsd_drm_drawable_info *info, *next; 159235783Skib 160235783Skib DRM_SPINLOCK(&dev->drw_lock); 161235783Skib for (info = RB_MIN(drawable_tree, &dev->drw_head); 162235783Skib info != NULL ; info = next) { 163235783Skib next = RB_NEXT(drawable_tree, &dev->drw_head, info); 164235783Skib RB_REMOVE(drawable_tree, &dev->drw_head, 165235783Skib (struct bsd_drm_drawable_info *)info); 166235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 167235783Skib free_unr(dev->drw_unrhdr, info->handle); 168235783Skib free(info->info.rects, DRM_MEM_DRAWABLE); 169235783Skib free(info, DRM_MEM_DRAWABLE); 170235783Skib DRM_SPINLOCK(&dev->drw_lock); 171235783Skib } 172235783Skib DRM_SPINUNLOCK(&dev->drw_lock); 173235783Skib} 174