Path: blob/21.2-virgl/src/gallium/targets/d3dadapter9/drm.c
4565 views
/*1* Copyright 2011 Joakim Sindholt <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE. */2122/* XXX: header order is slightly screwy here */23#include "loader.h"2425#include "adapter9.h"2627#include "pipe-loader/pipe_loader.h"2829#include "pipe/p_screen.h"30#include "pipe/p_state.h"3132#include "target-helpers/drm_helper.h"33#include "target-helpers/sw_helper.h"34#include "frontend/drm_driver.h"3536#include "d3dadapter/d3dadapter9.h"37#include "d3dadapter/drm.h"3839#include "util/xmlconfig.h"40#include "util/driconf.h"4142#include "drm-uapi/drm.h"43#include <sys/ioctl.h>44#include <fcntl.h>45#include <stdio.h>4647#define DBG_CHANNEL DBG_ADAPTER4849const driOptionDescription __driConfigOptionsNine[] = {50DRI_CONF_SECTION_PERFORMANCE51DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)52DRI_CONF_SECTION_END53DRI_CONF_SECTION_NINE54DRI_CONF_NINE_OVERRIDEVENDOR(-1)55DRI_CONF_NINE_THROTTLE(-2)56DRI_CONF_NINE_THREADSUBMIT(true)57DRI_CONF_NINE_ALLOWDISCARDDELAYEDRELEASE(true)58DRI_CONF_NINE_TEARFREEDISCARD(true)59DRI_CONF_NINE_CSMT(-1)60DRI_CONF_NINE_DYNAMICTEXTUREWORKAROUND(true)61DRI_CONF_NINE_SHADERINLINECONSTANTS(false)62DRI_CONF_NINE_SHMEM_LIMIT()63DRI_CONF_NINE_FORCESWRENDERINGONCPU(false)64DRI_CONF_SECTION_END65DRI_CONF_SECTION_DEBUG66DRI_CONF_OVERRIDE_VRAM_SIZE()67DRI_CONF_SECTION_END68};6970struct fallback_card_config {71const char *name;72unsigned vendor_id;73unsigned device_id;74} fallback_cards[] = {75{"NV124", 0x10de, 0x13C2}, /* NVIDIA GeForce GTX 970 */76{"HAWAII", 0x1002, 0x67b1}, /* AMD Radeon R9 290 */77{"Haswell Mobile", 0x8086, 0x13C2}, /* Intel Haswell Mobile */78{"SVGA3D", 0x15ad, 0x0405}, /* VMware SVGA 3D */79};8081/* prototypes */82void83d3d_match_vendor_id( D3DADAPTER_IDENTIFIER9* drvid,84unsigned fallback_ven,85unsigned fallback_dev,86const char* fallback_name );8788void d3d_fill_driver_version(D3DADAPTER_IDENTIFIER9* drvid);8990void d3d_fill_cardname(D3DADAPTER_IDENTIFIER9* drvid);9192struct d3dadapter9drm_context93{94struct d3dadapter9_context base;95struct pipe_loader_device *dev, *swdev;96int fd;97};9899static void100drm_destroy( struct d3dadapter9_context *ctx )101{102struct d3dadapter9drm_context *drm = (struct d3dadapter9drm_context *)ctx;103104if (ctx->ref && ctx->hal != ctx->ref)105ctx->ref->destroy(ctx->ref);106/* because ref is a wrapper around hal, freeing ref frees hal too. */107else if (ctx->hal)108ctx->hal->destroy(ctx->hal);109110if (drm->swdev && drm->swdev != drm->dev)111pipe_loader_release(&drm->swdev, 1);112if (drm->dev)113pipe_loader_release(&drm->dev, 1);114115close(drm->fd);116FREE(ctx);117}118119static inline void120get_bus_info( int fd,121DWORD *vendorid,122DWORD *deviceid,123DWORD *subsysid,124DWORD *revision )125{126int vid, did;127128if (loader_get_pci_id_for_fd(fd, &vid, &did)) {129DBG("PCI info: vendor=0x%04x, device=0x%04x\n",130vid, did);131*vendorid = vid;132*deviceid = did;133*subsysid = 0;134*revision = 0;135} else {136DBG("Unable to detect card. Faking %s\n", fallback_cards[0].name);137*vendorid = fallback_cards[0].vendor_id;138*deviceid = fallback_cards[0].device_id;139*subsysid = 0;140*revision = 0;141}142}143144static inline void145read_descriptor( struct d3dadapter9_context *ctx,146int fd, int override_vendorid )147{148unsigned i;149BOOL found;150D3DADAPTER_IDENTIFIER9 *drvid = &ctx->identifier;151152memset(drvid, 0, sizeof(*drvid));153get_bus_info(fd, &drvid->VendorId, &drvid->DeviceId,154&drvid->SubSysId, &drvid->Revision);155snprintf(drvid->DeviceName, sizeof(drvid->DeviceName),156"Gallium 0.4 with %s", ctx->hal->get_vendor(ctx->hal));157snprintf(drvid->Description, sizeof(drvid->Description),158"%s", ctx->hal->get_name(ctx->hal));159160if (override_vendorid > 0) {161found = FALSE;162/* fill in device_id and card name for fake vendor */163for (i = 0; i < sizeof(fallback_cards)/sizeof(fallback_cards[0]); i++) {164if (fallback_cards[i].vendor_id == override_vendorid) {165DBG("Faking card '%s' vendor 0x%04x, device 0x%04x\n",166fallback_cards[i].name,167fallback_cards[i].vendor_id,168fallback_cards[i].device_id);169drvid->VendorId = fallback_cards[i].vendor_id;170drvid->DeviceId = fallback_cards[i].device_id;171snprintf(drvid->Description, sizeof(drvid->Description),172"%s", fallback_cards[i].name);173found = TRUE;174break;175}176}177if (!found) {178DBG("Unknown fake vendor 0x%04x! Using detected vendor !\n", override_vendorid);179}180}181/* choose fall-back vendor if necessary to allow182* the following functions to return sane results */183d3d_match_vendor_id(drvid, fallback_cards[0].vendor_id, fallback_cards[0].device_id, fallback_cards[0].name);184/* fill in driver name and version info */185d3d_fill_driver_version(drvid);186/* override Description field with Windows like names */187d3d_fill_cardname(drvid);188189/* this driver isn't WHQL certified */190drvid->WHQLLevel = 0;191192/* this value is fixed */193drvid->DeviceIdentifier.Data1 = 0xaeb2cdd4;194drvid->DeviceIdentifier.Data2 = 0x6e41;195drvid->DeviceIdentifier.Data3 = 0x43ea;196drvid->DeviceIdentifier.Data4[0] = 0x94;197drvid->DeviceIdentifier.Data4[1] = 0x1c;198drvid->DeviceIdentifier.Data4[2] = 0x83;199drvid->DeviceIdentifier.Data4[3] = 0x61;200drvid->DeviceIdentifier.Data4[4] = 0xcc;201drvid->DeviceIdentifier.Data4[5] = 0x76;202drvid->DeviceIdentifier.Data4[6] = 0x07;203drvid->DeviceIdentifier.Data4[7] = 0x81;204}205206static HRESULT WINAPI207drm_create_adapter( int fd,208ID3DAdapter9 **ppAdapter )209{210struct d3dadapter9drm_context *ctx = CALLOC_STRUCT(d3dadapter9drm_context);211HRESULT hr;212bool different_device;213driOptionCache defaultInitOptions;214driOptionCache userInitOptions;215int throttling_value_user = -2;216int override_vendorid = -1;217bool sw_rendering;218219if (!ctx) { return E_OUTOFMEMORY; }220221ctx->base.destroy = drm_destroy;222223/* Although the fd is provided from external source, mesa/nine224* takes ownership of it. */225fd = loader_get_user_preferred_fd(fd, &different_device);226ctx->fd = fd;227ctx->base.linear_framebuffer = different_device;228229if (!pipe_loader_drm_probe_fd(&ctx->dev, fd)) {230ERR("Failed to probe drm fd %d.\n", fd);231FREE(ctx);232close(fd);233return D3DERR_DRIVERINTERNALERROR;234}235236ctx->base.hal = pipe_loader_create_screen(ctx->dev);237if (!ctx->base.hal) {238ERR("Unable to load requested driver.\n");239drm_destroy(&ctx->base);240return D3DERR_DRIVERINTERNALERROR;241}242243if (!ctx->base.hal->get_param(ctx->base.hal, PIPE_CAP_DMABUF)) {244ERR("The driver is not capable of dma-buf sharing."245"Abandon to load nine state tracker\n");246drm_destroy(&ctx->base);247return D3DERR_DRIVERINTERNALERROR;248}249250/* Previously was set to PIPE_CAP_MAX_FRAMES_IN_FLIGHT,251* but the change of value of this cap to 1 seems to cause252* regressions. */253ctx->base.throttling_value = 2;254ctx->base.throttling = ctx->base.throttling_value > 0;255256driParseOptionInfo(&defaultInitOptions, __driConfigOptionsNine,257ARRAY_SIZE(__driConfigOptionsNine));258driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0,259"nine", NULL, NULL, 0, NULL, 0);260if (driCheckOption(&userInitOptions, "throttle_value", DRI_INT)) {261throttling_value_user = driQueryOptioni(&userInitOptions, "throttle_value");262if (throttling_value_user == -1)263ctx->base.throttling = FALSE;264else if (throttling_value_user >= 0) {265ctx->base.throttling = TRUE;266ctx->base.throttling_value = throttling_value_user;267}268}269270ctx->base.vblank_mode = driQueryOptioni(&userInitOptions, "vblank_mode");271ctx->base.thread_submit = driQueryOptionb(&userInitOptions, "thread_submit"); /* TODO: default to TRUE if different_device */272override_vendorid = driQueryOptioni(&userInitOptions, "override_vendorid");273274ctx->base.discard_delayed_release = driQueryOptionb(&userInitOptions, "discard_delayed_release");275ctx->base.tearfree_discard = driQueryOptionb(&userInitOptions, "tearfree_discard");276277if (ctx->base.tearfree_discard && !ctx->base.discard_delayed_release) {278ERR("tearfree_discard requires discard_delayed_release\n");279ctx->base.tearfree_discard = FALSE;280}281282ctx->base.csmt_force = driQueryOptioni(&userInitOptions, "csmt_force");283ctx->base.dynamic_texture_workaround = driQueryOptionb(&userInitOptions, "dynamic_texture_workaround");284ctx->base.shader_inline_constants = driQueryOptionb(&userInitOptions, "shader_inline_constants");285ctx->base.memfd_virtualsizelimit = driQueryOptioni(&userInitOptions, "texture_memory_limit");286ctx->base.override_vram_size = driQueryOptioni(&userInitOptions, "override_vram_size");287sw_rendering = driQueryOptionb(&userInitOptions, "force_sw_rendering_on_cpu");288289driDestroyOptionCache(&userInitOptions);290driDestroyOptionInfo(&defaultInitOptions);291292/* wrap it to create a software screen that can share resources */293if (sw_rendering && pipe_loader_sw_probe_wrapped(&ctx->swdev, ctx->base.hal))294ctx->base.ref = pipe_loader_create_screen(ctx->swdev);295else {296/* Use the hardware for sw rendering */297ctx->swdev = ctx->dev;298ctx->base.ref = ctx->base.hal;299}300301/* read out PCI info */302read_descriptor(&ctx->base, fd, override_vendorid);303304/* create and return new ID3DAdapter9 */305hr = NineAdapter9_new(&ctx->base, (struct NineAdapter9 **)ppAdapter);306if (FAILED(hr)) {307drm_destroy(&ctx->base);308return hr;309}310311return D3D_OK;312}313314const struct D3DAdapter9DRM drm9_desc = {315.major_version = D3DADAPTER9DRM_MAJOR,316.minor_version = D3DADAPTER9DRM_MINOR,317.create_adapter = drm_create_adapter318};319320321