X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fwinsys%2Fsvga%2Fdrm%2Fvmw_screen_dri.c;h=62d1b18b9e3473bc2cbb2fb5a9586a7975ac30f6;hb=882ca6dfb0f3d17e0f8bc917307d915ab1718069;hp=f4c1642f2d430079c954cfddb5369fe8d67eacab;hpb=e4c54d404959aa1bce26caa313c0a47e65ff211a;p=mesa.git diff --git a/src/gallium/winsys/svga/drm/vmw_screen_dri.c b/src/gallium/winsys/svga/drm/vmw_screen_dri.c index f4c1642f2d4..62d1b18b9e3 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen_dri.c +++ b/src/gallium/winsys/svga/drm/vmw_screen_dri.c @@ -1,5 +1,5 @@ /********************************************************** - * Copyright 2009 VMware, Inc. All rights reserved. + * Copyright 2009-2015 VMware, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -27,41 +27,46 @@ #include "pipe/p_compiler.h" #include "util/u_inlines.h" #include "util/u_memory.h" -#include "util/u_format.h" -#include "vmw_screen.h" - -#include "trace/tr_drm.h" +#include "util/format/u_format.h" +#include "vmw_context.h" #include "vmw_screen.h" #include "vmw_surface.h" -#include "vmw_fence.h" -#include "vmw_context.h" +#include "vmw_buffer.h" +#include "svga_drm_public.h" +#include "svga3d_surfacedefs.h" + +#include "state_tracker/drm_driver.h" -#include -#include #include "vmwgfx_drm.h" #include #include +#include + +struct dri1_api_version { + int major; + int minor; + int patch_level; +}; static struct svga_winsys_surface * vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, struct winsys_handle *whandle, SVGA3dSurfaceFormat *format); + +static struct svga_winsys_surface * +vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws, + struct winsys_handle *whandle, + SVGA3dSurfaceFormat *format); static boolean vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, struct svga_winsys_surface *surface, unsigned stride, struct winsys_handle *whandle); -static struct dri1_api dri1_api_hooks; -static struct dri1_api_version ddx_required = { 0, 1, 0 }; -static struct dri1_api_version ddx_compat = { 0, 0, 0 }; -static struct dri1_api_version dri_required = { 4, 0, 0 }; -static struct dri1_api_version dri_compat = { 4, 0, 0 }; -static struct dri1_api_version drm_required = { 1, 0, 0 }; -static struct dri1_api_version drm_compat = { 1, 0, 0 }; -static struct dri1_api_version drm_scanout = { 0, 9, 0 }; +static struct dri1_api_version drm_required = { 2, 1, 0 }; +static struct dri1_api_version drm_compat = { 2, 0, 0 }; static boolean vmw_dri1_check_version(const struct dri1_api_version *cur, @@ -74,206 +79,140 @@ vmw_dri1_check_version(const struct dri1_api_version *cur, if (cur->major == required->major && cur->minor >= required->minor) return TRUE; - fprintf(stderr, "%s version failure.\n", component); - fprintf(stderr, "%s version is %d.%d.%d and this driver can only work\n" - "with versions %d.%d.x through %d.x.x.\n", - component, - cur->major, - cur->minor, - cur->patch_level, required->major, required->minor, compat->major); + vmw_error("%s version failure.\n", component); + vmw_error("%s version is %d.%d.%d and this driver can only work\n" + "with versions %d.%d.x through %d.x.x.\n", + component, + cur->major, cur->minor, cur->patch_level, + required->major, required->minor, compat->major); return FALSE; } -/* This is actually the entrypoint to the entire driver, called by the - * libGL (or EGL, or ...) code via the drm_api_hooks table at the - * bottom of the file. +/* This is actually the entrypoint to the entire driver, + * called by the target bootstrap code. */ -static struct pipe_screen * -vmw_drm_create_screen(struct drm_api *drm_api, - int fd, - struct drm_create_screen_arg *arg) +struct svga_winsys_screen * +svga_drm_winsys_screen_create(int fd) { struct vmw_winsys_screen *vws; - struct pipe_screen *screen; - struct dri1_create_screen_arg *dri1; - boolean use_old_scanout_flag = FALSE; - - if (!arg || arg->mode == DRM_CREATE_NORMAL) { - struct dri1_api_version drm_ver; - drmVersionPtr ver; - - ver = drmGetVersion(fd); - if (ver == NULL) - return NULL; - - drm_ver.major = ver->version_major; - drm_ver.minor = ver->version_minor; - drm_ver.patch_level = 0; /* ??? */ - - drmFreeVersion(ver); - if (!vmw_dri1_check_version(&drm_ver, &drm_required, - &drm_compat, "vmwgfx drm driver")) - return NULL; - - if (!vmw_dri1_check_version(&drm_ver, &drm_scanout, - &drm_compat, "use old scanout field (not a error)")) - use_old_scanout_flag = TRUE; - } + struct dri1_api_version drm_ver; + drmVersionPtr ver; - if (arg != NULL) { - switch (arg->mode) { - case DRM_CREATE_NORMAL: - break; - case DRM_CREATE_DRI1: - dri1 = (struct dri1_create_screen_arg *)arg; - if (!vmw_dri1_check_version(&dri1->ddx_version, &ddx_required, - &ddx_compat, "ddx - driver api")) - return NULL; - if (!vmw_dri1_check_version(&dri1->dri_version, &dri_required, - &dri_compat, "dri info")) - return NULL; - if (!vmw_dri1_check_version(&dri1->drm_version, &drm_required, - &drm_compat, "vmwgfx drm driver")) - return NULL; - if (!vmw_dri1_check_version(&dri1->drm_version, &drm_scanout, - &drm_compat, "use old scanout field (not a error)")) - use_old_scanout_flag = TRUE; - dri1->api = &dri1_api_hooks; -#if 0 - break; -#else - assert(!"No dri 1 support for now\n"); - return NULL; -#endif - default: - return NULL; - } - } + ver = drmGetVersion(fd); + if (ver == NULL) + return NULL; - vws = vmw_winsys_create( fd, use_old_scanout_flag ); + drm_ver.major = ver->version_major; + drm_ver.minor = ver->version_minor; + drm_ver.patch_level = 0; /* ??? */ + + drmFreeVersion(ver); + if (!vmw_dri1_check_version(&drm_ver, &drm_required, + &drm_compat, "vmwgfx drm driver")) + return NULL; + + vws = vmw_winsys_create(fd); if (!vws) goto out_no_vws; /* XXX do this properly */ - vws->base.surface_from_handle = vmw_drm_surface_from_handle; + vws->base.surface_from_handle = vws->base.have_gb_objects ? + vmw_drm_gb_surface_from_handle : vmw_drm_surface_from_handle; vws->base.surface_get_handle = vmw_drm_surface_get_handle; - screen = svga_screen_create( &vws->base ); - if (!screen) - goto out_no_screen; - - return screen; - - /* Failure cases: - */ -out_no_screen: - vmw_winsys_destroy( vws ); + return &vws->base; out_no_vws: return NULL; } -static INLINE boolean -vmw_dri1_intersect_src_bbox(struct drm_clip_rect *dst, - int dst_x, - int dst_y, - const struct drm_clip_rect *src, - const struct drm_clip_rect *bbox) -{ - int xy1; - int xy2; - - xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : - (int)bbox->x1 + dst_x; - xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : - (int)bbox->x2 + dst_x; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->x1 = xy1; - dst->x2 = xy2; - - xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : - (int)bbox->y1 + dst_y; - xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : - (int)bbox->y2 + dst_y; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->y1 = xy1; - dst->y2 = xy2; - return TRUE; -} - /** - * No fancy get-surface-from-sarea stuff here. - * Just use the present blit. + * vmw_drm_gb_surface_from_handle - Create a shared surface + * + * @sws: Screen to register the surface with. + * @whandle: struct winsys_handle identifying the kernel surface object + * @format: On successful return points to a value describing the + * surface format. + * + * Returns a refcounted pointer to a struct svga_winsys_surface + * embedded in a struct vmw_svga_winsys_surface on success or NULL + * on failure. */ - -static void -vmw_dri1_present_locked(struct pipe_context *locked_pipe, - struct pipe_surface *surf, - const struct drm_clip_rect *rect, - unsigned int num_clip, - int x_draw, int y_draw, - const struct drm_clip_rect *bbox, - struct pipe_fence_handle **p_fence) +static struct svga_winsys_surface * +vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws, + struct winsys_handle *whandle, + SVGA3dSurfaceFormat *format) { -#if 0 - struct svga_winsys_surface *srf = - svga_screen_texture_get_winsys_surface(surf->texture); - struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); - struct vmw_winsys_screen *vws = - vmw_winsys_screen(svga_winsys_screen(locked_pipe->screen)); - struct drm_clip_rect clip; - int i; - struct - { - SVGA3dCmdHeader header; - SVGA3dCmdPresent body; - SVGA3dCopyRect rect; - } cmd; - boolean visible = FALSE; - uint32_t fence_seq = 0; - - VMW_FUNC; - cmd.header.id = SVGA_3D_CMD_PRESENT; - cmd.header.size = sizeof cmd.body + sizeof cmd.rect; - cmd.body.sid = vsrf->sid; - - for (i = 0; i < num_clip; ++i) { - if (!vmw_dri1_intersect_src_bbox(&clip, x_draw, y_draw, rect++, bbox)) - continue; - - cmd.rect.x = clip.x1; - cmd.rect.y = clip.y1; - cmd.rect.w = clip.x2 - clip.x1; - cmd.rect.h = clip.y2 - clip.y1; - cmd.rect.srcx = (int)clip.x1 - x_draw; - cmd.rect.srcy = (int)clip.y1 - y_draw; - - vmw_printf("%s: Clip %d x %d y %d w %d h %d srcx %d srcy %d\n", - __FUNCTION__, - i, - cmd.rect.x, - cmd.rect.y, - cmd.rect.w, cmd.rect.h, cmd.rect.srcx, cmd.rect.srcy); - - vmw_ioctl_command(vws, &cmd, sizeof cmd.header + cmd.header.size, - &fence_seq); - visible = TRUE; - } + struct vmw_svga_winsys_surface *vsrf; + struct svga_winsys_surface *ssrf; + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + SVGA3dSurfaceAllFlags flags; + uint32_t mip_levels; + struct vmw_buffer_desc desc; + struct pb_manager *provider = vws->pools.gmr; + struct pb_buffer *pb_buf; + uint32_t handle; + int ret; - *p_fence = (visible) ? vmw_pipe_fence(fence_seq) : NULL; - vmw_svga_winsys_surface_reference(&vsrf, NULL); -#else - assert(!"No dri 1 support for now\n"); -#endif + if (whandle->offset != 0) { + fprintf(stderr, "Attempt to import unsupported winsys offset %u\n", + whandle->offset); + return NULL; + } + + ret = vmw_ioctl_gb_surface_ref(vws, whandle, &flags, format, + &mip_levels, &handle, &desc.region); + + if (ret) { + fprintf(stderr, "Failed referencing shared surface. SID %d.\n" + "Error %d (%s).\n", + whandle->handle, ret, strerror(-ret)); + return NULL; + } + + if (mip_levels != 1) { + fprintf(stderr, "Incorrect number of mipmap levels on shared surface." + " SID %d, levels %d\n", + whandle->handle, mip_levels); + goto out_mip; + } + + vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); + if (!vsrf) + goto out_mip; + + pipe_reference_init(&vsrf->refcnt, 1); + p_atomic_set(&vsrf->validated, 0); + vsrf->screen = vws; + vsrf->sid = handle; + vsrf->size = vmw_region_size(desc.region); + + /* + * Synchronize backing buffers of shared surfaces using the + * kernel, since we don't pass fence objects around between + * processes. + */ + desc.pb_desc.alignment = 4096; + desc.pb_desc.usage = VMW_BUFFER_USAGE_SHARED | VMW_BUFFER_USAGE_SYNC; + pb_buf = provider->create_buffer(provider, vsrf->size, &desc.pb_desc); + vsrf->buf = vmw_svga_winsys_buffer_wrap(pb_buf); + if (!vsrf->buf) + goto out_no_buf; + ssrf = svga_winsys_surface(vsrf); + + return ssrf; + +out_no_buf: + FREE(vsrf); +out_mip: + vmw_ioctl_region_destroy(desc.region); + vmw_ioctl_surface_destroy(vws, whandle->handle); + return NULL; } static struct svga_winsys_surface * vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, - struct winsys_handle *whandle, + struct winsys_handle *whandle, SVGA3dSurfaceFormat *format) { struct vmw_svga_winsys_surface *vsrf; @@ -282,42 +221,77 @@ vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, union drm_vmw_surface_reference_arg arg; struct drm_vmw_surface_arg *req = &arg.req; struct drm_vmw_surface_create_req *rep = &arg.rep; + uint32_t handle = 0; + struct drm_vmw_size size; + SVGA3dSize base_size; int ret; int i; - /** - * The vmware device specific handle is the hardware SID. - * FIXME: We probably want to move this to the ioctl implementations. - */ + if (whandle->offset != 0) { + fprintf(stderr, "Attempt to import unsupported winsys offset %u\n", + whandle->offset); + return NULL; + } + + switch (whandle->type) { + case WINSYS_HANDLE_TYPE_SHARED: + case WINSYS_HANDLE_TYPE_KMS: + handle = whandle->handle; + break; + case WINSYS_HANDLE_TYPE_FD: + ret = drmPrimeFDToHandle(vws->ioctl.drm_fd, whandle->handle, + &handle); + if (ret) { + vmw_error("Failed to get handle from prime fd %d.\n", + (int) whandle->handle); + return NULL; + } + break; + default: + vmw_error("Attempt to import unsupported handle type %d.\n", + whandle->type); + return NULL; + } memset(&arg, 0, sizeof(arg)); - req->sid = whandle->handle; + req->sid = handle; + rep->size_addr = (unsigned long)&size; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, &arg, sizeof(arg)); + /* + * Need to close the handle we got from prime. + */ + if (whandle->type == WINSYS_HANDLE_TYPE_FD) + vmw_ioctl_surface_destroy(vws, handle); + if (ret) { - fprintf(stderr, "Failed referencing shared surface. SID %d.\n" - "Error %d (%s).\n", - whandle->handle, ret, strerror(-ret)); - return NULL; + /* + * Any attempt to share something other than a surface, like a dumb + * kms buffer, should fail here. + */ + vmw_error("Failed referencing shared surface. SID %d.\n" + "Error %d (%s).\n", + handle, ret, strerror(-ret)); + return NULL; } if (rep->mip_levels[0] != 1) { - fprintf(stderr, "Incorrect number of mipmap levels on shared surface." - " SID %d, levels %d\n", - whandle->handle, rep->mip_levels[0]); + vmw_error("Incorrect number of mipmap levels on shared surface." + " SID %d, levels %d\n", + handle, rep->mip_levels[0]); goto out_mip; } for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { if (rep->mip_levels[i] != 0) { - fprintf(stderr, "Incorrect number of faces levels on shared surface." - " SID %d, face %d present.\n", - whandle->handle, i); + vmw_error("Incorrect number of faces levels on shared surface." + " SID %d, face %d present.\n", + handle, i); goto out_mip; } - } + } vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); if (!vsrf) @@ -326,14 +300,24 @@ vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); vsrf->screen = vws; - vsrf->sid = whandle->handle; + vsrf->sid = handle; ssrf = svga_winsys_surface(vsrf); *format = rep->format; + /* Estimate usage, for early flushing. */ + + base_size.width = size.width; + base_size.height = size.height; + base_size.depth = size.depth; + vsrf->size = svga3dsurface_get_serialized_size(rep->format, base_size, + rep->mip_levels[0], + FALSE); + return ssrf; out_mip: - vmw_ioctl_surface_destroy(vws, whandle->handle); + vmw_ioctl_surface_destroy(vws, handle); + return NULL; } @@ -343,7 +327,9 @@ vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, unsigned stride, struct winsys_handle *whandle) { + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); struct vmw_svga_winsys_surface *vsrf; + int ret; if (!surface) return FALSE; @@ -351,24 +337,26 @@ vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, vsrf = vmw_svga_winsys_surface(surface); whandle->handle = vsrf->sid; whandle->stride = stride; + whandle->offset = 0; + + switch (whandle->type) { + case WINSYS_HANDLE_TYPE_SHARED: + case WINSYS_HANDLE_TYPE_KMS: + whandle->handle = vsrf->sid; + break; + case WINSYS_HANDLE_TYPE_FD: + ret = drmPrimeHandleToFD(vws->ioctl.drm_fd, vsrf->sid, DRM_CLOEXEC, + (int *)&whandle->handle); + if (ret) { + vmw_error("Failed to get file descriptor from prime.\n"); + return FALSE; + } + break; + default: + vmw_error("Attempt to export unsupported handle type %d.\n", + whandle->type); + return FALSE; + } return TRUE; } - - -static struct dri1_api dri1_api_hooks = { - .front_srf_locked = NULL, - .present_locked = vmw_dri1_present_locked -}; - -static struct drm_api vmw_drm_api_hooks = { - .name = "vmwgfx", - .driver_name = "vmwgfx", - .create_screen = vmw_drm_create_screen, - .destroy = NULL, -}; - -struct drm_api* drm_api_create() -{ - return trace_drm_create(&vmw_drm_api_hooks); -}