diff options
author | Joakim Sindholt <[email protected]> | 2011-08-04 15:14:06 +0200 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2014-11-18 02:02:54 +0000 |
commit | fdd96578ef2dfe9c4ad5aab5858036298d444a64 (patch) | |
tree | 3230b0fb321381250a506503825318facb10ca73 /src/gallium/targets | |
parent | 7d2573b5376bb4f9ce9a50e0b965e06032b135a9 (diff) |
nine: Add state tracker nine for Direct3D9 (v3)
Work of Joakim Sindholt (zhasha) and Christoph Bumiller (chrisbmr).
DRI3 port done by Axel Davy (mannerov).
v2: - nine_debug.c: klass extended from 32 chars to 96 (for sure) by glennk
- Nine improvements by Axel Davy (which also fixed some wine tests)
- by Emil Velikov:
- convert to static/shared drivers
- Sort and cleanup the includes
- Use AM_CPPFLAGS for the defines
- Add the linker garbage collector
- Restrict the exported symbols (think llvm)
v3: - small nine fixes
- build system improvements by Emil Velikov
v4: [Emil Velikov]
- Do no link against libudev. No longer needed.
Acked-by: Jose Fonseca <[email protected]>
Reviewed-by: Marek Olšák <[email protected]>
Reviewed-by: Axel Davy <[email protected]>
Signed-off-by: David Heidelberg <[email protected]>
Diffstat (limited to 'src/gallium/targets')
-rw-r--r-- | src/gallium/targets/d3dadapter9/Makefile.am | 131 | ||||
-rw-r--r-- | src/gallium/targets/d3dadapter9/d3d.pc.in | 11 | ||||
-rw-r--r-- | src/gallium/targets/d3dadapter9/d3dadapter9.sym | 6 | ||||
-rw-r--r-- | src/gallium/targets/d3dadapter9/drm.c | 327 | ||||
-rw-r--r-- | src/gallium/targets/d3dadapter9/getproc.c | 47 |
5 files changed, 522 insertions, 0 deletions
diff --git a/src/gallium/targets/d3dadapter9/Makefile.am b/src/gallium/targets/d3dadapter9/Makefile.am new file mode 100644 index 00000000000..62312369adc --- /dev/null +++ b/src/gallium/targets/d3dadapter9/Makefile.am @@ -0,0 +1,131 @@ +# Copyright © 2012 Intel Corporation +# +# 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 = \ + -I$(top_srcdir)/include/D3D9 \ + -I$(top_srcdir)/src/loader \ + -I$(top_srcdir)/src/mapi/ \ + -I$(top_srcdir)/src/mesa/ \ + -I$(top_srcdir)/src/mesa/drivers/dri/common/ \ + -I$(top_builddir)/src/mesa/drivers/dri/common/ \ + -I$(top_srcdir)/src/gallium/winsys \ + -I$(top_srcdir)/src/gallium/state_trackers/nine \ + $(GALLIUM_TARGET_CFLAGS) \ + $(VISIBILITY_CFLAGS) + +if HAVE_GALLIUM_STATIC_TARGETS +AM_CPPFLAGS = \ + -DNINE_TARGET \ + -DGALLIUM_STATIC_TARGETS=1 + +else + +AM_CPPFLAGS = \ + -DPIPE_SEARCH_DIR=\"$(libdir)/gallium-pipe\" \ + $(GALLIUM_PIPE_LOADER_DEFINES) + +endif + +ninedir = $(D3D_DRIVER_INSTALL_DIR) +nine_LTLIBRARIES = d3dadapter9.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = d3d.pc + +d3dadapter9_la_SOURCES = \ + getproc.c \ + drm.c + +d3dadapter9_la_LDFLAGS = \ + -shared \ + -shrext .so \ + -module \ + -no-undefined \ + -version-number $(NINE_MAJOR):$(NINE_MINOR) \ + $(GC_SECTIONS) \ + $(LD_NO_UNDEFINED) + +if HAVE_LD_VERSION_SCRIPT +d3dadapter9_la_LDFLAGS += \ + -Wl,--version-script=$(top_srcdir)/src/gallium/targets/d3dadapter9/d3dadapter9.sym +endif # HAVE_LD_VERSION_SCRIPT + +d3dadapter9_la_LIBADD = \ + $(top_builddir)/src/gallium/auxiliary/libgallium.la \ + $(top_builddir)/src/gallium/state_trackers/nine/libninetracker.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(top_builddir)/src/gallium/winsys/sw/wrapper/libwsw.la \ + $(EXPAT_LIBS) \ + $(GALLIUM_COMMON_LIB_DEPS) + + +TARGET_DRIVERS = +TARGET_CPPFLAGS = +TARGET_LIB_DEPS = $(top_builddir)/src/loader/libloader.la + +include $(top_srcdir)/src/gallium/drivers/i915/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/ilo/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/nouveau/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/r300/Automake.inc +include $(top_srcdir)/src/gallium/drivers/r600/Automake.inc +include $(top_srcdir)/src/gallium/drivers/radeonsi/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/svga/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/freedreno/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/vc4/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/softpipe/Automake.inc +include $(top_srcdir)/src/gallium/drivers/llvmpipe/Automake.inc + +if HAVE_GALLIUM_STATIC_TARGETS + +d3dadapter9_la_CPPFLAGS = $(AM_CPPFLAGS) $(TARGET_CPPFLAGS) +d3dadapter9_la_LIBADD += $(TARGET_LIB_DEPS) \ + $(TARGET_RADEON_WINSYS) $(TARGET_RADEON_COMMON) + +else # HAVE_GALLIUM_STATIC_TARGETS + +d3dadapter9_la_LIBADD += \ + $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader.la \ + $(GALLIUM_PIPE_LOADER_WINSYS_LIBS) \ + $(GALLIUM_PIPE_LOADER_LIBS) + +endif # HAVE_GALLIUM_STATIC_TARGETS + +if HAVE_MESA_LLVM +nodist_EXTRA_d3dadapter9_la_SOURCES = dummy.cpp +d3dadapter9_la_LDFLAGS += $(LLVM_LDFLAGS) +d3dadapter9_la_LIBADD += $(LLVM_LIBS) +endif + +d3dadapterdir = $(includedir)/d3dadapter +d3dadapter_HEADERS = \ + $(top_srcdir)/include/d3dadapter/d3dadapter9.h \ + $(top_srcdir)/include/d3dadapter/drm.h \ + $(top_srcdir)/include/d3dadapter/present.h diff --git a/src/gallium/targets/d3dadapter9/d3d.pc.in b/src/gallium/targets/d3dadapter9/d3d.pc.in new file mode 100644 index 00000000000..9a18a5c1b8e --- /dev/null +++ b/src/gallium/targets/d3dadapter9/d3d.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +moduledir=@D3D_DRIVER_INSTALL_DIR@ + +Name: d3d +Description: Native D3D driver modules +Version: @VERSION@ +Requires.private: @DRI_PC_REQ_PRIV@ +Cflags: -I${includedir} diff --git a/src/gallium/targets/d3dadapter9/d3dadapter9.sym b/src/gallium/targets/d3dadapter9/d3dadapter9.sym new file mode 100644 index 00000000000..2290daea7a3 --- /dev/null +++ b/src/gallium/targets/d3dadapter9/d3dadapter9.sym @@ -0,0 +1,6 @@ +{ + global: + D3DAdapter9GetProc; + local: + *; +}; diff --git a/src/gallium/targets/d3dadapter9/drm.c b/src/gallium/targets/d3dadapter9/drm.c new file mode 100644 index 00000000000..d0b72e07bc2 --- /dev/null +++ b/src/gallium/targets/d3dadapter9/drm.c @@ -0,0 +1,327 @@ +/* + * Copyright 2011 Joakim Sindholt <[email protected]> + * + * 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 + * on 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 + * THE AUTHOR(S) AND/OR THEIR 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 "loader.h" + +#include "adapter9.h" + +#include "pipe-loader/pipe_loader.h" + +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "target-helpers/inline_drm_helper.h" +#include "target-helpers/inline_sw_helper.h" +#include "state_tracker/drm_driver.h" + +#include "d3dadapter/d3dadapter9.h" +#include "d3dadapter/drm.h" + +#include <libdrm/drm.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <stdio.h> + +#define DBG_CHANNEL DBG_ADAPTER + +#define VERSION_DWORD(hi, lo) \ + ((DWORD)( \ + ((DWORD)((hi) & 0xFFFF) << 16) | \ + (DWORD)((lo) & 0xFFFF) \ + )) + +/* Regarding os versions, we should not define our own as that would simply be + * weird. Defaulting to Win2k/XP seems sane considering the origin of D3D9. The + * driver also defaults to being a generic D3D9 driver, which of course only + * matters if you're actually using the DDI. */ +#define VERSION_HIGH VERSION_DWORD(0x0006, 0x000E) /* winxp, d3d9 */ +#define VERSION_LOW VERSION_DWORD(0x0000, 0x0001) /* version, build */ + +struct d3dadapter9drm_context +{ + struct d3dadapter9_context base; + struct pipe_loader_device *dev, *swdev; +}; + +static void +drm_destroy( struct d3dadapter9_context *ctx ) +{ +#if !GALLIUM_STATIC_TARGETS + struct d3dadapter9drm_context *drm = (struct d3dadapter9drm_context *)ctx; + + /* pipe_loader_sw destroys the context */ + if (drm->swdev) + pipe_loader_release(&drm->swdev, 1); + if (drm->dev) + pipe_loader_release(&drm->dev, 1); +#endif + + FREE(ctx); +} + +/* read a DWORD in the form 0xnnnnnnnn, which is how sysfs pci id stuff is + * formatted. */ +static INLINE DWORD +read_file_dword( const char *name ) +{ + char buf[32]; + int fd, r; + + fd = open(name, O_RDONLY); + if (fd < 0) { + DBG("Unable to get PCI information from `%s'\n", name); + return 0; + } + + r = read(fd, buf, 32); + close(fd); + + return (r > 0) ? (DWORD)strtol(buf, NULL, 0) : 0; +} + +/* sysfs doesn't expose the revision as its own file, so this function grabs a + * dword at an offset in the raw PCI header. The reason this isn't used for all + * data is that the kernel will make corrections but not expose them in the raw + * header bytes. */ +static INLINE DWORD +read_config_dword( int fd, + unsigned offset ) +{ + DWORD r = 0; + + if (lseek(fd, offset, SEEK_SET) != offset) { return 0; } + if (read(fd, &r, 4) != 4) { return 0; } + + return r; +} + +static INLINE void +get_bus_info( int fd, + DWORD *vendorid, + DWORD *deviceid, + DWORD *subsysid, + DWORD *revision ) +{ + drm_unique_t u; + + u.unique_len = 0; + u.unique = NULL; + + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { return; } + u.unique = CALLOC(u.unique_len+1, 1); + + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { return; } + u.unique[u.unique_len] = '\0'; + + DBG("DRM Device BusID: %s\n", u.unique); + if (strncmp("pci:", u.unique, 4) == 0) { + char fname[512]; /* this ought to be enough */ + int l = snprintf(fname, 512, "/sys/bus/pci/devices/%s/", u.unique+4); + + /* VendorId */ + snprintf(fname+l, 512-l, "vendor"); + *vendorid = read_file_dword(fname); + /* DeviceId */ + snprintf(fname+l, 512-l, "device"); + *deviceid = read_file_dword(fname); + /* SubSysId */ + snprintf(fname+l, 512-l, "subsystem_device"); + *subsysid = (read_file_dword(fname) << 16) & 0xFFFF0000; + snprintf(fname+l, 512-l, "subsystem_vendor"); + *subsysid |= read_file_dword(fname) & 0x0000FFFF; + /* Revision */ + { + int cfgfd; + + snprintf(fname+l, 512-l, "config"); + cfgfd = open(fname, O_RDONLY); + if (cfgfd >= 0) { + *revision = read_config_dword(cfgfd, 0x8) & 0x000000FF; + close(cfgfd); + } else { + DBG("Unable to get raw PCI information from `%s'\n", fname); + } + } + DBG("PCI info: vendor=0x%04x, device=0x%04x, subsys=0x%08x, rev=%d\n", + *vendorid, *deviceid, *subsysid, *revision); + } else { + DBG("Unsupported BusID type.\n"); + } + + FREE(u.unique); +} + +static INLINE void +read_descriptor( struct d3dadapter9_context *ctx, + int fd ) +{ + D3DADAPTER_IDENTIFIER9 *drvid = &ctx->identifier; + + memset(drvid, 0, sizeof(*drvid)); + get_bus_info(fd, &drvid->VendorId, &drvid->DeviceId, + &drvid->SubSysId, &drvid->Revision); + + strncpy(drvid->Driver, "libd3dadapter9.so", sizeof(drvid->Driver)); + strncpy(drvid->DeviceName, ctx->hal->get_name(ctx->hal), 32); + snprintf(drvid->Description, sizeof(drvid->Description), + "Gallium 0.4 with %s", ctx->hal->get_vendor(ctx->hal)); + + drvid->DriverVersionLowPart = VERSION_LOW; + drvid->DriverVersionHighPart = VERSION_HIGH; + + /* To make a pseudo-real GUID we use the PCI bus data and some string */ + drvid->DeviceIdentifier.Data1 = drvid->VendorId; + drvid->DeviceIdentifier.Data2 = drvid->DeviceId; + drvid->DeviceIdentifier.Data3 = drvid->SubSysId; + memcpy(drvid->DeviceIdentifier.Data4, "Gallium3D", 8); + + drvid->WHQLLevel = 1; /* This fakes WHQL validaion */ + + /* XXX Fake NVIDIA binary driver on Windows. + * + * OS version: 4=95/98/NT4, 5=2000, 6=2000/XP, 7=Vista, 8=Win7 + */ + strncpy(drvid->Driver, "nvd3dum.dll", sizeof(drvid->Driver)); + strncpy(drvid->Description, "NVIDIA GeForce GTX 680", sizeof(drvid->Description)); + drvid->DriverVersionLowPart = VERSION_DWORD(12, 6658); /* minor, build */ + drvid->DriverVersionHighPart = VERSION_DWORD(6, 15); /* OS, major */ + drvid->SubSysId = 0; + drvid->Revision = 0; + drvid->DeviceIdentifier.Data1 = 0xaeb2cdd4; + drvid->DeviceIdentifier.Data2 = 0x6e41; + drvid->DeviceIdentifier.Data3 = 0x43ea; + drvid->DeviceIdentifier.Data4[0] = 0x94; + drvid->DeviceIdentifier.Data4[1] = 0x1c; + drvid->DeviceIdentifier.Data4[2] = 0x83; + drvid->DeviceIdentifier.Data4[3] = 0x61; + drvid->DeviceIdentifier.Data4[4] = 0xcc; + drvid->DeviceIdentifier.Data4[5] = 0x76; + drvid->DeviceIdentifier.Data4[6] = 0x07; + drvid->DeviceIdentifier.Data4[7] = 0x81; + drvid->WHQLLevel = 0; +} + +static HRESULT WINAPI +drm_create_adapter( int fd, + ID3DAdapter9 **ppAdapter ) +{ + struct d3dadapter9drm_context *ctx = CALLOC_STRUCT(d3dadapter9drm_context); + HRESULT hr; + int i, different_device; + const struct drm_conf_ret *throttle_ret = NULL; + const struct drm_conf_ret *dmabuf_ret = NULL; + +#if !GALLIUM_STATIC_TARGETS + const char *paths[] = { + getenv("D3D9_DRIVERS_PATH"), + getenv("D3D9_DRIVERS_DIR"), + PIPE_SEARCH_DIR + }; +#endif + + if (!ctx) { return E_OUTOFMEMORY; } + + ctx->base.destroy = drm_destroy; + + fd = loader_get_user_preferred_fd(fd, &different_device); + ctx->base.linear_framebuffer = !!different_device; + +#if GALLIUM_STATIC_TARGETS + ctx->base.hal = dd_create_screen(fd); +#else + /* use pipe-loader to dlopen appropriate drm driver */ + if (!pipe_loader_drm_probe_fd(&ctx->dev, fd, FALSE)) { + ERR("Failed to probe drm fd %d.\n", fd); + FREE(ctx); + close(fd); + return D3DERR_DRIVERINTERNALERROR; + } + + /* use pipe-loader to create a drm screen (hal) */ + ctx->base.hal = NULL; + for (i = 0; !ctx->base.hal && i < Elements(paths); ++i) { + if (!paths[i]) { continue; } + ctx->base.hal = pipe_loader_create_screen(ctx->dev, paths[i]); + } +#endif + if (!ctx->base.hal) { + ERR("Unable to load requested driver.\n"); + drm_destroy(&ctx->base); + return D3DERR_DRIVERINTERNALERROR; + } + +#if GALLIUM_STATIC_TARGETS + dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD); + throttle_ret = dd_configuration(DRM_CONF_THROTTLE); +#else + dmabuf_ret = pipe_loader_configuration(ctx->dev, DRM_CONF_SHARE_FD); + throttle_ret = pipe_loader_configuration(ctx->dev, DRM_CONF_THROTTLE); +#endif // GALLIUM_STATIC_TARGETS + if (!dmabuf_ret || !dmabuf_ret->val.val_bool) { + ERR("The driver is not capable of dma-buf sharing." + "Abandon to load nine state tracker\n"); + drm_destroy(&ctx->base); + return D3DERR_DRIVERINTERNALERROR; + } + + if (throttle_ret && throttle_ret->val.val_int != -1) { + ctx->base.throttling = TRUE; + ctx->base.throttling_value = throttle_ret->val.val_int; + } else + ctx->base.throttling = FALSE; + + +#if GALLIUM_STATIC_TARGETS + ctx->base.ref = ninesw_create_screen(ctx->base.hal); +#else + /* wrap it to create a software screen that can share resources */ + if (pipe_loader_sw_probe_wrapped(&ctx->swdev, ctx->base.hal)) { + ctx->base.ref = NULL; + for (i = 0; !ctx->base.ref && i < Elements(paths); ++i) { + if (!paths[i]) { continue; } + ctx->base.ref = pipe_loader_create_screen(ctx->swdev, paths[i]); + } + } +#endif + if (!ctx->base.ref) { + ERR("Couldn't wrap drm screen to swrast screen. Software devices " + "will be unavailable.\n"); + } + + /* read out PCI info */ + read_descriptor(&ctx->base, fd); + + /* create and return new ID3DAdapter9 */ + hr = NineAdapter9_new(&ctx->base, (struct NineAdapter9 **)ppAdapter); + if (FAILED(hr)) { + drm_destroy(&ctx->base); + return hr; + } + + return D3D_OK; +} + +const struct D3DAdapter9DRM drm9_desc = { + .major_version = D3DADAPTER9DRM_MAJOR, + .minor_version = D3DADAPTER9DRM_MINOR, + .create_adapter = drm_create_adapter +}; diff --git a/src/gallium/targets/d3dadapter9/getproc.c b/src/gallium/targets/d3dadapter9/getproc.c new file mode 100644 index 00000000000..2aa79a444ed --- /dev/null +++ b/src/gallium/targets/d3dadapter9/getproc.c @@ -0,0 +1,47 @@ +/* + * Copyright 2013 Joakim Sindholt <[email protected]> + * + * 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 + * on 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 + * THE AUTHOR(S) AND/OR THEIR 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 <string.h> + +#include "util/u_memory.h" + +#include "d3dadapter/drm.h" +extern const struct D3DAdapter9DRM drm9_desc; + +struct { + const char *name; + const void *desc; +} drivers[] = { + { D3DADAPTER9DRM_NAME, &drm9_desc }, +}; + +PUBLIC const void * WINAPI +D3DAdapter9GetProc( const char *name ) +{ + int i; + for (i = 0; i < Elements(drivers); ++i) { + if (strcmp(name, drivers[i].name) == 0) { + return drivers[i].desc; + } + } + return NULL; +} |