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_put_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 uint32_t format; 92 93 if (args->bpp != 32) 94 return -EINVAL; 95 96 pitch = args->width * 4; 97 args->size = pitch * args->height; 98 args->size = ALIGN(args->size, PAGE_SIZE); 99 100 ret = virtio_gpu_gem_create(file_priv, dev, args->size, &gobj, 101 &args->handle); 102 if (ret) 103 goto fail; 104 105 format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888); 106 virtio_gpu_resource_id_get(vgdev, &resid); 107 virtio_gpu_cmd_create_resource(vgdev, resid, format, 108 args->width, args->height); 109 110 /* attach the object to the resource */ 111 obj = gem_to_virtio_gpu_obj(gobj); 112 ret = virtio_gpu_object_attach(vgdev, obj, resid, NULL); 113 if (ret) 114 goto fail; 115 116 obj->dumb = true; 117 args->pitch = pitch; 118 return ret; 119 120 fail: 121 return ret; 122 } 123 124 int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, 125 struct drm_device *dev, 126 uint32_t handle, uint64_t *offset_p) 127 { 128 struct drm_gem_object *gobj; 129 struct virtio_gpu_object *obj; 130 131 BUG_ON(!offset_p); 132 gobj = drm_gem_object_lookup(file_priv, handle); 133 if (gobj == NULL) 134 return -ENOENT; 135 obj = gem_to_virtio_gpu_obj(gobj); 136 *offset_p = virtio_gpu_object_mmap_offset(obj); 137 drm_gem_object_put_unlocked(gobj); 138 return 0; 139 } 140 141 int virtio_gpu_gem_object_open(struct drm_gem_object *obj, 142 struct drm_file *file) 143 { 144 struct virtio_gpu_device *vgdev = obj->dev->dev_private; 145 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 146 struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); 147 int r; 148 149 if (!vgdev->has_virgl_3d) 150 return 0; 151 152 r = virtio_gpu_object_reserve(qobj, false); 153 if (r) 154 return r; 155 156 virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id, 157 qobj->hw_res_handle); 158 virtio_gpu_object_unreserve(qobj); 159 return 0; 160 } 161 162 void virtio_gpu_gem_object_close(struct drm_gem_object *obj, 163 struct drm_file *file) 164 { 165 struct virtio_gpu_device *vgdev = obj->dev->dev_private; 166 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 167 struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); 168 int r; 169 170 if (!vgdev->has_virgl_3d) 171 return; 172 173 r = virtio_gpu_object_reserve(qobj, false); 174 if (r) 175 return; 176 177 virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id, 178 qobj->hw_res_handle); 179 virtio_gpu_object_unreserve(qobj); 180 } 181