diff options
author | Jaroslav Hensl <emulator@emulace.cz> | 2023-04-10 14:53:37 +0200 |
---|---|---|
committer | Jaroslav Hensl <emulator@emulace.cz> | 2023-04-10 14:53:37 +0200 |
commit | 503e91046f60a86823629d43e64e2d0fcc006549 (patch) | |
tree | 7f4815da1ae1a94ede4d35aeb32b7ec2b32427e2 /vmware | |
download | vmdisp9x-503e91046f60a86823629d43e64e2d0fcc006549.tar.gz |
public release
Diffstat (limited to 'vmware')
-rw-r--r-- | vmware/pci.c | 277 | ||||
-rw-r--r-- | vmware/pci.h | 101 | ||||
-rw-r--r-- | vmware/pci32.c | 2 | ||||
-rw-r--r-- | vmware/svga.c | 1971 | ||||
-rw-r--r-- | vmware/svga.h | 153 | ||||
-rw-r--r-- | vmware/svga32.c | 2 | ||||
-rw-r--r-- | vmware/svga3d.c | 1222 | ||||
-rw-r--r-- | vmware/svga3d.h | 149 | ||||
-rw-r--r-- | vmware/svga3d_caps.h | 140 | ||||
-rw-r--r-- | vmware/svga3d_reg.h | 3189 | ||||
-rw-r--r-- | vmware/svga_all.h | 13 | ||||
-rw-r--r-- | vmware/svga_escape.h | 89 | ||||
-rw-r--r-- | vmware/svga_overlay.h | 201 | ||||
-rw-r--r-- | vmware/svga_reg.h | 1610 |
14 files changed, 9119 insertions, 0 deletions
diff --git a/vmware/pci.c b/vmware/pci.c new file mode 100644 index 0000000..93647b4 --- /dev/null +++ b/vmware/pci.c @@ -0,0 +1,277 @@ +/* -*- Mode: C; c-basic-offset: 3 -*-
+ *
+ * pci.c - Simple PCI configuration interface. This implementation
+ * only supports type 1 accesses to configuration space,
+ * and it ignores the PCI BIOS.
+ *
+ * This file is part of Metalkit, a simple collection of modules for
+ * writing software that runs on the bare metal. Get the latest code
+ * at http://svn.navi.cx/misc/trunk/metalkit/
+ *
+ * Copyright (c) 2008-2009 Micah Dowty
+ *
+ * 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 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 <stdlib.h>
+#include "svga_all.h"
+
+#ifdef VXD32
+#define IO_IN32
+#define IO_OUT32
+#define IO_OUT16
+#define IO_IN16
+#define IO_IN8
+#include "io32.h"
+#else
+#include "io.h"
+#endif
+
+/*
+ * There can be up to 256 PCI busses, but it takes a noticeable
+ * amount of time to scan that whole space. Limit the number of
+ * supported busses to something more reasonable...
+ */
+#define PCI_MAX_BUSSES 0x20
+
+#define PCI_REG_CONFIG_ADDRESS 0xCF8
+#define PCI_REG_CONFIG_DATA 0xCFC
+
+#ifndef VXD32
+#pragma code_seg( _INIT )
+#else
+#include "code32.h"
+#endif
+
+/*
+ * PCIConfigPackAddress --
+ *
+ * Pack a 32-bit CONFIG_ADDRESS value.
+ */
+
+static uint32
+PCIConfigPackAddress(const PCIAddress __far *addr, uint16 offset)
+{
+ const uint32 enableBit = 0x80000000UL;
+
+ return (((uint32)addr->bus << 16) |
+ ((uint32)addr->device << 11) |
+ ((uint32)addr->function << 8) |
+ offset | enableBit);
+}
+
+
+/*
+ * PCI_ConfigRead32 --
+ * PCI_ConfigRead16 --
+ * PCI_ConfigRead8 --
+ * PCI_ConfigWrite32 --
+ * PCI_ConfigWrite16 --
+ * PCI_ConfigWrite8 --
+ *
+ * Access a device's PCI configuration space, using configuration
+ * mechanism #1. All new machines should use method #1, method #2
+ * is for legacy compatibility.
+ *
+ * See http://www.osdev.org/wiki/PCI
+ */
+
+uint32
+PCI_ConfigRead32(const PCIAddress __far *addr, uint16 offset)
+{
+ outpd(PCI_REG_CONFIG_ADDRESS, PCIConfigPackAddress(addr, offset));
+ return inpd(PCI_REG_CONFIG_DATA);
+}
+
+uint16
+PCI_ConfigRead16(const PCIAddress __far *addr, uint16 offset)
+{
+ outpd(PCI_REG_CONFIG_ADDRESS, PCIConfigPackAddress(addr, offset));
+ return inpw(PCI_REG_CONFIG_DATA);
+}
+
+uint8
+PCI_ConfigRead8(const PCIAddress __far *addr, uint16 offset)
+{
+ outpd(PCI_REG_CONFIG_ADDRESS, PCIConfigPackAddress(addr, offset));
+ return inp(PCI_REG_CONFIG_DATA);
+}
+
+void
+PCI_ConfigWrite32(const PCIAddress __far *addr, uint16 offset, uint32 data)
+{
+ outpd(PCI_REG_CONFIG_ADDRESS, PCIConfigPackAddress(addr, offset));
+ outpd(PCI_REG_CONFIG_DATA, data);
+}
+
+void
+PCI_ConfigWrite16(const PCIAddress __far *addr, uint16 offset, uint16 data)
+{
+ outpd(PCI_REG_CONFIG_ADDRESS, PCIConfigPackAddress(addr, offset));
+ outpw(PCI_REG_CONFIG_DATA, data);
+}
+
+void
+PCI_ConfigWrite8(const PCIAddress __far *addr, uint16 offset, uint8 data)
+{
+ outpd(PCI_REG_CONFIG_ADDRESS, PCIConfigPackAddress(addr, offset));
+ outpd(PCI_REG_CONFIG_DATA, data);
+}
+
+
+/*
+ * PCI_ScanBus --
+ *
+ * Scan the PCI bus for devices. Before starting a scan,
+ * the caller should zero the PCIScanState structure.
+ * Every time this function is called, it returns the next
+ * device in sequence.
+ *
+ * Returns TRUE if a device was found, leaving that device's
+ * vendorId, productId, and address in 'state'.
+ *
+ * Returns FALSE if there are no more devices.
+ */
+
+Bool
+PCI_ScanBus(PCIScanState __far *state)
+{
+ PCIConfigSpace config;
+
+ for (;;) {
+ config.words[0] = PCI_ConfigRead32(&state->nextAddr, 0);
+
+ state->addr = state->nextAddr;
+
+ if (++state->nextAddr.function == 0x8) {
+ state->nextAddr.function = 0;
+ if (++state->nextAddr.device == 0x20) {
+ state->nextAddr.device = 0;
+ if (++state->nextAddr.bus == PCI_MAX_BUSSES) {
+ return FALSE;
+ }
+ }
+ }
+
+ if (config.words[0] != 0xFFFFFFFFUL) {
+ state->vendorId = config.vendorId;
+ state->deviceId = config.deviceId;
+ return TRUE;
+ }
+ }
+}
+
+
+/*
+ * PCI_FindDevice --
+ *
+ * Scan the PCI bus for a device with a specific vendor and device ID.
+ *
+ * On success, returns TRUE and puts the device address into 'addrOut'.
+ * If the device was not found, returns FALSE.
+ */
+
+Bool
+PCI_FindDevice(uint16 vendorId, uint16 deviceId, PCIAddress __far *addrOut)
+{
+ PCIScanState busScan = {0};
+
+ while (PCI_ScanBus(&busScan)) {
+ if (busScan.vendorId == vendorId && busScan.deviceId == deviceId) {
+ *addrOut = busScan.addr;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * PCI_SetBAR --
+ *
+ * Set one of a device's Base Address Registers to the provided value.
+ */
+
+void
+PCI_SetBAR(const PCIAddress __far *addr, int index, uint32 value)
+{
+ // PCI_ConfigWrite32(addr, offsetof(PCIConfigSpace, BAR[index]), value);
+ PCI_ConfigWrite32(addr, 16+4*index, value);
+}
+
+
+/*
+ * PCI_GetBARAddr --
+ *
+ * Get the current address set in one of the device's Base Address Registers.
+ * We mask off the lower bits that are not part of the address. IO bars are
+ * 4 byte aligned so we mask lower 2 bits, and memory bars are 16-byte aligned
+ * so we mask the lower 4 bits.
+ */
+
+uint32
+PCI_GetBARAddr(const PCIAddress __far *addr, int index)
+{
+ // uint32 bar = PCI_ConfigRead32(addr, offsetof(PCIConfigSpace, BAR[index]));
+ uint32 bar = PCI_ConfigRead32(addr, 16+4*index);
+ uint32 mask = (bar & PCI_CONF_BAR_IO) ? 0x3 : 0xf;
+
+ return bar & ~mask;
+}
+
+uint32
+PCI_GetSubsystem(const PCIAddress __far *addr)
+{
+ uint32 subsys = PCI_ConfigRead32(addr, 44);
+
+ return subsys;
+}
+
+
+/*
+ * PCI_SetMemEnable --
+ *
+ * Enable or disable a device's memory and IO space. This must be
+ * called to enable a device's resources after setting all
+ * applicable BARs. Also enables/disables bus mastering.
+ */
+
+void
+PCI_SetMemEnable(const PCIAddress __far *addr, Bool enable)
+{
+ //uint16 command = PCI_ConfigRead16(addr, offsetof(PCIConfigSpace, command));
+ uint16 command = PCI_ConfigRead16(addr, 4);
+
+ /* Mem space enable, IO space enable, bus mastering. */
+ const uint16 flags = 0x0007;
+
+ if (enable) {
+ command |= flags;
+ } else {
+ command &= ~flags;
+ }
+
+ //PCI_ConfigWrite16(addr, offsetof(PCIConfigSpace, command), command);
+ PCI_ConfigWrite16(addr, 4, command);
+
+}
+
diff --git a/vmware/pci.h b/vmware/pci.h new file mode 100644 index 0000000..080fc86 --- /dev/null +++ b/vmware/pci.h @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset: 3 -*-
+ *
+ * pci.h - Simple PCI configuration interface. This implementation
+ * only supports type 1 accesses to configuration space,
+ * and it ignores the PCI BIOS.
+ *
+ * This file is part of Metalkit, a simple collection of modules for
+ * writing software that runs on the bare metal. Get the latest code
+ * at http://svn.navi.cx/misc/trunk/metalkit/
+ *
+ * Copyright (c) 2008-2009 Micah Dowty
+ *
+ * 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 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.
+ */
+
+#ifndef __PCI_H__
+#define __PCI_H__
+
+#include "types16.h"
+
+#pragma pack(push)
+#pragma pack(1)
+typedef union PCIConfigSpace {
+ uint32 words[16];
+ struct { // offset
+ uint16 vendorId; // 0
+ uint16 deviceId; // 2
+ uint16 command; // 4
+ uint16 status; // 6
+ uint16 revisionId; // 8
+ uint8 subclass; // 10
+ uint8 classCode; // 11
+ uint8 cacheLineSize; // 12
+ uint8 latTimer; // 13
+ uint8 headerType; // 14
+ uint8 BIST; // 15
+ uint32 BAR[6]; // 16
+ uint32 cardbusCIS; // 40
+ uint16 subsysVendorId; // 44
+ uint16 subsysId; // 46
+ uint32 expansionRomAddr; // 48
+ uint32 reserved0; // 52
+ uint32 reserved1; // 56
+ uint8 intrLine; // 60
+ uint8 intrPin; // 61
+ uint8 minGrant; // 62
+ uint8 maxLatency; // 63
+ };
+} PCIConfigSpace;
+#pragma pack(pop)
+
+typedef struct PCIAddress {
+ uint8 bus, device, function, padding;
+} PCIAddress;
+
+typedef struct PCIScanState {
+ uint16 vendorId;
+ uint16 deviceId;
+ PCIAddress nextAddr;
+ PCIAddress addr;
+} PCIScanState;
+
+// BAR bits
+#define PCI_CONF_BAR_IO 0x01
+#define PCI_CONF_BAR_64BIT 0x04
+#define PCI_CONF_BAR_PREFETCH 0x08
+
+uint32 PCI_ConfigRead32(const PCIAddress __far *addr, uint16 offset);
+uint16 PCI_ConfigRead16(const PCIAddress __far *addr, uint16 offset);
+uint8 PCI_ConfigRead8(const PCIAddress __far *addr, uint16 offset);
+void PCI_ConfigWrite32(const PCIAddress __far *addr, uint16 offset, uint32 data);
+void PCI_ConfigWrite16(const PCIAddress __far *addr, uint16 offset, uint16 data);
+void PCI_ConfigWrite8(const PCIAddress __far *addr, uint16 offset, uint8 data);
+
+Bool PCI_ScanBus(PCIScanState __far *state);
+Bool PCI_FindDevice(uint16 vendorId, uint16 deviceId, PCIAddress __far *addrOut);
+void PCI_SetBAR(const PCIAddress __far *addr, int index, uint32 value);
+uint32 PCI_GetBARAddr(const PCIAddress __far *addr, int index);
+void PCI_SetMemEnable(const PCIAddress __far *addr, Bool enable);
+uint32 PCI_GetSubsystem(const PCIAddress __far *addr);
+
+#endif /* __PCI_H__ */
diff --git a/vmware/pci32.c b/vmware/pci32.c new file mode 100644 index 0000000..cd00f19 --- /dev/null +++ b/vmware/pci32.c @@ -0,0 +1,2 @@ +#define VXD32
+#include "pci.c"
diff --git a/vmware/svga.c b/vmware/svga.c new file mode 100644 index 0000000..76d69fb --- /dev/null +++ b/vmware/svga.c @@ -0,0 +1,1971 @@ +/********************************************************** + * Copyright 2008-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga.c -- + * + * This is a simple example driver for the VMware SVGA device. + * It handles initialization, register accesses, low-level + * command FIFO writes, and host/guest synchronization. + */ + +//#include <string.h> /* include some basics like NULL */ +#include "winhack.h" + +#include "svga_all.h" +#include "pci.h" + +#ifdef VXD32 +#define IO_IN32 +#define IO_OUT32 +#include "io32.h" +#else +#include "io.h" +#endif + +#include "drvlib.h" + +#ifndef VXD32 +#include "dpmi.h" +#endif + +#ifdef DBGPRINT +void dbg_printf( const char *s, ... ); +#else +#define dbg_printf(...) +#endif + +#ifndef MIN +#define MIN(a, b) (((a) > (b)) ? (b) : (a)) +#endif + +#ifndef MAX +#define MAX(a, b) (((b) > (a)) ? (b) : (a)) +#endif + +#ifdef VXD32 +#include "code32.h" +#endif + + +SVGADevice gSVGA; + +static void SVGAFIFOFull(void); + +#ifndef REALLY_TINY +static void SVGAInterruptHandler(int vector); +#endif + +#ifdef REALLY_TINY +# ifdef VXD32 +# define Console_Panic(x) +# define SVGA_Panic(x) +# else +# define Console_Panic(x) dbg_printf("PANIC: %s\n", x) +# define SVGA_Panic(x) dbg_printf("PANIC: %s\n", x) +# endif +#endif + +#ifndef VXD32 +#pragma code_seg( _INIT ) +#endif + +/* + *----------------------------------------------------------------------------- + * + * SVGA_Init -- + * + * Initialize the global SVGA device. This locates it on the PCI bus, + * negotiates device version, and maps the command FIFO and framebuffer + * memory. + * + * Intr_Init() must have already been called. If the SVGA device + * supports interrupts, this will initalize them. + * + * Does not switch video modes. + * + * Results: + * void. + * + * Side effects: + * Steals various IOspace and memory regions. + * In this example code they're constant addresses, but in reality + * you'll need to negotiate these with the operating system. + * + *----------------------------------------------------------------------------- + */ + +int +SVGA_Init(Bool enableFIFO) +{ + int vga_found = 0; + + if (PCI_FindDevice(PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_SVGA2, + &gSVGA.pciAddr)) { + gSVGA.vendorId = PCI_VENDOR_ID_VMWARE; + gSVGA.deviceId = PCI_DEVICE_ID_VMWARE_SVGA2; +#ifndef VXD32 + dbg_printf("PCI VMWare SVGA-II: %X:%X\n", gSVGA.vendorId, gSVGA.deviceId); +#endif + + vga_found = 1; + } + + if (PCI_FindDevice(PCI_VENDOR_ID_INNOTEK, PCI_DEVICE_ID_VBOX_VGA, &gSVGA.pciAddr)) { + uint32 subsys = PCI_GetSubsystem(&gSVGA.pciAddr); + if(subsys == PCI_SUBCLASS_ID_SVGA2) + { + gSVGA.vendorId = PCI_VENDOR_ID_INNOTEK; + gSVGA.deviceId = PCI_DEVICE_ID_VBOX_VGA; +#ifndef VXD32 + dbg_printf("PCI VBox SVGA: %X:%X\n", gSVGA.vendorId, gSVGA.deviceId); +#endif + vga_found = 1; + } + else + { +#ifndef VXD32 + dbg_printf("PCI VBox VGA, subclass %lX = this driver is not for it!\n", subsys); +#endif + } + } + + if(vga_found == 0) + { + Console_Panic("No VMware SVGA device found."); + return 1; + } + + /* + * Use the default base address for each memory region. + * We must map at least ioBase before using ReadReg/WriteReg. + */ + + PCI_SetMemEnable(&gSVGA.pciAddr, TRUE); + if(gSVGA.deviceId == PCI_DEVICE_ID_VBOX_VGA) { + /* VBox SVGA have swapped IO and VRAM in PCI BAR */ + gSVGA.fbMem = (void __far*) PCI_GetBARAddr(&gSVGA.pciAddr, 0); + gSVGA.ioBase = PCI_GetBARAddr(&gSVGA.pciAddr, 1); + } else { + gSVGA.ioBase = PCI_GetBARAddr(&gSVGA.pciAddr, 0); + gSVGA.fbMem = (void __far*) PCI_GetBARAddr(&gSVGA.pciAddr, 1); + } + gSVGA.fifoMem = (void __far*) PCI_GetBARAddr(&gSVGA.pciAddr, 2); + +#ifndef VXD32 /* version negotiation is done in PM16 driver, only get addresses here */ + /* + * Version negotiation: + * + * 1. Write to SVGA_REG_ID the maximum ID supported by this driver. + * 2. Read from SVGA_REG_ID + * a. If we read back the same value, this ID is supported. We're done. + * b. If not, decrement the ID and repeat. + */ + + gSVGA.deviceVersionId = SVGA_ID_2; + do { + SVGA_WriteReg(SVGA_REG_ID, gSVGA.deviceVersionId); + if (SVGA_ReadReg(SVGA_REG_ID) == gSVGA.deviceVersionId) { + break; + } else { + gSVGA.deviceVersionId--; + } + } while (gSVGA.deviceVersionId >= SVGA_ID_0); + + if (gSVGA.deviceVersionId < SVGA_ID_0) { + Console_Panic("Error negotiating SVGA device version."); + } +#endif + + /* + * We must determine the FIFO and FB size after version + * negotiation, since the default version (SVGA_ID_0) + * does not support the FIFO buffer at all. + */ + + gSVGA.vramSize = SVGA_ReadReg(SVGA_REG_VRAM_SIZE); + gSVGA.fbSize = SVGA_ReadReg(SVGA_REG_FB_SIZE); + gSVGA.fifoSize = SVGA_ReadReg(SVGA_REG_MEM_SIZE); + + /* + * Sanity-check the FIFO and framebuffer sizes. + * These are arbitrary values. + */ + + if (gSVGA.fbSize < 0x100000) { + SVGA_Panic("FB size very small, probably incorrect."); + } + if (gSVGA.fifoSize < 0x20000) { + SVGA_Panic("FIFO size very small, probably incorrect."); + } + + /* + * If the device is new enough to support capability flags, get the + * capabilities register. + */ + + if (gSVGA.deviceVersionId >= SVGA_ID_1) { + gSVGA.capabilities = SVGA_ReadReg(SVGA_REG_CAPABILITIES); + } + + /* + * Optional interrupt initialization. + * + * This uses the default IRQ that was assigned to our + * device by the BIOS. + */ + +#ifndef REALLY_TINY + if (gSVGA.capabilities & SVGA_CAP_IRQMASK) { + uint8 irq = PCI_ConfigRead8(&gSVGA.pciAddr, offsetof(PCIConfigSpace, intrLine)); + + /* Start out with all SVGA IRQs masked */ + SVGA_WriteReg(SVGA_REG_IRQMASK, 0); + + /* Clear all pending IRQs stored by the device */ + IO_Out32(gSVGA.ioBase + SVGA_IRQSTATUS_PORT, 0xFF); + + /* Clear all pending IRQs stored by us */ + SVGA_ClearIRQ(); + + /* Enable the IRQ */ + Intr_SetHandler(IRQ_VECTOR(irq), SVGAInterruptHandler); + Intr_SetMask(irq, TRUE); + } +#endif + gSVGA.fifoLinear = 0; + gSVGA.fifoSel = 0; + gSVGA.fifoAct = 0; + + if(enableFIFO) + { + SVGA_Enable(); + } + + return 0; +} + +/* + *----------------------------------------------------------------------------- + * + * SVGA_Enable -- + * + * Enable the SVGA device along with the SVGA FIFO. + * + * Results: + * void. + * + * Side effects: + * Initializes the command FIFO. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_Enable(void) +{ + /* + * Initialize the command FIFO. The beginning of FIFO memory is + * used for an additional set of registers, the "FIFO registers". + * These are higher-performance memory mapped registers which + * happen to live in the same space as the FIFO. The driver is + * responsible for allocating space for these registers, according + * to the maximum number of registers supported by this driver + * release. + */ + + gSVGA.fifoMem[SVGA_FIFO_MIN] = SVGA_FIFO_NUM_REGS * sizeof(uint32); + gSVGA.fifoMem[SVGA_FIFO_MAX] = gSVGA.fifoSize; + //gSVGA.fifoMem[SVGA_FIFO_MAX] = 0xFFFCUL - gSVGA.fifoMem[SVGA_FIFO_MIN]; + gSVGA.fifoMem[SVGA_FIFO_NEXT_CMD] = gSVGA.fifoMem[SVGA_FIFO_MIN]; + gSVGA.fifoMem[SVGA_FIFO_STOP] = gSVGA.fifoMem[SVGA_FIFO_MIN]; + + /* + * Prep work for 3D version negotiation. See SVGA3D_Init for + * details, but we have to give the host our 3D protocol version + * before enabling the FIFO. + */ + + if (SVGA_HasFIFOCap(SVGA_CAP_EXTENDED_FIFO) && + SVGA_IsFIFORegValid(SVGA_FIFO_GUEST_3D_HWVERSION)) { + + gSVGA.fifoMem[SVGA_FIFO_GUEST_3D_HWVERSION] = SVGA3D_HWVERSION_CURRENT; + } + + /* + * Enable the SVGA device and FIFO. + */ + + SVGA_WriteReg(SVGA_REG_ENABLE, TRUE); + SVGA_WriteReg(SVGA_REG_CONFIG_DONE, TRUE); + + /* + * Now that the FIFO is initialized, we can do an IRQ sanity check. + * This makes sure that the VM's chipset and our own IRQ code + * works. Better to find out now if something's wrong, than to + * deadlock later. + * + * This inserts a FIFO fence, does a legacy sync to drain the FIFO, + * then ensures that we received all applicable interrupts. + */ + +#ifndef REALLY_TINY + if (gSVGA.capabilities & SVGA_CAP_IRQMASK) { + + SVGA_WriteReg(SVGA_REG_IRQMASK, SVGA_IRQFLAG_ANY_FENCE); + SVGA_ClearIRQ(); + + SVGA_InsertFence(); + + SVGA_WriteReg(SVGA_REG_SYNC, 1); + while (SVGA_ReadReg(SVGA_REG_BUSY) != FALSE); + + SVGA_WriteReg(SVGA_REG_IRQMASK, 0); + + /* Check whether the interrupt occurred without blocking. */ + if ((gSVGA.irq.pending & SVGA_IRQFLAG_ANY_FENCE) == 0) { + SVGA_Panic("SVGA IRQ appears to be present but broken."); + } + + SVGA_WaitForIRQ(); + } +#endif +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_Disable -- + * + * Disable the SVGA portion of the video adapter, switching back + * to VGA mode. + * + * Results: + * void. + * + * Side effects: + * Switches modes. Disables the command FIFO, without flushing it. + * (Any commands still in the FIFO will be lost.) + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_Disable(void) +{ + SVGA_WriteReg(SVGA_REG_ENABLE, FALSE); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_SetMode -- + * + * This switches the SVGA video mode and enables SVGA device. + * + * Results: + * void. + * + * Side effects: + * Transitions to SVGA mode if SVGA device currently disabled. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_SetMode(uint32 width, // IN + uint32 height, // IN + uint32 bpp) // IN +{ + gSVGA.width = width; + gSVGA.height = height; + gSVGA.bpp = bpp; + + SVGA_WriteReg(SVGA_REG_WIDTH, width); + SVGA_WriteReg(SVGA_REG_HEIGHT, height); + SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, bpp); + SVGA_ReadReg(SVGA_REG_FB_OFFSET); + SVGA_WriteReg(SVGA_REG_ENABLE, TRUE); + gSVGA.pitch = SVGA_ReadReg(SVGA_REG_BYTES_PER_LINE); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_Panic -- + * + * This is a Panic handler which works in SVGA mode. It disables SVGA, + * then executes the Console's panic handler. + * + * Results: + * Never returns. + * + * Side effects: + * Disables SVGA mode, initializes VGA text mode. + * + *----------------------------------------------------------------------------- + */ + +#ifndef REALLY_TINY +void +SVGA_Panic(const char *msg) // IN +{ + SVGA_Disable(); + ConsoleVGA_Init(); + Console_Panic(msg); +} +#endif + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_DefaultFaultHandler -- + * + * This is a default fault handler which works in SVGA mode. It + * disables SVGA, then executes the Console's default fault + * handler. + * + * Results: + * Never returns. + * + * Side effects: + * Disables SVGA mode, initializes VGA text mode. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_DefaultFaultHandler(int vector) // IN +{ +#ifndef REALLY_TINY + SVGA_Disable(); + Console_UnhandledFault(vector); +#endif +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_ReadReg -- + * + * Read an SVGA device register (SVGA_REG_*). + * This must be called after the PCI device's IOspace has been mapped. + * + * Results: + * 32-bit register value. + * + * Side effects: + * Depends on the register value. Some special registers + * like SVGA_REG_BUSY have significant side-effects. + * + *----------------------------------------------------------------------------- + */ + +uint32 +SVGA_ReadReg(uint32 index) // IN +{ + outpd(gSVGA.ioBase + SVGA_INDEX_PORT, index); + return inpd(gSVGA.ioBase + SVGA_VALUE_PORT); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_WriteReg -- + * + * Write an SVGA device register (SVGA_REG_*). + * This must be called after the PCI device's IOspace has been mapped. + * + * Results: + * void. + * + * Side effects: + * Depends on the register value. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_WriteReg(uint32 index, // IN + uint32 value) // IN +{ + outpd(gSVGA.ioBase + SVGA_INDEX_PORT, index); + outpd(gSVGA.ioBase + SVGA_VALUE_PORT, value); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_IsFIFORegValid -- + * + * Check whether space has been allocated for a particular FIFO register. + * + * This isn't particularly useful for our simple examples, since the + * same binary is responsible for both allocating and using the FIFO, + * but a real driver may need to check this if the module which handles + * initialization and mode switches is separate from the module which + * actually writes to the FIFO. + * + * Results: + * TRUE if the register has been allocated, FALSE if the register + * does not exist. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Bool +SVGA_IsFIFORegValid(int reg) +{ + return gSVGA.fifoMem[SVGA_FIFO_MIN] > (reg << 2); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_HasFIFOCap -- + * + * Check whether the SVGA device has a particular FIFO capability bit. + * + * Results: + * TRUE if the capability is present, FALSE if it's absent. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Bool +SVGA_HasFIFOCap(unsigned long cap) +{ + return (gSVGA.fifoMem[SVGA_FIFO_CAPABILITIES] & cap) != 0; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_FIFOReserve -- + * + * Begin writing a command to the FIFO buffer. There are several + * examples floating around which show how to write to the FIFO + * buffer, but this is the preferred method: write directly to + * FIFO memory in the common case, but if the command would not + * be contiguous, use a bounce buffer. + * + * This method is easy to use, and quite fast. The X.org driver + * does not yet use this method, but recent Windows drivers use + * it. + * + * The main principles here are: + * + * - There are multiple code paths. In the best case, we write + * directly to the FIFO. In the next-best case, we use a + * static bounce buffer. If you need to support arbitrarily + * large commands, you can have a worst case in which you use + * a dynamically sized bounce buffer. + * + * - We must tell the host that we're reserving FIFO + * space. This is important because the device doesn't + * guarantee it will preserve the contents of FIFO memory + * which hasn't been reserved. If we write to a totally + * unused portion of the FIFO and the VM is suspended, on + * resume that data will no longer exist. + * + * This function is not re-entrant. If your driver is + * multithreaded or may be used from multiple processes + * concurrently, you must make sure to serialize all FIFO + * commands. + * + * The caller must pair this command with SVGA_FIFOCommit or + * SVGA_FIFOCommitAll. + * + * Results: + * Returns a pointer to the location where the FIFO command can + * be written. There will be room for at least 'bytes' bytes of + * data. + * + * Side effects: + * Begins a FIFO command, reserves space in the FIFO. + * May block (in SVGAFIFOFull) if the FIFO is full. + * + *----------------------------------------------------------------------------- + */ + +void __far * +SVGA_FIFOReserve(uint32 bytes) // IN +{ + volatile uint32 __far *fifo = gSVGA.fifoMem; + uint32 max = fifo[SVGA_FIFO_MAX]; + uint32 min = fifo[SVGA_FIFO_MIN]; +#if 0 + uint32 nextCmd = fifo[SVGA_FIFO_NEXT_CMD]; + Bool reserveable = SVGA_HasFIFOCap(SVGA_FIFO_CAP_RESERVE); +#endif + + /* + * This example implementation uses only a statically allocated + * buffer. If you want to support arbitrarily large commands, + * dynamically allocate a buffer if and only if it's necessary. + */ + + if (bytes > sizeof gSVGA.fifo.bounceBuffer || + bytes > (max - min)) { + SVGA_Panic("FIFO command too large"); + } + + if (bytes % sizeof(uint32)) { + SVGA_Panic("FIFO command length not 32-bit aligned"); + } + + if (gSVGA.fifo.reservedSize != 0) { + SVGA_Panic("FIFOReserve before FIFOCommit"); + } + + gSVGA.fifo.reservedSize = bytes; + +#if 0 + while (1) { + uint32 stop = fifo[SVGA_FIFO_STOP]; + Bool reserveInPlace = FALSE; + Bool needBounce = FALSE; + + /* + * Find a strategy for dealing with "bytes" of data: + * - reserve in place, if there's room and the FIFO supports it + * - reserve in bounce buffer, if there's room in FIFO but not + * contiguous or FIFO can't safely handle reservations + * - otherwise, sync the FIFO and try again. + */ + + if (nextCmd >= stop) { + /* There is no valid FIFO data between nextCmd and max */ + + if (nextCmd + bytes < max || + (nextCmd + bytes == max && stop > min)) { + /* + * Fastest path 1: There is already enough contiguous space + * between nextCmd and max (the end of the buffer). + * + * Note the edge case: If the "<" path succeeds, we can + * quickly return without performing any other tests. If + * we end up on the "==" path, we're writing exactly up to + * the top of the FIFO and we still need to make sure that + * there is at least one unused DWORD at the bottom, in + * order to be sure we don't fill the FIFO entirely. + * + * If the "==" test succeeds, but stop <= min (the FIFO + * would be completely full if we were to reserve this + * much space) we'll end up hitting the FIFOFull path below. + */ + reserveInPlace = TRUE; + } else if ((max - nextCmd) + (stop - min) <= bytes) { + /* + * We have to split the FIFO command into two pieces, + * but there still isn't enough total free space in + * the FIFO to store it. + * + * Note the "<=". We need to keep at least one DWORD + * of the FIFO free at all times, or we won't be able + * to tell the difference between full and empty. + */ + SVGAFIFOFull(); + } else { + /* + * Data fits in FIFO but only if we split it. + * Need to bounce to guarantee contiguous buffer. + */ + needBounce = TRUE; + } + + } else { + /* There is FIFO data between nextCmd and max */ + + if (nextCmd + bytes < stop) { + /* + * Fastest path 2: There is already enough contiguous space + * between nextCmd and stop. + */ + reserveInPlace = TRUE; + } else { + /* + * There isn't enough room between nextCmd and stop. + * The FIFO is too full to accept this command. + */ + SVGAFIFOFull(); + } + } + + /* + * If we decided we can write directly to the FIFO, make sure + * the VMX can safely support this. + */ + if (reserveInPlace) { + if (reserveable || bytes <= sizeof(uint32)) { + gSVGA.fifo.usingBounceBuffer = FALSE; + if (reserveable) { + fifo[SVGA_FIFO_RESERVED] = bytes; + } + return nextCmd + (uint8 __far*) fifo; + } else { + /* + * Need to bounce because we can't trust the VMX to safely + * handle uncommitted data in FIFO. + */ + needBounce = TRUE; + } + } + + /* + * If we reach here, either we found a full FIFO, called + * SVGAFIFOFull to make more room, and want to try again, or we + * decided to use a bounce buffer instead. + */ + if (needBounce) { + gSVGA.fifo.usingBounceBuffer = TRUE; + return (void __far *)(&gSVGA.fifo.bounceBuffer[0]); + } + } /* while (1) */ +#else + gSVGA.fifo.usingBounceBuffer = TRUE; + return (void __far *)(&gSVGA.fifo.bounceBuffer[0]); +#endif +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_FIFOCommit -- + * + * Commit a block of FIFO data which was placed in the buffer + * returned by SVGA_FIFOReserve. Every Reserve must be paired + * with exactly one Commit, but the sizes don't have to match. + * The caller is free to commit less space than they + * reserved. This can be used if the command size isn't known in + * advance, but it is reasonable to make a worst-case estimate. + * + * The commit size does not have to match the size of a single + * FIFO command. This can be used to write a partial command, or + * to write multiple commands at once. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + + +#ifndef VXD32 +static void WriteFifo(uint32 pos, uint32 dw) +{ + uint32 act = pos >> 16; + uint16 off = pos & 0xFFFF; + + uint32 __far *ptr; + + if(act != gSVGA.fifoAct) + { + DPMI_SetSegBase(gSVGA.fifoSel, gSVGA.fifoLinear + (act << 16)); + gSVGA.fifoAct = act; + } + + //dbg_printf("Fifo: %ld (%X:%X)\n", pos, gSVGA.fifoAct, off); + + ptr = (uint32 __far *)(gSVGA.fifoSel :> off); + + *ptr = dw; +} +#endif + +void +SVGA_FIFOCommit(uint32 bytes) // IN +{ + volatile uint32 __far *fifo = gSVGA.fifoMem; + uint32 nextCmd = fifo[SVGA_FIFO_NEXT_CMD]; + uint32 max = fifo[SVGA_FIFO_MAX]; + uint32 min = fifo[SVGA_FIFO_MIN]; + Bool reserveable = 0; //SVGA_HasFIFOCap(SVGA_FIFO_CAP_RESERVE); + + if (gSVGA.fifo.reservedSize == 0) { + SVGA_Panic("FIFOCommit before FIFOReserve"); + } + gSVGA.fifo.reservedSize = 0; + + if (gSVGA.fifo.usingBounceBuffer) { + /* + * Slow paths: copy out of a bounce buffer. + */ + uint8 __far *buffer = gSVGA.fifo.bounceBuffer; + + if (reserveable) { + /* + * Slow path: bulk copy out of a bounce buffer in two chunks. + * + * Note that the second chunk may be zero-length if the reserved + * size was large enough to wrap around but the commit size was + * small enough that everything fit contiguously into the FIFO. + * + * Note also that we didn't need to tell the FIFO about the + * reservation in the bounce buffer, but we do need to tell it + * about the data we're bouncing from there into the FIFO. + */ + + uint32 chunkSize = MIN(bytes, max - nextCmd); + fifo[SVGA_FIFO_RESERVED] = bytes; + drv_memcpy(nextCmd + (uint8 __far*) fifo, buffer, chunkSize); + drv_memcpy(min + (uint8 __far*) fifo, buffer + chunkSize, bytes - chunkSize); + + } else { + /* + * Slowest path: copy one dword at a time, updating NEXT_CMD as + * we go, so that we bound how much data the guest has written + * and the host doesn't know to checkpoint. + */ + + uint32 *dword = (uint32 *)buffer; + + while (bytes > 0) { + //fifo[nextCmd / sizeof(uint32)] = *dword++; + +#ifndef VXD32 + WriteFifo(nextCmd, *dword); +#else + fifo[nextCmd / sizeof(uint32)] = *dword; +#endif + dword++; + + nextCmd += sizeof(uint32); + if (nextCmd >= max) { + nextCmd = min; + } + fifo[SVGA_FIFO_NEXT_CMD] = nextCmd; + bytes -= sizeof *dword; + } + } + } + + /* + * Atomically update NEXT_CMD, if we didn't already + */ + if (!gSVGA.fifo.usingBounceBuffer || reserveable) { + nextCmd += bytes; + if (nextCmd >= max) { + nextCmd -= max - min; + } + fifo[SVGA_FIFO_NEXT_CMD] = nextCmd; + } + + /* + * Clear the reservation in the FIFO. + */ + if (reserveable) { + fifo[SVGA_FIFO_RESERVED] = 0; + } +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_FIFOCommitAll -- + * + * This is a convenience wrapper for SVGA_FIFOCommit(), which + * always commits the last reserved block in its entirety. + * + * Results: + * None. + * + * Side effects: + * SVGA_FIFOCommit. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_FIFOCommitAll(void) +{ + SVGA_FIFOCommit(gSVGA.fifo.reservedSize); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_FIFOReserveCmd -- + * + * This is a convenience wrapper around SVGA_FIFOReserve, which + * prefixes the reserved memory block with a uint32 that + * indicates the command type. + * + * Results: + * Always returns a pointer to 'bytes' bytes of reserved space in the FIFO. + * + * Side effects: + * Begins a FIFO command, reserves space in the FIFO. Writes a + * 1-word header into the FIFO. May block (in SVGAFIFOFull) if + * the FIFO is full. + * + *----------------------------------------------------------------------------- + */ + +void __far * +SVGA_FIFOReserveCmd(uint32 type, // IN + uint32 bytes) // IN +{ + uint32 __far *cmd = SVGA_FIFOReserve(bytes + sizeof type); + cmd[0] = type; + return cmd + 1; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_FIFOReserveEscape -- + * + * This is a convenience wrapper around SVGA_FIFOReserve, which + * prefixes the reserved memory block with an ESCAPE command header. + * + * ESCAPE commands are a way of encoding extensible and + * variable-length packets within the basic FIFO protocol + * itself. ESCAPEs are used for some SVGA device functionality, + * like video overlays, for VMware's internal debugging tools, + * and for communicating with third party code that can load into + * the SVGA device. + * + * Results: + * Always returns a pointer to 'bytes' bytes of reserved space in the FIFO. + * + * Side effects: + * Begins a FIFO command, reserves space in the FIFO. Writes a + * 3-word header into the FIFO. May block (in SVGAFIFOFull) if + * the FIFO is full. + * + *----------------------------------------------------------------------------- + */ + +void __far * +SVGA_FIFOReserveEscape(uint32 nsid, // IN + uint32 bytes) // IN +{ + uint32 paddedBytes = (bytes + 3) & ~3UL; +#pragma pack(push) +#pragma pack(1) + struct { + uint32 cmd; + uint32 nsid; + uint32 size; + } __far *header; +#pragma pack(pop) + + header = SVGA_FIFOReserve(paddedBytes + sizeof(*header)); + + header->cmd = SVGA_CMD_ESCAPE; + header->nsid = nsid; + header->size = bytes; + + return header + 1; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGAFIFOFull -- + * + * This function is called repeatedly as long as the FIFO has too + * little free space for us to continue. + * + * The simplest implementation of this function is a no-op. This + * will just burn guest CPU until space is available. (That's a + * bad idea, since the host probably needs that CPU in order to + * make progress on emptying the FIFO.) + * + * A better implementation would sleep until a FIFO progress + * interrupt occurs. Depending on the OS you're writing drivers + * for, this may deschedule the calling task or it may simply put + * the CPU to sleep. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +#if 0 +void +SVGAFIFOFull(void) +{ +#ifndef REALLY_TINY + if (SVGA_IsFIFORegValid(SVGA_FIFO_FENCE_GOAL) && + (gSVGA.capabilities & SVGA_CAP_IRQMASK)) { + + /* + * On hosts which support interrupts, we can sleep until the + * FIFO_PROGRESS interrupt occurs. This is the most efficient + * thing to do when the FIFO fills up. + * + * As with the IRQ-based SVGA_SyncToFence(), this will only work + * on Workstation 6.5 virtual machines and later. + */ + + SVGA_WriteReg(SVGA_REG_IRQMASK, SVGA_IRQFLAG_FIFO_PROGRESS); + SVGA_ClearIRQ(); + SVGA_RingDoorbell(); + SVGA_WaitForIRQ(); + SVGA_WriteReg(SVGA_REG_IRQMASK, 0); + + } else { + + /* + * Fallback implementation: Perform one iteration of the + * legacy-style sync. This synchronously processes FIFO commands + * for an arbitrary amount of time, then returns control back to + * the guest CPU. + */ + + SVGA_WriteReg(SVGA_REG_SYNC, 1); + SVGA_ReadReg(SVGA_REG_BUSY); + } +#endif +} +#endif + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_InsertFence -- + * + * Write a new fence value to the FIFO. + * + * Fences are the basis of the SVGA device's synchronization + * model. A fence is a marker inserted into the FIFO by the + * guest. The host processes all FIFO commands in order. Once the + * fence is reached, the host does two things: + * + * - The fence value is written to the SVGA_FIFO_FENCE register. + * - Optionally, an interrupt is raised. + * + * There are multiple ways to use fences for synchronization. See + * SVGA_SyncToFence and SVGA_HasFencePassed. + * + * Results: + * + * Returns the value of the fence we inserted. Fence values + * increment, wrapping around at 32 bits. Fence value zero is + * reserved to mean "no fence". This function never returns zero. + * + * Certain very old versions of the VMware SVGA device do not + * support fences. On these devices, we always return 1. On these + * devices, SyncToFence will always do a full Sync and + * SyncToFence will always return FALSE, so the actual fence + * value we use is unimportant. Code written to use fences will + * run inefficiently, but it will still be correct. + * + * Side effects: + * Writes to the FIFO. Increments our nextFence. + * + *----------------------------------------------------------------------------- + */ + +uint32 +SVGA_InsertFence(void) +{ + uint32 fence; + +#pragma pack(push) +#pragma pack(1) + struct { + uint32 id; + uint32 fence; + } __far *cmd; +#pragma pack(pop) + + if (!SVGA_HasFIFOCap(SVGA_FIFO_CAP_FENCE)) { + return 1; + } + + if (gSVGA.fifo.nextFence == 0) { + gSVGA.fifo.nextFence = 1; + } + fence = gSVGA.fifo.nextFence++; + + cmd = SVGA_FIFOReserve(sizeof *cmd); + cmd->id = SVGA_CMD_FENCE; + cmd->fence = fence; + SVGA_FIFOCommitAll(); + + return fence; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_SyncToFence -- + * + * Sleep until the SVGA device has processed all FIFO commands + * prior to the insertion point of the specified fence. + * + * This is the most important way to maintain synchronization + * between the driver and the SVGA3D device itself. It can be + * used to provide flow control between the host and the guest, + * or to ensure that DMA operations have completed before reusing + * guest memory. + * + * If the provided fence is zero or it has already passed, + * this is a no-op. + * + * If the SVGA device and virtual machine hardware version are + * both new enough (Workstation 6.5 or later), this will use an + * efficient interrupt-driven mechanism to sleep until just after + * the host processes the fence. + * + * If not, this will use a less efficient synchronization + * mechanism which may require the host to process significantly + * more of the FIFO than is necessary. + * + * Results: + * void. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_SyncToFence(uint32 fence) // IN +{ + if (!fence) { + return; + } + + if (!SVGA_HasFIFOCap(SVGA_FIFO_CAP_FENCE)) { + /* + * Fall back on the legacy sync if the host does not support + * fences. This is the old sync mechanism that has been + * supported in the SVGA device pretty much since the dawn of + * time: write to the SYNC register, then read from BUSY until + * it's nonzero. This will drain the entire FIFO. + * + * The parameter we write to SVGA_REG_SYNC is an arbitrary + * nonzero value which can be used for debugging, but which is + * ignored by release builds of VMware products. + */ + + SVGA_WriteReg(SVGA_REG_SYNC, 1); + while (SVGA_ReadReg(SVGA_REG_BUSY) != FALSE); + return; + } + + if (SVGA_HasFencePassed(fence)) { + /* + * Nothing to do + */ + + return; + } + +#ifndef REALLY_TINY + if (SVGA_IsFIFORegValid(SVGA_FIFO_FENCE_GOAL) && + (gSVGA.capabilities & SVGA_CAP_IRQMASK)) { + + /* + * On hosts which support interrupts and which support the + * FENCE_GOAL interrupt, we can use our preferred + * synchronization mechanism. + * + * This provides low latency notification both from guest to + * host and from host to guest, and it doesn't block the guest + * while we're waiting. + * + * This will only work on Workstation 6.5 virtual machines + * or later. Older virtual machines did not allocate an IRQ + * for the SVGA device, and the IRQMASK capability will be + * unset. + */ + + /* + * Set the fence goal. This asks the host to send an interrupt + * when this specific fence has been reached. + */ + + gSVGA.fifoMem[SVGA_FIFO_FENCE_GOAL] = fence; + SVGA_WriteReg(SVGA_REG_IRQMASK, SVGA_IRQFLAG_FENCE_GOAL); + + SVGA_ClearIRQ(); + + /* + * Must check again, in case we reached the fence between the + * first HasFencePassed and when we set up the IRQ. + * + * As a small performance optimization, we check yet again after + * RingDoorbell, since there's a chance that RingDoorbell will + * deschedule this VM and process some SVGA FIFO commands in a + * way that appears synchronous from the VM's point of view. + */ + + if (!SVGA_HasFencePassed(fence)) { + /* + * We're about to go to sleep. Make sure the host is awake. + */ + SVGA_RingDoorbell(); + + if (!SVGA_HasFencePassed(fence)) { + SVGA_WaitForIRQ(); + } + } + + SVGA_WriteReg(SVGA_REG_IRQMASK, 0); + + } else +#endif // REALLY_TINY + { + /* + * Sync-to-fence mechanism for older hosts. Wake up the host, + * and spin on BUSY until we've reached the fence. This + * processes FIFO commands synchronously, blocking the VM's + * execution entirely until it's done. + */ + + Bool busy = TRUE; + + SVGA_WriteReg(SVGA_REG_SYNC, 1); + + while (!SVGA_HasFencePassed(fence) && busy) { + busy = (SVGA_ReadReg(SVGA_REG_BUSY) != 0); + } + } + +#ifndef REALLY_TINY + if (!SVGA_HasFencePassed(fence)) { + /* + * This shouldn't happen. If it does, there might be a bug in + * the SVGA device. + */ + SVGA_Panic("SyncToFence failed!"); + } +#endif +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_HasFencePassed -- + * + * Test whether the host has processed all FIFO commands prior to + * the insertion point of the specified fence. + * + * This function tolerates fence wrap-around, but it will return + * the wrong result if 'fence' is more than 2^31 fences old. It + * is recommended that callers don't allow fence values to + * persist indefinitely. Once we notice that a fence has been + * passed, that fence variable should be set to zero so we don't + * test it in the future. + * + * Results: + * TRUE if the fence has been passed, + * TRUE if fence==0 (no fence), + * FALSE if the fence has not been passed, + * FALSE if the SVGA device does not support fences. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Bool +SVGA_HasFencePassed(uint32 fence) // IN +{ + if (!fence) { + return TRUE; + } + + if (!SVGA_HasFIFOCap(SVGA_FIFO_CAP_FENCE)) { + return FALSE; + } + + return ((int32)(gSVGA.fifoMem[SVGA_FIFO_FENCE] - fence)) >= 0; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_RingDoorbell -- + * + * FIFO fences are fundamentally a host-to-guest notification + * mechanism. This is the opposite: we can explicitly wake up + * the host when we know there is work for it to do. + * + * Background: The host processes the SVGA command FIFO in a + * separate thread which runs asynchronously with the virtual + * machine's CPU and other I/O devices. When the SVGA device is + * idle, this thread is sleeping. It periodically wakes up to + * poll for new commands. This polling must occur for various + * reasons, but it's mostly related to the historical way in + * which the SVGA device processes 2D updates. + * + * This polling introduces significant latency between when the + * first new command is placed in an empty FIFO, and when the + * host begins processing it. Normally this isn't a huge problem + * since the host and guest run fairly asynchronously, but in + * a synchronization-heavy workload this can be a bottleneck. + * + * For example, imagine an application with a worst-case + * synchronization bottleneck: The guest enqueues a single FIFO + * command, then waits for that command to finish using + * SyncToFence, then the guest spends a little time doing + * CPU-intensive processing before the cycle repeats. The + * workload may be latency-bound if the host-to-guest or + * guest-to-host notifications ever block. + * + * One solution would be for the guest to explicitly wake up the + * SVGA3D device any time a command is enqueued. This would solve + * the latency bottleneck above, but it would be inefficient on + * single-CPU host machines. One could easily imagine a situation + * in which we wake up the host after enqueueing one FIFO + * command, the physical CPU context switches to the SVGA + * device's thread, the single command is processed, then we + * context switch back to running guest code. + * + * Our recommended solution is to wake up the host only either: + * + * - After a "significant" amount of work has been enqueued into + * the FIFO. For example, at least one 3D drawing command. + * + * - After a complete frame has been rendered. + * + * - Just before the guest sleeps for any reason. + * + * This function implements the above guest wakeups. It uses the + * SVGA_FIFO_BUSY register to quickly assess whether the SVGA + * device may be idle. If so, it asynchronously wakes up the host + * by writing to SVGA_REG_SYNC. + * + * Results: + * None. + * + * Side effects: + * May wake up the SVGA3D device. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_RingDoorbell(void) +{ + if (SVGA_IsFIFORegValid(SVGA_FIFO_BUSY) && + gSVGA.fifoMem[SVGA_FIFO_BUSY] == FALSE) { + + /* Remember that we already rang the doorbell. */ + gSVGA.fifoMem[SVGA_FIFO_BUSY] = TRUE; + + /* + * Asynchronously wake up the SVGA3D device. The second + * parameter is an arbitrary nonzero 'sync reason' which can be + * used for debugging, but which isn't part of the SVGA3D + * protocol proper and which isn't used by release builds of + * VMware products. + */ + SVGA_WriteReg(SVGA_REG_SYNC, 1); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_Flush -- + * + * Force to apply all register changes. Useful if registry changes + * needs be applyed immediately + * + *----------------------------------------------------------------------------- + */ +void SVGA_Flush(void) +{ + SVGA_WriteReg(SVGA_REG_SYNC, 1); + while (SVGA_ReadReg(SVGA_REG_BUSY) != FALSE); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_ClearIRQ -- + * + * Clear all pending IRQs. Any IRQs which occurred prior to this + * function call will be ignored by the next SVGA_WaitForIRQ() + * call. + * + * Does not affect the current IRQ mask. This function is not + * useful unless the SVGA device has IRQ support. + * + * Results: + * Returns a mask of all the interrupt flags that were set prior + * to the clear. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +#ifndef REALLY_TINY +/* +uint32 +SVGA_ClearIRQ(void) +{ + uint32 flags = 0; + Atomic_Exchange(gSVGA.irq.pending, flags); + + return flags; +}*/ + +uint32 SVGA_ClearIRQ(void); +#pragma aux SVGA_ClearIRQ = \ + ".386" \ + "push eax" \ + "xor eax, eax" \ + "xchg ptr gSVGA.irq.pending, eax" \ + "mov dx, ax" \ + "shr eax, 16" \ + "xchg dx, ax" \ + "xchg bx, ax" \ + "pop eax" \ + "xchg bx, ax" \ + value [dx ax] modify [bx]; + +#endif + +/* + *----------------------------------------------------------------------------- + * + * SVGA_WaitForIRQ -- + * + * Sleep until an SVGA interrupt occurs. When we wake up, return + * a mask of all SVGA IRQs which occurred while we were asleep. + * + * The design of this function will be different for every OS, + * but it is imperative that you ensure it will work properly + * no matter when the interrupt actually occurs. The IRQ could have + * already happened (any time since the last ClearIRQ, it could + * happen while this function is running, or it could happen + * after we decide to sleep. + * + * In this example: + * + * 1. If the IRQ occurred before this function was called, + * the bit will already be set in irq.pending. We can return. + * + * 2. If the IRQ occurs while this function is executing, we + * ask our IRQ handler to do a light-weight context switch + * back to the beginning of this function, so we can + * re-examine irq.pending before sleeping. + * + * 3. If the IRQ occurs while we're sleeping, we wake up + * from the HLT instruction and re-test irq.pending. + * + * Results: + * Returns a mask of all the interrupt flags that were set prior + * to the clear. This will always be nonzero. + * + * Side effects: + * Clears the irq.pending flags for exactly the set of IRQs we return. + * + *----------------------------------------------------------------------------- + */ +#ifndef REALLY_TINY +static __attribute__ ((noinline)) uint32 +SVGAWaitForIRQInternal(void *arg, ...) +{ + uint32 flags = 0; + + /* + * switchContext must be set to TRUE before we halt, or we'll deadlock. + * This variable is marked as volatile, plus we use a compiler memory barrier. + */ + gSVGA.irq.switchContext = TRUE; + asm volatile ("" ::: "memory"); + + Atomic_Exchange(gSVGA.irq.pending, flags); + + if (!flags) { + Intr_Halt(); + } + + /* + * Must set switchContext to FALSE before this stack frame is deallocated. + */ + gSVGA.irq.switchContext = FALSE; + asm volatile ("" ::: "memory"); + + return flags; +} + +uint32 +SVGA_WaitForIRQ(void) +{ + uint32 flags; + + /* + * Store this CPU context, and tell the IRQ handler to return + * here if an IRQ occurs. We use IntrContext here just like a + * setjmp/longjmp that works in ISRs. + * + * This must be above the irq.pending check, so that we re-test + * irq.pending if an IRQ occurs after testing irq.pending but + * before we halt. Without this, we could deadlock if an IRQ + * comes in before we actually halt but after we've decided to + * halt. + */ + + Intr_SaveContext((IntrContext*) &gSVGA.irq.newContext); + + do { + /* + * XXX: The arguments here are a kludge to prevent the interrupt + * stack frame from overlapping the stack frame referenced + * by Intr_SaveContext(). + * + * Be sure to look at the generated assembly and compare the + * size of this argument list to the amount of stack space + * allocated for Intr_SaveContext. + */ + flags = SVGAWaitForIRQInternal(NULL, NULL, NULL, NULL, NULL, NULL); + + } while (flags == 0); + + return flags; +} + +#endif + +/* + *----------------------------------------------------------------------------- + * + * SVGAInterruptHandler -- + * + * This is the ISR for the SVGA device's interrupt. We ask the + * SVGA device which interrupt occurred, and clear its flag. + * + * To report this IRQ to the rest of the driver, we: + * + * 1. Atomically remember the IRQ in the irq.pending bitmask. + * + * 2. Optionally switch to a different light-weight thread + * or a different place in this thread upon returning. + * This is analogous to waking up a sleeping thread in + * a driver for a real operating system. See SVGA_WaitForIRQ + * for details. + * + * Results: + * void. + * + * Side effects: + * Sets bits in pendingIRQs. Reads and clears the device's IRQ flags. + * May switch execution contexts. + * + *----------------------------------------------------------------------------- + */ + +#ifndef REALLY_TINY +void +SVGAInterruptHandler(int vector) // IN (unused) +{ + IntrContext *context = Intr_GetContext(vector); + + /* + * The SVGA_IRQSTATUS_PORT is a separate I/O port, not a register. + * Reading from it gives us the set of IRQ flags which are + * set. Writing a '1' to any bit in this register will clear the + * corresponding flag. + * + * Here, we read then clear all flags. + */ + + uint16 port = gSVGA.ioBase + SVGA_IRQSTATUS_PORT; + uint32 irqFlags = IO_In32(port); + IO_Out32(port, irqFlags); + + gSVGA.irq.count++; + + if (!irqFlags) { + SVGA_Panic("Spurious SVGA IRQ"); + } + + Atomic_Or(gSVGA.irq.pending, irqFlags); + + if (gSVGA.irq.switchContext) { + drv_memcpy((void*) &gSVGA.irq.oldContext, context, sizeof *context); + drv_memcpy(context, (void*) &gSVGA.irq.newContext, sizeof *context); + gSVGA.irq.switchContext = FALSE; + } +} +#endif + + +/* + *---------------------------------------------------------------------- + * + * SVGA_AllocGMR -- + * + * Allocate a buffer from the framebuffer GMR for screen/DMA operations. + * Returns both a pointer (for us to use) and an SVGAGuestPtr (for the + * SVGA device to use). + * + * XXX: This is a trivial implementation which just returns + * consecutive addresses in the framebuffer. + * + * Results: + * Returns a local pointer and an SVGAGuestPtr to unused memory. + * + * Side effects: + * Allocates memory. + * + *---------------------------------------------------------------------- + */ + +void __far * +SVGA_AllocGMR(uint32 size, // IN + SVGAGuestPtr __far *ptr) // OUT +{ + static SVGAGuestPtr nextPtr = { SVGA_GMR_FRAMEBUFFER, 0 }; + *ptr = nextPtr; + nextPtr.offset += size; + return gSVGA.fbMem + ptr->offset; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_Update -- + * + * Send a 2D update rectangle through the FIFO. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_Update(uint32 x, // IN + uint32 y, // IN + uint32 width, // IN + uint32 height) // IN +{ + SVGAFifoCmdUpdate __far *cmd = SVGA_FIFOReserveCmd(SVGA_CMD_UPDATE, sizeof *cmd); + cmd->x = x; + cmd->y = y; + cmd->width = width; + cmd->height = height; + SVGA_FIFOCommitAll(); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_BeginDefineCursor -- + * + * Begin an SVGA_CMD_DEFINE_CURSOR command. This copies the command header + * into the FIFO, and reserves enough space for the cursor image itself. + * We return pointers to FIFO memory where the AND/XOR masks can be written. + * When finished, the caller must invoke SVGA_FIFOCommitAll(). + * + * Results: + * Returns pointers to memory where the caller can store the AND/XOR masks. + * + * Side effects: + * Reserves space in the FIFO. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_BeginDefineCursor(const SVGAFifoCmdDefineCursor __far *cursorInfo, // IN + void __far * __far *andMask, // OUT + void __far * __far *xorMask) // OUT +{ + uint32 andPitch = ((cursorInfo->andMaskDepth * cursorInfo->width + 31) >> 5) << 2; + uint32 andSize = andPitch * cursorInfo->height; + uint32 xorPitch = ((cursorInfo->xorMaskDepth * cursorInfo->width + 31) >> 5) << 2; + uint32 xorSize = xorPitch * cursorInfo->height; + + SVGAFifoCmdDefineCursor __far *cmd = SVGA_FIFOReserveCmd(SVGA_CMD_DEFINE_CURSOR, + sizeof *cmd + andSize + xorSize); + *cmd = *cursorInfo; + *andMask = (void*) (cmd + 1); + *xorMask = (void*) (andSize + (uint8 __far*) *andMask); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_BeginDefineAlphaCursor -- + * + * Begin an SVGA_CMD_DEFINE_ALPHA_CURSOR command. This copies the + * command header into the FIFO, and reserves enough space for + * the cursor image itself. We return a pointer to the FIFO + * memory where the caller should write a pre-multiplied BGRA + * image. When finished, the caller must invoke SVGA_FIFOCommitAll(). + * + * Results: + * Returns pointers to memory where the caller can store the image. + * + * Side effects: + * Reserves space in the FIFO. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_BeginDefineAlphaCursor(const SVGAFifoCmdDefineAlphaCursor __far *cursorInfo, // IN + void __far * __far * data) // OUT +{ + uint32 imageSize = cursorInfo->width * cursorInfo->height * sizeof(uint32); + SVGAFifoCmdDefineAlphaCursor __far *cmd = SVGA_FIFOReserveCmd(SVGA_CMD_DEFINE_ALPHA_CURSOR, + sizeof *cmd + imageSize); + *cmd = *cursorInfo; + *data = (void*) (cmd + 1); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_MoveCursor -- + * + * Change the position or visibility of the hardware cursor, using + * the Cursor Bypass 3 protocol. + * + * Results: + * None. + * + * Side effects: + * Modifies FIFO registers. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_MoveCursor(uint32 visible, // IN + uint32 x, // IN + uint32 y, // IN + uint32 screenId) // IN +{ + if (SVGA_HasFIFOCap(SVGA_FIFO_CAP_SCREEN_OBJECT)) { + gSVGA.fifoMem[SVGA_FIFO_CURSOR_SCREEN_ID] = screenId; + } + + if (SVGA_HasFIFOCap(SVGA_FIFO_CAP_CURSOR_BYPASS_3)) { + gSVGA.fifoMem[SVGA_FIFO_CURSOR_ON] = visible; + gSVGA.fifoMem[SVGA_FIFO_CURSOR_X] = x; + gSVGA.fifoMem[SVGA_FIFO_CURSOR_Y] = y; + gSVGA.fifoMem[SVGA_FIFO_CURSOR_COUNT]++; + } +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_BeginVideoSetRegs -- + * + * Begin an SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS command. This can be + * used to set an arbitrary number of video registers atomically. + * + * Results: + * Returns a pointer to the command. The caller must fill in (*setRegs)->items. + * + * Side effects: + * Reserves space in the FIFO. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_BeginVideoSetRegs(uint32 streamId, // IN + uint32 numItems, // IN + SVGAEscapeVideoSetRegs __far * __far * setRegs) // OUT +{ + SVGAEscapeVideoSetRegs __far *cmd; + uint32 cmdSize = (sizeof *cmd + - sizeof cmd->items + + numItems * sizeof cmd->items[0]); + + cmd = SVGA_FIFOReserveEscape(SVGA_ESCAPE_NSID_VMWARE, cmdSize); + cmd->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; + cmd->header.streamId = streamId; + + *setRegs = cmd; +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_VideoSetReg -- + * + * Atomically set all registers in a video overlay unit. + * + * 'maxReg' should be the highest video overlay register that the + * caller understands. We will not set any registers with IDs + * higher than maxReg. This prevents older applications compiled + * with newer headers from sending improper values to new overlay + * registers. + * + * Each video overlay unit (specified by streamId) has a collection + * of 32-bit registers which control the operation of that overlay. + * Changes to these registers take effect at the next Flush. + * + * Results: + * None. + * + * Side effects: + * Writes a FIFO command. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_VideoSetAllRegs(uint32 streamId, // IN + SVGAOverlayUnit __far *regs, // IN + uint32 maxReg) // IN +{ + uint32 __far *regArray = (uint32 __far*) regs; + const uint32 numRegs = maxReg + 1; + SVGAEscapeVideoSetRegs __far *setRegs; + uint32 i; + + SVGA_BeginVideoSetRegs(streamId, numRegs, &setRegs); + + for (i = 0; i < numRegs; i++) { + setRegs->items[i].registerId = i; + setRegs->items[i].value = regArray[i]; + } + + SVGA_FIFOCommitAll(); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_VideoSetReg -- + * + * Set a single video overlay register. + * + * Each video overlay unit (specified by streamId) has a collection + * of 32-bit registers which control the operation of that overlay. + * Changes to these registers take effect at the next Flush. + * + * Results: + * None. + * + * Side effects: + * Writes a FIFO command. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_VideoSetReg(uint32 streamId, // IN + uint32 registerId, // IN + uint32 value) // IN +{ + SVGAEscapeVideoSetRegs __far *setRegs; + + SVGA_BeginVideoSetRegs(streamId, 1, &setRegs); + setRegs->items[0].registerId = registerId; + setRegs->items[0].value = value; + SVGA_FIFOCommitAll(); +} + + +/* + *----------------------------------------------------------------------------- + * + * SVGA_VideoFlush -- + * + * Update a video overlay. On a VideoFlush, all register changes + * take effect, and the device will perform a DMA transfer to + * copy the next frame of video from guest memory. + * + * The SVGA device will generally perform a DMA transfer from + * overlay memory only during a VideoFlush. The DMA operation + * will usually be completed before the host moves to the next + * FIFO command. However, this is not guaranteed. In unusual + * conditions, the device may re-perform the DMA operation at any + * time. This means that, as long as an overlay is enabled, its + * corresponding guest memory must be valid. + * + * Results: + * None. + * + * Side effects: + * Writes a FIFO command. May cause an asynchronous DMA transfer. + * + *----------------------------------------------------------------------------- + */ + +void +SVGA_VideoFlush(uint32 streamId) // IN +{ + SVGAEscapeVideoFlush __far *cmd; + + cmd = SVGA_FIFOReserveEscape(SVGA_ESCAPE_NSID_VMWARE, sizeof *cmd); + cmd->cmdType = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH; + cmd->streamId = streamId; + SVGA_FIFOCommitAll(); +} diff --git a/vmware/svga.h b/vmware/svga.h new file mode 100644 index 0000000..6095045 --- /dev/null +++ b/vmware/svga.h @@ -0,0 +1,153 @@ +/********************************************************** + * Copyright 2008-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga.h -- + * + * This is a simple example driver for the VMware SVGA device. + * It handles initialization, register accesses, low-level + * command FIFO writes, and host/guest synchronization. + */ + +#ifndef __SVGA_H__ +#define __SVGA_H__ + +#include "types16.h" +#include "pci.h" +//#include "intr.h" + +#define REALLY_TINY + +// XXX: Shouldn't have to do this here. +//#define INLINE __inline__ +#define INLINE inline + +#include "svga_reg.h" +#include "svga_escape.h" +#include "svga_overlay.h" +#include "svga3d_reg.h" + +typedef struct SVGADevice { + PCIAddress pciAddr; // 0 + uint32 ioBase; // 4 + uint32 __far *fifoMem; // 8 + uint8 __far *fbMem; // 16 + uint32 fifoSize; // 20 + + uint32 fifoLinear; // 24 + uint16 fifoSel; // 28 + uint16 fifoAct; // 32 + + uint32 fifoPhy; + + uint32 fbSize; + uint32 fbLinear; + uint32 fbPhy; + uint32 vramSize; + + uint32 deviceVersionId; + uint32 capabilities; + + uint32 width; + uint32 height; + uint32 bpp; + uint32 pitch; + + struct { + uint32 reservedSize; + Bool usingBounceBuffer; + uint8 bounceBuffer[16 * 1024]; + uint32 nextFence; + } fifo; + + /* VMWare SVGAII and VBox SVGA is same device with different PCI ID */ + uint16 vendorId; + uint16 deviceId; + +#ifndef REALLY_TINY + volatile struct { + uint32 pending; + uint32 switchContext; + IntrContext oldContext; + IntrContext newContext; + uint32 count; + } irq; +#endif + +} SVGADevice; + +extern SVGADevice gSVGA; + +#ifndef VXD32 +int __loadds SVGA_Init(Bool enableFIFO); +#else +int SVGA_Init(Bool enableFIFO); +#endif +void SVGA_Enable(void); +void SVGA_SetMode(uint32 width, uint32 height, uint32 bpp); +void SVGA_Disable(void); +void SVGA_Panic(const char *err); +void SVGA_DefaultFaultHandler(int vector); + +void SVGA_Flush(void); + +uint32 SVGA_ReadReg(uint32 index); +void SVGA_WriteReg(uint32 index, uint32 value); +uint32 SVGA_ClearIRQ(void); +uint32 SVGA_WaitForIRQ(); + +Bool SVGA_IsFIFORegValid(int reg); +Bool SVGA_HasFIFOCap(unsigned long cap); + +void __far *SVGA_FIFOReserve(uint32 bytes); +void __far *SVGA_FIFOReserveCmd(uint32 type, uint32 bytes); +void __far *SVGA_FIFOReserveEscape(uint32 nsid, uint32 bytes); +void SVGA_FIFOCommit(uint32 bytes); +void SVGA_FIFOCommitAll(void); + +uint32 SVGA_InsertFence(void); +void SVGA_SyncToFence(uint32 fence); +Bool SVGA_HasFencePassed(uint32 fence); +void SVGA_RingDoorbell(void); + +void __far *SVGA_AllocGMR(uint32 size, SVGAGuestPtr __far *ptr); + +/* 2D commands */ + +void SVGA_Update(uint32 x, uint32 y, uint32 width, uint32 height); +void SVGA_BeginDefineCursor(const SVGAFifoCmdDefineCursor __far *cursorInfo, + void __far * __far *andMask, void __far * __far *xorMask); +void SVGA_BeginDefineAlphaCursor(const SVGAFifoCmdDefineAlphaCursor __far *cursorInfo, + void __far * __far *data); +void SVGA_MoveCursor(uint32 visible, uint32 x, uint32 y, uint32 screenId); + +void SVGA_BeginVideoSetRegs(uint32 streamId, uint32 numItems, + SVGAEscapeVideoSetRegs __far * __far *setRegs); +void SVGA_VideoSetAllRegs(uint32 streamId, SVGAOverlayUnit __far *regs, uint32 maxReg); +void SVGA_VideoSetReg(uint32 streamId, uint32 registerId, uint32 value); +void SVGA_VideoFlush(uint32 streamId); + + +#endif /* __SVGA_H__ */ diff --git a/vmware/svga32.c b/vmware/svga32.c new file mode 100644 index 0000000..1091735 --- /dev/null +++ b/vmware/svga32.c @@ -0,0 +1,2 @@ +#define VXD32
+#include "svga.c"
diff --git a/vmware/svga3d.c b/vmware/svga3d.c new file mode 100644 index 0000000..bd48035 --- /dev/null +++ b/vmware/svga3d.c @@ -0,0 +1,1222 @@ +/********************************************************** + * Copyright 2008-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga3d.c -- + * + * FIFO command level interface to the SVGA3D protocol used by + * the VMware SVGA device. + */ + +#include <string.h> +#include "svga_all.h" + +#ifdef DBGPRINT +void dbg_printf( const char *s, ... ); +#else +#define dbg_printf(...) +#endif + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_Init -- + * + * Perform 3D-only initialization for the SVGA device. This + * function negotiates SVGA3D protocol versions between the host + * and the guest. + * + * The 3D protocol negotiation works as follows: + * + * 1. Before enabling the FIFO, the guest writes its 3D protocol + * version to the SVGA_FIFO_GUEST_3D_HWVERSION register. + * We do this step in SVGA_Init(). + * + * 2. When the FIFO is enabled, the host checks our 3D version + * for compatibility. If the host can support our protocol, + * the host puts its protocol version in SVGA_FIFO_3D_HWVERSION. + * If the host cannot support our protocol, it leaves the + * version set to zero. + * + * This function must be called after the FIFO is enabled. + * (After SVGA_SetMode.) + * + * Results: + * None. + * + * Side effects: + * Panic if the host is incompatible with 3D. + * + *---------------------------------------------------------------------- + */ + +Bool +SVGA3D_Init(void) +{ + SVGA3dHardwareVersion hwVersion; + + if (!(gSVGA.capabilities & SVGA_CAP_EXTENDED_FIFO)) { + dbg_printf("3D requires the Extended FIFO capability."); + } + + if (SVGA_HasFIFOCap(SVGA_FIFO_CAP_3D_HWVERSION_REVISED)) { + hwVersion = gSVGA.fifoMem[SVGA_FIFO_3D_HWVERSION_REVISED]; + } else { + if (gSVGA.fifoMem[SVGA_FIFO_MIN] <= sizeof(uint32) * SVGA_FIFO_GUEST_3D_HWVERSION) { + dbg_printf("GUEST_3D_HWVERSION register not present."); + } + hwVersion = gSVGA.fifoMem[SVGA_FIFO_3D_HWVERSION]; + } + + /* + * Check the host's version, make sure we're binary compatible. + */ + + if (hwVersion == 0) { + dbg_printf("3D disabled by host."); + return FALSE; + } + if (hwVersion < SVGA3D_HWVERSION_WS65_B1) { + dbg_printf("Host SVGA3D protocol is too old, not binary compatible."); + return FALSE; + } + + return TRUE; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_FIFOReserve -- + * + * Reserve space for an SVGA3D FIFO command. + * + * The 2D SVGA commands have been around for a while, so they + * have a rather asymmetric structure. The SVGA3D protocol is + * more uniform: each command begins with a header containing the + * command number and the full size. + * + * This is a convenience wrapper around SVGA_FIFOReserve. We + * reserve space for the whole command, and write the header. + * + * This function must be paired with SVGA_FIFOCommitAll(). + * + * Results: + * Returns a pointer to the space reserved for command-specific + * data. It must be 'cmdSize' bytes long. + * + * Side effects: + * Begins a FIFO reservation. + * + *---------------------------------------------------------------------- + */ + +void * +SVGA3D_FIFOReserve(uint32 cmd, // IN + uint32 cmdSize) // IN +{ + SVGA3dCmdHeader __far *header; + + header = SVGA_FIFOReserve(sizeof *header + cmdSize); + header->id = cmd; + header->size = cmdSize; + + return &header[1]; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginDefineSurface -- + * + * Begin a SURFACE_DEFINE command. This reserves space for it in + * the FIFO, and returns pointers to the command's faces and + * mipsizes arrays. + * + * This function must be paired with SVGA_FIFOCommitAll(). + * The faces and mipSizes arrays are initialized to zero. + * + * This creates a "surface" object in the SVGA3D device, + * with the provided surface ID (sid). Surfaces are generic + * containers for host VRAM objects like textures, vertex + * buffers, and depth/stencil buffers. + * + * Surfaces are hierarchial: + * + * - Surface may have multiple faces (for cube maps) + * + * - Each face has a list of mipmap levels + * + * - Each mipmap image may have multiple volume + * slices, if the image is three dimensional. + * + * - Each slice is a 2D array of 'blocks' + * + * - Each block may be one or more pixels. + * (Usually 1, more for DXT or YUV formats.) + * + * Surfaces are generic host VRAM objects. The SVGA3D device + * may optimize surfaces according to the format they were + * created with, but this format does not limit the ways in + * which the surface may be used. For example, a depth surface + * can be used as a texture, or a floating point image may + * be used as a vertex buffer. Some surface usages may be + * lower performance, due to software emulation, but any + * usage should work with any surface. + * + * If 'sid' is already defined, the old surface is deleted + * and this new surface replaces it. + * + * Surface IDs are arbitrary small non-negative integers, + * global to the entire SVGA device. + * + * Results: + * Returns pointers to arrays allocated in the FIFO for 'faces' + * and 'mipSizes'. + * + * Side effects: + * Begins a FIFO reservation. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginDefineSurface(uint32 sid, // IN + SVGA3dSurfaceFlags flags, // IN + SVGA3dSurfaceFormat format, // IN + SVGA3dSurfaceFace **faces, // OUT + SVGA3dSize **mipSizes, // OUT + uint32 numMipSizes) // IN +{ + SVGA3dCmdDefineSurface *cmd; + + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SURFACE_DEFINE, sizeof *cmd + + sizeof **mipSizes * numMipSizes); + + cmd->sid = sid; + cmd->surfaceFlags = flags; + cmd->format = format; + + *faces = &cmd->face[0]; + *mipSizes = (SVGA3dSize*) &cmd[1]; + + memset(*faces, 0, sizeof **faces * SVGA3D_MAX_SURFACE_FACES); + memset(*mipSizes, 0, sizeof **mipSizes * numMipSizes); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_DestroySurface -- + * + * Release the host VRAM encapsulated by a particular surface ID. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_DestroySurface(uint32 sid) // IN +{ + SVGA3dCmdDestroySurface *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SURFACE_DESTROY, sizeof *cmd); + cmd->sid = sid; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginSurfaceDMA-- + * + * Begin a SURFACE_DMA command. This reserves space for it in + * the FIFO, and returns a pointer to the command's box array. + * This function must be paired with SVGA_FIFOCommitAll(). + * + * When the SVGA3D device asynchronously processes this FIFO + * command, a DMA operation is performed between host VRAM and + * a generic SVGAGuestPtr. The guest pointer may refer to guest + * VRAM (provided by the SVGA PCI device) or to guest system + * memory that has been set up as a Guest Memory Region (GMR) + * by the SVGA device. + * + * The guest's DMA buffer must remain valid (not freed, paged out, + * or overwritten) until the host has finished processing this + * command. The guest can determine that the host has finished + * by using the SVGA device's FIFO Fence mechanism. + * + * The guest's image buffer can be an arbitrary size and shape. + * Guest image data is interpreted according to the SVGA3D surface + * format specified when the surface was defined. + * + * The caller may optionally define the guest image's pitch. + * guestImage->pitch can either be zero (assume image is tightly + * packed) or it must be the number of bytes between vertically + * adjacent image blocks. + * + * The provided copybox list specifies which regions of the source + * image are to be copied, and where they appear on the destination. + * + * NOTE: srcx/srcy are always on the guest image and x/y are + * always on the host image, regardless of the actual transfer + * direction! + * + * For efficiency, the SVGA3D device is free to copy more data + * than specified. For example, it may round copy boxes outwards + * such that they lie on particular alignment boundaries. + * + * The box array is initialized with zeroes. + * + * Results: + * Returns pointers to a box array allocated in the FIFO. + * + * Side effects: + * Begins a FIFO reservation. + * Begins a FIFO command which will eventually perform DMA. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginSurfaceDMA(SVGA3dGuestImage *guestImage, // IN + SVGA3dSurfaceImageId *hostImage, // IN + SVGA3dTransferType transfer, // IN + SVGA3dCopyBox **boxes, // OUT + uint32 numBoxes) // IN +{ + SVGA3dCmdSurfaceDMA *cmd; + uint32 boxesSize = sizeof **boxes * numBoxes; + + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SURFACE_DMA, sizeof *cmd + boxesSize); + + cmd->guest = *guestImage; + cmd->host = *hostImage; + cmd->transfer = transfer; + *boxes = (SVGA3dCopyBox*) &cmd[1]; + + memset(*boxes, 0, boxesSize); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_DefineContext -- + * + * Create a new context, to be referred to with the provided ID. + * + * Context objects encapsulate all render state, and shader + * objects are per-context. + * + * Surfaces are not per-context. The same surface can be shared + * between multiple contexts, and surface operations can occur + * without a context. + * + * If the provided context ID already existed, it is redefined. + * + * Context IDs are arbitrary small non-negative integers, + * global to the entire SVGA device. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_DefineContext(uint32 cid) // IN +{ + SVGA3dCmdDefineContext *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_CONTEXT_DEFINE, sizeof *cmd); + cmd->cid = cid; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_DestroyContext -- + * + * Delete a context created with SVGA3D_DefineContext. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_DestroyContext(uint32 cid) // IN +{ + SVGA3dCmdDestroyContext *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_CONTEXT_DESTROY, sizeof *cmd); + cmd->cid = cid; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetRenderTarget -- + * + * Bind a surface object to a particular render target attachment + * point on the current context. Render target attachment points + * exist for color buffers, a depth buffer, and a stencil buffer. + * + * The SVGA3D device is quite lenient about the types of surfaces + * that may be used as render targets. The color buffers must + * all be the same size, but the depth and stencil buffers do not + * have to be the same size as the color buffer. All attachments + * are optional. + * + * Some combinations of render target formats may require software + * emulation, depending on the capabilities of the host graphics + * API and graphics hardware. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetRenderTarget(uint32 cid, // IN + SVGA3dRenderTargetType type, // IN + SVGA3dSurfaceImageId *target) // IN +{ + SVGA3dCmdSetRenderTarget *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd); + cmd->cid = cid; + cmd->type = type; + cmd->target = *target; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetTransform -- + * + * Set one of the current context's transform matrices. + * The 'type' parameter should be an SVGA3D_TRANSFORM_* constant. + * + * All transformation matrices follow Direct3D-style coordinate + * system semantics. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + +void +SVGA3D_SetTransform(uint32 cid, // IN + SVGA3dTransformType type, // IN + const float *matrix) // IN +{ + SVGA3dCmdSetTransform *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETTRANSFORM, sizeof *cmd); + cmd->cid = cid; + cmd->type = type; + memcpy(&cmd->matrix[0], matrix, sizeof(float) * 16); + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetMaterial -- + * + * Set all material data for one SVGA3dFace. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetMaterial(uint32 cid, // IN + SVGA3dFace face, // IN + const SVGA3dMaterial *material) // IN +{ + SVGA3dCmdSetMaterial *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETMATERIAL, sizeof *cmd); + cmd->cid = cid; + cmd->face = face; + memcpy(&cmd->material, material, sizeof *material); + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetLightEnabled -- + * + * Enable or disable one fixed-function light. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetLightEnabled(uint32 cid, // IN + uint32 index, // IN + Bool enabled) // IN +{ + SVGA3dCmdSetLightEnabled *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETLIGHTENABLED, sizeof *cmd); + cmd->cid = cid; + cmd->index = index; + cmd->enabled = enabled; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetLightData -- + * + * Set all state for one fixed-function light. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetLightData(uint32 cid, // IN + uint32 index, // IN + const SVGA3dLightData *data) // IN +{ + SVGA3dCmdSetLightData *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETLIGHTDATA, sizeof *cmd); + cmd->cid = cid; + cmd->index = index; + memcpy(&cmd->data, data, sizeof *data); + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_DefineShader -- + * + * Upload the bytecode for a new shader. The bytecode is "SVGA3D + * format", which is theoretically a binary-compatible superset + * of Microsoft's DirectX shader bytecode. In practice, the + * SVGA3D bytecode doesn't yet have any extensions to DirectX's + * bytecode format. + * + * The SVGA3D device supports shader models 1.1 through 2.0. + * + * The caller chooses a shader ID (small positive integer) by + * which this shader will be identified in future commands. This + * ID is in a namespace which is per-context and per-shader-type. + * + * 'bytecodeLen' is specified in bytes. It must be a multiple of 4. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_DefineShader(uint32 cid, // IN + uint32 shid, // IN + SVGA3dShaderType type, // IN + const uint32 *bytecode, // IN + uint32 bytecodeLen) // IN +{ + SVGA3dCmdDefineShader *cmd; + + if (bytecodeLen & 3) { + dbg_printf("Shader bytecode length isn't a multiple of 32 bits!"); + } + + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen); + cmd->cid = cid; + cmd->shid = shid; + cmd->type = type; + memcpy(&cmd[1], bytecode, bytecodeLen); + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_DestroyShader -- + * + * Delete a shader that was created by SVGA3D_DefineShader. If + * the shader was the current vertex or pixel shader for its + * context, rendering results are undefined until a new shader is + * bound. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_DestroyShader(uint32 cid, // IN + uint32 shid, // IN + SVGA3dShaderType type) // IN +{ + SVGA3dCmdDestroyShader *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd); + cmd->cid = cid; + cmd->shid = shid; + cmd->type = type; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetShaderConst -- + * + * Set the value of a shader constant. + * + * Shader constants are analogous to uniform variables in GLSL, + * except that they belong to the render context rather than to + * an individual shader. + * + * Constants may have one of three types: A 4-vector of floats, + * a 4-vector of integers, or a single boolean flag. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetShaderConst(uint32 cid, // IN + uint32 reg, // IN + SVGA3dShaderType type, // IN + SVGA3dShaderConstType ctype, // IN + const void *value) // IN +{ + SVGA3dCmdSetShaderConst *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd); + cmd->cid = cid; + cmd->reg = reg; + cmd->type = type; + cmd->ctype = ctype; + + switch (ctype) { + + case SVGA3D_CONST_TYPE_FLOAT: + case SVGA3D_CONST_TYPE_INT: + memcpy(&cmd->values, value, sizeof cmd->values); + break; + + case SVGA3D_CONST_TYPE_BOOL: + memset(&cmd->values, 0, sizeof cmd->values); + cmd->values[0] = *(uint32*)value; + break; + + default: + dbg_printf("Bad shader constant type."); + break; + + } + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetShader -- + * + * Switch active shaders. This binds a new vertex or pixel shader + * to the specified context. + * + * A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching + * back to the fixed function vertex or pixel pipeline. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetShader(uint32 cid, // IN + SVGA3dShaderType type, // IN + uint32 shid) // IN +{ + SVGA3dCmdSetShader *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SET_SHADER, sizeof *cmd); + cmd->cid = cid; + cmd->type = type; + cmd->shid = shid; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginPresent -- + * + * Begin a PRESENT command. This reserves space for it in the + * FIFO, and returns a pointer to the command's rectangle array. + * This function must be paired with SVGA_FIFOCommitAll(). + * + * Present is the SVGA3D device's way of transferring fully + * rendered images to the 2D portion of the SVGA device. Present + * is a hardware accelerated surface-to-screen blit. + * + * Important caveats: + * + * - Present may or may not modify the guest-visible 2D + * framebuffer. If you need to read back rendering results, + * use an surface DMA transfer. + * + * - Present is a good place to think about flow control + * between the host and the guest. If the host and guest + * have no other form of synchronization, the FIFO could + * fill with many frames worth of rendering commands. The + * host will visibly lag the guest. Depending on the + * size of the FIFO and the size of the frames, it could + * lag by hours! It is advisable to use FIFO fences in order + * to guarantee that no more than one or two Presents are + * queued in the FIFO at any given time. + * + * Results: + * None. + * + * Side effects: + * May or may not write to the 2D framebuffer. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginPresent(uint32 sid, // IN + SVGA3dCopyRect **rects, // OUT + uint32 numRects) // IN +{ + SVGA3dCmdPresent *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_PRESENT, sizeof *cmd + + sizeof **rects * numRects); + cmd->sid = sid; + *rects = (SVGA3dCopyRect*) &cmd[1]; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginClear -- + * + * Begin a CLEAR command. This reserves space for it in the FIFO, + * and returns a pointer to the command's rectangle array. This + * function must be paired with SVGA_FIFOCommitAll(). + * + * Clear is a rendering operation which fills a list of + * rectangles with constant values on all render target types + * indicated by 'flags'. + * + * Clear is not affected by clipping, depth test, or other + * render state which affects the fragment pipeline. + * + * Results: + * None. + * + * Side effects: + * May write to attached render target surfaces. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginClear(uint32 cid, // IN + SVGA3dClearFlag flags, // IN + uint32 color, // IN + float depth, // IN + uint32 stencil, // IN + SVGA3dRect **rects, // OUT + uint32 numRects) // IN +{ + SVGA3dCmdClear *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_CLEAR, sizeof *cmd + + sizeof **rects * numRects); + cmd->cid = cid; + cmd->clearFlag = flags; + cmd->color = color; + cmd->depth = depth; + cmd->stencil = stencil; + *rects = (SVGA3dRect*) &cmd[1]; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginDrawPrimitives -- + * + * Begin a DRAW_PRIMITIVES command. This reserves space for it in + * the FIFO, and returns a pointer to the command's arrays. + * This function must be paired with SVGA_FIFOCommitAll(). + * + * Drawing commands consist of two variable-length arrays: + * SVGA3dVertexDecl elements declare a set of vertex buffers to + * use while rendering, and SVGA3dPrimitiveRange elements specify + * groups of primitives each with an optional index buffer. + * + * The decls and ranges arrays are initialized to zero. + * + * Results: + * None. + * + * Side effects: + * May write to attached render target surfaces. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginDrawPrimitives(uint32 cid, // IN + SVGA3dVertexDecl **decls, // OUT + uint32 numVertexDecls, // IN + SVGA3dPrimitiveRange **ranges, // OUT + uint32 numRanges) // IN +{ + SVGA3dCmdDrawPrimitives *cmd; + SVGA3dVertexDecl *declArray; + SVGA3dPrimitiveRange *rangeArray; + uint32 declSize = sizeof **decls * numVertexDecls; + uint32 rangeSize = sizeof **ranges * numRanges; + + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_DRAW_PRIMITIVES, sizeof *cmd + + declSize + rangeSize); + + cmd->cid = cid; + cmd->numVertexDecls = numVertexDecls; + cmd->numRanges = numRanges; + + declArray = (SVGA3dVertexDecl*) &cmd[1]; + rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls]; + + memset(declArray, 0, declSize); + memset(rangeArray, 0, rangeSize); + + *decls = declArray; + *ranges = rangeArray; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginSurfaceCopy -- + * + * Begin a SURFACE_COPY command. This reserves space for it in + * the FIFO, and returns a pointer to the command's arrays. This + * function must be paired with SVGA_FIFOCommitAll(). + * + * The box array is initialized with zeroes. + * + * Results: + * None. + * + * Side effects: + * Asynchronously copies a list of boxes from surface to surface. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginSurfaceCopy(SVGA3dSurfaceImageId *src, // IN + SVGA3dSurfaceImageId *dest, // IN + SVGA3dCopyBox **boxes, // OUT + uint32 numBoxes) // IN +{ + SVGA3dCmdSurfaceCopy *cmd; + uint32 boxesSize = sizeof **boxes * numBoxes; + + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize); + + cmd->src = *src; + cmd->dest = *dest; + *boxes = (SVGA3dCopyBox*) &cmd[1]; + + memset(*boxes, 0, boxesSize); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SurfaceStretchBlt -- + * + * Issue a SURFACE_STRETCHBLT command: an asynchronous + * surface-to-surface blit, with scaling. + * + * Results: + * None. + * + * Side effects: + * Asynchronously copies one box from surface to surface. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SurfaceStretchBlt(SVGA3dSurfaceImageId *src, // IN + SVGA3dSurfaceImageId *dest, // IN + SVGA3dBox *boxSrc, // IN + SVGA3dBox *boxDest, // IN + SVGA3dStretchBltMode mode) // IN +{ + SVGA3dCmdSurfaceStretchBlt *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd); + cmd->src = *src; + cmd->dest = *dest; + cmd->boxSrc = *boxSrc; + cmd->boxDest = *boxDest; + cmd->mode = mode; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetViewport -- + * + * Set the current context's viewport rectangle. The viewport + * is clipped to the dimensions of the current render target, + * then all rendering is clipped to the viewport. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetViewport(uint32 cid, // IN + SVGA3dRect *rect) // IN +{ + SVGA3dCmdSetViewport *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd); + cmd->cid = cid; + cmd->rect = *rect; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_SetZRange -- + * + * Set the range of the depth buffer to use. 'min' and 'max' + * are values between 0.0 and 1.0. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_SetZRange(uint32 cid, // IN + float zMin, // IN + float zMax) // IN +{ + SVGA3dCmdSetZRange *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETZRANGE, sizeof *cmd); + cmd->cid = cid; + cmd->zRange.min = zMin; + cmd->zRange.max = zMax; + SVGA_FIFOCommitAll(); +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginSetTextureState -- + * + * Begin a SETTEXTURESTATE command. This reserves space for it in + * the FIFO, and returns a pointer to the command's texture state + * array. This function must be paired with SVGA_FIFOCommitAll(). + * + * This command sets rendering state which is per-texture-unit. + * + * XXX: Individual texture states need documentation. However, + * they are very similar to the texture states defined by + * Direct3D. The D3D documentation is a good starting point + * for understanding SVGA3D texture states. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginSetTextureState(uint32 cid, // IN + SVGA3dTextureState **states, // OUT + uint32 numStates) // IN +{ + SVGA3dCmdSetTextureState *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETTEXTURESTATE, sizeof *cmd + + sizeof **states * numStates); + cmd->cid = cid; + *states = (SVGA3dTextureState*) &cmd[1]; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginSetRenderState -- + * + * Begin a SETRENDERSTATE command. This reserves space for it in + * the FIFO, and returns a pointer to the command's texture state + * array. This function must be paired with SVGA_FIFOCommitAll(). + * + * This command sets rendering state which is global to the context. + * + * XXX: Individual render states need documentation. However, + * they are very similar to the render states defined by + * Direct3D. The D3D documentation is a good starting point + * for understanding SVGA3D render states. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginSetRenderState(uint32 cid, // IN + SVGA3dRenderState **states, // OUT + uint32 numStates) // IN +{ + SVGA3dCmdSetRenderState *cmd; + cmd = SVGA3D_FIFOReserve(SVGA_3D_CMD_SETRENDERSTATE, sizeof *cmd + + sizeof **states * numStates); + cmd->cid = cid; + *states = (SVGA3dRenderState*) &cmd[1]; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginPresentReadback -- + * + * Begin a PRESENT_READBACK command. This reserves space for it + * in the FIFO, and returns a pointer to the command's SVGA3dRect + * array. This function must be paired with + * SVGA_FIFOCommitAll(). + * + * This command will update the 2D framebuffer with the most + * recently presented data in the supplied regions. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginPresentReadback(SVGA3dRect **rects, // OUT + uint32 numRects) // IN +{ + void *cmd; + cmd = (void *) SVGA3D_FIFOReserve(SVGA_3D_CMD_PRESENT_READBACK, + sizeof **rects * numRects); + *rects = (SVGA3dRect*) cmd; +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BeginBlitSurfaceToScreen -- + * + * Begin a BLIT_SURFACE_TO_SCREEN command. This reserves space + * for it in the FIFO, and optionally returns a pointer to the + * command's clip rectangle array. This function must be paired + * with SVGA_FIFOCommitAll(). + * + * Copy an SVGA3D surface image to a Screen Object. This command + * requires the SVGA Screen Object capability to be present. + * Copies a rectangular region of a surface image to a + * rectangular region of a screen or a portion of the virtual + * coordinate space that contains all screens. + * + * If destScreenId is SVGA_ID_INVALID, the destination rectangle + * is in virtual coordinates rather than in screen coordinates. + * + * If the source and destination rectangle are different sizes, + * the image will be scaled using a backend-specific algorithm. + * + * This command may optionally include a clip rectangle list. If + * zero rectangles are specified, there is no clip region. The + * entire destination rectangle is drawn. If one or more + * rectangles are specified, they describe a destination clipping + * region in the same coordinate system as destRect. + * + * Results: + * None. + * + * Side effects: + * Writes to the Screen Object. + * Begins a new FIFO command. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BeginBlitSurfaceToScreen(const SVGA3dSurfaceImageId *srcImage, // IN + const SVGASignedRect *srcRect, // IN + uint32 destScreenId, // IN (optional) + const SVGASignedRect *destRect, // IN + SVGASignedRect **clipRects, // IN (optional) + uint32 numClipRects) // IN (optional) +{ + SVGA3dCmdBlitSurfaceToScreen *cmd = + SVGA3D_FIFOReserve(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, + sizeof *cmd + numClipRects * sizeof(SVGASignedRect)); + + cmd->srcImage = *srcImage; + cmd->srcRect = *srcRect; + cmd->destScreenId = destScreenId; + cmd->destRect = *destRect; + + if (clipRects) { + *clipRects = (SVGASignedRect*) &cmd[1]; + } +} + + +/* + *---------------------------------------------------------------------- + * + * SVGA3D_BlitSurfaceToScreen -- + * + * This is a convenience wrapper around + * SVGA3D_BeginBlitSurfaceToScreen, for callers who do not + * require a clip rectangle list. + * + * Results: + * None. + * + * Side effects: + * Writes to the Screen Object. + * + *---------------------------------------------------------------------- + */ + +void +SVGA3D_BlitSurfaceToScreen(const SVGA3dSurfaceImageId *srcImage, // IN + const SVGASignedRect *srcRect, // IN + uint32 destScreenId, // IN (optional) + const SVGASignedRect *destRect) // IN +{ + SVGA3D_BeginBlitSurfaceToScreen(srcImage, srcRect, destScreenId, destRect, NULL, 0); + SVGA_FIFOCommitAll(); +} diff --git a/vmware/svga3d.h b/vmware/svga3d.h new file mode 100644 index 0000000..1242754 --- /dev/null +++ b/vmware/svga3d.h @@ -0,0 +1,149 @@ +/********************************************************** + * Copyright 2008-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga3d.h -- + * + * FIFO command level interface to the SVGA3D protocol used by + * the VMware SVGA device. + */ + +#ifndef __SVGA3D_H__ +#define __SVGA3D_H__ + +#include "svga.h" +#include "svga3d_reg.h" + + +/* + * SVGA Device Interoperability + */ + +Bool SVGA3D_Init(void); +void SVGA3D_BeginPresent(uint32 sid, SVGA3dCopyRect **rects, uint32 numRects); +void SVGA3D_BeginPresentReadback(SVGA3dRect **rects, uint32 numRects); +void SVGA3D_BlitSurfaceToScreen(const SVGA3dSurfaceImageId *srcImage, + const SVGASignedRect *srcRect, + uint32 destScreenId, + const SVGASignedRect *destRect); +void SVGA3D_BeginBlitSurfaceToScreen(const SVGA3dSurfaceImageId *srcImage, + const SVGASignedRect *srcRect, + uint32 destScreenId, + const SVGASignedRect *destRect, + SVGASignedRect **clipRects, + uint32 numClipRects); + + +/* + * Surface Management + */ + +void SVGA3D_BeginDefineSurface(uint32 sid, + SVGA3dSurfaceFlags flags, + SVGA3dSurfaceFormat format, + SVGA3dSurfaceFace **faces, + SVGA3dSize **mipSizes, + uint32 numMipSizes); +void SVGA3D_DestroySurface(uint32 sid); +void SVGA3D_BeginSurfaceDMA(SVGA3dGuestImage *guestImage, + SVGA3dSurfaceImageId *hostImage, + SVGA3dTransferType transfer, + SVGA3dCopyBox **boxes, + uint32 numBoxes); + + +/* + * Context Management + */ + +void SVGA3D_DefineContext(uint32 cid); +void SVGA3D_DestroyContext(uint32 cid); + + +/* + * Drawing Operations + */ + +void SVGA3D_BeginClear(uint32 cid, SVGA3dClearFlag flags, + uint32 color, float depth, uint32 stencil, + SVGA3dRect **rects, uint32 numRects); +void SVGA3D_BeginDrawPrimitives(uint32 cid, + SVGA3dVertexDecl **decls, + uint32 numVertexDecls, + SVGA3dPrimitiveRange **ranges, + uint32 numRanges); + +/* + * Blits + */ + +void SVGA3D_BeginSurfaceCopy(SVGA3dSurfaceImageId *src, + SVGA3dSurfaceImageId *dest, + SVGA3dCopyBox **boxes, uint32 numBoxes); + +void SVGA3D_SurfaceStretchBlt(SVGA3dSurfaceImageId *src, + SVGA3dSurfaceImageId *dest, + SVGA3dBox *boxSrc, SVGA3dBox *boxDest, + SVGA3dStretchBltMode mode); + +/* + * Shared FFP/Shader Render State + */ + +void SVGA3D_SetRenderTarget(uint32 cid, SVGA3dRenderTargetType type, + SVGA3dSurfaceImageId *target); +void SVGA3D_SetZRange(uint32 cid, float zMin, float zMax); +void SVGA3D_SetViewport(uint32 cid, SVGA3dRect *rect); +void SVGA3D_SetScissorRect(uint32 cid, SVGA3dRect *rect); +void SVGA3D_SetClipPlane(uint32 cid, uint32 index, const float *plane); +void SVGA3D_BeginSetTextureState(uint32 cid, SVGA3dTextureState **states, + uint32 numStates); +void SVGA3D_BeginSetRenderState(uint32 cid, SVGA3dRenderState **states, + uint32 numStates); + + +/* + * Fixed-function Render State + */ + +void SVGA3D_SetTransform(uint32 cid, SVGA3dTransformType type, + const float *matrix); +void SVGA3D_SetMaterial(uint32 cid, SVGA3dFace face, const SVGA3dMaterial *material); +void SVGA3D_SetLightData(uint32 cid, uint32 index, const SVGA3dLightData *data); +void SVGA3D_SetLightEnabled(uint32 cid, uint32 index, Bool enabled); + + +/* + * Shaders + */ + +void SVGA3D_DefineShader(uint32 cid, uint32 shid, SVGA3dShaderType type, + const uint32 *bytecode, uint32 bytecodeLen); +void SVGA3D_DestroyShader(uint32 cid, uint32 shid, SVGA3dShaderType type); +void SVGA3D_SetShaderConst(uint32 cid, uint32 reg, SVGA3dShaderType type, + SVGA3dShaderConstType ctype, const void *value); +void SVGA3D_SetShader(uint32 cid, SVGA3dShaderType type, uint32 shid); + +#endif /* __SVGA3D_H__ */ diff --git a/vmware/svga3d_caps.h b/vmware/svga3d_caps.h new file mode 100644 index 0000000..3eab532 --- /dev/null +++ b/vmware/svga3d_caps.h @@ -0,0 +1,140 @@ +/********************************************************** + * Copyright 2007-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga3d_caps.h -- + * + * Definitions for SVGA3D hardware capabilities. Capabilities + * are used to query for optional rendering features during + * driver initialization. The capability data is stored as very + * basic key/value dictionary within the "FIFO register" memory + * area at the beginning of BAR2. + * + * Note that these definitions are only for 3D capabilities. + * The SVGA device also has "device capabilities" and "FIFO + * capabilities", which are non-3D-specific and are stored as + * bitfields rather than key/value pairs. + */ + +#ifndef _SVGA3D_CAPS_H_ +#define _SVGA3D_CAPS_H_ + +#define SVGA_FIFO_3D_CAPS_SIZE (SVGA_FIFO_3D_CAPS_LAST - \ + SVGA_FIFO_3D_CAPS + 1) + + +/* + * SVGA3dCapsRecordType + * + * Record types that can be found in the caps block. + * Related record types are grouped together numerically so that + * SVGA3dCaps_FindRecord() can be applied on a range of record + * types. + */ + +typedef enum { + SVGA3DCAPS_RECORD_UNKNOWN = 0, + SVGA3DCAPS_RECORD_DEVCAPS_MIN = 0x100, + SVGA3DCAPS_RECORD_DEVCAPS = 0x100, + SVGA3DCAPS_RECORD_DEVCAPS_MAX = 0x1ff, + SVGA3DCAPS_RECORD_DEVCAPS_FORCE32 = 0xffffffff +} SVGA3dCapsRecordType; + + +/* + * SVGA3dCapsRecordHeader + * + * Header field leading each caps block record. Contains the offset (in + * register words, NOT bytes) to the next caps block record (or the end + * of caps block records which will be a zero word) and the record type + * as defined above. + */ + +typedef +struct SVGA3dCapsRecordHeader { + uint32 length; + SVGA3dCapsRecordType type; +} +SVGA3dCapsRecordHeader; + + +/* + * SVGA3dCapsRecord + * + * Caps block record; "data" is a placeholder for the actual data structure + * contained within the record; for example a record containing a FOOBAR + * structure would be of size "sizeof(SVGA3dCapsRecordHeader) + + * sizeof(FOOBAR)". + */ + +typedef +struct SVGA3dCapsRecord { + SVGA3dCapsRecordHeader header; + uint32 data[1]; +} +SVGA3dCapsRecord; + + +typedef uint32 SVGA3dCapPair[2]; + + +/* + *---------------------------------------------------------------------- + * + * SVGA3dCaps_FindRecord + * + * Finds the record with the highest-valued type within the given range + * in the caps block. + * + * Result: pointer to found record, or NULL if not found. + * + *---------------------------------------------------------------------- + */ + +static INLINE SVGA3dCapsRecord * +SVGA3dCaps_FindRecord(const uint32 *capsBlock, + SVGA3dCapsRecordType recordTypeMin, + SVGA3dCapsRecordType recordTypeMax) +{ + SVGA3dCapsRecord *record, *found = NULL; + uint32 offset; + + /* + * Search linearly through the caps block records for the specified type. + */ + for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) { + record = (SVGA3dCapsRecord *) (capsBlock + offset); + if ((record->header.type >= recordTypeMin) && + (record->header.type <= recordTypeMax) && + (!found || (record->header.type > found->header.type))) { + found = record; + } + } + + return found; +} + + +#endif // _SVGA3D_CAPS_H_ diff --git a/vmware/svga3d_reg.h b/vmware/svga3d_reg.h new file mode 100644 index 0000000..9b009d5 --- /dev/null +++ b/vmware/svga3d_reg.h @@ -0,0 +1,3189 @@ +/********************************************************** + * Copyright 1998-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga3d_reg.h -- + * + * SVGA 3D hardware definitions + */ + +#ifndef _SVGA3D_REG_H_ +#define _SVGA3D_REG_H_ + +#include "svga_reg.h" + +/* + * Extra types + */ + +typedef struct uint64 { + uint32 low; + uint32 hi; +} uint64; + +typedef uint16 SVGA3dLogicOp; +typedef uint32 SVGA3dSurface1Flags; +typedef uint32 SVGA3dSurface2Flags; +typedef uint64 SVGA3dSurfaceAllFlags; +typedef uint32 SVGAMobId; + +#define SVGA3D_INVALID_ID ((uint32)-1) + +typedef uint64 PPN64; +typedef uint32 PPN; + +/* + * Limits + */ +#define SVGA3D_NUM_TEXTURE_UNITS 32 +#define SVGA3D_NUM_LIGHTS 8 + +/* + * 3D Hardware Version + * + * The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo + * register. Is set by the host and read by the guest. This lets + * us make new guest drivers which are backwards-compatible with old + * SVGA hardware revisions. It does not let us support old guest + * drivers. Good enough for now. + * + */ + +#define SVGA3D_MAKE_HWVERSION(major, minor) (((unsigned long)(major) << 16) | ((unsigned long)(minor) & 0xFF)) +#define SVGA3D_MAJOR_HWVERSION(version) ((unsigned long)(version) >> 16) +#define SVGA3D_MINOR_HWVERSION(version) ((unsigned long)(version) & 0xFF) + +typedef enum { + SVGA3D_HWVERSION_WS5_RC1 = SVGA3D_MAKE_HWVERSION(0, 1), + SVGA3D_HWVERSION_WS5_RC2 = SVGA3D_MAKE_HWVERSION(0, 2), + SVGA3D_HWVERSION_WS51_RC1 = SVGA3D_MAKE_HWVERSION(0, 3), + SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1), + SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4), + SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0), + SVGA3D_HWVERSION_WS8_B1 = SVGA3D_MAKE_HWVERSION(2, 1), + SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS8_B1, +} SVGA3dHardwareVersion; + +/* + * Generic Types + */ + +typedef uint32 SVGA3dBool; /* 32-bit Bool definition */ +#define SVGA3D_NUM_CLIPPLANES 6 +#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS 8 +#define SVGA3D_MAX_CONTEXT_IDS 256 +#define SVGA3D_MAX_SURFACE_IDS (32 * 1024) + +/* + * Surface formats. + * + * If you modify this list, be sure to keep GLUtil.c in sync. It + * includes the internal format definition of each surface in + * GLUtil_ConvertSurfaceFormat, and it contains a table of + * human-readable names in GLUtil_GetFormatName. + */ + +typedef enum SVGA3dSurfaceFormat { + SVGA3D_FORMAT_INVALID = 0, + + SVGA3D_X8R8G8B8 = 1, + SVGA3D_A8R8G8B8 = 2, + + SVGA3D_R5G6B5 = 3, + SVGA3D_X1R5G5B5 = 4, + SVGA3D_A1R5G5B5 = 5, + SVGA3D_A4R4G4B4 = 6, + + SVGA3D_Z_D32 = 7, + SVGA3D_Z_D16 = 8, + SVGA3D_Z_D24S8 = 9, + SVGA3D_Z_D15S1 = 10, + + SVGA3D_LUMINANCE8 = 11, + SVGA3D_LUMINANCE4_ALPHA4 = 12, + SVGA3D_LUMINANCE16 = 13, + SVGA3D_LUMINANCE8_ALPHA8 = 14, + + SVGA3D_DXT1 = 15, + SVGA3D_DXT2 = 16, + SVGA3D_DXT3 = 17, + SVGA3D_DXT4 = 18, + SVGA3D_DXT5 = 19, + + SVGA3D_BUMPU8V8 = 20, + SVGA3D_BUMPL6V5U5 = 21, + SVGA3D_BUMPX8L8V8U8 = 22, + SVGA3D_BUMPL8V8U8 = 23, + + SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */ + SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */ + + SVGA3D_A2R10G10B10 = 26, + + /* signed formats */ + SVGA3D_V8U8 = 27, + SVGA3D_Q8W8V8U8 = 28, + SVGA3D_CxV8U8 = 29, + + /* mixed formats */ + SVGA3D_X8L8V8U8 = 30, + SVGA3D_A2W10V10U10 = 31, + + SVGA3D_ALPHA8 = 32, + + /* Single- and dual-component floating point formats */ + SVGA3D_R_S10E5 = 33, + SVGA3D_R_S23E8 = 34, + SVGA3D_RG_S10E5 = 35, + SVGA3D_RG_S23E8 = 36, + + /* + * Any surface can be used as a buffer object, but SVGA3D_BUFFER is + * the most efficient format to use when creating new surfaces + * expressly for index or vertex data. + */ + + SVGA3D_BUFFER = 37, + + SVGA3D_Z_D24X8 = 38, + + SVGA3D_V16U16 = 39, + + SVGA3D_G16R16 = 40, + SVGA3D_A16B16G16R16 = 41, + + /* Packed Video formats */ + SVGA3D_UYVY = 42, + SVGA3D_YUY2 = 43, + + /* Planar video formats */ + SVGA3D_NV12 = 44, + + /* Video format with alpha */ + SVGA3D_AYUV = 45, + + SVGA3D_BC4_UNORM = 108, + SVGA3D_BC5_UNORM = 111, + + /* Advanced D3D9 depth formats. */ + SVGA3D_Z_DF16 = 118, + SVGA3D_Z_DF24 = 119, + SVGA3D_Z_D24S8_INT = 120, + + SVGA3D_FORMAT_MAX +} SVGA3dSurfaceFormat; + +typedef uint32 SVGA3dColor; /* a, r, g, b */ + +/* + * These match the D3DFORMAT_OP definitions used by Direct3D. We need + * them so that we can query the host for what the supported surface + * operations are (when we're using the D3D backend, in particular), + * and so we can send those operations to the guest. + */ +typedef enum { + SVGA3DFORMAT_OP_TEXTURE = 0x00000001, + SVGA3DFORMAT_OP_VOLUMETEXTURE = 0x00000002, + SVGA3DFORMAT_OP_CUBETEXTURE = 0x00000004, + SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET = 0x00000008, + SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET = 0x00000010, + SVGA3DFORMAT_OP_ZSTENCIL = 0x00000040, + SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH = 0x00000080, + +/* + * This format can be used as a render target if the current display mode + * is the same depth if the alpha channel is ignored. e.g. if the device + * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the + * format op list entry for A8R8G8B8 should have this cap. + */ + SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET = 0x00000100, + +/* + * This format contains DirectDraw support (including Flip). This flag + * should not to be set on alpha formats. + */ + SVGA3DFORMAT_OP_DISPLAYMODE = 0x00000400, + +/* + * The rasterizer can support some level of Direct3D support in this format + * and implies that the driver can create a Context in this mode (for some + * render target format). When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE + * flag must also be set. + */ + SVGA3DFORMAT_OP_3DACCELERATION = 0x00000800, + +/* + * This is set for a private format when the driver has put the bpp in + * the structure. + */ + SVGA3DFORMAT_OP_PIXELSIZE = 0x00001000, + +/* + * Indicates that this format can be converted to any RGB format for which + * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified + */ + SVGA3DFORMAT_OP_CONVERT_TO_ARGB = 0x00002000, + +/* + * Indicates that this format can be used to create offscreen plain surfaces. + */ + SVGA3DFORMAT_OP_OFFSCREENPLAIN = 0x00004000, + +/* + * Indicated that this format can be read as an SRGB texture (meaning that the + * sampler will linearize the looked up data) + */ + SVGA3DFORMAT_OP_SRGBREAD = 0x00008000, + +/* + * Indicates that this format can be used in the bumpmap instructions + */ + SVGA3DFORMAT_OP_BUMPMAP = 0x00010000, + +/* + * Indicates that this format can be sampled by the displacement map sampler + */ + SVGA3DFORMAT_OP_DMAP = 0x00020000, + +/* + * Indicates that this format cannot be used with texture filtering + */ + SVGA3DFORMAT_OP_NOFILTER = 0x00040000, + +/* + * Indicates that format conversions are supported to this RGB format if + * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format. + */ + SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB = 0x00080000, + +/* + * Indicated that this format can be written as an SRGB target (meaning that the + * pixel pipe will DE-linearize data on output to format) + */ + SVGA3DFORMAT_OP_SRGBWRITE = 0x00100000, + +/* + * Indicates that this format cannot be used with alpha blending + */ + SVGA3DFORMAT_OP_NOALPHABLEND = 0x00200000, + +/* + * Indicates that the device can auto-generated sublevels for resources + * of this format + */ + SVGA3DFORMAT_OP_AUTOGENMIPMAP = 0x00400000, + +/* + * Indicates that this format can be used by vertex texture sampler + */ + SVGA3DFORMAT_OP_VERTEXTEXTURE = 0x00800000, + +/* + * Indicates that this format supports neither texture coordinate wrap + * modes, nor mipmapping + */ + SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP = 0x01000000 +} SVGA3dFormatOp; + +/* + * This structure is a conversion of SVGA3DFORMAT_OP_*. + * Entries must be located at the same position. + */ +typedef union { + uint32 value; + struct { + uint32 texture : 1; + uint32 volumeTexture : 1; + uint32 cubeTexture : 1; + uint32 offscreenRenderTarget : 1; + uint32 sameFormatRenderTarget : 1; + uint32 unknown1 : 1; + uint32 zStencil : 1; + uint32 zStencilArbitraryDepth : 1; + uint32 sameFormatUpToAlpha : 1; + uint32 unknown2 : 1; + uint32 displayMode : 1; + uint32 acceleration3d : 1; + uint32 pixelSize : 1; + uint32 convertToARGB : 1; + uint32 offscreenPlain : 1; + uint32 sRGBRead : 1; + uint32 bumpMap : 1; + uint32 dmap : 1; + uint32 noFilter : 1; + uint32 memberOfGroupARGB : 1; + uint32 sRGBWrite : 1; + uint32 noAlphaBlend : 1; + uint32 autoGenMipMap : 1; + uint32 vertexTexture : 1; + uint32 noTexCoordWrapNorMip : 1; + }; +} SVGA3dSurfaceFormatCaps; + +/* + * SVGA_3D_CMD_SETRENDERSTATE Types. All value types + * must fit in a uint32. + */ + +typedef enum { + SVGA3D_RS_INVALID = 0, + SVGA3D_RS_ZENABLE = 1, /* SVGA3dBool */ + SVGA3D_RS_ZWRITEENABLE = 2, /* SVGA3dBool */ + SVGA3D_RS_ALPHATESTENABLE = 3, /* SVGA3dBool */ + SVGA3D_RS_DITHERENABLE = 4, /* SVGA3dBool */ + SVGA3D_RS_BLENDENABLE = 5, /* SVGA3dBool */ + SVGA3D_RS_FOGENABLE = 6, /* SVGA3dBool */ + SVGA3D_RS_SPECULARENABLE = 7, /* SVGA3dBool */ + SVGA3D_RS_STENCILENABLE = 8, /* SVGA3dBool */ + SVGA3D_RS_LIGHTINGENABLE = 9, /* SVGA3dBool */ + SVGA3D_RS_NORMALIZENORMALS = 10, /* SVGA3dBool */ + SVGA3D_RS_POINTSPRITEENABLE = 11, /* SVGA3dBool */ + SVGA3D_RS_POINTSCALEENABLE = 12, /* SVGA3dBool */ + SVGA3D_RS_STENCILREF = 13, /* uint32 */ + SVGA3D_RS_STENCILMASK = 14, /* uint32 */ + SVGA3D_RS_STENCILWRITEMASK = 15, /* uint32 */ + SVGA3D_RS_FOGSTART = 16, /* float */ + SVGA3D_RS_FOGEND = 17, /* float */ + SVGA3D_RS_FOGDENSITY = 18, /* float */ + SVGA3D_RS_POINTSIZE = 19, /* float */ + SVGA3D_RS_POINTSIZEMIN = 20, /* float */ + SVGA3D_RS_POINTSIZEMAX = 21, /* float */ + SVGA3D_RS_POINTSCALE_A = 22, /* float */ + SVGA3D_RS_POINTSCALE_B = 23, /* float */ + SVGA3D_RS_POINTSCALE_C = 24, /* float */ + SVGA3D_RS_FOGCOLOR = 25, /* SVGA3dColor */ + SVGA3D_RS_AMBIENT = 26, /* SVGA3dColor */ + SVGA3D_RS_CLIPPLANEENABLE = 27, /* SVGA3dClipPlanes */ + SVGA3D_RS_FOGMODE = 28, /* SVGA3dFogMode */ + SVGA3D_RS_FILLMODE = 29, /* SVGA3dFillMode */ + SVGA3D_RS_SHADEMODE = 30, /* SVGA3dShadeMode */ + SVGA3D_RS_LINEPATTERN = 31, /* SVGA3dLinePattern */ + SVGA3D_RS_SRCBLEND = 32, /* SVGA3dBlendOp */ + SVGA3D_RS_DSTBLEND = 33, /* SVGA3dBlendOp */ + SVGA3D_RS_BLENDEQUATION = 34, /* SVGA3dBlendEquation */ + SVGA3D_RS_CULLMODE = 35, /* SVGA3dFace */ + SVGA3D_RS_ZFUNC = 36, /* SVGA3dCmpFunc */ + SVGA3D_RS_ALPHAFUNC = 37, /* SVGA3dCmpFunc */ + SVGA3D_RS_STENCILFUNC = 38, /* SVGA3dCmpFunc */ + SVGA3D_RS_STENCILFAIL = 39, /* SVGA3dStencilOp */ + SVGA3D_RS_STENCILZFAIL = 40, /* SVGA3dStencilOp */ + SVGA3D_RS_STENCILPASS = 41, /* SVGA3dStencilOp */ + SVGA3D_RS_ALPHAREF = 42, /* float (0.0 .. 1.0) */ + SVGA3D_RS_FRONTWINDING = 43, /* SVGA3dFrontWinding */ + SVGA3D_RS_COORDINATETYPE = 44, /* SVGA3dCoordinateType */ + SVGA3D_RS_ZBIAS = 45, /* float */ + SVGA3D_RS_RANGEFOGENABLE = 46, /* SVGA3dBool */ + SVGA3D_RS_COLORWRITEENABLE = 47, /* SVGA3dColorMask */ + SVGA3D_RS_VERTEXMATERIALENABLE = 48, /* SVGA3dBool */ + SVGA3D_RS_DIFFUSEMATERIALSOURCE = 49, /* SVGA3dVertexMaterial */ + SVGA3D_RS_SPECULARMATERIALSOURCE = 50, /* SVGA3dVertexMaterial */ + SVGA3D_RS_AMBIENTMATERIALSOURCE = 51, /* SVGA3dVertexMaterial */ + SVGA3D_RS_EMISSIVEMATERIALSOURCE = 52, /* SVGA3dVertexMaterial */ + SVGA3D_RS_TEXTUREFACTOR = 53, /* SVGA3dColor */ + SVGA3D_RS_LOCALVIEWER = 54, /* SVGA3dBool */ + SVGA3D_RS_SCISSORTESTENABLE = 55, /* SVGA3dBool */ + SVGA3D_RS_BLENDCOLOR = 56, /* SVGA3dColor */ + SVGA3D_RS_STENCILENABLE2SIDED = 57, /* SVGA3dBool */ + SVGA3D_RS_CCWSTENCILFUNC = 58, /* SVGA3dCmpFunc */ + SVGA3D_RS_CCWSTENCILFAIL = 59, /* SVGA3dStencilOp */ + SVGA3D_RS_CCWSTENCILZFAIL = 60, /* SVGA3dStencilOp */ + SVGA3D_RS_CCWSTENCILPASS = 61, /* SVGA3dStencilOp */ + SVGA3D_RS_VERTEXBLEND = 62, /* SVGA3dVertexBlendFlags */ + SVGA3D_RS_SLOPESCALEDEPTHBIAS = 63, /* float */ + SVGA3D_RS_DEPTHBIAS = 64, /* float */ + + + /* + * Output Gamma Level + * + * Output gamma effects the gamma curve of colors that are output from the + * rendering pipeline. A value of 1.0 specifies a linear color space. If the + * value is <= 0.0, gamma correction is ignored and linear color space is + * used. + */ + + SVGA3D_RS_OUTPUTGAMMA = 65, /* float */ + SVGA3D_RS_ZVISIBLE = 66, /* SVGA3dBool */ + SVGA3D_RS_LASTPIXEL = 67, /* SVGA3dBool */ + SVGA3D_RS_CLIPPING = 68, /* SVGA3dBool */ + SVGA3D_RS_WRAP0 = 69, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP1 = 70, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP2 = 71, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP3 = 72, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP4 = 73, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP5 = 74, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP6 = 75, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP7 = 76, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP8 = 77, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP9 = 78, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP10 = 79, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP11 = 80, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP12 = 81, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP13 = 82, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP14 = 83, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP15 = 84, /* SVGA3dWrapFlags */ + SVGA3D_RS_MULTISAMPLEANTIALIAS = 85, /* SVGA3dBool */ + SVGA3D_RS_MULTISAMPLEMASK = 86, /* uint32 */ + SVGA3D_RS_INDEXEDVERTEXBLENDENABLE = 87, /* SVGA3dBool */ + SVGA3D_RS_TWEENFACTOR = 88, /* float */ + SVGA3D_RS_ANTIALIASEDLINEENABLE = 89, /* SVGA3dBool */ + SVGA3D_RS_COLORWRITEENABLE1 = 90, /* SVGA3dColorMask */ + SVGA3D_RS_COLORWRITEENABLE2 = 91, /* SVGA3dColorMask */ + SVGA3D_RS_COLORWRITEENABLE3 = 92, /* SVGA3dColorMask */ + SVGA3D_RS_SEPARATEALPHABLENDENABLE = 93, /* SVGA3dBool */ + SVGA3D_RS_SRCBLENDALPHA = 94, /* SVGA3dBlendOp */ + SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */ + SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */ + SVGA3D_RS_TRANSPARENCYANTIALIAS = 97, /* SVGA3dTransparencyAntialiasType */ + SVGA3D_RS_LINEAA = 98, /* SVGA3dBool */ + SVGA3D_RS_LINEWIDTH = 99, /* float */ + SVGA3D_RS_MAX +} SVGA3dRenderStateName; + +typedef enum { + SVGA3D_TRANSPARENCYANTIALIAS_NORMAL = 0, + SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE = 1, + SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE = 2, + SVGA3D_TRANSPARENCYANTIALIAS_MAX +} SVGA3dTransparencyAntialiasType; + +typedef enum { + SVGA3D_VERTEXMATERIAL_NONE = 0, /* Use the value in the current material */ + SVGA3D_VERTEXMATERIAL_DIFFUSE = 1, /* Use the value in the diffuse component */ + SVGA3D_VERTEXMATERIAL_SPECULAR = 2, /* Use the value in the specular component */ +} SVGA3dVertexMaterial; + +typedef enum { + SVGA3D_FILLMODE_INVALID = 0, + SVGA3D_FILLMODE_POINT = 1, + SVGA3D_FILLMODE_LINE = 2, + SVGA3D_FILLMODE_FILL = 3, + SVGA3D_FILLMODE_MAX +} SVGA3dFillModeType; + + +typedef +union { + struct { + uint16 mode; /* SVGA3dFillModeType */ + uint16 face; /* SVGA3dFace */ + }; + uint32 uintValue; +} SVGA3dFillMode; + +typedef enum { + SVGA3D_SHADEMODE_INVALID = 0, + SVGA3D_SHADEMODE_FLAT = 1, + SVGA3D_SHADEMODE_SMOOTH = 2, + SVGA3D_SHADEMODE_PHONG = 3, /* Not supported */ + SVGA3D_SHADEMODE_MAX +} SVGA3dShadeMode; + +typedef +union { + struct { + uint16 repeat; + uint16 pattern; + }; + uint32 uintValue; +} SVGA3dLinePattern; + +typedef enum { + SVGA3D_BLENDOP_INVALID = 0, + SVGA3D_BLENDOP_ZERO = 1, + SVGA3D_BLENDOP_ONE = 2, + SVGA3D_BLENDOP_SRCCOLOR = 3, + SVGA3D_BLENDOP_INVSRCCOLOR = 4, + SVGA3D_BLENDOP_SRCALPHA = 5, + SVGA3D_BLENDOP_INVSRCALPHA = 6, + SVGA3D_BLENDOP_DESTALPHA = 7, + SVGA3D_BLENDOP_INVDESTALPHA = 8, + SVGA3D_BLENDOP_DESTCOLOR = 9, + SVGA3D_BLENDOP_INVDESTCOLOR = 10, + SVGA3D_BLENDOP_SRCALPHASAT = 11, + SVGA3D_BLENDOP_BLENDFACTOR = 12, + SVGA3D_BLENDOP_INVBLENDFACTOR = 13, + SVGA3D_BLENDOP_MAX +} SVGA3dBlendOp; + +typedef enum { + SVGA3D_BLENDEQ_INVALID = 0, + SVGA3D_BLENDEQ_ADD = 1, + SVGA3D_BLENDEQ_SUBTRACT = 2, + SVGA3D_BLENDEQ_REVSUBTRACT = 3, + SVGA3D_BLENDEQ_MINIMUM = 4, + SVGA3D_BLENDEQ_MAXIMUM = 5, + SVGA3D_BLENDEQ_MAX +} SVGA3dBlendEquation; + +typedef enum { + SVGA3D_FRONTWINDING_INVALID = 0, + SVGA3D_FRONTWINDING_CW = 1, + SVGA3D_FRONTWINDING_CCW = 2, + SVGA3D_FRONTWINDING_MAX +} SVGA3dFrontWinding; + +typedef enum { + SVGA3D_FACE_INVALID = 0, + SVGA3D_FACE_NONE = 1, + SVGA3D_FACE_FRONT = 2, + SVGA3D_FACE_BACK = 3, + SVGA3D_FACE_FRONT_BACK = 4, + SVGA3D_FACE_MAX +} SVGA3dFace; + +/* + * The order and the values should not be changed + */ + +typedef enum { + SVGA3D_CMP_INVALID = 0, + SVGA3D_CMP_NEVER = 1, + SVGA3D_CMP_LESS = 2, + SVGA3D_CMP_EQUAL = 3, + SVGA3D_CMP_LESSEQUAL = 4, + SVGA3D_CMP_GREATER = 5, + SVGA3D_CMP_NOTEQUAL = 6, + SVGA3D_CMP_GREATEREQUAL = 7, + SVGA3D_CMP_ALWAYS = 8, + SVGA3D_CMP_MAX +} SVGA3dCmpFunc; + +/* + * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows + * the fog factor to be specified in the alpha component of the specular + * (a.k.a. secondary) vertex color. + */ +typedef enum { + SVGA3D_FOGFUNC_INVALID = 0, + SVGA3D_FOGFUNC_EXP = 1, + SVGA3D_FOGFUNC_EXP2 = 2, + SVGA3D_FOGFUNC_LINEAR = 3, + SVGA3D_FOGFUNC_PER_VERTEX = 4 +} SVGA3dFogFunction; + +/* + * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex + * or per-pixel basis. + */ +typedef enum { + SVGA3D_FOGTYPE_INVALID = 0, + SVGA3D_FOGTYPE_VERTEX = 1, + SVGA3D_FOGTYPE_PIXEL = 2, + SVGA3D_FOGTYPE_MAX = 3 +} SVGA3dFogType; + +/* + * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is + * computed using the eye Z value of each pixel (or vertex), whereas range- + * based fog is computed using the actual distance (range) to the eye. + */ +typedef enum { + SVGA3D_FOGBASE_INVALID = 0, + SVGA3D_FOGBASE_DEPTHBASED = 1, + SVGA3D_FOGBASE_RANGEBASED = 2, + SVGA3D_FOGBASE_MAX = 3 +} SVGA3dFogBase; + +typedef enum { + SVGA3D_STENCILOP_INVALID = 0, + SVGA3D_STENCILOP_KEEP = 1, + SVGA3D_STENCILOP_ZERO = 2, + SVGA3D_STENCILOP_REPLACE = 3, + SVGA3D_STENCILOP_INCRSAT = 4, + SVGA3D_STENCILOP_DECRSAT = 5, + SVGA3D_STENCILOP_INVERT = 6, + SVGA3D_STENCILOP_INCR = 7, + SVGA3D_STENCILOP_DECR = 8, + SVGA3D_STENCILOP_MAX +} SVGA3dStencilOp; + +typedef enum { + SVGA3D_CLIPPLANE_0 = (1 << 0), + SVGA3D_CLIPPLANE_1 = (1 << 1), + SVGA3D_CLIPPLANE_2 = (1 << 2), + SVGA3D_CLIPPLANE_3 = (1 << 3), + SVGA3D_CLIPPLANE_4 = (1 << 4), + SVGA3D_CLIPPLANE_5 = (1 << 5), +} SVGA3dClipPlanes; + +typedef enum { + SVGA3D_CLEAR_COLOR = 0x1, + SVGA3D_CLEAR_DEPTH = 0x2, + SVGA3D_CLEAR_STENCIL = 0x4 +} SVGA3dClearFlag; + +typedef enum { + SVGA3D_RT_DEPTH = 0, + SVGA3D_RT_STENCIL = 1, + SVGA3D_RT_COLOR0 = 2, + SVGA3D_RT_COLOR1 = 3, + SVGA3D_RT_COLOR2 = 4, + SVGA3D_RT_COLOR3 = 5, + SVGA3D_RT_COLOR4 = 6, + SVGA3D_RT_COLOR5 = 7, + SVGA3D_RT_COLOR6 = 8, + SVGA3D_RT_COLOR7 = 9, + SVGA3D_RT_MAX, + SVGA3D_RT_INVALID = ((uint32)-1), +} SVGA3dRenderTargetType; + +#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1) + +typedef +union { + struct { + uint32 red : 1; + uint32 green : 1; + uint32 blue : 1; + uint32 alpha : 1; + }; + uint32 uintValue; +} SVGA3dColorMask; + +typedef enum { + SVGA3D_VBLEND_DISABLE = 0, + SVGA3D_VBLEND_1WEIGHT = 1, + SVGA3D_VBLEND_2WEIGHT = 2, + SVGA3D_VBLEND_3WEIGHT = 3, +} SVGA3dVertexBlendFlags; + +typedef enum { + SVGA3D_WRAPCOORD_0 = 1 << 0, + SVGA3D_WRAPCOORD_1 = 1 << 1, + SVGA3D_WRAPCOORD_2 = 1 << 2, + SVGA3D_WRAPCOORD_3 = 1 << 3, + SVGA3D_WRAPCOORD_ALL = 0xF, +} SVGA3dWrapFlags; + +/* + * SVGA_3D_CMD_TEXTURESTATE Types. All value types + * must fit in a uint32. + */ + +typedef enum { + SVGA3D_TS_INVALID = 0, + SVGA3D_TS_MIN = 1, + SVGA3D_TS_BIND_TEXTURE = 1, /* SVGA3dSurfaceId */ + SVGA3D_TS_COLOROP = 2, /* SVGA3dTextureCombiner */ + SVGA3D_TS_COLORARG1 = 3, /* SVGA3dTextureArgData */ + SVGA3D_TS_COLORARG2 = 4, /* SVGA3dTextureArgData */ + SVGA3D_TS_ALPHAOP = 5, /* SVGA3dTextureCombiner */ + SVGA3D_TS_ALPHAARG1 = 6, /* SVGA3dTextureArgData */ + SVGA3D_TS_ALPHAARG2 = 7, /* SVGA3dTextureArgData */ + SVGA3D_TS_ADDRESSU = 8, /* SVGA3dTextureAddress */ + SVGA3D_TS_ADDRESSV = 9, /* SVGA3dTextureAddress */ + SVGA3D_TS_MIPFILTER = 10, /* SVGA3dTextureFilter */ + SVGA3D_TS_MAGFILTER = 11, /* SVGA3dTextureFilter */ + SVGA3D_TS_MINFILTER = 12, /* SVGA3dTextureFilter */ + SVGA3D_TS_BORDERCOLOR = 13, /* SVGA3dColor */ + SVGA3D_TS_TEXCOORDINDEX = 14, /* uint32 */ + SVGA3D_TS_TEXTURETRANSFORMFLAGS = 15, /* SVGA3dTexTransformFlags */ + SVGA3D_TS_TEXCOORDGEN = 16, /* SVGA3dTextureCoordGen */ + SVGA3D_TS_BUMPENVMAT00 = 17, /* float */ + SVGA3D_TS_BUMPENVMAT01 = 18, /* float */ + SVGA3D_TS_BUMPENVMAT10 = 19, /* float */ + SVGA3D_TS_BUMPENVMAT11 = 20, /* float */ + SVGA3D_TS_TEXTURE_MIPMAP_LEVEL = 21, /* uint32 */ + SVGA3D_TS_TEXTURE_LOD_BIAS = 22, /* float */ + SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL = 23, /* uint32 */ + SVGA3D_TS_ADDRESSW = 24, /* SVGA3dTextureAddress */ + + + /* + * Sampler Gamma Level + * + * Sampler gamma effects the color of samples taken from the sampler. A + * value of 1.0 will produce linear samples. If the value is <= 0.0 the + * gamma value is ignored and a linear space is used. + */ + + SVGA3D_TS_GAMMA = 25, /* float */ + SVGA3D_TS_BUMPENVLSCALE = 26, /* float */ + SVGA3D_TS_BUMPENVLOFFSET = 27, /* float */ + SVGA3D_TS_COLORARG0 = 28, /* SVGA3dTextureArgData */ + SVGA3D_TS_ALPHAARG0 = 29, /* SVGA3dTextureArgData */ + SVGA3D_TS_PREGB_MAX = 30, /* Max value before GBObjects */ + SVGA3D_TS_CONSTANT = 30, /* SVGA3dColor */ + SVGA3D_TS_COLOR_KEY_ENABLE = 31, /* SVGA3dBool */ + SVGA3D_TS_COLOR_KEY = 32, /* SVGA3dColor */ + SVGA3D_TS_MAX +} SVGA3dTextureStateName; + +typedef enum { + SVGA3D_TC_INVALID = 0, + SVGA3D_TC_DISABLE = 1, + SVGA3D_TC_SELECTARG1 = 2, + SVGA3D_TC_SELECTARG2 = 3, + SVGA3D_TC_MODULATE = 4, + SVGA3D_TC_ADD = 5, + SVGA3D_TC_ADDSIGNED = 6, + SVGA3D_TC_SUBTRACT = 7, + SVGA3D_TC_BLENDTEXTUREALPHA = 8, + SVGA3D_TC_BLENDDIFFUSEALPHA = 9, + SVGA3D_TC_BLENDCURRENTALPHA = 10, + SVGA3D_TC_BLENDFACTORALPHA = 11, + SVGA3D_TC_MODULATE2X = 12, + SVGA3D_TC_MODULATE4X = 13, + SVGA3D_TC_DSDT = 14, + SVGA3D_TC_DOTPRODUCT3 = 15, + SVGA3D_TC_BLENDTEXTUREALPHAPM = 16, + SVGA3D_TC_ADDSIGNED2X = 17, + SVGA3D_TC_ADDSMOOTH = 18, + SVGA3D_TC_PREMODULATE = 19, + SVGA3D_TC_MODULATEALPHA_ADDCOLOR = 20, + SVGA3D_TC_MODULATECOLOR_ADDALPHA = 21, + SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22, + SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23, + SVGA3D_TC_BUMPENVMAPLUMINANCE = 24, + SVGA3D_TC_MULTIPLYADD = 25, + SVGA3D_TC_LERP = 26, + SVGA3D_TC_MAX +} SVGA3dTextureCombiner; + +#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0) + +typedef enum { + SVGA3D_TEX_ADDRESS_INVALID = 0, + SVGA3D_TEX_ADDRESS_WRAP = 1, + SVGA3D_TEX_ADDRESS_MIRROR = 2, + SVGA3D_TEX_ADDRESS_CLAMP = 3, + SVGA3D_TEX_ADDRESS_BORDER = 4, + SVGA3D_TEX_ADDRESS_MIRRORONCE = 5, + SVGA3D_TEX_ADDRESS_EDGE = 6, + SVGA3D_TEX_ADDRESS_MAX +} SVGA3dTextureAddress; + +/* + * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is + * disabled, and the rasterizer should use the magnification filter instead. + */ +typedef enum { + SVGA3D_TEX_FILTER_NONE = 0, + SVGA3D_TEX_FILTER_NEAREST = 1, + SVGA3D_TEX_FILTER_LINEAR = 2, + SVGA3D_TEX_FILTER_ANISOTROPIC = 3, + SVGA3D_TEX_FILTER_FLATCUBIC = 4, // Deprecated, not implemented + SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, // Deprecated, not implemented + SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, // Not currently implemented + SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, // Not currently implemented + SVGA3D_TEX_FILTER_MAX +} SVGA3dTextureFilter; + +typedef enum { + SVGA3D_TEX_TRANSFORM_OFF = 0, + SVGA3D_TEX_TRANSFORM_S = (1 << 0), + SVGA3D_TEX_TRANSFORM_T = (1 << 1), + SVGA3D_TEX_TRANSFORM_R = (1 << 2), + SVGA3D_TEX_TRANSFORM_Q = (1 << 3), + SVGA3D_TEX_PROJECTED = (1 << 15), +} SVGA3dTexTransformFlags; + +typedef enum { + SVGA3D_TEXCOORD_GEN_OFF = 0, + SVGA3D_TEXCOORD_GEN_EYE_POSITION = 1, + SVGA3D_TEXCOORD_GEN_EYE_NORMAL = 2, + SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3, + SVGA3D_TEXCOORD_GEN_SPHERE = 4, + SVGA3D_TEXCOORD_GEN_MAX +} SVGA3dTextureCoordGen; + +/* + * Texture argument constants for texture combiner + */ +typedef enum { + SVGA3D_TA_INVALID = 0, + SVGA3D_TA_CONSTANT = 1, + SVGA3D_TA_PREVIOUS = 2, + SVGA3D_TA_DIFFUSE = 3, + SVGA3D_TA_TEXTURE = 4, + SVGA3D_TA_SPECULAR = 5, + SVGA3D_TA_MAX +} SVGA3dTextureArgData; + +#define SVGA3D_TM_MASK_LEN 4 + +/* Modifiers for texture argument constants defined above. */ +typedef enum { + SVGA3D_TM_NONE = 0, + SVGA3D_TM_ALPHA = (1 << SVGA3D_TM_MASK_LEN), + SVGA3D_TM_ONE_MINUS = (2 << SVGA3D_TM_MASK_LEN), +} SVGA3dTextureArgModifier; + +#define SVGA3D_INVALID_ID ((uint32)-1) +#define SVGA3D_MAX_CLIP_PLANES 6 + +/* + * This is the limit to the number of fixed-function texture + * transforms and texture coordinates we can support. It does *not* + * correspond to the number of texture image units (samplers) we + * support! + */ +#define SVGA3D_MAX_TEXTURE_COORDS 8 + +/* + * Vertex declarations + * + * Notes: + * + * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you + * draw with any POSITIONT vertex arrays, the programmable vertex + * pipeline will be implicitly disabled. Drawing will take place as if + * no vertex shader was bound. + */ + +typedef enum { + SVGA3D_DECLUSAGE_POSITION = 0, + SVGA3D_DECLUSAGE_BLENDWEIGHT, // 1 + SVGA3D_DECLUSAGE_BLENDINDICES, // 2 + SVGA3D_DECLUSAGE_NORMAL, // 3 + SVGA3D_DECLUSAGE_PSIZE, // 4 + SVGA3D_DECLUSAGE_TEXCOORD, // 5 + SVGA3D_DECLUSAGE_TANGENT, // 6 + SVGA3D_DECLUSAGE_BINORMAL, // 7 + SVGA3D_DECLUSAGE_TESSFACTOR, // 8 + SVGA3D_DECLUSAGE_POSITIONT, // 9 + SVGA3D_DECLUSAGE_COLOR, // 10 + SVGA3D_DECLUSAGE_FOG, // 11 + SVGA3D_DECLUSAGE_DEPTH, // 12 + SVGA3D_DECLUSAGE_SAMPLE, // 13 + SVGA3D_DECLUSAGE_MAX +} SVGA3dDeclUsage; + +typedef enum { + SVGA3D_DECLMETHOD_DEFAULT = 0, + SVGA3D_DECLMETHOD_PARTIALU, + SVGA3D_DECLMETHOD_PARTIALV, + SVGA3D_DECLMETHOD_CROSSUV, // Normal + SVGA3D_DECLMETHOD_UV, + SVGA3D_DECLMETHOD_LOOKUP, // Lookup a displacement map + SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} SVGA3dDeclMethod; + +typedef enum { + SVGA3D_DECLTYPE_FLOAT1 = 0, + SVGA3D_DECLTYPE_FLOAT2 = 1, + SVGA3D_DECLTYPE_FLOAT3 = 2, + SVGA3D_DECLTYPE_FLOAT4 = 3, + SVGA3D_DECLTYPE_D3DCOLOR = 4, + SVGA3D_DECLTYPE_UBYTE4 = 5, + SVGA3D_DECLTYPE_SHORT2 = 6, + SVGA3D_DECLTYPE_SHORT4 = 7, + SVGA3D_DECLTYPE_UBYTE4N = 8, + SVGA3D_DECLTYPE_SHORT2N = 9, + SVGA3D_DECLTYPE_SHORT4N = 10, + SVGA3D_DECLTYPE_USHORT2N = 11, + SVGA3D_DECLTYPE_USHORT4N = 12, + SVGA3D_DECLTYPE_UDEC3 = 13, + SVGA3D_DECLTYPE_DEC3N = 14, + SVGA3D_DECLTYPE_FLOAT16_2 = 15, + SVGA3D_DECLTYPE_FLOAT16_4 = 16, + SVGA3D_DECLTYPE_MAX, +} SVGA3dDeclType; + +/* + * This structure is used for the divisor for geometry instancing; + * it's a direct translation of the Direct3D equivalent. + */ +typedef union { + struct { + /* + * For index data, this number represents the number of instances to draw. + * For instance data, this number represents the number of + * instances/vertex in this stream + */ + uint32 count : 30; + + /* + * This is 1 if this is supposed to be the data that is repeated for + * every instance. + */ + uint32 indexedData : 1; + + /* + * This is 1 if this is supposed to be the per-instance data. + */ + uint32 instanceData : 1; + }; + + uint32 value; +} SVGA3dVertexDivisor; + +typedef enum { + SVGA3D_PRIMITIVE_INVALID = 0, + SVGA3D_PRIMITIVE_TRIANGLELIST = 1, + SVGA3D_PRIMITIVE_POINTLIST = 2, + SVGA3D_PRIMITIVE_LINELIST = 3, + SVGA3D_PRIMITIVE_LINESTRIP = 4, + SVGA3D_PRIMITIVE_TRIANGLESTRIP = 5, + SVGA3D_PRIMITIVE_TRIANGLEFAN = 6, + SVGA3D_PRIMITIVE_MAX +} SVGA3dPrimitiveType; + +typedef enum { + SVGA3D_COORDINATE_INVALID = 0, + SVGA3D_COORDINATE_LEFTHANDED = 1, + SVGA3D_COORDINATE_RIGHTHANDED = 2, + SVGA3D_COORDINATE_MAX +} SVGA3dCoordinateType; + +typedef enum { + SVGA3D_TRANSFORM_INVALID = 0, + SVGA3D_TRANSFORM_WORLD = 1, + SVGA3D_TRANSFORM_VIEW = 2, + SVGA3D_TRANSFORM_PROJECTION = 3, + SVGA3D_TRANSFORM_TEXTURE0 = 4, + SVGA3D_TRANSFORM_TEXTURE1 = 5, + SVGA3D_TRANSFORM_TEXTURE2 = 6, + SVGA3D_TRANSFORM_TEXTURE3 = 7, + SVGA3D_TRANSFORM_TEXTURE4 = 8, + SVGA3D_TRANSFORM_TEXTURE5 = 9, + SVGA3D_TRANSFORM_TEXTURE6 = 10, + SVGA3D_TRANSFORM_TEXTURE7 = 11, + SVGA3D_TRANSFORM_WORLD1 = 12, + SVGA3D_TRANSFORM_WORLD2 = 13, + SVGA3D_TRANSFORM_WORLD3 = 14, + SVGA3D_TRANSFORM_MAX +} SVGA3dTransformType; + +typedef enum { + SVGA3D_LIGHTTYPE_INVALID = 0, + SVGA3D_LIGHTTYPE_POINT = 1, + SVGA3D_LIGHTTYPE_SPOT1 = 2, /* 1-cone, in degrees */ + SVGA3D_LIGHTTYPE_SPOT2 = 3, /* 2-cone, in radians */ + SVGA3D_LIGHTTYPE_DIRECTIONAL = 4, + SVGA3D_LIGHTTYPE_MAX +} SVGA3dLightType; + +typedef enum { + SVGA3D_CUBEFACE_POSX = 0, + SVGA3D_CUBEFACE_NEGX = 1, + SVGA3D_CUBEFACE_POSY = 2, + SVGA3D_CUBEFACE_NEGY = 3, + SVGA3D_CUBEFACE_POSZ = 4, + SVGA3D_CUBEFACE_NEGZ = 5, +} SVGA3dCubeFace; + +typedef enum { + SVGA3D_SHADERTYPE_INVALID = 0, + SVGA3D_SHADERTYPE_MIN = 1, + SVGA3D_SHADERTYPE_VS = 1, + SVGA3D_SHADERTYPE_PS = 2, + SVGA3D_SHADERTYPE_PREDX_MAX = 3, + SVGA3D_SHADERTYPE_GS = 3, + SVGA3D_SHADERTYPE_DX10_MAX = 4, + SVGA3D_SHADERTYPE_HS = 4, + SVGA3D_SHADERTYPE_DS = 5, + SVGA3D_SHADERTYPE_CS = 6, + SVGA3D_SHADERTYPE_MAX = 7 +} SVGA3dShaderType; + +#define SVGA3D_NUM_SHADERTYPE_PREDX \ + (SVGA3D_SHADERTYPE_PREDX_MAX - SVGA3D_SHADERTYPE_MIN) + +#define SVGA3D_NUM_SHADERTYPE_DX10 \ + (SVGA3D_SHADERTYPE_DX10_MAX - SVGA3D_SHADERTYPE_MIN) + +#define SVGA3D_NUM_SHADERTYPE \ + (SVGA3D_SHADERTYPE_MAX - SVGA3D_SHADERTYPE_MIN) + +/* + * Register limits for shader consts. + */ +#define SVGA3D_CONSTREG_MAX 256 +#define SVGA3D_CONSTINTREG_MAX 16 +#define SVGA3D_CONSTBOOLREG_MAX 16 + +typedef enum { + SVGA3D_CONST_TYPE_FLOAT = 0, + SVGA3D_CONST_TYPE_INT = 1, + SVGA3D_CONST_TYPE_BOOL = 2, +} SVGA3dShaderConstType; + +#define SVGA3D_MAX_SURFACE_FACES 6 + +typedef enum { + SVGA3D_STRETCH_BLT_POINT = 0, + SVGA3D_STRETCH_BLT_LINEAR = 1, + SVGA3D_STRETCH_BLT_MAX +} SVGA3dStretchBltMode; + +typedef enum { + SVGA3D_QUERYTYPE_OCCLUSION = 0, + SVGA3D_QUERYTYPE_MAX +} SVGA3dQueryType; + +typedef enum { + SVGA3D_QUERYSTATE_PENDING = 0, /* Waiting on the host (set by guest) */ + SVGA3D_QUERYSTATE_SUCCEEDED = 1, /* Completed successfully (set by host) */ + SVGA3D_QUERYSTATE_FAILED = 2, /* Completed unsuccessfully (set by host) */ + SVGA3D_QUERYSTATE_NEW = 3, /* Never submitted (For guest use only) */ +} SVGA3dQueryState; + +typedef enum { + SVGA3D_WRITE_HOST_VRAM = 1, + SVGA3D_READ_HOST_VRAM = 2, +} SVGA3dTransferType; + +/* + * The maximum number of vertex arrays we're guaranteed to support in + * SVGA_3D_CMD_DRAWPRIMITIVES. + */ +#define SVGA3D_MAX_VERTEX_ARRAYS 32 + +/* + * The maximum number of primitive ranges we're guaranteed to support + * in SVGA_3D_CMD_DRAWPRIMITIVES. + */ +#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32 + +/* + * Identifiers for commands in the command FIFO. + * + * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of + * the SVGA3D protocol and remain reserved; they should not be used in the + * future. + * + * IDs between 1040 and 1999 (inclusive) are available for use by the + * current SVGA3D protocol. + * + * FIFO clients other than SVGA3D should stay below 1000, or at 2000 + * and up. + */ + +#define SVGA_3D_CMD_LEGACY_BASE 1000 +#define SVGA_3D_CMD_BASE 1040 + +#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0 // Deprecated +#define SVGA_3D_CMD_SURFACE_DESTROY SVGA_3D_CMD_BASE + 1 +#define SVGA_3D_CMD_SURFACE_COPY SVGA_3D_CMD_BASE + 2 +#define SVGA_3D_CMD_SURFACE_STRETCHBLT SVGA_3D_CMD_BASE + 3 +#define SVGA_3D_CMD_SURFACE_DMA SVGA_3D_CMD_BASE + 4 +#define SVGA_3D_CMD_CONTEXT_DEFINE SVGA_3D_CMD_BASE + 5 +#define SVGA_3D_CMD_CONTEXT_DESTROY SVGA_3D_CMD_BASE + 6 +#define SVGA_3D_CMD_SETTRANSFORM SVGA_3D_CMD_BASE + 7 +#define SVGA_3D_CMD_SETZRANGE SVGA_3D_CMD_BASE + 8 +#define SVGA_3D_CMD_SETRENDERSTATE SVGA_3D_CMD_BASE + 9 +#define SVGA_3D_CMD_SETRENDERTARGET SVGA_3D_CMD_BASE + 10 +#define SVGA_3D_CMD_SETTEXTURESTATE SVGA_3D_CMD_BASE + 11 +#define SVGA_3D_CMD_SETMATERIAL SVGA_3D_CMD_BASE + 12 +#define SVGA_3D_CMD_SETLIGHTDATA SVGA_3D_CMD_BASE + 13 +#define SVGA_3D_CMD_SETLIGHTENABLED SVGA_3D_CMD_BASE + 14 +#define SVGA_3D_CMD_SETVIEWPORT SVGA_3D_CMD_BASE + 15 +#define SVGA_3D_CMD_SETCLIPPLANE SVGA_3D_CMD_BASE + 16 +#define SVGA_3D_CMD_CLEAR SVGA_3D_CMD_BASE + 17 +#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 // Deprecated +#define SVGA_3D_CMD_SHADER_DEFINE SVGA_3D_CMD_BASE + 19 +#define SVGA_3D_CMD_SHADER_DESTROY SVGA_3D_CMD_BASE + 20 +#define SVGA_3D_CMD_SET_SHADER SVGA_3D_CMD_BASE + 21 +#define SVGA_3D_CMD_SET_SHADER_CONST SVGA_3D_CMD_BASE + 22 +#define SVGA_3D_CMD_DRAW_PRIMITIVES SVGA_3D_CMD_BASE + 23 +#define SVGA_3D_CMD_SETSCISSORRECT SVGA_3D_CMD_BASE + 24 +#define SVGA_3D_CMD_BEGIN_QUERY SVGA_3D_CMD_BASE + 25 +#define SVGA_3D_CMD_END_QUERY SVGA_3D_CMD_BASE + 26 +#define SVGA_3D_CMD_WAIT_FOR_QUERY SVGA_3D_CMD_BASE + 27 +#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 // Deprecated +#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29 +#define SVGA_3D_CMD_SURFACE_DEFINE_V2 SVGA_3D_CMD_BASE + 30 +#define SVGA_3D_CMD_GENERATE_MIPMAPS SVGA_3D_CMD_BASE + 31 +#define SVGA_3D_CMD_ACTIVATE_SURFACE SVGA_3D_CMD_BASE + 40 +#define SVGA_3D_CMD_DEACTIVATE_SURFACE SVGA_3D_CMD_BASE + 41 +//#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 42 + +/* GPU10 commands */ +#define SVGA_3D_CMD_SCREEN_DMA 1082 +#define SVGA_3D_CMD_DEAD1 1083 +#define SVGA_3D_CMD_DEAD2 1084 + +#define SVGA_3D_CMD_DEAD12 1085 +#define SVGA_3D_CMD_DEAD13 1086 +#define SVGA_3D_CMD_DEAD14 1087 +#define SVGA_3D_CMD_DEAD15 1088 +#define SVGA_3D_CMD_DEAD16 1089 +#define SVGA_3D_CMD_DEAD17 1090 + +#define SVGA_3D_CMD_SET_OTABLE_BASE 1091 +#define SVGA_3D_CMD_READBACK_OTABLE 1092 + +#define SVGA_3D_CMD_DEFINE_GB_MOB 1093 +#define SVGA_3D_CMD_DESTROY_GB_MOB 1094 +#define SVGA_3D_CMD_DEAD3 1095 +#define SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING 1096 + +#define SVGA_3D_CMD_DEFINE_GB_SURFACE 1097 +#define SVGA_3D_CMD_DESTROY_GB_SURFACE 1098 +#define SVGA_3D_CMD_BIND_GB_SURFACE 1099 +#define SVGA_3D_CMD_COND_BIND_GB_SURFACE 1100 +#define SVGA_3D_CMD_UPDATE_GB_IMAGE 1101 +#define SVGA_3D_CMD_UPDATE_GB_SURFACE 1102 +#define SVGA_3D_CMD_READBACK_GB_IMAGE 1103 +#define SVGA_3D_CMD_READBACK_GB_SURFACE 1104 +#define SVGA_3D_CMD_INVALIDATE_GB_IMAGE 1105 +#define SVGA_3D_CMD_INVALIDATE_GB_SURFACE 1106 + +#define SVGA_3D_CMD_DEFINE_GB_CONTEXT 1107 +#define SVGA_3D_CMD_DESTROY_GB_CONTEXT 1108 +#define SVGA_3D_CMD_BIND_GB_CONTEXT 1109 +#define SVGA_3D_CMD_READBACK_GB_CONTEXT 1110 +#define SVGA_3D_CMD_INVALIDATE_GB_CONTEXT 1111 + +#define SVGA_3D_CMD_DEFINE_GB_SHADER 1112 +#define SVGA_3D_CMD_DESTROY_GB_SHADER 1113 +#define SVGA_3D_CMD_BIND_GB_SHADER 1114 + +#define SVGA_3D_CMD_SET_OTABLE_BASE64 1115 + +#define SVGA_3D_CMD_BEGIN_GB_QUERY 1116 +#define SVGA_3D_CMD_END_GB_QUERY 1117 +#define SVGA_3D_CMD_WAIT_FOR_GB_QUERY 1118 + +#define SVGA_3D_CMD_NOP 1119 + +#define SVGA_3D_CMD_ENABLE_GART 1120 +#define SVGA_3D_CMD_DISABLE_GART 1121 +#define SVGA_3D_CMD_MAP_MOB_INTO_GART 1122 +#define SVGA_3D_CMD_UNMAP_GART_RANGE 1123 + +#define SVGA_3D_CMD_DEFINE_GB_SCREENTARGET 1124 +#define SVGA_3D_CMD_DESTROY_GB_SCREENTARGET 1125 +#define SVGA_3D_CMD_BIND_GB_SCREENTARGET 1126 +#define SVGA_3D_CMD_UPDATE_GB_SCREENTARGET 1127 + +#define SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL 1128 +#define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129 + +#define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE 1130 + +#define SVGA_3D_CMD_GB_SCREEN_DMA 1131 +#define SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH 1132 +#define SVGA_3D_CMD_GB_MOB_FENCE 1133 +#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 1134 +#define SVGA_3D_CMD_DEFINE_GB_MOB64 1135 +#define SVGA_3D_CMD_REDEFINE_GB_MOB64 1136 +#define SVGA_3D_CMD_NOP_ERROR 1137 + +#define SVGA_3D_CMD_SET_VERTEX_STREAMS 1138 +#define SVGA_3D_CMD_SET_VERTEX_DECLS 1139 +#define SVGA_3D_CMD_SET_VERTEX_DIVISORS 1140 +#define SVGA_3D_CMD_DRAW 1141 +#define SVGA_3D_CMD_DRAW_INDEXED 1142 + +#define SVGA_3D_CMD_DX_MIN 1143 +#define SVGA_3D_CMD_DX_DEFINE_CONTEXT 1143 +#define SVGA_3D_CMD_DX_DESTROY_CONTEXT 1144 +#define SVGA_3D_CMD_DX_BIND_CONTEXT 1145 +#define SVGA_3D_CMD_DX_READBACK_CONTEXT 1146 +#define SVGA_3D_CMD_DX_INVALIDATE_CONTEXT 1147 +#define SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER 1148 +#define SVGA_3D_CMD_DX_SET_SHADER_RESOURCES 1149 +#define SVGA_3D_CMD_DX_SET_SHADER 1150 +#define SVGA_3D_CMD_DX_SET_SAMPLERS 1151 +#define SVGA_3D_CMD_DX_DRAW 1152 +#define SVGA_3D_CMD_DX_DRAW_INDEXED 1153 +#define SVGA_3D_CMD_DX_DRAW_INSTANCED 1154 +#define SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED 1155 +#define SVGA_3D_CMD_DX_DRAW_AUTO 1156 +#define SVGA_3D_CMD_DX_SET_INPUT_LAYOUT 1157 +#define SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS 1158 +#define SVGA_3D_CMD_DX_SET_INDEX_BUFFER 1159 +#define SVGA_3D_CMD_DX_SET_TOPOLOGY 1160 +#define SVGA_3D_CMD_DX_SET_RENDERTARGETS 1161 +#define SVGA_3D_CMD_DX_SET_BLEND_STATE 1162 +#define SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE 1163 +#define SVGA_3D_CMD_DX_SET_RASTERIZER_STATE 1164 +#define SVGA_3D_CMD_DX_DEFINE_QUERY 1165 +#define SVGA_3D_CMD_DX_DESTROY_QUERY 1166 +#define SVGA_3D_CMD_DX_BIND_QUERY 1167 +#define SVGA_3D_CMD_DX_SET_QUERY_OFFSET 1168 +#define SVGA_3D_CMD_DX_BEGIN_QUERY 1169 +#define SVGA_3D_CMD_DX_END_QUERY 1170 +#define SVGA_3D_CMD_DX_READBACK_QUERY 1171 +#define SVGA_3D_CMD_DX_SET_PREDICATION 1172 +#define SVGA_3D_CMD_DX_SET_SOTARGETS 1173 +#define SVGA_3D_CMD_DX_SET_VIEWPORTS 1174 +#define SVGA_3D_CMD_DX_SET_SCISSORRECTS 1175 +#define SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW 1176 +#define SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW 1177 +#define SVGA_3D_CMD_DX_PRED_COPY_REGION 1178 +#define SVGA_3D_CMD_DX_PRED_COPY 1179 +#define SVGA_3D_CMD_DX_PRESENTBLT 1180 +#define SVGA_3D_CMD_DX_GENMIPS 1181 +#define SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE 1182 +#define SVGA_3D_CMD_DX_READBACK_SUBRESOURCE 1183 +#define SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE 1184 +#define SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW 1185 +#define SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW 1186 +#define SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW 1187 +#define SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW 1188 +#define SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW 1189 +#define SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW 1190 +#define SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT 1191 +#define SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT 1192 +#define SVGA_3D_CMD_DX_DEFINE_BLEND_STATE 1193 +#define SVGA_3D_CMD_DX_DESTROY_BLEND_STATE 1194 +#define SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE 1195 +#define SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE 1196 +#define SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE 1197 +#define SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE 1198 +#define SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE 1199 +#define SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE 1200 +#define SVGA_3D_CMD_DX_DEFINE_SHADER 1201 +#define SVGA_3D_CMD_DX_DESTROY_SHADER 1202 +#define SVGA_3D_CMD_DX_BIND_SHADER 1203 +#define SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT 1204 +#define SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT 1205 +#define SVGA_3D_CMD_DX_SET_STREAMOUTPUT 1206 +#define SVGA_3D_CMD_DX_SET_COTABLE 1207 +#define SVGA_3D_CMD_DX_READBACK_COTABLE 1208 +#define SVGA_3D_CMD_DX_BUFFER_COPY 1209 +#define SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER 1210 +#define SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK 1211 +#define SVGA_3D_CMD_DX_MOVE_QUERY 1212 +#define SVGA_3D_CMD_DX_BIND_ALL_QUERY 1213 +#define SVGA_3D_CMD_DX_READBACK_ALL_QUERY 1214 +#define SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER 1215 +#define SVGA_3D_CMD_DX_MOB_FENCE_64 1216 +#define SVGA_3D_CMD_DX_BIND_ALL_SHADER 1217 +#define SVGA_3D_CMD_DX_HINT 1218 +#define SVGA_3D_CMD_DX_BUFFER_UPDATE 1219 +#define SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET 1220 +#define SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET 1221 +#define SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET 1222 +#define SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET 1223 +#define SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET 1224 +#define SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET 1225 + +#define SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER 1226 +#define SVGA_3D_CMD_DX_MAX 1227 + +#define SVGA_3D_CMD_SCREEN_COPY 1227 + +#define SVGA_3D_CMD_RESERVED1 1228 +#define SVGA_3D_CMD_RESERVED2 1229 +#define SVGA_3D_CMD_RESERVED3 1230 +#define SVGA_3D_CMD_RESERVED4 1231 +#define SVGA_3D_CMD_RESERVED5 1232 +#define SVGA_3D_CMD_RESERVED6 1233 +#define SVGA_3D_CMD_RESERVED7 1234 +#define SVGA_3D_CMD_RESERVED8 1235 + +#define SVGA_3D_CMD_GROW_OTABLE 1236 +#define SVGA_3D_CMD_DX_GROW_COTABLE 1237 +#define SVGA_3D_CMD_INTRA_SURFACE_COPY 1238 + +#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V3 1239 + +#define SVGA_3D_CMD_DX_RESOLVE_COPY 1240 +#define SVGA_3D_CMD_DX_PRED_RESOLVE_COPY 1241 +#define SVGA_3D_CMD_DX_PRED_CONVERT_REGION 1242 +#define SVGA_3D_CMD_DX_PRED_CONVERT 1243 +#define SVGA_3D_CMD_WHOLE_SURFACE_COPY 1244 + +#define SVGA_3D_CMD_DX_DEFINE_UA_VIEW 1245 +#define SVGA_3D_CMD_DX_DESTROY_UA_VIEW 1246 +#define SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT 1247 +#define SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT 1248 +#define SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT 1249 +#define SVGA_3D_CMD_DX_SET_UA_VIEWS 1250 + +#define SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT 1251 +#define SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT 1252 +#define SVGA_3D_CMD_DX_DISPATCH 1253 +#define SVGA_3D_CMD_DX_DISPATCH_INDIRECT 1254 + +#define SVGA_3D_CMD_WRITE_ZERO_SURFACE 1255 +#define SVGA_3D_CMD_UPDATE_ZERO_SURFACE 1256 +#define SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER 1257 +#define SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT 1258 + +#define SVGA_3D_CMD_LOGICOPS_BITBLT 1259 +#define SVGA_3D_CMD_LOGICOPS_TRANSBLT 1260 +#define SVGA_3D_CMD_LOGICOPS_STRETCHBLT 1261 +#define SVGA_3D_CMD_LOGICOPS_COLORFILL 1262 +#define SVGA_3D_CMD_LOGICOPS_ALPHABLEND 1263 +#define SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND 1264 + +#define SVGA_3D_CMD_DX_COPY_COTABLE_INTO_MOB 1265 + +#define SVGA_3D_CMD_UPDATE_GB_SCREENTARGET_V2 1266 + +#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 1267 +#define SVGA_3D_CMD_DX_SET_CS_UA_VIEWS 1268 +#define SVGA_3D_CMD_DX_SET_MIN_LOD 1269 + +#define SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2 1272 +#define SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB 1273 +#define SVGA_3D_CMD_DX_SET_SHADER_IFACE 1274 +#define SVGA_3D_CMD_DX_BIND_STREAMOUTPUT 1275 +#define SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS 1276 +#define SVGA_3D_CMD_DX_BIND_SHADER_IFACE 1277 + +#define SVGA_3D_CMD_UPDATE_GB_SCREENTARGET_MOVE 1278 + +#define SVGA_3D_CMD_DX_PRED_STAGING_COPY 1281 +#define SVGA_3D_CMD_DX_STAGING_COPY 1282 +#define SVGA_3D_CMD_DX_PRED_STAGING_COPY_REGION 1283 +#define SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS_V2 1284 +#define SVGA_3D_CMD_DX_SET_INDEX_BUFFER_V2 1285 +#define SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS_OFFSET_AND_SIZE 1286 +#define SVGA_3D_CMD_DX_SET_INDEX_BUFFER_OFFSET_AND_SIZE 1287 +#define SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE_V2 1288 +#define SVGA_3D_CMD_DX_PRED_STAGING_CONVERT_REGION 1289 +#define SVGA_3D_CMD_DX_PRED_STAGING_CONVERT 1290 +#define SVGA_3D_CMD_DX_STAGING_BUFFER_COPY 1291 + +#define SVGA_3D_CMD_MAX 1303 +#define SVGA_3D_CMD_FUTURE_MAX 3000 + +/* + * Common substructures used in multiple FIFO commands: + */ + +typedef struct { + union { + struct { + uint16 function; // SVGA3dFogFunction + uint8 type; // SVGA3dFogType + uint8 base; // SVGA3dFogBase + }; + uint32 uintValue; + }; +} SVGA3dFogMode; + +/* + * Uniquely identify one image (a 1D/2D/3D array) from a surface. This + * is a surface ID as well as face/mipmap indices. + */ + +typedef +struct SVGA3dSurfaceImageId { + uint32 sid; + uint32 face; + uint32 mipmap; +} SVGA3dSurfaceImageId; + +typedef +struct SVGA3dGuestImage { + SVGAGuestPtr ptr; + + /* + * A note on interpretation of pitch: This value of pitch is the + * number of bytes between vertically adjacent image + * blocks. Normally this is the number of bytes between the first + * pixel of two adjacent scanlines. With compressed textures, + * however, this may represent the number of bytes between + * compression blocks rather than between rows of pixels. + * + * XXX: Compressed textures currently must be tightly packed in guest memory. + * + * If the image is 1-dimensional, pitch is ignored. + * + * If 'pitch' is zero, the SVGA3D device calculates a pitch value + * assuming each row of blocks is tightly packed. + */ + uint32 pitch; +} SVGA3dGuestImage; + + +/* + * FIFO command format definitions: + */ + +/* + * The data size header following cmdNum for every 3d command + */ +typedef +struct { + uint32 id; + uint32 size; +} SVGA3dCmdHeader; + +/* + * A surface is a hierarchy of host VRAM surfaces: 1D, 2D, or 3D, with + * optional mipmaps and cube faces. + */ + +typedef +struct { + uint32 width; + uint32 height; + uint32 depth; +} SVGA3dSize; + +/* + * Guest-backed objects definitions. + */ +typedef enum { + SVGA_OTABLE_MOB = 0, + SVGA_OTABLE_MIN = 0, + SVGA_OTABLE_SURFACE = 1, + SVGA_OTABLE_CONTEXT = 2, + SVGA_OTABLE_SHADER = 3, + SVGA_OTABLE_SCREENTARGET = 4, + + SVGA_OTABLE_DX9_MAX = 5, + + SVGA_OTABLE_DXCONTEXT = 5, + SVGA_OTABLE_DX_MAX = 6, + + SVGA_OTABLE_RESERVED1 = 6, + SVGA_OTABLE_RESERVED2 = 7, + + /* + * Additions to this table need to be tied to HW-version features and + * checkpointed accordingly. + */ + SVGA_OTABLE_DEVEL_MAX = 8, + SVGA_OTABLE_MAX = 8 +} SVGAOTableType; + +typedef enum { + SVGA_COTABLE_MIN = 0, + SVGA_COTABLE_RTVIEW = 0, + SVGA_COTABLE_DSVIEW = 1, + SVGA_COTABLE_SRVIEW = 2, + SVGA_COTABLE_ELEMENTLAYOUT = 3, + SVGA_COTABLE_BLENDSTATE = 4, + SVGA_COTABLE_DEPTHSTENCIL = 5, + SVGA_COTABLE_RASTERIZERSTATE = 6, + SVGA_COTABLE_SAMPLER = 7, + SVGA_COTABLE_STREAMOUTPUT = 8, + SVGA_COTABLE_DXQUERY = 9, + SVGA_COTABLE_DXSHADER = 10, + SVGA_COTABLE_DX10_MAX = 11, + SVGA_COTABLE_UAVIEW = 11, + SVGA_COTABLE_MAX = 12, +} SVGACOTableType; + + +/* + * The largest size (number of entries) allowed in a COTable. + */ +#define SVGA_COTABLE_MAX_IDS (MAX_UINT16 - 2) + +typedef enum SVGAMobFormat { + SVGA3D_MOBFMT_INVALID = SVGA3D_INVALID_ID, + SVGA3D_MOBFMT_PTDEPTH_0 = 0, + SVGA3D_MOBFMT_MIN = 0, + SVGA3D_MOBFMT_PTDEPTH_1 = 1, + SVGA3D_MOBFMT_PTDEPTH_2 = 2, + SVGA3D_MOBFMT_RANGE = 3, + SVGA3D_MOBFMT_PTDEPTH64_0 = 4, + SVGA3D_MOBFMT_PTDEPTH64_1 = 5, + SVGA3D_MOBFMT_PTDEPTH64_2 = 6, + SVGA3D_MOBFMT_PREDX_MAX = 7, + SVGA3D_MOBFMT_EMPTY = 7, + SVGA3D_MOBFMT_MAX, + + /* + * This isn't actually used by the guest, but is a mob-format used + * internally by the SVGA device (and is therefore not binary compatible). + */ + SVGA3D_MOBFMT_HB, +} SVGAMobFormat; + +#define SVGA3D_MOB_EMPTY_BASE 1 + +/* + * Multisample pattern types. + */ + +typedef enum SVGA3dMSPattern { + SVGA3D_MS_PATTERN_NONE = 0, + SVGA3D_MS_PATTERN_MIN = 0, + SVGA3D_MS_PATTERN_STANDARD = 1, + SVGA3D_MS_PATTERN_CENTER = 2, + SVGA3D_MS_PATTERN_MAX = 3, +} SVGA3dMSPattern; + +/* + * Precision settings for each sample. + */ + +typedef enum SVGA3dMSQualityLevel { + SVGA3D_MS_QUALITY_NONE = 0, + SVGA3D_MS_QUALITY_MIN = 0, + SVGA3D_MS_QUALITY_FULL = 1, + SVGA3D_MS_QUALITY_MAX = 2, +} SVGA3dMSQualityLevel; + + +typedef enum { + SVGA3D_SURFACE_CUBEMAP = (1 << 0), + SVGA3D_SURFACE_HINT_STATIC = (1 << 1), + SVGA3D_SURFACE_HINT_DYNAMIC = (1 << 2), + SVGA3D_SURFACE_HINT_INDEXBUFFER = (1 << 3), + SVGA3D_SURFACE_HINT_VERTEXBUFFER = (1 << 4), + SVGA3D_SURFACE_HINT_TEXTURE = (1 << 5), + SVGA3D_SURFACE_HINT_RENDERTARGET = (1 << 6), + SVGA3D_SURFACE_HINT_DEPTHSTENCIL = (1 << 7), + SVGA3D_SURFACE_HINT_WRITEONLY = (1 << 8), + SVGA3D_SURFACE_MASKABLE_ANTIALIAS = (1 << 9), + SVGA3D_SURFACE_AUTOGENMIPMAPS = (1 << 10), +} SVGA3dSurfaceFlags; + +typedef +struct { + uint32 numMipLevels; +} SVGA3dSurfaceFace; + +typedef +struct { + uint32 sid; + SVGA3dSurfaceFlags surfaceFlags; + SVGA3dSurfaceFormat format; + /* + * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace + * structures must have the same value of numMipLevels field. + * Otherwise, all but the first SVGA3dSurfaceFace structures must have the + * numMipLevels set to 0. + */ + SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES]; + /* + * Followed by an SVGA3dSize structure for each mip level in each face. + * + * A note on surface sizes: Sizes are always specified in pixels, + * even if the true surface size is not a multiple of the minimum + * block size of the surface's format. For example, a 3x3x1 DXT1 + * compressed texture would actually be stored as a 4x4x1 image in + * memory. + */ +} SVGA3dCmdDefineSurface; /* SVGA_3D_CMD_SURFACE_DEFINE */ + +typedef +struct { + uint32 sid; + SVGA3dSurfaceFlags surfaceFlags; + SVGA3dSurfaceFormat format; + /* + * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace + * structures must have the same value of numMipLevels field. + * Otherwise, all but the first SVGA3dSurfaceFace structures must have the + * numMipLevels set to 0. + */ + SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES]; + uint32 multisampleCount; + SVGA3dTextureFilter autogenFilter; + /* + * Followed by an SVGA3dSize structure for each mip level in each face. + * + * A note on surface sizes: Sizes are always specified in pixels, + * even if the true surface size is not a multiple of the minimum + * block size of the surface's format. For example, a 3x3x1 DXT1 + * compressed texture would actually be stored as a 4x4x1 image in + * memory. + */ +} SVGA3dCmdDefineSurface_v2; /* SVGA_3D_CMD_SURFACE_DEFINE_V2 */ + +typedef +struct { + uint32 sid; +} SVGA3dCmdDestroySurface; /* SVGA_3D_CMD_SURFACE_DESTROY */ + +typedef +struct { + uint32 cid; +} SVGA3dCmdDefineContext; /* SVGA_3D_CMD_CONTEXT_DEFINE */ + +typedef +struct { + uint32 cid; +} SVGA3dCmdDestroyContext; /* SVGA_3D_CMD_CONTEXT_DESTROY */ + +typedef +struct { + uint32 cid; + SVGA3dClearFlag clearFlag; + uint32 color; + float depth; + uint32 stencil; + /* Followed by variable number of SVGA3dRect structures */ +} SVGA3dCmdClear; /* SVGA_3D_CMD_CLEAR */ + +typedef +struct SVGA3dCopyRect { + uint32 x; + uint32 y; + uint32 w; + uint32 h; + uint32 srcx; + uint32 srcy; +} SVGA3dCopyRect; + +typedef +struct SVGA3dCopyBox { + uint32 x; + uint32 y; + uint32 z; + uint32 w; + uint32 h; + uint32 d; + uint32 srcx; + uint32 srcy; + uint32 srcz; +} SVGA3dCopyBox; + +typedef +struct { + uint32 x; + uint32 y; + uint32 w; + uint32 h; +} SVGA3dRect; + +typedef +struct { + uint32 x; + uint32 y; + uint32 z; + uint32 w; + uint32 h; + uint32 d; +} SVGA3dBox; + +typedef +struct { + uint32 x; + uint32 y; + uint32 z; +} SVGA3dPoint; + +typedef +struct { + SVGA3dLightType type; + SVGA3dBool inWorldSpace; + float diffuse[4]; + float specular[4]; + float ambient[4]; + float position[4]; + float direction[4]; + float range; + float falloff; + float attenuation0; + float attenuation1; + float attenuation2; + float theta; + float phi; +} SVGA3dLightData; + +typedef +struct { + uint32 sid; + /* Followed by variable number of SVGA3dCopyRect structures */ +} SVGA3dCmdPresent; /* SVGA_3D_CMD_PRESENT */ + +typedef +struct { + SVGA3dRenderStateName state; + union { + uint32 uintValue; + float floatValue; + }; +} SVGA3dRenderState; + +typedef +struct { + uint32 cid; + /* Followed by variable number of SVGA3dRenderState structures */ +} SVGA3dCmdSetRenderState; /* SVGA_3D_CMD_SETRENDERSTATE */ + +typedef +struct { + uint32 cid; + SVGA3dRenderTargetType type; + SVGA3dSurfaceImageId target; +} SVGA3dCmdSetRenderTarget; /* SVGA_3D_CMD_SETRENDERTARGET */ + +typedef +struct { + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dest; + /* Followed by variable number of SVGA3dCopyBox structures */ +} SVGA3dCmdSurfaceCopy; /* SVGA_3D_CMD_SURFACE_COPY */ + +typedef +struct { + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dest; + SVGA3dBox boxSrc; + SVGA3dBox boxDest; + SVGA3dStretchBltMode mode; +} SVGA3dCmdSurfaceStretchBlt; /* SVGA_3D_CMD_SURFACE_STRETCHBLT */ + +typedef +struct { + /* + * If the discard flag is present in a surface DMA operation, the host may + * discard the contents of the current mipmap level and face of the target + * surface before applying the surface DMA contents. + */ + uint32 discard : 1; + + /* + * If the unsynchronized flag is present, the host may perform this upload + * without syncing to pending reads on this surface. + */ + uint32 unsynchronized : 1; + + /* + * Guests *MUST* set the reserved bits to 0 before submitting the command + * suffix as future flags may occupy these bits. + */ + uint32 reserved : 30; +} SVGA3dSurfaceDMAFlags; + +typedef +struct { + SVGA3dGuestImage guest; + SVGA3dSurfaceImageId host; + SVGA3dTransferType transfer; + /* + * Followed by variable number of SVGA3dCopyBox structures. For consistency + * in all clipping logic and coordinate translation, we define the + * "source" in each copyBox as the guest image and the + * "destination" as the host image, regardless of transfer + * direction. + * + * For efficiency, the SVGA3D device is free to copy more data than + * specified. For example, it may round copy boxes outwards such + * that they lie on particular alignment boundaries. + */ +} SVGA3dCmdSurfaceDMA; /* SVGA_3D_CMD_SURFACE_DMA */ + +/* + * SVGA3dCmdSurfaceDMASuffix -- + * + * This is a command suffix that will appear after a SurfaceDMA command in + * the FIFO. It contains some extra information that hosts may use to + * optimize performance or protect the guest. This suffix exists to preserve + * backwards compatibility while also allowing for new functionality to be + * implemented. + */ + +typedef +struct { + uint32 suffixSize; + + /* + * The maximum offset is used to determine the maximum offset from the + * guestPtr base address that will be accessed or written to during this + * surfaceDMA. If the suffix is supported, the host will respect this + * boundary while performing surface DMAs. + * + * Defaults to MAX_UINT32 + */ + uint32 maximumOffset; + + /* + * A set of flags that describes optimizations that the host may perform + * while performing this surface DMA operation. The guest should never rely + * on behaviour that is different when these flags are set for correctness. + * + * Defaults to 0 + */ + SVGA3dSurfaceDMAFlags flags; +} SVGA3dCmdSurfaceDMASuffix; + +/* + * SVGA_3D_CMD_DRAW_PRIMITIVES -- + * + * This command is the SVGA3D device's generic drawing entry point. + * It can draw multiple ranges of primitives, optionally using an + * index buffer, using an arbitrary collection of vertex buffers. + * + * Each SVGA3dVertexDecl defines a distinct vertex array to bind + * during this draw call. The declarations specify which surface + * the vertex data lives in, what that vertex data is used for, + * and how to interpret it. + * + * Each SVGA3dPrimitiveRange defines a collection of primitives + * to render using the same vertex arrays. An index buffer is + * optional. + */ + +typedef +struct { + /* + * A range hint is an optional specification for the range of indices + * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed + * that the entire array will be used. + * + * These are only hints. The SVGA3D device may use them for + * performance optimization if possible, but it's also allowed to + * ignore these values. + */ + uint32 first; + uint32 last; +} SVGA3dArrayRangeHint; + +typedef +struct { + /* + * Define the origin and shape of a vertex or index array. Both + * 'offset' and 'stride' are in bytes. The provided surface will be + * reinterpreted as a flat array of bytes in the same format used + * by surface DMA operations. To avoid unnecessary conversions, the + * surface should be created with the SVGA3D_BUFFER format. + * + * Index 0 in the array starts 'offset' bytes into the surface. + * Index 1 begins at byte 'offset + stride', etc. Array indices may + * not be negative. + */ + uint32 surfaceId; + uint32 offset; + uint32 stride; +} SVGA3dArray; + +typedef +struct { + /* + * Describe a vertex array's data type, and define how it is to be + * used by the fixed function pipeline or the vertex shader. It + * isn't useful to have two VertexDecls with the same + * VertexArrayIdentity in one draw call. + */ + SVGA3dDeclType type; + SVGA3dDeclMethod method; + SVGA3dDeclUsage usage; + uint32 usageIndex; +} SVGA3dVertexArrayIdentity; + +typedef +struct { + SVGA3dVertexArrayIdentity identity; + SVGA3dArray array; + SVGA3dArrayRangeHint rangeHint; +} SVGA3dVertexDecl; + +typedef +struct { + /* + * Define a group of primitives to render, from sequential indices. + * + * The value of 'primitiveType' and 'primitiveCount' imply the + * total number of vertices that will be rendered. + */ + SVGA3dPrimitiveType primType; + uint32 primitiveCount; + + /* + * Optional index buffer. If indexArray.surfaceId is + * SVGA3D_INVALID_ID, we render without an index buffer. Rendering + * without an index buffer is identical to rendering with an index + * buffer containing the sequence [0, 1, 2, 3, ...]. + * + * If an index buffer is in use, indexWidth specifies the width in + * bytes of each index value. It must be less than or equal to + * indexArray.stride. + * + * (Currently, the SVGA3D device requires index buffers to be tightly + * packed. In other words, indexWidth == indexArray.stride) + */ + SVGA3dArray indexArray; + uint32 indexWidth; + + /* + * Optional index bias. This number is added to all indices from + * indexArray before they are used as vertex array indices. This + * can be used in multiple ways: + * + * - When not using an indexArray, this bias can be used to + * specify where in the vertex arrays to begin rendering. + * + * - A positive number here is equivalent to increasing the + * offset in each vertex array. + * + * - A negative number can be used to render using a small + * vertex array and an index buffer that contains large + * values. This may be used by some applications that + * crop a vertex buffer without modifying their index + * buffer. + * + * Note that rendering with a negative bias value may be slower and + * use more memory than rendering with a positive or zero bias. + */ + int32 indexBias; +} SVGA3dPrimitiveRange; + +typedef +struct { + uint32 cid; + uint32 numVertexDecls; + uint32 numRanges; + + /* + * There are two variable size arrays after the + * SVGA3dCmdDrawPrimitives structure. In order, + * they are: + * + * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than + * SVGA3D_MAX_VERTEX_ARRAYS; + * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than + * SVGA3D_MAX_DRAW_PRIMITIVE_RANGES; + * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains + * the frequency divisor for the corresponding vertex decl). + */ +} SVGA3dCmdDrawPrimitives; /* SVGA_3D_CMD_DRAWPRIMITIVES */ + +typedef +struct { + uint32 stage; + SVGA3dTextureStateName name; + union { + uint32 value; + float floatValue; + }; +} SVGA3dTextureState; + +typedef +struct { + uint32 cid; + /* Followed by variable number of SVGA3dTextureState structures */ +} SVGA3dCmdSetTextureState; /* SVGA_3D_CMD_SETTEXTURESTATE */ + +typedef +struct { + uint32 cid; + SVGA3dTransformType type; + float matrix[16]; +} SVGA3dCmdSetTransform; /* SVGA_3D_CMD_SETTRANSFORM */ + +typedef +struct { + float min; + float max; +} SVGA3dZRange; + +typedef +struct { + uint32 cid; + SVGA3dZRange zRange; +} SVGA3dCmdSetZRange; /* SVGA_3D_CMD_SETZRANGE */ + +typedef +struct { + float diffuse[4]; + float ambient[4]; + float specular[4]; + float emissive[4]; + float shininess; +} SVGA3dMaterial; + +typedef +struct { + uint32 cid; + SVGA3dFace face; + SVGA3dMaterial material; +} SVGA3dCmdSetMaterial; /* SVGA_3D_CMD_SETMATERIAL */ + +typedef +struct { + uint32 cid; + uint32 index; + SVGA3dLightData data; +} SVGA3dCmdSetLightData; /* SVGA_3D_CMD_SETLIGHTDATA */ + +typedef +struct { + uint32 cid; + uint32 index; + uint32 enabled; +} SVGA3dCmdSetLightEnabled; /* SVGA_3D_CMD_SETLIGHTENABLED */ + +typedef +struct { + uint32 cid; + SVGA3dRect rect; +} SVGA3dCmdSetViewport; /* SVGA_3D_CMD_SETVIEWPORT */ + +typedef +struct { + uint32 cid; + SVGA3dRect rect; +} SVGA3dCmdSetScissorRect; /* SVGA_3D_CMD_SETSCISSORRECT */ + +typedef +struct { + uint32 cid; + uint32 index; + float plane[4]; +} SVGA3dCmdSetClipPlane; /* SVGA_3D_CMD_SETCLIPPLANE */ + +typedef +struct { + uint32 cid; + uint32 shid; + SVGA3dShaderType type; + /* Followed by variable number of DWORDs for shader bycode */ +} SVGA3dCmdDefineShader; /* SVGA_3D_CMD_SHADER_DEFINE */ + +typedef +struct { + uint32 cid; + uint32 shid; + SVGA3dShaderType type; +} SVGA3dCmdDestroyShader; /* SVGA_3D_CMD_SHADER_DESTROY */ + +typedef +struct { + uint32 cid; + uint32 reg; /* register number */ + SVGA3dShaderType type; + SVGA3dShaderConstType ctype; + uint32 values[4]; +} SVGA3dCmdSetShaderConst; /* SVGA_3D_CMD_SET_SHADER_CONST */ + +typedef +struct { + uint32 cid; + SVGA3dShaderType type; + uint32 shid; +} SVGA3dCmdSetShader; /* SVGA_3D_CMD_SET_SHADER */ + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; +} SVGA3dCmdBeginQuery; /* SVGA_3D_CMD_BEGIN_QUERY */ + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; + SVGAGuestPtr guestResult; /* Points to an SVGA3dQueryResult structure */ +} SVGA3dCmdEndQuery; /* SVGA_3D_CMD_END_QUERY */ + +typedef +struct { + uint32 cid; /* Same parameters passed to END_QUERY */ + SVGA3dQueryType type; + SVGAGuestPtr guestResult; +} SVGA3dCmdWaitForQuery; /* SVGA_3D_CMD_WAIT_FOR_QUERY */ + +typedef +struct { + uint32 totalSize; /* Set by guest before query is ended. */ + SVGA3dQueryState state; /* Set by host or guest. See SVGA3dQueryState. */ + union { /* Set by host on exit from PENDING state */ + uint32 result32; + }; +} SVGA3dQueryResult; + +/* + * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN -- + * + * This is a blit from an SVGA3D surface to a Screen Object. Just + * like GMR-to-screen blits, this blit may be directed at a + * specific screen or to the virtual coordinate space. + * + * The blit copies from a rectangular region of an SVGA3D surface + * image to a rectangular region of a screen or screens. + * + * This command takes an optional variable-length list of clipping + * rectangles after the body of the command. If no rectangles are + * specified, there is no clipping region. The entire destRect is + * drawn to. If one or more rectangles are included, they describe + * a clipping region. The clip rectangle coordinates are measured + * relative to the top-left corner of destRect. + * + * This clipping region serves multiple purposes: + * + * - It can be used to perform an irregularly shaped blit more + * efficiently than by issuing many separate blit commands. + * + * - It is equivalent to allowing blits with non-integer + * source coordinates. You could blit just one half-pixel + * of a source, for example, by specifying a larger + * destination rectangle than you need, then removing + * part of it using a clip rectangle. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + * + * Limitations: + * + * - Currently, no backend supports blits from a mipmap or face + * other than the first one. + */ + +typedef +struct { + SVGA3dSurfaceImageId srcImage; + SVGASignedRect srcRect; + uint32 destScreenId; /* Screen ID or SVGA_ID_INVALID for virt. coords */ + SVGASignedRect destRect; /* Supports scaling if src/rest different size */ + /* Clipping: zero or more SVGASignedRects follow */ +} SVGA3dCmdBlitSurfaceToScreen; /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */ + +typedef +struct { + uint32 sid; + SVGA3dTextureFilter filter; +} SVGA3dCmdGenerateMipmaps; /* SVGA_3D_CMD_GENERATE_MIPMAPS */ + + +/* + * Capability query index. + * + * Notes: + * + * 1. SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of + * fixed-function texture units available. Each of these units + * work in both FFP and Shader modes, and they support texture + * transforms and texture coordinates. The host may have additional + * texture image units that are only usable with shaders. + * + * 2. The BUFFER_FORMAT capabilities are deprecated, and they always + * return TRUE. Even on physical hardware that does not support + * these formats natively, the SVGA3D device will provide an emulation + * which should be invisible to the guest OS. + * + * In general, the SVGA3D device should support any operation on + * any surface format, it just may perform some of these + * operations in software depending on the capabilities of the + * available physical hardware. + * + * XXX: In the future, we will add capabilities that describe in + * detail what formats are supported in hardware for what kinds + * of operations. + */ + +typedef enum { + SVGA3D_DEVCAP_3D = 0, + SVGA3D_DEVCAP_MAX_LIGHTS = 1, + SVGA3D_DEVCAP_MAX_TEXTURES = 2, /* See note (1) */ + SVGA3D_DEVCAP_MAX_CLIP_PLANES = 3, + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = 4, + SVGA3D_DEVCAP_VERTEX_SHADER = 5, + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = 6, + SVGA3D_DEVCAP_FRAGMENT_SHADER = 7, + SVGA3D_DEVCAP_MAX_RENDER_TARGETS = 8, + SVGA3D_DEVCAP_S23E8_TEXTURES = 9, + SVGA3D_DEVCAP_S10E5_TEXTURES = 10, + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = 11, + SVGA3D_DEVCAP_D16_BUFFER_FORMAT = 12, /* See note (2) */ + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = 13, /* See note (2) */ + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = 14, /* See note (2) */ + SVGA3D_DEVCAP_QUERY_TYPES = 15, + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = 16, + SVGA3D_DEVCAP_MAX_POINT_SIZE = 17, + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = 18, + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = 19, + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = 20, + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = 21, + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = 22, + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = 23, + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = 24, + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = 25, + SVGA3D_DEVCAP_MAX_VERTEX_INDEX = 26, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = 27, + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = 28, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = 29, + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = 30, + SVGA3D_DEVCAP_TEXTURE_OPS = 31, + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = 32, + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = 33, + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = 34, + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = 35, + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = 36, + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = 37, + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = 38, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = 39, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = 40, + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = 41, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = 42, + SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = 43, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = 44, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = 45, + SVGA3D_DEVCAP_SURFACEFMT_DXT1 = 46, + SVGA3D_DEVCAP_SURFACEFMT_DXT2 = 47, + SVGA3D_DEVCAP_SURFACEFMT_DXT3 = 48, + SVGA3D_DEVCAP_SURFACEFMT_DXT4 = 49, + SVGA3D_DEVCAP_SURFACEFMT_DXT5 = 50, + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = 51, + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = 52, + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = 53, + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = 54, + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = 55, + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = 56, + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = 57, + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = 58, + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = 59, + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = 60, + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = 61, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = 63, + + /* + * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color + * render targets. This does no include the depth or stencil targets. + */ + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = 64, + + SVGA3D_DEVCAP_SURFACEFMT_V16U16 = 65, + SVGA3D_DEVCAP_SURFACEFMT_G16R16 = 66, + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67, + SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68, + SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69, + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = 70, + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = 71, + SVGA3D_DEVCAP_ALPHATOCOVERAGE = 72, + SVGA3D_DEVCAP_SUPERSAMPLE = 73, + SVGA3D_DEVCAP_AUTOGENMIPMAPS = 74, + SVGA3D_DEVCAP_SURFACEFMT_NV12 = 75, + SVGA3D_DEVCAP_SURFACEFMT_AYUV = 76, + + /* + * This is the maximum number of SVGA context IDs that the guest + * can define using SVGA_3D_CMD_CONTEXT_DEFINE. + */ + SVGA3D_DEVCAP_MAX_CONTEXT_IDS = 77, + + /* + * This is the maximum number of SVGA surface IDs that the guest + * can define using SVGA_3D_CMD_SURFACE_DEFINE*. + */ + SVGA3D_DEVCAP_MAX_SURFACE_IDS = 78, + + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = 79, + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = 80, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = 81, + + SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = 82, + SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = 83, + + /* + * Don't add new caps into the previous section; the values in this + * enumeration must not change. You can put new values right before + * SVGA3D_DEVCAP_MAX. + */ + SVGA3D_DEVCAP_MAX /* This must be the last index. */ +} SVGA3dDevCapIndex; + +typedef union { + Bool b; + uint32 u; + int32 i; + float f; +} SVGA3dDevCapResult; + +/******************************************************************************* + * + * G P U 1 0 + * + ******************************************************************************/ + +/* https://elixir.bootlin.com/linux/v5.2-rc3/source/drivers/gpu/drm/vmwgfx/device_include/svga3d_cmd.h */ + +/* + * Screen DMA command + * + * Available with SVGA_FIFO_CAP_SCREEN_OBJECT_2. The SVGA_CAP_3D device + * cap bit is not required. + * + * - refBuffer and destBuffer are 32bit BGRX; refBuffer and destBuffer could + * be different, but it is required that guest makes sure refBuffer has + * exactly the same contents that were written to when last time screen DMA + * command is received by host. + * + * - changemap is generated by lib/blit, and it has the changes from last + * received screen DMA or more. + */ + +typedef struct SVGA3dCmdScreenDMA { + uint32 screenId; + SVGAGuestImage refBuffer; + SVGAGuestImage destBuffer; + SVGAGuestImage changeMap; +} +SVGA3dCmdScreenDMA; /* SVGA_3D_CMD_SCREEN_DMA */ + +/* + * Logic ops + */ + +#define SVGA3D_LOTRANSBLT_HONORALPHA (0x01) +#define SVGA3D_LOSTRETCHBLT_MIRRORX (0x01) +#define SVGA3D_LOSTRETCHBLT_MIRRORY (0x02) +#define SVGA3D_LOALPHABLEND_SRCHASALPHA (0x01) + +typedef +struct SVGA3dCmdLogicOpsBitBlt { + /* + * All LogicOps surfaces are one-level + * surfaces so mipmap & face should always + * be zero. + */ + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dst; + SVGA3dLogicOp logicOp; + /* Followed by variable number of SVGA3dCopyBox structures */ +} +SVGA3dCmdLogicOpsBitBlt; /* SVGA_3D_CMD_LOGICOPS_BITBLT */ + + +typedef +struct SVGA3dCmdLogicOpsTransBlt { + /* + * All LogicOps surfaces are one-level + * surfaces so mipmap & face should always + * be zero. + */ + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dst; + uint32 color; + uint32 flags; + SVGA3dBox srcBox; + SVGA3dBox dstBox; +} +SVGA3dCmdLogicOpsTransBlt; /* SVGA_3D_CMD_LOGICOPS_TRANSBLT */ + + +typedef +struct SVGA3dCmdLogicOpsStretchBlt { + /* + * All LogicOps surfaces are one-level + * surfaces so mipmap & face should always + * be zero. + */ + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dst; + uint16 mode; + uint16 flags; + SVGA3dBox srcBox; + SVGA3dBox dstBox; +} +SVGA3dCmdLogicOpsStretchBlt; /* SVGA_3D_CMD_LOGICOPS_STRETCHBLT */ + + +typedef +struct SVGA3dCmdLogicOpsColorFill { + /* + * All LogicOps surfaces are one-level + * surfaces so mipmap & face should always + * be zero. + */ + SVGA3dSurfaceImageId dst; + uint32 color; + SVGA3dLogicOp logicOp; + /* Followed by variable number of SVGA3dRect structures. */ +} +SVGA3dCmdLogicOpsColorFill; /* SVGA_3D_CMD_LOGICOPS_COLORFILL */ + + +typedef +struct SVGA3dCmdLogicOpsAlphaBlend { + /* + * All LogicOps surfaces are one-level + * surfaces so mipmap & face should always + * be zero. + */ + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dst; + uint32 alphaVal; + uint32 flags; + SVGA3dBox srcBox; + SVGA3dBox dstBox; +} +SVGA3dCmdLogicOpsAlphaBlend; /* SVGA_3D_CMD_LOGICOPS_ALPHABLEND */ + +#define SVGA3D_CLEARTYPE_INVALID_GAMMA_INDEX 0xFFFFFFFF + +#define SVGA3D_CLEARTYPE_GAMMA_WIDTH 512 +#define SVGA3D_CLEARTYPE_GAMMA_HEIGHT 16 + +typedef +struct SVGA3dCmdLogicOpsClearTypeBlend { + /* + * All LogicOps surfaces are one-level + * surfaces so mipmap & face should always + * be zero. + */ + SVGA3dSurfaceImageId tmp; + SVGA3dSurfaceImageId dst; + SVGA3dSurfaceImageId gammaSurf; + SVGA3dSurfaceImageId alphaSurf; + uint32 gamma; + uint32 color; + uint32 color2; + int32 alphaOffsetX; + int32 alphaOffsetY; + /* Followed by variable number of SVGA3dBox structures */ +} +SVGA3dCmdLogicOpsClearTypeBlend; /* SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND */ + + +/* + * Guest-backed objects definitions. + */ + +typedef +struct { + SVGAMobFormat ptDepth; + uint32 sizeInBytes; + PPN64 base; +} +SVGAOTableMobEntry; +#define SVGA3D_OTABLE_MOB_ENTRY_SIZE (sizeof(SVGAOTableMobEntry)) + +typedef +struct { + SVGA3dSurfaceFormat format; + SVGA3dSurface1Flags surface1Flags; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; + SVGAMobId mobid; + uint32 arraySize; + uint32 mobPitch; + SVGA3dSurface2Flags surface2Flags; + uint8 multisamplePattern; + uint8 qualityLevel; + uint8 pad0[2]; + uint32 pad1[3]; +} +SVGAOTableSurfaceEntry; +#define SVGA3D_OTABLE_SURFACE_ENTRY_SIZE (sizeof(SVGAOTableSurfaceEntry)) + +typedef +struct { + uint32 cid; + SVGAMobId mobid; +} +SVGAOTableContextEntry; +#define SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE (sizeof(SVGAOTableContextEntry)) + +typedef +struct { + SVGA3dShaderType type; + uint32 sizeInBytes; + uint32 offsetInBytes; + SVGAMobId mobid; +} +SVGAOTableShaderEntry; +#define SVGA3D_OTABLE_SHADER_ENTRY_SIZE (sizeof(SVGAOTableShaderEntry)) + +#define SVGA_STFLAG_PRIMARY (1 << 0) +#define SVGA_STFLAG_RESERVED (1 << 1) /* Added with cap SVGA_CAP_HP_CMD_QUEUE */ +typedef uint32 SVGAScreenTargetFlags; + +typedef +struct { + SVGA3dSurfaceImageId image; + uint32 width; + uint32 height; + int32 xRoot; + int32 yRoot; + SVGAScreenTargetFlags flags; + uint32 dpi; + uint32 pad[7]; +} +SVGAOTableScreenTargetEntry; +#define SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE \ + (sizeof(SVGAOTableScreenTargetEntry)) + +typedef +struct { + float value[4]; +} +SVGA3dShaderConstFloat; + +typedef +struct { + int32 value[4]; +} +SVGA3dShaderConstInt; + +typedef +struct { + uint32 value; +} +SVGA3dShaderConstBool; + +typedef +struct { + uint16 streamOffset; + uint8 stream; + uint8 type; + uint8 methodUsage; + uint8 usageIndex; +} +SVGAGBVertexElement; + +typedef +struct { + uint32 sid; + uint16 stride; + uint32 offset; +} +SVGAGBVertexStream; +typedef +struct { + SVGA3dRect viewport; + SVGA3dRect scissorRect; + SVGA3dZRange zRange; + + SVGA3dSurfaceImageId renderTargets[SVGA3D_RT_MAX]; + SVGAGBVertexElement decl1[4]; + + uint32 renderStates[SVGA3D_RS_MAX]; + SVGAGBVertexElement decl2[18]; + uint32 pad0[2]; + + struct { + SVGA3dFace face; + SVGA3dMaterial material; + } material; + + float clipPlanes[SVGA3D_NUM_CLIPPLANES][4]; + float matrices[SVGA3D_TRANSFORM_MAX][16]; + + SVGA3dBool lightEnabled[SVGA3D_NUM_LIGHTS]; + SVGA3dLightData lightData[SVGA3D_NUM_LIGHTS]; + + /* + * Shaders currently bound + */ + uint32 shaders[SVGA3D_NUM_SHADERTYPE_PREDX]; + SVGAGBVertexElement decl3[10]; + uint32 pad1[3]; + + uint32 occQueryActive; + uint32 occQueryValue; + + /* + * Int/Bool Shader constants + */ + SVGA3dShaderConstInt pShaderIValues[SVGA3D_CONSTINTREG_MAX]; + SVGA3dShaderConstInt vShaderIValues[SVGA3D_CONSTINTREG_MAX]; + uint16 pShaderBValues; + uint16 vShaderBValues; + + + SVGAGBVertexStream streams[SVGA3D_MAX_VERTEX_ARRAYS]; + SVGA3dVertexDivisor divisors[SVGA3D_MAX_VERTEX_ARRAYS]; + uint32 numVertexDecls; + uint32 numVertexStreams; + uint32 numVertexDivisors; + uint32 pad2[30]; + + /* + * Texture Stages + * + * SVGA3D_TS_INVALID through SVGA3D_TS_CONSTANT are in the + * textureStages array. + * SVGA3D_TS_COLOR_KEY is in tsColorKey. + */ + uint32 tsColorKey[SVGA3D_NUM_TEXTURE_UNITS]; + uint32 textureStages[SVGA3D_NUM_TEXTURE_UNITS][SVGA3D_TS_CONSTANT + 1]; + uint32 tsColorKeyEnable[SVGA3D_NUM_TEXTURE_UNITS]; + + /* + * Float Shader constants. + */ + SVGA3dShaderConstFloat pShaderFValues[SVGA3D_CONSTREG_MAX]; + SVGA3dShaderConstFloat vShaderFValues[SVGA3D_CONSTREG_MAX]; +} +SVGAGBContextData; +#define SVGA3D_CONTEXT_DATA_SIZE (sizeof(SVGAGBContextData)) + +/* + * SVGA3dCmdSetOTableBase -- + * + * This command allows the guest to specify the base PPN of the + * specified object table. + */ + +typedef +struct { + SVGAOTableType type; + PPN baseAddress; + uint32 sizeInBytes; + uint32 validSizeInBytes; + SVGAMobFormat ptDepth; +} +SVGA3dCmdSetOTableBase; /* SVGA_3D_CMD_SET_OTABLE_BASE */ + +typedef +struct { + SVGAOTableType type; + PPN64 baseAddress; + uint32 sizeInBytes; + uint32 validSizeInBytes; + SVGAMobFormat ptDepth; +} +SVGA3dCmdSetOTableBase64; /* SVGA_3D_CMD_SET_OTABLE_BASE64 */ + +/* + * Guests using SVGA_3D_CMD_GROW_OTABLE are promising that + * the new OTable contains the same contents as the old one, except possibly + * for some new invalid entries at the end. + * + * (Otherwise, guests should use one of the SetOTableBase commands.) + */ +typedef +struct { + SVGAOTableType type; + PPN64 baseAddress; + uint32 sizeInBytes; + uint32 validSizeInBytes; + SVGAMobFormat ptDepth; +} +SVGA3dCmdGrowOTable; /* SVGA_3D_CMD_GROW_OTABLE */ + +typedef +struct { + SVGAOTableType type; +} +SVGA3dCmdReadbackOTable; /* SVGA_3D_CMD_READBACK_OTABLE */ + +/* + * Define a memory object (Mob) in the OTable. + */ + +typedef +struct SVGA3dCmdDefineGBMob { + SVGAMobId mobid; + SVGAMobFormat ptDepth; + PPN base; + uint32 sizeInBytes; +} +SVGA3dCmdDefineGBMob; /* SVGA_3D_CMD_DEFINE_GB_MOB */ + + +/* + * Destroys an object in the OTable. + */ + +typedef +struct SVGA3dCmdDestroyGBMob { + SVGAMobId mobid; +} +SVGA3dCmdDestroyGBMob; /* SVGA_3D_CMD_DESTROY_GB_MOB */ + + +/* + * Define a memory object (Mob) in the OTable with a PPN64 base. + */ + +typedef +struct SVGA3dCmdDefineGBMob64 { + SVGAMobId mobid; + SVGAMobFormat ptDepth; + PPN64 base; + uint32 sizeInBytes; +} +SVGA3dCmdDefineGBMob64; /* SVGA_3D_CMD_DEFINE_GB_MOB64 */ + +/* + * Redefine an object in the OTable with PPN64 base. + */ + +typedef +struct SVGA3dCmdRedefineGBMob64 { + SVGAMobId mobid; + SVGAMobFormat ptDepth; + PPN64 base; + uint32 sizeInBytes; +} +SVGA3dCmdRedefineGBMob64; /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */ + +/* + * Notification that the page tables have been modified. + */ + +typedef +struct SVGA3dCmdUpdateGBMobMapping { + SVGAMobId mobid; +} +SVGA3dCmdUpdateGBMobMapping; /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */ + +/* + * Define a guest-backed surface. + */ + +typedef +struct SVGA3dCmdDefineGBSurface { + uint32 sid; + SVGA3dSurface1Flags surfaceFlags; + SVGA3dSurfaceFormat format; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; +} +SVGA3dCmdDefineGBSurface; /* SVGA_3D_CMD_DEFINE_GB_SURFACE */ + +/* + * Defines a guest-backed surface, adding the arraySize field. + */ +typedef +struct SVGA3dCmdDefineGBSurface_v2 { + uint32 sid; + SVGA3dSurface1Flags surfaceFlags; + SVGA3dSurfaceFormat format; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; + uint32 arraySize; + uint32 pad; +} +SVGA3dCmdDefineGBSurface_v2; /* SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 */ + +/* + * Defines a guest-backed surface, adding the larger flags. + */ +typedef +struct SVGA3dCmdDefineGBSurface_v3 { + uint32 sid; + SVGA3dSurfaceAllFlags surfaceFlags; + SVGA3dSurfaceFormat format; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dMSPattern multisamplePattern; + SVGA3dMSQualityLevel qualityLevel; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; + uint32 arraySize; +} +SVGA3dCmdDefineGBSurface_v3; /* SVGA_3D_CMD_DEFINE_GB_SURFACE_V3 */ + +/* + * Defines a guest-backed surface, adding buffer byte stride. + */ +typedef +struct SVGA3dCmdDefineGBSurface_v4 { + uint32 sid; + SVGA3dSurfaceAllFlags surfaceFlags; + SVGA3dSurfaceFormat format; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dMSPattern multisamplePattern; + SVGA3dMSQualityLevel qualityLevel; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; + uint32 arraySize; + uint32 bufferByteStride; +} +SVGA3dCmdDefineGBSurface_v4; /* SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 */ + +/* + * Destroy a guest-backed surface. + */ + +typedef +struct SVGA3dCmdDestroyGBSurface { + uint32 sid; +} +SVGA3dCmdDestroyGBSurface; /* SVGA_3D_CMD_DESTROY_GB_SURFACE */ + +/* + * Bind a guest-backed surface to a mob. + */ + +typedef +struct SVGA3dCmdBindGBSurface { + uint32 sid; + SVGAMobId mobid; +} +SVGA3dCmdBindGBSurface; /* SVGA_3D_CMD_BIND_GB_SURFACE */ + +typedef +struct SVGA3dCmdBindGBSurfaceWithPitch { + uint32 sid; + SVGAMobId mobid; + uint32 baseLevelPitch; +} +SVGA3dCmdBindGBSurfaceWithPitch; /* SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH */ + +/* + * Conditionally bind a mob to a guest-backed surface if testMobid + * matches the currently bound mob. Optionally issue a + * readback/update on the surface while it is still bound to the old + * mobid if the mobid is changed by this command. + */ + +#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_READBACK (1 << 0) +#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_UPDATE (1 << 1) + +typedef +struct SVGA3dCmdCondBindGBSurface { + uint32 sid; + SVGAMobId testMobid; + SVGAMobId mobid; + uint32 flags; +} +SVGA3dCmdCondBindGBSurface; /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */ + +/* + * Update an image in a guest-backed surface. + * (Inform the device that the guest-contents have been updated.) + */ + +typedef +struct SVGA3dCmdUpdateGBImage { + SVGA3dSurfaceImageId image; + SVGA3dBox box; +} +SVGA3dCmdUpdateGBImage; /* SVGA_3D_CMD_UPDATE_GB_IMAGE */ + +/* + * Update an entire guest-backed surface. + * (Inform the device that the guest-contents have been updated.) + */ + +typedef +struct SVGA3dCmdUpdateGBSurface { + uint32 sid; +} +SVGA3dCmdUpdateGBSurface; /* SVGA_3D_CMD_UPDATE_GB_SURFACE */ + +/* + * Readback an image in a guest-backed surface. + * (Request the device to flush the dirty contents into the guest.) + */ + +typedef +struct SVGA3dCmdReadbackGBImage { + SVGA3dSurfaceImageId image; +} +SVGA3dCmdReadbackGBImage; /* SVGA_3D_CMD_READBACK_GB_IMAGE */ + +/* + * Readback an entire guest-backed surface. + * (Request the device to flush the dirty contents into the guest.) + */ + +typedef +struct SVGA3dCmdReadbackGBSurface { + uint32 sid; +} +SVGA3dCmdReadbackGBSurface; /* SVGA_3D_CMD_READBACK_GB_SURFACE */ + +/* + * Readback a sub rect of an image in a guest-backed surface. After + * issuing this command the driver is required to issue an update call + * of the same region before issuing any other commands that reference + * this surface or rendering is not guaranteed. + */ + +typedef +struct SVGA3dCmdReadbackGBImagePartial { + SVGA3dSurfaceImageId image; + SVGA3dBox box; + uint32 invertBox; +} +SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */ + + +/* + * Invalidate an image in a guest-backed surface. + * (Notify the device that the contents can be lost.) + */ + +typedef +struct SVGA3dCmdInvalidateGBImage { + SVGA3dSurfaceImageId image; +} +SVGA3dCmdInvalidateGBImage; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */ + +/* + * Invalidate an entire guest-backed surface. + * (Notify the device that the contents if all images can be lost.) + */ + +typedef +struct SVGA3dCmdInvalidateGBSurface { + uint32 sid; +} +SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */ + +/* + * Invalidate a sub rect of an image in a guest-backed surface. After + * issuing this command the driver is required to issue an update call + * of the same region before issuing any other commands that reference + * this surface or rendering is not guaranteed. + */ + +typedef +struct SVGA3dCmdInvalidateGBImagePartial { + SVGA3dSurfaceImageId image; + SVGA3dBox box; + uint32 invertBox; +} +SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */ + + +/* + * Define a guest-backed context. + */ + +typedef +struct SVGA3dCmdDefineGBContext { + uint32 cid; +} +SVGA3dCmdDefineGBContext; /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */ + +/* + * Destroy a guest-backed context. + */ + +typedef +struct SVGA3dCmdDestroyGBContext { + uint32 cid; +} +SVGA3dCmdDestroyGBContext; /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */ + +/* + * Bind a guest-backed context. + * + * validContents should be set to 0 for new contexts, + * and 1 if this is an old context which is getting paged + * back on to the device. + * + * For new contexts, it is recommended that the driver + * issue commands to initialize all interesting state + * prior to rendering. + */ + +typedef +struct SVGA3dCmdBindGBContext { + uint32 cid; + SVGAMobId mobid; + uint32 validContents; +} +SVGA3dCmdBindGBContext; /* SVGA_3D_CMD_BIND_GB_CONTEXT */ + +/* + * Readback a guest-backed context. + * (Request that the device flush the contents back into guest memory.) + */ + +typedef +struct SVGA3dCmdReadbackGBContext { + uint32 cid; +} +SVGA3dCmdReadbackGBContext; /* SVGA_3D_CMD_READBACK_GB_CONTEXT */ + +/* + * Invalidate a guest-backed context. + */ +typedef +struct SVGA3dCmdInvalidateGBContext { + uint32 cid; +} +SVGA3dCmdInvalidateGBContext; /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */ + +/* + * Define a guest-backed shader. + */ + +typedef +struct SVGA3dCmdDefineGBShader { + uint32 shid; + SVGA3dShaderType type; + uint32 sizeInBytes; +} +SVGA3dCmdDefineGBShader; /* SVGA_3D_CMD_DEFINE_GB_SHADER */ + +/* + * Bind a guest-backed shader. + */ + +typedef +struct SVGA3dCmdBindGBShader { + uint32 shid; + SVGAMobId mobid; + uint32 offsetInBytes; +} +SVGA3dCmdBindGBShader; /* SVGA_3D_CMD_BIND_GB_SHADER */ + +/* + * Destroy a guest-backed shader. + */ + +typedef +struct SVGA3dCmdDestroyGBShader { + uint32 shid; +} +SVGA3dCmdDestroyGBShader; /* SVGA_3D_CMD_DESTROY_GB_SHADER */ + +typedef +struct { + uint32 cid; + uint32 regStart; + SVGA3dShaderType shaderType; + SVGA3dShaderConstType constType; + + /* + * Followed by a variable number of shader constants. + * + * Note that FLOAT and INT constants are 4-dwords in length, while + * BOOL constants are 1-dword in length. + */ +} +SVGA3dCmdSetGBShaderConstInline; /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */ + + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; +} +SVGA3dCmdBeginGBQuery; /* SVGA_3D_CMD_BEGIN_GB_QUERY */ + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; + SVGAMobId mobid; + uint32 offset; +} +SVGA3dCmdEndGBQuery; /* SVGA_3D_CMD_END_GB_QUERY */ + + +/* + * SVGA_3D_CMD_WAIT_FOR_GB_QUERY -- + * + * The semantics of this command are identical to the + * SVGA_3D_CMD_WAIT_FOR_QUERY except that the results are written + * to a Mob instead of a GMR. + */ + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; + SVGAMobId mobid; + uint32 offset; +} +SVGA3dCmdWaitForGBQuery; /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */ + + +typedef +struct { + SVGAMobId mobid; + uint32 mustBeZero; + uint32 initialized; +} +SVGA3dCmdEnableGart; /* SVGA_3D_CMD_ENABLE_GART */ + +typedef +struct { + SVGAMobId mobid; + uint32 gartOffset; +} +SVGA3dCmdMapMobIntoGart; /* SVGA_3D_CMD_MAP_MOB_INTO_GART */ + + +typedef +struct { + uint32 gartOffset; + uint32 numPages; +} +SVGA3dCmdUnmapGartRange; /* SVGA_3D_CMD_UNMAP_GART_RANGE */ + + +/* + * Screen Targets + */ + +typedef +struct { + uint32 stid; + uint32 width; + uint32 height; + int32 xRoot; + int32 yRoot; + SVGAScreenTargetFlags flags; + + /* + * The physical DPI that the guest expects this screen displayed at. + * + * Guests which are not DPI-aware should set this to zero. + */ + uint32 dpi; +} +SVGA3dCmdDefineGBScreenTarget; /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */ + +typedef +struct { + uint32 stid; +} +SVGA3dCmdDestroyGBScreenTarget; /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */ + +typedef +struct { + uint32 stid; + SVGA3dSurfaceImageId image; +} +SVGA3dCmdBindGBScreenTarget; /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */ + +typedef +struct { + uint32 stid; + SVGA3dRect rect; +} +SVGA3dCmdUpdateGBScreenTarget; /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */ + +typedef +struct SVGA3dCmdGBScreenDMA { + uint32 screenId; + uint32 dead; + SVGAMobId destMobID; + uint32 destPitch; + SVGAMobId changeMapMobID; +} +SVGA3dCmdGBScreenDMA; /* SVGA_3D_CMD_GB_SCREEN_DMA */ + +typedef +struct { + uint32 value; + uint32 mobId; + uint32 mobOffset; +} +SVGA3dCmdGBMobFence; /* SVGA_3D_CMD_GB_MOB_FENCE */ + +typedef +struct { + uint32 stid; + SVGA3dSurfaceImageId dest; + + uint32 statusMobId; + uint32 statusMobOffset; + + /* Reserved fields */ + uint32 mustBeInvalidId; + uint32 mustBeZero; +} +SVGA3dCmdScreenCopy; /* SVGA_3D_CMD_SCREEN_COPY */ + +#define SVGA_SCREEN_COPY_STATUS_FAILURE 0x00 +#define SVGA_SCREEN_COPY_STATUS_SUCCESS 0x01 +#define SVGA_SCREEN_COPY_STATUS_INVALID 0xFFFFFFFF + + +#endif /* _SVGA3D_REG_H_ */ diff --git a/vmware/svga_all.h b/vmware/svga_all.h new file mode 100644 index 0000000..de26664 --- /dev/null +++ b/vmware/svga_all.h @@ -0,0 +1,13 @@ +#ifndef __SVGA_ALL_H__INCLUDED__
+#define __SVGA_ALL_H__INCLUDED__
+
+#pragma pack(push)
+#pragma pack(1)
+#include "svga.h"
+#include "svga_reg.h"
+#include "svga3d.h"
+#include "svga3d_reg.h"
+#include "svga3d_caps.h"
+#pragma pack(pop)
+
+#endif /* __SVGA_ALL_H__INCLUDED__ */
diff --git a/vmware/svga_escape.h b/vmware/svga_escape.h new file mode 100644 index 0000000..7b85e9b --- /dev/null +++ b/vmware/svga_escape.h @@ -0,0 +1,89 @@ +/********************************************************** + * Copyright 2007-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga_escape.h -- + * + * Definitions for our own (vendor-specific) SVGA Escape commands. + */ + +#ifndef _SVGA_ESCAPE_H_ +#define _SVGA_ESCAPE_H_ + + +/* + * Namespace IDs for the escape command + */ + +#define SVGA_ESCAPE_NSID_VMWARE 0x00000000 +#define SVGA_ESCAPE_NSID_DEVEL 0xFFFFFFFF + + +/* + * Within SVGA_ESCAPE_NSID_VMWARE, we multiplex commands according to + * the first DWORD of escape data (after the nsID and size). As a + * guideline we're using the high word and low word as a major and + * minor command number, respectively. + * + * Major command number allocation: + * + * 0000: Reserved + * 0001: SVGA_ESCAPE_VMWARE_LOG (svga_binary_logger.h) + * 0002: SVGA_ESCAPE_VMWARE_VIDEO (svga_overlay.h) + * 0003: SVGA_ESCAPE_VMWARE_HINT (svga_escape.h) + */ + +#define SVGA_ESCAPE_VMWARE_MAJOR_MASK 0xFFFF0000 + + +/* + * SVGA Hint commands. + * + * These escapes let the SVGA driver provide optional information to + * he host about the state of the guest or guest applications. The + * host can use these hints to make user interface or performance + * decisions. + * + * Notes: + * + * - SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN is deprecated for guests + * that use the SVGA Screen Object extension. Instead of sending + * this escape, use the SVGA_SCREEN_FULLSCREEN_HINT flag on your + * Screen Object. + */ + +#define SVGA_ESCAPE_VMWARE_HINT 0x00030000 +#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001 // Deprecated + +typedef +struct { + uint32 command; + uint32 fullscreen; + struct { + int32 x, y; + } monitorPosition; +} SVGAEscapeHintFullscreen; + +#endif /* _SVGA_ESCAPE_H_ */ diff --git a/vmware/svga_overlay.h b/vmware/svga_overlay.h new file mode 100644 index 0000000..82c1d3f --- /dev/null +++ b/vmware/svga_overlay.h @@ -0,0 +1,201 @@ +/********************************************************** + * Copyright 2007-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga_overlay.h -- + * + * Definitions for video-overlay support. + */ + +#ifndef _SVGA_OVERLAY_H_ +#define _SVGA_OVERLAY_H_ + +#include "svga_reg.h" + +/* + * Video formats we support + */ + +#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2' +#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2' +#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y' + +typedef enum { + SVGA_OVERLAY_FORMAT_INVALID = 0, + SVGA_OVERLAY_FORMAT_YV12 = VMWARE_FOURCC_YV12, + SVGA_OVERLAY_FORMAT_YUY2 = VMWARE_FOURCC_YUY2, + SVGA_OVERLAY_FORMAT_UYVY = VMWARE_FOURCC_UYVY, +} SVGAOverlayFormat; + +#define SVGA_VIDEO_COLORKEY_MASK 0x00ffffff + +#define SVGA_ESCAPE_VMWARE_VIDEO 0x00020000 + +#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS 0x00020001 + /* FIFO escape layout: + * Type, Stream Id, (Register Id, Value) pairs */ + +#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH 0x00020002 + /* FIFO escape layout: + * Type, Stream Id */ + +typedef +struct SVGAEscapeVideoSetRegs { + struct { + uint32 cmdType; + uint32 streamId; + } header; + + // May include zero or more items. + struct { + uint32 registerId; + uint32 value; + } items[1]; +} SVGAEscapeVideoSetRegs; + +typedef +struct SVGAEscapeVideoFlush { + uint32 cmdType; + uint32 streamId; +} SVGAEscapeVideoFlush; + + +/* + * Struct definitions for the video overlay commands built on + * SVGAFifoCmdEscape. + */ +typedef +struct { + uint32 command; + uint32 overlay; +} SVGAFifoEscapeCmdVideoBase; + +typedef +struct { + SVGAFifoEscapeCmdVideoBase videoCmd; +} SVGAFifoEscapeCmdVideoFlush; + +typedef +struct { + SVGAFifoEscapeCmdVideoBase videoCmd; + struct { + uint32 regId; + uint32 value; + } items[1]; +} SVGAFifoEscapeCmdVideoSetRegs; + +typedef +struct { + SVGAFifoEscapeCmdVideoBase videoCmd; + struct { + uint32 regId; + uint32 value; + } items[SVGA_VIDEO_NUM_REGS]; +} SVGAFifoEscapeCmdVideoSetAllRegs; + + +/* + *---------------------------------------------------------------------- + * + * VMwareVideoGetAttributes -- + * + * Computes the size, pitches and offsets for YUV frames. + * + * Results: + * TRUE on success; otherwise FALSE on failure. + * + * Side effects: + * Pitches and offsets for the given YUV frame are put in 'pitches' + * and 'offsets' respectively. They are both optional though. + * + *---------------------------------------------------------------------- + */ + +static INLINE Bool +VMwareVideoGetAttributes(const SVGAOverlayFormat format, // IN + uint32 *width, // IN / OUT + uint32 *height, // IN / OUT + uint32 *size, // OUT + uint32 *pitches, // OUT (optional) + uint32 *offsets) // OUT (optional) +{ + int tmp; + + *width = (*width + 1) & ~1; + + if (offsets) { + offsets[0] = 0; + } + + switch (format) { + case VMWARE_FOURCC_YV12: + *height = (*height + 1) & ~1; + *size = (*width + 3) & ~3; + + if (pitches) { + pitches[0] = *size; + } + + *size *= *height; + + if (offsets) { + offsets[1] = *size; + } + + tmp = ((*width >> 1) + 3) & ~3; + + if (pitches) { + pitches[1] = pitches[2] = tmp; + } + + tmp *= (*height >> 1); + *size += tmp; + + if (offsets) { + offsets[2] = *size; + } + + *size += tmp; + break; + + case VMWARE_FOURCC_YUY2: + case VMWARE_FOURCC_UYVY: + *size = *width * 2; + + if (pitches) { + pitches[0] = *size; + } + + *size *= *height; + break; + + default: + return FALSE; + } + + return TRUE; +} + +#endif // _SVGA_OVERLAY_H_ diff --git a/vmware/svga_reg.h b/vmware/svga_reg.h new file mode 100644 index 0000000..04707c3 --- /dev/null +++ b/vmware/svga_reg.h @@ -0,0 +1,1610 @@ +/********************************************************** + * Copyright 1998-2009 VMware, Inc. All rights reserved. + * + * 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 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. + * + **********************************************************/ + +/* + * svga_reg.h -- + * + * Virtual hardware definitions for the VMware SVGA II device. + */ + +#ifndef _SVGA_REG_H_ +#define _SVGA_REG_H_ + +/* + * PCI device IDs. + */ +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 + +#define PCI_VENDOR_ID_INNOTEK 0x80EE +#define PCI_DEVICE_ID_VBOX_VGA 0xBEEF + +#define PCI_SUBCLASS_ID_SVGA2 0x040515ADUL + +/* + * SVGA_REG_ENABLE bit definitions. + */ +#define SVGA_REG_ENABLE_DISABLE 0 +#define SVGA_REG_ENABLE_ENABLE 1 +#define SVGA_REG_ENABLE_HIDE 2 +#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\ + SVGA_REG_ENABLE_HIDE) + +/* + * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned + * cursor bypass mode. This is still supported, but no new guest + * drivers should use it. + */ +#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */ +#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */ + +/* + * The maximum framebuffer size that can traced for e.g. guests in VESA mode. + * The changeMap in the monitor is proportional to this number. Therefore, we'd + * like to keep it as small as possible to reduce monitor overhead (using + * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over + * 4k!). + * + * NB: For compatibility reasons, this value must be greater than 0xff0000. + * See bug 335072. + */ +#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000 + +#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 +#define SVGA_MAX_PSEUDOCOLORS (1UL << SVGA_MAX_PSEUDOCOLOR_DEPTH) +#define SVGA_NUM_PALETTE_REGS (3UL * SVGA_MAX_PSEUDOCOLORS) + +#define SVGA_MAGIC 0x900000UL +#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) + +#define SVGA_VERSION_3 3 +#define SVGA_ID_3 SVGA_MAKE_ID(SVGA_VERSION_3) + +/* Version 2 let the address of the frame buffer be unsigned on Win32 */ +#define SVGA_VERSION_2 2 +#define SVGA_ID_2 SVGA_MAKE_ID(SVGA_VERSION_2) + +/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so + PALETTE_BASE has moved */ +#define SVGA_VERSION_1 1 +#define SVGA_ID_1 SVGA_MAKE_ID(SVGA_VERSION_1) + +/* Version 0 is the initial version */ +#define SVGA_VERSION_0 0 +#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0) + +/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */ +#define SVGA_ID_INVALID 0xFFFFFFFF + +/* Port offsets, relative to BAR0 */ +#define SVGA_INDEX_PORT 0x0 +#define SVGA_VALUE_PORT 0x1 +#define SVGA_BIOS_PORT 0x2 +#define SVGA_IRQSTATUS_PORT 0x8 + +/* + * Interrupt source flags for IRQSTATUS_PORT and IRQMASK. + * + * Interrupts are only supported when the + * SVGA_CAP_IRQMASK capability is present. + */ +#define SVGA_IRQFLAG_ANY_FENCE 0x1 /* Any fence was passed */ +#define SVGA_IRQFLAG_FIFO_PROGRESS 0x2 /* Made forward progress in the FIFO */ +#define SVGA_IRQFLAG_FENCE_GOAL 0x4 /* SVGA_FIFO_FENCE_GOAL reached */ + +/* + * Registers + */ + +enum { + SVGA_REG_ID = 0, + SVGA_REG_ENABLE = 1, + SVGA_REG_WIDTH = 2, + SVGA_REG_HEIGHT = 3, + SVGA_REG_MAX_WIDTH = 4, + SVGA_REG_MAX_HEIGHT = 5, + SVGA_REG_DEPTH = 6, + SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ + SVGA_REG_PSEUDOCOLOR = 8, + SVGA_REG_RED_MASK = 9, + SVGA_REG_GREEN_MASK = 10, + SVGA_REG_BLUE_MASK = 11, + SVGA_REG_BYTES_PER_LINE = 12, + SVGA_REG_FB_START = 13, /* (Deprecated) */ + SVGA_REG_FB_OFFSET = 14, + SVGA_REG_VRAM_SIZE = 15, + SVGA_REG_FB_SIZE = 16, + + /* ID 0 implementation only had the above registers, then the palette */ + + SVGA_REG_CAPABILITIES = 17, + SVGA_REG_MEM_START = 18, /* (Deprecated) */ + SVGA_REG_MEM_SIZE = 19, + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ + SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ + SVGA_REG_CURSOR_ID = 24, /* (Deprecated) */ + SVGA_REG_CURSOR_X = 25, /* (Deprecated) */ + SVGA_REG_CURSOR_Y = 26, /* (Deprecated) */ + SVGA_REG_CURSOR_ON = 27, /* (Deprecated) */ + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */ + SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ + SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ + SVGA_REG_NUM_DISPLAYS = 31, /* (Deprecated) */ + SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ + SVGA_REG_IRQMASK = 33, /* Interrupt mask */ + + /* Legacy multi-monitor support */ + SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */ + SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */ + SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */ + SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */ + SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */ + SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */ + SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */ + + /* See "Guest memory regions" below. */ + SVGA_REG_GMR_ID = 41, + SVGA_REG_GMR_DESCRIPTOR = 42, + SVGA_REG_GMR_MAX_IDS = 43, + SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44, + + SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ + SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */ + SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */ + + /* SVGA_3 registers */ + SVGA_REG_COMMAND_LOW = 48, + SVGA_REG_COMMAND_HIGH = 49, + SVGA_REG_MAX_PRIMARY_MEM = 50, + SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, + SVGA_REG_DEV_CAP = 52, + SVGA_REG_CMD_PREPEND_LOW = 53, + SVGA_REG_CMD_PREPEND_HIGH = 54, + SVGA_REG_SCREENTARGET_MAX_WIDTH = 55, + SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56, + SVGA_REG_MOB_MAX_SIZE = 57, + SVGA_REG_BLANK_SCREEN_TARGETS = 58, + SVGA_REG_CAP2 = 59, + SVGA_REG_DEVEL_CAP = 60, + SVGA_REG_GUEST_DRIVER_ID = 61, + SVGA_REG_GUEST_DRIVER_VERSION1 = 62, + SVGA_REG_GUEST_DRIVER_VERSION2 = 63, + SVGA_REG_GUEST_DRIVER_VERSION3 = 64, + SVGA_REG_CURSOR_MOBID = 65, + SVGA_REG_CURSOR_MAX_BYTE_SIZE = 66, + SVGA_REG_CURSOR_MAX_DIMENSION = 67, + SVGA_REG_FIFO_CAPS = 68, + SVGA_REG_FENCE = 69, + SVGA_REG_CURSOR4_ON = 70, + SVGA_REG_CURSOR4_X = 71, + SVGA_REG_CURSOR4_Y = 72, + SVGA_REG_CURSOR4_SCREEN_ID = 73, + SVGA_REG_CURSOR4_SUBMIT = 74, + SVGA_REG_SCREENDMA = 75, + SVGA_REG_GBOBJECT_MEM_SIZE_KB = 76, + SVGA_REG_REGS_START_HIGH32 = 77, + SVGA_REG_REGS_START_LOW32 = 78, + SVGA_REG_FB_START_HIGH32 = 79, + SVGA_REG_FB_START_LOW32 = 80, + SVGA_REG_MSHINT = 81, + SVGA_REG_IRQ_STATUS = 82, + SVGA_REG_DIRTY_TRACKING = 83, + SVGA_REG_FENCE_GOAL = 84, + SVGA_REG_TOP = 85, /* Must be 1 more than the last register */ + + SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ + /* Next 768 (== 256*3) registers exist for colormap */ + + SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS + /* Base of scratch registers */ + /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage: + First 4 are reserved for VESA BIOS Extension; any remaining are for + the use of the current SVGA driver. */ +}; + + +/* + * Guest memory regions (GMRs): + * + * This is a new memory mapping feature available in SVGA devices + * which have the SVGA_CAP_GMR bit set. Previously, there were two + * fixed memory regions available with which to share data between the + * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs + * are our name for an extensible way of providing arbitrary DMA + * buffers for use between the driver and the SVGA device. They are a + * new alternative to framebuffer memory, usable for both 2D and 3D + * graphics operations. + * + * Since GMR mapping must be done synchronously with guest CPU + * execution, we use a new pair of SVGA registers: + * + * SVGA_REG_GMR_ID -- + * + * Read/write. + * This register holds the 32-bit ID (a small positive integer) + * of a GMR to create, delete, or redefine. Writing this register + * has no side-effects. + * + * SVGA_REG_GMR_DESCRIPTOR -- + * + * Write-only. + * Writing this register will create, delete, or redefine the GMR + * specified by the above ID register. If this register is zero, + * the GMR is deleted. Any pointers into this GMR (including those + * currently being processed by FIFO commands) will be + * synchronously invalidated. + * + * If this register is nonzero, it must be the physical page + * number (PPN) of a data structure which describes the physical + * layout of the memory region this GMR should describe. The + * descriptor structure will be read synchronously by the SVGA + * device when this register is written. The descriptor need not + * remain allocated for the lifetime of the GMR. + * + * The guest driver should write SVGA_REG_GMR_ID first, then + * SVGA_REG_GMR_DESCRIPTOR. + * + * SVGA_REG_GMR_MAX_IDS -- + * + * Read-only. + * The SVGA device may choose to support a maximum number of + * user-defined GMR IDs. This register holds the number of supported + * IDs. (The maximum supported ID plus 1) + * + * SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH -- + * + * Read-only. + * The SVGA device may choose to put a limit on the total number + * of SVGAGuestMemDescriptor structures it will read when defining + * a single GMR. + * + * The descriptor structure is an array of SVGAGuestMemDescriptor + * structures. Each structure may do one of three things: + * + * - Terminate the GMR descriptor list. + * (ppn==0, numPages==0) + * + * - Add a PPN or range of PPNs to the GMR's virtual address space. + * (ppn != 0, numPages != 0) + * + * - Provide the PPN of the next SVGAGuestMemDescriptor, in order to + * support multi-page GMR descriptor tables without forcing the + * driver to allocate physically contiguous memory. + * (ppn != 0, numPages == 0) + * + * Note that each physical page of SVGAGuestMemDescriptor structures + * can describe at least 2MB of guest memory. If the driver needs to + * use more than one page of descriptor structures, it must use one of + * its SVGAGuestMemDescriptors to point to an additional page. The + * device will never automatically cross a page boundary. + * + * Once the driver has described a GMR, it is immediately available + * for use via any FIFO command that uses an SVGAGuestPtr structure. + * These pointers include a GMR identifier plus an offset into that + * GMR. + * + * The driver must check the SVGA_CAP_GMR bit before using the GMR + * registers. + */ + +/* + * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer + * memory as well. In the future, these IDs could even be used to + * allow legacy memory regions to be redefined by the guest as GMRs. + * + * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA + * is being phased out. Please try to use user-defined GMRs whenever + * possible. + */ +#define SVGA_GMR_NULL ((uint32) -1) +#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) // Guest Framebuffer (GFB) + +typedef +struct SVGAGuestMemDescriptor { + uint32 ppn; + uint32 numPages; +} SVGAGuestMemDescriptor; + +typedef +struct SVGAGuestPtr { + uint32 gmrId; + uint32 offset; +} SVGAGuestPtr; + + +/* + * SVGAGMRImageFormat -- + * + * This is a packed representation of the source 2D image format + * for a GMR-to-screen blit. Currently it is defined as an encoding + * of the screen's color depth and bits-per-pixel, however, 16 bits + * are reserved for future use to identify other encodings (such as + * RGBA or higher-precision images). + * + * Currently supported formats: + * + * bpp depth Format Name + * --- ----- ----------- + * 32 24 32-bit BGRX + * 24 24 24-bit BGR + * 16 16 RGB 5-6-5 + * 16 15 RGB 5-5-5 + * + */ + +typedef +struct SVGAGMRImageFormat { + union { + struct { + uint32 bitsPerPixel : 8; + uint32 colorDepth : 8; + uint32 reserved : 16; // Must be zero + }; + + uint32 value; + }; +} SVGAGMRImageFormat; + +typedef +struct SVGAGuestImage { + SVGAGuestPtr ptr; + + /* + * A note on interpretation of pitch: This value of pitch is the + * number of bytes between vertically adjacent image + * blocks. Normally this is the number of bytes between the first + * pixel of two adjacent scanlines. With compressed textures, + * however, this may represent the number of bytes between + * compression blocks rather than between rows of pixels. + * + * XXX: Compressed textures currently must be tightly packed in guest memory. + * + * If the image is 1-dimensional, pitch is ignored. + * + * If 'pitch' is zero, the SVGA3D device calculates a pitch value + * assuming each row of blocks is tightly packed. + */ + uint32 pitch; +} SVGAGuestImage; + +/* + * SVGAColorBGRX -- + * + * A 24-bit color format (BGRX), which does not depend on the + * format of the legacy guest framebuffer (GFB) or the current + * GMRFB state. + */ + +typedef +struct SVGAColorBGRX { + union { + struct { + uint32 b : 8; + uint32 g : 8; + uint32 r : 8; + uint32 x : 8; // Unused + }; + + uint32 value; + }; +} SVGAColorBGRX; + + +/* + * SVGASignedRect -- + * SVGASignedPoint -- + * + * Signed rectangle and point primitives. These are used by the new + * 2D primitives for drawing to Screen Objects, which can occupy a + * signed virtual coordinate space. + * + * SVGASignedRect specifies a half-open interval: the (left, top) + * pixel is part of the rectangle, but the (right, bottom) pixel is + * not. + */ + +typedef +struct SVGASignedRect { + int32 left; + int32 top; + int32 right; + int32 bottom; +} SVGASignedRect; + +typedef +struct SVGASignedPoint { + int32 x; + int32 y; +} SVGASignedPoint; + + +/* + * Capabilities + * + * Note the holes in the bitfield. Missing bits have been deprecated, + * and must not be reused. Those capabilities will never be reported + * by new versions of the SVGA device. + * + * SVGA_CAP_GMR2 -- + * Provides asynchronous commands to define and remap guest memory + * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and + * SVGA_REG_MEMORY_SIZE. + * + * SVGA_CAP_SCREEN_OBJECT_2 -- + * Allow screen object support, and require backing stores from the + * guest for each screen object. + */ + +#define SVGA_CAP_NONE 0x00000000UL +#define SVGA_CAP_RECT_COPY 0x00000002UL +#define SVGA_CAP_CURSOR 0x00000020UL +#define SVGA_CAP_CURSOR_BYPASS 0x00000040UL // Legacy (Use Cursor Bypass 3 instead) +#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080UL // Legacy (Use Cursor Bypass 3 instead) +#define SVGA_CAP_8BIT_EMULATION 0x00000100UL +#define SVGA_CAP_ALPHA_CURSOR 0x00000200UL +#define SVGA_CAP_3D 0x00004000UL +#define SVGA_CAP_EXTENDED_FIFO 0x00008000UL +#define SVGA_CAP_MULTIMON 0x00010000UL // Legacy multi-monitor support +#define SVGA_CAP_PITCHLOCK 0x00020000UL +#define SVGA_CAP_IRQMASK 0x00040000UL +#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000UL // Legacy multi-monitor support +#define SVGA_CAP_GMR 0x00100000UL +#define SVGA_CAP_TRACES 0x00200000UL +#define SVGA_CAP_GMR2 0x00400000UL +#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000UL +/* svga3 caps */ +#define SVGA_CAP_COMMAND_BUFFERS 0x01000000UL +#define SVGA_CAP_DEAD1 0x02000000UL +#define SVGA_CAP_CMD_BUFFERS_2 0x04000000UL +#define SVGA_CAP_GBOBJECTS 0x08000000UL +#define SVGA_CAP_DX 0x10000000UL +#define SVGA_CAP_HP_CMD_QUEUE 0x20000000UL +#define SVGA_CAP_NO_BB_RESTRICTION 0x40000000UL +#define SVGA_CAP_CAP2_REGISTER 0x80000000UL + +/* + * FIFO register indices. + * + * The FIFO is a chunk of device memory mapped into guest physmem. It + * is always treated as 32-bit words. + * + * The guest driver gets to decide how to partition it between + * - FIFO registers (there are always at least 4, specifying where the + * following data area is and how much data it contains; there may be + * more registers following these, depending on the FIFO protocol + * version in use) + * - FIFO data, written by the guest and slurped out by the VMX. + * These indices are 32-bit word offsets into the FIFO. + */ + +enum { + /* + * Block 1 (basic registers): The originally defined FIFO registers. + * These exist and are valid for all versions of the FIFO protocol. + */ + + SVGA_FIFO_MIN = 0, + SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ + SVGA_FIFO_NEXT_CMD, + SVGA_FIFO_STOP, + + /* + * Block 2 (extended registers): Mandatory registers for the extended + * FIFO. These exist if the SVGA caps register includes + * SVGA_CAP_EXTENDED_FIFO; some of them are valid only if their + * associated capability bit is enabled. + * + * Note that when originally defined, SVGA_CAP_EXTENDED_FIFO implied + * support only for (FIFO registers) CAPABILITIES, FLAGS, and FENCE. + * This means that the guest has to test individually (in most cases + * using FIFO caps) for the presence of registers after this; the VMX + * can define "extended FIFO" to mean whatever it wants, and currently + * won't enable it unless there's room for that set and much more. + */ + + SVGA_FIFO_CAPABILITIES = 4, + SVGA_FIFO_FLAGS, + // Valid with SVGA_FIFO_CAP_FENCE: + SVGA_FIFO_FENCE, + + /* + * Block 3a (optional extended registers): Additional registers for the + * extended FIFO, whose presence isn't actually implied by + * SVGA_CAP_EXTENDED_FIFO; these exist if SVGA_FIFO_MIN is high enough to + * leave room for them. + * + * These in block 3a, the VMX currently considers mandatory for the + * extended FIFO. + */ + + // Valid if exists (i.e. if extended FIFO enabled): + SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ + // Valid with SVGA_FIFO_CAP_PITCHLOCK: + SVGA_FIFO_PITCHLOCK, + + // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: + SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ + SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ + SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ + SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ + SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ + + // Valid with SVGA_FIFO_CAP_RESERVE: + SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ + + /* + * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2: + * + * By default this is SVGA_ID_INVALID, to indicate that the cursor + * coordinates are specified relative to the virtual root. If this + * is set to a specific screen ID, cursor position is reinterpreted + * as a signed offset relative to that screen's origin. + */ + SVGA_FIFO_CURSOR_SCREEN_ID, + + /* + * Valid with SVGA_FIFO_CAP_DEAD + * + * An arbitrary value written by the host, drivers should not use it. + */ + SVGA_FIFO_DEAD, + + /* + * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED: + * + * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h) + * on platforms that can enforce graphics resource limits. + */ + SVGA_FIFO_3D_HWVERSION_REVISED, + + /* + * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new + * registers, but this must be done carefully and with judicious use of + * capability bits, since comparisons based on SVGA_FIFO_MIN aren't + * enough to tell you whether the register exists: we've shipped drivers + * and products that used SVGA_FIFO_3D_CAPS but didn't know about some of + * the earlier ones. The actual order of introduction was: + * - PITCHLOCK + * - 3D_CAPS + * - CURSOR_* (cursor bypass 3) + * - RESERVED + * So, code that wants to know whether it can use any of the + * aforementioned registers, or anything else added after PITCHLOCK and + * before 3D_CAPS, needs to reason about something other than + * SVGA_FIFO_MIN. + */ + + /* + * 3D caps block space; valid with 3D hardware version >= + * SVGA3D_HWVERSION_WS6_B1. + */ + SVGA_FIFO_3D_CAPS = 32, + SVGA_FIFO_3D_CAPS_LAST = 32 + 255, + + /* + * End of VMX's current definition of "extended-FIFO registers". + * Registers before here are always enabled/disabled as a block; either + * the extended FIFO is enabled and includes all preceding registers, or + * it's disabled entirely. + * + * Block 3b (truly optional extended registers): Additional registers for + * the extended FIFO, which the VMX already knows how to enable and + * disable with correct granularity. + * + * Registers after here exist if and only if the guest SVGA driver + * sets SVGA_FIFO_MIN high enough to leave room for them. + */ + + // Valid if register exists: + SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */ + SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */ + SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */ + + /* + * Always keep this last. This defines the maximum number of + * registers we know about. At power-on, this value is placed in + * the SVGA_REG_MEM_REGS register, and we expect the guest driver + * to allocate this much space in FIFO memory for registers. + */ + SVGA_FIFO_NUM_REGS +}; + + +/* + * Definition of registers included in extended FIFO support. + * + * The guest SVGA driver gets to allocate the FIFO between registers + * and data. It must always allocate at least 4 registers, but old + * drivers stopped there. + * + * The VMX will enable extended FIFO support if and only if the guest + * left enough room for all registers defined as part of the mandatory + * set for the extended FIFO. + * + * Note that the guest drivers typically allocate the FIFO only at + * initialization time, not at mode switches, so it's likely that the + * number of FIFO registers won't change without a reboot. + * + * All registers less than this value are guaranteed to be present if + * svgaUser->fifo.extended is set. Any later registers must be tested + * individually for compatibility at each use (in the VMX). + * + * This value is used only by the VMX, so it can change without + * affecting driver compatibility; keep it that way? + */ +#define SVGA_FIFO_EXTENDED_MANDATORY_REGS (SVGA_FIFO_3D_CAPS_LAST + 1) + + +/* + * FIFO Synchronization Registers + * + * This explains the relationship between the various FIFO + * sync-related registers in IOSpace and in FIFO space. + * + * SVGA_REG_SYNC -- + * + * The SYNC register can be used in two different ways by the guest: + * + * 1. If the guest wishes to fully sync (drain) the FIFO, + * it will write once to SYNC then poll on the BUSY + * register. The FIFO is sync'ed once BUSY is zero. + * + * 2. If the guest wants to asynchronously wake up the host, + * it will write once to SYNC without polling on BUSY. + * Ideally it will do this after some new commands have + * been placed in the FIFO, and after reading a zero + * from SVGA_FIFO_BUSY. + * + * (1) is the original behaviour that SYNC was designed to + * support. Originally, a write to SYNC would implicitly + * trigger a read from BUSY. This causes us to synchronously + * process the FIFO. + * + * This behaviour has since been changed so that writing SYNC + * will *not* implicitly cause a read from BUSY. Instead, it + * makes a channel call which asynchronously wakes up the MKS + * thread. + * + * New guests can use this new behaviour to implement (2) + * efficiently. This lets guests get the host's attention + * without waiting for the MKS to poll, which gives us much + * better CPU utilization on SMP hosts and on UP hosts while + * we're blocked on the host GPU. + * + * Old guests shouldn't notice the behaviour change. SYNC was + * never guaranteed to process the entire FIFO, since it was + * bounded to a particular number of CPU cycles. Old guests will + * still loop on the BUSY register until the FIFO is empty. + * + * Writing to SYNC currently has the following side-effects: + * + * - Sets SVGA_REG_BUSY to TRUE (in the monitor) + * - Asynchronously wakes up the MKS thread for FIFO processing + * - The value written to SYNC is recorded as a "reason", for + * stats purposes. + * + * If SVGA_FIFO_BUSY is available, drivers are advised to only + * write to SYNC if SVGA_FIFO_BUSY is FALSE. Drivers should set + * SVGA_FIFO_BUSY to TRUE after writing to SYNC. The MKS will + * eventually set SVGA_FIFO_BUSY on its own, but this approach + * lets the driver avoid sending multiple asynchronous wakeup + * messages to the MKS thread. + * + * SVGA_REG_BUSY -- + * + * This register is set to TRUE when SVGA_REG_SYNC is written, + * and it reads as FALSE when the FIFO has been completely + * drained. + * + * Every read from this register causes us to synchronously + * process FIFO commands. There is no guarantee as to how many + * commands each read will process. + * + * CPU time spent processing FIFO commands will be billed to + * the guest. + * + * New drivers should avoid using this register unless they + * need to guarantee that the FIFO is completely drained. It + * is overkill for performing a sync-to-fence. Older drivers + * will use this register for any type of synchronization. + * + * SVGA_FIFO_BUSY -- + * + * This register is a fast way for the guest driver to check + * whether the FIFO is already being processed. It reads and + * writes at normal RAM speeds, with no monitor intervention. + * + * If this register reads as TRUE, the host is guaranteeing that + * any new commands written into the FIFO will be noticed before + * the MKS goes back to sleep. + * + * If this register reads as FALSE, no such guarantee can be + * made. + * + * The guest should use this register to quickly determine + * whether or not it needs to wake up the host. If the guest + * just wrote a command or group of commands that it would like + * the host to begin processing, it should: + * + * 1. Read SVGA_FIFO_BUSY. If it reads as TRUE, no further + * action is necessary. + * + * 2. Write TRUE to SVGA_FIFO_BUSY. This informs future guest + * code that we've already sent a SYNC to the host and we + * don't need to send a duplicate. + * + * 3. Write a reason to SVGA_REG_SYNC. This will send an + * asynchronous wakeup to the MKS thread. + */ + + +/* + * FIFO Capabilities + * + * Fence -- Fence register and command are supported + * Accel Front -- Front buffer only commands are supported + * Pitch Lock -- Pitch lock register is supported + * Video -- SVGA Video overlay units are supported + * Escape -- Escape command is supported + * + * XXX: Add longer descriptions for each capability, including a list + * of the new features that each capability provides. + * + * SVGA_FIFO_CAP_SCREEN_OBJECT -- + * + * Provides dynamic multi-screen rendering, for improved Unity and + * multi-monitor modes. With Screen Object, the guest can + * dynamically create and destroy 'screens', which can represent + * Unity windows or virtual monitors. Screen Object also provides + * strong guarantees that DMA operations happen only when + * guest-initiated. Screen Object deprecates the BAR1 guest + * framebuffer (GFB) and all commands that work only with the GFB. + * + * New registers: + * FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID + * + * New 2D commands: + * DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN, + * BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY + * + * New 3D commands: + * BLIT_SURFACE_TO_SCREEN + * + * New guarantees: + * + * - The host will not read or write guest memory, including the GFB, + * except when explicitly initiated by a DMA command. + * + * - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK, + * is guaranteed to complete before any subsequent FENCEs. + * + * - All legacy commands which affect a Screen (UPDATE, PRESENT, + * PRESENT_READBACK) as well as new Screen blit commands will + * all behave consistently as blits, and memory will be read + * or written in FIFO order. + * + * For example, if you PRESENT from one SVGA3D surface to multiple + * places on the screen, the data copied will always be from the + * SVGA3D surface at the time the PRESENT was issued in the FIFO. + * This was not necessarily true on devices without Screen Object. + * + * This means that on devices that support Screen Object, the + * PRESENT_READBACK command should not be necessary unless you + * actually want to read back the results of 3D rendering into + * system memory. (And for that, the BLIT_SCREEN_TO_GMRFB + * command provides a strict superset of functionality.) + * + * - When a screen is resized, either using Screen Object commands or + * legacy multimon registers, its contents are preserved. + * + * SVGA_FIFO_CAP_GMR2 -- + * + * Provides new commands to define and remap guest memory regions (GMR). + * + * New 2D commands: + * DEFINE_GMR2, REMAP_GMR2. + * + * SVGA_FIFO_CAP_3D_HWVERSION_REVISED -- + * + * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists. + * This register may replace SVGA_FIFO_3D_HWVERSION on platforms + * that enforce graphics resource limits. This allows the platform + * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest + * drivers that do not limit their resources. + * + * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators + * are codependent (and thus we use a single capability bit). + * + * SVGA_FIFO_CAP_SCREEN_OBJECT_2 -- + * + * Modifies the DEFINE_SCREEN command to include a guest provided + * backing store in GMR memory and the bytesPerLine for the backing + * store. This capability requires the use of a backing store when + * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT + * is present then backing stores are optional. + * + * SVGA_FIFO_CAP_DEAD -- + * + * Drivers should not use this cap bit. This cap bit can not be + * reused since some hosts already expose it. + */ + +#define SVGA_FIFO_CAP_NONE 0 +#define SVGA_FIFO_CAP_FENCE (1<<0) +#define SVGA_FIFO_CAP_ACCELFRONT (1<<1) +#define SVGA_FIFO_CAP_PITCHLOCK (1<<2) +#define SVGA_FIFO_CAP_VIDEO (1<<3) +#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4) +#define SVGA_FIFO_CAP_ESCAPE (1<<5) +#define SVGA_FIFO_CAP_RESERVE (1<<6) +#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7) +#define SVGA_FIFO_CAP_GMR2 (1<<8) +#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2 +#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9) +#define SVGA_FIFO_CAP_DEAD (1<<10) + + +/* + * FIFO Flags + * + * Accel Front -- Driver should use front buffer only commands + */ + +#define SVGA_FIFO_FLAG_NONE 0 +#define SVGA_FIFO_FLAG_ACCELFRONT (1<<0) +#define SVGA_FIFO_FLAG_RESERVED (1<<31) // Internal use only + +/* + * FIFO reservation sentinel value + */ + +#define SVGA_FIFO_RESERVED_UNKNOWN 0xffffffff + + +/* + * Video overlay support + */ + +#define SVGA_NUM_OVERLAY_UNITS 32 + + +/* + * Video capabilities that the guest is currently using + */ + +#define SVGA_VIDEO_FLAG_COLORKEY 0x0001 + + +/* + * Offsets for the video overlay registers + */ + +enum { + SVGA_VIDEO_ENABLED = 0, + SVGA_VIDEO_FLAGS, + SVGA_VIDEO_DATA_OFFSET, + SVGA_VIDEO_FORMAT, + SVGA_VIDEO_COLORKEY, + SVGA_VIDEO_SIZE, // Deprecated + SVGA_VIDEO_WIDTH, + SVGA_VIDEO_HEIGHT, + SVGA_VIDEO_SRC_X, + SVGA_VIDEO_SRC_Y, + SVGA_VIDEO_SRC_WIDTH, + SVGA_VIDEO_SRC_HEIGHT, + SVGA_VIDEO_DST_X, // Signed int32 + SVGA_VIDEO_DST_Y, // Signed int32 + SVGA_VIDEO_DST_WIDTH, + SVGA_VIDEO_DST_HEIGHT, + SVGA_VIDEO_PITCH_1, + SVGA_VIDEO_PITCH_2, + SVGA_VIDEO_PITCH_3, + SVGA_VIDEO_DATA_GMRID, // Optional, defaults to SVGA_GMR_FRAMEBUFFER + SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID) + SVGA_VIDEO_NUM_REGS +}; + + +/* + * SVGA Overlay Units + * + * width and height relate to the entire source video frame. + * srcX, srcY, srcWidth and srcHeight represent subset of the source + * video frame to be displayed. + */ + +typedef struct SVGAOverlayUnit { + uint32 enabled; + uint32 flags; + uint32 dataOffset; + uint32 format; + uint32 colorKey; + uint32 size; + uint32 width; + uint32 height; + uint32 srcX; + uint32 srcY; + uint32 srcWidth; + uint32 srcHeight; + int32 dstX; + int32 dstY; + uint32 dstWidth; + uint32 dstHeight; + uint32 pitches[3]; + uint32 dataGMRId; + uint32 dstScreenId; +} SVGAOverlayUnit; + + +/* + * SVGAScreenObject -- + * + * This is a new way to represent a guest's multi-monitor screen or + * Unity window. Screen objects are only supported if the + * SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set. + * + * If Screen Objects are supported, they can be used to fully + * replace the functionality provided by the framebuffer registers + * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY. + * + * The screen object is a struct with guaranteed binary + * compatibility. New flags can be added, and the struct may grow, + * but existing fields must retain their meaning. + * + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of + * a SVGAGuestPtr that is used to back the screen contents. This + * memory must come from the GFB. The guest is not allowed to + * access the memory and doing so will have undefined results. The + * backing store is required to be page aligned and the size is + * padded to the next page boundry. The number of pages is: + * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE + * + * The pitch in the backingStore is required to be at least large + * enough to hold a 32bbp scanline. It is recommended that the + * driver pad bytesPerLine for a potential performance win. + * + * The cloneCount field is treated as a hint from the guest that + * the user wants this display to be cloned, countCount times. A + * value of zero means no cloning should happen. + */ + +#define SVGA_SCREEN_MUST_BE_SET (1 << 0) // Must be set or results undefined +#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET // Deprecated +#define SVGA_SCREEN_IS_PRIMARY (1 << 1) // Guest considers this screen to be 'primary' +#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) // Guest is running a fullscreen app here + +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is + * deactivated the base layer is defined to lose all contents and + * become black. When a screen is deactivated the backing store is + * optional. When set backingPtr and bytesPerLine will be ignored. + */ +#define SVGA_SCREEN_DEACTIVATE (1 << 3) + +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set + * the screen contents will be outputted as all black to the user + * though the base layer contents is preserved. The screen base layer + * can still be read and written to like normal though the no visible + * effect will be seen by the user. When the flag is changed the + * screen will be blanked or redrawn to the current contents as needed + * without any extra commands from the driver. This flag only has an + * effect when the screen is not deactivated. + */ +#define SVGA_SCREEN_BLANKING (1 << 4) + +typedef +struct SVGAScreenObject { + uint32 structSize; // sizeof(SVGAScreenObject) + uint32 id; + uint32 flags; + struct { + uint32 width; + uint32 height; + } size; + struct { + int32 x; + int32 y; + } root; + + /* + * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional + * with SVGA_FIFO_CAP_SCREEN_OBJECT. + */ + SVGAGuestImage backingStore; + uint32 cloneCount; +} SVGAScreenObject; + + +/* + * Commands in the command FIFO: + * + * Command IDs defined below are used for the traditional 2D FIFO + * communication (not all commands are available for all versions of the + * SVGA FIFO protocol). + * + * Note the holes in the command ID numbers: These commands have been + * deprecated, and the old IDs must not be reused. + * + * Command IDs from 1000 to 1999 are reserved for use by the SVGA3D + * protocol. + * + * Each command's parameters are described by the comments and + * structs below. + */ + +typedef enum { + SVGA_CMD_INVALID_CMD = 0, + SVGA_CMD_UPDATE = 1, + SVGA_CMD_RECT_COPY = 3, + SVGA_CMD_DEFINE_CURSOR = 19, + SVGA_CMD_DEFINE_ALPHA_CURSOR = 22, + SVGA_CMD_UPDATE_VERBOSE = 25, + SVGA_CMD_FRONT_ROP_FILL = 29, + SVGA_CMD_FENCE = 30, + SVGA_CMD_ESCAPE = 33, + SVGA_CMD_DEFINE_SCREEN = 34, + SVGA_CMD_DESTROY_SCREEN = 35, + SVGA_CMD_DEFINE_GMRFB = 36, + SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37, + SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38, + SVGA_CMD_ANNOTATION_FILL = 39, + SVGA_CMD_ANNOTATION_COPY = 40, + SVGA_CMD_DEFINE_GMR2 = 41, + SVGA_CMD_REMAP_GMR2 = 42, + SVGA_CMD_MAX +} SVGAFifoCmdId; + +#define SVGA_CMD_MAX_DATASIZE (256 * 1024) +#define SVGA_CMD_MAX_ARGS 64 + + +/* + * SVGA_CMD_UPDATE -- + * + * This is a DMA transfer which copies from the Guest Framebuffer + * (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which + * intersect with the provided virtual rectangle. + * + * This command does not support using arbitrary guest memory as a + * data source- it only works with the pre-defined GFB memory. + * This command also does not support signed virtual coordinates. + * If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with + * negative root x/y coordinates, the negative portion of those + * screens will not be reachable by this command. + * + * This command is not necessary when using framebuffer + * traces. Traces are automatically enabled if the SVGA FIFO is + * disabled, and you may explicitly enable/disable traces using + * SVGA_REG_TRACES. With traces enabled, any write to the GFB will + * automatically act as if a subsequent SVGA_CMD_UPDATE was issued. + * + * Traces and SVGA_CMD_UPDATE are the only supported ways to render + * pseudocolor screen updates. The newer Screen Object commands + * only support true color formats. + * + * Availability: + * Always available. + */ + +typedef +struct { + uint32 x; + uint32 y; + uint32 width; + uint32 height; +} SVGAFifoCmdUpdate; + + +/* + * SVGA_CMD_RECT_COPY -- + * + * Perform a rectangular DMA transfer from one area of the GFB to + * another, and copy the result to any screens which intersect it. + * + * Availability: + * SVGA_CAP_RECT_COPY + */ + +typedef +struct { + uint32 srcX; + uint32 srcY; + uint32 destX; + uint32 destY; + uint32 width; + uint32 height; +} SVGAFifoCmdRectCopy; + + +/* + * SVGA_CMD_DEFINE_CURSOR -- + * + * Provide a new cursor image, as an AND/XOR mask. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_CURSOR + */ + +typedef +struct { + uint32 id; // Reserved, must be zero. + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + uint32 andMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL + uint32 xorMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL + /* + * Followed by scanline data for AND mask, then XOR mask. + * Each scanline is padded to a 32-bit boundary. + */ +} SVGAFifoCmdDefineCursor; + + +/* + * SVGA_CMD_DEFINE_ALPHA_CURSOR -- + * + * Provide a new cursor image, in 32-bit BGRA format. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_ALPHA_CURSOR + */ + +typedef +struct { + uint32 id; // Reserved, must be zero. + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + /* Followed by scanline data */ +} SVGAFifoCmdDefineAlphaCursor; + + +/* + * SVGA_CMD_UPDATE_VERBOSE -- + * + * Just like SVGA_CMD_UPDATE, but also provide a per-rectangle + * 'reason' value, an opaque cookie which is used by internal + * debugging tools. Third party drivers should not use this + * command. + * + * Availability: + * SVGA_CAP_EXTENDED_FIFO + */ + +typedef +struct { + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 reason; +} SVGAFifoCmdUpdateVerbose; + + +/* + * SVGA_CMD_FRONT_ROP_FILL -- + * + * This is a hint which tells the SVGA device that the driver has + * just filled a rectangular region of the GFB with a solid + * color. Instead of reading these pixels from the GFB, the device + * can assume that they all equal 'color'. This is primarily used + * for remote desktop protocols. + * + * Availability: + * SVGA_FIFO_CAP_ACCELFRONT + */ + +#define SVGA_ROP_COPY 0x03 + +typedef +struct { + uint32 color; // In the same format as the GFB + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 rop; // Must be SVGA_ROP_COPY +} SVGAFifoCmdFrontRopFill; + + +/* + * SVGA_CMD_FENCE -- + * + * Insert a synchronization fence. When the SVGA device reaches + * this command, it will copy the 'fence' value into the + * SVGA_FIFO_FENCE register. It will also compare the fence against + * SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the + * SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will + * raise this interrupt. + * + * Availability: + * SVGA_FIFO_FENCE for this command, + * SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL. + */ + +typedef +struct { + uint32 fence; +} SVGAFifoCmdFence; + + +/* + * SVGA_CMD_ESCAPE -- + * + * Send an extended or vendor-specific variable length command. + * This is used for video overlay, third party plugins, and + * internal debugging tools. See svga_escape.h + * + * Availability: + * SVGA_FIFO_CAP_ESCAPE + */ + +typedef +struct { + uint32 nsid; + uint32 size; + /* followed by 'size' bytes of data */ +} SVGAFifoCmdEscape; + + +/* + * SVGA_CMD_DEFINE_SCREEN -- + * + * Define or redefine an SVGAScreenObject. See the description of + * SVGAScreenObject above. The video driver is responsible for + * generating new screen IDs. They should be small positive + * integers. The virtual device will have an implementation + * specific upper limit on the number of screen IDs + * supported. Drivers are responsible for recycling IDs. The first + * valid ID is zero. + * + * - Interaction with other registers: + * + * For backwards compatibility, when the GFB mode registers (WIDTH, + * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device + * deletes all screens other than screen #0, and redefines screen + * #0 according to the specified mode. Drivers that use + * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0. + * + * If you use screen objects, do not use the legacy multi-mon + * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*). + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAScreenObject screen; // Variable-length according to version +} SVGAFifoCmdDefineScreen; + + +/* + * SVGA_CMD_DESTROY_SCREEN -- + * + * Destroy an SVGAScreenObject. Its ID is immediately available for + * re-use. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + uint32 screenId; +} SVGAFifoCmdDestroyScreen; + + +/* + * SVGA_CMD_DEFINE_GMRFB -- + * + * This command sets a piece of SVGA device state called the + * Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a + * piece of light-weight state which identifies the location and + * format of an image in guest memory or in BAR1. The GMRFB has + * an arbitrary size, and it doesn't need to match the geometry + * of the GFB or any screen object. + * + * The GMRFB can be redefined as often as you like. You could + * always use the same GMRFB, you could redefine it before + * rendering from a different guest screen, or you could even + * redefine it before every blit. + * + * There are multiple ways to use this command. The simplest way is + * to use it to move the framebuffer either to elsewhere in the GFB + * (BAR1) memory region, or to a user-defined GMR. This lets a + * driver use a framebuffer allocated entirely out of normal system + * memory, which we encourage. + * + * Another way to use this command is to set up a ring buffer of + * updates in GFB memory. If a driver wants to ensure that no + * frames are skipped by the SVGA device, it is important that the + * driver not modify the source data for a blit until the device is + * done processing the command. One efficient way to accomplish + * this is to use a ring of small DMA buffers. Each buffer is used + * for one blit, then we move on to the next buffer in the + * ring. The FENCE mechanism is used to protect each buffer from + * re-use until the device is finished with that buffer's + * corresponding blit. + * + * This command does not affect the meaning of SVGA_CMD_UPDATE. + * UPDATEs always occur from the legacy GFB memory area. This + * command has no support for pseudocolor GMRFBs. Currently only + * true-color 15, 16, and 24-bit depths are supported. Future + * devices may expose capabilities for additional framebuffer + * formats. + * + * The default GMRFB value is undefined. Drivers must always send + * this command at least once before performing any blit from the + * GMRFB. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAGuestPtr ptr; + uint32 bytesPerLine; + SVGAGMRImageFormat format; +} SVGAFifoCmdDefineGMRFB; + + +/* + * SVGA_CMD_BLIT_GMRFB_TO_SCREEN -- + * + * This is a guest-to-host blit. It performs a DMA operation to + * copy a rectangular region of pixels from the current GMRFB to + * one or more Screen Objects. + * + * The destination coordinate may be specified relative to a + * screen's origin (if a screen ID is specified) or relative to the + * virtual coordinate system's origin (if the screen ID is + * SVGA_ID_INVALID). The actual destination may span zero or more + * screens, in the case of a virtual destination rect or a rect + * which extends off the edge of the specified screen. + * + * This command writes to the screen's "base layer": the underlying + * framebuffer which exists below any cursor or video overlays. No + * action is necessary to explicitly hide or update any overlays + * which exist on top of the updated region. + * + * The SVGA device is guaranteed to finish reading from the GMRFB + * by the time any subsequent FENCE commands are reached. + * + * This command consumes an annotation. See the + * SVGA_CMD_ANNOTATION_* commands for details. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + SVGASignedRect destRect; + uint32 destScreenId; +} SVGAFifoCmdBlitGMRFBToScreen; + + +/* + * SVGA_CMD_BLIT_SCREEN_TO_GMRFB -- + * + * This is a host-to-guest blit. It performs a DMA operation to + * copy a rectangular region of pixels from a single Screen Object + * back to the current GMRFB. + * + * Usage note: This command should be used rarely. It will + * typically be inefficient, but it is necessary for some types of + * synchronization between 3D (GPU) and 2D (CPU) rendering into + * overlapping areas of a screen. + * + * The source coordinate is specified relative to a screen's + * origin. The provided screen ID must be valid. If any parameters + * are invalid, the resulting pixel values are undefined. + * + * This command reads the screen's "base layer". Overlays like + * video and cursor are not included, but any data which was sent + * using a blit-to-screen primitive will be available, no matter + * whether the data's original source was the GMRFB or the 3D + * acceleration hardware. + * + * Note that our guest-to-host blits and host-to-guest blits aren't + * symmetric in their current implementation. While the parameters + * are identical, host-to-guest blits are a lot less featureful. + * They do not support clipping: If the source parameters don't + * fully fit within a screen, the blit fails. They must originate + * from exactly one screen. Virtual coordinates are not directly + * supported. + * + * Host-to-guest blits do support the same set of GMRFB formats + * offered by guest-to-host blits. + * + * The SVGA device is guaranteed to finish writing to the GMRFB by + * the time any subsequent FENCE commands are reached. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint destOrigin; + SVGASignedRect srcRect; + uint32 srcScreenId; +} SVGAFifoCmdBlitScreenToGMRFB; + + +/* + * SVGA_CMD_ANNOTATION_FILL -- + * + * This is a blit annotation. This command stores a small piece of + * device state which is consumed by the next blit-to-screen + * command. The state is only cleared by commands which are + * specifically documented as consuming an annotation. Other + * commands (such as ESCAPEs for debugging) may intervene between + * the annotation and its associated blit. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value, specified here as a color in + * SVGAColorBGRX format. + * + * The SVGA device can still render the blit correctly even if it + * ignores this annotation, but the annotation may allow it to + * perform the blit more efficiently, for example by ignoring the + * source data and performing a fill in hardware. + * + * This annotation is most important for performance when the + * user's display is being remoted over a network connection. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAColorBGRX color; +} SVGAFifoCmdAnnotationFill; + + +/* + * SVGA_CMD_ANNOTATION_COPY -- + * + * This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more + * information about annotations. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value as those which already exist at an + * identically-sized region on the same or a different screen. + * + * Note that the source pixels for the COPY in this annotation are + * sampled before applying the anqnotation's associated blit. They + * are allowed to overlap with the blit's destination pixels. + * + * The copy source rectangle is specified the same way as the blit + * destination: it can be a rectangle which spans zero or more + * screens, specified relative to either a screen or to the virtual + * coordinate system's origin. If the source rectangle includes + * pixels which are not from exactly one screen, the results are + * undefined. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + uint32 srcScreenId; +} SVGAFifoCmdAnnotationCopy; + + +/* + * SVGA_CMD_DEFINE_GMR2 -- + * + * Define guest memory region v2. See the description of GMRs above. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef +struct { + uint32 gmrId; + uint32 numPages; +} +SVGAFifoCmdDefineGMR2; + + +/* + * SVGA_CMD_REMAP_GMR2 -- + * + * Remap guest memory region v2. See the description of GMRs above. + * + * This command allows guest to modify a portion of an existing GMR by + * invalidating it or reassigning it to different guest physical pages. + * The pages are identified by physical page number (PPN). The pages + * are assumed to be pinned and valid for DMA operations. + * + * Description of command flags: + * + * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR. + * The PPN list must not overlap with the remap region (this can be + * handled trivially by referencing a separate GMR). If flag is + * disabled, PPN list is appended to SVGARemapGMR command. + * + * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise + * it is in PPN32 format. + * + * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry. + * A single PPN can be used to invalidate a portion of a GMR or + * map it to to a single guest scratch page. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef enum { + SVGA_REMAP_GMR2_PPN32 = 0, + SVGA_REMAP_GMR2_VIA_GMR = (1 << 0), + SVGA_REMAP_GMR2_PPN64 = (1 << 1), + SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2), +} SVGARemapGMR2Flags; + +typedef +struct { + uint32 gmrId; + SVGARemapGMR2Flags flags; + uint32 offsetPages; // offset in pages to begin remap + uint32 numPages; // number of pages to remap + /* + * Followed by additional data depending on SVGARemapGMR2Flags. + * + * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows. + * Otherwise an array of page descriptors in PPN32 or PPN64 format + * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag + * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry. + */ +} +SVGAFifoCmdRemapGMR2; + +#endif |