1 /* 2 * Copyright (C) 2015 Red Hat, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 #include <drm/drmP.h> 27 #include "virtgpu_drv.h" 28 29 void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj) 30 { 31 struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(gem_obj); 32 33 if (obj) 34 virtio_gpu_object_unref(&obj); 35 } 36 37 struct virtio_gpu_object *virtio_gpu_alloc_object(struct drm_device *dev, 38 size_t size, bool kernel, 39 bool pinned) 40 { 41 struct virtio_gpu_device *vgdev = dev->dev_private; 42 struct virtio_gpu_object *obj; 43 int ret; 44 45 ret = virtio_gpu_object_create(vgdev, size, kernel, pinned, &obj); 46 if (ret) 47 return ERR_PTR(ret); 48 49 return obj; 50 } 51 52 int virtio_gpu_gem_create(struct drm_file *file, 53 struct drm_device *dev, 54 uint64_t size, 55 struct drm_gem_object **obj_p, 56 uint32_t *handle_p) 57 { 58 struct virtio_gpu_object *obj; 59 int ret; 60 u32 handle; 61 62 obj = virtio_gpu_alloc_object(dev, size, false, false); 63 if (IS_ERR(obj)) 64 return PTR_ERR(obj); 65 66 ret = drm_gem_handle_create(file, &obj->gem_base, &handle); 67 if (ret) { 68 drm_gem_object_release(&obj->gem_base); 69 return ret; 70 } 71 72 *obj_p = &obj->gem_base; 73 74 /* drop reference from allocate - handle holds it now */ 75 drm_gem_object_unreference_unlocked(&obj->gem_base); 76 77 *handle_p = handle; 78 return 0; 79 } 80 81 int virtio_gpu_mode_dumb_create(struct drm_file *file_priv, 82 struct drm_device *dev, 83 struct drm_mode_create_dumb *args) 84 { 85 struct virtio_gpu_device *vgdev = dev->dev_private; 86 struct drm_gem_object *gobj; 87 struct virtio_gpu_object *obj; 88 int ret; 89 uint32_t pitch; 90 uint32_t resid; 91 92 pitch = args->width * ((args->bpp + 1) / 8); 93 args->size = pitch * args->height; 94 args->size = ALIGN(args->size, PAGE_SIZE); 95 96 ret = virtio_gpu_gem_create(file_priv, dev, args->size, &gobj, 97 &args->handle); 98 if (ret) 99 goto fail; 100 101 virtio_gpu_resource_id_get(vgdev, &resid); 102 virtio_gpu_cmd_create_resource(vgdev, resid, 103 2, args->width, args->height); 104 105 /* attach the object to the resource */ 106 obj = gem_to_virtio_gpu_obj(gobj); 107 ret = virtio_gpu_object_attach(vgdev, obj, resid, NULL); 108 if (ret) 109 goto fail; 110 111 obj->dumb = true; 112 args->pitch = pitch; 113 return ret; 114 115 fail: 116 return ret; 117 } 118 119 int virtio_gpu_mode_dumb_destroy(struct drm_file *file_priv, 120 struct drm_device *dev, 121 uint32_t handle) 122 { 123 return drm_gem_handle_delete(file_priv, handle); 124 } 125 126 int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, 127 struct drm_device *dev, 128 uint32_t handle, uint64_t *offset_p) 129 { 130 struct drm_gem_object *gobj; 131 struct virtio_gpu_object *obj; 132 BUG_ON(!offset_p); 133 gobj = drm_gem_object_lookup(file_priv, handle); 134 if (gobj == NULL) 135 return -ENOENT; 136 obj = gem_to_virtio_gpu_obj(gobj); 137 *offset_p = virtio_gpu_object_mmap_offset(obj); 138 drm_gem_object_unreference_unlocked(gobj); 139 return 0; 140 } 141 142 int virtio_gpu_gem_object_open(struct drm_gem_object *obj, 143 struct drm_file *file) 144 { 145 struct virtio_gpu_device *vgdev = obj->dev->dev_private; 146 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 147 struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); 148 int r; 149 150 if (!vgdev->has_virgl_3d) 151 return 0; 152 153 r = virtio_gpu_object_reserve(qobj, false); 154 if (r) 155 return r; 156 157 virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id, 158 qobj->hw_res_handle); 159 virtio_gpu_object_unreserve(qobj); 160 return 0; 161 } 162 163 void virtio_gpu_gem_object_close(struct drm_gem_object *obj, 164 struct drm_file *file) 165 { 166 struct virtio_gpu_device *vgdev = obj->dev->dev_private; 167 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 168 struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); 169 int r; 170 171 if (!vgdev->has_virgl_3d) 172 return; 173 174 r = virtio_gpu_object_reserve(qobj, false); 175 if (r) 176 return; 177 178 virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id, 179 qobj->hw_res_handle); 180 virtio_gpu_object_unreserve(qobj); 181 } 182