1/********************************************************** 2 * Copyright 2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26 27#include "pipe/p_compiler.h" 28#include "util/u_inlines.h" 29#include "util/u_memory.h" 30#include "util/u_format.h" 31#include "vmw_screen.h" 32 33#include "vmw_surface.h" 34#include "svga_drm_public.h" 35 36#include "state_tracker/drm_driver.h" 37 38#include "vmwgfx_drm.h" 39#include <xf86drm.h> 40 41#include <stdio.h> 42 43struct dri1_api_version { 44 int major; 45 int minor; 46 int patch_level; 47}; 48 49static struct svga_winsys_surface * 50vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, 51 struct winsys_handle *whandle, 52 SVGA3dSurfaceFormat *format); 53static boolean 54vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, 55 struct svga_winsys_surface *surface, 56 unsigned stride, 57 struct winsys_handle *whandle); 58 59static struct dri1_api_version drm_required = { 2, 1, 0 }; 60static struct dri1_api_version drm_compat = { 2, 0, 0 }; 61 62static boolean 63vmw_dri1_check_version(const struct dri1_api_version *cur, 64 const struct dri1_api_version *required, 65 const struct dri1_api_version *compat, 66 const char component[]) 67{ 68 if (cur->major > required->major && cur->major <= compat->major) 69 return TRUE; 70 if (cur->major == required->major && cur->minor >= required->minor) 71 return TRUE; 72 73 fprintf(stderr, "%s version failure.\n", component); 74 fprintf(stderr, "%s version is %d.%d.%d and this driver can only work\n" 75 "with versions %d.%d.x through %d.x.x.\n", 76 component, 77 cur->major, 78 cur->minor, 79 cur->patch_level, required->major, required->minor, compat->major); 80 return FALSE; 81} 82 83/* This is actually the entrypoint to the entire driver, 84 * called by the target bootstrap code. 85 */ 86struct svga_winsys_screen * 87svga_drm_winsys_screen_create(int fd) 88{ 89 struct vmw_winsys_screen *vws; 90 struct dri1_api_version drm_ver; 91 drmVersionPtr ver; 92 93 ver = drmGetVersion(fd); 94 if (ver == NULL) 95 return NULL; 96 97 drm_ver.major = ver->version_major; 98 drm_ver.minor = ver->version_minor; 99 drm_ver.patch_level = 0; /* ??? */ 100 101 drmFreeVersion(ver); 102 if (!vmw_dri1_check_version(&drm_ver, &drm_required, 103 &drm_compat, "vmwgfx drm driver")) 104 return NULL; 105 106 vws = vmw_winsys_create( fd, FALSE ); 107 if (!vws) 108 goto out_no_vws; 109 110 /* XXX do this properly */ 111 vws->base.surface_from_handle = vmw_drm_surface_from_handle; 112 vws->base.surface_get_handle = vmw_drm_surface_get_handle; 113 114 return &vws->base; 115 116out_no_vws: 117 return NULL; 118} 119 120static INLINE boolean 121vmw_dri1_intersect_src_bbox(struct drm_clip_rect *dst, 122 int dst_x, 123 int dst_y, 124 const struct drm_clip_rect *src, 125 const struct drm_clip_rect *bbox) 126{ 127 int xy1; 128 int xy2; 129 130 xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : 131 (int)bbox->x1 + dst_x; 132 xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : 133 (int)bbox->x2 + dst_x; 134 if (xy1 >= xy2 || xy1 < 0) 135 return FALSE; 136 137 dst->x1 = xy1; 138 dst->x2 = xy2; 139 140 xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : 141 (int)bbox->y1 + dst_y; 142 xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : 143 (int)bbox->y2 + dst_y; 144 if (xy1 >= xy2 || xy1 < 0) 145 return FALSE; 146 147 dst->y1 = xy1; 148 dst->y2 = xy2; 149 return TRUE; 150} 151 152static struct svga_winsys_surface * 153vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, 154 struct winsys_handle *whandle, 155 SVGA3dSurfaceFormat *format) 156{ 157 struct vmw_svga_winsys_surface *vsrf; 158 struct svga_winsys_surface *ssrf; 159 struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); 160 union drm_vmw_surface_reference_arg arg; 161 struct drm_vmw_surface_arg *req = &arg.req; 162 struct drm_vmw_surface_create_req *rep = &arg.rep; 163 int ret; 164 int i; 165 166 /** 167 * The vmware device specific handle is the hardware SID. 168 * FIXME: We probably want to move this to the ioctl implementations. 169 */ 170 171 memset(&arg, 0, sizeof(arg)); 172 req->sid = whandle->handle; 173 174 ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, 175 &arg, sizeof(arg)); 176 177 if (ret) { 178 fprintf(stderr, "Failed referencing shared surface. SID %d.\n" 179 "Error %d (%s).\n", 180 whandle->handle, ret, strerror(-ret)); 181 return NULL; 182 } 183 184 if (rep->mip_levels[0] != 1) { 185 fprintf(stderr, "Incorrect number of mipmap levels on shared surface." 186 " SID %d, levels %d\n", 187 whandle->handle, rep->mip_levels[0]); 188 goto out_mip; 189 } 190 191 for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 192 if (rep->mip_levels[i] != 0) { 193 fprintf(stderr, "Incorrect number of faces levels on shared surface." 194 " SID %d, face %d present.\n", 195 whandle->handle, i); 196 goto out_mip; 197 } 198 } 199 200 vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); 201 if (!vsrf) 202 goto out_mip; 203 204 pipe_reference_init(&vsrf->refcnt, 1); 205 p_atomic_set(&vsrf->validated, 0); 206 vsrf->screen = vws; 207 vsrf->sid = whandle->handle; 208 ssrf = svga_winsys_surface(vsrf); 209 *format = rep->format; 210 211 return ssrf; 212 213out_mip: 214 vmw_ioctl_surface_destroy(vws, whandle->handle); 215 return NULL; 216} 217 218static boolean 219vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, 220 struct svga_winsys_surface *surface, 221 unsigned stride, 222 struct winsys_handle *whandle) 223{ 224 struct vmw_svga_winsys_surface *vsrf; 225 226 if (!surface) 227 return FALSE; 228 229 vsrf = vmw_svga_winsys_surface(surface); 230 whandle->handle = vsrf->sid; 231 whandle->stride = stride; 232 233 return TRUE; 234} 235