diff options
author | Giovanni Campagna <[email protected]> | 2014-07-23 19:37:31 +0100 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2014-07-30 16:33:09 +0100 |
commit | 3b176c441b7ddc5f7d2f891da3f76cf3c1814ce1 (patch) | |
tree | a99421810f0150b9759363fb56910a160d10ad97 /src/gallium/winsys/sw | |
parent | 8430af5ebe1ee8119e14ae8fe00ec98fda40c57f (diff) |
gallium: Add a dumb drm/kms winsys backed swrast provider
Add a new winsys and target that can be used with a dri2 state tracker
and loader instead of drisw. This allows to use gbm as a dri2/image
loader and avoid the extra copy from the backbuffer to the shadow
frontbuffer.
The new driver is called "kms_swrast", and is loaded by gbm as a
fallback, because it is only useful with the gbm platform (as no buffer
sharing is possible)
To force select the driver set the environment variable
GBM_ALWAYS_SOFTWARE
[Emil Velikov]
- Rebase on top of gallium megadriver.
- s/text/test/ in configure.ac (Spotted by Andreas Pokorny).
- Add scons support for winsys/sw/kms-dri and fix the build.
- Provide separate DriverAPI, due to different InitScreen hook.
Signed-off-by: Emil Velikov <[email protected]>
Diffstat (limited to 'src/gallium/winsys/sw')
-rw-r--r-- | src/gallium/winsys/sw/kms-dri/Makefile.am | 32 | ||||
-rw-r--r-- | src/gallium/winsys/sw/kms-dri/SConscript | 26 | ||||
-rw-r--r-- | src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c | 312 | ||||
-rw-r--r-- | src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.h | 37 |
4 files changed, 407 insertions, 0 deletions
diff --git a/src/gallium/winsys/sw/kms-dri/Makefile.am b/src/gallium/winsys/sw/kms-dri/Makefile.am new file mode 100644 index 00000000000..cb3b61deea6 --- /dev/null +++ b/src/gallium/winsys/sw/kms-dri/Makefile.am @@ -0,0 +1,32 @@ +# Copyright © 2012 Intel Corporation +# 2013 Red Hat, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +include $(top_srcdir)/src/gallium/Automake.inc + +AM_CFLAGS = \ + $(GALLIUM_WINSYS_CFLAGS) \ + $(LIBDRM_CFLAGS) + +noinst_LTLIBRARIES = libswkmsdri.la + +libswkmsdri_la_SOURCES = kms_dri_sw_winsys.c diff --git a/src/gallium/winsys/sw/kms-dri/SConscript b/src/gallium/winsys/sw/kms-dri/SConscript new file mode 100644 index 00000000000..0a6c335cbd7 --- /dev/null +++ b/src/gallium/winsys/sw/kms-dri/SConscript @@ -0,0 +1,26 @@ +####################################################################### +# SConscript for kms-dri winsys + + +Import('*') + +if env['platform'] not in ('linux'): + Return() + +env = env.Clone() + +env.PkgUseModules('DRM') + +env.Append(CPPPATH = [ +# 'include', + '#/src/gallium/include', + '#/src/gallium/auxiliary', +]) + +ws_kms_dri = env.ConvenienceLibrary( + target = 'ws_kms_dri', + source = [ + 'kms_dri_sw_winsys.c', + ] +) +Export('ws_kms_dri') diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c new file mode 100644 index 00000000000..e21c4c2627a --- /dev/null +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c @@ -0,0 +1,312 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <[email protected]> + * 2013 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <limits.h> + +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#include <dlfcn.h> +#include <xf86drm.h> + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_double_list.h" + +#include "state_tracker/sw_winsys.h" +#include "state_tracker/drm_driver.h" + +#if 0 +#define DEBUG(msg, ...) fprintf(stderr, msg, __VA_ARGS__) +#else +#define DEBUG(msg, ...) +#endif + +struct sw_winsys; + +struct sw_winsys *kms_dri_create_winsys(int fd); + +struct kms_sw_displaytarget +{ + enum pipe_format format; + unsigned width; + unsigned height; + unsigned stride; + unsigned size; + + uint32_t handle; + void *mapped; + + int ref_count; + struct list_head link; +}; + +struct kms_sw_winsys +{ + struct sw_winsys base; + + int fd; + struct list_head bo_list; +}; + +static INLINE struct kms_sw_displaytarget * +kms_sw_displaytarget( struct sw_displaytarget *dt ) +{ + return (struct kms_sw_displaytarget *)dt; +} + +static INLINE struct kms_sw_winsys * +kms_sw_winsys( struct sw_winsys *ws ) +{ + return (struct kms_sw_winsys *)ws; +} + + +static boolean +kms_sw_is_displaytarget_format_supported( struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format ) +{ + /* TODO: check visuals or other sensible thing here */ + return TRUE; +} + +static struct sw_displaytarget * +kms_sw_displaytarget_create(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws); + struct kms_sw_displaytarget *kms_sw_dt; + struct drm_mode_create_dumb create_req; + struct drm_mode_destroy_dumb destroy_req; + int ret; + + kms_sw_dt = CALLOC_STRUCT(kms_sw_displaytarget); + if(!kms_sw_dt) + goto no_dt; + + kms_sw_dt->ref_count = 1; + + kms_sw_dt->format = format; + kms_sw_dt->width = width; + kms_sw_dt->height = height; + + create_req.bpp = 32; + create_req.width = width; + create_req.height = height; + create_req.handle = 0; + ret = drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_req); + if (ret) + goto free_bo; + + kms_sw_dt->stride = create_req.pitch; + kms_sw_dt->size = create_req.size; + kms_sw_dt->handle = create_req.handle; + + list_add(&kms_sw_dt->link, &kms_sw->bo_list); + + DEBUG("KMS-DEBUG: created buffer %u (size %u)\n", kms_sw_dt->handle, kms_sw_dt->size); + + *stride = kms_sw_dt->stride; + return (struct sw_displaytarget *)kms_sw_dt; + + free_bo: + memset(&destroy_req, 0, sizeof destroy_req); + destroy_req.handle = create_req.handle; + drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_req); + FREE(kms_sw_dt); + no_dt: + return NULL; +} + +static void +kms_sw_displaytarget_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws); + struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); + struct drm_mode_destroy_dumb destroy_req; + + kms_sw_dt->ref_count --; + if (kms_sw_dt->ref_count > 0) + return; + + memset(&destroy_req, 0, sizeof destroy_req); + destroy_req.handle = kms_sw_dt->handle; + drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_req); + + list_del(&kms_sw_dt->link); + + DEBUG("KMS-DEBUG: destroyed buffer %u\n", kms_sw_dt->handle); + + FREE(kms_sw_dt); +} + +static void * +kms_sw_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags) +{ + struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws); + struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); + struct drm_mode_map_dumb map_req; + int prot, ret; + + memset(&map_req, 0, sizeof map_req); + map_req.handle = kms_sw_dt->handle; + ret = drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_req); + if (ret) + return NULL; + + prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | PROT_WRITE); + kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, + kms_sw->fd, map_req.offset); + + if (kms_sw_dt->mapped == MAP_FAILED) + return NULL; + + DEBUG("KMS-DEBUG: mapped buffer %u (size %u) at %p\n", + kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped); + + return kms_sw_dt->mapped; +} + +static void +kms_sw_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); + + DEBUG("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->mapped); + + munmap(kms_sw_dt->mapped, kms_sw_dt->size); + kms_sw_dt->mapped = NULL; +} + +static struct sw_displaytarget * +kms_sw_displaytarget_from_handle(struct sw_winsys *ws, + const struct pipe_resource *templ, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws); + struct kms_sw_displaytarget *kms_sw_dt; + + LIST_FOR_EACH_ENTRY(kms_sw_dt, &kms_sw->bo_list, link) { + if (kms_sw_dt->handle == whandle->handle) { + kms_sw_dt->ref_count++; + + DEBUG("KMS-DEBUG: imported buffer %u (size %u)\n", kms_sw_dt->handle, kms_sw_dt->size); + + *stride = kms_sw_dt->stride; + return (struct sw_displaytarget *)kms_sw_dt; + } + } + + assert(0); + return NULL; +} + +static boolean +kms_sw_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); + + assert(whandle->type == DRM_API_HANDLE_TYPE_SHARED); + whandle->handle = kms_sw_dt->handle; + whandle->stride = kms_sw_dt->stride; + return TRUE; +} + +static void +kms_sw_displaytarget_display(struct sw_winsys *ws, + struct sw_displaytarget *dt, + void *context_private, + struct pipe_box *box) +{ + /* This function should not be called, instead the dri2 loader should + handle swap buffers internally. + */ + assert(0); +} + + +static void +kms_destroy_sw_winsys(struct sw_winsys *winsys) +{ + FREE(winsys); +} + +struct sw_winsys * +kms_dri_create_winsys(int fd) +{ + struct kms_sw_winsys *ws; + + ws = CALLOC_STRUCT(kms_sw_winsys); + if (!ws) + return NULL; + + ws->fd = fd; + list_inithead(&ws->bo_list); + + ws->base.destroy = kms_destroy_sw_winsys; + + ws->base.is_displaytarget_format_supported = kms_sw_is_displaytarget_format_supported; + + /* screen texture functions */ + ws->base.displaytarget_create = kms_sw_displaytarget_create; + ws->base.displaytarget_destroy = kms_sw_displaytarget_destroy; + ws->base.displaytarget_from_handle = kms_sw_displaytarget_from_handle; + ws->base.displaytarget_get_handle = kms_sw_displaytarget_get_handle; + + /* texture functions */ + ws->base.displaytarget_map = kms_sw_displaytarget_map; + ws->base.displaytarget_unmap = kms_sw_displaytarget_unmap; + + ws->base.displaytarget_display = kms_sw_displaytarget_display; + + return &ws->base; +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */
\ No newline at end of file diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.h b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.h new file mode 100644 index 00000000000..e276a723466 --- /dev/null +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.h @@ -0,0 +1,37 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <[email protected]> + * 2013 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef KMS_DRI_SW_WINSYS +#define KMS_DRI_SW_WINSYS + +struct sw_winsys; + +struct sw_winsys *kms_dri_create_winsys(int fd); + +#endif |