vmw_screen_dri.c revision 3f28dbd9bb78f03681005cafa115008595b3c27d
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 = { 1, 0, 0 }; 60static struct dri1_api_version drm_compat = { 1, 0, 0 }; 61static struct dri1_api_version drm_scanout = { 0, 9, 0 }; 62 63static boolean 64vmw_dri1_check_version(const struct dri1_api_version *cur, 65 const struct dri1_api_version *required, 66 const struct dri1_api_version *compat, 67 const char component[]) 68{ 69 if (cur->major > required->major && cur->major <= compat->major) 70 return TRUE; 71 if (cur->major == required->major && cur->minor >= required->minor) 72 return TRUE; 73 74 fprintf(stderr, "%s version failure.\n", component); 75 fprintf(stderr, "%s version is %d.%d.%d and this driver can only work\n" 76 "with versions %d.%d.x through %d.x.x.\n", 77 component, 78 cur->major, 79 cur->minor, 80 cur->patch_level, required->major, required->minor, compat->major); 81 return FALSE; 82} 83 84/* This is actually the entrypoint to the entire driver, 85 * called by the target bootstrap code. 86 */ 87struct svga_winsys_screen * 88svga_drm_winsys_screen_create(int fd) 89{ 90 struct vmw_winsys_screen *vws; 91 boolean use_old_scanout_flag = FALSE; 92 93 struct dri1_api_version drm_ver; 94 drmVersionPtr ver; 95 96 ver = drmGetVersion(fd); 97 if (ver == NULL) 98 return NULL; 99 100 drm_ver.major = ver->version_major; 101 drm_ver.minor = ver->version_minor; 102 drm_ver.patch_level = 0; /* ??? */ 103 104 drmFreeVersion(ver); 105 if (!vmw_dri1_check_version(&drm_ver, &drm_required, 106 &drm_compat, "vmwgfx drm driver")) 107 return NULL; 108 109 if (!vmw_dri1_check_version(&drm_ver, &drm_scanout, 110 &drm_compat, "use old scanout field (not a error)")) 111 use_old_scanout_flag = TRUE; 112 113 vws = vmw_winsys_create( fd, use_old_scanout_flag ); 114 if (!vws) 115 goto out_no_vws; 116 117 /* XXX do this properly */ 118 vws->base.surface_from_handle = vmw_drm_surface_from_handle; 119 vws->base.surface_get_handle = vmw_drm_surface_get_handle; 120 121 return &vws->base; 122 123out_no_vws: 124 return NULL; 125} 126 127static INLINE boolean 128vmw_dri1_intersect_src_bbox(struct drm_clip_rect *dst, 129 int dst_x, 130 int dst_y, 131 const struct drm_clip_rect *src, 132 const struct drm_clip_rect *bbox) 133{ 134 int xy1; 135 int xy2; 136 137 xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : 138 (int)bbox->x1 + dst_x; 139 xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : 140 (int)bbox->x2 + dst_x; 141 if (xy1 >= xy2 || xy1 < 0) 142 return FALSE; 143 144 dst->x1 = xy1; 145 dst->x2 = xy2; 146 147 xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : 148 (int)bbox->y1 + dst_y; 149 xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : 150 (int)bbox->y2 + dst_y; 151 if (xy1 >= xy2 || xy1 < 0) 152 return FALSE; 153 154 dst->y1 = xy1; 155 dst->y2 = xy2; 156 return TRUE; 157} 158 159static struct svga_winsys_surface * 160vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, 161 struct winsys_handle *whandle, 162 SVGA3dSurfaceFormat *format) 163{ 164 struct vmw_svga_winsys_surface *vsrf; 165 struct svga_winsys_surface *ssrf; 166 struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); 167 union drm_vmw_surface_reference_arg arg; 168 struct drm_vmw_surface_arg *req = &arg.req; 169 struct drm_vmw_surface_create_req *rep = &arg.rep; 170 int ret; 171 int i; 172 173 /** 174 * The vmware device specific handle is the hardware SID. 175 * FIXME: We probably want to move this to the ioctl implementations. 176 */ 177 178 memset(&arg, 0, sizeof(arg)); 179 req->sid = whandle->handle; 180 181 ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, 182 &arg, sizeof(arg)); 183 184 if (ret) { 185 fprintf(stderr, "Failed referencing shared surface. SID %d.\n" 186 "Error %d (%s).\n", 187 whandle->handle, ret, strerror(-ret)); 188 return NULL; 189 } 190 191 if (rep->mip_levels[0] != 1) { 192 fprintf(stderr, "Incorrect number of mipmap levels on shared surface." 193 " SID %d, levels %d\n", 194 whandle->handle, rep->mip_levels[0]); 195 goto out_mip; 196 } 197 198 for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 199 if (rep->mip_levels[i] != 0) { 200 fprintf(stderr, "Incorrect number of faces levels on shared surface." 201 " SID %d, face %d present.\n", 202 whandle->handle, i); 203 goto out_mip; 204 } 205 } 206 207 vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); 208 if (!vsrf) 209 goto out_mip; 210 211 pipe_reference_init(&vsrf->refcnt, 1); 212 p_atomic_set(&vsrf->validated, 0); 213 vsrf->screen = vws; 214 vsrf->sid = whandle->handle; 215 ssrf = svga_winsys_surface(vsrf); 216 *format = rep->format; 217 218 return ssrf; 219 220out_mip: 221 vmw_ioctl_surface_destroy(vws, whandle->handle); 222 return NULL; 223} 224 225static boolean 226vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, 227 struct svga_winsys_surface *surface, 228 unsigned stride, 229 struct winsys_handle *whandle) 230{ 231 struct vmw_svga_winsys_surface *vsrf; 232 233 if (!surface) 234 return FALSE; 235 236 vsrf = vmw_svga_winsys_surface(surface); 237 whandle->handle = vsrf->sid; 238 whandle->stride = stride; 239 240 return TRUE; 241} 242