13bfa90b6Smrg/* 23bfa90b6Smrg * Copyright 2011 VMWare, Inc. 33bfa90b6Smrg * All Rights Reserved. 43bfa90b6Smrg * 53bfa90b6Smrg * Permission is hereby granted, free of charge, to any person obtaining a 63bfa90b6Smrg * copy of this software and associated documentation files (the 73bfa90b6Smrg * "Software"), to deal in the Software without restriction, including 83bfa90b6Smrg * without limitation the rights to use, copy, modify, merge, publish, 93bfa90b6Smrg * distribute, sub license, and/or sell copies of the Software, and to 103bfa90b6Smrg * permit persons to whom the Software is furnished to do so, subject to 113bfa90b6Smrg * the following conditions: 123bfa90b6Smrg * 133bfa90b6Smrg * The above copyright notice and this permission notice (including the 143bfa90b6Smrg * next paragraph) shall be included in all copies or substantial portions 153bfa90b6Smrg * of the Software. 163bfa90b6Smrg * 173bfa90b6Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 183bfa90b6Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 193bfa90b6Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 203bfa90b6Smrg * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 213bfa90b6Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 223bfa90b6Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 233bfa90b6Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 243bfa90b6Smrg * 253bfa90b6Smrg * Author: Jakob Bornecrantz <wallbraker@gmail.com> 263bfa90b6Smrg * Author: Thomas Hellstrom <thellstrom@vmware.com> 273bfa90b6Smrg */ 283bfa90b6Smrg 293bfa90b6Smrg#ifdef HAVE_CONFIG_H 303bfa90b6Smrg#include "config.h" 313bfa90b6Smrg#endif 323bfa90b6Smrg 333bfa90b6Smrg#include <stdint.h> 343bfa90b6Smrg#include <errno.h> 353bfa90b6Smrg#include <sys/mman.h> 363bfa90b6Smrg#include "vmwgfx_drm.h" 373bfa90b6Smrg#include <xf86drm.h> 383bfa90b6Smrg#include "vmwgfx_drmi.h" 393bfa90b6Smrg 403bfa90b6Smrg#define uint32 uint32_t 413bfa90b6Smrg#define int32 int32_t 423bfa90b6Smrg#define uint16 uint16_t 433bfa90b6Smrg#define uint8 uint8_t 443bfa90b6Smrg 453bfa90b6Smrg#include "svga3d_reg.h" 463bfa90b6Smrg#include "vmwgfx_driver.h" 4725dbecb6Smrg#include "common_compat.h" 483bfa90b6Smrg 493bfa90b6Smrgstatic int 503bfa90b6Smrgvmwgfx_fence_wait(int drm_fd, uint32_t handle, Bool unref) 513bfa90b6Smrg{ 523bfa90b6Smrg struct drm_vmw_fence_wait_arg farg; 533bfa90b6Smrg memset(&farg, 0, sizeof(farg)); 543bfa90b6Smrg 553bfa90b6Smrg farg.handle = handle; 563bfa90b6Smrg farg.flags = DRM_VMW_FENCE_FLAG_EXEC; 573bfa90b6Smrg farg.timeout_us = 10*1000000; 583bfa90b6Smrg farg.cookie_valid = 0; 593bfa90b6Smrg 603bfa90b6Smrg if (unref) 613bfa90b6Smrg farg.wait_options |= DRM_VMW_WAIT_OPTION_UNREF; 623bfa90b6Smrg 633bfa90b6Smrg return drmCommandWriteRead(drm_fd, DRM_VMW_FENCE_WAIT, &farg, 643bfa90b6Smrg sizeof(farg)); 653bfa90b6Smrg} 663bfa90b6Smrg 673bfa90b6Smrgstatic void 683bfa90b6Smrgvmwgfx_fence_unref(int drm_fd, uint32_t handle) 693bfa90b6Smrg{ 703bfa90b6Smrg struct drm_vmw_fence_arg farg; 713bfa90b6Smrg memset(&farg, 0, sizeof(farg)); 723bfa90b6Smrg 733bfa90b6Smrg farg.handle = handle; 743bfa90b6Smrg 753bfa90b6Smrg (void) drmCommandWrite(drm_fd, DRM_VMW_FENCE_UNREF, &farg, 763bfa90b6Smrg sizeof(farg)); 773bfa90b6Smrg} 783bfa90b6Smrg 793bfa90b6Smrg 803bfa90b6Smrgint 813bfa90b6Smrgvmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region) 823bfa90b6Smrg{ 833bfa90b6Smrg BoxPtr clips = REGION_RECTS(region); 843bfa90b6Smrg unsigned int num_clips = REGION_NUM_RECTS(region); 8525dbecb6Smrg unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS); 863bfa90b6Smrg struct drm_vmw_fence_rep rep; 873bfa90b6Smrg struct drm_vmw_present_readback_arg arg; 883bfa90b6Smrg int ret; 893bfa90b6Smrg unsigned i; 903bfa90b6Smrg struct drm_vmw_rect *rects, *r; 913bfa90b6Smrg 9225dbecb6Smrg if (num_clips == 0) 9325dbecb6Smrg return 0; 9425dbecb6Smrg 9525dbecb6Smrg rects = malloc(alloc_clips * sizeof(*rects)); 963bfa90b6Smrg if (!rects) { 973bfa90b6Smrg LogMessage(X_ERROR, "Failed to alloc cliprects for " 983bfa90b6Smrg "present readback.\n"); 993bfa90b6Smrg return -1; 1003bfa90b6Smrg } 1013bfa90b6Smrg 10225dbecb6Smrg while (num_clips > 0) { 10325dbecb6Smrg unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS); 1043bfa90b6Smrg 10525dbecb6Smrg memset(&arg, 0, sizeof(arg)); 10625dbecb6Smrg memset(&rep, 0, sizeof(rep)); 10725dbecb6Smrg memset(rects, 0, alloc_clips * sizeof(*rects)); 1083bfa90b6Smrg 10925dbecb6Smrg arg.fb_id = fb_id; 11025dbecb6Smrg arg.num_clips = cur_clips; 11125dbecb6Smrg arg.clips_ptr = (unsigned long) rects; 1123bfa90b6Smrg 11325dbecb6Smrg /* Only request a fence on the last clip batch */ 11425dbecb6Smrg arg.fence_rep = (cur_clips == num_clips) ? (unsigned long) &rep : 0UL; 11525dbecb6Smrg rep.error = -EFAULT; 11625dbecb6Smrg 11725dbecb6Smrg for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) { 11825dbecb6Smrg r->x = clips->x1; 11925dbecb6Smrg r->y = clips->y1; 12025dbecb6Smrg r->w = clips->x2 - clips->x1; 12125dbecb6Smrg r->h = clips->y2 - clips->y1; 1223bfa90b6Smrg } 12325dbecb6Smrg 12425dbecb6Smrg ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT_READBACK, &arg, 12525dbecb6Smrg sizeof(arg)); 12625dbecb6Smrg if (ret) 12725dbecb6Smrg LogMessage(X_ERROR, "Present readback error %s.\n", strerror(-ret)); 12825dbecb6Smrg 12925dbecb6Smrg /* Sync if we have a fence to avoid racing with Xorg SW rendering. */ 13025dbecb6Smrg if (rep.error == 0) { 13125dbecb6Smrg ret = vmwgfx_fence_wait(drm_fd, rep.handle, TRUE); 13225dbecb6Smrg if (ret) { 13325dbecb6Smrg LogMessage(X_ERROR, "Present readback fence wait error %s.\n", 13425dbecb6Smrg strerror(-ret)); 13525dbecb6Smrg /* vmwgfx_fence_wait() takes care of this if ret == 0. */ 13625dbecb6Smrg vmwgfx_fence_unref(drm_fd, rep.handle); 13725dbecb6Smrg } 13825dbecb6Smrg } 13925dbecb6Smrg 14025dbecb6Smrg num_clips -= cur_clips; 1413bfa90b6Smrg } 1423bfa90b6Smrg 14325dbecb6Smrg free(rects); 14425dbecb6Smrg 1453bfa90b6Smrg return 0; 1463bfa90b6Smrg} 1473bfa90b6Smrg 1483bfa90b6Smrg 1493bfa90b6Smrgint 1503bfa90b6Smrgvmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x, 1513bfa90b6Smrg unsigned int dst_y, RegionPtr region, uint32_t handle) 1523bfa90b6Smrg{ 1533bfa90b6Smrg BoxPtr clips = REGION_RECTS(region); 1543bfa90b6Smrg unsigned int num_clips = REGION_NUM_RECTS(region); 15525dbecb6Smrg unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS); 1563bfa90b6Smrg struct drm_vmw_present_arg arg; 1573bfa90b6Smrg unsigned int i; 1583bfa90b6Smrg struct drm_vmw_rect *rects, *r; 1593bfa90b6Smrg int ret; 1603bfa90b6Smrg 1613bfa90b6Smrg if (num_clips == 0) 1623bfa90b6Smrg return 0; 1633bfa90b6Smrg 16425dbecb6Smrg rects = malloc(alloc_clips * sizeof(*rects)); 1653bfa90b6Smrg if (!rects) { 1663bfa90b6Smrg LogMessage(X_ERROR, "Failed to alloc cliprects for " 1673bfa90b6Smrg "present.\n"); 1683bfa90b6Smrg return -1; 1693bfa90b6Smrg } 1703bfa90b6Smrg 17125dbecb6Smrg while (num_clips > 0) { 17225dbecb6Smrg unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS); 17325dbecb6Smrg 17425dbecb6Smrg memset(&arg, 0, sizeof(arg)); 17525dbecb6Smrg memset(rects, 0, alloc_clips * sizeof(*rects)); 17625dbecb6Smrg arg.fb_id = fb_id; 17725dbecb6Smrg arg.sid = handle; 17825dbecb6Smrg arg.dest_x = dst_x; 17925dbecb6Smrg arg.dest_y = dst_y; 18025dbecb6Smrg arg.num_clips = cur_clips; 18125dbecb6Smrg arg.clips_ptr = (unsigned long) rects; 18225dbecb6Smrg 18325dbecb6Smrg for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) { 18425dbecb6Smrg r->x = clips->x1; 18525dbecb6Smrg r->y = clips->y1; 18625dbecb6Smrg r->w = clips->x2 - clips->x1; 18725dbecb6Smrg r->h = clips->y2 - clips->y1; 18825dbecb6Smrg } 18925dbecb6Smrg 19025dbecb6Smrg ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg)); 19125dbecb6Smrg if (ret) 19225dbecb6Smrg LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret)); 1933bfa90b6Smrg 19425dbecb6Smrg num_clips -= cur_clips; 1953bfa90b6Smrg } 1963bfa90b6Smrg 1973bfa90b6Smrg free(rects); 19825dbecb6Smrg 19925dbecb6Smrg return 0; 2003bfa90b6Smrg} 2013bfa90b6Smrg 2023bfa90b6Smrg 2033bfa90b6Smrgstruct vmwgfx_int_dmabuf { 2043bfa90b6Smrg struct vmwgfx_dmabuf buf; 2053bfa90b6Smrg uint64_t map_handle; 2063bfa90b6Smrg uint64_t sync_handle; 2073bfa90b6Smrg int sync_valid; 2083bfa90b6Smrg int drm_fd; 2093bfa90b6Smrg uint32_t map_count; 2103bfa90b6Smrg void *addr; 2113bfa90b6Smrg}; 2123bfa90b6Smrg 2133bfa90b6Smrgstatic inline struct vmwgfx_int_dmabuf * 2143bfa90b6Smrgvmwgfx_int_dmabuf(struct vmwgfx_dmabuf *buf) 2153bfa90b6Smrg{ 2163bfa90b6Smrg return (struct vmwgfx_int_dmabuf *) buf; 2173bfa90b6Smrg} 2183bfa90b6Smrg 2193bfa90b6Smrgstruct vmwgfx_dmabuf* 2203bfa90b6Smrgvmwgfx_dmabuf_alloc(int drm_fd, size_t size) 2213bfa90b6Smrg{ 2223bfa90b6Smrg union drm_vmw_alloc_dmabuf_arg arg; 2233bfa90b6Smrg struct vmwgfx_dmabuf *buf; 2243bfa90b6Smrg struct vmwgfx_int_dmabuf *ibuf; 2253bfa90b6Smrg int ret; 2263bfa90b6Smrg 2273bfa90b6Smrg ibuf = calloc(1, sizeof(*ibuf)); 2283bfa90b6Smrg if (!ibuf) 2293bfa90b6Smrg return NULL; 2303bfa90b6Smrg 2313bfa90b6Smrg buf = &ibuf->buf; 2323bfa90b6Smrg memset(&arg, 0, sizeof(arg)); 2333bfa90b6Smrg arg.req.size = size; 2343bfa90b6Smrg 2353bfa90b6Smrg ret = drmCommandWriteRead(drm_fd, DRM_VMW_ALLOC_DMABUF, &arg, 2363bfa90b6Smrg sizeof(arg)); 2373bfa90b6Smrg if (ret) 2383bfa90b6Smrg goto out_kernel_fail; 2393bfa90b6Smrg 2403bfa90b6Smrg ibuf = vmwgfx_int_dmabuf(buf); 2413bfa90b6Smrg ibuf->map_handle = arg.rep.map_handle; 2423bfa90b6Smrg ibuf->drm_fd = drm_fd; 2433bfa90b6Smrg buf->handle = arg.rep.handle; 2443bfa90b6Smrg buf->gmr_id = arg.rep.cur_gmr_id; 2453bfa90b6Smrg buf->gmr_offset = arg.rep.cur_gmr_offset; 2463bfa90b6Smrg buf->size = size; 2473bfa90b6Smrg 2483bfa90b6Smrg return buf; 2493bfa90b6Smrg out_kernel_fail: 2503bfa90b6Smrg free(buf); 2513bfa90b6Smrg return NULL; 2523bfa90b6Smrg} 2533bfa90b6Smrg 2543bfa90b6Smrgvoid * 2553bfa90b6Smrgvmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf) 2563bfa90b6Smrg{ 2573bfa90b6Smrg struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); 2583bfa90b6Smrg 2593bfa90b6Smrg if (ibuf->addr) 2603bfa90b6Smrg return ibuf->addr; 2613bfa90b6Smrg 2623bfa90b6Smrg ibuf->addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, 2633bfa90b6Smrg ibuf->drm_fd, ibuf->map_handle); 2643bfa90b6Smrg 2653bfa90b6Smrg if (ibuf->addr == MAP_FAILED) { 2663bfa90b6Smrg ibuf->addr = NULL; 2673bfa90b6Smrg return NULL; 2683bfa90b6Smrg } 2693bfa90b6Smrg 2703bfa90b6Smrg ibuf->map_count++; 2713bfa90b6Smrg return ibuf->addr; 2723bfa90b6Smrg} 2733bfa90b6Smrg 2743bfa90b6Smrgvoid 2753bfa90b6Smrgvmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf) 2763bfa90b6Smrg{ 2773bfa90b6Smrg struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); 2783bfa90b6Smrg 2793bfa90b6Smrg if (--ibuf->map_count) 2803bfa90b6Smrg return; 2813bfa90b6Smrg 2823bfa90b6Smrg /* 2833bfa90b6Smrg * It's a pretty important performance optimzation not to call 2843bfa90b6Smrg * munmap here, although we should watch out for cases where we might fill 2853bfa90b6Smrg * the virtual memory space of the process. 2863bfa90b6Smrg */ 2873bfa90b6Smrg} 2883bfa90b6Smrg 2893bfa90b6Smrgvoid 2903bfa90b6Smrgvmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf) 2913bfa90b6Smrg{ 2923bfa90b6Smrg struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); 2933bfa90b6Smrg struct drm_vmw_unref_dmabuf_arg arg; 2943bfa90b6Smrg 2953bfa90b6Smrg if (ibuf->addr) { 2963bfa90b6Smrg munmap(ibuf->addr, buf->size); 2973bfa90b6Smrg ibuf->addr = NULL; 2983bfa90b6Smrg } 2993bfa90b6Smrg 3003bfa90b6Smrg memset(&arg, 0, sizeof(arg)); 3013bfa90b6Smrg arg.handle = buf->handle; 3023bfa90b6Smrg 3033bfa90b6Smrg (void) drmCommandWrite(ibuf->drm_fd, DRM_VMW_UNREF_DMABUF, &arg, 3043bfa90b6Smrg sizeof(arg)); 3053bfa90b6Smrg free(buf); 3063bfa90b6Smrg} 3073bfa90b6Smrg 3083bfa90b6Smrgint 30922f7e8e5Smrgvmwgfx_dma(int host_x, int host_y, 3103bfa90b6Smrg RegionPtr region, struct vmwgfx_dmabuf *buf, 3113bfa90b6Smrg uint32_t buf_pitch, uint32_t surface_handle, int to_surface) 3123bfa90b6Smrg{ 3133bfa90b6Smrg BoxPtr clips = REGION_RECTS(region); 3143bfa90b6Smrg unsigned int num_clips = REGION_NUM_RECTS(region); 3153bfa90b6Smrg struct drm_vmw_execbuf_arg arg; 3163bfa90b6Smrg struct drm_vmw_fence_rep rep; 3173bfa90b6Smrg int ret; 3183bfa90b6Smrg unsigned i; 3193bfa90b6Smrg SVGA3dCopyBox *cb; 3203bfa90b6Smrg SVGA3dCmdSurfaceDMASuffix *suffix; 3213bfa90b6Smrg SVGA3dCmdSurfaceDMA *body; 3223bfa90b6Smrg struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); 3233bfa90b6Smrg struct { 3243bfa90b6Smrg SVGA3dCmdHeader header; 3253bfa90b6Smrg SVGA3dCmdSurfaceDMA body; 3263bfa90b6Smrg SVGA3dCopyBox cb; 3273bfa90b6Smrg } *cmd; 32825dbecb6Smrg static unsigned int max_clips = 32925dbecb6Smrg (SVGA_CB_MAX_COMMAND_SIZE - sizeof(*cmd) - sizeof(*suffix)) / 33025dbecb6Smrg sizeof(cmd->cb) + 1; 33125dbecb6Smrg 33225dbecb6Smrg while (num_clips > 0) { 33325dbecb6Smrg unsigned int size; 33425dbecb6Smrg unsigned int cur_clips; 33525dbecb6Smrg 33625dbecb6Smrg cur_clips = min(num_clips, max_clips); 33725dbecb6Smrg size = sizeof(*cmd) + (cur_clips - 1) * sizeof(cmd->cb) + 33825dbecb6Smrg sizeof(*suffix); 33925dbecb6Smrg 34025dbecb6Smrg cmd = calloc(1, size); 34125dbecb6Smrg if (!cmd) 34225dbecb6Smrg return -1; 34325dbecb6Smrg 34425dbecb6Smrg cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; 34525dbecb6Smrg cmd->header.size = sizeof(cmd->body) + cur_clips * sizeof(cmd->cb) + 34625dbecb6Smrg sizeof(*suffix); 34725dbecb6Smrg cb = &cmd->cb; 34825dbecb6Smrg 34925dbecb6Smrg suffix = (SVGA3dCmdSurfaceDMASuffix *) &cb[cur_clips]; 35025dbecb6Smrg suffix->suffixSize = sizeof(*suffix); 35125dbecb6Smrg suffix->maximumOffset = (uint32_t) -1; 35225dbecb6Smrg suffix->flags.discard = 0; 35325dbecb6Smrg suffix->flags.unsynchronized = 0; 35425dbecb6Smrg suffix->flags.reserved = 0; 35525dbecb6Smrg 35625dbecb6Smrg body = &cmd->body; 35725dbecb6Smrg body->guest.ptr.gmrId = buf->gmr_id; 35825dbecb6Smrg body->guest.ptr.offset = buf->gmr_offset; 35925dbecb6Smrg body->guest.pitch = buf_pitch; 36025dbecb6Smrg body->host.sid = surface_handle; 36125dbecb6Smrg body->host.face = 0; 36225dbecb6Smrg body->host.mipmap = 0; 36325dbecb6Smrg 36425dbecb6Smrg body->transfer = (to_surface ? SVGA3D_WRITE_HOST_VRAM : 36525dbecb6Smrg SVGA3D_READ_HOST_VRAM); 36625dbecb6Smrg 36725dbecb6Smrg for (i = 0; i < cur_clips; i++, cb++, clips++) { 36825dbecb6Smrg cb->x = (uint16_t) clips->x1 + host_x; 36925dbecb6Smrg cb->y = (uint16_t) clips->y1 + host_y; 37025dbecb6Smrg cb->z = 0; 37125dbecb6Smrg cb->srcx = (uint16_t) clips->x1; 37225dbecb6Smrg cb->srcy = (uint16_t) clips->y1; 37325dbecb6Smrg cb->srcz = 0; 37425dbecb6Smrg cb->w = (uint16_t) (clips->x2 - clips->x1); 37525dbecb6Smrg cb->h = (uint16_t) (clips->y2 - clips->y1); 37625dbecb6Smrg cb->d = 1; 3773bfa90b6Smrg#if 0 37825dbecb6Smrg LogMessage(X_INFO, "DMA! x: %u y: %u srcx: %u srcy: %u w: %u h: %u %s\n", 37925dbecb6Smrg cb->x, cb->y, cb->srcx, cb->srcy, cb->w, cb->h, 38025dbecb6Smrg to_surface ? "to" : "from"); 3813bfa90b6Smrg#endif 3823bfa90b6Smrg 38325dbecb6Smrg } 3843bfa90b6Smrg 38525dbecb6Smrg memset(&arg, 0, sizeof(arg)); 38625dbecb6Smrg memset(&rep, 0, sizeof(rep)); 38725dbecb6Smrg 38825dbecb6Smrg rep.error = -EFAULT; 3893bfa90b6Smrg 39025dbecb6Smrg /* Only require a fence if readback and last batch of cliprects. */ 39125dbecb6Smrg arg.fence_rep = ((to_surface && (cur_clips == num_clips)) ? 39225dbecb6Smrg 0UL : (unsigned long) &rep); 39325dbecb6Smrg arg.commands = (unsigned long)cmd; 39425dbecb6Smrg arg.command_size = size; 39525dbecb6Smrg arg.throttle_us = 0; 39625dbecb6Smrg arg.version = DRM_VMW_EXECBUF_VERSION; 3973bfa90b6Smrg 39825dbecb6Smrg ret = drmCommandWrite(ibuf->drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); 3993bfa90b6Smrg if (ret) { 40025dbecb6Smrg LogMessage(X_ERROR, "DMA error %s.\n", strerror(-ret)); 40125dbecb6Smrg } 40225dbecb6Smrg 40325dbecb6Smrg free(cmd); 40425dbecb6Smrg num_clips -= cur_clips; 40525dbecb6Smrg 40625dbecb6Smrg if (rep.error == 0) { 40725dbecb6Smrg ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.handle, TRUE); 40825dbecb6Smrg if (ret) { 40925dbecb6Smrg LogMessage(X_ERROR, "DMA from host fence wait error %s.\n", 41025dbecb6Smrg strerror(-ret)); 41125dbecb6Smrg /* vmwgfx_fence_wait() takes care of this if ret == 0. */ 41225dbecb6Smrg vmwgfx_fence_unref(ibuf->drm_fd, rep.handle); 41325dbecb6Smrg } 4143bfa90b6Smrg } 4153bfa90b6Smrg } 4163bfa90b6Smrg 4173bfa90b6Smrg return 0; 4183bfa90b6Smrg} 4193bfa90b6Smrg 4203bfa90b6Smrgint 4213bfa90b6Smrgvmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out) 4223bfa90b6Smrg{ 4233bfa90b6Smrg struct drm_vmw_getparam_arg gp_arg; 4243bfa90b6Smrg int ret; 4253bfa90b6Smrg 4263bfa90b6Smrg memset(&gp_arg, 0, sizeof(gp_arg)); 4273bfa90b6Smrg gp_arg.param = param; 4283bfa90b6Smrg ret = drmCommandWriteRead(drm_fd, DRM_VMW_GET_PARAM, 4293bfa90b6Smrg &gp_arg, sizeof(gp_arg)); 4303bfa90b6Smrg 4313bfa90b6Smrg if (ret == 0) { 4323bfa90b6Smrg *out = gp_arg.value; 4333bfa90b6Smrg } 4343bfa90b6Smrg 4353bfa90b6Smrg return ret; 4363bfa90b6Smrg} 4373bfa90b6Smrg 4383bfa90b6Smrgint 4393bfa90b6Smrgvmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree) 4403bfa90b6Smrg{ 4413bfa90b6Smrg uint64_t v1, v2; 4423bfa90b6Smrg int ret; 4433bfa90b6Smrg 4443bfa90b6Smrg ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_STREAMS, &v1); 4453bfa90b6Smrg if (ret) 4463bfa90b6Smrg return ret; 4473bfa90b6Smrg 4483bfa90b6Smrg ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_FREE_STREAMS, &v2); 4493bfa90b6Smrg if (ret) 4503bfa90b6Smrg return ret; 4513bfa90b6Smrg 4523bfa90b6Smrg *ntot = (uint32_t)v1; 4533bfa90b6Smrg *nfree = (uint32_t)v2; 4543bfa90b6Smrg 4553bfa90b6Smrg return 0; 4563bfa90b6Smrg} 4573bfa90b6Smrg 4583bfa90b6Smrgint 4593bfa90b6Smrgvmwgfx_claim_stream(int drm_fd, uint32_t *out) 4603bfa90b6Smrg{ 4613bfa90b6Smrg struct drm_vmw_stream_arg s_arg; 4623bfa90b6Smrg int ret; 4633bfa90b6Smrg 4643bfa90b6Smrg ret = drmCommandRead(drm_fd, DRM_VMW_CLAIM_STREAM, 4653bfa90b6Smrg &s_arg, sizeof(s_arg)); 4663bfa90b6Smrg 4673bfa90b6Smrg if (ret) 4683bfa90b6Smrg return -1; 4693bfa90b6Smrg 4703bfa90b6Smrg *out = s_arg.stream_id; 4713bfa90b6Smrg return 0; 4723bfa90b6Smrg} 4733bfa90b6Smrg 4743bfa90b6Smrgint 4753bfa90b6Smrgvmwgfx_unref_stream(int drm_fd, uint32_t stream_id) 4763bfa90b6Smrg{ 4773bfa90b6Smrg struct drm_vmw_stream_arg s_arg; 4783bfa90b6Smrg int ret; 4793bfa90b6Smrg 4803bfa90b6Smrg memset(&s_arg, 0, sizeof(s_arg)); 4813bfa90b6Smrg s_arg.stream_id = stream_id; 4823bfa90b6Smrg 4833bfa90b6Smrg ret = drmCommandWrite(drm_fd, DRM_VMW_UNREF_STREAM, 4843bfa90b6Smrg &s_arg, sizeof(s_arg)); 4853bfa90b6Smrg 4863bfa90b6Smrg return (ret != 0) ? -1 : 0; 4873bfa90b6Smrg} 4883bfa90b6Smrg 4893bfa90b6Smrgint 4903bfa90b6Smrgvmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot) 4913bfa90b6Smrg{ 4923bfa90b6Smrg struct drm_vmw_cursor_bypass_arg arg; 4933bfa90b6Smrg int ret; 4943bfa90b6Smrg 4953bfa90b6Smrg memset(&arg, 0, sizeof(arg)); 4963bfa90b6Smrg arg.flags = DRM_VMW_CURSOR_BYPASS_ALL; 4973bfa90b6Smrg arg.xhot = xhot; 4983bfa90b6Smrg arg.yhot = yhot; 4993bfa90b6Smrg 5003bfa90b6Smrg ret = drmCommandWrite(drm_fd, DRM_VMW_CURSOR_BYPASS, 5013bfa90b6Smrg &arg, sizeof(arg)); 5023bfa90b6Smrg 5033bfa90b6Smrg return ret; 5043bfa90b6Smrg} 5053bfa90b6Smrg 5063bfa90b6Smrgint 5073bfa90b6Smrgvmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects, 5083bfa90b6Smrg struct drm_vmw_rect *rects) 5093bfa90b6Smrg{ 5103bfa90b6Smrg struct drm_vmw_update_layout_arg arg; 5113bfa90b6Smrg 5123bfa90b6Smrg memset(&arg, 0, sizeof(arg)); 5133bfa90b6Smrg 5143bfa90b6Smrg arg.num_outputs = num_rects; 5153bfa90b6Smrg arg.rects = (unsigned long) rects; 5163bfa90b6Smrg 5173bfa90b6Smrg return drmCommandWrite(drm_fd, DRM_VMW_UPDATE_LAYOUT, &arg, 5183bfa90b6Smrg sizeof(arg)); 5193bfa90b6Smrg} 5203bfa90b6Smrg 5213bfa90b6Smrg 5223bfa90b6Smrgint 5233bfa90b6Smrgvmwgfx_max_fb_size(int drm_fd, size_t *size) 5243bfa90b6Smrg{ 5253bfa90b6Smrg uint64_t tmp_size; 5263bfa90b6Smrg 5273bfa90b6Smrg if (vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_MAX_FB_SIZE, &tmp_size) != 0) 5283bfa90b6Smrg return -1; 5293bfa90b6Smrg 5303bfa90b6Smrg *size = tmp_size; 5313bfa90b6Smrg 5323bfa90b6Smrg return 0; 5333bfa90b6Smrg} 53422f7e8e5Smrg 53522f7e8e5Smrg#ifdef HAVE_LIBDRM_2_4_38 53622f7e8e5Smrg/** 53722f7e8e5Smrg * vmwgfx_prime_fd_to_handle - Return a TTM handle to a prime object 53822f7e8e5Smrg * 53922f7e8e5Smrg * @drm_fd: File descriptor for the drm connection. 54022f7e8e5Smrg * @prime_fd: File descriptor identifying the prime object. 54122f7e8e5Smrg * @handle: Pointer to returned TTM handle. 54222f7e8e5Smrg * 54322f7e8e5Smrg * Takes a reference on the underlying object and returns a TTM handle to it. 54422f7e8e5Smrg */ 54522f7e8e5Smrgint 54622f7e8e5Smrgvmwgfx_prime_fd_to_handle(int drm_fd, int prime_fd, uint32_t *handle) 54722f7e8e5Smrg{ 54822f7e8e5Smrg *handle = 0; 54922f7e8e5Smrg 55022f7e8e5Smrg return drmPrimeFDToHandle(drm_fd, prime_fd, handle); 55122f7e8e5Smrg} 55222f7e8e5Smrg 55322f7e8e5Smrg/** 55422f7e8e5Smrg * vmwgfx_prime_release_handle - Release a reference on a TTM object 55522f7e8e5Smrg * 55622f7e8e5Smrg * @drm_fd: File descriptor for the drm connection. 55722f7e8e5Smrg * @handle: TTM handle as returned by vmwgfx_prime_fd_to_handle. 55822f7e8e5Smrg * 55922f7e8e5Smrg * Releases the reference obtained by vmwgfx_prime_fd_to_handle(). 56022f7e8e5Smrg */ 56122f7e8e5Smrgvoid 56222f7e8e5Smrgvmwgfx_prime_release_handle(int drm_fd, uint32_t handle) 56322f7e8e5Smrg{ 56422f7e8e5Smrg struct drm_vmw_surface_arg s_arg; 56522f7e8e5Smrg 56622f7e8e5Smrg memset(&s_arg, 0, sizeof(s_arg)); 56722f7e8e5Smrg s_arg.sid = handle; 56822f7e8e5Smrg 56922f7e8e5Smrg (void) drmCommandWrite(drm_fd, DRM_VMW_UNREF_SURFACE, &s_arg, 57022f7e8e5Smrg sizeof(s_arg)); 57122f7e8e5Smrg} 57222f7e8e5Smrg#endif /* HAVE_LIBDRM_2_4_38 */ 573