1145132Sanholt/*- 2145132Sanholt * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 3145132Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 4145132Sanholt * All Rights Reserved. 5145132Sanholt * 6145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 7145132Sanholt * copy of this software and associated documentation files (the "Software"), 8145132Sanholt * to deal in the Software without restriction, including without limitation 9145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 11145132Sanholt * Software is furnished to do so, subject to the following conditions: 12145132Sanholt * 13145132Sanholt * The above copyright notice and this permission notice (including the next 14145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 15145132Sanholt * Software. 16145132Sanholt * 17145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20145132Sanholt * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21145132Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22145132Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23145132Sanholt * OTHER DEALINGS IN THE SOFTWARE. 24145132Sanholt * 25145132Sanholt * Authors: 26145132Sanholt * Rickard E. (Rik) Faith <faith@valinux.com> 27145132Sanholt * Gareth Hughes <gareth@valinux.com> 28145132Sanholt * 29145132Sanholt */ 30145132Sanholt 31152909Sanholt#include <sys/cdefs.h> 32152909Sanholt__FBSDID("$FreeBSD$"); 33152909Sanholt 34182080Srnoland/** @file drm_drawable.c 35182080Srnoland * This file implements ioctls to store information along with DRM drawables, 36182080Srnoland * such as the current set of cliprects for vblank-synced buffer swaps. 37182080Srnoland */ 38182080Srnoland 39145132Sanholt#include "dev/drm/drmP.h" 40145132Sanholt 41182080Srnolandstruct bsd_drm_drawable_info { 42182080Srnoland struct drm_drawable_info info; 43182080Srnoland int handle; 44182080Srnoland RB_ENTRY(bsd_drm_drawable_info) tree; 45182080Srnoland}; 46182080Srnoland 47182080Srnolandstatic int 48182080Srnolanddrm_drawable_compare(struct bsd_drm_drawable_info *a, 49182080Srnoland struct bsd_drm_drawable_info *b) 50145132Sanholt{ 51182080Srnoland if (a->handle > b->handle) 52182080Srnoland return 1; 53182080Srnoland if (a->handle < b->handle) 54182080Srnoland return -1; 55182080Srnoland return 0; 56182080Srnoland} 57145132Sanholt 58182080SrnolandRB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree, 59182080Srnoland drm_drawable_compare); 60145132Sanholt 61182080Srnolandstruct drm_drawable_info * 62182080Srnolanddrm_get_drawable_info(struct drm_device *dev, int handle) 63182080Srnoland{ 64182080Srnoland struct bsd_drm_drawable_info find, *result; 65182080Srnoland 66182080Srnoland find.handle = handle; 67182080Srnoland result = RB_FIND(drawable_tree, &dev->drw_head, &find); 68182080Srnoland 69182080Srnoland return &result->info; 70182080Srnoland} 71182080Srnoland 72182080Srnolandint drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) 73182080Srnoland{ 74183573Srnoland struct drm_draw *draw = data; 75182080Srnoland struct bsd_drm_drawable_info *info; 76182080Srnoland 77183834Srnoland info = malloc(sizeof(struct bsd_drm_drawable_info), DRM_MEM_DRAWABLE, 78183834Srnoland M_NOWAIT | M_ZERO); 79182080Srnoland if (info == NULL) 80182080Srnoland return ENOMEM; 81182080Srnoland 82182080Srnoland info->handle = alloc_unr(dev->drw_unrhdr); 83182080Srnoland DRM_SPINLOCK(&dev->drw_lock); 84182080Srnoland RB_INSERT(drawable_tree, &dev->drw_head, info); 85182080Srnoland draw->handle = info->handle; 86182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 87182080Srnoland 88182080Srnoland DRM_DEBUG("%d\n", draw->handle); 89182080Srnoland 90145132Sanholt return 0; 91145132Sanholt} 92145132Sanholt 93182080Srnolandint drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) 94145132Sanholt{ 95183573Srnoland struct drm_draw *draw = (struct drm_draw *)data; 96182080Srnoland struct drm_drawable_info *info; 97182080Srnoland 98182080Srnoland DRM_SPINLOCK(&dev->drw_lock); 99182080Srnoland info = drm_get_drawable_info(dev, draw->handle); 100182080Srnoland if (info != NULL) { 101182080Srnoland RB_REMOVE(drawable_tree, &dev->drw_head, 102182080Srnoland (struct bsd_drm_drawable_info *)info); 103182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 104182080Srnoland free_unr(dev->drw_unrhdr, draw->handle); 105183834Srnoland free(info->rects, DRM_MEM_DRAWABLE); 106183834Srnoland free(info, DRM_MEM_DRAWABLE); 107182080Srnoland return 0; 108182080Srnoland } else { 109182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 110182080Srnoland return EINVAL; 111182080Srnoland } 112145132Sanholt} 113182080Srnoland 114182080Srnolandint drm_update_draw(struct drm_device *dev, void *data, 115182080Srnoland struct drm_file *file_priv) 116182080Srnoland{ 117182080Srnoland struct drm_drawable_info *info; 118182080Srnoland struct drm_update_draw *update = (struct drm_update_draw *)data; 119182080Srnoland int ret; 120182080Srnoland 121182080Srnoland info = drm_get_drawable_info(dev, update->handle); 122182080Srnoland if (info == NULL) 123182080Srnoland return EINVAL; 124182080Srnoland 125182080Srnoland switch (update->type) { 126182080Srnoland case DRM_DRAWABLE_CLIPRECTS: 127182080Srnoland DRM_SPINLOCK(&dev->drw_lock); 128182080Srnoland if (update->num != info->num_rects) { 129183834Srnoland free(info->rects, DRM_MEM_DRAWABLE); 130182080Srnoland info->rects = NULL; 131182080Srnoland info->num_rects = 0; 132182080Srnoland } 133182080Srnoland if (update->num == 0) { 134182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 135182080Srnoland return 0; 136182080Srnoland } 137182080Srnoland if (info->rects == NULL) { 138183834Srnoland info->rects = malloc(sizeof(*info->rects) * 139183834Srnoland update->num, DRM_MEM_DRAWABLE, M_NOWAIT); 140182080Srnoland if (info->rects == NULL) { 141182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 142182080Srnoland return ENOMEM; 143182080Srnoland } 144182080Srnoland info->num_rects = update->num; 145182080Srnoland } 146182080Srnoland /* For some reason the pointer arg is unsigned long long. */ 147182080Srnoland ret = copyin((void *)(intptr_t)update->data, info->rects, 148182080Srnoland sizeof(*info->rects) * info->num_rects); 149182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 150182080Srnoland return ret; 151182080Srnoland default: 152182080Srnoland return EINVAL; 153182080Srnoland } 154182080Srnoland} 155182080Srnoland 156182080Srnolandvoid drm_drawable_free_all(struct drm_device *dev) 157182080Srnoland{ 158182080Srnoland struct bsd_drm_drawable_info *info, *next; 159182080Srnoland 160182080Srnoland DRM_SPINLOCK(&dev->drw_lock); 161182080Srnoland for (info = RB_MIN(drawable_tree, &dev->drw_head); 162182080Srnoland info != NULL ; info = next) { 163182080Srnoland next = RB_NEXT(drawable_tree, &dev->drw_head, info); 164182080Srnoland RB_REMOVE(drawable_tree, &dev->drw_head, 165182080Srnoland (struct bsd_drm_drawable_info *)info); 166182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 167182080Srnoland free_unr(dev->drw_unrhdr, info->handle); 168183834Srnoland free(info->info.rects, DRM_MEM_DRAWABLE); 169183834Srnoland free(info, DRM_MEM_DRAWABLE); 170182080Srnoland DRM_SPINLOCK(&dev->drw_lock); 171182080Srnoland } 172182080Srnoland DRM_SPINUNLOCK(&dev->drw_lock); 173182080Srnoland} 174