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* 38 virtio_gpu_alloc_object(struct drm_device *dev, 39 struct virtio_gpu_object_params *params, 40 struct virtio_gpu_fence *fence) 41 { 42 struct virtio_gpu_device *vgdev = dev->dev_private; 43 struct virtio_gpu_object *obj; 44 int ret; 45 46 ret = virtio_gpu_object_create(vgdev, params, &obj, fence); 47 if (ret) 48 return ERR_PTR(ret); 49 50 return obj; 51 } 52 53 int virtio_gpu_gem_create(struct drm_file *file, 54 struct drm_device *dev, 55 struct virtio_gpu_object_params *params, 56 struct drm_gem_object **obj_p, 57 uint32_t *handle_p) 58 { 59 struct virtio_gpu_object *obj; 60 int ret; 61 u32 handle; 62 63 obj = virtio_gpu_alloc_object(dev, params, NULL); 64 if (IS_ERR(obj)) 65 return PTR_ERR(obj); 66 67 ret = drm_gem_handle_create(file, &obj->gem_base, &handle); 68 if (ret) { 69 drm_gem_object_release(&obj->gem_base); 70 return ret; 71 } 72 73 *obj_p = &obj->gem_base; 74 75 /* drop reference from allocate - handle holds it now */ 76 drm_gem_object_put_unlocked(&obj->gem_base); 77 78 *handle_p = handle; 79 return 0; 80 } 81 82 int virtio_gpu_mode_dumb_create(struct drm_file *file_priv, 83 struct drm_device *dev, 84 struct drm_mode_create_dumb *args) 85 { 86 struct drm_gem_object *gobj; 87 struct virtio_gpu_object_params params = { 0 }; 88 int ret; 89 uint32_t pitch; 90 91 if (args->bpp != 32) 92 return -EINVAL; 93 94 pitch = args->width * 4; 95 args->size = pitch * args->height; 96 args->size = ALIGN(args->size, PAGE_SIZE); 97 98 params.format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888); 99 params.width = args->width; 100 params.height = args->height; 101 params.size = args->size; 102 params.dumb = true; 103 ret = virtio_gpu_gem_create(file_priv, dev, ¶ms, &gobj, 104 &args->handle); 105 if (ret) 106 goto fail; 107 108 args->pitch = pitch; 109 return ret; 110 111 fail: 112 return ret; 113 } 114 115 int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, 116 struct drm_device *dev, 117 uint32_t handle, uint64_t *offset_p) 118 { 119 struct drm_gem_object *gobj; 120 struct virtio_gpu_object *obj; 121 122 BUG_ON(!offset_p); 123 gobj = drm_gem_object_lookup(file_priv, handle); 124 if (gobj == NULL) 125 return -ENOENT; 126 obj = gem_to_virtio_gpu_obj(gobj); 127 *offset_p = virtio_gpu_object_mmap_offset(obj); 128 drm_gem_object_put_unlocked(gobj); 129 return 0; 130 } 131 132 int virtio_gpu_gem_object_open(struct drm_gem_object *obj, 133 struct drm_file *file) 134 { 135 struct virtio_gpu_device *vgdev = obj->dev->dev_private; 136 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 137 struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); 138 int r; 139 140 if (!vgdev->has_virgl_3d) 141 return 0; 142 143 r = virtio_gpu_object_reserve(qobj, false); 144 if (r) 145 return r; 146 147 virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id, 148 qobj->hw_res_handle); 149 virtio_gpu_object_unreserve(qobj); 150 return 0; 151 } 152 153 void virtio_gpu_gem_object_close(struct drm_gem_object *obj, 154 struct drm_file *file) 155 { 156 struct virtio_gpu_device *vgdev = obj->dev->dev_private; 157 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 158 struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); 159 int r; 160 161 if (!vgdev->has_virgl_3d) 162 return; 163 164 r = virtio_gpu_object_reserve(qobj, false); 165 if (r) 166 return; 167 168 virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id, 169 qobj->hw_res_handle); 170 virtio_gpu_object_unreserve(qobj); 171 } 172