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